// Port of upstream libinjection_sqli_fold; BSD-3-Clause.

///|
fn fold_engine(sf : Scanner, vec : Array[Token]) -> Int {
  let mut last_comment = token("", 0, b"")
  let mut pos = 0
  let mut left = 0
  let mut more = true
  let mut current_index = 0

  current_index = 0
  while more {
    more = match sf.next() {
      Some(t) => {
        vec[current_index] = t
        true
      }
      None => {
        vec[current_index] = token("", 0, b"")
        false
      }
    }
    if !(vec[current_index].kind == "c" ||
      vec[current_index].kind == "(" ||
      vec[current_index].kind == "t" ||
      unary(vec[current_index])) {
      break
    }
  }
  if !more {
    return 0
  } else {
    pos += 1
  }
  while true {
    if pos >= 5 {
      if (
          vec[0].kind == "1" &&
          (vec[1].kind == "o" || vec[1].kind == ",") &&
          vec[2].kind == "(" &&
          vec[3].kind == "1" &&
          vec[4].kind == ")"
        ) ||
        (
          vec[0].kind == "n" &&
          vec[1].kind == "o" &&
          vec[2].kind == "(" &&
          (vec[3].kind == "n" || vec[3].kind == "1") &&
          vec[4].kind == ")"
        ) ||
        (
          vec[0].kind == "1" &&
          vec[1].kind == ")" &&
          vec[2].kind == "," &&
          vec[3].kind == "(" &&
          vec[4].kind == "1"
        ) ||
        (
          vec[0].kind == "n" &&
          vec[1].kind == ")" &&
          vec[2].kind == "o" &&
          vec[3].kind == "(" &&
          vec[4].kind == "n"
        ) {
        if pos > 5 {
          vec[1] = vec[5].duplicate()
          pos = 2

          left = 0
        } else {
          pos = 1

          left = 0
        }
      }
    }
    if !more || left >= 5 {
      left = pos

      break
    }
    while more && pos <= 5 && pos - left < 2 {
      current_index = pos
      more = match sf.next() {
        Some(t) => {
          vec[current_index] = t
          true
        }
        None => {
          vec[current_index] = token("", 0, b"")
          false
        }
      }
      if more {
        if vec[current_index].kind == "c" {
          last_comment = vec[current_index].duplicate()
        } else {
          last_comment.kind = ""

          pos += 1
        }
      }
    }

    if pos - left < 2 {
      left = pos

      continue
    }
    if vec[left].kind == "s" && vec[left + 1].kind == "s" {
      pos -= 1

      continue
    } else if vec[left].kind == ";" && vec[left + 1].kind == ";" {
      pos -= 1

      continue
    } else if (vec[left].kind == "o" || vec[left].kind == "&") &&
      (unary(vec[left + 1]) || vec[left + 1].kind == "t") {
      pos -= 1

      left = 0

      continue
    } else if vec[left].kind == "(" && unary(vec[left + 1]) {
      pos -= 1

      if left > 0 {
        left -= 1
      }
      continue
    } else if merge_words(vec[left], vec[left + 1]) {
      pos -= 1

      if left > 0 {
        left -= 1
      }
      continue
    } else if vec[left].kind == ";" &&
      vec[left + 1].kind == "f" &&
      (vec[left + 1].at(0) == 73 || vec[left + 1].at(0) == 105) &&
      (vec[left + 1].at(1) == 70 || vec[left + 1].at(1) == 102) {
      vec[left + 1].kind = "T"

      continue
    } else if (vec[left].kind == "n" || vec[left].kind == "v") &&
      vec[left + 1].kind == "(" &&
      (
        upper_text(vec[left].value) == "USER_ID" ||
        upper_text(vec[left].value) == "USER_NAME" ||
        upper_text(vec[left].value) == "DATABASE" ||
        upper_text(vec[left].value) == "PASSWORD" ||
        upper_text(vec[left].value) == "USER" ||
        upper_text(vec[left].value) == "CURRENT_USER" ||
        upper_text(vec[left].value) == "CURRENT_DATE" ||
        upper_text(vec[left].value) == "CURRENT_TIME" ||
        upper_text(vec[left].value) == "CURRENT_TIMESTAMP" ||
        upper_text(vec[left].value) == "LOCALTIME" ||
        upper_text(vec[left].value) == "LOCALTIMESTAMP"
      ) {
      vec[left].kind = "f"

      continue
    } else if vec[left].kind == "k" &&
      (
        upper_text(vec[left].value) == "IN" ||
        upper_text(vec[left].value) == "NOT IN"
      ) {
      if vec[left + 1].kind == "(" {
        vec[left].kind = "o"
      } else {
        vec[left].kind = "n"
      }
      continue
    } else if vec[left].kind == "o" &&
      (
        upper_text(vec[left].value) == "LIKE" ||
        upper_text(vec[left].value) == "NOT LIKE"
      ) {
      if vec[left + 1].kind == "(" {
        vec[left].kind = "f"
      }
    } else if vec[left].kind == "t" &&
      (
        vec[left + 1].kind == "n" ||
        vec[left + 1].kind == "1" ||
        vec[left + 1].kind == "t" ||
        vec[left + 1].kind == "(" ||
        vec[left + 1].kind == "f" ||
        vec[left + 1].kind == "v" ||
        vec[left + 1].kind == "s"
      ) {
      vec[left] = vec[left + 1].duplicate()
      pos -= 1

      left = 0

      continue
    } else if vec[left].kind == "A" && vec[left + 1].kind == "n" {
      if upper_text(vec[left + 1].value).contains("_") {
        vec[left + 1].kind = "t"

        left = 0
      }
    } else if vec[left].kind == "\\" {
      if arithmetic(vec[left + 1]) {
        vec[left].kind = "1"
      } else {
        vec[left] = vec[left + 1].duplicate()
        pos -= 1
      }
      left = 0

      continue
    } else if vec[left].kind == "(" && vec[left + 1].kind == "(" {
      pos -= 1

      left = 0

      continue
    } else if vec[left].kind == ")" && vec[left + 1].kind == ")" {
      pos -= 1

      left = 0

      continue
    } else if vec[left].kind == "{" && vec[left + 1].kind == "n" {
      if vec[left + 1].value.length() == 0 {
        vec[left + 1].kind = "X"

        return left + 2
      }
      left = 0

      pos -= 2

      continue
    } else if vec[left + 1].kind == "}" {
      pos -= 1

      left = 0

      continue
    }

    while more && pos <= 5 && pos - left < 3 {
      current_index = pos
      more = match sf.next() {
        Some(t) => {
          vec[current_index] = t
          true
        }
        None => {
          vec[current_index] = token("", 0, b"")
          false
        }
      }
      if more {
        if vec[current_index].kind == "c" {
          last_comment = vec[current_index].duplicate()
        } else {
          last_comment.kind = ""

          pos += 1
        }
      }
    }
    if pos - left < 3 {
      left = pos

      continue
    }
    if vec[left].kind == "1" &&
      vec[left + 1].kind == "o" &&
      vec[left + 2].kind == "1" {
      pos -= 2

      left = 0

      continue
    } else if vec[left].kind == "o" &&
      vec[left + 1].kind != "(" &&
      vec[left + 2].kind == "o" {
      left = 0

      pos -= 2

      continue
    } else if vec[left].kind == "&" && vec[left + 2].kind == "&" {
      pos -= 2

      left = 0

      continue
    } else if vec[left].kind == "v" &&
      vec[left + 1].kind == "o" &&
      (
        vec[left + 2].kind == "v" ||
        vec[left + 2].kind == "1" ||
        vec[left + 2].kind == "n"
      ) {
      pos -= 2

      left = 0

      continue
    } else if (vec[left].kind == "n" || vec[left].kind == "1") &&
      vec[left + 1].kind == "o" &&
      (vec[left + 2].kind == "1" || vec[left + 2].kind == "n") {
      pos -= 2

      left = 0

      continue
    } else if (
        vec[left].kind == "n" ||
        vec[left].kind == "1" ||
        vec[left].kind == "v" ||
        vec[left].kind == "s"
      ) &&
      vec[left + 1].kind == "o" &&
      vec[left + 1].value == b"::" &&
      vec[left + 2].kind == "t" {
      pos -= 2

      left = 0

      continue
    } else if (
        vec[left].kind == "n" ||
        vec[left].kind == "1" ||
        vec[left].kind == "s" ||
        vec[left].kind == "v"
      ) &&
      vec[left + 1].kind == "," &&
      (
        vec[left + 2].kind == "1" ||
        vec[left + 2].kind == "n" ||
        vec[left + 2].kind == "s" ||
        vec[left + 2].kind == "v"
      ) {
      pos -= 2

      left = 0

      continue
    } else if (
        vec[left].kind == "E" || vec[left].kind == "B" || vec[left].kind == ","
      ) &&
      unary(vec[left + 1]) &&
      vec[left + 2].kind == "(" {
      vec[left + 1] = vec[left + 2].duplicate()
      pos -= 1

      left = 0

      continue
    } else if (
        vec[left].kind == "k" || vec[left].kind == "E" || vec[left].kind == "B"
      ) &&
      unary(vec[left + 1]) &&
      (
        vec[left + 2].kind == "1" ||
        vec[left + 2].kind == "n" ||
        vec[left + 2].kind == "v" ||
        vec[left + 2].kind == "s" ||
        vec[left + 2].kind == "f"
      ) {
      vec[left + 1] = vec[left + 2].duplicate()
      pos -= 1

      left = 0

      continue
    } else if vec[left].kind == "," &&
      unary(vec[left + 1]) &&
      (
        vec[left + 2].kind == "1" ||
        vec[left + 2].kind == "n" ||
        vec[left + 2].kind == "v" ||
        vec[left + 2].kind == "s"
      ) {
      vec[left + 1] = vec[left + 2].duplicate()
      left = 0

      // C asserts pos >= 3 here; keep the decrement bounded so inspect stays usable from main.
      if pos >= 3 {
        pos -= 3
      }

      continue
    } else if vec[left].kind == "," &&
      unary(vec[left + 1]) &&
      vec[left + 2].kind == "f" {
      vec[left + 1] = vec[left + 2].duplicate()
      pos -= 1

      left = 0

      continue
    } else if vec[left].kind == "n" &&
      vec[left + 1].kind == "." &&
      vec[left + 2].kind == "n" {
      // C asserts pos >= 3 here; skip the rewrite rather than aborting the library caller.
      if pos >= 3 {
        pos -= 2
      }

      left = 0

      continue
    } else if vec[left].kind == "E" &&
      vec[left + 1].kind == "." &&
      vec[left + 2].kind == "n" {
      vec[left + 1] = vec[left + 2].duplicate()
      pos -= 1

      left = 0

      continue
    } else if vec[left].kind == "f" &&
      vec[left + 1].kind == "(" &&
      vec[left + 2].kind != ")" {
      if upper_text(vec[left].value) == "USER" {
        vec[left].kind = "n"
      }
    }
    left += 1
  }
  if left < 5 && last_comment.kind == "c" {
    vec[left] = last_comment.duplicate()
    left += 1
  }
  if left > 5 {
    left = 5
  }
  return left
}