github.com/driusan/dgit@v0.0.0-20221118233547-f39f0c15edbb/git/delta/reader.go (about) 1 package delta 2 3 import ( 4 "fmt" 5 "io" 6 7 "compress/flate" 8 ) 9 10 // Reader reads a Delta from Src and computes the 11 // delta using Base to resolve inserts. 12 type Reader struct { 13 src flate.Reader 14 base io.ReadSeeker 15 16 sz uint64 17 // unread from the last read 18 cached []byte 19 } 20 21 // Creates a new Delta using src and base as the source and 22 func NewReader(src flate.Reader, base io.ReadSeeker) Reader { 23 d := Reader{src: src, base: base} 24 // Read the source length. We don't care about the value, 25 // but need to advance the stream by an approprite amount 26 d.readVariable() 27 28 // Read the target length so we know when we've finished processing 29 // the delta stream. 30 d.sz = d.readVariable() 31 return d 32 } 33 34 // Reads the resolved delta from the underlying delta stream into buf 35 func (d *Reader) Read(buf []byte) (int, error) { 36 // Read the cached data before we read more from 37 // the stream 38 if len(d.cached) > 0 { 39 return d.readCached(buf) 40 } 41 instruction, err := d.src.ReadByte() 42 if err != nil { 43 return 0, err 44 } 45 if instruction == 0 { 46 panic("Reserved/undocumented instruction found.") 47 } 48 if instruction >= 128 { 49 var offset, length uint64 50 51 if instruction&0x01 != 0 { 52 o, err := d.src.ReadByte() 53 if err != nil { 54 return 0, err 55 } 56 offset = uint64(o) 57 } 58 if instruction&0x02 != 0 { 59 o, err := d.src.ReadByte() 60 if err != nil { 61 return 0, err 62 } 63 offset |= uint64(o) << 8 64 } 65 if instruction&0x04 != 0 { 66 o, err := d.src.ReadByte() 67 if err != nil { 68 return 0, err 69 } 70 offset |= uint64(o) << 16 71 } 72 if instruction&0x08 != 0 { 73 o, err := d.src.ReadByte() 74 if err != nil { 75 return 0, err 76 } 77 offset |= uint64(o) << 24 78 } 79 80 if instruction&0x10 != 0 { 81 l, err := d.src.ReadByte() 82 if err != nil { 83 return 0, err 84 } 85 length = uint64(l) 86 } 87 if instruction&0x20 != 0 { 88 l, err := d.src.ReadByte() 89 if err != nil { 90 return 0, err 91 } 92 length |= uint64(l) << 8 93 } 94 if instruction&0x40 != 0 { 95 l, err := d.src.ReadByte() 96 if err != nil { 97 return 0, err 98 } 99 length |= uint64(l) << 16 100 } 101 if length == 0 { 102 length = 0x10000 103 } 104 105 if _, err := d.base.Seek(int64(offset), io.SeekStart); err != nil { 106 return 0, err 107 } 108 if uint64(len(buf)) >= length { 109 // It should all fit in the buffer 110 n, err := io.ReadFull(d.base, buf[:length]) 111 if err != nil { 112 return n, err 113 } 114 if int(n) != int(length) { 115 return n, fmt.Errorf("Could not read %v bytes", length) 116 } 117 return n, err 118 } 119 // It's not going to all fit in the buffer, so cache it 120 // and then return from the cache 121 d.cached = make([]byte, length) 122 if _, err := io.ReadFull(d.base, d.cached); err != nil { 123 return 0, err 124 } 125 return d.readCached(buf) 126 } else { 127 // Read instruction bytes 128 length := int(instruction) 129 if len(buf) >= length { 130 // It fits into the buffer, so don't 131 // bother caching, 132 n, err := io.ReadFull(d.src, buf[:length]) 133 if n != length { 134 return n, fmt.Errorf("Could not read %v bytes", n) 135 } 136 return n, err 137 } 138 d.cached = make([]byte, length) 139 n, err := io.ReadFull(d.src, d.cached) 140 if err != nil { 141 return n, err 142 } 143 if n != length { 144 return n, fmt.Errorf("Insert: Could not read %v bytes", length) 145 } 146 return d.readCached(buf) 147 } 148 panic("Unreachable code reached") 149 } 150 151 func (d *Reader) readCached(buf []byte) (n int, err error) { 152 n = copy(buf, d.cached) 153 if n == len(d.cached) { 154 d.cached = nil 155 } else { 156 d.cached = d.cached[n:] 157 } 158 return n, nil 159 } 160 161 // Reads a variable length integer from the underlying stream and 162 // returns it as a uint64 163 func (d *Reader) readVariable() uint64 { 164 var val uint64 165 var i uint = 0 166 for { 167 b, err := d.src.ReadByte() 168 if err != nil { 169 panic(err) 170 } 171 val |= uint64(b&127) << (i * 7) 172 if b < 128 { 173 break 174 } 175 i += 1 176 } 177 return val 178 } 179 180 func (d Reader) Len() int { 181 return int(d.sz) 182 }