vmcore/
non_volatile_store.rs1#![warn(missing_docs)]
7#![forbid(unsafe_code)]
8
9use thiserror::Error;
10
11#[derive(Error, Debug)]
13#[error("error accessing non-volatile store")]
14pub struct NonVolatileStoreError(#[from] anyhow::Error);
15
16impl NonVolatileStoreError {
17 pub fn new(e: impl Into<anyhow::Error>) -> NonVolatileStoreError {
19 Self(e.into())
20 }
21}
22
23#[async_trait::async_trait]
33pub trait NonVolatileStore: Send + Sync {
34 async fn persist(&mut self, data: Vec<u8>) -> Result<(), NonVolatileStoreError>;
36
37 async fn restore(&mut self) -> Result<Option<Vec<u8>>, NonVolatileStoreError>;
39}
40
41#[async_trait::async_trait]
43impl NonVolatileStore for Box<dyn NonVolatileStore> {
44 async fn persist(&mut self, data: Vec<u8>) -> Result<(), NonVolatileStoreError> {
45 (**self).persist(data).await
46 }
47
48 async fn restore(&mut self) -> Result<Option<Vec<u8>>, NonVolatileStoreError> {
49 (**self).restore().await
50 }
51}
52
53#[async_trait::async_trait]
55impl<T> NonVolatileStore for &mut T
56where
57 T: NonVolatileStore,
58{
59 async fn persist(&mut self, data: Vec<u8>) -> Result<(), NonVolatileStoreError> {
60 (**self).persist(data).await
61 }
62
63 async fn restore(&mut self) -> Result<Option<Vec<u8>>, NonVolatileStoreError> {
64 (**self).restore().await
65 }
66}
67
68#[derive(Default)]
71pub struct EphemeralNonVolatileStore(Option<Vec<u8>>);
72
73impl EphemeralNonVolatileStore {
74 pub fn new_boxed() -> Box<dyn NonVolatileStore> {
77 Box::new(Self::default())
78 }
79}
80
81#[async_trait::async_trait]
82impl NonVolatileStore for EphemeralNonVolatileStore {
83 async fn persist(&mut self, data: Vec<u8>) -> Result<(), NonVolatileStoreError> {
84 self.0 = Some(data);
85 Ok(())
86 }
87
88 async fn restore(&mut self) -> Result<Option<Vec<u8>>, NonVolatileStoreError> {
89 Ok(self.0.clone())
90 }
91}
92
93pub mod resources {
97 use super::EphemeralNonVolatileStore;
98 use super::NonVolatileStore;
99 use mesh::MeshPayload;
100 use std::convert::Infallible;
101 use vm_resource::CanResolveTo;
102 use vm_resource::ResolveResource;
103 use vm_resource::ResourceId;
104 use vm_resource::declare_static_resolver;
105 use vm_resource::kind::NonVolatileStoreKind;
106
107 impl CanResolveTo<ResolvedNonVolatileStore> for NonVolatileStoreKind {
108 type Input<'a> = ();
109 }
110
111 pub struct ResolvedNonVolatileStore(pub Box<dyn NonVolatileStore>);
113
114 impl<T: 'static + NonVolatileStore> From<T> for ResolvedNonVolatileStore {
115 fn from(store: T) -> Self {
116 Self(Box::new(store))
117 }
118 }
119
120 pub struct EphemeralNonVolatileStoreResolver;
122
123 #[derive(MeshPayload)]
125 pub struct EphemeralNonVolatileStoreHandle;
126
127 impl ResourceId<NonVolatileStoreKind> for EphemeralNonVolatileStoreHandle {
128 const ID: &'static str = "ephemeral";
129 }
130
131 declare_static_resolver! {
132 EphemeralNonVolatileStoreResolver,
133 (NonVolatileStoreKind, EphemeralNonVolatileStoreHandle),
134 }
135
136 impl ResolveResource<NonVolatileStoreKind, EphemeralNonVolatileStoreHandle>
137 for EphemeralNonVolatileStoreResolver
138 {
139 type Error = Infallible;
140 type Output = ResolvedNonVolatileStore;
141
142 fn resolve(
143 &self,
144 EphemeralNonVolatileStoreHandle: EphemeralNonVolatileStoreHandle,
145 _input: (),
146 ) -> Result<Self::Output, Infallible> {
147 Ok(EphemeralNonVolatileStore::default().into())
148 }
149 }
150}