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
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
//
// Copyright (c) DUSK NETWORK. All rights reserved.

use alloc::sync::Arc;
use core::convert::Infallible;
use rkyv::ser::Serializer;

use bytecheck::CheckBytes;
use rkyv::validation::validators::DefaultValidator;
use rkyv::{check_archived_root, Archive, Fallible, Serialize};

use crate::{Ident, Store, StoreProvider, StoreSerializer, Stored};

use super::{Token, TokenBuffer};

/// A clonable reference to a store
pub struct StoreRef<I> {
    inner: Arc<dyn Store<Identifier = I>>,
}

impl<I> StoreRef<I> {
    /// Creates a new StoreReference
    pub fn new<S: 'static + Store<Identifier = I>>(store: S) -> StoreRef<I> {
        StoreRef {
            inner: Arc::new(store),
        }
    }
}

impl<I> StoreRef<I> {
    /// Store a value, returning a `Stored` fat pointer that also carries a
    /// reference to the underlying storage with it    
    pub fn store<T>(&self, t: &T) -> Stored<T, I>
    where
        T: Serialize<StoreSerializer<I>>,
    {
        Stored::new(self.clone(), self.put(t))
    }

    /// Put a value into the store, returning an Ident.
    pub fn put<T>(&self, t: &T) -> Ident<T, I>
    where
        T: Serialize<StoreSerializer<I>>,
    {
        let mut ser = self.serializer();
        ser.serialize(t);
        let id = ser.commit();
        Ident::new(id)
    }

    /// Put raw bytes into the store, returning an Ident.
    pub fn put_raw(&self, bytes: &[u8]) -> I {
        let mut ser = self.serializer();
        // write the bytes using the `Serializer` directly.
        ser.write(bytes).unwrap();
        ser.commit()
    }

    /// Return a serializer associated with this store
    pub fn serializer(&self) -> StoreSerializer<I> {
        StoreSerializer::new(self.clone(), self.inner.request_buffer())
    }

    /// Gets a reference to an archived value
    pub fn get<T>(&self, ident: &Ident<T, I>) -> &T::Archived
    where
        T: Archive,
        T::Archived: for<'a> CheckBytes<DefaultValidator<'a>>,
    {
        let buffer = self.get_raw(ident.erase());

        let root = check_archived_root::<T>(buffer).unwrap();
        root
    }

    /// Gets a reference to the backing bytes of an archived value
    pub fn get_raw(&self, i: &I) -> &[u8] {
        self.inner.get(i)
    }

    /// Persist the storage to a backend
    pub fn persist(&self) -> Result<(), ()> {
        self.inner.persist()
    }

    /// Commit written data, returns an identifier
    pub fn commit(&self, buffer: &mut TokenBuffer) -> I {
        self.inner.commit(buffer)
    }

    /// Request extra space n the underlying buffer
    pub fn extend(&self, buffer: &mut TokenBuffer) -> Result<(), ()> {
        self.inner.extend(buffer)
    }

    /// Accept the token back
    pub fn return_token(&self, token: Token) {
        self.inner.return_token(token)
    }
}

impl<I> StoreProvider<I> for StoreRef<I> {
    fn store(&self) -> &StoreRef<I> {
        self
    }
}

impl<I> Clone for StoreRef<I> {
    fn clone(&self) -> Self {
        Self {
            inner: self.inner.clone(),
        }
    }
}

impl<I> Fallible for StoreRef<I> {
    type Error = Infallible;
}