der/asn1/
octet_string.rs

1//! ASN.1 `OCTET STRING` support.
2
3use crate::{
4    asn1::AnyRef, ord::OrdIsValueOrd, ByteSlice, DecodeValue, EncodeValue, Error, ErrorKind,
5    FixedTag, Header, Length, Reader, Result, Tag, Writer,
6};
7
8#[cfg(feature = "alloc")]
9use alloc::vec::Vec;
10
11/// ASN.1 `OCTET STRING` type: borrowed form.
12///
13/// Octet strings represent contiguous sequences of octets, a.k.a. bytes.
14///
15/// This is a zero-copy reference type which borrows from the input data.
16#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
17pub struct OctetStringRef<'a> {
18    /// Inner value
19    inner: ByteSlice<'a>,
20}
21
22impl<'a> OctetStringRef<'a> {
23    /// Create a new ASN.1 `OCTET STRING` from a byte slice.
24    pub fn new(slice: &'a [u8]) -> Result<Self> {
25        ByteSlice::new(slice)
26            .map(|inner| Self { inner })
27            .map_err(|_| ErrorKind::Length { tag: Self::TAG }.into())
28    }
29
30    /// Borrow the inner byte slice.
31    pub fn as_bytes(&self) -> &'a [u8] {
32        self.inner.as_slice()
33    }
34
35    /// Get the length of the inner byte slice.
36    pub fn len(&self) -> Length {
37        self.inner.len()
38    }
39
40    /// Is the inner byte slice empty?
41    pub fn is_empty(&self) -> bool {
42        self.inner.is_empty()
43    }
44}
45
46impl AsRef<[u8]> for OctetStringRef<'_> {
47    fn as_ref(&self) -> &[u8] {
48        self.as_bytes()
49    }
50}
51
52impl<'a> DecodeValue<'a> for OctetStringRef<'a> {
53    fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> Result<Self> {
54        let inner = ByteSlice::decode_value(reader, header)?;
55        Ok(Self { inner })
56    }
57}
58
59impl EncodeValue for OctetStringRef<'_> {
60    fn value_len(&self) -> Result<Length> {
61        self.inner.value_len()
62    }
63
64    fn encode_value(&self, writer: &mut dyn Writer) -> Result<()> {
65        self.inner.encode_value(writer)
66    }
67}
68
69impl FixedTag for OctetStringRef<'_> {
70    const TAG: Tag = Tag::OctetString;
71}
72
73impl OrdIsValueOrd for OctetStringRef<'_> {}
74
75impl<'a> From<&OctetStringRef<'a>> for OctetStringRef<'a> {
76    fn from(value: &OctetStringRef<'a>) -> OctetStringRef<'a> {
77        *value
78    }
79}
80
81impl<'a> TryFrom<AnyRef<'a>> for OctetStringRef<'a> {
82    type Error = Error;
83
84    fn try_from(any: AnyRef<'a>) -> Result<OctetStringRef<'a>> {
85        any.decode_into()
86    }
87}
88
89impl<'a> From<OctetStringRef<'a>> for AnyRef<'a> {
90    fn from(octet_string: OctetStringRef<'a>) -> AnyRef<'a> {
91        AnyRef::from_tag_and_value(Tag::OctetString, octet_string.inner)
92    }
93}
94
95impl<'a> From<OctetStringRef<'a>> for &'a [u8] {
96    fn from(octet_string: OctetStringRef<'a>) -> &'a [u8] {
97        octet_string.as_bytes()
98    }
99}
100
101/// ASN.1 `OCTET STRING` type: owned form..
102///
103/// Octet strings represent contiguous sequences of octets, a.k.a. bytes.
104///
105/// This type provides the same functionality as [`OctetStringRef`] but owns
106/// the backing data.
107#[cfg(feature = "alloc")]
108#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
109#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
110pub struct OctetString {
111    /// Bitstring represented as a slice of bytes.
112    inner: Vec<u8>,
113}
114
115#[cfg(feature = "alloc")]
116impl OctetString {
117    /// Create a new ASN.1 `OCTET STRING`.
118    pub fn new(bytes: impl Into<Vec<u8>>) -> Result<Self> {
119        let inner = bytes.into();
120
121        // Ensure the bytes parse successfully as an `OctetStringRef`
122        OctetStringRef::new(&inner)?;
123
124        Ok(Self { inner })
125    }
126
127    /// Borrow the inner byte slice.
128    pub fn as_bytes(&self) -> &[u8] {
129        self.inner.as_slice()
130    }
131
132    /// Get the length of the inner byte slice.
133    pub fn len(&self) -> Length {
134        self.value_len().expect("invalid OCTET STRING length")
135    }
136
137    /// Is the inner byte slice empty?
138    pub fn is_empty(&self) -> bool {
139        self.inner.is_empty()
140    }
141}
142
143#[cfg(feature = "alloc")]
144impl AsRef<[u8]> for OctetString {
145    fn as_ref(&self) -> &[u8] {
146        self.as_bytes()
147    }
148}
149
150#[cfg(feature = "alloc")]
151impl<'a> DecodeValue<'a> for OctetString {
152    fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> Result<Self> {
153        Self::new(reader.read_vec(header.length)?)
154    }
155}
156
157#[cfg(feature = "alloc")]
158impl EncodeValue for OctetString {
159    fn value_len(&self) -> Result<Length> {
160        self.inner.len().try_into()
161    }
162
163    fn encode_value(&self, writer: &mut dyn Writer) -> Result<()> {
164        writer.write(&self.inner)
165    }
166}
167
168#[cfg(feature = "alloc")]
169impl FixedTag for OctetString {
170    const TAG: Tag = Tag::OctetString;
171}
172
173#[cfg(feature = "alloc")]
174impl<'a> From<&'a OctetString> for OctetStringRef<'a> {
175    fn from(octet_string: &'a OctetString) -> OctetStringRef<'a> {
176        // Ensured to parse successfully in constructor
177        OctetStringRef::new(&octet_string.inner).expect("invalid OCTET STRING")
178    }
179}
180
181#[cfg(feature = "alloc")]
182impl OrdIsValueOrd for OctetString {}