1pub use rg3d_core_derive::Visit;
12
13pub mod prelude {
14 pub use super::{Visit, VisitError, VisitResult, Visitor};
16}
17
18use crate::{
19 algebra::{
20 Complex, Matrix2, Matrix3, Matrix4, Quaternion, UnitComplex, UnitQuaternion, Vector2,
21 Vector3, Vector4,
22 },
23 io::{self, FileLoadError},
24 pool::{Handle, Pool},
25 replace_slashes,
26};
27
28use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
29use fxhash::FxHashMap;
30use std::collections::HashMap;
31use std::{
32 any::Any,
33 cell::{Cell, RefCell},
34 collections::hash_map::Entry,
35 fmt::{Display, Formatter},
36 fs::File,
37 hash::Hash,
38 io::{BufWriter, Cursor, Read, Write},
39 ops::{DerefMut, Range},
40 path::{Path, PathBuf},
41 rc::Rc,
42 string::FromUtf8Error,
43 sync::{Arc, Mutex, RwLock},
44};
45use uuid::Uuid;
46
47pub enum FieldKind {
48 Bool(bool),
49 U8(u8),
50 I8(i8),
51 U16(u16),
52 I16(i16),
53 U32(u32),
54 I32(i32),
55 U64(u64),
56 I64(i64),
57 F32(f32),
58 F64(f64),
59 Vector3(Vector3<f32>),
60 UnitQuaternion(UnitQuaternion<f32>),
61 Matrix4(Matrix4<f32>),
62 Data(Vec<u8>),
63 Matrix3(Matrix3<f32>),
64 Vector2(Vector2<f32>),
65 Vector4(Vector4<f32>),
66 Uuid(Uuid),
67 UnitComplex(UnitComplex<f32>),
68 PodArray {
69 type_id: u8,
70 element_size: u32,
71 bytes: Vec<u8>,
72 },
73 Matrix2(Matrix2<f32>),
74}
75
76pub trait Pod: Copy {
77 fn type_id() -> u8;
78}
79
80impl Pod for u8 {
81 fn type_id() -> u8 {
82 0
83 }
84}
85
86impl Pod for i8 {
87 fn type_id() -> u8 {
88 1
89 }
90}
91
92impl Pod for u16 {
93 fn type_id() -> u8 {
94 2
95 }
96}
97
98impl Pod for i16 {
99 fn type_id() -> u8 {
100 3
101 }
102}
103
104impl Pod for u32 {
105 fn type_id() -> u8 {
106 4
107 }
108}
109
110impl Pod for i32 {
111 fn type_id() -> u8 {
112 5
113 }
114}
115
116impl Pod for u64 {
117 fn type_id() -> u8 {
118 6
119 }
120}
121
122impl Pod for i64 {
123 fn type_id() -> u8 {
124 7
125 }
126}
127
128impl Pod for f32 {
129 fn type_id() -> u8 {
130 8
131 }
132}
133
134impl Pod for f64 {
135 fn type_id() -> u8 {
136 9
137 }
138}
139
140pub struct PodVecView<'a, T: Pod> {
141 type_id: u8,
142 vec: &'a mut Vec<T>,
143}
144
145impl<'a, T: Pod> PodVecView<'a, T> {
146 pub fn from_pod_vec(vec: &'a mut Vec<T>) -> Self {
147 Self {
148 type_id: T::type_id(),
149 vec,
150 }
151 }
152}
153
154impl<'a, T: Pod> Visit for PodVecView<'a, T> {
155 fn visit(&mut self, name: &str, visitor: &mut Visitor) -> VisitResult {
156 if visitor.reading {
157 if let Some(field) = visitor.find_field(name) {
158 match &field.kind {
159 FieldKind::PodArray {
160 type_id,
161 element_size,
162 bytes,
163 } => {
164 if *type_id == self.type_id {
165 let mut owned_bytes = bytes.clone();
166 let len = owned_bytes.len() / (*element_size as usize);
167 *self.vec = unsafe {
168 Vec::from_raw_parts(owned_bytes.as_mut_ptr() as *mut T, len, len)
169 };
170 std::mem::forget(owned_bytes);
171 Ok(())
172 } else {
173 Err(VisitError::TypeMismatch)
174 }
175 }
176 _ => Err(VisitError::FieldTypeDoesNotMatch),
177 }
178 } else {
179 Err(VisitError::FieldDoesNotExist(name.to_owned()))
180 }
181 } else if visitor.find_field(name).is_some() {
182 Err(VisitError::FieldAlreadyExists(name.to_owned()))
183 } else {
184 let node = visitor.current_node();
185 node.fields.push(Field::new(
186 name,
187 FieldKind::PodArray {
188 type_id: T::type_id(),
189 element_size: std::mem::size_of::<T>() as u32,
190 bytes: unsafe {
191 let mut data = self.vec.clone();
192 let bytes = Vec::from_raw_parts(
193 data.as_mut_ptr() as *mut u8,
194 data.len() * std::mem::size_of::<T>(),
195 data.capacity() * std::mem::size_of::<T>(),
196 );
197 std::mem::forget(data);
198 bytes
199 },
200 },
201 ));
202 Ok(())
203 }
204 }
205}
206
207impl FieldKind {
208 fn as_string(&self) -> String {
209 match self {
210 Self::Bool(data) => format!("<bool = {}>, ", data),
211 Self::U8(data) => format!("<u8 = {}>, ", data),
212 Self::I8(data) => format!("<i8 = {}>, ", data),
213 Self::U16(data) => format!("<u16 = {}>, ", data),
214 Self::I16(data) => format!("<i16 = {}>, ", data),
215 Self::U32(data) => format!("<u32 = {}>, ", data),
216 Self::I32(data) => format!("<i32 = {}>, ", data),
217 Self::U64(data) => format!("<u64 = {}>, ", data),
218 Self::I64(data) => format!("<i64 = {}>, ", data),
219 Self::F32(data) => format!("<f32 = {}>, ", data),
220 Self::F64(data) => format!("<f64 = {}>, ", data),
221 Self::Vector3(data) => format!("<vec3 = {}; {}; {}>, ", data.x, data.y, data.z),
222 Self::UnitQuaternion(data) => {
223 format!("<quat = {}; {}; {}; {}>, ", data.i, data.j, data.k, data.w)
224 }
225 Self::Matrix4(data) => {
226 let mut out = String::from("<mat4 = ");
227 for f in data.iter() {
228 out += format!("{}; ", f).as_str();
229 }
230 out
231 }
232 Self::Data(data) => {
233 let out = match String::from_utf8(data.clone()) {
234 Ok(s) => s,
235 Err(_) => base64::encode(data),
236 };
237 format!("<data = {}>, ", out)
238 }
239 Self::Matrix3(data) => {
240 let mut out = String::from("<mat3 = ");
241 for f in data.iter() {
242 out += format!("{}; ", f).as_str();
243 }
244 out
245 }
246 Self::Vector2(data) => format!("<vec2 = {}; {}>, ", data.x, data.y),
247 Self::Vector4(data) => {
248 format!("<vec4 = {}; {}; {}; {}>, ", data.x, data.y, data.z, data.w)
249 }
250 Self::Uuid(uuid) => uuid.to_string(),
251 Self::UnitComplex(data) => {
252 format!("<complex = {}; {}>, ", data.re, data.im)
253 }
254 FieldKind::PodArray {
255 type_id,
256 element_size,
257 bytes,
258 } => {
259 let base64_encoded = base64::encode(bytes);
260 format!(
261 "<podarray = {}; {}; [{}]>",
262 type_id, element_size, base64_encoded
263 )
264 }
265 Self::Matrix2(data) => {
266 let mut out = String::from("<mat2 = ");
267 for f in data.iter() {
268 out += format!("{}; ", f).as_str();
269 }
270 out
271 }
272 }
273 }
274}
275
276macro_rules! impl_field_data {
277 ($type_name:ty, $($kind:tt)*) => {
278 impl Visit for $type_name {
279 fn visit(&mut self, name: &str, visitor: &mut Visitor) -> VisitResult {
280 if visitor.reading {
281 if let Some(field) = visitor.find_field(name) {
282 match field.kind {
283 $($kind)*(data) => {
284 *self = data.clone();
285 Ok(())
286 },
287 _ => Err(VisitError::FieldTypeDoesNotMatch)
288 }
289 } else {
290 Err(VisitError::FieldDoesNotExist(name.to_owned()))
291 }
292 } else if visitor.find_field(name).is_some() {
293 Err(VisitError::FieldAlreadyExists(name.to_owned()))
294 } else {
295 let node = visitor.current_node();
296 node.fields.push(Field::new(name, $($kind)*(self.clone())));
297 Ok(())
298 }
299 }
300 }
301 };
302}
303
304pub struct Data<'a> {
307 vec: &'a mut Vec<u8>,
308}
309
310impl_field_data!(u64, FieldKind::U64);
311impl_field_data!(i64, FieldKind::I64);
312impl_field_data!(u32, FieldKind::U32);
313impl_field_data!(i32, FieldKind::I32);
314impl_field_data!(u16, FieldKind::U16);
315impl_field_data!(i16, FieldKind::I16);
316impl_field_data!(u8, FieldKind::U8);
317impl_field_data!(i8, FieldKind::I8);
318impl_field_data!(f32, FieldKind::F32);
319impl_field_data!(f64, FieldKind::F64);
320impl_field_data!(Vector3<f32>, FieldKind::Vector3);
321impl_field_data!(UnitQuaternion<f32>, FieldKind::UnitQuaternion);
322impl_field_data!(Matrix4<f32>, FieldKind::Matrix4);
323impl_field_data!(bool, FieldKind::Bool);
324impl_field_data!(Matrix3<f32>, FieldKind::Matrix3);
325impl_field_data!(Vector2<f32>, FieldKind::Vector2);
326impl_field_data!(Vector4<f32>, FieldKind::Vector4);
327impl_field_data!(Uuid, FieldKind::Uuid);
328impl_field_data!(UnitComplex<f32>, FieldKind::UnitComplex);
329impl_field_data!(Matrix2<f32>, FieldKind::Matrix2);
330
331impl<'a> Visit for Data<'a> {
332 fn visit(&mut self, name: &str, visitor: &mut Visitor) -> VisitResult {
333 if visitor.reading {
334 if let Some(field) = visitor.find_field(name) {
335 match &field.kind {
336 FieldKind::Data(data) => {
337 *self.vec = data.clone();
338 Ok(())
339 }
340 _ => Err(VisitError::FieldTypeDoesNotMatch),
341 }
342 } else {
343 Err(VisitError::FieldDoesNotExist(name.to_owned()))
344 }
345 } else if visitor.find_field(name).is_some() {
346 Err(VisitError::FieldAlreadyExists(name.to_owned()))
347 } else {
348 let node = visitor.current_node();
349 node.fields
350 .push(Field::new(name, FieldKind::Data(self.vec.clone())));
351 Ok(())
352 }
353 }
354}
355
356pub struct Field {
357 name: String,
358 kind: FieldKind,
359}
360
361#[derive(Debug)]
362pub enum VisitError {
363 Io(std::io::Error),
364 UnknownFieldType(u8),
365 FieldDoesNotExist(String),
366 FieldAlreadyExists(String),
367 RegionAlreadyExists(String),
368 InvalidCurrentNode,
369 FieldTypeDoesNotMatch,
370 RegionDoesNotExist(String),
371 NoActiveNode,
372 NotSupportedFormat,
373 InvalidName,
374 TypeMismatch,
375 RefCellAlreadyMutableBorrowed,
376 User(String),
377 UnexpectedRcNullIndex,
378 PoisonedMutex,
379 FileLoadError(FileLoadError),
380}
381
382impl Display for VisitError {
383 fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
384 match self {
385 Self::Io(io) => write!(f, "io error: {}", io),
386 Self::UnknownFieldType(type_index) => write!(f, "unknown field type {}", type_index),
387 Self::FieldDoesNotExist(name) => write!(f, "field does not exists {}", name),
388 Self::FieldAlreadyExists(name) => write!(f, "field already exists {}", name),
389 Self::RegionAlreadyExists(name) => write!(f, "region already exists {}", name),
390 Self::InvalidCurrentNode => write!(f, "invalid current node"),
391 Self::FieldTypeDoesNotMatch => write!(f, "field type does not match"),
392 Self::RegionDoesNotExist(name) => write!(f, "region does not exists {}", name),
393 Self::NoActiveNode => write!(f, "no active node"),
394 Self::NotSupportedFormat => write!(f, "not supported format"),
395 Self::InvalidName => write!(f, "invalid name"),
396 Self::TypeMismatch => write!(f, "type mismatch"),
397 Self::RefCellAlreadyMutableBorrowed => write!(f, "ref cell already mutable borrowed"),
398 Self::User(msg) => write!(f, "user defined error: {}", msg),
399 Self::UnexpectedRcNullIndex => write!(f, "unexpected rc null index"),
400 Self::PoisonedMutex => write!(f, "attempt to lock poisoned mutex"),
401 Self::FileLoadError(e) => write!(f, "file load error: {:?}", e),
402 }
403 }
404}
405
406impl<'a, T> From<std::sync::PoisonError<std::sync::MutexGuard<'a, T>>> for VisitError {
407 fn from(_: std::sync::PoisonError<std::sync::MutexGuard<'a, T>>) -> Self {
408 Self::PoisonedMutex
409 }
410}
411
412impl<'a, T> From<std::sync::PoisonError<&mut T>> for VisitError {
413 fn from(_: std::sync::PoisonError<&mut T>) -> Self {
414 Self::PoisonedMutex
415 }
416}
417
418impl<'a, T> From<std::sync::PoisonError<std::sync::RwLockWriteGuard<'_, T>>> for VisitError {
419 fn from(_: std::sync::PoisonError<std::sync::RwLockWriteGuard<'_, T>>) -> Self {
420 Self::PoisonedMutex
421 }
422}
423
424impl From<std::io::Error> for VisitError {
425 fn from(io_err: std::io::Error) -> Self {
426 Self::Io(io_err)
427 }
428}
429
430impl From<FromUtf8Error> for VisitError {
431 fn from(_: FromUtf8Error) -> Self {
432 Self::InvalidName
433 }
434}
435
436impl From<String> for VisitError {
437 fn from(s: String) -> Self {
438 Self::User(s)
439 }
440}
441
442impl From<FileLoadError> for VisitError {
443 fn from(e: FileLoadError) -> Self {
444 Self::FileLoadError(e)
445 }
446}
447
448pub type VisitResult = Result<(), VisitError>;
449
450impl Field {
451 pub fn new(name: &str, kind: FieldKind) -> Self {
452 Self {
453 name: name.to_owned(),
454 kind,
455 }
456 }
457
458 fn save(field: &Field, file: &mut dyn Write) -> VisitResult {
459 let name = field.name.as_bytes();
460 file.write_u32::<LittleEndian>(name.len() as u32)?;
461 file.write_all(name)?;
462 match &field.kind {
463 FieldKind::U8(data) => {
464 file.write_u8(1)?;
465 file.write_u8(*data)?;
466 }
467 FieldKind::I8(data) => {
468 file.write_i8(2)?;
469 file.write_i8(*data)?;
470 }
471 FieldKind::U16(data) => {
472 file.write_u8(3)?;
473 file.write_u16::<LittleEndian>(*data)?;
474 }
475 FieldKind::I16(data) => {
476 file.write_u8(4)?;
477 file.write_i16::<LittleEndian>(*data)?;
478 }
479 FieldKind::U32(data) => {
480 file.write_u8(5)?;
481 file.write_u32::<LittleEndian>(*data)?;
482 }
483 FieldKind::I32(data) => {
484 file.write_u8(6)?;
485 file.write_i32::<LittleEndian>(*data)?;
486 }
487 FieldKind::U64(data) => {
488 file.write_u8(7)?;
489 file.write_u64::<LittleEndian>(*data)?;
490 }
491 FieldKind::I64(data) => {
492 file.write_u8(8)?;
493 file.write_i64::<LittleEndian>(*data)?;
494 }
495 FieldKind::F32(data) => {
496 file.write_u8(9)?;
497 file.write_f32::<LittleEndian>(*data)?;
498 }
499 FieldKind::F64(data) => {
500 file.write_u8(10)?;
501 file.write_f64::<LittleEndian>(*data)?;
502 }
503 FieldKind::Vector3(data) => {
504 file.write_u8(11)?;
505 file.write_f32::<LittleEndian>(data.x)?;
506 file.write_f32::<LittleEndian>(data.y)?;
507 file.write_f32::<LittleEndian>(data.z)?;
508 }
509 FieldKind::UnitQuaternion(data) => {
510 file.write_u8(12)?;
511 file.write_f32::<LittleEndian>(data.i)?;
512 file.write_f32::<LittleEndian>(data.j)?;
513 file.write_f32::<LittleEndian>(data.k)?;
514 file.write_f32::<LittleEndian>(data.w)?;
515 }
516 FieldKind::Matrix4(data) => {
517 file.write_u8(13)?;
518 for f in data.iter() {
519 file.write_f32::<LittleEndian>(*f)?;
520 }
521 }
522 FieldKind::Data(data) => {
523 file.write_u8(14)?;
524 file.write_u32::<LittleEndian>(data.len() as u32)?;
525 file.write_all(data.as_slice())?;
526 }
527 FieldKind::Bool(data) => {
528 file.write_u8(15)?;
529 file.write_u8(if *data { 1 } else { 0 })?;
530 }
531 FieldKind::Matrix3(data) => {
532 file.write_u8(16)?;
533 for f in data.iter() {
534 file.write_f32::<LittleEndian>(*f)?;
535 }
536 }
537 FieldKind::Vector2(data) => {
538 file.write_u8(17)?;
539 file.write_f32::<LittleEndian>(data.x)?;
540 file.write_f32::<LittleEndian>(data.y)?;
541 }
542 FieldKind::Vector4(data) => {
543 file.write_u8(18)?;
544 file.write_f32::<LittleEndian>(data.x)?;
545 file.write_f32::<LittleEndian>(data.y)?;
546 file.write_f32::<LittleEndian>(data.z)?;
547 file.write_f32::<LittleEndian>(data.w)?;
548 }
549 FieldKind::Uuid(uuid) => {
550 file.write_u8(19)?;
551 file.write_all(uuid.as_bytes())?;
552 }
553 FieldKind::UnitComplex(c) => {
554 file.write_u8(20)?;
555 file.write_f32::<LittleEndian>(c.re)?;
556 file.write_f32::<LittleEndian>(c.im)?;
557 }
558 FieldKind::PodArray {
559 type_id,
560 element_size,
561 bytes,
562 } => {
563 file.write_u8(21)?;
564 file.write_u8(*type_id)?;
565 file.write_u32::<LittleEndian>(*element_size)?;
566 file.write_u64::<LittleEndian>(bytes.len() as u64)?;
567 file.write_all(bytes)?;
568 }
569 FieldKind::Matrix2(data) => {
570 file.write_u8(22)?;
571 for f in data.iter() {
572 file.write_f32::<LittleEndian>(*f)?;
573 }
574 }
575 }
576 Ok(())
577 }
578
579 fn load(file: &mut dyn Read) -> Result<Field, VisitError> {
580 let name_len = file.read_u32::<LittleEndian>()? as usize;
581 let mut raw_name = vec![Default::default(); name_len];
582 file.read_exact(raw_name.as_mut_slice())?;
583 let id = file.read_u8()?;
584 Ok(Field::new(
585 String::from_utf8(raw_name)?.as_str(),
586 match id {
587 1 => FieldKind::U8(file.read_u8()?),
588 2 => FieldKind::I8(file.read_i8()?),
589 3 => FieldKind::U16(file.read_u16::<LittleEndian>()?),
590 4 => FieldKind::I16(file.read_i16::<LittleEndian>()?),
591 5 => FieldKind::U32(file.read_u32::<LittleEndian>()?),
592 6 => FieldKind::I32(file.read_i32::<LittleEndian>()?),
593 7 => FieldKind::U64(file.read_u64::<LittleEndian>()?),
594 8 => FieldKind::I64(file.read_i64::<LittleEndian>()?),
595 9 => FieldKind::F32(file.read_f32::<LittleEndian>()?),
596 10 => FieldKind::F64(file.read_f64::<LittleEndian>()?),
597 11 => FieldKind::Vector3({
598 let x = file.read_f32::<LittleEndian>()?;
599 let y = file.read_f32::<LittleEndian>()?;
600 let z = file.read_f32::<LittleEndian>()?;
601 Vector3::new(x, y, z)
602 }),
603 12 => FieldKind::UnitQuaternion({
604 let x = file.read_f32::<LittleEndian>()?;
605 let y = file.read_f32::<LittleEndian>()?;
606 let z = file.read_f32::<LittleEndian>()?;
607 let w = file.read_f32::<LittleEndian>()?;
608 UnitQuaternion::new_normalize(Quaternion::new(w, x, y, z))
609 }),
610 13 => FieldKind::Matrix4({
611 let mut f = [0.0f32; 16];
612 for n in &mut f {
613 *n = file.read_f32::<LittleEndian>()?;
614 }
615 Matrix4::from_row_slice(&f)
616 }),
617 14 => FieldKind::Data({
618 let len = file.read_u32::<LittleEndian>()? as usize;
619 let mut vec = vec![Default::default(); len];
620 file.read_exact(vec.as_mut_slice())?;
621 vec
622 }),
623 15 => FieldKind::Bool(file.read_u8()? != 0),
624 16 => FieldKind::Matrix3({
625 let mut f = [0.0f32; 9];
626 for n in &mut f {
627 *n = file.read_f32::<LittleEndian>()?;
628 }
629 Matrix3::from_row_slice(&f)
630 }),
631 17 => FieldKind::Vector2({
632 let x = file.read_f32::<LittleEndian>()?;
633 let y = file.read_f32::<LittleEndian>()?;
634 Vector2::new(x, y)
635 }),
636 18 => FieldKind::Vector4({
637 let x = file.read_f32::<LittleEndian>()?;
638 let y = file.read_f32::<LittleEndian>()?;
639 let z = file.read_f32::<LittleEndian>()?;
640 let w = file.read_f32::<LittleEndian>()?;
641 Vector4::new(x, y, z, w)
642 }),
643 19 => FieldKind::Uuid({
644 let mut bytes = uuid::Bytes::default();
645 file.read_exact(&mut bytes)?;
646 Uuid::from_bytes(bytes)
647 }),
648 20 => FieldKind::UnitComplex({
649 let re = file.read_f32::<LittleEndian>()?;
650 let im = file.read_f32::<LittleEndian>()?;
651 UnitComplex::from_complex(Complex::new(re, im))
652 }),
653 21 => {
654 let type_id = file.read_u8()?;
655 let element_size = file.read_u32::<LittleEndian>()?;
656 let data_size = file.read_u64::<LittleEndian>()?;
657 let mut bytes = vec![0; data_size as usize];
658 file.read_exact(&mut bytes)?;
659 FieldKind::PodArray {
660 type_id,
661 element_size,
662 bytes,
663 }
664 }
665 22 => FieldKind::Matrix2({
666 let mut f = [0.0f32; 3];
667 for n in &mut f {
668 *n = file.read_f32::<LittleEndian>()?;
669 }
670 Matrix2::from_row_slice(&f)
671 }),
672 _ => return Err(VisitError::UnknownFieldType(id)),
673 },
674 ))
675 }
676
677 fn as_string(&self) -> String {
678 format!("{}{}", self.name, self.kind.as_string())
679 }
680}
681
682pub struct Node {
683 name: String,
684 fields: Vec<Field>,
685 parent: Handle<Node>,
686 children: Vec<Handle<Node>>,
687}
688
689impl Node {
690 fn new(name: &str, parent: Handle<Node>) -> Self {
691 Self {
692 name: name.to_owned(),
693 fields: Vec::new(),
694 parent,
695 children: Vec::new(),
696 }
697 }
698}
699
700impl Default for Node {
701 fn default() -> Self {
702 Self {
703 name: String::new(),
704 fields: Vec::new(),
705 parent: Handle::NONE,
706 children: Vec::new(),
707 }
708 }
709}
710
711pub struct Visitor {
712 nodes: Pool<Node>,
713 rc_map: FxHashMap<u64, Rc<dyn Any>>,
714 arc_map: FxHashMap<u64, Arc<dyn Any + Send + Sync>>,
715 reading: bool,
716 current_node: Handle<Node>,
717 root: Handle<Node>,
718}
719
720pub trait Visit {
721 fn visit(&mut self, name: &str, visitor: &mut Visitor) -> VisitResult;
722}
723
724impl Default for Visitor {
725 fn default() -> Self {
726 Self::new()
727 }
728}
729
730impl Visitor {
731 const MAGIC: &'static str = "RG3D";
732
733 pub fn new() -> Self {
734 let mut nodes = Pool::new();
735 let root = nodes.spawn(Node::new("__ROOT__", Handle::NONE));
736 Self {
737 nodes,
738 rc_map: FxHashMap::default(),
739 arc_map: FxHashMap::default(),
740 reading: false,
741 current_node: root,
742 root,
743 }
744 }
745
746 fn find_field(&mut self, name: &str) -> Option<&mut Field> {
747 let node = self.nodes.borrow_mut(self.current_node);
748 for field in node.fields.iter_mut() {
749 if field.name == name {
750 return Some(field);
751 }
752 }
753 None
754 }
755
756 pub fn is_reading(&self) -> bool {
757 self.reading
758 }
759
760 fn current_node(&mut self) -> &mut Node {
761 self.nodes.borrow_mut(self.current_node)
762 }
763
764 pub fn enter_region(&mut self, name: &str) -> VisitResult {
765 let node = self.nodes.borrow(self.current_node);
766 if self.reading {
767 let mut region = Handle::NONE;
768 for child_handle in node.children.iter() {
769 let child = self.nodes.borrow(*child_handle);
770 if child.name == name {
771 region = *child_handle;
772 break;
773 }
774 }
775 if region.is_some() {
776 self.current_node = region;
777 Ok(())
778 } else {
779 Err(VisitError::RegionDoesNotExist(name.to_owned()))
780 }
781 } else {
782 for child_handle in node.children.iter() {
784 let child = self.nodes.borrow(*child_handle);
785 if child.name == name {
786 return Err(VisitError::RegionAlreadyExists(name.to_owned()));
787 }
788 }
789
790 let node_handle = self.nodes.spawn(Node::new(name, self.current_node));
791 self.nodes
792 .borrow_mut(self.current_node)
793 .children
794 .push(node_handle);
795 self.current_node = node_handle;
796
797 Ok(())
798 }
799 }
800
801 pub fn leave_region(&mut self) -> VisitResult {
802 self.current_node = self.nodes.borrow(self.current_node).parent;
803 if self.current_node.is_none() {
804 Err(VisitError::NoActiveNode)
805 } else {
806 Ok(())
807 }
808 }
809
810 fn print_node(&self, node_handle: Handle<Node>, nesting: usize, out_string: &mut String) {
811 let offset = (0..nesting).map(|_| "\t").collect::<String>();
812 let node = self.nodes.borrow(node_handle);
813 *out_string += format!(
814 "{}{}[Fields={}, Children={}]: ",
815 offset,
816 node.name,
817 node.fields.len(),
818 node.children.len()
819 )
820 .as_str();
821 for field in node.fields.iter() {
822 *out_string += field.as_string().as_str();
823 }
824
825 *out_string += "\n";
826
827 for child_handle in node.children.iter() {
828 self.print_node(*child_handle, nesting + 1, out_string);
829 }
830 }
831
832 pub fn save_text(&self) -> String {
833 let mut out_string = String::new();
834 self.print_node(self.root, 0, &mut out_string);
835 out_string
836 }
837
838 pub fn save_binary<P: AsRef<Path>>(&self, path: P) -> VisitResult {
839 let mut writer = BufWriter::new(File::create(path)?);
840 writer.write_all(Self::MAGIC.as_bytes())?;
841 let mut stack = vec![self.root];
842 while let Some(node_handle) = stack.pop() {
843 let node = self.nodes.borrow(node_handle);
844 let name = node.name.as_bytes();
845 writer.write_u32::<LittleEndian>(name.len() as u32)?;
846 writer.write_all(name)?;
847
848 writer.write_u32::<LittleEndian>(node.fields.len() as u32)?;
849 for field in node.fields.iter() {
850 Field::save(field, &mut writer)?
851 }
852
853 writer.write_u32::<LittleEndian>(node.children.len() as u32)?;
854 stack.extend_from_slice(&node.children);
855 }
856 Ok(())
857 }
858
859 fn load_node_binary(&mut self, file: &mut dyn Read) -> Result<Handle<Node>, VisitError> {
860 let name_len = file.read_u32::<LittleEndian>()? as usize;
861 let mut raw_name = vec![Default::default(); name_len];
862 file.read_exact(raw_name.as_mut_slice())?;
863
864 let mut node = Node {
865 name: String::from_utf8(raw_name)?,
866 ..Node::default()
867 };
868
869 let field_count = file.read_u32::<LittleEndian>()? as usize;
870 for _ in 0..field_count {
871 let field = Field::load(file)?;
872 node.fields.push(field);
873 }
874
875 let mut children = Vec::new();
876 let child_count = file.read_u32::<LittleEndian>()? as usize;
877 for _ in 0..child_count {
878 children.push(self.load_node_binary(file)?);
879 }
880
881 node.children = children.clone();
882
883 let handle = self.nodes.spawn(node);
884 for child_handle in children.iter() {
885 let child = self.nodes.borrow_mut(*child_handle);
886 child.parent = handle;
887 }
888
889 Ok(handle)
890 }
891
892 pub async fn load_binary<P: AsRef<Path>>(path: P) -> Result<Self, VisitError> {
893 let mut reader = Cursor::new(io::load_file(path).await?);
894 let mut magic: [u8; 4] = Default::default();
895 reader.read_exact(&mut magic)?;
896 if !magic.eq(Self::MAGIC.as_bytes()) {
897 return Err(VisitError::NotSupportedFormat);
898 }
899 let mut visitor = Self {
900 nodes: Pool::new(),
901 rc_map: Default::default(),
902 arc_map: Default::default(),
903 reading: true,
904 current_node: Handle::NONE,
905 root: Handle::NONE,
906 };
907 visitor.root = visitor.load_node_binary(&mut reader)?;
908 visitor.current_node = visitor.root;
909 Ok(visitor)
910 }
911}
912
913impl<T> Visit for RefCell<T>
914where
915 T: Visit + 'static,
916{
917 fn visit(&mut self, name: &str, visitor: &mut Visitor) -> VisitResult {
918 if let Ok(mut data) = self.try_borrow_mut() {
919 data.visit(name, visitor)
920 } else {
921 Err(VisitError::RefCellAlreadyMutableBorrowed)
922 }
923 }
924}
925
926impl<T> Visit for Vec<T>
927where
928 T: Default + Visit + 'static,
929{
930 fn visit(&mut self, name: &str, visitor: &mut Visitor) -> VisitResult {
931 visitor.enter_region(name)?;
932
933 let mut len = self.len() as u32;
934 len.visit("Length", visitor)?;
935
936 if visitor.reading {
937 for index in 0..len {
938 let region_name = format!("Item{}", index);
939 visitor.enter_region(region_name.as_str())?;
940 let mut object = T::default();
941 object.visit("ItemData", visitor)?;
942 self.push(object);
943 visitor.leave_region()?;
944 }
945 } else {
946 for (index, item) in self.iter_mut().enumerate() {
947 let region_name = format!("Item{}", index);
948 visitor.enter_region(region_name.as_str())?;
949 item.visit("ItemData", visitor)?;
950 visitor.leave_region()?;
951 }
952 }
953 visitor.leave_region()?;
954 Ok(())
955 }
956}
957
958impl<T> Visit for Option<T>
959where
960 T: Default + Visit + 'static,
961{
962 fn visit(&mut self, name: &str, visitor: &mut Visitor) -> VisitResult {
963 visitor.enter_region(name)?;
964
965 let mut is_some = if self.is_some() { 1u8 } else { 0u8 };
966 is_some.visit("IsSome", visitor)?;
967
968 if is_some != 0 {
969 if visitor.reading {
970 let mut value = T::default();
971 value.visit("Data", visitor)?;
972 *self = Some(value);
973 } else {
974 self.as_mut().unwrap().visit("Data", visitor)?;
975 }
976 }
977
978 visitor.leave_region()?;
979 Ok(())
980 }
981}
982
983impl Visit for String {
984 fn visit(&mut self, name: &str, visitor: &mut Visitor) -> VisitResult {
985 visitor.enter_region(name)?;
986
987 let mut len = self.as_bytes().len() as u32;
988 len.visit("Length", visitor)?;
989
990 let mut data = if visitor.reading {
991 Vec::new()
992 } else {
993 Vec::from(self.as_bytes())
994 };
995
996 let mut proxy = Data { vec: &mut data };
997 proxy.visit("Data", visitor)?;
998
999 if visitor.reading {
1000 *self = String::from_utf8(data)?;
1001 }
1002 visitor.leave_region()
1003 }
1004}
1005
1006impl Visit for PathBuf {
1007 fn visit(&mut self, name: &str, visitor: &mut Visitor) -> VisitResult {
1008 visitor.enter_region(name)?;
1009
1010 let portable_path = replace_slashes(&self);
1013
1014 let bytes = if let Some(path_str) = portable_path.as_os_str().to_str() {
1015 path_str.as_bytes()
1016 } else {
1017 return Err(VisitError::InvalidName);
1018 };
1019
1020 let mut len = bytes.len() as u32;
1021 len.visit("Length", visitor)?;
1022
1023 let mut data = if visitor.reading {
1024 Vec::new()
1025 } else {
1026 Vec::from(bytes)
1027 };
1028
1029 let mut proxy = Data { vec: &mut data };
1030 proxy.visit("Data", visitor)?;
1031
1032 if visitor.reading {
1033 *self = PathBuf::from(String::from_utf8(data)?);
1034 }
1035
1036 visitor.leave_region()
1037 }
1038}
1039
1040impl<T> Visit for Cell<T>
1041where
1042 T: Copy + Clone + Visit + 'static,
1043{
1044 fn visit(&mut self, name: &str, visitor: &mut Visitor) -> VisitResult {
1045 let mut value = self.get();
1046 value.visit(name, visitor)?;
1047 if visitor.is_reading() {
1048 self.set(value);
1049 }
1050 Ok(())
1051 }
1052}
1053
1054impl<T> Visit for Rc<T>
1055where
1056 T: Visit + 'static,
1057{
1058 fn visit(&mut self, name: &str, visitor: &mut Visitor) -> VisitResult {
1059 visitor.enter_region(name)?;
1060
1061 if visitor.reading {
1062 let mut raw = 0u64;
1063 raw.visit("Id", visitor)?;
1064 if raw == 0 {
1065 return Err(VisitError::UnexpectedRcNullIndex);
1066 }
1067 if let Some(ptr) = visitor.rc_map.get(&raw) {
1068 if let Ok(res) = Rc::downcast::<T>(ptr.clone()) {
1069 *self = res;
1070 } else {
1071 return Err(VisitError::TypeMismatch);
1072 }
1073 } else {
1074 visitor.rc_map.insert(raw as u64, self.clone());
1076
1077 let raw = rc_to_raw(self);
1078 unsafe { &mut *raw }.visit("RcData", visitor)?;
1079 }
1080 } else {
1081 let raw = rc_to_raw(self);
1083
1084 let mut index = raw as u64;
1086 index.visit("Id", visitor)?;
1087
1088 if let Entry::Vacant(entry) = visitor.rc_map.entry(index) {
1089 entry.insert(self.clone());
1090 unsafe { &mut *raw }.visit("RcData", visitor)?;
1091 }
1092 }
1093
1094 visitor.leave_region()?;
1095
1096 Ok(())
1097 }
1098}
1099
1100impl<T> Visit for Mutex<T>
1101where
1102 T: Visit + Send,
1103{
1104 fn visit(&mut self, name: &str, visitor: &mut Visitor) -> VisitResult {
1105 self.get_mut()?.visit(name, visitor)
1106 }
1107}
1108
1109impl<T> Visit for parking_lot::Mutex<T>
1110where
1111 T: Visit + Send,
1112{
1113 fn visit(&mut self, name: &str, visitor: &mut Visitor) -> VisitResult {
1114 self.get_mut().visit(name, visitor)
1115 }
1116}
1117
1118impl<T> Visit for Box<T>
1119where
1120 T: Visit,
1121{
1122 fn visit(&mut self, name: &str, visitor: &mut Visitor) -> VisitResult {
1123 self.deref_mut().visit(name, visitor)
1124 }
1125}
1126
1127impl<T> Visit for RwLock<T>
1128where
1129 T: Visit + Send,
1130{
1131 fn visit(&mut self, name: &str, visitor: &mut Visitor) -> VisitResult {
1132 self.write()?.visit(name, visitor)
1133 }
1134}
1135
1136fn arc_to_raw<T>(arc: &Arc<T>) -> *mut T {
1137 &**arc as *const T as *mut T
1138}
1139
1140fn rc_to_raw<T>(rc: &Rc<T>) -> *mut T {
1141 &**rc as *const T as *mut T
1142}
1143
1144impl<T> Visit for Arc<T>
1145where
1146 T: Visit + Send + Sync + 'static,
1147{
1148 fn visit(&mut self, name: &str, visitor: &mut Visitor) -> VisitResult {
1149 visitor.enter_region(name)?;
1150
1151 if visitor.reading {
1152 let mut raw = 0u64;
1153 raw.visit("Id", visitor)?;
1154 if raw == 0 {
1155 return Err(VisitError::UnexpectedRcNullIndex);
1156 }
1157 if let Some(ptr) = visitor.arc_map.get(&raw) {
1158 if let Ok(res) = Arc::downcast::<T>(ptr.clone()) {
1159 *self = res;
1160 } else {
1161 return Err(VisitError::TypeMismatch);
1162 }
1163 } else {
1164 visitor.arc_map.insert(raw as u64, self.clone());
1166
1167 let raw = arc_to_raw(self);
1168 unsafe { &mut *raw }.visit("ArcData", visitor)?;
1169 }
1170 } else {
1171 let raw = arc_to_raw(self);
1173
1174 let mut index = raw as u64;
1176 index.visit("Id", visitor)?;
1177
1178 if let Entry::Vacant(entry) = visitor.arc_map.entry(index) {
1179 entry.insert(self.clone());
1180 unsafe { &mut *raw }.visit("ArcData", visitor)?;
1181 }
1182 }
1183
1184 visitor.leave_region()?;
1185
1186 Ok(())
1187 }
1188}
1189
1190impl<T> Visit for std::rc::Weak<T>
1191where
1192 T: Default + Visit + 'static,
1193{
1194 fn visit(&mut self, name: &str, visitor: &mut Visitor) -> VisitResult {
1195 visitor.enter_region(name)?;
1196
1197 if visitor.reading {
1198 let mut raw = 0u64;
1199 raw.visit("Id", visitor)?;
1200
1201 if raw != 0 {
1202 if let Some(ptr) = visitor.rc_map.get(&raw) {
1203 if let Ok(res) = Rc::downcast::<T>(ptr.clone()) {
1204 *self = Rc::downgrade(&res);
1205 } else {
1206 return Err(VisitError::TypeMismatch);
1207 }
1208 } else {
1209 let rc = Rc::new(T::default());
1211 visitor.rc_map.insert(raw as u64, rc.clone());
1212
1213 let raw = rc_to_raw(&rc);
1214 unsafe { &mut *raw }.visit("RcData", visitor)?;
1215
1216 *self = Rc::downgrade(&rc);
1217 }
1218 }
1219 } else if let Some(rc) = std::rc::Weak::upgrade(self) {
1220 let raw = rc_to_raw(&rc);
1222
1223 let mut index = raw as u64;
1225 index.visit("Id", visitor)?;
1226
1227 if let Entry::Vacant(entry) = visitor.rc_map.entry(index) {
1228 entry.insert(rc);
1229 unsafe { &mut *raw }.visit("RcData", visitor)?;
1230 }
1231 } else {
1232 let mut index = 0u64;
1233 index.visit("Id", visitor)?;
1234 }
1235
1236 visitor.leave_region()?;
1237
1238 Ok(())
1239 }
1240}
1241
1242impl<T> Visit for std::sync::Weak<T>
1243where
1244 T: Default + Visit + Send + Sync + 'static,
1245{
1246 fn visit(&mut self, name: &str, visitor: &mut Visitor) -> VisitResult {
1247 visitor.enter_region(name)?;
1248
1249 if visitor.reading {
1250 let mut raw = 0u64;
1251 raw.visit("Id", visitor)?;
1252
1253 if raw != 0 {
1254 if let Some(ptr) = visitor.arc_map.get(&raw) {
1255 if let Ok(res) = Arc::downcast::<T>(ptr.clone()) {
1256 *self = Arc::downgrade(&res);
1257 } else {
1258 return Err(VisitError::TypeMismatch);
1259 }
1260 } else {
1261 let arc = Arc::new(T::default());
1263 visitor.arc_map.insert(raw as u64, arc.clone());
1264
1265 let raw = arc_to_raw(&arc);
1266 unsafe { &mut *raw }.visit("ArcData", visitor)?;
1267
1268 *self = Arc::downgrade(&arc);
1269 }
1270 }
1271 } else if let Some(arc) = std::sync::Weak::upgrade(self) {
1272 let raw = arc_to_raw(&arc);
1274
1275 let mut index = raw as u64;
1277 index.visit("Id", visitor)?;
1278
1279 if let Entry::Vacant(entry) = visitor.arc_map.entry(index) {
1280 entry.insert(arc);
1281 unsafe { &mut *raw }.visit("ArcData", visitor)?;
1282 }
1283 } else {
1284 let mut index = 0u64;
1285 index.visit("Id", visitor)?;
1286 }
1287
1288 visitor.leave_region()?;
1289
1290 Ok(())
1291 }
1292}
1293
1294impl<K, V> Visit for FxHashMap<K, V>
1295where
1296 K: Visit + Default + Clone + Hash + Eq,
1297 V: Visit + Default,
1298{
1299 fn visit(&mut self, name: &str, visitor: &mut Visitor) -> VisitResult {
1300 visitor.enter_region(name)?;
1301
1302 let mut count = self.len() as u32;
1303 count.visit("Count", visitor)?;
1304
1305 if visitor.is_reading() {
1306 for i in 0..(count as usize) {
1307 let name = format!("Item{}", i);
1308
1309 visitor.enter_region(name.as_str())?;
1310
1311 let mut key = K::default();
1312 key.visit("Key", visitor)?;
1313
1314 let mut value = V::default();
1315 value.visit("Value", visitor)?;
1316
1317 self.insert(key, value);
1318
1319 visitor.leave_region()?;
1320 }
1321 } else {
1322 for (i, (key, value)) in self.iter_mut().enumerate() {
1323 let name = format!("Item{}", i);
1324
1325 visitor.enter_region(name.as_str())?;
1326
1327 let mut key = key.clone();
1328 key.visit("Key", visitor)?;
1329
1330 value.visit("Value", visitor)?;
1331
1332 visitor.leave_region()?;
1333 }
1334 }
1335
1336 visitor.leave_region()
1337 }
1338}
1339
1340impl<K, V> Visit for HashMap<K, V>
1341where
1342 K: Visit + Default + Clone + Hash + Eq,
1343 V: Visit + Default,
1344{
1345 fn visit(&mut self, name: &str, visitor: &mut Visitor) -> VisitResult {
1346 visitor.enter_region(name)?;
1347
1348 let mut count = self.len() as u32;
1349 count.visit("Count", visitor)?;
1350
1351 if visitor.is_reading() {
1352 for i in 0..(count as usize) {
1353 let name = format!("Item{}", i);
1354
1355 visitor.enter_region(name.as_str())?;
1356
1357 let mut key = K::default();
1358 key.visit("Key", visitor)?;
1359
1360 let mut value = V::default();
1361 value.visit("Value", visitor)?;
1362
1363 self.insert(key, value);
1364
1365 visitor.leave_region()?;
1366 }
1367 } else {
1368 for (i, (key, value)) in self.iter_mut().enumerate() {
1369 let name = format!("Item{}", i);
1370
1371 visitor.enter_region(name.as_str())?;
1372
1373 let mut key = key.clone();
1374 key.visit("Key", visitor)?;
1375
1376 value.visit("Value", visitor)?;
1377
1378 visitor.leave_region()?;
1379 }
1380 }
1381
1382 visitor.leave_region()
1383 }
1384}
1385
1386impl<T: Default + Visit, const SIZE: usize> Visit for [T; SIZE] {
1387 fn visit(&mut self, name: &str, visitor: &mut Visitor) -> VisitResult {
1388 visitor.enter_region(name)?;
1389
1390 let mut len = SIZE as u32;
1391 len.visit("Length", visitor)?;
1392
1393 if visitor.reading {
1394 if len > SIZE as u32 {
1395 return VisitResult::Err(VisitError::User(format!(
1396 "Not enough space in static array, got {}, needed {}!",
1397 len, SIZE
1398 )));
1399 }
1400
1401 for index in 0..len {
1402 let region_name = format!("Item{}", index);
1403 visitor.enter_region(region_name.as_str())?;
1404 let mut object = T::default();
1405 object.visit("ItemData", visitor)?;
1406 self[index as usize] = object;
1407 visitor.leave_region()?;
1408 }
1409 } else {
1410 for (index, item) in self.iter_mut().enumerate() {
1411 let region_name = format!("Item{}", index);
1412 visitor.enter_region(region_name.as_str())?;
1413 item.visit("ItemData", visitor)?;
1414 visitor.leave_region()?;
1415 }
1416 }
1417
1418 visitor.leave_region()
1419 }
1420}
1421
1422impl<T: Visit> Visit for Range<T> {
1423 fn visit(&mut self, name: &str, visitor: &mut Visitor) -> VisitResult {
1424 visitor.enter_region(name)?;
1425
1426 self.start.visit("Start", visitor)?;
1427 self.end.visit("End", visitor)?;
1428
1429 visitor.leave_region()
1430 }
1431}
1432
1433#[cfg(test)]
1434mod test {
1435 use crate::visitor::{Data, Visit, VisitError, VisitResult, Visitor};
1436 use std::{fs::File, io::Write, path::Path, rc::Rc};
1437
1438 pub struct Model {
1439 data: u64,
1440 }
1441
1442 pub struct Texture {
1443 data: Vec<u8>,
1444 }
1445
1446 impl Visit for Texture {
1447 fn visit(&mut self, name: &str, visitor: &mut Visitor) -> VisitResult {
1448 visitor.enter_region(name)?;
1449 let mut proxy = Data {
1450 vec: &mut self.data,
1451 };
1452 proxy.visit("Data", visitor)?;
1453 visitor.leave_region()
1454 }
1455 }
1456
1457 impl Visit for Model {
1458 fn visit(&mut self, name: &str, visitor: &mut Visitor) -> VisitResult {
1459 visitor.enter_region(name)?;
1460 self.data.visit("Data", visitor)?;
1461 visitor.leave_region()
1462 }
1463 }
1464
1465 impl Visit for ResourceKind {
1466 fn visit(&mut self, name: &str, visitor: &mut Visitor) -> VisitResult {
1467 match self {
1468 ResourceKind::Unknown => Err(VisitError::User("invalid resource type".to_string())),
1469 ResourceKind::Texture(tex) => tex.visit(name, visitor),
1470 ResourceKind::Model(model) => model.visit(name, visitor),
1471 }
1472 }
1473 }
1474
1475 #[allow(dead_code)]
1476 pub enum ResourceKind {
1477 Unknown,
1478 Model(Model),
1479 Texture(Texture),
1480 }
1481
1482 struct Resource {
1483 kind: ResourceKind,
1484 data: u16,
1485 }
1486
1487 impl Resource {
1488 fn new(kind: ResourceKind) -> Self {
1489 Self { kind, data: 0 }
1490 }
1491 }
1492
1493 impl Default for Resource {
1494 fn default() -> Self {
1495 Self {
1496 kind: ResourceKind::Unknown,
1497 data: 0,
1498 }
1499 }
1500 }
1501
1502 impl Visit for Resource {
1503 fn visit(&mut self, name: &str, visitor: &mut Visitor) -> VisitResult {
1504 visitor.enter_region(name)?;
1505 if visitor.reading {
1506 } else {
1507 let mut kind_id: u8 = match &self.kind {
1508 ResourceKind::Unknown => {
1509 return Err(VisitError::User("Invalid resource!".to_string()))
1510 }
1511 ResourceKind::Model(_) => 0,
1512 ResourceKind::Texture(_) => 1,
1513 };
1514 kind_id.visit("KindId", visitor)?;
1515 self.kind.visit("KindData", visitor)?;
1516 }
1517 self.data.visit("ResData", visitor)?;
1518 visitor.leave_region()
1519 }
1520 }
1521
1522 #[derive(Default)]
1523 struct Foo {
1524 bar: u64,
1525 shared_resource: Option<Rc<Resource>>,
1526 }
1527
1528 impl Foo {
1529 fn new(resource: Rc<Resource>) -> Self {
1530 Self {
1531 bar: 123,
1532 shared_resource: Some(resource),
1533 }
1534 }
1535 }
1536
1537 impl Visit for Foo {
1538 fn visit(&mut self, name: &str, visitor: &mut Visitor) -> VisitResult {
1539 visitor.enter_region(name)?;
1540 self.bar.visit("Bar", visitor)?;
1541 self.shared_resource.visit("SharedResource", visitor)?;
1542 visitor.leave_region()
1543 }
1544 }
1545
1546 #[test]
1547 fn visitor_test() {
1548 let path = Path::new("test.bin");
1549
1550 {
1552 let mut visitor = Visitor::new();
1553 let mut resource = Rc::new(Resource::new(ResourceKind::Model(Model { data: 555 })));
1554 resource.visit("SharedResource", &mut visitor).unwrap();
1555
1556 let mut objects = vec![Foo::new(resource.clone()), Foo::new(resource)];
1557
1558 objects.visit("Objects", &mut visitor).unwrap();
1559
1560 visitor.save_binary(path).unwrap();
1561 if let Ok(mut file) = File::create(Path::new("test.txt")) {
1562 file.write_all(visitor.save_text().as_bytes()).unwrap();
1563 }
1564 }
1565
1566 {
1568 let mut visitor = futures::executor::block_on(Visitor::load_binary(path)).unwrap();
1569 let mut resource: Rc<Resource> = Rc::new(Default::default());
1570 resource.visit("SharedResource", &mut visitor).unwrap();
1571
1572 let mut objects: Vec<Foo> = Vec::new();
1573 objects.visit("Objects", &mut visitor).unwrap();
1574 }
1575 }
1576}