github.com/searKing/golang/go@v1.2.117/io/sniff.readseeker.go (about)

     1  // Copyright 2021 The searKing Author. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package io
     6  
     7  import (
     8  	"io"
     9  )
    10  
    11  type sniffReadSeeker struct {
    12  	source   io.ReadSeeker
    13  	pos      int64 // history pos
    14  	sniffing bool
    15  }
    16  
    17  func newSniffReadSeeker(r io.ReadSeeker) *sniffReadSeeker {
    18  	sr := &sniffReadSeeker{
    19  		source: r,
    20  	}
    21  	sr.init()
    22  	return sr
    23  }
    24  
    25  func (sr *sniffReadSeeker) init() ReadSniffer {
    26  	curPos, err := sr.source.Seek(0, io.SeekCurrent)
    27  	if err != nil {
    28  		// in case of source with io.ReadSeeker but not seekable actually, that is FakeReadSeeker
    29  		return newSniffReader(sr.source)
    30  	}
    31  	sr.pos = curPos
    32  	return sr
    33  }
    34  
    35  // Sniff starts or stops sniffing, restarts if stop and start called one by one
    36  // true to start sniffing all data unread actually
    37  // false to return a multi reader with all data sniff buffered and source
    38  func (sr *sniffReadSeeker) Sniff(sniffing bool) ReadSniffer {
    39  	if sr.sniffing == sniffing {
    40  		return sr
    41  	}
    42  	sr.sniffing = sniffing
    43  	if !sniffing {
    44  		_, err := sr.source.Seek(sr.pos, io.SeekStart)
    45  		if err != nil {
    46  			// in case of source with io.ReadSeeker but not seekable actually, that is FakeReadSeeker
    47  			return newSniffReader(sr.source)
    48  		}
    49  	}
    50  	return sr
    51  }
    52  
    53  func (sr *sniffReadSeeker) Read(p []byte) (n int, err error) {
    54  	n, err = sr.source.Read(p)
    55  	if err != nil {
    56  		return
    57  	}
    58  	if !sr.sniffing {
    59  		sr.pos = sr.pos + int64(n)
    60  	}
    61  	return
    62  }