# dynfmt - Dynamic Formatting in Rust A crate for formatting strings dynamically. `dynfmt` provides several implementations for formats that implement a subset of the [`std::fmt`] facilities. Parsing of the format string and arguments checks are performed at runtime. There is also the option to implement new formats. The public API is exposed via the [`Format`] trait, which contains formatting helper functions and lower-level utilities to interface with format strings. See the Features section for a list of provided implementations. ## Usage ```rust use dynfmt::{Format, NoopFormat}; let formatted = NoopFormat.format("hello, world", &["unused"]); assert_eq!("hello, world", formatted.expect("formatting failed")); ``` See the [`Format`] trait for more methods. ## Features This crate ships with a set of features that either activate formatting capabilities or new format implementations: - `json` **(default)**: Implements the serialization of complex structures via JSON. Certain formats, such as Python, also have a _representation_ format (`%r`) that makes use of this feature, if enabled. Without this feature, such values will cause an error. - `python`: Implements the `printf`-like format that python 2 used for formatting strings. See [`PythonFormat`] for more information. - `curly`: A simple format string syntax using curly braces for arguments. Similar to .NET and Rust, but much less capable. See [`SimpleCurlyFormat`] for mor information. ## Extensibility Implement the [`Format`] trait to create a new format. The only required method is `iter_args`, which must return an iterator over [`ArgumentSpec`] structs. Based on the capabilities of the format, the specs can be parameterized with formatting parameters. ```rust use std::str::MatchIndices; use dynfmt::{ArgumentSpec, Format, Error}; struct HashFormat; impl<'f> Format<'f> for HashFormat { type Iter = HashIter<'f>; fn iter_args(&self, format: &'f str) -> Result> { Ok(HashIter(format.match_indices('#'))) } } struct HashIter<'f>(MatchIndices<'f, char>); impl<'f> Iterator for HashIter<'f> { type Item = Result, Error<'f>>; fn next(&mut self) -> Option { self.0.next().map(|(index, _)| Ok(ArgumentSpec::new(index, index + 1))) } } let formatted = HashFormat.format("hello, #", &["world"]); assert_eq!("hello, world", formatted.expect("formatting failed")); ``` [`std::fmt`]: https://doc.rust-lang.org/stable/std/fmt/ [`serde::Serialize`]: https://docs.rs/serde/latest/serde/trait.Serialize.html [`Format`]: https://docs.rs/dynfmt/latest/dynfmt/trait.Format.html [`ArgumentSpec`]: https://docs.rs/dynfmt/latest/dynfmt/struct.ArgumentSpec.html [`PythonFormat`]: https://docs.rs/dynfmt/latest/dynfmt/python/struct.PythonFormat.html [`SimpleCurlyFormat`]: https://docs.rs/dynfmt/latest/dynfmt/curly/struct.SimpleCurlyFormat.html License: MIT