1#![allow(unused)]
2use std::str::FromStr;
3use schemars::{schema::{InstanceType, Schema, SchemaObject, SingleOrVec, StringValidation, SubschemaValidation}, JsonSchema};
4
5use thiserror::Error;
6
7use serde::{de::Error, Deserialize, Serialize};
8
9use super::{RawRepr, RANGE_PATTERN};
10
11#[derive(Clone, Debug, PartialEq)]
12pub struct Range<T> {
13 start: T,
14 end: T,
15 raw: String,
16}
17
18impl<T> Serialize for Range<T> {
19 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
20 where
21 S: serde::Serializer,
22 {
23 serializer.serialize_str(&self.raw)
24 }
25}
26impl<T> JsonSchema for Range<T> {
27 fn schema_name() -> String {
28 String::from("Range")
29 }
30
31 fn json_schema(gen: &mut schemars::gen::SchemaGenerator) -> schemars::schema::Schema {
32 let mut schema = SchemaObject::default();
33 schema.subschemas = Some(Box::new(SubschemaValidation {
35 one_of: Some(vec![
36 Schema::Object(SchemaObject {
38 instance_type: Some(SingleOrVec::Single(Box::new(InstanceType::String))),
39 string: Some(Box::new(StringValidation {
40 pattern: Some(RANGE_PATTERN.to_string()),
41 ..Default::default()
42
43 })),
44 ..Default::default()
45 }),
46 Schema::Object(SchemaObject {
48 instance_type: Some(SingleOrVec::Single(Box::new(InstanceType::Number))),
49 ..Default::default()
50 }),
51 ]),
52 ..Default::default()
53 }));
54
55 Schema::Object(schema)
56
57 }
58}
59
60impl<'de, T> Deserialize<'de> for Range<T>
61where
62 T: FromStr,
63 T::Err: std::error::Error + 'static,
64{
65 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
66 where
67 D: serde::Deserializer<'de>,
68 {
69 let raw: String = Deserialize::deserialize(deserializer)?;
70 let range: Range<T> = raw.parse().map_err(|e| D::Error::custom(e))?;
71
72 Ok(range)
73 }
74}
75
76impl<T> RawRepr for Range<T> {
77 fn raw(&self) -> &str {
79 &self.raw
80 }
81}
82
83use std::fmt::{Debug, Display};
84#[derive(Debug, Error, PartialEq)]
85pub enum ParseRangeError<T: FromStr>
86where
87 T::Err: std::error::Error + 'static,
88{
89 #[error("Wrong number of elements for a range, it should be 2. Example: 0 .. 1")]
90 WrongArgNumber,
91 #[error("Failed to parse start bound: {0}")]
92 InvalidStart(#[source] T::Err),
93 #[error("Failed to parse end bound: {0}")]
94 InvalidEnd(#[source] T::Err),
95}
96
97use super::quantity;
98
99impl<T> FromStr for Range<T>
100where
101 T: FromStr,
102 T::Err: std::error::Error + 'static,
103{
104 type Err = ParseRangeError<T>;
105
106 fn from_str(s: &str) -> Result<Self, Self::Err> {
107 let parts: Vec<&str> = s.split("..").map(|part| part.trim()).collect();
108
109 if parts.len() != 2 {
110 return Err(ParseRangeError::WrongArgNumber);
111 }
112
113 let start_unit = quantity::get_unit(parts[0]);
114 let end_unit = quantity::get_unit(parts[1]);
115
116 let mut start = parts[0].to_string();
117 let mut end = parts[1].to_string();
118 if start_unit.is_some() && end_unit.is_none() {
119 end += start_unit.expect("already checked")
120 } else if start_unit.is_none() && end_unit.is_some() {
121 start += end_unit.expect("already checked")
122 }
123
124 let start: T = start
125 .parse()
126 .map_err(|e| ParseRangeError::InvalidStart(e))?;
127 let end: T = end.parse().map_err(|e| ParseRangeError::InvalidEnd(e))?;
128
129 Ok(Range {
130 start,
131 end,
132 raw: s.to_string(),
133 })
134 }
135}
136
137#[cfg(test)]
138mod tests {
139 use std::num::ParseIntError;
140
141
142 use super::*;
143
144 use super::quantity::*;
145
146 #[test]
147 fn same_unit_when_only_one() {
148 let raw = "0..1m2";
149 let range: Range<Area> = raw.parse().expect("valid range should be parsed");
150 assert_eq!(
151 range,
152 Range {
153 start: Area::new("0 m²").unwrap(),
154 end: Area::new("1 m^2").unwrap(),
155 raw: raw.to_string()
156 }
157 );
158 }
159
160 #[test]
161 fn different_units() {
162 let raw = "10km^+2..1m2";
163 let range: Range<Area> = raw.parse().expect("valid range should be parsed");
164 assert_eq!(
165 range,
166 Range {
167 start: Area::new("10 km²").unwrap(),
168 end: Area::new("1 m^2").unwrap(),
169 raw: raw.to_string()
170 }
171 );
172 }
173
174 #[test]
175 fn parse_valid_range() {
176 let raw = "0 .. 1";
177 let range: Range<i32> = raw.parse().expect("Valid range should be parsed");
178 assert_eq!(
179 range,
180 Range {
181 start: 0,
182 end: 1,
183 raw: raw.to_string()
184 }
185 )
186 }
187 #[test]
188 fn serialize_range() {
189 let range = Range {
190 start: 0,
191 end: 1,
192 raw: "0 .. 1".to_string(),
193 };
194 let serialized = serde_json::to_string(&range).expect("Serialization should succeed");
195 assert_eq!(serialized, "\"0 .. 1\"");
196 }
197 #[test]
213 fn parse_invalid_range_wrong_arg_number() {
214 let raw = "0 .. 1 .. 2";
215 let result: Result<Range<i32>, _> = raw.parse();
216 assert_eq!(result.unwrap_err(), ParseRangeError::WrongArgNumber);
217 }
218
219 #[test]
220 fn parse_invalid_range_invalid_start() {
221 let raw = "a .. 1";
222 let result: Result<Range<i32>, _> = raw.parse();
223 assert_eq!(
224 result.unwrap_err(),
225 ParseRangeError::InvalidStart("a".parse::<i32>().unwrap_err())
226 );
227 }
228
229 #[test]
230 fn parse_invalid_range_invalid_end() {
231 let raw = "0 .. b";
232 let result: Result<Range<i32>, _> = raw.parse();
233 assert_eq!(
234 result.unwrap_err(),
235 ParseRangeError::InvalidEnd("b".parse::<i32>().unwrap_err())
236 );
237 }
238}