From 4c57761fec01eb1ff49a2b4a95ebdd1d6ba3602f Mon Sep 17 00:00:00 2001 From: Samuel Colvin Date: Wed, 1 Nov 2023 18:30:30 +0000 Subject: [PATCH] adding index to JsonValue --- src/lib.rs | 2 +- src/value.rs | 49 +++++++++++++++++++------------- tests/main.rs | 78 ++++++++++++++++++++++++++++----------------------- 3 files changed, 74 insertions(+), 55 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 2249af97..b4cb8899 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -18,7 +18,7 @@ pub use lazy_index_map::LazyIndexMap; pub use number_decoder::{NumberAny, NumberFloat, NumberInt, NumberRange}; pub use parse::{Parser, Peak}; pub use string_decoder::{StringDecoder, StringDecoderRange}; -pub use value::{JsonArray, JsonObject, JsonValue}; +pub use value::{JsonArray, JsonData, JsonObject, JsonValue}; #[cfg(feature = "python")] pub use python::python_parse; diff --git a/src/value.rs b/src/value.rs index 0e945485..2b018abb 100644 --- a/src/value.rs +++ b/src/value.rs @@ -11,7 +11,13 @@ use crate::string_decoder::{StringDecoder, Tape}; use crate::JsonError; #[derive(Clone, Debug, PartialEq)] -pub enum JsonValue { +pub struct JsonValue { + pub index: usize, + pub data: JsonData, +} + +#[derive(Clone, Debug, PartialEq)] +pub enum JsonData { Null, Bool(bool), Int(i64), @@ -27,15 +33,15 @@ pub type JsonObject = Arc>; #[cfg(feature = "python")] impl pyo3::ToPyObject for JsonValue { fn to_object(&self, py: pyo3::Python<'_>) -> pyo3::PyObject { - match self { - Self::Null => py.None(), - Self::Bool(b) => b.to_object(py), - Self::Int(i) => i.to_object(py), - Self::BigInt(b) => b.to_object(py), - Self::Float(f) => f.to_object(py), - Self::String(s) => s.to_object(py), - Self::Array(v) => pyo3::types::PyList::new(py, v.iter().map(|v| v.to_object(py))).to_object(py), - Self::Object(o) => { + match &self.data { + JsonData::Null => py.None(), + JsonData::Bool(b) => b.to_object(py), + JsonData::Int(i) => i.to_object(py), + JsonData::BigInt(b) => b.to_object(py), + JsonData::Float(f) => f.to_object(py), + JsonData::String(s) => s.to_object(py), + JsonData::Array(v) => pyo3::types::PyList::new(py, v.iter().map(|v| v.to_object(py))).to_object(py), + JsonData::Object(o) => { let dict = pyo3::types::PyDict::new(py); for (k, v) in o.iter() { dict.set_item(k, v.to_object(py)).unwrap(); @@ -61,6 +67,10 @@ impl JsonValue { parser.finish().map_err(map_err)?; Ok(v) } + + pub fn new(index: usize, data: JsonData) -> Self { + Self { index, data } + } } macro_rules! check_recursion { @@ -82,29 +92,30 @@ pub(crate) fn take_value( tape: &mut Tape, mut recursion_limit: u8, ) -> JsonResult { + let index = parser.index; match peak { Peak::True => { parser.consume_true()?; - Ok(JsonValue::Bool(true)) + Ok(JsonValue::new(index, JsonData::Bool(true))) } Peak::False => { parser.consume_false()?; - Ok(JsonValue::Bool(false)) + Ok(JsonValue::new(index, JsonData::Bool(false))) } Peak::Null => { parser.consume_null()?; - Ok(JsonValue::Null) + Ok(JsonValue::new(index, JsonData::Null)) } Peak::String => { let s = parser.consume_string::(tape)?; - Ok(JsonValue::String(s.to_string())) + Ok(JsonValue::new(index, JsonData::String(s.to_string()))) } Peak::Num(first) => { let n = parser.consume_number::(first)?; match n { - NumberAny::Int(NumberInt::Int(int)) => Ok(JsonValue::Int(int)), - NumberAny::Int(NumberInt::BigInt(big_int)) => Ok(JsonValue::BigInt(big_int)), - NumberAny::Float(float) => Ok(JsonValue::Float(float)), + NumberAny::Int(NumberInt::Int(int)) => Ok(JsonValue::new(index, JsonData::Int(int))), + NumberAny::Int(NumberInt::BigInt(big_int)) => Ok(JsonValue::new(index, JsonData::BigInt(big_int))), + NumberAny::Float(float) => Ok(JsonValue::new(index, JsonData::Float(float))), } } Peak::Array => { @@ -122,7 +133,7 @@ pub(crate) fn take_value( array.push(v); } } - Ok(JsonValue::Array(Arc::new(array))) + Ok(JsonValue::new(index, JsonData::Array(Arc::new(array)))) } Peak::Object => { // same for objects @@ -144,7 +155,7 @@ pub(crate) fn take_value( } } - Ok(JsonValue::Object(Arc::new(object))) + Ok(JsonValue::new(index, JsonData::Object(Arc::new(object)))) } } } diff --git a/tests/main.rs b/tests/main.rs index 7af96659..308cd387 100644 --- a/tests/main.rs +++ b/tests/main.rs @@ -7,8 +7,8 @@ use std::sync::Arc; use smallvec::smallvec; use jiter::{ - FilePosition, Jiter, JiterErrorType, JsonErrorType, JsonResult, JsonType, JsonValue, LazyIndexMap, NumberAny, - NumberInt, Parser, Peak, StringDecoder, StringDecoderRange, + FilePosition, Jiter, JiterErrorType, JsonData, JsonErrorType, JsonResult, JsonType, JsonValue, LazyIndexMap, + NumberAny, NumberInt, Parser, Peak, StringDecoder, StringDecoderRange, }; fn json_vec(parser: &mut Parser, peak: Option) -> JsonResult> { @@ -387,14 +387,14 @@ test_position! { #[test] fn parse_tiny_float() { let v = JsonValue::parse(b"8e-7766666666").unwrap(); - assert_eq!(v, JsonValue::Float(0.0)); + assert_eq!(v, JsonData::Float(0.0)); } #[test] fn parse_zero_float() { let v = JsonValue::parse(b"0.1234").unwrap(); match v { - JsonValue::Float(v) => assert!((0.1234 - v).abs() < 1e-6), + JsonData::Float(v) => assert!((0.1234 - v).abs() < 1e-6), other => panic!("unexpected value: {other:?}"), }; } @@ -403,7 +403,7 @@ fn parse_zero_float() { fn parse_zero_exp_float() { let v = JsonValue::parse(b"0.12e3").unwrap(); match v { - JsonValue::Float(v) => assert!((120.0 - v).abs() < 1e-3), + JsonData::Float(v) => assert!((120.0 - v).abs() < 1e-3), other => panic!("unexpected value: {other:?}"), }; } @@ -431,7 +431,7 @@ fn udb_string() { let bytes: Vec = vec![34, 92, 117, 100, 66, 100, 100, 92, 117, 100, 70, 100, 100, 34]; let v = JsonValue::parse(&bytes).unwrap(); match v { - JsonValue::String(s) => assert_eq!(s.as_bytes(), [244, 135, 159, 157]), + JsonData::String(s) => assert_eq!(s.as_bytes(), [244, 135, 159, 157]), _ => panic!("unexpected value {v:?}"), } } @@ -442,16 +442,23 @@ fn parse_object() { let v = JsonValue::parse(json.as_bytes()).unwrap(); let mut expected = LazyIndexMap::new(); - expected.insert("foo".to_string(), JsonValue::String("bar".to_string())); + expected.insert( + "foo".to_string(), + JsonValue::new(1, JsonData::String("bar".to_string())), + ); expected.insert( "spam".to_string(), - JsonValue::Array(Arc::new(smallvec![ - JsonValue::Int(1), - JsonValue::Null, - JsonValue::Bool(true) - ])), + JsonValue::new( + 15, + JsonData::Array(Arc::new(smallvec![ + JsonData::Int(1), + JsonData::Null, + JsonData::Bool(true) + ])), + ), ); - assert_eq!(v, JsonValue::Object(Arc::new(expected))); + assert_eq!(v.index, 0); + assert_eq!(v.data, JsonData::Object(Arc::new(expected))); } #[test] @@ -460,10 +467,10 @@ fn parse_array_3() { let v = JsonValue::parse(json.as_bytes()).unwrap(); assert_eq!( v, - JsonValue::Array(Arc::new(smallvec![ - JsonValue::Int(1), - JsonValue::Null, - JsonValue::Bool(true) + JsonData::Array(Arc::new(smallvec![ + JsonData::Int(1), + JsonData::Null, + JsonData::Bool(true) ])) ); } @@ -472,7 +479,7 @@ fn parse_array_3() { fn parse_array_empty() { let json = r#"[ ]"#; let v = JsonValue::parse(json.as_bytes()).unwrap(); - assert_eq!(v, JsonValue::Array(Arc::new(smallvec![]))); + assert_eq!(v, JsonData::Array(Arc::new(smallvec![]))); } #[test] @@ -489,12 +496,12 @@ fn parse_value_nested() { let v = JsonValue::parse(json.as_bytes()).unwrap(); assert_eq!( v, - JsonValue::Array(Arc::new(smallvec![ - JsonValue::Int(1), - JsonValue::Int(2), - JsonValue::Array(Arc::new(smallvec![JsonValue::Int(3), JsonValue::Int(4)])), - JsonValue::Int(5), - JsonValue::Int(6), + JsonData::Array(Arc::new(smallvec![ + JsonData::Int(1), + JsonData::Int(2), + JsonData::Array(Arc::new(smallvec![JsonData::Int(3), JsonData::Int(4)])), + JsonData::Int(5), + JsonData::Int(6), ]),) ) } @@ -520,12 +527,12 @@ fn pass1_to_value() { let json = read_file("./benches/pass1.json"); let json_data = json.as_bytes(); let v = JsonValue::parse(json_data).unwrap(); - let array = match v { - JsonValue::Array(array) => array, + let array = match v.data { + JsonData::Array(array) => array, v => panic!("expected array, not {:?}", v), }; assert_eq!(array.len(), 20); - assert_eq!(array[0], JsonValue::String("JSON Test Pattern pass1".to_string())); + assert_eq!(array[0], JsonData::String("JSON Test Pattern pass1".to_string())); } #[test] @@ -655,12 +662,12 @@ fn test_crazy_massive_int() { #[test] fn unique_iter_object() { let value = JsonValue::parse(br#" {"x": 1, "x": 2} "#).unwrap(); - if let JsonValue::Object(obj) = value { + if let JsonData::Object(obj) = value.data { assert_eq!(obj.len(), 1); let mut unique = obj.iter_unique(); let first = unique.next().unwrap(); assert_eq!(first.0, "x"); - assert_eq!(first.1, &JsonValue::Int(2)); + assert_eq!(first.1.data, JsonData::Int(2)); assert!(unique.next().is_none()); } else { panic!("expected object"); @@ -670,12 +677,12 @@ fn unique_iter_object() { #[test] fn unique_iter_object_repeat() { let value = JsonValue::parse(br#" {"x": 1, "x": 1} "#).unwrap(); - if let JsonValue::Object(obj) = value { + if let JsonData::Object(obj) = value.data { assert_eq!(obj.len(), 1); let mut unique = obj.iter_unique(); let first = unique.next().unwrap(); assert_eq!(first.0, "x"); - assert_eq!(first.1, &JsonValue::Int(1)); + assert_eq!(first.1.data, JsonData::Int(1)); assert!(unique.next().is_none()); } else { panic!("expected object"); @@ -698,8 +705,9 @@ fn test_recursion_limit_incr() { let json = format!("[{}]", json); let bytes = json.as_bytes(); let value = JsonValue::parse(bytes).unwrap(); - match value { - JsonValue::Array(v) => { + assert_eq!(value.index, 0); + match value.data { + JsonData::Array(v) => { assert_eq!(v.len(), 2000); } _ => panic!("expected array"), @@ -738,8 +746,8 @@ fn test_4300_int() { let bytes = json.as_bytes(); let value = JsonValue::parse(bytes).unwrap(); let expected_big_int = BigInt::from_str(&json).unwrap(); - match value { - JsonValue::BigInt(v) => { + match value.data { + JsonData::BigInt(v) => { assert_eq!(v, expected_big_int); } _ => panic!("expected array, got {:?}", value),