blob: ba306452b48f9f44ef62e021c6e9fb27c1bc99da [file] [log] [blame]
// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:collection';
import 'dart:convert';
import 'dart:math';
import 'dart:typed_data';
import 'package:collection/collection.dart';
import 'package:crypto/crypto.dart';
import 'document/values/converter.dart';
// TODO: consider short function names and importing with prefix.
/// Concatenate two byte arrays.
Uint8List concatUint8Lists(Uint8List a, Uint8List b) {
return Uint8List(a.length + b.length)..setAll(0, a)..setAll(a.length, b);
}
// TODO: consider using Iterable instead of List.
/// Concatenate list of byte arrays.
Uint8List concatListOfUint8Lists(List<Uint8List> list) {
int sumLength = 0;
for (final x in list) {
sumLength += x.length;
}
final result = Uint8List(sumLength);
int pos = 0;
for (final x in list) {
result.setAll(pos, x);
pos += x.length;
}
return result;
}
/// Returns a _view_ of a region of [x] starting at [start] (inclusive) and
/// ending at [end] (exclusive).
Uint8List getSublistView(Uint8List x, {int start = 0, int end}) {
end ??= x.length;
return UnmodifiableUint8ListView(
x.buffer.asUint8List(x.offsetInBytes + start, end - start));
}
/// Returns a Uint8List created from the utf8 encoding of [string].
/// [string] must be non-null.
Uint8List getUint8ListFromString(String string) {
return Uint8List.fromList(utf8.encode(string));
}
/// Returns a Uint8List created from the binary encoding of [number].
Uint8List getUint8ListFromNumber(num number) {
IntConverter converter = IntConverter();
return converter.serialize(number);
}
/// Returns a new HashMap with Uint8Lists as a keys.
/// Note: The type T is enforced only at compile time.
HashMap<Uint8List, T> newUint8ListMap<T>() {
const listEquality = ListEquality<int>();
return HashMap<Uint8List, T>(
equals: listEquality.equals, hashCode: listEquality.hash);
}
/// Returns true if `a` and `b` are equal.
/// Returns false otherwise.
bool uint8ListsAreEqual(Uint8List a, Uint8List b) {
if (a == b) {
return true;
}
const listEquality = ListEquality<int>();
return listEquality.equals(a, b);
}
/// Compares lists `a` and `b`.
/// Returns 0 if the content of the two list is equal.
/// Returns a number less than 0 if `a` is short or lexicographical before `b`.
/// Returns a number greater than 0 otherwise.
int _compareLists(List a, List b) {
final minLength = min(a.length, b.length);
for (int i = 0; i < minLength; i++) {
if (a[i] != b[i]) {
return a[i] - b[i];
}
}
// Missing parts come before present ones.
return a.length.compareTo(b.length);
}
/// Returns a new ordered HashMap with Uint8Lists as a keys.
/// Note: The type T is enforced only at compile time.
SplayTreeMap<Uint8List, T> newUint8ListOrderedMap<T>() {
return SplayTreeMap<Uint8List, T>(_compareLists);
}
/// Returns a 20 bytes long hash of [data].
Uint8List hash(Uint8List data) {
final iterable = sha256.convert(data).bytes.getRange(0, 20);
return Uint8List.fromList(List.from(iterable));
}
final _random = Random.secure();
/// Returns a list of random bytes of a given [length].
Uint8List randomUint8List(int length) {
final result = Uint8List(length);
for (int i = 0; i < length; i++) {
result[i] = _random.nextInt(256);
}
return result;
}
/// Checks if [keyPrefix] is the prefix of the [key].
/// Both [keyPrefix] and [key] must not be null.
bool hasPrefix(Uint8List key, Uint8List keyPrefix) {
if (keyPrefix.length > key.length) {
return false;
}
for (int i = 0; i < keyPrefix.length; i++) {
if (key[i] != keyPrefix[i]) {
return false;
}
}
return true;
}