    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

    use std::error::Error;

    use crate::map::Map;
    use crate::value::{Value, ValueKind};

    pub fn parse(
        uri: Option<&String>,
        text: &str,
    ) -> Result<Map<String, Value>, Box<dyn Error + Send + Sync>> {
        let value = from_ron_value(uri, ron::from_str(text)?)?;
        match value.kind {
            ValueKind::Table(map) => Ok(map),

            _ => Ok(Map::new()),
        }
    }

    fn from_ron_value(
        uri: Option<&String>,
        value: ron::Value,
    ) -> Result<Value, Box<dyn Error + Send + Sync>> {
        let kind = match value {
            ron::Value::Option(value) => match value {
                Some(value) => from_ron_value(uri, *value)?.kind,
                None => ValueKind::Nil,
            },

            ron::Value::Unit => ValueKind::Nil,

            ron::Value::Bool(value) => ValueKind::Boolean(value),

            ron::Value::Number(value) => match value {
                ron::Number::Float(value) => ValueKind::Float(value.get()),
                ron::Number::Integer(value) => ValueKind::I64(value),
            },

            ron::Value::Char(value) => ValueKind::String(value.to_string()),

            ron::Value::String(value) => ValueKind::String(value),

            ron::Value::Seq(values) => {
                let array = values
                    .into_iter()
                    .map(|value| from_ron_value(uri, value))
                    .collect::<Result<Vec<_>, _>>()?;

                ValueKind::Array(array)
            }

            ron::Value::Map(values) => {
                let map = values
                    .iter()
                    .map(|(key, value)| -> Result<_, Box<dyn Error + Send + Sync>> {
                        let key = key.clone().into_rust::<String>()?;
                        let value = from_ron_value(uri, value.clone())?;

                        Ok((key, value))
                    })
                    .collect::<Result<Map<_, _>, _>>()?;

                ValueKind::Table(map)
            }
        };

        Ok(Value::new(uri, kind))
    }