diff --git a/.travis.yml b/.travis.yml index 5561513..cf8b1c9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,12 +3,12 @@ cache: cargo rust: - stable - beta - - 1.40.0 + - 1.52.0 jobs: include: - - rust: 1.40.0 + - rust: 1.52.0 env: TEST_MINIMAL_VERSIONS=1 - - rust: 1.40.0 + - rust: 1.52.0 env: LINT=1 before_install: - | diff --git a/CHANGELOG.md b/CHANGELOG.md index 7fddc3c..e1e3b68 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,43 @@ ## [Unreleased] +## [0.8.0] + +* Bump minimum supported Rust version to 1.56.0. +* Iterator types returned by `tree::v7400::NodeHandle::{children, children_by_name}` + now have a name. +* All iterator types now have `std::iter::FusedIterator` impl. +* `tree::v7400::NodeHandle::first_child_by_name()` is added. +* Now some items on docs.rs have pretty badges indicating the items is only + enabled with some features. + + This won't affect any builds by other users. `cargo doc --all-features` + and other commands should still run successfully with stable toolchain. +* Bump internal dependencies. + +## Added +* `tree::v7400::NodeHandle::first_child_by_name()` is added. + + `node.first_child_by_name(name)` returns the same result as + `node.children_by_name(name).next()`. + +## Fixed +* Fixed incorrect attribute type value being written by the writer. + +## Breaking changes +* Bump minimum supported Rust version to 1.56.0. + +## Non-breaking changes +* Iterator types returned by `tree::v7400::NodeHandle::{children, children_by_name}` + now have a name. + + `NodeHandle::children()` returns `Children<'_>`. + + `NodeHandle::children_by_name()` returns `ChildrenByName<'_>`. + + By this change, now these iterators can be included in other types as a field. +* All iterator types defined by this crate now have `std::iter::FusedIterator` impl. + +## [0.7.0] + +* Bump minimum supported Rust version to 1.49. +* Bump internal dependencies. + ## [0.6.0] * Minimum supported Rust version is bumped to 1.40.0. @@ -269,7 +306,10 @@ Totally rewritten. -[Unreleased]: +[Unreleased]: +[0.8.0]: +[0.7.0]: +[0.6.1]: [0.6.0]: [0.5.0]: [0.4.4]: diff --git a/Cargo.toml b/Cargo.toml index b266481..a379d8d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,8 +1,9 @@ [package] name = "fbxcel" -version = "0.6.0" +version = "0.8.0" authors = ["YOSHIOKA Takuma "] -edition = "2018" +edition = "2021" +rust-version = "1.56" license = "MIT OR Apache-2.0" readme = "README.md" description = "Excellent FBX library" @@ -12,6 +13,14 @@ categories = ["parser-implementations"] [package.metadata.docs.rs] all-features = true +# See . +# +# Didn't create `docsrs` feature, since this (`#[doc(cfg(feature = ...))]`) +# depends on nightly feature and it prevents `cargo doc --all-features` from +# running with stable rust toolchain. +# See +# for unstable `#[doc(cfg(...))]` attribute. +rustc-args = ["--cfg", "docsrs"] [features] default = [] @@ -22,12 +31,12 @@ writer = [] [dependencies] byteorder = "1" indextree = { version = "4", optional = true } -libflate = "0.1" +libflate = "1.0.1" log = "0.4.4" -string-interner = { version = "0.7", optional = true, default-features = false } +string-interner = { version = "0.14.0", optional = true, default-features = false, features = ["backends", "inline-more", "std"] } [dev-dependencies] -env_logger = "0.7" +env_logger = "0.9.0" [badges] maintenance = { status = "passively-maintained" } diff --git a/README.md b/README.md index 214f69f..aabef2a 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ [![Build Status](https://travis-ci.com/lo48576/fbxcel.svg?branch=develop)](https://travis-ci.com/lo48576/fbxcel) [![Latest version](https://img.shields.io/crates/v/fbxcel.svg)](https://crates.io/crates/fbxcel) [![Documentation](https://docs.rs/fbxcel/badge.svg)](https://docs.rs/fbxcel) -![Minimum rustc version: 1.40](https://img.shields.io/badge/rustc-1.40+-lightgray.svg) +![Minimum rustc version: 1.56](https://img.shields.io/badge/rustc-1.56+-lightgray.svg) `fbxcel` is an FBX library for Rust programming language. @@ -37,7 +37,7 @@ Currently there is no plan to support FBX ASCII format. ## Rust version -Latest stable compiler (currently 1.40) is supported. +Latest stable compiler (currently 1.52) is supported. ## License diff --git a/src/lib.rs b/src/lib.rs index 9c88f72..339c948 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,17 +1,18 @@ //! The excellent FBX library. //! -//! `low` module provides low-level data types such as FBX header, node +//! [`low`] module provides low-level data types such as FBX header, node //! attribute value, etc. //! -//! `pull_parser` module provides pull parser for FBX binary format. +//! [`pull_parser`] module provides pull parser for FBX binary format. //! ASCII format is not supported. //! -//! `tree` module provides tree types, which allow users to access FBX data as +//! [`tree`] module provides tree types, which allow users to access FBX data as //! tree, not as stream of parser events. //! To use `tree` module, enable `tree` feature. //! -//! `writer` module provides writer types. +//! [`writer`] module provides writer types. //! To use `writer` module, enable `writer` feature. +#![cfg_attr(feature = "docsrs", feature(doc_cfg))] #![forbid(unsafe_code)] #![warn(missing_docs)] #![warn(clippy::missing_docs_in_private_items)] @@ -19,6 +20,8 @@ pub mod low; pub mod pull_parser; #[cfg(feature = "tree")] +#[cfg_attr(feature = "docsrs", doc(cfg(feature = "tree")))] pub mod tree; #[cfg(feature = "writer")] +#[cfg_attr(feature = "docsrs", doc(cfg(feature = "writer")))] pub mod writer; diff --git a/src/low.rs b/src/low.rs index cf76573..5e7b873 100644 --- a/src/low.rs +++ b/src/low.rs @@ -1,6 +1,7 @@ //! Low-level or primitive data types for FBX binary. #[cfg(feature = "writer")] +#[cfg_attr(feature = "docsrs", doc(cfg(feature = "writer")))] pub(crate) use self::fbx_header::MAGIC; pub use self::{ fbx_header::{FbxHeader, HeaderError}, diff --git a/src/low/fbx_header.rs b/src/low/fbx_header.rs index 0794b26..d875231 100644 --- a/src/low/fbx_header.rs +++ b/src/low/fbx_header.rs @@ -116,10 +116,10 @@ mod tests { let mut cursor = Cursor::new(wrong_header); // `HeaderError` may contain `io::Error` and is not comparable. assert!( - match FbxHeader::load(cursor.by_ref()).unwrap_err() { - HeaderError::MagicNotDetected => true, - _ => false, - }, + matches!( + FbxHeader::load(cursor.by_ref()), + Err(HeaderError::MagicNotDetected) + ), "Invalid magic should be reported by `MagicNotDetected`" ); assert!( diff --git a/src/low/v7400/array_attribute.rs b/src/low/v7400/array_attribute.rs index a754e65..121ed33 100644 --- a/src/low/v7400/array_attribute.rs +++ b/src/low/v7400/array_attribute.rs @@ -31,6 +31,7 @@ impl ArrayAttributeEncoding { /// Returns the raw value. #[cfg(feature = "writer")] + #[cfg_attr(feature = "docsrs", doc(cfg(feature = "writer")))] pub(crate) fn to_u32(self) -> u32 { match self { ArrayAttributeEncoding::Direct => 0, @@ -55,7 +56,7 @@ impl FromReader for ArrayAttributeEncoding { fn from_reader(reader: &mut impl io::Read) -> Result { let raw_encoding = u32::from_reader(reader)?; let encoding = ArrayAttributeEncoding::from_u32(raw_encoding) - .ok_or_else(|| DataError::InvalidArrayAttributeEncoding(raw_encoding))?; + .ok_or(DataError::InvalidArrayAttributeEncoding(raw_encoding))?; Ok(encoding) } } diff --git a/src/low/v7400/attribute/type_.rs b/src/low/v7400/attribute/type_.rs index 24796c1..5028ada 100644 --- a/src/low/v7400/attribute/type_.rs +++ b/src/low/v7400/attribute/type_.rs @@ -58,6 +58,7 @@ impl AttributeType { /// Returns the type code. #[cfg(feature = "writer")] + #[cfg_attr(feature = "docsrs", doc(cfg(feature = "writer")))] pub(crate) fn type_code(self) -> u8 { match self { AttributeType::Bool => b'C', @@ -81,7 +82,7 @@ impl FromReader for AttributeType { fn from_reader(reader: &mut impl io::Read) -> Result { let type_code = u8::from_reader(reader)?; let attr_type = Self::from_type_code(type_code) - .ok_or_else(|| DataError::InvalidAttributeTypeCode(type_code))?; + .ok_or(DataError::InvalidAttributeTypeCode(type_code))?; Ok(attr_type) } } diff --git a/src/low/v7400/attribute/value.rs b/src/low/v7400/attribute/value.rs index b5ee365..7d9f279 100644 --- a/src/low/v7400/attribute/value.rs +++ b/src/low/v7400/attribute/value.rs @@ -13,9 +13,7 @@ use crate::low::v7400::AttributeType; /// * `get_*_or_type()` returns `Result<_, AttributeType>`. /// + If a value of the expected type available, returns `Ok(_)`. /// + If not, returns `Ok(ty)` where `ty` is value type (same value as -/// returned by [`type_()`][`type_`]. -/// -/// [`type_`]: #method.type_ +/// returned by [`type_`][`Self::type_()`] method. #[derive(Debug, Clone, PartialEq)] pub enum AttributeValue { /// Single `bool`. @@ -46,6 +44,7 @@ pub enum AttributeValue { Binary(Vec), } +/// Implement direct value getters. macro_rules! impl_val_getter { ($variant:ident, $ty_ret:ty, $opt_getter:ident, $opt_doc:expr, $res_getter:ident, $res_doc:expr,) => { #[doc = $opt_doc] @@ -63,9 +62,10 @@ macro_rules! impl_val_getter { _ => Err(self.type_()), } } - } + }; } +/// Implement value reference getters. macro_rules! impl_ref_getter { ($variant:ident, $ty_ret:ty, $opt_getter:ident, $opt_doc:expr, $res_getter:ident, $res_doc:expr,) => { #[doc = $opt_doc] @@ -83,7 +83,7 @@ macro_rules! impl_ref_getter { _ => Err(self.type_()), } } - } + }; } impl AttributeValue { @@ -254,6 +254,7 @@ impl AttributeValue { } } +/// Implement `From` trait. macro_rules! impl_from { (direct: $ty:ty, $variant:ident) => { impl From<$ty> for AttributeValue { diff --git a/src/low/v7400/node_header.rs b/src/low/v7400/node_header.rs index 73ef7e3..b1178f7 100644 --- a/src/low/v7400/node_header.rs +++ b/src/low/v7400/node_header.rs @@ -29,6 +29,7 @@ impl NodeHeader { /// Returns node end marker. #[cfg(feature = "writer")] + #[cfg_attr(feature = "docsrs", doc(cfg(feature = "writer")))] pub(crate) fn node_end() -> Self { Self { end_offset: 0, diff --git a/src/pull_parser.rs b/src/pull_parser.rs index 835fe3e..1edd7e3 100644 --- a/src/pull_parser.rs +++ b/src/pull_parser.rs @@ -7,7 +7,7 @@ //! These modules are common among all supported FBX versions: //! //! * Error types (defined in [`error`] module). -//! * [`AnyParser`] feature (defined in [`any`] module). +//! * [`AnyParser`][`any::AnyParser`] feature (defined in [`any`] module). //! * Parser source traits and wrappers (defined in [`reader`] module). //! //! # Using pull parser @@ -81,11 +81,6 @@ //! ), //! } //! ``` -//! -//! [`any`]: any/index.html -//! [`error`]: error/index.html -//! [`reader`]: reader/index.html -//! [`AnyParser`]: any/enum.AnyParser.html pub use self::{ error::{Error, Result, Warning}, diff --git a/src/pull_parser/any.rs b/src/pull_parser/any.rs index 0b9c5f4..63c68c4 100644 --- a/src/pull_parser/any.rs +++ b/src/pull_parser/any.rs @@ -50,9 +50,6 @@ fn parser_version(header: FbxHeader) -> Result { /// This works for seekable readers (which implement [`std::io::Seek`]), but /// [`from_seekable_reader`] should be used for them, because it is more /// efficent. -/// -/// [`std::io::Seek`]: https://doc.rust-lang.org/stable/std/io/trait.Seek.html -/// [`from_seekable_reader`]: fn.from_seekable_reader.html pub fn from_reader(mut reader: R) -> Result>> { let header = FbxHeader::load(&mut reader)?; match parser_version(header)? { diff --git a/src/pull_parser/reader.rs b/src/pull_parser/reader.rs index 6773875..8c4eed7 100644 --- a/src/pull_parser/reader.rs +++ b/src/pull_parser/reader.rs @@ -25,9 +25,7 @@ mod source; /// A trait for types which can be data sources. /// /// Users can implement this manually, but usually it is enough to use wrappers -/// in the [`reader`] module. -/// -/// [`reader`]: index.html +/// in the [`reader`][`self`] module. pub trait ParserSource: Sized + io::Read { /// Returns the offset of a byte which would be read next. /// @@ -35,12 +33,9 @@ pub trait ParserSource: Sized + io::Read { /// as possible. /// /// Reader types with [`std::io::Seek`] can implement this as - /// `self.seek(SeekFrom::Current(0)).unwrap()`, but this is fallible and + /// `self.stream_position().unwrap()`, but this is fallible and /// can be inefficient. /// Use of [`PositionCacheReader`] is reccomended. - /// - /// [`std::io::Seek`]: https://doc.rust-lang.org/stable/std/io/trait.Seek.html - /// [`PositionCacheReader`]: struct.PositionCacheReader.html fn position(&self) -> u64; /// Skips (seeks formward) the given size. @@ -62,9 +57,6 @@ pub trait ParserSource: Sized + io::Read { /// reader.skip_distance(7).expect("Failed to skip"); /// assert_eq!(reader.position(), 7); /// ``` - /// - /// [`std::io::Seek::seek`]: - /// https://doc.rust-lang.org/stable/std/io/trait.Seek.html#tymethod.seek fn skip_distance(&mut self, distance: u64) -> io::Result<()> { // NOTE: `let mut limited = self.by_ref().take(distance);` is E0507. let mut limited = io::Read::take(self.by_ref(), distance); @@ -95,9 +87,6 @@ pub trait ParserSource: Sized + io::Read { /// reader.skip_to(7).expect("Failed to skip"); /// assert_eq!(reader.position(), 7); /// ``` - /// - /// [`std::io::Seek::seek`]: - /// https://doc.rust-lang.org/stable/std/io/trait.Seek.html#tymethod.seek fn skip_to(&mut self, pos: u64) -> io::Result<()> { let distance = pos .checked_sub(self.position()) diff --git a/src/pull_parser/reader/position_cache.rs b/src/pull_parser/reader/position_cache.rs index 0f24afc..f586e93 100644 --- a/src/pull_parser/reader/position_cache.rs +++ b/src/pull_parser/reader/position_cache.rs @@ -62,7 +62,7 @@ impl PositionCacheReader { /// /// A seek beyond the end of a stream is allowed, but behavior is defined by /// the implementation. - /// See the document for [`std::io::Seek::seek()`][`std::io::Seek::seek`]. + /// See the document for [`std::io::Seek::seek()`]. /// /// # Examples /// @@ -79,9 +79,6 @@ impl PositionCacheReader { /// reader.skip_distance(7).expect("Failed to skip"); /// assert_eq!(reader.position(), 7); /// ``` - /// - /// [`std::io::Seek::seek`]: - /// https://doc.rust-lang.org/stable/std/io/trait.Seek.html#tymethod.seek pub fn skip_distance(&mut self, mut distance: u64) -> io::Result<()> where R: io::Seek, diff --git a/src/pull_parser/reader/source.rs b/src/pull_parser/reader/source.rs index ca94471..dae0ccf 100644 --- a/src/pull_parser/reader/source.rs +++ b/src/pull_parser/reader/source.rs @@ -12,10 +12,6 @@ use crate::pull_parser::{reader::PositionCacheReader, ParserSource}; /// /// This internally uses `PositionCacheReader`, so users don't need to wrap /// readers by `PositionCacheReader` manually. -/// -/// [`std::io::Seek`]: https://doc.rust-lang.org/stable/std/io/trait.Seek.html -/// [`PositionCacheReader`]: struct.PositionCacheReader.html -/// [`SeekableSource`]: struct.SeekableSource.html #[derive(Debug, Clone, Copy)] pub struct PlainSource { /// Inner reader. @@ -93,9 +89,6 @@ impl ParserSource for PlainSource { /// /// This internally uses [`PositionCacheReader`], so users don't need to wrap /// readers by [`PositionCacheReader`] manually. -/// -/// [`PlainSource`]: struct.PlainSource.html -/// [`PositionCacheReader`]: struct.PositionCacheReader.html #[derive(Debug, Clone, Copy)] pub struct SeekableSource { /// Inner reader. diff --git a/src/pull_parser/v7400.rs b/src/pull_parser/v7400.rs index 0170624..331df39 100644 --- a/src/pull_parser/v7400.rs +++ b/src/pull_parser/v7400.rs @@ -1,8 +1,6 @@ //! Parser-related stuff for FBX 7.4 or later. //! -//! To see how to setup a parser, see module documentation of [`pull_parser`]. -//! -//! [`pull_parser`]: ../index.html +//! To see how to setup a parser, see module documentation of [`pull_parser`][`super`]. pub(crate) use self::read::{FromParser, FromReader}; pub use self::{ diff --git a/src/pull_parser/v7400/attribute/array.rs b/src/pull_parser/v7400/attribute/array.rs index 0bfccfd..7234251 100644 --- a/src/pull_parser/v7400/attribute/array.rs +++ b/src/pull_parser/v7400/attribute/array.rs @@ -47,8 +47,9 @@ impl io::Read for AttributeStreamDecoder { pub(crate) struct ArrayAttributeValues { /// Decoded reader. reader: R, - /// Number of total elements. - total_elements: u32, + // `total_elements`: unused. + ///// Number of total elements. + //total_elements: u32, /// Number of rest elements. rest_elements: u32, /// Whether an error is happened. @@ -65,7 +66,7 @@ where pub(crate) fn new(reader: R, total_elements: u32) -> Self { Self { reader, - total_elements, + //total_elements, rest_elements: total_elements, has_error: false, _element_type: PhantomData, @@ -78,6 +79,7 @@ where } } +/// Implement common traits for `ArrayAttributeValues`. macro_rules! impl_array_attr_values { ($ty_elem:ty, $read_elem:ident) => { impl Iterator for ArrayAttributeValues { @@ -108,6 +110,8 @@ macro_rules! impl_array_attr_values { (0, Some(self.rest_elements as usize)) } } + + impl std::iter::FusedIterator for ArrayAttributeValues {} }; } @@ -121,8 +125,9 @@ impl_array_attr_values! { f64, read_f64 } pub(crate) struct BooleanArrayAttributeValues { /// Decoded reader. reader: R, - /// Number of total elements. - total_elements: u32, + // `total_elements`: unused. + ///// Number of total elements. + //total_elements: u32, /// Number of rest elements. rest_elements: u32, /// Whether an error is happened. @@ -136,7 +141,7 @@ impl BooleanArrayAttributeValues { pub(crate) fn new(reader: R, total_elements: u32) -> Self { Self { reader, - total_elements, + //total_elements, rest_elements: total_elements, has_error: false, has_incorrect_boolean_value: false, @@ -187,3 +192,5 @@ impl Iterator for BooleanArrayAttributeValues { (0, Some(self.rest_elements as usize)) } } + +impl std::iter::FusedIterator for BooleanArrayAttributeValues {} diff --git a/src/pull_parser/v7400/attribute/iter.rs b/src/pull_parser/v7400/attribute/iter.rs index 1e8cf52..fb63547 100644 --- a/src/pull_parser/v7400/attribute/iter.rs +++ b/src/pull_parser/v7400/attribute/iter.rs @@ -1,6 +1,7 @@ //! Node attribute iterators. use std::io; +use std::iter; use crate::pull_parser::{ v7400::attribute::{loader::LoadAttribute, Attributes}, @@ -65,7 +66,7 @@ where I: Iterator, V: LoadAttribute, { - /// Creates a new `Iter`. + /// Creates a new iterator. pub(crate) fn new(attributes: &'a mut Attributes<'r, R>, loaders: I) -> Self { Self { attributes, @@ -83,14 +84,22 @@ where type Item = Result; fn next(&mut self) -> Option { - load_next(&mut self.attributes, &mut self.loaders) + load_next(self.attributes, &mut self.loaders) } fn size_hint(&self) -> (usize, Option) { - make_size_hint_for_attrs(&self.attributes, &self.loaders) + make_size_hint_for_attrs(self.attributes, &self.loaders) } } +impl<'a, 'r, R, I, V> iter::FusedIterator for BorrowedIter<'a, 'r, R, I> +where + R: ParserSource, + I: Iterator, + V: LoadAttribute, +{ +} + /// Node attributes iterator with buffered I/O. #[derive(Debug)] pub struct BorrowedIterBuffered<'a, 'r, R, I> { @@ -106,7 +115,7 @@ where I: Iterator, V: LoadAttribute, { - /// Creates a new `IterBuffered`. + /// Creates a new iterator. pub(crate) fn new(attributes: &'a mut Attributes<'r, R>, loaders: I) -> Self { Self { attributes, @@ -124,14 +133,22 @@ where type Item = Result; fn next(&mut self) -> Option { - load_next_buffered(&mut self.attributes, &mut self.loaders) + load_next_buffered(self.attributes, &mut self.loaders) } fn size_hint(&self) -> (usize, Option) { - make_size_hint_for_attrs(&self.attributes, &self.loaders) + make_size_hint_for_attrs(self.attributes, &self.loaders) } } +impl<'a, 'r, R, I, V> iter::FusedIterator for BorrowedIterBuffered<'a, 'r, R, I> +where + R: ParserSource + io::BufRead, + I: Iterator, + V: LoadAttribute, +{ +} + /// Node attributes iterator. #[derive(Debug)] pub struct OwnedIter<'r, R, I> { @@ -173,6 +190,14 @@ where } } +impl<'r, R, I, V> iter::FusedIterator for OwnedIter<'r, R, I> +where + R: ParserSource, + I: Iterator, + V: LoadAttribute, +{ +} + /// Node attributes iterator with buffered I/O. #[derive(Debug)] pub struct OwnedIterBuffered<'r, R, I> { @@ -188,7 +213,7 @@ where I: Iterator, V: LoadAttribute, { - /// Creates a new `IterBuffered`. + /// Creates a new iterator. pub(crate) fn new(attributes: Attributes<'r, R>, loaders: I) -> Self { Self { attributes, @@ -213,3 +238,11 @@ where make_size_hint_for_attrs(&self.attributes, &self.loaders) } } + +impl<'r, R, I, V> iter::FusedIterator for OwnedIterBuffered<'r, R, I> +where + R: ParserSource + io::BufRead, + I: Iterator, + V: LoadAttribute, +{ +} diff --git a/src/pull_parser/v7400/attribute/loader.rs b/src/pull_parser/v7400/attribute/loader.rs index 543703d..10e7440 100644 --- a/src/pull_parser/v7400/attribute/loader.rs +++ b/src/pull_parser/v7400/attribute/loader.rs @@ -16,10 +16,8 @@ use crate::pull_parser::{error::DataError, Result}; /// attribute". /// Users should implement them manually for types they want to interpret. /// -/// For simple types, [`pull_parser::v7400::attribute::loaders`] module contains +/// For simple types, [`pull_parser::v7400::attribute::loaders`][`super::loaders`] module contains /// useful loaders. -/// -/// [`pull_parser::v7400::attribute::loaders`]: loaders/index.html pub trait LoadAttribute: Sized + fmt::Debug { /// Result type on successful read. type Output; diff --git a/src/pull_parser/v7400/attribute/loaders/direct.rs b/src/pull_parser/v7400/attribute/loaders/direct.rs index 6dc12e2..8715792 100644 --- a/src/pull_parser/v7400/attribute/loaders/direct.rs +++ b/src/pull_parser/v7400/attribute/loaders/direct.rs @@ -8,8 +8,6 @@ use crate::{ }; /// Loader for [`AttributeValue`]. -/// -/// [`AttributeValue`]: ../../../../low/v7400/enum.AttributeValue.html #[derive(Default, Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct DirectLoader; diff --git a/src/pull_parser/v7400/attribute/loaders/type_.rs b/src/pull_parser/v7400/attribute/loaders/type_.rs index 0b488d0..cdc3eef 100644 --- a/src/pull_parser/v7400/attribute/loaders/type_.rs +++ b/src/pull_parser/v7400/attribute/loaders/type_.rs @@ -11,8 +11,6 @@ use crate::{ /// /// This returns only node attribute type ([`AttributeType`]) and discands /// its real value. -/// -/// [`AttributeType`]: ../../../../low/v7400/enum.AttributeType.html #[derive(Default, Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct TypeLoader; diff --git a/src/pull_parser/v7400/parser.rs b/src/pull_parser/v7400/parser.rs index 7d6dcd2..7dcafee 100644 --- a/src/pull_parser/v7400/parser.rs +++ b/src/pull_parser/v7400/parser.rs @@ -21,8 +21,6 @@ type WarningHandler = Box Result<()>>; /// Creates a new [`Parser`] from the given reader. /// /// Returns an error if the given FBX version in unsupported. -/// -/// [`Parser`]: struct.Parser.html pub fn from_reader(header: FbxHeader, reader: R) -> Result>> where R: io::Read, @@ -36,8 +34,6 @@ where /// Creates a new [`Parser`] from the given seekable reader. /// /// Returns an error if the given FBX version in unsupported. -/// -/// [`Parser`]: struct.Parser.html pub fn from_seekable_reader(header: FbxHeader, reader: R) -> Result>> where R: io::Read + io::Seek, @@ -107,7 +103,7 @@ impl Parser { /// }); /// ``` /// - /// [syntactic position]: ../struct.SyntacticPosition.html + /// [syntactic position]: `SyntacticPosition` pub fn set_warning_handler(&mut self, warning_handler: F) where F: 'static + FnMut(Warning, &SyntacticPosition) -> Result<()>, @@ -187,9 +183,6 @@ impl Parser { /// already failed and returned error. /// If you call `next_event()` with failed parser, error created from /// [`OperationError::AlreadyAborted`] will be returned. - /// - /// [`OperationError::AlreadyAborted`]: - /// ../error/enum.OperationError.html#variant.AlreadyAborted pub fn next_event(&mut self) -> Result> { let previous_depth = self.current_depth(); @@ -293,19 +286,14 @@ impl Parser { let has_children = self.state.last_event_kind() == Some(EventKind::EndNode); let has_attributes = current_node.attributes_count != 0; - if !has_children && has_attributes { - // Ok, the current node implicitly ends here without node - // end marker. - self.state.started_nodes.pop(); - return Ok(EventKind::EndNode); - } else { + if has_children || !has_attributes { // It's odd, the current node should have a node end marker // at the ending, but `node_end_offset` data tells that the // node ends without node end marker. self.warn(Warning::MissingNodeEndMarker, self.position())?; - self.state.started_nodes.pop(); - return Ok(EventKind::EndNode); } + self.state.started_nodes.pop(); + return Ok(EventKind::EndNode); } } @@ -411,12 +399,12 @@ impl Parser { /// Because of this, some errors can be overlooked, or detected at the /// different position from the true error position. /// - /// To detect errors correctly, you should use [`next_event`] manually. + /// To detect errors correctly, you should use [`next_event`][`Self::next_event`] manually. /// See an example to how to do this. /// /// # Panics /// - /// Panics if there are no open nodes, i.e. when [`current_depth()`][`current_depth`] + /// Panics if there are no open nodes, i.e. when [`current_depth()`][`Self::current_depth`] /// returns 0. /// /// # Examples @@ -452,9 +440,7 @@ impl Parser { /// } /// ``` /// - /// [`next_event`]: #method.next_event - /// [`current_depth`]: #method.current_depth - /// [`EndNode`]: enum.Event.html#variant.EndNode + /// [`EndNode`]: `Event::EndNode` pub fn skip_current_node(&mut self) -> Result<()> { let end_pos = self .state diff --git a/src/pull_parser/v7400/read.rs b/src/pull_parser/v7400/read.rs index 28648d5..b4fe571 100644 --- a/src/pull_parser/v7400/read.rs +++ b/src/pull_parser/v7400/read.rs @@ -18,6 +18,7 @@ impl FromReader for u8 { } } +/// Implement `FromReader` trait for primitive types. macro_rules! impl_from_reader_for_primitives { ($ty:ty, $read_method:ident) => { impl FromReader for $ty { diff --git a/src/tree.rs b/src/tree.rs index b06682d..4c3a4c4 100644 --- a/src/tree.rs +++ b/src/tree.rs @@ -43,9 +43,6 @@ //! //! About tree loaders, see [`v7400::Loader`]. //! (Currently, only `v7400` tree is supported.) -//! -//! [`any`]: any/index.html -//! [`v7400::Loader`]: v7400/struct.Loader.html pub mod any; pub mod v7400; diff --git a/src/tree/any.rs b/src/tree/any.rs index 818f41e..2186840 100644 --- a/src/tree/any.rs +++ b/src/tree/any.rs @@ -27,8 +27,8 @@ pub enum AnyTree { impl AnyTree { /// Loads a tree from the given reader. /// - /// This works for seekable readers (which implement `std::io::Seek`), but - /// `from_seekable_reader` should be used for them, because it is more + /// This works for seekable readers (which implement [`std::io::Seek`]), but + /// [`from_seekable_reader`][`Self::from_seekable_reader`] should be used for them, because it is more /// efficent. pub fn from_reader(reader: impl Read) -> Result { match pull_parser::any::from_reader(reader)? { diff --git a/src/tree/v7400.rs b/src/tree/v7400.rs index f80c852..2620b06 100644 --- a/src/tree/v7400.rs +++ b/src/tree/v7400.rs @@ -3,7 +3,7 @@ use std::fmt; use indextree::Arena; -use string_interner::StringInterner; +use string_interner::{DefaultBackend, StringInterner}; use crate::low::v7400::AttributeValue; @@ -11,7 +11,10 @@ use self::node::{NodeData, NodeNameSym}; pub use self::{ error::LoadError, loader::Loader, - node::{handle::NodeHandle, NodeId}, + node::{ + handle::{Children, ChildrenByName, NodeHandle}, + NodeId, + }, }; mod macros; @@ -26,7 +29,7 @@ pub struct Tree { /// Tree data. arena: Arena, /// Node name interner. - node_names: StringInterner, + node_names: StringInterner>, /// (Implicit) root node ID. root_id: NodeId, } @@ -34,13 +37,13 @@ pub struct Tree { impl Tree { /// Returns the root node. pub fn root(&self) -> NodeHandle<'_> { - NodeHandle::new(&self, self.root_id) + NodeHandle::new(self, self.root_id) } /// Creates a new `Tree`. fn new( arena: Arena, - node_names: StringInterner, + node_names: StringInterner>, root_id: NodeId, ) -> Self { Self { @@ -53,6 +56,7 @@ impl Tree { /// Returns internally managed node data. /// /// # Panics + /// /// Panics if a node with the given node ID does not exist in the tree. pub(crate) fn node(&self, node_id: NodeId) -> &indextree::Node { self.arena.get(node_id.raw()).unwrap_or_else(|| { @@ -173,7 +177,7 @@ impl Tree { /// Pretty-print the tree for debugging purpose. /// /// Be careful, this output format may change in future. - pub fn debug_tree<'a>(&'a self) -> impl fmt::Debug + 'a { + pub fn debug_tree(&self) -> impl fmt::Debug + '_ { DebugTree { tree: self } } } diff --git a/src/tree/v7400/loader.rs b/src/tree/v7400/loader.rs index 6edfab4..0afbd94 100644 --- a/src/tree/v7400/loader.rs +++ b/src/tree/v7400/loader.rs @@ -2,7 +2,7 @@ use indextree::Arena; use log::{debug, error, trace}; -use string_interner::StringInterner; +use string_interner::{DefaultBackend, StringInterner}; use crate::{ low::v7400::FbxFooter, @@ -19,7 +19,7 @@ pub struct Loader { /// Tree data. arena: Arena, /// Node name interner. - node_names: StringInterner, + node_names: StringInterner>, /// (Implicit) root node ID. root_id: NodeId, } @@ -40,9 +40,6 @@ impl Loader { /// /// If the tree is successfully read but FBX footer is not, /// `Ok(tree, Err(parser_error))` is returned. - /// - /// [`LoadError::BadParser`]: enum.LoadError.html#variant.BadParser - /// [`Parser::is_used()`]: ../../pull_parser/v7400/struct.Parser.html#method.is_used pub fn load( mut self, parser: &mut Parser, diff --git a/src/tree/v7400/macros.rs b/src/tree/v7400/macros.rs index ae93ecc..bb56144 100644 --- a/src/tree/v7400/macros.rs +++ b/src/tree/v7400/macros.rs @@ -28,9 +28,10 @@ /// // `IntoIterator`. /// Node2: (vec!["hello".into(), "world".into(), 42i32.into()]) {} /// // Use brackets to specify attributes one by one. -/// Node3: ["hello", "world", 3.14f32, &b"BINARY"[..]] {} +/// Node3: ["hello", "world", 1.234f32, &b"BINARY"[..]] {} /// }; /// ``` +#[cfg_attr(feature = "docsrs", doc(cfg(feature = "tree")))] #[macro_export] macro_rules! tree_v7400 { (@__node, $tree:ident, $parent:ident,) => {}; @@ -131,7 +132,7 @@ mod tests { let _ = tree_v7400! { Hello: { Hello1: (vec!["string".into()]) {}, - Hello2: [3.14f32, 42i64] {} + Hello2: [1.234f32, 42i64] {} } World: { World1: { @@ -156,7 +157,7 @@ mod tests { Node1_2_child: {}, }, }, - Node2: [true, 42i16, 42i32, 42i64, 1.414f32, 3.14f64] { + Node2: [true, 42i16, 42i32, 42i64, 1.414f32, 1.234f64] { Node2_0: (vec![vec![true, false].into(), vec![0i32, 42i32].into()]) {}, Node2_1: [ vec![std::f32::NAN, std::f32::INFINITY], @@ -188,7 +189,7 @@ mod tests { tree.append_attribute(node1_id, true); let node1_0_id = tree.append_new(node1_id, "Node1_0"); tree.append_attribute(node1_0_id, 42i32); - tree.append_attribute(node1_0_id, 3.14f64); + tree.append_attribute(node1_0_id, 1.234f64); let node1_1_id = tree.append_new(node1_id, "Node1_1"); tree.append_attribute(node1_1_id, &[1u8, 2, 4, 8, 16] as &[_]); tree.append_attribute(node1_1_id, "Hello, world"); @@ -202,7 +203,7 @@ mod tests { Node0_1: {}, }, Node1: [true] { - Node1_0: (vec![42i32.into(), 3.14f64.into()]) {} + Node1_0: (vec![42i32.into(), 1.234f64.into()]) {} Node1_1: [&[1u8, 2, 4, 8, 16][..], "Hello, world"] {} }, }; diff --git a/src/tree/v7400/node.rs b/src/tree/v7400/node.rs index 40044f4..0a1c238 100644 --- a/src/tree/v7400/node.rs +++ b/src/tree/v7400/node.rs @@ -1,7 +1,5 @@ //! Node type. -use indextree; - use crate::tree::v7400::{NodeHandle, Tree}; pub(crate) use self::{data::NodeData, name::NodeNameSym}; @@ -31,9 +29,9 @@ impl NodeId { /// /// This may panic if the given node ID is not used in the given tree. /// - /// Even if `new()` does not panic, subsequent operations through - /// `NodeHandle` object may panic if the given node ID is not used in the - /// given tree. + /// Even if creation of an invalid node ID does not panic, subsequent + /// operations through `NodeHandle` object may panic if the given node ID is + /// not used in the given tree. pub fn to_handle(self, tree: &Tree) -> NodeHandle<'_> { NodeHandle::new(tree, self) } diff --git a/src/tree/v7400/node/handle.rs b/src/tree/v7400/node/handle.rs index e1d0799..01bca11 100644 --- a/src/tree/v7400/node/handle.rs +++ b/src/tree/v7400/node/handle.rs @@ -1,5 +1,7 @@ //! Node handle. +use std::fmt; + use crate::{ low::v7400::AttributeValue, tree::v7400::{NodeData, NodeId, NodeNameSym, Tree}, @@ -65,24 +67,29 @@ impl<'a> NodeHandle<'a> { } /// Returns an iterator of children with the given name. - pub fn children(&self) -> impl Iterator> + 'a { - let tree = self.tree; - self.node_id - .raw() - .children(&tree.arena) - .map(move |child_id| NodeId::new(child_id).to_handle(tree)) + #[inline] + #[must_use] + pub fn children(&self) -> Children<'a> { + Children { + tree: self.tree, + iter: self.node_id.raw().children(&self.tree.arena), + } } /// Returns an iterator of children with the given name. - pub fn children_by_name(&self, name: &str) -> impl Iterator> + 'a { - // Using `flat_map` for `Option`, the iterator can return - // `None` before without traversing the tree if `target_name` is not - // registered. - self.tree - .node_name_sym(name) - .map(|sym| self.children().filter(move |child| child.name_sym() == sym)) - .into_iter() - .flatten() + #[inline] + #[must_use] + pub fn children_by_name(&self, name: &str) -> ChildrenByName<'a> { + ChildrenByName { + name_sym: self.tree.node_name_sym(name), + children_iter: self.children(), + } + } + + /// Returns the first child with the given name. + #[must_use] + pub fn first_child_by_name(&self, name: &str) -> Option { + self.children_by_name(name).next() } /// Compares nodes strictly. @@ -98,6 +105,7 @@ impl<'a> NodeHandle<'a> { } } +/// Implement accessors to neighbor nodes. macro_rules! impl_related_node_accessor { ( $( @@ -169,3 +177,58 @@ fn nodes_strict_eq(left: NodeHandle<'_>, right: NodeHandle<'_>) -> bool { } true } + +/// An iterator of children of a node. +#[derive(Clone)] +pub struct Children<'a> { + /// Tree. + tree: &'a Tree, + /// Raw node children iterator. + iter: indextree::Children<'a, NodeData>, +} + +impl<'a> Iterator for Children<'a> { + type Item = NodeHandle<'a>; + + fn next(&mut self) -> Option { + let child_id = self.iter.next()?; + Some(NodeId::new(child_id).to_handle(self.tree)) + } +} + +impl std::iter::FusedIterator for Children<'_> {} + +impl<'a> fmt::Debug for Children<'a> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_struct("Children").finish() + } +} + +/// An iterator of children of a node, with a specific name. +#[derive(Clone)] +pub struct ChildrenByName<'a> { + /// Name symbol. + name_sym: Option, + /// Children node iterator. + children_iter: Children<'a>, +} + +impl<'a> Iterator for ChildrenByName<'a> { + type Item = NodeHandle<'a>; + + fn next(&mut self) -> Option { + let name_sym = self.name_sym?; + self.children_iter + .find(|child| child.name_sym() == name_sym) + } +} + +impl std::iter::FusedIterator for ChildrenByName<'_> {} + +impl<'a> fmt::Debug for ChildrenByName<'a> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_struct("ChildrenByName") + .field("name_sym", &self.name_sym) + .finish() + } +} diff --git a/src/tree/v7400/node/name.rs b/src/tree/v7400/node/name.rs index 42c27a6..be1725d 100644 --- a/src/tree/v7400/node/name.rs +++ b/src/tree/v7400/node/name.rs @@ -1,21 +1,21 @@ //! Node name. -use string_interner::{self, Sym}; +use string_interner::symbol::{Symbol, SymbolU32}; /// Symbol for interned node name. // This is an opaque-typedef pattern. // `string_interner::Sym` has efficient implementation, so use it internally. #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] -pub(crate) struct NodeNameSym(Sym); +pub(crate) struct NodeNameSym(SymbolU32); -impl string_interner::Symbol for NodeNameSym { +impl Symbol for NodeNameSym { /// This may panic if the given value is too large. /// /// As of writing this, string-interner 0.7.0 panics if the given value is /// greater than `u32::max_value() - 1`. /// See [`string_interner::Sym`] for detail. - fn from_usize(v: usize) -> Self { - Self(Sym::from_usize(v)) + fn try_from_usize(v: usize) -> Option { + SymbolU32::try_from_usize(v).map(Self) } fn to_usize(self) -> usize { diff --git a/src/writer/v7400/binary.rs b/src/writer/v7400/binary.rs index 798fc82..7c100cb 100644 --- a/src/writer/v7400/binary.rs +++ b/src/writer/v7400/binary.rs @@ -89,13 +89,6 @@ //! //! # Ok::<_, fbxcel::writer::v7400::binary::Error>(()) //! ``` -//! -//! [`AttributesWriter`]: struct.AttributesWriter.html -//! [`Writer::close_node`]: struct.Writer.html#method.close_node -//! [`Writer::finalize`]: struct.Writer.html#method.finalize -//! [`Writer::finalize_and_flush`]: struct.Writer.html#method.finalize_and_flush -//! [`Writer::new`]: struct.Writer.html#method.new -//! [`Writer::new_node`]: struct.Writer.html#method.new_node use std::{ convert::TryFrom, @@ -120,7 +113,7 @@ mod footer; /// Binary writer. /// -/// See [module documentation](index.html) for usage. +/// See [module documentation][`self`] for usage. #[derive(Debug, Clone)] pub struct Writer { /// Writer destination. @@ -218,7 +211,7 @@ impl Writer { return Ok(()); } - let current_pos = self.sink.seek(SeekFrom::Current(0))?; + let current_pos = self.sink.stream_position()?; current_node.header.bytelen_attributes = current_pos - current_node.body_pos; current_node.is_attrs_finalized = true; @@ -244,7 +237,7 @@ impl Writer { let bytelen_name = u8::try_from(name.len()).map_err(|_| Error::NodeNameTooLong(name.len()))?; - let header_pos = self.sink.seek(SeekFrom::Current(0))?; + let header_pos = self.sink.stream_position()?; let header = NodeHeader { end_offset: 0, @@ -259,7 +252,7 @@ impl Writer { // Write node name. self.sink.write_all(name.as_ref())?; - let body_pos = self.sink.seek(SeekFrom::Current(0))?; + let body_pos = self.sink.stream_position()?; self.open_nodes.push(OpenNode { header_pos, @@ -288,7 +281,7 @@ impl Writer { } // Update node header. - let node_end_pos = self.sink.seek(SeekFrom::Current(0))?; + let node_end_pos = self.sink.stream_position()?; self.sink.seek(SeekFrom::Start(current_node.header_pos))?; current_node.header.end_offset = node_end_pos; assert_eq!( @@ -304,6 +297,7 @@ impl Writer { /// Writes the given tree. #[cfg(feature = "tree")] + #[cfg_attr(feature = "docsrs", doc(cfg(feature = "tree")))] pub fn write_tree(&mut self, tree: &crate::tree::v7400::Tree) -> Result<()> { use crate::low::v7400::AttributeValue; @@ -370,9 +364,7 @@ impl Writer { /// Finalizes the FBX binary and returns the inner sink. /// - /// You may want to use [`finalize_and_flush()`]. - /// - /// [`finalize_and_flush()`]: #method.finalize_and_flush + /// You may want to use [`finalize_and_flush()`][`Self::finalize_and_flush()`]. pub fn finalize(mut self, footer: &FbxFooter<'_>) -> Result { self.finalize_impl(footer)?; @@ -401,7 +393,7 @@ impl Writer { { let len = match footer.padding_len { FbxFooterPaddingLength::Default => { - let current = self.sink.seek(SeekFrom::Current(0))?; + let current = self.sink.stream_position()?; current.wrapping_neg() & 0x0f } FbxFooterPaddingLength::Forced(len) => u64::from(len), diff --git a/src/writer/v7400/binary/attributes.rs b/src/writer/v7400/binary/attributes.rs index 0f9b81a..e21e04f 100644 --- a/src/writer/v7400/binary/attributes.rs +++ b/src/writer/v7400/binary/attributes.rs @@ -72,6 +72,7 @@ pub struct AttributesWriter<'a, W: Write> { writer: &'a mut Writer, } +/// Implement `append_*` methods for single value. macro_rules! impl_single_attr_append { ($( $(#[$meta:meta])* @@ -89,6 +90,7 @@ macro_rules! impl_single_attr_append { } } +/// Implement `append_*` methods for array values. macro_rules! impl_arr_from_iter { ($( $(#[$meta:meta])* @@ -155,10 +157,13 @@ impl<'a, W: Write + Seek> AttributesWriter<'a, W> { .writer .current_node_header() .expect("Should never fail: some nodes must be open if `AttributesWriter` exists"); - node_header.num_attributes = node_header - .num_attributes - .checked_add(1) - .ok_or_else(|| Error::TooManyAttributes(node_header.num_attributes as usize))?; + node_header.num_attributes = + node_header + .num_attributes + .checked_add(1) + .ok_or(Error::TooManyAttributes( + node_header.num_attributes as usize, + ))?; Ok(()) } @@ -193,7 +198,7 @@ impl<'a, W: Write + Seek> AttributesWriter<'a, W> { // Write attribute header. self.write_type_code(ty)?; - let header_pos = self.writer.sink().seek(SeekFrom::Current(0))?; + let header_pos = self.writer.sink().stream_position()?; // Write array header placeholder. self.write_array_header(&ArrayAttributeHeader { @@ -210,7 +215,7 @@ impl<'a, W: Write + Seek> AttributesWriter<'a, W> { /// Note that this should be called at the end of the array attribute. fn finalize_array(&mut self, header_pos: u64, header: &ArrayAttributeHeader) -> Result<()> { // Write real array header. - let end_pos = self.writer.sink().seek(SeekFrom::Current(0))?; + let end_pos = self.writer.sink().stream_position()?; self.writer.sink().seek(SeekFrom::Start(header_pos))?; self.write_array_header(header)?; self.writer.sink().seek(SeekFrom::Start(end_pos))?; @@ -240,13 +245,13 @@ impl<'a, W: Write + Seek> AttributesWriter<'a, W> { /// Writes an `f32` array attribute. append_arr_f32_from_iter: f32 { from_result_iter: append_arr_f32_from_result_iter, - tyval: ArrI32, + tyval: ArrF32, }, /// Writes an `f64` array attribute. append_arr_f64_from_iter: f64 { from_result_iter: append_arr_f64_from_result_iter, - tyval: ArrI64, + tyval: ArrF64, }, } @@ -259,7 +264,7 @@ impl<'a, W: Write + Seek> AttributesWriter<'a, W> { self.write_type_code(ty)?; // Write special attribute header (dummy). - let header_pos = self.writer.sink().seek(SeekFrom::Current(0))?; + let header_pos = self.writer.sink().stream_position()?; self.writer.sink().write_all(&0u32.to_le_bytes())?; Ok(header_pos) @@ -273,7 +278,7 @@ impl<'a, W: Write + Seek> AttributesWriter<'a, W> { let bytelen = u32::try_from(bytelen).map_err(|_| Error::AttributeTooLong(bytelen))?; // Write real special attribute header. - let end_pos = self.writer.sink().seek(SeekFrom::Current(0))?; + let end_pos = self.writer.sink().stream_position()?; self.writer.sink().seek(SeekFrom::Start(header_pos))?; self.writer.sink().write_all(&bytelen.to_le_bytes())?; self.writer.sink().seek(SeekFrom::Start(end_pos))?; @@ -324,7 +329,7 @@ impl<'a, W: Write + Seek> AttributesWriter<'a, W> { self.writer.sink().write_all(&[v])?; len = len .checked_add(1) - .ok_or_else(|| Error::AttributeTooLong(std::usize::MAX))?; + .ok_or(Error::AttributeTooLong(std::usize::MAX))?; Ok(()) })?; @@ -350,7 +355,7 @@ impl<'a, W: Write + Seek> AttributesWriter<'a, W> { self.writer.sink().write_all(&[v])?; len = len .checked_add(1) - .ok_or_else(|| Error::AttributeTooLong(std::usize::MAX))?; + .ok_or(Error::AttributeTooLong(std::usize::MAX))?; Ok(()) })?; @@ -371,7 +376,7 @@ impl<'a, W: Write + Seek> AttributesWriter<'a, W> { self.writer.sink().write_all(buf)?; len = len .checked_add(char_len) - .ok_or_else(|| Error::AttributeTooLong(std::usize::MAX))?; + .ok_or(Error::AttributeTooLong(std::usize::MAX))?; Ok(()) })?; @@ -399,7 +404,7 @@ impl<'a, W: Write + Seek> AttributesWriter<'a, W> { self.writer.sink().write_all(buf)?; len = len .checked_add(char_len) - .ok_or_else(|| Error::AttributeTooLong(std::usize::MAX))?; + .ok_or(Error::AttributeTooLong(std::usize::MAX))?; Ok(()) })?; diff --git a/src/writer/v7400/binary/attributes/array.rs b/src/writer/v7400/binary/attributes/array.rs index 4bb9815..19aa700 100644 --- a/src/writer/v7400/binary/attributes/array.rs +++ b/src/writer/v7400/binary/attributes/array.rs @@ -2,7 +2,7 @@ use std::{ convert::TryFrom, - io::{self, Seek, SeekFrom, Write}, + io::{self, Seek, Write}, }; use crate::{ @@ -78,7 +78,7 @@ pub(crate) fn write_array_attr_result_iter write_elements_result_iter(writer.sink(), iter)?, ArrayAttributeEncoding::Zlib => { @@ -90,7 +90,7 @@ pub(crate) fn write_array_attr_result_iter`. /// Node2: (vec!["hello".into(), "world".into(), 42i32.into()]) {} /// // Use brackets to specify attributes one by one. -/// Node3: ["hello", "world", 3.14f32, &b"BINARY"[..]] {} +/// Node3: ["hello", "world", 1.234f32, &b"BINARY"[..]] {} /// }, /// )?; /// let _buf = writer.finalize_and_flush(&Default::default())?; /// # Ok::<_, Box>(()) /// ``` +#[cfg_attr(feature = "docsrs", doc(cfg(feature = "writer")))] #[macro_export] macro_rules! write_v7400_binary { ( @@ -181,7 +182,7 @@ mod tests { tree={ Hello: { Hello1: (vec!["string".into()]) {}, - Hello2: [3.14f32, 42i64] {} + Hello2: [1.234f32, 42i64] {} } World: { World1: { diff --git a/tests/write-and-parse-v7400-binary.rs b/tests/write-and-parse-v7400-binary.rs index e064b3b..f9fbda2 100644 --- a/tests/write-and-parse-v7400-binary.rs +++ b/tests/write-and-parse-v7400-binary.rs @@ -116,7 +116,7 @@ fn tree_write_v7500() -> Result<(), Box> { Node0_1: {}, }, Node1: [true] { - Node1_0: (vec![42i32.into(), 3.14f64.into()]) {} + Node1_0: (vec![42i32.into(), 1.234f64.into()]) {} Node1_1: [&[1u8, 2, 4, 8, 16][..], "Hello, world"] {} }, }, @@ -191,7 +191,7 @@ fn macro_v7400_idempotence() -> Result<(), Box> { Node0_1: {}, }, Node1: [true] { - Node1_0: (vec![42i32.into(), 3.14f64.into()]) {} + Node1_0: (vec![42i32.into(), 1.234f64.into()]) {} Node1_1: [&[1u8, 2, 4, 8, 16][..], "Hello, world"] {} }, }, @@ -243,7 +243,7 @@ fn macro_v7400_idempotence() -> Result<(), Box> { ); assert!(attrs .load_next(DirectLoader)? - .map_or(false, |attr| attr.strict_eq(&3.14f64.into()))); + .map_or(false, |attr| attr.strict_eq(&1.234f64.into()))); assert_eq!(attrs.total_count(), 2); } expect_node_end(&mut parser)?; diff --git a/tests/write-tree-and-parse-v7400-binary.rs b/tests/write-tree-and-parse-v7400-binary.rs index 193bf86..6da82b2 100644 --- a/tests/write-tree-and-parse-v7400-binary.rs +++ b/tests/write-tree-and-parse-v7400-binary.rs @@ -22,7 +22,7 @@ fn tree_write_parse_idempotence_v7500() -> Result<(), Box Node0_1: {}, }, Node1: [true] { - Node1_0: (vec![42i32.into(), 3.14f64.into()]) {} + Node1_0: (vec![42i32.into(), 1.234f64.into()]) {} Node1_1: [&[1u8, 2, 4, 8, 16][..], "Hello, world"] {} }, };