candid/
ser.rs

1//! Serialize a Rust data structure to Candid binary format
2
3use super::error::{Error, Result};
4use super::types;
5#[cfg(feature = "value")]
6use super::types::value::IDLValue;
7use super::types::{internal::Opcode, Field, Type, TypeEnv, TypeInner};
8use byteorder::{LittleEndian, WriteBytesExt};
9use leb128::write::{signed as sleb128_encode, unsigned as leb128_encode};
10use std::collections::{BTreeMap, TryReserveError};
11use std::io;
12use std::vec::Vec;
13
14/// Use this struct to serialize a sequence of Rust values (heterogeneous) to IDL binary message.
15#[derive(Default)]
16pub struct IDLBuilder {
17    type_ser: TypeSerialize,
18    value_ser: ValueSerializer,
19}
20
21impl IDLBuilder {
22    pub fn new() -> Self {
23        // We cannot share the memo table across different Builder. Because the same Rust
24        // type can map to a different but equivalent candid type for different builder,
25        // due to memo match happening in different time/order.
26        types::internal::env_clear();
27        IDLBuilder {
28            type_ser: TypeSerialize::new(),
29            value_ser: ValueSerializer::new(),
30        }
31    }
32    pub fn arg<'a, T: types::CandidType>(&'a mut self, value: &T) -> Result<&'a mut Self> {
33        self.type_ser.push_type(&T::ty())?;
34        value.idl_serialize(&mut self.value_ser)?;
35        Ok(self)
36    }
37    #[cfg_attr(docsrs, doc(cfg(feature = "value")))]
38    #[cfg(feature = "value")]
39    pub fn value_arg<'a>(&'a mut self, value: &IDLValue) -> Result<&'a mut Self> {
40        use super::CandidType;
41        self.type_ser.push_type(&value.value_ty())?;
42        value.idl_serialize(&mut self.value_ser)?;
43        Ok(self)
44    }
45    #[cfg_attr(docsrs, doc(cfg(feature = "value")))]
46    #[cfg(feature = "value")]
47    /// Annotate IDLValue with (TypeEnv, Type). Note that the TypeEnv will be added to the serializer state.
48    /// If the Type can already be resolved by previous TypeEnvs, you don't need to pass TypeEnv again.
49    pub fn value_arg_with_type<'a>(
50        &'a mut self,
51        value: &IDLValue,
52        env: &TypeEnv,
53        t: &Type,
54    ) -> Result<&'a mut Self> {
55        use super::CandidType;
56        let env = self.type_ser.env.merge(env)?;
57        let v = value.annotate_type(true, env, t)?;
58        self.type_ser.push_type(t)?;
59        v.idl_serialize(&mut self.value_ser)?;
60        Ok(self)
61    }
62    pub fn serialize<W: io::Write>(&mut self, mut writer: W) -> Result<()> {
63        writer.write_all(b"DIDL")?;
64        self.type_ser.serialize()?;
65        writer.write_all(self.type_ser.get_result())?;
66        writer.write_all(self.value_ser.get_result())?;
67        Ok(())
68    }
69    pub fn serialize_to_vec(&mut self) -> Result<Vec<u8>> {
70        let mut vec = Vec::new();
71        self.serialize(&mut vec)?;
72        Ok(vec)
73    }
74    /// If serializing a large amount of data, you can try to reserve the capacity of the
75    /// value serializer ahead of time to avoid reallocation.
76    pub fn try_reserve_value_serializer_capacity(
77        &mut self,
78        additional: usize,
79    ) -> std::result::Result<(), TryReserveError> {
80        self.value_ser.try_reserve(additional)
81    }
82}
83
84/// A structure for serializing Rust values to IDL.
85#[derive(Default)]
86pub struct ValueSerializer {
87    value: Vec<u8>,
88}
89
90impl ValueSerializer {
91    /// Creates a new IDL serializer.
92    #[inline]
93    pub fn new() -> Self {
94        ValueSerializer { value: Vec::new() }
95    }
96    pub fn get_result(&self) -> &[u8] {
97        &self.value
98    }
99    #[doc(hidden)]
100    pub fn write_leb128(&mut self, value: u64) -> Result<()> {
101        leb128_encode(&mut self.value, value)?;
102        Ok(())
103    }
104    #[doc(hidden)]
105    pub fn write(&mut self, bytes: &[u8]) -> Result<()> {
106        use std::io::Write;
107        self.value.write_all(bytes)?;
108        Ok(())
109    }
110    #[doc(hidden)]
111    pub fn try_reserve(&mut self, additional: usize) -> std::result::Result<(), TryReserveError> {
112        self.value.try_reserve(additional)
113    }
114}
115
116macro_rules! serialize_num {
117    ($name:ident, $ty:ty, $($method:tt)*) => {
118        paste::item! {
119            fn [<serialize_ $name>](self, v: $ty) -> Result<()> {
120                self.value.$($method)*(v)?;
121                Ok(())
122            }
123        }
124    };
125}
126
127impl<'a> types::Serializer for &'a mut ValueSerializer {
128    type Error = Error;
129    type Compound = Compound<'a>;
130    fn serialize_bool(self, v: bool) -> Result<()> {
131        self.write(&[v as u8])?;
132        Ok(())
133    }
134    #[cfg(feature = "bignum")]
135    fn serialize_int(self, v: &crate::Int) -> Result<()> {
136        v.encode(&mut self.value)
137    }
138    #[cfg(feature = "bignum")]
139    fn serialize_nat(self, v: &crate::Nat) -> Result<()> {
140        v.encode(&mut self.value)
141    }
142    fn serialize_i128(self, v: i128) -> Result<()> {
143        crate::types::leb128::encode_int(&mut self.value, v)
144    }
145    fn serialize_u128(self, v: u128) -> Result<()> {
146        crate::types::leb128::encode_nat(&mut self.value, v)
147    }
148    serialize_num!(nat8, u8, write_u8);
149    serialize_num!(nat16, u16, write_u16::<LittleEndian>);
150    serialize_num!(nat32, u32, write_u32::<LittleEndian>);
151    serialize_num!(nat64, u64, write_u64::<LittleEndian>);
152
153    serialize_num!(int8, i8, write_i8);
154    serialize_num!(int16, i16, write_i16::<LittleEndian>);
155    serialize_num!(int32, i32, write_i32::<LittleEndian>);
156    serialize_num!(int64, i64, write_i64::<LittleEndian>);
157
158    serialize_num!(float32, f32, write_f32::<LittleEndian>);
159    serialize_num!(float64, f64, write_f64::<LittleEndian>);
160
161    fn serialize_text(self, v: &str) -> Result<()> {
162        let buf = v.as_bytes();
163        self.write_leb128(buf.len() as u64)?;
164        self.value.extend_from_slice(buf);
165        Ok(())
166    }
167    fn serialize_null(self, _v: ()) -> Result<()> {
168        Ok(())
169    }
170    fn serialize_empty(self) -> Result<()> {
171        Err(Error::msg("cannot encode empty type"))
172    }
173    fn serialize_principal(self, blob: &[u8]) -> Result<()> {
174        self.write(&[1])?;
175        self.write_leb128(blob.len() as u64)?;
176        self.write(blob)?;
177        Ok(())
178    }
179    fn serialize_function(self, blob: &[u8], meth: &str) -> Result<()> {
180        self.write(&[1])?;
181        self.serialize_principal(blob)?;
182        self.serialize_text(meth)
183    }
184    fn serialize_option<T>(self, v: Option<&T>) -> Result<()>
185    where
186        T: super::CandidType + ?Sized,
187    {
188        match v {
189            None => {
190                self.write_leb128(0)?;
191                Ok(())
192            }
193            Some(v) => {
194                self.write_leb128(1)?;
195                v.idl_serialize(self)
196            }
197        }
198    }
199    fn serialize_variant(self, index: u64) -> Result<Self::Compound> {
200        self.write_leb128(index)?;
201        Ok(Self::Compound { ser: self })
202    }
203    fn serialize_struct(self) -> Result<Self::Compound> {
204        Ok(Self::Compound { ser: self })
205    }
206    fn serialize_vec(self, len: usize) -> Result<Self::Compound> {
207        self.write_leb128(len as u64)?;
208        Ok(Self::Compound { ser: self })
209    }
210    fn serialize_blob(self, blob: &[u8]) -> Result<()> {
211        self.write_leb128(blob.len() as u64)?;
212        self.write(blob)?;
213        Ok(())
214    }
215}
216
217pub struct Compound<'a> {
218    ser: &'a mut ValueSerializer,
219}
220impl types::Compound for Compound<'_> {
221    type Error = Error;
222    fn serialize_element<T>(&mut self, value: &T) -> Result<()>
223    where
224        T: types::CandidType + ?Sized,
225    {
226        value.idl_serialize(&mut *self.ser)?;
227        Ok(())
228    }
229    fn serialize_blob(&mut self, blob: &[u8]) -> Result<()> {
230        use crate::types::Serializer;
231        self.ser.serialize_blob(blob)
232    }
233}
234
235/// A structure for serializing Rust values to IDL types.
236#[derive(Default)]
237pub struct TypeSerialize {
238    type_table: Vec<Vec<u8>>,
239    type_map: BTreeMap<Type, i32>,
240    env: TypeEnv,
241    args: Vec<Type>,
242    result: Vec<u8>,
243}
244
245impl TypeSerialize {
246    #[inline]
247    pub fn new() -> Self {
248        TypeSerialize {
249            type_table: Vec::new(),
250            type_map: BTreeMap::new(),
251            env: TypeEnv::new(),
252            args: Vec::new(),
253            result: Vec::new(),
254        }
255    }
256    pub fn get_result(&self) -> &[u8] {
257        &self.result
258    }
259    #[inline]
260    fn build_type(&mut self, t: &Type) -> Result<()> {
261        if self.type_map.contains_key(t) {
262            return Ok(());
263        }
264        let actual_type = if let TypeInner::Var(id) = t.as_ref() {
265            self.env.rec_find_type(id)?
266        } else {
267            t
268        }
269        .clone();
270        if types::internal::is_primitive(&actual_type) {
271            return Ok(());
272        }
273        // This is a hack to remove (some) equivalent mu types
274        // from the type table.
275        // Someone should implement Pottier's O(nlogn) algorithm
276        // http://gallium.inria.fr/~fpottier/publis/gauthier-fpottier-icfp04.pdf
277        // Disable this "optimization", as unroll is expensive and has to be called on every recursion.
278        // let unrolled = types::internal::unroll(t);
279        // if let Some(idx) = self.type_map.get(&unrolled) {
280        //    let idx = *idx;
281        //    self.type_map.insert(t.clone(), idx);
282        //    return Ok(());
283        // }
284
285        let idx = self.type_table.len();
286        self.type_map.insert(t.clone(), idx as i32);
287        self.type_table.push(Vec::new());
288        let mut buf = Vec::new();
289        match actual_type.as_ref() {
290            TypeInner::Opt(ref ty) => {
291                self.build_type(ty)?;
292                sleb128_encode(&mut buf, Opcode::Opt as i64)?;
293                self.encode(&mut buf, ty)?;
294            }
295            TypeInner::Vec(ref ty) => {
296                self.build_type(ty)?;
297                sleb128_encode(&mut buf, Opcode::Vec as i64)?;
298                self.encode(&mut buf, ty)?;
299            }
300            TypeInner::Record(fs) => {
301                for Field { ty, .. } in fs {
302                    self.build_type(ty)?;
303                }
304
305                sleb128_encode(&mut buf, Opcode::Record as i64)?;
306                leb128_encode(&mut buf, fs.len() as u64)?;
307                for Field { id, ty } in fs {
308                    leb128_encode(&mut buf, u64::from(id.get_id()))?;
309                    self.encode(&mut buf, ty)?;
310                }
311            }
312            TypeInner::Variant(fs) => {
313                for Field { ty, .. } in fs {
314                    self.build_type(ty)?;
315                }
316
317                sleb128_encode(&mut buf, Opcode::Variant as i64)?;
318                leb128_encode(&mut buf, fs.len() as u64)?;
319                for Field { id, ty } in fs {
320                    leb128_encode(&mut buf, u64::from(id.get_id()))?;
321                    self.encode(&mut buf, ty)?;
322                }
323            }
324            TypeInner::Service(ref ms) => {
325                for (_, ty) in ms {
326                    self.build_type(ty)?;
327                }
328                sleb128_encode(&mut buf, Opcode::Service as i64)?;
329                leb128_encode(&mut buf, ms.len() as u64)?;
330                for (id, ty) in ms {
331                    let name = id.as_bytes();
332                    leb128_encode(&mut buf, name.len() as u64)?;
333                    buf.extend_from_slice(name);
334                    self.encode(&mut buf, ty)?;
335                }
336            }
337            TypeInner::Func(ref func) => {
338                for ty in func.args.iter().chain(func.rets.iter()) {
339                    self.build_type(ty)?;
340                }
341                for ty in &func.rets {
342                    self.build_type(ty)?;
343                }
344                sleb128_encode(&mut buf, Opcode::Func as i64)?;
345                leb128_encode(&mut buf, func.args.len() as u64)?;
346                for ty in &func.args {
347                    self.encode(&mut buf, ty)?;
348                }
349                leb128_encode(&mut buf, func.rets.len() as u64)?;
350                for ty in &func.rets {
351                    self.encode(&mut buf, ty)?;
352                }
353                leb128_encode(&mut buf, func.modes.len() as u64)?;
354                for m in &func.modes {
355                    use crate::types::FuncMode;
356                    let m = match m {
357                        FuncMode::Query => 1,
358                        FuncMode::Oneway => 2,
359                        FuncMode::CompositeQuery => 3,
360                    };
361                    sleb128_encode(&mut buf, m)?;
362                }
363            }
364            _ => unreachable!(),
365        };
366        self.type_table[idx] = buf;
367        Ok(())
368    }
369    #[doc(hidden)]
370    pub fn push_type(&mut self, t: &Type) -> Result<()> {
371        self.args.push(t.clone());
372        self.build_type(t)
373    }
374    fn encode(&self, buf: &mut Vec<u8>, t: &Type) -> Result<()> {
375        if let TypeInner::Var(id) = t.as_ref() {
376            let actual_type = self.env.rec_find_type(id)?;
377            if types::internal::is_primitive(actual_type) {
378                return self.encode(buf, actual_type);
379            }
380        }
381        match t.as_ref() {
382            TypeInner::Null => sleb128_encode(buf, Opcode::Null as i64),
383            TypeInner::Bool => sleb128_encode(buf, Opcode::Bool as i64),
384            TypeInner::Nat => sleb128_encode(buf, Opcode::Nat as i64),
385            TypeInner::Int => sleb128_encode(buf, Opcode::Int as i64),
386            TypeInner::Nat8 => sleb128_encode(buf, Opcode::Nat8 as i64),
387            TypeInner::Nat16 => sleb128_encode(buf, Opcode::Nat16 as i64),
388            TypeInner::Nat32 => sleb128_encode(buf, Opcode::Nat32 as i64),
389            TypeInner::Nat64 => sleb128_encode(buf, Opcode::Nat64 as i64),
390            TypeInner::Int8 => sleb128_encode(buf, Opcode::Int8 as i64),
391            TypeInner::Int16 => sleb128_encode(buf, Opcode::Int16 as i64),
392            TypeInner::Int32 => sleb128_encode(buf, Opcode::Int32 as i64),
393            TypeInner::Int64 => sleb128_encode(buf, Opcode::Int64 as i64),
394            TypeInner::Float32 => sleb128_encode(buf, Opcode::Float32 as i64),
395            TypeInner::Float64 => sleb128_encode(buf, Opcode::Float64 as i64),
396            TypeInner::Text => sleb128_encode(buf, Opcode::Text as i64),
397            TypeInner::Reserved => sleb128_encode(buf, Opcode::Reserved as i64),
398            TypeInner::Empty => sleb128_encode(buf, Opcode::Empty as i64),
399            TypeInner::Principal => sleb128_encode(buf, Opcode::Principal as i64),
400            TypeInner::Knot(ref id) => {
401                let ty = types::internal::find_type(id)
402                    .ok_or_else(|| Error::msg("knot TypeId not found"))?;
403                let idx = self
404                    .type_map
405                    .get(&ty)
406                    .ok_or_else(|| Error::msg(format!("knot type {ty} not found")))?;
407                sleb128_encode(buf, i64::from(*idx))
408            }
409            TypeInner::Var(_) => {
410                let idx = self
411                    .type_map
412                    .get(t)
413                    .ok_or_else(|| Error::msg(format!("var type {t} not found")))?;
414                sleb128_encode(buf, i64::from(*idx))
415            }
416            TypeInner::Future => unreachable!(),
417            _ => {
418                let idx = self
419                    .type_map
420                    .get(t)
421                    .ok_or_else(|| Error::msg(format!("type {t} not found")))?;
422                sleb128_encode(buf, i64::from(*idx))
423            }
424        }?;
425        Ok(())
426    }
427    #[doc(hidden)]
428    pub fn serialize(&mut self) -> Result<()> {
429        leb128_encode(&mut self.result, self.type_table.len() as u64)?;
430        self.result.append(&mut self.type_table.concat());
431
432        leb128_encode(&mut self.result, self.args.len() as u64)?;
433        let mut ty_encode = Vec::new();
434        for t in &self.args {
435            self.encode(&mut ty_encode, t)?;
436        }
437        self.result.append(&mut ty_encode);
438        Ok(())
439    }
440}