// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

library convert.percent.decoder;

import 'dart:convert';

import 'package:typed_data/typed_data.dart';

import '../charcodes.dart';
import '../utils.dart';

/// The canonical instance of [PercentDecoder].
const percentDecoder = PercentDecoder._();

const _lastPercent = -1;

/// A converter that decodes percent-encoded strings into byte arrays.
///
/// To be maximally flexible, this will decode any percent-encoded byte and
/// will allow any non-percent-encoded byte other than `%`. By default, it
/// interprets `+` as `0x2B` rather than `0x20` as emitted by
/// [Uri.encodeQueryComponent].
///
/// This will throw a [FormatException] if the input string has an incomplete
/// percent-encoding, or if it contains non-ASCII code units.
class PercentDecoder extends Converter<String, List<int>> {
  const PercentDecoder._();

  List<int> convert(String string) {
    var buffer = Uint8Buffer();
    var lastDigit = _decode(string.codeUnits, 0, string.length, buffer);

    if (lastDigit != null) {
      throw FormatException(
          "Input ended with incomplete encoded byte.", string, string.length);
    }

    return buffer.buffer.asUint8List(0, buffer.length);
  }

  StringConversionSink startChunkedConversion(Sink<List<int>> sink) =>
      _PercentDecoderSink(sink);
}

/// A conversion sink for chunked percent-encoded decoding.
class _PercentDecoderSink extends StringConversionSinkBase {
  /// The underlying sink to which decoded byte arrays will be passed.
  final Sink<List<int>> _sink;

  /// The trailing digit from the previous string.
  ///
  /// This is `null` if the previous string ended with a complete
  /// percent-encoded byte or a literal character. It's [_lastPercent] if the
  /// most recent string ended with `%`. Otherwise, the most recent string ended
  /// with a `%` followed by a hexadecimal digit, and this is that digit. Since
  /// it's the most significant digit, it's always a multiple of 16.
  int? _lastDigit;

  _PercentDecoderSink(this._sink);

  void addSlice(String string, int start, int end, bool isLast) {
    RangeError.checkValidRange(start, end, string.length);

    if (start == end) {
      if (isLast) _close(string, end);
      return;
    }

    var buffer = Uint8Buffer();
    var codeUnits = string.codeUnits;
    if (_lastDigit == _lastPercent) {
      _lastDigit = 16 * digitForCodeUnit(codeUnits, start);
      start++;

      if (start == end) {
        if (isLast) _close(string, end);
        return;
      }
    }

    if (_lastDigit != null) {
      buffer.add(_lastDigit! + digitForCodeUnit(codeUnits, start));
      start++;
    }

    _lastDigit = _decode(codeUnits, start, end, buffer);

    _sink.add(buffer.buffer.asUint8List(0, buffer.length));
    if (isLast) _close(string, end);
  }

  ByteConversionSink asUtf8Sink(bool allowMalformed) =>
      _PercentDecoderByteSink(_sink);

  void close() => _close();

  /// Like [close], but includes [string] and [index] in the [FormatException]
  /// if one is thrown.
  void _close([String? string, int? index]) {
    if (_lastDigit != null) {
      throw FormatException(
          "Input ended with incomplete encoded byte.", string, index);
    }

    _sink.close();
  }
}

/// A conversion sink for chunked percent-encoded decoding from UTF-8 bytes.
class _PercentDecoderByteSink extends ByteConversionSinkBase {
  /// The underlying sink to which decoded byte arrays will be passed.
  final Sink<List<int>> _sink;

  /// The trailing digit from the previous string.
  ///
  /// This is `null` if the previous string ended with a complete
  /// percent-encoded byte or a literal character. It's [_lastPercent] if the
  /// most recent string ended with `%`. Otherwise, the most recent string ended
  /// with a `%` followed by a hexadecimal digit, and this is that digit. Since
  /// it's the most significant digit, it's always a multiple of 16.
  int? _lastDigit;

  _PercentDecoderByteSink(this._sink);

  void add(List<int> chunk) => addSlice(chunk, 0, chunk.length, false);

  void addSlice(List<int> chunk, int start, int end, bool isLast) {
    RangeError.checkValidRange(start, end, chunk.length);

    if (start == end) {
      if (isLast) _close(chunk, end);
      return;
    }

    var buffer = Uint8Buffer();
    if (_lastDigit == _lastPercent) {
      _lastDigit = 16 * digitForCodeUnit(chunk, start);
      start++;

      if (start == end) {
        if (isLast) _close(chunk, end);
        return;
      }
    }

    if (_lastDigit != null) {
      buffer.add(_lastDigit! + digitForCodeUnit(chunk, start));
      start++;
    }

    _lastDigit = _decode(chunk, start, end, buffer);

    _sink.add(buffer.buffer.asUint8List(0, buffer.length));
    if (isLast) _close(chunk, end);
  }

  void close() => _close();

  /// Like [close], but includes [chunk] and [index] in the [FormatException]
  /// if one is thrown.
  void _close([List<int>? chunk, int? index]) {
    if (_lastDigit != null) {
      throw FormatException(
          "Input ended with incomplete encoded byte.", chunk, index);
    }

    _sink.close();
  }
}

/// Decodes [codeUnits] and writes the result into [destination].
///
/// This reads from [codeUnits] between [sourceStart] and [sourceEnd]. It writes
/// the result into [destination] starting at [destinationStart].
///
/// If there's a leftover digit at the end of the decoding, this returns that
/// digit. Otherwise it returns `null`.
int? _decode(List<int> codeUnits, int start, int end, Uint8Buffer buffer) {
  // A bitwise OR of all code units in [codeUnits]. This allows us to check for
  // out-of-range code units without adding more branches than necessary to the
  // core loop.
  var codeUnitOr = 0;

  // The beginning of the current slice of adjacent non-% characters. We can add
  // all of these to the buffer at once.
  var sliceStart = start;
  for (var i = start; i < end; i++) {
    // First, loop through non-% characters.
    var codeUnit = codeUnits[i];
    if (codeUnits[i] != $percent) {
      codeUnitOr |= codeUnit;
      continue;
    }

    // We found a %. The slice from `sliceStart` to `i` represents characters
    // than can be copied to the buffer as-is.
    if (i > sliceStart) {
      _checkForInvalidCodeUnit(codeUnitOr, codeUnits, sliceStart, i);
      buffer.addAll(codeUnits, sliceStart, i);
    }

    // Now decode the percent-encoded byte and add it as well.
    i++;
    if (i >= end) return _lastPercent;

    var firstDigit = digitForCodeUnit(codeUnits, i);
    i++;
    if (i >= end) return 16 * firstDigit;

    var secondDigit = digitForCodeUnit(codeUnits, i);
    buffer.add(16 * firstDigit + secondDigit);

    // The next iteration will look for non-% characters again.
    sliceStart = i + 1;
  }

  if (end > sliceStart) {
    _checkForInvalidCodeUnit(codeUnitOr, codeUnits, sliceStart, end);
    if (start == sliceStart) {
      buffer.addAll(codeUnits);
    } else {
      buffer.addAll(codeUnits, sliceStart, end);
    }
  }

  return null;
}

void _checkForInvalidCodeUnit(
    int codeUnitOr, List<int> codeUnits, int start, int end) {
  if (codeUnitOr >= 0 && codeUnitOr <= 0x7f) return;

  for (var i = start; i < end; i++) {
    var codeUnit = codeUnits[i];
    if (codeUnit >= 0 && codeUnit <= 0x7f) continue;
    throw FormatException(
        "Non-ASCII code unit "
        "U+${codeUnit.toRadixString(16).padLeft(4, '0')}",
        codeUnits,
        i);
  }
}
