// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.

export interface DBEntry {
  source: string;
  compressible?: boolean;
  charset?: string;
  extensions?: string[];
}

export function consumeToken(v: string): [token: string, rest: string] {
  const notPos = indexOf(v, isNotTokenChar);
  if (notPos === -1) {
    return [v, ""];
  }
  if (notPos === 0) {
    return ["", v];
  }
  return [v.slice(0, notPos), v.slice(notPos)];
}

export function consumeValue(v: string): [value: string, rest: string] {
  if (!v) {
    return ["", v];
  }
  if (v[0] !== `"`) {
    return consumeToken(v);
  }
  let value = "";
  for (let i = 1; i < v.length; i++) {
    const r = v[i];
    if (r === `"`) {
      return [value, v.slice(i + 1)];
    }
    const next = v[i + 1];
    if (r === "\\" && typeof next === "string" && isTSpecial(next)) {
      value += next;
      i++;
      continue;
    }
    if (r === "\r" || r === "\n") {
      return ["", v];
    }
    value += v[i];
  }
  return ["", v];
}

export function consumeMediaParam(
  v: string,
): [key: string, value: string, rest: string] {
  let rest = v.trimStart();
  if (!rest.startsWith(";")) {
    return ["", "", v];
  }
  rest = rest.slice(1);
  rest = rest.trimStart();
  let param: string;
  [param, rest] = consumeToken(rest);
  param = param.toLowerCase();
  if (!param) {
    return ["", "", v];
  }
  rest = rest.slice(1);
  rest = rest.trimStart();
  const [value, rest2] = consumeValue(rest);
  if (value === "" && rest2 === rest) {
    return ["", "", v];
  }
  rest = rest2;
  return [param, value, rest];
}

export function decode2331Encoding(v: string): string | undefined {
  const sv = v.split(`'`, 3);
  if (sv.length !== 3) {
    return undefined;
  }
  const [sv0, , sv2] = sv as [string, string, string];
  const charset = sv0.toLowerCase();
  if (!charset) {
    return undefined;
  }
  if (charset !== "us-ascii" && charset !== "utf-8") {
    return undefined;
  }
  const encv = decodeURI(sv2);
  if (!encv) {
    return undefined;
  }
  return encv;
}

function indexOf<T>(s: Iterable<T>, fn: (s: T) => boolean): number {
  let i = -1;
  for (const v of s) {
    i++;
    if (fn(v)) {
      return i;
    }
  }
  return -1;
}

export function isIterator<T>(obj: unknown): obj is Iterable<T> {
  if (obj === null || obj === undefined) {
    return false;
  }
  // deno-lint-ignore no-explicit-any
  return typeof (obj as any)[Symbol.iterator] === "function";
}

export function isToken(s: string): boolean {
  if (!s) {
    return false;
  }
  return indexOf(s, isNotTokenChar) < 0;
}

function isNotTokenChar(r: string): boolean {
  return !isTokenChar(r);
}

function isTokenChar(r: string): boolean {
  const code = r.charCodeAt(0);
  return code > 0x20 && code < 0x7f && !isTSpecial(r);
}

export function isTSpecial(r: string): boolean {
  return r[0] ? `()<>@,;:\\"/[]?=`.includes(r[0]) : false;
}

const CHAR_CODE_SPACE = " ".charCodeAt(0);
const CHAR_CODE_TILDE = "~".charCodeAt(0);

export function needsEncoding(s: string): boolean {
  for (const b of s) {
    const charCode = b.charCodeAt(0);
    if (
      (charCode < CHAR_CODE_SPACE || charCode > CHAR_CODE_TILDE) && b !== "\t"
    ) {
      return true;
    }
  }
  return false;
}

// denoCacheMetadata={"headers":{"report-to":"{\"group\":\"cf-nel\",\"max_age\":604800,\"endpoints\":[{\"url\":\"https://a.nel.cloudflare.com/report/v4?s=XhgreNuz7a%2BAwryj0W%2FvMKzyXzko4oF8C3vi0nviRMRvTwteOj32Hq3OfXEsDqMPrbDG4o817MEfxsiOH1bu8hA7iVYrkvVDd%2BEG7%2BEXeyMYnCBTWbA6CwA%3D\"}]}","access-control-expose-headers":"*","date":"Tue, 28 Jul 2026 12:31:15 GMT","content-type":"text/typescript","access-control-allow-origin":"*","server":"cloudflare","accept-ranges":"bytes","content-security-policy":"default-src 'none'; script-src 'none'; style-src 'none'; img-src 'none'; font-src 'none'; connect-src 'none'; frame-src 'none'; object-src 'none'; frame-ancestors 'none'; sandbox; form-action 'none';","x-jsr-backend":"modules","cf-cache-status":"HIT","etag":"\"4eafc265a261fbcda5991050aacaa7e5\"","set-cookie":"__cf_bm=.mR196HpNUdbXqdOhAQ._1XRv5UMwWSugtPZ4Pf1erw-1785241875.3807197-1.0.1.1-IoxEqvcproy91tfcUVvxBFdcTinUcCi3L7ZVqvwWenz_9sAnLTP3gYHIBU8d9inqeR96dVqHhA6er.C0F73nkd9O0wGFCT81uCcj3drxipmeWRpgvPhYSVQy35OIDEW_; HttpOnly; SameSite=None; Secure; Path=/; Domain=jsr.io; Expires=Tue, 28 Jul 2026 13:01:15 GMT","cross-origin-resource-policy":"cross-origin","x-content-type-options":"nosniff","cache-control":"public, max-age=31536000, immutable","vary":"Origin","x-robots-tag":"noindex","content-length":"3253","alt-svc":"h3=\":443\"; ma=86400","age":"29176","nel":"{\"report_to\":\"cf-nel\",\"success_fraction\":0.0,\"max_age\":604800}","cf-ray":"a223e6590e7d7db6-LAX"},"url":"https://jsr.io/@std/media-types/1.0.3/_util.ts","time":1785241875}