Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- use std::collections::HashMap;
- #[derive(Debug, PartialEq)]
- enum Json {
- Number(i64),
- Bool(bool),
- String(String),
- Array(Vec<Json>),
- Object(HashMap<String, Json>),
- }
- struct Pointer<'a, 'b> {
- value: &'a mut Json,
- path: Vec<&'b str>,
- position: usize,
- }
- enum Either<'a, 'b> {
- Left(Pointer<'a, 'b>),
- Right(Vec<&'b str>)
- }
- fn nearest_mut<'a, 'b>(obj: &'a mut Json, path: Vec<&'b str>) -> Pointer<'a, 'b> {
- let valid_path = nearest_path(obj, path);
- exact_mut(obj, valid_path).unwrap()
- }
- fn exact_mut<'a, 'b>(obj: &'a mut Json, path: Vec<&'b str>) -> Option<Pointer<'a, 'b>> {
- let mut i = 0;
- let mut target = obj;
- for token in path.iter() {
- i += 1;
- // borrow checker gets confused about `target` being mutably borrowed too many times because of the loop
- // this once-per-loop binding makes the scope clearer and circumvents the error
- let target_once = target;
- let target_opt = match *target_once {
- Json::Object(ref mut map) => map.get_mut(*token),
- Json::Array(ref mut list) => match token.parse::<usize>() {
- Ok(t) => list.get_mut(t),
- Err(_) => None,
- },
- _ => None,
- };
- if let Some(t) = target_opt {
- target = t;
- } else {
- return None;
- }
- }
- Some(Pointer {
- path,
- position: i,
- value: target,
- })
- }
- /// Return a mutable pointer to JSON element having shared
- /// the nearest common path with provided JSON.
- fn nearest_path<'a, 'b>(obj: &'a Json, path: Vec<&'b str>) -> Vec<&'b str> {
- let mut i = 0;
- let mut target = obj;
- let mut valid_paths = vec![];
- for token in path.iter() {
- // borrow checker gets confused about `target` being mutably borrowed too many times because of the loop
- // this once-per-loop binding makes the scope clearer and circumvents the error
- let target_opt = match *target {
- Json::Object(ref map) => map.get(*token),
- Json::Array(ref list) => match token.parse::<usize>() {
- Ok(t) => list.get(t),
- Err(_) => None,
- },
- _ => None,
- };
- if let Some(t) = target_opt {
- target = t;
- valid_paths.push(*token)
- } else {
- return valid_paths;
- }
- }
- return valid_paths
- }
- #[test]
- fn nearest_path_test() {
- let baz_obj = Json::String("baz".to_string());
- let bar_obj = Json::Object(vec![
- ("baz".to_string(), baz_obj)].into_iter().collect());
- let mut foo_obj = Json::Object(vec![
- ("bar".to_string(), bar_obj)].into_iter().collect());
- let output:Vec<String> = match nearest_mut(&mut foo_obj, vec!["foo","baz"]).value {
- Json::Object(k) => k.keys().map(|r| r.clone()).collect(),
- _ => vec![]
- };
- assert_eq!(output, vec!["bar".to_string()])
- }
- #[test]
- fn exact_path_test() {
- let baz_obj = Json::String("baz".to_string());
- let bar_obj = Json::Object(vec![
- ("baz".to_string(), baz_obj)].into_iter().collect());
- let mut foo_obj = Json::Object(vec![
- ("bar".to_string(), bar_obj)].into_iter().collect());
- let output:String = match nearest_mut(&mut foo_obj, vec!["bar","baz"]).value {
- Json::String(r) => r.clone(),
- _ => "".to_string()
- };
- assert_eq!(output, "baz".to_string())
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement