Skip to main content

fyrox_core/visitor/
mod.rs

1// Copyright (c) 2019-present Dmitry Stepanov and Fyrox Engine contributors.
2//
3// Permission is hereby granted, free of charge, to any person obtaining a copy
4// of this software and associated documentation files (the "Software"), to deal
5// in the Software without restriction, including without limitation the rights
6// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7// copies of the Software, and to permit persons to whom the Software is
8// furnished to do so, subject to the following conditions:
9//
10// The above copyright notice and this permission notice shall be included in all
11// copies or substantial portions of the Software.
12//
13// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19// SOFTWARE.
20
21//! Visitor is a tree-based serializer/deserializer with intermediate representation for stored data.
22//! When data is serialized, it will be transformed into an intermediate representation and only then
23//! will be dumped onto the disk. Deserialization is the same: the data (binary or text) is read
24//! and converted into an intermediate representation (IR). End users can use this IR to save or load
25//! their structures of pretty much any complexity.
26//!
27//! # Overview
28//!
29//! Visitor uses a tree to create structured data storage. Basic unit is a *node* - it is a container
30//! for data fields. Each node has a name, handle to parent, set of handles to children nodes and a
31//! container for data fields. Data field is a pair of a name and a value, the value can be any of
32//! simple Rust types and some of the trivially copyable data structures (vectors, matrices, etc.).
33//! The main criteria of what could be the field and what not is the ability to be represented as
34//! a set of bytes.
35//!
36//! See [`Visitor`] docs for more info.
37
38#![warn(missing_docs)]
39
40pub mod blackboard;
41pub mod error;
42pub mod field;
43mod impls;
44pub mod pod;
45mod reader;
46mod writer;
47
48pub use fyrox_core_derive::Visit;
49
50pub mod prelude {
51    //! Types to use `#[derive(Visit)]`
52    pub use super::{Visit, VisitResult, Visitor};
53    pub use crate::visitor::error::VisitError;
54}
55
56use crate::pool::PoolError;
57use crate::{
58    array_as_u8_slice_mut,
59    io::{self},
60    pool::{Handle, Pool},
61    visitor::{
62        reader::{ascii::AsciiReader, binary::BinaryReader, Reader},
63        writer::{ascii::AsciiWriter, binary::BinaryWriter, Writer},
64    },
65};
66use bitflags::bitflags;
67use blackboard::Blackboard;
68use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
69use error::VisitError;
70use field::{Field, FieldKind};
71use fxhash::FxHashMap;
72use std::{
73    any::Any,
74    fmt::{Debug, Formatter},
75    fs::File,
76    hash::Hash,
77    io::{BufWriter, Cursor, Read, Write},
78    ops::{Deref, DerefMut},
79    path::Path,
80    rc::Rc,
81    sync::Arc,
82};
83
84/// Version of the visitor.
85#[repr(u32)]
86pub enum VisitorVersion {
87    /// The first stable release of Fyrox 1.0.
88    FirstStableRelease,
89
90    /// ^^ Add a new version above this line ^^.
91    ///
92    /// There are few major rules:
93    ///
94    /// 1) New version name should be something like `VectorFlattening`, and clearly describe the
95    /// changes introduced by the new version. Always add a doc comment that contains a clear
96    /// description of what was changed.
97    /// 2) Do **NOT** add explicit number value for a new version. The compiler will do that for you,
98    /// and there will be no chance of mistake. `Legacy` variant is an exception.
99    /// 3) Existing version entries must **NOT** be deleted or moved.
100    /// 4) `Last` variant must always be the last.
101    Last,
102}
103
104/// Current version number of the visitor.
105pub const CURRENT_VERSION: u32 = (VisitorVersion::Last as u32).saturating_sub(1);
106
107/// Proxy struct for plain data. It is used to serialize arrays of trivially copyable data (`Vec<u8>`)
108/// directly as a large chunk of data. For example, an attempt to serialize `Vec<u8>` serialize each
109/// byte as a separate node which is very inefficient.
110///
111/// BinaryBlob stores data very much like [`crate::visitor::pod::PodVecView`] except that BinaryBlob
112/// has less type safety. In practice, it is used with `T` = `u8` for Strings and Paths. However,
113/// it accepts any type T that is Copy, and it lacks the type_id system that PodVecView has for
114/// checking that the data it is reading comes from the expected type.
115pub struct BinaryBlob<'a, T>
116where
117    T: Copy,
118{
119    /// A reference to a vector that represents a binary blob.
120    pub vec: &'a mut Vec<T>,
121}
122
123impl<T> Visit for BinaryBlob<'_, T>
124where
125    T: Copy + bytemuck::Pod,
126{
127    fn visit(&mut self, name: &str, visitor: &mut Visitor) -> VisitResult {
128        if visitor.reading {
129            if let Some(field) = visitor.find_field(name) {
130                match &field.kind {
131                    FieldKind::BinaryBlob(data) => {
132                        let len = data.len() / size_of::<T>();
133                        let mut vec = Vec::<T>::with_capacity(len);
134
135                        unsafe {
136                            std::ptr::copy_nonoverlapping(
137                                data.as_ptr(),
138                                array_as_u8_slice_mut(&mut vec).as_mut_ptr(),
139                                data.len(),
140                            );
141
142                            vec.set_len(len);
143                        }
144
145                        *self.vec = vec;
146
147                        Ok(())
148                    }
149                    _ => Err(VisitError::FieldTypeDoesNotMatch {
150                        expected: stringify!(FieldKind::BinaryBlob),
151                        actual: format!("{:?}", field.kind),
152                    }),
153                }
154            } else {
155                Err(VisitError::field_does_not_exist(name, visitor))
156            }
157        } else if visitor.find_field(name).is_some() {
158            Err(VisitError::FieldAlreadyExists(name.to_owned()))
159        } else {
160            let node = visitor.current_node();
161
162            let len_bytes = self.vec.len() * std::mem::size_of::<T>();
163            let mut bytes = Vec::<u8>::with_capacity(len_bytes);
164            bytes.extend_from_slice(unsafe {
165                std::slice::from_raw_parts(self.vec.as_ptr() as *const u8, len_bytes)
166            });
167
168            node.fields
169                .push(Field::new(name, FieldKind::BinaryBlob(bytes)));
170
171            Ok(())
172        }
173    }
174}
175
176/// The result of a [Visit::visit] or of a Visitor encoding operation such as [Visitor::save_binary_to_file].
177/// It has no value unless an error occurred.
178pub type VisitResult = Result<(), VisitError>;
179
180trait VisitableElementaryField {
181    fn write(&self, file: &mut dyn Write) -> VisitResult;
182    fn read(&mut self, file: &mut dyn Read) -> VisitResult;
183}
184
185macro_rules! impl_visitable_elementary_field {
186    ($ty:ty, $write:ident, $read:ident $(, $endian:ident)*) => {
187        impl VisitableElementaryField for $ty {
188            fn write(&self, file: &mut dyn Write) -> VisitResult {
189                file.$write::<$($endian)*>(*self)?;
190                Ok(())
191            }
192
193            fn read(&mut self, file: &mut dyn Read) -> VisitResult {
194                *self = file.$read::<$($endian)*>()?;
195                Ok(())
196            }
197        }
198    };
199}
200impl_visitable_elementary_field!(f64, write_f64, read_f64, LittleEndian);
201impl_visitable_elementary_field!(f32, write_f32, read_f32, LittleEndian);
202impl_visitable_elementary_field!(u8, write_u8, read_u8);
203impl_visitable_elementary_field!(i8, write_i8, read_i8);
204impl_visitable_elementary_field!(u16, write_u16, read_u16, LittleEndian);
205impl_visitable_elementary_field!(i16, write_i16, read_i16, LittleEndian);
206impl_visitable_elementary_field!(u32, write_u32, read_u32, LittleEndian);
207impl_visitable_elementary_field!(i32, write_i32, read_i32, LittleEndian);
208impl_visitable_elementary_field!(u64, write_u64, read_u64, LittleEndian);
209impl_visitable_elementary_field!(i64, write_i64, read_i64, LittleEndian);
210
211/// A node is a collection of [Fields](Field) that exists within a tree of nodes that allows a
212/// [Visitor] to store its data. Each node has a name, and may have a parent node and child nodes.
213/// A node is used when visiting complex data, that cannot be represented by a simple memory block.
214#[derive(Debug)]
215pub struct VisitorNode {
216    name: String,
217    fields: Vec<Field>,
218    parent: Handle<VisitorNode>,
219    children: Vec<Handle<VisitorNode>>,
220}
221
222impl VisitorNode {
223    fn new(name: &str, parent: Handle<VisitorNode>) -> Self {
224        Self {
225            name: name.to_owned(),
226            fields: Vec::new(),
227            parent,
228            children: Vec::new(),
229        }
230    }
231}
232
233impl Default for VisitorNode {
234    fn default() -> Self {
235        Self {
236            name: String::new(),
237            fields: Vec::new(),
238            parent: Handle::NONE,
239            children: Vec::new(),
240        }
241    }
242}
243
244/// A RegionGuard is a [Visitor] wrapper that automatically leaves the current region when it is
245/// dropped.
246#[must_use = "the guard must be used"]
247pub struct RegionGuard<'a>(&'a mut Visitor);
248
249impl Deref for RegionGuard<'_> {
250    type Target = Visitor;
251
252    fn deref(&self) -> &Self::Target {
253        self.0
254    }
255}
256
257impl DerefMut for RegionGuard<'_> {
258    fn deref_mut(&mut self) -> &mut Self::Target {
259        self.0
260    }
261}
262
263impl Drop for RegionGuard<'_> {
264    fn drop(&mut self) {
265        // If we acquired RegionGuard instance, then it is safe to assert that
266        // `leave_region` was successful.
267        self.0.leave_region().unwrap();
268    }
269}
270
271bitflags! {
272    /// Flags that can be used to influence the behavior of [Visit::visit] methods.
273    #[derive(Debug)]
274    pub struct VisitorFlags: u32 {
275        /// No flags set, do nothing special.
276        const NONE = 0;
277        /// Tell [crate::variable::InheritableVariable::visit] to assume that it's
278        /// [VariableFlags::MODIFIED](create::variable::VariableFlags::MODIFIED) is set,
279        /// and therefore write its data. Otherwise, InheritableVariable has the special
280        /// property of *not writing itself* when the `MODIFIED` flag is not set.
281        const SERIALIZE_EVERYTHING = 1 << 1;
282    }
283}
284
285/// Visitor is a tree-based serializer/deserializer with intermediate representation for stored data.
286/// When data is serialized, it will be transformed into an intermediate representation and only then
287/// will be dumped onto the disk. Deserialization is the same: the data (binary or text) is read
288/// and converted into an intermediate representation (IR). End users can use this IR to save or load
289/// their structures of pretty much any complexity.
290///
291/// # Overview
292///
293/// Visitor uses a tree to create structured data storage. Basic unit is a *node* - it is a container
294/// for data fields. Each node has a name, handle to parent, set of handles to children nodes and a
295/// container for data fields. Data field is a pair of a name and a value, the value can be any of
296/// simple Rust types and some of the trivially copyable data structures (vectors, matrices, etc.).
297/// The main criteria of what could be the field and what not is the ability to be represented as
298/// a set of bytes.
299///
300/// Instead of calling visitor methods to read or write the visitor's data, reading and writing
301/// happen in the [Visit::visit] method of a variable that will either store the read value
302/// or holds the value to be written.
303///
304/// For example, `x.visit("MyValue", &mut visitor)` will do one of:
305///
306/// 1. Take the value of `x` and store it in `visitor` under the name "MyValue", if `visitor.is_reading()` is false.
307/// 2. Read a value named "MyValue" from `visitor` and store it in `x`, if `visitor.is_reading()` is true.
308///
309/// Whether the value of `x` gets written into `visitor` or overwritten with a value from `visitor` is determined
310/// by whether [Visitor::is_reading()] returns true or false.
311pub struct Visitor {
312    /// The nodes that make up this visitors tree.
313    nodes: Pool<VisitorNode>,
314    /// The id for the next `Rc` or `Arc` that the visitor encounters.
315    unique_id_counter: u64,
316    /// The name of the type of the `Rc` or `Arc` associated with each id.
317    /// This allows type mismatch errors to include type information.
318    type_name_map: FxHashMap<u64, &'static str>,
319    /// The `Rc` value associated with each id, to allow the visitor to find the `Rc` when reading.
320    rc_map: FxHashMap<u64, Rc<dyn Any>>,
321    /// The `Arc` value associated with each id, to allow the visitor to find the `Arc` when reading.
322    arc_map: FxHashMap<u64, Arc<dyn Any + Send + Sync>>,
323    /// True if this visitor is being read from, during loading.
324    /// False if this visitor is being written to, during saving.
325    reading: bool,
326    /// The handle of the node that is currently being written to or read from.
327    current_node: Handle<VisitorNode>,
328    /// The handle of the start of the tree.
329    root: Handle<VisitorNode>,
330    /// The version number of the visitor. See [`VisitorVersion`].
331    version: u32,
332    /// A place to store whatever objects may be needed to help with reading and writing values.
333    pub blackboard: Blackboard,
334    /// Flags that can activate special behavior in some Visit values, such as
335    /// [crate::variable::InheritableVariable].
336    pub flags: VisitorFlags,
337}
338
339impl Debug for Visitor {
340    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
341        let mut output = f.debug_struct("Visitor");
342
343        output.field("flags", &self.flags);
344
345        for (i, node) in self.nodes.iter().enumerate() {
346            output.field(&format!("node{i}"), node);
347        }
348
349        output.finish()
350    }
351}
352
353/// Trait of types that can be read from a [Visitor] or written to a Visitor.
354///
355/// ## Code Generation
356///
357/// Procedural macro could be used to generate trivial implementations for this trait, which covers
358/// 99% of the cases. Consider the following example:
359///
360/// ```rust
361/// use fyrox_core::visitor::prelude::*;
362///
363/// #[derive(Visit, Default)]
364/// struct MyType {
365///     field_a: u32,
366///     field_b: String
367/// }
368/// ```
369///
370/// The generated code will be something like this:
371///
372/// ```rust
373/// use fyrox_core::visitor::prelude::*;
374///
375/// struct MyType {
376///     field_a: u32,
377///     field_b: String
378/// }
379///
380/// impl Visit for MyType {
381///     fn visit(&mut self, name: &str, visitor: &mut Visitor) -> VisitResult {
382///         let mut region = visitor.enter_region(name)?;
383///
384///         self.field_a.visit("FieldA", &mut region)?;
385///         self.field_b.visit("FieldB", &mut region)?;
386///
387///         Ok(())
388///     }
389/// }
390/// ```
391///
392/// ### Type Attributes
393///
394/// - `#[visit(optional)]` - marks all the fields of the type as optional and suppresses any errors
395/// on serialization and deserialization. In the generated code, all the fields will be visited like
396/// this `let _ = self.field_a.visit("FieldA", &mut region);`
397/// - `#[visit(pre_visit_method = "function_name")]` - name of a function, that will be called
398/// before the generated body.
399/// - `#[visit(post_visit_method = "function_name")]` - name of a function, that will be called
400/// after the generated body.
401///
402/// ### Field Attributes
403///
404/// - `#[visit(skip)]` - disables serialization and deserialization of the field.
405/// - `#[visit(rename = "new_name")]` - overrides the name of the field with `new_name`. In the
406/// generated code, all the fields will be visited like this `self.field_a.visit("new_name", &mut region)?;`
407/// - `#[visit(optional)]` - marks the field as optional and suppresses any errors on serialization
408/// and deserialization. In the generated code, all the fields will be visited like this
409/// `let _ = self.field_a.visit("FieldA", &mut region);`
410pub trait Visit {
411    /// Read or write this value, depending on whether [Visitor::is_reading()] is true or false.
412    ///
413    /// # In Write Mode
414    ///
415    /// The given name is a key to identify where this value will be stored in the visitor.
416    /// Whether this name indicates a field or a region is determined by the value being visited.
417    /// No two regions can exist with the same name as children of a single node,
418    /// and no two fields can exist with the same name within a single node,
419    /// but a region may share the same name as a field. If a name clash occurs, then an error
420    /// is returned. Otherwise the value is written into the Visitor data at the given name.
421    ///
422    /// # In Read Mode
423    ///
424    /// The given name is a key to identify where this value should be found the visitor.
425    /// Whether the name indicates a field or a region is determined by the the value being visited.
426    /// If the field or region is not found with the given name
427    /// then an error is returned. Otherwise the value being visited will be mutated
428    /// to match the data in the visitor.
429    ///
430    /// # Buiding a Complex Value out of Multiple Fields
431    ///
432    /// If representing this value requires more than one field,
433    /// [Visitor::enter_region] can be used to create a new node within the
434    /// visitor with the given name, and the fields of this value can then read from
435    /// or write to that node using the returned Visitor without risk of name
436    /// clashes.
437    ///
438    /// See the documentation for [the Visit derive macro](fyrox_core_derive::Visit) for examples of how to
439    /// implement Visit for some simple types.
440    ///
441    /// # Abnormal Implementations
442    ///
443    /// Types with special needs may choose to read and write in unusual ways. In addition to choosing
444    /// whether they will store their data in a region or a field, a value might choose to do neither.
445    /// A value may also choose to attempt to read its data in multiple ways so as to remain
446    /// backwards-compatible with older versions where the format of data storage may be different.
447    ///
448    /// See [crate::variable::InheritableVariable::visit] for an example of an abnormal implementation of Visit.
449    fn visit(&mut self, name: &str, visitor: &mut Visitor) -> VisitResult;
450}
451
452impl Default for Visitor {
453    fn default() -> Self {
454        Self::new()
455    }
456}
457
458/// Format of the data that be used by a [`Visitor`] instance for reading or writing from/to an
459/// external storage.
460#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
461#[must_use]
462pub enum Format {
463    /// The format is unknown and unsupported.
464    Unknown,
465    /// Binary format. The fastest and smallest, but changes cannot be merged by a version control
466    /// system, thus not suitable for collaborative work. It should be used primarily for production
467    /// builds.
468    Binary,
469    /// Slow and "fat" format, but changes can be merged by a version control system. It makes this
470    /// format ideal for collaborative work.
471    Ascii,
472}
473
474impl Visitor {
475    /// Sequence of bytes that is automatically written at the start when a visitor is encoded into
476    /// bytes. It is written by [Visitor::save_binary_to_file], [Visitor::save_binary_to_memory],
477    /// and [Visitor::save_binary_to_vec].
478    ///
479    /// [Visitor::load_binary_from_file] will return an error if this sequence of bytes is not present
480    /// at the beginning of the file, and [Visitor::load_binary_from_memory] will return an error of
481    /// these bytes are not at the beginning of the given slice.
482    pub const MAGIC_BINARY_CURRENT: &'static str = "FBAF";
483
484    /// Sequence of bytes that is automatically written at the start when a visitor is encoded into
485    /// ascii form. It is written by [Visitor::save_ascii_to_file], [Visitor::save_ascii_to_memory],
486    /// and [Visitor::save_ascii_to_string].
487    ///
488    /// [Visitor::load_ascii_from_file] will return an error if this sequence of bytes is not present
489    /// at the beginning of the file, and [Visitor::load_ascii_from_memory] will return an error of
490    /// these bytes are not at the beginning of the given slice.
491    pub const MAGIC_ASCII_CURRENT: &'static str = "FTAX";
492
493    /// Checks whether the given reader points to a supported file format or not.
494    #[must_use]
495    pub fn is_supported(src: &mut dyn Read) -> bool {
496        Self::detect_format(src) != Format::Unknown
497    }
498
499    /// Tries to extract the information about the file format in the given reader.
500    pub fn detect_format(src: &mut dyn Read) -> Format {
501        let mut magic: [u8; 4] = Default::default();
502        if src.read_exact(&mut magic).is_ok() {
503            if magic.eq(Visitor::MAGIC_BINARY_CURRENT.as_bytes()) {
504                return Format::Binary;
505            } else if magic.eq(Visitor::MAGIC_ASCII_CURRENT.as_bytes()) {
506                return Format::Ascii;
507            }
508        }
509        Format::Unknown
510    }
511
512    /// Tries to extract the information about the file format in the given slice.
513    pub fn detect_format_from_slice(data: &[u8]) -> Format {
514        let mut src = Cursor::new(data);
515        Self::detect_format(&mut src)
516    }
517
518    /// Creates a Visitor containing only a single node called "`__ROOT__`" which will be the
519    /// current region of the visitor.
520    pub fn new() -> Self {
521        let mut nodes = Pool::new();
522        let root = nodes.spawn(VisitorNode::new("__ROOT__", Handle::NONE));
523        Self {
524            nodes,
525            unique_id_counter: 1,
526            type_name_map: FxHashMap::default(),
527            rc_map: FxHashMap::default(),
528            arc_map: FxHashMap::default(),
529            reading: false,
530            current_node: root,
531            root,
532            version: CURRENT_VERSION,
533            blackboard: Blackboard::new(),
534            flags: VisitorFlags::NONE,
535        }
536    }
537
538    fn gen_unique_id(&mut self) -> u64 {
539        let id = self.unique_id_counter;
540        self.unique_id_counter += 1;
541        id
542    }
543
544    fn rc_id<T>(&mut self, rc: &Rc<T>) -> (u64, bool)
545    where
546        T: Any,
547    {
548        if let Some(id) = self.rc_map.iter().find_map(|(id, ptr)| {
549            if Rc::as_ptr(ptr) as *const T == Rc::as_ptr(rc) {
550                Some(*id)
551            } else {
552                None
553            }
554        }) {
555            (id, false)
556        } else {
557            let id = self.gen_unique_id();
558            self.type_name_map.insert(id, std::any::type_name::<T>());
559            self.rc_map.insert(id, rc.clone());
560            (id, true)
561        }
562    }
563
564    fn arc_id<T>(&mut self, arc: &Arc<T>) -> (u64, bool)
565    where
566        T: Any + Send + Sync,
567    {
568        if let Some(id) = self.arc_map.iter().find_map(|(id, ptr)| {
569            if Arc::as_ptr(ptr) as *const T == Arc::as_ptr(arc) {
570                Some(*id)
571            } else {
572                None
573            }
574        }) {
575            (id, false)
576        } else {
577            let id = self.gen_unique_id();
578            self.type_name_map.insert(id, std::any::type_name::<T>());
579            self.arc_map.insert(id, arc.clone());
580            (id, true)
581        }
582    }
583
584    /// Tries to find a field by its name.
585    pub fn find_field(&mut self, name: &str) -> Option<&mut Field> {
586        self.nodes
587            .borrow_mut(self.current_node)
588            .fields
589            .iter_mut()
590            .find(|field| field.name == name)
591    }
592
593    /// Tries to find a node by its name.
594    pub fn find_node(&self, name: &str) -> Option<&VisitorNode> {
595        self.nodes.iter().find(|n| n.name == name)
596    }
597
598    /// True if this Visitor is changing the values that it visits. In other words,
599    /// `x.visit("MyValue", &mut visitor)` will result in `x` being mutated to match whatever value
600    /// is stored in `visitor`.
601    ///
602    /// False if this visitor is copying and storing the values that it visits. In other words,
603    /// `x.visit("MyValue", &mut visitor)` will result in `x` being unchanged, but `visitor` will
604    /// be mutated to store the value of `x` under the name "MyValue".
605    pub fn is_reading(&self) -> bool {
606        self.reading
607    }
608
609    fn current_node(&mut self) -> &mut VisitorNode {
610        self.nodes.borrow_mut(self.current_node)
611    }
612
613    /// Returns version number of the visitor.
614    pub fn version(&self) -> u32 {
615        self.version
616    }
617
618    /// Returns true of a region with the given name exists as a child of the current node.
619    /// When reading, `has_region` returning true means that `enter_region` will succeed.
620    /// When writing, `has_region` returning true means that `enter_region` will fail.
621    pub fn has_region(&self, name: &str) -> bool {
622        let node = self.nodes.borrow(self.current_node);
623        node.children
624            .iter()
625            .any(|child| self.nodes.borrow(*child).name == name)
626    }
627
628    /// If [Visitor::is_reading], find a node with the given name that is a child of the current
629    /// node, and return a Visitor for the found node. Return an error if no node with that name exists.
630    ///
631    /// If not reading, create a node with the given name as a chld of the current node, and return
632    /// a visitor for the new node. Return an error if a node with  that name already exists.
633    pub fn enter_region(&mut self, name: &str) -> Result<RegionGuard, VisitError> {
634        let node = self.nodes.borrow(self.current_node);
635        if self.reading {
636            let mut region = Handle::NONE;
637            for child_handle in node.children.iter() {
638                let child = self.nodes.borrow(*child_handle);
639                if child.name == name {
640                    region = *child_handle;
641                    break;
642                }
643            }
644            if region.is_some() {
645                self.current_node = region;
646                Ok(RegionGuard(self))
647            } else {
648                Err(VisitError::RegionDoesNotExist(
649                    self.breadcrumbs() + " > " + name,
650                ))
651            }
652        } else {
653            // Make sure that node does not exist already.
654            for child_handle in node.children.iter() {
655                let child = self.nodes.borrow(*child_handle);
656                if child.name == name {
657                    return Err(VisitError::RegionAlreadyExists(name.to_owned()));
658                }
659            }
660
661            let node_handle = self.nodes.spawn(VisitorNode::new(name, self.current_node));
662            self.nodes
663                .borrow_mut(self.current_node)
664                .children
665                .push(node_handle);
666            self.current_node = node_handle;
667
668            Ok(RegionGuard(self))
669        }
670    }
671
672    /// Return a string representing all the regions from the root
673    /// to the current node.
674    pub fn breadcrumbs(&self) -> String {
675        self.build_breadcrumb(" > ")
676    }
677
678    /// Return a string representing all the regions from the root
679    /// to the current node, using the given string as the separator between
680    /// region names.
681    fn build_breadcrumb(&self, separator: &str) -> String {
682        let mut rev = String::new();
683        let mut handle = self.current_node;
684        loop {
685            let node = self.nodes.try_borrow(handle);
686            let Ok(node) = node else {
687                break;
688            };
689            if !rev.is_empty() {
690                rev.extend(separator.chars().rev());
691            }
692            rev.extend(node.name.chars().rev());
693            handle = node.parent;
694        }
695        rev.chars().rev().collect()
696    }
697
698    /// The name of the current region. This should never be None if the Visitor is operating normally,
699    /// because there should be no way to leave the initial `__ROOT__` region.
700    pub fn current_region(&self) -> Result<&str, PoolError> {
701        self.nodes
702            .try_borrow(self.current_node)
703            .map(|n| n.name.as_str())
704    }
705
706    fn leave_region(&mut self) -> VisitResult {
707        self.current_node = self.nodes.borrow(self.current_node).parent;
708        if self.current_node.is_none() {
709            Err(VisitError::NoActiveNode)
710        } else {
711            Ok(())
712        }
713    }
714
715    /// Get the content of the current node in human-readable form.
716    pub fn debug(&self) -> String {
717        let mut w = Cursor::new(Vec::<u8>::new());
718        let result = self.debug_to(&mut w);
719        match result {
720            Ok(()) => String::from_utf8_lossy(w.get_ref()).into_owned(),
721            Err(err) => err.to_string(),
722        }
723    }
724
725    /// Write the content of the current node in human-readable form.
726    pub fn debug_to<W: Write>(&self, w: &mut W) -> VisitResult {
727        let writer = AsciiWriter::default();
728        writer.write_node(self, &self.nodes[self.current_node], 0, w)?;
729        writeln!(w)?;
730        w.flush()?;
731        Ok(())
732    }
733
734    /// Create a string containing all the data of this Visitor in ascii form. The string is
735    /// formatted to be human-readable with each node on its own line and tabs to indent child nodes.
736    pub fn save_ascii_to_string(&self) -> String {
737        let mut cursor = Cursor::<Vec<u8>>::default();
738        self.save_ascii_to_memory(&mut cursor).unwrap();
739        String::from_utf8(cursor.into_inner()).unwrap()
740    }
741
742    /// Create a string containing all the data of this Visitor in ascii form and saves it to the given
743    /// path. The string is formatted to be human-readable with each node on its own line and tabs
744    /// to indent child nodes.
745    pub fn save_ascii_to_file(&self, path: impl AsRef<Path>) -> VisitResult {
746        let mut writer = BufWriter::new(File::create(path)?);
747        let text = self.save_ascii_to_string();
748        writer.write_all(text.as_bytes())?;
749        Ok(())
750    }
751
752    /// Create a string containing all the data of this Visitor in ascii form and writes it to the
753    /// given writer. The string is formatted to be human-readable with each node on its own line
754    /// and tabs to indent child nodes.
755    pub fn save_ascii_to_memory(&self, mut dest: impl Write) -> VisitResult {
756        let writer = AsciiWriter::default();
757        writer.write(self, &mut dest)
758    }
759
760    /// Tries to create a visitor from the given data. The returned instance can then be used to
761    /// deserialize some data.
762    pub fn load_ascii_from_memory(data: &[u8]) -> Result<Self, VisitError> {
763        let mut src = Cursor::new(data);
764        let mut reader = AsciiReader::new(&mut src);
765        reader.read()
766    }
767
768    /// Tries to create a visitor from the given file. The returned instance can then be used to
769    /// deserialize some data.
770    pub async fn load_ascii_from_file(path: impl AsRef<Path>) -> Result<Self, VisitError> {
771        Self::load_ascii_from_memory(&io::load_file(path).await?)
772    }
773
774    /// Write the data of this Visitor to the given writer. Begin by writing [Visitor::MAGIC_BINARY_CURRENT].
775    pub fn save_binary_to_memory(&self, mut dest: impl Write) -> VisitResult {
776        let writer = BinaryWriter::default();
777        writer.write(self, &mut dest)
778    }
779
780    /// Encode the data of this visitor into bytes and push the bytes into the given `Vec<u8>`.
781    /// Begin by writing [Visitor::MAGIC_BINARY_CURRENT].
782    pub fn save_binary_to_vec(&self) -> Result<Vec<u8>, VisitError> {
783        let mut writer = Cursor::new(Vec::new());
784        self.save_binary_to_memory(&mut writer)?;
785        Ok(writer.into_inner())
786    }
787
788    /// Create a file at the given path and write the data of this visitor into that file in a
789    /// non-human-readable binary format so that the data can be reconstructed using [Visitor::load_binary_from_file].
790    /// Begin by writing [Visitor::MAGIC_BINARY_CURRENT].
791    pub fn save_binary_to_file(&self, path: impl AsRef<Path>) -> VisitResult {
792        let writer = BufWriter::new(File::create(path)?);
793        self.save_binary_to_memory(writer)
794    }
795
796    /// Create a visitor by reading data from the file at the given path, assuming that the file was
797    /// created using [Visitor::save_binary_to_file]. Return a [VisitError::NotSupportedFormat] if
798    /// [Visitor::MAGIC_BINARY_CURRENT] is not the first bytes read from the file.
799    pub async fn load_binary_from_file(path: impl AsRef<Path>) -> Result<Self, VisitError> {
800        Self::load_binary_from_memory(&io::load_file(path).await?)
801    }
802
803    /// Create a visitor by decoding data from the given byte slice, assuming that the bytes are in
804    /// the format that would be produced by [Visitor::save_binary_to_vec]. Return a
805    /// [VisitError::NotSupportedFormat] if [Visitor::MAGIC_BINARY_CURRENT] is not the first bytes read from
806    /// the slice.
807    pub fn load_binary_from_memory(data: &[u8]) -> Result<Self, VisitError> {
808        let mut src = Cursor::new(data);
809        let mut reader = BinaryReader::new(&mut src);
810        reader.read()
811    }
812
813    /// Tries to load a visitor from the given file. This method automatically detects a format of
814    /// the incoming data (binary or ASCII) and tries to load it.
815    pub async fn load_from_file(path: impl AsRef<Path>) -> Result<Self, VisitError> {
816        Self::load_from_memory(&io::load_file(path).await?)
817    }
818
819    /// Tries to load a visitor from the given data. This method automatically detects a format of
820    /// the incoming data (binary or ASCII) and tries to load it.
821    pub fn load_from_memory(data: &[u8]) -> Result<Self, VisitError> {
822        match Self::detect_format_from_slice(data) {
823            Format::Unknown => Err(VisitError::NotSupportedFormat),
824            Format::Binary => Self::load_binary_from_memory(data),
825            Format::Ascii => Self::load_ascii_from_memory(data),
826        }
827    }
828}
829
830#[cfg(test)]
831mod test {
832    use crate::visitor::{BinaryBlob, Visit, VisitResult, Visitor};
833    use nalgebra::{
834        Matrix2, Matrix3, Matrix4, UnitComplex, UnitQuaternion, Vector2, Vector3, Vector4,
835    };
836    use std::sync::Arc;
837    use std::{fs::File, io::Write, path::Path, rc, rc::Rc, sync};
838    use uuid::{uuid, Uuid};
839
840    #[derive(Visit, Default, PartialEq, Debug)]
841    pub struct Model {
842        data: u64,
843    }
844
845    #[derive(Default, PartialEq, Debug)]
846    pub struct Texture {
847        data: Vec<u8>,
848    }
849
850    impl Visit for Texture {
851        fn visit(&mut self, name: &str, visitor: &mut Visitor) -> VisitResult {
852            let mut region = visitor.enter_region(name)?;
853            let mut proxy = BinaryBlob {
854                vec: &mut self.data,
855            };
856            proxy.visit("Data", &mut region)?;
857            Ok(())
858        }
859    }
860
861    #[allow(dead_code)]
862    #[derive(Visit, PartialEq, Debug, Default)]
863    pub enum ResourceKind {
864        #[default]
865        Unknown,
866        Model(Model),
867        Texture(Texture),
868    }
869
870    #[derive(Visit, PartialEq, Debug)]
871    struct Resource {
872        kind: ResourceKind,
873        data: u16,
874    }
875
876    impl Resource {
877        fn new(kind: ResourceKind) -> Self {
878            Self { kind, data: 0 }
879        }
880    }
881
882    impl Default for Resource {
883        fn default() -> Self {
884            Self {
885                kind: ResourceKind::Unknown,
886                data: 0,
887            }
888        }
889    }
890
891    #[derive(Default, Visit, Debug)]
892    struct Weaks {
893        weak_resource_arc: Option<sync::Weak<Resource>>,
894        weak_resource_rc: Option<rc::Weak<Resource>>,
895    }
896
897    impl PartialEq for Weaks {
898        fn eq(&self, other: &Self) -> bool {
899            self.weak_resource_arc.as_ref().and_then(|r| r.upgrade())
900                == other.weak_resource_arc.as_ref().and_then(|r| r.upgrade())
901                && self.weak_resource_rc.as_ref().and_then(|r| r.upgrade())
902                    == other.weak_resource_rc.as_ref().and_then(|r| r.upgrade())
903        }
904    }
905
906    #[derive(Default, Visit, Debug, PartialEq)]
907    struct Foo {
908        boolean: bool,
909        num_u8: u8,
910        num_i8: i8,
911        num_u16: u16,
912        num_i16: i16,
913        num_u32: u32,
914        num_i32: i32,
915        num_u64: u64,
916        num_i64: i64,
917        num_f32: f32,
918        num_f64: f64,
919        quat: UnitQuaternion<f32>,
920        mat4: Matrix4<f32>,
921        array: Vec<u8>,
922        mat3: Matrix3<f32>,
923        uuid: Uuid,
924        complex: UnitComplex<f32>,
925        mat2: Matrix2<f32>,
926
927        vec2_u8: Vector2<u8>,
928        vec2_i8: Vector2<i8>,
929        vec2_u16: Vector2<u16>,
930        vec2_i16: Vector2<i16>,
931        vec2_u32: Vector2<u32>,
932        vec2_i32: Vector2<i32>,
933        vec2_u64: Vector2<u64>,
934        vec2_i64: Vector2<i64>,
935
936        vec3_u8: Vector3<u8>,
937        vec3_i8: Vector3<i8>,
938        vec3_u16: Vector3<u16>,
939        vec3_i16: Vector3<i16>,
940        vec3_u32: Vector3<u32>,
941        vec3_i32: Vector3<i32>,
942        vec3_u64: Vector3<u64>,
943        vec3_i64: Vector3<i64>,
944
945        vec4_u8: Vector4<u8>,
946        vec4_i8: Vector4<i8>,
947        vec4_u16: Vector4<u16>,
948        vec4_i16: Vector4<i16>,
949        vec4_u32: Vector4<u32>,
950        vec4_i32: Vector4<i32>,
951        vec4_u64: Vector4<u64>,
952        vec4_i64: Vector4<i64>,
953
954        string: String,
955
956        vec2_f32: Vector2<f32>,
957        vec2_f64: Vector2<f64>,
958        vec3_f32: Vector3<f32>,
959        vec3_f64: Vector3<f64>,
960        vec4_f32: Vector4<f32>,
961        vec4_f64: Vector4<f64>,
962
963        shared_resource: Option<Rc<Resource>>,
964        shared_resource_arc: Option<Arc<Resource>>,
965        weaks: Weaks,
966    }
967
968    impl Foo {
969        fn new(resource: Rc<Resource>, arc_resource: Arc<Resource>) -> Self {
970            Self {
971                boolean: true,
972                num_u8: 123,
973                num_i8: -123,
974                num_u16: 123,
975                num_i16: -123,
976                num_u32: 123,
977                num_i32: -123,
978                num_u64: 123,
979                num_i64: -123,
980                num_f32: 123.321,
981                num_f64: 123.321,
982                quat: UnitQuaternion::from_euler_angles(1.0, 2.0, 3.0),
983                mat4: Matrix4::new_scaling(3.0),
984                array: vec![1, 2, 3, 4],
985                mat3: Matrix3::new_scaling(3.0),
986                uuid: uuid!("51a582c0-30d7-4dbc-b5a0-da8ea186edce"),
987                complex: UnitComplex::new(0.0),
988                mat2: Matrix2::new_scaling(2.0),
989                vec2_u8: Vector2::new(1, 2),
990                vec2_i8: Vector2::new(-1, -2),
991                vec2_u16: Vector2::new(1, 2),
992                vec2_i16: Vector2::new(-1, -2),
993                vec2_u32: Vector2::new(1, 2),
994                vec2_i32: Vector2::new(-1, -2),
995                vec2_u64: Vector2::new(1, 2),
996                vec2_i64: Vector2::new(-1, -2),
997                vec3_u8: Vector3::new(1, 2, 3),
998                vec3_i8: Vector3::new(-1, -2, -3),
999                vec3_u16: Vector3::new(1, 2, 3),
1000                vec3_i16: Vector3::new(-1, -2, -3),
1001                vec3_u32: Vector3::new(1, 2, 3),
1002                vec3_i32: Vector3::new(-1, -2, -3),
1003                vec3_u64: Vector3::new(1, 2, 3),
1004                vec3_i64: Vector3::new(-1, -2, -3),
1005                vec4_u8: Vector4::new(1, 2, 3, 4),
1006                vec4_i8: Vector4::new(-1, -2, -3, -4),
1007                vec4_u16: Vector4::new(1, 2, 3, 4),
1008                vec4_i16: Vector4::new(-1, -2, -3, -4),
1009                vec4_u32: Vector4::new(1, 2, 3, 4),
1010                vec4_i32: Vector4::new(-1, -2, -3, -4),
1011                vec4_u64: Vector4::new(1, 2, 3, 4),
1012                vec4_i64: Vector4::new(-1, -2, -3, -4),
1013                vec2_f32: Vector2::new(123.321, 234.432),
1014                vec2_f64: Vector2::new(123.321, 234.432),
1015                vec3_f32: Vector3::new(123.321, 234.432, 567.765),
1016                vec3_f64: Vector3::new(123.321, 234.432, 567.765),
1017                vec4_f32: Vector4::new(123.321, 234.432, 567.765, 890.098),
1018                vec4_f64: Vector4::new(123.321, 234.432, 567.765, 890.098),
1019                weaks: Weaks {
1020                    weak_resource_arc: Some(Arc::downgrade(&arc_resource)),
1021                    weak_resource_rc: Some(Rc::downgrade(&resource)),
1022                },
1023                shared_resource: Some(resource),
1024                shared_resource_arc: Some(arc_resource),
1025                string: "This Is A String With Reserved Characters <>:;{}[\\\\\\\\\\] \
1026                and \"quotes\" many \"\"\"quotes\"\"\"\" and line\nbreak\ttabs\t\t\t\t"
1027                    .to_string(),
1028            }
1029        }
1030    }
1031
1032    fn resource() -> Rc<Resource> {
1033        Rc::new(Resource::new(ResourceKind::Model(Model { data: 555 })))
1034    }
1035
1036    fn resource_arc() -> Arc<Resource> {
1037        Arc::new(Resource::new(ResourceKind::Model(Model { data: 555 })))
1038    }
1039
1040    fn objects(resource: Rc<Resource>, arc_resource: Arc<Resource>) -> Vec<Foo> {
1041        vec![
1042            Foo::new(resource.clone(), arc_resource.clone()),
1043            Foo::new(resource, arc_resource),
1044        ]
1045    }
1046
1047    fn serialize() -> Visitor {
1048        let mut resource = resource();
1049        let mut resource_arc = resource_arc();
1050        let mut objects = objects(resource.clone(), resource_arc.clone());
1051
1052        let mut visitor = Visitor::new();
1053        resource.visit("SharedResource", &mut visitor).unwrap();
1054        resource_arc
1055            .visit("SharedResourceArc", &mut visitor)
1056            .unwrap();
1057        objects.visit("Objects", &mut visitor).unwrap();
1058        visitor
1059    }
1060
1061    #[test]
1062    fn visitor_test_binary() {
1063        let path = Path::new("test.bin");
1064
1065        // Save
1066        {
1067            let visitor = serialize();
1068
1069            visitor.save_binary_to_file(path).unwrap();
1070            if let Ok(mut file) = File::create(Path::new("test.txt")) {
1071                file.write_all(visitor.save_ascii_to_string().as_bytes())
1072                    .unwrap();
1073            }
1074        }
1075
1076        // Load
1077        {
1078            let expected_resource = resource();
1079            let expected_resource_arc = resource_arc();
1080            let expected_objects =
1081                objects(expected_resource.clone(), expected_resource_arc.clone());
1082
1083            let mut visitor = futures::executor::block_on(Visitor::load_from_file(path)).unwrap();
1084            let mut resource: Rc<Resource> = Rc::new(Default::default());
1085            resource.visit("SharedResource", &mut visitor).unwrap();
1086            assert_eq!(resource, expected_resource);
1087
1088            let mut resource_arc: Arc<Resource> = Arc::new(Default::default());
1089            resource_arc
1090                .visit("SharedResourceArc", &mut visitor)
1091                .unwrap();
1092            assert_eq!(resource_arc, expected_resource_arc);
1093
1094            let mut objects: Vec<Foo> = Vec::new();
1095            objects.visit("Objects", &mut visitor).unwrap();
1096            assert_eq!(objects, expected_objects);
1097        }
1098    }
1099
1100    #[test]
1101    fn visitor_test_ascii() {
1102        let path = Path::new("test_ascii.txt");
1103
1104        // Save
1105        {
1106            let visitor = serialize();
1107            visitor.save_ascii_to_file(path).unwrap();
1108        }
1109
1110        // Load
1111        {
1112            let expected_resource = resource();
1113            let expected_resource_arc = resource_arc();
1114            let expected_objects =
1115                objects(expected_resource.clone(), expected_resource_arc.clone());
1116
1117            let mut visitor =
1118                futures::executor::block_on(Visitor::load_ascii_from_file(path)).unwrap();
1119            let mut resource: Rc<Resource> = Rc::new(Default::default());
1120            resource.visit("SharedResource", &mut visitor).unwrap();
1121            assert_eq!(resource, expected_resource);
1122
1123            let mut resource_arc: Arc<Resource> = Arc::new(Default::default());
1124            resource_arc
1125                .visit("SharedResourceArc", &mut visitor)
1126                .unwrap();
1127            assert_eq!(resource_arc, expected_resource_arc);
1128
1129            let mut objects: Vec<Foo> = Vec::new();
1130            objects.visit("Objects", &mut visitor).unwrap();
1131            assert_eq!(objects, expected_objects);
1132        }
1133    }
1134}