All files / src/utils bytes.ts

84.37% Statements 27/32
75% Branches 9/12
84.61% Functions 11/13
84.37% Lines 27/32

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 8733x   33x 33x   33x         9003x 431x 8572x 5524x 3048x     3048x   8995x   8995x 8290x 1045x         7245x             2x       5x       50x 36x     14x       4x       2390x       626x               8x       186x       17x               3x      
import { Binary, Types } from 'cafe-utility'
 
const DECODER = new TextDecoder()
const ENCODER = new TextEncoder()
 
export class Bytes {
  protected readonly bytes: Uint8Array
  public readonly length: number
 
  constructor(bytes: Uint8Array | ArrayBuffer | string | Bytes, byteLength?: number | number[]) {
    if (bytes instanceof Bytes) {
      this.bytes = bytes.bytes
    } else if (typeof bytes === 'string') {
      this.bytes = Binary.hexToUint8Array(Types.asHexString(bytes, { name: 'Bytes#constructor(bytes)' }))
    } else Iif (bytes instanceof ArrayBuffer) {
      this.bytes = new Uint8Array(bytes)
    } else {
      this.bytes = bytes
    }
    this.length = this.bytes.length
 
    if (byteLength) {
      if (Array.isArray(byteLength)) {
        Iif (!byteLength.includes(this.length)) {
          throw new Error(
            `Bytes#checkByteLength: bytes length is ${this.length} but expected ${byteLength.join(' or ')}`,
          )
        }
      } else Iif (this.length !== byteLength) {
        throw new Error(`Bytes#checkByteLength: bytes length is ${this.length} but expected ${byteLength}`)
      }
    }
  }
 
  static keccak256(bytes: Uint8Array | ArrayBuffer | string | Bytes): Bytes {
    return new Bytes(Binary.keccak256(new Bytes(bytes).toUint8Array()))
  }
 
  static fromUtf8(utf8: string): Bytes {
    return new Bytes(ENCODER.encode(utf8))
  }
 
  static fromSlice(bytes: Uint8Array, start: number, length?: number): Bytes {
    if (length === undefined) {
      return new Bytes(bytes.slice(start))
    }
 
    return new Bytes(bytes.slice(start, start + length))
  }
 
  offset(index: number): Uint8Array {
    return new Uint8Array(this.bytes.slice(index))
  }
 
  public toUint8Array(): Uint8Array {
    return new Uint8Array(this.bytes)
  }
 
  public toHex(): string {
    return Binary.uint8ArrayToHex(this.bytes)
  }
 
  public toBase64(): string {
    return Binary.uint8ArrayToBase64(this.bytes)
  }
 
  public toBase32(): string {
    return Binary.uint8ArrayToBase32(this.bytes)
  }
 
  public toString(): string {
    return this.toHex()
  }
 
  public toUtf8(): string {
    return DECODER.decode(this.bytes)
  }
 
  public toJSON(): unknown {
    return JSON.parse(this.toUtf8())
  }
 
  public equals(other: Bytes | Uint8Array | string): boolean {
    return this.toHex() === new Bytes(other).toHex()
  }
}