asnfuzzgen_codecs/per/uper/encode/
mod.rs

1//! ASN.1 Aper Encoder module.
2
3use bitvec::prelude::*;
4
5use crate::{PerCodecData, PerCodecError};
6
7#[allow(unused)]
8use crate::per::common::encode::*;
9
10/// Encode a Choice Index
11///
12/// During Encoding a 'CHOICE' Type to help decoding, the 'CHOICE' Index is encoded first, followed
13/// by the actual encoding of the 'CHOICE' variant.
14pub fn encode_choice_idx(
15    data: &mut PerCodecData,
16    lb: i128,
17    ub: i128,
18    is_extensible: bool,
19    idx: i128,
20    extended: bool,
21) -> Result<(), PerCodecError> {
22
23    encode_choice_idx_common(data, lb, ub, is_extensible, idx, extended, false)
24}
25
26/// Encode sequence header
27pub fn encode_sequence_header(
28    data: &mut PerCodecData,
29    is_extensible: bool,
30    optionals: &BitSlice<u8, Msb0>,
31    extended: bool,
32) -> Result<(), PerCodecError> {
33
34    encode_sequence_header_common(data, is_extensible, optionals, extended, false)
35}
36
37/// Encode an INTEGER
38///
39/// This API is also used by other `encode` functions to encode an integer value.
40///
41/// Note: The maximum (and minimum) value to be decoded is limited to an `i128` value. For the
42/// protocols that are currently supported this limit is acceptable.
43pub fn encode_integer(
44    data: &mut PerCodecData,
45    lb: Option<i128>,
46    ub: Option<i128>,
47    is_extensible: bool,
48    value: i128,
49    extended: bool,
50) -> Result<(), PerCodecError> {
51
52    encode_integer_common(data, lb, ub, is_extensible, value, extended, false)
53}
54
55/// Encode a BOOLEAN Value
56///
57/// Encodes a boolean value into the passed `PerCodecData` structure.
58pub fn encode_bool(data: &mut PerCodecData, value: bool) -> Result<(), PerCodecError> {
59
60    encode_bool_common(data, value, true)
61}
62
63/// Encode an ENUMERATED Value
64pub fn encode_enumerated(
65    data: &mut PerCodecData,
66    lb: Option<i128>,
67    ub: Option<i128>,
68    is_extensible: bool,
69    value: i128,
70    extended: bool,
71) -> Result<(), PerCodecError> {
72
73    encode_enumerated_common(data, lb, ub, is_extensible, value, extended, false)
74}
75
76/// Encode a Bit String
77pub fn encode_bitstring(
78    data: &mut PerCodecData,
79    lb: Option<i128>,
80    ub: Option<i128>,
81    is_extensible: bool,
82    bit_string: &BitSlice<u8, Msb0>,
83    extended: bool,
84) -> Result<(), PerCodecError> {
85
86    encode_bitstring_common(data, lb, ub, is_extensible, bit_string, extended, false)
87}
88
89/// Encode an OCTET STRING
90pub fn encode_octetstring(
91    data: &mut PerCodecData,
92    lb: Option<i128>,
93    ub: Option<i128>,
94    is_extensible: bool,
95    octet_string: &Vec<u8>,
96    extended: bool,
97) -> Result<(), PerCodecError> {
98
99    encode_octet_string_common(data, lb, ub, is_extensible, octet_string, extended, false)
100}
101
102// Encode a Length Determinent
103pub fn encode_length_determinent(
104    data: &mut PerCodecData,
105    lb: Option<i128>,
106    ub: Option<i128>,
107    normally_small: bool,
108    value: usize,
109) -> Result<(), PerCodecError> {
110
111    encode_length_determinent_common(data, lb, ub, normally_small, value, false)
112}
113
114/// Encode a VisibleString CharacterString Type.
115pub fn encode_visible_string(
116    data: &mut PerCodecData,
117    lb: Option<i128>,
118    ub: Option<i128>,
119    is_extensible: bool,
120    value: &String,
121    extended: bool,
122) -> Result<(), PerCodecError> {
123
124    encode_ascii_ish_string_common(data, lb, ub, is_extensible, value, extended)
125}
126
127/// Encode a PrintableString CharacterString Type.
128pub fn encode_printable_string(
129    data: &mut PerCodecData,
130    lb: Option<i128>,
131    ub: Option<i128>,
132    is_extensible: bool,
133    value: &String,
134    extended: bool,
135) -> Result<(), PerCodecError> {
136
137    encode_ascii_ish_string_common(data, lb, ub, is_extensible, value, extended)
138}
139
140/// Encode a UTF8String CharacterString Type.
141pub fn encode_utf8_string(
142    data: &mut PerCodecData,
143    lb: Option<i128>,
144    ub: Option<i128>,
145    is_extensible: bool,
146    value: &String,
147    extended: bool,
148) -> Result<(), PerCodecError> {
149
150    encode_octet_string_common(
151        data,
152        lb,
153        ub,
154        is_extensible,
155        value.as_bytes(),
156        extended,
157        false,
158    )
159}
160
161// Common function used by PrintableString and VisibleString
162fn encode_ascii_ish_string_common(
163    data: &mut PerCodecData,
164    lb: Option<i128>,
165    ub: Option<i128>,
166    is_extensible: bool,
167    value: &str,
168    extended: bool,
169) -> Result<(), PerCodecError> {
170    if extended {
171        return Err(PerCodecError::new(
172            "Encode of extended octetstring not yet implemented",
173        ));
174    }
175
176    if is_extensible {
177        data.encode_bool(extended);
178    }
179
180    encode_length_determinent_common(data, lb, ub, false, value.len(), false)?;
181
182    // FIXME: bits_per_char is hardcoded it shold be obtained from the 'alphabet' of the string.
183    let bits_per_char = 7;
184    let offset = 8 - bits_per_char;
185    let chars_vec = value
186        .chars()
187        .map(|c| BitSlice::<_, Msb0>::from_element(&(c as u8))[offset..].to_bitvec())
188        .collect::<Vec<_>>()
189        .into_iter()
190        .flatten()
191        .collect::<BitVec<u8, Msb0>>();
192
193    data.append_bits(chars_vec.as_bitslice());
194
195    Ok(())
196}
197
198#[cfg(test)]
199mod tests {
200
201    use super::*;
202
203    #[test]
204    fn encode_bool_always_success() {
205        let mut data = PerCodecData::new_uper();
206
207        let result = encode_bool(&mut data, true);
208        assert!(result.is_ok());
209        assert_eq!(data.bits.len(), 1);
210        assert_eq!(data.bits[0], true);
211    }
212
213    #[test]
214    fn int_too_small() {
215        assert!(encode_integer(
216            &mut PerCodecData::new_uper(),
217            Some(1),
218            None,
219            false,
220            0,
221            false
222        )
223        .is_err());
224    }
225
226    #[test]
227    fn int_too_big() {
228        assert!(encode_integer(
229            &mut PerCodecData::new_uper(),
230            Some(-1),
231            Some(0),
232            false,
233            1,
234            false
235        )
236        .is_err());
237    }
238
239    #[test]
240    fn octetstring_too_small() {
241        assert!(encode_octetstring(
242            &mut PerCodecData::new_uper(),
243            Some(2),
244            None,
245            false,
246            &vec![0],
247            false
248        )
249        .is_err());
250    }
251    #[test]
252    fn octetstring_too_big() {
253        assert!(encode_octetstring(
254            &mut PerCodecData::new_uper(),
255            None,
256            Some(1),
257            false,
258            &vec![0, 0],
259            false
260        )
261        .is_err());
262    }
263
264    #[test]
265    fn string_too_small() {
266        assert!(encode_visible_string(
267            &mut PerCodecData::new_uper(),
268            Some(2),
269            None,
270            false,
271            &"a".to_string(),
272            false
273        )
274        .is_err());
275    }
276
277    #[test]
278    fn string_too_big() {
279        assert!(encode_visible_string(
280            &mut PerCodecData::new_uper(),
281            None,
282            Some(1),
283            false,
284            &"aa".to_string(),
285            false
286        )
287        .is_err());
288    }
289
290    #[test]
291    fn length_too_small() {
292        assert!(
293            encode_length_determinent(&mut PerCodecData::new_uper(), Some(2), None, false, 1,)
294                .is_err()
295        );
296    }
297    #[test]
298    fn length_too_big() {
299        assert!(
300            encode_length_determinent(&mut PerCodecData::new_uper(), None, Some(1), false, 2,)
301                .is_err()
302        );
303    }
304
305    #[test]
306    fn big_length_too_big() {
307        assert!(encode_length_determinent(
308            &mut PerCodecData::new_uper(),
309            None,
310            Some(65536),
311            false,
312            65537,
313        )
314        .is_err());
315    }
316
317    #[test]
318    fn bitstring_too_small() {
319        assert!(encode_bitstring(
320            &mut PerCodecData::new_uper(),
321            Some(2),
322            None,
323            false,
324            bits![u8, Msb0; 0],
325            false
326        )
327        .is_err());
328    }
329
330    #[test]
331    fn bitstring_too_big() {
332        assert!(encode_bitstring(
333            &mut PerCodecData::new_uper(),
334            None,
335            Some(1),
336            false,
337            bits![u8, Msb0; 0, 0],
338            false
339        )
340        .is_err());
341    }
342
343    #[test]
344    fn bitstring_uper_ascii_ish_string() {
345        // Taken from the example in x.691
346        let value = "John".to_string();
347        let mut codec_data = &mut PerCodecData::new_uper();
348        let result = encode_visible_string(&mut codec_data, None, None, false, &value, false);
349        assert!(result.is_ok(), "{:#?}", result.err().unwrap());
350    }
351}