Cbor.js декодирует BYTES в ассоциативный объект вместо Array/TypedArray

У меня есть полезная нагрузка CBOR, содержащая MAP с полем BYTES:

// simplified testcase:
var data = [0xBF, 0x63, 0x72, 0x61, 0x77, 0x58, 0x10, 0x00,
            0xFF, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF,
            0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0xFF]

CBOR-диагностика:

BF                                     # map(*)
   63                                  # text(3)
      726177                           # "raw"
   58 10                               # bytes(16)
      00FF00FF0000FFFFFFFFFFFF000000FF# [16 bytes]
   FF                                  # end of map(*)

или, в стандартной записи объекта: {"raw": h'00FF00FF0000FFFFFFFFFFFF000000FF'}

Когда я декодирую приведенную выше полезную нагрузку в JavaScript (используя cbor.js):

// prepare an ArrayBuffer to pass to CBOR.decode:
var buf = new ArrayBuffer(data.length)
var bi = new Int8Array(buf)
for(var i = 0; i < data.length; i++) bi[i] = data[i]

var decoded = CBOR.decode(buf)
console.info('decoded:', JSON.stringify(decoded))
console.info('isArray:', Array.isArray(decoded.raw))

«необработанное» поле — это не настоящий Array (для которого Array.isArray(...) вернет true), а «объективированная» версия такого массива:

декодировано: {"raw":{"0":0, "1":255, "2":0, "3":255, "4":0, "5":0, "6":255, "7":255, "8":255, "9":255, "10":255, "11":255, "12":0, "13":0, "14":0,"15 ":255}}

isArray: ложь

это вызывает у меня некоторые проблемы, так как позже мне понадобится правильный тип Array (или TypedArray) для передачи в движок JavaScript QML, и этот «объективированный» объект не принимается; Мне нужно вручную преобразовать в правильный массив:

if (!Array.isArray(texture.raw)) {
    console.warn(`Texture data is not an array. Conversion will be slow!`)
    var data = new Array(Object.keys(texture.raw).length)
    for(var k in texture.raw)
        data[k] = texture.raw[k]
    root.textureData = data
} else {
    root.textureData = texture.raw
}

но это очень медленно.

Можно ли сделать что-нибудь лучше? например более быстрое преобразование? инструкция для cbor.js для его правильного декодирования? что-то другое?

🤔 А знаете ли вы, что...
С помощью JavaScript можно создавать клиентские приложения для мобильных устройств с использованием фреймворков, таких как React Native и NativeScript.


51
1

Ответ:

Решено

Вы можете добавить свойство «длина», а затем превратить его в настоящий массив с помощью Array.from():

if (!Array.isArray(texture.raw)) {
    const rlen = Object.keys(texture.raw).length;
    texture.raw.length = rlen;
    root.textureData = Array.from(texture.raw);
} 
else {
    root.textureData = texture.raw
}

Обратите внимание, что приведенный выше код делает в основном то же самое, что и ваш код, но он не будет медленным, если только этот «сырой» материал не имеет размера в мегабайтах. (В этом случае все, что вы с ним делаете, также будет соответствовать этому размеру.)