jsonptr/
pointer.rs

1use crate::{token::InvalidEncodingError, Components, Token, Tokens};
2use alloc::{
3    borrow::ToOwned,
4    fmt,
5    string::{String, ToString},
6    vec::Vec,
7};
8use core::{borrow::Borrow, cmp::Ordering, ops::Deref, str::FromStr};
9
10/*
11░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
12╔══════════════════════════════════════════════════════════════════════════════╗
13║                                                                              ║
14║                                   Pointer                                    ║
15║                                  ¯¯¯¯¯¯¯¯¯                                   ║
16╚══════════════════════════════════════════════════════════════════════════════╝
17░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
18*/
19
20/// A JSON Pointer is a string containing a sequence of zero or more reference
21/// [`Token`]s, each prefixed by a `'/'` character.
22///
23/// See [RFC 6901 for more
24/// information](https://datatracker.ietf.org/doc/html/rfc6901).
25///
26/// ## Example
27/// ```rust
28/// use jsonptr::{Pointer, resolve::Resolve};
29/// use serde_json::{json, Value};
30///
31/// let data = json!({ "foo": { "bar": "baz" } });
32/// let ptr = Pointer::from_static("/foo/bar");
33/// let bar = data.resolve(&ptr).unwrap();
34/// assert_eq!(bar, "baz");
35/// ```
36#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
37// See https://doc.rust-lang.org/src/std/path.rs.html#1985
38#[cfg_attr(not(doc), repr(transparent))]
39pub struct Pointer(str);
40
41impl Default for &'static Pointer {
42    fn default() -> Self {
43        Pointer::root()
44    }
45}
46impl core::fmt::Display for Pointer {
47    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
48        self.0.fmt(f)
49    }
50}
51impl Pointer {
52    /// Private constructor for strings that are known to be correctly encoded
53    ///
54    /// This is a zero-copy constructor
55    fn new<S: AsRef<str> + ?Sized>(s: &S) -> &Self {
56        unsafe { &*(core::ptr::from_ref::<str>(s.as_ref()) as *const Self) }
57    }
58
59    /// Constant reference to a root pointer
60    pub const fn root() -> &'static Self {
61        // unsafe { &*(core::ptr::from_ref::<str>("") as *const Self) }
62        #[allow(clippy::ref_as_ptr)]
63        unsafe {
64            &*("" as *const str as *const Self)
65        }
66    }
67
68    /// Attempts to parse a string into a `Pointer`.
69    ///
70    /// If successful, this does not allocate.
71    ///
72    /// ## Errors
73    /// Returns a `ParseError` if the string is not a valid JSON Pointer.
74    pub fn parse<S: AsRef<str> + ?Sized>(s: &S) -> Result<&Self, ParseError> {
75        validate(s.as_ref()).map(Self::new)
76    }
77
78    /// Creates a static `Pointer` from a string.
79    ///
80    /// # Panics
81    ///
82    /// Will panic if the string does not represent a valid pointer.
83    ///
84    /// # Examples
85    ///
86    /// ```
87    /// use jsonptr::{Pointer, resolve::Resolve};
88    /// use serde_json::{json, Value};
89    ///
90    /// const POINTER: &Pointer = Pointer::from_static("/foo/bar");
91    /// let data = json!({ "foo": { "bar": "baz" } });
92    /// let bar = data.resolve(POINTER).unwrap();
93    /// assert_eq!(bar, "baz");
94    /// ```
95    pub const fn from_static(s: &'static str) -> &'static Self {
96        assert!(validate(s).is_ok(), "invalid json pointer");
97        unsafe { &*(core::ptr::from_ref::<str>(s) as *const Self) }
98    }
99
100    /// The encoded string representation of this `Pointer`
101    pub fn as_str(&self) -> &str {
102        &self.0
103    }
104
105    /// Converts into an owned [`PointerBuf`]
106    pub fn to_buf(&self) -> PointerBuf {
107        PointerBuf(self.0.to_string())
108    }
109
110    /// Returns an iterator of `Token`s in the `Pointer`.
111    pub fn tokens(&self) -> Tokens {
112        let mut s = self.0.split('/');
113        // skipping the first '/'
114        s.next();
115        Tokens::new(s)
116    }
117
118    /// Returns the number of tokens in the `Pointer`.
119    pub fn count(&self) -> usize {
120        self.tokens().count()
121    }
122
123    /// Returns `true` if the JSON Pointer equals `""`.
124    pub fn is_root(&self) -> bool {
125        self.0.is_empty()
126    }
127
128    /// Returns a `serde_json::Value` representation of this `Pointer`
129    #[cfg(feature = "json")]
130    pub fn to_json_value(&self) -> serde_json::Value {
131        serde_json::Value::String(self.0.to_string())
132    }
133
134    /// Returns the last `Token` in the `Pointer`.
135    pub fn back(&self) -> Option<Token> {
136        self.0
137            .rsplit_once('/')
138            .map(|(_, back)| Token::from_encoded_unchecked(back))
139    }
140
141    /// Returns the last token in the `Pointer`.
142    ///
143    /// alias for `back`
144    pub fn last(&self) -> Option<Token> {
145        self.back()
146    }
147
148    /// Returns the first `Token` in the `Pointer`.
149    pub fn front(&self) -> Option<Token> {
150        if self.is_root() {
151            return None;
152        }
153        self.0[1..]
154            .split_once('/')
155            .map_or_else(
156                || Token::from_encoded_unchecked(&self.0[1..]),
157                |(front, _)| Token::from_encoded_unchecked(front),
158            )
159            .into()
160    }
161
162    /// Returns the first `Token` in the `Pointer`.
163    ///
164    /// alias for `front`
165    pub fn first(&self) -> Option<Token> {
166        self.front()
167    }
168
169    /// Splits the `Pointer` into the first `Token` and a remainder `Pointer`.
170    pub fn split_front(&self) -> Option<(Token, &Self)> {
171        if self.is_root() {
172            return None;
173        }
174        self.0[1..]
175            .find('/')
176            .map_or_else(
177                || (Token::from_encoded_unchecked(&self.0[1..]), Self::root()),
178                |idx| {
179                    let (front, back) = self.0[1..].split_at(idx);
180                    (Token::from_encoded_unchecked(front), Self::new(back))
181                },
182            )
183            .into()
184    }
185    /// Splits the `Pointer` at the given index if the character at the index is
186    /// a separator backslash (`'/'`), returning `Some((head, tail))`. Otherwise,
187    /// returns `None`.
188    ///
189    /// For the following JSON Pointer, the following splits are possible (0, 4, 8):
190    /// ```text
191    /// /foo/bar/baz
192    /// ↑   ↑   ↑
193    /// 0   4   8
194    /// ```
195    /// All other indices will return `None`.
196    ///
197    /// ## Example
198    ///
199    /// ```rust
200    /// # use jsonptr::Pointer;
201    /// let ptr = Pointer::from_static("/foo/bar/baz");
202    /// let (head, tail) = ptr.split_at(4).unwrap();
203    /// assert_eq!(head, Pointer::from_static("/foo"));
204    /// assert_eq!(tail, Pointer::from_static("/bar/baz"));
205    /// assert_eq!(ptr.split_at(3), None);
206    /// ```
207    pub fn split_at(&self, offset: usize) -> Option<(&Self, &Self)> {
208        if self.0.as_bytes().get(offset).copied() != Some(b'/') {
209            return None;
210        }
211        let (head, tail) = self.0.split_at(offset);
212        Some((Self::new(head), Self::new(tail)))
213    }
214
215    /// Splits the `Pointer` into the parent path and the last `Token`.
216    pub fn split_back(&self) -> Option<(&Self, Token)> {
217        self.0
218            .rsplit_once('/')
219            .map(|(front, back)| (Self::new(front), Token::from_encoded_unchecked(back)))
220    }
221
222    /// A pointer to the parent of the current path.
223    pub fn parent(&self) -> Option<&Self> {
224        self.0.rsplit_once('/').map(|(front, _)| Self::new(front))
225    }
226
227    /// Returns the pointer stripped of the given suffix.
228    pub fn strip_suffix<'a>(&'a self, suffix: &Self) -> Option<&'a Self> {
229        self.0.strip_suffix(&suffix.0).map(Self::new)
230    }
231
232    /// Returns the pointer stripped of the given prefix.
233    pub fn strip_prefix<'a>(&'a self, prefix: &Self) -> Option<&'a Self> {
234        self.0.strip_prefix(&prefix.0).map(Self::new)
235    }
236    /// Attempts to get a `Token` by the index. Returns `None` if the index is
237    /// out of bounds.
238    ///
239    /// ## Example
240    /// ```rust
241    /// use jsonptr::{Pointer, Token};
242    ///
243    /// let ptr = Pointer::from_static("/foo/bar");
244    /// assert_eq!(ptr.get(0), Some("foo".into()));
245    /// assert_eq!(ptr.get(1), Some("bar".into()));
246    /// assert_eq!(ptr.get(2), None);
247    ///
248    /// let ptr = Pointer::root();
249    /// assert_eq!(ptr.get(0), None);
250    /// ```
251    pub fn get(&self, index: usize) -> Option<Token> {
252        self.tokens().nth(index).clone()
253    }
254
255    /// Attempts to resolve a [`R::Value`] based on the path in this [`Pointer`].
256    ///
257    /// ## Errors
258    /// Returns [`R::Error`] if an error occurs while resolving.
259    ///
260    /// The rules of such are determined by the `R`'s implementation of
261    /// [`Resolve`] but provided implementations return [`ResolveError`] if:
262    /// - The path is unreachable (e.g. a scalar is encountered prior to the end
263    ///   of the path)
264    /// - The path is not found (e.g. a key in an object or an index in an array
265    ///   does not exist)
266    /// - A [`Token`] cannot be parsed as an array [`Index`]
267    /// - An array [`Index`] is out of bounds
268    ///
269    /// [`R::Value`]: `crate::resolve::Resolve::Value`
270    /// [`R::Error`]: `crate::resolve::Resolve::Error`
271    /// [`Resolve`]: `crate::resolve::Resolve`
272    /// [`ResolveError`]: `crate::resolve::ResolveError`
273    /// [`Token`]: `crate::Token`
274    /// [`Index`]: `crate::index::Index`
275    #[cfg(feature = "resolve")]
276    pub fn resolve<'v, R: crate::Resolve>(&self, value: &'v R) -> Result<&'v R::Value, R::Error> {
277        value.resolve(self)
278    }
279
280    /// Attempts to resolve a mutable [`R::Value`] based on the path in this
281    /// `Pointer`.
282    ///
283    /// ## Errors
284    /// Returns [`R::Error`] if an error occurs while
285    /// resolving.
286    ///
287    /// The rules of such are determined by the `R`'s implementation of
288    /// [`ResolveMut`] but provided implementations return [`ResolveError`] if:
289    /// - The path is unreachable (e.g. a scalar is encountered prior to the end
290    ///   of the path)
291    /// - The path is not found (e.g. a key in an object or an index in an array
292    ///   does not exist)
293    /// - A [`Token`] cannot be parsed as an array [`Index`]
294    /// - An array [`Index`] is out of bounds
295    ///
296    /// [`R::Value`]: `crate::resolve::ResolveMut::Value`
297    /// [`R::Error`]: `crate::resolve::ResolveMut::Error`
298    /// [`ResolveMut`]: `crate::resolve::ResolveMut`
299    /// [`ResolveError`]: `crate::resolve::ResolveError`
300    /// [`Token`]: `crate::Token`
301    /// [`Index`]: `crate::index::Index`
302
303    #[cfg(feature = "resolve")]
304    pub fn resolve_mut<'v, R: crate::ResolveMut>(
305        &self,
306        value: &'v mut R,
307    ) -> Result<&'v mut R::Value, R::Error> {
308        value.resolve_mut(self)
309    }
310
311    /// Finds the commonality between this and another `Pointer`.
312    pub fn intersection<'a>(&'a self, other: &Self) -> &'a Self {
313        if self.is_root() || other.is_root() {
314            return Self::root();
315        }
316        let mut idx = 0;
317        for (a, b) in self.tokens().zip(other.tokens()) {
318            if a != b {
319                break;
320            }
321            idx += a.encoded().len() + 1;
322        }
323        self.split_at(idx).map_or(self, |(head, _)| head)
324    }
325
326    /// Attempts to delete a `serde_json::Value` based upon the path in this
327    /// `Pointer`.
328    ///
329    /// The rules of deletion are determined by the `D`'s implementation of
330    /// [`Delete`]. The supplied implementations (`"json"` & `"toml"`) operate
331    /// as follows:
332    /// - If the `Pointer` can be resolved, the `Value` is deleted and returned.
333    /// - If the `Pointer` fails to resolve for any reason, `Ok(None)` is returned.
334    /// - If the `Pointer` is root, `value` is replaced:
335    ///     - `"json"`: `serde_json::Value::Null`
336    ///     - `"toml"`: `toml::Value::Table::Default`
337    ///
338    ///
339    /// ## Examples
340    /// ### Deleting a resolved pointer:
341    /// ```rust
342    /// use jsonptr::{Pointer, delete::Delete};
343    /// use serde_json::json;
344    ///
345    /// let mut data = json!({ "foo": { "bar": { "baz": "qux" } } });
346    /// let ptr = Pointer::from_static("/foo/bar/baz");
347    /// assert_eq!(data.delete(&ptr), Some("qux".into()));
348    /// assert_eq!(data, json!({ "foo": { "bar": {} } }));
349    /// ```
350    /// ### Deleting a non-existent Pointer returns `None`:
351    /// ```rust
352    /// use jsonptr::{ Pointer, delete::Delete };
353    /// use serde_json::json;
354    ///
355    /// let mut data = json!({});
356    /// let ptr = Pointer::from_static("/foo/bar/baz");
357    /// assert_eq!(ptr.delete(&mut data), None);
358    /// assert_eq!(data, json!({}));
359    /// ```
360    /// ### Deleting a root pointer replaces the value with `Value::Null`:
361    /// ```rust
362    /// use jsonptr::{Pointer, delete::Delete};
363    /// use serde_json::json;
364    ///
365    /// let mut data = json!({ "foo": { "bar": "baz" } });
366    /// let ptr = Pointer::root();
367    /// assert_eq!(data.delete(&ptr), Some(json!({ "foo": { "bar": "baz" } })));
368    /// assert!(data.is_null());
369    /// ```
370    ///
371    /// [`Delete`]: crate::delete::Delete
372    #[cfg(feature = "delete")]
373    pub fn delete<D: crate::Delete>(&self, value: &mut D) -> Option<D::Value> {
374        value.delete(self)
375    }
376
377    /// Attempts to assign `src` to `dest` based on the path in this `Pointer`.
378    ///
379    /// If the path is partially available, the missing portions will be created. If the path
380    /// contains a zero index, such as `"/0"`, then an array will be created. Otherwise, objects
381    /// will be utilized to create the missing path.
382    ///
383    /// ## Example
384    /// ```rust
385    /// use jsonptr::Pointer;
386    /// use serde_json::{json, Value};
387    ///
388    /// let mut data = json!([]);
389    /// let mut ptr = Pointer::from_static("/0/foo");
390    /// let replaced = ptr.assign(&mut data, json!("bar")).unwrap();
391    /// assert_eq!(data, json!([{"foo": "bar"}]));
392    /// assert_eq!(replaced, None);
393    /// ```
394    ///
395    /// ## Errors
396    /// Returns [`Assign::Error`] if the path is invalid or if the value cannot be assigned.
397    ///
398    /// [`Assign::Error`]: crate::assign::Assign::Error
399    #[cfg(feature = "assign")]
400    pub fn assign<D, V>(&self, dest: &mut D, src: V) -> Result<Option<D::Value>, D::Error>
401    where
402        D: crate::Assign,
403        V: Into<D::Value>,
404    {
405        dest.assign(self, src)
406    }
407
408    /// Returns [`Components`] of this JSON Pointer.
409    ///
410    /// A [`Component`](crate::Component) is either [`Token`] or the root
411    /// location of a document.
412    /// ## Example
413    /// ```
414    /// # use jsonptr::{Component, Pointer};
415    /// let ptr = Pointer::parse("/a/b").unwrap();
416    /// let mut components = ptr.components();
417    /// assert_eq!(components.next(), Some(Component::Root));
418    /// assert_eq!(components.next(), Some(Component::Token("a".into())));
419    /// assert_eq!(components.next(), Some(Component::Token("b".into())));
420    /// assert_eq!(components.next(), None);
421    /// ```
422    pub fn components(&self) -> Components {
423        self.into()
424    }
425
426    /// Creates an owned [`PointerBuf`] like `self` but with `token` appended.
427    ///
428    /// See [`PointerBuf::push_back`] for more details.
429    ///
430    /// **Note**: this method allocates. If you find yourself calling it more
431    /// than once for a given pointer, consider using [`PointerBuf::push_back`]
432    /// instead.
433    ///
434    /// ## Examples
435    /// ```
436    /// let ptr = jsonptr::Pointer::from_static("/foo");
437    /// let foobar = ptr.with_trailing_token("bar");
438    /// assert_eq!(foobar, "/foo/bar");
439    /// ```
440    pub fn with_trailing_token<'t>(&self, token: impl Into<Token<'t>>) -> PointerBuf {
441        let mut buf = self.to_buf();
442        buf.push_back(token.into());
443        buf
444    }
445
446    /// Creates an owned [`PointerBuf`] like `self` but with `token` prepended.
447    ///
448    /// See [`PointerBuf::push_front`] for more details.
449    ///
450    /// **Note**: this method allocates. If you find yourself calling it more
451    /// than once for a given pointer, consider using [`PointerBuf::push_front`]
452    /// instead.
453    ///
454    /// ## Examples
455    /// ```
456    /// let ptr = jsonptr::Pointer::from_static("/bar");
457    /// let foobar = ptr.with_leading_token("foo");
458    /// assert_eq!(foobar, "/foo/bar");
459    /// ```
460    pub fn with_leading_token<'t>(&self, token: impl Into<Token<'t>>) -> PointerBuf {
461        let mut buf = self.to_buf();
462        buf.push_front(token);
463        buf
464    }
465
466    /// Creates an owned [`PointerBuf`] like `self` but with `other` appended to
467    /// the end.
468    ///
469    /// See [`PointerBuf::append`] for more details.
470    ///
471    /// **Note**: this method allocates. If you find yourself calling it more
472    /// than once for a given pointer, consider using [`PointerBuf::append`]
473    /// instead.
474    ///
475    /// ## Examples
476    /// ```
477    /// let ptr = jsonptr::Pointer::from_static("/foo");
478    /// let other = jsonptr::Pointer::from_static("/bar/baz");
479    /// assert_eq!(ptr.concat(other), "/foo/bar/baz");
480    /// ```
481    pub fn concat(&self, other: &Pointer) -> PointerBuf {
482        let mut buf = self.to_buf();
483        buf.append(other);
484        buf
485    }
486
487    //  Returns the length of `self` in encoded format.
488    ///
489    /// This length expresses the byte count of the underlying string that
490    /// represents the RFC 6091 Pointer. See also [`std::str::len`].
491    ///
492    /// ## Examples
493    /// ```
494    /// let mut ptr = jsonptr::Pointer::from_static("/foo/bar").to_buf();
495    /// assert_eq!(ptr.len(), 8);
496    ///
497    /// ptr.push_back("~");
498    /// assert_eq!(ptr.len(), 11);
499    ///
500    /// ```
501    pub fn len(&self) -> usize {
502        self.0.len()
503    }
504
505    /// Returns `true` if the `Pointer` is empty (i.e. root).    
506    ///
507    /// ## Examples
508    /// ```
509    /// let mut ptr = jsonptr::PointerBuf::new();
510    /// assert!(ptr.is_empty());
511    ///
512    /// ptr.push_back("foo");
513    /// assert!(!ptr.is_empty());
514    /// ```
515    pub fn is_empty(&self) -> bool {
516        self.0.is_empty()
517    }
518}
519
520#[cfg(feature = "serde")]
521impl serde::Serialize for Pointer {
522    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
523    where
524        S: serde::Serializer,
525    {
526        <str>::serialize(&self.0, serializer)
527    }
528}
529
530#[cfg(feature = "serde")]
531impl<'de: 'p, 'p> serde::Deserialize<'de> for &'p Pointer {
532    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
533    where
534        D: serde::Deserializer<'de>,
535    {
536        use serde::de::{Error, Visitor};
537
538        struct PointerVisitor;
539
540        impl<'a> Visitor<'a> for PointerVisitor {
541            type Value = &'a Pointer;
542
543            fn expecting(&self, formatter: &mut core::fmt::Formatter) -> core::fmt::Result {
544                formatter.write_str("a borrowed Pointer")
545            }
546
547            fn visit_borrowed_str<E>(self, v: &'a str) -> Result<Self::Value, E>
548            where
549                E: Error,
550            {
551                Pointer::parse(v).map_err(|err| {
552                    Error::custom(format!("failed to parse json pointer\n\ncaused by:\n{err}"))
553                })
554            }
555        }
556
557        deserializer.deserialize_str(PointerVisitor)
558    }
559}
560
561impl ToOwned for Pointer {
562    type Owned = PointerBuf;
563
564    fn to_owned(&self) -> Self::Owned {
565        self.to_buf()
566    }
567}
568
569impl PartialEq<&str> for Pointer {
570    fn eq(&self, other: &&str) -> bool {
571        &&self.0 == other
572    }
573}
574impl<'p> PartialEq<String> for &'p Pointer {
575    fn eq(&self, other: &String) -> bool {
576        self.0.eq(other)
577    }
578}
579impl PartialEq<str> for Pointer {
580    fn eq(&self, other: &str) -> bool {
581        &self.0 == other
582    }
583}
584
585impl PartialEq<Pointer> for &str {
586    fn eq(&self, other: &Pointer) -> bool {
587        *self == (&other.0)
588    }
589}
590
591impl PartialEq<Pointer> for String {
592    fn eq(&self, other: &Pointer) -> bool {
593        self == &other.0
594    }
595}
596
597impl PartialEq<Pointer> for str {
598    fn eq(&self, other: &Pointer) -> bool {
599        self == &other.0
600    }
601}
602
603impl PartialEq<String> for Pointer {
604    fn eq(&self, other: &String) -> bool {
605        &self.0 == other
606    }
607}
608
609impl PartialEq<PointerBuf> for Pointer {
610    fn eq(&self, other: &PointerBuf) -> bool {
611        self.0 == other.0
612    }
613}
614
615impl PartialEq<Pointer> for PointerBuf {
616    fn eq(&self, other: &Pointer) -> bool {
617        self.0 == other.0
618    }
619}
620impl PartialEq<PointerBuf> for String {
621    fn eq(&self, other: &PointerBuf) -> bool {
622        self == &other.0
623    }
624}
625impl PartialEq<String> for PointerBuf {
626    fn eq(&self, other: &String) -> bool {
627        &self.0 == other
628    }
629}
630
631impl PartialEq<PointerBuf> for str {
632    fn eq(&self, other: &PointerBuf) -> bool {
633        self == other.0
634    }
635}
636impl PartialEq<PointerBuf> for &str {
637    fn eq(&self, other: &PointerBuf) -> bool {
638        *self == other.0
639    }
640}
641
642impl AsRef<Pointer> for Pointer {
643    fn as_ref(&self) -> &Pointer {
644        self
645    }
646}
647impl AsRef<Pointer> for PointerBuf {
648    fn as_ref(&self) -> &Pointer {
649        self
650    }
651}
652
653impl PartialEq<PointerBuf> for &Pointer {
654    fn eq(&self, other: &PointerBuf) -> bool {
655        self.0 == other.0
656    }
657}
658
659impl PartialEq<&Pointer> for PointerBuf {
660    fn eq(&self, other: &&Pointer) -> bool {
661        self.0 == other.0
662    }
663}
664
665#[cfg(feature = "json")]
666impl From<&Pointer> for serde_json::Value {
667    fn from(ptr: &Pointer) -> Self {
668        ptr.to_json_value()
669    }
670}
671
672impl AsRef<str> for Pointer {
673    fn as_ref(&self) -> &str {
674        &self.0
675    }
676}
677
678impl Borrow<str> for Pointer {
679    fn borrow(&self) -> &str {
680        &self.0
681    }
682}
683
684impl AsRef<[u8]> for Pointer {
685    fn as_ref(&self) -> &[u8] {
686        self.0.as_bytes()
687    }
688}
689
690impl PartialOrd<PointerBuf> for Pointer {
691    fn partial_cmp(&self, other: &PointerBuf) -> Option<Ordering> {
692        self.0.partial_cmp(other.0.as_str())
693    }
694}
695
696impl PartialOrd<Pointer> for PointerBuf {
697    fn partial_cmp(&self, other: &Pointer) -> Option<Ordering> {
698        self.0.as_str().partial_cmp(&other.0)
699    }
700}
701impl PartialOrd<&Pointer> for PointerBuf {
702    fn partial_cmp(&self, other: &&Pointer) -> Option<Ordering> {
703        self.0.as_str().partial_cmp(&other.0)
704    }
705}
706
707impl PartialOrd<Pointer> for String {
708    fn partial_cmp(&self, other: &Pointer) -> Option<Ordering> {
709        self.as_str().partial_cmp(&other.0)
710    }
711}
712impl PartialOrd<String> for &Pointer {
713    fn partial_cmp(&self, other: &String) -> Option<Ordering> {
714        self.0.partial_cmp(other.as_str())
715    }
716}
717
718impl PartialOrd<PointerBuf> for String {
719    fn partial_cmp(&self, other: &PointerBuf) -> Option<Ordering> {
720        self.as_str().partial_cmp(other.0.as_str())
721    }
722}
723
724impl PartialOrd<Pointer> for str {
725    fn partial_cmp(&self, other: &Pointer) -> Option<Ordering> {
726        self.partial_cmp(&other.0)
727    }
728}
729
730impl PartialOrd<PointerBuf> for str {
731    fn partial_cmp(&self, other: &PointerBuf) -> Option<Ordering> {
732        self.partial_cmp(other.0.as_str())
733    }
734}
735impl PartialOrd<PointerBuf> for &str {
736    fn partial_cmp(&self, other: &PointerBuf) -> Option<Ordering> {
737        (*self).partial_cmp(other.0.as_str())
738    }
739}
740impl PartialOrd<Pointer> for &str {
741    fn partial_cmp(&self, other: &Pointer) -> Option<Ordering> {
742        (*self).partial_cmp(&other.0)
743    }
744}
745
746impl PartialOrd<&str> for &Pointer {
747    fn partial_cmp(&self, other: &&str) -> Option<Ordering> {
748        PartialOrd::partial_cmp(&self.0[..], &other[..])
749    }
750}
751
752impl PartialOrd<String> for Pointer {
753    fn partial_cmp(&self, other: &String) -> Option<Ordering> {
754        self.0.partial_cmp(other.as_str())
755    }
756}
757
758impl PartialOrd<&str> for PointerBuf {
759    fn partial_cmp(&self, other: &&str) -> Option<Ordering> {
760        PartialOrd::partial_cmp(&self.0[..], &other[..])
761    }
762}
763
764impl<'p> PartialOrd<PointerBuf> for &'p Pointer {
765    fn partial_cmp(&self, other: &PointerBuf) -> Option<Ordering> {
766        self.0.partial_cmp(other.0.as_str())
767    }
768}
769
770impl PartialOrd<String> for PointerBuf {
771    fn partial_cmp(&self, other: &String) -> Option<Ordering> {
772        self.0.partial_cmp(other)
773    }
774}
775
776impl<'a> IntoIterator for &'a Pointer {
777    type Item = Token<'a>;
778    type IntoIter = Tokens<'a>;
779    fn into_iter(self) -> Self::IntoIter {
780        self.tokens()
781    }
782}
783
784/*
785░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
786╔══════════════════════════════════════════════════════════════════════════════╗
787║                                                                              ║
788║                                  PointerBuf                                  ║
789║                                 ¯¯¯¯¯¯¯¯¯¯¯¯                                 ║
790╚══════════════════════════════════════════════════════════════════════════════╝
791░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
792*/
793
794/// An owned, mutable [`Pointer`] (akin to `String`).
795///
796/// This type provides methods like [`PointerBuf::push_back`] and
797/// [`PointerBuf::replace`] that mutate the pointer in place. It also
798/// implements [`core::ops::Deref`] to [`Pointer`], meaning that all methods on
799/// [`Pointer`] slices are available on `PointerBuf` values as well.
800#[derive(Clone, Default, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
801pub struct PointerBuf(String);
802
803impl PointerBuf {
804    /// Creates a new `PointerBuf` pointing to a document root.
805    pub fn new() -> Self {
806        Self(String::new())
807    }
808
809    /// Attempts to parse a string into a `PointerBuf`.
810    ///
811    /// ## Errors
812    /// Returns a [`ParseError`] if the string is not a valid JSON Pointer.
813    pub fn parse<S: AsRef<str> + ?Sized>(s: &S) -> Result<Self, ParseError> {
814        Pointer::parse(&s).map(Pointer::to_buf)
815    }
816
817    /// Creates a new `PointerBuf` from a slice of non-encoded strings.
818    pub fn from_tokens<'a, T>(tokens: impl IntoIterator<Item = T>) -> Self
819    where
820        T: Into<Token<'a>>,
821    {
822        let mut inner = String::new();
823        for t in tokens.into_iter().map(Into::into) {
824            inner.push('/');
825            inner.push_str(t.encoded());
826        }
827        PointerBuf(inner)
828    }
829
830    /// Coerces to a Pointer slice.
831    pub fn as_ptr(&self) -> &Pointer {
832        self
833    }
834
835    /// Pushes a `Token` onto the front of this `Pointer`.
836    pub fn push_front<'t>(&mut self, token: impl Into<Token<'t>>) {
837        self.0.insert(0, '/');
838        self.0.insert_str(1, token.into().encoded());
839    }
840
841    /// Pushes a `Token` onto the back of this `Pointer`.
842    pub fn push_back<'t>(&mut self, token: impl Into<Token<'t>>) {
843        self.0.push('/');
844        self.0.push_str(token.into().encoded());
845    }
846
847    /// Removes and returns the last `Token` in the `Pointer` if it exists.
848    pub fn pop_back(&mut self) -> Option<Token<'static>> {
849        if let Some(idx) = self.0.rfind('/') {
850            let back = Token::from_encoded_unchecked(self.0.split_off(idx + 1));
851            self.0.pop(); // remove trailing `/`
852            Some(back)
853        } else {
854            None
855        }
856    }
857
858    /// Removes and returns the first `Token` in the `Pointer` if it exists.
859    pub fn pop_front(&mut self) -> Option<Token<'static>> {
860        (!self.is_root()).then(|| {
861            // if not root, must contain at least one `/`
862            let mut token = if let Some(idx) = self.0[1..].find('/') {
863                let token = self.0.split_off(idx + 1);
864                core::mem::replace(&mut self.0, token)
865            } else {
866                core::mem::take(&mut self.0)
867            };
868            token.remove(0); // remove leading `/`
869            Token::from_encoded_unchecked(token)
870        })
871    }
872
873    /// Merges two `Pointer`s by appending `other` onto `self`.
874    pub fn append<P: AsRef<Pointer>>(&mut self, other: P) -> &PointerBuf {
875        let other = other.as_ref();
876        if self.is_root() {
877            self.0 = other.0.to_string();
878        } else if !other.is_root() {
879            self.0.push_str(&other.0);
880        }
881        self
882    }
883
884    /// Attempts to replace a `Token` by the index, returning the replaced
885    /// `Token` if it already exists. Returns `None` otherwise.
886    ///
887    /// ## Errors
888    /// A [`ReplaceError`] is returned if the index is out of bounds.
889    pub fn replace<'t>(
890        &mut self,
891        index: usize,
892        token: impl Into<Token<'t>>,
893    ) -> Result<Option<Token>, ReplaceError> {
894        if self.is_root() {
895            return Err(ReplaceError {
896                count: self.count(),
897                index,
898            });
899        }
900        let mut tokens = self.tokens().collect::<Vec<_>>();
901        if index >= tokens.len() {
902            return Err(ReplaceError {
903                count: tokens.len(),
904                index,
905            });
906        }
907        let old = tokens.get(index).map(super::token::Token::to_owned);
908        tokens[index] = token.into();
909
910        let mut buf = String::new();
911        for token in tokens {
912            buf.push('/');
913            buf.push_str(token.encoded());
914        }
915        self.0 = buf;
916
917        Ok(old)
918    }
919
920    /// Clears the `Pointer`, setting it to root (`""`).
921    pub fn clear(&mut self) {
922        self.0.clear();
923    }
924}
925
926impl FromStr for PointerBuf {
927    type Err = ParseError;
928    fn from_str(s: &str) -> Result<Self, Self::Err> {
929        Self::try_from(s)
930    }
931}
932
933impl Borrow<Pointer> for PointerBuf {
934    fn borrow(&self) -> &Pointer {
935        self.as_ptr()
936    }
937}
938
939impl Deref for PointerBuf {
940    type Target = Pointer;
941    fn deref(&self) -> &Self::Target {
942        Pointer::new(&self.0)
943    }
944}
945
946#[cfg(feature = "serde")]
947impl<'de> serde::Deserialize<'de> for PointerBuf {
948    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
949    where
950        D: serde::Deserializer<'de>,
951    {
952        use serde::de::Error;
953        let s = String::deserialize(deserializer)?;
954        PointerBuf::try_from(s).map_err(D::Error::custom)
955    }
956}
957
958#[cfg(feature = "serde")]
959impl serde::Serialize for PointerBuf {
960    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
961    where
962        S: serde::Serializer,
963    {
964        String::serialize(&self.0, serializer)
965    }
966}
967
968impl From<Token<'_>> for PointerBuf {
969    fn from(t: Token) -> Self {
970        PointerBuf::from_tokens([t])
971    }
972}
973
974impl TryFrom<String> for PointerBuf {
975    type Error = ParseError;
976    fn try_from(value: String) -> Result<Self, Self::Error> {
977        let _ = validate(&value)?;
978        Ok(Self(value))
979    }
980}
981
982impl From<usize> for PointerBuf {
983    fn from(value: usize) -> Self {
984        PointerBuf::from_tokens([value])
985    }
986}
987
988impl<'a> IntoIterator for &'a PointerBuf {
989    type Item = Token<'a>;
990    type IntoIter = Tokens<'a>;
991    fn into_iter(self) -> Self::IntoIter {
992        self.tokens()
993    }
994}
995
996impl TryFrom<&str> for PointerBuf {
997    type Error = ParseError;
998    fn try_from(value: &str) -> Result<Self, Self::Error> {
999        Pointer::parse(value).map(Pointer::to_buf)
1000    }
1001}
1002
1003impl PartialEq<&str> for PointerBuf {
1004    fn eq(&self, other: &&str) -> bool {
1005        &self.0 == other
1006    }
1007}
1008
1009impl PartialEq<str> for PointerBuf {
1010    fn eq(&self, other: &str) -> bool {
1011        self.0 == other
1012    }
1013}
1014
1015impl core::fmt::Display for PointerBuf {
1016    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1017        self.0.fmt(f)
1018    }
1019}
1020
1021const fn validate(value: &str) -> Result<&str, ParseError> {
1022    if value.is_empty() {
1023        return Ok(value);
1024    }
1025    let bytes = value.as_bytes();
1026    if bytes[0] != b'/' {
1027        return Err(ParseError::NoLeadingBackslash);
1028    }
1029    let mut ptr_offset = 0; // offset within the pointer of the most recent '/' separator
1030    let mut tok_offset = 0; // offset within the current token
1031
1032    let bytes = value.as_bytes();
1033    let mut i = 0;
1034    while i < bytes.len() {
1035        match bytes[i] {
1036            b'/' => {
1037                // backslashes ('/') separate tokens
1038                // we increment the ptr_offset to point to this character
1039                ptr_offset = i;
1040                // and reset the token offset
1041                tok_offset = 0;
1042            }
1043            b'~' => {
1044                // if the character is a '~', then the next character must be '0' or '1'
1045                // otherwise the encoding is invalid and `InvalidEncodingError` is returned
1046                if i + 1 >= bytes.len() || (bytes[i + 1] != b'0' && bytes[i + 1] != b'1') {
1047                    // the pointer is not properly encoded
1048                    //
1049                    // we use the pointer offset, which points to the last
1050                    // encountered separator, as the offset of the error.
1051                    // The source `InvalidEncodingError` then uses the token
1052                    // offset.
1053                    //
1054                    // "/foo/invalid~encoding"
1055                    //      ^       ^
1056                    //      |       |
1057                    //  ptr_offset  |
1058                    //          tok_offset
1059                    //
1060                    return Err(ParseError::InvalidEncoding {
1061                        offset: ptr_offset,
1062                        source: InvalidEncodingError { offset: tok_offset },
1063                    });
1064                }
1065                // already checked the next character, so we skip it
1066                i += 1;
1067                // incrementing the pointer offset since the next byte has
1068                // already been checked
1069                tok_offset += 1;
1070            }
1071            _ => {}
1072        }
1073        i += 1;
1074        // not a separator so we increment the token offset
1075        tok_offset += 1;
1076    }
1077    Ok(value)
1078}
1079
1080/*
1081░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
1082╔══════════════════════════════════════════════════════════════════════════════╗
1083║                                                                              ║
1084║                                  ParseError                                  ║
1085║                                 ¯¯¯¯¯¯¯¯¯¯¯¯                                 ║
1086╚══════════════════════════════════════════════════════════════════════════════╝
1087░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
1088*/
1089
1090/// Indicates that a `Pointer` was malformed and unable to be parsed.
1091#[derive(Debug, PartialEq)]
1092pub enum ParseError {
1093    /// `Pointer` did not start with a backslash (`'/'`).
1094    NoLeadingBackslash,
1095
1096    /// `Pointer` contained invalid encoding (e.g. `~` not followed by `0` or
1097    /// `1`).
1098    InvalidEncoding {
1099        /// Offset of the partial pointer starting with the token that contained
1100        /// the invalid encoding
1101        offset: usize,
1102        /// The source `InvalidEncodingError`
1103        source: InvalidEncodingError,
1104    },
1105}
1106
1107impl fmt::Display for ParseError {
1108    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1109        match self {
1110            Self::NoLeadingBackslash { .. } => {
1111                write!(
1112                    f,
1113                    "json pointer is malformed as it does not start with a backslash ('/')"
1114                )
1115            }
1116            Self::InvalidEncoding { source, .. } => write!(f, "{source}"),
1117        }
1118    }
1119}
1120
1121impl ParseError {
1122    /// Returns `true` if this error is `NoLeadingBackslash`
1123    pub fn is_no_leading_backslash(&self) -> bool {
1124        matches!(self, Self::NoLeadingBackslash { .. })
1125    }
1126
1127    /// Returns `true` if this error is `InvalidEncoding`    
1128    pub fn is_invalid_encoding(&self) -> bool {
1129        matches!(self, Self::InvalidEncoding { .. })
1130    }
1131
1132    /// Offset of the partial pointer starting with the token which caused the error.
1133    ///
1134    /// ```text
1135    /// "/foo/invalid~tilde/invalid"
1136    ///      ↑
1137    /// ```
1138    ///
1139    /// ```
1140    /// # use jsonptr::PointerBuf;
1141    /// let err = PointerBuf::parse("/foo/invalid~tilde/invalid").unwrap_err();
1142    /// assert_eq!(err.pointer_offset(), 4)
1143    /// ```
1144    pub fn pointer_offset(&self) -> usize {
1145        match *self {
1146            Self::NoLeadingBackslash { .. } => 0,
1147            Self::InvalidEncoding { offset, .. } => offset,
1148        }
1149    }
1150
1151    /// Offset of the character index from within the first token of
1152    /// [`Self::pointer_offset`])
1153    ///
1154    /// ```text
1155    /// "/foo/invalid~tilde/invalid"
1156    ///              ↑
1157    ///              8
1158    /// ```
1159    /// ```
1160    /// # use jsonptr::PointerBuf;
1161    /// let err = PointerBuf::parse("/foo/invalid~tilde/invalid").unwrap_err();
1162    /// assert_eq!(err.source_offset(), 8)
1163    /// ```
1164    pub fn source_offset(&self) -> usize {
1165        match self {
1166            Self::NoLeadingBackslash { .. } => 0,
1167            Self::InvalidEncoding { source, .. } => source.offset,
1168        }
1169    }
1170
1171    /// Offset of the first invalid encoding from within the pointer.
1172    /// ```text
1173    /// "/foo/invalid~tilde/invalid"
1174    ///              ↑
1175    ///             12
1176    /// ```
1177    /// ```
1178    /// use jsonptr::PointerBuf;
1179    /// let err = PointerBuf::parse("/foo/invalid~tilde/invalid").unwrap_err();
1180    /// assert_eq!(err.complete_offset(), 12)
1181    /// ```
1182    pub fn complete_offset(&self) -> usize {
1183        self.source_offset() + self.pointer_offset()
1184    }
1185}
1186
1187#[cfg(feature = "std")]
1188impl std::error::Error for ParseError {
1189    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
1190        match self {
1191            Self::InvalidEncoding { source, .. } => Some(source),
1192            Self::NoLeadingBackslash => None,
1193        }
1194    }
1195}
1196
1197/*
1198░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
1199╔══════════════════════════════════════════════════════════════════════════════╗
1200║                                                                              ║
1201║                              ReplaceTokenError                               ║
1202║                             ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯                              ║
1203╚══════════════════════════════════════════════════════════════════════════════╝
1204░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
1205*/
1206
1207/// Returned from [`PointerBuf::replace`] when the provided index is out of
1208/// bounds.
1209#[derive(Debug, PartialEq, Eq)]
1210pub struct ReplaceError {
1211    /// The index of the token that was out of bounds.
1212    pub index: usize,
1213    /// The number of tokens in the `Pointer`.
1214    pub count: usize,
1215}
1216
1217impl fmt::Display for ReplaceError {
1218    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1219        write!(f, "index {} is out of bounds ({})", self.index, self.count)
1220    }
1221}
1222
1223#[cfg(feature = "std")]
1224impl std::error::Error for ReplaceError {}
1225
1226/*
1227░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
1228╔══════════════════════════════════════════════════════════════════════════════╗
1229║                                                                              ║
1230║                                    Tests                                     ║
1231║                                   ¯¯¯¯¯¯¯                                    ║
1232╚══════════════════════════════════════════════════════════════════════════════╝
1233░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
1234*/
1235
1236#[cfg(test)]
1237mod tests {
1238    use std::error::Error;
1239
1240    use super::*;
1241    use quickcheck::TestResult;
1242    use quickcheck_macros::quickcheck;
1243
1244    #[test]
1245    #[should_panic = "invalid json pointer"]
1246    fn from_const_validates() {
1247        let _ = Pointer::from_static("foo/bar");
1248    }
1249
1250    #[test]
1251    fn strip_suffix() {
1252        let p = Pointer::new("/example/pointer/to/some/value");
1253        let stripped = p.strip_suffix(Pointer::new("/to/some/value")).unwrap();
1254        assert_eq!(stripped, "/example/pointer");
1255    }
1256
1257    #[test]
1258    fn strip_prefix() {
1259        let p = Pointer::new("/example/pointer/to/some/value");
1260        let stripped = p.strip_prefix(Pointer::new("/example/pointer")).unwrap();
1261        assert_eq!(stripped, "/to/some/value");
1262    }
1263
1264    #[test]
1265    fn parse_error_is_no_leading_backslash() {
1266        let err = ParseError::NoLeadingBackslash;
1267        assert!(err.is_no_leading_backslash());
1268        assert!(!err.is_invalid_encoding());
1269    }
1270
1271    #[test]
1272    fn parse_error_is_invalid_encoding() {
1273        let err = ParseError::InvalidEncoding {
1274            offset: 0,
1275            source: InvalidEncodingError { offset: 1 },
1276        };
1277        assert!(!err.is_no_leading_backslash());
1278        assert!(err.is_invalid_encoding());
1279    }
1280
1281    #[test]
1282    fn parse() {
1283        let tests = [
1284            ("", Ok("")),
1285            ("/", Ok("/")),
1286            ("/foo", Ok("/foo")),
1287            ("/foo/bar", Ok("/foo/bar")),
1288            ("/foo/bar/baz", Ok("/foo/bar/baz")),
1289            ("/foo/bar/baz/~0", Ok("/foo/bar/baz/~0")),
1290            ("/foo/bar/baz/~1", Ok("/foo/bar/baz/~1")),
1291            ("/foo/bar/baz/~01", Ok("/foo/bar/baz/~01")),
1292            ("/foo/bar/baz/~10", Ok("/foo/bar/baz/~10")),
1293            ("/foo/bar/baz/~11", Ok("/foo/bar/baz/~11")),
1294            ("/foo/bar/baz/~1/~0", Ok("/foo/bar/baz/~1/~0")),
1295            ("missing-slash", Err(ParseError::NoLeadingBackslash)),
1296            (
1297                "/~",
1298                Err(ParseError::InvalidEncoding {
1299                    offset: 0,
1300                    source: InvalidEncodingError { offset: 1 },
1301                }),
1302            ),
1303            (
1304                "/~2",
1305                Err(ParseError::InvalidEncoding {
1306                    offset: 0,
1307                    source: InvalidEncodingError { offset: 1 },
1308                }),
1309            ),
1310            (
1311                "/~a",
1312                Err(ParseError::InvalidEncoding {
1313                    offset: 0,
1314                    source: InvalidEncodingError { offset: 1 },
1315                }),
1316            ),
1317        ];
1318        for (input, expected) in tests {
1319            let actual = Pointer::parse(input).map(Pointer::as_str);
1320            assert_eq!(actual, expected);
1321        }
1322    }
1323
1324    #[test]
1325    fn parse_error_offsets() {
1326        let err = Pointer::parse("/foo/invalid~encoding").unwrap_err();
1327        assert_eq!(err.pointer_offset(), 4);
1328        assert_eq!(err.source_offset(), 8);
1329        assert_eq!(err.complete_offset(), 12);
1330
1331        let err = Pointer::parse("invalid~encoding").unwrap_err();
1332        assert_eq!(err.pointer_offset(), 0);
1333        assert_eq!(err.source_offset(), 0);
1334
1335        let err = Pointer::parse("no-leading/slash").unwrap_err();
1336        assert!(err.source().is_none());
1337    }
1338
1339    #[test]
1340    #[cfg(feature = "std")]
1341    fn parse_error_source() {
1342        use std::error::Error;
1343        let err = Pointer::parse("/foo/invalid~encoding").unwrap_err();
1344        assert!(err.source().is_some());
1345        let source = err.source().unwrap();
1346        assert!(source.is::<InvalidEncodingError>());
1347
1348        let err = Pointer::parse("no-leading/slash").unwrap_err();
1349        assert!(err.source().is_none());
1350    }
1351
1352    #[test]
1353    fn pointerbuf_as_pointer_returns_pointer() {
1354        let ptr = PointerBuf::parse("/foo/bar").unwrap();
1355        assert_eq!(ptr.as_ptr(), ptr);
1356    }
1357
1358    #[test]
1359    fn pointer_buf_clear() {
1360        let mut ptr = PointerBuf::from_tokens(["foo", "bar"]);
1361        ptr.clear();
1362        assert_eq!(ptr, "");
1363    }
1364
1365    #[test]
1366    fn push_pop_back() {
1367        let mut ptr = PointerBuf::default();
1368        assert_eq!(ptr, "", "default, root pointer should equal \"\"");
1369        assert_eq!(ptr.count(), 0, "default pointer should have 0 tokens");
1370
1371        ptr.push_back("foo");
1372        assert_eq!(ptr, "/foo", "pointer should equal \"/foo\" after push_back");
1373
1374        ptr.push_back("bar");
1375        assert_eq!(ptr, "/foo/bar");
1376        ptr.push_back("/baz");
1377        assert_eq!(ptr, "/foo/bar/~1baz");
1378
1379        let mut ptr = PointerBuf::from_tokens(["foo", "bar"]);
1380        assert_eq!(ptr.pop_back(), Some("bar".into()));
1381        assert_eq!(ptr, "/foo", "pointer should equal \"/foo\" after pop_back");
1382        assert_eq!(ptr.pop_back(), Some("foo".into()));
1383        assert_eq!(ptr, "", "pointer should equal \"\" after pop_back");
1384    }
1385
1386    #[test]
1387    fn replace_token() {
1388        let mut ptr = PointerBuf::try_from("/test/token").unwrap();
1389
1390        let res = ptr.replace(0, "new");
1391        assert!(res.is_ok());
1392        assert_eq!(ptr, "/new/token");
1393
1394        let res = ptr.replace(3, "invalid");
1395
1396        assert!(res.is_err());
1397    }
1398
1399    #[test]
1400    fn push_pop_front() {
1401        let mut ptr = PointerBuf::default();
1402        assert_eq!(ptr, "");
1403        assert_eq!(ptr.count(), 0);
1404        ptr.push_front("bar");
1405        assert_eq!(ptr, "/bar");
1406        assert_eq!(ptr.count(), 1);
1407
1408        ptr.push_front("foo");
1409        assert_eq!(ptr, "/foo/bar");
1410        assert_eq!(ptr.count(), 2);
1411
1412        ptr.push_front("too");
1413        assert_eq!(ptr, "/too/foo/bar");
1414        assert_eq!(ptr.count(), 3);
1415
1416        assert_eq!(ptr.pop_front(), Some("too".into()));
1417        assert_eq!(ptr, "/foo/bar");
1418        assert_eq!(ptr.count(), 2);
1419
1420        assert_eq!(ptr.pop_back(), Some("bar".into()));
1421        assert_eq!(ptr, "/foo");
1422        assert_eq!(ptr.count(), 1);
1423        assert_eq!(ptr.pop_front(), Some("foo".into()));
1424        assert_eq!(ptr, "");
1425    }
1426
1427    #[test]
1428    fn display_replace_token_error() {
1429        let err = ReplaceError { index: 3, count: 2 };
1430        assert_eq!(format!("{err}"), "index 3 is out of bounds (2)");
1431    }
1432
1433    #[test]
1434    fn pop_front_works_with_empty_strings() {
1435        {
1436            let mut ptr = PointerBuf::from_tokens(["bar", "", ""]);
1437
1438            assert_eq!(ptr.tokens().count(), 3);
1439            let mut token = ptr.pop_front();
1440            assert_eq!(token, Some(Token::from_encoded_unchecked("bar")));
1441            assert_eq!(ptr.tokens().count(), 2);
1442            token = ptr.pop_front();
1443            assert_eq!(token, Some(Token::from_encoded_unchecked("")));
1444            assert_eq!(ptr.tokens().count(), 1);
1445            token = ptr.pop_front();
1446            assert_eq!(token, Some(Token::from_encoded_unchecked("")));
1447            assert_eq!(ptr.tokens().count(), 0);
1448            assert_eq!(ptr, Pointer::root());
1449        }
1450        {
1451            let mut ptr = PointerBuf::new();
1452            assert_eq!(ptr.tokens().count(), 0);
1453            ptr.push_back("");
1454            assert_eq!(ptr.tokens().count(), 1);
1455            ptr.pop_back();
1456            assert_eq!(ptr.tokens().count(), 0);
1457        }
1458        {
1459            let mut ptr = PointerBuf::new();
1460            let input = ["", "", "", "foo", "", "bar", "baz", ""];
1461            for (idx, &s) in input.iter().enumerate() {
1462                assert_eq!(ptr.tokens().count(), idx);
1463                ptr.push_back(s);
1464            }
1465            assert_eq!(ptr.tokens().count(), input.len());
1466            for (idx, s) in input.iter().enumerate() {
1467                assert_eq!(ptr.tokens().count(), 8 - idx);
1468                assert_eq!(ptr.front().unwrap().decoded(), *s);
1469                assert_eq!(ptr.pop_front().unwrap().decoded(), *s);
1470            }
1471            assert_eq!(ptr.tokens().count(), 0);
1472            assert!(ptr.front().is_none());
1473            assert!(ptr.pop_front().is_none());
1474        }
1475    }
1476
1477    #[test]
1478    fn formatting() {
1479        assert_eq!(PointerBuf::from_tokens(["foo", "bar"]), "/foo/bar");
1480        assert_eq!(
1481            PointerBuf::from_tokens(["~/foo", "~bar", "/baz"]),
1482            "/~0~1foo/~0bar/~1baz"
1483        );
1484        assert_eq!(PointerBuf::from_tokens(["field", "", "baz"]), "/field//baz");
1485        assert_eq!(PointerBuf::default(), "");
1486
1487        let ptr = PointerBuf::from_tokens(["foo", "bar", "baz"]);
1488        assert_eq!(ptr.to_string(), "/foo/bar/baz");
1489    }
1490
1491    #[test]
1492    fn last() {
1493        let ptr = Pointer::from_static("/foo/bar");
1494
1495        assert_eq!(ptr.last(), Some("bar".into()));
1496
1497        let ptr = Pointer::from_static("/foo/bar/-");
1498        assert_eq!(ptr.last(), Some("-".into()));
1499
1500        let ptr = Pointer::from_static("/-");
1501        assert_eq!(ptr.last(), Some("-".into()));
1502
1503        let ptr = Pointer::root();
1504        assert_eq!(ptr.last(), None);
1505
1506        let ptr = Pointer::from_static("/bar");
1507        assert_eq!(ptr.last(), Some("bar".into()));
1508    }
1509
1510    #[test]
1511    fn first() {
1512        let ptr = Pointer::from_static("/foo/bar");
1513        assert_eq!(ptr.first(), Some("foo".into()));
1514
1515        let ptr = Pointer::from_static("/foo/bar/-");
1516        assert_eq!(ptr.first(), Some("foo".into()));
1517
1518        let ptr = Pointer::root();
1519        assert_eq!(ptr.first(), None);
1520    }
1521
1522    #[test]
1523    fn pointerbuf_try_from() {
1524        let ptr = PointerBuf::from_tokens(["foo", "bar", "~/"]);
1525
1526        assert_eq!(PointerBuf::try_from("/foo/bar/~0~1").unwrap(), ptr);
1527        let into: PointerBuf = "/foo/bar/~0~1".try_into().unwrap();
1528        assert_eq!(ptr, into);
1529    }
1530
1531    #[test]
1532    fn default() {
1533        let ptr = PointerBuf::default();
1534        assert_eq!(ptr, "");
1535        assert_eq!(ptr.count(), 0);
1536
1537        let ptr = <&Pointer>::default();
1538        assert_eq!(ptr, "");
1539    }
1540
1541    #[test]
1542    #[cfg(all(feature = "serde", feature = "json"))]
1543    fn to_json_value() {
1544        use serde_json::Value;
1545        let ptr = Pointer::from_static("/foo/bar");
1546        assert_eq!(ptr.to_json_value(), Value::String(String::from("/foo/bar")));
1547    }
1548
1549    #[cfg(all(feature = "resolve", feature = "json"))]
1550    #[test]
1551    fn resolve() {
1552        // full tests in resolve.rs
1553        use serde_json::json;
1554        let value = json!({
1555            "foo": {
1556                "bar": {
1557                    "baz": "qux"
1558                }
1559            }
1560        });
1561        let ptr = Pointer::from_static("/foo/bar/baz");
1562        let resolved = ptr.resolve(&value).unwrap();
1563        assert_eq!(resolved, &json!("qux"));
1564    }
1565
1566    #[cfg(all(feature = "delete", feature = "json"))]
1567    #[test]
1568    fn delete() {
1569        use serde_json::json;
1570        let mut value = json!({
1571            "foo": {
1572                "bar": {
1573                    "baz": "qux"
1574                }
1575            }
1576        });
1577        let ptr = Pointer::from_static("/foo/bar/baz");
1578        let deleted = ptr.delete(&mut value).unwrap();
1579        assert_eq!(deleted, json!("qux"));
1580        assert_eq!(
1581            value,
1582            json!({
1583                "foo": {
1584                    "bar": {}
1585                }
1586            })
1587        );
1588    }
1589
1590    #[cfg(all(feature = "assign", feature = "json"))]
1591    #[test]
1592    fn assign() {
1593        use serde_json::json;
1594        let mut value = json!({});
1595        let ptr = Pointer::from_static("/foo/bar");
1596        let replaced = ptr.assign(&mut value, json!("baz")).unwrap();
1597        assert_eq!(replaced, None);
1598        assert_eq!(
1599            value,
1600            json!({
1601                "foo": {
1602                    "bar": "baz"
1603                }
1604            })
1605        );
1606    }
1607
1608    #[test]
1609    fn get() {
1610        let ptr = Pointer::from_static("/0/1/2/3/4/5/6/7/8/9");
1611        for i in 0..10 {
1612            assert_eq!(ptr.get(i).unwrap().decoded(), i.to_string());
1613        }
1614    }
1615
1616    #[test]
1617    fn replace_token_success() {
1618        let mut ptr = PointerBuf::from_tokens(["foo", "bar", "baz"]);
1619        assert!(ptr.replace(1, "qux").is_ok());
1620        assert_eq!(ptr, PointerBuf::from_tokens(["foo", "qux", "baz"]));
1621
1622        assert!(ptr.replace(0, "corge").is_ok());
1623        assert_eq!(ptr, PointerBuf::from_tokens(["corge", "qux", "baz"]));
1624
1625        assert!(ptr.replace(2, "quux").is_ok());
1626        assert_eq!(ptr, PointerBuf::from_tokens(["corge", "qux", "quux"]));
1627    }
1628
1629    #[test]
1630    fn replace_token_out_of_bounds() {
1631        let mut ptr = PointerBuf::from_tokens(["foo", "bar"]);
1632        assert!(ptr.replace(2, "baz").is_err());
1633        assert_eq!(ptr, PointerBuf::from_tokens(["foo", "bar"])); // Ensure original pointer is unchanged
1634    }
1635
1636    #[test]
1637    fn replace_token_with_empty_string() {
1638        let mut ptr = PointerBuf::from_tokens(["foo", "bar", "baz"]);
1639        assert!(ptr.replace(1, "").is_ok());
1640        assert_eq!(ptr, PointerBuf::from_tokens(["foo", "", "baz"]));
1641    }
1642
1643    #[test]
1644    fn replace_token_in_empty_pointer() {
1645        let mut ptr = PointerBuf::default();
1646        assert!(ptr.replace(0, "foo").is_err());
1647        assert_eq!(ptr, PointerBuf::default()); // Ensure the pointer remains empty
1648    }
1649
1650    #[test]
1651    fn pop_back_works_with_empty_strings() {
1652        {
1653            let mut ptr = PointerBuf::new();
1654            ptr.push_back("");
1655            ptr.push_back("");
1656            ptr.push_back("bar");
1657
1658            assert_eq!(ptr.tokens().count(), 3);
1659            ptr.pop_back();
1660            assert_eq!(ptr.tokens().count(), 2);
1661            ptr.pop_back();
1662            assert_eq!(ptr.tokens().count(), 1);
1663            ptr.pop_back();
1664            assert_eq!(ptr.tokens().count(), 0);
1665            assert_eq!(ptr, PointerBuf::new());
1666        }
1667        {
1668            let mut ptr = PointerBuf::new();
1669            assert_eq!(ptr.tokens().count(), 0);
1670            ptr.push_back("");
1671            assert_eq!(ptr.tokens().count(), 1);
1672            ptr.pop_back();
1673            assert_eq!(ptr.tokens().count(), 0);
1674        }
1675        {
1676            let mut ptr = PointerBuf::new();
1677            let input = ["", "", "", "foo", "", "bar", "baz", ""];
1678            for (idx, &s) in input.iter().enumerate() {
1679                assert_eq!(ptr.tokens().count(), idx);
1680                ptr.push_back(s);
1681            }
1682            assert_eq!(ptr.tokens().count(), input.len());
1683            for (idx, s) in input.iter().enumerate().rev() {
1684                assert_eq!(ptr.tokens().count(), idx + 1);
1685                assert_eq!(ptr.back().unwrap().decoded(), *s);
1686                assert_eq!(ptr.pop_back().unwrap().decoded(), *s);
1687            }
1688            assert_eq!(ptr.tokens().count(), 0);
1689            assert!(ptr.back().is_none());
1690            assert!(ptr.pop_back().is_none());
1691        }
1692    }
1693
1694    #[test]
1695    // `clippy::useless_asref` is tripping here because the `as_ref` is being
1696    // called on the same type (`&Pointer`). This is just to ensure that the
1697    // `as_ref` method is implemented correctly and stays that way.
1698    #[allow(clippy::useless_asref)]
1699    fn pointerbuf_as_ref_returns_pointer() {
1700        let ptr_str = "/foo/bar";
1701        let ptr = Pointer::from_static(ptr_str);
1702        let ptr_buf = ptr.to_buf();
1703        assert_eq!(ptr_buf.as_ref(), ptr);
1704        let r: &Pointer = ptr.as_ref();
1705        assert_eq!(ptr, r);
1706
1707        let s: &str = ptr.as_ref();
1708        assert_eq!(s, ptr_str);
1709
1710        let b: &[u8] = ptr.as_ref();
1711        assert_eq!(b, ptr_str.as_bytes());
1712    }
1713
1714    #[test]
1715    fn from_tokens() {
1716        let ptr = PointerBuf::from_tokens(["foo", "bar", "baz"]);
1717        assert_eq!(ptr, "/foo/bar/baz");
1718    }
1719
1720    #[test]
1721    fn pointer_borrow() {
1722        let ptr = Pointer::from_static("/foo/bar");
1723        let borrowed: &str = ptr.borrow();
1724        assert_eq!(borrowed, "/foo/bar");
1725    }
1726
1727    #[test]
1728    #[cfg(feature = "json")]
1729    fn into_value() {
1730        use serde_json::Value;
1731        let ptr = Pointer::from_static("/foo/bar");
1732        let value: Value = ptr.into();
1733        assert_eq!(value, Value::String("/foo/bar".to_string()));
1734    }
1735
1736    #[test]
1737    fn intersect() {
1738        let base = Pointer::from_static("/foo/bar");
1739        let a = Pointer::from_static("/foo/bar/qux");
1740        let b = Pointer::from_static("/foo/bar");
1741        assert_eq!(a.intersection(b), base);
1742
1743        let base = Pointer::from_static("");
1744        let a = Pointer::from_static("/foo");
1745        let b = Pointer::from_static("/");
1746        assert_eq!(a.intersection(b), base);
1747
1748        let base = Pointer::from_static("");
1749        let a = Pointer::from_static("/fooqux");
1750        let b = Pointer::from_static("/foobar");
1751        assert_eq!(a.intersection(b), base);
1752    }
1753
1754    #[quickcheck]
1755    fn qc_pop_and_push(mut ptr: PointerBuf) -> bool {
1756        let original_ptr = ptr.clone();
1757        let mut tokens = Vec::with_capacity(ptr.count());
1758        while let Some(token) = ptr.pop_back() {
1759            tokens.push(token);
1760        }
1761        if ptr.count() != 0 || !ptr.is_root() || ptr.last().is_some() || ptr.first().is_some() {
1762            return false;
1763        }
1764        for token in tokens.drain(..) {
1765            ptr.push_front(token);
1766        }
1767        if ptr != original_ptr {
1768            return false;
1769        }
1770        while let Some(token) = ptr.pop_front() {
1771            tokens.push(token);
1772        }
1773        if ptr.count() != 0 || !ptr.is_root() || ptr.last().is_some() || ptr.first().is_some() {
1774            return false;
1775        }
1776        for token in tokens {
1777            ptr.push_back(token);
1778        }
1779        ptr == original_ptr
1780    }
1781
1782    #[quickcheck]
1783    fn qc_split(ptr: PointerBuf) -> bool {
1784        if let Some((head, tail)) = ptr.split_front() {
1785            {
1786                let Some(first) = ptr.first() else {
1787                    return false;
1788                };
1789                if first != head {
1790                    return false;
1791                }
1792            }
1793            {
1794                let mut copy = ptr.clone();
1795                copy.pop_front();
1796                if copy != tail {
1797                    return false;
1798                }
1799            }
1800            {
1801                let mut buf = tail.to_buf();
1802                buf.push_front(head.clone());
1803                if buf != ptr {
1804                    return false;
1805                }
1806            }
1807            {
1808                let fmt = alloc::format!("/{}{tail}", head.encoded());
1809                if Pointer::parse(&fmt).unwrap() != ptr {
1810                    return false;
1811                }
1812            }
1813        } else {
1814            return ptr.is_root()
1815                && ptr.count() == 0
1816                && ptr.last().is_none()
1817                && ptr.first().is_none();
1818        }
1819        if let Some((head, tail)) = ptr.split_back() {
1820            {
1821                let Some(last) = ptr.last() else {
1822                    return false;
1823                };
1824                if last != tail {
1825                    return false;
1826                }
1827            }
1828            {
1829                let mut copy = ptr.clone();
1830                copy.pop_back();
1831                if copy != head {
1832                    return false;
1833                }
1834            }
1835            {
1836                let mut buf = head.to_buf();
1837                buf.push_back(tail.clone());
1838                if buf != ptr {
1839                    return false;
1840                }
1841            }
1842            {
1843                let fmt = alloc::format!("{head}/{}", tail.encoded());
1844                if Pointer::parse(&fmt).unwrap() != ptr {
1845                    return false;
1846                }
1847            }
1848            if Some(head) != ptr.parent() {
1849                return false;
1850            }
1851        } else {
1852            return ptr.is_root()
1853                && ptr.count() == 0
1854                && ptr.last().is_none()
1855                && ptr.first().is_none();
1856        }
1857        true
1858    }
1859
1860    #[quickcheck]
1861    fn qc_from_tokens(tokens: Vec<String>) -> bool {
1862        let buf = PointerBuf::from_tokens(&tokens);
1863        let reconstructed: Vec<_> = buf.tokens().collect();
1864        reconstructed
1865            .into_iter()
1866            .zip(tokens)
1867            .all(|(a, b)| a.decoded() == b)
1868    }
1869
1870    #[quickcheck]
1871    fn qc_intersection(base: PointerBuf, suffix_0: PointerBuf, suffix_1: PointerBuf) -> TestResult {
1872        if suffix_0.first() == suffix_1.first() {
1873            // base must be the true intersection
1874            return TestResult::discard();
1875        }
1876        let mut a = base.clone();
1877        a.append(&suffix_0);
1878        let mut b = base.clone();
1879        b.append(&suffix_1);
1880        let isect = a.intersection(&b);
1881        TestResult::from_bool(isect == base)
1882    }
1883
1884    #[cfg(all(feature = "json", feature = "std", feature = "serde"))]
1885    #[test]
1886    fn serde() {
1887        use serde::Deserialize;
1888        let ptr = PointerBuf::from_tokens(["foo", "bar"]);
1889        let json = serde_json::to_string(&ptr).unwrap();
1890        assert_eq!(json, "\"/foo/bar\"");
1891        let deserialized: PointerBuf = serde_json::from_str(&json).unwrap();
1892        assert_eq!(deserialized, ptr);
1893
1894        let ptr = Pointer::from_static("/foo/bar");
1895        let json = serde_json::to_string(&ptr).unwrap();
1896        assert_eq!(json, "\"/foo/bar\"");
1897
1898        let mut de = serde_json::Deserializer::from_str("\"/foo/bar\"");
1899        let p = <&Pointer>::deserialize(&mut de).unwrap();
1900        assert_eq!(p, ptr);
1901        let s = serde_json::to_string(p).unwrap();
1902        assert_eq!(json, s);
1903
1904        let invalid = serde_json::from_str::<&Pointer>("\"foo/bar\"");
1905        assert!(invalid.is_err());
1906        assert_eq!(
1907            invalid.unwrap_err().to_string(),
1908            "failed to parse json pointer\n\ncaused by:\njson pointer is malformed as it does not start with a backslash ('/') at line 1 column 9"
1909        );
1910    }
1911
1912    #[test]
1913    fn to_owned() {
1914        let ptr = Pointer::from_static("/bread/crumbs");
1915        let buf = ptr.to_owned();
1916        assert_eq!(buf, "/bread/crumbs");
1917    }
1918
1919    #[test]
1920    fn concat() {
1921        let ptr = Pointer::from_static("/foo");
1922        let barbaz = Pointer::from_static("/bar/baz");
1923        assert_eq!(ptr.concat(barbaz), "/foo/bar/baz");
1924    }
1925
1926    #[test]
1927    fn with_leading_token() {
1928        let ptr = Pointer::from_static("/bar");
1929        let foobar = ptr.with_leading_token("foo");
1930        assert_eq!(foobar, "/foo/bar");
1931    }
1932
1933    #[test]
1934    fn with_trailing_token() {
1935        let ptr = Pointer::from_static("/foo");
1936        let foobar = ptr.with_trailing_token("bar");
1937        assert_eq!(foobar, "/foo/bar");
1938    }
1939
1940    #[test]
1941    fn len() {
1942        let ptr = Pointer::from_static("/foo/bar");
1943        assert_eq!(ptr.len(), 8);
1944        let mut ptr = ptr.to_buf();
1945        ptr.push_back("~");
1946        assert_eq!(ptr.len(), 11);
1947    }
1948
1949    #[test]
1950    fn is_empty() {
1951        assert!(Pointer::from_static("").is_empty());
1952        assert!(!Pointer::from_static("/").is_empty());
1953    }
1954
1955    #[test]
1956    #[allow(clippy::cmp_owned, unused_must_use)]
1957    fn partial_eq() {
1958        let ptr_string = String::from("/bread/crumbs");
1959        let ptr_str = "/bread/crumbs";
1960        let ptr = Pointer::from_static(ptr_str);
1961        let ptr_buf = ptr.to_buf();
1962        <&Pointer as PartialEq<&Pointer>>::eq(&ptr, &ptr);
1963        <Pointer as PartialEq<&str>>::eq(ptr, &ptr_str);
1964        <&Pointer as PartialEq<String>>::eq(&ptr, &ptr_string);
1965        <Pointer as PartialEq<String>>::eq(ptr, &ptr_string);
1966        <Pointer as PartialEq<PointerBuf>>::eq(ptr, &ptr_buf);
1967        <&str as PartialEq<Pointer>>::eq(&ptr_str, ptr);
1968        <String as PartialEq<Pointer>>::eq(&ptr_string, ptr);
1969        <str as PartialEq<Pointer>>::eq(ptr_str, ptr);
1970        <PointerBuf as PartialEq<str>>::eq(&ptr_buf, ptr_str);
1971        <PointerBuf as PartialEq<PointerBuf>>::eq(&ptr_buf, &ptr_buf);
1972        <PointerBuf as PartialEq<Pointer>>::eq(&ptr_buf, ptr);
1973        <Pointer as PartialEq<PointerBuf>>::eq(ptr, &ptr_buf);
1974        <PointerBuf as PartialEq<&Pointer>>::eq(&ptr_buf, &ptr);
1975        <PointerBuf as PartialEq<&str>>::eq(&ptr_buf, &ptr_str);
1976        <PointerBuf as PartialEq<String>>::eq(&ptr_buf, &ptr_string);
1977        <&Pointer as PartialEq<PointerBuf>>::eq(&ptr, &ptr_buf);
1978        <str as PartialEq<PointerBuf>>::eq(ptr_str, &ptr_buf);
1979        <&str as PartialEq<PointerBuf>>::eq(&ptr_str, &ptr_buf);
1980        <String as PartialEq<PointerBuf>>::eq(&ptr_string, &ptr_buf);
1981    }
1982
1983    #[test]
1984    fn partial_ord() {
1985        let a_str = "/foo/bar";
1986        let a_string = a_str.to_string();
1987        let a_ptr = Pointer::from_static(a_str);
1988        let a_buf = a_ptr.to_buf();
1989        let b_str = "/foo/bar";
1990        let b_string = b_str.to_string();
1991        let b_ptr = Pointer::from_static(b_str);
1992        let b_buf = b_ptr.to_buf();
1993        let c_str = "/foo/bar/baz";
1994        let c_string = c_str.to_string();
1995        let c_ptr = Pointer::from_static(c_str);
1996        let c_buf = c_ptr.to_buf();
1997
1998        assert!(<Pointer as PartialOrd<PointerBuf>>::lt(a_ptr, &c_buf));
1999        assert!(<PointerBuf as PartialOrd<Pointer>>::lt(&a_buf, c_ptr));
2000        assert!(<String as PartialOrd<Pointer>>::lt(&a_string, c_ptr));
2001        assert!(<str as PartialOrd<Pointer>>::lt(a_str, c_ptr));
2002        assert!(<str as PartialOrd<PointerBuf>>::lt(a_str, &c_buf));
2003        assert!(<&str as PartialOrd<Pointer>>::lt(&a_str, c_ptr));
2004        assert!(<&str as PartialOrd<PointerBuf>>::lt(&a_str, &c_buf));
2005        assert!(<&Pointer as PartialOrd<PointerBuf>>::lt(&a_ptr, &c_buf));
2006        assert!(<&Pointer as PartialOrd<&str>>::lt(&b_ptr, &c_str));
2007        assert!(<Pointer as PartialOrd<String>>::lt(a_ptr, &c_string));
2008        assert!(<PointerBuf as PartialOrd<&str>>::lt(&a_buf, &c_str));
2009        assert!(<PointerBuf as PartialOrd<String>>::lt(&a_buf, &c_string));
2010        assert!(a_ptr < c_buf);
2011        assert!(c_buf > a_ptr);
2012        assert!(a_buf < c_ptr);
2013        assert!(a_ptr < c_buf);
2014        assert!(a_ptr < c_ptr);
2015        assert!(a_ptr <= c_ptr);
2016        assert!(c_ptr > a_ptr);
2017        assert!(c_ptr >= a_ptr);
2018        assert!(a_ptr == b_ptr);
2019        assert!(a_ptr <= b_ptr);
2020        assert!(a_ptr >= b_ptr);
2021        assert!(a_string < c_buf);
2022        assert!(a_string <= c_buf);
2023        assert!(c_string > a_buf);
2024        assert!(c_string >= a_buf);
2025        assert!(a_string == b_buf);
2026        assert!(a_ptr < c_buf);
2027        assert!(a_ptr <= c_buf);
2028        assert!(c_ptr > a_buf);
2029        assert!(c_ptr >= a_buf);
2030        assert!(a_ptr == b_buf);
2031        assert!(a_ptr <= b_buf);
2032        assert!(a_ptr >= b_buf);
2033        assert!(a_ptr < c_buf);
2034        assert!(c_ptr > b_string);
2035        // couldn't inline this
2036        #[allow(clippy::nonminimal_bool)]
2037        let not = !(a_ptr > c_buf);
2038        assert!(not);
2039    }
2040
2041    #[test]
2042    fn intersection() {
2043        struct Test {
2044            base: &'static str,
2045            a_suffix: &'static str,
2046            b_suffix: &'static str,
2047        }
2048
2049        let tests = [
2050            Test {
2051                base: "",
2052                a_suffix: "/",
2053                b_suffix: "/a/b/c",
2054            },
2055            Test {
2056                base: "",
2057                a_suffix: "",
2058                b_suffix: "",
2059            },
2060            Test {
2061                base: "/a",
2062                a_suffix: "/",
2063                b_suffix: "/suffix",
2064            },
2065            Test {
2066                base: "/a",
2067                a_suffix: "/suffix",
2068                b_suffix: "",
2069            },
2070            Test {
2071                base: "/¦\\>‶“lv\u{eedd}\u{8a}Y\n\u{99}𘐷vT\n\u{4}Hª\\ 嗱\\Yl6Y`\"1\u{6dd}\u{17}\0\u{10}ዄ8\"Z닍6i)V;\u{6be4c}\u{b}\u{59836}`\u{1e}㑍§~05\u{1d}\u{8a}[뵔\u{437c3}j\u{f326}\";*\u{c}*U\u{1b}\u{8a}I\u{4}묁",
2072                a_suffix: "/Y\u{2064}",
2073                b_suffix: "",
2074            }
2075        ];
2076
2077        for Test {
2078            base,
2079            a_suffix,
2080            b_suffix,
2081        } in tests
2082        {
2083            let base = PointerBuf::parse(base).expect(&format!("failed to parse ${base}"));
2084            let mut a = base.clone();
2085            let mut b = base.clone();
2086            a.append(PointerBuf::parse(a_suffix).unwrap());
2087            b.append(PointerBuf::parse(b_suffix).unwrap());
2088            let intersection = a.intersection(&b);
2089            assert_eq!(intersection, base);
2090        }
2091    }
2092    #[test]
2093    fn parse_error_display() {
2094        assert_eq!(
2095            ParseError::NoLeadingBackslash.to_string(),
2096            "json pointer is malformed as it does not start with a backslash ('/')"
2097        );
2098    }
2099
2100    #[test]
2101    fn into_iter() {
2102        use core::iter::IntoIterator;
2103
2104        let ptr = PointerBuf::from_tokens(["foo", "bar", "baz"]);
2105        let tokens: Vec<Token> = ptr.into_iter().collect();
2106        let from_tokens = PointerBuf::from_tokens(tokens);
2107        assert_eq!(ptr, from_tokens);
2108
2109        let ptr = Pointer::from_static("/foo/bar/baz");
2110        let tokens: Vec<_> = ptr.into_iter().collect();
2111        assert_eq!(ptr, PointerBuf::from_tokens(tokens));
2112    }
2113
2114    #[test]
2115    fn from_str() {
2116        let p = PointerBuf::from_str("/foo/bar").unwrap();
2117        assert_eq!(p, "/foo/bar");
2118    }
2119
2120    #[test]
2121    fn from_token() {
2122        let p = PointerBuf::from(Token::new("foo"));
2123        assert_eq!(p, "/foo");
2124    }
2125
2126    #[test]
2127    fn from_usize() {
2128        let p = PointerBuf::from(0);
2129        assert_eq!(p, "/0");
2130    }
2131
2132    #[test]
2133    fn borrow() {
2134        let ptr = PointerBuf::from_tokens(["foo", "bar"]);
2135        let borrowed: &Pointer = ptr.borrow();
2136        assert_eq!(borrowed, "/foo/bar");
2137    }
2138}