1use crate::prelude::*;
2use darling::FromMeta;
3use icydb_primitives::ScalarKind;
4use proc_macro2::TokenStream;
5use quote::{ToTokens, format_ident, quote};
6use std::str::FromStr;
7
8#[derive(Clone, Copy, Debug, Default, Deserialize, Eq, PartialEq, Serialize)]
18pub enum Cardinality {
19 #[default]
20 One,
21 Opt,
22 Many,
23}
24
25impl FromStr for Cardinality {
26 type Err = &'static str;
27
28 fn from_str(s: &str) -> Result<Self, Self::Err> {
29 match s {
30 "One" => Ok(Self::One),
31 "Opt" => Ok(Self::Opt),
32 "Many" => Ok(Self::Many),
33 _ => Err("unknown Cardinality"),
34 }
35 }
36}
37
38impl FromMeta for Cardinality {
39 fn from_string(s: &str) -> Result<Self, darling::Error> {
40 s.parse::<Self>()
41 .map_err(|_| darling::Error::unknown_value(s))
42 }
43}
44
45impl ToTokens for Cardinality {
46 fn to_tokens(&self, tokens: &mut TokenStream) {
47 let ident = format_ident!("{self:?}");
48
49 tokens.extend(quote!(::icydb::schema::types::Cardinality::#ident));
50 }
51}
52
53#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
62#[remain::sorted]
63pub enum Primitive {
64 Account,
65 Blob,
66 Bool,
67 Date,
68 Decimal,
69 Duration,
70 Float32,
71 Float64,
72 Int8,
73 Int16,
74 Int32,
75 Int64,
76 Int128,
77 IntBig,
78 Nat8,
79 Nat16,
80 Nat32,
81 Nat64,
82 Nat128,
83 NatBig,
84 Principal,
85 Subaccount,
86 Text,
87 Timestamp,
88 Ulid,
89 Unit,
90}
91
92impl FromStr for Primitive {
93 type Err = &'static str;
94
95 fn from_str(s: &str) -> Result<Self, Self::Err> {
96 match s {
97 "Account" => Ok(Self::Account),
98 "Blob" => Ok(Self::Blob),
99 "Bool" => Ok(Self::Bool),
100 "Date" => Ok(Self::Date),
101 "Decimal" => Ok(Self::Decimal),
102 "Duration" => Ok(Self::Duration),
103 "Float32" => Ok(Self::Float32),
104 "Float64" => Ok(Self::Float64),
105 "Int8" => Ok(Self::Int8),
106 "Int16" => Ok(Self::Int16),
107 "Int32" => Ok(Self::Int32),
108 "Int64" => Ok(Self::Int64),
109 "Int128" => Ok(Self::Int128),
110 "IntBig" => Ok(Self::IntBig),
111 "Nat8" => Ok(Self::Nat8),
112 "Nat16" => Ok(Self::Nat16),
113 "Nat32" => Ok(Self::Nat32),
114 "Nat64" => Ok(Self::Nat64),
115 "Nat128" => Ok(Self::Nat128),
116 "NatBig" => Ok(Self::NatBig),
117 "Principal" => Ok(Self::Principal),
118 "Subaccount" => Ok(Self::Subaccount),
119 "Text" => Ok(Self::Text),
120 "Timestamp" => Ok(Self::Timestamp),
121 "Ulid" => Ok(Self::Ulid),
122 "Unit" => Ok(Self::Unit),
123 _ => Err("unknown Primitive"),
124 }
125 }
126}
127
128const fn primitive_scalar_kind(primitive: Primitive) -> ScalarKind {
129 match primitive {
130 Primitive::Account => ScalarKind::Account,
131 Primitive::Blob => ScalarKind::Blob,
132 Primitive::Bool => ScalarKind::Bool,
133 Primitive::Date => ScalarKind::Date,
134 Primitive::Decimal => ScalarKind::Decimal,
135 Primitive::Duration => ScalarKind::Duration,
136 Primitive::Float32 => ScalarKind::Float32,
137 Primitive::Float64 => ScalarKind::Float64,
138 Primitive::Int8 | Primitive::Int16 | Primitive::Int32 | Primitive::Int64 => ScalarKind::Int,
139 Primitive::Int128 => ScalarKind::Int128,
140 Primitive::IntBig => ScalarKind::IntBig,
141 Primitive::Nat8 | Primitive::Nat16 | Primitive::Nat32 | Primitive::Nat64 => ScalarKind::Nat,
142 Primitive::Nat128 => ScalarKind::Nat128,
143 Primitive::NatBig => ScalarKind::NatBig,
144 Primitive::Principal => ScalarKind::Principal,
145 Primitive::Subaccount => ScalarKind::Subaccount,
146 Primitive::Text => ScalarKind::Text,
147 Primitive::Timestamp => ScalarKind::Timestamp,
148 Primitive::Ulid => ScalarKind::Ulid,
149 Primitive::Unit => ScalarKind::Unit,
150 }
151}
152
153impl Primitive {
154 #[must_use]
155 pub const fn supports_arithmetic(self) -> bool {
156 primitive_scalar_kind(self).supports_arithmetic()
157 }
158
159 #[must_use]
160 pub const fn is_primary_key_component_encodable(self) -> bool {
161 primitive_scalar_kind(self).is_primary_key_component_encodable()
162 }
163
164 #[must_use]
165 pub const fn is_primary_key_encodable(self) -> bool {
166 primitive_scalar_kind(self).is_primary_key_component_encodable()
167 }
168
169 #[must_use]
170 pub const fn supports_remainder(self) -> bool {
171 matches!(
172 self,
173 Self::Decimal
174 | Self::Int8
175 | Self::Int16
176 | Self::Int32
177 | Self::Int64
178 | Self::Int128
179 | Self::Nat8
180 | Self::Nat16
181 | Self::Nat32
182 | Self::Nat64
183 | Self::Nat128
184 )
185 }
186
187 #[must_use]
188 pub const fn supports_copy(self) -> bool {
189 !matches!(self, Self::Blob | Self::IntBig | Self::NatBig | Self::Text)
190 }
191
192 #[must_use]
193 pub const fn supports_hash(self) -> bool {
194 !matches!(self, Self::Blob | Self::Unit)
195 }
196
197 #[must_use]
199 pub const fn supports_numeric_value(self) -> bool {
200 matches!(
201 self,
202 Self::Date
203 | Self::Decimal
204 | Self::Duration
205 | Self::Int8
206 | Self::Int16
207 | Self::Int32
208 | Self::Int64
209 | Self::Int128
210 | Self::IntBig
211 | Self::Float32
212 | Self::Float64
213 | Self::Nat8
214 | Self::Nat16
215 | Self::Nat32
216 | Self::Nat64
217 | Self::Nat128
218 | Self::NatBig
219 | Self::Timestamp
220 )
221 }
222
223 #[must_use]
225 pub const fn supports_ord(self) -> bool {
226 primitive_scalar_kind(self).supports_ordering()
227 }
228
229 #[must_use]
234 pub const fn is_decimal(self) -> bool {
235 matches!(self, Self::Decimal)
236 }
237
238 #[must_use]
241 pub const fn is_numeric(self) -> bool {
242 self.is_int() || self.is_float() || self.is_decimal()
243 }
244
245 #[must_use]
246 pub const fn is_float(self) -> bool {
247 matches!(self, Self::Float32 | Self::Float64)
248 }
249
250 #[must_use]
251 pub const fn is_signed_int(self) -> bool {
252 matches!(
253 self,
254 Self::Int8 | Self::Int16 | Self::Int32 | Self::Int64 | Self::Int128 | Self::IntBig
255 )
256 }
257
258 #[must_use]
259 pub const fn is_unsigned_int(self) -> bool {
260 matches!(
261 self,
262 Self::Nat8 | Self::Nat16 | Self::Nat32 | Self::Nat64 | Self::Nat128 | Self::NatBig
263 )
264 }
265
266 #[must_use]
267 pub const fn is_int(self) -> bool {
268 self.is_signed_int() || self.is_unsigned_int()
269 }
270}
271
272impl FromMeta for Primitive {
273 fn from_string(s: &str) -> Result<Self, darling::Error> {
274 s.parse::<Self>()
275 .map_err(|_| darling::Error::unknown_value(s))
276 }
277}
278
279impl ToTokens for Primitive {
280 fn to_tokens(&self, tokens: &mut TokenStream) {
281 let ident = format_ident!("{self:?}");
282
283 tokens.extend(quote!(::icydb::schema::types::Primitive::#ident));
284 }
285}