use crate::{
parser::Parser, reader::Reader, util::utf8::from_utf8, value::Value, JsonInput, Read, Result,
};
pub fn get_by_schema<'de, Input: JsonInput<'de>>(json: Input, mut schema: Value) -> Result<Value> {
let slice = json.to_u8_slice();
let reader = Read::new(slice, false);
let mut parser = Parser::new(reader);
parser.get_by_schema(&mut schema)?;
let index = parser.read.index();
if json.need_utf8_valid() {
from_utf8(&slice[..index])?;
}
Ok(schema)
}
#[cfg(test)]
mod test {
use super::*;
use crate::from_str;
fn test_success(schema: &str, json: &str, expected: &str) {
let schema = from_str(schema).unwrap();
let actual = get_by_schema(json, schema).unwrap();
assert_eq!(from_str::<Value>(expected).unwrap(), actual);
}
fn test_failed(schema: &str, json: &str) {
let schema = from_str(schema).unwrap();
let actual = get_by_schema(json, schema);
assert!(actual.is_err());
}
#[test]
fn test_success_1() {
let (schema, json, expected) = (
r#"{"true": null, "false": null, "null":null, "int": null, "double":null,
"string": null, "object": null, "array": null}"#,
r#"{"true": true, "false": false, "null": null, "int": 1, "double": 1.0, "string": "string",
"object": {
"object": {},
"array": []
},
"array": [{}, [], {"a":1}, [-1]]
}"#,
r#"{"true": true, "false": false, "null": null, "int": 1, "double": 1.0, "string": "string",
"object": {
"object": {},
"array": []
},
"array": [{}, [], {"a":1}, [-1]]
}"#,
);
test_success(schema, json, expected);
}
#[test]
fn test_success_2() {
let (schema, json, expected) = (
r#"{"true": false, "false": true, "null": {}, "int": 2, "double":2.0,
"string": "", "object": null, "array": []}"#,
r#"{"true": true, "false": false, "null": null, "int": 1, "double": 1.0, "string": "string",
"object": {
"object": {},
"array": [{}, [], [{}, []], true, null, "str", 1, 1.0]
},
"array": [{}, [], [{}, []], true, null, "str", 1, 1.0]
}"#,
r#"{"true": true, "false": false, "null": null, "int": 1, "double": 1.0, "string": "string",
"object": {
"object": {},
"array": [{}, [], [{}, []], true, null, "str", 1, 1.0]
},
"array": [{}, [], [{}, []], true, null, "str", 1, 1.0]
}"#,
);
test_success(schema, json, expected);
}
#[test]
fn test_success_3() {
let (schema, json, expected) = (
r#"{"true": null, "false": null, "null":null, "int": null, "double":null,
"string": null, "object": null, "array": null}"#,
"[]",
"[]",
);
test_success(schema, json, expected);
}
#[test]
fn test_success_4() {
let (schema, json, expected) =
(r#"{"obj":{}}"#, r#"{"obj":{"a":1}}"#, r#"{"obj":{"a":1}}"#);
test_success(schema, json, expected);
}
#[test]
fn test_success_5() {
let (schema, json, expected) = (
r#"{"obj":{"a":2}}"#,
r#"{"obj":{"a":1, "b":1}}"#,
r#"{"obj":{"a":1}}"#,
);
test_success(schema, json, expected);
}
#[test]
fn test_success_6() {
let (schema, json, expected) = (
r#"{"bool2bool":true, "bool2int":1, "bool2dbl": 1.0, "bool2str": "str",
"bool2null": null, "bool2obj": {}, "bool2arr": [],
"int2bool":true, "int2int":1, "int2dbl": 1.0, "int2str": "str",
"int2null": null, "int2obj": {}, "int2arr": [],
"dbl2bool":true, "dbl2int":1, "dbl2dbl": 1.0, "dbl2str": "str",
"dbl2null": null, "dbl2obj": {}, "dbl2arr": [],
"str2bool":true, "str2int":1, "str2dbl": 1.0, "str2str": "str",
"str2null": null, "str2obj": {}, "str2arr": [],
"null2bool":true, "null2int":1, "null2dbl": 1.0, "null2str": "str",
"null2null": null, "null2obj": {}, "null2arr": [],
"obj2bool":true, "obj2int":1, "obj2dbl": 1.0, "obj2str": "str",
"obj2null": null, "obj2obj": {}, "obj2arr": [],
"arr2bool":true, "arr2int":1, "arr2dbl": 1.0, "arr2str": "str",
"arr2null": null, "arr2obj": {}, "arr2arr": []
}"#,
r#"{
"bool2bool":false, "bool2int":false, "bool2dbl": false, "bool2str": false,
"bool2null": false, "bool2obj": false, "bool2arr": false,
"int2bool":2, "int2int":2, "int2dbl": 2, "int2str": 2,
"int2null": 2, "int2obj": 2, "int2arr": 2,
"dbl2bool":3.0, "dbl2int":3.0, "dbl2dbl": 3.0, "dbl2str": 3.0,
"dbl2null": 3.0, "dbl2obj": 3.0, "dbl2arr": 3.0,
"str2bool":"string", "str2int":"string", "str2dbl": "string", "str2str": "string",
"str2null": "string", "str2obj": "string", "str2arr": "string",
"null2bool":null, "null2int":null, "null2dbl": null, "null2str": null,
"null2null": null, "null2obj": null, "null2arr": null,
"obj2bool": {"a":1}, "obj2int":{"a":1}, "obj2dbl": {"a":1}, "obj2str":{"a":1},
"obj2null": {"a":1}, "obj2obj": {"a":1}, "obj2arr": {"a":1},
"arr2bool":[1], "arr2int":[1], "arr2dbl": [1], "arr2str": [1],
"arr2null": [1], "arr2obj": [1], "arr2arr": [1]
}"#,
r#"{
"bool2bool":false, "bool2int":false, "bool2dbl": false, "bool2str": false,
"bool2null": false, "bool2obj": false, "bool2arr": false,
"int2bool":2, "int2int":2, "int2dbl": 2, "int2str": 2,
"int2null": 2, "int2obj": 2, "int2arr": 2,
"dbl2bool":3.0, "dbl2int":3.0, "dbl2dbl": 3.0, "dbl2str": 3.0,
"dbl2null": 3.0, "dbl2obj": 3.0, "dbl2arr": 3.0,
"str2bool":"string", "str2int":"string", "str2dbl": "string", "str2str": "string",
"str2null": "string", "str2obj": "string", "str2arr": "string",
"null2bool":null, "null2int":null, "null2dbl": null, "null2str": null,
"null2null": null, "null2obj": null, "null2arr": null,
"obj2bool": {"a":1}, "obj2int":{"a":1}, "obj2dbl": {"a":1}, "obj2str":{"a":1},
"obj2null": {"a":1}, "obj2obj": {"a":1}, "obj2arr": {"a":1},
"arr2bool":[1], "arr2int":[1], "arr2dbl": [1], "arr2str": [1],
"arr2null": [1], "arr2obj": [1], "arr2arr": [1]
}"#,
);
test_success(schema, json, expected);
}
#[test]
fn test_success_7() {
let (schema, json, expected) = (
r#"{"a":1, "b":[1], "c": {"d":1}}"#,
r#"{"o":2, "p":[2], "c":{"k":1}}"#,
r#"{"a":1,"b":[1],"c":{"d":1}}"#,
);
test_success(schema, json, expected);
}
#[test]
fn test_success_8() {
let (schema, json, expected) = (
r#"{"a":1, "b":[1], "c": {}}"#,
r#"{"o":2, "b":[2], "c":{"k":1}}"#,
r#"{"a":1,"b":[2],"c":{"k":1}}"#,
);
test_success(schema, json, expected);
}
#[test]
fn test_failed_1() {
let (schema, json) = ("{}", "nul");
test_failed(schema, json);
}
#[test]
fn test_failed_2() {
let (schema, json) = ("{}", "fals");
test_failed(schema, json);
}
#[test]
fn test_failed_3() {
let (schema, json) = ("{}", "tru");
test_failed(schema, json);
}
#[test]
fn test_failed_4() {
let (schema, json) = ("{}", "string");
test_failed(schema, json);
}
#[test]
fn test_failed_5() {
let (schema, json) = ("{}", r#"{"obj":}"#);
test_failed(schema, json);
}
#[test]
fn test_failed_6() {
let (schema, json) = ("{}", "[null,]");
test_failed(schema, json);
}
#[test]
fn test_failed_7() {
let (schema, json) = ("true", "{}");
test_failed(schema, json);
}
#[test]
fn test_failed_8() {
let (schema, json) = (r#"{"a": 1}"#, "{123}");
test_failed(schema, json);
}
}