cbor_data/builder/
writers.rs

1use super::low_level::Bytes;
2use crate::Writer;
3use std::marker::PhantomData;
4
5/// Builder for an array value, used by `write_array_ret()`.
6///
7/// see [`trait Encoder`](trait.Encoder.html) for usage examples
8pub struct ArrayWriter<'a> {
9    bytes: Bytes<'a>,
10    count: u64,
11    max_definite: Option<u64>,
12}
13
14impl<'a> ArrayWriter<'a> {
15    pub(crate) fn new(bytes: &'a mut Vec<u8>, max_definite: Option<u64>) -> Self {
16        Self {
17            bytes: Bytes::Borrowed(bytes),
18            count: 0,
19            max_definite,
20        }
21    }
22    fn non_tracking(&mut self, max_definite: Option<u64>) -> ArrayWriter {
23        ArrayWriter {
24            bytes: self.bytes.copy(),
25            count: 0,
26            max_definite,
27        }
28    }
29    /// Configure the limit above which indefinite size encoding will be used.
30    ///
31    /// The default is 255, which is the largest size up to which definite size is at least as
32    /// compact as indefinite size. Set to 23 to avoid moving bytes around when finishing the array.
33    /// Set to `None` to always use indefinite size encoding.
34    pub fn set_max_definite_size(&mut self, size: Option<u64>) {
35        self.max_definite = size;
36    }
37
38    pub(crate) fn count(&self) -> u64 {
39        self.count
40    }
41}
42
43impl<'a> Writer for ArrayWriter<'a> {
44    type Output = Self;
45
46    fn bytes<T>(&mut self, f: impl FnOnce(&mut Vec<u8>) -> T) -> T {
47        self.count += 1;
48        f(self.bytes.as_mut())
49    }
50
51    fn into_output(self) -> Self::Output {
52        self
53    }
54
55    fn max_definite(&self) -> Option<u64> {
56        self.max_definite
57    }
58
59    fn set_max_definite(&mut self, max: Option<u64>) {
60        self.max_definite = max;
61    }
62}
63
64/// Builder for a dict value, used by `write_dict_rec()`.
65///
66/// see [`trait Encoder`](trait.Encoder.html) for usage examples
67pub struct DictWriter<'a>(ArrayWriter<'a>);
68
69impl<'a> DictWriter<'a> {
70    pub(crate) fn new(bytes: &'a mut Vec<u8>, max_definite: Option<u64>) -> Self {
71        Self(ArrayWriter::new(bytes, max_definite))
72    }
73
74    pub(crate) fn count(&self) -> u64 {
75        self.0.count
76    }
77
78    pub fn max_definite(&self) -> Option<u64> {
79        self.0.max_definite
80    }
81
82    /// Configure the limit above which indefinite size encoding will be used.
83    ///
84    /// The default is 255, which is the largest size up to which definite size is at least as
85    /// compact as indefinite size. Set to 23 to avoid moving bytes around when finishing the array.
86    /// Set to `None` to always use indefinite size encoding.
87    pub fn set_max_definite_size(&mut self, size: Option<u64>) {
88        self.0.max_definite = size;
89    }
90
91    /// Add one key–value pair to the dict.
92    ///
93    /// ```
94    /// # use cbor_data::{CborBuilder, Writer, Encoder};
95    /// let cbor = CborBuilder::new().encode_dict(|builder| {
96    ///     builder.with_key("the answer", |b| b.encode_u64(42));
97    /// });
98    /// ```
99    pub fn with_key(
100        &mut self,
101        key: &str,
102        f: impl FnOnce(SingleBuilder<'_, '_>) -> SingleResult,
103    ) -> &mut Self {
104        self.with_cbor_key(|b| b.write_str(key, None), f)
105    }
106
107    pub fn with_cbor_key(
108        &mut self,
109        k: impl FnOnce(SingleBuilder<'_, '_>) -> SingleResult,
110        v: impl FnOnce(SingleBuilder<'_, '_>) -> SingleResult,
111    ) -> &mut Self {
112        k(SingleBuilder(&mut self.0.non_tracking(self.0.max_definite)));
113        v(SingleBuilder(&mut self.0));
114        self
115    }
116
117    pub fn try_write_pair<E>(
118        &mut self,
119        f: impl FnOnce(KeyBuilder<'_, '_>) -> Result<SingleResult, E>,
120    ) -> Result<&mut Self, E> {
121        f(KeyBuilder(&mut self.0))?;
122        Ok(self)
123    }
124}
125
126/// Builder for the first step of [`try_write_pair`](struct.DictWriter.html#method.try_write_pair)
127///
128/// This builder can be used for exactly one item (which may be a complex one, like an array)
129/// and returns a [`SingleBuilder`](struct.SingleBuilder.html) that needs to be used to write
130/// the value for this dictionary entry.
131pub struct KeyBuilder<'a, 'b>(&'b mut ArrayWriter<'a>);
132
133impl<'a, 'b> Writer for KeyBuilder<'a, 'b> {
134    type Output = SingleBuilder<'a, 'b>;
135
136    fn bytes<T>(&mut self, f: impl FnOnce(&mut Vec<u8>) -> T) -> T {
137        self.0.non_tracking(self.0.max_definite).bytes(f)
138    }
139
140    fn into_output(self) -> Self::Output {
141        SingleBuilder(self.0)
142    }
143
144    fn max_definite(&self) -> Option<u64> {
145        self.0.max_definite
146    }
147
148    fn set_max_definite(&mut self, max: Option<u64>) {
149        self.0.set_max_definite(max);
150    }
151}
152
153/// Builder for the single value of a dict key.
154///
155/// This builder can be used for exactly one item (which may be a complex one, like an array)
156/// and returns a [`SingleResult`](struct.SingleResult.html) to prove to its
157/// [`DictWriter`](struct.DictWriter.html) that it has been used.
158pub struct SingleBuilder<'a, 'b>(&'b mut ArrayWriter<'a>);
159
160/// Result value of using a [`SingleBuilder`](struct.SingleBuilder.html) proving that it has been used.
161///
162/// This value needs to be returned to [`DictWriter.with_key()`](struct.DictWriter.html#method.with_key).
163/// You can only obtain it by using the `SingleBuilder`.
164pub struct SingleResult {
165    ph: PhantomData<u8>,
166}
167
168impl<'a, 'b> Writer for SingleBuilder<'a, 'b> {
169    type Output = SingleResult;
170
171    fn bytes<T>(&mut self, f: impl FnOnce(&mut Vec<u8>) -> T) -> T {
172        self.0.bytes(f)
173    }
174
175    fn into_output(self) -> Self::Output {
176        SingleResult { ph: PhantomData }
177    }
178
179    fn max_definite(&self) -> Option<u64> {
180        self.0.max_definite
181    }
182
183    fn set_max_definite(&mut self, max: Option<u64>) {
184        self.0.set_max_definite(max);
185    }
186}