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