1use crate::{Decodable, Decoder, Encodable, Encoder, ErrorKind, header::Header, Length, Result, Slice, Tag};
5
6#[derive(Clone, Copy, Debug, Eq, PartialEq)]
8pub struct TaggedValue<V> {
9 tag: Tag,
10 value: V,
11}
12
13pub 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 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 pub fn as_bytes(&self) -> &'a [u8] {
63 self.value.as_bytes()
64 }
65
66 pub fn length(&self) -> Length {
68 self.value.length()
69 }
70
71 pub fn is_empty(&self) -> bool {
73 self.value.is_empty()
74 }
75
76 #[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 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#[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}