armour/types/
entry.rs

1use rapira::{Rapira, RapiraError};
2use serde::Serialize;
3
4use crate::{Cid, Record};
5
6#[derive(Clone, Debug, Serialize)]
7pub struct Entry<Val: Record> {
8    #[serde(flatten)]
9    pub key: Val::SelfId,
10    #[serde(flatten)]
11    pub val: Val,
12}
13
14impl<Val: Record> Entry<Val> {
15    pub fn new(key: Val::SelfId, val: Val) -> Self {
16        Self { key, val }
17    }
18
19    pub fn get_id(self) -> Val::SelfId {
20        self.key
21    }
22    pub fn get_val(&self) -> &Val {
23        &self.val
24    }
25    pub fn split(self) -> (Val::SelfId, Val) {
26        let Self { key, val } = self;
27        (key, val)
28    }
29
30    pub fn split_ref(&self) -> (&Val::SelfId, &Val) {
31        let Self { key, val } = &self;
32        (key, val)
33    }
34}
35
36impl<Val: Record> From<(Val::SelfId, Val)> for Entry<Val> {
37    fn from(tuple: (Val::SelfId, Val)) -> Self {
38        Self::new(tuple.0, tuple.1)
39    }
40}
41
42const fn a_b_size(a: Option<usize>, b: Option<usize>) -> Option<usize> {
43    match a {
44        Some(s) => match b {
45            Some(ss) => Some(s + ss),
46            None => None,
47        },
48        None => None,
49    }
50}
51
52impl<Val> Rapira for Entry<Val>
53where
54    Val: Record + Rapira,
55    <Val::SelfId as Cid>::B: Rapira,
56{
57    const STATIC_SIZE: Option<usize> =
58        a_b_size(Val::STATIC_SIZE, <Val::SelfId as Cid>::B::STATIC_SIZE);
59    const MIN_SIZE: usize = {
60        let a = Val::MIN_SIZE;
61        let b = <Val::SelfId as Cid>::B::MIN_SIZE;
62        a + b
63    };
64
65    fn size(&self) -> usize {
66        match Self::STATIC_SIZE {
67            Some(s) => s,
68            // None => self.key.bytes().as_ref().len(),
69            None => self.key.encode().size() + self.val.size(),
70        }
71    }
72
73    fn check_bytes(slice: &mut &[u8]) -> rapira::Result<()> {
74        <Val::SelfId as Cid>::B::check_bytes(slice)?;
75        Val::check_bytes(slice)?;
76        Ok(())
77    }
78
79    unsafe fn from_slice_unchecked(slice: &mut &[u8]) -> rapira::Result<Self>
80    where
81        Self: Sized,
82    {
83        unsafe {
84            let key = <Val::SelfId as Cid>::B::from_slice_unchecked(slice)?;
85            let key = <Val::SelfId>::from_bytes(key.as_ref())
86                .map_err(|_| RapiraError::Other("Cid::from_bytes error"))?;
87            let val = Val::from_slice_unchecked(slice)?;
88            Ok(Entry::new(key, val))
89        }
90    }
91
92    fn from_slice(slice: &mut &[u8]) -> rapira::Result<Self>
93    where
94        Self: Sized,
95    {
96        let key = <Val::SelfId as Cid>::B::from_slice(slice)?;
97        let key = <Val::SelfId>::from_bytes(key.as_ref())
98            .map_err(|_| RapiraError::Other("Entry Cid error"))?;
99        let val = Val::from_slice(slice)?;
100        Ok(Self::new(key, val))
101    }
102
103    unsafe fn from_slice_unsafe(slice: &mut &[u8]) -> rapira::Result<Self>
104    where
105        Self: Sized,
106    {
107        unsafe {
108            let key = <Val::SelfId as Cid>::B::from_slice_unsafe(slice)?;
109            let key = <Val::SelfId>::from_bytes_unsafe(key.as_ref());
110            let val = Val::from_slice_unsafe(slice)?;
111            Ok(Self::new(key, val))
112        }
113    }
114
115    fn convert_to_bytes(&self, slice: &mut [u8], cursor: &mut usize) {
116        self.key.encode().convert_to_bytes(slice, cursor);
117        self.val.convert_to_bytes(slice, cursor);
118    }
119
120    fn try_convert_to_bytes(&self, slice: &mut [u8], cursor: &mut usize) -> rapira::Result<()> {
121        self.key.encode().try_convert_to_bytes(slice, cursor)?;
122        self.val.try_convert_to_bytes(slice, cursor)?;
123        Ok(())
124    }
125}
126
127#[cfg(feature = "ts")]
128impl<Val> TypeDef for Entry<Val>
129where
130    Self: 'static,
131    Val: Record + TypeDef,
132    Val::SelfId: TypeDef,
133{
134    const INFO: TypeInfo = TypeInfo::Defined(DefinedTypeInfo {
135        def: TypeDefinition {
136            docs: None,
137            path: &[],
138            name: Ident("Entry"),
139            generic_vars: &[Ident("T"), Ident("Id")],
140            def: TypeExpr::Intersection(TypeIntersection {
141                docs: None,
142                members: &[TypeExpr::Ref(&Val::SelfId::INFO), TypeExpr::Ref(&Val::INFO)],
143            }),
144        },
145        generic_args: &[],
146    });
147}
148
149#[cfg(feature = "ts-rs")]
150mod fake_id {
151    use rapira::Rapira;
152
153    use crate::{GetType, Record};
154
155    #[derive(Debug, PartialOrd, Ord, PartialEq, Eq, Clone, Copy, Hash, ts_rs::TS, Rapira)]
156    pub struct Fake {
157        data: (),
158    }
159
160    impl GetType for Fake {
161        const TYPE: crate::Typ = crate::Typ::Void;
162    }
163
164    impl Record for Fake {
165        type SelfId = crate::Fuid<()>;
166        type Value = Vec<u8>;
167
168        const NAME: &'static str = "fake";
169
170        fn deser(bytes: &[u8]) -> Self {
171            rapira::deserialize(bytes).expect("fake")
172        }
173
174        fn ser(&self) -> Vec<u8> {
175            rapira::serialize(self)
176        }
177    }
178}
179
180// export type Entry<T, ID> = T & ID;
181#[cfg(feature = "ts-rs")]
182impl<Val: Record> ts_rs::TS for Entry<Val>
183where
184    Val: ts_rs::TS,
185    Val::SelfId: ts_rs::TS,
186{
187    type OptionInnerType = Self;
188    type WithoutGenerics = Entry<fake_id::Fake>;
189    fn ident() -> String {
190        "Entry".to_owned()
191    }
192    fn name() -> String {
193        {
194            let val_name = <Val as ts_rs::TS>::name();
195            let id_name = <Val::SelfId as ts_rs::TS>::name();
196            format!("Entry<{val_name}, {id_name}>")
197        }
198    }
199    fn decl_concrete() -> String {
200        Self::decl()
201    }
202    fn decl() -> String {
203        // let entry = <Entry<Val> as ts_rs::TS>::inline();
204        // let val = <Val as ts_rs::TS>::inline();
205        // let key = <Val::SelfId as ts_rs::TS>::inline();
206        // format!("type Entry<Val, Key> = Val & Key;")
207        "type Entry<Val, Key> = Val & Key;".to_string()
208    }
209    fn inline() -> String {
210        <[String]>::join(
211            &[
212                <Val::SelfId as ts_rs::TS>::inline_flattened(),
213                <Val as ts_rs::TS>::inline_flattened(),
214            ],
215            " & ",
216        )
217        .replace(" } & { ", " ")
218    }
219    fn inline_flattened() -> String {
220        Self::inline()
221    }
222    fn visit_generics(v: &mut impl ts_rs::TypeVisitor)
223    where
224        Self: 'static,
225    {
226        v.visit::<Val>();
227        v.visit::<Val::SelfId>();
228        <Val as ts_rs::TS>::visit_generics(v);
229        <Val::SelfId as ts_rs::TS>::visit_generics(v);
230    }
231    fn output_path() -> Option<std::path::PathBuf> {
232        Some(std::path::PathBuf::from("entry.ts"))
233    }
234    fn visit_dependencies(v: &mut impl ts_rs::TypeVisitor)
235    where
236        Self: 'static,
237    {
238        <Val as ts_rs::TS>::visit_dependencies(v);
239        <Val::SelfId as ts_rs::TS>::visit_dependencies(v);
240    }
241
242    fn dependencies() -> Vec<ts_rs::Dependency>
243    where
244        Self: 'static,
245    {
246        let mut deps: Vec<ts_rs::Dependency> = vec![];
247        struct Visit<'a>(&'a mut Vec<ts_rs::Dependency>);
248        impl<'a> ts_rs::TypeVisitor for Visit<'a> {
249            fn visit<T: ts_rs::TS + 'static + ?Sized>(&mut self) {
250                if let Some(dep) = ts_rs::Dependency::from_ty::<T>() {
251                    self.0.push(dep);
252                }
253            }
254        }
255        let mut v = Visit(&mut deps);
256        <Val as ts_rs::TS>::visit_dependencies(&mut v);
257        <Val::SelfId as ts_rs::TS>::visit_dependencies(&mut v);
258
259        vec![]
260    }
261}