1use super::{start, end};
9
10use serde::de::*;
11
12use std::borrow::Borrow;
13use std::cmp::{PartialEq, Eq, PartialOrd, Ord, Ordering};
14use std::convert::*;
15use std::fmt::{self, Debug, Display, Formatter};
16use std::hash::{Hash, Hasher};
17use std::ops::{Deref, Range};
18
19
20
21#[derive(Clone)]
24pub struct Spanned<V> {
25 pub(crate) start: usize,
26 pub(crate) end: usize,
27 pub(crate) value: V,
28}
29
30impl<V> Spanned<V> {
31 pub fn start(&self) -> usize { self.start }
34
35 pub fn end(&self) -> usize { self.end }
38
39 pub fn span(&self) -> (usize, usize) { (self.start, self.end) }
42
43 pub fn range(&self) -> Range<usize> { self.start .. self.end }
46
47 pub fn into_inner(self) -> V { self.value }
49
50 pub fn get_ref(&self) -> &V { &self.value }
52
53 pub fn get_mut(&mut self) -> &mut V { &mut self.value }
55}
56
57impl Borrow<str> for Str<'_> { fn borrow(&self) -> &str { self.get_ref() } }
58impl Borrow<str> for String { fn borrow(&self) -> &str { self.get_ref() } }
59impl<V> Deref for Spanned<V> { fn deref(&self) -> &Self::Target { &self.value } type Target = V; }
60impl<R, V: AsRef<R>> AsRef<R> for Spanned<V> { fn as_ref(&self) -> &R { self.value.as_ref() } }
62impl<V: Debug> Debug for Spanned<V> { fn fmt(&self, fmt: &mut Formatter) -> fmt::Result { self.value.fmt(fmt) } }
63impl<V: Display> Display for Spanned<V> { fn fmt(&self, fmt: &mut Formatter) -> fmt::Result { self.value.fmt(fmt) } }
64impl<V> From<V> for Spanned<V> { fn from(v: V) -> Self { Self { value: v, start: 0, end: 0 } } }
65impl<V: Eq> Eq for Spanned<V> {}
66impl<V: Ord> Ord for Spanned<V> { fn cmp(&self, other: &Self) -> Ordering { self.value.cmp(&other.value) } }
67impl<V: PartialEq> PartialEq for Spanned<V> { fn eq(&self, other: &Self) -> bool { self.value.eq(&other.value) } }
68impl<V: PartialOrd> PartialOrd for Spanned<V> { fn partial_cmp(&self, other: &Self) -> Option<Ordering> { self.value.partial_cmp(&other.value) } }
69impl<V: Hash> Hash for Spanned<V> { fn hash<H: Hasher>(&self, hasher: &mut H) { self.value.hash(hasher) } }
70
71impl<'de, V: Deserialize<'de>> Deserialize<'de> for Spanned<V> {
72 fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
73 let (start, start_ch) = start().unwrap_or((0, '\0'));
74 let value = V::deserialize(deserializer)?;
75 let end = end().unwrap_or(0);
76 let end = if "[{ntf\"".contains(start_ch) { end } else { end.saturating_sub(1) };
77 Ok(Self { start, end, value })
78 }
79}
80
81
82
83#[doc = "Owned, arbitrary json value + span information" ] pub type Value = Spanned<super::Value>;
84#[doc = "`null` + span information" ] pub type Null = Spanned<()>;
85#[doc = "`true` or `false` + span information" ] pub type Bool = Spanned<bool>;
86#[doc = "Borrowed number like `123` + span information" ] pub type Num<'n> = Spanned<&'n serde_json::Number>;
87#[doc = "Owned number like `123` + span information" ] pub type Number = Spanned<serde_json::Number>;
88#[doc = "Borrowed string like `\"abc\"` + span information" ] pub type Str<'s> = Spanned<&'s str>;
89#[doc = "Owned string like `\"abc\"` + span information" ] pub type String = Spanned<std::string::String>;
90#[doc = "Borrowed object like `{\"a\":1, \"b\":2}` + span information" ] pub type Obj<'o> = Spanned<&'o super::Map<self::String, self::Value>>;
91#[doc = "Owned object like `{\"a\":1, \"b\":2}` + span information" ] pub type Object = Spanned<super::Map<self::String, self::Value>>;
92#[doc = "Borrowed array like `[1,2,3]` + span information" ] pub type Span<'s> = Spanned<&'s [self::Value]>;
93#[doc = "Owned array like `[1,2,3]` + span information" ] pub type Array = Spanned<Vec<self::Value>>;
94
95impl Value {
106 #[doc="`Some(span + ()) if self is `null`" ] pub fn as_span_null (&self) -> Option<Null> { match self.value { super::Value::Null => Some(Spanned { start: self.start, end: self.end, value: () }), _ => None } }
107 #[doc="`Some(span + inner)` if self is `true` or `false`" ] pub fn as_span_bool (&self) -> Option<Bool> { match self.value { super::Value::Bool(v) => Some(Spanned { start: self.start, end: self.end, value: v }), _ => None } }
108 #[doc="`Some(span + &inner)` if self is a number like `123`" ] pub fn as_span_number (&self) -> Option<Num> { match &self.value { super::Value::Number(v) => Some(Spanned { start: self.start, end: self.end, value: &v }), _ => None } }
109 #[doc="`Some(span + &inner)` if self is a string like `\"asdf\"`" ] pub fn as_span_string (&self) -> Option<Str> { match &self.value { super::Value::String(v) => Some(Spanned { start: self.start, end: self.end, value: &v }), _ => None } }
110 #[doc="`Some(span + &inner)` if self is an array like `[1, 2, 3]`" ] pub fn as_span_array (&self) -> Option<Span> { match &self.value { super::Value::Array(v) => Some(Spanned { start: self.start, end: self.end, value: v }), _ => None } }
111 #[doc="`Some(span + &inner)` if self is an object like `{\"a\": 1, \"b\": 2}`" ] pub fn as_span_object (&self) -> Option<Obj> { match &self.value { super::Value::Object(v) => Some(Spanned { start: self.start, end: self.end, value: v }), _ => None } }
112
113 #[doc="`Ok(span + ())` if self is `null`, otherwise Err(self)" ] pub fn into_span_null (self) -> Result<Null, Self> { let Self { start, end, value } = self; match value { super::Value::Null => Ok(Spanned { start, end, value: () }), value => Err(Spanned { start, end, value }) } }
116 #[doc="`Ok(span + inner)` if self is `true` or `false`, otherwise Err(self)" ] pub fn into_span_bool (self) -> Result<Bool, Self> { let Self { start, end, value } = self; match value { super::Value::Bool(v) => Ok(Spanned { start, end, value: v }), value => Err(Spanned { start, end, value }) } }
117 #[doc="`Ok(span + inner)` if self is a number like `123`, otherwise Err(self)" ] pub fn into_span_number (self) -> Result<Number, Self> { let Self { start, end, value } = self; match value { super::Value::Number(v) => Ok(Spanned { start, end, value: v }), value => Err(Spanned { start, end, value }) } }
118 #[doc="`Ok(span + inner)` if self is a string like `\"asdf\"`, otherwise Err(self)" ] pub fn into_span_string (self) -> Result<String, Self> { let Self { start, end, value } = self; match value { super::Value::String(v) => Ok(Spanned { start, end, value: v }), value => Err(Spanned { start, end, value }) } }
119 #[doc="`Ok(span + inner)` if self is an array like `[1, 2, 3]`, otherwise Err(self)" ] pub fn into_span_array (self) -> Result<Array, Self> { let Self { start, end, value } = self; match value { super::Value::Array(v) => Ok(Spanned { start, end, value: v }), value => Err(Spanned { start, end, value }) } }
120 #[doc="`Ok(span + inner)` if self is an object like `{\"a\": 1, \"b\": 2}`, otherwise Err(self)" ] pub fn into_span_object (self) -> Result<Object, Self> { let Self { start, end, value } = self; match value { super::Value::Object(v) => Ok(Spanned { start, end, value: v }), value => Err(Spanned { start, end, value }) } }
121
122 pub fn pointer(&self, path: &str) -> Option<&Value> {
124 if path == "" { return Some(self) }
125 if !path.starts_with("/") { return None }
126 let mut current = self;
127 let tokens = path.split('/').skip(1).map(|t| t.replace("~1", "/").replace("~0", "~"));
128 for token in tokens {
129 current = match ¤t.value {
130 super::Value::Object(o) => o.get(token.as_str())?,
131 super::Value::Array(a) => a.get(token.parse::<usize>().ok()?)?,
132 _other => return None,
133 };
134 }
135 Some(current)
136 }
137
138 pub fn pointer_mut(&mut self, path: &str) -> Option<&mut Value> {
140 if path == "" { return Some(self) }
141 if !path.starts_with("/") { return None }
142 let mut current = self;
143 let tokens = path.split('/').skip(1).map(|t| t.replace("~1", "/").replace("~0", "~"));
144 for token in tokens {
145 current = match &mut current.value {
146 super::Value::Object(o) => o.get_mut(token.as_str())?,
147 super::Value::Array(a) => a.get_mut(token.parse::<usize>().ok()?)?,
148 _other => return None,
149 };
150 }
151 Some(current)
152 }
153}
154
155#[cfg(test)] mod tests {
156 use crate::*;
157
158 #[test] fn pointer() {
159 let text = "{\"a\": {\"b\": [0, [0, 1, {\"c\": \"value\"}]]}}";
160 let v : spanned::Value = from_str(text).unwrap();
161 assert_eq!(&text[v.pointer("").unwrap().range()], "{\"a\": {\"b\": [0, [0, 1, {\"c\": \"value\"}]]}}");
162 assert_eq!(&text[v.pointer("/a").unwrap().range()], "{\"b\": [0, [0, 1, {\"c\": \"value\"}]]}");
163 assert_eq!(&text[v.pointer("/a/b").unwrap().range()], "[0, [0, 1, {\"c\": \"value\"}]]");
164 assert_eq!(&text[v.pointer("/a/b/0").unwrap().range()], "0");
165 assert_eq!(&text[v.pointer("/a/b/1").unwrap().range()], "[0, 1, {\"c\": \"value\"}]");
166 assert_eq!(&text[v.pointer("/a/b/1/0").unwrap().range()], "0");
167 assert_eq!(&text[v.pointer("/a/b/1/1").unwrap().range()], "1");
168 assert_eq!(&text[v.pointer("/a/b/1/2").unwrap().range()], "{\"c\": \"value\"}");
169 assert_eq!(&text[v.pointer("/a/b/1/2/c").unwrap().range()], "\"value\"");
170
171 assert!( v.pointer("/a/b/1/2/d").is_none());
172 assert!( v.pointer("/a/b/1/2/").is_none());
173 assert!( v.pointer("/a/b/1/3").is_none());
174 assert!( v.pointer("/a/b/1/").is_none());
175 assert!( v.pointer("/a/b/2").is_none());
176 assert!( v.pointer("/a/b/").is_none());
177 assert!( v.pointer("/a/nope").is_none());
178 assert!( v.pointer("/a/").is_none());
179 assert!( v.pointer("/nope").is_none());
180 assert!( v.pointer("/").is_none());
181 }
182
183 #[test] fn pointer_mut() {
184 let text = "{\"a\": {\"b\": [0, [0, 1, {\"c\": \"value\"}]]}}";
185 let mut v : spanned::Value = from_str(text).unwrap();
186 assert_eq!(&text[v.pointer_mut("").unwrap().range()], "{\"a\": {\"b\": [0, [0, 1, {\"c\": \"value\"}]]}}");
187 assert_eq!(&text[v.pointer_mut("/a").unwrap().range()], "{\"b\": [0, [0, 1, {\"c\": \"value\"}]]}");
188 assert_eq!(&text[v.pointer_mut("/a/b").unwrap().range()], "[0, [0, 1, {\"c\": \"value\"}]]");
189 assert_eq!(&text[v.pointer_mut("/a/b/0").unwrap().range()], "0");
190 assert_eq!(&text[v.pointer_mut("/a/b/1").unwrap().range()], "[0, 1, {\"c\": \"value\"}]");
191 assert_eq!(&text[v.pointer_mut("/a/b/1/0").unwrap().range()], "0");
192 assert_eq!(&text[v.pointer_mut("/a/b/1/1").unwrap().range()], "1");
193 assert_eq!(&text[v.pointer_mut("/a/b/1/2").unwrap().range()], "{\"c\": \"value\"}");
194 assert_eq!(&text[v.pointer_mut("/a/b/1/2/c").unwrap().range()], "\"value\"");
195
196 assert!( v.pointer_mut("/a/b/1/2/d").is_none());
197 assert!( v.pointer_mut("/a/b/1/2/").is_none());
198 assert!( v.pointer_mut("/a/b/1/3").is_none());
199 assert!( v.pointer_mut("/a/b/1/").is_none());
200 assert!( v.pointer_mut("/a/b/2").is_none());
201 assert!( v.pointer_mut("/a/b/").is_none());
202 assert!( v.pointer_mut("/a/nope").is_none());
203 assert!( v.pointer_mut("/a/").is_none());
204 assert!( v.pointer_mut("/nope").is_none());
205 assert!( v.pointer_mut("/").is_none());
206 }
207}