schematic_types/
strings.rs1use crate::*;
2use std::fmt;
3use std::net::{Ipv4Addr, Ipv6Addr};
4use std::path::{Path, PathBuf};
5use std::time::{Duration, SystemTime};
6
7#[derive(Clone, Debug, Default, PartialEq)]
8#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
9pub struct StringType {
10 #[cfg_attr(
11 feature = "serde",
12 serde(default, skip_serializing_if = "Option::is_none")
13 )]
14 pub default: Option<LiteralValue>,
15
16 #[cfg_attr(
17 feature = "serde",
18 serde(default, skip_serializing_if = "Option::is_none")
19 )]
20 pub enum_values: Option<Vec<String>>,
21
22 #[cfg_attr(
23 feature = "serde",
24 serde(default, skip_serializing_if = "Option::is_none")
25 )]
26 pub format: Option<String>,
27
28 #[cfg_attr(
29 feature = "serde",
30 serde(default, skip_serializing_if = "Option::is_none")
31 )]
32 pub max_length: Option<usize>,
33
34 #[cfg_attr(
35 feature = "serde",
36 serde(default, skip_serializing_if = "Option::is_none")
37 )]
38 pub min_length: Option<usize>,
39
40 #[cfg_attr(
41 feature = "serde",
42 serde(default, skip_serializing_if = "Option::is_none")
43 )]
44 pub pattern: Option<String>,
45}
46
47impl StringType {
48 pub fn new(value: impl AsRef<str>) -> Self {
50 StringType {
51 default: Some(LiteralValue::String(value.as_ref().to_owned())),
52 ..StringType::default()
53 }
54 }
55}
56
57impl fmt::Display for StringType {
58 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
59 if self.max_length.is_some_and(|max| max == 1)
60 && self.min_length.is_some_and(|min| min == 1)
61 {
62 write!(f, "char")
63 } else if let Some(format) = &self.format {
64 write!(f, "string:{format}")
65 } else {
66 write!(f, "string")
67 }
68 }
69}
70
71macro_rules! impl_string {
72 ($type:ty) => {
73 impl Schematic for $type {
74 fn build_schema(mut schema: SchemaBuilder) -> Schema {
75 schema.string_default()
76 }
77 }
78 };
79}
80
81macro_rules! impl_string_format {
82 ($type:ty, $format:expr_2021) => {
83 impl Schematic for $type {
84 fn build_schema(mut schema: SchemaBuilder) -> Schema {
85 schema.string(StringType {
86 format: Some($format.into()),
87 ..StringType::default()
88 })
89 }
90 }
91 };
92}
93
94impl Schematic for char {
95 fn build_schema(mut schema: SchemaBuilder) -> Schema {
96 schema.string(StringType {
97 max_length: Some(1),
98 min_length: Some(1),
99 ..StringType::default()
100 })
101 }
102}
103
104impl_string!(str);
105impl_string!(&str);
106impl_string!(String);
107
108impl_string_format!(Path, "path");
109impl_string_format!(&Path, "path");
110impl_string_format!(PathBuf, "path");
111
112impl_string_format!(Ipv4Addr, "ipv4");
113impl_string_format!(Ipv6Addr, "ipv6");
114
115impl_string_format!(SystemTime, "time");
116impl_string_format!(Duration, "duration");