1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207
//! A YAML 1.2 parser using greedy parsing algorithm with PEG atoms.
//!
//! The major purpose of this crate is to let the user build their own YAML reader / builder / validator.
//!
//! This parser is not ensure about YAML spec but almost functions are well-implemented.
//! (test case is [here](https://github.com/KmolYuan/yaml-peg-rs/blob/main/src/tests/test.yaml))
//!
//! The buffer reader has also not implemented, but the chunks can be read by sub-parsers.
//!
//! # Parser
//!
//! Function [`parse`] is used to parse YAML string into [`Node`] data structure,
//! which has a data holder [`Yaml`].
//! There also has multiple thread version corresponding to [`parse_arc`], [`ArcNode`], [`ArcYaml`].
//! To get back as string, please use [`dump`] function.
//!
//! There are also have some macros for building [`NodeBase`] structure from Rust data.
//! Especially [`node!`] / [`node_arc!`] macro, almost data can be built by the macro literally.
//!
//! If you went to rise your own error message, [`indicated_msg`] might be a good choice.
//!
//! # Anchors
//!
//! The anchor system [`AnchorBase`] is implemented by using [`alloc::rc::Rc`] and [`alloc::sync::Arc`] as inner handler.
//! Additionally, [`anchors!`] macro can used to create anchor visitor by yourself.
//!
//! # Serialization and Deserialization
//!
//! Enable `serde` / `serde-std` feature to use `serde` crate.
//! The crate provides a set of protocol traits to convert between custom Rust data.
//! Please be aware that the additional fields will be discard when convert to a fix-sized structure.
//! For example, the structure fields can be turned into map keys as well.
//!
//! On the other hand, the primitive types still able to transform to YAML data without serialization,
//! according to `From` and `Into` traits.
#![cfg_attr(
feature = "serde",
doc = "See [`serialize`] module for more information."
)]
#![cfg_attr(doc_cfg, feature(doc_cfg))]
#![cfg_attr(not(feature = "serde-std"), no_std)]
#![warn(missing_docs)]
extern crate alloc;
pub use crate::{
anchors::*,
dumper::dump,
indicator::*,
node::*,
parser::{parse, parse_arc},
yaml::*,
};
/// Create [`Node`] items literally.
///
/// Literals and expressions will be transformed to [`Yaml`] automatically by calling [`Into::into`].
///
/// ```
/// use yaml_peg::{node, Node};
///
/// let k = "a";
/// assert_eq!(node!(k), node!("a"));
/// assert_eq!(node!(()), Node::from(()));
/// ```
///
/// Arrays and maps can be created from this macro directly through brackets (`[]`, `{}`).
///
/// ```
/// use yaml_peg::{node, yaml_array, yaml_map};
///
/// assert_eq!(node!([1, 2]), node!(yaml_array![1, 2]));
/// assert_eq!(node!({1 => 2}), node!(yaml_map! { 1 => 2 }));
/// ```
///
/// The [`YamlBase::Anchor`] is also supported by the syntax:
///
/// ```
/// use yaml_peg::{node, YamlBase};
///
/// assert_eq!(node!(YamlBase::Anchor("x".into())), node!(*"x"));
/// ```
///
/// For [`ArcNode`], please use [`node_arc!`], which has same API.
#[macro_export]
macro_rules! node {
([$($token:tt)*]) => {
$crate::node!($crate::yaml_array![$($token)*])
};
({$($token:tt)*}) => {
$crate::node!($crate::yaml_map! { $($token)* })
};
(*$anchor:expr) => {
$crate::node!($crate::YamlBase::Anchor($anchor.into()))
};
($yaml:expr) => {
$crate::Node::from($yaml)
};
}
/// Create [`ArcNode`] items literally.
///
/// The API is same as [`node!`] macro.
///
/// ```
/// use yaml_peg::{node_arc as node, ArcNode};
///
/// assert_eq!(node!(()), ArcNode::from(()));
/// ```
#[macro_export]
macro_rules! node_arc {
([$($token:tt)*]) => {
$crate::node_arc!($crate::yaml_array![$($token)*])
};
({$($token:tt)*}) => {
$crate::node_arc!($crate::yaml_map![$($token)*])
};
(*$anchor:expr) => {
$crate::node_arc!($crate::YamlBase::Anchor($anchor.into()))
};
($yaml:expr) => {
$crate::ArcNode::from($yaml)
};
}
/// Create [`YamlBase::Array`] items literally.
///
/// All items will convert to [`NodeBase`] automatically.
///
/// ```
/// use yaml_peg::{node, yaml_array, Yaml};
///
/// assert_eq!(
/// yaml_array!["a", "b", "c"],
/// Yaml::Array(vec![node!("a"), node!("b"), node!("c")])
/// );
/// ```
#[macro_export]
macro_rules! yaml_array {
($v:expr; $n:expr) => {{
extern crate alloc;
$crate::YamlBase::Array(alloc::vec![$crate::NodeBase::from($v); $n])
}};
($($v:expr),* $(,)?) => {{
extern crate alloc;
$crate::YamlBase::Array(alloc::vec![$($crate::NodeBase::from($v)),*])
}};
}
/// Create [`YamlBase::Map`] items literally.
///
/// All items will convert to [`NodeBase`] automatically.
///
/// ```
/// use yaml_peg::{node, yaml_map, Yaml};
///
/// assert_eq!(
/// yaml_map! { "a" => "b", "c" => "d" },
/// Yaml::Map(
/// vec![(node!("a"), node!("b")), (node!("c"), node!("d"))]
/// .into_iter()
/// .collect()
/// )
/// );
/// ```
#[macro_export]
macro_rules! yaml_map {
($($k:expr => $v:expr),* $(,)?) => {{
extern crate alloc;
$crate::YamlBase::Map(alloc::vec![
$(($crate::NodeBase::from($k), $crate::NodeBase::from($v))),*
].into_iter().collect())
}};
}
/// Create a custom anchor visitor.
///
/// The anchor name should implement [`alloc::string::ToString`] trait.
/// All items will convert to [`NodeBase`] automatically.
///
/// ```
/// use yaml_peg::{node, anchors};
///
/// let v = anchors![
/// "my-boss" => node!({"name" => "Henry"}),
/// ];
/// assert_eq!(v["my-boss"]["name"], node!("Henry"));
/// ```
#[macro_export]
macro_rules! anchors {
($($k:expr => $v:expr),* $(,)?) => {{
extern crate alloc;
alloc::vec![$(($k.to_string(), $crate::NodeBase::from($v))),*].into_iter().collect::<$crate::AnchorBase<_>>()
}};
}
mod anchors;
pub mod dumper;
mod indicator;
mod node;
pub mod parser;
pub mod repr;
#[cfg(feature = "serde")]
#[cfg_attr(doc_cfg, doc(cfg(feature = "serde")))]
pub mod serialize;
#[cfg(test)]
mod tests;
mod yaml;