1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package io.netty.handler.codec;
17
18 import static io.netty.util.internal.ObjectUtil.checkPositiveOrZero;
19
20 import io.netty.buffer.ByteBuf;
21 import io.netty.channel.ChannelHandler.Sharable;
22 import io.netty.channel.ChannelHandlerContext;
23 import io.netty.util.internal.ObjectUtil;
24
25 import java.nio.ByteOrder;
26 import java.util.List;
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55 @Sharable
56 public class LengthFieldPrepender extends MessageToMessageEncoder<ByteBuf> {
57
58 private final ByteOrder byteOrder;
59 private final int lengthFieldLength;
60 private final boolean lengthIncludesLengthFieldLength;
61 private final int lengthAdjustment;
62
63
64
65
66
67
68
69
70
71
72 public LengthFieldPrepender(int lengthFieldLength) {
73 this(lengthFieldLength, false);
74 }
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89 public LengthFieldPrepender(int lengthFieldLength, boolean lengthIncludesLengthFieldLength) {
90 this(lengthFieldLength, 0, lengthIncludesLengthFieldLength);
91 }
92
93
94
95
96
97
98
99
100
101
102
103
104 public LengthFieldPrepender(int lengthFieldLength, int lengthAdjustment) {
105 this(lengthFieldLength, lengthAdjustment, false);
106 }
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123 public LengthFieldPrepender(int lengthFieldLength, int lengthAdjustment, boolean lengthIncludesLengthFieldLength) {
124 this(ByteOrder.BIG_ENDIAN, lengthFieldLength, lengthAdjustment, lengthIncludesLengthFieldLength);
125 }
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143 public LengthFieldPrepender(
144 ByteOrder byteOrder, int lengthFieldLength,
145 int lengthAdjustment, boolean lengthIncludesLengthFieldLength) {
146 super(ByteBuf.class);
147 if (lengthFieldLength != 1 && lengthFieldLength != 2 &&
148 lengthFieldLength != 3 && lengthFieldLength != 4 &&
149 lengthFieldLength != 8) {
150 throw new IllegalArgumentException(
151 "lengthFieldLength must be either 1, 2, 3, 4, or 8: " +
152 lengthFieldLength);
153 }
154 this.byteOrder = ObjectUtil.checkNotNull(byteOrder, "byteOrder");
155 this.lengthFieldLength = lengthFieldLength;
156 this.lengthIncludesLengthFieldLength = lengthIncludesLengthFieldLength;
157 this.lengthAdjustment = lengthAdjustment;
158 }
159
160 @Override
161 protected void encode(ChannelHandlerContext ctx, ByteBuf msg, List<Object> out) throws Exception {
162 int length = msg.readableBytes() + lengthAdjustment;
163 if (lengthIncludesLengthFieldLength) {
164 length += lengthFieldLength;
165 }
166
167 checkPositiveOrZero(length, "length");
168
169 switch (lengthFieldLength) {
170 case 1:
171 if (length >= 256) {
172 throw new IllegalArgumentException(
173 "length does not fit into a byte: " + length);
174 }
175 out.add(ctx.alloc().buffer(1).order(byteOrder).writeByte((byte) length));
176 break;
177 case 2:
178 if (length >= 65536) {
179 throw new IllegalArgumentException(
180 "length does not fit into a short integer: " + length);
181 }
182 out.add(ctx.alloc().buffer(2).order(byteOrder).writeShort((short) length));
183 break;
184 case 3:
185 if (length >= 16777216) {
186 throw new IllegalArgumentException(
187 "length does not fit into a medium integer: " + length);
188 }
189 out.add(ctx.alloc().buffer(3).order(byteOrder).writeMedium(length));
190 break;
191 case 4:
192 out.add(ctx.alloc().buffer(4).order(byteOrder).writeInt(length));
193 break;
194 case 8:
195 out.add(ctx.alloc().buffer(8).order(byteOrder).writeLong(length));
196 break;
197 default:
198 throw new Error("should not reach here");
199 }
200 out.add(msg.retain());
201 }
202 }