1use core::{
2 fmt::Write,
3 ops::{ControlFlow::*, Deref, DerefMut},
4};
5
6use serde::{Deserialize, Serialize};
7
8use crate::{IntoKeys, KeysIter, Node, Transcode, Traversal, TreeKey};
9
10#[derive(Clone, Copy, Debug, PartialEq, Eq, Ord, PartialOrd, Serialize, Deserialize, Hash)]
37#[repr(transparent)]
38#[serde(transparent)]
39pub struct JsonPathIter<'a>(&'a str);
40
41impl core::fmt::Display for JsonPathIter<'_> {
42 #[inline]
43 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
44 self.0.fmt(f)
45 }
46}
47
48impl<'a, T> From<&'a T> for JsonPathIter<'a>
49where
50 T: AsRef<str> + ?Sized,
51{
52 #[inline]
53 fn from(value: &'a T) -> Self {
54 Self(value.as_ref())
55 }
56}
57
58impl<'a> From<JsonPathIter<'a>> for &'a str {
59 #[inline]
60 fn from(value: JsonPathIter<'a>) -> Self {
61 value.0
62 }
63}
64
65impl<'a> Iterator for JsonPathIter<'a> {
66 type Item = &'a str;
67
68 fn next(&mut self) -> Option<Self::Item> {
69 for (open, close) in [
70 (".'", Continue("'")), (".", Break(['.', '['])), ("['", Continue("']")), ("[", Continue("]")), ] {
75 if let Some(rest) = self.0.strip_prefix(open) {
76 let (end, sep) = match close {
77 Break(close) => (rest.find(close).unwrap_or(rest.len()), 0),
78 Continue(close) => (rest.find(close)?, close.len()),
79 };
80 let (next, rest) = rest.split_at(end);
81 self.0 = &rest[sep..];
82 return Some(next);
83 }
84 }
85 None
86 }
87}
88
89impl core::iter::FusedIterator for JsonPathIter<'_> {}
90
91#[derive(
99 Clone, Copy, Debug, Default, PartialEq, Eq, Ord, PartialOrd, Serialize, Deserialize, Hash,
100)]
101#[repr(transparent)]
102#[serde(transparent)]
103pub struct JsonPath<T: ?Sized>(pub T);
104
105impl<T> From<T> for JsonPath<T> {
106 #[inline]
107 fn from(value: T) -> Self {
108 Self(value)
109 }
110}
111
112impl<T> JsonPath<T> {
113 #[inline]
115 pub fn into_inner(self) -> T {
116 self.0
117 }
118}
119
120impl<T: ?Sized> Deref for JsonPath<T> {
121 type Target = T;
122 #[inline]
123 fn deref(&self) -> &Self::Target {
124 &self.0
125 }
126}
127
128impl<T: ?Sized> DerefMut for JsonPath<T> {
129 #[inline]
130 fn deref_mut(&mut self) -> &mut Self::Target {
131 &mut self.0
132 }
133}
134
135impl<T: core::fmt::Display> core::fmt::Display for JsonPath<T> {
136 #[inline]
137 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
138 self.0.fmt(f)
139 }
140}
141
142impl<'a, T: AsRef<str> + ?Sized> IntoKeys for &'a JsonPath<T> {
143 type IntoKeys = KeysIter<JsonPathIter<'a>>;
144 #[inline]
145 fn into_keys(self) -> Self::IntoKeys {
146 JsonPathIter::from(self.0.as_ref()).into_keys()
147 }
148}
149
150impl<T: Write + ?Sized> Transcode for JsonPath<T> {
151 fn transcode<M, K>(&mut self, keys: K) -> Result<Node, Traversal>
152 where
153 M: TreeKey + ?Sized,
154 K: IntoKeys,
155 {
156 M::traverse_by_key(keys.into_keys(), |index, name, _len| {
157 match name {
158 Some(name) => {
159 debug_assert!(!name.contains(['.', '\'', '[', ']']));
160 self.0.write_char('.').and_then(|()| self.0.write_str(name))
161 }
162 None => self
163 .0
164 .write_char('[')
165 .and_then(|()| self.0.write_str(itoa::Buffer::new().format(index)))
166 .and_then(|()| self.0.write_char(']')),
167 }
168 .or(Err(()))
169 })
170 .try_into()
171 }
172}