0

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.

jpillora
  • 5,194
  • 2
  • 44
  • 56
  • 1
    Just as a quick hint/idea: You could create types for each protocol and describe the fields through [Tags](http://golang.org/ref/spec#Tag). You can access the tags through reflection. This could work similar to JSON/XML marshalling/unmarshalling. – seong Aug 06 '14 at 09:19
  • 1
    So it is possible to do rudimentary code generation with reflect, but it's a massive pain in the butt. Basically all you can do is select which function you're going to run (but you have to have the functions largely pre-written) and bind variables into local scope (using closures). For many applications this works well enough, but it's always pretty painful. The simplest example I know of is a package I'm working on to randomly generate instances of arbitrary types. It's not published yet, but here's a snippet of the important code: https://gist.github.com/joshlf13/dcfd1eaf8ab4677d2ad8 – joshlf Aug 06 '14 at 09:36
  • If you want an example of how it can be a *lot* uglier, see here: https://github.com/joshlf13/gopack – joshlf Aug 06 '14 at 09:37
  • Also, not sure if this is the sort of thing you're looking for, but this might help: http://godoc.org/code.google.com/p/gopacket – joshlf Aug 06 '14 at 09:37

1 Answers1

2

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 :

Elwinar
  • 9,103
  • 32
  • 40