serde_strings/
lib.rs

1// serde-strings
2// Copyright (C) SOFe
3//
4// Licensed under the Apache License, Version 2.0 (the License);
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8//     http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an AS IS BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15
16use std::fmt::Display;
17use std::str::FromStr;
18
19use serde::{de::Error, Deserialize, Deserializer, Serialize, Serializer};
20
21/// Wraps a value Display and/or FromStr value to be used as a field in a derive(Serialize) or
22/// derive(Deserialize) struct/enum.
23#[derive(Clone, Copy, Debug, Default, Hash, Eq, PartialEq, Ord, PartialOrd)]
24pub struct SerdeStr<T> {
25    /// The inner value
26    pub value: T,
27}
28
29impl<T> SerdeStr<T> {
30    /// Gets a reference of the inner value.
31    #[inline]
32    pub fn value(&self) -> &T {
33        &self.value
34    }
35
36    /// Gets a mutable reference of the inner value.
37    #[inline]
38    pub fn value_mut(&mut self) -> &mut T {
39        &mut self.value
40    }
41
42    /// Sets the inner value.
43    #[inline]
44    pub fn set_value(&mut self, t: T) {
45        self.value = t;
46    }
47
48    /// Moves out the inner value.
49    #[inline]
50    pub fn unwrap(self) -> T {
51        self.value
52    }
53}
54
55/// Creates a SerdeStr from its inner value.
56impl<T> From<T> for SerdeStr<T> {
57    #[inline]
58    fn from(value: T) -> Self {
59        Self { value }
60    }
61}
62
63impl<'de, T: FromStr> Deserialize<'de> for SerdeStr<T>
64where
65    T: FromStr,
66    <T as FromStr>::Err: Display,
67{
68    #[inline]
69    fn deserialize<D>(de: D) -> Result<Self, D::Error>
70    where
71        D: Deserializer<'de>,
72    {
73        Ok(Self {
74            value: String::deserialize(de)?
75                .parse()
76                .map_err(|err| Error::custom(err))?,
77        })
78    }
79}
80
81impl<T> Serialize for SerdeStr<T>
82where
83    T: Display,
84{
85    #[inline]
86    fn serialize<S>(&self, ser: S) -> Result<S::Ok, S::Error>
87    where
88        S: Serializer,
89    {
90        self.value.to_string().serialize(ser)
91    }
92}
93
94#[cfg(test)]
95mod test_de {
96    use std::collections::HashMap;
97
98    use serde_derive::Deserialize;
99
100    use crate::SerdeStr;
101
102    #[derive(Debug, PartialEq)]
103    struct IsParsed(i32);
104
105    impl std::str::FromStr for IsParsed {
106        type Err = &'static str;
107
108        fn from_str(str: &str) -> Result<Self, Self::Err> {
109            Ok(IsParsed(str.len() as i32))
110        }
111    }
112
113    #[derive(Debug, Deserialize, PartialEq)]
114    struct Schema {
115        data: SerdeStr<IsParsed>,
116    }
117
118    #[test]
119    fn test_parse() {
120        let mut map = HashMap::new();
121        map.insert("data", "abc");
122        let json = serde_json::to_string(&map).unwrap();
123        let parsed = serde_json::from_str::<Schema>(&json);
124        assert_eq!(
125            parsed.unwrap(),
126            Schema {
127                data: SerdeStr { value: IsParsed(3) }
128            }
129        );
130    }
131}
132
133#[cfg(test)]
134mod test_ser {
135    use std::fmt::{Display, Formatter, Result};
136
137    use serde_derive::Serialize;
138
139    use crate::SerdeStr;
140
141    #[derive(Debug)]
142    struct CanDisplay(&'static str);
143
144    impl Display for CanDisplay {
145        fn fmt(&self, f: &mut Formatter) -> Result {
146            write!(f, "{}", self.0.len())
147        }
148    }
149
150    #[derive(Debug, Serialize)]
151    struct Schema {
152        data: SerdeStr<CanDisplay>,
153    }
154
155    #[test]
156    fn test_display() {
157        let json = serde_json::to_string(&Schema {
158            data: SerdeStr {
159                value: CanDisplay("abc"),
160            },
161        });
162        assert_eq!(json.unwrap(), r##"{"data":"3"}"##);
163    }
164}