// 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.encoder;

import 'dart:convert';

import 'package:charcode/ascii.dart';

/// The canonical instance of [PercentEncoder].
const percentEncoder = const PercentEncoder._();

/// A converter that encodes byte arrays into percent-encoded strings.
///
/// [encoder] encodes all bytes other than ASCII letters, decimal digits, or one
/// of `-._~`. This matches the behavior of [Uri.encodeQueryComponent] except
/// that it doesn't encode `0x20` bytes to the `+` character.
///
/// This will throw a [RangeError] if the byte array has any digits that don't
/// fit in the gamut of a byte.
class PercentEncoder
    extends ChunkedConverter<List<int>, String, List<int>, String> {
  const PercentEncoder._();

  String convert(List<int> bytes) => _convert(bytes, 0, bytes.length);

  ByteConversionSink startChunkedConversion(Sink<String> sink) =>
      new _PercentEncoderSink(sink);
}

/// A conversion sink for chunked percentadecimal encoding.
class _PercentEncoderSink extends ByteConversionSinkBase {
  /// The underlying sink to which decoded byte arrays will be passed.
  final Sink<String> _sink;

  _PercentEncoderSink(this._sink);

  void add(List<int> chunk) {
    _sink.add(_convert(chunk, 0, chunk.length));
  }

  void addSlice(List<int> chunk, int start, int end, bool isLast) {
    RangeError.checkValidRange(start, end, chunk.length);
    _sink.add(_convert(chunk, start, end));
    if (isLast) _sink.close();
  }

  void close() {
    _sink.close();
  }
}

String _convert(List<int> bytes, int start, int end) {
  var buffer = new StringBuffer();

  // A bitwise OR of all bytes in [bytes]. This allows us to check for
  // out-of-range bytes without adding more branches than necessary to the
  // core loop.
  var byteOr = 0;
  for (var i = start; i < end; i++) {
    var byte = bytes[i];
    byteOr |= byte;

    // If the byte is an uppercase letter, convert it to lowercase to check if
    // it's unreserved. This works because uppercase letters in ASCII are
    // exactly `0b100000 = 0x20` less than lowercase letters, so if we ensure
    // that that bit is 1 we ensure that the letter is lowercase.
    var letter = 0x20 | byte;
    if ((letter >= $a && letter <= $z) ||
        byte == $dash ||
        byte == $dot ||
        byte == $underscore ||
        byte == $tilde) {
      // Unreserved characters are safe to write as-is.
      buffer.writeCharCode(byte);
      continue;
    }

    buffer.writeCharCode($percent);

    // The bitwise arithmetic here is equivalent to `byte ~/ 16` and `byte % 16`
    // for valid byte values, but is easier for dart2js to optimize given that
    // it can't prove that [byte] will always be positive.
    buffer.writeCharCode(_codeUnitForDigit((byte & 0xF0) >> 4));
    buffer.writeCharCode(_codeUnitForDigit(byte & 0x0F));
  }

  if (byteOr >= 0 && byteOr <= 255) return buffer.toString();

  // If there was an invalid byte, find it and throw an exception.
  for (var i = start; i < end; i++) {
    var byte = bytes[i];
    if (byte >= 0 && byte <= 0xff) continue;
    throw new FormatException(
        "Invalid byte ${byte < 0 ? "-" : ""}0x${byte.abs().toRadixString(16)}.",
        bytes, i);
  }

  throw 'unreachable';
}

/// Returns the ASCII/Unicode code unit corresponding to the hexadecimal digit
/// [digit].
int _codeUnitForDigit(int digit) => digit < 10 ? digit + $0 : digit + $A - 10;
