added visitor version number

This commit is contained in:
Dmitry Stepanov
2025-04-26 16:35:03 +03:00
parent c54f4fc7f5
commit 574aac33a9
5 changed files with 46 additions and 13 deletions
+19 -5
View File
@@ -80,6 +80,9 @@ use std::{
sync::Arc,
};
/// Latest version number of the visitor.
pub const LATEST_VERSION: u32 = 1;
/// Proxy struct for plain data. It is used to serialize arrays of trivially copyable data (`Vec<u8>`)
/// directly as a large chunk of data. For example, an attempt to serialize `Vec<u8>` serialize each
/// byte as a separate node which is very inefficient.
@@ -289,6 +292,7 @@ pub struct Visitor {
reading: bool,
current_node: Handle<VisitorNode>,
root: Handle<VisitorNode>,
version: u32,
/// A place to store whatever objects may be needed to help with reading and writing values.
pub blackboard: Blackboard,
/// Flags that can activate special behavior in some Visit values, such as
@@ -376,6 +380,9 @@ pub enum Format {
}
impl Visitor {
/// Old header marker for binary version.
pub const MAGIC_BINARY_OLD: &'static str = "RG3D";
/// Sequence of bytes that is automatically written at the start when a visitor is encoded into
/// bytes. It is written by [Visitor::save_binary_to_file], [Visitor::save_binary_to_memory],
/// and [Visitor::save_binary_to_vec].
@@ -383,7 +390,10 @@ impl Visitor {
/// [Visitor::load_binary_from_file] will return an error if this sequence of bytes is not present
/// at the beginning of the file, and [Visitor::load_binary_from_memory] will return an error of
/// these bytes are not at the beginning of the given slice.
pub const MAGIC_BINARY: &'static str = "RG3D";
pub const MAGIC_BINARY_CURRENT: &'static str = "FBAF";
/// Old header marker for ASCII version.
pub const MAGIC_ASCII_OLD: &'static str = "FTAF";
/// Sequence of bytes that is automatically written at the start when a visitor is encoded into
/// ascii form. It is written by [Visitor::save_ascii_to_file], [Visitor::save_ascii_to_memory],
@@ -392,8 +402,7 @@ impl Visitor {
/// [Visitor::load_ascii_from_file] will return an error if this sequence of bytes is not present
/// at the beginning of the file, and [Visitor::load_ascii_from_memory] will return an error of
/// these bytes are not at the beginning of the given slice.
// Fyrox Text Asset Format.
pub const MAGIC_ASCII: &'static str = "FTAF";
pub const MAGIC_ASCII_CURRENT: &'static str = "FTAX";
/// Checks whether the given reader points to a supported file format or not.
#[must_use]
@@ -405,9 +414,13 @@ impl Visitor {
pub fn detect_format(src: &mut dyn Read) -> Format {
let mut magic: [u8; 4] = Default::default();
if src.read_exact(&mut magic).is_ok() {
if magic.eq(Visitor::MAGIC_BINARY.as_bytes()) {
if magic.eq(Visitor::MAGIC_BINARY_OLD.as_bytes())
|| magic.eq(Visitor::MAGIC_BINARY_CURRENT.as_bytes())
{
return Format::Binary;
} else if magic.eq(Visitor::MAGIC_ASCII.as_bytes()) {
} else if magic.eq(Visitor::MAGIC_ASCII_OLD.as_bytes())
|| magic.eq(Visitor::MAGIC_ASCII_CURRENT.as_bytes())
{
return Format::Ascii;
}
}
@@ -433,6 +446,7 @@ impl Visitor {
reading: false,
current_node: root,
root,
version: LATEST_VERSION,
blackboard: Blackboard::new(),
flags: VisitorFlags::NONE,
}
+14 -3
View File
@@ -371,9 +371,17 @@ impl Reader for AsciiReader<'_> {
let src = &mut self.src;
let magic: [u8; 4] = [src.next()?, src.next()?, src.next()?, src.next()?];
if !magic.eq(Visitor::MAGIC_ASCII.as_bytes()) {
let version = if magic.eq(Visitor::MAGIC_ASCII_OLD.as_bytes()) {
0u32
} else if magic.eq(Visitor::MAGIC_ASCII_CURRENT.as_bytes()) {
src.skip_until(|ch| ch != b':')?;
src.skip_n(1)?;
src.read_num_until::<u32, _>(b';')?
} else {
return Err(VisitError::NotSupportedFormat);
}
};
let mut visitor = Visitor {
nodes: Pool::new(),
unique_id_counter: 1,
@@ -382,6 +390,7 @@ impl Reader for AsciiReader<'_> {
reading: true,
current_node: Handle::NONE,
root: Handle::NONE,
version,
blackboard: Blackboard::new(),
flags: VisitorFlags::NONE,
};
@@ -583,7 +592,7 @@ mod test {
#[test]
fn test_parse_visitor() {
let input = r#"FTAF
let input = r#"FTAX:1;
SomeNode
[2:
U8<u8:123>
@@ -609,6 +618,8 @@ mod test {
let visitor = reader.read().unwrap();
assert_eq!(visitor.version, 1);
let some_node = visitor.find_node("SomeNode").unwrap();
assert_eq!(some_node.fields.len(), 2);
assert_eq!(
+9 -2
View File
@@ -244,9 +244,15 @@ impl Reader for BinaryReader<'_> {
let mut magic: [u8; 4] = Default::default();
src.read_exact(&mut magic)?;
if !magic.eq(Visitor::MAGIC_BINARY.as_bytes()) {
let version = if magic.eq(Visitor::MAGIC_BINARY_OLD.as_bytes()) {
0u32
} else if magic.eq(Visitor::MAGIC_BINARY_CURRENT.as_bytes()) {
src.read_u32::<LittleEndian>()?
} else {
return Err(VisitError::NotSupportedFormat);
}
};
let mut visitor = Visitor {
nodes: Pool::new(),
unique_id_counter: 1,
@@ -255,6 +261,7 @@ impl Reader for BinaryReader<'_> {
reading: true,
current_node: Handle::NONE,
root: Handle::NONE,
version,
blackboard: Blackboard::new(),
flags: VisitorFlags::NONE,
};
+2 -2
View File
@@ -21,7 +21,7 @@
use crate::visitor::{
field::{Field, FieldKind},
writer::Writer,
VisitResult, Visitor, VisitorNode,
VisitResult, Visitor, VisitorNode, LATEST_VERSION,
};
use base64::Engine;
use byteorder::WriteBytesExt;
@@ -250,7 +250,7 @@ impl Writer for AsciiWriter {
}
fn write(&self, visitor: &Visitor, dest: &mut dyn Write) -> VisitResult {
writeln!(dest, "{}", Visitor::MAGIC_ASCII)?;
writeln!(dest, "{}:{};", Visitor::MAGIC_ASCII_CURRENT, LATEST_VERSION)?;
self.write_node(visitor, &visitor.nodes[visitor.root], 0, dest)
}
}
+2 -1
View File
@@ -273,7 +273,8 @@ impl Writer for BinaryWriter {
}
fn write(&self, visitor: &Visitor, dest: &mut dyn Write) -> VisitResult {
dest.write_all(Visitor::MAGIC_BINARY.as_bytes())?;
dest.write_all(Visitor::MAGIC_BINARY_CURRENT.as_bytes())?;
dest.write_u32::<LittleEndian>(visitor.version)?;
let mut stack = vec![visitor.root];
while let Some(node_handle) = stack.pop() {
let node = visitor.nodes.borrow(node_handle);