rasn/jer/
enc.rs

1//! # Encoding JER.
2
3use jzon::{object::Object, JsonValue};
4
5use crate::{
6    bits::to_vec,
7    enc::Error,
8    error::{EncodeError, JerEncodeErrorKind},
9    types::{fields::Fields, variants},
10};
11
12pub struct Encoder {
13    stack: alloc::vec::Vec<&'static str>,
14    constructed_stack: alloc::vec::Vec<Object>,
15    root_value: Option<JsonValue>,
16}
17
18impl Default for Encoder {
19    fn default() -> Self {
20        Self::new()
21    }
22}
23
24impl Encoder {
25    pub fn new() -> Self {
26        Self {
27            stack: alloc::vec![],
28            constructed_stack: alloc::vec![],
29            root_value: None,
30        }
31    }
32
33    pub fn root_value(self) -> Result<JsonValue, EncodeError> {
34        Ok(self
35            .root_value
36            .ok_or(JerEncodeErrorKind::NoRootValueFound)?)
37    }
38
39    pub fn to_json(self) -> alloc::string::String {
40        self.root_value.map_or(<_>::default(), |v| v.dump())
41    }
42
43    fn update_root_or_constructed(&mut self, value: JsonValue) -> Result<(), EncodeError> {
44        match self.stack.pop() {
45            Some(id) => {
46                self.constructed_stack
47                    .last_mut()
48                    .ok_or_else(|| JerEncodeErrorKind::JsonEncoder {
49                        msg: "Internal stack mismatch!".into(),
50                    })?
51                    .insert(id, value);
52            }
53            None => {
54                self.root_value = Some(value);
55            }
56        };
57        Ok(())
58    }
59}
60
61impl crate::Encoder for Encoder {
62    type Ok = ();
63
64    type Error = EncodeError;
65
66    fn encode_any(
67        &mut self,
68        t: crate::Tag,
69        value: &crate::types::Any,
70    ) -> Result<Self::Ok, Self::Error> {
71        self.encode_octet_string(t, <_>::default(), &value.contents)
72    }
73
74    fn encode_bool(&mut self, _: crate::Tag, value: bool) -> Result<Self::Ok, Self::Error> {
75        self.update_root_or_constructed(JsonValue::Boolean(value))
76    }
77
78    fn encode_bit_string(
79        &mut self,
80        _t: crate::Tag,
81        constraints: crate::types::Constraints,
82        value: &crate::types::BitStr,
83    ) -> Result<Self::Ok, Self::Error> {
84        let bytes = to_vec(value)
85            .iter()
86            .fold(alloc::string::String::new(), |mut acc, bit| {
87                acc.push_str(&alloc::format!("{bit:02X?}"));
88                acc
89            });
90        let json_value = if constraints
91            .size()
92            .map_or(false, |s| s.constraint.is_fixed())
93        {
94            JsonValue::String(bytes)
95        } else {
96            let mut value_map = JsonValue::new_object();
97            value_map
98                .insert("value", bytes)
99                .and(value_map.insert("length", JsonValue::Number(value.len().into())))
100                .map_err(|_| {
101                    EncodeError::custom("Failed to create BitString object!", self.codec())
102                })?;
103            value_map
104        };
105        self.update_root_or_constructed(json_value)
106    }
107
108    fn encode_enumerated<E: crate::types::Enumerated>(
109        &mut self,
110        _: crate::Tag,
111        value: &E,
112    ) -> Result<Self::Ok, Self::Error> {
113        self.update_root_or_constructed(JsonValue::String(alloc::string::String::from(
114            value.identifier(),
115        )))
116    }
117
118    fn encode_object_identifier(
119        &mut self,
120        _t: crate::Tag,
121        value: &[u32],
122    ) -> Result<Self::Ok, Self::Error> {
123        self.update_root_or_constructed(JsonValue::String(
124            value
125                .iter()
126                .map(|arc| alloc::format!("{arc}"))
127                .collect::<alloc::vec::Vec<alloc::string::String>>()
128                .join("."),
129        ))
130    }
131
132    fn encode_integer(
133        &mut self,
134        _t: crate::Tag,
135        _c: crate::types::Constraints,
136        value: &num_bigint::BigInt,
137    ) -> Result<Self::Ok, Self::Error> {
138        let as_i64: i64 =
139            value
140                .try_into()
141                .map_err(|_| JerEncodeErrorKind::ExceedsSupportedIntSize {
142                    value: value.clone(),
143                })?;
144        self.update_root_or_constructed(JsonValue::Number(as_i64.into()))
145    }
146
147    fn encode_null(&mut self, _: crate::Tag) -> Result<Self::Ok, Self::Error> {
148        self.update_root_or_constructed(JsonValue::Null)
149    }
150
151    fn encode_octet_string(
152        &mut self,
153        _t: crate::Tag,
154        _c: crate::types::Constraints,
155        value: &[u8],
156    ) -> Result<Self::Ok, Self::Error> {
157        self.update_root_or_constructed(JsonValue::String(value.iter().fold(
158            alloc::string::String::new(),
159            |mut acc, bit| {
160                acc.push_str(&alloc::format!("{bit:02X?}"));
161                acc
162            },
163        )))
164    }
165
166    fn encode_general_string(
167        &mut self,
168        _t: crate::Tag,
169        _c: crate::types::Constraints,
170        value: &crate::types::GeneralString,
171    ) -> Result<Self::Ok, Self::Error> {
172        self.update_root_or_constructed(JsonValue::String(
173            alloc::string::String::from_utf8(value.to_vec())
174                .map_err(|e| JerEncodeErrorKind::InvalidCharacter { error: e })?,
175        ))
176    }
177
178    fn encode_utf8_string(
179        &mut self,
180        _t: crate::Tag,
181        _c: crate::types::Constraints,
182        value: &str,
183    ) -> Result<Self::Ok, Self::Error> {
184        self.update_root_or_constructed(JsonValue::String(value.into()))
185    }
186
187    fn encode_visible_string(
188        &mut self,
189        _t: crate::Tag,
190        _c: crate::types::Constraints,
191        value: &crate::types::VisibleString,
192    ) -> Result<Self::Ok, Self::Error> {
193        self.update_root_or_constructed(JsonValue::String(
194            alloc::string::String::from_utf8(value.as_iso646_bytes().to_vec())
195                .map_err(|e| JerEncodeErrorKind::InvalidCharacter { error: e })?,
196        ))
197    }
198
199    fn encode_ia5_string(
200        &mut self,
201        _t: crate::Tag,
202        _c: crate::types::Constraints,
203        value: &crate::types::Ia5String,
204    ) -> Result<Self::Ok, Self::Error> {
205        self.update_root_or_constructed(JsonValue::String(
206            alloc::string::String::from_utf8(value.as_iso646_bytes().to_vec())
207                .map_err(|e| JerEncodeErrorKind::InvalidCharacter { error: e })?,
208        ))
209    }
210
211    fn encode_printable_string(
212        &mut self,
213        _t: crate::Tag,
214        _c: crate::types::Constraints,
215        value: &crate::types::PrintableString,
216    ) -> Result<Self::Ok, Self::Error> {
217        self.update_root_or_constructed(JsonValue::String(
218            alloc::string::String::from_utf8(value.as_bytes().to_vec())
219                .map_err(|e| JerEncodeErrorKind::InvalidCharacter { error: e })?,
220        ))
221    }
222
223    fn encode_numeric_string(
224        &mut self,
225        _t: crate::Tag,
226        _c: crate::types::Constraints,
227        value: &crate::types::NumericString,
228    ) -> Result<Self::Ok, Self::Error> {
229        self.update_root_or_constructed(JsonValue::String(
230            alloc::string::String::from_utf8(value.as_bytes().to_vec())
231                .map_err(|e| JerEncodeErrorKind::InvalidCharacter { error: e })?,
232        ))
233    }
234
235    fn encode_teletex_string(
236        &mut self,
237        _t: crate::Tag,
238        _c: crate::types::Constraints,
239        _value: &crate::types::TeletexString,
240    ) -> Result<Self::Ok, Self::Error> {
241        todo!()
242    }
243
244    fn encode_bmp_string(
245        &mut self,
246        _t: crate::Tag,
247        _c: crate::types::Constraints,
248        value: &crate::types::BmpString,
249    ) -> Result<Self::Ok, Self::Error> {
250        self.update_root_or_constructed(JsonValue::String(
251            alloc::string::String::from_utf8(value.to_bytes())
252                .map_err(|e| JerEncodeErrorKind::InvalidCharacter { error: e })?,
253        ))
254    }
255
256    fn encode_generalized_time(
257        &mut self,
258        _t: crate::Tag,
259        value: &crate::types::GeneralizedTime,
260    ) -> Result<Self::Ok, Self::Error> {
261        self.update_root_or_constructed(JsonValue::String(
262            alloc::string::String::from_utf8(
263                crate::ber::enc::Encoder::datetime_to_canonical_generalized_time_bytes(value),
264            )
265            .map_err(|e| JerEncodeErrorKind::InvalidCharacter { error: e })?,
266        ))
267    }
268
269    fn encode_utc_time(
270        &mut self,
271        _t: crate::Tag,
272        value: &crate::types::UtcTime,
273    ) -> Result<Self::Ok, Self::Error> {
274        self.update_root_or_constructed(JsonValue::String(
275            alloc::string::String::from_utf8(
276                crate::ber::enc::Encoder::datetime_to_canonical_utc_time_bytes(value),
277            )
278            .map_err(|e| JerEncodeErrorKind::InvalidCharacter { error: e })?,
279        ))
280    }
281
282    fn encode_explicit_prefix<V: crate::Encode>(
283        &mut self,
284        _: crate::Tag,
285        value: &V,
286    ) -> Result<Self::Ok, Self::Error> {
287        value.encode(self)
288    }
289
290    fn encode_sequence<C, F>(
291        &mut self,
292        __t: crate::Tag,
293        encoder_scope: F,
294    ) -> Result<Self::Ok, Self::Error>
295    where
296        C: crate::types::Constructed,
297        F: FnOnce(&mut Self) -> Result<(), Self::Error>,
298    {
299        let mut field_names = [C::FIELDS, C::EXTENDED_FIELDS.unwrap_or(Fields::empty())]
300            .iter()
301            .flat_map(|f| f.iter())
302            .map(|f| f.name)
303            .collect::<alloc::vec::Vec<&str>>();
304        field_names.reverse();
305        for name in field_names {
306            self.stack.push(name);
307        }
308        self.constructed_stack.push(Object::new());
309        (encoder_scope)(self)?;
310        let value_map =
311            self.constructed_stack
312                .pop()
313                .ok_or_else(|| JerEncodeErrorKind::JsonEncoder {
314                    msg: "Internal stack mismatch!".into(),
315                })?;
316        self.update_root_or_constructed(JsonValue::Object(value_map))
317    }
318
319    fn encode_sequence_of<E: crate::Encode>(
320        &mut self,
321        _t: crate::Tag,
322        value: &[E],
323        _c: crate::types::Constraints,
324    ) -> Result<Self::Ok, Self::Error> {
325        self.update_root_or_constructed(JsonValue::Array(value.iter().try_fold(
326            alloc::vec![],
327            |mut acc, v| {
328                let mut item_encoder = Self::new();
329                v.encode(&mut item_encoder).and(
330                    item_encoder
331                        .root_value()
332                        .map(|rv| acc.push(rv))
333                        .map(|_| acc),
334                )
335            },
336        )?))
337    }
338
339    fn encode_set<C, F>(&mut self, tag: crate::Tag, value: F) -> Result<Self::Ok, Self::Error>
340    where
341        C: crate::types::Constructed,
342        F: FnOnce(&mut Self) -> Result<(), Self::Error>,
343    {
344        self.encode_sequence::<C, F>(tag, value)
345    }
346
347    fn encode_set_of<E: crate::Encode>(
348        &mut self,
349        _t: crate::Tag,
350        value: &crate::types::SetOf<E>,
351        _c: crate::types::Constraints,
352    ) -> Result<Self::Ok, Self::Error> {
353        self.update_root_or_constructed(JsonValue::Array(value.iter().try_fold(
354            alloc::vec![],
355            |mut acc, v| {
356                let mut item_encoder = Self::new();
357                v.encode(&mut item_encoder).and(
358                    item_encoder
359                        .root_value()
360                        .map(|rv| acc.push(rv))
361                        .map(|_| acc),
362                )
363            },
364        )?))
365    }
366
367    fn encode_some<E: crate::Encode>(&mut self, value: &E) -> Result<Self::Ok, Self::Error> {
368        value.encode(self)
369    }
370
371    fn encode_some_with_tag_and_constraints<E: crate::Encode>(
372        &mut self,
373        _t: crate::Tag,
374        _c: crate::types::Constraints,
375        value: &E,
376    ) -> Result<Self::Ok, Self::Error> {
377        value.encode(self)
378    }
379
380    fn encode_none<E: crate::Encode>(&mut self) -> Result<Self::Ok, Self::Error> {
381        self.stack.pop();
382        Ok(())
383    }
384
385    fn encode_none_with_tag(&mut self, _t: crate::Tag) -> Result<Self::Ok, Self::Error> {
386        self.stack.pop();
387        Ok(())
388    }
389
390    fn encode_choice<E: crate::Encode + crate::types::Choice>(
391        &mut self,
392        _c: crate::types::Constraints,
393        tag: crate::types::Tag,
394        encode_fn: impl FnOnce(&mut Self) -> Result<crate::Tag, Self::Error>,
395    ) -> Result<Self::Ok, Self::Error> {
396        let variants = variants::Variants::from_slice(
397            &[E::VARIANTS, E::EXTENDED_VARIANTS.unwrap_or(&[])].concat(),
398        );
399
400        let identifier = variants
401            .iter()
402            .enumerate()
403            .find_map(|(i, &variant_tag)| {
404                (tag == variant_tag)
405                    .then_some(E::IDENTIFIERS.get(i))
406                    .flatten()
407            })
408            .ok_or_else(|| crate::error::EncodeError::variant_not_in_choice(self.codec()))?;
409
410        if variants.is_empty() {
411            self.update_root_or_constructed(JsonValue::Object(Object::new()))
412        } else {
413            self.constructed_stack.push(Object::new());
414            self.stack.push(identifier);
415            (encode_fn)(self)?;
416            let value_map =
417                self.constructed_stack
418                    .pop()
419                    .ok_or_else(|| JerEncodeErrorKind::JsonEncoder {
420                        msg: "Internal stack mismatch!".into(),
421                    })?;
422            self.update_root_or_constructed(JsonValue::Object(value_map))
423        }
424    }
425
426    fn encode_extension_addition<E: crate::Encode>(
427        &mut self,
428        _t: crate::Tag,
429        _c: crate::types::Constraints,
430        value: E,
431    ) -> Result<Self::Ok, Self::Error> {
432        value.encode(self)
433    }
434
435    fn encode_extension_addition_group<E>(
436        &mut self,
437        value: Option<&E>,
438    ) -> Result<Self::Ok, Self::Error>
439    where
440        E: crate::Encode + crate::types::Constructed,
441    {
442        match value {
443            Some(v) => v.encode(self),
444            None => self.encode_none::<E>(),
445        }
446    }
447
448    fn codec(&self) -> crate::Codec {
449        crate::Codec::Jer
450    }
451}