ssh_key/certificate/
options_map.rs
1use crate::{
4 checked::CheckedSum, decode::Decode, encode::Encode, reader::Reader, writer::Writer, Error,
5 Result,
6};
7use alloc::{string::String, vec::Vec};
8use core::cmp::Ordering;
9
10pub type OptionsMap = alloc::collections::BTreeMap<String, String>;
12
13impl Decode for OptionsMap {
14 fn decode(reader: &mut impl Reader) -> Result<Self> {
15 reader.read_nested(|reader| {
16 let mut entries = Vec::<(String, String)>::new();
17
18 while !reader.is_finished() {
19 let name = String::decode(reader)?;
20 let data = String::decode(reader)?;
21
22 if let Some((prev_name, _)) = entries.last() {
26 if prev_name.cmp(&name) != Ordering::Less {
27 return Err(Error::FormatEncoding);
28 }
29 }
30
31 entries.push((name, data));
32 }
33
34 Ok(OptionsMap::from_iter(entries))
35 })
36 }
37}
38
39impl Encode for OptionsMap {
40 fn encoded_len(&self) -> Result<usize> {
41 self.iter().try_fold(4, |acc, (name, data)| {
42 [acc, 4, name.len(), 4, data.len()].checked_sum()
43 })
44 }
45
46 fn encode(&self, writer: &mut impl Writer) -> Result<()> {
47 self.encoded_len()?
48 .checked_sub(4)
49 .ok_or(Error::Length)?
50 .encode(writer)?;
51
52 for (name, data) in self {
53 name.encode(writer)?;
54 data.encode(writer)?;
55 }
56
57 Ok(())
58 }
59}