///|
/// HTTP 请求方法。
///
/// 这里独立定义一份枚举,而不是直接复用 `moonbitlang/async/http` 的 `RequestMethod`,
/// 是为了让 config / headers / merge / url 这几个包保持纯逻辑、不依赖 async 运行时;
/// 两者之间的转换被隔离在 transport 包里。
///
/// 派生 `Hash` 是必须的:`Config.method_headers` 用 `Map[Method, Headers]` 存
/// 「按方法分层的默认头」,而 Map 的 key 需要 `Hash + Eq`。
pub(all) enum Method {
  Get
  Head
  Post
  Put
  Delete
  Connect
  Options
  Trace
  Patch
} derive(Eq, Hash, Debug)

///|
pub extend Method with Eq::{equal, not_equal}

///|
pub extend Method with Hash::{hash, hash_combine}

///|
pub extend Method with @debug.Debug::{to_repr}

///|
/// 请求行里使用的大写方法名,例如 `GET`。用于拼出可读的请求行与日志。
pub fn Method::to_string(self : Method) -> String {
  match self {
    Get => "GET"
    Head => "HEAD"
    Post => "POST"
    Put => "PUT"
    Delete => "DELETE"
    Connect => "CONNECT"
    Options => "OPTIONS"
    Trace => "TRACE"
    Patch => "PATCH"
  }
}

///|
/// 解析方法名,大小写不敏感;无法识别时返回 `None`。
///
/// 不在这里抛错:调用方(传输层或用户代码)才知道该报什么错,
/// 保持这个纯函数只有「找到/没找到」两种结果。
pub fn Method::parse(name : StringView) -> Method? {
  for meth in [Get, Head, Post, Put, Delete, Connect, Options, Trace, Patch] {
    // compare_ignore_ascii_case 比先大小写折叠再比较更直接,也少一次分配。
    if name.compare_ignore_ascii_case(meth.to_string()) == 0 {
      return Some(meth)
    }
  }
  None
}