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
use std::borrow::Cow;
use std::ffi::CStr;
use std::io;

use lmdb_zero::traits::AsLmdbBytes;

#[cfg(feature = "hash")]
mod hash;

#[cfg(feature = "block")]
mod block;

#[cfg(feature = "account")]
mod accounts;

#[cfg(feature = "keys")]
mod keys;

pub trait IntoDatabaseValue {
    fn database_byte_size(&self) -> usize;
    fn copy_into_database(&self, bytes: &mut [u8]);
}

pub trait FromDatabaseValue {
    fn copy_from_database(bytes: &[u8]) -> io::Result<Self> where Self: Sized;
}

pub trait AsDatabaseBytes {
    fn as_database_bytes(&self) -> Cow<[u8]>;
}

// Trait implementations
impl IntoDatabaseValue for [u8] {
    fn database_byte_size(&self) -> usize {
        self.len()
    }

    fn copy_into_database(&self, bytes: &mut [u8]) {
        bytes.copy_from_slice(self);
    }
}

impl IntoDatabaseValue for str {
    fn database_byte_size(&self) -> usize {
        self.len()
    }

    fn copy_into_database(&self, bytes: &mut [u8]) {
        bytes.copy_from_slice(self.as_bytes());
    }
}

impl FromDatabaseValue for String {
    fn copy_from_database(bytes: &[u8]) -> io::Result<Self> where Self: Sized {
        Ok(String::from_utf8(bytes.to_vec()).unwrap())
    }
}

impl FromDatabaseValue for u32 {
    fn copy_from_database(bytes: &[u8]) -> io::Result<Self> where Self: Sized {
        let lmdb_result: Result<&lmdb_zero::Unaligned<u32>, String> = lmdb_zero::traits::FromLmdbBytes::from_lmdb_bytes(bytes);
        Ok(lmdb_result.map_err(|e| io::Error::new(io::ErrorKind::Other, e))?.get())
    }
}

// Conflicting implementation:
//impl<T> FromDatabaseValue for T
//    where T: lmdb_zero::traits::FromLmdbBytes + ?Sized {
//    fn copy_from_database(bytes: &[u8]) -> io::Result<Self> where Self: Sized {
//        Ok(lmdb_zero::traits::FromLmdbBytes::from_lmdb_bytes(bytes).map_err(|e| io::Error::new(io::ErrorKind::Other, e))?.to_owned())
//    }
//}

//impl<T> AsDatabaseBytes for T
//    where T: lmdb_zero::traits::AsLmdbBytes + ?Sized {
//    fn as_database_bytes(&self) -> Cow<[u8]> {
//        return Cow::Borrowed(self.as_lmdb_bytes());
//    }
//}

macro_rules! as_lmdb_bytes {
    ($t: ty) => {
impl AsDatabaseBytes for $t {
    fn as_database_bytes(&self) -> Cow<[u8]> {
        return Cow::Borrowed(self.as_lmdb_bytes());
    }
}
    };
}

as_lmdb_bytes!(u16);
as_lmdb_bytes!(i16);
as_lmdb_bytes!(u32);
as_lmdb_bytes!(i32);
as_lmdb_bytes!(u64);
as_lmdb_bytes!(i64);
as_lmdb_bytes!(f32);
as_lmdb_bytes!(f64);
as_lmdb_bytes!(str);
as_lmdb_bytes!(CStr);
as_lmdb_bytes!(char);

as_lmdb_bytes!([u16]);
as_lmdb_bytes!([i16]);
as_lmdb_bytes!([u32]);
as_lmdb_bytes!([i32]);
as_lmdb_bytes!([u64]);
as_lmdb_bytes!([i64]);
as_lmdb_bytes!([f32]);
as_lmdb_bytes!([f64]);
as_lmdb_bytes!([char]);