]>
Commit | Line | Data |
---|---|---|
f67539c2 TL |
1 | /// Licensed to the Apache Software Foundation (ASF) under one |
2 | /// or more contributor license agreements. See the NOTICE file | |
3 | /// distributed with this work for additional information | |
4 | /// regarding copyright ownership. The ASF licenses this file | |
5 | /// to you under the Apache License, Version 2.0 (the | |
6 | /// "License"); you may not use this file except in compliance | |
7 | /// with the License. You may obtain a copy of the License at | |
8 | /// | |
9 | /// http://www.apache.org/licenses/LICENSE-2.0 | |
10 | /// | |
11 | /// Unless required by applicable law or agreed to in writing, | |
12 | /// software distributed under the License is distributed on an | |
13 | /// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | |
14 | /// KIND, either express or implied. See the License for the | |
15 | /// specific language governing permissions and limitations | |
16 | /// under the License. | |
17 | ||
18 | part of thrift; | |
19 | ||
20 | class TBinaryProtocolFactory implements TProtocolFactory<TBinaryProtocol> { | |
21 | TBinaryProtocolFactory({this.strictRead: false, this.strictWrite: true}); | |
22 | ||
23 | final bool strictRead; | |
24 | final bool strictWrite; | |
25 | ||
26 | TBinaryProtocol getProtocol(TTransport transport) { | |
27 | return new TBinaryProtocol(transport, | |
28 | strictRead: strictRead, strictWrite: strictWrite); | |
29 | } | |
30 | } | |
31 | ||
32 | /// Binary protocol implementation for Thrift. | |
33 | /// | |
34 | /// Adapted from the C# version. | |
35 | class TBinaryProtocol extends TProtocol { | |
36 | static const int VERSION_MASK = 0xffff0000; | |
37 | static const int VERSION_1 = 0x80010000; | |
38 | ||
39 | static const Utf8Codec _utf8Codec = const Utf8Codec(); | |
40 | ||
41 | final bool strictRead; | |
42 | final bool strictWrite; | |
43 | ||
44 | TBinaryProtocol(TTransport transport, | |
45 | {this.strictRead: false, this.strictWrite: true}) | |
46 | : super(transport); | |
47 | ||
48 | /// write | |
49 | void writeMessageBegin(TMessage message) { | |
50 | if (strictWrite) { | |
51 | int version = VERSION_1 | message.type; | |
52 | writeI32(version); | |
53 | writeString(message.name); | |
54 | writeI32(message.seqid); | |
55 | } else { | |
56 | writeString(message.name); | |
57 | writeByte(message.type); | |
58 | writeI32(message.seqid); | |
59 | } | |
60 | } | |
61 | ||
62 | void writeMessageEnd() {} | |
63 | ||
64 | void writeStructBegin(TStruct struct) {} | |
65 | ||
66 | void writeStructEnd() {} | |
67 | ||
68 | void writeFieldBegin(TField field) { | |
69 | writeByte(field.type); | |
70 | writeI16(field.id); | |
71 | } | |
72 | ||
73 | void writeFieldEnd() {} | |
74 | ||
75 | void writeFieldStop() { | |
76 | writeByte(TType.STOP); | |
77 | } | |
78 | ||
79 | void writeMapBegin(TMap map) { | |
80 | writeByte(map.keyType); | |
81 | writeByte(map.valueType); | |
82 | writeI32(map.length); | |
83 | } | |
84 | ||
85 | void writeMapEnd() {} | |
86 | ||
87 | void writeListBegin(TList list) { | |
88 | writeByte(list.elementType); | |
89 | writeI32(list.length); | |
90 | } | |
91 | ||
92 | void writeListEnd() {} | |
93 | ||
94 | void writeSetBegin(TSet set) { | |
95 | writeByte(set.elementType); | |
96 | writeI32(set.length); | |
97 | } | |
98 | ||
99 | void writeSetEnd() {} | |
100 | ||
101 | void writeBool(bool b) { | |
102 | if (b == null) b = false; | |
103 | writeByte(b ? 1 : 0); | |
104 | } | |
105 | ||
106 | final ByteData _byteOut = new ByteData(1); | |
107 | void writeByte(int byte) { | |
108 | if (byte == null) byte = 0; | |
109 | _byteOut.setUint8(0, byte); | |
110 | transport.write(_byteOut.buffer.asUint8List(), 0, 1); | |
111 | } | |
112 | ||
113 | final ByteData _i16Out = new ByteData(2); | |
114 | void writeI16(int i16) { | |
115 | if (i16 == null) i16 = 0; | |
116 | _i16Out.setInt16(0, i16); | |
117 | transport.write(_i16Out.buffer.asUint8List(), 0, 2); | |
118 | } | |
119 | ||
120 | final ByteData _i32Out = new ByteData(4); | |
121 | void writeI32(int i32) { | |
122 | if (i32 == null) i32 = 0; | |
123 | _i32Out.setInt32(0, i32); | |
124 | transport.write(_i32Out.buffer.asUint8List(), 0, 4); | |
125 | } | |
126 | ||
127 | final Uint8List _i64Out = new Uint8List(8); | |
128 | void writeI64(int i64) { | |
129 | if (i64 == null) i64 = 0; | |
130 | var i = new Int64(i64); | |
131 | var bts = i.toBytes(); | |
132 | for (var j = 0; j < 8; j++) { | |
133 | _i64Out[j] = bts[8 - j - 1]; | |
134 | } | |
135 | transport.write(_i64Out, 0, 8); | |
136 | } | |
137 | ||
138 | void writeString(String s) { | |
139 | var bytes = s != null ? _utf8Codec.encode(s) : new Uint8List.fromList([]); | |
140 | writeI32(bytes.length); | |
141 | transport.write(bytes, 0, bytes.length); | |
142 | } | |
143 | ||
144 | final ByteData _doubleOut = new ByteData(8); | |
145 | void writeDouble(double d) { | |
146 | if (d == null) d = 0.0; | |
147 | _doubleOut.setFloat64(0, d); | |
148 | transport.write(_doubleOut.buffer.asUint8List(), 0, 8); | |
149 | } | |
150 | ||
151 | void writeBinary(Uint8List bytes) { | |
152 | var length = bytes.length; | |
153 | writeI32(length); | |
154 | transport.write(bytes, 0, length); | |
155 | } | |
156 | ||
157 | /// read | |
158 | TMessage readMessageBegin() { | |
159 | String name; | |
160 | int type; | |
161 | int seqid; | |
162 | ||
163 | int size = readI32(); | |
164 | if (size < 0) { | |
165 | int version = size & VERSION_MASK; | |
166 | if (version != VERSION_1) { | |
167 | throw new TProtocolError(TProtocolErrorType.BAD_VERSION, | |
168 | "Bad version in readMessageBegin: $version"); | |
169 | } | |
170 | type = size & 0x000000ff; | |
171 | name = readString(); | |
172 | seqid = readI32(); | |
173 | } else { | |
174 | if (strictRead) { | |
175 | throw new TProtocolError(TProtocolErrorType.BAD_VERSION, | |
176 | "Missing version in readMessageBegin"); | |
177 | } | |
178 | name = _readString(size); | |
179 | type = readByte(); | |
180 | seqid = readI32(); | |
181 | } | |
182 | return new TMessage(name, type, seqid); | |
183 | } | |
184 | ||
185 | void readMessageEnd() {} | |
186 | ||
187 | TStruct readStructBegin() { | |
188 | return new TStruct(); | |
189 | } | |
190 | ||
191 | void readStructEnd() {} | |
192 | ||
193 | TField readFieldBegin() { | |
194 | String name = ""; | |
195 | int type = readByte(); | |
196 | int id = type != TType.STOP ? readI16() : 0; | |
197 | ||
198 | return new TField(name, type, id); | |
199 | } | |
200 | ||
201 | void readFieldEnd() {} | |
202 | ||
203 | TMap readMapBegin() { | |
204 | int keyType = readByte(); | |
205 | int valueType = readByte(); | |
206 | int length = readI32(); | |
207 | ||
208 | return new TMap(keyType, valueType, length); | |
209 | } | |
210 | ||
211 | void readMapEnd() {} | |
212 | ||
213 | TList readListBegin() { | |
214 | int elementType = readByte(); | |
215 | int length = readI32(); | |
216 | ||
217 | return new TList(elementType, length); | |
218 | } | |
219 | ||
220 | void readListEnd() {} | |
221 | ||
222 | TSet readSetBegin() { | |
223 | int elementType = readByte(); | |
224 | int length = readI32(); | |
225 | ||
226 | return new TSet(elementType, length); | |
227 | } | |
228 | ||
229 | void readSetEnd() {} | |
230 | ||
231 | bool readBool() => readByte() == 1; | |
232 | ||
233 | final Uint8List _byteIn = new Uint8List(1); | |
234 | int readByte() { | |
235 | transport.readAll(_byteIn, 0, 1); | |
236 | return _byteIn.buffer.asByteData().getUint8(0); | |
237 | } | |
238 | ||
239 | final Uint8List _i16In = new Uint8List(2); | |
240 | int readI16() { | |
241 | transport.readAll(_i16In, 0, 2); | |
242 | return _i16In.buffer.asByteData().getInt16(0); | |
243 | } | |
244 | ||
245 | final Uint8List _i32In = new Uint8List(4); | |
246 | int readI32() { | |
247 | transport.readAll(_i32In, 0, 4); | |
248 | return _i32In.buffer.asByteData().getInt32(0); | |
249 | } | |
250 | ||
251 | final Uint8List _i64In = new Uint8List(8); | |
252 | int readI64() { | |
253 | transport.readAll(_i64In, 0, 8); | |
254 | var i = new Int64.fromBytesBigEndian(_i64In); | |
255 | return i.toInt(); | |
256 | } | |
257 | ||
258 | final Uint8List _doubleIn = new Uint8List(8); | |
259 | double readDouble() { | |
260 | transport.readAll(_doubleIn, 0, 8); | |
261 | return _doubleIn.buffer.asByteData().getFloat64(0); | |
262 | } | |
263 | ||
264 | String readString() { | |
265 | int size = readI32(); | |
266 | return _readString(size); | |
267 | } | |
268 | ||
269 | String _readString(int size) { | |
270 | Uint8List stringIn = new Uint8List(size); | |
271 | transport.readAll(stringIn, 0, size); | |
272 | return _utf8Codec.decode(stringIn); | |
273 | } | |
274 | ||
275 | Uint8List readBinary() { | |
276 | int length = readI32(); | |
277 | Uint8List binaryIn = new Uint8List(length); | |
278 | transport.readAll(binaryIn, 0, length); | |
279 | return binaryIn; | |
280 | } | |
281 | } |