///|
pub enum JsonValue {
  JNull
  JBool(Bool)
  JNumber(String)
  JString(String)
  JArray(Array[JsonValue])
  JObject(Array[JsonPair])
} derive(Debug, Eq)

///|
pub struct JsonPair {
  key : String
  value : JsonValue
} derive(Debug, Eq)

///|
pub struct JsonParseResult {
  value : JsonValue?
  diagnostics : DiagnosticBag
} derive(Debug, Eq)

///|
pub fn JsonPair::new(key : String, value : JsonValue) -> JsonPair {
  { key, value }
}

///|
pub fn JsonValue::string(value : String) -> JsonValue {
  JString(value)
}

///|
pub fn JsonValue::object_field(self : JsonValue, key : String) -> JsonValue? {
  match self {
    JObject(fields) => {
      for field in fields {
        if field.key == key {
          return Some(field.value)
        }
      }
      None
    }
    _ => None
  }
}

///|
pub fn JsonValue::string_value(self : JsonValue) -> String? {
  match self {
    JString(value) => Some(value)
    _ => None
  }
}

///|
pub fn JsonValue::number_value(self : JsonValue) -> String? {
  match self {
    JNumber(value) => Some(value)
    _ => None
  }
}

///|
pub fn JsonValue::array_value(self : JsonValue) -> Array[JsonValue]? {
  match self {
    JArray(value) => Some(value)
    _ => None
  }
}

///|
pub fn JsonValue::object_value(self : JsonValue) -> Array[JsonPair]? {
  match self {
    JObject(value) => Some(value)
    _ => None
  }
}