1use crate::prelude::*;
2use candid::CandidType;
3use darling::FromMeta;
4use derive_more::{Display, FromStr};
5use proc_macro2::TokenStream;
6use quote::{ToTokens, format_ident, quote};
7
8#[derive(
13 CandidType, Clone, Copy, Default, Debug, Deserialize, Display, Eq, FromStr, PartialEq, Serialize,
14)]
15pub enum Cardinality {
16 #[default]
17 One,
18 Opt,
19 Many,
20}
21
22impl FromMeta for Cardinality {
23 fn from_string(s: &str) -> Result<Self, darling::Error> {
24 s.parse::<Self>()
25 .map_err(|_| darling::Error::unknown_value(s))
26 }
27}
28
29impl ToTokens for Cardinality {
30 fn to_tokens(&self, tokens: &mut TokenStream) {
31 let ident = format_ident!("{self}");
32
33 tokens.extend(quote!(::icydb::schema::types::Cardinality::#ident));
34 }
35}
36
37#[derive(
42 CandidType, Clone, Copy, Debug, Deserialize, Display, Eq, PartialEq, FromStr, Serialize,
43)]
44#[remain::sorted]
45pub enum Primitive {
46 Account,
47 Blob,
48 Bool,
49 Date,
50 Decimal,
51 Duration,
52 E8s,
53 E18s,
54 Float32,
55 Float64,
56 Int,
57 Int8,
58 Int16,
59 Int32,
60 Int64,
61 Int128,
62 Nat,
63 Nat8,
64 Nat16,
65 Nat32,
66 Nat64,
67 Nat128,
68 Principal,
69 Subaccount,
70 Text,
71 Timestamp,
72 Ulid,
73 Unit,
74}
75
76impl Primitive {
77 #[must_use]
78 pub const fn supports_arithmetic(self) -> bool {
79 self.is_int() || self.is_fixed_point() || self.is_decimal()
80 }
81
82 #[must_use]
83 pub const fn supports_copy(self) -> bool {
84 !matches!(self, Self::Blob | Self::Int | Self::Nat | Self::Text)
85 }
86
87 #[must_use]
88 pub const fn supports_display(self) -> bool {
89 !matches!(self, Self::Blob | Self::Unit)
90 }
91
92 #[must_use]
93 pub const fn supports_hash(self) -> bool {
94 !matches!(self, Self::Blob | Self::Unit)
95 }
96
97 #[must_use]
99 pub const fn supports_num_cast(self) -> bool {
100 matches!(
101 self,
102 Self::Date
103 | Self::Decimal
104 | Self::Duration
105 | Self::E8s
106 | Self::E18s
107 | Self::Int8
108 | Self::Int16
109 | Self::Int32
110 | Self::Int64
111 | Self::Float32
112 | Self::Float64
113 | Self::Nat8
114 | Self::Nat16
115 | Self::Nat32
116 | Self::Nat64
117 | Self::Timestamp
118 )
119 }
120
121 #[must_use]
123 pub const fn supports_ord(self) -> bool {
124 !matches!(self, Self::Blob | Self::Unit)
125 }
126
127 #[must_use]
132 pub const fn is_decimal(self) -> bool {
133 matches!(self, Self::Decimal)
134 }
135
136 #[must_use]
139 pub const fn is_numeric(self) -> bool {
140 self.is_int() || self.is_float() || self.is_fixed_point() || self.is_decimal()
141 }
142
143 #[must_use]
144 pub const fn is_float(self) -> bool {
145 matches!(self, Self::Float32 | Self::Float64)
146 }
147
148 #[must_use]
149 pub const fn is_signed_int(self) -> bool {
150 matches!(
151 self,
152 Self::Int | Self::Int8 | Self::Int16 | Self::Int32 | Self::Int64
153 )
154 }
155
156 #[must_use]
157 pub const fn is_unsigned_int(self) -> bool {
158 matches!(
159 self,
160 Self::Nat | Self::Nat8 | Self::Nat16 | Self::Nat32 | Self::Nat64
161 )
162 }
163
164 #[must_use]
165 pub const fn is_int(self) -> bool {
166 self.is_signed_int() || self.is_unsigned_int()
167 }
168
169 #[must_use]
170 pub const fn is_fixed_point(self) -> bool {
171 matches!(self, Self::E8s | Self::E18s)
172 }
173
174 #[must_use]
175 pub fn as_type(self) -> TokenStream {
176 let ident = format_ident!("{self}");
177
178 quote!(::icydb::types::#ident)
179 }
180
181 pub fn num_cast_fn(self) -> Result<&'static str, darling::Error> {
186 match self {
187 Self::E18s => Ok("u128"),
188 Self::Float32 => Ok("f32"),
189 Self::Float64 | Self::Decimal => Ok("f64"),
190 Self::Int8 => Ok("i8"),
191 Self::Int16 => Ok("i16"),
192 Self::Int32 | Self::Date => Ok("i32"),
193 Self::Int64 => Ok("i64"),
194 Self::Nat8 => Ok("u8"),
195 Self::Nat16 => Ok("u16"),
196 Self::Nat32 => Ok("u32"),
197 Self::Nat64 | Self::Duration | Self::E8s | Self::Timestamp => Ok("u64"),
198 _ => Err(darling::Error::custom(format!(
199 "numeric cast is unsupported for primitive {self}"
200 ))),
201 }
202 }
203}
204
205impl FromMeta for Primitive {
206 fn from_string(s: &str) -> Result<Self, darling::Error> {
207 s.parse::<Self>()
208 .map_err(|_| darling::Error::unknown_value(s))
209 }
210}
211
212impl ToTokens for Primitive {
213 fn to_tokens(&self, tokens: &mut TokenStream) {
214 let ident = format_ident!("{self}");
215
216 tokens.extend(quote!(::icydb::schema::types::Primitive::#ident));
217 }
218}
219
220#[derive(CandidType, Clone, Copy, Debug, Deserialize, Display, FromStr, Serialize)]
225pub enum StoreType {
226 Data,
227 Index,
228}
229
230impl FromMeta for StoreType {
231 fn from_string(s: &str) -> Result<Self, darling::Error> {
232 s.parse::<Self>()
233 .map_err(|_| darling::Error::unknown_value(s))
234 }
235}
236
237impl ToTokens for StoreType {
238 fn to_tokens(&self, tokens: &mut TokenStream) {
239 let ident = format_ident!("{self}");
240
241 tokens.extend(quote!(::icydb::schema::types::StoreType::#ident));
242 }
243}