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
// 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 core::marker::PhantomData;

use crate::canon::{Canon, InvalidEncoding};
use crate::store::{ByteSink, ByteSource, Ident, Sink, Source, Store};

// We set the buffer size to 4kib for now, subject to change.
const BUF_SIZE: usize = 1024 * 4;

static mut BUF: [u8; BUF_SIZE] = [0; BUF_SIZE];

/// Store usable across ffi-boundraries
#[derive(Clone, Default)]
pub struct BridgeStore<I> {
    _marker: PhantomData<I>,
}

impl<I> BridgeStore<I>
where
    I: Ident,
{
    /// Create a new bridge store
    pub fn new() -> Self {
        BridgeStore {
            _marker: PhantomData,
        }
    }
}

#[derive(Debug, Clone)]
pub enum BridgeStoreError {
    InvalidEncoding,
}

impl<S: Store> Canon<S> for BridgeStoreError {
    fn write(&self, _sink: &mut impl Sink<S>) -> Result<(), S::Error> {
        Ok(())
    }

    fn read(_source: &mut impl Source<S>) -> Result<Self, S::Error> {
        Ok(BridgeStoreError::InvalidEncoding)
    }

    fn encoded_len(&self) -> usize {
        0
    }
}

impl From<InvalidEncoding> for BridgeStoreError {
    fn from(_: InvalidEncoding) -> Self {
        BridgeStoreError::InvalidEncoding
    }
}

impl<I> Store for BridgeStore<I>
where
    I: 'static + Ident,
{
    type Ident = I;
    type Error = InvalidEncoding;

    fn fetch(
        &self,
        id: &Self::Ident,
        into: &mut [u8],
    ) -> Result<(), Self::Error> {
        unsafe {
            let slice = id.as_ref();
            let id_len = slice.len();
            // first copy the id into the buffer
            into[0..id_len].copy_from_slice(slice);
            b_get(&mut into[0]);
            Ok(())
        }
    }

    fn get<T: Canon<Self>>(&self, id: &Self::Ident) -> Result<T, Self::Error> {
        unsafe {
            let slice = id.as_ref();
            let id_len = slice.len();
            BUF[0..id_len].copy_from_slice(slice);
            b_get(&mut BUF[0]);
            // b_get has written T into the buffer
            let mut source = ByteSource::new(&BUF[..], self.clone());
            Canon::<Self>::read(&mut source)
        }
    }

    fn put<T: Canon<Self>>(&self, t: &T) -> Result<Self::Ident, Self::Error> {
        unsafe {
            let len = t.encoded_len();
            let mut sink = ByteSink::new(&mut BUF, self.clone());
            Canon::<Self>::write(t, &mut sink)?;
            let mut id = Self::Ident::default();
            b_put(&mut BUF[0], len, &mut id.as_mut()[0]);
            Ok(id)
        }
    }

    fn put_raw(&self, bytes: &[u8]) -> Result<Self::Ident, Self::Error> {
        unsafe {
            let mut id = Self::Ident::default();
            let len = bytes.len();
            BUF[0..len].copy_from_slice(bytes);
            b_put(&mut BUF[0], len, &mut id.as_mut()[0]);
            Ok(id)
        }
    }
}

extern "C" {
    pub fn b_put(buf: &mut u8, len: usize, ret: &mut u8);
    pub fn b_get(buf: &mut u8);
}