defuse_serde_utils/
cow.rs1use std::{borrow::Cow, marker::PhantomData};
2
3use serde::{Deserializer, Serializer};
4use serde_with::{DeserializeAs, SerializeAs, ser::SerializeAsWrap};
5
6pub struct AsCowSlice<As: ?Sized>(PhantomData<As>);
10
11impl<T, As> SerializeAs<Cow<'_, [T]>> for AsCowSlice<As>
12where
13 T: Clone,
14 As: SerializeAs<T>,
15{
16 fn serialize_as<S>(source: &Cow<'_, [T]>, serializer: S) -> Result<S::Ok, S::Error>
17 where
18 S: Serializer,
19 {
20 serializer.collect_seq(source.iter().map(SerializeAsWrap::<T, As>::new))
21 }
22}
23
24impl<'de, 'a, T, As> DeserializeAs<'de, Cow<'a, [T]>> for AsCowSlice<As>
25where
26 T: Clone,
27 As: DeserializeAs<'de, T>,
28{
29 fn deserialize_as<D>(deserializer: D) -> Result<Cow<'a, [T]>, D::Error>
30 where
31 D: Deserializer<'de>,
32 {
33 <Vec<As> as DeserializeAs<'de, Vec<T>>>::deserialize_as(deserializer).map(Cow::Owned)
34 }
35}
36
37#[cfg(feature = "schemars-v0_8")]
38const _: () = {
39 use schemars::{SchemaGenerator, schema::Schema};
40 use serde_with::schemars_0_8::JsonSchemaAs;
41
42 impl<T, As> JsonSchemaAs<Cow<'_, [T]>> for AsCowSlice<As>
43 where
44 T: Clone,
45 As: JsonSchemaAs<T>,
46 {
47 fn schema_name() -> String {
48 <Vec<As> as JsonSchemaAs<Vec<T>>>::schema_name()
49 }
50
51 fn json_schema(generator: &mut SchemaGenerator) -> Schema {
52 <Vec<As> as JsonSchemaAs<Vec<T>>>::json_schema(generator)
53 }
54
55 fn is_referenceable() -> bool {
56 <Vec<As> as JsonSchemaAs<Vec<T>>>::is_referenceable()
57 }
58 }
59};
60
61#[cfg(test)]
62mod tests {
63 use super::*;
64 use serde::{Deserialize, Serialize};
65 use serde_with::{DisplayFromStr, serde_as};
66
67 #[serde_as]
68 #[derive(Debug, Serialize, Deserialize)]
69 struct S<'a> {
70 #[serde_as(as = "AsCowSlice<DisplayFromStr>")]
71 amounts: Cow<'a, [u128]>,
72 }
73
74 #[test]
75 fn serializes_as_strings() {
76 let s = S {
77 amounts: Cow::Owned(vec![1, u128::MAX]),
78 };
79 let json = serde_json::to_string(&s).unwrap();
80 assert_eq!(json, format!(r#"{{"amounts":["1","{}"]}}"#, u128::MAX));
81 }
82
83 #[test]
84 fn roundtrip() {
85 let s = S {
86 amounts: Cow::Owned(vec![0, 42, u128::MAX]),
87 };
88 let json = serde_json::to_string(&s).unwrap();
89 let back: S = serde_json::from_str(&json).unwrap();
90 assert_eq!(back.amounts.into_owned(), vec![0, 42, u128::MAX]);
91 }
92}