diff --git a/eazy_test.go b/eazy_test.go index 83316d9..cb54106 100644 --- a/eazy_test.go +++ b/eazy_test.go @@ -64,12 +64,7 @@ func TestMagic(t *testing.T) { } func TestLiteral(t *testing.T) { - t.Run("ver1", func(t *testing.T) { testLiteral(t, 1) }) - if t.Failed() { - return - } - - t.Run("ver0", func(t *testing.T) { testLiteral(t, 0) }) + testAllVersions(t, testLiteral) } func testLiteral(t *testing.T, ver int) { @@ -109,12 +104,7 @@ func testLiteral(t *testing.T, ver int) { } func TestCopy(t *testing.T) { - t.Run("ver1", func(t *testing.T) { testCopy(t, 1) }) - if t.Failed() { - return - } - - t.Run("ver0", func(t *testing.T) { testCopy(t, 0) }) + testAllVersions(t, testCopy) } func testCopy(t *testing.T, ver int) { @@ -212,8 +202,8 @@ func TestBug1(t *testing.T) { _, _ = b.Write([]byte{0xfd, 0x03, 0x65}) // offset n, err = r.Read(p) - assert.ErrorIs(t, err, io.EOF) - assert.Equal(t, 9, n) + assert.ErrorIs(t, err, ErrOverflow) + assert.Equal(t, 0, n) } func TestPadding(t *testing.T) { @@ -278,7 +268,7 @@ func TestPadding(t *testing.T) { } func TestZeroRegion(t *testing.T) { - b := []byte{Meta, MetaReset, 2, Meta, MetaVer, 1, Copy | 10, OffLong, 0} + b := []byte{Meta, MetaReset, 2, Meta, MetaVer, 0, Copy | 10, OffLong, 0} r := NewReaderBytes(b) p := make([]byte, 16) @@ -488,7 +478,7 @@ func TestRunlenDecoder(t *testing.T) { d := NewReader(&b) _, _ = b.Write([]byte{Meta, MetaReset | 0, 4}) //nolint:staticcheck - _, _ = b.Write([]byte{Meta, MetaVer | 0, 1}) //nolint:staticcheck + _, _ = b.Write([]byte{Meta, MetaVer | 0, 0}) //nolint:staticcheck _, _ = b.Write([]byte{Literal | 1, 'a', Copy | 5, OffLong, 1}) _, _ = b.Write([]byte{Literal | 2, 'b', 'c', Copy | 5, OffLong, 2}) _, _ = b.Write([]byte{Literal | 2, 'x', 'x'}) @@ -553,7 +543,7 @@ func TestRunlenEncoder(t *testing.T) { // - for i := 0; i < len(data); { + for i := 3; i < len(data); { i += copy(data[i:], zeros) } @@ -562,9 +552,9 @@ func TestRunlenEncoder(t *testing.T) { assert.Equal(t, 0x1005, n) off = len(exp) - enclen = 0x1005 - Len1 - 0x100 + enclen = 0x1005 - 3 - Len1 - 0x100 - _, _ = exp.Write([]byte{Copy | Len2, byte(enclen), byte(enclen >> 8), OffLong, 0}) + _, _ = exp.Write([]byte{Literal | 3, '0', '0', '0', Copy | Len2, byte(enclen), byte(enclen >> 8), OffLong, 0}) if !assert.Equal(t, Dump(exp[off:]), Dump(b[off:])) { t.Logf("dump\n%s", Dump(b)) @@ -650,13 +640,7 @@ func testGiantLiteral(t *testing.T, f func(rnd *rand.Rand, bs int) []byte) { } func TestUnsupportedVersion(t *testing.T) { - var b Buf - - w := NewWriter(&b, 128, 16) - - _, _ = w.Write([]byte{0}) - - b[len(Magic)+2]++ + b := append([]byte{}, Meta, MetaVer|0, byte(Version+1)) //nolint:staticcheck r := NewReaderBytes(b) @@ -717,12 +701,7 @@ func TestLongMeta(t *testing.T) { } func TestLongLenOff(t *testing.T) { - t.Run("ver1", func(t *testing.T) { testLongLenOff(t, 1) }) - if t.Failed() { - return - } - - t.Run("ver0", func(t *testing.T) { testLongLenOff(t, 0) }) + testAllVersions(t, testLongLenOff) } func testLongLenOff(t *testing.T, ver int) { @@ -763,12 +742,7 @@ func testLongLenOff(t *testing.T, ver int) { } func TestOnFile(t *testing.T) { - t.Run("ver1", func(t *testing.T) { testOnFile(t, 1) }) - if t.Failed() { - return - } - - t.Run("ver0", func(t *testing.T) { testOnFile(t, 0) }) + testAllVersions(t, testOnFile) } func testOnFile(t *testing.T, ver int) { @@ -846,6 +820,15 @@ func testOnFile(t *testing.T, ver int) { t.Logf("compression ratio %v", float32(dec.Len())/float32(enc.Len())) } +func testAllVersions(t *testing.T, f func(t *testing.T, ver int)) { + for ver := 0; ver >= 0; ver-- { + t.Run(fmt.Sprintf("ver%d", ver), func(t *testing.T) { f(t, ver) }) + if t.Failed() { + return + } + } +} + func TestOnFileRatioEstimator(t *testing.T) { if *ratioEstimator == 0 { t.Skipf("set --ratio-estimator=N to run, N is number of iterations") @@ -1149,108 +1132,96 @@ func nextIndex(b []byte, st int, s ...[]byte) (i int) { } func TestPrintLengthEncoding(t *testing.T) { - f := func(t *testing.T, ver int) { - var b Buf - e := Encoder{Ver: ver} - - for _, l := range []int{ - 1, - Len1 - 1, - Len1, - Len1 + 1, - 255, 256, - Len1 + 256 - 1, - Len1 + 256, - Len1 + 256 + 1, - Len1 + 256 + 0x10000 - 1, - Len1 + 256 + 0x10000, - } { - b = e.Tag(b[:0], Literal, l) - - t.Logf("value %5d (0x%5[1]x) encoded as % x", l, b) - } - - d := Decoder{Ver: ver} - - for _, b := range [][]byte{ - {0x00}, - {0x01}, - {Len1 - 1}, - {Len1, 0x00}, - {Len1, 0x01}, - {Len1, 0xff}, - {Len2, 0x00, 0x00}, - {Len2, 0x01, 0x00}, - {Len2, 0x00, 0x01}, - } { - _, l, i, err := d.Tag(b, 0) - assert.NoError(t, err) - assert.Equal(t, len(b), i) + testAllVersions(t, testPrintLengthEncoding) +} - t.Logf("value %5d (0x%5[1]x) decoded from % x", l, b) - } +func testPrintLengthEncoding(t *testing.T, ver int) { + var b Buf + e := Encoder{Ver: ver} + + for _, l := range []int{ + 1, + Len1 - 1, + Len1, + Len1 + 1, + 255, 256, + Len1 + 256 - 1, + Len1 + 256, + Len1 + 256 + 1, + Len1 + 256 + 0x10000 - 1, + Len1 + 256 + 0x10000, + } { + b = e.Tag(b[:0], Literal, l) + + t.Logf("value %5d (0x%5[1]x) encoded as % x", l, b) } - t.Run("ver0", func(t *testing.T) { - f(t, 0) - }) + d := Decoder{Ver: ver} + + for _, b := range [][]byte{ + {0x00}, + {0x01}, + {Len1 - 1}, + {Len1, 0x00}, + {Len1, 0x01}, + {Len1, 0xff}, + {Len2, 0x00, 0x00}, + {Len2, 0x01, 0x00}, + {Len2, 0x00, 0x01}, + } { + _, l, i, err := d.Tag(b, 0) + assert.NoError(t, err) + assert.Equal(t, len(b), i) - t.Run("ver1", func(t *testing.T) { - f(t, 1) - }) + t.Logf("value %5d (0x%5[1]x) decoded from % x", l, b) + } } func TestPrintOffsetEncoding(t *testing.T) { - f := func(t *testing.T, ver int) { - var b Buf - e := Encoder{Ver: ver} - - for _, off := range []int{ - 1, - Off1 - 1, - Off1, - Off1 + 1, - 255, 256, - Off1 + 256 - 1, - Off1 + 256, - Off1 + 256 + 1, - Off1 + 256 + 0x10000 - 1, - Off1 + 256 + 0x10000, - } { - b = e.Offset(b[:0], off, 0) - - t.Logf("value %5d (0x%5[1]x) encoded as % x", off, b) - } + testAllVersions(t, testPrintOffsetEncoding) +} - d := Decoder{Ver: ver} - - for _, b := range [][]byte{ - {0x00}, - {0x01}, - {Off1 - 1}, - {Off1, 0x00}, - {Off1, 0x01}, - {Off1, 0xff}, - {Off2, 0x00, 0x00}, - {Off2, 0x01, 0x00}, - {Off2, 0x00, 0x01}, - {0xfd, 0x03, 0x65}, // TestBug1 - } { - off, i, err := d.Offset(b, 0, 0) - assert.NoError(t, err, "buf % x", b) - assert.Equal(t, len(b), i, "buf % x", b) - - t.Logf("value %5d (0x%5[1]x) decoded from % x", off, b) - } +func testPrintOffsetEncoding(t *testing.T, ver int) { + var b Buf + e := Encoder{Ver: ver} + + for _, off := range []int{ + 1, + Off1 - 1, + Off1, + Off1 + 1, + 255, 256, + Off1 + 256 - 1, + Off1 + 256, + Off1 + 256 + 1, + Off1 + 256 + 0x10000 - 1, + Off1 + 256 + 0x10000, + } { + b = e.Offset(b[:0], off, 0) + + t.Logf("value %5d (0x%5[1]x) encoded as % x", off, b) } - t.Run("ver0", func(t *testing.T) { - f(t, 0) - }) - - t.Run("ver1", func(t *testing.T) { - f(t, 1) - }) + d := Decoder{Ver: ver} + + for _, b := range [][]byte{ + {0x00}, + {0x01}, + {Off1 - 1}, + {Off1, 0x00}, + {Off1, 0x01}, + {Off1, 0xff}, + {Off2, 0x00, 0x00}, + {Off2, 0x01, 0x00}, + {Off2, 0x00, 0x01}, + {0xfd, 0x03, 0x65}, // TestBug1 + } { + off, i, err := d.Offset(b, 0, 0) + assert.NoError(t, err, "buf % x", b) + assert.Equal(t, len(b), i, "buf % x", b) + + t.Logf("value %5d (0x%5[1]x) decoded from % x", off, b) + } } func (b *Buf) Len() int { return len(*b) } diff --git a/reader.go b/reader.go index 769efcc..036ca80 100644 --- a/reader.go +++ b/reader.go @@ -63,13 +63,6 @@ var ( ErrOverflow = errors.New("length/offset overflow") ) -const ( - legacy1 = "\x00\x03tlz\x00\x13000\x00\x20" - legacy2 = "\x00\x02eazy\x00\x08" -) - -const maxVer = 1 - // NewReader creates new decompressor reading from r. func NewReader(r io.Reader) *Reader { return &Reader{ @@ -206,11 +199,6 @@ func (r *Reader) read(p []byte, st int) (n, i int, err error) { } func (r *Reader) readTag(st int) (i int, err error) { - st, err = r.checkLegacy(st) - if err != nil { - return st, err - } - i = st // skip zero padding @@ -294,7 +282,7 @@ func (r *Reader) continueMetaTag(st int) (i int, err error) { } case MetaVer: r.d.Ver = int(r.b[i]) - if r.d.Ver > maxVer { + if r.d.Ver > Version { return st, fmt.Errorf("%w: %v", ErrUnsupportedVersion, r.d.Ver) } case MetaReset: @@ -319,43 +307,6 @@ func (r *Reader) continueMetaTag(st int) (i int, err error) { return i, nil } -func (r *Reader) checkLegacy(st int) (int, error) { - check := func(legacy string, st int) (int, error) { - db := r.b[st:] - - if len(db) < len(legacy)+1 && bytes.Equal(db, []byte(legacy)[:len(db)]) { //nolint:gocritic - return st, ErrShortBuffer - } - - if len(db) >= len(legacy)+1 && bytes.Equal(db[:len(legacy)], []byte(legacy)) { //nolint:gocritic - i := len(legacy) - - bs := int(db[i]) - i++ - - r.reset(bs) - - return i, nil - } - - return st, nil - } - - i := st - - i, err := check(legacy1, i) - if err != nil { - return i, err - } - - i, err = check(legacy2, i) - if err != nil { - return i, err - } - - return i, nil -} - func (r *Reader) reset(bs int) { bs = 1 << bs @@ -375,96 +326,7 @@ func (r *Reader) reset(bs int) { r.state = 0 } -func (d Decoder) tag0(b []byte, st int) (tag, l, i int, err error) { - if st >= len(b) { - return 0, 0, st, ErrShortBuffer - } - - i = st - - tag = int(b[i]) & TagMask - l = int(b[i]) & TagLenMask - i++ - - switch l { - case Len1: - if i+1 > len(b) { - return tag, l, st, ErrShortBuffer - } - - l = int(b[i]) - i++ - case Len2: - if i+2 > len(b) { - return tag, l, st, ErrShortBuffer - } - - l = int(b[i])<<8 | int(b[i+1]) - i += 2 - case Len4: - if i+4 > len(b) { - return tag, l, st, ErrShortBuffer - } - - l = int(b[i])<<24 | int(b[i+1])<<16 | int(b[i+2])<<8 | int(b[i+3]) - i += 4 - case Len8: - return tag, l, st, ErrOverflow - default: - // l is embedded - } - - return tag, l, i, nil -} - -func (d Decoder) offset0(b []byte, st, l int) (off, i int, err error) { - if st >= len(b) { - return 0, st, ErrShortBuffer - } - - i = st - - off = int(b[i]) - i++ - - switch off { - case Off1: - if i+1 > len(b) { - return off, st, ErrShortBuffer - } - - off = int(b[i]) - i++ - case Off2: - if i+2 > len(b) { - return off, st, ErrShortBuffer - } - - off = int(b[i])<<8 | int(b[i+1]) - i += 2 - case Off4: - if i+4 > len(b) { - return off, st, ErrShortBuffer - } - - off = int(b[i])<<24 | int(b[i+1])<<16 | int(b[i+2])<<8 | int(b[i+3]) - i += 4 - case Off8: - return off, st, ErrOverflow - default: - // off is embedded - } - - off += l - - return off, i, nil -} - func (d Decoder) Tag(b []byte, st int) (tag, l, i int, err error) { - if d.Ver == 0 { - return d.tag0(b, st) - } - if st >= len(b) { return 0, 0, st, ErrShortBuffer } @@ -509,10 +371,6 @@ func (d Decoder) Tag(b []byte, st int) (tag, l, i int, err error) { } func (d Decoder) Offset(b []byte, st, l int) (off, i int, err error) { - if d.Ver == 0 { - return d.offset0(b, st, l) - } - var long bool i = st diff --git a/writer.go b/writer.go index 2fb8646..64f10aa 100644 --- a/writer.go +++ b/writer.go @@ -105,7 +105,7 @@ const ( Magic = "\x80\x02eazy" // Version is the latest supported format version. - Version = 1 + Version = 0 minCopyChunk = 6 ) @@ -212,7 +212,7 @@ func (w *Writer) Write(p []byte) (done int, err error) { } // runlen encoding - if off >= 0 && i > done+off && w.e.Ver >= 1 { + if off >= 0 && i > done+off { done, i = w.writeRunlen(p, done, done+off, i) continue @@ -450,7 +450,9 @@ func (w *Writer) appendHeader(b []byte) []byte { b = w.appendMagic(b) } - b = append(b, Meta, MetaVer|0, byte(w.e.Ver)) //nolint:staticcheck + if w.e.Ver != 0 { + b = append(b, Meta, MetaVer|0, byte(w.e.Ver)) //nolint:staticcheck + } b = w.appendReset(b, len(w.block)) @@ -485,41 +487,7 @@ func (w *Writer) copyData(d []byte, st, end int) { } } -func (e Encoder) tag0(b []byte, tag byte, l int) []byte { - switch { - case l < Len1: - return append(b, tag|byte(l)) - case l <= 0xff: - return append(b, tag|Len1, byte(l)) - case l <= 0xffff: - return append(b, tag|Len2, byte(l>>8), byte(l)) - case l <= 0xffff_ffff: - return append(b, tag|Len4, byte(l>>24), byte(l>>16), byte(l>>8), byte(l)) - default: - return append(b, tag|Len8, byte(l>>56), byte(l>>48), byte(l>>40), byte(l>>32), byte(l>>24), byte(l>>16), byte(l>>8), byte(l)) - } -} - -func (e Encoder) off0(b []byte, l int) []byte { - switch { - case l < Off1: - return append(b, byte(l)) - case l <= 0xff: - return append(b, Off1, byte(l)) - case l <= 0xffff: - return append(b, Off2, byte(l>>8), byte(l)) - case l <= 0xffff_ffff: - return append(b, Off4, byte(l>>24), byte(l>>16), byte(l>>8), byte(l)) - default: - return append(b, Off8, byte(l>>56), byte(l>>48), byte(l>>40), byte(l>>32), byte(l>>24), byte(l>>16), byte(l>>8), byte(l)) - } -} - func (e Encoder) Tag(b []byte, tag byte, l int) []byte { - if e.Ver == 0 { - return e.tag0(b, tag, l) - } - if l < Len1 { return append(b, tag|byte(l)) } @@ -546,10 +514,6 @@ func (e Encoder) Tag(b []byte, tag byte, l int) []byte { } func (e Encoder) Offset(b []byte, off, l int) []byte { - if e.Ver == 0 { - return e.off0(b, off-l) - } - if off >= l { off -= l } else {