Skip to content

ByteVector sealed

sealedclassByteVector

An 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.

dart
final bv = ByteVector.fromValidHex('deadbeef');
print(bv.size);    // 4
print(bv.toHex());  // 'deadbeef'

See also:

  • BitVector, which operates at bit granularity.

Constructors

ByteVector() factory

factoryByteVector(List<int>bytes)

Creates a ByteVector from a list of byte values.

Implementation
dart
factory ByteVector(List<int> bytes) =>
    _Chunk(_View(At.array(Uint8List.fromList(bytes)), 0, bytes.length));

ByteVector.concatAll() factory

factoryByteVector.concatAll(IList<ByteVector>bvs)

Creates a byte vector by concatenating all vectors in bvs.

Implementation
dart
factory ByteVector.concatAll(IList<ByteVector> bvs) =>
    bvs.foldLeft(ByteVector.empty, (acc, bv) => acc.concat(bv));

ByteVector.fill() factory

factoryByteVector.fill(intsize,intbyte)

Creates a size-byte vector with every byte set to byte.

Implementation
dart
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

factoryByteVector.from(RIterableOnce<int>bs)

Creates a byte vector from a sequence of bytes.

Implementation
dart
factory ByteVector.from(RIterableOnce<int> bs) => ByteVector(bs.toList());

ByteVector.fromBigInt() factory

factoryByteVector.fromBigInt(BigIntvalue, {Option<int>size= const None(),Endianordering= 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
dart
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

factoryByteVector.fromDart(Iterable<int>bs)

Creates a byte vector from a Dart iterable of bytes.

Implementation
dart
factory ByteVector.fromDart(Iterable<int> bs) => ByteVector(bs.toList());

ByteVector.fromInt() factory

factoryByteVector.fromInt(inti, {intsize=4,Endianordering= 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
dart
factory ByteVector.fromInt(
  int i, {
  int size = 4,
  Endian ordering = Endian.big,
}) => BitVector.fromInt(i, size: size * 8, ordering: ordering).bytes;

ByteVector.high() factory

factoryByteVector.high(intsize)

Creates a size-byte vector with all bytes set to 0xFF.

Implementation
dart
factory ByteVector.high(int size) => ByteVector.fill(size, 0xff);

ByteVector.low() factory

factoryByteVector.low(intsize)

Creates a size-byte vector with all bytes set to 0x00.

Implementation
dart
factory ByteVector.low(int size) => ByteVector.fill(size, 0x00);

ByteVector.of() factory

factoryByteVector.of(intbyte)

Creates a single-byte vector containing byte.

Implementation
dart
factory ByteVector.of(int byte) => ByteVector.fill(1, byte);

ByteVector.view() factory

factoryByteVector.view(Uint8Listbytes)

Creates a byte vector backed by the given Uint8List without copying.

Implementation
dart
factory ByteVector.view(Uint8List bytes) =>
    _Chunk(_View(At.array(Uint8List.view(bytes.buffer)), 0, bytes.length));

ByteVector.viewAt() factory

factoryByteVector.viewAt(Atat,intsize)

Creates a byte vector backed by an At accessor with the given size.

Implementation
dart
factory ByteVector.viewAt(At at, int size) => _Chunk(_View(at, 0, size));

Properties

bits no setter

BitVectorgetbits

Returns a BitVector view of these bytes.

Implementation
dart
BitVector get bits => toBitVector();

hashCode no setter override

intgethashCode

The 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
dart
@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

intgethead

Returns the first byte, or throws if empty.

Implementation
dart
int get head => get(0);

headOption no setter

Option<int>getheadOption

Returns Some(head) if non-empty, otherwise None.

Implementation
dart
Option<int> get headOption => size > 0 ? Some(head) : none();

init no setter

ByteVectorgetinit

Returns all bytes except the last.

Implementation
dart
ByteVector get init => dropRight(1);

isEmpty no setter

boolgetisEmpty

Returns true if this vector contains no bytes.

Implementation
dart
bool get isEmpty => size == 0;

last no setter

intgetlast

Returns the last byte, or throws if empty.

Implementation
dart
int get last => get(size - 1);

lastOption no setter

Option<int>getlastOption

Returns Some(last) if non-empty, otherwise None.

Implementation
dart
Option<int> get lastOption => lift(size - 1);

length no setter

intgetlength

Alias for size.

Implementation
dart
int get length => size;

nonEmpty no setter

boolgetnonEmpty

Returns true if this vector contains at least one byte.

Implementation
dart
bool get nonEmpty => !isEmpty;

not no setter

Returns the bitwise complement of this vector.

Implementation
dart
ByteVector get not => _mapS((b) => ~b);

reverse no setter

ByteVectorgetreverse

Returns a vector with bytes in reverse order.

Implementation
dart
ByteVector get reverse => ByteVector.viewAt(At((i) => get(size - i - 1)), size);

runtimeType no setter inherited

TypegetruntimeType

A representation of the runtime type of the object.

Inherited from Object.

Implementation
dart
external Type get runtimeType;

size no setter

intgetsize

The number of bytes in this vector.

Implementation
dart
int get size;

tail no setter

ByteVectorgettail

Returns all bytes except the first.

Implementation
dart
ByteVector get tail => drop(1);

Methods

acquire()

Either<String,ByteVector>acquire(intbytes)

Returns the first bytes from this vector, or an error if there are fewer than bytes available.

Implementation
dart
Either<String, ByteVector> acquire(int bytes) => Either.cond(
  () => size >= bytes,
  () => take(bytes),
  () => 'Cannot acquire $bytes bytes from ByteVector of size $size',
);

and()

Returns a bitwise AND of this vector and other.

Implementation
dart
ByteVector and(ByteVector other) => _zipWithS(other, (b, b2) => b & b2);

append()

ByteVectorappend(intbyte)

Returns a new vector with byte appended.

Implementation
dart
ByteVector append(int byte) => concat(ByteVector.of(byte));

bufferBy()

ByteVectorbufferBy([intchunkSize=1024])

Returns a buffered version that amortizes appends by collecting them into internal chunks of chunkSize bytes.

Implementation
dart
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()

ByteVectorcompact()

Returns a single-chunk copy of this vector if not already compacted.

Implementation
dart
ByteVector compact() {
  return switch (this) {
    final _Chunk _ => this,
    _ => copy(),
  };
}

concat()

Concatenates other to the end of this vector.

Implementation
dart
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>(intn,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
dart
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()

boolcontainsSlice(ByteVectorslice)

Returns true if this vector contains slice as a contiguous subsequence.

Implementation
dart
bool containsSlice(ByteVector slice) => indexOfSlice(slice).isDefined;

copy()

Returns a guaranteed fresh copy of this vector's bytes.

Implementation
dart
ByteVector copy() {
  final sz = size;
  final arr = toByteArray();
  return _Chunk(_View(At.array(arr), 0, sz));
}

copyToArray()

voidcopyToArray(Uint8Listxs,intstart)

Copies the bytes into xs starting at offset start.

Implementation
dart
void copyToArray(Uint8List xs, int start) {
  var i = start;

  _foreachV((v) {
    v.copyToArray(xs, i);
    i += v.size;
  });
}

drop()

ByteVectordrop(intn)

Returns a vector of all bytes except the first n.

Implementation
dart
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()

ByteVectordropRight(intn)

Returns all bytes except the last n.

Implementation
dart
ByteVector dropRight(int n) => take(size - max(0, n));

dropWhile()

ByteVectordropWhile(boolFunction(int)p)

Drops the longest prefix of bytes satisfying p.

Implementation
dart
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()

boolendsWith(ByteVectorb)

Returns true if this vector ends with b.

Implementation
dart
bool endsWith(ByteVector b) => takeRight(b.size) == b;

foldLeft()

AfoldLeft<A>(Az,AFunction(A,int)f)

Left-folds over each byte, accumulating from z using f.

Implementation
dart
A foldLeft<A>(A z, Function2<A, int, A> f) {
  var acc = z;
  _foreachS((b) => acc = f(acc, b));
  return acc;
}

foldRight()

AfoldRight<A>(Ainit,AFunction(int,A)f)

Right-folds over each byte, accumulating from init using f.

Implementation
dart
A foldRight<A>(A init, Function2<int, A, A> f) => reverse.foldLeft(init, (a, b) => f(b, a));

foreach()

voidforeach(voidFunction(int)f)

Invokes f for each byte in order.

Implementation
dart
void foreach(Function1<int, void> f) => _foreachV((v) => v.foreach(f));

get()

intget(intindex)

Returns the byte at index.

Implementation
dart
int get(int index) => _getImpl(index);

grouped()

RIterator<ByteVector>grouped(intchunkSize)

Partitions this vector into an iterator of non-overlapping chunks of chunkSize bytes. The last chunk may be smaller.

Implementation
dart
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(ByteVectorslice, [intfrom=0])

Returns the index of the first occurrence of slice at or after from, or None if not found.

Implementation
dart
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()

ByteVectorinsert(intidx,intb)

Inserts byte b at position idx.

Implementation
dart
ByteVector insert(int idx, int b) => take(idx).append(b).concat(drop(idx));

lift()

Option<int>lift(intix)

Returns Some(get(ix)) if ix is in bounds, otherwise None.

Implementation
dart
Option<int> lift(int ix) => Option.when(() => 0 <= ix && ix < size, () => get(ix));

map()

ByteVectormap(intFunction(int)f)

Returns a new vector with f applied to each byte.

Implementation
dart
ByteVector map(Function1<int, int> f) => ByteVector.viewAt(At((i) => f(get(i))), size);

noSuchMethod() inherited

dynamicnoSuchMethod(Invocationinvocation)

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:

dart
dynamic object = 1;
object.add(42); // Statically allowed, run-time error

This 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:

dart
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
dart
@pragma("vm:entry-point")
@pragma("wasm:entry-point")
external dynamic noSuchMethod(Invocation invocation);

or()

Returns a bitwise OR of this vector and other.

Implementation
dart
ByteVector or(ByteVector other) => _zipWithS(other, (b, b2) => b | b2);

padLeft()

ByteVectorpadLeft(intn)

Left-pads this vector with zero bytes to a total length of n.

Throws ArgumentError if n is less than size.

Implementation
dart
ByteVector padLeft(int n) {
  if (n < size) {
    throw ArgumentError('ByteVector.padLeft($n)');
  } else {
    return ByteVector.low(n - size).concat(this);
  }
}

padRight()

ByteVectorpadRight(intn)

Right-pads this vector with zero bytes to a total length of n.

Throws ArgumentError if n is less than size.

Implementation
dart
ByteVector padRight(int n) {
  if (n < size) {
    throw ArgumentError('ByteVector.padRight($n)');
  } else {
    return concat(ByteVector.low(n - size));
  }
}

padTo()

ByteVectorpadTo(intn)

Alias for padRight.

Implementation
dart
ByteVector padTo(int n) => padRight(n);

patch()

ByteVectorpatch(intix,ByteVectorb)

Replaces bytes at position ix with the contents of b.

Implementation
dart
ByteVector patch(int ix, ByteVector b) => take(ix).concat(b).concat(drop(ix + b.size));

prepend()

ByteVectorprepend(intbyte)

Returns a new vector with byte prepended.

Implementation
dart
ByteVector prepend(int byte) => ByteVector([byte]).concat(this);

printHexDump()

voidprintHexDump()

Prints a colorized hex dump to stdout.

Implementation
dart
void printHexDump() => HexDumpFormat.defaultFormat.printBytes(this);

rotateLeft()

ByteVectorrotateLeft(intn)

Circularly shifts bits left by n positions.

Implementation
dart
ByteVector rotateLeft(int n) => bits.rotateLeft(n).bytes;

rotateRight()

ByteVectorrotateRight(intn)

Circularly shifts bits right by n positions.

Implementation
dart
ByteVector rotateRight(int n) => bits.rotateRight(n).bytes;

shiftLeft()

ByteVectorshiftLeft(intn)

Left shifts the bits of this vector by n positions.

Implementation
dart
ByteVector shiftLeft(int n) => bits.shiftLeft(n).bytes;

shiftRight()

ByteVectorshiftRight(intn,boolsignExtension)

Right shifts the bits by n positions, with optional signExtension.

Implementation
dart
ByteVector shiftRight(int n, bool signExtension) => bits.shiftRight(n, signExtension).bytes;

slice()

ByteVectorslice(intfrom,intuntil)

Returns bytes from index from up to (but not including) until.

Implementation
dart
ByteVector slice(int from, int until) => drop(from).take(until - max(0, from));

sliding()

RIterator<ByteVector>sliding(intn, [intstep=1])

Returns an iterator of n-byte sliding windows, advancing step bytes between consecutive windows.

Implementation
dart
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()

ByteVectorsplice(intix,ByteVectorb)

Inserts b at position ix without removing existing bytes.

Implementation
dart
ByteVector splice(int ix, ByteVector b) => take(ix).concat(b).concat(drop(ix));

splitAt()

RecordsplitAt(intix)

Splits this vector at ix, returning (take(ix), drop(ix)).

Implementation
dart
(ByteVector, ByteVector) splitAt(int ix) => (take(ix), drop(ix));

startsWith()

boolstartsWith(ByteVectorb)

Returns true if this vector starts with b.

Implementation
dart
bool startsWith(ByteVector b) => take(b.size) == b;

take()

ByteVectortake(intn)

Returns the first n bytes of this vector.

Implementation
dart
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()

ByteVectortakeRight(intn)

Returns the last n bytes of this vector.

Implementation
dart
ByteVector takeRight(int n) => drop(size - n);

takeWhile()

ByteVectortakeWhile(boolFunction(int)p)

Takes the longest prefix of bytes satisfying p.

Implementation
dart
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()

StringtoBase16([HexAlphabetalphabet= Alphabets.hexLower])

Alias for toHex.

Implementation
dart
String toBase16([HexAlphabet alphabet = Alphabets.hexLower]) => toHex(alphabet);

toBase32()

StringtoBase32([Base32Alphabetalphabet= Alphabets.base32])

Encodes as a base-32 string using the given alphabet.

Implementation
dart
String toBase32([Base32Alphabet alphabet = Alphabets.base32]) {
  const bitsPerChar = 5;

  final bytes = toByteArray();
  final bldr = StringBuffer();

  int bidx = 0;
  while ((bidx ~&#47; 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) ~&#47; bitsPerChar * bitsPerChar) - bytes.length) *
        8 ~&#47;
        bitsPerChar;

    var i = 0;

    while (i < padLen) {
      bldr.write(alphabet.pad);
      i += 1;
    }
  }

  return bldr.toString();
}

toBase58()

StringtoBase58([Base58Alphabetalphabet= Alphabets.base58])

Encodes as a base-58 string using the given alphabet.

Implementation
dart
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 ~&#47; radix;
        final rem = value % radix;

        value = div;
        chars = chars.prepended(alphabet.toChar(rem.toInt()));
      }
    }
  }
}

toBase64()

StringtoBase64([Base64Alphabetalphabet= Alphabets.base64])

Encodes as a base-64 string using the given alphabet.

Implementation
dart
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()

StringtoBase64NoPad()

Encodes as base-64 without padding.

Implementation
dart
String toBase64NoPad() => toBase64(Alphabets.base64NoPad);

toBase64Url()

StringtoBase64Url()

Encodes as URL-safe base-64.

Implementation
dart
String toBase64Url() => toBase64(Alphabets.base64Url);

toBase64UrlNoPad()

StringtoBase64UrlNoPad()

Encodes as URL-safe base-64 without padding.

Implementation
dart
String toBase64UrlNoPad() => toBase64(Alphabets.base64UrlNoPad);

toBigInt()

BigInttoBigInt({boolsigned=true,Endianordering= Endian.big})

Converts to a BigInt using the given sign and byte ordering.

Implementation
dart
BigInt toBigInt({bool signed = true, Endian ordering = Endian.big}) =>
    bits.toBigInt(signed: signed, ordering: ordering);

toBin()

StringtoBin([BinaryAlphabetalphabet= Alphabets.binary])

Encodes as a binary string using the given alphabet.

Implementation
dart
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()

BitVectortoBitVector()

Converts this byte vector to a BitVector.

Implementation
dart
BitVector toBitVector() => BitVector.fromByteVector(this);

toByteArray()

Uint8ListtoByteArray()

Returns the contents as a Uint8List.

Implementation
dart
Uint8List toByteArray() {
  final buf = Uint8List(size);
  copyToArray(buf, 0);
  return buf;
}

toHex()

StringtoHex([HexAlphabetalphabet= Alphabets.hexLower])

Encodes as a hexadecimal string using the given alphabet.

Implementation
dart
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()

StringtoHexDump()

Returns a plain-text hex dump (no ANSI colors).

Implementation
dart
String toHexDump() => HexDumpFormat.noAnsi.renderBytes(this);

toHexDumpColorized()

StringtoHexDumpColorized()

Returns a colorized hex dump.

Implementation
dart
String toHexDumpColorized() => HexDumpFormat.defaultFormat.renderBytes(this);

toIList()

IList<int>toIList()

Returns the contents as an IList of byte values.

Implementation
dart
IList<int> toIList() => IList.fromDart(toByteArray());

toInt()

inttoInt({Endianordering= Endian.big})

Converts to a signed Dart int using the given byte ordering.

Implementation
dart
int toInt({Endian ordering = Endian.big}) => bits.toInt(ordering: ordering);

toString() override

StringtoString()

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
dart
@override
String toString() {
  if (isEmpty) {
    return 'ByteVector.empty';
  } else if (size < 512) {
    return 'ByteVector(${toHex()})';
  } else {
    return 'ByteVector($size, $hashCode)';
  }
}

toUnsignedInt()

inttoUnsignedInt({Endianordering= Endian.big})

Converts to an unsigned Dart int using the given byte ordering.

Implementation
dart
int toUnsignedInt({Endian ordering = Endian.big}) =>
    bits.toInt(signed: false, ordering: ordering);

unbuffer()

ByteVectorunbuffer()

Materializes any buffered appends.

Implementation
dart
ByteVector unbuffer() => this;

update()

ByteVectorupdate(intidx,intb)

Returns a new vector with the byte at idx replaced by b.

Implementation
dart
ByteVector update(int idx, int b) {
  _checkIndex(idx);
  return take(idx).append(b).concat(drop(idx + 1));
}

xor()

Returns a bitwise XOR of this vector and other.

Implementation
dart
ByteVector xor(ByteVector other) => _zipWithS(other, (b, b2) => b ^ b2);

zipWith()

ByteVectorzipWith(ByteVectorother,intFunction(int,int)f)

Zips this vector with other element-wise, combining bytes with f.

Implementation
dart
ByteVector zipWith(ByteVector other, Function2<int, int, int> f) => _zipWithS(other, f);

zipWithI()

ByteVectorzipWithI(ByteVectorother,intFunction(int,int)op)

Zips this vector with other element-wise using op.

Implementation
dart
ByteVector zipWithI(ByteVector other, Function2<int, int, int> op) =>
    zipWith(other, (l, r) => op(l, r));

Operators

operator &()

ByteVectoroperator &(ByteVectorother)

Bitwise AND of this vector and other.

Implementation
dart
ByteVector operator &(ByteVector other) => and(other);

operator <<()

ByteVectoroperator <<(intn)

Left shift by n bits.

Implementation
dart
ByteVector operator <<(int n) => shiftLeft(n);

operator ==() override

booloperator ==(Objectother)

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 == o must be true.

  • Symmetric: For all objects o1 and o2, o1 == o2 and o2 == o1 must either both be true, or both be false.

  • Transitive: For all objects o1, o2, and o3, if o1 == o2 and o2 == o3 are true, then o1 == o3 must 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
dart
@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 >>()

ByteVectoroperator >>(intn)

Arithmetic right shift by n bits (sign-extending).

Implementation
dart
ByteVector operator >>(int n) => shiftRight(n, true);

operator >>>()

ByteVectoroperator >>>(intn)

Logical right shift by n bits (zero-filling).

Implementation
dart
ByteVector operator >>>(int n) => shiftRight(n, false);

operator []()

intoperator [](intidx)

Returns the byte at idx.

Implementation
dart
int operator [](int idx) => _getImpl(idx);

operator ^()

ByteVectoroperator ^(ByteVectorother)

Bitwise XOR of this vector and other.

Implementation
dart
ByteVector operator ^(ByteVector other) => xor(other);

operator |()

ByteVectoroperator |(ByteVectorother)

Bitwise OR of this vector and other.

Implementation
dart
ByteVector operator |(ByteVector other) => or(other);

operator ~()

ByteVectoroperator ~()

Bitwise NOT. Returns the complement of this vector.

Implementation
dart
ByteVector operator ~() => not;

Static Properties

empty final

finalByteVectorempty

An empty byte vector containing zero bytes.

Implementation
dart
static final ByteVector empty = _Chunk(_View.empty());

Static Methods

fromBase32()

Option<ByteVector>fromBase32(Strings, [Base32Alphabetalphabet= Alphabets.base32,]);

Decodes a base-32 string into a ByteVector, returning None on failure.

Implementation
dart
static Option<ByteVector> fromBase32(
  String s, [
  Base32Alphabet alphabet = Alphabets.base32,
]) => fromBase32Descriptive(s, alphabet).toOption();

fromBase32Descriptive()

Either<String,ByteVector>fromBase32Descriptive(Stringstr, [Base32Alphabetalphabet= Alphabets.base32,]);

Decodes a base-32 string, returning a descriptive error on failure.

Implementation
dart
static Either<String, ByteVector> fromBase32Descriptive(
  String str, [
  Base32Alphabet alphabet = Alphabets.base32,
]) => fromBase32Internal(str, alphabet).map((a) => a.$1);

fromBase58()

Option<ByteVector>fromBase58(Strings, [Base58Alphabetalphabet= Alphabets.base58,]);

Decodes a base-58 string into a ByteVector, returning None on failure.

Implementation
dart
static Option<ByteVector> fromBase58(
  String s, [
  Base58Alphabet alphabet = Alphabets.base58,
]) => fromBase58Descriptive(s, alphabet).toOption();

fromBase58Descriptive()

Either<String,ByteVector>fromBase58Descriptive(Stringstr, [Base58Alphabetalphabet= Alphabets.base58,]);

Decodes a base-58 string, returning a descriptive error on failure.

Implementation
dart
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(Strings, [Base64Alphabetalphabet= Alphabets.base64,]);

Decodes a base-64 string into a ByteVector, returning None on failure.

Implementation
dart
static Option<ByteVector> fromBase64(
  String s, [
  Base64Alphabet alphabet = Alphabets.base64,
]) => fromBase64Descriptive(s, alphabet).toOption();

fromBase64Descriptive()

Either<String,ByteVector>fromBase64Descriptive(Stringstr, [Base64Alphabetalphabet= Alphabets.base64,]);

Decodes a base-64 string, returning a descriptive error on failure.

Implementation
dart
static Either<String, ByteVector> fromBase64Descriptive(
  String str, [
  Base64Alphabet alphabet = Alphabets.base64,
]) => fromBase64Internal(str, alphabet).map((a) => a.$1);

fromBin()

Option<ByteVector>fromBin(Strings)

Decodes a binary string into a ByteVector, returning None on failure.

Implementation
dart
static Option<ByteVector> fromBin(String s) => fromBinDescriptive(s).toOption();

fromBinDescriptive()

Either<String,ByteVector>fromBinDescriptive(Stringstr, [BinaryAlphabetalphabet= Alphabets.binary,]);

Decodes a binary string, returning a descriptive error on failure.

Implementation
dart
static Either<String, ByteVector> fromBinDescriptive(
  String str, [
  BinaryAlphabet alphabet = Alphabets.binary,
]) => fromBinInternal(str, alphabet).map((a) => a.$1);

fromHex()

Option<ByteVector>fromHex(Strings, [HexAlphabetalphabet= Alphabets.hexLower,]);

Decodes a hex string into a ByteVector, returning None on failure.

Implementation
dart
static Option<ByteVector> fromHex(
  String s, [
  HexAlphabet alphabet = Alphabets.hexLower,
]) => fromHexDescriptive(s, alphabet).toOption();

fromHexDescriptive()

Either<String,ByteVector>fromHexDescriptive(Stringstr, [HexAlphabetalphabet= Alphabets.hexLower,]);

Decodes a hex string, returning a descriptive error on failure.

Implementation
dart
static Either<String, ByteVector> fromHexDescriptive(
  String str, [
  HexAlphabet alphabet = Alphabets.hexLower,
]) => fromHexInternal(str, alphabet).map((a) => a.$1);

fromValidBase32()

ByteVectorfromValidBase32(Strings, [Base32Alphabetalphabet= Alphabets.base32,]);

Decodes a base-32 string into a ByteVector, throwing on failure.

Implementation
dart
static ByteVector fromValidBase32(
  String s, [
  Base32Alphabet alphabet = Alphabets.base32,
]) => fromBase32Descriptive(s, alphabet).fold((err) => throw ArgumentError(err), identity);

fromValidBase58()

ByteVectorfromValidBase58(Strings, [Base58Alphabetalphabet= Alphabets.base58,]);

Decodes a base-58 string into a ByteVector, throwing on failure.

Implementation
dart
static ByteVector fromValidBase58(
  String s, [
  Base58Alphabet alphabet = Alphabets.base58,
]) => fromBase58Descriptive(s, alphabet).fold((err) => throw ArgumentError(err), identity);

fromValidBase64()

ByteVectorfromValidBase64(Strings, [Base64Alphabetalphabet= Alphabets.base64,]);

Decodes a base-64 string into a ByteVector, throwing on failure.

Implementation
dart
static ByteVector fromValidBase64(
  String s, [
  Base64Alphabet alphabet = Alphabets.base64,
]) => fromBase64Descriptive(s, alphabet).fold((err) => throw ArgumentError(err), identity);

fromValidBin()

ByteVectorfromValidBin(Strings, [BinaryAlphabetalphabet= Alphabets.binary,]);

Decodes a binary string into a ByteVector, throwing on failure.

Implementation
dart
static ByteVector fromValidBin(
  String s, [
  BinaryAlphabet alphabet = Alphabets.binary,
]) => fromBinDescriptive(s, alphabet).fold((err) => throw ArgumentError(err), identity);

fromValidHex()

ByteVectorfromValidHex(Strings, [HexAlphabetalphabet= Alphabets.hexLower,]);

Decodes a hex string into a ByteVector, throwing on failure.

Implementation
dart
static ByteVector fromValidHex(
  String s, [
  HexAlphabet alphabet = Alphabets.hexLower,
]) => fromHexDescriptive(s, alphabet).fold((err) => throw ArgumentError(err), identity);