///|
/// One segment in an RFC 6901 JSON Pointer.
pub(all) enum PathSegment {
Property(String)
Index(Int)
} derive(Eq, Debug)
///|
/// An immutable path into either a schema or an instance document.
pub(all) struct JsonPointer {
segments : Array[PathSegment]
} derive(Eq, Debug)
///|
pub fn JsonPointer::root() -> JsonPointer {
{ segments: [], }
}
///|
pub fn JsonPointer::property(self : JsonPointer, name : String) -> JsonPointer {
let next = self.segments.copy()
next.push(Property(name))
{ segments: next, }
}
///|
pub fn JsonPointer::index(self : JsonPointer, index : Int) -> JsonPointer {
let next = self.segments.copy()
next.push(Index(index))
{ segments: next, }
}
///|
pub fn JsonPointer::parent(self : JsonPointer) -> JsonPointer? {
if self.segments.is_empty() {
None
} else {
let next : Array[PathSegment] = []
for index, segment in self.segments {
if index + 1 < self.segments.length() {
next.push(segment)
}
}
Some({ segments: next, })
}
}
///|
pub fn JsonPointer::depth(self : JsonPointer) -> Int {
self.segments.length()
}
///|
pub fn JsonPointer::is_root(self : JsonPointer) -> Bool {
self.segments.is_empty()
}
///|
fn pointer_escape(text : String) -> String {
let output = StringBuilder()
for character in text {
match character {
'~' => output.write_string("~0")
'/' => output.write_string("~1")
_ => output.write_char(character)
}
}
output.to_string()
}
///|
pub fn JsonPointer::to_string(self : JsonPointer) -> String {
let output = StringBuilder()
for segment in self.segments {
output.write_char('/')
match segment {
Property(name) => output.write_string(pointer_escape(name))
Index(index) => output.write_string(index.to_string())
}
}
output.to_string()
}
///|
pub fn JsonPointer::display(self : JsonPointer) -> String {
if self.is_root() {
""
} else {
self.to_string()
}
}
///|
pub fn JsonPointer::segments_copy(self : JsonPointer) -> Array[PathSegment] {
self.segments.copy()
}
///|
pub fn JsonPointer::append(
self : JsonPointer,
suffix : JsonPointer,
) -> JsonPointer {
let next = self.segments.copy()
for segment in suffix.segments {
next.push(segment)
}
{ segments: next, }
}
///|
pub fn JsonPointer::last_property(self : JsonPointer) -> String? {
if self.segments.is_empty() {
None
} else {
match self.segments[self.segments.length() - 1] {
Property(name) => Some(name)
Index(_) => None
}
}
}
///|
pub fn JsonPointer::last_index(self : JsonPointer) -> Int? {
if self.segments.is_empty() {
None
} else {
match self.segments[self.segments.length() - 1] {
Index(index) => Some(index)
Property(_) => None
}
}
}