#![warn(missing_docs)]
#![forbid(unsafe_code)]
use thiserror::Error;
#[derive(Error, Debug)]
#[error("error accessing non-volatile store")]
pub struct NonVolatileStoreError(#[from] anyhow::Error);
impl NonVolatileStoreError {
pub fn new(e: impl Into<anyhow::Error>) -> NonVolatileStoreError {
Self(e.into())
}
}
#[async_trait::async_trait]
pub trait NonVolatileStore: Send + Sync {
async fn persist(&mut self, data: Vec<u8>) -> Result<(), NonVolatileStoreError>;
async fn restore(&mut self) -> Result<Option<Vec<u8>>, NonVolatileStoreError>;
}
#[async_trait::async_trait]
impl NonVolatileStore for Box<dyn NonVolatileStore> {
async fn persist(&mut self, data: Vec<u8>) -> Result<(), NonVolatileStoreError> {
(**self).persist(data).await
}
async fn restore(&mut self) -> Result<Option<Vec<u8>>, NonVolatileStoreError> {
(**self).restore().await
}
}
#[async_trait::async_trait]
impl<T> NonVolatileStore for &mut T
where
T: NonVolatileStore,
{
async fn persist(&mut self, data: Vec<u8>) -> Result<(), NonVolatileStoreError> {
(**self).persist(data).await
}
async fn restore(&mut self) -> Result<Option<Vec<u8>>, NonVolatileStoreError> {
(**self).restore().await
}
}
#[derive(Default)]
pub struct EphemeralNonVolatileStore(Option<Vec<u8>>);
impl EphemeralNonVolatileStore {
pub fn new_boxed() -> Box<dyn NonVolatileStore> {
Box::new(Self::default())
}
}
#[async_trait::async_trait]
impl NonVolatileStore for EphemeralNonVolatileStore {
async fn persist(&mut self, data: Vec<u8>) -> Result<(), NonVolatileStoreError> {
self.0 = Some(data);
Ok(())
}
async fn restore(&mut self) -> Result<Option<Vec<u8>>, NonVolatileStoreError> {
Ok(self.0.clone())
}
}
pub mod resources {
use super::EphemeralNonVolatileStore;
use super::NonVolatileStore;
use mesh::MeshPayload;
use std::convert::Infallible;
use vm_resource::declare_static_resolver;
use vm_resource::kind::NonVolatileStoreKind;
use vm_resource::CanResolveTo;
use vm_resource::ResolveResource;
use vm_resource::ResourceId;
impl CanResolveTo<ResolvedNonVolatileStore> for NonVolatileStoreKind {
type Input<'a> = ();
}
pub struct ResolvedNonVolatileStore(pub Box<dyn NonVolatileStore>);
impl<T: 'static + NonVolatileStore> From<T> for ResolvedNonVolatileStore {
fn from(store: T) -> Self {
Self(Box::new(store))
}
}
pub struct EphemeralNonVolatileStoreResolver;
#[derive(MeshPayload)]
pub struct EphemeralNonVolatileStoreHandle;
impl ResourceId<NonVolatileStoreKind> for EphemeralNonVolatileStoreHandle {
const ID: &'static str = "ephemeral";
}
declare_static_resolver! {
EphemeralNonVolatileStoreResolver,
(NonVolatileStoreKind, EphemeralNonVolatileStoreHandle),
}
impl ResolveResource<NonVolatileStoreKind, EphemeralNonVolatileStoreHandle>
for EphemeralNonVolatileStoreResolver
{
type Error = Infallible;
type Output = ResolvedNonVolatileStore;
fn resolve(
&self,
EphemeralNonVolatileStoreHandle: EphemeralNonVolatileStoreHandle,
_input: (),
) -> Result<Self::Output, Infallible> {
Ok(EphemeralNonVolatileStore::default().into())
}
}
}