#[derive(Debug,PartialEq)]
pub enum Json {
JSON {
value: Vec<Json>,
},
OBJECT {
name: String,
value: Vec<Json>,
},
ARRAY {
name: String,
value: Vec<ArrayVal>,
},
STRING {
name: String,
value: String,
},
NUMBER {
name: String,
value: f32,
},
BOOL {
name: String,
value: bool,
},
NULL {
name: String,
}
}
#[derive(Debug,PartialEq)]
pub enum ArrayVal {
STRING(String),
NUMBER(f32),
BOOL(bool),
NULL,
}
impl Json {
pub fn new() -> Json {
Json::JSON {
value: Vec::new(),
}
}
pub fn add_object(&mut self, name: String, value: Vec<Json>) -> &mut Json {
match self {
Json::JSON { value: j_val }=> {
j_val.push(Json::OBJECT { name, value });
match j_val.last_mut() {
Some(value) => {
return value;
},
None => {
panic!("Unexpected error in `add_object(...)`. Should never occur.")
}
}
},
Json::OBJECT { name: _, value: o_val } => {
o_val.push(Json::OBJECT { name, value });
match o_val.last_mut() {
Some(value) => {
return value;
},
None => {
panic!("Unexpected error in `add_object(...)`. Should never occur.")
}
}
},
_ => {
panic!("The function `add_object(`name`,`value`)` may only be called on a `Json::JSON` or `Json::OBJECT`.");
}
}
}
pub fn add_array(&mut self, name: String, value: Vec<ArrayVal>) -> &mut Json {
match self {
Json::JSON { value: j_val }=> {
j_val.push(Json::ARRAY { name, value });
return self;
},
Json::OBJECT { name: _, value: o_val } => {
o_val.push(Json::ARRAY { name, value });
return self;
},
_ => {
panic!("The function `add_array(`name`,`value`)` may only be called on a `Json::JSON` or `Json::OBJECT`.");
}
}
}
pub fn add_string(&mut self, name: String, value: String) -> &mut Json{
match self {
Json::JSON { value: j_val }=> {
j_val.push(Json::STRING { name, value });
return self;
},
Json::OBJECT { name: _, value: o_val } => {
o_val.push(Json::STRING { name, value });
return self;
},
_ => {
panic!("The function `add_string(`name`,`value`)` may only be called on a `Json::JSON` or `Json::OBJECT`.");
}
}
}
pub fn arr_add_string(&mut self, value: String) {
match self {
Json::ARRAY { name: _, value: a_val } => {
a_val.push(ArrayVal::STRING(value));
},
_ => {
panic!("Functions starting with `arr_` may only be called on a `Json::ARRAY`.");
}
}
}
pub fn add_number(&mut self, name: String, value: f32) -> &mut Json{
match self {
Json::JSON { value: j_val }=> {
j_val.push(Json::NUMBER { name, value });
return self;
},
Json::OBJECT { name: _, value: o_val } => {
o_val.push(Json::NUMBER { name, value });
return self;
},
_ => {
panic!("The function `add_number(`name`,`value`)` may only be called on a `Json::JSON` or `Json::OBJECT`.");
}
}
}
pub fn arr_add_number(&mut self, value: f32) {
match self {
Json::ARRAY { name: _, value: a_val } => {
a_val.push(ArrayVal::NUMBER(value));
},
_ => {
panic!("Functions starting with `arr_` may only be called on a `Json::ARRAY`.");
}
}
}
pub fn add_bool(&mut self, name: String, value: bool) -> &mut Json {
match self {
Json::JSON { value: j_val }=> {
j_val.push(Json::BOOL { name, value });
return self;
},
Json::OBJECT { name: _, value: o_val } => {
o_val.push(Json::BOOL { name, value });
return self;
},
_ => {
panic!("The function `add_bool(`name`,`value`)` may only be called on a `Json::JSON` or `Json::OBJECT`.");
}
}
}
pub fn arr_add_bool(&mut self, value: bool) {
match self {
Json::ARRAY { name: _, value: a_val } => {
a_val.push(ArrayVal::BOOL(value));
},
_ => {
panic!("Functions starting with `arr_` may only be called on a `Json::ARRAY`.");
}
}
}
pub fn add_null(&mut self, name: String) -> &mut Json{
match self {
Json::JSON { value: j_val }=> {
j_val.push(Json::NULL { name });
return self;
},
Json::OBJECT { name: _, value: o_val } => {
o_val.push(Json::NULL { name });
return self;
},
_ => {
panic!("The function `add_null(`name`)` may only be called on a `Json::JSON` or `Json::OBJECT`.");
}
}
}
pub fn arr_add_null(&mut self) {
match self {
Json::ARRAY { name: _, value: a_val } => {
a_val.push(ArrayVal::NULL);
},
_ => {
panic!("Functions starting with `arr_` may only be called on a `Json::ARRAY`.");
}
}
}
pub fn get(&self, name: &str) -> Option<&Json> {
match self {
Json::JSON { value } => {
for n in 0..value.len() {
match &value[n] {
Json::JSON { value: _ } => {
panic!("A `Json::JSON` may not contain a `Json::JSON`.");
},
Json::OBJECT { name: comp, value: _ } => {
match name == comp {
false => {},
true => {
return Some(&value[n]);
}
}
},
Json::ARRAY { name: comp, value: _} => {
match name == comp {
false => {},
true => {
return Some(&value[n]);
}
}
},
Json::STRING { name: comp, value: _} => {
match name == comp {
false => {},
true => {
return Some(&value[n]);
}
}
},
Json::NUMBER { name: comp, value: _ } => {
match name == comp {
false => {},
true => {
return Some(&value[n]);
}
}
},
Json::BOOL { name: comp, value: _ } => {
match name == comp {
false => {},
true => {
return Some(&value[n]);
}
}
},
Json::NULL { name: comp } => {
match name == comp {
false => {},
true => {
return Some(&value[n]);
}
}
}
}
}
return None;
},
Json::OBJECT { name: _, value } => {
for n in 0..value.len() {
match &value[n] {
Json::JSON { value: _ } => {
panic!("A `Json::OBJECT` may not contain a `Json::JSON`.");
},
Json::OBJECT { name: comp, value: _ } => {
match name == comp {
false => {},
true => {
return Some(&value[n]);
}
}
},
Json::ARRAY { name: comp, value: _} => {
match name == comp {
false => {},
true => {
return Some(&value[n]);
}
}
},
Json::STRING { name: comp, value: _} => {
match name == comp {
false => {},
true => {
return Some(&value[n]);
}
}
},
Json::NUMBER { name: comp, value: _ } => {
match name == comp {
false => {},
true => {
return Some(&value[n]);
}
}
},
Json::BOOL { name: comp, value: _ } => {
match name == comp {
false => {},
true => {
return Some(&value[n]);
}
}
},
Json::NULL { name: comp } => {
match name == comp {
false => {},
true => {
return Some(&value[n]);
}
}
}
}
}
return None;
},
_ => {
panic!("The function `get(`name`)` may only be called on a `Json::JSON` or `Json::OBJECT`");
}
}
}
pub fn arr_get(&self, which: usize) -> Option<&ArrayVal> {
todo!()
}
pub fn get_mut(&mut self, name: &str) -> Option<&mut Json> {
todo!()
}
pub fn arr_get_mut(&mut self, which: usize) -> Option<&mut ArrayVal> {
todo!()
}
pub fn names_match(&self, name: &Vec<String>) -> bool {
match self {
Json::JSON { value: left } => {
match left.len() == name.len() {
false => {
return false;
},
true => {
let mut result = false;
for n in 0..left.len() {
match &left[n] {
Json::JSON { value: _ } => {
panic!("A `Json::JSON` may not contain a `Json::JSON`.");
},
Json::OBJECT { name: left, value: _ } => {
result = left == &name[n];
},
Json::ARRAY { name: left, value: _ } => {
result = left == &name[n];
},
Json::STRING { name: left, value: _ } => {
result = left == &name[n];
},
Json::NUMBER { name: left, value: _ } => {
result = left == &name[n];
},
Json::BOOL { name: left, value: _ } => {
result = left == &name[n];
},
Json::NULL { name: left } => {
result = left == &name[n];
}
}
}
return result;
}
}
},
Json::OBJECT { name: _, value: left} => {
match left.len() == name.len() {
false => {
return false;
},
true => {
let mut result = false;
for n in 0..left.len() {
match &left[n] {
Json::JSON { value: _ } => {
panic!("A `Json::OBJECT` may not contain a `Json::JSON`.")
},
Json::OBJECT { name: left, value: _ } => {
result = left == &name[n];
},
Json::ARRAY { name: left, value: _ } => {
result = left == &name[n];
},
Json::STRING { name: left, value: _ } => {
result = left == &name[n];
},
Json::NUMBER { name: left, value: _ } => {
result = left == &name[n];
},
Json::BOOL { name: left, value: _ } => {
result = left == &name[n];
},
Json::NULL { name: left } => {
result = left == &name[n];
}
}
}
return result;
}
}
},
_ => {
panic!("The function `names_match(`&self`,`name`)` may only be called on a `Json::JSON` or `Json::OBJECT`.");
}
}
}
pub fn form_matches(&self, reference: &Json) -> bool {
match self {
Json::JSON { value: left } => {
match reference {
Json::JSON { value: right } => {
match left.len() == right.len() {
false => {
return false;
},
true => {
let mut result = false;
for n in 0..left.len() {
match &left[n] {
Json::JSON { value: _ } => {
panic!("A `Json::JSON` may not contain a `Json::JSON`.");
},
Json::OBJECT { name: name_l, value: _ } => {
match &right[n] {
Json::OBJECT { name: name_r, value: _} => {
result = name_l == name_r;
},
_ => {
result = false;
}
}
},
Json::ARRAY { name: name_l, value: _ } => {
match &right[n] {
Json::ARRAY { name: name_r, value: _} => {
result = name_l == name_r;
},
_ => {
result = false;
}
}
},
Json::STRING { name: name_l, value: _ } => {
match &right[n] {
Json::STRING { name: name_r, value: _} => {
result = name_l == name_r;
},
_ => {
result= false;
}
}
},
Json::NUMBER { name: name_l, value: _ } => {
match &right[n] {
Json::NUMBER { name: name_r, value: _} => {
result = name_l == name_r;
},
_ => {
result = false;
}
}
},
Json::BOOL { name: name_l, value: _ } => {
match &right[n] {
Json::BOOL { name: name_r, value: _} => {
result = name_l == name_r;
},
_ => {
result = false;
}
}
},
Json::NULL { name: name_l } => {
match &right[n] {
Json::NULL { name: name_r } => {
result = name_l == name_r;
},
_ => {
result = false;
}
}
},
}
}
return result;
},
}
},
_ => {
panic!("The function `matches_names(`&self`,`reference`)` requires `reference` to be `Json::JSON` if called on a `Json::JSON`.");
}
}
},
Json::OBJECT { name: _, value: left } => {
match reference {
Json::OBJECT { name: _, value: right } => {
match left.len() == right.len() {
false => {
return false;
},
true => {
let mut result = false;
for n in 0..left.len() {
match &left[n] {
Json::JSON { value: _ } => {
panic!("A `Json::OBJECT` may not contain a `Json::JSON`.");
},
Json::OBJECT { name: name_l, value: _ } => {
match &right[n] {
Json::OBJECT { name: name_r, value: _} => {
result = name_l == name_r;
},
_ => {
result = false;
}
}
},
Json::ARRAY { name: name_l, value: _ } => {
match &right[n] {
Json::ARRAY { name: name_r, value: _} => {
result = name_l == name_r;
},
_ => {
result = false;
}
}
},
Json::STRING { name: name_l, value: _ } => {
match &right[n] {
Json::STRING { name: name_r, value: _} => {
result = name_l == name_r;
},
_ => {
result= false;
}
}
},
Json::NUMBER { name: name_l, value: _ } => {
match &right[n] {
Json::NUMBER { name: name_r, value: _} => {
result = name_l == name_r;
},
_ => {
result = false;
}
}
},
Json::BOOL { name: name_l, value: _ } => {
match &right[n] {
Json::BOOL { name: name_r, value: _} => {
result = name_l == name_r;
},
_ => {
result = false;
}
}
},
Json::NULL { name: name_l } => {
match &right[n] {
Json::NULL { name: name_r } => {
result = name_l == name_r;
},
_ => {
result = false;
}
}
},
}
}
return result;
},
}
},
_ => {
panic!("The function `form_matches(`&self`,`reference`)` requires `reference` to be `Json::OBJECT` if called on a `Json::OBJECT`.");
}
}
},
_ => {
panic!("The function `form_matches(`&self`,`reference`)` may only be called on `Json::JSON` or `Json::OBJECT`.");
}
}
}
pub fn is_object(&self) -> bool {
todo!()
}
pub fn is_array(&self) -> bool {
todo!()
}
pub fn is_string(&self) -> bool {
todo!()
}
pub fn is_number(&self) -> bool {
todo!()
}
pub fn is_bool(&self) -> bool {
todo!()
}
pub fn is_null(&self) -> bool {
match self {
Json::NULL { name: _ } => {
return true;
},
_ => {
return false;
},
}
}
pub fn print(&self) -> String {
match self {
Json::JSON { value } => {
let mut s = String::from("{");
for n in 0..value.len() {
match &value[n] {
Json::JSON { value: _} => {
panic!("A `Json::JSON` may not contain a `Json::JSON`.");
},
_ => {
s.push_str(&value[n].print());
s.push(',');
}
}
}
s.pop();
s.push('}');
return s;
},
Json::OBJECT { name, value } => {
let mut s = format!("\"{}\":",name);
s.push('{');
for n in 0..value.len() {
match &value[n] {
Json::JSON { value: _} => {
panic!("A `Json::OBJECT` may not contain a `Json::JSON`.");
},
_ => {
s.push_str(&value[n].print());
s.push(',');
}
}
}
s.pop();
s.push('}');
return s;
},
Json::ARRAY { name, value } => {
let mut s = String::from("[");
for n in 0..value.len() {
match &value[n] {
ArrayVal::STRING(value) => {
s.push_str(&format!("\"{}\",",value));
},
ArrayVal::NUMBER(value) => {
s.push_str(&format!("{},",value));
},
ArrayVal::BOOL(value) => {
match value {
true => {
s.push_str("true,");
},
false => {
s.push_str("false,");
},
}
},
ArrayVal::NULL => {
s.push_str("null,");
},
}
}
s.pop();
s.push(']');
return format!("\"{}\":{}",name,s);
},
Json::STRING { name, value } => {
return format!("\"{}\":\"{}\"",name,value);
},
Json::NUMBER { name, value } => {
return format!("\"{}\":{}",name,value);
},
Json::BOOL { name, value } => {
match value {
true => {
return format!("\"{}\":true",name);
},
false => {
return format!("\"{}\":false",name);
},
}
},
Json::NULL { name } => {
return format!("\"{}\":null",name);
},
}
}
pub fn pretty_print(&self) -> String {
todo!()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_construct_json() {
let json = Json::new();
match json {
Json::JSON { value } => {
assert_eq!(value.len(),0);
},
_ => {
panic!("Expected `Json::JSON`.");
}
}
}
#[test]
fn test_add_values() {
let mut json = Json::new();
json.add_bool("works".to_string(), true);
json.add_array("array".to_string(), vec![]);
json.add_null("nothing".to_string());
json.add_string("hello".to_string(),"world".to_string());
json.add_number("version".to_string(),1.0);
match json {
Json::JSON { value } => {
assert_eq!(value[0],Json::BOOL { name: String::from("works"), value: true });
assert_eq!(value[1],Json::ARRAY { name: String::from("array"), value: Vec::new() });
assert_eq!(value[2],Json::NULL { name: String::from("nothing") });
assert_eq!(value[3],Json::STRING { name: String::from("hello"), value: String::from("world") });
assert_eq!(value[4],Json::NUMBER { name: String::from("version"), value: 1.0 });
},
_ => {
panic!("Expected `Json::JSON`.");
}
}
}
#[test]
fn test_get() {
let mut json = Json::new();
json.add_null(String::from("hello"));
json.add_null(String::from("world"));
match json.get("hello") {
Some(json) => {
match json {
Json::NULL { name } => {
assert_eq!("hello", &name[..]);
},
_ => {
panic!("Expected `Json::NULL`.");
}
}
},
None => {
panic!("Was not found.");
}
}
match json.get("world") {
Some(json) => {
match json {
Json::NULL { name } => {
assert_eq!("world", &name[..]);
},
_ => {
panic!("Expected `Json::NULL`.");
}
}
},
None => {
panic!("Was not found.");
}
}
}
#[test]
fn test_matches_description() {
}
#[test]
fn test_match_names() {
let mut reference = Vec::new();
reference.push(String::from("one"));
reference.push(String::from("two"));
reference.push(String::from("three"));
reference.push(String::from("four"));
reference.push(String::from("five"));
let mut json = Json::new();
json.add_bool(String::from("one"), true);
json.add_string(String::from("two"), String::from("yes"));
json.add_number(String::from("three"), 3.3);
json.add_null(String::from("four"));
json.add_array(String::from("five"), Vec::new());
assert!(json.names_match(&reference));
}
#[test]
fn test_print() {
let mut json = Json::new();
json.add_string(String::from("Hello"), String::from("World!"));
json.add_number(String::from("Version"),1.0);
json.add_array(String::from("Print functions"), vec![ArrayVal::STRING(String::from("print(&self)")),ArrayVal::STRING(String::from("pretty_print(&self)"))]);
json.add_bool(String::from("Hope this works"), true);
json.add_null(String::from("Problems"));
json.add_object(String::from("More info"),Vec::new()).add_array(String::from("Todo"),vec![ArrayVal::STRING(String::from("parser")),ArrayVal::STRING(String::from("etc"))]);
match json.get("Hello") {
Some(json) => {
assert_eq!("\"Hello\":\"World!\"",&json.print());
},
None => {
panic!("Hello was not found.");
}
}
match json.get("Version") {
Some(json) => {
assert_eq!("\"Version\":1",&json.print());
},
None => {
panic!("Version was not found.")
}
}
match json.get("Print functions") {
Some(json) => {
assert_eq!("\"Print functions\":[\"print(&self)\",\"pretty_print(&self)\"]",&json.print());
},
None => {
panic!("Print functions not found");
}
}
match json.get("Hope this works") {
Some(json) => {
assert_eq!("\"Hope this works\":true",&json.print());
},
None => {
panic!("Hope this works not found.");
},
}
match json.get("Problems") {
Some(json) => {
assert_eq!("\"Problems\":null",&json.print());
},
None => {
panic!("Problems not found xD .");
}
}
match json.get("More info") {
Some(json) => {
assert_eq!("\"More info\":{\"Todo\":[\"parser\",\"etc\"]}",&json.print());
},
None => {
},
}
assert_eq!("{\"Hello\":\"World!\",\"Version\":1,\"Print functions\":[\"print(&self)\",\"pretty_print(&self)\"],\"Hope this works\":true,\"Problems\":null,\"More info\":{\"Todo\":[\"parser\",\"etc\"]}}",&json.print());
}
}