go4.org@v0.0.0-20230225012048-214862532bf5/readerutil/fakeseeker.go (about) 1 /* 2 Copyright 2014 The Perkeep Authors 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package readerutil 18 19 import ( 20 "errors" 21 "fmt" 22 "io" 23 "os" 24 ) 25 26 // fakeSeeker can seek to the ends but any read not at the current 27 // position will fail. 28 type fakeSeeker struct { 29 r io.Reader 30 size int64 31 32 fakePos int64 33 realPos int64 34 } 35 36 // NewFakeSeeker returns a ReadSeeker that can pretend to Seek (based 37 // on the provided total size of the reader's content), but any reads 38 // will fail if the fake seek position doesn't match reality. 39 func NewFakeSeeker(r io.Reader, size int64) io.ReadSeeker { 40 return &fakeSeeker{r: r, size: size} 41 } 42 43 func (fs *fakeSeeker) Seek(offset int64, whence int) (int64, error) { 44 var newo int64 45 switch whence { 46 default: 47 return 0, errors.New("invalid whence") 48 case os.SEEK_SET: 49 newo = offset 50 case os.SEEK_CUR: 51 newo = fs.fakePos + offset 52 case os.SEEK_END: 53 newo = fs.size + offset 54 } 55 if newo < 0 { 56 return 0, errors.New("negative seek") 57 } 58 fs.fakePos = newo 59 return newo, nil 60 } 61 62 func (fs *fakeSeeker) Read(p []byte) (n int, err error) { 63 if fs.fakePos != fs.realPos { 64 return 0, fmt.Errorf("attempt to read from fake seek offset %d; real offset is %d", fs.fakePos, fs.realPos) 65 } 66 n, err = fs.r.Read(p) 67 fs.fakePos += int64(n) 68 fs.realPos += int64(n) 69 return 70 }