protodef
Version:
A simple yet powerful way to define binary protocols
125 lines (95 loc) • 3.79 kB
Markdown
# New datatypes
You can create new datatypes for Protodef.
Three functions need to be created to define a datatype.
An optional `schema` property can be added to validate whether the type is used properly in new types.
It must be defined as a json schema. See the [ProtoDef](https://github.com/ProtoDef-io/ProtoDef) repo for schema examples of existing types.
## read
read takes 4 arguments:
* buffer : the buffer from which to read the data
* offset : where to start reading the buffer
* typeArgs : (optional) the arguments passed to the type
* context : (optional) an object to get values previously read in the containing type
It must returns an object with two values:
* value : the read value
* size : the number of bytes read by the buffer
Example:
That read function has 2 typeArgs : type and endVal.
It increases the value of a cursor in order to eventually return the size.
The PartialReadError error needs to be thrown if buffer doesn't contain enough bytes.
```js
function readEntityMetadata(buffer, offset, {type,endVal}) {
let cursor = offset;
const metadata = [];
let item;
while(true) {
if(offset+1>buffer.length)
throw new PartialReadError();
item = buffer.readUInt8(cursor);
if(item === endVal) {
return {
value: metadata,
size: cursor + 1 - offset
};
}
const results = this.read(buffer, cursor, type, {});
metadata.push(results.value);
cursor += results.size;
}
}
```
Useful function: this.read which takes 5 arguments:
* buffer : the buffer from which to read the data
* offset : where to start reading the buffer
* type : the type to read
* typeArgs : (optional) the arguments passed to the type
* context : (optional) an object to get values previously read in the containing type
Can be used to read already existing datatype.
## write
write takes 5 arguments:
* value : the value to be written
* buffer : the buffer to write in
* offset : the offset at which to write in the buffer
* typeArgs : (optional) the arguments passed to the type
* context : (optional) an object to get values previously read in the containing type
It must return the offset increased with the number of bytes written.
Example:
This write function updates the offset at each this.write called.
```js
function writeEntityMetadata(value, buffer, offset, {type,endVal}) {
const self = this;
value.forEach(function(item) {
offset = self.write(item, buffer, offset, type, {});
});
buffer.writeUInt8(endVal, offset);
return offset + 1;
}
```
Useful function: this.write which takes 6 arguments:
* value : the value to be written
* buffer : the buffer to write in
* offset : the offset at which to write in the buffer
* type : the type to write
* typeArgs : (optional) the arguments passed to the type
* context : (optional) an object to get values previously written in the containing type
## sizeOf
sizeOf takes 3 arguments:
* value : the value for which to compute the buffer size
* typeArgs : (optional) the arguments passed to the type
* context : (optional) an object to get values previously read in the containing type
It must return the size of the buffer needed to write the given value.
Example:
This sizeOf function calls this.sizeOf to get the size of each value and return the sum.
```js
function sizeOfEntityMetadata(value, {type}) {
let size = 1;
for(let i = 0; i < value.length; ++i) {
size += this.sizeOf(value[i], type, {});
}
return size;
}
```
Useful function : this.sizeOf which takes 4 arguments:
* value : the value for which to compute the buffer size
* type : the type to get the size of
* typeArgs : (optional) the arguments passed to the type
* context : (optional) an object to get values previously written in the containing type