You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

decode_reader.go 6.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290
  1. package rardecode
  2. import (
  3. "errors"
  4. "io"
  5. )
  6. const (
  7. minWindowSize = 0x40000
  8. maxQueuedFilters = 8192
  9. )
  10. var (
  11. errTooManyFilters = errors.New("rardecode: too many filters")
  12. errInvalidFilter = errors.New("rardecode: invalid filter")
  13. )
  14. // filter functions take a byte slice, the current output offset and
  15. // returns transformed data.
  16. type filter func(b []byte, offset int64) ([]byte, error)
  17. // filterBlock is a block of data to be processed by a filter.
  18. type filterBlock struct {
  19. length int // length of block
  20. offset int // bytes to be read before start of block
  21. reset bool // drop all existing queued filters
  22. filter filter // filter function
  23. }
  24. // decoder is the interface for decoding compressed data
  25. type decoder interface {
  26. init(r io.ByteReader, reset bool) error // initialize decoder for current file
  27. fill(w *window) ([]*filterBlock, error) // fill window with decoded data, returning any filters
  28. }
  29. // window is a sliding window buffer.
  30. type window struct {
  31. buf []byte
  32. mask int // buf length mask
  33. r int // index in buf for reads (beginning)
  34. w int // index in buf for writes (end)
  35. l int // length of bytes to be processed by copyBytes
  36. o int // offset of bytes to be processed by copyBytes
  37. }
  38. // buffered returns the number of bytes yet to be read from window
  39. func (w *window) buffered() int { return (w.w - w.r) & w.mask }
  40. // available returns the number of bytes that can be written before the window is full
  41. func (w *window) available() int { return (w.r - w.w - 1) & w.mask }
  42. func (w *window) reset(log2size uint, clear bool) {
  43. size := 1 << log2size
  44. if size < minWindowSize {
  45. size = minWindowSize
  46. }
  47. if size > len(w.buf) {
  48. b := make([]byte, size)
  49. if clear {
  50. w.w = 0
  51. } else if len(w.buf) > 0 {
  52. n := copy(b, w.buf[w.w:])
  53. n += copy(b[n:], w.buf[:w.w])
  54. w.w = n
  55. }
  56. w.buf = b
  57. w.mask = size - 1
  58. } else if clear {
  59. for i := range w.buf {
  60. w.buf[i] = 0
  61. }
  62. w.w = 0
  63. }
  64. w.r = w.w
  65. }
  66. // writeByte writes c to the end of the window
  67. func (w *window) writeByte(c byte) {
  68. w.buf[w.w] = c
  69. w.w = (w.w + 1) & w.mask
  70. }
  71. // copyBytes copies len bytes at off distance from the end
  72. // to the end of the window.
  73. func (w *window) copyBytes(len, off int) {
  74. len &= w.mask
  75. n := w.available()
  76. if len > n {
  77. // if there is not enough space availaible we copy
  78. // as much as we can and save the offset and length
  79. // of the remaining data to be copied later.
  80. w.l = len - n
  81. w.o = off
  82. len = n
  83. }
  84. i := (w.w - off) & w.mask
  85. for ; len > 0; len-- {
  86. w.buf[w.w] = w.buf[i]
  87. w.w = (w.w + 1) & w.mask
  88. i = (i + 1) & w.mask
  89. }
  90. }
  91. // read reads bytes from the beginning of the window into p
  92. func (w *window) read(p []byte) (n int) {
  93. if w.r > w.w {
  94. n = copy(p, w.buf[w.r:])
  95. w.r = (w.r + n) & w.mask
  96. p = p[n:]
  97. }
  98. if w.r < w.w {
  99. l := copy(p, w.buf[w.r:w.w])
  100. w.r += l
  101. n += l
  102. }
  103. if w.l > 0 && n > 0 {
  104. // if we have successfully read data, copy any
  105. // leftover data from a previous copyBytes.
  106. l := w.l
  107. w.l = 0
  108. w.copyBytes(l, w.o)
  109. }
  110. return n
  111. }
  112. // decodeReader implements io.Reader for decoding compressed data in RAR archives.
  113. type decodeReader struct {
  114. win window // sliding window buffer used as decode dictionary
  115. dec decoder // decoder being used to unpack file
  116. tot int64 // total bytes read
  117. buf []byte // filter input/output buffer
  118. outbuf []byte // filter output not yet read
  119. err error
  120. filters []*filterBlock // list of filterBlock's, each with offset relative to previous in list
  121. }
  122. func (d *decodeReader) init(r io.ByteReader, dec decoder, winsize uint, reset bool) error {
  123. if reset {
  124. d.filters = nil
  125. }
  126. d.err = nil
  127. d.outbuf = nil
  128. d.tot = 0
  129. d.win.reset(winsize, reset)
  130. d.dec = dec
  131. return d.dec.init(r, reset)
  132. }
  133. func (d *decodeReader) readErr() error {
  134. err := d.err
  135. d.err = nil
  136. return err
  137. }
  138. // queueFilter adds a filterBlock to the end decodeReader's filters.
  139. func (d *decodeReader) queueFilter(f *filterBlock) error {
  140. if f.reset {
  141. d.filters = nil
  142. }
  143. if len(d.filters) >= maxQueuedFilters {
  144. return errTooManyFilters
  145. }
  146. // offset & length must be < window size
  147. f.offset &= d.win.mask
  148. f.length &= d.win.mask
  149. // make offset relative to previous filter in list
  150. for _, fb := range d.filters {
  151. if f.offset < fb.offset {
  152. // filter block must not start before previous filter
  153. return errInvalidFilter
  154. }
  155. f.offset -= fb.offset
  156. }
  157. d.filters = append(d.filters, f)
  158. return nil
  159. }
  160. // processFilters processes any filters valid at the current read index
  161. // and stores the output in outbuf.
  162. func (d *decodeReader) processFilters() (err error) {
  163. f := d.filters[0]
  164. if f.offset > 0 {
  165. return nil
  166. }
  167. d.filters = d.filters[1:]
  168. if d.win.buffered() < f.length {
  169. // fill() didn't return enough bytes
  170. err = d.readErr()
  171. if err == nil || err == io.EOF {
  172. return errInvalidFilter
  173. }
  174. return err
  175. }
  176. if cap(d.buf) < f.length {
  177. d.buf = make([]byte, f.length)
  178. }
  179. d.outbuf = d.buf[:f.length]
  180. n := d.win.read(d.outbuf)
  181. for {
  182. // run filter passing buffer and total bytes read so far
  183. d.outbuf, err = f.filter(d.outbuf, d.tot)
  184. if err != nil {
  185. return err
  186. }
  187. if cap(d.outbuf) > cap(d.buf) {
  188. // Filter returned a bigger buffer, save it for future filters.
  189. d.buf = d.outbuf
  190. }
  191. if len(d.filters) == 0 {
  192. return nil
  193. }
  194. f = d.filters[0]
  195. if f.offset != 0 {
  196. // next filter not at current offset
  197. f.offset -= n
  198. return nil
  199. }
  200. if f.length != len(d.outbuf) {
  201. return errInvalidFilter
  202. }
  203. d.filters = d.filters[1:]
  204. if cap(d.outbuf) < cap(d.buf) {
  205. // Filter returned a smaller buffer. Copy it back to the saved buffer
  206. // so the next filter can make use of the larger buffer if needed.
  207. d.outbuf = append(d.buf[:0], d.outbuf...)
  208. }
  209. }
  210. }
  211. // fill fills the decodeReader's window
  212. func (d *decodeReader) fill() {
  213. if d.err != nil {
  214. return
  215. }
  216. var fl []*filterBlock
  217. fl, d.err = d.dec.fill(&d.win) // fill window using decoder
  218. for _, f := range fl {
  219. err := d.queueFilter(f)
  220. if err != nil {
  221. d.err = err
  222. return
  223. }
  224. }
  225. }
  226. // Read decodes data and stores it in p.
  227. func (d *decodeReader) Read(p []byte) (n int, err error) {
  228. if len(d.outbuf) == 0 {
  229. // no filter output, see if we need to create more
  230. if d.win.buffered() == 0 {
  231. // fill empty window
  232. d.fill()
  233. if d.win.buffered() == 0 {
  234. return 0, d.readErr()
  235. }
  236. } else if len(d.filters) > 0 {
  237. f := d.filters[0]
  238. if f.offset == 0 && f.length > d.win.buffered() {
  239. d.fill() // filter at current offset needs more data
  240. }
  241. }
  242. if len(d.filters) > 0 {
  243. if err := d.processFilters(); err != nil {
  244. return 0, err
  245. }
  246. }
  247. }
  248. if len(d.outbuf) > 0 {
  249. // copy filter output into p
  250. n = copy(p, d.outbuf)
  251. d.outbuf = d.outbuf[n:]
  252. } else if len(d.filters) > 0 {
  253. f := d.filters[0]
  254. if f.offset < len(p) {
  255. // only read data up to beginning of next filter
  256. p = p[:f.offset]
  257. }
  258. n = d.win.read(p) // read directly from window
  259. f.offset -= n // adjust first filter offset by bytes just read
  260. } else {
  261. n = d.win.read(p) // read directly from window
  262. }
  263. d.tot += int64(n)
  264. return n, nil
  265. }