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 if (lengthFieldLength != 1 && lengthFieldLength != 2 &&
147 lengthFieldLength != 3 && lengthFieldLength != 4 &&
148 lengthFieldLength != 8) {
149 throw new IllegalArgumentException(
150 "lengthFieldLength must be either 1, 2, 3, 4, or 8: " +
151 lengthFieldLength);
152 }
153 this.byteOrder = ObjectUtil.checkNotNull(byteOrder, "byteOrder");
154 this.lengthFieldLength = lengthFieldLength;
155 this.lengthIncludesLengthFieldLength = lengthIncludesLengthFieldLength;
156 this.lengthAdjustment = lengthAdjustment;
157 }
158
159 @Override
160 protected void encode(ChannelHandlerContext ctx, ByteBuf msg, List<Object> out) throws Exception {
161 int length = msg.readableBytes() + lengthAdjustment;
162 if (lengthIncludesLengthFieldLength) {
163 length += lengthFieldLength;
164 }
165
166 checkPositiveOrZero(length, "length");
167
168 switch (lengthFieldLength) {
169 case 1:
170 if (length >= 256) {
171 throw new IllegalArgumentException(
172 "length does not fit into a byte: " + length);
173 }
174 out.add(ctx.alloc().buffer(1).order(byteOrder).writeByte((byte) length));
175 break;
176 case 2:
177 if (length >= 65536) {
178 throw new IllegalArgumentException(
179 "length does not fit into a short integer: " + length);
180 }
181 out.add(ctx.alloc().buffer(2).order(byteOrder).writeShort((short) length));
182 break;
183 case 3:
184 if (length >= 16777216) {
185 throw new IllegalArgumentException(
186 "length does not fit into a medium integer: " + length);
187 }
188 out.add(ctx.alloc().buffer(3).order(byteOrder).writeMedium(length));
189 break;
190 case 4:
191 out.add(ctx.alloc().buffer(4).order(byteOrder).writeInt(length));
192 break;
193 case 8:
194 out.add(ctx.alloc().buffer(8).order(byteOrder).writeLong(length));
195 break;
196 default:
197 throw new Error("should not reach here");
198 }
199 out.add(msg.retain());
200 }
201 }