///|
priv enum PathSegment {
Key(String)
Index(Int)
}
///|
let max_path_length = 16384
///|
let max_path_segments = 256
///|
fn format_path(segments : Array[PathSegment], format : PathFormat) -> String {
match format {
JsonPointer => format_json_pointer(segments)
JavaScript => format_javascript_path(segments)
}
}
///|
fn checked_path(
segments : Array[PathSegment],
format : PathFormat,
) -> String raise FlattenJsonError {
guard segments.length() <= max_path_segments else {
raise PathDepthExceeded(segments.length())
}
let mut raw_length = 0
for segment in segments {
match segment {
Key(key) => {
raw_length = raw_length + key.length()
guard raw_length <= max_path_length else {
raise PathLengthExceeded(raw_length)
}
}
Index(_) => ()
}
}
let path = format_path(segments, format)
guard path.length() <= max_path_length else {
raise PathLengthExceeded(path.length())
}
path
}
///|
fn parse_path(
path : String,
format : PathFormat,
) -> Array[PathSegment] raise FlattenJsonError {
guard path.length() <= max_path_length else {
raise PathLengthExceeded(path.length())
}
let segments = match format {
JsonPointer => parse_json_pointer(path)
JavaScript => parse_javascript_path(path)
}
guard segments.length() <= max_path_segments else {
raise PathDepthExceeded(segments.length())
}
segments
}
///|
fn is_array_index_token(value : String) -> Bool {
let chars = value.iter().to_array()
!chars.is_empty() &&
chars.all(char => char.is_ascii_digit()) &&
(chars.length() == 1 || chars[0] != '0')
}