code: function RecordType(attrs, opts) {
    // Force creation of the options object in case we need to register this
    // record's name.
    opts = opts || {};
  
    // Save the namespace to restore it as we leave this record's scope.
    var namespace = opts.namespace;
    if (attrs.namespace !== undefined) {
      opts.namespace = attrs.namespace;
    } else if (attrs.name) {
      // Fully qualified names' namespaces are used when no explicit namespace
      // attribute was specified.
      var match = /^(.*)\.[^.]+$/.exec(attrs.name);
      if (match) {
        opts.namespace = match[1];
      }
    }
    Type.call(this, attrs, opts);
  
    if (!Array.isArray(attrs.fields)) {
      throw new Error(f('non-array record fields: %j', attrs.fields));
    }
    if (utils.hasDuplicates(attrs.fields, function (f) { return f.name; })) {
      throw new Error(f('duplicate field name: %j', attrs.fields));
    }
    this._fieldsMap = {};
    this._fields = attrs.fields.map(function (f) {
      var field = new Field(f, opts);
      this._fieldsMap[field.getName()] = field;
      return field;
    }, this);
  
    this._isError = attrs.type === 'error';
    this._constructor = this._createConstructor();
    this._read = this._createReader();
    this._skip = this._createSkipper();
    this._write = this._createWriter();
    this._check = this._createChecker();
  
    opts.namespace = namespace;
  }
docs: Avro record.
  
  Values are represented as instances of a programmatically generated
  constructor (similar to a "specific record"), available via the
  `getRecordConstructor` method. This "specific record class" gives
  significant speedups over using generics objects.
  
  Note that vanilla objects are still accepted as valid as long as their
  fields match (this makes it much more convenient to do simple things like
  update nested records).
  
  This type is also used for errors (similar, except for the extra `Error`
  constructor call) and for messages (see comment below).