blueprint_core/
metadata.rs1use core::convert::Infallible;
4use core::fmt;
5use core::str::FromStr;
6
7use alloc::borrow::Cow;
8use alloc::collections::BTreeMap;
9use alloc::collections::btree_map::{Entry, Iter, IterMut};
10use alloc::string::String;
11use alloc::vec::Vec;
12use bytes::{Bytes, BytesMut};
13
14#[derive(Clone, Debug, Default, PartialEq)]
20pub struct MetadataMap<T> {
21 map: BTreeMap<Cow<'static, str>, T>,
22}
23
24impl<T> MetadataMap<T> {
25 pub fn new() -> Self {
27 Self {
28 map: BTreeMap::new(),
29 }
30 }
31
32 pub fn len(&self) -> usize {
34 self.map.len()
35 }
36
37 pub fn is_empty(&self) -> bool {
39 self.map.is_empty()
40 }
41
42 pub fn insert<K, V>(&mut self, key: K, value: V) -> Option<T>
50 where
51 K: Into<Cow<'static, str>>,
52 V: Into<T>,
53 {
54 self.map.insert(key.into(), value.into())
55 }
56
57 pub fn get<K>(&self, key: K) -> Option<&T>
59 where
60 K: AsRef<str>,
61 {
62 self.map.get(key.as_ref())
63 }
64
65 pub fn get_mut<K>(&mut self, key: &K) -> Option<&mut T>
67 where
68 K: AsRef<str>,
69 {
70 self.map.get_mut(key.as_ref())
71 }
72
73 pub fn remove<K>(&mut self, key: &K) -> Option<T>
76 where
77 K: AsRef<str>,
78 {
79 self.map.remove(key.as_ref())
80 }
81
82 pub fn clear(&mut self) {
84 self.map.clear();
85 }
86
87 pub fn iter(&self) -> Iter<'_, Cow<'static, str>, T> {
89 self.map.iter()
90 }
91
92 pub fn iter_mut(&mut self) -> IterMut<'_, Cow<'static, str>, T> {
94 self.map.iter_mut()
95 }
96
97 pub fn entry<K>(&mut self, key: K) -> Entry<'_, Cow<'static, str>, T>
99 where
100 K: Into<Cow<'static, str>>,
101 {
102 self.map.entry(key.into())
103 }
104
105 pub fn extend(&mut self, other: Self) {
107 self.map.extend(other.map);
108 }
109}
110
111#[derive(Clone, Default)]
117pub struct MetadataValue {
118 inner: Bytes,
119 is_sensitive: bool,
120}
121
122impl FromStr for MetadataValue {
123 type Err = Infallible;
124
125 fn from_str(s: &str) -> Result<Self, Self::Err> {
126 Ok(Self {
127 inner: Bytes::copy_from_slice(s.as_bytes()),
128 is_sensitive: false,
129 })
130 }
131}
132
133impl MetadataValue {
134 pub fn from_bytes(value: Bytes) -> Self {
136 Self {
137 inner: value,
138 is_sensitive: false,
139 }
140 }
141
142 pub fn from_sensitive_str(value: &str) -> Self {
144 Self {
145 inner: Bytes::copy_from_slice(value.as_bytes()),
146 is_sensitive: true,
147 }
148 }
149
150 pub fn from_sensitive_bytes(value: Bytes) -> Self {
152 Self {
153 inner: value,
154 is_sensitive: true,
155 }
156 }
157
158 pub fn is_sensitive(&self) -> bool {
160 self.is_sensitive
161 }
162
163 pub fn len(&self) -> usize {
165 self.inner.len()
166 }
167
168 pub fn is_empty(&self) -> bool {
170 self.inner.is_empty()
171 }
172
173 pub fn to_str(&self) -> Result<&str, core::str::Utf8Error> {
175 core::str::from_utf8(&self.inner)
176 }
177
178 pub fn into_bytes(self) -> Bytes {
180 self.inner
181 }
182
183 pub fn as_bytes(&self) -> &[u8] {
184 &self.inner[..]
185 }
186}
187
188impl AsRef<[u8]> for MetadataValue {
189 #[inline]
190 fn as_ref(&self) -> &[u8] {
191 self.inner.as_ref()
192 }
193}
194
195impl fmt::Debug for MetadataValue {
196 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
197 if self.is_sensitive {
198 f.write_str("Sensitive")
199 } else {
200 f.write_str("\"")?;
201 let mut from = 0;
202 let bytes = self.as_bytes();
203 for (i, &b) in bytes.iter().enumerate() {
204 if !is_visible_ascii(b) || b == b'"' {
205 if from != i {
206 f.write_str(
207 core::str::from_utf8(&bytes[from..i]).map_err(|_| fmt::Error)?,
208 )?;
209 }
210 if b == b'"' {
211 f.write_str("\\\"")?;
212 } else {
213 write!(f, "\\x{b:x}")?;
214 }
215 from = i + 1;
216 }
217 }
218
219 if from != bytes.len() {
220 f.write_str(core::str::from_utf8(&bytes[from..]).map_err(|_| fmt::Error)?)?;
221 }
222 f.write_str("\"")
223 }
224 }
225}
226
227impl From<&str> for MetadataValue {
228 fn from(value: &str) -> Self {
229 Self::from_str(value).unwrap()
230 }
231}
232
233impl From<Bytes> for MetadataValue {
234 fn from(value: Bytes) -> Self {
235 Self::from_bytes(value)
236 }
237}
238
239impl From<&Bytes> for MetadataValue {
240 fn from(value: &Bytes) -> Self {
241 Self::from_bytes(value.clone())
242 }
243}
244
245impl From<BytesMut> for MetadataValue {
246 fn from(value: BytesMut) -> Self {
247 Self::from_bytes(value.freeze())
248 }
249}
250
251impl From<&BytesMut> for MetadataValue {
252 fn from(value: &BytesMut) -> Self {
253 Self::from_bytes(value.clone().freeze())
254 }
255}
256
257impl From<String> for MetadataValue {
258 fn from(value: String) -> Self {
259 Self::from_str(&value).unwrap()
260 }
261}
262
263impl From<&String> for MetadataValue {
264 fn from(value: &String) -> Self {
265 Self::from_str(value).unwrap()
266 }
267}
268
269impl From<&[u8]> for MetadataValue {
270 fn from(value: &[u8]) -> Self {
271 Self::from_bytes(Bytes::copy_from_slice(value))
272 }
273}
274
275impl From<Vec<u8>> for MetadataValue {
276 fn from(value: Vec<u8>) -> Self {
277 Self::from_bytes(Bytes::from(value))
278 }
279}
280
281impl From<&Vec<u8>> for MetadataValue {
282 fn from(value: &Vec<u8>) -> Self {
283 Self::from_bytes(Bytes::copy_from_slice(value))
284 }
285}
286
287impl<const N: usize> From<[u8; N]> for MetadataValue {
288 fn from(value: [u8; N]) -> Self {
289 Self::from_bytes(Bytes::copy_from_slice(&value))
290 }
291}
292
293impl<const N: usize> From<&[u8; N]> for MetadataValue {
294 fn from(value: &[u8; N]) -> Self {
295 Self::from_bytes(Bytes::copy_from_slice(value))
296 }
297}
298
299macro_rules! impl_from_numbers {
300 ($($t:ty),*) => {
301 $(
302 impl From<$t> for MetadataValue {
304 fn from(value: $t) -> Self {
305 Self::from_bytes(Bytes::copy_from_slice(&value.to_be_bytes()))
306 }
307 }
308
309 impl From<&$t> for MetadataValue {
310 fn from(value: &$t) -> Self {
311 Self::from_bytes(Bytes::copy_from_slice(&value.to_be_bytes()))
312 }
313 }
314 )*
315
316 };
317}
318
319macro_rules! impl_try_from_metadata_for_numbers {
320 ($($t:ty),*) => {
321 $(
322 impl core::convert::TryFrom<MetadataValue> for $t {
324 type Error = core::array::TryFromSliceError;
325
326 fn try_from(value: MetadataValue) -> Result<Self, Self::Error> {
327 let bytes = value.as_bytes();
328 let mut arr = [0; core::mem::size_of::<Self>()];
329 arr.copy_from_slice(bytes);
330 Ok(Self::from_be_bytes(arr))
331 }
332 }
333
334 impl core::convert::TryFrom<&MetadataValue> for $t {
336 type Error = core::array::TryFromSliceError;
337
338 fn try_from(value: &MetadataValue) -> Result<Self, Self::Error> {
339 let bytes = value.as_bytes();
340 let mut arr = [0; core::mem::size_of::<Self>()];
341 arr.copy_from_slice(bytes);
342 Ok(Self::from_be_bytes(arr))
343 }
344 }
345 )*
346 };
347}
348
349impl_from_numbers! { u16, u32, u64, u128, usize, i16, i32, i64, i128, isize }
350impl_try_from_metadata_for_numbers! { u16, u32, u64, u128, usize, i16, i32, i64, i128, isize }
351
352const fn is_visible_ascii(b: u8) -> bool {
353 b >= 32 && b < 127 || b == b'\t'
354}