Skip to main content

librqbit_buffers/
lib.rs

1// This crate used for making working with &[u8] or Vec<u8> generic in other parts of librqbit,
2// for nicer display of binary data etc.
3//
4// Not useful outside of librqbit.
5
6use std::borrow::Borrow;
7
8use bytes::Bytes;
9use serde::{Deserializer, Serialize};
10use serde_derive::Deserialize;
11
12use clone_to_owned::CloneToOwned;
13
14#[derive(Default, PartialEq, Eq, Hash, Clone, PartialOrd, Ord)]
15pub struct ByteBufOwned(pub bytes::Bytes);
16
17#[derive(Default, Deserialize, PartialEq, Eq, Hash, Clone, Copy, PartialOrd, Ord)]
18#[serde(transparent)]
19pub struct ByteBuf<'a>(pub &'a [u8]);
20
21pub trait ByteBufT:
22    AsRef<[u8]>
23    + Default
24    + std::hash::Hash
25    + Serialize
26    + Eq
27    + core::fmt::Debug
28    + CloneToOwned
29    + Borrow<[u8]>
30{
31}
32
33impl ByteBufT for ByteBufOwned {}
34
35impl ByteBufT for ByteBuf<'_> {}
36
37struct HexBytes<'a>(&'a [u8]);
38impl std::fmt::Display for HexBytes<'_> {
39    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
40        for byte in self.0 {
41            write!(f, "{byte:02x?}")?;
42        }
43        Ok(())
44    }
45}
46
47fn debug_bytes(b: &[u8], f: &mut std::fmt::Formatter<'_>, debug_strings: bool) -> std::fmt::Result {
48    if b.is_empty() {
49        return Ok(());
50    }
51    if b.iter().all(|b| *b == 0) {
52        return write!(f, "<{} bytes, all zeroes>", b.len());
53    }
54    match std::str::from_utf8(b) {
55        Ok(s) => {
56            if debug_strings {
57                return write!(f, "{s:?}");
58            } else {
59                return write!(f, "{s}");
60            }
61        }
62        Err(_e) => {}
63    };
64
65    // up to 20 bytes, display hex
66    if b.len() <= 20 {
67        return write!(f, "<{} bytes, 0x{}>", b.len(), HexBytes(b));
68    }
69
70    write!(f, "<{} bytes>", b.len())
71}
72
73impl std::fmt::Debug for ByteBuf<'_> {
74    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
75        debug_bytes(self.0, f, true)
76    }
77}
78
79impl std::fmt::Display for ByteBuf<'_> {
80    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
81        debug_bytes(self.0, f, false)
82    }
83}
84
85impl std::fmt::Debug for ByteBufOwned {
86    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
87        debug_bytes(&self.0, f, true)
88    }
89}
90
91impl std::fmt::Display for ByteBufOwned {
92    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
93        debug_bytes(&self.0, f, false)
94    }
95}
96
97impl CloneToOwned for ByteBuf<'_> {
98    type Target = ByteBufOwned;
99
100    fn clone_to_owned(&self, within_buffer: Option<&Bytes>) -> Self::Target {
101        // Try zero-copy from the provided buffer.
102        if let Some(within_buffer) = within_buffer {
103            let haystack = within_buffer.as_ptr() as usize;
104            let haystack_end = haystack + within_buffer.len();
105            let needle = self.0.as_ptr() as usize;
106            let needle_end = needle + self.0.len();
107
108            if needle >= haystack && needle_end <= haystack_end {
109                return ByteBufOwned(within_buffer.slice_ref(self.0.as_ref()));
110            } else {
111                #[cfg(debug_assertions)]
112                panic!("bug: broken buffers! not inside within_buffer");
113            }
114        }
115
116        ByteBufOwned(Bytes::copy_from_slice(self.0))
117    }
118}
119
120impl CloneToOwned for ByteBufOwned {
121    type Target = ByteBufOwned;
122
123    fn clone_to_owned(&self, _within_buffer: Option<&Bytes>) -> Self::Target {
124        ByteBufOwned(self.0.clone())
125    }
126}
127
128impl std::convert::AsRef<[u8]> for ByteBuf<'_> {
129    fn as_ref(&self) -> &[u8] {
130        self.0
131    }
132}
133
134impl std::convert::AsRef<[u8]> for ByteBufOwned {
135    fn as_ref(&self) -> &[u8] {
136        &self.0
137    }
138}
139
140impl std::borrow::Borrow<[u8]> for ByteBufOwned {
141    fn borrow(&self) -> &[u8] {
142        &self.0
143    }
144}
145
146impl std::borrow::Borrow<[u8]> for ByteBuf<'_> {
147    fn borrow(&self) -> &[u8] {
148        self.0
149    }
150}
151
152impl<'a> From<&'a [u8]> for ByteBuf<'a> {
153    fn from(b: &'a [u8]) -> Self {
154        Self(b)
155    }
156}
157
158impl<'a> From<&'a [u8]> for ByteBufOwned {
159    fn from(b: &'a [u8]) -> Self {
160        Self(b.to_owned().into())
161    }
162}
163
164impl From<Vec<u8>> for ByteBufOwned {
165    fn from(b: Vec<u8>) -> Self {
166        Self(b.into())
167    }
168}
169
170impl From<Bytes> for ByteBufOwned {
171    fn from(b: Bytes) -> Self {
172        Self(b)
173    }
174}
175
176impl serde::ser::Serialize for ByteBuf<'_> {
177    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
178    where
179        S: serde::Serializer,
180    {
181        serializer.serialize_bytes(self.as_ref())
182    }
183}
184
185impl serde::ser::Serialize for ByteBufOwned {
186    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
187    where
188        S: serde::Serializer,
189    {
190        serializer.serialize_bytes(self.as_ref())
191    }
192}
193
194impl<'de> serde::de::Deserialize<'de> for ByteBufOwned {
195    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
196    where
197        D: Deserializer<'de>,
198    {
199        struct Visitor;
200
201        impl serde::de::Visitor<'_> for Visitor {
202            type Value = ByteBufOwned;
203
204            fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
205                formatter.write_str("byte string")
206            }
207            fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
208            where
209                E: serde::de::Error,
210            {
211                Ok(v.to_owned().into())
212            }
213        }
214        deserializer.deserialize_byte_buf(Visitor {})
215    }
216}