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 }