blob: 2ad02070d740a528a1f10f6ca2b2a0eeaebe6a21 [file] [log] [blame]
khenaidoo7d3c5582021-08-11 18:09:44 -04001// Copyright 2019+ Klaus Post. All rights reserved.
2// License information can be found in the LICENSE file.
3// Based on work by Yann Collet, released under BSD License.
4
5package zstd
6
7import (
8 "fmt"
9 "io"
10 "io/ioutil"
11)
12
13type byteBuffer interface {
14 // Read up to 8 bytes.
Akash Reddy Kankanalac28f0e22025-06-16 11:00:55 +053015 // Returns io.ErrUnexpectedEOF if this cannot be satisfied.
16 readSmall(n int) ([]byte, error)
khenaidoo7d3c5582021-08-11 18:09:44 -040017
18 // Read >8 bytes.
19 // MAY use the destination slice.
20 readBig(n int, dst []byte) ([]byte, error)
21
22 // Read a single byte.
23 readByte() (byte, error)
24
25 // Skip n bytes.
Akash Reddy Kankanalac28f0e22025-06-16 11:00:55 +053026 skipN(n int64) error
khenaidoo7d3c5582021-08-11 18:09:44 -040027}
28
29// in-memory buffer
30type byteBuf []byte
31
Akash Reddy Kankanalac28f0e22025-06-16 11:00:55 +053032func (b *byteBuf) readSmall(n int) ([]byte, error) {
khenaidoo7d3c5582021-08-11 18:09:44 -040033 if debugAsserts && n > 8 {
34 panic(fmt.Errorf("small read > 8 (%d). use readBig", n))
35 }
36 bb := *b
37 if len(bb) < n {
Akash Reddy Kankanalac28f0e22025-06-16 11:00:55 +053038 return nil, io.ErrUnexpectedEOF
khenaidoo7d3c5582021-08-11 18:09:44 -040039 }
40 r := bb[:n]
41 *b = bb[n:]
Akash Reddy Kankanalac28f0e22025-06-16 11:00:55 +053042 return r, nil
khenaidoo7d3c5582021-08-11 18:09:44 -040043}
44
45func (b *byteBuf) readBig(n int, dst []byte) ([]byte, error) {
46 bb := *b
47 if len(bb) < n {
48 return nil, io.ErrUnexpectedEOF
49 }
50 r := bb[:n]
51 *b = bb[n:]
52 return r, nil
53}
54
khenaidoo7d3c5582021-08-11 18:09:44 -040055func (b *byteBuf) readByte() (byte, error) {
56 bb := *b
57 if len(bb) < 1 {
58 return 0, nil
59 }
60 r := bb[0]
61 *b = bb[1:]
62 return r, nil
63}
64
Akash Reddy Kankanalac28f0e22025-06-16 11:00:55 +053065func (b *byteBuf) skipN(n int64) error {
khenaidoo7d3c5582021-08-11 18:09:44 -040066 bb := *b
Akash Reddy Kankanalac28f0e22025-06-16 11:00:55 +053067 if n < 0 {
68 return fmt.Errorf("negative skip (%d) requested", n)
69 }
70 if int64(len(bb)) < n {
khenaidoo7d3c5582021-08-11 18:09:44 -040071 return io.ErrUnexpectedEOF
72 }
73 *b = bb[n:]
74 return nil
75}
76
77// wrapper around a reader.
78type readerWrapper struct {
79 r io.Reader
80 tmp [8]byte
81}
82
Akash Reddy Kankanalac28f0e22025-06-16 11:00:55 +053083func (r *readerWrapper) readSmall(n int) ([]byte, error) {
khenaidoo7d3c5582021-08-11 18:09:44 -040084 if debugAsserts && n > 8 {
85 panic(fmt.Errorf("small read > 8 (%d). use readBig", n))
86 }
87 n2, err := io.ReadFull(r.r, r.tmp[:n])
88 // We only really care about the actual bytes read.
Akash Reddy Kankanalac28f0e22025-06-16 11:00:55 +053089 if err != nil {
90 if err == io.EOF {
91 return nil, io.ErrUnexpectedEOF
92 }
93 if debugDecoder {
khenaidoo7d3c5582021-08-11 18:09:44 -040094 println("readSmall: got", n2, "want", n, "err", err)
95 }
Akash Reddy Kankanalac28f0e22025-06-16 11:00:55 +053096 return nil, err
khenaidoo7d3c5582021-08-11 18:09:44 -040097 }
Akash Reddy Kankanalac28f0e22025-06-16 11:00:55 +053098 return r.tmp[:n], nil
khenaidoo7d3c5582021-08-11 18:09:44 -040099}
100
101func (r *readerWrapper) readBig(n int, dst []byte) ([]byte, error) {
102 if cap(dst) < n {
103 dst = make([]byte, n)
104 }
105 n2, err := io.ReadFull(r.r, dst[:n])
106 if err == io.EOF && n > 0 {
107 err = io.ErrUnexpectedEOF
108 }
109 return dst[:n2], err
110}
111
112func (r *readerWrapper) readByte() (byte, error) {
113 n2, err := r.r.Read(r.tmp[:1])
114 if err != nil {
Akash Reddy Kankanalac28f0e22025-06-16 11:00:55 +0530115 if err == io.EOF {
116 err = io.ErrUnexpectedEOF
117 }
khenaidoo7d3c5582021-08-11 18:09:44 -0400118 return 0, err
119 }
120 if n2 != 1 {
121 return 0, io.ErrUnexpectedEOF
122 }
123 return r.tmp[0], nil
124}
125
Akash Reddy Kankanalac28f0e22025-06-16 11:00:55 +0530126func (r *readerWrapper) skipN(n int64) error {
127 n2, err := io.CopyN(ioutil.Discard, r.r, n)
128 if n2 != n {
khenaidoo7d3c5582021-08-11 18:09:44 -0400129 err = io.ErrUnexpectedEOF
130 }
131 return err
132}