///|
pub fn quote_string(value : String) -> String {
  let buf = StringBuilder(size_hint=value.length() + 2)
  buf.write_char('"')
  for c in value.iter() {
    if c == '"' || c == '\\' {
      buf.write_char('\\')
      buf.write_char(c)
    } else if c == '\r' || c == '\n' {
      buf.write_char('_')
    } else {
      buf.write_char(c)
    }
  }
  buf.write_char('"')
  buf.to_string()
}

///|
pub fn encode_param_value(value : String) -> String {
  if needs_quoted(value) {
    quote_string(value)
  } else {
    value
  }
}

///|
pub fn encode_ext_value(
  value : String,
  charset? : String = "UTF-8",
  language? : String = "",
) -> String {
  let buf = StringBuilder(
    size_hint=value.length() * 3 + charset.length() + language.length() + 2,
  )
  buf.write_string(charset)
  buf.write_char('\'')
  buf.write_string(language)
  buf.write_char('\'')
  let bytes = @utf8.encode(value)
  for byte in bytes.iter() {
    let c = byte.to_char()
    if is_attr_char(c) {
      buf.write_char(c)
    } else {
      append_percent_hex(buf, byte.to_int())
    }
  }
  buf.to_string()
}

///|
pub fn serialize_param(param : Parameter) -> String {
  let name = if param.extended { param.name + "*" } else { param.name }
  if param.extended {
    name + "=" + param.raw_value
  } else {
    name + "=" + encode_param_value(param.value)
  }
}

///|
pub fn serialize(disposition : Disposition) -> String {
  let buf = StringBuilder(size_hint=64)
  buf.write_string(disposition.kind.to_token())
  for p in disposition.params {
    buf.write_string("; ")
    buf.write_string(serialize_param(p))
  }
  buf.to_string()
}