1use std::ops::Deref;
2
3use binrw::{BinRead, BinWrite};
4
5#[cfg(feature = "zeroize")]
6use zeroize::Zeroize;
7
8#[derive(Debug, Clone)]
9#[cfg_attr(feature = "zeroize", derive(Zeroize))]
10enum Inner<'b> {
11 Owned(Vec<u8>),
12
13 #[cfg_attr(feature = "zeroize", zeroize(skip))]
14 Borrowed(&'b [u8]),
15}
16
17#[derive(Debug, Clone)]
21#[cfg_attr(feature = "zeroize", derive(Zeroize))]
22pub struct Bytes<'b> {
23 inner: Inner<'b>,
24}
25
26impl<'b> Default for Bytes<'b> {
27 fn default() -> Self {
28 Self {
29 inner: Inner::Owned(Default::default()),
30 }
31 }
32}
33
34impl<'b> Bytes<'b> {
35 pub const fn owned(value: Vec<u8>) -> Self {
37 Self {
38 inner: Inner::Owned(value),
39 }
40 }
41
42 pub const fn borrowed(value: &'b [u8]) -> Self {
44 Self {
45 inner: Inner::Borrowed(value),
46 }
47 }
48
49 pub fn as_borrow<'a: 'b>(&'a self) -> Bytes<'a> {
51 Bytes::borrowed(self)
52 }
53
54 pub fn into_vec(self) -> Vec<u8> {
56 match self.inner {
57 Inner::Owned(vec) => vec,
58 Inner::Borrowed(slice) => slice.to_vec(),
59 }
60 }
61}
62
63impl Deref for Bytes<'_> {
64 type Target = [u8];
65
66 fn deref(&self) -> &Self::Target {
67 match self.inner {
68 Inner::Owned(ref vec) => vec,
69 Inner::Borrowed(slice) => slice,
70 }
71 }
72}
73
74impl AsRef<[u8]> for Bytes<'_> {
75 fn as_ref(&self) -> &[u8] {
76 self
77 }
78}
79
80impl PartialEq for Bytes<'_> {
81 fn eq(&self, other: &Bytes<'_>) -> bool {
82 **self == **other
83 }
84}
85
86impl Eq for Bytes<'_> {}
87
88impl From<Vec<u8>> for Bytes<'_> {
89 fn from(value: Vec<u8>) -> Self {
90 Self::owned(value)
91 }
92}
93
94impl<'b> From<&'b [u8]> for Bytes<'b> {
95 fn from(value: &'b [u8]) -> Self {
96 Self::borrowed(value)
97 }
98}
99
100impl BinRead for Bytes<'_> {
101 type Args<'a> = ();
102
103 fn read_options<R: std::io::Read + std::io::Seek>(
104 reader: &mut R,
105 endian: binrw::Endian,
106 args: Self::Args<'_>,
107 ) -> binrw::BinResult<Self> {
108 let size = u32::read_be(reader)?;
109
110 BinRead::read_options(
111 reader,
112 endian,
113 binrw::VecArgs {
114 count: size as usize,
115 inner: args,
116 },
117 )
118 .map(Self::owned)
119 }
120}
121
122impl BinWrite for Bytes<'_> {
123 type Args<'a> = ();
124
125 fn write_options<W: std::io::Write + std::io::Seek>(
126 &self,
127 writer: &mut W,
128 endian: binrw::Endian,
129 args: Self::Args<'_>,
130 ) -> binrw::BinResult<()> {
131 let buf = &**self;
132 let size = buf.len() as u32;
133
134 size.write_be(writer)?;
135 buf.write_options(writer, endian, args)
136 }
137}