1#![cfg_attr(not(feature = "std"), no_std)]
5
6#[cfg(feature = "std")]
7extern crate std as core;
8
9extern crate alloc;
10
11use alloc::borrow::Cow;
12use alloc::string::{String, ToString};
13use core::iter;
14
15#[derive(Debug, PartialEq, Eq)]
17pub enum Query<'a> {
18 Index { index: usize, from_last: bool },
20 Key(Cow<'a, str>),
22}
23
24#[derive(Clone, Debug, PartialEq, Eq)]
26pub enum SetResult<T> {
27 NotSet,
29 Set,
31 Replaced(T),
33}
34
35impl Query<'static> {
36 pub fn index(index: usize) -> Self {
38 Query::Index {
39 index,
40 from_last: false,
41 }
42 }
43
44 pub fn index_from_last(index: usize) -> Self {
46 Query::Index {
47 index,
48 from_last: true,
49 }
50 }
51
52 pub fn key_owned(key: String) -> Self {
54 Query::Key(Cow::Owned(key))
55 }
56}
57
58impl<'a> Query<'a> {
59 pub fn key(key: &'a str) -> Self {
61 Query::Key(Cow::Borrowed(key))
62 }
63
64 pub fn is_from_last(&self) -> bool {
66 match self {
67 Query::Index { from_last, .. } => *from_last,
68 _ => false,
69 }
70 }
71
72 pub fn is_key(&self) -> bool {
74 match self {
75 Query::Key(_) => true,
76 _ => false,
77 }
78 }
79
80 pub fn is_index(&self) -> bool {
82 match self {
83 Query::Index { .. } => true,
84 _ => false,
85 }
86 }
87
88 pub fn as_key(&self) -> Option<&str> {
90 match self {
91 Query::Key(s) => Some(s.as_ref()),
92 _ => None,
93 }
94 }
95
96 pub fn as_index(&self) -> Option<i64> {
99 match self {
100 Query::Index { index, from_last } => Some(if *from_last {
101 -1 - (*index as i64)
102 } else {
103 *index as i64
104 }),
105 _ => None,
106 }
107 }
108
109 pub fn to_owned(&self) -> Query<'static> {
111 match self {
112 Query::Index { index, from_last } => Query::Index {
113 index: *index,
114 from_last: *from_last,
115 },
116 Query::Key(key) => Query::Key(Cow::Owned(key.to_string())),
117 }
118 }
119}
120
121impl<'a> Clone for Query<'a> {
122 fn clone(&self) -> Query<'static> {
123 self.to_owned()
124 }
125}
126
127pub trait AccessNext<T = Self> {
129 fn access_next<'a>(&self, query: &Query<'a>) -> Option<&T>;
130}
131
132pub trait AccessNextMut<T = Self> {
134 fn access_next_mut<'a>(&mut self, query: &Query<'a>) -> Option<&mut T>;
135}
136
137pub trait AccessNextOwned<T = Self>: Sized {
139 fn access_next_owned<'a>(self, query: &Query<'a>) -> Option<T>;
140}
141
142pub trait Access: AccessNext + Sized {
144 fn access<'a, I: IntoIterator<Item = &'a Query<'a>>>(&self, queries: I) -> Option<&Self> {
145 queries.into_iter().fold(Some(self), |res, query| {
146 res.and_then(|res| res.access_next(query))
147 })
148 }
149}
150
151pub trait AccessMut: AccessNextMut + Sized {
153 fn access_mut<'a, I: IntoIterator<Item = &'a Query<'a>>>(
154 &mut self,
155 queries: I,
156 ) -> Option<&mut Self> {
157 queries.into_iter().fold(Some(self), |res, query| {
158 res.and_then(|res| res.access_next_mut(query))
159 })
160 }
161}
162
163pub trait AccessOwned: AccessNextOwned {
165 fn access_owned<'a, I: IntoIterator<Item = &'a Query<'a>>>(self, queries: I) -> Option<Self> {
166 queries.into_iter().fold(Some(self), |res, query| {
167 res.and_then(|res| res.access_next_owned(query))
168 })
169 }
170}
171
172pub trait QuerySetItem: Sized {
174 fn query_set_item<'a>(&mut self, query: &Query<'a>, val: Self) -> SetResult<Self>;
175}
176
177struct SkipLastIter<I, T>
178where
179 I: Iterator<Item = T>,
180{
181 iter: iter::Peekable<I>,
182 last: Option<T>,
183}
184
185impl<I, T> SkipLastIter<I, T>
186where
187 I: Iterator<Item = T>,
188{
189 fn new(iter: I) -> Self {
190 Self {
191 iter: iter.peekable(),
192 last: None,
193 }
194 }
195}
196
197impl<I, T> Iterator for SkipLastIter<I, T>
198where
199 I: Iterator<Item = T>,
200{
201 type Item = T;
202 fn next(&mut self) -> Option<Self::Item> {
203 let next = self.iter.next();
204 if next.is_none() {
205 return None;
206 }
207 if self.iter.peek().is_none() {
208 self.last = next;
209 return None;
210 }
211 next
212 }
213}
214
215pub trait QuerySet: QuerySetItem + AccessMut {
217 fn query_set<'a, I: IntoIterator<Item = &'a Query<'a>>>(
218 &mut self,
219 queries: I,
220 val: Self,
221 ) -> SetResult<Self> {
222 let mut iter = SkipLastIter::new(queries.into_iter());
223 let item = self.access_mut(&mut iter);
224 if let Some(item) = item {
225 if let Some(last) = iter.last {
226 item.query_set_item(last, val)
227 } else {
228 SetResult::NotSet
230 }
231 } else {
232 SetResult::NotSet
234 }
235 }
236}
237
238impl From<usize> for Query<'static> {
239 fn from(index: usize) -> Self {
240 Self::Index {
241 index,
242 from_last: false,
243 }
244 }
245}
246
247impl From<isize> for Query<'static> {
248 fn from(index: isize) -> Self {
249 if index.is_negative() {
250 Self::Index {
251 index: index.abs() as usize - 1,
252 from_last: true,
253 }
254 } else {
255 Self::Index {
256 index: index as usize,
257 from_last: false,
258 }
259 }
260 }
261}
262
263impl From<i8> for Query<'static> {
264 fn from(index: i8) -> Self {
265 (index as isize).into()
266 }
267}
268
269impl From<i16> for Query<'static> {
270 fn from(index: i16) -> Self {
271 (index as isize).into()
272 }
273}
274
275impl From<i32> for Query<'static> {
276 fn from(index: i32) -> Self {
277 (index as isize).into()
278 }
279}
280
281impl From<i64> for Query<'static> {
282 fn from(index: i64) -> Self {
283 (index as isize).into()
284 }
285}
286
287impl From<u8> for Query<'static> {
288 fn from(index: u8) -> Self {
289 (index as usize).into()
290 }
291}
292
293impl From<u16> for Query<'static> {
294 fn from(index: u16) -> Self {
295 (index as usize).into()
296 }
297}
298
299impl From<u32> for Query<'static> {
300 fn from(index: u32) -> Self {
301 (index as usize).into()
302 }
303}
304
305impl From<u64> for Query<'static> {
306 fn from(index: u64) -> Self {
307 (index as usize).into()
308 }
309}
310
311impl From<String> for Query<'static> {
312 fn from(key: String) -> Self {
313 Self::Key(Cow::Owned(key))
314 }
315}
316
317impl<'a> From<&'a str> for Query<'a> {
318 fn from(key: &'a str) -> Self {
319 Self::Key(Cow::Borrowed(key))
320 }
321}
322
323#[cfg(feature = "json")]
324impl AccessNext for serde_json::Value {
325 fn access_next<'a>(&self, query: &Query<'a>) -> Option<&Self> {
326 match self {
327 serde_json::Value::Null => None,
328 serde_json::Value::Bool(_) => None,
329 serde_json::Value::Number(_) => None,
330 serde_json::Value::String(_) => None,
331 serde_json::Value::Array(array) => match query {
332 Query::Index { index, from_last } => {
333 if *from_last {
334 if *index >= array.len() {
335 return None;
336 }
337 array.get(array.len() - 1 - index)
338 } else {
339 array.get(*index)
340 }
341 }
342 Query::Key(_) => None,
343 },
344 serde_json::Value::Object(map) => match query {
345 Query::Index { .. } => None,
346 Query::Key(key) => map.get(&key.to_string()),
347 },
348 }
349 }
350}
351
352#[cfg(feature = "json")]
353impl Access for serde_json::Value {}
354
355#[cfg(feature = "json")]
356impl AccessNextMut for serde_json::Value {
357 fn access_next_mut<'a>(&mut self, query: &Query<'a>) -> Option<&mut Self> {
358 match self {
359 serde_json::Value::Null => None,
360 serde_json::Value::Bool(_) => None,
361 serde_json::Value::Number(_) => None,
362 serde_json::Value::String(_) => None,
363 serde_json::Value::Array(array) => match query {
364 Query::Index { index, from_last } => {
365 if *from_last {
366 if *index >= array.len() {
367 return None;
368 }
369 let index = array.len() - 1 - index;
370 array.get_mut(index)
371 } else {
372 array.get_mut(*index)
373 }
374 }
375 Query::Key(_) => None,
376 },
377 serde_json::Value::Object(map) => match query {
378 Query::Index { .. } => None,
379 Query::Key(key) => map.get_mut(&key.to_string()),
380 },
381 }
382 }
383}
384
385#[cfg(feature = "json")]
386impl AccessMut for serde_json::Value {}
387
388#[cfg(feature = "json")]
389impl AccessNextOwned for serde_json::Value {
390 fn access_next_owned<'a>(self, query: &Query<'a>) -> Option<Self> {
391 match self {
392 serde_json::Value::Null => None,
393 serde_json::Value::Bool(_) => None,
394 serde_json::Value::Number(_) => None,
395 serde_json::Value::String(_) => None,
396 serde_json::Value::Array(array) => match query {
397 Query::Index { index, from_last } => {
398 if *from_last {
399 if *index >= array.len() {
400 return None;
401 }
402 array.get(array.len() - 1 - index).cloned()
403 } else {
404 array.get(*index).cloned()
405 }
406 }
407 Query::Key(_) => None,
408 },
409 serde_json::Value::Object(map) => match query {
410 Query::Index { .. } => None,
411 Query::Key(key) => map.get(&key.to_string()).cloned(),
412 },
413 }
414 }
415}
416
417#[cfg(feature = "json")]
418impl AccessOwned for serde_json::Value {}
419
420#[cfg(feature = "json")]
421impl QuerySetItem for serde_json::Value {
422 fn query_set_item<'a>(&mut self, query: &Query<'a>, val: Self) -> SetResult<Self> {
423 match self {
424 serde_json::Value::Null => SetResult::NotSet,
425 serde_json::Value::Bool(_) => SetResult::NotSet,
426 serde_json::Value::Number(_) => SetResult::NotSet,
427 serde_json::Value::String(_) => SetResult::NotSet,
428 serde_json::Value::Array(array) => match query {
429 Query::Index { index, from_last } => {
430 if *from_last {
431 if *index >= array.len() {
432 return SetResult::NotSet;
433 }
434 let index = array.len() - 1 - index;
435 array.push(val);
436 SetResult::Replaced(array.swap_remove(index))
437 } else {
438 if *index == array.len() {
439 array.push(val);
440 SetResult::Set
441 } else if *index > array.len() {
442 array.resize(index + 1, serde_json::Value::Null);
443 array[*index] = val;
444 SetResult::Set
445 } else {
446 array.push(val);
447 SetResult::Replaced(array.swap_remove(*index))
448 }
449 }
450 }
451 Query::Key(_) => SetResult::NotSet,
452 },
453 serde_json::Value::Object(map) => match query {
454 Query::Index { .. } => SetResult::NotSet,
455 Query::Key(key) => {
456 if let Some(res) = map.insert(key.to_string(), val) {
457 SetResult::Replaced(res)
458 } else {
459 SetResult::Set
460 }
461 }
462 },
463 }
464 }
465}
466
467#[macro_export]
474macro_rules! query {
475 ($($item:expr),*) => {
476 &[$($crate::Query::from(($item))),*]
477 }
478}
479
480#[cfg(feature = "json")]
481impl QuerySet for serde_json::Value {}
482
483#[cfg(test)]
484mod tests {
485 use super::*;
486 #[cfg(feature = "json")]
487 use alloc::vec;
488 #[cfg(feature = "json")]
489 use serde_json::json;
490
491 #[cfg(feature = "json")]
492 #[test]
493 fn access_json_object() {
494 let mut value = json!({"a": 1, "b": 2});
495 let query = vec!["a".into()];
496 assert_eq!(value.access(&query), Some(&json!(1)));
497 assert_eq!(value.access_mut(&query), Some(&mut json!(1)));
498 assert_eq!(value.clone().access_owned(&query), Some(json!(1)));
499 let query = vec!["b".into()];
500 assert_eq!(value.access(&query), Some(&json!(2)));
501 let query = vec!["c".into()];
502 assert_eq!(value.access(&query), None);
503 }
504
505 #[cfg(feature = "json")]
506 #[test]
507 fn access_json_array() {
508 let mut value = json!([1, 2, 3]);
509 let query = vec![0.into()];
510 assert_eq!(value.access(&query), Some(&json!(1)));
511 assert_eq!(value.access_mut(&query), Some(&mut json!(1)));
512 assert_eq!(value.clone().access_owned(&query), Some(json!(1)));
513 let query = vec![1.into()];
514 assert_eq!(value.access(&query), Some(&json!(2)));
515 let query = vec![(-1).into()];
516 assert_eq!(value.access(&query), Some(&json!(3)));
517 let query = vec![(-2).into()];
518 assert_eq!(value.access(&query), Some(&json!(2)));
519 let query = vec![4.into()];
520 assert_eq!(value.access(&query), None);
521 }
522
523 #[cfg(feature = "json")]
524 #[test]
525 fn access_json_nested() {
526 let mut value = json!([{"a": 1}, [2, 3], {"c": 4}]);
527 let query = vec![0.into(), "a".into()];
528 assert_eq!(value.access(&query), Some(&json!(1)));
529 assert_eq!(value.access_mut(&query), Some(&mut json!(1)));
530 assert_eq!(value.clone().access_owned(&query), Some(json!(1)));
531 let query = vec![(-1).into(), "c".into()];
532 assert_eq!(value.access(&query), Some(&json!(4)));
533 let query = vec![1.into(), (-1).into()];
534 assert_eq!(value.access(&query), Some(&json!(3)));
535 let query = vec![0.into(), "b".into()];
536 assert_eq!(value.access(&query), None);
537 let query = vec![1.into(), 2.into()];
538 assert_eq!(value.access(&query), None);
539 }
540
541 #[cfg(feature = "json")]
542 #[test]
543 fn query_set_json_array() {
544 let mut value = json!([1, 2, 3]);
545
546 let query = vec![0.into()];
547 assert_eq!(
548 value.query_set(&query, json!(4)),
549 SetResult::Replaced(json!(1))
550 );
551 assert_eq!(value, json!([4, 2, 3]));
552
553 let query = vec![3.into()];
554 assert_eq!(value.query_set(&query, json!(5)), SetResult::Set);
555 assert_eq!(value, json!([4, 2, 3, 5]));
556
557 let query = vec![5.into()];
558 assert_eq!(value.query_set(&query, json!(6)), SetResult::Set);
559 assert_eq!(value, json!([4, 2, 3, 5, null, 6]));
560
561 let query = vec![(-2).into()];
562 assert_eq!(
563 value.query_set(&query, json!(7)),
564 SetResult::Replaced(json!(null))
565 );
566 assert_eq!(value, json!([4, 2, 3, 5, 7, 6]));
567
568 let query = vec![(-7).into()];
569 assert_eq!(value.query_set(&query, json!(9)), SetResult::NotSet);
570 assert_eq!(value, json!([4, 2, 3, 5, 7, 6]));
571 }
572
573 #[cfg(feature = "json")]
574 #[test]
575 fn query_set_json_object() {
576 let mut value = json!({"a": 1, "b": 2});
577
578 assert_eq!(
579 value.query_set(query!["a"], json!(3)),
580 SetResult::Replaced(json!(1))
581 );
582 assert_eq!(value, json!({"a": 3, "b": 2}));
583
584 assert_eq!(value.query_set(query!["c"], json!(4)), SetResult::Set);
585 assert_eq!(value, json!({"a": 3, "b": 2, "c": 4}));
586 }
587
588 #[cfg(feature = "json")]
589 #[test]
590 fn query_set_json_nested() {
591 let mut value = json!([{"a": 1}, [2, 3], {"c": 4}]);
592
593 assert_eq!(
594 value.query_set(query![0, "a"], json!(2)),
595 SetResult::Replaced(json!(1))
596 );
597 assert_eq!(value, json!([{"a": 2}, [2, 3], {"c": 4}]));
598
599 assert_eq!(value.query_set(query![2, "b"], json!(5)), SetResult::Set);
600 assert_eq!(value, json!([{"a": 2}, [2, 3], {"c": 4, "b": 5}]));
601
602 assert_eq!(value.query_set(query![1, 2], json!(6)), SetResult::Set);
603 assert_eq!(value, json!([{"a": 2}, [2, 3, 6], {"c": 4, "b": 5}]));
604
605 assert_eq!(
606 value.query_set(query![-2, -3], json!(7)),
607 SetResult::Replaced(json!(2))
608 );
609 assert_eq!(value, json!([{"a": 2}, [7, 3, 6], {"c": 4, "b": 5}]));
610
611 assert_eq!(
612 value.query_set(query![3, "key"], json!(8)),
613 SetResult::NotSet
614 );
615 assert_eq!(value, json!([{"a": 2}, [7, 3, 6], {"c": 4, "b": 5}]));
616 }
617}