///|
fn escape_pointer_key(key : String) -> String {
key.replace_all(old="~", new="~0").replace_all(old="/", new="~1")
}
///|
fn format_json_pointer(segments : Array[PathSegment]) -> String {
let output = StringBuilder()
for segment in segments {
output.write_char('/')
match segment {
Key(key) => output.write_string(escape_pointer_key(key))
Index(index) => output.write_object(index)
}
}
output.to_string()
}
///|
fn parse_json_pointer(
path : String,
) -> Array[PathSegment] raise FlattenJsonError {
if path == "" {
return []
}
guard path.has_prefix("/") else { raise InvalidPath(path) }
let segments : Array[PathSegment] = []
for token in path[1:].split("/") {
let value = unescape_pointer_key(token.to_owned(), path)
if is_array_index_token(value) {
let index = try @string.parse_int(value) catch {
_ => raise InvalidPath(path)
} noraise {
value => value
}
segments.push(Index(index))
} else {
segments.push(Key(value))
}
}
segments
}
///|
fn unescape_pointer_key(
token : String,
path : String,
) -> String raise FlattenJsonError {
let chars = token.iter().to_array()
let output = StringBuilder()
let mut index = 0
while index < chars.length() {
if chars[index] == '~' {
guard index + 1 < chars.length() else { raise InvalidPath(path) }
match chars[index + 1] {
'0' => output.write_char('~')
'1' => output.write_char('/')
_ => raise InvalidPath(path)
}
index = index + 2
} else {
output.write_char(chars[index])
index = index + 1
}
}
output.to_string()
}