der/asn1/
octet_string.rs
1use crate::{
4 asn1::AnyRef, ord::OrdIsValueOrd, BytesRef, Decode, DecodeValue, EncodeValue, ErrorKind,
5 FixedTag, Header, Length, Reader, Result, Tag, Writer,
6};
7
8#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
14pub struct OctetStringRef<'a> {
15 inner: BytesRef<'a>,
17}
18
19impl<'a> OctetStringRef<'a> {
20 pub fn new(slice: &'a [u8]) -> Result<Self> {
22 BytesRef::new(slice)
23 .map(|inner| Self { inner })
24 .map_err(|_| ErrorKind::Length { tag: Self::TAG }.into())
25 }
26
27 pub fn as_bytes(&self) -> &'a [u8] {
29 self.inner.as_slice()
30 }
31
32 pub fn len(&self) -> Length {
34 self.inner.len()
35 }
36
37 pub fn is_empty(&self) -> bool {
39 self.inner.is_empty()
40 }
41
42 pub fn decode_into<T: Decode<'a>>(&self) -> Result<T> {
44 Decode::from_der(self.as_bytes())
45 }
46}
47
48impl_any_conversions!(OctetStringRef<'a>, 'a);
49
50impl AsRef<[u8]> for OctetStringRef<'_> {
51 fn as_ref(&self) -> &[u8] {
52 self.as_bytes()
53 }
54}
55
56impl<'a> DecodeValue<'a> for OctetStringRef<'a> {
57 fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> Result<Self> {
58 let inner = BytesRef::decode_value(reader, header)?;
59 Ok(Self { inner })
60 }
61}
62
63impl EncodeValue for OctetStringRef<'_> {
64 fn value_len(&self) -> Result<Length> {
65 self.inner.value_len()
66 }
67
68 fn encode_value(&self, writer: &mut impl Writer) -> Result<()> {
69 self.inner.encode_value(writer)
70 }
71}
72
73impl FixedTag for OctetStringRef<'_> {
74 const TAG: Tag = Tag::OctetString;
75}
76
77impl OrdIsValueOrd for OctetStringRef<'_> {}
78
79impl<'a> From<&OctetStringRef<'a>> for OctetStringRef<'a> {
80 fn from(value: &OctetStringRef<'a>) -> OctetStringRef<'a> {
81 *value
82 }
83}
84
85impl<'a> From<OctetStringRef<'a>> for AnyRef<'a> {
86 fn from(octet_string: OctetStringRef<'a>) -> AnyRef<'a> {
87 AnyRef::from_tag_and_value(Tag::OctetString, octet_string.inner)
88 }
89}
90
91impl<'a> From<OctetStringRef<'a>> for &'a [u8] {
92 fn from(octet_string: OctetStringRef<'a>) -> &'a [u8] {
93 octet_string.as_bytes()
94 }
95}
96
97#[cfg(feature = "alloc")]
98pub use self::allocating::OctetString;
99
100#[cfg(feature = "alloc")]
101mod allocating {
102 use super::*;
103 use crate::referenced::*;
104 use alloc::vec::Vec;
105
106 #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
113 pub struct OctetString {
114 pub(super) inner: Vec<u8>,
116 }
117
118 impl OctetString {
119 pub fn new(bytes: impl Into<Vec<u8>>) -> Result<Self> {
121 let inner = bytes.into();
122
123 OctetStringRef::new(&inner)?;
125
126 Ok(Self { inner })
127 }
128
129 pub fn as_bytes(&self) -> &[u8] {
131 self.inner.as_slice()
132 }
133
134 pub fn into_bytes(self) -> Vec<u8> {
136 self.inner
137 }
138
139 pub fn len(&self) -> Length {
141 self.value_len().expect("invalid OCTET STRING length")
142 }
143
144 pub fn is_empty(&self) -> bool {
146 self.inner.is_empty()
147 }
148 }
149
150 impl_any_conversions!(OctetString);
151
152 impl AsRef<[u8]> for OctetString {
153 fn as_ref(&self) -> &[u8] {
154 self.as_bytes()
155 }
156 }
157
158 impl<'a> DecodeValue<'a> for OctetString {
159 fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> Result<Self> {
160 Self::new(reader.read_vec(header.length)?)
161 }
162 }
163
164 impl EncodeValue for OctetString {
165 fn value_len(&self) -> Result<Length> {
166 self.inner.len().try_into()
167 }
168
169 fn encode_value(&self, writer: &mut impl Writer) -> Result<()> {
170 writer.write(&self.inner)
171 }
172 }
173
174 impl FixedTag for OctetString {
175 const TAG: Tag = Tag::OctetString;
176 }
177
178 impl<'a> From<&'a OctetString> for OctetStringRef<'a> {
179 fn from(octet_string: &'a OctetString) -> OctetStringRef<'a> {
180 OctetStringRef::new(&octet_string.inner).expect("invalid OCTET STRING")
182 }
183 }
184
185 impl OrdIsValueOrd for OctetString {}
186
187 impl<'a> RefToOwned<'a> for OctetStringRef<'a> {
188 type Owned = OctetString;
189 fn ref_to_owned(&self) -> Self::Owned {
190 OctetString {
191 inner: Vec::from(self.inner.as_slice()),
192 }
193 }
194 }
195
196 impl OwnedToRef for OctetString {
197 type Borrowed<'a> = OctetStringRef<'a>;
198 fn owned_to_ref(&self) -> Self::Borrowed<'_> {
199 self.into()
200 }
201 }
202
203 #[cfg(feature = "arbitrary")]
206 impl<'a> arbitrary::Arbitrary<'a> for OctetString {
207 fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
208 Self::new(Vec::arbitrary(u)?).map_err(|_| arbitrary::Error::IncorrectFormat)
209 }
210
211 fn size_hint(depth: usize) -> (usize, Option<usize>) {
212 arbitrary::size_hint::and(u8::size_hint(depth), Vec::<u8>::size_hint(depth))
213 }
214 }
215}
216
217#[cfg(feature = "bytes")]
218mod bytes {
219 use super::OctetString;
220 use crate::{DecodeValue, EncodeValue, FixedTag, Header, Length, Reader, Result, Tag, Writer};
221 use bytes::Bytes;
222
223 impl<'a> DecodeValue<'a> for Bytes {
224 fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> Result<Self> {
225 OctetString::decode_value(reader, header).map(|octet_string| octet_string.inner.into())
226 }
227 }
228
229 impl EncodeValue for Bytes {
230 fn value_len(&self) -> Result<Length> {
231 self.len().try_into()
232 }
233
234 fn encode_value(&self, writer: &mut impl Writer) -> Result<()> {
235 writer.write(self.as_ref())
236 }
237 }
238
239 impl FixedTag for Bytes {
240 const TAG: Tag = Tag::OctetString;
241 }
242}
243
244#[cfg(test)]
245mod tests {
246 use crate::asn1::{OctetStringRef, PrintableStringRef};
247
248 #[test]
249 fn octet_string_decode_into() {
250 let der = b"\x13\x02\x68\x69";
252 let oct = OctetStringRef::new(der).unwrap();
253
254 let res = oct.decode_into::<PrintableStringRef<'_>>().unwrap();
255 assert_eq!(AsRef::<str>::as_ref(&res), "hi");
256 }
257}