vmgs_broker/
non_volatile_store.rs

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4//! Implementation of [`NonVolatileStore`] for VMGS files.
5
6use crate::VmgsClient;
7use crate::VmgsClientError;
8use async_trait::async_trait;
9use thiserror::Error;
10use vmcore::non_volatile_store::NonVolatileStore;
11use vmcore::non_volatile_store::NonVolatileStoreError;
12
13/// A [`NonVolatileStore`] implementation for VMGS files.
14pub struct VmgsNonVolatileStore {
15    vmgs: VmgsClient,
16    file_id: vmgs_format::FileId,
17    encrypted: bool,
18}
19
20/// Error returned when a VMGS file is requested to be opened in encrypted mode,
21/// but the VMGS broker was not compiled with encryption support.
22#[derive(Debug, Error)]
23#[error("the vmgs_broker crate was not compiled with encryption support")]
24pub struct EncryptionNotSupported;
25
26impl VmgsNonVolatileStore {
27    /// Create a new [`NonVolatileStore`] object backed by a particular VMGS
28    /// file-id.
29    pub fn new(
30        vmgs: VmgsClient,
31        file_id: vmgs_format::FileId,
32        encrypted: bool,
33    ) -> Result<Self, EncryptionNotSupported> {
34        if encrypted && !cfg!(with_encryption) {
35            return Err(EncryptionNotSupported);
36        }
37        Ok(Self {
38            vmgs,
39            file_id,
40            encrypted,
41        })
42    }
43}
44
45#[async_trait]
46impl NonVolatileStore for VmgsNonVolatileStore {
47    async fn persist(&mut self, data: Vec<u8>) -> Result<(), NonVolatileStoreError> {
48        #[cfg(with_encryption)]
49        if self.encrypted {
50            self.vmgs
51                .write_file_encrypted(self.file_id, data)
52                .await
53                .map_err(NonVolatileStoreError::new)?;
54            return Ok(());
55        }
56
57        assert!(!self.encrypted);
58
59        self.vmgs
60            .write_file(self.file_id, data)
61            .await
62            .map_err(NonVolatileStoreError::new)?;
63
64        Ok(())
65    }
66
67    async fn restore(&mut self) -> Result<Option<Vec<u8>>, NonVolatileStoreError> {
68        match self.vmgs.read_file(self.file_id).await {
69            Ok(buf) => Ok(Some(buf)),
70            Err(VmgsClientError::Vmgs(vmgs::Error::FileInfoAllocated)) => Ok(None),
71            Err(e) => Err(NonVolatileStoreError::new(e)),
72        }
73    }
74}