1use std::{
4 cell::OnceCell,
5 fmt::{self, Display},
6};
7
8#[derive(Copy, Clone)]
11pub enum Path<'a> {
12 Root,
14 Seq {
16 parent: &'a Path<'a>,
18 index: usize,
20 },
21 Map {
23 parent: &'a Path<'a>,
25 key: &'a str,
27 },
28 Alias {
30 parent: &'a Path<'a>,
32 },
33 Unknown {
35 parent: &'a Path<'a>,
37 },
38}
39
40impl Display for Path<'_> {
41 fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
42 struct Parent<'a>(&'a Path<'a>);
43
44 impl Display for Parent<'_> {
45 fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
46 match self.0 {
47 Path::Root => Ok(()),
48 path => write!(formatter, "{}.", path),
49 }
50 }
51 }
52
53 match self {
54 Path::Root => formatter.write_str("."),
55 Path::Seq { parent, index } => write!(formatter, "{}[{}]", parent, index),
56 Path::Map { parent, key } => write!(formatter, "{}{}", Parent(parent), key),
57 Path::Alias { parent } => write!(formatter, "{}", parent),
58 Path::Unknown { parent } => write!(formatter, "{}?", Parent(parent)),
59 }
60 }
61}
62
63impl<'a> Path<'a> {
64 pub fn to_owned_path(&self) -> OwnedPath {
66 match self {
67 Path::Root => OwnedPath::Root,
68 Path::Seq { parent, index } => OwnedPath::Seq {
69 parent: Box::new(parent.to_owned_path()),
70 index: *index,
71 borrowed: OnceCell::new(),
72 },
73 Path::Map { parent, key } => OwnedPath::Map {
74 parent: Box::new(parent.to_owned_path()),
75 key: key.to_string(),
76 borrowed: OnceCell::new(),
77 },
78 Path::Alias { parent } => OwnedPath::Alias {
79 parent: Box::new(parent.to_owned_path()),
80 borrowed: OnceCell::new(),
81 },
82 Path::Unknown { parent } => OwnedPath::Unknown {
83 parent: Box::new(parent.to_owned_path()),
84 borrowed: OnceCell::new(),
85 },
86 }
87 }
88}
89
90pub enum OwnedPath {
92 Root,
94 Seq {
96 parent: Box<OwnedPath>,
98 index: usize,
100 borrowed: OnceCell<Path<'static>>,
102 },
103 Map {
105 parent: Box<OwnedPath>,
107 key: String,
109 borrowed: OnceCell<Path<'static>>,
111 },
112 Alias {
114 parent: Box<OwnedPath>,
116 borrowed: OnceCell<Path<'static>>,
118 },
119 Unknown {
121 parent: Box<OwnedPath>,
123 borrowed: OnceCell<Path<'static>>,
125 },
126}
127
128impl<'a> OwnedPath {
129 pub fn as_path(&'a self) -> &'a Path<'a> {
131 static ROOT: Path<'static> = Path::Root;
132
133 match self {
134 OwnedPath::Root => &ROOT,
135 OwnedPath::Seq {
136 parent,
137 index,
138 borrowed,
139 } => {
140 let borrowed = borrowed.get_or_init(|| {
141 let parent = parent.as_path();
142 unsafe {
144 std::mem::transmute(Path::Seq {
145 parent,
146 index: *index,
147 })
148 }
149 });
150 borrowed
151 }
152 OwnedPath::Map {
153 parent,
154 key,
155 borrowed,
156 } => {
157 let borrowed = borrowed.get_or_init(|| {
158 let parent = parent.as_path();
159 unsafe {
161 std::mem::transmute(Path::Map {
162 parent,
163 key: key.as_ref(),
164 })
165 }
166 });
167 borrowed
168 }
169 OwnedPath::Alias { parent, borrowed } => {
170 let borrowed = borrowed.get_or_init(|| {
171 let parent = parent.as_path();
172 unsafe { std::mem::transmute(Path::Alias { parent }) }
174 });
175 borrowed
176 }
177 OwnedPath::Unknown { parent, borrowed } => {
178 let borrowed = borrowed.get_or_init(|| {
179 let parent = parent.as_path();
180 unsafe { std::mem::transmute(Path::Unknown { parent }) }
182 });
183 borrowed
184 }
185 }
186 }
187}