Skip to main content

qusql_type/
type_.rs

1// Licensed under the Apache License, Version 2.0 (the "License");
2// you may not use this file except in compliance with the License.
3// You may obtain a copy of the License at
4//
5// http://www.apache.org/licenses/LICENSE-2.0
6//
7// Unless required by applicable law or agreed to in writing, software
8// distributed under the License is distributed on an "AS IS" BASIS,
9// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10// See the License for the specific language governing permissions and
11// limitations under the License.
12
13use alloc::{
14    borrow::Cow,
15    fmt::{Display, Write},
16    sync::Arc,
17    vec::Vec,
18};
19use qusql_parse::Span;
20
21/// Canonical base type of a type
22#[derive(Debug, Clone, Copy, PartialEq, Eq)]
23pub enum BaseType {
24    /// There are no constraint of the value
25    Any,
26    /// The value must be boolean
27    Bool,
28    /// The value must be a binary blob
29    Bytes,
30    Date,
31    DateTime,
32    /// The value must be some kind of float
33    Float,
34    /// The value must be some kind of integer
35    Integer,
36    String,
37    Time,
38    TimeStamp,
39    TimeInterval,
40}
41
42impl Display for BaseType {
43    fn fmt(&self, f: &mut alloc::fmt::Formatter<'_>) -> alloc::fmt::Result {
44        match self {
45            BaseType::Any => f.write_str("any"),
46            BaseType::Bool => f.write_str("bool"),
47            BaseType::Bytes => f.write_str("bytes"),
48            BaseType::Date => f.write_str("date"),
49            BaseType::DateTime => f.write_str("datetime"),
50            BaseType::Float => f.write_str("float"),
51            BaseType::Integer => f.write_str("integer"),
52            BaseType::String => f.write_str("string"),
53            BaseType::Time => f.write_str("time"),
54            BaseType::TimeStamp => f.write_str("timestamp"),
55            BaseType::TimeInterval => f.write_str("timeinterval"),
56        }
57    }
58}
59
60#[derive(Debug, Clone, PartialEq, Eq)]
61pub enum ArgType {
62    Normal,
63    ListHack,
64}
65
66/// Represent the type of a value
67#[derive(Debug, Clone, PartialEq, Eq)]
68pub enum Type<'a> {
69    // This type is used internally and should not escape to the user
70    #[doc(hidden)]
71    Args(BaseType, Arc<Vec<(usize, ArgType, Span)>>),
72    Base(BaseType),
73    Enum(Arc<Vec<Cow<'a, str>>>),
74    F32,
75    F64,
76    I16,
77    I24,
78    I32,
79    I64,
80    I8,
81    Invalid,
82    JSON,
83    Set(Arc<Vec<Cow<'a, str>>>),
84    U16,
85    U24,
86    U32,
87    U64,
88    U8,
89    // This type is used internally and should not escape to the user
90    #[doc(hidden)]
91    Null,
92}
93
94impl<'a> Display for Type<'a> {
95    fn fmt(&self, f: &mut alloc::fmt::Formatter<'_>) -> alloc::fmt::Result {
96        match self {
97            Type::Args(t, a) => {
98                write!(f, "args({t}")?;
99                for (a, _, _) in a.iter() {
100                    write!(f, ", {a}")?;
101                }
102                f.write_char(')')
103            }
104            Type::Base(t) => t.fmt(f),
105            Type::F32 => f.write_str("f32"),
106            Type::F64 => f.write_str("f64"),
107            Type::I16 => f.write_str("i16"),
108            Type::I24 => f.write_str("i24"),
109            Type::I32 => f.write_str("i32"),
110            Type::I64 => f.write_str("i64"),
111            Type::I8 => f.write_str("i8"),
112            Type::Invalid => f.write_str("invalid"),
113            Type::JSON => f.write_str("json"),
114            Type::U16 => f.write_str("u16"),
115            Type::U24 => f.write_str("u24"),
116            Type::U32 => f.write_str("u32"),
117            Type::U64 => f.write_str("u64"),
118            Type::U8 => f.write_str("u8"),
119            Type::Null => f.write_str("null"),
120            Type::Enum(v) => {
121                f.write_str("enum(")?;
122                for (i, v) in v.iter().enumerate() {
123                    if i != 0 {
124                        f.write_str(", ")?;
125                    }
126                    write!(f, "'{v}'")?
127                }
128                f.write_char(')')
129            }
130            Type::Set(v) => {
131                f.write_str("set(")?;
132                for (i, v) in v.iter().enumerate() {
133                    if i != 0 {
134                        f.write_str(", ")?;
135                    }
136                    write!(f, "'{v}'")?
137                }
138                f.write_char(')')
139            }
140        }
141    }
142}
143
144impl<'a> Type<'a> {
145    /// Compute the canonical base type
146    pub fn base(&self) -> BaseType {
147        match self {
148            Type::Args(t, _) => *t,
149            Type::Base(t) => *t,
150            Type::Enum(_) => BaseType::String,
151            Type::F32 => BaseType::Float,
152            Type::F64 => BaseType::Float,
153            Type::I16 => BaseType::Integer,
154            Type::I24 => BaseType::Integer,
155            Type::I32 => BaseType::Integer,
156            Type::I64 => BaseType::Integer,
157            Type::I8 => BaseType::Integer,
158            Type::Invalid => BaseType::Any,
159            Type::JSON => BaseType::Any,
160            Type::Null => BaseType::Any,
161            Type::Set(_) => BaseType::String,
162            Type::U16 => BaseType::Integer,
163            Type::U24 => BaseType::Integer,
164            Type::U32 => BaseType::Integer,
165            Type::U64 => BaseType::Integer,
166            Type::U8 => BaseType::Integer,
167        }
168    }
169}
170
171impl<'a> From<BaseType> for Type<'a> {
172    fn from(t: BaseType) -> Self {
173        Type::Base(t)
174    }
175}
176
177/// Represent a type with not_null information
178#[derive(Debug, Clone, PartialEq, Eq)]
179pub struct FullType<'a> {
180    pub t: Type<'a>,
181    pub not_null: bool,
182    pub list_hack: bool,
183}
184
185impl<'a> FullType<'a> {
186    pub(crate) fn new(t: impl Into<Type<'a>>, not_null: bool) -> Self {
187        Self {
188            t: t.into(),
189            not_null,
190            list_hack: false,
191        }
192    }
193
194    /// Construct a new invalid type
195    pub fn invalid() -> Self {
196        Self {
197            t: Type::Invalid,
198            not_null: false,
199            list_hack: false,
200        }
201    }
202}
203
204impl<'a> core::ops::Deref for FullType<'a> {
205    type Target = Type<'a>;
206
207    fn deref(&self) -> &Self::Target {
208        &self.t
209    }
210}
211
212impl<'a> Display for FullType<'a> {
213    fn fmt(&self, f: &mut alloc::fmt::Formatter<'_>) -> alloc::fmt::Result {
214        self.t.fmt(f)?;
215        if self.list_hack {
216            f.write_str(" list_hack")?;
217        }
218        if self.not_null {
219            f.write_str(" not null")?;
220        }
221        Ok(())
222    }
223}