sval/data/
binary.rs

1use crate::{std::fmt, tags, Result, Stream, Value};
2
3/**
4An adapter that streams a slice of 8bit unsigned integers as binary.
5
6For fixed-size arrays, see the [`BinaryArray`] type.
7*/
8#[repr(transparent)]
9pub struct BinarySlice([u8]);
10
11impl BinarySlice {
12    /**
13    Treat a slice of 8bit unsigned integers as binary.
14    */
15    #[inline(always)]
16    pub const fn new<'a>(binary: &'a [u8]) -> &'a Self {
17        // SAFETY: `Binary` and `[u8]` have the same ABI
18        unsafe { &*(binary as *const _ as *const BinarySlice) }
19    }
20
21    /**
22    Get a reference to the underlying slice.
23    */
24    #[inline(always)]
25    pub const fn as_slice(&self) -> &[u8] {
26        &self.0
27    }
28}
29
30impl fmt::Debug for BinarySlice {
31    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
32        fmt::Debug::fmt(&self.0, f)
33    }
34}
35
36impl AsRef<[u8]> for BinarySlice {
37    #[inline(always)]
38    fn as_ref(&self) -> &[u8] {
39        &self.0
40    }
41}
42
43impl Value for BinarySlice {
44    fn stream<'sval, S: Stream<'sval> + ?Sized>(&'sval self, stream: &mut S) -> Result {
45        stream.binary_begin(Some(self.0.len()))?;
46        stream.binary_fragment(&self.0)?;
47        stream.binary_end()
48    }
49
50    #[inline(always)]
51    fn to_binary(&self) -> Option<&[u8]> {
52        Some(&self.0)
53    }
54}
55
56/**
57An adapter that streams a slice of 8bit unsigned integers as binary with a fixed size.
58
59This type is like [`BinarySlice`], but for fixed-size arrays.
60*/
61#[repr(transparent)]
62pub struct BinaryArray<const N: usize>([u8; N]);
63
64impl<const N: usize> BinaryArray<N> {
65    /**
66    Treat a slice of 8bit unsigned integers as binary.
67    */
68    #[inline(always)]
69    pub const fn new<'a>(binary: &'a [u8; N]) -> &'a Self {
70        // SAFETY: `Binary` and `[u8; N]` have the same ABI
71        unsafe { &*(binary as *const _ as *const BinaryArray<N>) }
72    }
73
74    /**
75    Get a reference to the underlying slice.
76    */
77    #[inline(always)]
78    pub const fn as_slice(&self) -> &[u8; N] {
79        &self.0
80    }
81}
82
83impl<const N: usize> fmt::Debug for BinaryArray<N> {
84    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
85        fmt::Debug::fmt(&self.0, f)
86    }
87}
88
89impl<const N: usize> AsRef<[u8; N]> for BinaryArray<N> {
90    #[inline(always)]
91    fn as_ref(&self) -> &[u8; N] {
92        &self.0
93    }
94}
95
96impl<const N: usize> Value for BinaryArray<N> {
97    fn stream<'sval, S: Stream<'sval> + ?Sized>(&'sval self, stream: &mut S) -> Result {
98        stream.tagged_begin(Some(&tags::CONSTANT_SIZE), None, None)?;
99        stream.binary_begin(Some(self.0.len()))?;
100        stream.binary_fragment(&self.0)?;
101        stream.binary_end()?;
102        stream.tagged_end(Some(&tags::CONSTANT_SIZE), None, None)
103    }
104
105    #[inline(always)]
106    fn to_binary(&self) -> Option<&[u8]> {
107        Some(&self.0)
108    }
109}
110
111#[cfg(test)]
112mod tests {
113    use super::*;
114
115    #[test]
116    fn binary_cast() {
117        assert_eq!(Some(b"abc" as &[u8]), BinarySlice::new(b"abc").to_binary());
118        assert_eq!(Some(b"abc" as &[u8]), BinaryArray::new(b"abc").to_binary());
119    }
120}