1use std::any::{Any, TypeId};
11use std::collections::HashMap;
12use glam::{Vec2, Vec3};
13
14#[derive(Debug, Clone, PartialEq, Eq)]
20pub enum DeserializeError {
21 WrongType { expected: &'static str, got: &'static str },
23 MissingKey(String),
25 IndexOutOfBounds { index: usize, len: usize },
27 ParseError(String),
29 Custom(String),
31}
32
33impl std::fmt::Display for DeserializeError {
34 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
35 match self {
36 DeserializeError::WrongType { expected, got } => {
37 write!(f, "type mismatch: expected {expected}, got {got}")
38 }
39 DeserializeError::MissingKey(k) => write!(f, "missing key: '{k}'"),
40 DeserializeError::IndexOutOfBounds { index, len } => {
41 write!(f, "index {index} out of bounds (len {len})")
42 }
43 DeserializeError::ParseError(s) => write!(f, "parse error: {s}"),
44 DeserializeError::Custom(s) => write!(f, "{s}"),
45 }
46 }
47}
48
49impl std::error::Error for DeserializeError {}
50
51#[derive(Debug, Clone, PartialEq)]
57pub enum SerializedValue {
58 Null,
59 Bool(bool),
60 Int(i64),
61 Float(f64),
62 Str(String),
63 Bytes(Vec<u8>),
64 List(Vec<SerializedValue>),
65 Map(HashMap<String, SerializedValue>),
66}
67
68impl SerializedValue {
69 pub fn null() -> Self { SerializedValue::Null }
72 pub fn bool(b: bool) -> Self { SerializedValue::Bool(b) }
73 pub fn int(i: i64) -> Self { SerializedValue::Int(i) }
74 pub fn float(f: f64) -> Self { SerializedValue::Float(f) }
75 pub fn str(s: impl Into<String>) -> Self { SerializedValue::Str(s.into()) }
76 pub fn bytes(b: Vec<u8>) -> Self { SerializedValue::Bytes(b) }
77 pub fn list(v: Vec<SerializedValue>) -> Self { SerializedValue::List(v) }
78 pub fn map(m: HashMap<String, SerializedValue>) -> Self { SerializedValue::Map(m) }
79
80 pub fn empty_map() -> Self {
81 SerializedValue::Map(HashMap::new())
82 }
83
84 pub fn empty_list() -> Self {
85 SerializedValue::List(Vec::new())
86 }
87
88 pub fn as_bool(&self) -> Option<bool> {
91 if let SerializedValue::Bool(b) = self { Some(*b) } else { None }
92 }
93
94 pub fn as_int(&self) -> Option<i64> {
95 match self {
96 SerializedValue::Int(i) => Some(*i),
97 SerializedValue::Float(f) => Some(*f as i64),
98 _ => None,
99 }
100 }
101
102 pub fn as_float(&self) -> Option<f64> {
103 match self {
104 SerializedValue::Float(f) => Some(*f),
105 SerializedValue::Int(i) => Some(*i as f64),
106 _ => None,
107 }
108 }
109
110 pub fn as_str(&self) -> Option<&str> {
111 if let SerializedValue::Str(s) = self { Some(s.as_str()) } else { None }
112 }
113
114 pub fn as_bytes(&self) -> Option<&[u8]> {
115 if let SerializedValue::Bytes(b) = self { Some(b.as_slice()) } else { None }
116 }
117
118 pub fn as_list(&self) -> Option<&[SerializedValue]> {
119 if let SerializedValue::List(v) = self { Some(v.as_slice()) } else { None }
120 }
121
122 pub fn as_map(&self) -> Option<&HashMap<String, SerializedValue>> {
123 if let SerializedValue::Map(m) = self { Some(m) } else { None }
124 }
125
126 pub fn as_map_mut(&mut self) -> Option<&mut HashMap<String, SerializedValue>> {
127 if let SerializedValue::Map(m) = self { Some(m) } else { None }
128 }
129
130 pub fn is_null(&self) -> bool {
131 matches!(self, SerializedValue::Null)
132 }
133
134 pub fn get(&self, key: &str) -> Option<&SerializedValue> {
138 self.as_map()?.get(key)
139 }
140
141 pub fn index(&self, i: usize) -> Option<&SerializedValue> {
143 self.as_list()?.get(i)
144 }
145
146 pub fn insert(&mut self, key: impl Into<String>, value: SerializedValue) -> bool {
148 if let SerializedValue::Map(m) = self {
149 m.insert(key.into(), value);
150 true
151 } else {
152 false
153 }
154 }
155
156 pub fn push(&mut self, value: SerializedValue) -> bool {
158 if let SerializedValue::List(v) = self {
159 v.push(value);
160 true
161 } else {
162 false
163 }
164 }
165
166 pub fn type_name(&self) -> &'static str {
168 match self {
169 SerializedValue::Null => "Null",
170 SerializedValue::Bool(_) => "Bool",
171 SerializedValue::Int(_) => "Int",
172 SerializedValue::Float(_) => "Float",
173 SerializedValue::Str(_) => "Str",
174 SerializedValue::Bytes(_) => "Bytes",
175 SerializedValue::List(_) => "List",
176 SerializedValue::Map(_) => "Map",
177 }
178 }
179
180 pub fn to_json_string(&self) -> String {
184 let mut buf = String::with_capacity(64);
185 self.write_json(&mut buf);
186 buf
187 }
188
189 fn write_json(&self, buf: &mut String) {
190 match self {
191 SerializedValue::Null => buf.push_str("null"),
192 SerializedValue::Bool(b) => buf.push_str(if *b { "true" } else { "false" }),
193 SerializedValue::Int(i) => buf.push_str(&i.to_string()),
194 SerializedValue::Float(f) => {
195 if f.is_nan() {
196 buf.push_str("null"); } else if f.is_infinite() {
198 buf.push_str(if *f > 0.0 { "1e308" } else { "-1e308" });
199 } else {
200 buf.push_str(&format!("{f:?}"));
201 }
202 }
203 SerializedValue::Str(s) => {
204 buf.push('"');
205 for ch in s.chars() {
206 match ch {
207 '"' => buf.push_str("\\\""),
208 '\\' => buf.push_str("\\\\"),
209 '\n' => buf.push_str("\\n"),
210 '\r' => buf.push_str("\\r"),
211 '\t' => buf.push_str("\\t"),
212 c if (c as u32) < 0x20 => {
213 buf.push_str(&format!("\\u{:04x}", c as u32));
214 }
215 c => buf.push(c),
216 }
217 }
218 buf.push('"');
219 }
220 SerializedValue::Bytes(bytes) => {
221 buf.push('"');
223 for b in bytes {
224 buf.push_str(&format!("{b:02x}"));
225 }
226 buf.push('"');
227 }
228 SerializedValue::List(items) => {
229 buf.push('[');
230 for (i, item) in items.iter().enumerate() {
231 if i > 0 {
232 buf.push(',');
233 }
234 item.write_json(buf);
235 }
236 buf.push(']');
237 }
238 SerializedValue::Map(m) => {
239 buf.push('{');
240 let mut first = true;
241 let mut keys: Vec<&String> = m.keys().collect();
243 keys.sort();
244 for key in keys {
245 if !first {
246 buf.push(',');
247 }
248 first = false;
249 SerializedValue::Str(key.clone()).write_json(buf);
250 buf.push(':');
251 m[key].write_json(buf);
252 }
253 buf.push('}');
254 }
255 }
256 }
257
258 pub fn from_json_str(s: &str) -> Result<Self, DeserializeError> {
262 let mut parser = JsonParser::new(s.trim());
263 let v = parser.parse_value()?;
264 parser.skip_whitespace();
265 Ok(v)
266 }
267}
268
269impl Default for SerializedValue {
270 fn default() -> Self {
271 SerializedValue::Null
272 }
273}
274
275struct JsonParser<'a> {
280 src: &'a [u8],
281 pos: usize,
282}
283
284impl<'a> JsonParser<'a> {
285 fn new(s: &'a str) -> Self {
286 Self { src: s.as_bytes(), pos: 0 }
287 }
288
289 fn skip_whitespace(&mut self) {
290 while self.pos < self.src.len() && self.src[self.pos].is_ascii_whitespace() {
291 self.pos += 1;
292 }
293 }
294
295 fn peek(&self) -> Option<u8> {
296 self.src.get(self.pos).copied()
297 }
298
299 fn consume(&mut self) -> Option<u8> {
300 if self.pos < self.src.len() {
301 let b = self.src[self.pos];
302 self.pos += 1;
303 Some(b)
304 } else {
305 None
306 }
307 }
308
309 fn expect(&mut self, b: u8) -> Result<(), DeserializeError> {
310 match self.consume() {
311 Some(got) if got == b => Ok(()),
312 Some(got) => Err(DeserializeError::ParseError(format!(
313 "expected '{}' got '{}'",
314 b as char, got as char
315 ))),
316 None => Err(DeserializeError::ParseError("unexpected EOF".into())),
317 }
318 }
319
320 fn parse_value(&mut self) -> Result<SerializedValue, DeserializeError> {
321 self.skip_whitespace();
322 match self.peek() {
323 Some(b'n') => self.parse_null(),
324 Some(b't') | Some(b'f') => self.parse_bool(),
325 Some(b'"') => self.parse_string(),
326 Some(b'[') => self.parse_array(),
327 Some(b'{') => self.parse_object(),
328 Some(b'-') | Some(b'0'..=b'9') => self.parse_number(),
329 Some(c) => Err(DeserializeError::ParseError(format!("unexpected char '{}'", c as char))),
330 None => Err(DeserializeError::ParseError("unexpected EOF".into())),
331 }
332 }
333
334 fn parse_null(&mut self) -> Result<SerializedValue, DeserializeError> {
335 self.expect(b'n')?;
336 self.expect(b'u')?;
337 self.expect(b'l')?;
338 self.expect(b'l')?;
339 Ok(SerializedValue::Null)
340 }
341
342 fn parse_bool(&mut self) -> Result<SerializedValue, DeserializeError> {
343 if self.peek() == Some(b't') {
344 self.expect(b't')?; self.expect(b'r')?; self.expect(b'u')?; self.expect(b'e')?;
345 Ok(SerializedValue::Bool(true))
346 } else {
347 self.expect(b'f')?; self.expect(b'a')?; self.expect(b'l')?; self.expect(b's')?; self.expect(b'e')?;
348 Ok(SerializedValue::Bool(false))
349 }
350 }
351
352 fn parse_string(&mut self) -> Result<SerializedValue, DeserializeError> {
353 self.expect(b'"')?;
354 let mut s = String::new();
355 loop {
356 match self.consume() {
357 Some(b'"') => break,
358 Some(b'\\') => {
359 match self.consume() {
360 Some(b'"') => s.push('"'),
361 Some(b'\\') => s.push('\\'),
362 Some(b'/') => s.push('/'),
363 Some(b'n') => s.push('\n'),
364 Some(b'r') => s.push('\r'),
365 Some(b't') => s.push('\t'),
366 Some(b'u') => {
367 let mut hex = String::new();
369 for _ in 0..4 {
370 hex.push(self.consume().unwrap_or(b'0') as char);
371 }
372 let code = u32::from_str_radix(&hex, 16).unwrap_or(0xFFFD);
373 s.push(char::from_u32(code).unwrap_or('\u{FFFD}'));
374 }
375 Some(c) => s.push(c as char),
376 None => return Err(DeserializeError::ParseError("unterminated string".into())),
377 }
378 }
379 Some(c) => s.push(c as char),
380 None => return Err(DeserializeError::ParseError("unterminated string".into())),
381 }
382 }
383 Ok(SerializedValue::Str(s))
384 }
385
386 fn parse_number(&mut self) -> Result<SerializedValue, DeserializeError> {
387 let start = self.pos;
388 if self.peek() == Some(b'-') { self.pos += 1; }
389 while matches!(self.peek(), Some(b'0'..=b'9')) { self.pos += 1; }
390 let is_float = matches!(self.peek(), Some(b'.') | Some(b'e') | Some(b'E'));
391 if is_float {
392 if self.peek() == Some(b'.') {
393 self.pos += 1;
394 while matches!(self.peek(), Some(b'0'..=b'9')) { self.pos += 1; }
395 }
396 if matches!(self.peek(), Some(b'e') | Some(b'E')) {
397 self.pos += 1;
398 if matches!(self.peek(), Some(b'+') | Some(b'-')) { self.pos += 1; }
399 while matches!(self.peek(), Some(b'0'..=b'9')) { self.pos += 1; }
400 }
401 }
402 let slice = std::str::from_utf8(&self.src[start..self.pos])
403 .map_err(|e| DeserializeError::ParseError(e.to_string()))?;
404 if is_float {
405 let f: f64 = slice.parse()
406 .map_err(|e: std::num::ParseFloatError| DeserializeError::ParseError(e.to_string()))?;
407 Ok(SerializedValue::Float(f))
408 } else {
409 let i: i64 = slice.parse()
410 .map_err(|e: std::num::ParseIntError| DeserializeError::ParseError(e.to_string()))?;
411 Ok(SerializedValue::Int(i))
412 }
413 }
414
415 fn parse_array(&mut self) -> Result<SerializedValue, DeserializeError> {
416 self.expect(b'[')?;
417 let mut items = Vec::new();
418 self.skip_whitespace();
419 if self.peek() == Some(b']') {
420 self.pos += 1;
421 return Ok(SerializedValue::List(items));
422 }
423 loop {
424 items.push(self.parse_value()?);
425 self.skip_whitespace();
426 match self.peek() {
427 Some(b',') => { self.pos += 1; }
428 Some(b']') => { self.pos += 1; break; }
429 Some(c) => return Err(DeserializeError::ParseError(format!("expected ',' or ']' got '{}'", c as char))),
430 None => return Err(DeserializeError::ParseError("unterminated array".into())),
431 }
432 }
433 Ok(SerializedValue::List(items))
434 }
435
436 fn parse_object(&mut self) -> Result<SerializedValue, DeserializeError> {
437 self.expect(b'{')?;
438 let mut map = HashMap::new();
439 self.skip_whitespace();
440 if self.peek() == Some(b'}') {
441 self.pos += 1;
442 return Ok(SerializedValue::Map(map));
443 }
444 loop {
445 self.skip_whitespace();
446 let key_val = self.parse_string()?;
447 let key = match key_val {
448 SerializedValue::Str(s) => s,
449 _ => return Err(DeserializeError::ParseError("expected string key".into())),
450 };
451 self.skip_whitespace();
452 self.expect(b':')?;
453 let value = self.parse_value()?;
454 map.insert(key, value);
455 self.skip_whitespace();
456 match self.peek() {
457 Some(b',') => { self.pos += 1; }
458 Some(b'}') => { self.pos += 1; break; }
459 Some(c) => return Err(DeserializeError::ParseError(format!("expected ',' or '}}' got '{}'", c as char))),
460 None => return Err(DeserializeError::ParseError("unterminated object".into())),
461 }
462 }
463 Ok(SerializedValue::Map(map))
464 }
465}
466
467pub trait Serialize {
473 fn serialize(&self) -> SerializedValue;
474}
475
476pub trait Deserialize: Sized {
478 fn deserialize(v: &SerializedValue) -> Result<Self, DeserializeError>;
479}
480
481impl Serialize for bool {
484 fn serialize(&self) -> SerializedValue { SerializedValue::Bool(*self) }
485}
486
487impl Deserialize for bool {
488 fn deserialize(v: &SerializedValue) -> Result<Self, DeserializeError> {
489 v.as_bool().ok_or(DeserializeError::WrongType { expected: "Bool", got: v.type_name() })
490 }
491}
492
493impl Serialize for i32 {
496 fn serialize(&self) -> SerializedValue { SerializedValue::Int(*self as i64) }
497}
498
499impl Deserialize for i32 {
500 fn deserialize(v: &SerializedValue) -> Result<Self, DeserializeError> {
501 v.as_int().map(|i| i as i32)
502 .ok_or(DeserializeError::WrongType { expected: "Int", got: v.type_name() })
503 }
504}
505
506impl Serialize for i64 {
509 fn serialize(&self) -> SerializedValue { SerializedValue::Int(*self) }
510}
511
512impl Deserialize for i64 {
513 fn deserialize(v: &SerializedValue) -> Result<Self, DeserializeError> {
514 v.as_int().ok_or(DeserializeError::WrongType { expected: "Int", got: v.type_name() })
515 }
516}
517
518impl Serialize for u32 {
521 fn serialize(&self) -> SerializedValue { SerializedValue::Int(*self as i64) }
522}
523
524impl Deserialize for u32 {
525 fn deserialize(v: &SerializedValue) -> Result<Self, DeserializeError> {
526 v.as_int().map(|i| i as u32)
527 .ok_or(DeserializeError::WrongType { expected: "Int", got: v.type_name() })
528 }
529}
530
531impl Serialize for u64 {
534 fn serialize(&self) -> SerializedValue { SerializedValue::Int(*self as i64) }
535}
536
537impl Deserialize for u64 {
538 fn deserialize(v: &SerializedValue) -> Result<Self, DeserializeError> {
539 v.as_int().map(|i| i as u64)
540 .ok_or(DeserializeError::WrongType { expected: "Int", got: v.type_name() })
541 }
542}
543
544impl Serialize for f32 {
547 fn serialize(&self) -> SerializedValue { SerializedValue::Float(*self as f64) }
548}
549
550impl Deserialize for f32 {
551 fn deserialize(v: &SerializedValue) -> Result<Self, DeserializeError> {
552 v.as_float().map(|f| f as f32)
553 .ok_or(DeserializeError::WrongType { expected: "Float", got: v.type_name() })
554 }
555}
556
557impl Serialize for f64 {
560 fn serialize(&self) -> SerializedValue { SerializedValue::Float(*self) }
561}
562
563impl Deserialize for f64 {
564 fn deserialize(v: &SerializedValue) -> Result<Self, DeserializeError> {
565 v.as_float().ok_or(DeserializeError::WrongType { expected: "Float", got: v.type_name() })
566 }
567}
568
569impl Serialize for String {
572 fn serialize(&self) -> SerializedValue { SerializedValue::Str(self.clone()) }
573}
574
575impl Deserialize for String {
576 fn deserialize(v: &SerializedValue) -> Result<Self, DeserializeError> {
577 v.as_str().map(|s| s.to_string())
578 .ok_or(DeserializeError::WrongType { expected: "Str", got: v.type_name() })
579 }
580}
581
582impl Serialize for &str {
585 fn serialize(&self) -> SerializedValue { SerializedValue::Str(self.to_string()) }
586}
587
588impl<T: Serialize> Serialize for Vec<T> {
591 fn serialize(&self) -> SerializedValue {
592 SerializedValue::List(self.iter().map(|v| v.serialize()).collect())
593 }
594}
595
596impl<T: Deserialize> Deserialize for Vec<T> {
597 fn deserialize(v: &SerializedValue) -> Result<Self, DeserializeError> {
598 let list = v.as_list()
599 .ok_or(DeserializeError::WrongType { expected: "List", got: v.type_name() })?;
600 list.iter().map(T::deserialize).collect()
601 }
602}
603
604impl<V: Serialize> Serialize for HashMap<String, V> {
607 fn serialize(&self) -> SerializedValue {
608 let mut m = HashMap::new();
609 for (k, v) in self {
610 m.insert(k.clone(), v.serialize());
611 }
612 SerializedValue::Map(m)
613 }
614}
615
616impl<V: Deserialize> Deserialize for HashMap<String, V> {
617 fn deserialize(sv: &SerializedValue) -> Result<Self, DeserializeError> {
618 let map = sv.as_map()
619 .ok_or(DeserializeError::WrongType { expected: "Map", got: sv.type_name() })?;
620 let mut out = HashMap::new();
621 for (k, v) in map {
622 out.insert(k.clone(), V::deserialize(v)?);
623 }
624 Ok(out)
625 }
626}
627
628impl<T: Serialize> Serialize for Option<T> {
631 fn serialize(&self) -> SerializedValue {
632 match self {
633 Some(v) => v.serialize(),
634 None => SerializedValue::Null,
635 }
636 }
637}
638
639impl<T: Deserialize> Deserialize for Option<T> {
640 fn deserialize(v: &SerializedValue) -> Result<Self, DeserializeError> {
641 if v.is_null() {
642 Ok(None)
643 } else {
644 T::deserialize(v).map(Some)
645 }
646 }
647}
648
649impl Serialize for Vec2 {
652 fn serialize(&self) -> SerializedValue {
653 let mut m = HashMap::new();
654 m.insert("x".to_string(), SerializedValue::Float(self.x as f64));
655 m.insert("y".to_string(), SerializedValue::Float(self.y as f64));
656 SerializedValue::Map(m)
657 }
658}
659
660impl Deserialize for Vec2 {
661 fn deserialize(v: &SerializedValue) -> Result<Self, DeserializeError> {
662 let x = v.get("x")
663 .and_then(|v| v.as_float())
664 .ok_or_else(|| DeserializeError::MissingKey("x".into()))? as f32;
665 let y = v.get("y")
666 .and_then(|v| v.as_float())
667 .ok_or_else(|| DeserializeError::MissingKey("y".into()))? as f32;
668 Ok(Vec2::new(x, y))
669 }
670}
671
672impl Serialize for Vec3 {
675 fn serialize(&self) -> SerializedValue {
676 let mut m = HashMap::new();
677 m.insert("x".to_string(), SerializedValue::Float(self.x as f64));
678 m.insert("y".to_string(), SerializedValue::Float(self.y as f64));
679 m.insert("z".to_string(), SerializedValue::Float(self.z as f64));
680 SerializedValue::Map(m)
681 }
682}
683
684impl Deserialize for Vec3 {
685 fn deserialize(v: &SerializedValue) -> Result<Self, DeserializeError> {
686 let x = v.get("x").and_then(|v| v.as_float())
687 .ok_or_else(|| DeserializeError::MissingKey("x".into()))? as f32;
688 let y = v.get("y").and_then(|v| v.as_float())
689 .ok_or_else(|| DeserializeError::MissingKey("y".into()))? as f32;
690 let z = v.get("z").and_then(|v| v.as_float())
691 .ok_or_else(|| DeserializeError::MissingKey("z".into()))? as f32;
692 Ok(Vec3::new(x, y, z))
693 }
694}
695
696type SerializeFn = Box<dyn Fn(*const u8) -> SerializedValue + Send + Sync>;
701type DeserializeFn = Box<dyn Fn(&SerializedValue) -> Box<dyn Any + Send + Sync> + Send + Sync>;
702
703struct ComponentEntry {
704 type_id: TypeId,
705 name: String,
706 serialize: SerializeFn,
707 deserialize: DeserializeFn,
708}
709
710pub struct ComponentSerializer {
714 by_name: HashMap<String, usize>,
715 by_type: HashMap<TypeId, usize>,
716 entries: Vec<ComponentEntry>,
717}
718
719impl ComponentSerializer {
720 pub fn new() -> Self {
721 Self {
722 by_name: HashMap::new(),
723 by_type: HashMap::new(),
724 entries: Vec::new(),
725 }
726 }
727
728 pub fn register<T: Serialize + Deserialize + Any + Send + Sync + 'static>(
730 &mut self,
731 name: impl Into<String>,
732 ) {
733 let name = name.into();
734 let type_id = TypeId::of::<T>();
735 let idx = self.entries.len();
736 self.by_name.insert(name.clone(), idx);
737 self.by_type.insert(type_id, idx);
738 self.entries.push(ComponentEntry {
739 type_id,
740 name,
741 serialize: Box::new(|ptr| {
742 let reference = unsafe { &*(ptr as *const T) };
744 reference.serialize()
745 }),
746 deserialize: Box::new(|v| {
747 match T::deserialize(v) {
748 Ok(t) => Box::new(t) as Box<dyn Any + Send + Sync>,
749 Err(_) => Box::new(()) as Box<dyn Any + Send + Sync>,
750 }
751 }),
752 });
753 }
754
755 pub unsafe fn serialize_any(&self, type_id: TypeId, ptr: *const u8) -> Option<SerializedValue> {
760 let idx = self.by_type.get(&type_id)?;
761 Some((self.entries[*idx].serialize)(ptr))
762 }
763
764 pub fn deserialize_any(&self, name: &str, v: &SerializedValue) -> Option<Box<dyn Any + Send + Sync>> {
766 let idx = self.by_name.get(name)?;
767 Some((self.entries[*idx].deserialize)(v))
768 }
769
770 pub fn has_name(&self, name: &str) -> bool {
772 self.by_name.contains_key(name)
773 }
774
775 pub fn registered_names(&self) -> impl Iterator<Item = &str> {
777 self.by_name.keys().map(String::as_str)
778 }
779
780 pub fn len(&self) -> usize {
782 self.entries.len()
783 }
784}
785
786impl Default for ComponentSerializer {
787 fn default() -> Self {
788 Self::new()
789 }
790}
791
792#[cfg(test)]
797mod tests {
798 use super::*;
799
800 #[test]
801 fn serialize_primitives() {
802 assert_eq!(true.serialize(), SerializedValue::Bool(true));
803 assert_eq!(42i64.serialize(), SerializedValue::Int(42));
804 assert_eq!(3.14f64.serialize(), SerializedValue::Float(3.14));
805 assert_eq!("hello".serialize(), SerializedValue::Str("hello".into()));
806 }
807
808 #[test]
809 fn deserialize_primitives() {
810 assert_eq!(bool::deserialize(&SerializedValue::Bool(false)).unwrap(), false);
811 assert_eq!(i64::deserialize(&SerializedValue::Int(7)).unwrap(), 7);
812 assert_eq!(f64::deserialize(&SerializedValue::Float(1.5)).unwrap(), 1.5);
813 assert_eq!(String::deserialize(&SerializedValue::Str("hi".into())).unwrap(), "hi");
814 }
815
816 #[test]
817 fn serialize_vec2_roundtrip() {
818 let v = Vec2::new(1.0, 2.5);
819 let sv = v.serialize();
820 let v2 = Vec2::deserialize(&sv).unwrap();
821 assert!((v.x - v2.x).abs() < 1e-5);
822 assert!((v.y - v2.y).abs() < 1e-5);
823 }
824
825 #[test]
826 fn serialize_vec3_roundtrip() {
827 let v = Vec3::new(1.0, 2.0, 3.0);
828 let sv = v.serialize();
829 let v2 = Vec3::deserialize(&sv).unwrap();
830 assert!((v - v2).length() < 1e-5);
831 }
832
833 #[test]
834 fn serialize_vec_of_ints() {
835 let v: Vec<i64> = vec![10, 20, 30];
836 let sv = v.serialize();
837 let v2: Vec<i64> = Vec::deserialize(&sv).unwrap();
838 assert_eq!(v, v2);
839 }
840
841 #[test]
842 fn serialize_option_some_none() {
843 let some: Option<i64> = Some(99);
844 let none: Option<i64> = None;
845 assert_eq!(some.serialize(), SerializedValue::Int(99));
846 assert_eq!(none.serialize(), SerializedValue::Null);
847 assert_eq!(Option::<i64>::deserialize(&SerializedValue::Null).unwrap(), None);
848 assert_eq!(Option::<i64>::deserialize(&SerializedValue::Int(5)).unwrap(), Some(5));
849 }
850
851 #[test]
852 fn json_roundtrip_simple() {
853 let original = SerializedValue::Map({
854 let mut m = HashMap::new();
855 m.insert("name".into(), SerializedValue::Str("Alice".into()));
856 m.insert("score".into(), SerializedValue::Int(1000));
857 m.insert("alive".into(), SerializedValue::Bool(true));
858 m
859 });
860 let json = original.to_json_string();
861 let parsed = SerializedValue::from_json_str(&json).unwrap();
862 assert_eq!(parsed.get("name").and_then(|v| v.as_str()), Some("Alice"));
863 assert_eq!(parsed.get("score").and_then(|v| v.as_int()), Some(1000));
864 assert_eq!(parsed.get("alive").and_then(|v| v.as_bool()), Some(true));
865 }
866
867 #[test]
868 fn json_roundtrip_nested() {
869 let sv = SerializedValue::List(vec![
870 SerializedValue::Int(1),
871 SerializedValue::Float(2.5),
872 SerializedValue::Null,
873 SerializedValue::Bool(true),
874 ]);
875 let json = sv.to_json_string();
876 let parsed = SerializedValue::from_json_str(&json).unwrap();
877 assert_eq!(parsed.index(0).and_then(|v| v.as_int()), Some(1));
878 assert_eq!(parsed.index(2).map(|v| v.is_null()), Some(true));
879 }
880
881 #[test]
882 fn json_string_escape() {
883 let sv = SerializedValue::Str("say \"hello\"\nnewline".into());
884 let json = sv.to_json_string();
885 let parsed = SerializedValue::from_json_str(&json).unwrap();
886 assert_eq!(parsed.as_str(), Some("say \"hello\"\nnewline"));
887 }
888
889 #[test]
890 fn component_serializer_register_and_use() {
891 let mut cs = ComponentSerializer::new();
892 cs.register::<i64>("health");
893 assert!(cs.has_name("health"));
894 assert_eq!(cs.len(), 1);
895
896 let sv = SerializedValue::Int(100);
897 let boxed = cs.deserialize_any("health", &sv).unwrap();
898 let val = boxed.downcast_ref::<i64>().unwrap();
899 assert_eq!(*val, 100);
900 }
901
902 #[test]
903 fn wrong_type_error() {
904 let sv = SerializedValue::Str("not a bool".into());
905 let err = bool::deserialize(&sv).unwrap_err();
906 assert!(matches!(err, DeserializeError::WrongType { .. }));
907 }
908}