github.com/bodgit/sevenzip@v1.5.1/internal/delta/reader.go (about) 1 package delta 2 3 import ( 4 "errors" 5 "io" 6 ) 7 8 const ( 9 stateSize = 256 10 ) 11 12 type readCloser struct { 13 rc io.ReadCloser 14 state [stateSize]byte 15 delta int 16 } 17 18 func (rc *readCloser) Close() (err error) { 19 if rc.rc != nil { 20 err = rc.rc.Close() 21 rc.rc = nil 22 } 23 24 return 25 } 26 27 func (rc *readCloser) Read(p []byte) (int, error) { 28 if rc.rc == nil { 29 return 0, errors.New("delta: Read after Close") 30 } 31 32 n, err := rc.rc.Read(p) 33 if err != nil { 34 return n, err 35 } 36 37 var ( 38 buffer [stateSize]byte 39 j int 40 ) 41 42 copy(buffer[:], rc.state[:rc.delta]) 43 44 for i := 0; i < n; { 45 for j = 0; j < rc.delta && i < n; i++ { 46 p[i] = buffer[j] + p[i] 47 buffer[j] = p[i] 48 j++ 49 } 50 } 51 52 if j == rc.delta { 53 j = 0 54 } 55 56 copy(rc.state[:], buffer[j:rc.delta]) 57 copy(rc.state[rc.delta-j:], buffer[:j]) 58 59 return n, nil 60 } 61 62 // NewReader returns a new Delta io.ReadCloser. 63 func NewReader(p []byte, _ uint64, readers []io.ReadCloser) (io.ReadCloser, error) { 64 if len(readers) != 1 { 65 return nil, errors.New("delta: need exactly one reader") 66 } 67 68 if len(p) != 1 { 69 return nil, errors.New("delta: not enough properties") 70 } 71 72 return &readCloser{ 73 rc: readers[0], 74 delta: int(p[0] + 1), 75 }, nil 76 }