arthas 0.3.0

Arthas is an in-memory structure database.
Documentation

use serde_json::{self, Value};
use traits::FieldIntMap;
use std::iter::IntoIterator;
use bincode::SizeLimit;
use bincode::serde::{deserialize, serialize};


pub fn encode_wrapper(value: &Value, field_int_map: &FieldIntMap) -> Value {
    handle_wrapper(Action::Encode, value, field_int_map)
}

pub fn decode_wrapper(value: &Value, field_int_map: &FieldIntMap) -> Value {
    handle_wrapper(Action::Decode, value, field_int_map)
}

enum Action {
    Encode,
    Decode,
}

fn handle_wrapper(action: Action, value: &Value, field_int_map: &FieldIntMap) -> Value {
    if value.is_object() {
        let handled = match action {
            Action::Encode => encode(value.get("item").unwrap(), field_int_map),
            Action::Decode => decode(value.get("item").unwrap(), field_int_map),
        };

        let mut map = serde_json::Map::new();
        map.insert("id".to_owned(), value.get("id").unwrap().to_owned());
        map.insert("item".to_owned(), handled);
        Value::Object(map)
    } else {
        unreachable!()
    }
}

pub fn encode(value: &Value, field_int_map: &FieldIntMap) -> Value {
    let mut output = Value::Object(serde_json::Map::new());

    for (path, integer) in field_int_map {
        encode_segments(path,
                        &mut get_path_segments(path),
                        &mut Vec::new(),
                        value,
                        object_entry(&mut output, integer));
    }

    output
}

fn encode_segments<'a>(path: &str,
                       segments: &mut Vec<&'a str>,
                       current_path: &mut Vec<&'a str>,
                       current_input: &Value,
                       current_output: &mut Value) {
    let segment = segments.remove(0);
    current_path.push(segment);

    if segment == "[]" {
        if current_input.as_array().is_some() {
            for (index, input) in current_input.as_array().unwrap().into_iter().enumerate() {
                encode_segments(path,
                                segments,
                                current_path,
                                input,
                                array_get_value_mut(current_output, index));
            }
        }
    } else if segment == "{}" {
        if current_input.as_object().is_some() {
            for (field, input) in current_input.as_object().unwrap() {
                encode_segments(path,
                                segments,
                                current_path,
                                input,
                                object_entry_value_mut(current_output, field));
            }
        }
    } else if current_path.join(".") == path {
        *current_output = current_input.get(segment).unwrap().clone();
    } else {
        encode_segments(path,
                        segments,
                        current_path,
                        current_input.get(segment).unwrap(),
                        current_output);
    }

    segments.insert(0, segment);
    current_path.pop();
}

pub fn decode(value: &Value, int_field_map: &FieldIntMap) -> Value {
    let mut output = Value::Object(serde_json::Map::new());
    let path_value = replace_integer(value, int_field_map);

    for (path, input) in path_value.as_object().unwrap() {
        decode_segments(path,
                        &mut get_path_segments(path),
                        &mut Vec::new(),
                        input,
                        &mut output);
    }

    output
}

fn decode_segments<'a>(path: &str,
                       segments: &mut Vec<&'a str>,
                       current_path: &mut Vec<&'a str>,
                       current_input: &Value,
                       current_output: &mut Value) {
    let segment = segments.remove(0);
    current_path.push(segment);

    if segment == "[]" {
        if current_input.as_array().is_some() {
            for (index, input) in current_input.as_array().unwrap().into_iter().enumerate() {
                decode_segments(path,
                                segments,
                                current_path,
                                input,
                                array_get_value_mut(current_output, index));
            }
        } else {
            *current_output = Value::Array(Vec::new());
        }
    } else if segment == "{}" {
        if current_input.as_object().is_some() {
            for (field, input) in current_input.as_object().unwrap() {
                decode_segments(path,
                                segments,
                                current_path,
                                input,
                                object_entry_value_mut(current_output, field));
            }
        } else {
            *current_output = Value::Object(serde_json::Map::new());
        }
    } else if current_path.join(".") == path {
        object_insert(current_output, segment, current_input);
    } else {
        decode_segments(path,
                        segments,
                        current_path,
                        current_input,
                        object_entry_value_mut(current_output, segment));
    }

    segments.insert(0, segment);
    current_path.pop();
}

#[inline]
pub fn bin_encode<T: Into<String>>(input: T) -> Vec<u8> {
    serialize(&input.into(), SizeLimit::Infinite).unwrap()
}

#[inline]
pub fn bin_decode<T: AsRef<[u8]>>(input: T) -> String {
    deserialize(input.as_ref()).unwrap()
}

#[inline]
fn replace_integer(value: &Value, int_field_map: &FieldIntMap) -> Value {
    let mut map = serde_json::Map::new();

    for (integer, value) in value.as_object().unwrap() {
        map.insert(int_field_map.get(integer).cloned().unwrap(), value.clone());
    }

    Value::Object(map)

}

#[inline]
fn get_path_segments(path: &str) -> Vec<&str> {
    path.split('.').collect::<Vec<_>>()
}

#[inline]
fn object_entry<'a>(object: &'a mut Value, field: &str) -> &'a mut Value {
    if let Value::Object(ref mut map) = *object {
        if !map.contains_key(field) {
            map.insert(field.to_owned(), Value::Null);
        }

        map.get_mut(field).unwrap()
    } else {
        unreachable!()
    }
}

#[inline]
fn object_insert(object: &mut Value, field: &str, input: &Value) {
    if let Value::Object(ref mut map) = *object {
        map.insert(field.to_owned(), input.clone());
    } else {
        unreachable!()
    }
}

#[inline]
fn array_get_value_mut(array: &mut Value, index: usize) -> &mut Value {
    if array.as_array().is_none() {
        *array = Value::Array(Vec::new());
    }

    if let Value::Array(ref mut vec) = *array {
        if vec.get(index).is_none() {
            vec.push(Value::Object(serde_json::Map::new()));
        }

        &mut vec[index]
    } else {
        unreachable!()
    }
}

#[inline]
fn object_entry_value_mut<'a>(object: &'a mut Value, field: &str) -> &'a mut Value {
    if object.as_object().is_none() {
        *object = Value::Object(serde_json::Map::new());
    }

    if let Value::Object(ref mut map) = *object {
        if !map.contains_key(field) {
            map.insert(field.to_owned(), Value::Object(serde_json::Map::new()));
        }

        map.get_mut(field).unwrap()
    } else {
        unreachable!()
    }
}