|
1 |
| -use std::{str::FromStr, sync::Arc}; |
2 |
| - |
3 | 1 | use crate::{base::{schema::BasicValueType, value::BasicValue}, prelude::*};
|
4 | 2 |
|
5 |
| -#[derive(Debug, Clone)] |
6 |
| -pub enum UnionParseResult { |
7 |
| - Union(UnionType), |
8 |
| - Single(BasicValueType), |
9 |
| -} |
10 |
| - |
11 | 3 | /// Union type helper storing an auto-sorted set of types excluding `Union`
|
12 | 4 | #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord)]
|
13 | 5 | pub struct UnionType {
|
14 |
| - types: BTreeSet<BasicValueType>, |
| 6 | + possible_types: BTreeSet<BasicValueType>, |
15 | 7 | }
|
16 | 8 |
|
17 | 9 | impl UnionType {
|
18 |
| - fn new() -> Self { |
19 |
| - Self { types: BTreeSet::new() } |
20 |
| - } |
21 |
| - |
22 |
| - pub fn types(&self) -> &BTreeSet<BasicValueType> { |
23 |
| - &self.types |
24 |
| - } |
25 |
| - |
26 |
| - pub fn insert(&mut self, value: BasicValueType) -> bool { |
27 |
| - match value { |
28 |
| - BasicValueType::Union(union_type) => { |
29 |
| - let mut inserted = false; |
30 |
| - |
31 |
| - // Unpack nested union |
32 |
| - for item in union_type.types.into_iter() { |
33 |
| - // Recursively insert underlying types |
34 |
| - inserted = self.insert(item) || inserted; |
| 10 | + pub fn possible_types(&self) -> &BTreeSet<BasicValueType> { |
| 11 | + &self.possible_types |
| 12 | + } |
| 13 | + |
| 14 | + pub fn match_type(&self, value: &BasicValue) -> Option<BasicValueType> { |
| 15 | + // TODO: Use a general converter |
| 16 | + let typ = match value { |
| 17 | + BasicValue::Bytes(_) => Some(BasicValueType::Bytes), |
| 18 | + BasicValue::Str(_) => Some(BasicValueType::Str), |
| 19 | + BasicValue::Bool(_) => Some(BasicValueType::Bool), |
| 20 | + BasicValue::Int64(_) => Some(BasicValueType::Int64), |
| 21 | + BasicValue::Float32(_) => Some(BasicValueType::Float32), |
| 22 | + BasicValue::Float64(_) => Some(BasicValueType::Float64), |
| 23 | + BasicValue::Range(_) => Some(BasicValueType::Range), |
| 24 | + BasicValue::Uuid(_) => Some(BasicValueType::Uuid), |
| 25 | + BasicValue::Date(_) => Some(BasicValueType::Date), |
| 26 | + BasicValue::Time(_) => Some(BasicValueType::Time), |
| 27 | + BasicValue::LocalDateTime(_) => Some(BasicValueType::LocalDateTime), |
| 28 | + BasicValue::OffsetDateTime(_) => Some(BasicValueType::OffsetDateTime), |
| 29 | + BasicValue::Json(_) => Some(BasicValueType::Json), |
| 30 | + BasicValue::Vector(v) => { |
| 31 | + match v.first() { |
| 32 | + Some(first_elem) => self.match_type(first_elem), |
| 33 | + None => None, |
35 | 34 | }
|
36 |
| - |
37 |
| - inserted |
38 | 35 | }
|
| 36 | + }; |
39 | 37 |
|
40 |
| - other => self.types.insert(other), |
41 |
| - } |
42 |
| - } |
43 |
| - |
44 |
| - fn resolve(self) -> Result<UnionParseResult> { |
45 |
| - if self.types().is_empty() { |
46 |
| - anyhow::bail!("The union is empty"); |
47 |
| - } |
48 |
| - |
49 |
| - if self.types().len() == 1 { |
50 |
| - let mut type_tree: BTreeSet<BasicValueType> = self.into(); |
51 |
| - return Ok(UnionParseResult::Single(type_tree.pop_first().unwrap())); |
52 |
| - } |
53 |
| - |
54 |
| - Ok(UnionParseResult::Union(self)) |
55 |
| - } |
56 |
| - |
57 |
| - /// Move an iterable and parse it into a union type. |
58 |
| - /// If there is only one single unique type, it returns a single `BasicValueType`. |
59 |
| - pub fn parse_from<T>( |
60 |
| - input: impl IntoIterator<Item = BasicValueType, IntoIter = T>, |
61 |
| - ) -> Result<UnionParseResult> |
62 |
| - where |
63 |
| - T: Iterator<Item = BasicValueType>, |
64 |
| - { |
65 |
| - let mut union = Self::new(); |
66 |
| - |
67 |
| - for typ in input { |
68 |
| - union.insert(typ); |
69 |
| - } |
70 |
| - |
71 |
| - union.resolve() |
72 |
| - } |
73 |
| - |
74 |
| - /// Assume the input already contains multiple unique types, panic otherwise. |
75 |
| - /// |
76 |
| - /// This method is meant for streamlining the code for test cases. |
77 |
| - /// Use `parse_from()` instead unless you know the input. |
78 |
| - pub fn coerce_from<T>( |
79 |
| - input: impl IntoIterator<Item = BasicValueType, IntoIter = T>, |
80 |
| - ) -> Self |
81 |
| - where |
82 |
| - T: Iterator<Item = BasicValueType>, |
83 |
| - { |
84 |
| - match Self::parse_from(input) { |
85 |
| - Ok(UnionParseResult::Union(union)) => union, |
86 |
| - _ => panic!("Do not use `coerce_from()` for basic type lists that can possibly be one type."), |
87 |
| - } |
| 38 | + typ.and_then(|typ| { |
| 39 | + self.possible_types() |
| 40 | + .contains(&typ) |
| 41 | + .then_some(typ) |
| 42 | + }) |
88 | 43 | }
|
89 | 44 | }
|
90 | 45 |
|
91 |
| -impl Into<BTreeSet<BasicValueType>> for UnionType { |
92 |
| - fn into(self) -> BTreeSet<BasicValueType> { |
93 |
| - self.types |
94 |
| - } |
95 |
| -} |
96 |
| - |
97 |
| -pub trait ParseStr { |
98 |
| - type Out; |
99 |
| - type Err; |
100 |
| - |
101 |
| - fn parse_str(&self, value: &str) -> Result<Self::Out, Self::Err>; |
102 |
| -} |
103 |
| - |
104 |
| -impl ParseStr for BTreeSet<BasicValueType> { |
105 |
| - type Out = BasicValue; |
106 |
| - type Err = anyhow::Error; |
107 |
| - |
108 |
| - /// Try parsing the str value to each possible type, and return the first successful result |
109 |
| - fn parse_str(&self, value: &str) -> Result<BasicValue> { |
110 |
| - // Try parsing the value in the reversed order of the enum elements |
111 |
| - for typ in self.iter().rev() { |
112 |
| - match typ { |
113 |
| - BasicValueType::Uuid => { |
114 |
| - match value.parse().map(BasicValue::Uuid) { |
115 |
| - Ok(ret) => return Ok(ret), |
116 |
| - Err(_) => {} |
117 |
| - } |
118 |
| - } |
119 |
| - BasicValueType::OffsetDateTime => { |
120 |
| - match value.parse().map(BasicValue::OffsetDateTime) { |
121 |
| - Ok(ret) => return Ok(ret), |
122 |
| - Err(_) => {} |
123 |
| - } |
124 |
| - } |
125 |
| - BasicValueType::LocalDateTime => { |
126 |
| - match value.parse().map(BasicValue::LocalDateTime) { |
127 |
| - Ok(ret) => return Ok(ret), |
128 |
| - Err(_) => {} |
129 |
| - } |
130 |
| - } |
131 |
| - BasicValueType::Date => { |
132 |
| - match value.parse().map(BasicValue::Date) { |
133 |
| - Ok(ret) => return Ok(ret), |
134 |
| - Err(_) => {} |
135 |
| - } |
136 |
| - } |
137 |
| - BasicValueType::Time => { |
138 |
| - match value.parse().map(BasicValue::Time) { |
139 |
| - Ok(ret) => return Ok(ret), |
140 |
| - Err(_) => {} |
141 |
| - } |
142 |
| - } |
143 |
| - BasicValueType::Json => { |
144 |
| - match serde_json::Value::from_str(value) { |
145 |
| - Ok(ret) => return Ok(BasicValue::Json(ret.into())), |
146 |
| - Err(_) => {} |
147 |
| - } |
148 |
| - } |
149 |
| - BasicValueType::Str => { |
150 |
| - return Ok(BasicValue::Str(Arc::from(value))); |
151 |
| - } |
152 |
| - _ => {} |
153 |
| - } |
154 |
| - } |
155 |
| - |
156 |
| - anyhow::bail!("Cannot parse \"{}\"", value) |
157 |
| - } |
| 46 | +#[derive(Debug, Clone, Serialize)] |
| 47 | +pub struct UnionVariant<'a> { |
| 48 | + pub tag_id: &'a str, |
| 49 | + pub value: &'a BasicValue, |
158 | 50 | }
|
0 commit comments