Skip to content

Commit

Permalink
Fix initialy set arr path
Browse files Browse the repository at this point in the history
  • Loading branch information
XX committed Apr 8, 2018
1 parent e8fa9fe commit 4ac0078
Show file tree
Hide file tree
Showing 3 changed files with 140 additions and 56 deletions.
171 changes: 115 additions & 56 deletions src/path/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,77 +58,138 @@ impl Expression {
}
}

Expression::Subscript(expr, index) => match expr.get(root) {
Some(value) => match value.kind {
ValueKind::Array(ref array) => {
let index = sindex_to_uindex(index, array.len());

if index >= array.len() {
None
} else {
Some(&array[index])
Expression::Subscript(expr, index) => {
match expr.get(root) {
Some(value) => match value.kind {
ValueKind::Array(ref array) => {
let index = sindex_to_uindex(index, array.len());

if index >= array.len() {
None
} else {
Some(&array[index])
}
}
}

_ => None,
},
_ => None,
},

_ => None,
_ => None,
}
},
}
}

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_with(|| Value::new(None, ValueKind::Nil)),
),
Expression::Identifier(ref id) => {
match root.kind {
ValueKind::Table(ref mut map) => map.get_mut(id),

_ => None,
_ => None,
}
},

Expression::Child(ref expr, ref key) => match expr.get_mut(root) {
Some(value) => match value.kind {
Expression::Child(ref expr, ref key) => {
match expr.get_mut(root) {
Some(value) => {
match value.kind {
ValueKind::Table(ref mut map) => map.get_mut(key),

_ => None
}
},

_ => None,
}
},

Expression::Subscript(ref expr, index) => {
match expr.get_mut(root) {
Some(value) => match value.kind {
ValueKind::Array(ref mut array) => {
let index = sindex_to_uindex(index, array.len());

if index >= array.len() {
None
} else {
Some(&mut array[index])
}
}

_ => None,
},

_ => None,
}
},
}
}

pub fn get_mut_forcibly<'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(key.clone())
map.entry(id.clone())
.or_insert_with(|| Value::new(None, ValueKind::Nil)),
),

_ => {
*value = HashMap::<String, Value>::new().into();
_ => None,
}
},

if let ValueKind::Table(ref mut map) = value.kind {
Some(
map.entry(key.clone())
.or_insert_with(|| Value::new(None, ValueKind::Nil)),
)
} else {
unreachable!();
Expression::Child(ref expr, ref key) => {
match expr.get_mut_forcibly(root) {
Some(value) => match value.kind {
ValueKind::Table(ref mut map) => Some(
map.entry(key.clone())
.or_insert_with(|| Value::new(None, ValueKind::Nil)),
),

_ => {
*value = HashMap::<String, Value>::new().into();

if let ValueKind::Table(ref mut map) = value.kind {
Some(
map.entry(key.clone())
.or_insert_with(|| Value::new(None, ValueKind::Nil)),
)
} else {
unreachable!();
}
}
}
},
},

_ => None,
_ => None,
}
},

Expression::Subscript(ref expr, index) => match expr.get_mut(root) {
Some(value) => match value.kind {
ValueKind::Array(ref mut array) => {
let index = sindex_to_uindex(index, array.len());

if index >= array.len() {
array.resize((index + 1) as usize, Value::new(None, ValueKind::Nil));
Expression::Subscript(ref expr, index) => {
let mut do_again = false;
match expr.get_mut_forcibly(root) {
Some(value) => {
match value.kind {
ValueKind::Array(_) => (),
_ => *value = Vec::<Value>::new().into()
}

Some(&mut array[index])
}
match value.kind {
ValueKind::Array(ref mut array) => {
let index = sindex_to_uindex(index, array.len());

_ => None,
},
if index >= array.len() {
array.resize((index + 1) as usize, Value::new(None, ValueKind::Nil));
}

Some(&mut array[index])
}

_ => None,
_ => None
}
},
_ => None
}
},
}
}
Expand Down Expand Up @@ -171,7 +232,7 @@ impl Expression {
}

Expression::Child(ref expr, ref key) => {
if let Some(parent) = expr.get_mut(root) {
if let Some(parent) = expr.get_mut_forcibly(root) {
match parent.kind {
ValueKind::Table(_) => {
Expression::Identifier(key.clone()).set(parent, value);
Expand All @@ -188,11 +249,15 @@ impl Expression {
}

Expression::Subscript(ref expr, index) => {
if let Some(parent) = expr.get_mut(root) {
if let Some(parent) = expr.get_mut_forcibly(root) {
match parent.kind {
ValueKind::Array(_) => (),
_ => *parent = Vec::<Value>::new().into()
}

match parent.kind {
ValueKind::Array(ref mut array) => {
let uindex = sindex_to_uindex(index, array.len());

if uindex >= array.len() {
array.resize(
(uindex + 1) as usize,
Expand All @@ -203,13 +268,7 @@ impl Expression {
array[uindex] = value.clone();
}

_ => {
// Didn't find an array ...
// Add an array and do this again
*parent = Vec::<Value>::new().into();

Expression::Subscript(expr.clone(), index).set(parent, value);
}
_ => ()
}
}
}
Expand Down
9 changes: 9 additions & 0 deletions src/path/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,15 @@ mod test {
let expected = Child(Box::new(Identifier("abcd".into())), "efgh".into());

assert_eq!(parsed, expected);

let parsed: Expression = from_str("abcd.efgh.ijkl").unwrap();
let expected = Child(Box::new(
Child(Box::new(
Identifier("abcd".into())
), "efgh".into())
), "ijkl".into());

assert_eq!(parsed, expected);
}

#[test]
Expand Down
16 changes: 16 additions & 0 deletions tests/set.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ fn test_set_scalar_default() {
fn test_set_scalar_path() {
let mut c = Config::default();

c.set("first.second.third", true).unwrap();

assert_eq!(c.get("first.second.third").ok(), Some(true));

c.merge(File::new("tests/Settings", FileFormat::Toml))
.unwrap();

Expand All @@ -43,6 +47,18 @@ fn test_set_scalar_path() {
fn test_set_arr_path() {
let mut c = Config::default();

c.set("items[0].name", "Ivan").unwrap();

assert_eq!(c.get("items[0].name").ok(), Some("Ivan".to_string()));

c.set("data[0].things[1].name", "foo").unwrap();
c.set("data[0].things[1].value", 42).unwrap();
c.set("data[1]", 0).unwrap();

assert_eq!(c.get("data[0].things[1].name").ok(), Some("foo".to_string()));
assert_eq!(c.get("data[0].things[1].value").ok(), Some(42));
assert_eq!(c.get("data[1]").ok(), Some(0));

c.merge(File::new("tests/Settings", FileFormat::Toml))
.unwrap();

Expand Down

0 comments on commit 4ac0078

Please sign in to comment.