jmap_tools/pointer/
mod.rs1pub(crate) mod eval;
8pub(crate) mod parser;
9
10use crate::{Element, Key, Property, Value};
11use std::{
12 borrow::Cow,
13 fmt::{Debug, Display, Formatter},
14 iter::Peekable,
15 slice::Iter,
16};
17
18pub trait JsonPointerHandler<'x, P: Property, E: Element>: Debug {
19 fn eval_jptr<'y>(
20 &'y self,
21 pointer: JsonPointerIter<'_, P>,
22 results: &mut Vec<Cow<'y, Value<'x, P, E>>>,
23 );
24 fn patch_jptr<'y: 'x>(
25 &mut self,
26 pointer: JsonPointerIter<'_, P>,
27 value: Value<'y, P, E>,
28 ) -> bool;
29 fn to_value<'y>(&'y self) -> Cow<'y, Value<'x, P, E>>;
30}
31
32#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
33pub struct JsonPointer<P: Property>(pub(crate) Vec<JsonPointerItem<P>>);
34
35pub type JsonPointerIter<'x, P> = Peekable<Iter<'x, JsonPointerItem<P>>>;
36
37#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
38pub enum JsonPointerItem<P: Property> {
39 Root,
40 Wildcard,
41 Key(Key<'static, P>),
42 Number(u64),
43}
44
45impl<P: Property> JsonPointer<P> {
46 pub fn new(items: Vec<JsonPointerItem<P>>) -> Self {
47 Self(items)
48 }
49
50 pub fn iter(&self) -> JsonPointerIter<'_, P> {
51 self.0.iter().peekable()
52 }
53
54 #[allow(clippy::should_implement_trait)]
55 pub fn into_iter(self) -> impl Iterator<Item = JsonPointerItem<P>> {
56 self.0.into_iter()
57 }
58
59 pub fn into_inner(self) -> Vec<JsonPointerItem<P>> {
60 self.0
61 }
62
63 pub fn encode<I, T>(items: I) -> String
64 where
65 I: IntoIterator<Item = T>,
66 T: AsRef<str>,
67 {
68 let mut encoded = String::with_capacity(8);
69 for (pos, item) in items.into_iter().enumerate() {
70 if pos > 0 {
71 encoded.push('/');
72 }
73 let item = item.as_ref();
74 for c in item.chars() {
75 match c {
76 '~' => encoded.push_str("~0"),
77 '/' => encoded.push_str("~1"),
78 _ => encoded.push(c),
79 }
80 }
81 }
82 encoded
83 }
84
85 pub fn first(&self) -> Option<&JsonPointerItem<P>> {
86 self.0.first()
87 }
88
89 pub fn first_mut(&mut self) -> Option<&mut JsonPointerItem<P>> {
90 self.0.first_mut()
91 }
92
93 pub fn last(&self) -> Option<&JsonPointerItem<P>> {
94 self.0.last()
95 }
96
97 pub fn last_mut(&mut self) -> Option<&mut JsonPointerItem<P>> {
98 self.0.last_mut()
99 }
100
101 pub fn len(&self) -> usize {
102 self.0.len()
103 }
104
105 pub fn is_empty(&self) -> bool {
106 self.0.is_empty()
107 }
108
109 pub fn as_slice(&self) -> &[JsonPointerItem<P>] {
110 &self.0
111 }
112
113 pub fn as_mut_slice(&mut self) -> &mut [JsonPointerItem<P>] {
114 &mut self.0
115 }
116}
117
118impl<P: Property> JsonPointerItem<P> {
119 pub fn as_key(&self) -> Option<&Key<'static, P>> {
120 match self {
121 JsonPointerItem::Key(key) => Some(key),
122 _ => None,
123 }
124 }
125
126 pub fn as_property_key(&self) -> Option<&P> {
127 match self {
128 JsonPointerItem::Key(Key::Property(key)) => Some(key),
129 _ => None,
130 }
131 }
132
133 pub fn as_string_key(&self) -> Option<&str> {
134 match self {
135 JsonPointerItem::Key(Key::Borrowed(key)) => Some(key),
136 JsonPointerItem::Key(Key::Owned(key)) => Some(key),
137 _ => None,
138 }
139 }
140
141 pub fn to_cow(&self) -> Option<Cow<'_, str>> {
142 match self {
143 JsonPointerItem::Key(Key::Property(key)) => Some(key.to_cow()),
144 JsonPointerItem::Key(Key::Borrowed(key)) => Some(Cow::Borrowed(key)),
145 JsonPointerItem::Key(Key::Owned(key)) => Some(Cow::Borrowed(key)),
146 _ => None,
147 }
148 }
149}
150
151impl<P: Property> Display for JsonPointer<P> {
152 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
153 for (i, ptr) in self.0.iter().enumerate() {
154 if i > 0 {
155 write!(f, "/")?;
156 }
157
158 match ptr {
159 JsonPointerItem::Root => {}
160 JsonPointerItem::Wildcard => write!(f, "*")?,
161 JsonPointerItem::Key(k) => {
162 for c in k.to_string().chars() {
163 match c {
164 '~' => write!(f, "~0")?,
165 '/' => write!(f, "~1")?,
166 _ => write!(f, "{}", c)?,
167 }
168 }
169 }
170 JsonPointerItem::Number(n) => write!(f, "{}", n)?,
171 }
172 }
173 Ok(())
174 }
175}