nested-text 0.1.0

A fully spec-compliant NestedText v3.8 parser and serializer
Documentation
/// The three NestedText value types.
///
/// NestedText only has one scalar type (strings). Lists and dicts provide structure.
/// Dicts use `Vec<(String, Value)>` to preserve insertion order, which NestedText guarantees.
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Value {
    String(String),
    List(Vec<Value>),
    /// Key-value pairs in insertion order.
    Dict(Vec<(String, Value)>),
}

impl Value {
    pub fn as_str(&self) -> Option<&str> {
        match self {
            Value::String(s) => Some(s),
            _ => None,
        }
    }

    pub fn as_list(&self) -> Option<&[Value]> {
        match self {
            Value::List(v) => Some(v),
            _ => None,
        }
    }

    pub fn as_dict(&self) -> Option<&[(String, Value)]> {
        match self {
            Value::Dict(v) => Some(v),
            _ => None,
        }
    }

    pub fn is_string(&self) -> bool {
        matches!(self, Value::String(_))
    }

    pub fn is_list(&self) -> bool {
        matches!(self, Value::List(_))
    }

    pub fn is_dict(&self) -> bool {
        matches!(self, Value::Dict(_))
    }

    /// Look up a key in a dict value. Returns None if not a dict or key not found.
    pub fn get(&self, key: &str) -> Option<&Value> {
        match self {
            Value::Dict(pairs) => pairs.iter().find(|(k, _)| k == key).map(|(_, v)| v),
            _ => None,
        }
    }
}

impl From<String> for Value {
    fn from(s: String) -> Self {
        Value::String(s)
    }
}

impl From<&str> for Value {
    fn from(s: &str) -> Self {
        Value::String(s.to_string())
    }
}

impl From<Vec<Value>> for Value {
    fn from(v: Vec<Value>) -> Self {
        Value::List(v)
    }
}

impl From<Vec<(String, Value)>> for Value {
    fn from(v: Vec<(String, Value)>) -> Self {
        Value::Dict(v)
    }
}