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

/**
 * A [Codec] encodes and (if supported) decodes data.
 *
 * Codecs can be fused. For example fusing [json] and [utf8] produces
 * an encoder that can convert Json objects directly to bytes, or can decode
 * bytes directly to json objects.
 *
 * Fused codecs generally attempt to optimize the operations and can be faster
 * than executing each step of an encoding separately.
 */
abstract class Codec<S, T> {
  const Codec();

  /**
   * Encodes [input].
   *
   * The input is encoded as if by `encoder.convert`.
   */
  T encode(S input) => encoder.convert(input);

  /**
   * Decodes [encoded] data.
   *
   * The input is decoded as if by `decoder.convert`.
   */
  S decode(T encoded) => decoder.convert(encoded);

  /**
   * Returns the encoder from [S] to [T].
   *
   * It may be stateful and should not be reused.
   */
  Converter<S, T> get encoder;
  /**
   * Returns the decoder of `this`, converting from [T] to [S].
   *
   * It may be stateful an should not be reused.
   */
  Converter<T, S> get decoder;

  /**
   * Fuses `this` with `other`.
   *
   * When encoding, the resulting codec encodes with `this` before
   * encoding with [other].
   *
   * When decoding, the resulting codec decodes with [other] before decoding
   * with `this`.
   *
   * In some cases one needs to use the [inverted] codecs to be able to fuse
   * them correctly. That is, the output type of `this` ([T]) must match the
   * input type of the second codec [other].
   *
   * Examples:
   * ```dart
   * final jsonToBytes = json.fuse(utf8);
   * List<int> bytes = jsonToBytes.encode(["json-object"]);
   * var decoded = jsonToBytes.decode(bytes);
   * assert(decoded is List && decoded[0] == "json-object");
   *
   * var inverted = json.inverted;
   * var jsonIdentity = json.fuse(inverted);
   * var jsonObject = jsonIdentity.encode(["1", 2]);
   * assert(jsonObject is List && jsonObject[0] == "1" && jsonObject[1] == 2);
   * ```
   */
  // TODO(floitsch): use better example with line-splitter once that one is
  // in this library.
  Codec<S, R> fuse<R>(Codec<T, R> other) {
    return new _FusedCodec<S, T, R>(this, other);
  }

  /**
   * Inverts `this`.
   *
   * The [encoder] and [decoder] of the resulting codec are swapped.
   */
  Codec<T, S> get inverted => new _InvertedCodec<T, S>(this);
}

/**
 * Fuses the given codecs.
 *
 * In the non-chunked conversion simply invokes the non-chunked conversions in
 * sequence.
 */
class _FusedCodec<S, M, T> extends Codec<S, T> {
  final Codec<S, M> _first;
  final Codec<M, T> _second;

  Converter<S, T> get encoder => _first.encoder.fuse<T>(_second.encoder);
  Converter<T, S> get decoder => _second.decoder.fuse<S>(_first.decoder);

  _FusedCodec(this._first, this._second);
}

class _InvertedCodec<T, S> extends Codec<T, S> {
  final Codec<S, T> _codec;

  _InvertedCodec(Codec<S, T> codec) : _codec = codec;

  Converter<T, S> get encoder => _codec.decoder;
  Converter<S, T> get decoder => _codec.encoder;

  Codec<S, T> get inverted => _codec;
}
