All files / json-pack/src/cbor CborEncoder.ts

95.55% Statements 43/45
93.54% Branches 29/31
100% Functions 6/6
100% Lines 38/38

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 8218x 18x 18x 18x     18x             26x       1106927x   1002347x   68360x   4668x   28066x 25116x 25116x     13517x   8785x   1394x   129x   1247x   14x 14x 2x 2x     30x 28x 28x 28x 28x 23x         732x   2747x   7x         11536x 11507x       114x 114x 197812x 197812x         674x      
import {isFloat32} from '@jsonjoy.com/buffers/lib/isFloat32';
import {JsonPackExtension} from '../JsonPackExtension';
import {CborEncoderFast} from './CborEncoderFast';
import {JsonPackValue} from '../JsonPackValue';
import type {IWriter, IWriterGrowable} from '@jsonjoy.com/buffers/lib';
 
export class CborEncoder<W extends IWriter & IWriterGrowable = IWriter & IWriterGrowable> extends CborEncoderFast<W> {
  /**
   * Called when the encoder encounters a value that it does not know how to encode.
   *
   * @param value Some JavaScript value.
   */
  public writeUnknown(value: unknown): void {
    this.writeNull();
  }
 
  public writeAny(value: unknown): void {
    switch (typeof value) {
      case 'number':
        return this.writeNumber(value as number);
      case 'string':
        return this.writeStr(value);
      case 'boolean':
        return this.writer.u8(0xf4 + +value);
      case 'object': {
        if (!value) return this.writer.u8(0xf6);
        const constr = value.constructor;
        switch (constr) {
          case Object:
          case undefined:
            return this.writeObj(value as Record<string, unknown>);
          case Array:
            return this.writeArr(value as unknown[]);
          case Uint8Array:
            return this.writeBin(value as Uint8Array);
          case Map:
            return this.writeMap(value as Map<unknown, unknown>);
          case JsonPackExtension:
            return this.writeTag((<JsonPackExtension>value).tag, (<JsonPackExtension>value).val);
          case JsonPackValue: {
            const val = (value as JsonPackValue<unknown>).val;
            if (typeof val === 'number') return this.writeTkn(val);
            const buf = val as Uint8Array;
            return this.writer.buf(buf, buf.length);
          }
          default: {
            if (value instanceof Uint8Array) return this.writeBin(value);
            Iif (Array.isArray(value)) return this.writeArr(value);
            Iif (value instanceof Map) return this.writeMap(value);
            const proto = Object.getPrototypeOf(value);
            if (proto === Object.prototype || proto === null) return this.writeObj(value as Record<string, unknown>);
            return this.writeUnknown(value);
          }
        }
      }
      case 'undefined':
        return this.writeUndef();
      case 'bigint':
        return this.writeBigInt(value as bigint);
      default:
        return this.writeUnknown(value);
    }
  }
 
  public writeFloat(float: number): void {
    if (isFloat32(float)) this.writer.u8f32(0xfa, float);
    else this.writer.u8f64(0xfb, float);
  }
 
  public writeMap(map: Map<unknown, unknown>): void {
    this.writeMapHdr(map.size);
    map.forEach((value, key) => {
      this.writeAny(key);
      this.writeAny(value);
    });
  }
 
  public writeUndef(): void {
    this.writer.u8(0xf7);
  }
}