1use alloc::{collections::BTreeMap, format, string::String};
4use core::{
5 fmt,
6 ops::{Deref, DerefMut},
7};
8use serde::{de::DeserializeOwned, Deserialize, Serialize};
9use serde_json::Value;
10
11#[cfg(any(test, feature = "arbitrary"))]
12mod arbitrary_;
13
14#[derive(Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
27#[serde(transparent)]
28pub struct OtherFields {
29 inner: BTreeMap<String, serde_json::Value>,
30}
31
32impl OtherFields {
33 pub const fn new(inner: BTreeMap<String, serde_json::Value>) -> Self {
35 Self { inner }
36 }
37
38 pub fn insert_value(&mut self, key: String, value: impl Serialize) -> serde_json::Result<()> {
40 self.inner.insert(key, serde_json::to_value(value)?);
41 Ok(())
42 }
43
44 pub fn with_value(mut self, key: String, value: impl Serialize) -> serde_json::Result<Self> {
47 self.insert_value(key, value)?;
48 Ok(self)
49 }
50
51 pub fn deserialize_as<T: DeserializeOwned>(&self) -> serde_json::Result<T> {
53 serde_json::from_value(Value::Object(self.inner.clone().into_iter().collect()))
54 }
55
56 pub fn deserialize_into<T: DeserializeOwned>(self) -> serde_json::Result<T> {
58 serde_json::from_value(serde_json::Value::Object(self.inner.into_iter().collect()))
59 }
60
61 pub fn get_with<F, V>(&self, key: impl AsRef<str>, with: F) -> Option<V>
64 where
65 F: FnOnce(serde_json::Value) -> V,
66 {
67 self.inner.get(key.as_ref()).cloned().map(with)
68 }
69
70 pub fn get_deserialized<V: DeserializeOwned>(
72 &self,
73 key: impl AsRef<str>,
74 ) -> Option<serde_json::Result<V>> {
75 self.get_with(key, serde_json::from_value)
76 }
77
78 pub fn try_get_deserialized<V: DeserializeOwned>(
82 &self,
83 key: impl AsRef<str>,
84 ) -> serde_json::Result<V> {
85 let key = key.as_ref();
86 self.get_deserialized(key)
87 .ok_or_else(|| serde::de::Error::custom(format!("Missing field `{key}`")))?
88 }
89
90 pub fn remove_deserialized<V: DeserializeOwned>(
94 &mut self,
95 key: impl AsRef<str>,
96 ) -> Option<serde_json::Result<V>> {
97 self.inner.remove(key.as_ref()).map(serde_json::from_value)
98 }
99
100 pub fn remove_with<F, V>(&mut self, key: impl AsRef<str>, with: F) -> Option<V>
105 where
106 F: FnOnce(serde_json::Value) -> V,
107 {
108 self.inner.remove(key.as_ref()).map(with)
109 }
110
111 pub fn remove_entry_deserialized<V: DeserializeOwned>(
115 &mut self,
116 key: impl AsRef<str>,
117 ) -> Option<(String, serde_json::Result<V>)> {
118 self.inner
119 .remove_entry(key.as_ref())
120 .map(|(key, value)| (key, serde_json::from_value(value)))
121 }
122}
123
124impl fmt::Debug for OtherFields {
125 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
126 f.write_str("OtherFields ")?;
127 self.inner.fmt(f)
128 }
129}
130
131impl TryFrom<serde_json::Value> for OtherFields {
132 type Error = serde_json::Error;
133
134 fn try_from(value: serde_json::Value) -> Result<Self, Self::Error> {
135 serde_json::from_value(value).map(Self::new)
136 }
137}
138
139impl<K> FromIterator<(K, serde_json::Value)> for OtherFields
140where
141 K: Into<String>,
142{
143 fn from_iter<T: IntoIterator<Item = (K, serde_json::Value)>>(iter: T) -> Self {
144 Self { inner: iter.into_iter().map(|(key, value)| (key.into(), value)).collect() }
145 }
146}
147
148impl Deref for OtherFields {
149 type Target = BTreeMap<String, serde_json::Value>;
150
151 #[inline]
152 fn deref(&self) -> &BTreeMap<String, serde_json::Value> {
153 self.as_ref()
154 }
155}
156
157impl DerefMut for OtherFields {
158 fn deref_mut(&mut self) -> &mut Self::Target {
159 &mut self.inner
160 }
161}
162
163impl AsRef<BTreeMap<String, serde_json::Value>> for OtherFields {
164 fn as_ref(&self) -> &BTreeMap<String, serde_json::Value> {
165 &self.inner
166 }
167}
168
169impl IntoIterator for OtherFields {
170 type Item = (String, serde_json::Value);
171 type IntoIter = alloc::collections::btree_map::IntoIter<String, serde_json::Value>;
172
173 fn into_iter(self) -> Self::IntoIter {
174 self.inner.into_iter()
175 }
176}
177
178impl<'a> IntoIterator for &'a OtherFields {
179 type Item = (&'a String, &'a serde_json::Value);
180 type IntoIter = alloc::collections::btree_map::Iter<'a, String, serde_json::Value>;
181
182 fn into_iter(self) -> Self::IntoIter {
183 self.as_ref().iter()
184 }
185}
186
187#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize)]
191#[cfg_attr(any(test, feature = "arbitrary"), derive(arbitrary::Arbitrary))]
192pub struct WithOtherFields<T> {
193 #[serde(flatten)]
195 pub inner: T,
196 #[serde(flatten)]
198 pub other: OtherFields,
199}
200
201impl<T, U> AsRef<U> for WithOtherFields<T>
202where
203 T: AsRef<U>,
204{
205 fn as_ref(&self) -> &U {
206 self.inner.as_ref()
207 }
208}
209
210impl<T> WithOtherFields<T> {
211 pub fn new(inner: T) -> Self {
213 Self { inner, other: Default::default() }
214 }
215
216 pub fn into_inner(self) -> T {
218 self.inner
219 }
220
221 pub const fn inner(&self) -> &T {
223 &self.inner
224 }
225}
226
227impl<T> Deref for WithOtherFields<T> {
228 type Target = T;
229
230 fn deref(&self) -> &Self::Target {
231 &self.inner
232 }
233}
234
235impl<T> DerefMut for WithOtherFields<T> {
236 fn deref_mut(&mut self) -> &mut Self::Target {
237 &mut self.inner
238 }
239}
240
241impl<'de, T> Deserialize<'de> for WithOtherFields<T>
242where
243 T: Deserialize<'de> + Serialize,
244{
245 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
246 where
247 D: serde::Deserializer<'de>,
248 {
249 #[derive(Deserialize)]
250 struct WithOtherFieldsHelper<T> {
251 #[serde(flatten)]
252 inner: T,
253 #[serde(flatten)]
254 other: OtherFields,
255 }
256
257 let mut helper = WithOtherFieldsHelper::deserialize(deserializer)?;
258 if let Value::Object(map) =
262 serde_json::to_value(&helper.inner).map_err(serde::de::Error::custom)?
263 {
264 for key in map.keys() {
265 helper.other.remove(key);
266 }
267 }
268
269 Ok(Self { inner: helper.inner, other: helper.other })
270 }
271}
272
273#[cfg(test)]
274mod tests {
275 use super::*;
276 use alloc::string::ToString;
277 use rand::Rng;
278 use serde_json::json;
279 use similar_asserts::assert_eq;
280
281 #[test]
282 fn other_fields_arbitrary() {
283 let mut bytes = [0u8; 1024];
284 rand::thread_rng().fill(bytes.as_mut_slice());
285
286 let _ = arbitrary::Unstructured::new(&bytes).arbitrary::<OtherFields>().unwrap();
287 }
288
289 #[test]
290 fn test_correct_other() {
291 #[derive(Serialize, Deserialize)]
292 struct Inner {
293 a: u64,
294 }
295
296 #[derive(Serialize, Deserialize)]
297 struct InnerWrapper {
298 #[serde(flatten)]
299 inner: Inner,
300 }
301
302 let with_other: WithOtherFields<InnerWrapper> =
303 serde_json::from_str("{\"a\": 1, \"b\": 2}").unwrap();
304 assert_eq!(with_other.inner.inner.a, 1);
305 assert_eq!(
306 with_other.other,
307 OtherFields::new(BTreeMap::from_iter([("b".to_string(), serde_json::json!(2))]))
308 );
309 }
310
311 #[test]
312 fn test_with_other_fields_serialization() {
313 #[derive(Serialize, Deserialize, PartialEq, Debug)]
314 struct Inner {
315 a: u64,
316 b: String,
317 }
318
319 let inner = Inner { a: 42, b: "Hello".to_string() };
320 let mut other = BTreeMap::new();
321 other.insert("extra".to_string(), json!(99));
322
323 let with_other = WithOtherFields { inner, other: OtherFields::new(other.clone()) };
324 let serialized = serde_json::to_string(&with_other).unwrap();
325
326 let expected = r#"{"a":42,"b":"Hello","extra":99}"#;
327 assert_eq!(serialized, expected);
328 }
329
330 #[test]
331 fn test_remove_and_access_other_fields() {
332 #[derive(Serialize, Deserialize, PartialEq, Debug)]
333 struct Inner {
334 a: u64,
335 b: String,
336 }
337
338 let json_data = r#"{"a":42,"b":"Hello","extra":99, "another": "test"}"#;
339 let mut with_other: WithOtherFields<Inner> = serde_json::from_str(json_data).unwrap();
340
341 assert_eq!(with_other.other.inner.get("extra"), Some(&json!(99)));
342 assert_eq!(with_other.other.inner.get("another"), Some(&json!("test")));
343
344 with_other.other.remove("extra");
345 assert!(!with_other.other.inner.contains_key("extra"));
346 }
347
348 #[test]
349 fn test_deserialize_as() {
350 let mut map = BTreeMap::new();
351 map.insert("a".to_string(), json!(1));
352 let other_fields = OtherFields::new(map);
353 let deserialized: Result<BTreeMap<String, u64>, _> = other_fields.deserialize_as();
354 assert_eq!(deserialized.unwrap().get("a"), Some(&1));
355 }
356
357 #[test]
358 fn test_deserialize_into() {
359 let mut map = BTreeMap::new();
360 map.insert("a".to_string(), json!(1));
361 let other_fields = OtherFields::new(map);
362 let deserialized: Result<BTreeMap<String, u64>, _> = other_fields.deserialize_into();
363 assert_eq!(deserialized.unwrap().get("a"), Some(&1));
364 }
365
366 #[test]
367 fn test_get_with() {
368 let mut map = BTreeMap::new();
369 map.insert("key".to_string(), json!(42));
370 let other_fields = OtherFields::new(map);
371 let value: Option<u64> = other_fields.get_with("key", |v| v.as_u64().unwrap());
372 assert_eq!(value, Some(42));
373 }
374
375 #[test]
376 fn test_get_deserialized() {
377 let mut map = BTreeMap::new();
378 map.insert("key".to_string(), json!(42));
379 let other_fields = OtherFields::new(map);
380 let value: Option<serde_json::Result<u64>> = other_fields.get_deserialized("key");
381 assert_eq!(value.unwrap().unwrap(), 42);
382 }
383
384 #[test]
385 fn test_remove_deserialized() {
386 let mut map = BTreeMap::new();
387 map.insert("key".to_string(), json!(42));
388 let mut other_fields = OtherFields::new(map);
389 let value: Option<serde_json::Result<u64>> = other_fields.remove_deserialized("key");
390 assert_eq!(value.unwrap().unwrap(), 42);
391 assert!(!other_fields.inner.contains_key("key"));
392 }
393
394 #[test]
395 fn test_remove_with() {
396 let mut map = BTreeMap::new();
397 map.insert("key".to_string(), json!(42));
398 let mut other_fields = OtherFields::new(map);
399 let value: Option<u64> = other_fields.remove_with("key", |v| v.as_u64().unwrap());
400 assert_eq!(value, Some(42));
401 assert!(!other_fields.inner.contains_key("key"));
402 }
403
404 #[test]
405 fn test_remove_entry_deserialized() {
406 let mut map = BTreeMap::new();
407 map.insert("key".to_string(), json!(42));
408 let mut other_fields = OtherFields::new(map);
409 let entry: Option<(String, serde_json::Result<u64>)> =
410 other_fields.remove_entry_deserialized("key");
411 assert!(entry.is_some());
412 let (key, value) = entry.unwrap();
413 assert_eq!(key, "key");
414 assert_eq!(value.unwrap(), 42);
415 assert!(!other_fields.inner.contains_key("key"));
416 }
417
418 #[test]
419 fn test_try_from_value() {
420 let json_value = json!({ "key": "value" });
421 let other_fields = OtherFields::try_from(json_value).unwrap();
422 assert_eq!(other_fields.inner.get("key").unwrap(), &json!("value"));
423 }
424
425 #[test]
426 fn test_into_iter() {
427 let mut map = BTreeMap::new();
428 map.insert("key1".to_string(), json!("value1"));
429 map.insert("key2".to_string(), json!("value2"));
430 let other_fields = OtherFields::new(map.clone());
431
432 let iterated_map: BTreeMap<_, _> = other_fields.into_iter().collect();
433 assert_eq!(iterated_map, map);
434 }
435}