simple_tlv/
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::{Decodable, Decoder, Encodable, Encoder, ErrorKind, header::Header, Length, Result, Slice, Tag};
5
6/// SIMPLE-TLV data object.
7#[derive(Clone, Copy, Debug, Eq, PartialEq)]
8pub struct TaggedValue<V> {
9    tag: Tag,
10    value: V,
11}
12
13/// Raw SIMPLE-TLV data object `TaggedValue<Slice<'_>>`.
14pub type TaggedSlice<'a> = TaggedValue<Slice<'a>>;
15
16impl<V> TaggedValue<V>
17{
18    pub fn new(tag: Tag, value: V) -> Self {
19        Self { tag, value }
20    }
21
22    pub fn tag(&self) -> Tag {
23        self.tag
24    }
25}
26
27impl<'a, E> TaggedValue<&'a E>
28where
29    E: Encodable
30{
31    fn header(&self) -> Result<Header> {
32        Ok(Header {
33            tag: self.tag(),
34            length: self.value.encoded_length()?,
35        })
36    }
37}
38
39impl<'a, E> Encodable for TaggedValue<&'a E>
40where
41    E: Encodable
42{
43    fn encoded_length(&self) -> Result<Length> {
44        self.header()?.encoded_length()? + self.value.encoded_length()?
45    }
46    fn encode(&self, encoder: &mut Encoder<'_>) -> Result<()> {
47        self.header()?.encode(encoder)?;
48        encoder.encode(self.value)
49    }
50}
51
52impl<'a> TaggedSlice<'a> {
53
54    /// Create a new tagged slice, checking lengths.
55    pub fn from(tag: Tag, slice: &'a [u8]) -> Result<Self> {
56        Slice::new(slice)
57            .map(|slice| Self { tag, value: slice })
58            .map_err(|_| (ErrorKind::InvalidLength).into())
59    }
60
61    /// Borrow the inner byte slice.
62    pub fn as_bytes(&self) -> &'a [u8] {
63        self.value.as_bytes()
64    }
65
66    /// Get the length of the inner byte slice.
67    pub fn length(&self) -> Length {
68        self.value.length()
69    }
70
71    /// Is the inner byte slice empty?
72    pub fn is_empty(&self) -> bool {
73        self.value.is_empty()
74    }
75
76    /// Get the SIMPLE-TLV [`Header`] for this [`TaggedSlice`] value
77    #[allow(clippy::unnecessary_wraps)]
78    fn header(&self) -> Result<Header> {
79        Ok(Header {
80            tag: self.tag(),
81            length: self.length(),
82        })
83    }
84
85    /// Decode nested values, creating a new [`Decoder`] for
86    /// the data contained in the sequence's body and passing it to the provided
87    /// [`FnOnce`].
88    pub fn decode_nested<F, T>(&self, f: F) -> Result<T>
89    where
90        F: FnOnce(&mut Decoder<'a>) -> Result<T>,
91    {
92        let mut nested_decoder = Decoder::new(self.as_bytes());
93        let result = f(&mut nested_decoder)?;
94        nested_decoder.finish(result)
95    }
96}
97
98impl<'a> Decodable<'a> for TaggedSlice<'a> {
99    fn decode(decoder: &mut Decoder<'a>) -> Result<TaggedSlice<'a>> {
100        let header = Header::decode(decoder)?;
101        let tag = header.tag;
102        let len = header.length.to_usize();
103        let value = decoder.bytes(len).map_err(|_| ErrorKind::Length { tag })?;
104        Self::from(tag, value)
105    }
106}
107
108impl<'a> Encodable for TaggedSlice<'a> {
109    fn encoded_length(&self) -> Result<Length> {
110        self.header()?.encoded_length()? + self.length()
111    }
112
113    fn encode(&self, encoder: &mut Encoder<'_>) -> Result<()> {
114        self.header()?.encode(encoder)?;
115        encoder.bytes(self.as_bytes())
116    }
117}
118
119// /// Obtain the length of an ASN.1 `SEQUENCE` of [`Encodable`] values when
120// /// serialized as ASN.1 DER, including the `SEQUENCE` tag and length prefix.
121// pub fn encoded_length2(/*tag: Tag,*/ encodables: &[&dyn Encodable]) -> Result<Length> {
122//     let inner_len = Length::try_from(encodables)?;
123//     Header::new(crate::tag::MEANINGLESS_TAG, inner_len)?.encoded_length() + inner_len
124// }
125
126// /// Obtain the inner length of a container of [`Encodable`] values
127// /// excluding the tag and length.
128// pub(crate) fn sum_encoded_lengths(encodables: &[&dyn Encodable]) -> Result<Length> {
129//     encodables
130//         .iter()
131//         .fold(Ok(Length::zero()), |sum, encodable| {
132//             sum + encodable.encoded_length()?
133//         })
134// }
135
136
137#[cfg(test)]
138mod tests {
139    use core::convert::TryFrom;
140    use crate::{Encodable, Tag, TaggedSlice};
141
142    #[test]
143    fn encode() {
144        let mut buf = [0u8; 1024];
145
146        let short = TaggedSlice::from(Tag::try_from(0x66).unwrap(), &[1, 2, 3]).unwrap();
147
148        assert_eq!(
149            short.encode_to_slice(&mut buf).unwrap(),
150            &[0x66, 0x3, 1, 2, 3]
151        );
152
153        let slice = &[43u8; 256];
154        let long = TaggedSlice::from(Tag::try_from(0x66).unwrap(), slice).unwrap();
155        let encoded = long.encode_to_slice(&mut buf).unwrap();
156        assert_eq!(&encoded[..4], &[0x66, 0xFF, 0x01, 0x00]);
157        assert_eq!(&encoded[4..], slice);
158    }
159}