1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package io.netty5.handler.codec;
17
18 import io.netty5.buffer.api.Buffer;
19 import io.netty5.buffer.api.BufferAllocator;
20 import io.netty5.channel.ChannelHandlerAdapter;
21 import io.netty5.channel.ChannelHandlerContext;
22 import io.netty5.util.concurrent.Future;
23 import io.netty5.util.internal.TypeParameterMatcher;
24
25
26
27
28
29
30
31
32
33 public abstract class ByteToMessageCodec<I> extends ChannelHandlerAdapter {
34
35 private final TypeParameterMatcher outboundMsgMatcher;
36 private final MessageToByteEncoder<I> encoder;
37
38 private final ByteToMessageDecoder decoder = new ByteToMessageDecoder() {
39 @Override
40 public void decode(ChannelHandlerContext ctx, Buffer in) throws Exception {
41 ByteToMessageCodec.this.decode(ctx, in);
42 }
43
44 @Override
45 protected void decodeLast(ChannelHandlerContext ctx, Buffer in) throws Exception {
46 ByteToMessageCodec.this.decodeLast(ctx, in);
47 }
48 };
49
50
51
52
53 protected ByteToMessageCodec() {
54 this((BufferAllocator) null);
55 }
56
57
58
59
60 protected ByteToMessageCodec(Class<? extends I> outboundMessageType) {
61 this(outboundMessageType, null);
62 }
63
64
65
66
67
68
69
70 protected ByteToMessageCodec(BufferAllocator allocator) {
71 outboundMsgMatcher = TypeParameterMatcher.find(this, ByteToMessageCodec.class, "I");
72 encoder = new Encoder(allocator);
73 }
74
75
76
77
78
79
80
81
82 protected ByteToMessageCodec(Class<? extends I> outboundMessageType, BufferAllocator allocator) {
83 outboundMsgMatcher = TypeParameterMatcher.get(outboundMessageType);
84 encoder = new Encoder(allocator);
85 }
86
87 @Override
88 public final boolean isSharable() {
89
90 return false;
91 }
92
93
94
95
96
97
98 public boolean acceptOutboundMessage(Object msg) throws Exception {
99 return outboundMsgMatcher.match(msg);
100 }
101
102 @Override
103 public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
104 decoder.channelRead(ctx, msg);
105 }
106
107 @Override
108 public Future<Void> write(ChannelHandlerContext ctx, Object msg) {
109 return encoder.write(ctx, msg);
110 }
111
112 @Override
113 public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
114 decoder.channelReadComplete(ctx);
115 }
116
117 @Override
118 public void channelInactive(ChannelHandlerContext ctx) throws Exception {
119 decoder.channelInactive(ctx);
120 }
121
122 @Override
123 public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
124 try {
125 decoder.handlerAdded(ctx);
126 } finally {
127 encoder.handlerAdded(ctx);
128 }
129 }
130
131 @Override
132 public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
133 try {
134 decoder.handlerRemoved(ctx);
135 } finally {
136 encoder.handlerRemoved(ctx);
137 }
138 }
139
140
141
142
143 protected abstract void encode(ChannelHandlerContext ctx, I msg, Buffer out) throws Exception;
144
145
146
147
148 protected abstract void decode(ChannelHandlerContext ctx, Buffer in) throws Exception;
149
150
151
152
153 protected void decodeLast(ChannelHandlerContext ctx, Buffer in) throws Exception {
154 if (in.readableBytes() > 0) {
155
156
157 decode(ctx, in);
158 }
159 }
160
161 private final class Encoder extends MessageToByteEncoder<I> {
162 private final BufferAllocator allocator;
163
164 Encoder(BufferAllocator allocator) {
165 this.allocator = allocator;
166 }
167
168 @Override
169 public boolean acceptOutboundMessage(Object msg) throws Exception {
170 return ByteToMessageCodec.this.acceptOutboundMessage(msg);
171 }
172
173 @Override
174 protected Buffer allocateBuffer(ChannelHandlerContext ctx, I msg) throws Exception {
175 BufferAllocator alloc = allocator != null? allocator : ctx.bufferAllocator();
176 return alloc.allocate(256);
177 }
178
179 @Override
180 protected void encode(ChannelHandlerContext ctx, I msg, Buffer out) throws Exception {
181 ByteToMessageCodec.this.encode(ctx, msg, out);
182 }
183 }
184 }