1use crate::{
4 BytesRef, Decode, DecodeValue, EncodeValue, Error, ErrorKind, FixedTag, Header, Length, Reader,
5 Tag, Writer, asn1::AnyRef, ord::OrdIsValueOrd,
6};
7
8#[derive(Debug, Eq, Hash, PartialEq, PartialOrd, Ord)]
14#[repr(transparent)]
15pub struct OctetStringRef {
16 inner: BytesRef,
18}
19
20impl OctetStringRef {
21 pub fn new(slice: &[u8]) -> Result<&Self, Error> {
26 BytesRef::new(slice)
27 .map(Self::from_bytes_ref)
28 .map_err(|_| ErrorKind::Length { tag: Self::TAG }.into())
29 }
30
31 fn from_bytes_ref(bytes_ref: &BytesRef) -> &Self {
35 #[allow(unsafe_code)]
37 unsafe {
38 &*(bytes_ref.as_ptr() as *const Self)
39 }
40 }
41
42 #[must_use]
44 pub fn as_bytes(&self) -> &[u8] {
45 self.inner.as_slice()
46 }
47
48 #[must_use]
50 pub fn len(&self) -> Length {
51 self.inner.len()
52 }
53
54 #[must_use]
56 pub fn is_empty(&self) -> bool {
57 self.inner.is_empty()
58 }
59
60 pub fn decode_into<'a, T: Decode<'a>>(&'a self) -> Result<T, T::Error> {
65 Decode::from_der(self.as_bytes())
66 }
67}
68
69impl_any_conversions!(&'a OctetStringRef, 'a);
70
71impl AsRef<[u8]> for OctetStringRef {
72 fn as_ref(&self) -> &[u8] {
73 self.as_bytes()
74 }
75}
76
77impl<'a> DecodeValue<'a> for &'a OctetStringRef {
78 type Error = Error;
79
80 fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> Result<Self, Error> {
81 <&'a BytesRef>::decode_value(reader, header).map(OctetStringRef::from_bytes_ref)
82 }
83}
84
85impl EncodeValue for &OctetStringRef {
86 fn value_len(&self) -> Result<Length, Error> {
87 self.inner.value_len()
88 }
89
90 fn encode_value(&self, writer: &mut impl Writer) -> Result<(), Error> {
91 self.inner.encode_value(writer)
92 }
93}
94
95impl FixedTag for OctetStringRef {
96 const TAG: Tag = Tag::OctetString;
97}
98impl FixedTag for &OctetStringRef {
99 const TAG: Tag = Tag::OctetString;
100}
101
102impl OrdIsValueOrd for &OctetStringRef {}
103
104impl<'a> From<&'a OctetStringRef> for AnyRef<'a> {
105 fn from(octet_string: &'a OctetStringRef) -> AnyRef<'a> {
106 AnyRef::from_tag_and_value(Tag::OctetString, &octet_string.inner)
107 }
108}
109
110impl<'a> From<&'a OctetStringRef> for &'a [u8] {
111 fn from(octet_string: &'a OctetStringRef) -> &'a [u8] {
112 octet_string.as_bytes()
113 }
114}
115
116impl<'a> TryFrom<&'a [u8]> for &'a OctetStringRef {
117 type Error = Error;
118
119 fn try_from(byte_slice: &'a [u8]) -> Result<Self, Error> {
120 OctetStringRef::new(byte_slice)
121 }
122}
123
124impl<'a> TryFrom<&&'a [u8]> for &'a OctetStringRef {
126 type Error = Error;
127
128 fn try_from(byte_slice: &&'a [u8]) -> Result<Self, Error> {
129 OctetStringRef::new(byte_slice)
130 }
131}
132
133impl<'a, const N: usize> TryFrom<&'a [u8; N]> for &'a OctetStringRef {
134 type Error = Error;
135
136 fn try_from(byte_slice: &'a [u8; N]) -> Result<Self, Error> {
137 OctetStringRef::new(byte_slice)
138 }
139}
140
141impl<'a, const N: usize> TryFrom<&'a OctetStringRef> for [u8; N] {
142 type Error = Error;
143
144 fn try_from(octet_string: &'a OctetStringRef) -> Result<Self, Self::Error> {
145 octet_string
146 .as_bytes()
147 .try_into()
148 .map_err(|_| Tag::OctetString.length_error().into())
149 }
150}
151
152#[cfg(feature = "heapless")]
153impl<const N: usize> TryFrom<&OctetStringRef> for heapless::Vec<u8, N> {
154 type Error = Error;
155
156 fn try_from(octet_string: &OctetStringRef) -> Result<Self, Self::Error> {
157 octet_string
158 .as_bytes()
159 .try_into()
160 .map_err(|_| Tag::OctetString.length_error().into())
161 }
162}
163
164#[cfg(feature = "heapless")]
165impl<'a, const N: usize> TryFrom<&'a heapless::Vec<u8, N>> for &'a OctetStringRef {
166 type Error = Error;
167
168 fn try_from(byte_vec: &'a heapless::Vec<u8, N>) -> Result<Self, Error> {
169 OctetStringRef::new(byte_vec)
170 }
171}
172
173#[cfg(feature = "alloc")]
174pub use self::allocating::OctetString;
175
176#[cfg(feature = "alloc")]
177mod allocating {
178 use super::*;
179 use crate::BytesOwned;
180 use alloc::{
181 borrow::{Borrow, Cow, ToOwned},
182 boxed::Box,
183 vec::Vec,
184 };
185
186 #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
193 pub struct OctetString {
194 pub(super) inner: BytesOwned,
196 }
197
198 impl OctetString {
199 pub fn new(bytes: impl Into<Box<[u8]>>) -> Result<Self, Error> {
204 let inner = BytesOwned::new(bytes)?;
205
206 OctetStringRef::new(inner.as_slice())?;
208
209 Ok(Self { inner })
210 }
211
212 #[must_use]
214 pub fn as_bytes(&self) -> &[u8] {
215 self.inner.as_slice()
216 }
217
218 #[must_use]
220 pub fn into_bytes(self) -> Box<[u8]> {
221 self.inner.into()
222 }
223
224 #[must_use]
226 pub fn len(&self) -> Length {
227 self.inner.len()
228 }
229
230 #[must_use]
232 pub fn is_empty(&self) -> bool {
233 self.inner.is_empty()
234 }
235 }
236
237 impl_any_conversions!(OctetString);
238
239 impl AsRef<[u8]> for OctetString {
240 fn as_ref(&self) -> &[u8] {
241 self.as_bytes()
242 }
243 }
244
245 impl Borrow<OctetStringRef> for OctetString {
246 fn borrow(&self) -> &OctetStringRef {
247 OctetStringRef::from_bytes_ref(self.inner.as_ref())
248 }
249 }
250
251 impl<'a> DecodeValue<'a> for OctetString {
252 type Error = Error;
253
254 fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> Result<Self, Error> {
255 let inner = BytesOwned::decode_value_parts(reader, header, Self::TAG)?;
256 Ok(Self { inner })
257 }
258 }
259
260 impl EncodeValue for OctetString {
261 fn value_len(&self) -> Result<Length, Error> {
262 self.inner.value_len()
263 }
264
265 fn encode_value(&self, writer: &mut impl Writer) -> Result<(), Error> {
266 self.inner.encode_value(writer)
267 }
268 }
269
270 impl FixedTag for OctetString {
271 const TAG: Tag = Tag::OctetString;
272 }
273
274 impl OrdIsValueOrd for OctetString {}
275
276 impl<'a> From<&'a OctetString> for &'a OctetStringRef {
277 fn from(octet_string: &'a OctetString) -> &'a OctetStringRef {
278 OctetStringRef::from_bytes_ref(octet_string.inner.as_ref())
279 }
280 }
281
282 impl From<&OctetStringRef> for OctetString {
283 fn from(octet_string_ref: &OctetStringRef) -> OctetString {
284 Self {
285 inner: octet_string_ref.inner.to_owned(),
286 }
287 }
288 }
289
290 impl From<&OctetStringRef> for Vec<u8> {
291 fn from(octet_string: &OctetStringRef) -> Vec<u8> {
292 Vec::from(octet_string.as_bytes())
293 }
294 }
295
296 impl<'a> TryFrom<&'a Vec<u8>> for &'a OctetStringRef {
298 type Error = Error;
299
300 fn try_from(byte_vec: &'a Vec<u8>) -> Result<Self, Error> {
301 OctetStringRef::new(byte_vec)
302 }
303 }
304
305 impl From<OctetString> for Vec<u8> {
306 fn from(octet_string: OctetString) -> Vec<u8> {
307 octet_string.into_bytes().into()
308 }
309 }
310
311 impl ToOwned for OctetStringRef {
312 type Owned = OctetString;
313
314 fn to_owned(&self) -> OctetString {
315 self.into()
316 }
317 }
318
319 impl<'a> TryFrom<&'a Cow<'a, [u8]>> for &'a OctetStringRef {
320 type Error = Error;
321
322 fn try_from(byte_slice: &'a Cow<'a, [u8]>) -> Result<Self, Error> {
323 OctetStringRef::new(byte_slice)
324 }
325 }
326
327 impl<'a> TryFrom<&'a OctetStringRef> for Cow<'a, [u8]> {
328 type Error = Error;
329
330 fn try_from(octet_string: &'a OctetStringRef) -> Result<Self, Self::Error> {
331 Ok(Cow::Borrowed(octet_string.as_bytes()))
332 }
333 }
334
335 #[cfg(feature = "arbitrary")]
338 impl<'a> arbitrary::Arbitrary<'a> for OctetString {
339 fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
340 Self::new(Vec::arbitrary(u)?).map_err(|_| arbitrary::Error::IncorrectFormat)
341 }
342
343 fn size_hint(depth: usize) -> (usize, Option<usize>) {
344 arbitrary::size_hint::and(u8::size_hint(depth), Vec::<u8>::size_hint(depth))
345 }
346 }
347}
348
349#[cfg(feature = "bytes")]
350mod bytes {
351 use super::{OctetString, OctetStringRef};
352 use crate::{
353 DecodeValue, EncodeValue, Error, FixedTag, Header, Length, Reader, Result, Tag, Writer,
354 };
355 use alloc::vec::Vec;
356 use bytes::Bytes;
357
358 impl<'a> DecodeValue<'a> for Bytes {
359 type Error = Error;
360
361 fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> Result<Self> {
362 OctetString::decode_value(reader, header).map(Into::into)
363 }
364 }
365
366 impl EncodeValue for Bytes {
367 fn value_len(&self) -> Result<Length> {
368 self.len().try_into()
369 }
370
371 fn encode_value(&self, writer: &mut impl Writer) -> Result<()> {
372 writer.write(self.as_ref())
373 }
374 }
375
376 impl FixedTag for Bytes {
377 const TAG: Tag = Tag::OctetString;
378 }
379
380 impl From<&OctetStringRef> for Bytes {
381 fn from(octet_string: &OctetStringRef) -> Bytes {
382 Vec::from(octet_string).into()
383 }
384 }
385
386 impl From<OctetString> for Bytes {
387 fn from(octet_string: OctetString) -> Bytes {
388 Vec::from(octet_string).into()
389 }
390 }
391}
392
393#[cfg(test)]
394#[allow(clippy::unwrap_used)]
395mod tests {
396 use crate::{
397 Decode,
398 asn1::{OctetStringRef, PrintableStringRef},
399 };
400 use hex_literal::hex;
401
402 #[cfg(feature = "alloc")]
403 use {crate::Encode, alloc::borrow::Cow};
404
405 #[test]
406 fn octet_string_decode() {
407 const EXAMPLE: &[u8] = &hex!(
409 "040c" "48656c6c6f2c20776f726c64" );
412
413 let decoded = <&OctetStringRef>::from_der(EXAMPLE).unwrap();
414 assert_eq!(decoded.as_bytes(), b"Hello, world");
415 }
416
417 #[test]
418 fn octet_string_decode_into() {
419 let der = b"\x13\x02\x68\x69";
421 let oct = OctetStringRef::new(der).unwrap();
422
423 let res = oct.decode_into::<PrintableStringRef<'_>>().unwrap();
424 assert_eq!(AsRef::<str>::as_ref(&res), "hi");
425 }
426
427 #[cfg(feature = "alloc")]
428 #[test]
429 fn cow_octet_string_decode_and_encode() {
430 const EXAMPLE: &[u8] = &hex!(
432 "040c" "48656c6c6f2c20776f726c64" );
435
436 let decoded = Cow::<OctetStringRef>::from_der(EXAMPLE).unwrap();
437 assert_eq!(decoded.as_bytes(), b"Hello, world");
438
439 let encoded = decoded.to_der().unwrap();
440 assert_eq!(EXAMPLE, encoded);
441 }
442
443 #[test]
444 #[cfg(all(feature = "alloc", feature = "ber"))]
445 fn decode_ber_primitive_definite() {
446 use crate::{Decode, asn1::OctetString};
447 use hex_literal::hex;
448
449 const EXAMPLE: &[u8] = &hex!(
450 "040c" "48656c6c6f2c20776f726c64" );
453
454 let decoded = OctetString::from_ber(EXAMPLE).unwrap();
455 assert_eq!(decoded.as_bytes(), b"Hello, world");
456
457 let decoded = OctetString::from_der(EXAMPLE).unwrap();
458 assert_eq!(decoded.as_bytes(), b"Hello, world");
459 }
460
461 #[test]
462 #[cfg(all(feature = "alloc", feature = "ber"))]
463 fn decode_ber_constructed_indefinite() {
464 use crate::{Decode, asn1::OctetString};
465 use hex_literal::hex;
466
467 const EXAMPLE_BER: &[u8] = &hex!(
468 "2480" "040648656c6c6f2c" "040620776f726c64" "0000" );
473
474 let decoded = OctetString::from_ber(EXAMPLE_BER).unwrap();
475 assert_eq!(decoded.as_bytes(), b"Hello, world");
476 }
477
478 #[test]
479 #[cfg(all(feature = "alloc", feature = "ber"))]
480 fn decode_ber_constructed_definite() {
481 use crate::{Decode, Error, ErrorKind, Length, Tag, asn1::OctetString};
482 use hex_literal::hex;
483
484 const EXAMPLE_BER: &[u8] = &hex!(
485 "2410" "040648656c6c6f2c" "040620776f726c64" );
489
490 let err = OctetString::from_ber(EXAMPLE_BER).err().unwrap();
491 let expected = Error::new(
492 ErrorKind::Noncanonical {
493 tag: Tag::OctetString,
494 },
495 Length::new(1),
496 );
497 assert_eq!(expected, err);
498 }
499
500 #[test]
501 #[cfg(all(feature = "alloc", feature = "ber"))]
502 fn decode_context_specific_ber_explicit() {
503 use crate::{
504 EncodingRules, SliceReader, TagNumber,
505 asn1::{ContextSpecific, OctetString},
506 };
507 use hex_literal::hex;
508
509 let tag_number = TagNumber(0);
510
511 const EXAMPLE_BER: &[u8] = &hex!(
512 "A080" "2480" "040648656c6c6f2c" "040620776f726c64" "0000" "0000" );
519
520 let mut reader =
521 SliceReader::new_with_encoding_rules(EXAMPLE_BER, EncodingRules::Ber).unwrap();
522
523 let decoded = ContextSpecific::<OctetString>::decode_explicit(&mut reader, tag_number)
524 .unwrap()
525 .unwrap()
526 .value;
527
528 assert_eq!(decoded.as_bytes(), b"Hello, world");
529 }
530
531 #[test]
532 #[cfg(all(feature = "alloc", feature = "ber"))]
533 fn decode_context_specific_ber_implicit() {
534 use crate::{
535 EncodingRules, SliceReader, TagNumber,
536 asn1::{ContextSpecific, OctetString},
537 };
538 use hex_literal::hex;
539
540 let tag_number = TagNumber(0);
541
542 const EXAMPLE_BER: &[u8] = &hex!(
543 "A080" "040648656c6c6f2c" "040620776f726c64" "0000" );
548
549 let mut reader =
550 SliceReader::new_with_encoding_rules(EXAMPLE_BER, EncodingRules::Ber).unwrap();
551
552 let decoded = ContextSpecific::<OctetString>::decode_implicit(&mut reader, tag_number)
553 .unwrap()
554 .unwrap()
555 .value;
556
557 assert_eq!(decoded.as_bytes(), b"Hello, world");
558 }
559
560 #[test]
561 #[cfg(all(feature = "alloc", feature = "ber"))]
562 fn decode_ber_recursive_unsupported() {
563 use crate::{Decode, Error, ErrorKind, Length, asn1::OctetString};
564 use hex_literal::hex;
565
566 const EXAMPLE_BER: &[u8] = &hex!(
567 "2480" "2480" "040648656c6c6f2c" "040620776f726c64" "0000" "040620776f726c64" "0000" );
575
576 let err = OctetString::from_ber(EXAMPLE_BER).err().unwrap();
577 let expected = Error::new(ErrorKind::IndefiniteLength, Length::new(4));
578 assert_eq!(expected, err);
579 }
580}