tribles/
blob.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
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
pub mod schemas;

use crate::{
    id::RawId,
    value::schemas::hash::{Handle, HashProtocol},
    value::{Value, ValueSchema},
};

use std::{
    fmt::{self, Debug},
    hash::Hash,
    marker::PhantomData,
};

pub use anybytes::Bytes;

#[repr(transparent)]
pub struct Blob<S: BlobSchema> {
    pub bytes: Bytes,
    _schema: PhantomData<S>,
}

impl<S: BlobSchema> Blob<S> {
    pub fn new(bytes: Bytes) -> Self {
        Self {
            bytes,
            _schema: PhantomData,
        }
    }

    pub fn transmute<T: BlobSchema>(&self) -> &Blob<T> {
        unsafe { std::mem::transmute(self) }
    }

    pub fn as_handle<H>(&self) -> Value<Handle<H, S>>
    where
        H: HashProtocol,
        Handle<H, S>: ValueSchema,
    {
        let digest = H::digest(&self.bytes);
        Value::new(digest.into())
    }

    pub fn from_blob<'a, T>(&'a self) -> T
    where
        T: FromBlob<'a, S>,
    {
        <T as FromBlob<'a, S>>::from_blob(self)
    }

    pub fn try_from_blob<'a, T>(&'a self) -> Result<T, <T as TryFromBlob<S>>::Error>
    where
        T: TryFromBlob<'a, S>,
    {
        <T as TryFromBlob<'a, S>>::try_from_blob(self)
    }
}

impl<T: BlobSchema> Clone for Blob<T> {
    fn clone(&self) -> Self {
        Self {
            bytes: self.bytes.clone(),
            _schema: PhantomData,
        }
    }
}

impl<T: BlobSchema> PartialEq for Blob<T> {
    fn eq(&self, other: &Self) -> bool {
        self.bytes == other.bytes
    }
}

impl<T: BlobSchema> Eq for Blob<T> {}

impl<T: BlobSchema> Hash for Blob<T> {
    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
        self.bytes.hash(state);
    }
}

impl<T: BlobSchema> Debug for Blob<T> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "Blob<{}>", std::any::type_name::<T>())
    }
}

pub trait BlobSchema: Sized + 'static {
    const ID: RawId;

    fn to_blob<T: ToBlob<Self>>(t: T) -> Blob<Self> {
        t.to_blob()
    }

    fn try_to_blob<T: TryToBlob<Self>>(t: T) -> Result<Blob<Self>, <T as TryToBlob<Self>>::Error> {
        t.try_to_blob()
    }
}

pub trait ToBlob<S: BlobSchema> {
    fn to_blob(self) -> Blob<S>;
}
pub trait FromBlob<'a, S: BlobSchema> {
    fn from_blob(b: &'a Blob<S>) -> Self;
}

pub trait TryToBlob<S: BlobSchema> {
    type Error;
    fn try_to_blob(&self) -> Result<Blob<S>, Self::Error>;
}

pub trait TryFromBlob<'a, S: BlobSchema>: Sized {
    type Error;
    fn try_from_blob(b: &'a Blob<S>) -> Result<Self, Self::Error>;
}

impl<S: BlobSchema> ToBlob<S> for Blob<S> {
    fn to_blob(self) -> Blob<S> {
        self
    }
}

impl<'a, S: BlobSchema> FromBlob<'a, S> for Blob<S> {
    fn from_blob(b: &'a Blob<S>) -> Self {
        b.clone()
    }
}