| Index: lib/src/hash.dart | 
| diff --git a/lib/src/hash.dart b/lib/src/hash.dart | 
| index bb228fa55fed0fc14992eedfa6330b71312f19cd..6f9b33ba0f7fe7d41e5adcad93cb90cdd629fb74 100644 | 
| --- a/lib/src/hash.dart | 
| +++ b/lib/src/hash.dart | 
| @@ -4,30 +4,61 @@ | 
|  | 
| library crypto.hash; | 
|  | 
| +import 'dart:convert'; | 
| + | 
| +import 'digest.dart'; | 
| +import 'digest_sink.dart'; | 
| + | 
| /// An interface for cryptographic hash functions. | 
| /// | 
| -/// The [add] method adds data to the hash. The [close] method extracts the | 
| -/// message digest. | 
| -/// | 
| -/// If multiple instances of a given Hash is needed, the [newInstance] method | 
| -/// can provide a new instance. | 
| -// TODO(floitsch): make Hash implement Sink, EventSink or similar. | 
| -abstract class Hash { | 
| -  /// Add a list of bytes to the hash computation. | 
| +/// Every hash is a converter that takes a list of ints and returns a single | 
| +/// digest. When used in chunked mode, it will only ever add one digest to the | 
| +/// inner [Sink]. | 
| +abstract class Hash extends Converter<List<int>, Digest> { | 
| +  /// The internal block size of the hash in bytes. | 
| /// | 
| -  /// If [this] has already been closed, throws a [StateError]. | 
| -  void add(List<int> data); | 
| +  /// This is exposed for use by the [HMAC] class, which needs to know the block | 
| +  /// size for the [Hash] it uses. | 
| +  int get blockSize; | 
|  | 
| -  /// Finish the hash computation and extract the message digest as a list of | 
| -  /// bytes. | 
| -  List<int> close(); | 
| +  /// The sink for implementing the deprecated APIs that involved adding data | 
| +  /// directly to the [Hash] instance. | 
| +  ByteConversionSink _sink; | 
| + | 
| +  /// The sink that [_sink] sends the [Digest] to once it finishes hashing. | 
| +  final DigestSink _innerSink = new DigestSink(); | 
| + | 
| +  Hash() { | 
| +    _sink = startChunkedConversion(_innerSink); | 
| +  } | 
| + | 
| +  Digest convert(List<int> data) { | 
| +    var innerSink = new DigestSink(); | 
| +    var outerSink = startChunkedConversion(innerSink); | 
| +    outerSink.add(data); | 
| +    outerSink.close(); | 
| +    return innerSink.value; | 
| +  } | 
| + | 
| +  ByteConversionSink startChunkedConversion(Sink<Digest> sink); | 
|  | 
| /// Returns a new instance of this hash function. | 
| +  @Deprecated("Expires in 1.0.0. Use Hash.startChunkedConversion() instead.") | 
| Hash newInstance(); | 
|  | 
| -  /// The internal block size of the hash in bytes. | 
| +  /// Add a list of bytes to the hash computation. | 
| /// | 
| -  /// This is exposed for use by the [HMAC] class, which needs to know the block | 
| -  /// size for the [Hash] it uses. | 
| -  int get blockSize; | 
| +  /// If [this] has already been closed, throws a [StateError]. | 
| +  @Deprecated("Expires in 1.0.0. Use Hash.convert() or " | 
| +      "Hash.startChunkedConversion() instead.") | 
| +  void add(List<int> data) => _sink.add(data); | 
| + | 
| +  /// Finish the hash computation and extract the message digest as a list of | 
| +  /// bytes. | 
| +  @Deprecated("Expires in 1.0.0. Use Hash.convert() or " | 
| +      "Hash.startChunkedConversion() instead.") | 
| +  List<int> close() { | 
| +    _sink.close(); | 
| +    return _innerSink.value.bytes; | 
| +  } | 
| } | 
|  |