Skip to main content

nextjson/
bytes.rs

1//! Explicit byte-string wrapper for compact binary wire types.
2//!
3//! As in serde, plain `Vec<u8>` / `&[u8]` / `[u8; N]` keep the generic
4//! sequence representation (an array of `u8`), which is lossless everywhere.
5//! A type that wants a *native* byte string on the wire (length prefix + raw
6//! bytes in binary formats) wraps its slice in [`Bytes`]; the encoder then
7//! calls [`FormatEncoder::write_bytes`](crate::ser::FormatEncoder::write_bytes)
8//! and the decoder
9//! [`FormatDecoder::bytes`](crate::de::FormatDecoder::bytes).
10
11use alloc::borrow::Cow;
12use core::ops::Deref;
13
14use crate::de::{DecodeSlot, FormatDecoder, NsonDeserialize};
15use crate::error::{Error, Result};
16use crate::schema::{NsonSchema, TypeSchema};
17use crate::ser::{FormatEncoder, NsonSerialize};
18
19/// A borrowed byte string that round-trips through the dedicated bytes path.
20///
21/// ```rust
22/// use nextjson::Bytes;
23///
24/// let value = Bytes(b"\x00\x01binary");
25/// let json = nextjson::nextencode(&value)?;
26/// // JSON keeps the array spelling for compatibility with plain `Vec<u8>`:
27/// assert_eq!(json, b"[0,1,98,105,110,97,114,121]");
28/// # Ok::<(), nextjson::Error>(())
29/// ```
30#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
31pub struct Bytes<'a>(pub &'a [u8]);
32
33impl<'a> Bytes<'a> {
34    /// The wrapped byte slice.
35    pub fn as_bytes(&self) -> &'a [u8] {
36        self.0
37    }
38}
39
40impl<'a> From<&'a [u8]> for Bytes<'a> {
41    fn from(bytes: &'a [u8]) -> Self {
42        Bytes(bytes)
43    }
44}
45
46impl<'a> From<&'a str> for Bytes<'a> {
47    fn from(text: &'a str) -> Self {
48        Bytes(text.as_bytes())
49    }
50}
51
52impl<'a> Deref for Bytes<'a> {
53    type Target = [u8];
54    fn deref(&self) -> &[u8] {
55        self.0
56    }
57}
58
59impl<'a> AsRef<[u8]> for Bytes<'a> {
60    fn as_ref(&self) -> &[u8] {
61        self.0
62    }
63}
64
65impl NsonSchema for Bytes<'_> {
66    const SCHEMA: TypeSchema = TypeSchema::Bytes;
67}
68
69impl NsonSerialize for Bytes<'_> {
70    fn nextencode<E: FormatEncoder>(&self, encoder: &mut E) -> Result<(), E::Error> {
71        encoder.write_bytes(self.0)
72    }
73}
74
75impl<'de, 'a> NsonDeserialize<'de> for Bytes<'a>
76where
77    'de: 'a,
78{
79    fn nextdecode_into<D: FormatDecoder<'de>>(
80        decoder: &mut D,
81        out: &mut DecodeSlot<Self>,
82    ) -> Result<(), D::Error> {
83        match decoder.bytes()? {
84            Cow::Borrowed(b) => {
85                out.write(Bytes(b));
86                Ok(())
87            }
88            Cow::Owned(_) => Err(Error::invalid_type(
89                "a borrowed byte string (no escape sequences)",
90                "bytes",
91            )
92            .into()),
93        }
94    }
95}