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