1use crate::{
5 header::Header, Decodable, Decoder, Encodable, Encoder, ErrorKind, Length, Result, Slice, Tag,
6 TagLike,
7};
8
9#[derive(Clone, Copy, Debug, Eq, PartialEq)]
11pub struct TaggedValue<V, T = Tag> {
12 tag: T,
13 value: V,
14}
15
16pub 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 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 pub fn as_bytes(&self) -> &'a [u8] {
72 self.value.as_bytes()
73 }
74
75 pub fn length(&self) -> Length {
77 self.value.length()
78 }
79
80 pub fn is_empty(&self) -> bool {
82 self.value.is_empty()
83 }
84
85 #[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 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#[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}