boltbuild 0.1.0

BoltBuild is a programmable build system.
Documentation
use super::lua_interop::EnvironmentParent;
use super::{
    Environment, ReadWriteEnvironment, ReadWriteEnvironmentSeed, ReadWriteEnvironmentSequenceSeed,
    ReadWriteEnvironmentVec, SerializedReadWriteEnvironment,
};
use serde::de::{DeserializeSeed, Error, MapAccess, SeqAccess, Visitor};
use serde::ser::SerializeStruct;
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use std::collections::{BTreeMap, HashSet};
use std::fmt;
use std::sync::{Arc, Mutex};

impl<'a> Serialize for SerializedReadWriteEnvironment<'a> {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        let mut s = serializer.serialize_struct("Environment", 2)?;
        s.serialize_field(
            "parent",
            &match &self.0.lock().unwrap().parent {
                EnvironmentParent::None => SerializedEnvironmentParent::None,
                EnvironmentParent::Current(p) => {
                    SerializedEnvironmentParent::Current(p.lock().unwrap().index)
                }
                EnvironmentParent::Parent(p) => {
                    SerializedEnvironmentParent::Parent(p.lock().unwrap().index)
                }
                EnvironmentParent::Leaf(p) => {
                    SerializedEnvironmentParent::Leaf(p.lock().unwrap().index)
                }
            },
        )?;
        s.serialize_field(
            "values",
            &self
                .0
                .lock()
                .unwrap()
                .environment
                .values
                .iter()
                .collect::<BTreeMap<_, _>>(),
        )?;
        s.end()
    }
}

#[derive(Serialize, Deserialize)]
enum SerializedEnvironmentParent {
    None,
    Current(usize),
    Parent(usize),
    Leaf(usize),
}

impl<'de, 'a> DeserializeSeed<'de> for ReadWriteEnvironmentSeed<'a> {
    type Value = Arc<Mutex<ReadWriteEnvironment>>;

    fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
    where
        D: Deserializer<'de>,
    {
        enum Field {
            Parent,
            Values,
        }

        impl<'de> Deserialize<'de> for Field {
            fn deserialize<D>(deserializer: D) -> Result<Field, D::Error>
            where
                D: Deserializer<'de>,
            {
                struct FieldVisitor;

                impl<'de> Visitor<'de> for FieldVisitor {
                    type Value = Field;

                    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
                        formatter.write_str("`parent`, or `values`")
                    }

                    fn visit_str<E>(self, value: &str) -> Result<Field, E>
                    where
                        E: Error,
                    {
                        match value {
                            "parent" => Ok(Field::Parent),
                            "values" => Ok(Field::Values),
                            _ => Err(Error::unknown_field(value, &["parent", "values"])),
                        }
                    }
                }

                deserializer.deserialize_identifier(FieldVisitor)
            }
        }

        struct ReadWriteEnvironmentVisitor<'a> {
            current: &'a ReadWriteEnvironmentVec,
            parent: &'a ReadWriteEnvironmentVec,
        }

        impl<'de, 'a> Visitor<'de> for ReadWriteEnvironmentVisitor<'a> {
            type Value = Arc<Mutex<ReadWriteEnvironment>>;

            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
                formatter.write_str("struct Environment")
            }

            fn visit_seq<V>(self, mut seq: V) -> Result<Self::Value, V::Error>
            where
                V: SeqAccess<'de>,
            {
                let parent = seq
                    .next_element::<SerializedEnvironmentParent>()?
                    .ok_or_else(|| Error::invalid_length(0, &self))?;
                let values = seq
                    .next_element()?
                    .ok_or_else(|| Error::invalid_length(1, &self))?;
                let parent = match parent {
                    SerializedEnvironmentParent::None => EnvironmentParent::None,
                    SerializedEnvironmentParent::Current(index) => {
                        if self.current.len() <= index {
                            return Err(Error::custom(format!("invalid environment index {}; expected an index in the range 0..{}", index, self.current.len())));
                        }
                        EnvironmentParent::Current(self.current[index].clone())
                    }
                    SerializedEnvironmentParent::Parent(index) => {
                        if self.parent.len() <= index {
                            return Err(Error::custom(format!("invalid environment index {}; expected an index in the range 0..{}", index, self.parent.len())));
                        }
                        EnvironmentParent::Parent(self.parent[index].clone())
                    }
                    SerializedEnvironmentParent::Leaf(index) => {
                        if self.current.len() <= index {
                            return Err(Error::custom(format!("invalid environment index {}; expected an index in the range 0..{}", index, self.current.len())));
                        }
                        EnvironmentParent::Leaf(self.current[index].clone())
                    }
                };
                Ok(Arc::new(Mutex::new(ReadWriteEnvironment {
                    parent,
                    index: self.current.len(),
                    environment: Environment {
                        values,
                        used_keys: HashSet::new(),
                    },
                })))
            }

            fn visit_map<V>(self, mut map: V) -> Result<Self::Value, V::Error>
            where
                V: MapAccess<'de>,
            {
                let mut parent = None;
                let mut values = None;
                while let Some(key) = map.next_key()? {
                    match key {
                        Field::Parent => {
                            if parent.is_some() {
                                return Err(Error::duplicate_field("parent"));
                            }
                            parent = Some(map.next_value()?);
                        }
                        Field::Values => {
                            if values.is_some() {
                                return Err(Error::duplicate_field("values"));
                            }
                            values = Some(map.next_value()?);
                        }
                    }
                }
                let parent = parent.ok_or_else(|| Error::missing_field("parent"))?;
                let parent = match parent {
                    SerializedEnvironmentParent::None => EnvironmentParent::None,
                    SerializedEnvironmentParent::Current(index) => {
                        if self.current.len() <= index {
                            return Err(Error::custom(format!("invalid environment index {}; expected an index in the range 0..{}", index, self.current.len())));
                        }
                        EnvironmentParent::Current(self.current[index].clone())
                    }
                    SerializedEnvironmentParent::Parent(index) => {
                        if self.parent.len() <= index {
                            return Err(Error::custom(format!("invalid environment index {}; expected an index in the range 0..{}", index, self.parent.len())));
                        }
                        EnvironmentParent::Parent(self.parent[index].clone())
                    }
                    SerializedEnvironmentParent::Leaf(index) => {
                        if self.current.len() <= index {
                            return Err(Error::custom(format!("invalid environment index {}; expected an index in the range 0..{}", index, self.current.len())));
                        }
                        EnvironmentParent::Leaf(self.current[index].clone())
                    }
                };
                let values = values.ok_or_else(|| Error::missing_field("values"))?;
                Ok(Arc::new(Mutex::new(ReadWriteEnvironment {
                    parent,
                    index: self.current.len(),
                    environment: Environment {
                        values,
                        used_keys: HashSet::new(),
                    },
                })))
            }
        }

        deserializer.deserialize_struct(
            "Environment",
            &["parent", "values"],
            ReadWriteEnvironmentVisitor {
                current: self.current,
                parent: self.parent,
            },
        )
    }
}

impl<'de, 'a> DeserializeSeed<'de> for ReadWriteEnvironmentSequenceSeed<'a> {
    type Value = ReadWriteEnvironmentVec;

    fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
    where
        D: Deserializer<'de>,
    {
        struct EnvironmentSequenceVisitor<'a>(&'a ReadWriteEnvironmentVec);

        impl<'de, 'a> Visitor<'de> for EnvironmentSequenceVisitor<'a> {
            type Value = ReadWriteEnvironmentVec;

            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
                formatter.write_str("sequence of struct Environment")
            }

            fn visit_seq<V>(self, mut seq: V) -> Result<Self::Value, V::Error>
            where
                V: SeqAccess<'de>,
            {
                let mut result = ReadWriteEnvironmentVec::new();
                if let Some(size_hint) = seq.size_hint() {
                    result.reserve(size_hint);
                }
                while let Some(elem) = seq.next_element_seed(ReadWriteEnvironmentSeed {
                    current: &result,
                    parent: self.0,
                })? {
                    result.push(elem);
                }
                Ok(result)
            }
        }

        deserializer.deserialize_seq(EnvironmentSequenceVisitor(self.0))
    }
}