ProtoDef-io / node-protodef

Describe your protocol, and read it with ease.
MIT License
31 stars 18 forks source link

String encoding not working #139

Open Dinhero21 opened 1 year ago

Dinhero21 commented 1 year ago

I am trying to encode a utf16 string in protodef but when I do

"string": [
  "pstring", {
    "countType": "u16"
  }
]

it will encode a utf8 string and when I add

"string": [
  "pstring", {
    "countType": "u16",
    "encoding": "utf16"
  }
]

it will just give a validation error

Here is the validation error in case you need it:

{
  "keyword": "enum",
  "dataPath": "",
  "schemaPath": "#/oneOf/0/enum",
  "params": {
    "allowedValues": [
      "native"
    ]
  },
  "message": "should be equal to one of the allowed values",
  "schema": [
    "native"
  ],
  "parentSchema": {
    "enum": [
      "native"
    ]
  },
  "data": [
    "pstring",
    {
      "countType": "u16",
      "encoding": "utf16"
    }
  ]
}
Dinhero21 commented 1 year ago

I fixed my issue by creating my custom implementation:

function read (buffer: Buffer, offset: number): { value: string, size: number } {
  buffer = buffer.subarray(offset)

  const uint16Array = bufferToUint16Array(buffer)

  const length = uint16Array[0]

  const messageUint16Array = uint16Array.subarray(1, length + 1)

  const messageBuffer = uint16ArrayToBuffer(messageUint16Array)
  messageBuffer.swap16()

  const message = messageBuffer.toString('utf16le')

  return {
    value: message,
    size: size(message)
  }
}

function write (value: string, buffer: Buffer, offset: number): number {
  const messageBuffer = Buffer.from(value, 'utf16le')
  messageBuffer.swap16()

  const messageUint16Array = bufferToUint16Array(messageBuffer)

  const length = value.length
  const uint16Array = new Uint16Array([length, ...messageUint16Array])

  const encodedBuffer = uint16ArrayToBuffer(uint16Array)

  encodedBuffer.copy(buffer, offset)

  return offset + encodedBuffer.length
}

function size (value: string): number {
  return (value.length + 1) * 2
}

It fixes my problem but it would still be nice to have the option to do it natively.