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.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#[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 "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}