]> git.proxmox.com Git - ceph.git/blob - ceph/src/jaegertracing/thrift/tutorial/rs/README.md
update source to Ceph Pacific 16.2.2
[ceph.git] / ceph / src / jaegertracing / thrift / tutorial / rs / README.md
1 # Rust Language Bindings for Thrift
2
3 ## Getting Started
4
5 1. Get the [Thrift compiler](https://thrift.apache.org).
6
7 2. Add the following crates to your `Cargo.toml`.
8
9 ```toml
10 thrift = "x.y.z" # x.y.z is the version of the thrift compiler
11 ordered-float = "0.3.0"
12 try_from = "0.2.0"
13 ```
14
15 3. Add the same crates to your `lib.rs` or `main.rs`.
16
17 ```rust
18 extern crate ordered_float;
19 extern crate thrift;
20 extern crate try_from;
21 ```
22
23 4. Generate Rust sources for your IDL (for example, `Tutorial.thrift`).
24
25 ```shell
26 thrift -out my_rust_program/src --gen rs -r Tutorial.thrift
27 ```
28
29 5. Use the generated source in your code.
30
31 ```rust
32 // add extern crates here, or in your lib.rs
33 extern crate ordered_float;
34 extern crate thrift;
35 extern crate try_from;
36
37 // generated Rust module
38 mod tutorial;
39
40 use thrift::protocol::{TCompactInputProtocol, TCompactOutputProtocol};
41 use thrift::protocol::{TInputProtocol, TOutputProtocol};
42 use thrift::transport::{TFramedReadTransport, TFramedWriteTransport};
43 use thrift::transport::{TIoChannel, TTcpChannel};
44
45 use tutorial::{CalculatorSyncClient, TCalculatorSyncClient};
46 use tutorial::{Operation, Work};
47
48 fn main() {
49 match run() {
50 Ok(()) => println!("client ran successfully"),
51 Err(e) => {
52 println!("client failed with {:?}", e);
53 std::process::exit(1);
54 }
55 }
56 }
57
58 fn run() -> thrift::Result<()> {
59 //
60 // build client
61 //
62
63 println!("connect to server on 127.0.0.1:9090");
64 let mut c = TTcpChannel::new();
65 c.open("127.0.0.1:9090")?;
66
67 let (i_chan, o_chan) = c.split()?;
68
69 let i_prot = TCompactInputProtocol::new(
70 TFramedReadTransport::new(i_chan)
71 );
72 let o_prot = TCompactOutputProtocol::new(
73 TFramedWriteTransport::new(o_chan)
74 );
75
76 let mut client = CalculatorSyncClient::new(i_prot, o_prot);
77
78 //
79 // alright! - let's make some calls
80 //
81
82 // two-way, void return
83 client.ping()?;
84
85 // two-way with some return
86 let res = client.calculate(
87 72,
88 Work::new(7, 8, Operation::Multiply, None)
89 )?;
90 println!("multiplied 7 and 8, got {}", res);
91
92 // two-way and returns a Thrift-defined exception
93 let res = client.calculate(
94 77,
95 Work::new(2, 0, Operation::Divide, None)
96 );
97 match res {
98 Ok(v) => panic!("shouldn't have succeeded with result {}", v),
99 Err(e) => println!("divide by zero failed with {:?}", e),
100 }
101
102 // one-way
103 client.zip()?;
104
105 // done!
106 Ok(())
107 }
108 ```
109
110 ## Code Generation
111
112 ### Thrift Files and Generated Modules
113
114 The Thrift code generator takes each Thrift file and generates a Rust module
115 with the same name snake-cased. For example, running the compiler on
116 `ThriftTest.thrift` creates `thrift_test.rs`. To use these generated files add
117 `mod ...` and `use ...` declarations to your `lib.rs` or `main.rs` - one for
118 each generated file.
119
120 ### Results and Errors
121
122 The Thrift runtime library defines a `thrift::Result` and a `thrift::Error` type,
123 both of which are used throught the runtime library and in all generated code.
124 Conversions are defined from `std::io::Error`, `str` and `String` into
125 `thrift::Error`.
126
127 ### Thrift Type and their Rust Equivalents
128
129 Thrift defines a number of types, each of which is translated into its Rust
130 equivalent by the code generator.
131
132 * Primitives (bool, i8, i16, i32, i64, double, string, binary)
133 * Typedefs
134 * Enums
135 * Containers
136 * Structs
137 * Unions
138 * Exceptions
139 * Services
140 * Constants (primitives, containers, structs)
141
142 In addition, unless otherwise noted, thrift includes are translated into
143 `use ...` statements in the generated code, and all declarations, parameters,
144 traits and types in the generated code are namespaced appropriately.
145
146 The following subsections cover each type and their generated Rust equivalent.
147
148 ### Primitives
149
150 Thrift primitives have straightforward Rust equivalents.
151
152 * bool: `bool`
153 * i8: `i8`
154 * i16: `i16`
155 * i32: `i32`
156 * i64: `i64`
157 * double: `OrderedFloat<f64>`
158 * string: `String`
159 * binary: `Vec<u8>`
160
161 ### Typedefs
162
163 A typedef is translated to a `pub type` declaration.
164
165 ```thrift
166 typedef i64 UserId
167
168 typedef map<string, UserId> MapType
169 ```
170 ```rust
171 pub type UserId = i64;
172
173 pub type MapType = BTreeMap<String, Bonk>;
174 ```
175
176 ### Enums
177
178 A Thrift enum is represented as a Rust enum, and each variant is transcribed 1:1.
179
180 ```thrift
181 enum Numberz
182 {
183 ONE = 1,
184 TWO,
185 THREE,
186 FIVE = 5,
187 SIX,
188 EIGHT = 8
189 }
190 ```
191
192 ```rust
193 #[derive(Copy, Clone, Debug, Eq, Ord, PartialEq, PartialOrd)]
194 pub enum Numberz {
195 ONE = 1,
196 TWO = 2,
197 THREE = 3,
198 FIVE = 5,
199 SIX = 6,
200 EIGHT = 8,
201 }
202
203 impl TryFrom<i32> for Numberz {
204 // ...
205 }
206
207 ```
208
209 ### Containers
210
211 Thrift has three container types: list, set and map. They are translated into
212 Rust `Vec`, `BTreeSet` and `BTreeMap` respectively. Any Thrift type (this
213 includes structs, enums and typedefs) can be a list/set element or a map
214 key/value.
215
216 #### List
217
218 ```thrift
219 list <i32> numbers
220 ```
221
222 ```rust
223 numbers: Vec<i32>
224 ```
225
226 #### Set
227
228 ```thrift
229 set <i32> numbers
230 ```
231
232 ```rust
233 numbers: BTreeSet<i32>
234 ```
235
236 #### Map
237
238 ```thrift
239 map <string, i32> numbers
240 ```
241
242 ```rust
243 numbers: BTreeMap<String, i32>
244 ```
245
246 ### Structs
247
248 A Thrift struct is represented as a Rust struct, and each field transcribed 1:1.
249
250 ```thrift
251 struct CrazyNesting {
252 1: string string_field,
253 2: optional set<Insanity> set_field,
254 3: required list<
255 map<set<i32>, map<i32,set<list<map<Insanity,string>>>>>
256 >
257 4: binary binary_field
258 }
259 ```
260 ```rust
261 #[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd)]
262 pub struct CrazyNesting {
263 pub string_field: Option<String>,
264 pub set_field: Option<BTreeSet<Insanity>>,
265 pub list_field: Vec<
266 BTreeMap<
267 BTreeSet<i32>,
268 BTreeMap<i32, BTreeSet<Vec<BTreeMap<Insanity, String>>>>
269 >
270 >,
271 pub binary_field: Option<Vec<u8>>,
272 }
273
274 impl CrazyNesting {
275 pub fn read_from_in_protocol(i_prot: &mut TInputProtocol)
276 ->
277 thrift::Result<CrazyNesting> {
278 // ...
279 }
280 pub fn write_to_out_protocol(&self, o_prot: &mut TOutputProtocol)
281 ->
282 thrift::Result<()> {
283 // ...
284 }
285 }
286
287 ```
288 ##### Optionality
289
290 Thrift has 3 "optionality" types:
291
292 1. Required
293 2. Optional
294 3. Default
295
296 The Rust code generator encodes *Required* fields as the bare type itself, while
297 *Optional* and *Default* fields are encoded as `Option<TypeName>`.
298
299 ```thrift
300 struct Foo {
301 1: required string bar // 1. required
302 2: optional string baz // 2. optional
303 3: string qux // 3. default
304 }
305 ```
306
307 ```rust
308 pub struct Foo {
309 bar: String, // 1. required
310 baz: Option<String>, // 2. optional
311 qux: Option<String>, // 3. default
312 }
313 ```
314
315 ## Known Issues
316
317 * Struct constants are not supported
318 * Map, list and set constants require a const holder struct