tsukurou_table 0.2.0

A specialized map for storing values of varying types.
Documentation
// Copyright (C) 2018  Project Tsukurou!
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <https://www.gnu.org/licenses/>.

//! Implementation of the `Table` data type.

mod serde;

use std::collections::HashMap;

use value::{Value, FromValue, FromValueMut};

/// Contains `Value`s indexed by a string name.
///
/// # Examples
///
/// TODO
#[derive(Debug, Clone, PartialEq, Default)]
pub struct Table {
    map: HashMap<String, Value>,
}

impl Table {

    /// Constructs a new, empty table.
    pub fn new() -> Table {
        Table {
            map: HashMap::new(),
        }
    }

    /// Constructs a new table from the given initial map.
    pub fn with_map(map: HashMap<String, Value>) -> Table {
        Table {
            map,
        }
    }

    /// Checks if the given key exists in the map.
    pub fn exists(&self, name: &str) -> bool {
        self.map.contains_key(name)
    }

    /// Gets and parses the value with the given name and returns it,
    /// or returns `None` if the value doesn't exist or can't be parsed
    /// as this type.
    pub fn get<'a, T>(&'a self, name: &str) -> Option<T>
    where
        T: FromValue<'a>,
    {
        self.map.get(name)
            .and_then(T::from_value)
    }

    /// Gets and parses the value with the given name and returns it,
    /// or returns `None` if the value doesn't exist or can't be parsed
    /// as this type.
    pub fn get_mut<'a, T>(&'a mut self, name: &str) -> Option<T>
    where
        T: FromValueMut<'a>,
    {
        self.map.get_mut(name)
            .and_then(T::from_value_mut)
    }

    /// Updates the value assigned to this name, returning the previous
    /// one if it existed.
    pub fn set<T>(&mut self, name: &str, value: T) -> Option<Value>
    where
        Value: From<T>,
    {
        self.map.insert(name.to_string(), Value::from(value))
    }

    /// Removes any assignment of a value to this name, returning it
    /// if it existed.
    pub fn remove(&mut self, name: &str) -> Option<Value> {
        self.map.remove(name)
    }

    /// Removes all value assignments, resetting this table to a `new` state.
    pub fn clear(&mut self) {
        self.map.clear()
    }

    /// Produces an iterator over the keys and values in this table.
    ///
    /// Currently, this method only delegates to the inner `HashMap::iter()`.
    pub fn iter<'a>(&'a self)
        -> ::std::collections::hash_map::Iter<'a, String, Value>
    {
        self.map.iter()
    }

    /// Produces a mutable iterator over the keys and values in this table.
    ///
    /// Currently, this method only delegates to `HashMap::iter_mut()`.
    pub fn iter_mut<'a>(&'a mut self)
        -> ::std::collections::hash_map::IterMut<'a, String, Value>
    {
        self.map.iter_mut()
    }
}

impl From<HashMap<String, Value>> for Table {
    fn from(map: HashMap<String, Value>) -> Table {
        Table::with_map(map)
    }
}

impl<'a> IntoIterator for &'a Table {
    type Item = (&'a String, &'a Value);
    type IntoIter = ::std::collections::hash_map::Iter<'a, String, Value>;

    fn into_iter(self) -> Self::IntoIter {
        self.iter()
    }
}

impl<'a> IntoIterator for &'a mut Table {
    type Item = (&'a String, &'a mut Value);
    type IntoIter = ::std::collections::hash_map::IterMut<'a, String, Value>;

    fn into_iter(self) -> Self::IntoIter {
        self.iter_mut()
    }
}