]>
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 | //! Types used to send and receive primitives between a Thrift client and server. | |
19 | //! | |
20 | //! # Examples | |
21 | //! | |
22 | //! Create and use a `TInputProtocol`. | |
23 | //! | |
24 | //! ```no_run | |
25 | //! use thrift::protocol::{TBinaryInputProtocol, TInputProtocol}; | |
26 | //! use thrift::transport::TTcpChannel; | |
27 | //! | |
28 | //! // create the I/O channel | |
29 | //! let mut channel = TTcpChannel::new(); | |
30 | //! channel.open("127.0.0.1:9090").unwrap(); | |
31 | //! | |
32 | //! // create the protocol to decode bytes into types | |
33 | //! let mut protocol = TBinaryInputProtocol::new(channel, true); | |
34 | //! | |
35 | //! // read types from the wire | |
36 | //! let field_identifier = protocol.read_field_begin().unwrap(); | |
37 | //! let field_contents = protocol.read_string().unwrap(); | |
38 | //! let field_end = protocol.read_field_end().unwrap(); | |
39 | //! ``` | |
40 | //! | |
41 | //! Create and use a `TOutputProtocol`. | |
42 | //! | |
43 | //! ```no_run | |
44 | //! use thrift::protocol::{TBinaryOutputProtocol, TFieldIdentifier, TOutputProtocol, TType}; | |
45 | //! use thrift::transport::TTcpChannel; | |
46 | //! | |
47 | //! // create the I/O channel | |
48 | //! let mut channel = TTcpChannel::new(); | |
49 | //! channel.open("127.0.0.1:9090").unwrap(); | |
50 | //! | |
51 | //! // create the protocol to encode types into bytes | |
52 | //! let mut protocol = TBinaryOutputProtocol::new(channel, true); | |
53 | //! | |
54 | //! // write types | |
55 | //! protocol.write_field_begin(&TFieldIdentifier::new("string_thing", TType::String, 1)).unwrap(); | |
56 | //! protocol.write_string("foo").unwrap(); | |
57 | //! protocol.write_field_end().unwrap(); | |
58 | //! ``` | |
59 | ||
60 | use std::convert::{From, TryFrom}; | |
61 | use std::fmt; | |
62 | use std::fmt::{Display, Formatter}; | |
63 | ||
64 | use transport::{TReadTransport, TWriteTransport}; | |
65 | use {ProtocolError, ProtocolErrorKind}; | |
66 | ||
67 | #[cfg(test)] | |
68 | macro_rules! assert_eq_written_bytes { | |
69 | ($o_prot:ident, $expected_bytes:ident) => {{ | |
70 | assert_eq!($o_prot.transport.write_bytes(), &$expected_bytes); | |
71 | }}; | |
72 | } | |
73 | ||
74 | // FIXME: should take both read and write | |
75 | #[cfg(test)] | |
76 | macro_rules! copy_write_buffer_to_read_buffer { | |
77 | ($o_prot:ident) => {{ | |
78 | $o_prot.transport.copy_write_buffer_to_read_buffer(); | |
79 | }}; | |
80 | } | |
81 | ||
82 | #[cfg(test)] | |
83 | macro_rules! set_readable_bytes { | |
84 | ($i_prot:ident, $bytes:expr) => { | |
85 | $i_prot.transport.set_readable_bytes($bytes); | |
86 | }; | |
87 | } | |
88 | ||
89 | mod binary; | |
90 | mod compact; | |
91 | mod multiplexed; | |
92 | mod stored; | |
93 | ||
94 | pub use self::binary::{ | |
95 | TBinaryInputProtocol, TBinaryInputProtocolFactory, TBinaryOutputProtocol, | |
96 | TBinaryOutputProtocolFactory, | |
97 | }; | |
98 | pub use self::compact::{ | |
99 | TCompactInputProtocol, TCompactInputProtocolFactory, TCompactOutputProtocol, | |
100 | TCompactOutputProtocolFactory, | |
101 | }; | |
102 | pub use self::multiplexed::TMultiplexedOutputProtocol; | |
103 | pub use self::stored::TStoredInputProtocol; | |
104 | ||
105 | // Default maximum depth to which `TInputProtocol::skip` will skip a Thrift | |
106 | // field. A default is necessary because Thrift structs or collections may | |
107 | // contain nested structs and collections, which could result in indefinite | |
108 | // recursion. | |
109 | const MAXIMUM_SKIP_DEPTH: i8 = 64; | |
110 | ||
111 | /// Converts a stream of bytes into Thrift identifiers, primitives, | |
112 | /// containers, or structs. | |
113 | /// | |
114 | /// This trait does not deal with higher-level Thrift concepts like structs or | |
115 | /// exceptions - only with primitives and message or container boundaries. Once | |
116 | /// bytes are read they are deserialized and an identifier (for example | |
117 | /// `TMessageIdentifier`) or a primitive is returned. | |
118 | /// | |
119 | /// All methods return a `thrift::Result`. If an `Err` is returned the protocol | |
120 | /// instance and its underlying transport should be terminated. | |
121 | /// | |
122 | /// # Examples | |
123 | /// | |
124 | /// Create and use a `TInputProtocol` | |
125 | /// | |
126 | /// ```no_run | |
127 | /// use thrift::protocol::{TBinaryInputProtocol, TInputProtocol}; | |
128 | /// use thrift::transport::TTcpChannel; | |
129 | /// | |
130 | /// let mut channel = TTcpChannel::new(); | |
131 | /// channel.open("127.0.0.1:9090").unwrap(); | |
132 | /// | |
133 | /// let mut protocol = TBinaryInputProtocol::new(channel, true); | |
134 | /// | |
135 | /// let field_identifier = protocol.read_field_begin().unwrap(); | |
136 | /// let field_contents = protocol.read_string().unwrap(); | |
137 | /// let field_end = protocol.read_field_end().unwrap(); | |
138 | /// ``` | |
139 | pub trait TInputProtocol { | |
140 | /// Read the beginning of a Thrift message. | |
141 | fn read_message_begin(&mut self) -> ::Result<TMessageIdentifier>; | |
142 | /// Read the end of a Thrift message. | |
143 | fn read_message_end(&mut self) -> ::Result<()>; | |
144 | /// Read the beginning of a Thrift struct. | |
145 | fn read_struct_begin(&mut self) -> ::Result<Option<TStructIdentifier>>; | |
146 | /// Read the end of a Thrift struct. | |
147 | fn read_struct_end(&mut self) -> ::Result<()>; | |
148 | /// Read the beginning of a Thrift struct field. | |
149 | fn read_field_begin(&mut self) -> ::Result<TFieldIdentifier>; | |
150 | /// Read the end of a Thrift struct field. | |
151 | fn read_field_end(&mut self) -> ::Result<()>; | |
152 | /// Read a bool. | |
153 | fn read_bool(&mut self) -> ::Result<bool>; | |
154 | /// Read a fixed-length byte array. | |
155 | fn read_bytes(&mut self) -> ::Result<Vec<u8>>; | |
156 | /// Read a word. | |
157 | fn read_i8(&mut self) -> ::Result<i8>; | |
158 | /// Read a 16-bit signed integer. | |
159 | fn read_i16(&mut self) -> ::Result<i16>; | |
160 | /// Read a 32-bit signed integer. | |
161 | fn read_i32(&mut self) -> ::Result<i32>; | |
162 | /// Read a 64-bit signed integer. | |
163 | fn read_i64(&mut self) -> ::Result<i64>; | |
164 | /// Read a 64-bit float. | |
165 | fn read_double(&mut self) -> ::Result<f64>; | |
166 | /// Read a fixed-length string (not null terminated). | |
167 | fn read_string(&mut self) -> ::Result<String>; | |
168 | /// Read the beginning of a list. | |
169 | fn read_list_begin(&mut self) -> ::Result<TListIdentifier>; | |
170 | /// Read the end of a list. | |
171 | fn read_list_end(&mut self) -> ::Result<()>; | |
172 | /// Read the beginning of a set. | |
173 | fn read_set_begin(&mut self) -> ::Result<TSetIdentifier>; | |
174 | /// Read the end of a set. | |
175 | fn read_set_end(&mut self) -> ::Result<()>; | |
176 | /// Read the beginning of a map. | |
177 | fn read_map_begin(&mut self) -> ::Result<TMapIdentifier>; | |
178 | /// Read the end of a map. | |
179 | fn read_map_end(&mut self) -> ::Result<()>; | |
180 | /// Skip a field with type `field_type` recursively until the default | |
181 | /// maximum skip depth is reached. | |
182 | fn skip(&mut self, field_type: TType) -> ::Result<()> { | |
183 | self.skip_till_depth(field_type, MAXIMUM_SKIP_DEPTH) | |
184 | } | |
185 | /// Skip a field with type `field_type` recursively up to `depth` levels. | |
186 | fn skip_till_depth(&mut self, field_type: TType, depth: i8) -> ::Result<()> { | |
187 | if depth == 0 { | |
188 | return Err(::Error::Protocol(ProtocolError { | |
189 | kind: ProtocolErrorKind::DepthLimit, | |
190 | message: format!("cannot parse past {:?}", field_type), | |
191 | })); | |
192 | } | |
193 | ||
194 | match field_type { | |
195 | TType::Bool => self.read_bool().map(|_| ()), | |
196 | TType::I08 => self.read_i8().map(|_| ()), | |
197 | TType::I16 => self.read_i16().map(|_| ()), | |
198 | TType::I32 => self.read_i32().map(|_| ()), | |
199 | TType::I64 => self.read_i64().map(|_| ()), | |
200 | TType::Double => self.read_double().map(|_| ()), | |
201 | TType::String => self.read_string().map(|_| ()), | |
202 | TType::Struct => { | |
203 | self.read_struct_begin()?; | |
204 | loop { | |
205 | let field_ident = self.read_field_begin()?; | |
206 | if field_ident.field_type == TType::Stop { | |
207 | break; | |
208 | } | |
209 | self.skip_till_depth(field_ident.field_type, depth - 1)?; | |
210 | } | |
211 | self.read_struct_end() | |
212 | } | |
213 | TType::List => { | |
214 | let list_ident = self.read_list_begin()?; | |
215 | for _ in 0..list_ident.size { | |
216 | self.skip_till_depth(list_ident.element_type, depth - 1)?; | |
217 | } | |
218 | self.read_list_end() | |
219 | } | |
220 | TType::Set => { | |
221 | let set_ident = self.read_set_begin()?; | |
222 | for _ in 0..set_ident.size { | |
223 | self.skip_till_depth(set_ident.element_type, depth - 1)?; | |
224 | } | |
225 | self.read_set_end() | |
226 | } | |
227 | TType::Map => { | |
228 | let map_ident = self.read_map_begin()?; | |
229 | for _ in 0..map_ident.size { | |
230 | let key_type = map_ident | |
231 | .key_type | |
232 | .expect("non-zero sized map should contain key type"); | |
233 | let val_type = map_ident | |
234 | .value_type | |
235 | .expect("non-zero sized map should contain value type"); | |
236 | self.skip_till_depth(key_type, depth - 1)?; | |
237 | self.skip_till_depth(val_type, depth - 1)?; | |
238 | } | |
239 | self.read_map_end() | |
240 | } | |
241 | u => Err(::Error::Protocol(ProtocolError { | |
242 | kind: ProtocolErrorKind::Unknown, | |
243 | message: format!("cannot skip field type {:?}", &u), | |
244 | })), | |
245 | } | |
246 | } | |
247 | ||
248 | // utility (DO NOT USE IN GENERATED CODE!!!!) | |
249 | // | |
250 | ||
251 | /// Read an unsigned byte. | |
252 | /// | |
253 | /// This method should **never** be used in generated code. | |
254 | fn read_byte(&mut self) -> ::Result<u8>; | |
255 | } | |
256 | ||
257 | /// Converts Thrift identifiers, primitives, containers or structs into a | |
258 | /// stream of bytes. | |
259 | /// | |
260 | /// This trait does not deal with higher-level Thrift concepts like structs or | |
261 | /// exceptions - only with primitives and message or container boundaries. | |
262 | /// Write methods take an identifier (for example, `TMessageIdentifier`) or a | |
263 | /// primitive. Any or all of the fields in an identifier may be omitted when | |
264 | /// writing to the transport. Write methods may even be noops. All of this is | |
265 | /// transparent to the caller; as long as a matching `TInputProtocol` | |
266 | /// implementation is used, received messages will be decoded correctly. | |
267 | /// | |
268 | /// All methods return a `thrift::Result`. If an `Err` is returned the protocol | |
269 | /// instance and its underlying transport should be terminated. | |
270 | /// | |
271 | /// # Examples | |
272 | /// | |
273 | /// Create and use a `TOutputProtocol` | |
274 | /// | |
275 | /// ```no_run | |
276 | /// use thrift::protocol::{TBinaryOutputProtocol, TFieldIdentifier, TOutputProtocol, TType}; | |
277 | /// use thrift::transport::TTcpChannel; | |
278 | /// | |
279 | /// let mut channel = TTcpChannel::new(); | |
280 | /// channel.open("127.0.0.1:9090").unwrap(); | |
281 | /// | |
282 | /// let mut protocol = TBinaryOutputProtocol::new(channel, true); | |
283 | /// | |
284 | /// protocol.write_field_begin(&TFieldIdentifier::new("string_thing", TType::String, 1)).unwrap(); | |
285 | /// protocol.write_string("foo").unwrap(); | |
286 | /// protocol.write_field_end().unwrap(); | |
287 | /// ``` | |
288 | pub trait TOutputProtocol { | |
289 | /// Write the beginning of a Thrift message. | |
290 | fn write_message_begin(&mut self, identifier: &TMessageIdentifier) -> ::Result<()>; | |
291 | /// Write the end of a Thrift message. | |
292 | fn write_message_end(&mut self) -> ::Result<()>; | |
293 | /// Write the beginning of a Thrift struct. | |
294 | fn write_struct_begin(&mut self, identifier: &TStructIdentifier) -> ::Result<()>; | |
295 | /// Write the end of a Thrift struct. | |
296 | fn write_struct_end(&mut self) -> ::Result<()>; | |
297 | /// Write the beginning of a Thrift field. | |
298 | fn write_field_begin(&mut self, identifier: &TFieldIdentifier) -> ::Result<()>; | |
299 | /// Write the end of a Thrift field. | |
300 | fn write_field_end(&mut self) -> ::Result<()>; | |
301 | /// Write a STOP field indicating that all the fields in a struct have been | |
302 | /// written. | |
303 | fn write_field_stop(&mut self) -> ::Result<()>; | |
304 | /// Write a bool. | |
305 | fn write_bool(&mut self, b: bool) -> ::Result<()>; | |
306 | /// Write a fixed-length byte array. | |
307 | fn write_bytes(&mut self, b: &[u8]) -> ::Result<()>; | |
308 | /// Write an 8-bit signed integer. | |
309 | fn write_i8(&mut self, i: i8) -> ::Result<()>; | |
310 | /// Write a 16-bit signed integer. | |
311 | fn write_i16(&mut self, i: i16) -> ::Result<()>; | |
312 | /// Write a 32-bit signed integer. | |
313 | fn write_i32(&mut self, i: i32) -> ::Result<()>; | |
314 | /// Write a 64-bit signed integer. | |
315 | fn write_i64(&mut self, i: i64) -> ::Result<()>; | |
316 | /// Write a 64-bit float. | |
317 | fn write_double(&mut self, d: f64) -> ::Result<()>; | |
318 | /// Write a fixed-length string. | |
319 | fn write_string(&mut self, s: &str) -> ::Result<()>; | |
320 | /// Write the beginning of a list. | |
321 | fn write_list_begin(&mut self, identifier: &TListIdentifier) -> ::Result<()>; | |
322 | /// Write the end of a list. | |
323 | fn write_list_end(&mut self) -> ::Result<()>; | |
324 | /// Write the beginning of a set. | |
325 | fn write_set_begin(&mut self, identifier: &TSetIdentifier) -> ::Result<()>; | |
326 | /// Write the end of a set. | |
327 | fn write_set_end(&mut self) -> ::Result<()>; | |
328 | /// Write the beginning of a map. | |
329 | fn write_map_begin(&mut self, identifier: &TMapIdentifier) -> ::Result<()>; | |
330 | /// Write the end of a map. | |
331 | fn write_map_end(&mut self) -> ::Result<()>; | |
332 | /// Flush buffered bytes to the underlying transport. | |
333 | fn flush(&mut self) -> ::Result<()>; | |
334 | ||
335 | // utility (DO NOT USE IN GENERATED CODE!!!!) | |
336 | // | |
337 | ||
338 | /// Write an unsigned byte. | |
339 | /// | |
340 | /// This method should **never** be used in generated code. | |
341 | fn write_byte(&mut self, b: u8) -> ::Result<()>; // FIXME: REMOVE | |
342 | } | |
343 | ||
344 | impl<P> TInputProtocol for Box<P> | |
345 | where | |
346 | P: TInputProtocol + ?Sized, | |
347 | { | |
348 | fn read_message_begin(&mut self) -> ::Result<TMessageIdentifier> { | |
349 | (**self).read_message_begin() | |
350 | } | |
351 | ||
352 | fn read_message_end(&mut self) -> ::Result<()> { | |
353 | (**self).read_message_end() | |
354 | } | |
355 | ||
356 | fn read_struct_begin(&mut self) -> ::Result<Option<TStructIdentifier>> { | |
357 | (**self).read_struct_begin() | |
358 | } | |
359 | ||
360 | fn read_struct_end(&mut self) -> ::Result<()> { | |
361 | (**self).read_struct_end() | |
362 | } | |
363 | ||
364 | fn read_field_begin(&mut self) -> ::Result<TFieldIdentifier> { | |
365 | (**self).read_field_begin() | |
366 | } | |
367 | ||
368 | fn read_field_end(&mut self) -> ::Result<()> { | |
369 | (**self).read_field_end() | |
370 | } | |
371 | ||
372 | fn read_bool(&mut self) -> ::Result<bool> { | |
373 | (**self).read_bool() | |
374 | } | |
375 | ||
376 | fn read_bytes(&mut self) -> ::Result<Vec<u8>> { | |
377 | (**self).read_bytes() | |
378 | } | |
379 | ||
380 | fn read_i8(&mut self) -> ::Result<i8> { | |
381 | (**self).read_i8() | |
382 | } | |
383 | ||
384 | fn read_i16(&mut self) -> ::Result<i16> { | |
385 | (**self).read_i16() | |
386 | } | |
387 | ||
388 | fn read_i32(&mut self) -> ::Result<i32> { | |
389 | (**self).read_i32() | |
390 | } | |
391 | ||
392 | fn read_i64(&mut self) -> ::Result<i64> { | |
393 | (**self).read_i64() | |
394 | } | |
395 | ||
396 | fn read_double(&mut self) -> ::Result<f64> { | |
397 | (**self).read_double() | |
398 | } | |
399 | ||
400 | fn read_string(&mut self) -> ::Result<String> { | |
401 | (**self).read_string() | |
402 | } | |
403 | ||
404 | fn read_list_begin(&mut self) -> ::Result<TListIdentifier> { | |
405 | (**self).read_list_begin() | |
406 | } | |
407 | ||
408 | fn read_list_end(&mut self) -> ::Result<()> { | |
409 | (**self).read_list_end() | |
410 | } | |
411 | ||
412 | fn read_set_begin(&mut self) -> ::Result<TSetIdentifier> { | |
413 | (**self).read_set_begin() | |
414 | } | |
415 | ||
416 | fn read_set_end(&mut self) -> ::Result<()> { | |
417 | (**self).read_set_end() | |
418 | } | |
419 | ||
420 | fn read_map_begin(&mut self) -> ::Result<TMapIdentifier> { | |
421 | (**self).read_map_begin() | |
422 | } | |
423 | ||
424 | fn read_map_end(&mut self) -> ::Result<()> { | |
425 | (**self).read_map_end() | |
426 | } | |
427 | ||
428 | fn read_byte(&mut self) -> ::Result<u8> { | |
429 | (**self).read_byte() | |
430 | } | |
431 | } | |
432 | ||
433 | impl<P> TOutputProtocol for Box<P> | |
434 | where | |
435 | P: TOutputProtocol + ?Sized, | |
436 | { | |
437 | fn write_message_begin(&mut self, identifier: &TMessageIdentifier) -> ::Result<()> { | |
438 | (**self).write_message_begin(identifier) | |
439 | } | |
440 | ||
441 | fn write_message_end(&mut self) -> ::Result<()> { | |
442 | (**self).write_message_end() | |
443 | } | |
444 | ||
445 | fn write_struct_begin(&mut self, identifier: &TStructIdentifier) -> ::Result<()> { | |
446 | (**self).write_struct_begin(identifier) | |
447 | } | |
448 | ||
449 | fn write_struct_end(&mut self) -> ::Result<()> { | |
450 | (**self).write_struct_end() | |
451 | } | |
452 | ||
453 | fn write_field_begin(&mut self, identifier: &TFieldIdentifier) -> ::Result<()> { | |
454 | (**self).write_field_begin(identifier) | |
455 | } | |
456 | ||
457 | fn write_field_end(&mut self) -> ::Result<()> { | |
458 | (**self).write_field_end() | |
459 | } | |
460 | ||
461 | fn write_field_stop(&mut self) -> ::Result<()> { | |
462 | (**self).write_field_stop() | |
463 | } | |
464 | ||
465 | fn write_bool(&mut self, b: bool) -> ::Result<()> { | |
466 | (**self).write_bool(b) | |
467 | } | |
468 | ||
469 | fn write_bytes(&mut self, b: &[u8]) -> ::Result<()> { | |
470 | (**self).write_bytes(b) | |
471 | } | |
472 | ||
473 | fn write_i8(&mut self, i: i8) -> ::Result<()> { | |
474 | (**self).write_i8(i) | |
475 | } | |
476 | ||
477 | fn write_i16(&mut self, i: i16) -> ::Result<()> { | |
478 | (**self).write_i16(i) | |
479 | } | |
480 | ||
481 | fn write_i32(&mut self, i: i32) -> ::Result<()> { | |
482 | (**self).write_i32(i) | |
483 | } | |
484 | ||
485 | fn write_i64(&mut self, i: i64) -> ::Result<()> { | |
486 | (**self).write_i64(i) | |
487 | } | |
488 | ||
489 | fn write_double(&mut self, d: f64) -> ::Result<()> { | |
490 | (**self).write_double(d) | |
491 | } | |
492 | ||
493 | fn write_string(&mut self, s: &str) -> ::Result<()> { | |
494 | (**self).write_string(s) | |
495 | } | |
496 | ||
497 | fn write_list_begin(&mut self, identifier: &TListIdentifier) -> ::Result<()> { | |
498 | (**self).write_list_begin(identifier) | |
499 | } | |
500 | ||
501 | fn write_list_end(&mut self) -> ::Result<()> { | |
502 | (**self).write_list_end() | |
503 | } | |
504 | ||
505 | fn write_set_begin(&mut self, identifier: &TSetIdentifier) -> ::Result<()> { | |
506 | (**self).write_set_begin(identifier) | |
507 | } | |
508 | ||
509 | fn write_set_end(&mut self) -> ::Result<()> { | |
510 | (**self).write_set_end() | |
511 | } | |
512 | ||
513 | fn write_map_begin(&mut self, identifier: &TMapIdentifier) -> ::Result<()> { | |
514 | (**self).write_map_begin(identifier) | |
515 | } | |
516 | ||
517 | fn write_map_end(&mut self) -> ::Result<()> { | |
518 | (**self).write_map_end() | |
519 | } | |
520 | ||
521 | fn flush(&mut self) -> ::Result<()> { | |
522 | (**self).flush() | |
523 | } | |
524 | ||
525 | fn write_byte(&mut self, b: u8) -> ::Result<()> { | |
526 | (**self).write_byte(b) | |
527 | } | |
528 | } | |
529 | ||
530 | /// Helper type used by servers to create `TInputProtocol` instances for | |
531 | /// accepted client connections. | |
532 | /// | |
533 | /// # Examples | |
534 | /// | |
535 | /// Create a `TInputProtocolFactory` and use it to create a `TInputProtocol`. | |
536 | /// | |
537 | /// ```no_run | |
538 | /// use thrift::protocol::{TBinaryInputProtocolFactory, TInputProtocolFactory}; | |
539 | /// use thrift::transport::TTcpChannel; | |
540 | /// | |
541 | /// let mut channel = TTcpChannel::new(); | |
542 | /// channel.open("127.0.0.1:9090").unwrap(); | |
543 | /// | |
544 | /// let factory = TBinaryInputProtocolFactory::new(); | |
545 | /// let protocol = factory.create(Box::new(channel)); | |
546 | /// ``` | |
547 | pub trait TInputProtocolFactory { | |
548 | // Create a `TInputProtocol` that reads bytes from `transport`. | |
549 | fn create(&self, transport: Box<dyn TReadTransport + Send>) -> Box<dyn TInputProtocol + Send>; | |
550 | } | |
551 | ||
552 | impl<T> TInputProtocolFactory for Box<T> | |
553 | where | |
554 | T: TInputProtocolFactory + ?Sized, | |
555 | { | |
556 | fn create(&self, transport: Box<dyn TReadTransport + Send>) -> Box<dyn TInputProtocol + Send> { | |
557 | (**self).create(transport) | |
558 | } | |
559 | } | |
560 | ||
561 | /// Helper type used by servers to create `TOutputProtocol` instances for | |
562 | /// accepted client connections. | |
563 | /// | |
564 | /// # Examples | |
565 | /// | |
566 | /// Create a `TOutputProtocolFactory` and use it to create a `TOutputProtocol`. | |
567 | /// | |
568 | /// ```no_run | |
569 | /// use thrift::protocol::{TBinaryOutputProtocolFactory, TOutputProtocolFactory}; | |
570 | /// use thrift::transport::TTcpChannel; | |
571 | /// | |
572 | /// let mut channel = TTcpChannel::new(); | |
573 | /// channel.open("127.0.0.1:9090").unwrap(); | |
574 | /// | |
575 | /// let factory = TBinaryOutputProtocolFactory::new(); | |
576 | /// let protocol = factory.create(Box::new(channel)); | |
577 | /// ``` | |
578 | pub trait TOutputProtocolFactory { | |
579 | /// Create a `TOutputProtocol` that writes bytes to `transport`. | |
580 | fn create(&self, transport: Box<dyn TWriteTransport + Send>) -> Box<dyn TOutputProtocol + Send>; | |
581 | } | |
582 | ||
583 | impl<T> TOutputProtocolFactory for Box<T> | |
584 | where | |
585 | T: TOutputProtocolFactory + ?Sized, | |
586 | { | |
587 | fn create(&self, transport: Box<dyn TWriteTransport + Send>) -> Box<dyn TOutputProtocol + Send> { | |
588 | (**self).create(transport) | |
589 | } | |
590 | } | |
591 | ||
592 | /// Thrift message identifier. | |
593 | #[derive(Clone, Debug, Eq, PartialEq)] | |
594 | pub struct TMessageIdentifier { | |
595 | /// Service call the message is associated with. | |
596 | pub name: String, | |
597 | /// Message type. | |
598 | pub message_type: TMessageType, | |
599 | /// Ordered sequence number identifying the message. | |
600 | pub sequence_number: i32, | |
601 | } | |
602 | ||
603 | impl TMessageIdentifier { | |
604 | /// Create a `TMessageIdentifier` for a Thrift service-call named `name` | |
605 | /// with message type `message_type` and sequence number `sequence_number`. | |
606 | pub fn new<S: Into<String>>( | |
607 | name: S, | |
608 | message_type: TMessageType, | |
609 | sequence_number: i32, | |
610 | ) -> TMessageIdentifier { | |
611 | TMessageIdentifier { | |
612 | name: name.into(), | |
613 | message_type: message_type, | |
614 | sequence_number: sequence_number, | |
615 | } | |
616 | } | |
617 | } | |
618 | ||
619 | /// Thrift struct identifier. | |
620 | #[derive(Clone, Debug, Eq, PartialEq)] | |
621 | pub struct TStructIdentifier { | |
622 | /// Name of the encoded Thrift struct. | |
623 | pub name: String, | |
624 | } | |
625 | ||
626 | impl TStructIdentifier { | |
627 | /// Create a `TStructIdentifier` for a struct named `name`. | |
628 | pub fn new<S: Into<String>>(name: S) -> TStructIdentifier { | |
629 | TStructIdentifier { name: name.into() } | |
630 | } | |
631 | } | |
632 | ||
633 | /// Thrift field identifier. | |
634 | #[derive(Clone, Debug, Eq, PartialEq)] | |
635 | pub struct TFieldIdentifier { | |
636 | /// Name of the Thrift field. | |
637 | /// | |
638 | /// `None` if it's not sent over the wire. | |
639 | pub name: Option<String>, | |
640 | /// Field type. | |
641 | /// | |
642 | /// This may be a primitive, container, or a struct. | |
643 | pub field_type: TType, | |
644 | /// Thrift field id. | |
645 | /// | |
646 | /// `None` only if `field_type` is `TType::Stop`. | |
647 | pub id: Option<i16>, | |
648 | } | |
649 | ||
650 | impl TFieldIdentifier { | |
651 | /// Create a `TFieldIdentifier` for a field named `name` with type | |
652 | /// `field_type` and field id `id`. | |
653 | /// | |
654 | /// `id` should be `None` if `field_type` is `TType::Stop`. | |
655 | pub fn new<N, S, I>(name: N, field_type: TType, id: I) -> TFieldIdentifier | |
656 | where | |
657 | N: Into<Option<S>>, | |
658 | S: Into<String>, | |
659 | I: Into<Option<i16>>, | |
660 | { | |
661 | TFieldIdentifier { | |
662 | name: name.into().map(|n| n.into()), | |
663 | field_type: field_type, | |
664 | id: id.into(), | |
665 | } | |
666 | } | |
667 | } | |
668 | ||
669 | /// Thrift list identifier. | |
670 | #[derive(Clone, Debug, Eq, PartialEq)] | |
671 | pub struct TListIdentifier { | |
672 | /// Type of the elements in the list. | |
673 | pub element_type: TType, | |
674 | /// Number of elements in the list. | |
675 | pub size: i32, | |
676 | } | |
677 | ||
678 | impl TListIdentifier { | |
679 | /// Create a `TListIdentifier` for a list with `size` elements of type | |
680 | /// `element_type`. | |
681 | pub fn new(element_type: TType, size: i32) -> TListIdentifier { | |
682 | TListIdentifier { | |
683 | element_type: element_type, | |
684 | size: size, | |
685 | } | |
686 | } | |
687 | } | |
688 | ||
689 | /// Thrift set identifier. | |
690 | #[derive(Clone, Debug, Eq, PartialEq)] | |
691 | pub struct TSetIdentifier { | |
692 | /// Type of the elements in the set. | |
693 | pub element_type: TType, | |
694 | /// Number of elements in the set. | |
695 | pub size: i32, | |
696 | } | |
697 | ||
698 | impl TSetIdentifier { | |
699 | /// Create a `TSetIdentifier` for a set with `size` elements of type | |
700 | /// `element_type`. | |
701 | pub fn new(element_type: TType, size: i32) -> TSetIdentifier { | |
702 | TSetIdentifier { | |
703 | element_type: element_type, | |
704 | size: size, | |
705 | } | |
706 | } | |
707 | } | |
708 | ||
709 | /// Thrift map identifier. | |
710 | #[derive(Clone, Debug, Eq, PartialEq)] | |
711 | pub struct TMapIdentifier { | |
712 | /// Map key type. | |
713 | pub key_type: Option<TType>, | |
714 | /// Map value type. | |
715 | pub value_type: Option<TType>, | |
716 | /// Number of entries in the map. | |
717 | pub size: i32, | |
718 | } | |
719 | ||
720 | impl TMapIdentifier { | |
721 | /// Create a `TMapIdentifier` for a map with `size` entries of type | |
722 | /// `key_type -> value_type`. | |
723 | pub fn new<K, V>(key_type: K, value_type: V, size: i32) -> TMapIdentifier | |
724 | where | |
725 | K: Into<Option<TType>>, | |
726 | V: Into<Option<TType>>, | |
727 | { | |
728 | TMapIdentifier { | |
729 | key_type: key_type.into(), | |
730 | value_type: value_type.into(), | |
731 | size: size, | |
732 | } | |
733 | } | |
734 | } | |
735 | ||
736 | /// Thrift message types. | |
737 | #[derive(Clone, Copy, Debug, Eq, PartialEq)] | |
738 | pub enum TMessageType { | |
739 | /// Service-call request. | |
740 | Call, | |
741 | /// Service-call response. | |
742 | Reply, | |
743 | /// Unexpected error in the remote service. | |
744 | Exception, | |
745 | /// One-way service-call request (no response is expected). | |
746 | OneWay, | |
747 | } | |
748 | ||
749 | impl Display for TMessageType { | |
750 | fn fmt(&self, f: &mut Formatter) -> fmt::Result { | |
751 | match *self { | |
752 | TMessageType::Call => write!(f, "Call"), | |
753 | TMessageType::Reply => write!(f, "Reply"), | |
754 | TMessageType::Exception => write!(f, "Exception"), | |
755 | TMessageType::OneWay => write!(f, "OneWay"), | |
756 | } | |
757 | } | |
758 | } | |
759 | ||
760 | impl From<TMessageType> for u8 { | |
761 | fn from(message_type: TMessageType) -> Self { | |
762 | match message_type { | |
763 | TMessageType::Call => 0x01, | |
764 | TMessageType::Reply => 0x02, | |
765 | TMessageType::Exception => 0x03, | |
766 | TMessageType::OneWay => 0x04, | |
767 | } | |
768 | } | |
769 | } | |
770 | ||
771 | impl TryFrom<u8> for TMessageType { | |
772 | type Error = ::Error; | |
773 | fn try_from(b: u8) -> Result<Self, Self::Error> { | |
774 | match b { | |
775 | 0x01 => Ok(TMessageType::Call), | |
776 | 0x02 => Ok(TMessageType::Reply), | |
777 | 0x03 => Ok(TMessageType::Exception), | |
778 | 0x04 => Ok(TMessageType::OneWay), | |
779 | unkn => Err(::Error::Protocol(ProtocolError { | |
780 | kind: ProtocolErrorKind::InvalidData, | |
781 | message: format!("cannot convert {} to TMessageType", unkn), | |
782 | })), | |
783 | } | |
784 | } | |
785 | } | |
786 | ||
787 | /// Thrift struct-field types. | |
788 | #[derive(Clone, Copy, Debug, Eq, PartialEq)] | |
789 | pub enum TType { | |
790 | /// Indicates that there are no more serialized fields in this Thrift struct. | |
791 | Stop, | |
792 | /// Void (`()`) field. | |
793 | Void, | |
794 | /// Boolean. | |
795 | Bool, | |
796 | /// Signed 8-bit int. | |
797 | I08, | |
798 | /// Double-precision number. | |
799 | Double, | |
800 | /// Signed 16-bit int. | |
801 | I16, | |
802 | /// Signed 32-bit int. | |
803 | I32, | |
804 | /// Signed 64-bit int. | |
805 | I64, | |
806 | /// UTF-8 string. | |
807 | String, | |
808 | /// UTF-7 string. *Unsupported*. | |
809 | Utf7, | |
810 | /// Thrift struct. | |
811 | Struct, | |
812 | /// Map. | |
813 | Map, | |
814 | /// Set. | |
815 | Set, | |
816 | /// List. | |
817 | List, | |
818 | /// UTF-8 string. | |
819 | Utf8, | |
820 | /// UTF-16 string. *Unsupported*. | |
821 | Utf16, | |
822 | } | |
823 | ||
824 | impl Display for TType { | |
825 | fn fmt(&self, f: &mut Formatter) -> fmt::Result { | |
826 | match *self { | |
827 | TType::Stop => write!(f, "STOP"), | |
828 | TType::Void => write!(f, "void"), | |
829 | TType::Bool => write!(f, "bool"), | |
830 | TType::I08 => write!(f, "i08"), | |
831 | TType::Double => write!(f, "double"), | |
832 | TType::I16 => write!(f, "i16"), | |
833 | TType::I32 => write!(f, "i32"), | |
834 | TType::I64 => write!(f, "i64"), | |
835 | TType::String => write!(f, "string"), | |
836 | TType::Utf7 => write!(f, "UTF7"), | |
837 | TType::Struct => write!(f, "struct"), | |
838 | TType::Map => write!(f, "map"), | |
839 | TType::Set => write!(f, "set"), | |
840 | TType::List => write!(f, "list"), | |
841 | TType::Utf8 => write!(f, "UTF8"), | |
842 | TType::Utf16 => write!(f, "UTF16"), | |
843 | } | |
844 | } | |
845 | } | |
846 | ||
847 | /// Compare the expected message sequence number `expected` with the received | |
848 | /// message sequence number `actual`. | |
849 | /// | |
850 | /// Return `()` if `actual == expected`, `Err` otherwise. | |
851 | pub fn verify_expected_sequence_number(expected: i32, actual: i32) -> ::Result<()> { | |
852 | if expected == actual { | |
853 | Ok(()) | |
854 | } else { | |
855 | Err(::Error::Application(::ApplicationError { | |
856 | kind: ::ApplicationErrorKind::BadSequenceId, | |
857 | message: format!("expected {} got {}", expected, actual), | |
858 | })) | |
859 | } | |
860 | } | |
861 | ||
862 | /// Compare the expected service-call name `expected` with the received | |
863 | /// service-call name `actual`. | |
864 | /// | |
865 | /// Return `()` if `actual == expected`, `Err` otherwise. | |
866 | pub fn verify_expected_service_call(expected: &str, actual: &str) -> ::Result<()> { | |
867 | if expected == actual { | |
868 | Ok(()) | |
869 | } else { | |
870 | Err(::Error::Application(::ApplicationError { | |
871 | kind: ::ApplicationErrorKind::WrongMethodName, | |
872 | message: format!("expected {} got {}", expected, actual), | |
873 | })) | |
874 | } | |
875 | } | |
876 | ||
877 | /// Compare the expected message type `expected` with the received message type | |
878 | /// `actual`. | |
879 | /// | |
880 | /// Return `()` if `actual == expected`, `Err` otherwise. | |
881 | pub fn verify_expected_message_type(expected: TMessageType, actual: TMessageType) -> ::Result<()> { | |
882 | if expected == actual { | |
883 | Ok(()) | |
884 | } else { | |
885 | Err(::Error::Application(::ApplicationError { | |
886 | kind: ::ApplicationErrorKind::InvalidMessageType, | |
887 | message: format!("expected {} got {}", expected, actual), | |
888 | })) | |
889 | } | |
890 | } | |
891 | ||
892 | /// Check if a required Thrift struct field exists. | |
893 | /// | |
894 | /// Return `()` if it does, `Err` otherwise. | |
895 | pub fn verify_required_field_exists<T>(field_name: &str, field: &Option<T>) -> ::Result<()> { | |
896 | match *field { | |
897 | Some(_) => Ok(()), | |
898 | None => Err(::Error::Protocol(::ProtocolError { | |
899 | kind: ::ProtocolErrorKind::Unknown, | |
900 | message: format!("missing required field {}", field_name), | |
901 | })), | |
902 | } | |
903 | } | |
904 | ||
905 | /// Extract the field id from a Thrift field identifier. | |
906 | /// | |
907 | /// `field_ident` must *not* have `TFieldIdentifier.field_type` of type `TType::Stop`. | |
908 | /// | |
909 | /// Return `TFieldIdentifier.id` if an id exists, `Err` otherwise. | |
910 | pub fn field_id(field_ident: &TFieldIdentifier) -> ::Result<i16> { | |
911 | field_ident.id.ok_or_else(|| { | |
912 | ::Error::Protocol(::ProtocolError { | |
913 | kind: ::ProtocolErrorKind::Unknown, | |
914 | message: format!("missing field in in {:?}", field_ident), | |
915 | }) | |
916 | }) | |
917 | } | |
918 | ||
919 | #[cfg(test)] | |
920 | mod tests { | |
921 | ||
922 | use std::io::Cursor; | |
923 | ||
924 | use super::*; | |
925 | use transport::{TReadTransport, TWriteTransport}; | |
926 | ||
927 | #[test] | |
928 | fn must_create_usable_input_protocol_from_concrete_input_protocol() { | |
929 | let r: Box<dyn TReadTransport> = Box::new(Cursor::new([0, 1, 2])); | |
930 | let mut t = TCompactInputProtocol::new(r); | |
931 | takes_input_protocol(&mut t) | |
932 | } | |
933 | ||
934 | #[test] | |
935 | fn must_create_usable_input_protocol_from_boxed_input() { | |
936 | let r: Box<dyn TReadTransport> = Box::new(Cursor::new([0, 1, 2])); | |
937 | let mut t: Box<dyn TInputProtocol> = Box::new(TCompactInputProtocol::new(r)); | |
938 | takes_input_protocol(&mut t) | |
939 | } | |
940 | ||
941 | #[test] | |
942 | fn must_create_usable_output_protocol_from_concrete_output_protocol() { | |
943 | let w: Box<dyn TWriteTransport> = Box::new(vec![0u8; 10]); | |
944 | let mut t = TCompactOutputProtocol::new(w); | |
945 | takes_output_protocol(&mut t) | |
946 | } | |
947 | ||
948 | #[test] | |
949 | fn must_create_usable_output_protocol_from_boxed_output() { | |
950 | let w: Box<dyn TWriteTransport> = Box::new(vec![0u8; 10]); | |
951 | let mut t: Box<dyn TOutputProtocol> = Box::new(TCompactOutputProtocol::new(w)); | |
952 | takes_output_protocol(&mut t) | |
953 | } | |
954 | ||
955 | fn takes_input_protocol<R>(t: &mut R) | |
956 | where | |
957 | R: TInputProtocol, | |
958 | { | |
959 | t.read_byte().unwrap(); | |
960 | } | |
961 | ||
962 | fn takes_output_protocol<W>(t: &mut W) | |
963 | where | |
964 | W: TOutputProtocol, | |
965 | { | |
966 | t.flush().unwrap(); | |
967 | } | |
968 | } |