Skip to content

Commit

Permalink
Unified versions between xml and legacy file types
Browse files Browse the repository at this point in the history
This commit switches model::Version to be an enum with legacy and xml
variants to indicate which type of file the data came from and what
version it was.

This does not preclude the model::Vtk struct from being serialized
either as legacy or xml formats. That functionality remains flexible.

Fixes #12
  • Loading branch information
elrnv committed Jun 19, 2023
1 parent e096c40 commit 9966119
Show file tree
Hide file tree
Showing 9 changed files with 91 additions and 66 deletions.
3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ lz4 = { package = "lz4_flex", version = "0.10", optional = true }
flate2 = { version = "1.0.19", optional = true }
xz2 = { version = "0.1.6", optional = true } # LZMA
#quick-xml = { version = "0.25", features = ["serialize"], optional = true }
quick-xml = { path = "../quick-xml", features = ["serialize"], optional = true }
# quick-xml = { path = "../quick-xml", features = ["serialize"], optional = true }
quick-xml = { git = "https://github.com/elrnv/quick-xml", features = ["serialize"], optional = true, branch = "binary-support" }
serde = { version = "1.0", features = ["derive"], optional = true }
tokio = { version = "1.3", features = ["fs", "io-util"], optional = true }
rayon = { version = "1.0", optional = true }
Expand Down
20 changes: 10 additions & 10 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
//! let mut vtk_file = Vtk::import(&file_path)
//! .expect(&format!("Failed to load file: {:?}", file_path));
//!
//! vtk_file.version = Version::new((4,2)); // arbitrary change
//! vtk_file.version = Version::new_legacy(4,2); // arbitrary change
//!
//! vtk_file.export_ascii(&file_path)
//! .expect(&format!("Failed to save file: {:?}", file_path));
Expand All @@ -36,7 +36,7 @@
//!
//! let mut vtk_file = Vtk::parse_legacy_be(data).expect(&format!("Failed to parse file"));
//!
//! vtk_file.version = Version::new((4,2)); // arbitrary change
//! vtk_file.version = Version::new_legacy(4,2); // arbitrary change
//!
//! let mut output = String::new();
//! Vtk::write_legacy_ascii(vtk_file, &mut output).expect(&format!("Failed to write file"));
Expand Down Expand Up @@ -251,7 +251,7 @@ impl Vtk {
/// let vtk = Vtk::parse_legacy_be(vtk_ascii).expect("Failed to parse vtk file");
///
/// assert_eq!(vtk, Vtk {
/// version: Version::new((2,0)),
/// version: Version::new_legacy(2,0),
/// byte_order: ByteOrder::BigEndian,
/// title: String::from("Triangle example"),
/// file_path: None,
Expand Down Expand Up @@ -299,7 +299,7 @@ impl Vtk {
/// let vtk = Vtk::parse_legacy_le(vtk_ascii).expect("Failed to parse vtk file");
///
/// assert_eq!(vtk, Vtk {
/// version: Version::new((2,0)),
/// version: Version::new_legacy(2,0),
/// byte_order: ByteOrder::LittleEndian,
/// title: String::from("Triangle example"),
/// file_path: None,
Expand Down Expand Up @@ -368,7 +368,7 @@ impl Vtk {
/// let vtk = Vtk::parse_xml(input).expect("Failed to parse XML VTK file");
///
/// assert_eq!(vtk, Vtk {
/// version: Version::new((2,0)),
/// version: Version::new_xml(2,0),
/// byte_order: ByteOrder::BigEndian, // This is default
/// title: String::new(),
/// file_path: None,
Expand Down Expand Up @@ -603,7 +603,7 @@ impl Vtk {
/// use vtkio::model::*;
/// use std::path::PathBuf;
/// let vtk = Vtk {
/// version: Version::new((4,1)),
/// version: Version::new_legacy(4,1),
/// byte_order: ByteOrder::BigEndian,
/// title: String::from("Tetrahedron"),
/// file_path: Some(PathBuf::from("./test.vtk")),
Expand Down Expand Up @@ -671,7 +671,7 @@ impl Vtk {
/// let mut vtk_bytes = Vec::<u8>::new();
///
/// Vtk {
/// version: Version::new((2,0)),
/// version: Version::new_legacy(2,0),
/// byte_order: ByteOrder::BigEndian,
/// title: String::from("Triangle example"),
/// file_path: None,
Expand Down Expand Up @@ -705,7 +705,7 @@ impl Vtk {
/// let mut vtk_string = String::new();
///
/// Vtk {
/// version: Version::new((2,0)),
/// version: Version::new_legacy(2,0),
/// byte_order: ByteOrder::BigEndian, // Ignored
/// title: String::from("Triangle example"),
/// file_path: None,
Expand Down Expand Up @@ -756,7 +756,7 @@ impl Vtk {
/// let mut vtk_bytes = Vec::<u8>::new();
///
/// Vtk {
/// version: Version::new((2,0)),
/// version: Version::new_xml(2,0),
/// byte_order: ByteOrder::BigEndian,
/// title: String::from("Triangle example"),
/// file_path: None,
Expand Down Expand Up @@ -829,7 +829,7 @@ impl Vtk {
/// use vtkio::model::*;
/// use std::path::PathBuf;
/// let vtk = Vtk {
/// version: Version::new((4,1)),
/// version: Version::new_legacy(4,1),
/// title: String::from("Tetrahedron"),
/// byte_order: ByteOrder::BigEndian,
/// file_path: Some(PathBuf::from("./test.vtk")),
Expand Down
59 changes: 41 additions & 18 deletions src/model.rs
Original file line number Diff line number Diff line change
Expand Up @@ -231,31 +231,54 @@ impl Vtk {
}
}

/// Version number (e.g. `4.1 => Version { major: 4, minor: 1 }`)
/// Version number enum
///
/// Legacy and XML versions are distinct, and this enum splits the two into distinct variants.
/// New files can use the `Auto` variant, which will default to the minimum version supporting the latest features in `vtkio`.
#[derive(Copy, Clone, PartialEq, Debug)]
pub struct Version {
pub major: u8,
pub minor: u8,
pub enum Version {
/// Automatically handle versioning on write for both Legacy and XML formats.
Auto,
/// Loaded Legacy format with this version. Writing in XML format is handled as with the `Auto` variant.
Legacy { major: u32, minor: u32 },
/// Loaded XML format with this version. Writing in Legacy is handled as with the `Auto` variant.
XML { major: u32, minor: u32 },
}

impl Version {
pub fn new(pair: (u8, u8)) -> Self {
Version {
major: pair.0,
minor: pair.1,
pub fn new() -> Self {
Version::Auto
}
pub fn new_legacy(major: u32, minor: u32) -> Self {
Version::Legacy { major, minor }
}
pub fn new_xml(major: u32, minor: u32) -> Self {
Version::XML { major, minor }
}
pub fn to_xml(self) -> (u32, u32) {
match self {
Version::XML { major, minor } => (major, minor),
Version::Auto | Version::Legacy { .. } => {
// This is a conservative estimate.
// It is not established what the actual minimum version we write.
// Presumably this would only be a problem when working with very old versions of VTK.
(1, 0)
}
}
}
}

impl From<(u8, u8)> for Version {
fn from(pair: (u8, u8)) -> Self {
Version::new(pair)
pub fn to_legacy(self) -> (u32, u32) {
match self {
Version::Legacy { major, minor } => (major, minor),
Version::Auto | Version::XML { .. } => (2, 0),
}
}
}

impl fmt::Display for Version {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}.{}", self.major, self.minor)
pub fn fmt_as_xml(&self, f: &mut fmt::Formatter) -> fmt::Result {
let (major, minor) = self.to_xml();
write!(f, "{}.{}", major, minor)
}
pub fn fmt_as_legacy(&self, f: &mut fmt::Formatter) -> fmt::Result {
let (major, minor) = self.to_legacy();
write!(f, "{}.{}", major, minor)
}
}

Expand Down
8 changes: 4 additions & 4 deletions src/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ fn version(input: &[u8]) -> IResult<&[u8], Version> {
sp(tag_no_case("Version")),
))(input)?;
sp(map(
separated_pair(parse_u8, tag("."), parse_u8),
Version::new,
separated_pair(parse_u32, tag("."), parse_u32),
|(major, minor)| Version::new_legacy(major, minor),
))(input)
}

Expand Down Expand Up @@ -744,7 +744,7 @@ mod tests {
#[test]
fn version_test() {
let f = version("# vtk DataFile Version 2.0 \ntitle\n".as_bytes());
assert_eq!(f, Ok(("\ntitle\n".as_bytes(), Version::new((2, 0)))));
assert_eq!(f, Ok(("\ntitle\n".as_bytes(), Version::new_legacy(2, 0))));
}
#[test]
fn title_test() {
Expand All @@ -759,7 +759,7 @@ mod tests {
Ok((
"".as_bytes(),
(
Version::new((2, 0)),
Version::new_legacy(2, 0),
"This is a title".to_string(),
FileType::Binary
)
Expand Down
7 changes: 4 additions & 3 deletions src/writer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -435,8 +435,9 @@ mod write_vtk_impl {
&mut self,
vtk: Vtk,
) -> std::result::Result<&mut Self, Error> {
let version = vtk.version.to_legacy();
let source_path = vtk.file_path.as_ref().map(|p| p.as_ref());
writeln!(self, "# vtk DataFile Version {}", vtk.version)
writeln!(self, "# vtk DataFile Version {}.{}", version.0, version.1)
.map_err(|_| Error::Header(Header::Version))?;
writeln!(self, "{}", vtk.title).map_err(|_| Error::Header(Header::Version))?;
self.write_file_type()?;
Expand Down Expand Up @@ -578,7 +579,7 @@ mod write_vtk_impl {
let num_cells = cells.cell_verts.num_cells();

// Write CELLS structure.
if vtk.version.major >= 5 {
if version.0 >= 5 {
// From version 5 and on the cells are written as an offsets and connectivity pair.
let (connectivity, offsets) = cells.cell_verts.into_xml();

Expand Down Expand Up @@ -666,7 +667,7 @@ mod write_vtk_impl {
Error::DataSet(DataSetError::StructuredPoints(DataSetPart::Origin))
})?;

if vtk.version.major < 2 {
if version.0 < 2 {
write!(self, "ASPECT_RATIO")
} else {
write!(self, "SPACING")
Expand Down
10 changes: 5 additions & 5 deletions src/xml.rs
Original file line number Diff line number Diff line change
Expand Up @@ -304,7 +304,7 @@ mod version {
elem.parse()
.map_err(|e| de::Error::custom(format!("failed to parse version: {}", e)))
};
Ok(Version::new((advance(&mut iter)?, advance(&mut iter)?)))
Ok(Version::new_xml(advance(&mut iter)?, advance(&mut iter)?))
}
}

Expand All @@ -313,7 +313,7 @@ mod version {
where
S: Serializer,
{
let Version { major, minor } = self;
let (major, minor) = self.to_xml();
s.collect_str(&format_args!("{}.{}", major, minor))
}
}
Expand Down Expand Up @@ -965,7 +965,7 @@ mod vtkfile {
{
let mut vtk = VTKFile {
data_set_type: DataSetType::UnstructuredGrid,
version: model::Version::new((1, 0)),
version: model::Version::new_xml(0, 1),
byte_order: model::ByteOrder::BigEndian,
header_type: None,
compressor: Compressor::None,
Expand Down Expand Up @@ -1077,7 +1077,7 @@ impl Default for VTKFile {
fn default() -> VTKFile {
VTKFile {
data_set_type: DataSetType::ImageData,
version: model::Version::new((0, 1)),
version: model::Version::new_xml(0, 1),
byte_order: model::ByteOrder::BigEndian,
header_type: None,
compressor: Compressor::None,
Expand Down Expand Up @@ -4059,7 +4059,7 @@ mod tests {
assert_eq!(
vtk,
Vtk {
version: Version::new((1, 0)),
version: Version::new_xml(1, 0),
byte_order: ByteOrder::LittleEndian,
title: String::new(),
data: DataSet::inline(RectilinearGridPiece {
Expand Down
Loading

0 comments on commit 9966119

Please sign in to comment.