/*
********************************************************************
/* Reader API
********************************************************************
339989
@Override
    public void close()
        throws IOException
    {
        InputStream in = _inputSource;

        if (in != null) {
            _inputSource = null;
            if (_autoClose) {
                in.close();
            }
        }
        freeBuffers();
    }
614272
@Override
    public Object read(JSONReader r, JsonParser p) throws IOException
    {
        if (p.isExpectedStartObjectToken()) {
            final Object bean;
            try {
                bean = create();
            } catch (Exception e) {
                return _reportFailureToCreate(p, e);
            }
            p.setCurrentValue(bean);
            return _readBean(r, p, bean);
        }
        try {
            switch (p.currentTokenId()) {
            case JsonTokenId.ID_NULL:
                return null;
            case JsonTokenId.ID_STRING:
                return create(p.getText());
            case JsonTokenId.ID_NUMBER_INT:
                return create(p.getLongValue());
            default:
            }
        } catch (Exception e) {
            return _reportFailureToCreate(p, e);
        }
        throw JSONObjectException.from(p, "Can not create a %s instance out of %s",
                _type.getName(), _tokenDesc(p));
    }
440765
function createReader(noDecode, writerType, readerType) {
  if (noDecode) {
    return (function (skipper) {
      return function (tap) {
        var pos = tap.pos;
        skipper(tap);
        return tap.buf.slice(pos, tap.pos);
      };
    })(writerType._skip);
  } else if (readerType) {
    var resolver = readerType.createResolver(writerType);
    return function (tap) { return resolver._read(tap); };
  } else {
    return function (tap) { return writerType._read(tap); };
  }
}
328586
@Override
    public int read(byte[] out, final int off, final int len) throws IOException {
        if (off < 0 || len < 0 || (off + len) > out.length) {
            throw new IllegalArgumentException(String.format(
                    "Illegal arguments for read: byte[%d], off:%d, len:%d",
                    out.length, off, len));
        }

        final int end = off + len;
        int pos = off;
        int i;
        while (pos < end && (i = in.read(out, off, end - off)) >= 0) {
            pos += i;
        }
        return pos - off;
    }
848446
function read() {
        return __awaiter(this, void 0, void 0, function* () {
            let retry = xvt.idleTimeout * (1000 / xvt.pollingMS) >> 0;
            let warn = retry >> 1;
            xvt.entry = '';
            xvt.terminator = null;
            try {
                process.stdin.resume();
                while (xvt.carrier && retry && xvt.validator.isEmpty(xvt.terminator)) {
                    if (xvt.typeahead)
                        process.stdin.emit('data', '');
                    else
                        yield wait(xvt.pollingMS);
                    if (xvt.idleTimeout > 0 && --retry == warn)
                        beep();
                    if (xvt.sessionAllowed > 0 && !(retry % xvt.pollingMS)) {
                        let elapsed = (new Date().getTime() - xvt.sessionStart.getTime()) / 1000;
                        if (elapsed > xvt.sessionAllowed)
                            xvt.carrier = false;
                    }
                }
            }
            catch (err) {
                xvt.carrier = false;
            }
            if (!xvt.carrier || !retry) {
                //  any remaining cancel operations will take over, else bye-bye
                if (cancel.length) {
                    rubout(input.length);
                    xvt.entry = cancel;
                    out(xvt.entry);
                }
                else {
                    if (!xvt.carrier) {
                        outln(xvt.off, ' ** ', xvt.bright, 'your session expired', xvt.off, ' ** ');
                        xvt.reason = 'got exhausted';
                    }
                    if (!retry) {
                        outln(xvt.off, ' ** ', xvt.faint, 'timeout', xvt.off, ' ** ');
                        xvt.reason = 'fallen asleep';
                    }
                    beep();
                    hangup();
                }
                //return new Promise(reject => 'timeout')
            }
            if (cancel.length && xvt.terminator === '\x1B') {
                rubout(input.length);
                xvt.entry = cancel;
                out(xvt.entry);
            }
            //  sanity resets back to default stdin processing
            echo = true;
            eol = true;
            input = '';
        });
    }
396937
public JsonReader newJsonReader(Reader reader) {
    JsonReader jsonReader = new JsonReader(reader);
    jsonReader.setLenient(lenient);
    return jsonReader;
  }
1034323
@SuppressWarnings("unchecked")
	private void initInputReaders() throws Exception {
		int numGates = 0;
		//  ---------------- create the input readers ---------------------
		// in case where a logical input unions multiple physical inputs, create a union reader
		final int groupSize = this.config.getGroupSize(0);
		numGates += groupSize;
		if (groupSize == 1) {
			// non-union case
			inputReader = new MutableRecordReader<DeserializationDelegate<IT>>(
					getEnvironment().getInputGate(0),
					getEnvironment().getTaskManagerInfo().getTmpDirectories());
		} else if (groupSize > 1){
			// union case
			inputReader = new MutableRecordReader<IOReadableWritable>(
					new UnionInputGate(getEnvironment().getAllInputGates()),
					getEnvironment().getTaskManagerInfo().getTmpDirectories());
		} else {
			throw new Exception("Illegal input group size in task configuration: " + groupSize);
		}
		
		this.inputTypeSerializerFactory = this.config.getInputSerializer(0, getUserCodeClassLoader());
		@SuppressWarnings({ "rawtypes" })
		final MutableObjectIterator<?> iter = new ReaderIterator(inputReader, this.inputTypeSerializerFactory.getSerializer());
		this.reader = (MutableObjectIterator<IT>)iter;

		// final sanity check
		if (numGates != this.config.getNumInputs()) {
			throw new Exception("Illegal configuration: Number of input gates and group sizes are not consistent.");
		}
	}
1141831
@SuppressWarnings("unchecked")
	private void initInputReaders() throws Exception {
		
		MutableReader<?> inputReader;
		
		int numGates = 0;
		//  ---------------- create the input readers ---------------------
		// in case where a logical input unions multiple physical inputs, create a union reader
		final int groupSize = this.config.getGroupSize(0);
		numGates += groupSize;
		if (groupSize == 1) {
			// non-union case
			inputReader = new MutableRecordReader<DeserializationDelegate<IT>>(this);
		} else if (groupSize > 1){
			// union case
			
			MutableRecordReader<IOReadableWritable>[] readers = new MutableRecordReader[groupSize];
			for (int j = 0; j < groupSize; ++j) {
				readers[j] = new MutableRecordReader<IOReadableWritable>(this);
			}
			inputReader = new MutableUnionRecordReader<IOReadableWritable>(readers);
		} else {
			throw new Exception("Illegal input group size in task configuration: " + groupSize);
		}
		
		this.inputTypeSerializerFactory = this.config.getInputSerializer(0, this.userCodeClassLoader);
		
		if (this.inputTypeSerializerFactory.getDataType() == Record.class) {
			// record specific deserialization
			MutableReader<Record> reader = (MutableReader<Record>) inputReader;
			this.reader = (MutableObjectIterator<IT>)new RecordReaderIterator(reader);
		} else {
			// generic data type serialization
			MutableReader<DeserializationDelegate<?>> reader = (MutableReader<DeserializationDelegate<?>>) inputReader;
			@SuppressWarnings({ "rawtypes" })
			final MutableObjectIterator<?> iter = new ReaderIterator(reader, this.inputTypeSerializerFactory.getSerializer());
			this.reader = (MutableObjectIterator<IT>)iter;
		}
		
		// final sanity check
		if (numGates != this.config.getNumInputs()) {
			throw new Exception("Illegal configuration: Number of input gates and group sizes are not consistent.");
		}
	}
1173407
@Override
  public int read () throws IOException
  {
    // Do we need to get data?
    if (m_nPosition < 0)
    {
      if (m_bEncode)
      {
        final byte [] b3 = new byte [3];
        int numBinaryBytes = 0;
        for (int i = 0; i < 3; i++)
        {
          final int b = in.read ();

          // If end of stream, b is -1.
          if (b < 0)
            break;

          b3[i] = (byte) b;
          numBinaryBytes++;
        }

        if (numBinaryBytes > 0)
        {
          Base64._encode3to4 (b3, 0, numBinaryBytes, m_aBuffer, 0, m_nOptions);
          m_nPosition = 0;
          m_nNumSigBytes = 4;
        }
        else
        {
          return -1; // Must be end of stream
        }
      }
      else
      {
        // Else decoding
        final byte [] b4 = new byte [4];
        int i;
        for (i = 0; i < 4; i++)
        {
          // Read four "meaningful" bytes:
          int b;
          do
          {
            b = in.read ();
          } while (b >= 0 && m_aDecodabet[b & 0x7f] <= Base64.WHITE_SPACE_ENC);

          if (b < 0)
            break; // Reads a -1 if end of stream

          b4[i] = (byte) b;
        }

        if (i == 4)
        {
          m_nNumSigBytes = Base64._decode4to3 (b4, 0, m_aBuffer, 0, m_nOptions);
          m_nPosition = 0;
        }
        else
          if (i == 0)
          {
            return -1;
          }
          else
          {
            // Must have broken out from above.
            throw new IOException ("Improperly padded Base64 input.");
          } // end

      }
    }

    // Got data?
    if (m_nPosition >= 0)
    {
      if ( /* !encode && */m_nPosition >= m_nNumSigBytes)
      {
        return -1;
      }

      if (m_bEncode && m_bBreakLines && m_nLineLength >= Base64.MAX_LINE_LENGTH)
      {
        m_nLineLength = 0;
        return '\n';
      }
      {
        m_nLineLength++; // This isn't important when decoding
        // but throwing an extra "if" seems
        // just as wasteful.

        final int b = m_aBuffer[m_nPosition++];

        if (m_nPosition >= m_nBufferLength)
          m_nPosition = -1;

        return b & 0xFF; // This is how you "cast" a byte that's
                         // intended to be unsigned.
      }
    }

    // Else error
    throw new IOException ("Error in Base64 code reading stream.");
  }
522979
@Override
    public int read(byte[] output, int offset, int length) throws IOException {
        
        //Return -1 here because if we are closed or finished, we're at the end of the stream
        if(isClosed || isFinished()){
            if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled())
                Tr.debug(tc, "Nothing to read, stream is closed : " + isClosed + ", or finished : " + isFinished());
            return -1;
        }        
        
        if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled()) {
            Tr.entry(tc, "read" , "SRTInputStream31.read(byte[], int, int)");
        }
        
        if(output == null){
            if (TraceComponent.isAnyTracingEnabled() && tc.isErrorEnabled())
                Tr.error(tc, "read.write.bytearray.null");
            throw new NullPointerException(Tr.formatMessage(tc, "read.write.bytearray.null"));
        }
        if((offset < 0) || (length < 0) || (length > (output.length - offset))){
            if (TraceComponent.isAnyTracingEnabled() && tc.isErrorEnabled())
                Tr.error(tc, "read.write.offset.length.bytearraylength", new Object[] {offset, length, output.length});
            throw new IndexOutOfBoundsException(Tr.formatMessage(tc, "read.write.offset.length.bytearraylength", new Object[] {offset, length, output.length}));
        }
        
        int returnSize = 0;
        
        if(this.request.isAsyncStarted() && (this.getReadListener()!= null)){
            synchronized(this){
                //Check if isReady had returned false. If it did then an IllegalArgumentException will be thrown if a listener is set
                isReadyFalseCheck();
                
                returnSize = super.read(output, offset, length);
            }
        } else{
            returnSize = super.read(output, offset, length);
        }
        
        if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled()) {
            Tr.exit(tc, "read" , "SRTInputStream31.read(byte[], int, int) : " + returnSize);
        }
        
        return returnSize;
    }
520933
public static void readFully(Reader reader, char[] buffer, int offset) throws IOException {
    int originalOffset = offset;
    int expected = buffer.length - offset;
    while (offset < buffer.length) {
      int numRead = reader.read(buffer, offset, buffer.length - offset);
      if (numRead < 0) {
        throw new IOException(
                String.format("Reached end of stream earlier than expected. Expected to read %d bytes. Actual: %d",
                expected, offset - originalOffset));
      }
      offset += numRead;
    }
  }
263606
function Parser( tokenStream ){
   
    var debug = false;

    var currentToken, lastComment, types = [];
   
    function isAnyOf( type, possibleTypes ){
        for(var i = 0; i < possibleTypes.length; i++) {
            if ( possibleTypes[i] === type ){ 
                return true;
            }
        }
    
        return false;
    }

    function error( message ){
        throw new Error( message + 
            "\nAt line: " + currentToken.line + ", col: " +  currentToken.col + "\n\n" +
            tokenStream.neighborhood()
        );
    }

    function consume( expectedType ){
        currentToken = tokenStream.consume();

        if (debug) console.log("currentToken", currentToken);

        if ( expectedType && !isAnyOf( currentToken.type, Array.prototype.slice.call(arguments) )){
            error( "syntax error - expected \"" + Array.prototype.join.call( arguments, ", ") + "\", but got \"" + currentToken.type + "\"" ); 
        } 

        return currentToken;
    }

    function peak(){
        return tokenStream.peak();
    }

    function parseExtendsList(){
        
        consume("extends");

        return parseIdList();
    }
   

    function parseExtends(){
        
        consume("extends");

        // get the type name
        var r = consume();
        return r.contents;
    }
   
    function parseIdList(){

        var idlist = []
            , peaked;

        do {
            consume();

            if ( currentToken.type === "id" ){
                idlist.push( currentToken.contents );
            }
        } while ( (peaked = peak()) && (peaked.type === "id" || peaked.type === ",") )

        return idlist;
    }

    function parseImplements(){
         
        consume("implements");
        return parseIdList();

    }

    function parseClass( visibility ){
     
        // get visibility from current token or default
        visibility = visibility || "public";
        
        consume("class");  
       
        // get the type name for the class
        var typeName = consume().contents;
    
        // build the class type
        var def = new Class( typeName, visibility ); 
        def.line = currentToken.line;
    
        // set the description
        def.description = getLastComment();

        var peaked = peak(); 
        var parsedExtends = false;
    
        // parent class
        if ( peaked.type === "extends" ){
            parsedExtends = true;
            def.parentClass = parseExtends();
            peaked = peak();
        }
        
        // parse interfaces
        if ( peaked.type === "implements" ){
            def.interfaces = parseImplements();                       
            peaked = peak();
        }
 
        // parent class
        if ( peaked.type === "extends" ){
            if (parsedExtends) error("Duplicate extends encountered");
            def.parentClass = parseExtends();
        }       

        parseClassBody( def );

        if (debug) console.log(def);

        return def; 
    }

    function consumeBlock(){

        consume("{");
        var parenCount = 1;

        while ( parenCount != 0 ){
            consume();

            if (currentToken.type === "{") {
                parenCount++;
            } else if (currentToken.type === "}"){
                parenCount--;
            }
        }
    }

    function consumeWhile(){
        
        var possibleTypes = Array.prototype.slice.call(arguments);
        
        var consumed = [];
        while (isAnyOf( peak().type, possibleTypes)){
            consumed.push(consume.apply(null, arguments));
        }
        return consumed;
    }

    function consumeIf(){

        var possibleTypes = Array.prototype.slice.call(arguments);
        var peaked = peak();
        if (isAnyOf(peaked.type, possibleTypes)) consume();
    }

    function consumeUntil(){

        var possibleTypes = Array.prototype.slice.call(arguments);
        var peaked;
        while ( (peaked = peak()) && !isAnyOf( peaked.type, possibleTypes) ){
            consume();
        }
    }

    function consumeUntilInclusive(char){
        consumeUntil(char);
        consume(char);
    }

    function parseProperty( isStatic ){

        var currentLine = currentToken.line;

        consume("var");

        var name = consume().contents;
        var type;

        var peaked = peak();
        
        if (peaked.type === ":"){
           
            consume(":");
            type = consume("id").contents; 
            peaked = peak();
            
        }
       
        consumeUntilInclusive(";");

        var prop = new Property( name, type, getLastComment() ); 
        prop.line = currentLine;
        return prop;
    }
  
    function parseMethodArgument(){
    
        // id : Type = expression
        var name = consume("id").contents;
      
        var peaked = peak();

        var type;
        if (peaked.type === ":"){
            type = parseTypeAnnotation();
            peaked = peak();
        }

        var defaultVal;
        if (peaked.type === "="){    
            consume("=");
            defaultVal = consume("number", "string", "boolean", "null").contents; 
        }

        return new MethodArgument(name, type, defaultVal);
    }

    function parseTypeAnnotation(){
        consume(":");
        var ids = consumeWhile("id","->");
        return ids.reduce((a,x) => x.contents + a, "");
    }

    function parseMethodArguments(){

        // ( methodArgument, methodArgument )
        consume("(");

        var peaked, args = [];

        while ( (peaked = peak()) && peaked.type != ")"){
            
            if (peaked.type === "id"){
                args.push( parseMethodArgument() );
            } else if (peaked.type === ","){
                consume(","); // consume the ","
            } else {
                error("Failed to parse method arguments!");                
            }

        }
       
        consume(")");
        return args;
    }

    function getLastComment(){

        var lc = lastComment;
        lastComment = undefined;
        return lc ? lc.contents : lc;

    }

    function parseMethod( isStatic ){
    
        var currentLine = currentToken.line;

        // function MethodName( methodArgument, methodArgument ) : ExpectedType { ... } 
        consume("function");

        var name = consume("id", "new").contents;
        
        var args = parseMethodArguments();

        peaked = peak();
   
        var type;
        if (peaked.type === ":"){
           type = parseTypeAnnotation(); 
        }
    
        consumeBlock();

        var method = new Method( name, args, type, getLastComment() );
        method.line = currentLine;
        method.isStatic = isStatic;
        return method;
    }

    function parseClassMember( def, visibility ){

        // parse "public" or "private"
        var visibility = visibility ? visibility : consume("visibility").contents;     

        // hack to ignore private members
        if ( visibility === "private"){
            def = new Class();
        }

        var peaked = peak();
        var isStatic = false;
    
        if ( peaked.type === "static" ){
            isStatic = true;
            
            consume("static");
            peaked = peak();
        }

        if ( peaked.type === "inline" ){
           
            // TODO - parse inline
            consume("inline");
            peaked = peak();
        }
        
        if ( peaked.type === "var" ){
            return def.properties.push( parseProperty( isStatic ));
        } else if (peaked.type === "function"){
            return def.methods.push( parseMethod( isStatic )); 
        }

        throw new Error("Unknown class member encountered" + JSON.stringify( peaked ));
    }

    function parseClassBody( def ){

        consume("{");

        var peaked; 

        while ( (peaked = peak()) && peaked.type != "}"){
            if (peaked.type === "comment"){    
                parseComment();
                continue;
            } else if (peaked.type === "visibility"){
                parseClassMember( def );
                continue;
            } else if (peaked.type === "function"){
                parseClassMember( def, "private" );
                continue;
            } else if (peaked.type === "var"){
                parseClassMember( def, "private" );
                continue;
            } else if (peaked.type === "static"){
                parseClassMember( def, "private" );
                continue; 
            }

            consume();
        }

        consume("}");
    }

    function parseMethodDefinition(){
    
        // function MethodName( methodArgument, methodArgument ) : ExpectedType; 
        consume("function");

        var currentLine = currentToken.line;
        var name = consume("id", "new").contents;
        
        var args = parseMethodArguments();

        peaked = peak();
   
        var type;
        if (peaked.type === ":"){
           type = parseTypeAnnotation(); 
        }
    
        consumeUntilInclusive(";");

        var method = new Method( name, args, type, getLastComment() );
        method.line = currentLine;
        return method;
    }

    function parseInterfaceMember( def, visibility ){

        var visibility = visibility ? visibility : consume("visibility").contents;     

        // hack to ignore private members
        if ( visibility === "private"){
            def = new Interface();
        }

        var peaked = peak();
    
        if ( peaked.type === "var" ){
            return def.properties.push( parseProperty());
        } else if (peaked.type === "function"){
            return def.methods.push( parseMethodDefinition()); 
        }

        throw new Error("Unknown interface member type encountered" + JSON.stringify( peaked ));
    }
    
    function parseInterfaceBody( def ){

        consume("{");

        var peaked; 

        while ( (peaked = peak()) && peaked.type != "}"){
            if (peaked.type === "comment"){    
                parseComment();
                continue;
            } else if (peaked.type === "visibility"){
                parseInterfaceMember( def );
                continue;
            } else if (peaked.type === "function"){
                parseInterfaceMember( def, "public" );
                continue;
            }  

            consume();
        }

        consume("}");
    }

    function parseInterface( visibility ){

        visibility = visibility || "public";
        
        consume("interface");  
       
        // get the type name for the class
        var typeName = consume().contents;
    
        var def = new Interface( typeName, visibility ); 
        def.line = currentToken.line; 
        def.description = getLastComment();
        
        if ( peak().type === "extends" ){
            def.interfaces = parseExtendsList();
        }
        
        parseInterfaceBody( def );

        if (debug) console.log( def );

        return def; 
    }

    function parseTypedefBody( def ){

        def.isAnonymousObject = true;
        consume("{");

        var peaked; 

        while ( (peaked = peak()) && peaked.type != "}"){
            if (peaked.type === "comment"){    
                parseComment();
                continue;
            } else if (peaked.type === "var"){
                def.anonymousObject.properties.push(parseProperty());
                continue;
            } 

            consume();
        }

        consume("}");
    }

    function parseTypedef( visibility ){
      
        visibility = visibility || "public";
        
        consume("typedef");  
       
        var typeName = consume().contents;
   
        consume("=");

        var def = new Typedef( typeName, visibility ); 
        def.line = currentToken.line;
        def.description = getLastComment();
      
        // anonymous object body
        if (peak().type === "{"){
            parseTypedefBody( def );
        } else {
           def.alias = consume("id").contents;
        }

        if( debug ) console.log( def );

        return def; 
    }

    function parseComment() {
        var squashed = consume("comment");

        var peaked;
        while ( (peaked = peak()) && peaked.type === "comment" ){
            currentToken = consume();
            
            squashed.contents += "\n";
            squashed.contents += currentToken.contents; 
        }
    
        return lastComment = squashed;
    }

    function parseType(){ 
        
        var peaked = peak();
        var visibility = "public";
        
        if (peaked.type === "visibility"){
            consume("visibility");
            peaked = peak();
        }

        if (peaked.type === "class"){
            return parseClass( visibility ); 
        } else if (peaked.type === "interface"){
            return parseInterface( visibility ); 
        } else if (peaked.type === "typedef"){
            return parseTypedef( visibility );    
        } 

        error("Parser for type not implemented");    
    }
    
    this.parse = () => {
       
        var peaked;

        var types = [];
    
        while ( (peaked = peak()) ){
            if (peaked.type === "expose"){
                consume("expose"); 
                types.push( parseType() ); 
            } else if (peaked.type === "class"){
                parseClass(); 
            } else if (peaked.type === "typedef"){
                types.push( parseTypedef() ); 
            } else if (peaked.type === "interface"){
                types.push( parseInterface() ); 
            } else if ( peaked.type === "visibility" ){
                if (peaked.contents === "private") {
                    // parse, but don't add to types
                    parseType();
                    continue;
                }
                types.push( parseType() ); 
            } else if (peaked.type === "comment"){
                parseComment();
            } else {
                consume();
            }
        }

        return types;
    }
}
734581
public Toml read(Reader reader) {
    BufferedReader bufferedReader = null;
    try {
      bufferedReader = new BufferedReader(reader);

      StringBuilder w = new StringBuilder();
      String line = bufferedReader.readLine();
      while (line != null) {
        w.append(line).append('\n');
        line = bufferedReader.readLine();
      }
      read(w.toString());
    } catch (IOException e) {
      throw new RuntimeException(e);
    } finally {
      try {
        bufferedReader.close();
      } catch (IOException e) {}
    }
    return this;
  }
1317272
function readFile() {
                    return new Promise(function (resolve, reject) {
                        /** @type {?} */
                        var reader = new FileReader();
                        reader.onload = function (event) {
                            resolve(reader.result);
                        };
                        reader.onerror = function (err) {
                            reject(err);
                        };
                        reader.readAsDataURL(file);
                    });
                }
324640
@Override
    public void readExternal(PofReader reader)
            throws IOException {
        name = reader.readString(0);
        mutator = reader.readBoolean(1);
        args = reader.readObjectArray(2, new Object[0]);
    }
354271
function setUpReadable(stream, deserialize) {
  stream.deserialize = common.wrapIgnoreNull(deserialize);
  stream.finished = false;
  stream.reading = false;

  stream.terminate = function() {
    stream.finished = true;
    stream.on('data', function() {});
  };

  stream.on('cancelled', function() {
    stream.terminate();
  });
}
521616
@Override
  public synchronized int read(byte[] buf, int off, int len)
      throws IOException {
    checkNotClosed();

    validatePositionedReadArgs(nextReadPos, buf, off, len);
    if (len == 0) {
      return 0;
    }

    if (contentLength == 0 || (nextReadPos >= contentLength)) {
      return -1;
    }

    try {
      lazySeek(nextReadPos, len);
    } catch (EOFException e) {
      // the end of the file has moved
      return -1;
    }

    int bytesRead;
    try {
      bytesRead = wrappedStream.read(buf, off, len);
    } catch (EOFException e) {
      onReadFailure(e, len);
      // the base implementation swallows EOFs.
      return -1;
    } catch (IOException e) {
      onReadFailure(e, len);
      bytesRead = wrappedStream.read(buf, off, len);
    }

    if (bytesRead > 0) {
      pos += bytesRead;
      nextReadPos += bytesRead;
    }
    incrementBytesRead(bytesRead);
    return bytesRead;
  }