1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package io.netty5.handler.codec.compression;
17
18 import com.aayushatharva.brotli4j.encoder.Encoder;
19 import io.netty5.buffer.api.Buffer;
20 import io.netty5.buffer.api.BufferAllocator;
21
22 import java.io.IOException;
23 import java.util.Objects;
24 import java.util.function.Supplier;
25
26 import static java.util.Objects.requireNonNull;
27
28
29
30
31
32
33 public final class BrotliCompressor implements Compressor {
34 private final Encoder.Parameters parameters;
35
36 private enum State {
37 PROCESSING,
38 FINISHED,
39 CLOSED
40 }
41
42 private State state = State.PROCESSING;
43
44
45
46
47
48
49 private BrotliCompressor(Encoder.Parameters parameters) {
50 this.parameters = requireNonNull(parameters, "Parameters");
51 }
52
53
54
55
56
57
58
59 public static Supplier<BrotliCompressor> newFactory(Encoder.Parameters parameters) {
60 Objects.requireNonNull(parameters, "parameters");
61 return () -> new BrotliCompressor(parameters);
62 }
63
64
65
66
67
68
69
70 public static Supplier<BrotliCompressor> newFactory(BrotliOptions brotliOptions) {
71 return newFactory(brotliOptions.parameters());
72 }
73
74
75
76
77
78
79
80
81
82 public static Supplier<BrotliCompressor> newFactory() {
83 return newFactory(BrotliOptions.DEFAULT);
84 }
85
86 @Override
87 public Buffer compress(Buffer input, BufferAllocator allocator) throws CompressionException {
88 switch (state) {
89 case CLOSED:
90 throw new CompressionException("Compressor closed");
91 case FINISHED:
92 return allocator.allocate(0);
93 case PROCESSING:
94 if (input.readableBytes() == 0) {
95 return allocator.allocate(0);
96 }
97
98 byte[] uncompressed = new byte[input.readableBytes()];
99 try {
100 input.readBytes(uncompressed, 0, uncompressed.length);
101 byte[] compressed = Encoder.compress(uncompressed, parameters);
102 return allocator.copyOf(compressed);
103 } catch (IOException e) {
104 state = State.FINISHED;
105 throw new CompressionException(e);
106 }
107 default:
108 throw new IllegalStateException();
109 }
110 }
111
112 @Override
113 public Buffer finish(BufferAllocator allocator) {
114 switch (state) {
115 case CLOSED:
116 throw new CompressionException("Compressor closed");
117 case FINISHED:
118 case PROCESSING:
119 state = State.FINISHED;
120 return allocator.allocate(0);
121 default:
122 throw new IllegalStateException();
123 }
124 }
125
126 @Override
127 public boolean isFinished() {
128 return state != State.PROCESSING;
129 }
130
131 @Override
132 public boolean isClosed() {
133 return state == State.CLOSED;
134 }
135
136 @Override
137 public void close() {
138 state = State.CLOSED;
139 }
140 }