code: function createProtocol(attrs, opts) {
    opts = opts || {};
  
    var name = attrs.protocol;
    if (!name) {
      throw new Error('missing protocol name');
    }
    if (attrs.namespace !== undefined) {
      opts.namespace = attrs.namespace;
    } else {
      var match = /^(.*)\.[^.]+$/.exec(name);
      if (match) {
        opts.namespace = match[1];
      }
    }
    name = types.qualify(name, opts.namespace);
  
    if (attrs.types) {
      attrs.types.forEach(function (obj) { types.createType(obj, opts); });
    }
  
    var messages = {};
    if (attrs.messages) {
      Object.keys(attrs.messages).forEach(function (key) {
        messages[key] = new Message(key, attrs.messages[key], opts);
      });
    }
    return new Protocol(name, messages, opts.registry || {});
  }
docs: Protocol generation function.
  
  This should be used instead of the protocol constructor. The protocol's
  constructor performs no logic to better support efficient protocol copy.