// 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 and 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 _FusedCodec<S, T, R>(this, other);
  }

  /// Inverts `this`.
  ///
  /// The [encoder] and [decoder] of the resulting codec are swapped.
  Codec<T, S> get inverted => _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;
}
