rasn/types/strings/
octet.rs1use crate::prelude::*;
2
3use alloc::vec::Vec;
4
5#[cfg(all(feature = "arc-slice", feature = "bytes"))]
6compile_error!("features `arc-slice` and `bytes` conflict, choose one");
7
8#[cfg(all(not(feature = "arc-slice"), feature = "bytes"))]
9type BytesImpl = bytes::Bytes;
10
11#[cfg(all(feature = "arc-slice", not(feature = "bytes")))]
12type BytesImpl = arc_slice::ArcBytes<arc_slice::layout::ArcLayout<true, true>>;
13
14#[derive(Debug, Default, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
36pub struct OctetString(BytesImpl);
37
38impl OctetString {
39 pub const fn from_static(value: &'static [u8]) -> Self {
44 Self(BytesImpl::from_static(value))
45 }
46
47 pub fn from_slice(value: &[u8]) -> Self {
49 Self::from(value)
50 }
51}
52
53impl AsRef<[u8]> for OctetString {
54 fn as_ref(&self) -> &[u8] {
55 &self.0
56 }
57}
58
59impl<const N: usize> From<[u8; N]> for OctetString {
60 fn from(value: [u8; N]) -> Self {
61 cfg_if::cfg_if! {
62 if #[cfg(feature = "arc-slice")] {
63 Self(value.into())
64 } else {
65 Self(bytes::Bytes::copy_from_slice(&value))
66 }
67 }
68 }
69}
70
71impl From<Vec<u8>> for OctetString {
72 fn from(value: Vec<u8>) -> Self {
73 Self(value.into())
74 }
75}
76
77impl From<&[u8]> for OctetString {
78 fn from(value: &[u8]) -> Self {
79 cfg_if::cfg_if! {
80 if #[cfg(feature = "arc-slice")] {
81 Self(value.into())
82 } else {
83 Self(bytes::Bytes::copy_from_slice(value))
84 }
85 }
86 }
87}
88
89impl core::ops::Deref for OctetString {
90 type Target = [u8];
91
92 fn deref(&self) -> &Self::Target {
93 &self.0
94 }
95}
96
97impl PartialEq<[u8]> for OctetString {
98 fn eq(&self, value: &[u8]) -> bool {
99 self.0 == value
100 }
101}
102
103impl PartialEq<&[u8]> for OctetString {
104 fn eq(&self, value: &&[u8]) -> bool {
105 self.0 == *value
106 }
107}
108
109impl PartialEq<Vec<u8>> for OctetString {
110 fn eq(&self, value: &Vec<u8>) -> bool {
111 self.0 == *value
112 }
113}
114
115#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
119pub struct FixedOctetString<const N: usize>([u8; N]);
120
121impl<const N: usize> FixedOctetString<N> {
122 #[must_use]
124 pub fn new(value: [u8; N]) -> Self {
125 Self(value)
126 }
127}
128
129impl<const N: usize> From<[u8; N]> for FixedOctetString<N> {
130 fn from(value: [u8; N]) -> Self {
131 Self::new(value)
132 }
133}
134
135impl<const N: usize> TryFrom<Vec<u8>> for FixedOctetString<N> {
136 type Error = <[u8; N] as TryFrom<Vec<u8>>>::Error;
137
138 fn try_from(value: Vec<u8>) -> Result<Self, Self::Error> {
139 value.try_into().map(Self)
140 }
141}
142
143impl<const N: usize> TryFrom<&[u8]> for FixedOctetString<N> {
144 type Error = <[u8; N] as TryFrom<&'static [u8]>>::Error;
145
146 fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
147 value.try_into().map(Self)
148 }
149}
150
151impl<const N: usize> TryFrom<OctetString> for FixedOctetString<N> {
152 type Error = <[u8; N] as TryFrom<&'static [u8]>>::Error;
153
154 fn try_from(value: OctetString) -> Result<Self, Self::Error> {
155 (&*value).try_into().map(Self)
156 }
157}
158
159impl<const N: usize> core::ops::Deref for FixedOctetString<N> {
160 type Target = [u8; N];
161
162 fn deref(&self) -> &Self::Target {
163 &self.0
164 }
165}
166
167impl<const N: usize> core::ops::DerefMut for FixedOctetString<N> {
168 fn deref_mut(&mut self) -> &mut Self::Target {
169 &mut self.0
170 }
171}
172
173impl<const N: usize> AsnType for FixedOctetString<N> {
174 const TAG: Tag = Tag::OCTET_STRING;
175 const CONSTRAINTS: Constraints = constraints!(size_constraint!(N));
176 const IDENTIFIER: Identifier = Identifier::OCTET_STRING;
177}
178
179impl<const N: usize> Decode for FixedOctetString<N> {
180 fn decode_with_tag_and_constraints<D: Decoder>(
181 decoder: &mut D,
182 tag: Tag,
183 constraints: Constraints,
184 ) -> Result<Self, D::Error> {
185 let codec = decoder.codec();
186 let bytes = decoder.decode_octet_string::<alloc::borrow::Cow<[u8]>>(tag, constraints)?;
187 let len = bytes.len();
188 match bytes {
189 alloc::borrow::Cow::Borrowed(slice) => Self::try_from(slice).map_err(|_| {
190 D::Error::from(crate::error::DecodeError::fixed_string_conversion_failed(
191 tag,
192 bytes.len(),
193 N,
194 codec,
195 ))
196 }),
197 alloc::borrow::Cow::Owned(vec) => Self::try_from(vec).map_err(|_| {
198 D::Error::from(crate::error::DecodeError::fixed_string_conversion_failed(
199 tag, len, N, codec,
200 ))
201 }),
202 }
203 }
204}
205
206impl<const N: usize> Encode for FixedOctetString<N> {
207 fn encode_with_tag_and_constraints<'b, E: Encoder<'b>>(
208 &self,
209 encoder: &mut E,
210 tag: Tag,
211 constraints: Constraints,
212 identifier: Identifier,
213 ) -> Result<(), E::Error> {
214 encoder
215 .encode_octet_string(tag, constraints, &self.0, identifier)
216 .map(drop)
217 }
218}