flexiber/
tagged.rs

1// //! Common handling for types backed by byte slices with enforcement of the
2// //! format-level length limitation of 65,535 bytes.
3
4use crate::{
5    header::Header, Decodable, Decoder, Encodable, Encoder, ErrorKind, Length, Result, Slice, Tag,
6    TagLike,
7};
8
9/// BER-TLV data object.
10#[derive(Clone, Copy, Debug, Eq, PartialEq)]
11pub struct TaggedValue<V, T = Tag> {
12    tag: T,
13    value: V,
14}
15
16/// Raw BER-TLV data object `TaggedValue<Slice<'_>>`.
17pub type TaggedSlice<'a, T = Tag> = TaggedValue<Slice<'a>, T>;
18
19impl<V, T> TaggedValue<V, T>
20where
21    T: Copy,
22{
23    pub fn new(tag: T, value: V) -> Self {
24        Self { tag, value }
25    }
26
27    pub fn tag(&self) -> T {
28        self.tag
29    }
30}
31
32impl<E, T> TaggedValue<&'_ E, T>
33where
34    E: Encodable,
35    T: Copy + Encodable,
36{
37    fn header(&self) -> Result<Header<T>> {
38        Ok(Header {
39            tag: self.tag(),
40            length: self.value.encoded_length()?,
41        })
42    }
43}
44
45impl<E, T> Encodable for TaggedValue<&E, T>
46where
47    E: Encodable,
48    T: Copy + Encodable,
49{
50    fn encoded_length(&self) -> Result<Length> {
51        self.header()?.encoded_length()? + self.value.encoded_length()?
52    }
53    fn encode(&self, encoder: &mut Encoder<'_>) -> Result<()> {
54        self.header()?.encode(encoder)?;
55        encoder.encode(self.value)
56    }
57}
58
59impl<'a, T> TaggedSlice<'a, T>
60where
61    T: Copy,
62{
63    /// Create a new tagged slice, checking lengths.
64    pub fn from(tag: T, slice: &'a [u8]) -> Result<Self> {
65        Slice::new(slice)
66            .map(|slice| Self { tag, value: slice })
67            .map_err(|_| (ErrorKind::InvalidLength).into())
68    }
69
70    /// Borrow the inner byte slice.
71    pub fn as_bytes(&self) -> &'a [u8] {
72        self.value.as_bytes()
73    }
74
75    /// Get the length of the inner byte slice.
76    pub fn length(&self) -> Length {
77        self.value.length()
78    }
79
80    /// Is the inner byte slice empty?
81    pub fn is_empty(&self) -> bool {
82        self.value.is_empty()
83    }
84
85    /// Get the BER-TLV [`Header`] for this [`TaggedSlice`] value
86    #[allow(clippy::unnecessary_wraps)]
87    fn header(&self) -> Result<Header<T>> {
88        Ok(Header {
89            tag: self.tag(),
90            length: self.length(),
91        })
92    }
93
94    /// Decode nested values, creating a new [`Decoder`] for
95    /// the data contained in the sequence's body and passing it to the provided
96    /// [`FnOnce`].
97    pub fn decode_nested<F, R>(&self, f: F) -> Result<R>
98    where
99        F: FnOnce(&mut Decoder<'a>) -> Result<R>,
100    {
101        let mut nested_decoder = Decoder::new(self.as_bytes());
102        let result = f(&mut nested_decoder)?;
103        nested_decoder.finish(result)
104    }
105}
106
107impl<'a, T> Decodable<'a> for TaggedSlice<'a, T>
108where
109    T: Decodable<'a> + TagLike,
110{
111    fn decode(decoder: &mut Decoder<'a>) -> Result<Self> {
112        let header = Header::<T>::decode(decoder)?;
113        let tag = header.tag;
114        let len = header.length.to_usize();
115        let value = decoder.bytes(len).map_err(|_| ErrorKind::Length {
116            tag: tag.embedding(),
117        })?;
118        Self::from(tag, value)
119    }
120}
121
122impl<T> Encodable for TaggedSlice<'_, T>
123where
124    T: Copy + Encodable,
125{
126    fn encoded_length(&self) -> Result<Length> {
127        self.header()?.encoded_length()? + self.length()
128    }
129
130    fn encode(&self, encoder: &mut Encoder<'_>) -> Result<()> {
131        self.header()?.encode(encoder)?;
132        encoder.bytes(self.as_bytes())
133    }
134}
135
136// /// Obtain the length of an ASN.1 `SEQUENCE` of [`Encodable`] values when
137// /// serialized as ASN.1 DER, including the `SEQUENCE` tag and length prefix.
138// pub fn encoded_length2(/*tag: Tag,*/ encodables: &[&dyn Encodable]) -> Result<Length> {
139//     let inner_len = Length::try_from(encodables)?;
140//     Header::new(crate::tag::MEANINGLESS_TAG, inner_len)?.encoded_length() + inner_len
141// }
142
143// /// Obtain the inner length of a container of [`Encodable`] values
144// /// excluding the tag and length.
145// pub(crate) fn sum_encoded_lengths(encodables: &[&dyn Encodable]) -> Result<Length> {
146//     encodables
147//         .iter()
148//         .fold(Ok(Length::zero()), |sum, encodable| {
149//             sum + encodable.encoded_length()?
150//         })
151// }
152
153#[cfg(test)]
154mod tests {
155    use crate::{Encodable, Tag, TaggedSlice};
156    use core::convert::TryFrom;
157
158    #[test]
159    fn encode() {
160        let mut buf = [0u8; 1024];
161
162        let short = TaggedSlice::from(Tag::try_from(0x06).unwrap(), &[1, 2, 3]).unwrap();
163
164        assert_eq!(
165            short.encode_to_slice(&mut buf).unwrap(),
166            &[0x06, 0x3, 1, 2, 3]
167        );
168
169        let slice = &[43u8; 256];
170
171        let long = TaggedSlice::from(Tag::universal(0x66), slice).unwrap();
172        let encoded = long.encode_to_slice(&mut buf).unwrap();
173        assert_eq!(&encoded[..5], &[0x1F, 0x66, 0x82, 0x01, 0x00]);
174        assert_eq!(&encoded[5..], slice);
175
176        let long = TaggedSlice::from(Tag::universal(0x66).constructed(), slice).unwrap();
177        let encoded = long.encode_to_slice(&mut buf).unwrap();
178        assert_eq!(&encoded[..5], &[0x3F, 0x66, 0x82, 0x01, 0x00]);
179        assert_eq!(&encoded[5..], slice);
180
181        let long = TaggedSlice::from(Tag::application(0x66), slice).unwrap();
182        let encoded = long.encode_to_slice(&mut buf).unwrap();
183        assert_eq!(&encoded[..5], &[0x5F, 0x66, 0x82, 0x01, 0x00]);
184        assert_eq!(&encoded[5..], slice);
185
186        let long = TaggedSlice::from(Tag::application(0x66).constructed(), slice).unwrap();
187        let encoded = long.encode_to_slice(&mut buf).unwrap();
188        assert_eq!(&encoded[..5], &[0x7F, 0x66, 0x82, 0x01, 0x00]);
189        assert_eq!(&encoded[5..], slice);
190
191        let long = TaggedSlice::from(Tag::context(0x66), slice).unwrap();
192        let encoded = long.encode_to_slice(&mut buf).unwrap();
193        assert_eq!(&encoded[..5], &[0x9F, 0x66, 0x82, 0x01, 0x00]);
194        assert_eq!(&encoded[5..], slice);
195
196        let long = TaggedSlice::from(Tag::context(0x66).constructed(), slice).unwrap();
197        let encoded = long.encode_to_slice(&mut buf).unwrap();
198        assert_eq!(&encoded[..5], &[0xBF, 0x66, 0x82, 0x01, 0x00]);
199        assert_eq!(&encoded[5..], slice);
200
201        let long = TaggedSlice::from(Tag::private(0x66), slice).unwrap();
202        let encoded = long.encode_to_slice(&mut buf).unwrap();
203        assert_eq!(&encoded[..5], &[0xDF, 0x66, 0x82, 0x01, 0x00]);
204        assert_eq!(&encoded[5..], slice);
205
206        let long = TaggedSlice::from(Tag::private(0x66).constructed(), slice).unwrap();
207        let encoded = long.encode_to_slice(&mut buf).unwrap();
208        assert_eq!(&encoded[..5], &[0xFF, 0x66, 0x82, 0x01, 0x00]);
209        assert_eq!(&encoded[5..], slice);
210    }
211}