1use indexmap::{IndexMap, IndexSet};
2
3use crate::{
4 errors::BrdbSchemaError,
5 schema::{BrdbInterned, BrdbSchema, BrdbSchemaEnum, BrdbStruct, 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 s.as_brdb_struct_prop_value(schema, struct_name, prop_name)
246 }
247 fn as_brdb_struct_prop_array(
248 &self,
249 schema: &BrdbSchema,
250 struct_name: BrdbInterned,
251 prop_name: BrdbInterned,
252 ) -> Result<BrdbArrayIter, BrdbSchemaError> {
253 let BrdbValue::Struct(s) = self else {
254 return Err(BrdbSchemaError::ExpectedType(
255 "struct".to_owned(),
256 self.get_type().to_string(),
257 ));
258 };
259 s.as_brdb_struct_prop_array(schema, struct_name, prop_name)
260 }
261 fn as_brdb_struct_prop_map(
262 &self,
263 schema: &BrdbSchema,
264 struct_name: BrdbInterned,
265 prop_name: BrdbInterned,
266 ) -> Result<BrdbMapIter, BrdbSchemaError> {
267 let BrdbValue::Struct(s) = self else {
268 return Err(BrdbSchemaError::ExpectedType(
269 "struct".to_owned(),
270 self.get_type().to_string(),
271 ));
272 };
273 s.as_brdb_struct_prop_map(schema, struct_name, prop_name)
274 }
275}
276
277impl AsBrdbValue for BrdbStruct {
278 fn as_brdb_struct_prop_value(
279 &self,
280 schema: &BrdbSchema,
281 _struct_name: BrdbInterned,
282 prop_name: BrdbInterned,
283 ) -> Result<&dyn AsBrdbValue, BrdbSchemaError> {
284 if let Some(prop) = self.properties.get(&prop_name) {
285 Ok(prop)
286 } else {
287 Err(BrdbSchemaError::MissingStructField(
288 schema
289 .intern
290 .lookup(self.name)
291 .unwrap_or_else(|| "unknown struct".to_owned()),
292 schema
293 .intern
294 .lookup(prop_name)
295 .unwrap_or_else(|| "unknown property".to_owned()),
296 ))
297 }
298 }
299
300 fn as_brdb_struct_prop_array(
301 &self,
302 schema: &BrdbSchema,
303 _struct_name: BrdbInterned,
304 prop_name: BrdbInterned,
305 ) -> Result<BrdbArrayIter, BrdbSchemaError> {
306 match self.properties.get(&prop_name) {
307 Some(BrdbValue::Array(vec)) | Some(BrdbValue::FlatArray(vec)) => Ok(vec.as_brdb_iter()),
308 _ => Err(BrdbSchemaError::MissingStructField(
309 schema
310 .intern
311 .lookup(self.name)
312 .unwrap_or_else(|| "unknown struct".to_owned()),
313 schema
314 .intern
315 .lookup(prop_name)
316 .unwrap_or_else(|| "unknown property".to_owned()),
317 )),
318 }
319 }
320
321 fn as_brdb_struct_prop_map(
322 &self,
323 schema: &BrdbSchema,
324 _struct_name: BrdbInterned,
325 prop_name: BrdbInterned,
326 ) -> Result<BrdbMapIter, BrdbSchemaError> {
327 if let Some(BrdbValue::Map(map)) = self.properties.get(&prop_name) {
328 Ok(Box::new(map.iter().map(|(k, v)| {
329 (k as &dyn AsBrdbValue, v as &dyn AsBrdbValue)
330 })))
331 } else {
332 Err(BrdbSchemaError::MissingStructField(
333 schema
334 .intern
335 .lookup(self.name)
336 .unwrap_or_else(|| "unknown struct".to_owned()),
337 schema
338 .intern
339 .lookup(prop_name)
340 .unwrap_or_else(|| "unknown property".to_owned()),
341 ))
342 }
343 }
344}
345
346impl AsBrdbValue for WireVariant {
347 fn as_brdb_wire_variant(&self) -> Result<WireVariant, BrdbSchemaError> {
348 Ok(self.clone())
349 }
350}
351
352macro_rules! as_brdb_int(
353 ($ty:ty, $($rest:ty),*) => {
354 as_brdb_int!($ty);
355 as_brdb_int!($($rest),*);
356 };
357 ($ty:ty) => {
358 impl AsBrdbValue for $ty {
359 fn as_brdb_bool(&self) -> Result<bool, BrdbSchemaError> {
360 Ok(*self != 0)
361 }
362 fn as_brdb_u8(&self) -> Result<u8, BrdbSchemaError> {
363 Ok(*self as u8)
364 }
365 fn as_brdb_u16(&self) -> Result<u16, BrdbSchemaError> {
366 Ok(*self as u16)
367 }
368 fn as_brdb_u32(&self) -> Result<u32, BrdbSchemaError> {
369 Ok(*self as u32)
370 }
371 fn as_brdb_u64(&self) -> Result<u64, BrdbSchemaError> {
372 Ok(*self as u64)
373 }
374 fn as_brdb_i8(&self) -> Result<i8, BrdbSchemaError> {
375 Ok(*self as i8)
376 }
377 fn as_brdb_i16(&self) -> Result<i16, BrdbSchemaError> {
378 Ok(*self as i16)
379 }
380 fn as_brdb_i32(&self) -> Result<i32, BrdbSchemaError> {
381 Ok(*self as i32)
382 }
383 fn as_brdb_i64(&self) -> Result<i64, BrdbSchemaError> {
384 Ok(*self as i64)
385 }
386 fn as_brdb_f32(&self) -> Result<f32, BrdbSchemaError> {
387 Ok(*self as f32)
388 }
389 fn as_brdb_f64(&self) -> Result<f64, BrdbSchemaError> {
390 Ok(*self as f64)
391 }
392 fn as_brdb_wire_variant(
393 &self,
394 ) -> Result<WireVariant, BrdbSchemaError> {
395 Ok((*self).into())
396 }
397 }
398 }
399);
400as_brdb_int!(u8, u16, u32, u64, i8, i16, i32, i64);
401
402macro_rules! as_brdb_float {
403 ($ty:ty, $($rest:ty),*) => {
404 as_brdb_float!($ty);
405 as_brdb_float!($($rest),*);
406 };
407 ($ty:ty) => {
408 impl AsBrdbValue for $ty {
409 fn as_brdb_f32(&self) -> Result<f32, BrdbSchemaError> {
410 Ok(*self as f32)
411 }
412 fn as_brdb_f64(&self) -> Result<f64, BrdbSchemaError> {
413 Ok(*self as f64)
414 }
415 fn as_brdb_wire_variant(
416 &self,
417 ) -> Result<WireVariant, BrdbSchemaError> {
418 Ok(WireVariant::Number(*self as f64))
419 }
420 }
421 };
422}
423as_brdb_float!(f32, f64);
424
425impl AsBrdbValue for bool {
426 fn as_brdb_bool(&self) -> Result<bool, BrdbSchemaError> {
427 Ok(*self)
428 }
429 fn as_brdb_wire_variant(&self) -> Result<crate::schema::value::WireVariant, BrdbSchemaError> {
430 Ok(WireVariant::Bool(*self))
431 }
432}
433impl AsBrdbValue for String {
434 fn as_brdb_str(&self) -> Result<&str, BrdbSchemaError> {
435 Ok(self)
436 }
437}
438impl AsBrdbValue for &str {
439 fn as_brdb_str(&self) -> Result<&str, BrdbSchemaError> {
440 Ok(self)
441 }
442}
443
444pub trait AsBrdbIter {
445 fn as_brdb_iter(&self) -> BrdbArrayIter;
446}
447pub trait AsBrdbMapIter {
448 fn as_brdb_map_iter(&self) -> BrdbMapIter;
449}
450
451impl<T: AsBrdbValue> AsBrdbIter for Vec<T> {
452 fn as_brdb_iter(&self) -> BrdbArrayIter {
453 Box::new(self.iter().map(|v| v as &dyn AsBrdbValue))
454 }
455}
456impl<T: AsBrdbValue> AsBrdbIter for IndexSet<T> {
457 fn as_brdb_iter(&self) -> BrdbArrayIter {
458 Box::new(self.iter().map(|v| v as &dyn AsBrdbValue))
459 }
460}
461impl<K: AsBrdbValue, V: AsBrdbValue> AsBrdbMapIter for IndexMap<K, V> {
462 fn as_brdb_map_iter(&self) -> BrdbMapIter {
463 Box::new(
464 self.iter()
465 .map(|(k, v)| (k as &dyn AsBrdbValue, v as &dyn AsBrdbValue)),
466 )
467 }
468}
469
470macro_rules! as_brdb_tuple {
473 ($($name:ident $index:tt),*) => {
474 impl<$($name: AsBrdbValue),*> AsBrdbValue for ($($name),*) {
475 fn as_brdb_struct_prop_value(
476 &self,
477 schema: &BrdbSchema,
478 struct_name: BrdbInterned,
479 prop_name: BrdbInterned,
480 ) -> Result<&dyn AsBrdbValue, BrdbSchemaError> {
481 let s_ty = schema.get_struct_interned(struct_name).unwrap();
482 let prop_index = s_ty.get_index_of(&prop_name);
483 match prop_index {
484 $(
485 Some($index) => Ok(&self.$index),
486 )*
487 _ => Err(BrdbSchemaError::MissingStructField(
488 struct_name.get_or_else(schema, || "unknown struct".to_owned()),
489 prop_name.get_or_else(schema, || "unknown property".to_owned()),
490 )),
491 }
492 }
493 }
494 };
495}
496
497as_brdb_tuple!(A 0, B 1);
498as_brdb_tuple!(A 0, B 1, C 2);
499as_brdb_tuple!(A 0, B 1, C 2, D 3);
500as_brdb_tuple!(A 0, B 1, C 2, D 3, E 4);