From c26907b3ecf2b139fe61bf1403c952b85285ae02 Mon Sep 17 00:00:00 2001 From: Ryan Leckey Date: Sat, 3 Jun 2017 01:21:10 -0700 Subject: Add set and set_default (and deep merging) --- src/path/mod.rs | 120 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 120 insertions(+) (limited to 'src/path') diff --git a/src/path/mod.rs b/src/path/mod.rs index f889283..d2df442 100644 --- a/src/path/mod.rs +++ b/src/path/mod.rs @@ -1,4 +1,5 @@ use std::str::FromStr; +use std::collections::HashMap; use nom::ErrorKind; use error::*; use value::{Value, ValueKind}; @@ -33,6 +34,125 @@ impl Expression { } } + Expression::Child(expr, key) => { + match expr.get(root) { + Some(value) => { + match value.kind { + // Access on a table is identical to Identifier, it just forwards + ValueKind::Table(ref map) => map.get(&key), + + // all other variants return None + _ => None, + } + } + + _ => None, + } + } + + _ => { + unimplemented!(); + } + } + } + + pub fn get_mut<'a>(&self, root: &'a mut Value) -> Option<&'a mut Value> { + match *self { + Expression::Identifier(ref id) => { + match root.kind { + ValueKind::Table(ref mut map) => { + Some(map.entry(id.clone()).or_insert(Value::new(None, ValueKind::Nil))) + } + + _ => None, + } + } + + Expression::Child(ref expr, ref key) => { + match expr.get_mut(root) { + Some(value) => { + match value.kind { + ValueKind::Table(ref mut map) => { + Some(map.entry(key.clone()).or_insert(Value::new(None, ValueKind::Nil))) + } + + _ => { + *value = HashMap::::new().into(); + + if let ValueKind::Table(ref mut map) = value.kind { + Some(map.entry(key.clone()).or_insert(Value::new(None, ValueKind::Nil))) + } else { + println!("WHAT THE FUCK?"); + + unreachable!(); + } + } + } + } + + _ => None, + } + } + + _ => { + unimplemented!(); + } + } + } + + pub fn set<'a>(&self, root: &'a mut Value, value: Value) { + match *self { + Expression::Identifier(ref id) => { + // Ensure that root is a table + match root.kind { + ValueKind::Table(_) => { } + + _ => { + *root = HashMap::::new().into(); + } + } + + match value.kind { + ValueKind::Table(ref incoming_map) => { + // Pull out another table + let mut target = if let ValueKind::Table(ref mut map) = root.kind { + map.entry(id.clone()).or_insert(HashMap::::new().into()) + } else { + unreachable!(); + }; + + // Continue the deep merge + for (key, val) in incoming_map { + Expression::Identifier(key.clone()).set(&mut target, val.clone()); + } + } + + _ => { + if let ValueKind::Table(ref mut map) = root.kind { + // Just do a simple set + map.insert(id.clone(), value); + } + } + } + } + + Expression::Child(ref expr, ref key) => { + if let Some(parent) = expr.get_mut(root) { + match parent.kind { + ValueKind::Table(_) => { + Expression::Identifier(key.clone()).set(parent, value); + } + + _ => { + // Didn't find a table. Oh well. Make a table and do this anyway + *parent = HashMap::::new().into(); + + Expression::Identifier(key.clone()).set(parent, value); + } + } + } + } + _ => { unimplemented!(); } -- cgit v1.2.3