protodef
Version:
A simple yet powerful way to define binary protocols
86 lines (75 loc) • 2.51 kB
JavaScript
function getField (countField, context) {
const countFieldArr = countField.split('/')
let i = 0
if (countFieldArr[i] === '') {
while (context['..'] !== undefined) { context = context['..'] }
i++
}
for (; i < countFieldArr.length; i++) { context = context[countFieldArr[i]] }
return context
}
function getFieldInfo (fieldInfo) {
if (typeof fieldInfo === 'string') { return { type: fieldInfo } } else if (Array.isArray(fieldInfo)) { return { type: fieldInfo[0], typeArgs: fieldInfo[1] } } else if (typeof fieldInfo.type === 'string') { return fieldInfo } else { throw new Error('Not a fieldinfo') }
}
function getCount (buffer, offset, { count, countType }, rootNode) {
let c = 0
let size = 0
if (typeof count === 'number') { c = count } else if (typeof count !== 'undefined') {
c = getField(count, rootNode)
} else if (typeof countType !== 'undefined') {
({ size, value: c } = tryDoc(() => this.read(buffer, offset, getFieldInfo(countType), rootNode), '$count'))
} else { // TODO : broken schema, should probably error out.
c = 0
}
return { count: c, size }
}
function sendCount (len, buffer, offset, { count, countType }, rootNode) {
if (typeof count !== 'undefined' && len !== count) {
// TODO: Throw
} else if (typeof countType !== 'undefined') {
offset = this.write(len, buffer, offset, getFieldInfo(countType), rootNode)
} else {
// TODO: Throw
}
return offset
}
function calcCount (len, { count, countType }, rootNode) {
if (typeof count === 'undefined' && typeof countType !== 'undefined') { return tryDoc(() => this.sizeOf(len, getFieldInfo(countType), rootNode), '$count') } else { return 0 }
}
function addErrorField (e, field) {
e.field = e.field ? field + '.' + e.field : field
throw e
}
function tryCatch (tryfn, catchfn) {
try { return tryfn() } catch (e) { catchfn(e) }
}
function tryDoc (tryfn, field) {
return tryCatch(tryfn, (e) => addErrorField(e, field))
}
class ExtendableError extends Error {
constructor (message) {
super(message)
this.name = this.constructor.name
this.message = message
if (Error.captureStackTrace != null) {
Error.captureStackTrace(this, this.constructor.name)
}
}
}
class PartialReadError extends ExtendableError {
constructor (message) {
super(message)
this.partialReadError = true
}
}
module.exports = {
getField,
getFieldInfo,
addErrorField,
getCount,
sendCount,
calcCount,
tryCatch,
tryDoc,
PartialReadError
}