tlb/lib.rs
1#![doc = include_str!("../README.md")]
2//! ## Example
3//!
4//! Consider the following TL-B schema:
5//!
6//! ```tlb
7//! tag$10 query_id:uint64 amount:(VarUInteger 16) payload:(Maybe ^Cell) = Hello;
8//! ```
9//!
10//! Let's first define a struct `Hello` that holds these parameters:
11//!
12//! ```rust
13//! # use num_bigint::BigUint;
14//! # use tlb::Cell;
15//! struct Hello {
16//! pub query_id: u64,
17//! pub amount: BigUint,
18//! pub payload: Option<Cell>,
19//! }
20//! ```
21//!
22//! ### **Ser**ialization
23//!
24//! To be able to **ser**ialize a type to [`Cell`], we should implement
25//! [`CellSerialize`](crate::ser::CellSerialize) on it:
26//!
27//! ```
28//! # use num_bigint::BigUint;
29//! # use tlb::{
30//! # r#as::Ref,
31//! # bits::{r#as::{NBits, VarInt}, ser::BitWriterExt},
32//! # Cell,
33//! # ser::{CellSerialize, CellBuilder, CellBuilderError, CellSerializeExt},
34//! # StringError,
35//! # };
36//! #
37//! # struct Hello {
38//! # pub query_id: u64,
39//! # pub amount: BigUint,
40//! # pub payload: Option<Cell>,
41//! # }
42//! impl CellSerialize for Hello {
43//! fn store(&self, builder: &mut CellBuilder) -> Result<(), CellBuilderError> {
44//! builder
45//! // tag$10
46//! .pack_as::<_, NBits<2>>(0b10)?
47//! // query_id:uint64
48//! .pack(self.query_id)?
49//! // amount:(VarUInteger 16)
50//! .pack_as::<_, &VarInt<4>>(&self.amount)?
51//! // payload:(Maybe ^Cell)
52//! .store_as::<_, Option<Ref>>(self.payload.as_ref())?;
53//! Ok(())
54//! }
55//! }
56//!
57//! # fn main() -> Result<(), StringError> {
58//! // serialize value into cell
59//! let hello = Hello {
60//! query_id: 0,
61//! amount: 1_000u64.into(),
62//! payload: None,
63//! };
64//! let cell = hello.to_cell()?;
65//! # Ok(())
66//! # }
67//! ```
68//!
69//! ### **De**serialization
70//!
71//! To be able to **de**serialize a type from [`Cell`], we should implement
72//! [`CellDeserialize`](crate::de::CellDeserialize) on it:
73//!
74//! ```rust
75//! # use num_bigint::BigUint;
76//! # use tlb::{
77//! # r#as::{Ref, ParseFully},
78//! # bits::{r#as::{NBits, VarInt}, de::BitReaderExt, ser::BitWriterExt},
79//! # Cell,
80//! # de::{CellDeserialize, CellParser, CellParserError},
81//! # Error,
82//! # ser::{CellSerialize, CellBuilder, CellBuilderError, CellSerializeExt},
83//! # StringError,
84//! # };
85//! # #[derive(Debug, PartialEq)]
86//! # struct Hello {
87//! # pub query_id: u64,
88//! # pub amount: BigUint,
89//! # pub payload: Option<Cell>,
90//! # }
91//! # impl CellSerialize for Hello {
92//! # fn store(&self, builder: &mut CellBuilder) -> Result<(), CellBuilderError> {
93//! # builder
94//! # // tag$10
95//! # .pack_as::<_, NBits<2>>(0b10)?
96//! # // query_id:uint64
97//! # .pack(self.query_id)?
98//! # // amount:(VarUInteger 16)
99//! # .pack_as::<_, &VarInt<4>>(&self.amount)?
100//! # // payload:(Maybe ^Cell)
101//! # .store_as::<_, Option<Ref>>(self.payload.as_ref())?;
102//! # Ok(())
103//! # }
104//! # }
105//! impl<'de> CellDeserialize<'de> for Hello {
106//! fn parse(parser: &mut CellParser<'de>) -> Result<Self, CellParserError<'de>> {
107//! // tag$10
108//! let tag: u8 = parser.unpack_as::<_, NBits<2>>()?;
109//! if tag != 0b10 {
110//! return Err(Error::custom(format!("unknown tag: {tag:#b}")));
111//! }
112//! Ok(Self {
113//! // query_id:uint64
114//! query_id: parser.unpack()?,
115//! // amount:(VarUInteger 16)
116//! amount: parser.unpack_as::<_, VarInt<4>>()?,
117//! // payload:(Maybe ^Cell)
118//! payload: parser.parse_as::<_, Option<Ref<ParseFully>>>()?,
119//! })
120//! }
121//! }
122//!
123//! # fn main() -> Result<(), StringError> {
124//! # let orig = Hello {
125//! # query_id: 0,
126//! # amount: 1_000u64.into(),
127//! # payload: None,
128//! # };
129//! # let cell = orig.to_cell()?;
130//! let mut parser = cell.parser();
131//! let hello: Hello = parser.parse()?;
132//! # assert_eq!(hello, orig);
133//! # Ok(())
134//! # }
135//! ```
136pub mod r#as;
137mod boc;
138mod cell;
139pub mod de;
140pub mod ser;
141
142pub use self::{boc::*, cell::*};
143
144pub use tlbits::{self as bits, Context, Error, StringError, either};
145
146#[cfg(test)]
147mod tests;