text: "use strict";
  const { utf8Encode, utf8DecodeWithoutBOM } = require("./encoding");
  const { percentDecodeBytes, utf8PercentEncodeString, isURLEncodedPercentEncode } = require("./percent-encoding");
  
  function p(char) {
    return char.codePointAt(0);
  }
  
  // https://whatpr.org/url/518.html#concept-urlencoded-parser
  function parseUrlencoded(input) {
    const sequences = strictlySplitByteSequence(input, p("&"));
    const output = [];
    for (const bytes of sequences) {
      if (bytes.length === 0) {
        continue;
      }
  
      let name;
      let value;
      const indexOfEqual = bytes.indexOf(p("="));
  
      if (indexOfEqual >= 0) {
        name = bytes.slice(0, indexOfEqual);
        value = bytes.slice(indexOfEqual + 1);
      } else {
        name = bytes;
        value = new Uint8Array(0);
      }
  
      name = replaceByteInByteSequence(name, 0x2B, 0x20);
      value = replaceByteInByteSequence(value, 0x2B, 0x20);
  
      const nameString = utf8DecodeWithoutBOM(percentDecodeBytes(name));
      const valueString = utf8DecodeWithoutBOM(percentDecodeBytes(value));
  
      output.push([nameString, valueString]);
    }
    return output;
  }
  
  // https://whatpr.org/url/518.html#concept-urlencoded-string-parser
  function parseUrlencodedString(input) {
    return parseUrlencoded(utf8Encode(input));
  }
  
  // https://whatpr.org/url/518.html#concept-urlencoded-serializer
  function serializeUrlencoded(tuples, encodingOverride = undefined) {
    let encoding = "utf-8";
    if (encodingOverride !== undefined) {
      // TODO "get the output encoding", i.e. handle encoding labels vs. names.
      encoding = encodingOverride;
    }
  
    let output = "";
    for (const [i, tuple] of tuples.entries()) {
      // TODO: handle encoding override
  
      const name = utf8PercentEncodeString(tuple[0], isURLEncodedPercentEncode, true);
  
      let value = tuple[1];
      if (tuple.length > 2 && tuple[2] !== undefined) {
        if (tuple[2] === "hidden" && name === "_charset_") {
          value = encoding;
        } else if (tuple[2] === "file") {
          // value is a File object
          value = value.name;
        }
      }
  
      value = utf8PercentEncodeString(value, isURLEncodedPercentEncode, true);
  
      if (i !== 0) {
        output += "&";
      }
      output += `${name}=${value}`;
    }
    return output;
  }
  
  function strictlySplitByteSequence(buf, cp) {
    const list = [];
    let last = 0;
    let i = buf.indexOf(cp);
    while (i >= 0) {
      list.push(buf.slice(last, i));
      last = i + 1;
      i = buf.indexOf(cp, last);
    }
    if (last !== buf.length) {
      list.push(buf.slice(last));
    }
    return list;
  }
  
  function replaceByteInByteSequence(buf, from, to) {
    let i = buf.indexOf(from);
    while (i >= 0) {
      buf[i] = to;
      i = buf.indexOf(from, i + 1);
    }
    return buf;
  }
  
  module.exports = {
    parseUrlencodedString,
    serializeUrlencoded
  };
  