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
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
#![allow(clippy::wildcard_imports)]
use super::*;

pub type ManifestObject =
    Box<dyn Manifest<Iterator = Box<dyn Iterator<Item = StoredArchive> + 'static>> + 'static>;
pub type IndexObject = Box<dyn Index + 'static>;
pub type BackendObject = Box<dyn Backend<Index = IndexObject, Manifest = ManifestObject>>;

/// Wraps a manifest in an object safe way
#[derive(Debug)]
pub struct ManifestWrapper<T: Manifest>(T);

#[async_trait]
impl<T: Manifest> Manifest for ManifestWrapper<T> {
    type Iterator = Box<dyn Iterator<Item = StoredArchive> + 'static>;
    async fn last_modification(&mut self) -> Result<DateTime<FixedOffset>> {
        self.0.last_modification().await
    }
    async fn chunk_settings(&mut self) -> ChunkSettings {
        self.0.chunk_settings().await
    }
    async fn archive_iterator(&mut self) -> Self::Iterator {
        Box::new(self.0.archive_iterator().await)
    }
    async fn write_chunk_settings(&mut self, settings: ChunkSettings) -> Result<()> {
        self.0.write_chunk_settings(settings).await
    }
    async fn write_archive(&mut self, archive: StoredArchive) -> Result<()> {
        self.0.write_archive(archive).await
    }
    async fn touch(&mut self) -> Result<()> {
        self.0.touch().await
    }
}

#[async_trait]
impl Manifest for ManifestObject {
    type Iterator = Box<dyn Iterator<Item = StoredArchive> + 'static>;
    async fn last_modification(&mut self) -> Result<DateTime<FixedOffset>> {
        (**self).last_modification().await
    }
    async fn chunk_settings(&mut self) -> ChunkSettings {
        (**self).chunk_settings().await
    }
    async fn archive_iterator(&mut self) -> Self::Iterator {
        (**self).archive_iterator().await
    }
    async fn write_chunk_settings(&mut self, settings: ChunkSettings) -> Result<()> {
        (**self).write_chunk_settings(settings).await
    }
    async fn write_archive(&mut self, archive: StoredArchive) -> Result<()> {
        (**self).write_archive(archive).await
    }
    async fn touch(&mut self) -> Result<()> {
        (**self).touch().await
    }
}

#[async_trait]
impl Index for IndexObject {
    async fn lookup_chunk(&mut self, id: ChunkID) -> Option<SegmentDescriptor> {
        (**self).lookup_chunk(id).await
    }
    async fn set_chunk(&mut self, id: ChunkID, location: SegmentDescriptor) -> Result<()> {
        (**self).set_chunk(id, location).await
    }
    async fn known_chunks(&mut self) -> HashSet<ChunkID> {
        (**self).known_chunks().await
    }
    async fn commit_index(&mut self) -> Result<()> {
        (**self).commit_index().await
    }
    async fn count_chunk(&mut self) -> usize {
        (**self).count_chunk().await
    }
}

/// Wraps a Backend in an object safe way
#[derive(Debug, Clone)]
pub struct BackendWrapper<T: Backend>(T);

#[async_trait]
impl<T: Backend> Backend for BackendWrapper<T> {
    type Manifest = ManifestObject;
    type Index = IndexObject;
    fn get_index(&self) -> Self::Index {
        Box::new(self.0.get_index())
    }
    async fn write_key(&self, key: &EncryptedKey) -> Result<()> {
        self.0.write_key(key).await
    }
    async fn read_key(&self) -> Result<EncryptedKey> {
        self.0.read_key().await
    }
    fn get_manifest(&self) -> Self::Manifest {
        Box::new(ManifestWrapper(self.0.get_manifest()))
    }
    async fn read_chunk(&mut self, location: SegmentDescriptor) -> Result<Chunk> {
        self.0.read_chunk(location).await
    }
    async fn write_chunk(&mut self, chunk: Chunk) -> Result<SegmentDescriptor> {
        self.0.write_chunk(chunk).await
    }
    async fn close(&mut self) {
        self.0.close().await
    }
    fn get_object_handle(&self) -> BackendObject {
        self.0.get_object_handle()
    }
}

#[async_trait]
impl Backend for BackendObject {
    type Manifest = ManifestObject;
    type Index = IndexObject;
    fn get_index(&self) -> Self::Index {
        (**self).get_index()
    }
    async fn write_key(&self, key: &EncryptedKey) -> Result<()> {
        (**self).write_key(key).await
    }
    async fn read_key(&self) -> Result<EncryptedKey> {
        (**self).read_key().await
    }
    fn get_manifest(&self) -> Self::Manifest {
        (**self).get_manifest()
    }
    async fn read_chunk(&mut self, location: SegmentDescriptor) -> Result<Chunk> {
        (**self).read_chunk(location).await
    }
    async fn write_chunk(&mut self, chunk: Chunk) -> Result<SegmentDescriptor> {
        (**self).write_chunk(chunk).await
    }
    async fn close(&mut self) {
        (**self).close().await
    }
    fn get_object_handle(&self) -> BackendObject {
        (**self).get_object_handle()
    }
}

/// Consumes a `Backend` and converts it into a `BackendObject`
pub fn backend_to_object<T: Backend>(backend: T) -> BackendObject {
    Box::new(BackendWrapper(backend))
}

impl Clone for BackendObject {
    fn clone(&self) -> Self {
        self.get_object_handle()
    }
}