sbrd_gen/
value.rs

1#![deny(missing_debug_implementations)]
2//! Module for value
3
4use chrono::{NaiveDate, NaiveDateTime, NaiveTime};
5use rt_format::{Format, FormatArgument, NoNamedArguments, ParsedFormat, Specifier};
6use std::collections::BTreeMap;
7use std::fmt;
8use std::fmt::{Debug, Formatter};
9
10use serde::de::{Error, Unexpected, Visitor};
11use serde::{Deserialize, Deserializer, Serialize, Serializer};
12
13/// KVS for this crate
14pub type ValueMap<K, S> = BTreeMap<K, S>;
15/// KVS for [`DataValue`]
16///
17/// [`DataValue`]: ./enum.DataValue.html
18pub type DataValueMap<K> = ValueMap<K, DataValue>;
19
20/// Integer type for this crate
21pub type SbrdInt = i32;
22/// Real type for this crate
23pub type SbrdReal = f32;
24/// Boolean type for this crate
25pub type SbrdBool = bool;
26/// String type for this crate
27pub type SbrdString = String;
28/// DateTime type for this crate
29pub type SbrdDateTime = NaiveDateTime;
30/// Date type for this crate
31pub type SbrdDate = NaiveDate;
32/// Time type for this crate
33pub type SbrdTime = NaiveTime;
34
35/// Default format string for [`SbrdDateTime`]
36///
37/// [`SbrdDateTime`]: ./type.SbrdDateTime.html
38pub const DATE_TIME_DEFAULT_FORMAT: &str = "%Y-%m-%d %H:%M:%S";
39/// Default format string for [`SbrdDate`]
40///
41/// [`SbrdDate`]: ./type.SbrdDate.html
42pub const DATE_DEFAULT_FORMAT: &str = "%Y-%m-%d";
43/// Default format string for [`SbrdTime`]
44///
45/// [`SbrdTime`]: ./type.SbrdTime.html
46pub const TIME_DEFAULT_FORMAT: &str = "%H:%M:%S";
47
48/// Value for [`Schema`]
49///
50/// [`Schema`]: ../schema/struct.Schema.html
51#[derive(Debug, PartialEq, Clone)]
52pub enum DataValue {
53    /// Integer
54    Int(SbrdInt),
55    /// Real
56    Real(SbrdReal),
57    /// Boolean
58    Bool(SbrdBool),
59    /// String
60    String(String),
61    /// Null
62    Null,
63}
64
65impl From<SbrdInt> for DataValue {
66    fn from(v: SbrdInt) -> Self {
67        Self::Int(v)
68    }
69}
70
71impl From<SbrdReal> for DataValue {
72    fn from(v: SbrdReal) -> Self {
73        Self::Real(v)
74    }
75}
76
77impl From<SbrdBool> for DataValue {
78    fn from(v: SbrdBool) -> Self {
79        Self::Bool(v)
80    }
81}
82
83impl From<String> for DataValue {
84    fn from(v: String) -> Self {
85        Self::String(v)
86    }
87}
88
89impl From<SbrdDateTime> for DataValue {
90    fn from(v: SbrdDateTime) -> Self {
91        Self::String(v.format(DATE_TIME_DEFAULT_FORMAT).to_string())
92    }
93}
94
95impl From<SbrdDate> for DataValue {
96    fn from(v: SbrdDate) -> Self {
97        Self::String(v.format(DATE_DEFAULT_FORMAT).to_string())
98    }
99}
100
101impl From<SbrdTime> for DataValue {
102    fn from(v: SbrdTime) -> Self {
103        Self::String(v.format(TIME_DEFAULT_FORMAT).to_string())
104    }
105}
106
107struct DataValueVisitor;
108impl<'de> Visitor<'de> for DataValueVisitor {
109    type Value = DataValue;
110
111    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
112        formatter.write_str("null or string for value parameter.")
113    }
114
115    fn visit_i64<E>(self, v: i64) -> Result<Self::Value, E>
116    where
117        E: Error,
118    {
119        let i = SbrdInt::try_from(v);
120        match i {
121            Err(_) => Err(Error::invalid_value(Unexpected::Signed(v), &self)),
122            Ok(parsed) => Ok(DataValue::Int(parsed)),
123        }
124    }
125
126    fn visit_u64<E>(self, v: u64) -> Result<Self::Value, E>
127    where
128        E: Error,
129    {
130        let i = SbrdInt::try_from(v);
131        match i {
132            Err(_) => Err(Error::invalid_value(Unexpected::Unsigned(v as u64), &self)),
133            Ok(parsed) => Ok(DataValue::Int(parsed)),
134        }
135    }
136
137    fn visit_f64<E>(self, v: f64) -> Result<Self::Value, E>
138    where
139        E: Error,
140    {
141        Ok(DataValue::Real(v as SbrdReal))
142    }
143
144    fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
145    where
146        E: Error,
147    {
148        Ok(DataValue::String(v.to_string()))
149    }
150
151    fn visit_string<E>(self, v: String) -> Result<Self::Value, E>
152    where
153        E: Error,
154    {
155        Ok(DataValue::String(v))
156    }
157
158    fn visit_none<E>(self) -> Result<Self::Value, E>
159    where
160        E: Error,
161    {
162        Ok(DataValue::Null)
163    }
164
165    fn visit_some<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
166    where
167        D: Deserializer<'de>,
168    {
169        deserializer.deserialize_any(Self)
170    }
171}
172
173impl<'de> Deserialize<'de> for DataValue {
174    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
175    where
176        D: Deserializer<'de>,
177    {
178        deserializer.deserialize_option(DataValueVisitor)
179    }
180}
181
182impl Serialize for DataValue {
183    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
184    where
185        S: Serializer,
186    {
187        match &self {
188            DataValue::Int(v) => serializer.serialize_i32(*v),
189            DataValue::Real(v) => serializer.serialize_f32(*v),
190            DataValue::Bool(v) => serializer.serialize_bool(*v),
191            DataValue::String(v) => serializer.serialize_str(v),
192            DataValue::Null => serializer.serialize_unit(),
193        }
194    }
195}
196
197impl std::fmt::Display for DataValue {
198    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
199        match self {
200            DataValue::Int(v) => fmt::Display::fmt(v, f),
201            DataValue::Real(v) => fmt::Display::fmt(v, f),
202            DataValue::Bool(v) => fmt::Display::fmt(v, f),
203            DataValue::String(v) => fmt::Display::fmt(v, f),
204            DataValue::Null => write!(f, "null"),
205        }
206    }
207}
208
209impl FormatArgument for DataValue {
210    fn supports_format(&self, specifier: &Specifier) -> bool {
211        <&DataValue as FormatArgument>::supports_format(&self, specifier)
212    }
213
214    fn fmt_display(&self, f: &mut Formatter) -> fmt::Result {
215        <&DataValue as FormatArgument>::fmt_display(&self, f)
216    }
217
218    fn fmt_debug(&self, f: &mut Formatter) -> fmt::Result {
219        <&DataValue as FormatArgument>::fmt_debug(&self, f)
220    }
221
222    fn fmt_octal(&self, f: &mut Formatter) -> fmt::Result {
223        <&DataValue as FormatArgument>::fmt_octal(&self, f)
224    }
225
226    fn fmt_lower_hex(&self, f: &mut Formatter) -> fmt::Result {
227        <&DataValue as FormatArgument>::fmt_lower_hex(&self, f)
228    }
229
230    fn fmt_upper_hex(&self, f: &mut Formatter) -> fmt::Result {
231        <&DataValue as FormatArgument>::fmt_upper_exp(&self, f)
232    }
233
234    fn fmt_binary(&self, f: &mut Formatter) -> fmt::Result {
235        <&DataValue as FormatArgument>::fmt_binary(&self, f)
236    }
237
238    fn fmt_lower_exp(&self, f: &mut Formatter) -> fmt::Result {
239        <&DataValue as FormatArgument>::fmt_lower_exp(&self, f)
240    }
241
242    fn fmt_upper_exp(&self, f: &mut Formatter) -> fmt::Result {
243        <&DataValue as FormatArgument>::fmt_upper_exp(&self, f)
244    }
245
246    fn to_usize(&self) -> Result<usize, ()> {
247        <&DataValue as FormatArgument>::to_usize(&self)
248    }
249}
250
251impl<'a> FormatArgument for &'a DataValue {
252    fn supports_format(&self, specifier: &Specifier) -> bool {
253        // Not support debug format in release build.
254        if !cfg!(debug_assertions) && specifier.format == Format::Debug {
255            return false;
256        }
257
258        match self {
259            DataValue::Int(_) | DataValue::Null => true,
260            DataValue::Real(_) => matches!(
261                specifier.format,
262                Format::Display | Format::Debug | Format::LowerExp | Format::UpperExp
263            ),
264            DataValue::Bool(_) | DataValue::String(_) => {
265                matches!(specifier.format, Format::Display | Format::Debug)
266            }
267        }
268    }
269
270    fn fmt_display(&self, f: &mut Formatter) -> fmt::Result {
271        fmt::Display::fmt(*self, f)
272    }
273
274    fn fmt_debug(&self, f: &mut Formatter) -> fmt::Result {
275        fmt::Debug::fmt(*self, f)
276    }
277
278    fn fmt_octal(&self, f: &mut Formatter) -> fmt::Result {
279        match self {
280            DataValue::Int(v) => fmt::Octal::fmt(v, f),
281            DataValue::Null => {
282                // not format null value
283                self.fmt_display(f)
284            }
285            _ => Err(fmt::Error),
286        }
287    }
288
289    fn fmt_lower_hex(&self, f: &mut Formatter) -> fmt::Result {
290        match self {
291            DataValue::Int(v) => fmt::LowerHex::fmt(v, f),
292            DataValue::Null => {
293                // not format null value
294                self.fmt_display(f)
295            }
296            _ => Err(fmt::Error),
297        }
298    }
299
300    fn fmt_upper_hex(&self, f: &mut Formatter) -> fmt::Result {
301        match self {
302            DataValue::Int(v) => fmt::UpperHex::fmt(v, f),
303            DataValue::Null => {
304                // not format null value
305                self.fmt_display(f)
306            }
307            _ => Err(fmt::Error),
308        }
309    }
310
311    fn fmt_binary(&self, f: &mut Formatter) -> fmt::Result {
312        match self {
313            DataValue::Int(v) => fmt::Binary::fmt(v, f),
314            DataValue::Null => {
315                // not format null value
316                self.fmt_display(f)
317            }
318            _ => Err(fmt::Error),
319        }
320    }
321
322    fn fmt_lower_exp(&self, f: &mut Formatter) -> fmt::Result {
323        match self {
324            DataValue::Int(v) => fmt::LowerExp::fmt(v, f),
325            DataValue::Real(v) => fmt::LowerExp::fmt(v, f),
326            DataValue::Null => {
327                // not format null value
328                self.fmt_display(f)
329            }
330            _ => Err(fmt::Error),
331        }
332    }
333
334    fn fmt_upper_exp(&self, f: &mut Formatter) -> fmt::Result {
335        match self {
336            DataValue::Int(v) => fmt::UpperExp::fmt(v, f),
337            DataValue::Real(v) => fmt::UpperExp::fmt(v, f),
338            DataValue::Null => {
339                // not format null value
340                self.fmt_display(f)
341            }
342            _ => Err(fmt::Error),
343        }
344    }
345
346    fn to_usize(&self) -> Result<usize, ()> {
347        // Not support
348        Err(())
349    }
350}
351
352impl DataValue {
353    /// Convert to String to use when permute with other Strings
354    pub fn to_permutation_string(&self) -> String {
355        match self {
356            DataValue::Int(v) => v.to_string(),
357            DataValue::Real(v) => v.to_string(),
358            DataValue::Bool(v) => v.to_string(),
359            DataValue::String(v) => v.to_string(),
360            DataValue::Null => "".to_string(),
361        }
362    }
363
364    /// Convert to String to use parse
365    pub fn to_parse_string(&self) -> String {
366        match self {
367            DataValue::Int(v) => v.to_string(),
368            DataValue::Real(v) => v.to_string(),
369            DataValue::Bool(v) => v.to_string(),
370            DataValue::String(v) => v.to_string(),
371            DataValue::Null => "".to_string(),
372        }
373    }
374
375    /// Format this value
376    ///
377    /// Support [`Rust-format syntax`]. But not support position, variable, padding with character and [`Pointer`] format (`{:p}`).
378    /// [`Debug`] format is not supported in release build.
379    ///
380    /// # Examples
381    /// ```
382    /// fn main(){
383    ///     use sbrd_gen::value::DataValue;
384    ///
385    ///     assert_eq!(Some("ignore value".to_string()), DataValue::Int(12).format("ignore value"));
386    ///     assert_eq!(Some("12".to_string()), DataValue::Int(12).format("{}"));
387    ///     assert_eq!(Some("{}".to_string()), DataValue::Int(12).format("{{}}"));
388    ///     assert_eq!(Some("Rate= +12.35".to_string()), DataValue::Real(12.345).format("Rate={:+7.2}"));
389    ///     assert_eq!(Some("Rate=+012.35".to_string()), DataValue::Real(12.345).format("Rate={:+07.2}"));
390    ///     assert_eq!(Some(" aiueoあいうえお ".to_string()), DataValue::String("aiueoあいうえお".to_string()).format("{:^12}"));
391    ///     assert_eq!(Some("true    ".to_string()), DataValue::Bool(true).format("{:<8}"));
392    ///     assert_eq!(Some("null".to_string()), DataValue::Null.format("{:<10}"));
393    /// }
394    /// ```
395    ///
396    /// [`Rust-format syntax`]: https://doc.rust-lang.org/std/fmt/index.html#syntax
397    /// [`Pointer`]: https://doc.rust-lang.org/std/fmt/trait.Pointer.html
398    /// [`Debug`]: https://doc.rust-lang.org/std/fmt/trait.Debug.html
399    pub fn format(&self, format: &str) -> Option<String> {
400        let pos_args = [self];
401        let parsed_args = ParsedFormat::parse(format, &pos_args, &NoNamedArguments);
402        match parsed_args {
403            Ok(args) => Some(format!("{}", args)),
404            Err(_) => None,
405        }
406    }
407}