pjson_rs/parser/simd/
mod.rs1#[allow(unused_imports)] use sonic_rs::{JsonContainerTrait, JsonNumberTrait, JsonValueTrait, Value as SonicValue};
8
9pub struct SimdClassifier;
11
12impl SimdClassifier {
13 #[inline(always)]
15 pub fn classify_value_type(value: &SonicValue) -> ValueClass {
16 if value.is_number() {
18 if let Some(num) = value.as_number() {
19 if num.is_i64() {
20 ValueClass::Integer
21 } else if num.is_u64() {
22 ValueClass::UnsignedInteger
23 } else {
24 ValueClass::Float
25 }
26 } else {
27 ValueClass::Float
28 }
29 } else if value.is_str() {
30 ValueClass::String
31 } else if value.is_array() {
32 ValueClass::Array
33 } else if value.is_object() {
34 ValueClass::Object
35 } else if value.as_bool().is_some() {
36 ValueClass::Boolean
37 } else {
38 ValueClass::Null
39 }
40 }
41
42 #[inline(always)]
44 pub fn is_numeric_array(arr: &sonic_rs::Array) -> bool {
45 if arr.len() < 3 {
46 return false;
47 }
48
49 arr.iter().all(|v| v.is_number())
51 }
52
53 #[inline(always)]
55 pub fn calculate_total_string_length(arr: &sonic_rs::Array) -> usize {
56 arr.iter().filter_map(|v| v.as_str()).map(|s| s.len()).sum()
57 }
58
59 #[inline(always)]
61 pub fn scan_object_keys(obj: &sonic_rs::Object) -> KeyScanResult {
62 let mut result = KeyScanResult {
63 has_timestamp: false,
64 has_coordinates: false,
65 has_type_field: false,
66 key_count: obj.len(),
67 };
68
69 for (key, _) in obj.iter() {
71 match key.as_bytes() {
72 b"timestamp" | b"time" => result.has_timestamp = true,
73 b"coordinates" | b"coord" => result.has_coordinates = true,
74 b"type" => result.has_type_field = true,
75 _ => {}
76 }
77 }
78
79 result
80 }
81}
82
83#[derive(Debug, Clone, Copy, PartialEq)]
85pub enum ValueClass {
86 Object,
87 Array,
88 String,
89 Integer,
90 UnsignedInteger,
91 Float,
92 Boolean,
93 Null,
94}
95
96#[derive(Debug, Default)]
98pub struct KeyScanResult {
99 pub has_timestamp: bool,
100 pub has_coordinates: bool,
101 pub has_type_field: bool,
102 pub key_count: usize,
103}
104
105pub struct SimdNumericOps;
107
108impl SimdNumericOps {
109 #[inline(always)]
111 pub fn fast_array_sum(arr: &sonic_rs::Array) -> Option<f64> {
112 let mut sum = 0.0;
113 let mut count = 0;
114
115 for value in arr.iter() {
116 if let Some(num) = value.as_number() {
117 if let Some(f) = num.as_f64() {
118 sum += f;
119 count += 1;
120 }
121 } else {
122 return None; }
124 }
125
126 if count > 0 { Some(sum) } else { None }
127 }
128
129 #[inline(always)]
131 pub fn array_stats(arr: &sonic_rs::Array) -> Option<ArrayStats> {
132 let mut stats = ArrayStats {
133 min: f64::INFINITY,
134 max: f64::NEG_INFINITY,
135 sum: 0.0,
136 count: 0,
137 };
138
139 for value in arr.iter() {
140 if let Some(num) = value.as_number() {
141 if let Some(f) = num.as_f64() {
142 stats.min = stats.min.min(f);
143 stats.max = stats.max.max(f);
144 stats.sum += f;
145 stats.count += 1;
146 }
147 } else {
148 return None;
149 }
150 }
151
152 if stats.count > 0 { Some(stats) } else { None }
153 }
154}
155
156#[derive(Debug, Clone)]
158pub struct ArrayStats {
159 pub min: f64,
160 pub max: f64,
161 pub sum: f64,
162 pub count: usize,
163}
164
165impl ArrayStats {
166 pub fn mean(&self) -> f64 {
167 if self.count > 0 {
168 self.sum / self.count as f64
169 } else {
170 0.0
171 }
172 }
173}
174
175#[cfg(test)]
176mod tests {
177 use super::*;
178 use sonic_rs;
179
180 #[test]
181 fn test_simd_classifier() {
182 let json =
183 r#"{"number": 42, "text": "hello", "array": [1,2,3], "flag": true, "empty": null}"#;
184 let value: SonicValue = sonic_rs::from_str(json).unwrap();
185
186 if let Some(obj) = value.as_object() {
187 let scan_result = SimdClassifier::scan_object_keys(obj);
188 assert_eq!(scan_result.key_count, 5);
189 }
190 }
191
192 #[test]
193 fn test_numeric_array_detection() {
194 let json = "[1, 2, 3, 4, 5]";
195 let value: SonicValue = sonic_rs::from_str(json).unwrap();
196
197 if let Some(arr) = value.as_array() {
198 assert!(SimdClassifier::is_numeric_array(arr));
199 }
200 }
201
202 #[test]
203 fn test_array_stats() {
204 let json = "[1.5, 2.0, 3.5, 4.0]";
205 let value: SonicValue = sonic_rs::from_str(json).unwrap();
206
207 if let Some(arr) = value.as_array() {
208 let stats = SimdNumericOps::array_stats(arr).unwrap();
209 assert_eq!(stats.count, 4);
210 assert_eq!(stats.sum, 11.0);
211 assert_eq!(stats.mean(), 2.75);
212 }
213 }
214}