feat(Sequence)
This commit is contained in:
91
src/Sequence.js
Normal file
91
src/Sequence.js
Normal file
@ -0,0 +1,91 @@
|
||||
import { isHeadless, parse, serialize, sizeof } from '.'
|
||||
import { Type } from './Type'
|
||||
|
||||
export function Sequence(types) {
|
||||
const obj = { _types: types, _headless: false, _sizeof: 0 }
|
||||
Object.setPrototypeOf(obj, Sequence.prototype)
|
||||
obj.new(Sequence, [
|
||||
types.map((arg) => {
|
||||
if (typeof arg == 'function') {
|
||||
return arg.name
|
||||
} else {
|
||||
return arg
|
||||
}
|
||||
}),
|
||||
])
|
||||
|
||||
for (let i = 0; i < types.length; i++) {
|
||||
if (!Array.isArray(types[i])) {
|
||||
types[i] = [types[i]]
|
||||
}
|
||||
obj._headless |= isHeadless(...types[i])
|
||||
if (obj._headless) {
|
||||
obj._sizeof = null
|
||||
} else {
|
||||
obj._sizeof += sizeof(...types[i])
|
||||
}
|
||||
}
|
||||
|
||||
return obj
|
||||
}
|
||||
Sequence.prototype._srcValidate = function (src) {
|
||||
if (!Array.isArray(src) || src.length != this._types.length) {
|
||||
throw new Error(
|
||||
this._name +
|
||||
' source object should be array with length ' +
|
||||
this._types.length,
|
||||
)
|
||||
}
|
||||
}
|
||||
Sequence.prototype.serialize = function (dv, src) {
|
||||
if (dv.byteLength < this.sizeof(src)) {
|
||||
throw new Error(this._name + ' too small buffer')
|
||||
}
|
||||
this._srcValidate(src)
|
||||
|
||||
let offset = 0
|
||||
for (let i = 0; i < src.length; i++) {
|
||||
const item = src[i]
|
||||
const item_types = this._types[i]
|
||||
const item_frame = new DataView(dv.buffer, dv.byteOffset + offset)
|
||||
serialize(item_frame, item, ...item_types)
|
||||
offset += sizeof(item, ...item_types)
|
||||
}
|
||||
}
|
||||
Sequence.prototype.parse = function (dv) {
|
||||
const res = new Array(this._types.length)
|
||||
let offset = 0
|
||||
|
||||
for (let i = 0; i < res.length; i++) {
|
||||
const item_types = this._types[i]
|
||||
const item_frame = new DataView(dv.buffer, dv.byteOffset + offset)
|
||||
res[i] = parse(item_frame, ...item_types)
|
||||
offset += sizeof(res[i], ...item_types)
|
||||
}
|
||||
|
||||
return res
|
||||
}
|
||||
Sequence.prototype.isHeadless = function () {
|
||||
return this._headless
|
||||
}
|
||||
Sequence.prototype.sizeof = function (src) {
|
||||
if (this._headless) {
|
||||
if (src == undefined) {
|
||||
throw new Error('unknown sizeof ' + this._name)
|
||||
}
|
||||
this._srcValidate(src)
|
||||
|
||||
let size = 0
|
||||
for (let i = 0; i < src.length; i++) {
|
||||
const item = src[i]
|
||||
const item_types = this._types[i]
|
||||
size += sizeof(item, ...item_types)
|
||||
}
|
||||
|
||||
return size
|
||||
} else {
|
||||
return this._sizeof
|
||||
}
|
||||
}
|
||||
Object.setPrototypeOf(Sequence.prototype, Type.prototype)
|
||||
Object.freeze(Sequence.prototype)
|
||||
@ -6,13 +6,20 @@ export function Type() {
|
||||
Type.prototype.new = function (func, args) {
|
||||
this._name = func.name
|
||||
if (args !== undefined) {
|
||||
const str_args = Array.from(args).map((arg) => JSON.stringify(arg))
|
||||
const str_args = Array.from(args).map((arg) => {
|
||||
if (typeof arg == 'function') {
|
||||
return arg.name
|
||||
} else {
|
||||
return JSON.stringify(arg)
|
||||
}
|
||||
})
|
||||
this._name += '(' + str_args.join(', ') + ')'
|
||||
}
|
||||
}
|
||||
Type.prototype.toString = function () {
|
||||
return this._name
|
||||
}
|
||||
Type.prototype.toJSON = Type.prototype.toString
|
||||
Type.prototype.serialize = function () {
|
||||
throw new Error('should be overloaded')
|
||||
}
|
||||
|
||||
@ -5,6 +5,7 @@ import { Int } from './Int'
|
||||
import { ConstString } from './ConstString'
|
||||
import { ConstArray } from './ConstArray'
|
||||
import { ConstDataView } from './ConstDataView'
|
||||
import { Sequence } from './Sequence'
|
||||
import { Struct } from './Struct'
|
||||
|
||||
export {
|
||||
@ -15,6 +16,7 @@ export {
|
||||
ConstString,
|
||||
ConstArray,
|
||||
ConstDataView,
|
||||
Sequence,
|
||||
Struct,
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user