1use std::borrow::Cow;
2
3use facet::Facet;
4
5#[repr(u8)]
11#[derive(Debug, Clone, PartialEq, Eq, Facet)]
12pub enum MetadataValue<'a> {
13 String(Cow<'a, str>) = 0,
14 Bytes(Cow<'a, [u8]>) = 1,
15 U64(u64) = 2,
16}
17
18#[derive(Debug, Clone, Copy, PartialEq, Eq, Facet)]
25#[repr(transparent)]
26#[facet(transparent)]
27pub struct MetadataFlags(u64);
28
29impl MetadataFlags {
30 pub const NONE: Self = Self(0);
32
33 pub const SENSITIVE: Self = Self(1 << 0);
35
36 pub const NO_PROPAGATE: Self = Self(1 << 1);
38
39 pub fn contains(self, other: Self) -> bool {
41 (self.0 & other.0) == other.0
42 }
43}
44
45impl std::ops::BitOr for MetadataFlags {
46 type Output = Self;
47 fn bitor(self, rhs: Self) -> Self {
48 Self(self.0 | rhs.0)
49 }
50}
51
52impl std::ops::BitOrAssign for MetadataFlags {
53 fn bitor_assign(&mut self, rhs: Self) {
54 self.0 |= rhs.0;
55 }
56}
57
58impl std::ops::BitAnd for MetadataFlags {
59 type Output = Self;
60 fn bitand(self, rhs: Self) -> Self {
61 Self(self.0 & rhs.0)
62 }
63}
64
65impl std::ops::BitAndAssign for MetadataFlags {
66 fn bitand_assign(&mut self, rhs: Self) {
67 self.0 &= rhs.0;
68 }
69}
70
71#[derive(Debug, Clone, PartialEq, Eq, Facet)]
77pub struct MetadataEntry<'a> {
78 pub key: Cow<'a, str>,
79 pub value: MetadataValue<'a>,
80 pub flags: MetadataFlags,
81}
82
83impl<'a> MetadataValue<'a> {
84 pub fn into_owned(self) -> MetadataValue<'static> {
86 match self {
87 MetadataValue::String(s) => MetadataValue::String(Cow::Owned(s.into_owned())),
88 MetadataValue::Bytes(b) => MetadataValue::Bytes(Cow::Owned(b.into_owned())),
89 MetadataValue::U64(n) => MetadataValue::U64(n),
90 }
91 }
92}
93
94impl<'a> MetadataEntry<'a> {
95 pub fn str(key: impl Into<Cow<'a, str>>, value: impl Into<Cow<'a, str>>) -> Self {
97 MetadataEntry {
98 key: key.into(),
99 value: MetadataValue::String(value.into()),
100 flags: MetadataFlags::NONE,
101 }
102 }
103
104 pub fn u64(key: impl Into<Cow<'a, str>>, value: u64) -> Self {
106 MetadataEntry {
107 key: key.into(),
108 value: MetadataValue::U64(value),
109 flags: MetadataFlags::NONE,
110 }
111 }
112
113 pub fn bytes(key: impl Into<Cow<'a, str>>, value: impl Into<Cow<'a, [u8]>>) -> Self {
115 MetadataEntry {
116 key: key.into(),
117 value: MetadataValue::Bytes(value.into()),
118 flags: MetadataFlags::NONE,
119 }
120 }
121
122 pub fn with_flags(mut self, flags: MetadataFlags) -> Self {
124 self.flags = flags;
125 self
126 }
127
128 pub fn into_owned(self) -> MetadataEntry<'static> {
130 MetadataEntry {
131 key: Cow::Owned(self.key.into_owned()),
132 value: self.value.into_owned(),
133 flags: self.flags,
134 }
135 }
136}
137
138pub struct MetadataBuilder<'a> {
140 entries: Metadata<'a>,
141}
142
143impl<'a> MetadataBuilder<'a> {
144 pub fn str(mut self, key: impl Into<Cow<'a, str>>, value: impl Into<Cow<'a, str>>) -> Self {
146 self.entries.push(MetadataEntry::str(key, value));
147 self
148 }
149
150 pub fn u64(mut self, key: impl Into<Cow<'a, str>>, value: u64) -> Self {
152 self.entries.push(MetadataEntry::u64(key, value));
153 self
154 }
155
156 pub fn bytes(mut self, key: impl Into<Cow<'a, str>>, value: impl Into<Cow<'a, [u8]>>) -> Self {
158 self.entries.push(MetadataEntry::bytes(key, value));
159 self
160 }
161
162 pub fn done(self) -> Metadata<'a> {
164 self.entries
165 }
166}
167
168pub fn metadata_build<'a>() -> MetadataBuilder<'a> {
170 MetadataBuilder {
171 entries: Vec::new(),
172 }
173}
174
175pub type Metadata<'a> = Vec<MetadataEntry<'a>>;
178
179pub fn metadata_into_owned(metadata: Metadata<'_>) -> Metadata<'static> {
181 metadata
182 .into_iter()
183 .map(MetadataEntry::into_owned)
184 .collect()
185}
186
187pub fn metadata_get_str<'a>(metadata: &'a [MetadataEntry<'a>], key: &str) -> Option<&'a str> {
189 metadata.iter().find_map(|e| {
190 if e.key == key {
191 match &e.value {
192 MetadataValue::String(s) => Some(s.as_ref()),
193 _ => None,
194 }
195 } else {
196 None
197 }
198 })
199}
200
201pub fn metadata_get_u64(metadata: &[MetadataEntry], key: &str) -> Option<u64> {
203 metadata.iter().find_map(|e| {
204 if e.key == key {
205 match &e.value {
206 MetadataValue::U64(n) => Some(*n),
207 _ => None,
208 }
209 } else {
210 None
211 }
212 })
213}