jsonpath 0.1.1

JSONPath for Rust
Documentation

use serde_json::Value;
use structs::{Criterion, StackItem};

macro_rules! numbers {
  (integer => $next:expr, $operator:tt, $value:expr) => {{
    match $next.item.value {
      &Value::Number(ref source) => {
        match source.as_f64() {
          Some(ref float_value) => Some(*float_value $operator *$value as f64),
          None => {
            match source.as_i64() {
              Some(ref int_value) => Some(int_value $operator $value),
              None => None
            }
          }
        }
      },
      _ => None,
    }
  }};
  (float => $next:expr, $operator:tt, $value:expr) => {{
    match $next.item.value {
      &Value::Number(ref source) => {
        match source.as_f64() {
          Some(ref float_value) => Some(float_value $operator ($value)),
          None => {
            match source.as_i64() {
              Some(ref int_value) => Some((*int_value as f64) $operator *$value),
              None => None
            }
          }
        }
      },
      _ => None,
    }
  }}
}

pub fn filter(pattern: &Criterion, value: &Criterion, next: &StackItem) -> Option<bool> {
  match (pattern, value) {
    (&Criterion::Equal, &Criterion::Literal(ref content)) => {
      Some(next.item.value == content)
    }
    (&Criterion::Different, &Criterion::Literal(ref content)) => {
      Some(next.item.value != content)
    }
    (&Criterion::Lower, &Criterion::Number(ref value)) => {
      numbers!(integer => next, <, value)
    }
    (&Criterion::Greater, &Criterion::Number(ref value)) => {
      numbers!(integer => next, >, value)
    }
    (&Criterion::Lower, &Criterion::Float(ref value)) => {
      numbers!(float => next, <, value)
    }
    (&Criterion::Greater, &Criterion::Float(ref value)) => {
      numbers!(float => next, >, value)
    }
    _ => None
  }
}

pub fn vec_filter(pattern: &Criterion, value: &Criterion, values: &Vec<&Value>) -> Option<bool> {
  match (pattern, value) {
    (&Criterion::Equal, &Criterion::Literal(ref content)) => {
      for v in values.iter() {
        match *v {
          &Value::String(ref string_content) => {
            if string_content != content {
              return Some(false);
            }
          },
          _ => {},
        }
      }
      Some(true)
    }
    (&Criterion::Different, &Criterion::Literal(ref content)) => {
      for v in values.iter() {
        match *v {
          &Value::String(ref string_content) => {
            if string_content == content {
              return Some(false);
            }
          },
          _ => {},
        }
      }
      Some(true)
    }
    (&Criterion::Lower, &Criterion::Number(ref _value)) => {
      unimplemented!()
    }
    (&Criterion::Greater, &Criterion::Number(ref _value)) => {
      unimplemented!()
    }
    (&Criterion::Lower, &Criterion::Float(ref _value)) => {
      unimplemented!()
    }
    (&Criterion::Greater, &Criterion::Float(ref _value)) => {
      unimplemented!()
    }
    _ => None
  }
}