docs: function BlockEncoder(schema, opts) {
    opts = opts || {};
  
    stream.Duplex.call(this, {
      allowHalfOpen: true, // To support async compressors.
      writableObjectMode: true
    });
  
    var type;
    if (types.Type.isType(schema)) {
      type = schema;
      schema = undefined;
    } else {
      // Keep full schema to be able to write it to the header later.
      type = types.Type.forSchema(schema);
    }
  
    this._schema = schema;
    this._type = type;
    this._writeValue = function (tap, val) {
      try {
        this._type._write(tap, val);
      } catch (err) {
        this.emit('error', err);
      }
    };
    this._blockSize = opts.blockSize || 65536;
    this._tap = new Tap(utils.newBuffer(this._blockSize));
    this._codecs = opts.codecs;
    this._codec = opts.codec || 'null';
    this._blockCount = 0;
    this._syncMarker = opts.syncMarker || new utils.Lcg().nextBuffer(16);
    this._queue = new utils.OrderedQueue();
    this._pending = 0;
    this._finished = false;
    this._needHeader = false;
    this._needPush = false;
  
    this._metadata = opts.metadata || {};
    if (!MAP_BYTES_TYPE.isValid(this._metadata)) {
      throw new Error('invalid metadata');
    }
  
    var codec = this._codec;
    this._compress = (this._codecs || BlockEncoder.getDefaultCodecs())[codec];
    if (!this._compress) {
      throw new Error(f('unsupported codec: %s', codec));
    }
  
    if (opts.omitHeader !== undefined) { // Legacy option.
      opts.writeHeader = opts.omitHeader ? 'never' : 'auto';
    }
    switch (opts.writeHeader) {
      case false:
      case 'never':
        break;
      case undefined: // Backwards-compatibility (eager default would be better).
      case 'auto':
        this._needHeader = true;
        break;
      default:
        this._writeHeader();
    }
  
    this.on('finish', function () {
      this._finished = true;
      if (this._blockCount) {
        this._flushChunk();
      } else if (this._finished && this._needPush) {
        // We don't need to check `_isPending` since `_blockCount` is always
        // positive after the first flush.
        this.push(null);
      }
    });
  }