1use indexmap::{IndexMap, IndexSet};
2
3use crate::{
4 errors::BrdbSchemaError,
5 schema::{BrdbInterned, BrdbSchema, BrdbSchemaEnum, BrdbValue, WireVariant},
6};
7
8pub type BrdbArrayIter<'a> = Box<dyn ExactSizeIterator<Item = &'a dyn AsBrdbValue> + 'a>;
9pub type BrdbMapIter<'a> =
10 Box<dyn ExactSizeIterator<Item = (&'a dyn AsBrdbValue, &'a dyn AsBrdbValue)> + 'a>;
11
12pub trait AsBrdbValue {
14 fn as_brdb_bool(&self) -> Result<bool, BrdbSchemaError> {
15 Err(BrdbSchemaError::UnimplementedCast(
16 "bool".to_owned(),
17 std::any::type_name::<Self>(),
18 ))
19 }
20 fn as_brdb_u8(&self) -> Result<u8, BrdbSchemaError> {
21 Err(BrdbSchemaError::UnimplementedCast(
22 "u8".to_owned(),
23 std::any::type_name::<Self>(),
24 ))
25 }
26 fn as_brdb_u16(&self) -> Result<u16, BrdbSchemaError> {
27 Err(BrdbSchemaError::UnimplementedCast(
28 "u16".to_owned(),
29 std::any::type_name::<Self>(),
30 ))
31 }
32 fn as_brdb_u32(&self) -> Result<u32, BrdbSchemaError> {
33 Err(BrdbSchemaError::UnimplementedCast(
34 "u32".to_owned(),
35 std::any::type_name::<Self>(),
36 ))
37 }
38 fn as_brdb_u64(&self) -> Result<u64, BrdbSchemaError> {
39 Err(BrdbSchemaError::UnimplementedCast(
40 "u64".to_owned(),
41 std::any::type_name::<Self>(),
42 ))
43 }
44 fn as_brdb_i8(&self) -> Result<i8, BrdbSchemaError> {
45 Err(BrdbSchemaError::UnimplementedCast(
46 "i8".to_owned(),
47 std::any::type_name::<Self>(),
48 ))
49 }
50 fn as_brdb_i16(&self) -> Result<i16, BrdbSchemaError> {
51 Err(BrdbSchemaError::UnimplementedCast(
52 "i16".to_owned(),
53 std::any::type_name::<Self>(),
54 ))
55 }
56 fn as_brdb_i32(&self) -> Result<i32, BrdbSchemaError> {
57 Err(BrdbSchemaError::UnimplementedCast(
58 "i32".to_owned(),
59 std::any::type_name::<Self>(),
60 ))
61 }
62 fn as_brdb_i64(&self) -> Result<i64, BrdbSchemaError> {
63 Err(BrdbSchemaError::UnimplementedCast(
64 "i64".to_owned(),
65 std::any::type_name::<Self>(),
66 ))
67 }
68 fn as_brdb_f32(&self) -> Result<f32, BrdbSchemaError> {
69 Err(BrdbSchemaError::UnimplementedCast(
70 "f32".to_owned(),
71 std::any::type_name::<Self>(),
72 ))
73 }
74 fn as_brdb_f64(&self) -> Result<f64, BrdbSchemaError> {
75 Err(BrdbSchemaError::UnimplementedCast(
76 "f64".to_owned(),
77 std::any::type_name::<Self>(),
78 ))
79 }
80 fn as_brdb_str(&self) -> Result<&str, BrdbSchemaError> {
81 Err(BrdbSchemaError::UnimplementedCast(
82 "str".to_owned(),
83 std::any::type_name::<Self>(),
84 ))
85 }
86 fn as_brdb_asset(
87 &self,
88 _schema: &BrdbSchema,
89 _ty: &str,
90 ) -> Result<Option<usize>, BrdbSchemaError> {
91 Err(BrdbSchemaError::UnimplementedCast(
92 "asset".to_owned(),
93 std::any::type_name::<Self>(),
94 ))
95 }
96 fn as_brdb_enum(
97 &self,
98 _schema: &BrdbSchema,
99 _def: &BrdbSchemaEnum,
100 ) -> Result<i32, BrdbSchemaError> {
101 Err(BrdbSchemaError::UnimplementedCast(
102 "enum".to_owned(),
103 std::any::type_name::<Self>(),
104 ))
105 }
106
107 fn as_brdb_wire_variant(&self) -> Result<crate::schema::value::WireVariant, BrdbSchemaError> {
108 Err(BrdbSchemaError::UnimplementedCast(
109 "wire variant".to_owned(),
110 std::any::type_name::<Self>(),
111 ))
112 }
113
114 fn as_brdb_struct_prop_value(
116 &self,
117 _schema: &BrdbSchema,
118 _struct_name: BrdbInterned,
119 _prop_name: BrdbInterned,
120 ) -> Result<&dyn AsBrdbValue, BrdbSchemaError> {
121 Err(BrdbSchemaError::UnimplementedCast(
122 "struct property".to_owned(),
123 std::any::type_name::<Self>(),
124 ))
125 }
126
127 fn as_brdb_struct_prop_array(
129 &self,
130 _schema: &BrdbSchema,
131 _struct_name: BrdbInterned,
132 _prop_name: BrdbInterned,
133 ) -> Result<BrdbArrayIter, BrdbSchemaError> {
134 Err(BrdbSchemaError::UnimplementedCast(
135 "struct property array".to_owned(),
136 std::any::type_name::<Self>(),
137 ))
138 }
139
140 fn as_brdb_struct_prop_map(
142 &self,
143 _schema: &BrdbSchema,
144 _struct_name: BrdbInterned,
145 _prop_name: BrdbInterned,
146 ) -> Result<BrdbMapIter, BrdbSchemaError> {
147 Err(BrdbSchemaError::UnimplementedCast(
148 "struct property map".to_owned(),
149 std::any::type_name::<Self>(),
150 ))
151 }
152}
153
154impl AsBrdbValue for () {}
155
156macro_rules! as_brdb_fn {
157 ($fn_name:ident, $ty:ty, $method:ident) => {
158 fn $fn_name(&self) -> Result<$ty, BrdbSchemaError> {
159 if let BrdbValue::$method(v) = self {
160 Ok(*v as $ty)
161 } else {
162 Err(BrdbSchemaError::ExpectedType(
163 stringify!($ty).to_owned(),
164 self.get_type().to_string(),
165 ))
166 }
167 }
168 };
169}
170
171impl AsBrdbValue for BrdbValue {
173 as_brdb_fn!(as_brdb_bool, bool, Bool);
174 as_brdb_fn!(as_brdb_u8, u8, U8);
175 as_brdb_fn!(as_brdb_u16, u16, U16);
176 as_brdb_fn!(as_brdb_u32, u32, U32);
177 as_brdb_fn!(as_brdb_u64, u64, U64);
178 as_brdb_fn!(as_brdb_i8, i8, I8);
179 as_brdb_fn!(as_brdb_i16, i16, I16);
180 as_brdb_fn!(as_brdb_i32, i32, I32);
181 as_brdb_fn!(as_brdb_i64, i64, I64);
182 as_brdb_fn!(as_brdb_f32, f32, F32);
183 as_brdb_fn!(as_brdb_f64, f64, F64);
184 fn as_brdb_str(&self) -> Result<&str, BrdbSchemaError> {
185 if let BrdbValue::String(s) = self {
186 Ok(s)
187 } else {
188 Err(BrdbSchemaError::ExpectedType(
189 "str".to_owned(),
190 self.get_type().to_string(),
191 ))
192 }
193 }
194 fn as_brdb_asset(
195 &self,
196 _schema: &BrdbSchema,
197 _ty: &str,
198 ) -> Result<Option<usize>, BrdbSchemaError> {
199 if let BrdbValue::Asset(index) = self {
200 Ok(*index)
201 } else {
202 Err(BrdbSchemaError::ExpectedType(
203 "asset".to_owned(),
204 self.get_type().to_string(),
205 ))
206 }
207 }
208 fn as_brdb_enum(
209 &self,
210 _schema: &BrdbSchema,
211 _def: &BrdbSchemaEnum,
212 ) -> Result<i32, BrdbSchemaError> {
213 if let BrdbValue::Enum(e) = self {
214 Ok(e.value as i32)
215 } else {
216 Err(BrdbSchemaError::ExpectedType(
217 "enum".to_owned(),
218 self.get_type().to_string(),
219 ))
220 }
221 }
222 fn as_brdb_wire_variant(&self) -> Result<WireVariant, BrdbSchemaError> {
223 if let BrdbValue::WireVar(wire) = self {
224 Ok(wire.to_owned())
225 } else {
226 Err(BrdbSchemaError::ExpectedType(
227 "wire variant".to_owned(),
228 self.get_type().to_string(),
229 ))
230 }
231 }
232 fn as_brdb_struct_prop_value(
233 &self,
234 schema: &BrdbSchema,
235 _struct_name: BrdbInterned,
236 prop_name: BrdbInterned,
237 ) -> Result<&dyn AsBrdbValue, BrdbSchemaError> {
238 let BrdbValue::Struct(s) = self else {
239 return Err(BrdbSchemaError::ExpectedType(
240 "struct".to_owned(),
241 self.get_type().to_string(),
242 ));
243 };
244
245 if let Some(prop) = s.properties.get(&prop_name) {
246 Ok(prop)
247 } else {
248 Err(BrdbSchemaError::MissingStructField(
249 schema
250 .intern
251 .lookup(s.name)
252 .unwrap_or_else(|| "unknown struct".to_owned()),
253 schema
254 .intern
255 .lookup(prop_name)
256 .unwrap_or_else(|| "unknown property".to_owned()),
257 ))
258 }
259 }
260 fn as_brdb_struct_prop_array(
261 &self,
262 schema: &BrdbSchema,
263 _struct_name: BrdbInterned,
264 prop_name: BrdbInterned,
265 ) -> Result<BrdbArrayIter, BrdbSchemaError> {
266 let BrdbValue::Struct(s) = self else {
267 return Err(BrdbSchemaError::ExpectedType(
268 "struct".to_owned(),
269 self.get_type().to_string(),
270 ));
271 };
272 match s.properties.get(&prop_name) {
273 Some(BrdbValue::Array(vec)) | Some(BrdbValue::FlatArray(vec)) => Ok(vec.as_brdb_iter()),
274 _ => Err(BrdbSchemaError::MissingStructField(
275 schema
276 .intern
277 .lookup(s.name)
278 .unwrap_or_else(|| "unknown struct".to_owned()),
279 schema
280 .intern
281 .lookup(prop_name)
282 .unwrap_or_else(|| "unknown property".to_owned()),
283 )),
284 }
285 }
286 fn as_brdb_struct_prop_map(
287 &self,
288 schema: &BrdbSchema,
289 _struct_name: BrdbInterned,
290 prop_name: BrdbInterned,
291 ) -> Result<BrdbMapIter, BrdbSchemaError> {
292 let BrdbValue::Struct(s) = self else {
293 return Err(BrdbSchemaError::ExpectedType(
294 "struct".to_owned(),
295 self.get_type().to_string(),
296 ));
297 };
298 if let Some(BrdbValue::Map(map)) = s.properties.get(&prop_name) {
299 Ok(Box::new(map.iter().map(|(k, v)| {
300 (k as &dyn AsBrdbValue, v as &dyn AsBrdbValue)
301 })))
302 } else {
303 Err(BrdbSchemaError::MissingStructField(
304 schema
305 .intern
306 .lookup(s.name)
307 .unwrap_or_else(|| "unknown struct".to_owned()),
308 schema
309 .intern
310 .lookup(prop_name)
311 .unwrap_or_else(|| "unknown property".to_owned()),
312 ))
313 }
314 }
315}
316impl AsBrdbValue for WireVariant {
317 fn as_brdb_wire_variant(&self) -> Result<WireVariant, BrdbSchemaError> {
318 Ok(self.clone())
319 }
320}
321
322macro_rules! as_brdb_int(
323 ($ty:ty, $($rest:ty),*) => {
324 as_brdb_int!($ty);
325 as_brdb_int!($($rest),*);
326 };
327 ($ty:ty) => {
328 impl AsBrdbValue for $ty {
329 fn as_brdb_bool(&self) -> Result<bool, BrdbSchemaError> {
330 Ok(*self != 0)
331 }
332 fn as_brdb_u8(&self) -> Result<u8, BrdbSchemaError> {
333 Ok(*self as u8)
334 }
335 fn as_brdb_u16(&self) -> Result<u16, BrdbSchemaError> {
336 Ok(*self as u16)
337 }
338 fn as_brdb_u32(&self) -> Result<u32, BrdbSchemaError> {
339 Ok(*self as u32)
340 }
341 fn as_brdb_u64(&self) -> Result<u64, BrdbSchemaError> {
342 Ok(*self as u64)
343 }
344 fn as_brdb_i8(&self) -> Result<i8, BrdbSchemaError> {
345 Ok(*self as i8)
346 }
347 fn as_brdb_i16(&self) -> Result<i16, BrdbSchemaError> {
348 Ok(*self as i16)
349 }
350 fn as_brdb_i32(&self) -> Result<i32, BrdbSchemaError> {
351 Ok(*self as i32)
352 }
353 fn as_brdb_i64(&self) -> Result<i64, BrdbSchemaError> {
354 Ok(*self as i64)
355 }
356 fn as_brdb_f32(&self) -> Result<f32, BrdbSchemaError> {
357 Ok(*self as f32)
358 }
359 fn as_brdb_f64(&self) -> Result<f64, BrdbSchemaError> {
360 Ok(*self as f64)
361 }
362 fn as_brdb_wire_variant(
363 &self,
364 ) -> Result<WireVariant, BrdbSchemaError> {
365 Ok((*self).into())
366 }
367 }
368 }
369);
370as_brdb_int!(u8, u16, u32, u64, i8, i16, i32, i64);
371
372macro_rules! as_brdb_float {
373 ($ty:ty, $($rest:ty),*) => {
374 as_brdb_float!($ty);
375 as_brdb_float!($($rest),*);
376 };
377 ($ty:ty) => {
378 impl AsBrdbValue for $ty {
379 fn as_brdb_f32(&self) -> Result<f32, BrdbSchemaError> {
380 Ok(*self as f32)
381 }
382 fn as_brdb_f64(&self) -> Result<f64, BrdbSchemaError> {
383 Ok(*self as f64)
384 }
385 fn as_brdb_wire_variant(
386 &self,
387 ) -> Result<WireVariant, BrdbSchemaError> {
388 Ok(WireVariant::Number(*self as f64))
389 }
390 }
391 };
392}
393as_brdb_float!(f32, f64);
394
395impl AsBrdbValue for bool {
396 fn as_brdb_bool(&self) -> Result<bool, BrdbSchemaError> {
397 Ok(*self)
398 }
399 fn as_brdb_wire_variant(&self) -> Result<crate::schema::value::WireVariant, BrdbSchemaError> {
400 Ok(WireVariant::Bool(*self))
401 }
402}
403impl AsBrdbValue for String {
404 fn as_brdb_str(&self) -> Result<&str, BrdbSchemaError> {
405 Ok(self)
406 }
407}
408impl AsBrdbValue for &str {
409 fn as_brdb_str(&self) -> Result<&str, BrdbSchemaError> {
410 Ok(self)
411 }
412}
413
414pub trait AsBrdbIter {
415 fn as_brdb_iter(&self) -> BrdbArrayIter;
416}
417pub trait AsBrdbMapIter {
418 fn as_brdb_map_iter(&self) -> BrdbMapIter;
419}
420
421impl<T: AsBrdbValue> AsBrdbIter for Vec<T> {
422 fn as_brdb_iter(&self) -> BrdbArrayIter {
423 Box::new(self.iter().map(|v| v as &dyn AsBrdbValue))
424 }
425}
426impl<T: AsBrdbValue> AsBrdbIter for IndexSet<T> {
427 fn as_brdb_iter(&self) -> BrdbArrayIter {
428 Box::new(self.iter().map(|v| v as &dyn AsBrdbValue))
429 }
430}
431impl<K: AsBrdbValue, V: AsBrdbValue> AsBrdbMapIter for IndexMap<K, V> {
432 fn as_brdb_map_iter(&self) -> BrdbMapIter {
433 Box::new(
434 self.iter()
435 .map(|(k, v)| (k as &dyn AsBrdbValue, v as &dyn AsBrdbValue)),
436 )
437 }
438}
439
440macro_rules! as_brdb_tuple {
443 ($($name:ident $index:tt),*) => {
444 impl<$($name: AsBrdbValue),*> AsBrdbValue for ($($name),*) {
445 fn as_brdb_struct_prop_value(
446 &self,
447 schema: &BrdbSchema,
448 struct_name: BrdbInterned,
449 prop_name: BrdbInterned,
450 ) -> Result<&dyn AsBrdbValue, BrdbSchemaError> {
451 let s_ty = schema.get_struct_interned(struct_name).unwrap();
452 let prop_index = s_ty.get_index_of(&prop_name);
453 match prop_index {
454 $(
455 Some($index) => Ok(&self.$index),
456 )*
457 _ => Err(BrdbSchemaError::MissingStructField(
458 struct_name.get_or_else(schema, || "unknown struct".to_owned()),
459 prop_name.get_or_else(schema, || "unknown property".to_owned()),
460 )),
461 }
462 }
463 }
464 };
465}
466
467as_brdb_tuple!(A 0, B 1);
468as_brdb_tuple!(A 0, B 1, C 2);
469as_brdb_tuple!(A 0, B 1, C 2, D 3);
470as_brdb_tuple!(A 0, B 1, C 2, D 3, E 4);