// Copyright (c) 2013, 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.

part of dart.convert;

/**
 * The [ByteConversionSink] provides an interface for converters to
 * efficiently transmit byte data.
 *
 * Instead of limiting the interface to one non-chunked list of bytes it
 * accepts its input in chunks (themselves being lists of bytes).
 *
 * This abstract class will likely get more methods over time. Implementers are
 * urged to extend or mix in [ByteConversionSinkBase] to ensure that their
 * class covers the newly added methods.
 */
abstract class ByteConversionSink extends ChunkedConversionSink<List<int>> {
  ByteConversionSink();
  factory ByteConversionSink.withCallback(
      void callback(List<int> accumulated)) = _ByteCallbackSink;
  factory ByteConversionSink.from(Sink<List<int>> sink) = _ByteAdapterSink;

  /**
   * Adds the next [chunk] to `this`.
   *
   * Adds the bytes defined by [start] and [end]-exclusive to `this`.
   *
   * If [isLast] is `true` closes `this`.
   *
   * Contrary to `add` the given [chunk] must not be held onto. Once the method
   * returns, it is safe to overwrite the data in it.
   */
  void addSlice(List<int> chunk, int start, int end, bool isLast);

  // TODO(floitsch): add more methods:
  // - iterateBytes.
}

/**
 * This class provides a base-class for converters that need to accept byte
 * inputs.
 */
abstract class ByteConversionSinkBase extends ByteConversionSink {
  void add(List<int> chunk);
  void close();

  void addSlice(List<int> chunk, int start, int end, bool isLast) {
    add(chunk.sublist(start, end));
    if (isLast) close();
  }
}

/**
 * This class adapts a simple [Sink] to a [ByteConversionSink].
 *
 * All additional methods of the [ByteConversionSink] (compared to the
 * ChunkedConversionSink) are redirected to the `add` method.
 */
class _ByteAdapterSink extends ByteConversionSinkBase {
  final Sink<List<int>> _sink;

  _ByteAdapterSink(this._sink);

  void add(List<int> chunk) {
    _sink.add(chunk);
  }

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

/**
 * This class accumulates all chunks into one list of bytes
 * and invokes a callback when the sink is closed.
 *
 * This class can be used to terminate a chunked conversion.
 */
class _ByteCallbackSink extends ByteConversionSinkBase {
  static const _INITIAL_BUFFER_SIZE = 1024;

  final _ChunkedConversionCallback<List<int>> _callback;
  List<int> _buffer = new Uint8List(_INITIAL_BUFFER_SIZE);
  int _bufferIndex = 0;

  _ByteCallbackSink(void callback(List<int> accumulated))
      : this._callback = callback;

  void add(Iterable<int> chunk) {
    int freeCount = _buffer.length - _bufferIndex;
    if (chunk.length > freeCount) {
      // Grow the buffer.
      int oldLength = _buffer.length;
      int newLength = _roundToPowerOf2(chunk.length + oldLength) * 2;
      List<int> grown = new Uint8List(newLength);
      grown.setRange(0, _buffer.length, _buffer);
      _buffer = grown;
    }
    _buffer.setRange(_bufferIndex, _bufferIndex + chunk.length, chunk);
    _bufferIndex += chunk.length;
  }

  static int _roundToPowerOf2(int v) {
    assert(v > 0);
    v--;
    v |= v >> 1;
    v |= v >> 2;
    v |= v >> 4;
    v |= v >> 8;
    v |= v >> 16;
    v++;
    return v;
  }

  void close() {
    _callback(_buffer.sublist(0, _bufferIndex));
  }
}
