ByteVector sealed
sealed class ByteVectorAn immutable, indexable sequence of bytes with rich operations for binary data manipulation.
ByteVector supports bitwise operations (and, or, xor, not), shifting, slicing (take, drop, slice), and conversion to and from various base encodings (binary, hex, base32, base58, base64).
Internally represented as a persistent tree of byte chunks, enabling efficient concatenation and buffered appends while maintaining immutability.
final bv = ByteVector.fromValidHex('deadbeef');
print(bv.size); // 4
print(bv.toHex()); // 'deadbeef'See also:
- BitVector, which operates at bit granularity.
Constructors
ByteVector() factory
factory ByteVector(List<int> bytes)Creates a ByteVector from a list of byte values.
Implementation
factory ByteVector(List<int> bytes) =>
_Chunk(_View(At.array(Uint8List.fromList(bytes)), 0, bytes.length));ByteVector.concatAll() factory
factory ByteVector.concatAll(IList<ByteVector> bvs)Creates a byte vector by concatenating all vectors in bvs.
Implementation
factory ByteVector.concatAll(IList<ByteVector> bvs) =>
bvs.foldLeft(ByteVector.empty, (acc, bv) => acc.concat(bv));ByteVector.fill() factory
factory ByteVector.fill(int size, int byte)Creates a size-byte vector with every byte set to byte.
Implementation
factory ByteVector.fill(int size, int byte) {
assert(size >= 0, 'ByteVector.fill: size must be non-negative');
return _Chunk(_View(At((i) => byte), 0, size));
}ByteVector.from() factory
factory ByteVector.from(RIterableOnce<int> bs)Creates a byte vector from a sequence of bytes.
Implementation
factory ByteVector.from(RIterableOnce<int> bs) => ByteVector(bs.toList());ByteVector.fromBigInt() factory
factory ByteVector.fromBigInt(
BigInt value, {
Option<int> size = const None(),
Endian ordering = Endian.big,
})Creates a byte vector from a BigInt value.
If size is provided, the result is exactly that many bytes. Use ordering to specify byte order (Endian.big by default).
Implementation
factory ByteVector.fromBigInt(
BigInt value, {
Option<int> size = const None(),
Endian ordering = Endian.big,
}) => BitVector.fromBigInt(value, size: size.map((s) => s * 8), ordering: ordering).bytes;ByteVector.fromDart() factory
factory ByteVector.fromDart(Iterable<int> bs)Creates a byte vector from a Dart iterable of bytes.
Implementation
factory ByteVector.fromDart(Iterable<int> bs) => ByteVector(bs.toList());ByteVector.fromInt() factory
factory ByteVector.fromInt(int i, {int size = 4, Endian ordering = Endian.big})Creates a byte vector from an integer value.
The result has size bytes (default 4). Use ordering to specify byte order (Endian.big by default).
Implementation
factory ByteVector.fromInt(
int i, {
int size = 4,
Endian ordering = Endian.big,
}) => BitVector.fromInt(i, size: size * 8, ordering: ordering).bytes;ByteVector.high() factory
factory ByteVector.high(int size)Creates a size-byte vector with all bytes set to 0xFF.
Implementation
factory ByteVector.high(int size) => ByteVector.fill(size, 0xff);ByteVector.low() factory
factory ByteVector.low(int size)Creates a size-byte vector with all bytes set to 0x00.
Implementation
factory ByteVector.low(int size) => ByteVector.fill(size, 0x00);ByteVector.of() factory
factory ByteVector.of(int byte)Creates a single-byte vector containing byte.
Implementation
factory ByteVector.of(int byte) => ByteVector.fill(1, byte);ByteVector.view() factory
factory ByteVector.view(Uint8List bytes)Creates a byte vector backed by the given Uint8List without copying.
Implementation
factory ByteVector.view(Uint8List bytes) =>
_Chunk(_View(At.array(Uint8List.view(bytes.buffer)), 0, bytes.length));ByteVector.viewAt() factory
factory ByteVector.viewAt(At at, int size)Creates a byte vector backed by an At accessor with the given size.
Implementation
factory ByteVector.viewAt(At at, int size) => _Chunk(_View(at, 0, size));Properties
bits no setter
BitVector get bitsReturns a BitVector view of these bytes.
Implementation
BitVector get bits => toBitVector();hashCode no setter override
int get hashCodeThe hash code for this object.
A hash code is a single integer which represents the state of the object that affects operator == comparisons.
All objects have hash codes. The default hash code implemented by Object represents only the identity of the object, the same way as the default operator == implementation only considers objects equal if they are identical (see identityHashCode).
If operator == is overridden to use the object state instead, the hash code must also be changed to represent that state, otherwise the object cannot be used in hash based data structures like the default Set and Map implementations.
Hash codes must be the same for objects that are equal to each other according to operator ==. The hash code of an object should only change if the object changes in a way that affects equality. There are no further requirements for the hash codes. They need not be consistent between executions of the same program and there are no distribution guarantees.
Objects that are not equal are allowed to have the same hash code. It is even technically allowed that all instances have the same hash code, but if clashes happen too often, it may reduce the efficiency of hash-based data structures like HashSet or HashMap.
If a subclass overrides hashCode, it should override the operator == operator as well to maintain consistency.
Implementation
@override
int get hashCode {
const chunkSize = 1024 * 64;
var bytes = this;
var h = MurmurHash3.stringHash('ByteVector');
var iter = 1;
while (true) {
if (bytes.isEmpty) {
return MurmurHash3.finalizeHash(h, iter);
} else {
final chunk = bytes.take(chunkSize);
bytes = bytes.drop(chunkSize);
h = MurmurHash3.mix(h, MurmurHash3.bytesHash(chunk.toByteArray()));
iter += 1;
}
}
}head no setter
int get headReturns the first byte, or throws if empty.
Implementation
int get head => get(0);headOption no setter
Option<int> get headOptionReturns Some(head) if non-empty, otherwise None.
Implementation
Option<int> get headOption => size > 0 ? Some(head) : none();init no setter
ByteVector get initReturns all bytes except the last.
Implementation
ByteVector get init => dropRight(1);isEmpty no setter
bool get isEmptyReturns true if this vector contains no bytes.
Implementation
bool get isEmpty => size == 0;last no setter
int get lastReturns the last byte, or throws if empty.
Implementation
int get last => get(size - 1);lastOption no setter
Option<int> get lastOptionReturns Some(last) if non-empty, otherwise None.
Implementation
Option<int> get lastOption => lift(size - 1);length no setter
int get lengthAlias for size.
Implementation
int get length => size;nonEmpty no setter
bool get nonEmptyReturns true if this vector contains at least one byte.
Implementation
bool get nonEmpty => !isEmpty;not no setter
ByteVector get notReturns the bitwise complement of this vector.
Implementation
ByteVector get not => _mapS((b) => ~b);reverse no setter
ByteVector get reverseReturns a vector with bytes in reverse order.
Implementation
ByteVector get reverse => ByteVector.viewAt(At((i) => get(size - i - 1)), size);runtimeType no setter inherited
Type get runtimeTypeA representation of the runtime type of the object.
Inherited from Object.
Implementation
external Type get runtimeType;size no setter
int get sizeThe number of bytes in this vector.
Implementation
int get size;tail no setter
ByteVector get tailReturns all bytes except the first.
Implementation
ByteVector get tail => drop(1);Methods
acquire()
Either<String, ByteVector> acquire(int bytes)Returns the first bytes from this vector, or an error if there are fewer than bytes available.
Implementation
Either<String, ByteVector> acquire(int bytes) => Either.cond(
() => size >= bytes,
() => take(bytes),
() => 'Cannot acquire $bytes bytes from ByteVector of size $size',
);and()
ByteVector and(ByteVector other)Returns a bitwise AND of this vector and other.
Implementation
ByteVector and(ByteVector other) => _zipWithS(other, (b, b2) => b & b2);append()
ByteVector append(int byte)Returns a new vector with byte appended.
Implementation
ByteVector append(int byte) => concat(ByteVector.of(byte));bufferBy()
ByteVector bufferBy([int chunkSize = 1024])Returns a buffered version that amortizes appends by collecting them into internal chunks of chunkSize bytes.
Implementation
ByteVector bufferBy([int chunkSize = 1024]) {
switch (this) {
case final _Buffer b:
if (b.lastChunk.length >= chunkSize) {
return b;
} else {
return b.unbuffer().bufferBy(chunkSize);
}
default:
return _Buffer(this, Uint8List(chunkSize), 0, _BufferState(0));
}
}compact()
ByteVector compact()Returns a single-chunk copy of this vector if not already compacted.
Implementation
ByteVector compact() {
return switch (this) {
final _Chunk _ => this,
_ => copy(),
};
}concat()
ByteVector concat(ByteVector other)Concatenates other to the end of this vector.
Implementation
ByteVector concat(ByteVector other) {
if (isEmpty) {
return other;
} else if (other.isEmpty) {
return this;
} else {
return _Chunks(_Append(this, other)).bufferBy(64);
}
}consume()
Either<String, Record> consume<A>(
int n,
Either<String, A> Function(ByteVector) decode,
)Consumes the first n bytes, decoding them with decode and returning the remaining bytes paired with the decoded value.
Implementation
Either<String, (ByteVector, A)> consume<A>(
int n,
Function1<ByteVector, Either<String, A>> decode,
) => acquire(n).flatMap((toDecode) => decode(toDecode).map((decoded) => (drop(n), decoded)));containsSlice()
bool containsSlice(ByteVector slice)Returns true if this vector contains slice as a contiguous subsequence.
Implementation
bool containsSlice(ByteVector slice) => indexOfSlice(slice).isDefined;copy()
ByteVector copy()Returns a guaranteed fresh copy of this vector's bytes.
Implementation
ByteVector copy() {
final sz = size;
final arr = toByteArray();
return _Chunk(_View(At.array(arr), 0, sz));
}copyToArray()
void copyToArray(Uint8List xs, int start)Copies the bytes into xs starting at offset start.
Implementation
void copyToArray(Uint8List xs, int start) {
var i = start;
_foreachV((v) {
v.copyToArray(xs, i);
i += v.size;
});
}drop()
ByteVector drop(int n)Returns a vector of all bytes except the first n.
Implementation
ByteVector drop(int n) {
final n1 = max(min(n, size), 0);
if (n1 == size) {
return ByteVector.empty;
} else if (n1 == 0) {
return this;
} else {
ByteVector go(ByteVector cur, int n1) {
var currentCur = cur;
var currentN1 = n1;
final stack = <ByteVector>[];
while (true) {
switch (currentCur) {
case _Chunk(bytes: final bs):
var result = _Chunk(bs.drop(currentN1)) as ByteVector;
for (int i = stack.length - 1; i >= 0; i--) {
result = result.concat(stack[i]).unbuffer();
}
return result;
case _Append(left: final l, right: final r):
if (currentN1 > l.size) {
currentCur = r;
currentN1 -= l.size;
} else {
currentCur = l;
stack.add(r);
}
case final _Buffer b:
if (currentN1 > b.hd.size) {
currentCur = b.lastBytes;
currentN1 -= b.hd.size;
} else {
currentCur = b.hd;
stack.add(b.lastBytes);
}
case final _Chunks c:
currentCur = c.chunks;
}
}
}
return go(this, n1);
}
}dropRight()
ByteVector dropRight(int n)Returns all bytes except the last n.
Implementation
ByteVector dropRight(int n) => take(size - max(0, n));dropWhile()
ByteVector dropWhile(bool Function(int) p)Drops the longest prefix of bytes satisfying p.
Implementation
ByteVector dropWhile(Function1<int, bool> p) {
var toDrop = 0;
_foreachSPartial((i) {
final cont = p(i);
if (cont) toDrop += 1;
return cont;
});
return drop(toDrop);
}endsWith()
bool endsWith(ByteVector b)Returns true if this vector ends with b.
Implementation
bool endsWith(ByteVector b) => takeRight(b.size) == b;foldLeft()
A foldLeft<A>(A z, A Function(A, int) f)Left-folds over each byte, accumulating from z using f.
Implementation
A foldLeft<A>(A z, Function2<A, int, A> f) {
var acc = z;
_foreachS((b) => acc = f(acc, b));
return acc;
}foldRight()
A foldRight<A>(A init, A Function(int, A) f)Right-folds over each byte, accumulating from init using f.
Implementation
A foldRight<A>(A init, Function2<int, A, A> f) => reverse.foldLeft(init, (a, b) => f(b, a));foreach()
void foreach(void Function(int) f)Invokes f for each byte in order.
Implementation
void foreach(Function1<int, void> f) => _foreachV((v) => v.foreach(f));get()
int get(int index)Returns the byte at index.
Implementation
int get(int index) => _getImpl(index);grouped()
RIterator<ByteVector> grouped(int chunkSize)Partitions this vector into an iterator of non-overlapping chunks of chunkSize bytes. The last chunk may be smaller.
Implementation
RIterator<ByteVector> grouped(int chunkSize) {
if (isEmpty) {
return RIterator.empty();
} else if (size <= chunkSize) {
return RIterator.single(this);
} else {
return RIterator.single(take(chunkSize)).concat(drop(chunkSize).grouped(chunkSize));
}
}indexOfSlice()
Option<int> indexOfSlice(ByteVector slice, [int from = 0])Returns the index of the first occurrence of slice at or after from, or None if not found.
Implementation
Option<int> indexOfSlice(ByteVector slice, [int from = 0]) {
var b = this;
var idx = from;
while (true) {
if (b.startsWith(slice)) {
return Some(idx);
} else if (b.isEmpty) {
return none();
} else {
b = b.tail;
idx += 1;
}
}
}insert()
ByteVector insert(int idx, int b)Inserts byte b at position idx.
Implementation
ByteVector insert(int idx, int b) => take(idx).append(b).concat(drop(idx));lift()
Option<int> lift(int ix)Returns Some(get(ix)) if ix is in bounds, otherwise None.
Implementation
Option<int> lift(int ix) => Option.when(() => 0 <= ix && ix < size, () => get(ix));map()
ByteVector map(int Function(int) f)Returns a new vector with f applied to each byte.
Implementation
ByteVector map(Function1<int, int> f) => ByteVector.viewAt(At((i) => f(get(i))), size);noSuchMethod() inherited
dynamic noSuchMethod(Invocation invocation)Invoked when a nonexistent method or property is accessed.
A dynamic member invocation can attempt to call a member which doesn't exist on the receiving object. Example:
dynamic object = 1;
object.add(42); // Statically allowed, run-time errorThis invalid code will invoke the noSuchMethod method of the integer 1 with an Invocation representing the .add(42) call and arguments (which then throws).
Classes can override noSuchMethod to provide custom behavior for such invalid dynamic invocations.
A class with a non-default noSuchMethod invocation can also omit implementations for members of its interface. Example:
class MockList<T> implements List<T> {
noSuchMethod(Invocation invocation) {
log(invocation);
super.noSuchMethod(invocation); // Will throw.
}
}
void main() {
MockList().add(42);
}This code has no compile-time warnings or errors even though the MockList class has no concrete implementation of any of the List interface methods. Calls to List methods are forwarded to noSuchMethod, so this code will log an invocation similar to Invocation.method(#add, [42]) and then throw.
If a value is returned from noSuchMethod, it becomes the result of the original invocation. If the value is not of a type that can be returned by the original invocation, a type error occurs at the invocation.
The default behavior is to throw a NoSuchMethodError.
Inherited from Object.
Implementation
@pragma("vm:entry-point")
@pragma("wasm:entry-point")
external dynamic noSuchMethod(Invocation invocation);or()
ByteVector or(ByteVector other)Returns a bitwise OR of this vector and other.
Implementation
ByteVector or(ByteVector other) => _zipWithS(other, (b, b2) => b | b2);padLeft()
ByteVector padLeft(int n)Left-pads this vector with zero bytes to a total length of n.
Throws ArgumentError if n is less than size.
Implementation
ByteVector padLeft(int n) {
if (n < size) {
throw ArgumentError('ByteVector.padLeft($n)');
} else {
return ByteVector.low(n - size).concat(this);
}
}padRight()
ByteVector padRight(int n)Right-pads this vector with zero bytes to a total length of n.
Throws ArgumentError if n is less than size.
Implementation
ByteVector padRight(int n) {
if (n < size) {
throw ArgumentError('ByteVector.padRight($n)');
} else {
return concat(ByteVector.low(n - size));
}
}padTo()
ByteVector padTo(int n)Alias for padRight.
Implementation
ByteVector padTo(int n) => padRight(n);patch()
ByteVector patch(int ix, ByteVector b)Replaces bytes at position ix with the contents of b.
Implementation
ByteVector patch(int ix, ByteVector b) => take(ix).concat(b).concat(drop(ix + b.size));prepend()
ByteVector prepend(int byte)Returns a new vector with byte prepended.
Implementation
ByteVector prepend(int byte) => ByteVector([byte]).concat(this);printHexDump()
void printHexDump()Prints a colorized hex dump to stdout.
Implementation
void printHexDump() => HexDumpFormat.defaultFormat.printBytes(this);rotateLeft()
ByteVector rotateLeft(int n)Circularly shifts bits left by n positions.
Implementation
ByteVector rotateLeft(int n) => bits.rotateLeft(n).bytes;rotateRight()
ByteVector rotateRight(int n)Circularly shifts bits right by n positions.
Implementation
ByteVector rotateRight(int n) => bits.rotateRight(n).bytes;shiftLeft()
ByteVector shiftLeft(int n)Left shifts the bits of this vector by n positions.
Implementation
ByteVector shiftLeft(int n) => bits.shiftLeft(n).bytes;shiftRight()
ByteVector shiftRight(int n, bool signExtension)Right shifts the bits by n positions, with optional signExtension.
Implementation
ByteVector shiftRight(int n, bool signExtension) => bits.shiftRight(n, signExtension).bytes;slice()
ByteVector slice(int from, int until)Returns bytes from index from up to (but not including) until.
Implementation
ByteVector slice(int from, int until) => drop(from).take(until - max(0, from));sliding()
RIterator<ByteVector> sliding(int n, [int step = 1])Returns an iterator of n-byte sliding windows, advancing step bytes between consecutive windows.
Implementation
RIterator<ByteVector> sliding(int n, [int step = 1]) {
assert(n > 0 && step > 0, "both n and step must be positive");
RIterator<int> limit(RIterator<int> itr) =>
step < n ? itr.take((size - n) + 1) : itr.takeWhile((i) => i < size);
return limit(RIterator.iterate(0, (x) => x + step)).map((idx) => slice(idx, idx + n));
}splice()
ByteVector splice(int ix, ByteVector b)Inserts b at position ix without removing existing bytes.
Implementation
ByteVector splice(int ix, ByteVector b) => take(ix).concat(b).concat(drop(ix));splitAt()
Record splitAt(int ix)Splits this vector at ix, returning (take(ix), drop(ix)).
Implementation
(ByteVector, ByteVector) splitAt(int ix) => (take(ix), drop(ix));startsWith()
bool startsWith(ByteVector b)Returns true if this vector starts with b.
Implementation
bool startsWith(ByteVector b) => take(b.size) == b;take()
ByteVector take(int n)Returns the first n bytes of this vector.
Implementation
ByteVector take(int n) {
final n1 = max(min(n, size), 0);
if (n1 == size) {
return this;
} else if (n1 == 0) {
return ByteVector.empty;
} else {
ByteVector go(ByteVector accL, ByteVector cur, int n1) {
var currentAccL = accL;
var currentCur = cur;
var currentN1 = n1;
while (true) {
switch (currentCur) {
case _Chunk(bytes: final bs):
return currentAccL.concat(_Chunk(bs.take(currentN1)));
case _Append(left: final l, right: final r):
if (currentN1 > l.size) {
currentAccL = currentAccL.concat(l);
currentCur = r;
currentN1 -= l.size;
} else {
currentCur = l;
}
case final _Chunks c:
currentCur = c.chunks;
case final _Buffer b:
currentCur = b.unbuffer();
}
}
}
return go(ByteVector.empty, this, n1);
}
}takeRight()
ByteVector takeRight(int n)Returns the last n bytes of this vector.
Implementation
ByteVector takeRight(int n) => drop(size - n);takeWhile()
ByteVector takeWhile(bool Function(int) p)Takes the longest prefix of bytes satisfying p.
Implementation
ByteVector takeWhile(Function1<int, bool> p) {
var toTake = 0;
_foreachSPartial((i) {
final cont = p(i);
if (cont) toTake += 1;
return cont;
});
return take(toTake);
}toBase16()
String toBase16([HexAlphabet alphabet = Alphabets.hexLower])Alias for toHex.
Implementation
String toBase16([HexAlphabet alphabet = Alphabets.hexLower]) => toHex(alphabet);toBase32()
String toBase32([Base32Alphabet alphabet = Alphabets.base32])Encodes as a base-32 string using the given alphabet.
Implementation
String toBase32([Base32Alphabet alphabet = Alphabets.base32]) {
const bitsPerChar = 5;
final bytes = toByteArray();
final bldr = StringBuffer();
int bidx = 0;
while ((bidx ~/ 8) < bytes.length) {
final char = alphabet.toChar(_bitsAtOffset(bytes, bidx, bitsPerChar));
bldr.write(char);
bidx += bitsPerChar;
}
if (alphabet.pad != '0') {
final padLen =
(((bytes.length + bitsPerChar - 1) ~/ bitsPerChar * bitsPerChar) - bytes.length) *
8 ~/
bitsPerChar;
var i = 0;
while (i < padLen) {
bldr.write(alphabet.pad);
i += 1;
}
}
return bldr.toString();
}toBase58()
String toBase58([Base58Alphabet alphabet = Alphabets.base58])Encodes as a base-58 string using the given alphabet.
Implementation
String toBase58([Base58Alphabet alphabet = Alphabets.base58]) {
if (isEmpty) {
return '';
} else {
var value = toBigInt(signed: false);
var chars = IList.empty<String>();
final radix = BigInt.from(58);
final ones = IList.fill(takeWhile((b) => b == 0).length, '1');
while (true) {
if (value == BigInt.zero) {
return ones.concat(chars).mkString();
} else {
final div = value ~/ radix;
final rem = value % radix;
value = div;
chars = chars.prepended(alphabet.toChar(rem.toInt()));
}
}
}
}toBase64()
String toBase64([Base64Alphabet alphabet = Alphabets.base64])Encodes as a base-64 string using the given alphabet.
Implementation
String toBase64([Base64Alphabet alphabet = Alphabets.base64]) {
final bytes = toByteArray();
final bldr = StringBuffer();
var idx = 0;
final mod = bytes.length % 3;
while (idx < bytes.length - mod) {
var buffer =
((bytes[idx] & 0x0ff) << 16) | ((bytes[idx + 1] & 0x0ff) << 8) | (bytes[idx + 2] & 0x0ff);
final fourth = buffer & 0x3f;
buffer = buffer >> 6;
final third = buffer & 0x3f;
buffer = buffer >> 6;
final second = buffer & 0x3f;
buffer = buffer >> 6;
final first = buffer;
bldr
..write(alphabet.toChar(first))
..write(alphabet.toChar(second))
..write(alphabet.toChar(third))
..write(alphabet.toChar(fourth));
idx += 3;
}
if (mod == 1) {
var buffer = (bytes[idx] & 0x0ff) << 4;
final second = buffer & 0x3f;
buffer = buffer >> 6;
final first = buffer;
bldr
..write(alphabet.toChar(first))
..write(alphabet.toChar(second));
if (alphabet.pad != '0') {
bldr
..write(alphabet.pad)
..write(alphabet.pad);
}
} else if (mod == 2) {
var buffer = ((bytes[idx] & 0x0ff) << 10) | ((bytes[idx + 1] & 0x0ff) << 2);
final third = buffer & 0x3f;
buffer = buffer >> 6;
final second = buffer & 0x3f;
buffer = buffer >> 6;
final first = buffer;
bldr
..write(alphabet.toChar(first))
..write(alphabet.toChar(second))
..write(alphabet.toChar(third));
if (alphabet.pad != '0') {
bldr.write(alphabet.pad);
}
}
return bldr.toString();
}toBase64NoPad()
String toBase64NoPad()Encodes as base-64 without padding.
Implementation
String toBase64NoPad() => toBase64(Alphabets.base64NoPad);toBase64Url()
String toBase64Url()Encodes as URL-safe base-64.
Implementation
String toBase64Url() => toBase64(Alphabets.base64Url);toBase64UrlNoPad()
String toBase64UrlNoPad()Encodes as URL-safe base-64 without padding.
Implementation
String toBase64UrlNoPad() => toBase64(Alphabets.base64UrlNoPad);toBigInt()
BigInt toBigInt({bool signed = true, Endian ordering = Endian.big})Converts to a BigInt using the given sign and byte ordering.
Implementation
BigInt toBigInt({bool signed = true, Endian ordering = Endian.big}) =>
bits.toBigInt(signed: signed, ordering: ordering);toBin()
String toBin([BinaryAlphabet alphabet = Alphabets.binary])Encodes as a binary string using the given alphabet.
Implementation
String toBin([BinaryAlphabet alphabet = Alphabets.binary]) {
final bldr = StringBuffer();
foreach((b) {
var n = 7;
while (n >= 0) {
final idx = 1 & (b >> n);
bldr.write(alphabet.toChar(idx));
n -= 1;
}
});
return bldr.toString();
}toBitVector()
BitVector toBitVector()Converts this byte vector to a BitVector.
Implementation
BitVector toBitVector() => BitVector.fromByteVector(this);toByteArray()
Uint8List toByteArray()Returns the contents as a Uint8List.
Implementation
Uint8List toByteArray() {
final buf = Uint8List(size);
copyToArray(buf, 0);
return buf;
}toHex()
String toHex([HexAlphabet alphabet = Alphabets.hexLower])Encodes as a hexadecimal string using the given alphabet.
Implementation
String toHex([HexAlphabet alphabet = Alphabets.hexLower]) {
final out = List.filled(size * 2, '');
var i = 0;
foreach((b) {
out[i] = alphabet.toChar(b >> 4 & 0x0f);
out[i + 1] = alphabet.toChar(b & 0x0f);
i += 2;
});
return out.join();
}toHexDump()
String toHexDump()Returns a plain-text hex dump (no ANSI colors).
Implementation
String toHexDump() => HexDumpFormat.noAnsi.renderBytes(this);toHexDumpColorized()
String toHexDumpColorized()Returns a colorized hex dump.
Implementation
String toHexDumpColorized() => HexDumpFormat.defaultFormat.renderBytes(this);toIList()
IList<int> toIList()Returns the contents as an IList of byte values.
Implementation
IList<int> toIList() => IList.fromDart(toByteArray());toInt()
int toInt({Endian ordering = Endian.big})Converts to a signed Dart int using the given byte ordering.
Implementation
int toInt({Endian ordering = Endian.big}) => bits.toInt(ordering: ordering);toString() override
String toString()A string representation of this object.
Some classes have a default textual representation, often paired with a static parse function (like int.parse). These classes will provide the textual representation as their string representation.
Other classes have no meaningful textual representation that a program will care about. Such classes will typically override toString to provide useful information when inspecting the object, mainly for debugging or logging.
Implementation
@override
String toString() {
if (isEmpty) {
return 'ByteVector.empty';
} else if (size < 512) {
return 'ByteVector(${toHex()})';
} else {
return 'ByteVector($size, $hashCode)';
}
}toUnsignedInt()
int toUnsignedInt({Endian ordering = Endian.big})Converts to an unsigned Dart int using the given byte ordering.
Implementation
int toUnsignedInt({Endian ordering = Endian.big}) =>
bits.toInt(signed: false, ordering: ordering);unbuffer()
ByteVector unbuffer()Materializes any buffered appends.
Implementation
ByteVector unbuffer() => this;update()
ByteVector update(int idx, int b)Returns a new vector with the byte at idx replaced by b.
Implementation
ByteVector update(int idx, int b) {
_checkIndex(idx);
return take(idx).append(b).concat(drop(idx + 1));
}xor()
ByteVector xor(ByteVector other)Returns a bitwise XOR of this vector and other.
Implementation
ByteVector xor(ByteVector other) => _zipWithS(other, (b, b2) => b ^ b2);zipWith()
ByteVector zipWith(ByteVector other, int Function(int, int) f)Zips this vector with other element-wise, combining bytes with f.
Implementation
ByteVector zipWith(ByteVector other, Function2<int, int, int> f) => _zipWithS(other, f);zipWithI()
ByteVector zipWithI(ByteVector other, int Function(int, int) op)Zips this vector with other element-wise using op.
Implementation
ByteVector zipWithI(ByteVector other, Function2<int, int, int> op) =>
zipWith(other, (l, r) => op(l, r));Operators
operator &()
ByteVector operator &(ByteVector other)Bitwise AND of this vector and other.
Implementation
ByteVector operator &(ByteVector other) => and(other);operator <<()
ByteVector operator <<(int n)Left shift by n bits.
Implementation
ByteVector operator <<(int n) => shiftLeft(n);operator ==() override
bool operator ==(Object other)The equality operator.
The default behavior for all Objects is to return true if and only if this object and other are the same object.
Override this method to specify a different equality relation on a class. The overriding method must still be an equivalence relation. That is, it must be:
Total: It must return a boolean for all arguments. It should never throw.
Reflexive: For all objects
o,o == omust be true.Symmetric: For all objects
o1ando2,o1 == o2ando2 == o1must either both be true, or both be false.Transitive: For all objects
o1,o2, ando3, ifo1 == o2ando2 == o3are true, theno1 == o3must be true.
The method should also be consistent over time, so whether two objects are equal should only change if at least one of the objects was modified.
If a subclass overrides the equality operator, it should override the hashCode method as well to maintain consistency.
Implementation
@override
bool operator ==(Object other) {
if (other is ByteVector) {
if (identical(this, other)) {
return true;
} else {
final s = size;
if (s != other.size) {
return false;
} else {
var i = 0;
while (i < s) {
if (get(i) == other.get(i)) {
i += 1;
} else {
return false;
}
}
return true;
}
}
} else {
return false;
}
}operator >>()
ByteVector operator >>(int n)Arithmetic right shift by n bits (sign-extending).
Implementation
ByteVector operator >>(int n) => shiftRight(n, true);operator >>>()
ByteVector operator >>>(int n)Logical right shift by n bits (zero-filling).
Implementation
ByteVector operator >>>(int n) => shiftRight(n, false);operator
int operator [](int idx)Returns the byte at idx.
Implementation
int operator [](int idx) => _getImpl(idx);operator ^()
ByteVector operator ^(ByteVector other)Bitwise XOR of this vector and other.
Implementation
ByteVector operator ^(ByteVector other) => xor(other);operator |()
ByteVector operator |(ByteVector other)Bitwise OR of this vector and other.
Implementation
ByteVector operator |(ByteVector other) => or(other);operator ~()
ByteVector operator ~()Bitwise NOT. Returns the complement of this vector.
Implementation
ByteVector operator ~() => not;Static Properties
empty final
final ByteVector emptyAn empty byte vector containing zero bytes.
Implementation
static final ByteVector empty = _Chunk(_View.empty());Static Methods
fromBase32()
Option<ByteVector> fromBase32(
String s, [
Base32Alphabet alphabet = Alphabets.base32,
])Decodes a base-32 string into a ByteVector, returning None on failure.
Implementation
static Option<ByteVector> fromBase32(
String s, [
Base32Alphabet alphabet = Alphabets.base32,
]) => fromBase32Descriptive(s, alphabet).toOption();fromBase32Descriptive()
Either<String, ByteVector> fromBase32Descriptive(
String str, [
Base32Alphabet alphabet = Alphabets.base32,
])Decodes a base-32 string, returning a descriptive error on failure.
Implementation
static Either<String, ByteVector> fromBase32Descriptive(
String str, [
Base32Alphabet alphabet = Alphabets.base32,
]) => fromBase32Internal(str, alphabet).map((a) => a.$1);fromBase58()
Option<ByteVector> fromBase58(
String s, [
Base58Alphabet alphabet = Alphabets.base58,
])Decodes a base-58 string into a ByteVector, returning None on failure.
Implementation
static Option<ByteVector> fromBase58(
String s, [
Base58Alphabet alphabet = Alphabets.base58,
]) => fromBase58Descriptive(s, alphabet).toOption();fromBase58Descriptive()
Either<String, ByteVector> fromBase58Descriptive(
String str, [
Base58Alphabet alphabet = Alphabets.base58,
])Decodes a base-58 string, returning a descriptive error on failure.
Implementation
static Either<String, ByteVector> fromBase58Descriptive(
String str, [
Base58Alphabet alphabet = Alphabets.base58,
]) {
final zeroLength = str.takeWhile((c) => c == '1').length;
final zeroes = ByteVector.fill(zeroLength, 0);
final trim = str.splitAt(zeroLength).$2.split('').toIList();
final radix = BigInt.from(58);
try {
final decoded = trim.foldLeft(BigInt.zero, (a, c) {
try {
return a * radix + BigInt.from(alphabet.toIndex(c));
} catch (_) {
final idx = trim.takeWhile((x) => x != c).length;
throw ArgumentError("Invalid base 58 character '$c' at index $idx");
}
});
if (trim.isEmpty) {
return zeroes.asRight();
} else {
return zeroes
.concat(ByteVector.fromValidBin(decoded.toRadixString(2).dropWhile((c) => c == '0')))
.asRight();
}
} catch (e) {
return e.toString().asLeft();
}
}fromBase64()
Option<ByteVector> fromBase64(
String s, [
Base64Alphabet alphabet = Alphabets.base64,
])Decodes a base-64 string into a ByteVector, returning None on failure.
Implementation
static Option<ByteVector> fromBase64(
String s, [
Base64Alphabet alphabet = Alphabets.base64,
]) => fromBase64Descriptive(s, alphabet).toOption();fromBase64Descriptive()
Either<String, ByteVector> fromBase64Descriptive(
String str, [
Base64Alphabet alphabet = Alphabets.base64,
])Decodes a base-64 string, returning a descriptive error on failure.
Implementation
static Either<String, ByteVector> fromBase64Descriptive(
String str, [
Base64Alphabet alphabet = Alphabets.base64,
]) => fromBase64Internal(str, alphabet).map((a) => a.$1);fromBin()
Option<ByteVector> fromBin(String s)Decodes a binary string into a ByteVector, returning None on failure.
Implementation
static Option<ByteVector> fromBin(String s) => fromBinDescriptive(s).toOption();fromBinDescriptive()
Either<String, ByteVector> fromBinDescriptive(
String str, [
BinaryAlphabet alphabet = Alphabets.binary,
])Decodes a binary string, returning a descriptive error on failure.
Implementation
static Either<String, ByteVector> fromBinDescriptive(
String str, [
BinaryAlphabet alphabet = Alphabets.binary,
]) => fromBinInternal(str, alphabet).map((a) => a.$1);fromHex()
Option<ByteVector> fromHex(
String s, [
HexAlphabet alphabet = Alphabets.hexLower,
])Decodes a hex string into a ByteVector, returning None on failure.
Implementation
static Option<ByteVector> fromHex(
String s, [
HexAlphabet alphabet = Alphabets.hexLower,
]) => fromHexDescriptive(s, alphabet).toOption();fromHexDescriptive()
Either<String, ByteVector> fromHexDescriptive(
String str, [
HexAlphabet alphabet = Alphabets.hexLower,
])Decodes a hex string, returning a descriptive error on failure.
Implementation
static Either<String, ByteVector> fromHexDescriptive(
String str, [
HexAlphabet alphabet = Alphabets.hexLower,
]) => fromHexInternal(str, alphabet).map((a) => a.$1);fromValidBase32()
ByteVector fromValidBase32(
String s, [
Base32Alphabet alphabet = Alphabets.base32,
])Decodes a base-32 string into a ByteVector, throwing on failure.
Implementation
static ByteVector fromValidBase32(
String s, [
Base32Alphabet alphabet = Alphabets.base32,
]) => fromBase32Descriptive(s, alphabet).fold((err) => throw ArgumentError(err), identity);fromValidBase58()
ByteVector fromValidBase58(
String s, [
Base58Alphabet alphabet = Alphabets.base58,
])Decodes a base-58 string into a ByteVector, throwing on failure.
Implementation
static ByteVector fromValidBase58(
String s, [
Base58Alphabet alphabet = Alphabets.base58,
]) => fromBase58Descriptive(s, alphabet).fold((err) => throw ArgumentError(err), identity);fromValidBase64()
ByteVector fromValidBase64(
String s, [
Base64Alphabet alphabet = Alphabets.base64,
])Decodes a base-64 string into a ByteVector, throwing on failure.
Implementation
static ByteVector fromValidBase64(
String s, [
Base64Alphabet alphabet = Alphabets.base64,
]) => fromBase64Descriptive(s, alphabet).fold((err) => throw ArgumentError(err), identity);fromValidBin()
ByteVector fromValidBin(String s, [BinaryAlphabet alphabet = Alphabets.binary])Decodes a binary string into a ByteVector, throwing on failure.
Implementation
static ByteVector fromValidBin(
String s, [
BinaryAlphabet alphabet = Alphabets.binary,
]) => fromBinDescriptive(s, alphabet).fold((err) => throw ArgumentError(err), identity);fromValidHex()
ByteVector fromValidHex(String s, [HexAlphabet alphabet = Alphabets.hexLower])Decodes a hex string into a ByteVector, throwing on failure.
Implementation
static ByteVector fromValidHex(
String s, [
HexAlphabet alphabet = Alphabets.hexLower,
]) => fromHexDescriptive(s, alphabet).fold((err) => throw ArgumentError(err), identity);