In JavaScript (Node), I've written a module which accepts a list of fields and their types and returns an object with pack
and unpack
methods. Below is the code to pack and unpack IPv4:
var ipv4 = proto.add('struct', {
name: 'IPV4',
fields: {
version: 'int:4',
ihl: 'int:4',
dscp: 'int:6',
ecn: 'int:2',
length: 'int:16',
id: 'int:16',
flags: 'int:3',
offset: 'int:13',
ttl: 'int:8',
protocol: 'int:8',
checksum: 'int:16',
src: 'IPV4_ADDR',
dst: 'IPV4_ADDR',
// TODO: IPv4 OPTIONS
options: 'raw'
},
$length: 'length'
});
//then I can do
ipv4.pack({ version: 4, ... }); //=> buffer
//and
ipv4.unpack(buffer); //=> { ... }
Since JavaScript is dynamic, I can meta-program (reasonably) optimised pack
and unpack
functions. From what I understand, you cannot dynamically create functions in Go, though it appears this would be possible using the reflect
package. Is this worth pursuing? Or would it be too costly to use reflect
?
I'm hoping to avoid writing code like this for every network protocol I wish to parse.
If can accept a semi-dynamic solution, you could take inspiration in the numerous JSON alternative packages for Golang that are designed for speed. Their approach is to tag a struct, then run a tool (as part of a make configuration for example) to generate the MarshalJSON
and UnmarshalJSON
methods for the desired types. Which is clearly faster than using tags.
Some examples to help you :