twonly-app-dependencies/hashlib/lib/src/core/block_hash.dart
2025-12-07 16:10:41 +01:00

82 lines
2.2 KiB
Dart

// Copyright (c) 2023, Sudipto Chandra
// All rights reserved. Check LICENSE file for details.
import 'dart:typed_data';
import 'package:hashlib/src/core/hash_base.dart';
/// Base class used by block hash algorithms
abstract class BlockHashBase<T extends BlockHashSink> extends HashBase<T> {
const BlockHashBase();
}
/// Base class used by block hash algorithm sink implementations
abstract class BlockHashSink extends HashDigestSink {
/// The current position of data in the [buffer]
int pos = 0;
/// The message length in bytes
int messageLength = 0;
/// The internal block length of the algorithm in bytes
final int blockLength;
/// The main buffer
final Uint8List buffer;
/// The [buffer] as Uint32List
late final Uint32List sbuffer = Uint32List.view(buffer.buffer);
/// The [buffer] as ByteData
late final ByteData bdata = buffer.buffer.asByteData();
/// Get the message length in bits
int get messageLengthInBits => messageLength << 3;
/// Initialize a new sink for the block hash
///
/// Parameters:
/// - [blockLength] is the length of each block in each [$update] call.
/// - [bufferLength] is the buffer length where blocks are stored temporarily
BlockHashSink(this.blockLength, {int? bufferLength})
: assert(blockLength > 0 && (bufferLength ?? 0) >= 0),
buffer = Uint8List(bufferLength ?? blockLength);
@override
void reset() {
pos = 0;
messageLength = 0;
super.reset();
}
@override
void $process(List<int> chunk, int start, int end) {
int t = start;
if (pos > 0) {
for (; t < end && pos < blockLength; pos++, t++) {
buffer[pos] = chunk[t];
}
messageLength += t - start;
if (pos < blockLength) return;
$update(buffer);
pos = 0;
}
while ((end - t) >= blockLength) {
messageLength += blockLength;
$update(chunk, t);
t += blockLength;
}
messageLength += end - t;
for (; t < end; pos++, t++) {
buffer[pos] = chunk[t];
}
}
/// Internal method to update the message-digest with a single [block].
///
/// The method starts reading the block from [offset] index
void $update(List<int> block, [int offset = 0, bool last = false]);
}