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