1use core::{fmt::Write, ops::ControlFlow::*};
2
3use serde::{Deserialize, Serialize};
4
5use crate::{DescendError, IntoKeys, KeysIter, Schema, Transcode};
6
7#[derive(Clone, Copy, Debug, PartialEq, Eq, Ord, PartialOrd, Serialize, Deserialize, Hash)]
34#[repr(transparent)]
35#[serde(transparent)]
36pub struct JsonPathIter<'a>(&'a str);
37
38impl<'a> JsonPathIter<'a> {
39 pub fn new(value: &'a str) -> Self {
41 Self(value)
42 }
43}
44
45impl core::fmt::Display for JsonPathIter<'_> {
46 #[inline]
47 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
48 self.0.fmt(f)
49 }
50}
51
52impl<'a> Iterator for JsonPathIter<'a> {
53 type Item = &'a str;
54
55 fn next(&mut self) -> Option<Self::Item> {
56 for (open, close) in [
57 (".'", Continue("'")), (".", Break(['.', '['])), ("['", Continue("']")), ("[", Continue("]")), ] {
62 if let Some(rest) = self.0.strip_prefix(open) {
63 let (end, sep) = match close {
64 Break(close) => (rest.find(close).unwrap_or(rest.len()), 0),
65 Continue(close) => (rest.find(close)?, close.len()),
66 };
67 let (next, rest) = rest.split_at(end);
68 self.0 = &rest[sep..];
69 return Some(next);
70 }
71 }
72 None
73 }
74}
75
76impl core::iter::FusedIterator for JsonPathIter<'_> {}
77
78#[derive(
86 Clone, Copy, Debug, Default, PartialEq, Eq, Ord, PartialOrd, Serialize, Deserialize, Hash,
87)]
88#[repr(transparent)]
89#[serde(transparent)]
90pub struct JsonPath<T: ?Sized>(pub T);
91
92impl<T> JsonPath<T> {
93 #[inline]
95 pub fn into_inner(self) -> T {
96 self.0
97 }
98}
99
100impl<T: core::fmt::Display> core::fmt::Display for JsonPath<T> {
101 #[inline]
102 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
103 self.0.fmt(f)
104 }
105}
106
107impl<'a, T: AsRef<str> + ?Sized> IntoKeys for &'a JsonPath<T> {
108 type IntoKeys = KeysIter<JsonPathIter<'a>>;
109 #[inline]
110 fn into_keys(self) -> Self::IntoKeys {
111 JsonPathIter(self.0.as_ref()).into_keys()
112 }
113}
114
115impl<T: Write + ?Sized> Transcode for JsonPath<T> {
116 type Error = core::fmt::Error;
117
118 fn transcode(
119 &mut self,
120 schema: &Schema,
121 keys: impl IntoKeys,
122 ) -> Result<(), DescendError<Self::Error>> {
123 schema.descend(keys.into_keys(), |_meta, idx_internal| {
124 if let Some((index, internal)) = idx_internal {
125 if let Some(name) = internal.get_name(index) {
126 debug_assert!(!name.contains(['.', '\'', '[', ']']));
127 self.0.write_char('.')?;
128 self.0.write_str(name)?;
129 } else {
130 self.0.write_char('[')?;
131 self.0.write_str(itoa::Buffer::new().format(index))?;
132 self.0.write_char(']')?;
133 }
134 }
135 Ok(())
136 })
137 }
138}