All files / rpc-codec-binary/src decode.ts

85.71% Statements 54/63
91.66% Branches 22/24
100% Functions 1/1
85.48% Lines 53/62

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 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 1073x 3x                         3x     3x 1476x 1476x 1476x   360x 360x 360x 360x 360x 360x 360x         850x 850x 850x 850x 850x 850x 54x         54x 54x 54x     796x 796x 796x   850x 850x 850x   420x   282x   148x             190x 190x 190x 190x 14x         14x 14x 14x     176x 176x 176x   190x 190x 190x   54x   114x   22x         76x 76x 76x          
import {Uint8ArrayCut} from '@jsonjoy.com/buffers/lib/Uint8ArrayCut';
import {
  NotificationMessage,
  type RxMessage,
  RequestCompleteMessage,
  RequestDataMessage,
  RequestErrorMessage,
  RequestUnsubscribeMessage,
  ResponseCompleteMessage,
  ResponseDataMessage,
  ResponseErrorMessage,
  ResponseUnsubscribeMessage,
} from '@jsonjoy.com/rpc-messages';
import {BinaryMessageType} from './constants';
import {unknown} from '@jsonjoy.com/json-type/lib/value';
import type {IReader} from '@jsonjoy.com/buffers/lib/types';
 
export const decode = (reader: IReader): RxMessage => {
  const word = reader.u32();
  const type = word >>> 29;
  switch (type) {
    case BinaryMessageType.Notification: {
      const z = word & 0xff;
      const x = word >>> 8;
      const name = reader.ascii(z);
      const cut = new Uint8ArrayCut(reader.uint8, reader.x, x);
      const value = unknown(cut);
      reader.skip(x);
      return new NotificationMessage(name, value);
    }
    case BinaryMessageType.RequestData:
    case BinaryMessageType.RequestComplete:
    case BinaryMessageType.RequestError: {
      const z = reader.u8();
      const name = reader.ascii(z);
      const cutStart = reader.x;
      let x = 0,
        y = 0;
      if (word & 0b1_0000_00000000_00000000_00000000) {
        Iif (word & 0b10000000_00000000) {
          x = ((0b1111_11111111 & (word >>> 16)) << 15) | (word & 0b1111111_11111111);
          reader.skip(x);
          y = reader.u16();
        } else {
          x = ((0b1111_11111111 & (word >>> 16)) << 7) | ((word >>> 8) & 0x7f);
          reader.skip(x);
          y = ((word & 0xff) << 8) | reader.u8();
        }
      } else {
        x = (word >>> 16) & 0b1111_11111111;
        y = word & 0xffff;
        reader.skip(x);
      }
      const cut = new Uint8ArrayCut(reader.uint8, cutStart, x);
      const value = unknown(cut);
      switch (type) {
        case BinaryMessageType.RequestData:
          return new RequestDataMessage(y, name, value);
        case BinaryMessageType.RequestComplete:
          return new RequestCompleteMessage(y, name, value);
        case BinaryMessageType.RequestError:
          return new RequestErrorMessage(y, name, value);
      }
      break;
    }
    case BinaryMessageType.ResponseData:
    case BinaryMessageType.ResponseComplete:
    case BinaryMessageType.ResponseError: {
      const cutStart = reader.x;
      let x = 0,
        y = 0;
      if (word & 0b1_0000_00000000_00000000_00000000) {
        Iif (word & 0b10000000_00000000) {
          x = ((0b1111_11111111 & (word >>> 16)) << 15) | (word & 0b1111111_11111111);
          reader.skip(x);
          y = reader.u16();
        } else {
          x = ((0b1111_11111111 & (word >>> 16)) << 7) | ((word >>> 8) & 0x7f);
          reader.skip(x);
          y = ((word & 0xff) << 8) | reader.u8();
        }
      } else {
        x = (word >>> 16) & 0b1111_11111111;
        y = word & 0xffff;
        reader.skip(x);
      }
      const cut = new Uint8ArrayCut(reader.uint8, cutStart, x);
      const value = unknown(cut);
      switch (type) {
        case BinaryMessageType.ResponseData:
          return new ResponseDataMessage(y, value);
        case BinaryMessageType.ResponseComplete:
          return new ResponseCompleteMessage(y, value);
        case BinaryMessageType.ResponseError:
          return new ResponseErrorMessage(y, value);
      }
      break;
    }
    case BinaryMessageType.Control: {
      const isResponse = word & 0b1_00000000_00000000;
      const id = word & 0xffff;
      return isResponse ? new ResponseUnsubscribeMessage(id) : new RequestUnsubscribeMessage(id);
    }
  }
  throw new Error('UNKNOWN_MSG');
};