prek-serde-saphyr 1.2.0

YAML (de)serializer for Serde, emphasizing panic-free parsing, fast builds and good error reporting. Supports properties, comments, include
Documentation
//! Single-pass YAML serializer with optional anchors for Rc/Arc/Weak,
//! order preservation (uses the iterator order of your types), simple
//! style controls (block strings & flow containers), and special
//! float handling for NaN/±Inf. No intermediate YAML DOM is built.
//!
//! Usage example:
//!
//! ```
//! use serde::Serialize;
//! use std::rc::Rc;
//! use serde_saphyr::{to_string, RcAnchor, LitStr, FlowSeq};
//!
//! #[derive(Serialize)]
//! struct Cfg {
//!     name: String,
//!     ports: FlowSeq<Vec<u16>>,   // render `[8080, 8081]`
//!     note: LitStr<'static>,      // render as `|` block
//!     data: RcAnchor<Vec<i32>>,   // first sight => &a1
//!     alias: RcAnchor<Vec<i32>>,  // later sight => *a1
//! }
//!
//! fn main() {
//!     let shared = Rc::new(vec![1,2,3]);
//!     let cfg = Cfg {
//!         name: "demo".into(),
//!         ports: FlowSeq(vec![8080, 8081]),
//!         note: LitStr("line 1\nline 2"),
//!         data: RcAnchor(shared.clone()),
//!         alias: RcAnchor(shared),
//!     };
//!     println!("{}", to_string(&cfg).unwrap());
//! }
//! ```

use serde_core::ser::Error as _;

pub(crate) mod api;
pub mod error;
pub mod options;
pub(crate) mod quoting;
mod serializer;
mod wrapper_impls;
mod wrapping;
mod zmij_format;

pub use self::error::Error;
pub use self::serializer::YamlSerializer;
#[doc(hidden)]
pub use self::serializer::{MapSer, SeqSer, StructVariantSer, TupleSer};

/// Result alias.
pub type Result<T> = std::result::Result<T, Error>;

#[inline]
fn checked_indentation(indent_step: usize, depth: usize) -> Result<usize> {
    indent_step
        .checked_mul(depth)
        .ok_or_else(|| Error::custom("serializer indentation exceeds usize"))
}

#[inline]
fn checked_depth_add(depth: usize, additional_levels: usize) -> Result<usize> {
    depth
        .checked_add(additional_levels)
        .ok_or_else(|| Error::custom("serializer indentation depth exceeds usize"))
}

pub use crate::long_strings::{FoldStr, FoldString, LitStr, LitString};

// Flow hints and block-string hints: we use newtype-struct names.
const NAME_TUPLE_ANCHOR: &str = "__yaml_anchor";
const NAME_TUPLE_WEAK: &str = "__yaml_weak_anchor";
const NAME_FLOW_SEQ: &str = "__yaml_flow_seq";
const NAME_FLOW_MAP: &str = "__yaml_flow_map";
const NAME_TUPLE_COMMENTED: &str = "__yaml_commented";
const NAME_SPACE_AFTER: &str = "__yaml_space_after";
const NAME_DOUBLE_QUOTED: &str = "__yaml_double_quoted";
const NAME_SINGLE_QUOTED: &str = "__yaml_single_quoted";
const NAME_NULLABLE_TILDE: &str = "__yaml_nullable_tilde";

#[cfg(test)]
mod tests {
    use super::{checked_depth_add, checked_indentation};

    #[test]
    fn indentation_arithmetic_is_checked() {
        assert_eq!(checked_indentation(64, 2).unwrap(), 128);
        assert_eq!(
            checked_indentation(2, usize::MAX).unwrap_err().to_string(),
            "serializer indentation exceeds usize"
        );
        assert_eq!(
            checked_depth_add(usize::MAX, 1).unwrap_err().to_string(),
            "serializer indentation depth exceeds usize"
        );
        assert_eq!(
            checked_depth_add(usize::MAX - 1, 2)
                .unwrap_err()
                .to_string(),
            "serializer indentation depth exceeds usize"
        );
    }
}