1use crate::common::traits;
2
3mod bool;
4mod bytes;
5mod duration;
6mod float;
7mod int;
8mod null;
9mod optional;
10mod string;
11mod timestamp;
12pub use bool::Bool;
15pub use bytes::Bytes;
16pub use duration::Duration;
17pub use float::Float;
18pub use int::Int;
19pub use null::Null;
20pub use string::String;
21pub use timestamp::Timestamp;
22#[derive(Clone, Copy, Debug, Eq, PartialEq)]
25pub enum Kind {
26 Unspecified,
27 Error,
28 Dyn,
29 Any,
30 Boolean,
31 Bytes,
32 Float,
33 Duration,
34 Int,
35 List,
36 Map,
37 NullType,
38 Opaque,
39 String,
40 Struct,
41 Timestamp,
42 Type,
43 TypeParam,
44 UInt,
45 Unknown,
46}
47
48#[derive(Clone, Debug, Eq, PartialEq)]
49pub struct Type<'a> {
50 kind: Kind,
51 parameters: &'a [&'a Type<'a>],
52 runtime_type_name: &'a str,
53 trait_mask: u16,
54}
55
56pub const ANY_TYPE: Type = Type {
57 kind: Kind::Any,
58 parameters: &[],
59 runtime_type_name: "google.protobuf.Any",
60 trait_mask: traits::FIELD_TESTER_TYPE | traits::INDEXER_TYPE,
61};
62
63pub const BOOL_TYPE: Type = Type {
64 kind: Kind::Boolean,
65 parameters: &[],
66 runtime_type_name: "bool",
67 trait_mask: traits::COMPARER_TYPE | traits::NEGATOR_TYPE,
68};
69
70pub const BYTES_TYPE: Type = Type {
71 kind: Kind::Bytes,
72 parameters: &[],
73 runtime_type_name: "bytes",
74 trait_mask: traits::ADDER_TYPE | traits::COMPARER_TYPE | traits::SIZER_TYPE,
75};
76
77pub const FLOAT_TYPE: Type = Type {
78 kind: Kind::Float,
79 parameters: &[],
80 runtime_type_name: "float",
81 trait_mask: traits::ADDER_TYPE
82 | traits::COMPARER_TYPE
83 | traits::DIVIDER_TYPE
84 | traits::MULTIPLIER_TYPE
85 | traits::NEGATOR_TYPE
86 | traits::SUBTRACTOR_TYPE,
87};
88
89pub const DURATION_TYPE: Type = Type {
90 kind: Kind::Duration,
91 parameters: &[],
92 runtime_type_name: "google.protobuf.Duration",
93 trait_mask: traits::ADDER_TYPE
94 | traits::COMPARER_TYPE
95 | traits::NEGATOR_TYPE
96 | traits::RECEIVER_TYPE
97 | traits::SUBTRACTOR_TYPE,
98};
99
100pub const DYN_TYPE: Type = Type::simple_type(Kind::Dyn, "dyn");
101
102pub const ERROR_TYPE: Type = Type::simple_type(Kind::Error, "error");
103
104pub const INT_TYPE: Type = Type {
105 kind: Kind::Int,
106 parameters: &[],
107 runtime_type_name: "int",
108 trait_mask: traits::ADDER_TYPE
109 | traits::COMPARER_TYPE
110 | traits::DIVIDER_TYPE
111 | traits::MODDER_TYPE
112 | traits::MULTIPLIER_TYPE
113 | traits::NEGATOR_TYPE
114 | traits::SUBTRACTOR_TYPE,
115};
116
117pub const LIST_TYPE: Type = Type::new_list_type(&[&DYN_TYPE]);
118
119pub const MAP_TYPE: Type = Type::new_map_type(&[&DYN_TYPE, &DYN_TYPE]);
120
121pub const NULL_TYPE: Type = Type::simple_type(Kind::NullType, "null_type");
122
123pub const STRING_TYPE: Type = Type {
124 kind: Kind::String,
125 parameters: &[],
126 runtime_type_name: "string",
127 trait_mask: traits::ADDER_TYPE
128 | traits::COMPARER_TYPE
129 | traits::MATCHER_TYPE
130 | traits::RECEIVER_TYPE
131 | traits::SIZER_TYPE,
132};
133
134pub const TIMESTAMP_TYPE: Type = Type {
135 kind: Kind::Timestamp,
136 parameters: &[],
137 runtime_type_name: "google.protobuf.Timestamp",
138 trait_mask: traits::ADDER_TYPE | traits::COMPARER_TYPE | traits::RECEIVER_TYPE | traits::SUBTRACTOR_TYPE,
139};
140
141pub const TYPE_TYPE: Type = Type::simple_type(Kind::Type, "type");
142
143pub const UINT_TYPE: Type = Type {
144 kind: Kind::UInt,
145 parameters: &[],
146 runtime_type_name: "uint",
147 trait_mask: traits::ADDER_TYPE
148 | traits::COMPARER_TYPE
149 | traits::DIVIDER_TYPE
150 | traits::MODDER_TYPE
151 | traits::MULTIPLIER_TYPE
152 | traits::SUBTRACTOR_TYPE,
153};
154
155pub const UNKNOWN_TYPE: Type = Type::simple_type(Kind::Unknown, "unknown");
156
157impl<'a> Type<'a> {
158 pub const fn simple_type(kind: Kind, name: &str) -> Type<'_> {
159 Type {
160 kind,
161 parameters: &[],
162 runtime_type_name: name,
163 trait_mask: 0,
164 }
165 }
166
167 pub const fn new_list_type<'b>(param: &'b [&'b Type<'b>; 1]) -> Type<'b> {
168 Type {
169 kind: Kind::List,
170 parameters: param,
171 runtime_type_name: "list",
172 trait_mask: traits::ADDER_TYPE
173 | traits::CONTAINER_TYPE
174 | traits::INDEXER_TYPE
175 | traits::ITERABLE_TYPE
176 | traits::SIZER_TYPE,
177 }
178 }
179
180 pub const fn new_map_type<'b>(param: &'b [&'b Type<'b>; 2]) -> Type<'b> {
181 Type {
182 kind: Kind::Map,
183 parameters: param,
184 runtime_type_name: "map",
185 trait_mask: traits::CONTAINER_TYPE | traits::INDEXER_TYPE | traits::ITERABLE_TYPE | traits::SIZER_TYPE,
186 }
187 }
188
189 pub const fn new_unspecified_type(name: &str) -> Type<'_> {
190 Type {
191 kind: Kind::Unspecified,
192 parameters: &[],
193 runtime_type_name: name,
194 trait_mask: 0,
195 }
196 }
197
198 pub const fn new_opaque_type(name: &str) -> Type<'_> {
199 Type {
200 kind: Kind::Opaque,
201 parameters: &[],
202 runtime_type_name: name,
203 trait_mask: 0,
204 }
205 }
206
207 pub fn name(&self) -> &'a str {
208 self.runtime_type_name
209 }
210
211 pub fn has_trait(&self, t: u16) -> bool {
212 self.trait_mask & t == t
213 }
214}
215
216#[cfg(test)]
217mod tests {
218 use super::*;
219
220 #[test]
221 fn parameterized_type() {
222 let param = Type {
223 kind: Kind::Unspecified,
224 parameters: &[],
225 runtime_type_name: "",
226 trait_mask: 0,
227 };
228
229 let t = std::string::String::from("List");
230 let parameterized_list = Type {
231 kind: Kind::List,
232 parameters: &[¶m],
233 runtime_type_name: &t,
234 trait_mask: 0,
235 };
236 assert_eq!(¶m, parameterized_list.parameters[0]);
237
238 let params = [¶m];
239 let list2 = Type::new_list_type(¶ms);
240 assert_eq!(¶m, list2.parameters[0]);
241 assert_eq!(1, list2.parameters.len());
242
243 let params = [¶m, ¶m];
244 let map = Type::new_map_type(¶ms);
245 assert_eq!(¶m, map.parameters[0]);
246 assert_eq!(¶m, map.parameters[1]);
247 assert_eq!(2, map.parameters.len());
248 }
249}