#![crate_type = "rlib"]
extern crate rustc_serialize as serialize;
use serialize::json::Json;
use std::collections::hash_set;
use JsonPath::{Root,Descendant};
#[derive(Clone, Copy)]
pub enum JsonPath<'a:'b,'b> {
Root(&'a Json),
Descendant(&'a Json, &'b JsonPath<'a,'b>)
}
impl<'a,'b> JsonPath<'a,'b> {
#[inline]
fn root(r: &'a Json) -> JsonPath<'a,'b> {
Root(r)
}
#[inline]
fn descendant(&'b self, child: &'a Json) -> JsonPath<'a,'b> {
Descendant(child, self)
}
#[inline]
fn node(&self) -> &'a Json {
match *self {
Root(n) => n,
Descendant(n, _) => n
}
}
#[inline]
fn parent(&self) -> Option<&'b JsonPath<'a,'b>> {
match *self {
Root(..) => None,
Descendant(_, p) => Some(p)
}
}
}
pub trait Selector: Sized {
fn select<'a,'b,F>(&self, input: &JsonPath<'a,'b>, mut f: F)
where F: for<'c> FnMut(&JsonPath<'a,'c>);
#[inline]
fn boolean(self) -> BooleanSel<Self> {
BooleanSel { inner: self }
}
#[inline]
fn uint64(self) -> U64Sel<Self> {
U64Sel { inner: self }
}
#[inline]
fn int64(self) -> I64Sel<Self> {
I64Sel { inner: self }
}
#[inline]
fn float64(self) -> F64Sel<Self> {
F64Sel { inner: self }
}
#[inline]
fn string(self) -> StringSel<Self> {
StringSel { inner: self }
}
#[inline]
fn object(self) -> ObjectSel<Self> {
ObjectSel { inner: self }
}
#[inline]
fn list(self) -> ListSel<Self> {
ListSel { inner: self }
}
#[inline]
fn null(self) -> NullSel<Self> {
NullSel { inner: self }
}
#[inline]
fn at(self, index: usize) -> At<Self> {
At { inner: self, index: index }
}
#[inline]
fn key(self, name: &str) -> Key<Self> {
Key { inner: self, name: name }
}
#[inline]
fn child(self) -> Child<Self> {
Child { inner: self }
}
#[inline]
fn parent(self) -> Parent<Self> {
Parent { inner: self }
}
#[inline]
fn descend(self) -> Descend<Self> {
Descend { inner: self }
}
#[inline]
fn ascend(self) -> Ascend<Self> {
Ascend { inner: self }
}
#[inline]
fn wherein<T:Selector>(self, filter: T) -> Wherein<Self,T> {
Wherein { inner: self, filter: filter }
}
#[inline]
fn union<T1:Selector,T2:Selector>(self, left: T1, right: T2) -> Union<Self,T1,T2> {
Union { inner: self, left: left, right: right }
}
#[inline]
fn intersect<T1:Selector,T2:Selector>(self, left: T1, right: T2) -> Intersect<Self,T1,T2> {
Intersect { inner: self, left: left, right: right }
}
#[inline]
fn diff<T1:Selector,T2:Selector>(self, left: T1, right: T2) -> Diff<Self,T1,T2> {
Diff { inner: self, left: left, right: right }
}
#[inline]
fn and<T1:Selector,T2:Selector>(self, left: T1, right: T2) -> AndSel<Self,T1,T2> {
AndSel { inner: self, left: left, right: right }
}
#[inline]
fn or<T1:Selector,T2:Selector>(self, left: T1, right: T2) -> OrSel<Self,T1,T2> {
OrSel { inner: self, left: left, right: right }
}
}
#[derive(Clone, Copy)]
pub struct Node {
_dummy: ()
}
impl Selector for Node {
fn select<'a,'b,F>(&self, input: &JsonPath<'a,'b>, mut f: F)
where F: for<'c> FnMut(&JsonPath<'a,'c>) {
f(input)
}
}
pub struct ObjectSel<S> {
inner: S
}
impl<S:Selector> Selector for ObjectSel<S> {
fn select<'a,'b,F>(&self, input: &JsonPath<'a,'b>, mut f: F)
where F: for<'c> FnMut(&JsonPath<'a,'c>) {
self.inner.select(input, |x| {
match x.node() {
&Json::Object(..) => f(x),
_ => ()
}
})
}
}
pub struct ListSel<S> {
inner: S
}
impl<S:Selector> Selector for ListSel<S> {
fn select<'a,'b,F>(&self, input: &JsonPath<'a,'b>, mut f: F)
where F: for<'c> FnMut(&JsonPath<'a,'c>) {
self.inner.select(input, |x| {
match x.node() {
&Json::Array(..) => f(x),
_ => ()
}
})
}
}
pub struct StringSel<S> {
inner: S
}
pub struct StringEquals<'a,S> {
inner: S,
comp: &'a str
}
impl<S:Selector> StringSel<S> {
#[inline]
pub fn equals(self, comp: &str) -> StringEquals<S> {
let StringSel { inner } = self;
StringEquals { inner: inner, comp: comp }
}
}
impl<S:Selector> Selector for StringSel<S> {
fn select<'a,'b,F>(&self, input: &JsonPath<'a,'b>, mut f: F)
where F: for<'c> FnMut(&JsonPath<'a,'c>) {
self.inner.select(input, |x| {
match x.node() {
&Json::String(..) => f(x),
_ => ()
}
})
}
}
impl<'s,S:Selector> Selector for StringEquals<'s,S> {
fn select<'a,'b,F>(&self, input: &JsonPath<'a,'b>, mut f: F)
where F: for<'c> FnMut(&JsonPath<'a,'c>) {
self.inner.select(input, |x| {
match x.node() {
&Json::String(ref s) if self.comp == *s => f(x),
_ => ()
}
})
}
}
pub struct BooleanSel<S> {
inner: S
}
pub struct BooleanEquals<S> {
inner: S,
comp: bool
}
impl<S:Selector> BooleanSel<S> {
#[inline]
pub fn equals(self, comp: bool) -> BooleanEquals<S> {
let BooleanSel { inner } = self;
BooleanEquals { inner: inner, comp: comp }
}
}
impl<S:Selector> Selector for BooleanSel<S> {
fn select<'a,'b,F>(&self, input: &JsonPath<'a,'b>, mut f: F)
where F: for<'c> FnMut(&JsonPath<'a,'c>) {
self.inner.select(input, |x| {
match x.node() {
&Json::Boolean(..) => f(x),
_ => ()
}
})
}
}
impl<S:Selector> Selector for BooleanEquals<S> {
fn select<'a,'b,F>(&self, input: &JsonPath<'a,'b>, mut f: F)
where F: for<'c> FnMut(&JsonPath<'a,'c>) {
self.inner.select(input, |x| {
match x.node() {
&Json::Boolean(b) if b == self.comp => f(x),
_ => ()
}
})
}
}
pub struct U64Sel<S> {
inner: S
}
pub struct U64Equals<S> {
inner: S,
comp: u64
}
impl<S:Selector> U64Sel<S> {
#[inline]
pub fn equals(self, comp: u64) -> U64Equals<S> {
let U64Sel { inner } = self;
U64Equals { inner: inner, comp: comp }
}
}
impl<S:Selector> Selector for U64Sel<S> {
fn select<'a,'b,F>(&self, input: &JsonPath<'a,'b>, mut f: F)
where F: for<'c> FnMut(&JsonPath<'a,'c>) {
self.inner.select(input, |x| {
match x.node() {
&Json::U64(..) => f(x),
_ => ()
}
})
}
}
impl<S:Selector> Selector for U64Equals<S> {
fn select<'a,'b,F>(&self, input: &JsonPath<'a,'b>, mut f: F)
where F: for<'c> FnMut(&JsonPath<'a,'c>) {
self.inner.select(input, |x| {
match x.node() {
&Json::U64(b) if b == self.comp => f(x),
_ => ()
}
})
}
}
pub struct I64Sel<S> {
inner: S
}
pub struct I64Equals<S> {
inner: S,
comp: i64
}
impl<S:Selector> I64Sel<S> {
#[inline]
pub fn equals(self, comp: i64) -> I64Equals<S> {
let I64Sel { inner } = self;
I64Equals { inner: inner, comp: comp }
}
}
impl<S:Selector> Selector for I64Sel<S> {
fn select<'a,'b,F>(&self, input: &JsonPath<'a,'b>, mut f: F)
where F: for<'c> FnMut(&JsonPath<'a,'c>) {
self.inner.select(input, |x| {
match x.node() {
&Json::I64(..) => f(x),
_ => ()
}
})
}
}
impl<S:Selector> Selector for I64Equals<S> {
fn select<'a,'b,F>(&self, input: &JsonPath<'a,'b>, mut f: F)
where F: for<'c> FnMut(&JsonPath<'a,'c>) {
self.inner.select(input, |x| {
match x.node() {
&Json::I64(b) if b == self.comp => f(x),
_ => ()
}
})
}
}
pub struct F64Sel<S> {
inner: S
}
pub struct F64Equals<S> {
inner: S,
comp: f64
}
impl<S:Selector> F64Sel<S> {
#[inline]
pub fn equals(self, comp: f64) -> F64Equals<S> {
let F64Sel { inner } = self;
F64Equals { inner: inner, comp: comp }
}
}
impl<S:Selector> Selector for F64Sel<S> {
fn select<'a,'b,F>(&self, input: &JsonPath<'a,'b>, mut f: F)
where F: for<'c> FnMut(&JsonPath<'a,'c>) {
self.inner.select(input, |x| {
match x.node() {
&Json::F64(..) => f(x),
_ => ()
}
})
}
}
impl<S:Selector> Selector for F64Equals<S> {
fn select<'a,'b,F>(&self, input: &JsonPath<'a,'b>, mut f: F)
where F: for<'c> FnMut(&JsonPath<'a,'c>) {
self.inner.select(input, |x| {
match x.node() {
&Json::F64(b) if b == self.comp => f(x),
_ => ()
}
})
}
}
pub struct NullSel<S> {
inner: S
}
impl<S:Selector> Selector for NullSel<S> {
fn select<'a,'b,F>(&self, input: &JsonPath<'a,'b>, mut f: F)
where F: for<'c> FnMut(&JsonPath<'a,'c>) {
self.inner.select(input, |x| {
match x.node() {
&Json::Null => f(x),
_ => ()
}
})
}
}
pub struct At<S> {
inner: S,
index: usize
}
impl<S:Selector> Selector for At<S> {
fn select<'a,'b,F>(&self, input: &JsonPath<'a,'b>, mut f: F)
where F: for<'c> FnMut(&JsonPath<'a,'c>) {
self.inner.select(input, |x| {
match x.node() {
&Json::Array(ref v) => {
if v.len() > self.index {
f(&x.descendant(&v[self.index]))
}
}
_ => ()
}
})
}
}
pub struct Key<'f,S> {
inner: S,
name: &'f str
}
impl<'f,S:Selector> Selector for Key<'f,S> {
fn select<'a,'b,F>(&self, input: &JsonPath<'a,'b>, mut f: F)
where F: for<'c> FnMut(&JsonPath<'a,'c>) {
self.inner.select(input, |x| {
match x.node() {
&Json::Object(ref m) => {
match m.get(self.name) {
Some(e) => f(&x.descendant(e)),
_ => ()
}
},
_ => ()
}
})
}
}
pub struct Child<S> {
inner: S
}
impl<S:Selector> Selector for Child<S> {
fn select<'a,'b,F>(&self, input: &JsonPath<'a,'b>, mut f: F)
where F: for<'c> FnMut(&JsonPath<'a,'c>) {
self.inner.select(input, |x| {
match x.node() {
&Json::Object(ref m) => {
for (_,child) in m.iter() {
f(&x.descendant(child))
}
},
&Json::Array(ref v) => {
for child in v.iter() {
f(&x.descendant(child))
}
},
_ => ()
}
})
}
}
pub struct Parent<S> {
inner: S
}
impl<S:Selector> Selector for Parent<S> {
fn select<'a,'b,F>(&self, input: &JsonPath<'a,'b>, mut f: F)
where F: for<'c> FnMut(&JsonPath<'a,'c>) {
let mut seen = hash_set::HashSet::new();
self.inner.select(input, |x| {
match x.parent() {
Some(&p) => {
let j = p.node();
if !seen.contains(&(j as *const Json)) {
seen.insert(j as *const Json);
f(&p)
}
}
_ => ()
}
})
}
}
pub struct Descend<S> {
inner: S
}
fn descend_helper<'a,'b,F>(input: &JsonPath<'a,'b>,
seen: &mut hash_set::HashSet<*const Json>,
mut f: F)
where F: for<'c> FnMut(&JsonPath<'a,'c>) {
let j = input.node();
if !seen.contains(&(j as *const Json)) {
seen.insert(j as *const Json);
match j {
&Json::Object(ref m) => {
for (_,c) in m.iter() {
let inner = input.descendant(c);
f(&inner);
descend_helper(&inner, seen, |x| f(x))
}
},
&Json::Array(ref v) => {
for c in v.iter() {
let inner = input.descendant(c);
f(&inner);
descend_helper(&inner, seen, |x| f(x))
}
},
_ => ()
}
}
}
impl<S:Selector> Selector for Descend<S> {
fn select<'a,'b,F>(&self, input: &JsonPath<'a,'b>, mut f: F)
where F: for<'c> FnMut(&JsonPath<'a,'c>) {
let mut seen = hash_set::HashSet::new();
self.inner.select(input, |x| {
descend_helper(x, &mut seen, |x| f(x))
})
}
}
pub struct Ascend<S> {
inner: S
}
fn ascend_helper<'a,'b,F>(input: &JsonPath<'a,'b>,
seen: &mut hash_set::HashSet<*const Json>,
mut f: F)
where F: for<'c> FnMut(&JsonPath<'a,'c>) {
let mut current = *input;
loop {
match current.parent() {
Some(x) => {
let j = x.node();
if !seen.contains(&(j as *const Json)) {
seen.insert(j as *const Json);
f(x);
current = *x;
} else {
break;
}
},
_ => break
}
}
}
impl<S:Selector> Selector for Ascend<S> {
fn select<'a,'b,F>(&self, input: &JsonPath<'a,'b>, mut f: F)
where F: for<'c> FnMut(&JsonPath<'a,'c>) {
let mut seen = hash_set::HashSet::new();
self.inner.select(input, |n| {
ascend_helper(n, &mut seen, |x| f(x));
})
}
}
pub struct Wherein<S,T> {
inner: S,
filter: T
}
impl<S:Selector,T:Selector> Selector for Wherein<S,T> {
fn select<'a,'b,F>(&self, input: &JsonPath<'a,'b>, mut f: F)
where F: for<'c> FnMut(&JsonPath<'a,'c>) {
self.inner.select(input, |x| {
let mut matches = false;
self.filter.select(x, |_| matches = true);
if matches {
f(x)
}
})
}
}
pub struct Union<I,S,T> {
inner: I,
left: S,
right: T
}
impl<I:Selector,S:Selector,T:Selector> Selector for Union<I,S,T> {
fn select<'a,'b,F>(&self, input: &JsonPath<'a,'b>, mut f: F)
where F: for<'c> FnMut(&JsonPath<'a,'c>) {
let mut seen = hash_set::HashSet::new();
self.inner.select(input, |x| {
self.left.select(x, |x| {
let j = x.node();
if !seen.contains(&(j as *const Json)) {
seen.insert(j as *const Json);
f(x)
}
});
self.right.select(x, |x| {
let j = x.node();
if !seen.contains(&(j as *const Json)) {
seen.insert(j as *const Json);
f(x)
}
})
})
}
}
pub struct Intersect<I,S,T> {
inner: I,
left: S,
right: T
}
impl<I:Selector,S:Selector,T:Selector> Selector for Intersect<I,S,T> {
fn select<'a,'b,F>(&self, input: &JsonPath<'a,'b>, mut f: F)
where F: for<'c> FnMut(&JsonPath<'a,'c>) {
let mut seen_left = hash_set::HashSet::new();
let mut seen_right = hash_set::HashSet::new();
self.inner.select(input, |x| {
self.left.select(x, |x| {
let j = x.node();
seen_left.insert(j as *const Json);
if seen_right.contains(&(j as *const Json)) {
f(x)
}
});
self.right.select(x, |x| {
let j = x.node();
seen_right.insert(j as *const Json);
if seen_left.contains(&(j as *const Json)) {
f(x)
}
})
})
}
}
pub struct Diff<I,S,T> {
inner: I,
left: S,
right: T
}
impl<I:Selector,S:Selector,T:Selector> Selector for Diff<I,S,T> {
fn select<'a,'b,F>(&self, input: &JsonPath<'a,'b>, mut f: F)
where F: for<'c> FnMut(&JsonPath<'a,'c>) {
let mut seen = hash_set::HashSet::new();
self.inner.select(input, |x| {
self.right.select(x, |x| {
seen.insert(x.node() as *const Json);
})
});
self.inner.select(input, |x| {
self.left.select(x, |x| {
if !seen.contains(&(x.node() as *const Json)) {
f(x)
}
})
})
}
}
pub struct AndSel<I,S,T> {
inner: I,
left: S,
right: T
}
static SINGLETON: Json = Json::Boolean(true);
impl<I:Selector,S:Selector,T:Selector> Selector for AndSel<I,S,T> {
fn select<'a,'b,F>(&self, input: &JsonPath<'a,'b>, mut f: F)
where F: for<'c> FnMut(&JsonPath<'a,'c>) {
let mut found_left = false;
let mut found_right = false;
self.inner.select(input, |x| {
self.left.select(x, |_| found_left = true);
self.right.select(x, |_| found_right = true)
});
if found_left && found_right {
f(&input.descendant(&SINGLETON))
}
}
}
pub struct OrSel<I,S,T> {
inner: I,
left: S,
right: T
}
impl<I:Selector,S:Selector,T:Selector> Selector for OrSel<I,S,T> {
fn select<'a,'b,F>(&self, input: &JsonPath<'a,'b>, mut f: F)
where F: for<'c> FnMut(&JsonPath<'a,'c>) {
let mut found_left = false;
let mut found_right = false;
self.inner.select(input, |x| {
self.left.select(x, |_| found_left = true);
self.right.select(x, |_| found_right = true)
});
if found_left || found_right {
f(&input.descendant(&SINGLETON))
}
}
}
pub trait JsonExt {
fn query<S:Selector>(&self, s: S) -> Vec<&Json>;
}
impl JsonExt for Json {
fn query<S:Selector>(&self, s: S) -> Vec<&Json> {
let mut outvec = Vec::new();
{
s.select(&JsonPath::root(self), |x| {
outvec.push(x.node())
});
}
outvec
}
}
#[inline]
pub fn node() -> Node {
Node { _dummy: () }
}
#[inline]
pub fn boolean() -> BooleanSel<Node> {
node().boolean()
}
#[inline]
pub fn uint64() -> U64Sel<Node> {
node().uint64()
}
#[inline]
pub fn int64() -> I64Sel<Node> {
node().int64()
}
#[inline]
pub fn float64() -> F64Sel<Node> {
node().float64()
}
#[inline]
pub fn string() -> StringSel<Node> {
node().string()
}
#[inline]
pub fn object() -> ObjectSel<Node> {
node().object()
}
#[inline]
pub fn list() -> ListSel<Node> {
node().list()
}
#[inline]
pub fn null() -> NullSel<Node> {
node().null()
}
#[inline]
pub fn child() -> Child<Node> {
node().child()
}
#[inline]
pub fn parent() -> Parent<Node> {
node().parent()
}
#[inline]
pub fn descend() -> Descend<Node> {
node().descend()
}
#[inline]
pub fn ascend() -> Ascend<Node> {
node().ascend()
}
#[inline]
pub fn at(index: usize) -> At<Node> {
node().at(index)
}
#[inline]
pub fn key<'a>(name: &'a str) -> Key<'a, Node> {
node().key(name)
}
#[inline]
pub fn wherein<T:Selector>(filter: T) -> Wherein<Node,T> {
node().wherein(filter)
}
#[inline]
pub fn intersect<T1:Selector,T2:Selector>(left: T1, right: T2) -> Intersect<Node,T1,T2> {
node().intersect(left, right)
}
#[inline]
pub fn union<T1:Selector,T2:Selector>(left: T1, right: T2) -> Union<Node,T1,T2> {
node().union(left, right)
}
#[inline]
pub fn diff<T1:Selector,T2:Selector>(left: T1, right: T2) -> Diff<Node,T1,T2> {
node().diff(left, right)
}
#[inline]
pub fn and<T1:Selector,T2:Selector>(left: T1, right: T2) -> AndSel<Node,T1,T2> {
node().and(left, right)
}
#[inline]
pub fn or<T1:Selector,T2:Selector>(left: T1, right: T2) -> OrSel<Node,T1,T2> {
node().or(left, right)
}
#[cfg(test)]
mod test {
use super::{child,wherein,Selector,JsonExt};
use serialize::json;
fn from_str(s: &str) -> Option<json::Json> {
s.parse().ok()
}
#[test]
fn parent_unique() {
let json = from_str(r#"[{},{},{},{}]"#).unwrap();
let matches = json.query(child().parent());
assert_eq!(matches.len(), 1);
let matches = json.query(child().parent().child());
assert_eq!(matches.len(), 4);
}
#[test]
fn ascend_unique() {
let json = from_str(r#"[[{}],[{}],[{}],[{}]]"#).unwrap();
let matches = json.query(child().child().ascend());
assert_eq!(matches.len(), 5);
}
#[test]
fn union_unique() {
let json = from_str(r#"[[1],[2],[3],[1,2]]"#).unwrap();
let matches = json.query(
child().union(
wherein(child().uint64().equals(1)),
wherein(child().uint64().equals(2))));
assert_eq!(matches.len(), 3);
}
#[test]
fn match_null() {
let json = from_str(r#"[{},null,{},null,{}]"#).unwrap();
let matches = json.query(child().null());
assert_eq!(matches.len(), 2);
}
}