• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

Hyshmily / hotkey / 28835396755

07 Jul 2026 01:38AM UTC coverage: 89.623% (-0.7%) from 90.336%
28835396755

push

github

Hyshmily
fix and feat : fix known bugs and accept lz4 to wrap value for smaller memory,"wrap key" needs to consider

Signed-off-by: Hyshmily <cxm8607@outlook.com>

1325 of 1552 branches covered (85.37%)

Branch coverage included in aggregate %.

167 of 236 new or added lines in 12 files covered. (70.76%)

3745 of 4105 relevant lines covered (91.23%)

4.19 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

87.72
/common/src/main/java/io/github/hyshmily/hotkey/cache/codec/Lz4CacheCompressor.java
1
/*
2
 * Copyright 2026 Hyshmily. All Rights Reserved.
3
 *
4
 * Licensed under the Apache License, Version 2.0 (the "License");
5
 * you may not use this file except in compliance with the License.
6
 * You may obtain a copy of the License at
7
 *
8
 *     http://www.apache.org/licenses/LICENSE-2.0
9
 *
10
 * Unless required by applicable law or agreed to in writing, software
11
 * distributed under the License is distributed on an "AS IS" BASIS,
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 * See the License for the specific language governing permissions and
14
 * limitations under the License.
15
 */
16
package io.github.hyshmily.hotkey.cache.codec;
17

18
import io.github.hyshmily.hotkey.Internal;
19
import net.jpountz.lz4.LZ4Compressor;
20
import net.jpountz.lz4.LZ4Exception;
21
import net.jpountz.lz4.LZ4Factory;
22
import net.jpountz.lz4.LZ4FastDecompressor;
23

24
import java.io.IOException;
25
import java.util.Arrays;
26

27
import static java.nio.charset.StandardCharsets.UTF_8;
28

29
/**
30
 * LZ4-based {@link CacheCompressor}. Uses the fastest available LZ4 instance.
31
 *
32
 * <p>Format:
33
 * <ul>
34
 *   <li>Flag {@code 0x00} = uncompressed: {@code [0x00][raw bytes]}</li>
35
 *   <li>Flag {@code 0x01} = LZ4 compressed:
36
 *       {@code [0x01][4-byte original-length LE][LZ4 payload]}</li>
37
 * </ul>
38
 * Original length is bounds-checked during decompression to prevent resource
39
 * exhaustion attacks.
40
 */
41
@Internal
42
public class Lz4CacheCompressor implements CacheCompressor {
43

44
  private static final byte FLAG_RAW = 0;
45
  private static final byte FLAG_LZ4 = 1;
46

47
  private final LZ4Compressor compressor;
48
  private final LZ4FastDecompressor decompressor;
49

50
  public Lz4CacheCompressor() {
2✔
51
    LZ4Factory factory = LZ4Factory.fastestInstance();
2✔
52
    this.compressor = factory.fastCompressor();
4✔
53
    this.decompressor = factory.fastDecompressor();
4✔
54
  }
1✔
55

56
  @Override
57
  public Object wrap(Object value) {
58
    if (!(value instanceof String s)) return value;
9✔
59

60
    byte[] raw = s.getBytes(UTF_8);
4✔
61
    if (raw.length < MIN_COMPRESS_LENGTH) {
4✔
62
      byte[] buf = new byte[raw.length + 1];
6✔
63
      buf[0] = FLAG_RAW;
4✔
64
      System.arraycopy(raw, 0, buf, 1, raw.length);
7✔
65
      return buf;
2✔
66
    }
67

68
    int maxLen = compressor.maxCompressedLength(raw.length);
6✔
69
    byte[] compressed = new byte[maxLen + 5];
5✔
70
    compressed[0] = FLAG_LZ4;
4✔
71
    writeLen(compressed, raw.length);
4✔
72
    int len = compressor.compress(raw, 0, raw.length, compressed, 5, maxLen);
11✔
73
    return Arrays.copyOf(compressed, len + 5);
6✔
74
  }
75

76
  @Override
77
  public Object unwrap(Object stored) throws IOException {
78
    if (!(stored instanceof byte[] b)) return stored;
9✔
79
    if (b.length < 1) return stored;
4!
80
    if (b[0] == FLAG_RAW) {
4✔
81
      return new String(b, 1, b.length - 1, UTF_8);
11✔
82
    }
83
    if (b[0] != FLAG_LZ4) return stored;
5!
84
    if (b.length < 5) throw new IOException("Truncated LZ4 data");
9✔
85

86
    int originalLen = readLen(b);
3✔
87
    if (originalLen <= 0 || originalLen > 100_000_000) {
5!
NEW
88
      throw new IOException("Invalid decompressed length: " + originalLen);
×
89
    }
90

91
    byte[] restored = new byte[originalLen];
3✔
92
    try {
93
      decompressor.decompress(b, 5, restored, 0, originalLen);
9✔
NEW
94
    } catch (LZ4Exception e) {
×
NEW
95
      throw new IOException("LZ4 decompression failed", e);
×
96
    }
1✔
97
    return new String(restored, UTF_8);
6✔
98
  }
99

100
  private static void writeLen(byte[] buf, int len) {
101
    buf[1] = (byte) len;
5✔
102
    buf[2] = (byte) (len >>> 8);
7✔
103
    buf[3] = (byte) (len >>> 16);
7✔
104
    buf[4] = (byte) (len >>> 24);
7✔
105
  }
1✔
106

107
  private static int readLen(byte[] buf) {
108
    return ((buf[1] & 0xFF) | ((buf[2] & 0xFF) << 8) | ((buf[3] & 0xFF) << 16) | ((buf[4] & 0xFF) << 24));
30✔
109
  }
110
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc