use std::collections::HashMap;
use std::collections::hash_map::Iter;
use super::parser::ParsedValue;
pub type Dict = HashMap<String, Value>;
pub type List = Vec<Value>;
#[derive(Debug, PartialEq)]
pub enum Value {
Str(String),
Int(i64),
Float(f64),
Bool(bool),
Ident(String),
Dict(Dict),
List(List),
Null,
}
impl Value {
pub fn new_string<S>(s: S) -> Self where S: Into<String> {
Value::Str(s.into())
}
pub fn new_ident<S>(s: S) -> Self where S: Into<String> {
Value::Ident(s.into())
}
pub fn new_int(s: i64) -> Self {
Value::Int(s)
}
pub fn new_float(s: f64) -> Self {
Value::Float(s)
}
pub fn new_bool(s: bool) -> Self {
Value::Bool(s)
}
pub fn new_null() -> Self {
Value::Null
}
pub fn from_parsed_value(val: ParsedValue) -> Self {
match val {
ParsedValue::Str(s) => Self::new_string(s),
ParsedValue::Float(f) => Self::new_float(f),
ParsedValue::Bool(b) => Self::new_bool(b),
ParsedValue::Int(i) => Self::new_int(i),
ParsedValue::Ident(i) => Self::new_ident(i),
ParsedValue::Null => Self::new_null(),
}
}
pub fn get_str(&self) -> Option<&str> {
match *self {
Value::Str(ref s) => Some(&s),
_ => None
}
}
pub fn get_int(&self) -> Option<i64> {
match *self {
Value::Int(s) => Some(s),
_ => None
}
}
pub fn get_float(&self) -> Option<f64> {
match *self {
Value::Float(s) => Some(s),
_ => None
}
}
pub fn get_bool(&self) -> Option<bool> {
match *self {
Value::Bool(s) => Some(s),
_ => None
}
}
pub fn get_ident(&self) -> Option<&str> {
match *self {
Value::Ident(ref s) => Some(&s),
_ => None
}
}
pub fn get_dict(&self) -> Option<&Dict> {
match *self {
Value::Dict(ref s) => Some(s),
_ => None
}
}
pub fn get_list(&self) -> Option<&[Value]> {
match *self {
Value::List(ref s) => Some(&s),
_ => None
}
}
pub fn is_null(&self) -> bool {
match *self {
Value::Null => true,
_ => false,
}
}
}
#[derive(Debug, PartialEq)]
pub struct Node {
subnodes: HashMap<String, Node>,
attributes: HashMap<String, Value>,
}
impl Node {
pub fn new() -> Self {
Node {
subnodes: HashMap::new(),
attributes: HashMap::new(),
}
}
pub fn new_node_or_get<S>(&mut self, name: S) -> &mut Self where S: Into<String> {
self.subnodes.entry(name.into()).or_insert(Self::new())
}
pub fn insert_node<S>(&mut self, name: S, node: Node) -> Option<Node>
where S: Into<String> {
self.subnodes.insert(name.into(), node)
}
pub fn delete_node<S>(&mut self, name: S) -> Option<Node> where S: Into<String> {
self.subnodes.remove(&name.into())
}
pub fn get_node<S>(&self, name: S) -> Option<&Self> where S: Into<String> {
self.subnodes.get(&name.into())
}
pub fn get_node_mut<S>(&mut self, name: S) -> Option<&mut Self>
where S: Into<String> {
self.subnodes.get_mut(&name.into())
}
pub fn iter_nodes(&self) -> Iter<String, Node> {
self.subnodes.iter()
}
pub fn insert_attr<S>(&mut self, name: S, value: Value) -> Option<Value>
where S: Into<String> {
self.attributes.insert(name.into(), value)
}
pub fn delete_attr<S>(&mut self, name: S) -> Option<Value> where S: Into<String> {
self.attributes.remove(&name.into())
}
pub fn get_attr<S>(&self, name: S) -> Option<&Value> where S: Into<String> {
self.attributes.get(&name.into())
}
pub fn get_attr_mut<S>(&mut self, name: S) -> Option<&mut Value>
where S: Into<String> {
self.attributes.get_mut(&name.into())
}
pub fn iter_attrs(&self) -> Iter<String, Value> {
self.attributes.iter()
}
pub fn is_empty(&self) -> bool {
self.subnodes.is_empty() && self.attributes.is_empty()
}
pub fn has_node(&self, name: &String) -> bool {
self.subnodes.contains_key(name)
}
pub fn has_nodes(&self) -> bool {
!self.subnodes.is_empty()
}
pub fn node_count(&self) -> usize {
self.subnodes.len()
}
pub fn has_attr(&self, name: &String) -> bool {
self.attributes.contains_key(name)
}
pub fn has_attrs(&self) -> bool {
!self.attributes.is_empty()
}
pub fn attr_count(&self) -> usize {
self.attributes.len()
}
}
#[derive(Debug, PartialEq)]
pub struct Document {
nodes: HashMap<String, Node>,
}
impl Document {
pub fn new() -> Self {
Document {
nodes: HashMap::new(),
}
}
pub fn new_node_or_get<S>(&mut self, name: S) -> &mut Node where S: Into<String> {
self.nodes.entry(name.into()).or_insert(Node::new())
}
pub fn insert_node<S>(&mut self, name: S, node: Node) -> Option<Node>
where S: Into<String> {
self.nodes.insert(name.into(), node)
}
pub fn delete_node<S>(&mut self, name: S) -> Option<Node> where S: Into<String> {
self.nodes.remove(&name.into())
}
pub fn get_node<S>(&self, name: S) -> Option<&Node> where S: Into<String> {
self.nodes.get(&name.into())
}
pub fn get_node_mut<S>(&mut self, name: S) -> Option<&mut Node> where S: Into<String> {
self.nodes.get_mut(&name.into())
}
pub fn iter_nodes(&self) -> Iter<String, Node> {
self.nodes.iter()
}
pub fn is_empty(&self) -> bool {
self.nodes.is_empty()
}
pub fn has_node(&self, name: &String) -> bool {
self.nodes.contains_key(name)
}
pub fn has_nodes(&self) -> bool {
!self.nodes.is_empty()
}
pub fn node_count(&self) -> usize {
self.nodes.len()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn type_creations() {
let doc = Document::new();
assert_eq!(doc.nodes.len(), 0);
let node = Node::new();
assert_eq!(node.subnodes.len(), 0);
assert_eq!(node.attributes.len(), 0);
let string = Value::new_string("hello");
assert_eq!(string, Value::Str("hello".to_string()));
assert_eq!(string, Value::new_string("hello".to_string()));
let identifier = Value::new_ident("hello");
assert_eq!(identifier, Value::Ident("hello".to_string()));
assert_eq!(identifier, Value::new_ident("hello".to_string()));
let integer = Value::new_int(34);
assert_eq!(integer, Value::Int(34));
let floatval = Value::new_float(33.4);
assert_eq!(floatval, Value::Float(33.4));
let boolean = Value::new_bool(false);
assert_eq!(boolean, Value::Bool(false));
}
#[test]
fn node_with_subnodes() {
let mut node = Node::new();
assert!(node.is_empty());
assert!(!node.has_nodes());
assert!(!node.has_attrs());
assert_eq!(node.node_count(), 0);
assert_eq!(node.attr_count(), 0);
node.new_node_or_get("subnode_name").new_node_or_get("secondary_subnode");
assert_eq!(
node.get_node("subnode_name")
.expect("couldn't find subnode_name")
.get_node("secondary_subnode"),
Some(&Node::new()));
assert!(!node.is_empty());
assert!(node.has_nodes());
assert!(!node.has_attrs());
assert_eq!(node.node_count(), 1);
assert_eq!(node.attr_count(), 0);
let subnode = node.delete_node("subnode_name").expect("node should have existed");
assert!(node.is_empty());
assert!(!node.has_nodes());
assert!(!node.has_attrs());
assert_eq!(node.node_count(), 0);
assert_eq!(node.attr_count(), 0);
node.insert_node("new subnode", subnode);
assert!(!node.is_empty());
assert!(node.has_nodes());
assert!(!node.has_attrs());
assert_eq!(node.node_count(), 1);
assert_eq!(node.attr_count(), 0);
let mut iterable = node
.get_node("new subnode").expect("missing subnode 'new subnode'")
.iter_nodes();
assert_eq!(iterable.len(), 1);
assert_eq!(
iterable.next(),
Some((&("secondary_subnode".to_string()), &Node::new())));
assert_eq!(iterable.next(), None);
}
#[test]
fn node_with_attributes() {
let mut node = Node::new();
assert!(node.is_empty());
assert!(!node.has_nodes());
assert!(!node.has_attrs());
assert_eq!(node.node_count(), 0);
assert_eq!(node.attr_count(), 0);
assert_eq!(node.insert_attr("key", Value::new_int(6)), None);
assert!(!node.is_empty());
assert!(!node.has_nodes());
assert!(node.has_attrs());
assert_eq!(node.node_count(), 0);
assert_eq!(node.attr_count(), 1);
assert_eq!(node.delete_attr("key"), Some(Value::new_int(6)));
assert!(node.is_empty());
assert!(!node.has_nodes());
assert!(!node.has_attrs());
assert_eq!(node.node_count(), 0);
assert_eq!(node.attr_count(), 0);
assert_eq!(node.insert_attr("key", Value::new_int(7)), None);
assert!(!node.is_empty());
assert!(!node.has_nodes());
assert!(node.has_attrs());
assert_eq!(node.node_count(), 0);
assert_eq!(node.attr_count(), 1);
let mut iterable = node.iter_attrs();
assert_eq!(iterable.len(), 1);
assert_eq!(
iterable.next(),
Some((&("key".to_string()), &Value::new_int(7))));
assert_eq!(iterable.next(), None);
}
#[test]
fn document_tests() {
let mut doc = Document::new();
doc.new_node_or_get("node_name").new_node_or_get("subnode");
assert_eq!(
doc.get_node("node_name")
.expect("couldn't find node_name")
.get_node("subnode"),
Some(&Node::new()));
let mut iterable = doc
.get_node("node_name").expect("missing subnode 'node_name'")
.iter_nodes();
assert_eq!(iterable.len(), 1);
assert_eq!(
iterable.next(),
Some((&("subnode".to_string()), &Node::new())));
assert_eq!(iterable.next(), None);
}
}