У меня есть полезная нагрузка 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.
Вы можете добавить свойство «длина», а затем превратить его в настоящий массив с помощью 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
}
Обратите внимание, что приведенный выше код делает в основном то же самое, что и ваш код, но он не будет медленным, если только этот «сырой» материал не имеет размера в мегабайтах. (В этом случае все, что вы с ним делаете, также будет соответствовать этому размеру.)