1use parser::{parse, ParseError};
2use std::fmt::{Display, Formatter};
3use std::fmt::Result as FmtResult;
4use std::fmt::Write;
5use std::marker::PhantomData;
6use std::str::FromStr;
7
8use crate::parser;
9
10#[derive(Clone, Debug, Eq, PartialEq)]
15pub struct JsonPointer<S: AsRef<str>, C: AsRef<[S]>> {
16 pub(crate) ref_toks: C,
17 _phantom: PhantomData<S>,
18}
19
20impl<S: AsRef<str>, C: AsRef<[S]>> JsonPointer<S, C> {
21 pub fn new(ref_toks: C) -> JsonPointer<S, C> {
23 JsonPointer {
24 ref_toks,
25 _phantom: PhantomData,
26 }
27 }
28
29 pub fn uri_fragment(&self) -> String {
32 fn legal_fragment_byte(b: u8) -> bool {
33 matches!(b, 0x21 | 0x24 | 0x26..=0x3b | 0x3d | 0x3f..=0x5a | 0x5f | 0x61..=0x7a)
34 }
35
36 let mut s = "#".to_string();
37 for part in self.ref_toks.as_ref().iter() {
38 s += "/";
39 for b in part.as_ref().bytes() {
40 if legal_fragment_byte(b) {
41 s.push(b as char)
42 } else {
43 write!(s, "%{:02x}", b).unwrap()
44 }
45 }
46 }
47 s
48 }
49}
50
51impl<S: AsRef<str>> JsonPointer<S, Vec<S>> {
52 pub fn push(&mut self, component: S) {
54 self.ref_toks.push(component);
55 }
56
57 pub fn pop(&mut self) -> Option<S> {
59 self.ref_toks.pop()
60 }
61}
62
63impl<S: AsRef<str>, C: AsRef<[S]>> Display for JsonPointer<S, C> {
64 fn fmt(&self, fmt: &mut Formatter) -> FmtResult {
65 for part in self.ref_toks.as_ref().iter() {
66 write!(fmt, "/")?;
67 for ch in part.as_ref().chars() {
68 match ch {
69 '~' => write!(fmt, "~0"),
70 '/' => write!(fmt, "~1"),
71 c => write!(fmt, "{}", c),
72 }?
73 }
74 }
75 Ok(())
76 }
77}
78
79impl FromStr for JsonPointer<String, Vec<String>> {
80 type Err = ParseError;
81 fn from_str(s: &str) -> Result<Self, Self::Err> {
82 parse(s)
83 }
84}
85
86#[derive(Clone, Debug, PartialEq)]
88pub enum IndexError {
89 NoSuchKey(String),
91 NotIndexable,
93 OutOfBounds(usize),
95}