hcl_compat_uefi_nvram_storage/
storage_backend.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

//! Trait for abstracting the backend used for NVRAM storage

use thiserror::Error;

/// Error when accessing a [`StorageBackend`]
#[derive(Error, Debug)]
#[error("error accessing nvram storage backend")]
pub struct StorageBackendError(#[from] anyhow::Error);

impl StorageBackendError {
    /// Create a new [`StorageBackendError`]
    pub fn new(e: impl Into<anyhow::Error>) -> StorageBackendError {
        Self(e.into())
    }
}

/// Storage backend for accessing the NVRAM
#[async_trait::async_trait]
pub trait StorageBackend: Send + Sync {
    /// Write `data` to a non-volatile storage medium.
    async fn persist(&mut self, data: Vec<u8>) -> Result<(), StorageBackendError>;

    /// Read any previously written `data`. Returns `None` if no data exists.
    async fn restore(&mut self) -> Result<Option<Vec<u8>>, StorageBackendError>;
}

// Boilerplate: forward `StorageBackend` methods for `Box<dyn StorageBackend>`
#[async_trait::async_trait]
impl StorageBackend for Box<dyn StorageBackend> {
    async fn persist(&mut self, data: Vec<u8>) -> Result<(), StorageBackendError> {
        (**self).persist(data).await
    }

    async fn restore(&mut self) -> Result<Option<Vec<u8>>, StorageBackendError> {
        (**self).restore().await
    }
}

// Boilerplate: forward `StorageBackend` methods for `&mut StorageBackend`
#[async_trait::async_trait]
impl<T> StorageBackend for &mut T
where
    T: StorageBackend,
{
    async fn persist(&mut self, data: Vec<u8>) -> Result<(), StorageBackendError> {
        (**self).persist(data).await
    }

    async fn restore(&mut self) -> Result<Option<Vec<u8>>, StorageBackendError> {
        (**self).restore().await
    }
}