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
use crate::{repr::*, *};
use alloc::{
    string::{String, ToString},
    vec::Vec,
};
use core::iter::FromIterator;
use ritelinked::LinkedHashMap;

macro_rules! impl_from {
    ($from_ty1:ty $(| $from_ty2:ty)* as $ty:ident) => {
        impl<R: Repr> From<$from_ty1> for YamlBase<R> {
            fn from(s: $from_ty1) -> Self {
                Self::$ty(s.to_string())
            }
        }
        $(
        impl<R: Repr> From<$from_ty2> for YamlBase<R> {
            fn from(s: $from_ty2) -> Self {
                Self::$ty(s.to_string())
            }
        }
        )*
    };
}

/// A YAML data with [`alloc::rc::Rc`] holder.
pub type Yaml = YamlBase<RcRepr>;
/// A YAML data with [`alloc::sync::Arc`] holder.
pub type ArcYaml = YamlBase<ArcRepr>;
/// The array data structure of YAML.
pub type Array<R> = Vec<NodeBase<R>>;
/// The map data structure of YAML.
pub type Map<R> = LinkedHashMap<NodeBase<R>, NodeBase<R>>;

/// YAML data types, but it is recommended to use [`NodeBase`] for shorten code.
///
/// This type can convert from primitive types by `From` and `Into` methods.
///
/// ```
/// use yaml_peg::Yaml;
///
/// assert_eq!(Yaml::Int("20".into()), 20.into());
/// assert_eq!(Yaml::Float("0.001".into()), 1e-3.into());
/// ```
///
/// Also, the iterators can turn into arrays and maps.
///
/// ```
/// use yaml_peg::{Yaml, node};
/// use yaml_peg::{yaml_array, yaml_map};
///
/// use std::iter::FromIterator;
/// let v = vec![node!(1), node!(2), node!(3)];
/// assert_eq!(Yaml::from_iter(v), yaml_array![node!(1), node!(2), node!(3)]);
/// let m = vec![(node!(1), node!(2)), (node!(3), node!(4))];
/// assert_eq!(Yaml::from_iter(m), yaml_map!{node!(1) => node!(2), node!(3) => node!(4)});
/// ```
#[derive(Hash, Eq, PartialEq, Debug, Clone)]
pub enum YamlBase<R: Repr> {
    /// Null
    Null,
    /// Boolean
    Bool(bool),
    /// Integer
    Int(String),
    /// Float
    Float(String),
    /// String
    Str(String),
    /// Array
    Array(Array<R>),
    /// Map
    Map(Map<R>),
    /// Anchor insertion
    Anchor(String),
}

impl<R: Repr> YamlBase<R> {
    /// Check the anchor is valid.
    pub fn is_valid_anchor<S: ToString>(s: S) -> bool {
        parser::Parser::<R>::new(s.to_string().as_bytes())
            .identifier()
            .is_ok()
    }
}

impl<R: Repr> From<bool> for YamlBase<R> {
    fn from(b: bool) -> Self {
        Self::Bool(b)
    }
}

impl_from! { &str | String | &String as Str }
impl_from! { usize | u8 | u16 | u32 | u64 | u128 | isize | i8 | i16 | i32 | i64 | i128 as Int }
impl_from! { f32 | f64 as Float }

impl<R: Repr> FromIterator<NodeBase<R>> for YamlBase<R> {
    fn from_iter<T>(iter: T) -> Self
    where
        T: IntoIterator<Item = NodeBase<R>>,
    {
        Self::Array(iter.into_iter().collect())
    }
}

impl<R: Repr> FromIterator<(NodeBase<R>, NodeBase<R>)> for YamlBase<R> {
    fn from_iter<T>(iter: T) -> Self
    where
        T: IntoIterator<Item = (NodeBase<R>, NodeBase<R>)>,
    {
        Self::Map(iter.into_iter().collect())
    }
}