Skip to content

Commit e9f49cb

Browse files
authored
Merge pull request #105 from hobofan/feat/object_index
Implement `Index` and `IndexMut` for `Object`
2 parents a40f7dd + 892370f commit e9f49cb

File tree

3 files changed

+168
-8
lines changed

3 files changed

+168
-8
lines changed

src/object.rs

+89
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
use std::{ ptr, mem, str, slice, fmt };
2+
use std::ops::{ Index, IndexMut, Deref };
23

34
use value::JsonValue;
45

56
const KEY_BUF_LEN: usize = 32;
7+
static NULL: JsonValue = JsonValue::Null;
68

79
struct Node {
810
// Internal buffer to store keys that fit within `KEY_BUF_LEN`,
@@ -575,3 +577,90 @@ impl<'a> DoubleEndedIterator for IterMut<'a> {
575577
self.inner.next_back().map(|node| (node.key_str(), &mut node.value))
576578
}
577579
}
580+
581+
/// Implements indexing by `&str` to easily access object members:
582+
///
583+
/// ## Example
584+
///
585+
/// ```
586+
/// # #[macro_use]
587+
/// # extern crate json;
588+
/// # use json::JsonValue;
589+
/// #
590+
/// # fn main() {
591+
/// let value = object!{
592+
/// "foo" => "bar"
593+
/// };
594+
///
595+
/// if let JsonValue::Object(object) = value {
596+
/// assert!(object["foo"] == "bar");
597+
/// }
598+
/// # }
599+
/// ```
600+
// TODO: doc
601+
impl<'a> Index<&'a str> for Object {
602+
type Output = JsonValue;
603+
604+
fn index(&self, index: &str) -> &JsonValue {
605+
match self.get(index) {
606+
Some(value) => value,
607+
_ => &NULL
608+
}
609+
}
610+
}
611+
612+
impl Index<String> for Object {
613+
type Output = JsonValue;
614+
615+
fn index(&self, index: String) -> &JsonValue {
616+
self.index(index.deref())
617+
}
618+
}
619+
620+
impl<'a> Index<&'a String> for Object {
621+
type Output = JsonValue;
622+
623+
fn index(&self, index: &String) -> &JsonValue {
624+
self.index(index.deref())
625+
}
626+
}
627+
628+
/// Implements mutable indexing by `&str` to easily modify object members:
629+
///
630+
/// ## Example
631+
///
632+
/// ```
633+
/// # #[macro_use]
634+
/// # extern crate json;
635+
/// # use json::JsonValue;
636+
/// #
637+
/// # fn main() {
638+
/// let value = object!{};
639+
///
640+
/// if let JsonValue::Object(mut object) = value {
641+
/// object["foo"] = 42.into();
642+
///
643+
/// assert!(object["foo"] == 42);
644+
/// }
645+
/// # }
646+
/// ```
647+
impl<'a> IndexMut<&'a str> for Object {
648+
fn index_mut(&mut self, index: &str) -> &mut JsonValue {
649+
if self.get(index).is_none() {
650+
self.insert(index, JsonValue::Null);
651+
}
652+
self.get_mut(index).unwrap()
653+
}
654+
}
655+
656+
impl IndexMut<String> for Object {
657+
fn index_mut(&mut self, index: String) -> &mut JsonValue {
658+
self.index_mut(index.deref())
659+
}
660+
}
661+
662+
impl<'a> IndexMut<&'a String> for Object {
663+
fn index_mut(&mut self, index: &String) -> &mut JsonValue {
664+
self.index_mut(index.deref())
665+
}
666+
}

src/value/mod.rs

+2-8
Original file line numberDiff line numberDiff line change
@@ -586,10 +586,7 @@ impl<'a> Index<&'a str> for JsonValue {
586586

587587
fn index(&self, index: &str) -> &JsonValue {
588588
match *self {
589-
JsonValue::Object(ref object) => match object.get(index) {
590-
Some(value) => value,
591-
_ => &NULL
592-
},
589+
JsonValue::Object(ref object) => &object[index],
593590
_ => &NULL
594591
}
595592
}
@@ -631,10 +628,7 @@ impl<'a> IndexMut<&'a str> for JsonValue {
631628
fn index_mut(&mut self, index: &str) -> &mut JsonValue {
632629
match *self {
633630
JsonValue::Object(ref mut object) => {
634-
if object.get(index).is_none() {
635-
object.insert(index, JsonValue::Null);
636-
}
637-
object.get_mut(index).unwrap()
631+
&mut object[index]
638632
},
639633
_ => {
640634
*self = JsonValue::new_object();

tests/value.rs

+77
Original file line numberDiff line numberDiff line change
@@ -429,6 +429,83 @@ fn index_mut_by_string_ref() {
429429
assert_eq!(data["foo"], "bar");
430430
}
431431

432+
#[test]
433+
fn object_index_by_str() {
434+
let val = object!{
435+
"foo" => "bar"
436+
};
437+
if let JsonValue::Object(data) = val {
438+
assert_eq!(data["foo"], "bar");
439+
}
440+
}
441+
442+
#[test]
443+
fn object_index_by_string() {
444+
let val = object!{
445+
"foo" => "bar"
446+
};
447+
448+
if let JsonValue::Object(data) = val {
449+
assert_eq!(data["foo".to_string()], "bar");
450+
}
451+
}
452+
453+
#[test]
454+
fn object_index_by_string_ref() {
455+
let val = object!{
456+
"foo" => "bar"
457+
};
458+
459+
let key = "foo".to_string();
460+
let ref key_ref = key;
461+
462+
if let JsonValue::Object(data) = val {
463+
assert_eq!(data[key_ref], "bar");
464+
}
465+
}
466+
467+
#[test]
468+
fn object_index_mut_by_str() {
469+
let val = object!{
470+
"foo" => Null
471+
};
472+
473+
if let JsonValue::Object(mut data) = val {
474+
data["foo"] = "bar".into();
475+
476+
assert_eq!(data["foo"], "bar");
477+
}
478+
}
479+
480+
#[test]
481+
fn object_index_mut_by_string() {
482+
let val = object!{
483+
"foo" => Null
484+
};
485+
486+
if let JsonValue::Object(mut data) = val {
487+
data["foo".to_string()] = "bar".into();
488+
489+
assert_eq!(data["foo"], "bar");
490+
}
491+
}
492+
493+
#[test]
494+
fn object_index_mut_by_string_ref() {
495+
let val = object!{
496+
"foo" => Null
497+
};
498+
499+
let key = "foo".to_string();
500+
let ref key_ref = key;
501+
502+
if let JsonValue::Object(mut data) = val {
503+
data[key_ref] = "bar".into();
504+
505+
assert_eq!(data["foo"], "bar");
506+
}
507+
}
508+
432509
#[test]
433510
fn fmt_string() {
434511
let data: JsonValue = "foobar".into();

0 commit comments

Comments
 (0)