///|
/// JSON 文档内的路径片段。
pub(all) enum PathSegment {
  /// 对象成员,携带键名。
  Key(String)
  /// 数组元素,携带下标。
  Index(Int)
} derive(Eq, Debug, ToJson)

///|
/// 文档内某个值的位置。根路径为空。
///
/// 路径只描述结构位置,不携带任何“该值已经合法”的承诺。
pub(all) struct Path {
  segments : Array[PathSegment]
} derive(Eq, Debug, ToJson)

///|
/// 根路径(空路径)。
pub fn Path::root() -> Path {
  { segments: [] }
}

///|
/// 追加一个对象键片段。
pub fn Path::child_key(self : Path, key : String) -> Path {
  let segments = self.segments.copy()
  segments.push(PathSegment::Key(key))
  { segments, }
}

///|
/// 追加一个数组下标片段。
pub fn Path::child_index(self : Path, index : Int) -> Path {
  let segments = self.segments.copy()
  segments.push(PathSegment::Index(index))
  { segments, }
}

///|
/// 路径深度。
pub fn Path::length(self : Path) -> Int {
  self.segments.length()
}

///|
/// 是否为空路径(文档根)。
pub fn Path::is_root(self : Path) -> Bool {
  self.segments.is_empty()
}

///|
/// 渲染为 `$`、`$.city`、`$.items[0].name` 形式,便于日志与测试断言。
pub fn Path::to_string(self : Path) -> String {
  let out = StringBuilder()
  out.write_string("$")
  for segment in self.segments {
    match segment {
      PathSegment::Key(key) => {
        out.write_string(".")
        out.write_string(key)
      }
      PathSegment::Index(index) => {
        out.write_string("[")
        out.write_string(index.to_string())
        out.write_string("]")
      }
    }
  }
  out.to_string()
}