1 /*
2 *
3 * Copyright 2018 Google Inc. All rights reserved.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * 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, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18 #[macro_use]
19 #[cfg(not(miri))] // slow.
20 extern crate quickcheck;
21 extern crate flatbuffers;
22 extern crate flexbuffers;
23 extern crate rand;
24 extern crate serde;
25 #[macro_use]
26 extern crate serde_derive;
27 #[cfg(not(miri))] // slow.
28 #[macro_use]
29 extern crate quickcheck_derive;
30
31 mod flexbuffers_tests;
32 mod more_defaults_test;
33 mod optional_scalars_test;
34
35 #[allow(dead_code, unused_imports)]
36 #[path = "../../include_test/include_test1_generated.rs"]
37 pub mod include_test1_generated;
38
39 #[allow(dead_code, unused_imports)]
40 #[path = "../../include_test/sub/include_test2_generated.rs"]
41 pub mod include_test2_generated;
42
43 #[allow(dead_code, unused_imports)]
44 #[path = "../../namespace_test/namespace_test1_generated.rs"]
45 pub mod namespace_test1_generated;
46
47 #[allow(dead_code, unused_imports)]
48 #[path = "../../namespace_test/namespace_test2_generated.rs"]
49 pub mod namespace_test2_generated;
50
51 #[allow(dead_code, unused_imports)]
52 #[path = "../../monster_test_generated.rs"]
53 mod monster_test_generated;
54 pub use monster_test_generated::my_game;
55
56 #[allow(dead_code, unused_imports)]
57 #[path = "../../optional_scalars_generated.rs"]
58 mod optional_scalars_generated;
59
60 #[allow(dead_code, unused_imports)]
61 #[path = "../../arrays_test_generated.rs"]
62 mod arrays_test_generated;
63
64 #[rustfmt::skip] // TODO: Use standard rust formatting and remove dead code.
65 #[allow(dead_code)]
66 mod flatbuffers_tests {
67 use super::*;
68
69 // Include simple random number generator to ensure results will be the
70 // same across platforms.
71 // http://en.wikipedia.org/wiki/Park%E2%80%93Miller_random_number_generator
72 struct LCG(u64);
73 impl LCG {
new() -> Self74 fn new() -> Self {
75 LCG { 0: 48271 }
76 }
next(&mut self) -> u6477 fn next(&mut self) -> u64 {
78 let old = self.0;
79 self.0 = (self.0 * 279470273u64) % 4294967291u64;
80 old
81 }
reset(&mut self)82 fn reset(&mut self) {
83 self.0 = 48271
84 }
85 }
86
87 // test helper macro to return an error if two expressions are not equal
88 macro_rules! check_eq {
89 ($field_call:expr, $want:expr) => (
90 if $field_call == $want {
91 Ok(())
92 } else {
93 Err(stringify!($field_call))
94 }
95 )
96 }
97
98 #[test]
macro_check_eq()99 fn macro_check_eq() {
100 assert!(check_eq!(1, 1).is_ok());
101 assert!(check_eq!(1, 2).is_err());
102 }
103
104 // test helper macro to return an error if two expressions are equal
105 macro_rules! check_is_some {
106 ($field_call:expr) => (
107 if $field_call.is_some() {
108 Ok(())
109 } else {
110 Err(stringify!($field_call))
111 }
112 )
113 }
114
115 #[test]
macro_check_is_some()116 fn macro_check_is_some() {
117 let some: Option<usize> = Some(0);
118 let none: Option<usize> = None;
119 assert!(check_is_some!(some).is_ok());
120 assert!(check_is_some!(none).is_err());
121 }
122
123 #[test]
object_api_defaults()124 fn object_api_defaults() {
125 use my_game::example::*;
126 assert_eq!(
127 Vec3T::default(), Vec3T {
128 x: 0.0,
129 y: 0.0,
130 z: 0.0,
131 test1: 0.0,
132 test2: Color::empty(),
133 test3: TestT {
134 a: 0,
135 b: 0
136 }
137 });
138 assert_eq!(
139 MonsterT::default(),
140 MonsterT {
141 pos: None,
142 hp: 100,
143 mana: 150,
144 name: String::new(), // required string => default is empty string.
145 color: Color::Blue,
146 inventory: None,
147 testarrayoftables: None,
148 testarrayofstring: None,
149 testarrayofstring2: None,
150 testarrayofbools: None,
151 testarrayofsortedstruct: None,
152 enemy: None,
153 test: AnyT::NONE,
154 test4: None,
155 test5: None,
156 testnestedflatbuffer: None,
157 testempty: None,
158 testbool: false,
159 testhashs32_fnv1: 0,
160 testhashu32_fnv1: 0,
161 testhashs64_fnv1: 0,
162 testhashu64_fnv1: 0,
163 testhashs32_fnv1a: 0,
164 testhashu32_fnv1a: 0,
165 testhashs64_fnv1a: 0,
166 testhashu64_fnv1a: 0,
167 testf: 3.14159,
168 testf2: 3.0,
169 testf3: 0.0,
170 flex: None,
171 vector_of_longs: None,
172 vector_of_doubles: None,
173 parent_namespace_test: None,
174 vector_of_referrables: None,
175 single_weak_reference: 0,
176 vector_of_weak_references: None,
177 vector_of_strong_referrables: None,
178 co_owning_reference: 0,
179 vector_of_co_owning_references: None,
180 non_owning_reference: 0,
181 vector_of_non_owning_references: None,
182 any_unique: AnyUniqueAliasesT::NONE,
183 any_ambiguous: AnyAmbiguousAliasesT::NONE,
184 vector_of_enums: None,
185 signed_enum: Race::None,
186 testrequirednestedflatbuffer: None, // despite the name, it is not required.
187 scalar_key_sorted_tables: None,
188 }
189 );
190 }
191
create_serialized_example_with_generated_code(builder: &mut flatbuffers::FlatBufferBuilder)192 fn create_serialized_example_with_generated_code(builder: &mut flatbuffers::FlatBufferBuilder) {
193 let mon = {
194 let s0 = builder.create_string("test1");
195 let s1 = builder.create_string("test2");
196 let fred_name = builder.create_string("Fred");
197
198 // can't inline creation of this Vec3 because we refer to it by reference, so it must live
199 // long enough to be used by MonsterArgs.
200 let pos = my_game::example::Vec3::new(1.0, 2.0, 3.0, 3.0, my_game::example::Color::Green, &my_game::example::Test::new(5i16, 6i8));
201
202 let args = my_game::example::MonsterArgs{
203 hp: 80,
204 mana: 150,
205 name: Some(builder.create_string("MyMonster")),
206 pos: Some(&pos),
207 test_type: my_game::example::Any::Monster,
208 test: Some(my_game::example::Monster::create(builder, &my_game::example::MonsterArgs{
209 name: Some(fred_name),
210 ..Default::default()
211 }).as_union_value()),
212 inventory: Some(builder.create_vector_direct(&[0u8, 1, 2, 3, 4][..])),
213 test4: Some(builder.create_vector_direct(&[my_game::example::Test::new(10, 20),
214 my_game::example::Test::new(30, 40)])),
215 testarrayofstring: Some(builder.create_vector(&[s0, s1])),
216 ..Default::default()
217 };
218 my_game::example::Monster::create(builder, &args)
219 };
220 my_game::example::finish_monster_buffer(builder, mon);
221 }
222
create_serialized_example_with_library_code(builder: &mut flatbuffers::FlatBufferBuilder)223 fn create_serialized_example_with_library_code(builder: &mut flatbuffers::FlatBufferBuilder) {
224 let nested_union_mon = {
225 let name = builder.create_string("Fred");
226 let table_start = builder.start_table();
227 builder.push_slot_always(my_game::example::Monster::VT_NAME, name);
228 builder.end_table(table_start)
229 };
230 let pos = my_game::example::Vec3::new(1.0, 2.0, 3.0, 3.0, my_game::example::Color::Green, &my_game::example::Test::new(5i16, 6i8));
231 let inv = builder.create_vector(&[0u8, 1, 2, 3, 4]);
232
233 let test4 = builder.create_vector(&[my_game::example::Test::new(10, 20),
234 my_game::example::Test::new(30, 40)][..]);
235
236 let name = builder.create_string("MyMonster");
237 let testarrayofstring = builder.create_vector_of_strings(&["test1", "test2"][..]);
238
239 // begin building
240
241 let table_start = builder.start_table();
242 builder.push_slot(my_game::example::Monster::VT_HP, 80i16, 100);
243 builder.push_slot_always(my_game::example::Monster::VT_NAME, name);
244 builder.push_slot_always(my_game::example::Monster::VT_POS, &pos);
245 builder.push_slot(my_game::example::Monster::VT_TEST_TYPE, my_game::example::Any::Monster, my_game::example::Any::NONE);
246 builder.push_slot_always(my_game::example::Monster::VT_TEST, nested_union_mon);
247 builder.push_slot_always(my_game::example::Monster::VT_INVENTORY, inv);
248 builder.push_slot_always(my_game::example::Monster::VT_TEST4, test4);
249 builder.push_slot_always(my_game::example::Monster::VT_TESTARRAYOFSTRING, testarrayofstring);
250 let root = builder.end_table(table_start);
251 builder.finish(root, Some(my_game::example::MONSTER_IDENTIFIER));
252 }
253
serialized_example_is_accessible_and_correct(bytes: &[u8], identifier_required: bool, size_prefixed: bool) -> Result<(), &'static str>254 fn serialized_example_is_accessible_and_correct(bytes: &[u8], identifier_required: bool, size_prefixed: bool) -> Result<(), &'static str> {
255
256 if identifier_required {
257 let correct = if size_prefixed {
258 my_game::example::monster_size_prefixed_buffer_has_identifier(bytes)
259 } else {
260 my_game::example::monster_buffer_has_identifier(bytes)
261 };
262 check_eq!(correct, true)?;
263 }
264
265 let m = if size_prefixed {
266 my_game::example::size_prefixed_root_as_monster(bytes).unwrap()
267 } else {
268 my_game::example::root_as_monster(bytes).unwrap()
269 };
270
271 check_eq!(m.hp(), 80)?;
272 check_eq!(m.mana(), 150)?;
273 check_eq!(m.name(), "MyMonster")?;
274
275 let pos = m.pos().unwrap();
276 check_eq!(pos.x(), 1.0f32)?;
277 check_eq!(pos.y(), 2.0f32)?;
278 check_eq!(pos.z(), 3.0f32)?;
279 check_eq!(pos.test1(), 3.0f64)?;
280 check_eq!(pos.test2(), my_game::example::Color::Green)?;
281
282 let pos_test3 = pos.test3();
283 check_eq!(pos_test3.a(), 5i16)?;
284 check_eq!(pos_test3.b(), 6i8)?;
285
286 check_eq!(m.test_type(), my_game::example::Any::Monster)?;
287 check_is_some!(m.test())?;
288 let table2 = m.test().unwrap();
289 let monster2 = my_game::example::Monster::init_from_table(table2);
290
291 check_eq!(monster2.name(), "Fred")?;
292
293 check_is_some!(m.inventory())?;
294 let inv = m.inventory().unwrap();
295 check_eq!(inv.len(), 5)?;
296 check_eq!(inv.iter().sum::<u8>(), 10u8)?;
297 check_eq!(inv.iter().rev().sum::<u8>(), 10u8)?;
298
299 check_is_some!(m.test4())?;
300 let test4 = m.test4().unwrap();
301 check_eq!(test4.len(), 2)?;
302 check_eq!(test4[0].a() as i32 + test4[0].b() as i32 +
303 test4[1].a() as i32 + test4[1].b() as i32, 100)?;
304
305 check_is_some!(m.testarrayofstring())?;
306 let testarrayofstring = m.testarrayofstring().unwrap();
307 check_eq!(testarrayofstring.len(), 2)?;
308 check_eq!(testarrayofstring.get(0), "test1")?;
309 check_eq!(testarrayofstring.get(1), "test2")?;
310
311 Ok(())
312 }
313
314 #[test]
test_object_api_reads_correctly() -> Result<(), &'static str>315 fn test_object_api_reads_correctly() -> Result<(), &'static str>{
316 let mut fbb = flatbuffers::FlatBufferBuilder::new();
317 create_serialized_example_with_library_code(&mut fbb);
318
319 let m = my_game::example::root_as_monster(fbb.finished_data()).unwrap().unpack();
320
321 check_eq!(m.hp, 80)?;
322 check_eq!(m.mana, 150)?;
323 check_eq!(m.name, "MyMonster")?;
324
325 let pos = m.pos.as_ref().unwrap();
326 check_eq!(pos.x, 1.0f32)?;
327 check_eq!(pos.y, 2.0f32)?;
328 check_eq!(pos.z, 3.0f32)?;
329 check_eq!(pos.test1, 3.0f64)?;
330 check_eq!(pos.test2, my_game::example::Color::Green)?;
331
332 let pos_test3 = &pos.test3;
333 check_eq!(pos_test3.a, 5i16)?;
334 check_eq!(pos_test3.b, 6i8)?;
335
336 let monster2 = m.test.as_monster().unwrap();
337 check_eq!(monster2.name, "Fred")?;
338
339 let inv = m.inventory.as_ref().unwrap();
340 check_eq!(inv.len(), 5)?;
341 check_eq!(inv.iter().sum::<u8>(), 10u8)?;
342 check_eq!(inv.iter().rev().sum::<u8>(), 10u8)?;
343
344 let test4 = m.test4.as_ref().unwrap();
345 check_eq!(test4.len(), 2)?;
346 check_eq!(test4[0].a as i32 + test4[0].b as i32 +
347 test4[1].a as i32 + test4[1].b as i32, 100)?;
348
349 let testarrayofstring = m.testarrayofstring.as_ref().unwrap();
350 check_eq!(testarrayofstring.len(), 2)?;
351 check_eq!(testarrayofstring[0], "test1")?;
352 check_eq!(testarrayofstring[1], "test2")?;
353 Ok(())
354 }
355
356
357
358 // Disabled due to Windows CI limitations.
359 // #[test]
360 // fn builder_initializes_with_maximum_buffer_size() {
361 // flatbuffers::FlatBufferBuilder::new_with_capacity(flatbuffers::FLATBUFFERS_MAX_BUFFER_SIZE);
362 // }
363
364 #[should_panic]
365 #[test]
builder_abort_with_greater_than_maximum_buffer_size()366 fn builder_abort_with_greater_than_maximum_buffer_size() {
367 flatbuffers::FlatBufferBuilder::new_with_capacity(flatbuffers::FLATBUFFERS_MAX_BUFFER_SIZE+1);
368 }
369
370 #[test]
builder_collapses_into_vec()371 fn builder_collapses_into_vec() {
372 let mut b = flatbuffers::FlatBufferBuilder::new();
373 create_serialized_example_with_generated_code(&mut b);
374 let (backing_buf, head) = b.collapse();
375 serialized_example_is_accessible_and_correct(&backing_buf[head..], true, false).unwrap();
376 }
377
378 #[test]
379 #[cfg(not(miri))] // slow.
verifier_one_byte_errors_do_not_crash()380 fn verifier_one_byte_errors_do_not_crash() {
381 let mut b = flatbuffers::FlatBufferBuilder::new();
382 create_serialized_example_with_library_code(&mut b);
383 let mut badbuf = b.finished_data().to_vec();
384 // If the verifier says a buffer is okay then using it won't cause a crash.
385 // We use write_fmt since Debug visits all the fields - but there's no need to store anything.
386 struct ForgetfulWriter;
387 use std::fmt::Write;
388 impl Write for ForgetfulWriter {
389 fn write_str(&mut self, _: &str) -> Result<(), std::fmt::Error> {
390 Ok(())
391 }
392 }
393 let mut w = ForgetfulWriter;
394 for d in 1..=255u8 {
395 for i in 0..badbuf.len() {
396 let orig = badbuf[i];
397 badbuf[i] = badbuf[i].wrapping_add(d);
398 if let Ok(m) = flatbuffers::root::<my_game::example::Monster>(&badbuf) {
399 w.write_fmt(format_args!("{:?}", m)).unwrap()
400 }
401 badbuf[i] = orig;
402 }
403 }
404 }
405 #[test]
406 #[cfg(not(miri))] // slow.
verifier_too_many_tables()407 fn verifier_too_many_tables() {
408 use my_game::example::*;
409 let b = &mut flatbuffers::FlatBufferBuilder::new();
410 let r = Referrable::create(b, &ReferrableArgs { id: 42 });
411 let rs = b.create_vector(&vec![r; 500]);
412 let name = Some(b.create_string("foo"));
413 let m = Monster::create(b, &MonsterArgs {
414 vector_of_referrables: Some(rs),
415 name, // required field.
416 ..Default::default()
417 });
418 b.finish(m, None);
419
420 let data = b.finished_data();
421 let mut opts = flatbuffers::VerifierOptions::default();
422
423 opts.max_tables = 500;
424 let res = flatbuffers::root_with_opts::<Monster>(&opts, data);
425 assert_eq!(res.unwrap_err(), flatbuffers::InvalidFlatbuffer::TooManyTables);
426
427 opts.max_tables += 2;
428 assert!(flatbuffers::root_with_opts::<Monster>(&opts, data).is_ok());
429 }
430 #[test]
431 #[cfg(not(miri))] // slow.
verifier_apparent_size_too_large()432 fn verifier_apparent_size_too_large() {
433 use my_game::example::*;
434 let b = &mut flatbuffers::FlatBufferBuilder::new();
435 let name = Some(b.create_string("foo"));
436 // String amplification attack.
437 let s = b.create_string(&(std::iter::repeat("X").take(1000).collect::<String>()));
438 let testarrayofstring = Some(b.create_vector(&vec![s; 1000]));
439 let m = Monster::create(b, &MonsterArgs {
440 testarrayofstring,
441 name, // required field.
442 ..Default::default()
443 });
444 b.finish(m, None);
445 let data = b.finished_data();
446 assert!(data.len() < 5100); // est 4000 for the vector + 1000 for the string + 100 overhead.
447 let mut opts = flatbuffers::VerifierOptions::default();
448 opts.max_apparent_size = 1_000_000;
449
450 let res = flatbuffers::root_with_opts::<Monster>(&opts, data);
451 assert_eq!(res.unwrap_err(), flatbuffers::InvalidFlatbuffer::ApparentSizeTooLarge);
452
453 opts.max_apparent_size += 20_000;
454 assert!(flatbuffers::root_with_opts::<Monster>(&opts, data).is_ok());
455 }
456 #[test]
verifier_in_too_deep()457 fn verifier_in_too_deep() {
458 use my_game::example::*;
459 let b = &mut flatbuffers::FlatBufferBuilder::new();
460 let name = Some(b.create_string("foo"));
461 let mut prev_monster = None;
462 for _ in 0..11 {
463 prev_monster = Some(Monster::create(b, &MonsterArgs {
464 enemy: prev_monster,
465 name, // required field.
466 ..Default::default()
467 }));
468 };
469 b.finish(prev_monster.unwrap(), None);
470 let mut opts = flatbuffers::VerifierOptions::default();
471 opts.max_depth = 10;
472
473 let data = b.finished_data();
474 let res = flatbuffers::root_with_opts::<Monster>(&opts, data);
475 assert_eq!(res.unwrap_err(), flatbuffers::InvalidFlatbuffer::DepthLimitReached);
476
477 opts.max_depth += 1;
478 assert!(flatbuffers::root_with_opts::<Monster>(&opts, data).is_ok());
479 }
480
481 #[cfg(test)]
482 mod generated_constants {
483 extern crate flatbuffers;
484 use super::my_game;
485
486 #[test]
monster_identifier()487 fn monster_identifier() {
488 assert_eq!("MONS", my_game::example::MONSTER_IDENTIFIER);
489 }
490
491 #[test]
monster_file_extension()492 fn monster_file_extension() {
493 assert_eq!("mon", my_game::example::MONSTER_EXTENSION);
494 }
495
496 #[test]
enum_constants_are_public()497 fn enum_constants_are_public() {
498 assert_eq!(-1, my_game::example::Race::ENUM_MIN);
499 assert_eq!(2, my_game::example::Race::ENUM_MAX);
500 assert_eq!(my_game::example::Race::ENUM_VALUES, [
501 my_game::example::Race::None,
502 my_game::example::Race::Human,
503 my_game::example::Race::Dwarf,
504 my_game::example::Race::Elf,
505 ]);
506
507 assert_eq!(0, my_game::example::Any::ENUM_MIN);
508 assert_eq!(3, my_game::example::Any::ENUM_MAX);
509 assert_eq!(my_game::example::Any::ENUM_VALUES, [
510 my_game::example::Any::NONE,
511 my_game::example::Any::Monster,
512 my_game::example::Any::TestSimpleTableWithEnum,
513 my_game::example::Any::MyGame_Example2_Monster,
514 ]);
515
516 assert_eq!(0, my_game::example::AnyUniqueAliases::ENUM_MIN);
517 assert_eq!(3, my_game::example::AnyUniqueAliases::ENUM_MAX);
518 assert_eq!(my_game::example::AnyUniqueAliases::ENUM_VALUES, [
519 my_game::example::AnyUniqueAliases::NONE,
520 my_game::example::AnyUniqueAliases::M,
521 my_game::example::AnyUniqueAliases::TS,
522 my_game::example::AnyUniqueAliases::M2,
523 ]);
524
525 assert_eq!(0, my_game::example::AnyAmbiguousAliases::ENUM_MIN);
526 assert_eq!(3, my_game::example::AnyAmbiguousAliases::ENUM_MAX);
527 assert_eq!(my_game::example::AnyAmbiguousAliases::ENUM_VALUES, [
528 my_game::example::AnyAmbiguousAliases::NONE,
529 my_game::example::AnyAmbiguousAliases::M1,
530 my_game::example::AnyAmbiguousAliases::M2,
531 my_game::example::AnyAmbiguousAliases::M3,
532 ]);
533 }
534 }
535
536 #[cfg(test)]
537 mod lifetime_correctness {
538 extern crate flatbuffers;
539
540 use std::mem;
541
542 use super::my_game;
543 use super::load_file;
544
545 #[test]
table_get_field_from_static_buffer_1()546 fn table_get_field_from_static_buffer_1() {
547 let buf = load_file("../monsterdata_test.mon").expect("missing monsterdata_test.mon");
548 // create 'static slice
549 let slice: &[u8] = &buf;
550 let slice: &'static [u8] = unsafe { mem::transmute(slice) };
551 // make sure values retrieved from the 'static buffer are themselves 'static
552 let monster: my_game::example::Monster<'static> = my_game::example::root_as_monster(slice).unwrap();
553 // this line should compile:
554 let name: Option<&'static str> = monster._tab.get::<flatbuffers::ForwardsUOffset<&str>>(my_game::example::Monster::VT_NAME, None);
555 assert_eq!(name, Some("MyMonster"));
556 }
557
558 #[test]
table_get_field_from_static_buffer_2()559 fn table_get_field_from_static_buffer_2() {
560 static DATA: [u8; 4] = [0, 0, 0, 0]; // some binary data
561 let table: flatbuffers::Table<'static> = flatbuffers::Table::new(&DATA, 0);
562 // this line should compile:
563 table.get::<&'static str>(0, None);
564 }
565
566 #[test]
table_object_self_lifetime_in_closure()567 fn table_object_self_lifetime_in_closure() {
568 // This test is designed to ensure that lifetimes for temporary intermediate tables aren't inflated beyond where the need to be.
569 let buf = load_file("../monsterdata_test.mon").expect("missing monsterdata_test.mon");
570 let monster = my_game::example::root_as_monster(&buf).unwrap();
571 let enemy: Option<my_game::example::Monster> = monster.enemy();
572 // This line won't compile if "self" is required to live for the lifetime of buf above as the borrow disappears at the end of the closure.
573 let enemy_of_my_enemy = enemy.map(|e| {
574 // enemy (the Option) is consumed, and the enum's value is taken as a temporary (e) at the start of the closure
575 let name = e.name();
576 // ... the temporary dies here, so for this to compile name's lifetime must not be tied to the temporary
577 name
578 // If this test fails the error would be "`e` dropped here while still borrowed"
579 });
580 assert_eq!(enemy_of_my_enemy, Some("Fred"));
581 }
582 }
583
584 #[cfg(test)]
585 mod roundtrip_generated_code {
586 extern crate flatbuffers;
587
588 use super::my_game;
589
build_mon<'a, 'b>(builder: &'a mut flatbuffers::FlatBufferBuilder, args: &'b my_game::example::MonsterArgs) -> my_game::example::Monster<'a>590 fn build_mon<'a, 'b>(builder: &'a mut flatbuffers::FlatBufferBuilder, args: &'b my_game::example::MonsterArgs) -> my_game::example::Monster<'a> {
591 let mon = my_game::example::Monster::create(builder, &args);
592 my_game::example::finish_monster_buffer(builder, mon);
593 my_game::example::root_as_monster(builder.finished_data()).unwrap()
594 }
595
596 #[test]
scalar_store()597 fn scalar_store() {
598 let mut b = flatbuffers::FlatBufferBuilder::new();
599 let name = b.create_string("foo");
600 let m = build_mon(&mut b, &my_game::example::MonsterArgs{hp: 123, name: Some(name), ..Default::default()});
601 assert_eq!(m.hp(), 123);
602 }
603 #[test]
scalar_default()604 fn scalar_default() {
605 let mut b = flatbuffers::FlatBufferBuilder::new();
606 let name = b.create_string("foo");
607 let m = build_mon(&mut b, &my_game::example::MonsterArgs{name: Some(name), ..Default::default()});
608 assert_eq!(m.hp(), 100);
609 }
610 #[test]
string_store()611 fn string_store() {
612 let mut b = flatbuffers::FlatBufferBuilder::new();
613 let name = b.create_string("foobar");
614 let m = build_mon(&mut b, &my_game::example::MonsterArgs{name: Some(name), ..Default::default()});
615 assert_eq!(m.name(), "foobar");
616 }
617 #[test]
struct_store()618 fn struct_store() {
619 let mut b = flatbuffers::FlatBufferBuilder::new();
620 let name = b.create_string("foo");
621 let m = build_mon(&mut b, &my_game::example::MonsterArgs{
622 name: Some(name),
623 pos: Some(&my_game::example::Vec3::new(1.0, 2.0, 3.0, 4.0,
624 my_game::example::Color::Green,
625 &my_game::example::Test::new(98, 99))),
626 ..Default::default()
627 });
628 assert_eq!(m.pos(), Some(&my_game::example::Vec3::new(1.0, 2.0, 3.0, 4.0,
629 my_game::example::Color::Green,
630 &my_game::example::Test::new(98, 99))));
631 }
632 #[test]
struct_default()633 fn struct_default() {
634 let mut b = flatbuffers::FlatBufferBuilder::new();
635 let name = b.create_string("foo");
636 let m = build_mon(&mut b, &my_game::example::MonsterArgs{name: Some(name), ..Default::default()});
637 assert_eq!(m.pos(), None);
638 }
639 #[test]
enum_store()640 fn enum_store() {
641 let mut b = flatbuffers::FlatBufferBuilder::new();
642 let name = b.create_string("foo");
643 let m = build_mon(&mut b, &my_game::example::MonsterArgs{name: Some(name), color: my_game::example::Color::Red, ..Default::default()});
644 assert_eq!(m.color(), my_game::example::Color::Red);
645 }
646 #[test]
enum_default()647 fn enum_default() {
648 let mut b = flatbuffers::FlatBufferBuilder::new();
649 let name = b.create_string("foo");
650 let m = build_mon(&mut b, &my_game::example::MonsterArgs{name: Some(name), ..Default::default()});
651 assert_eq!(m.color(), my_game::example::Color::Blue);
652 }
653 #[test]
union_store()654 fn union_store() {
655 let b = &mut flatbuffers::FlatBufferBuilder::new();
656 {
657 let name_inner = b.create_string("foo");
658 let name_outer = b.create_string("bar");
659
660 let inner = my_game::example::Monster::create(b, &my_game::example::MonsterArgs{
661 name: Some(name_inner),
662 ..Default::default()
663 });
664 let outer = my_game::example::Monster::create(b, &my_game::example::MonsterArgs{
665 name: Some(name_outer),
666 test_type: my_game::example::Any::Monster,
667 test: Some(inner.as_union_value()),
668 ..Default::default()
669 });
670 my_game::example::finish_monster_buffer(b, outer);
671 }
672
673 let mon = my_game::example::root_as_monster(b.finished_data()).unwrap();
674 assert_eq!(mon.name(), "bar");
675 assert_eq!(mon.test_type(), my_game::example::Any::Monster);
676 assert_eq!(my_game::example::Monster::init_from_table(mon.test().unwrap()).name(),
677 "foo");
678 assert_eq!(mon.test_as_monster().unwrap().name(), "foo");
679 assert_eq!(mon.test_as_test_simple_table_with_enum(), None);
680 assert_eq!(mon.test_as_my_game_example_2_monster(), None);
681 }
682 #[test]
union_default()683 fn union_default() {
684 let mut b = flatbuffers::FlatBufferBuilder::new();
685 let name = b.create_string("foo");
686 let m = build_mon(&mut b, &my_game::example::MonsterArgs{name: Some(name), ..Default::default()});
687 assert_eq!(m.test_type(), my_game::example::Any::NONE);
688 assert_eq!(m.test(), None);
689 }
690 #[test]
table_full_namespace_store()691 fn table_full_namespace_store() {
692 let b = &mut flatbuffers::FlatBufferBuilder::new();
693 {
694 let name_inner = b.create_string("foo");
695 let name_outer = b.create_string("bar");
696
697 let inner = my_game::example::Monster::create(b, &my_game::example::MonsterArgs{
698 name: Some(name_inner),
699 ..Default::default()
700 });
701 let outer = my_game::example::Monster::create(b, &my_game::example::MonsterArgs{
702 name: Some(name_outer),
703 enemy: Some(inner),
704 ..Default::default()
705 });
706 my_game::example::finish_monster_buffer(b, outer);
707 }
708
709 let mon = my_game::example::root_as_monster(b.finished_data()).unwrap();
710 assert_eq!(mon.name(), "bar");
711 assert_eq!(mon.enemy().unwrap().name(), "foo");
712 }
713 #[test]
table_full_namespace_default()714 fn table_full_namespace_default() {
715 let mut b = flatbuffers::FlatBufferBuilder::new();
716 let name = b.create_string("foo");
717 let m = build_mon(&mut b, &my_game::example::MonsterArgs{name: Some(name), ..Default::default()});
718 assert_eq!(m.enemy(), None);
719 }
720 #[test]
table_store()721 fn table_store() {
722 let b = &mut flatbuffers::FlatBufferBuilder::new();
723 {
724 let id_inner = b.create_string("foo");
725 let name_outer = b.create_string("bar");
726
727 let inner = my_game::example::Stat::create(b, &my_game::example::StatArgs{
728 id: Some(id_inner),
729 ..Default::default()
730 });
731 let outer = my_game::example::Monster::create(b, &my_game::example::MonsterArgs{
732 name: Some(name_outer),
733 testempty: Some(inner),
734 ..Default::default()
735 });
736 my_game::example::finish_monster_buffer(b, outer);
737 }
738
739 let mon = my_game::example::root_as_monster(b.finished_data()).unwrap();
740 assert_eq!(mon.name(), "bar");
741 assert_eq!(mon.testempty().unwrap().id(), Some("foo"));
742 }
743 #[test]
table_default()744 fn table_default() {
745 let mut b = flatbuffers::FlatBufferBuilder::new();
746 let name = b.create_string("foo");
747 let m = build_mon(&mut b, &my_game::example::MonsterArgs{name: Some(name), ..Default::default()});
748 assert_eq!(m.testempty(), None);
749 }
750 #[test]
nested_flatbuffer_store()751 fn nested_flatbuffer_store() {
752 let b0 = {
753 let mut b0 = flatbuffers::FlatBufferBuilder::new();
754 let args = my_game::example::MonsterArgs{
755 hp: 123,
756 name: Some(b0.create_string("foobar")),
757 ..Default::default()
758 };
759 let mon = my_game::example::Monster::create(&mut b0, &args);
760 my_game::example::finish_monster_buffer(&mut b0, mon);
761 b0
762 };
763
764 let b1 = {
765 let mut b1 = flatbuffers::FlatBufferBuilder::new();
766 let args = my_game::example::MonsterArgs{
767 testnestedflatbuffer: Some(b1.create_vector(b0.finished_data())),
768 name: Some(b1.create_string("foo")),
769 ..Default::default()
770 };
771 let mon = my_game::example::Monster::create(&mut b1, &args);
772 my_game::example::finish_monster_buffer(&mut b1, mon);
773 b1
774 };
775
776 let m = my_game::example::root_as_monster(b1.finished_data()).unwrap();
777
778 assert!(m.testnestedflatbuffer().is_some());
779 assert_eq!(m.testnestedflatbuffer().unwrap(), b0.finished_data());
780
781 let m2_a = my_game::example::root_as_monster(m.testnestedflatbuffer().unwrap()).unwrap();
782 assert_eq!(m2_a.hp(), 123);
783 assert_eq!(m2_a.name(), "foobar");
784
785 assert!(m.testnestedflatbuffer_nested_flatbuffer().is_some());
786 let m2_b = m.testnestedflatbuffer_nested_flatbuffer().unwrap();
787
788 assert_eq!(m2_b.hp(), 123);
789 assert_eq!(m2_b.name(), "foobar");
790 }
791 #[test]
nested_flatbuffer_default()792 fn nested_flatbuffer_default() {
793 let mut b = flatbuffers::FlatBufferBuilder::new();
794 let name = b.create_string("foo");
795 let m = build_mon(&mut b, &my_game::example::MonsterArgs{name: Some(name), ..Default::default()});
796 assert!(m.testnestedflatbuffer().is_none());
797 }
798 #[test]
vector_of_string_store_helper_build()799 fn vector_of_string_store_helper_build() {
800 let mut b = flatbuffers::FlatBufferBuilder::new();
801 let v = b.create_vector_of_strings(&["foobar", "baz"]);
802 let name = b.create_string("foo");
803 let m = build_mon(&mut b, &my_game::example::MonsterArgs{
804 name: Some(name),
805 testarrayofstring: Some(v), ..Default::default()});
806 assert_eq!(m.testarrayofstring().unwrap().len(), 2);
807 assert_eq!(m.testarrayofstring().unwrap().get(0), "foobar");
808 assert_eq!(m.testarrayofstring().unwrap().get(1), "baz");
809
810 let rust_vec_inst = m.testarrayofstring().unwrap();
811 let rust_vec_iter_collect = rust_vec_inst.iter().collect::<Vec<_>>();
812 assert_eq!(rust_vec_iter_collect.len(), 2);
813 assert_eq!(rust_vec_iter_collect[0], "foobar");
814 assert_eq!(rust_vec_iter_collect[1], "baz");
815
816 let rust_vec_iter_rev_collect = rust_vec_inst.iter().rev().collect::<Vec<_>>();
817 assert_eq!(rust_vec_iter_rev_collect.len(), 2);
818 assert_eq!(rust_vec_iter_rev_collect[1], "foobar");
819 assert_eq!(rust_vec_iter_rev_collect[0], "baz");
820
821 }
822 #[test]
vector_of_string_store_manual_build()823 fn vector_of_string_store_manual_build() {
824 let mut b = flatbuffers::FlatBufferBuilder::new();
825 let s0 = b.create_string("foobar");
826 let s1 = b.create_string("baz");
827 let v = b.create_vector(&[s0, s1]);
828 let name = b.create_string("foo");
829 let m = build_mon(&mut b, &my_game::example::MonsterArgs{
830 name: Some(name),
831 testarrayofstring: Some(v), ..Default::default()});
832 assert_eq!(m.testarrayofstring().unwrap().len(), 2);
833 assert_eq!(m.testarrayofstring().unwrap().get(0), "foobar");
834 assert_eq!(m.testarrayofstring().unwrap().get(1), "baz");
835
836 let rust_vec_inst = m.testarrayofstring().unwrap();
837 let rust_vec_iter_collect = rust_vec_inst.iter().collect::<Vec<_>>();
838 assert_eq!(rust_vec_iter_collect.len(), 2);
839 assert_eq!(rust_vec_iter_collect[0], "foobar");
840 assert_eq!(rust_vec_iter_collect[1], "baz");
841
842 let rust_vec_iter_rev_collect = rust_vec_inst.iter().rev().collect::<Vec<_>>();
843 assert_eq!(rust_vec_iter_rev_collect.len(), 2);
844 assert_eq!(rust_vec_iter_rev_collect[0], "baz");
845 assert_eq!(rust_vec_iter_rev_collect[1], "foobar");
846 }
847 #[test]
vector_of_ubyte_store()848 fn vector_of_ubyte_store() {
849 let mut b = flatbuffers::FlatBufferBuilder::new();
850 let v = b.create_vector(&[123u8, 234u8][..]);
851 let name = b.create_string("foo");
852 let m = build_mon(&mut b, &my_game::example::MonsterArgs{
853 name: Some(name),
854 inventory: Some(v), ..Default::default()});
855 assert_eq!(m.inventory().unwrap(), &[123, 234][..]);
856 }
857 #[test]
vector_of_bool_store()858 fn vector_of_bool_store() {
859 let mut b = flatbuffers::FlatBufferBuilder::new();
860 let v = b.create_vector(&[false, true, false, true][..]);
861 let name = b.create_string("foo");
862 let m = build_mon(&mut b, &my_game::example::MonsterArgs{
863 name: Some(name),
864 testarrayofbools: Some(v), ..Default::default()});
865 assert_eq!(m.testarrayofbools().unwrap(), &[false, true, false, true][..]);
866
867 let rust_vec_inst = m.testarrayofbools().unwrap();
868 let rust_vec_iter_collect = rust_vec_inst.iter().collect::<Vec<_>>();
869 assert_eq!(rust_vec_iter_collect, &[&false, &true, &false, &true][..]);
870
871 let rust_vec_iter_rev_collect = rust_vec_inst.iter().rev().collect::<Vec<_>>();
872 assert_eq!(rust_vec_iter_rev_collect, &[&true, &false, &true, &false][..]);
873 }
874 #[test]
vector_of_f64_store()875 fn vector_of_f64_store() {
876 let mut b = flatbuffers::FlatBufferBuilder::new();
877 let v = b.create_vector(&[3.14159265359f64][..]);
878 let name = b.create_string("foo");
879 let m = build_mon(&mut b, &my_game::example::MonsterArgs{
880 name: Some(name),
881 vector_of_doubles: Some(v), ..Default::default()});
882 assert_eq!(m.vector_of_doubles().unwrap().len(), 1);
883 assert_eq!(m.vector_of_doubles().unwrap().get(0), 3.14159265359f64);
884
885 let rust_vec_inst = m.vector_of_doubles().unwrap();
886 let rust_vec_iter_collect = rust_vec_inst.iter().collect::<Vec<_>>();
887 assert_eq!(rust_vec_iter_collect.len(), 1);
888 assert_eq!(rust_vec_iter_collect[0], 3.14159265359f64);
889
890 let rust_vec_iter_rev_collect = rust_vec_inst.iter().rev().collect::<Vec<_>>();
891 assert_eq!(rust_vec_iter_rev_collect.len(), 1);
892 assert_eq!(rust_vec_iter_rev_collect[0], 3.14159265359f64);
893 }
894 #[test]
vector_of_struct_store()895 fn vector_of_struct_store() {
896 let mut b = flatbuffers::FlatBufferBuilder::new();
897 let v = b.create_vector(&[my_game::example::Test::new(127, -128), my_game::example::Test::new(3, 123)][..]);
898 let name = b.create_string("foo");
899 let m = build_mon(&mut b, &my_game::example::MonsterArgs{
900 name: Some(name),
901 test4: Some(v), ..Default::default()});
902 assert_eq!(m.test4().unwrap(), &[my_game::example::Test::new(127, -128), my_game::example::Test::new(3, 123)][..]);
903
904 let rust_vec_inst = m.test4().unwrap();
905 let rust_vec_iter_collect = rust_vec_inst.iter().collect::<Vec<_>>();
906 assert_eq!(rust_vec_iter_collect, &[&my_game::example::Test::new(127, -128), &my_game::example::Test::new(3, 123)][..]);
907
908 let rust_vec_iter_rev_collect = rust_vec_inst.iter().rev().collect::<Vec<_>>();
909 assert_eq!(rust_vec_iter_rev_collect, &[&my_game::example::Test::new(3, 123), &my_game::example::Test::new(127, -128)][..]);
910 }
911 #[test]
vector_of_struct_store_with_type_inference()912 fn vector_of_struct_store_with_type_inference() {
913 let mut b = flatbuffers::FlatBufferBuilder::new();
914 let v = b.create_vector(&[my_game::example::Test::new(127, -128),
915 my_game::example::Test::new(3, 123),
916 my_game::example::Test::new(100, 101)]);
917 let name = b.create_string("foo");
918 let m = build_mon(&mut b, &my_game::example::MonsterArgs{
919 name: Some(name),
920 test4: Some(v), ..Default::default()});
921 assert_eq!(m.test4().unwrap(), &[my_game::example::Test::new(127, -128), my_game::example::Test::new(3, 123), my_game::example::Test::new(100, 101)][..]);
922 }
923 #[test]
vector_of_enums_store()924 fn vector_of_enums_store() {
925 let mut b = flatbuffers::FlatBufferBuilder::new();
926 let v = b.create_vector::<my_game::example::Color>(&[my_game::example::Color::Red, my_game::example::Color::Green][..]);
927 let name = b.create_string("foo");
928 let m = build_mon(&mut b, &my_game::example::MonsterArgs{
929 name: Some(name),
930 vector_of_enums: Some(v), ..Default::default()});
931 assert_eq!(m.vector_of_enums().unwrap().len(), 2);
932 assert_eq!(m.vector_of_enums().unwrap().get(0), my_game::example::Color::Red);
933 assert_eq!(m.vector_of_enums().unwrap().get(1), my_game::example::Color::Green);
934 }
935 #[test]
vector_of_table_store()936 fn vector_of_table_store() {
937 let b = &mut flatbuffers::FlatBufferBuilder::new();
938 let t0 = {
939 let name = b.create_string("foo");
940 let args = my_game::example::MonsterArgs{hp: 55, name: Some(name), ..Default::default()};
941 my_game::example::Monster::create(b, &args)
942 };
943 let t1 = {
944 let name = b.create_string("bar");
945 let args = my_game::example::MonsterArgs{name: Some(name), ..Default::default()};
946 my_game::example::Monster::create(b, &args)
947 };
948 let v = b.create_vector(&[t0, t1][..]);
949 let name = b.create_string("foo");
950 let m = build_mon(b, &my_game::example::MonsterArgs{
951 name: Some(name),
952 testarrayoftables: Some(v), ..Default::default()});
953 assert_eq!(m.testarrayoftables().unwrap().len(), 2);
954 assert_eq!(m.testarrayoftables().unwrap().get(0).hp(), 55);
955 assert_eq!(m.testarrayoftables().unwrap().get(0).name(), "foo");
956 assert_eq!(m.testarrayoftables().unwrap().get(1).hp(), 100);
957 assert_eq!(m.testarrayoftables().unwrap().get(1).name(), "bar");
958
959 let rust_vec_inst = m.testarrayoftables().unwrap();
960 let rust_vec_iter_collect = rust_vec_inst.iter().collect::<Vec<_>>();
961 assert_eq!(rust_vec_iter_collect.len(), 2);
962 assert_eq!(rust_vec_iter_collect[0].hp(), 55);
963 assert_eq!(rust_vec_iter_collect[0].name(), "foo");
964 assert_eq!(rust_vec_iter_collect[1].hp(), 100);
965 assert_eq!(rust_vec_iter_collect[1].name(), "bar");
966
967 let rust_vec_iter_rev_collect = rust_vec_inst.iter().rev().collect::<Vec<_>>();
968 assert_eq!(rust_vec_iter_rev_collect.len(), 2);
969 assert_eq!(rust_vec_iter_rev_collect[0].hp(), 100);
970 assert_eq!(rust_vec_iter_rev_collect[0].name(), "bar");
971 assert_eq!(rust_vec_iter_rev_collect[1].hp(), 55);
972 assert_eq!(rust_vec_iter_rev_collect[1].name(), "foo");
973 }
974 }
975
976 #[cfg(test)]
977 mod generated_code_alignment_and_padding {
978 extern crate flatbuffers;
979 use super::my_game;
980
981 #[test]
enum_color_is_1_byte()982 fn enum_color_is_1_byte() {
983 assert_eq!(1, ::std::mem::size_of::<my_game::example::Color>());
984 }
985
986 #[test]
union_any_is_1_byte()987 fn union_any_is_1_byte() {
988 assert_eq!(1, ::std::mem::size_of::<my_game::example::Any>());
989 }
990
991 #[test]
union_any_is_aligned_to_1()992 fn union_any_is_aligned_to_1() {
993 assert_eq!(1, ::std::mem::align_of::<my_game::example::Any>());
994 }
995 #[test]
struct_test_is_4_bytes()996 fn struct_test_is_4_bytes() {
997 assert_eq!(4, ::std::mem::size_of::<my_game::example::Test>());
998 }
999 #[test]
struct_vec3_is_32_bytes()1000 fn struct_vec3_is_32_bytes() {
1001 assert_eq!(32, ::std::mem::size_of::<my_game::example::Vec3>());
1002 }
1003
1004 #[test]
struct_vec3_is_written_with_correct_alignment_in_table()1005 fn struct_vec3_is_written_with_correct_alignment_in_table() {
1006 let b = &mut flatbuffers::FlatBufferBuilder::new();
1007 {
1008 let name = b.create_string("foo");
1009 let mon = my_game::example::Monster::create(b, &my_game::example::MonsterArgs{
1010 name: Some(name),
1011 pos: Some(&my_game::example::Vec3::new(1.0, 2.0, 3.0, 4.0,
1012 my_game::example::Color::Green,
1013 &my_game::example::Test::new(98, 99))),
1014 ..Default::default()});
1015 my_game::example::finish_monster_buffer(b, mon);
1016 }
1017 let buf = b.finished_data();
1018 let mon = my_game::example::root_as_monster(buf).unwrap();
1019 let vec3 = mon.pos().unwrap();
1020
1021 let start_ptr = buf.as_ptr() as usize;
1022 let vec3_ptr = vec3 as *const my_game::example::Vec3 as usize;
1023
1024 assert!(vec3_ptr > start_ptr);
1025 // Vec3 is aligned to 8 wrt the flatbuffer.
1026 assert_eq!((vec3_ptr - start_ptr) % 8, 0);
1027 }
1028
1029 #[test]
struct_ability_is_8_bytes()1030 fn struct_ability_is_8_bytes() {
1031 assert_eq!(8, ::std::mem::size_of::<my_game::example::Ability>());
1032 }
1033
1034 #[test]
struct_ability_is_written_with_correct_alignment_in_table_vector()1035 fn struct_ability_is_written_with_correct_alignment_in_table_vector() {
1036 let b = &mut flatbuffers::FlatBufferBuilder::new();
1037 {
1038 let name = b.create_string("foo");
1039 let v = b.create_vector(&[my_game::example::Ability::new(1, 2),
1040 my_game::example::Ability::new(3, 4),
1041 my_game::example::Ability::new(5, 6)]);
1042 let mon = my_game::example::Monster::create(b, &my_game::example::MonsterArgs{
1043 name: Some(name),
1044 testarrayofsortedstruct: Some(v),
1045 ..Default::default()});
1046 my_game::example::finish_monster_buffer(b, mon);
1047 }
1048 let buf = b.finished_data();
1049 let mon = my_game::example::root_as_monster(buf).unwrap();
1050 let abilities = mon.testarrayofsortedstruct().unwrap();
1051
1052 let start_ptr = buf.as_ptr() as usize;
1053 for a in abilities.iter() {
1054 let a_ptr = a as *const my_game::example::Ability as usize;
1055 assert!(a_ptr > start_ptr);
1056 let aln = ::std::mem::align_of::<my_game::example::Ability>();
1057 assert_eq!((a_ptr - start_ptr) % aln, 0);
1058 }
1059 for a in abilities.iter().rev() {
1060 let a_ptr = a as *const my_game::example::Ability as usize;
1061 assert!(a_ptr > start_ptr);
1062 // Vec3 is aligned to 8 wrt the flatbuffer.
1063 assert_eq!((a_ptr - start_ptr) % 8, 0);
1064 }
1065 }
1066 }
1067
1068 #[cfg(test)]
1069 mod roundtrip_byteswap {
1070 #[cfg(not(miri))] // slow.
1071 extern crate quickcheck;
1072 extern crate flatbuffers;
1073
1074 const N: u64 = 10000;
1075
palindrome_32(x: f32) -> bool1076 fn palindrome_32(x: f32) -> bool {
1077 x == f32::from_bits(x.to_bits().swap_bytes())
1078 }
palindrome_64(x: f64) -> bool1079 fn palindrome_64(x: f64) -> bool {
1080 x == f64::from_bits(x.to_bits().swap_bytes())
1081 }
1082
prop_f32(x: f32)1083 fn prop_f32(x: f32) {
1084 use flatbuffers::byte_swap_f32;
1085
1086 let there = byte_swap_f32(x);
1087
1088 let back_again = byte_swap_f32(there);
1089
1090 if !palindrome_32(x) {
1091 assert!(x != there);
1092 }
1093
1094 assert_eq!(x, back_again);
1095 }
1096
prop_f64(x: f64)1097 fn prop_f64(x: f64) {
1098 use flatbuffers::byte_swap_f64;
1099
1100 let there = byte_swap_f64(x);
1101 let back_again = byte_swap_f64(there);
1102
1103 if !palindrome_64(x) {
1104 assert!(x != there);
1105 }
1106
1107 assert_eq!(x, back_again);
1108 }
1109
1110 // TODO(rw): Replace the implementations with the new stdlib endian-conversion functions.
1111 // TODO(rw): Re-enable these tests (currently, rare CI failures occur that seem spurious).
1112 // #[test]
1113 // fn fuzz_f32() { quickcheck::QuickCheck::new().max_tests(N).quickcheck(prop_f32 as fn(f32)); }
1114 // #[test]
1115 // fn fuzz_f64() { quickcheck::QuickCheck::new().max_tests(N).quickcheck(prop_f64 as fn(f64)); }
1116 }
1117
1118 #[cfg(not(miri))]
1119 quickcheck! {
1120 fn struct_of_structs(
1121 a_id: u32,
1122 a_distance: u32,
1123 b_a: i16,
1124 b_b: i8,
1125 c_id: u32,
1126 c_distance: u32
1127 ) -> bool {
1128 use my_game::example::*;
1129 let mut sos = StructOfStructs::default();
1130 let mut a = Ability::default();
1131 a.set_id(a_id);
1132 a.set_distance(a_distance);
1133 let mut b = Test::default();
1134 b.set_a(b_a);
1135 b.set_b(b_b);
1136 let mut c = Ability::default();
1137 c.set_id(c_id);
1138 c.set_distance(c_distance);
1139 sos.set_a(&a);
1140 sos.set_b(&b);
1141 sos.set_c(&c);
1142
1143 sos.a().id() == a_id &&
1144 sos.a().distance() == a_distance &&
1145 sos.b().a() == b_a &&
1146 sos.b().b() == b_b &&
1147 sos.c().id() == c_id &&
1148 sos.c().distance() == c_distance
1149 }
1150 }
1151
1152 #[cfg(not(miri))] // slow.
1153 #[cfg(test)]
1154 mod roundtrip_vectors {
1155
1156 #[cfg(test)]
1157 mod scalar {
1158 extern crate quickcheck;
1159 extern crate flatbuffers;
1160
1161 const N: u64 = 20;
1162
prop<T>(xs: Vec<T>) where T: for<'a> flatbuffers::Follow<'a, Inner = T> + flatbuffers::EndianScalar + flatbuffers::Push + ::std::fmt::Debug,1163 fn prop<T>(xs: Vec<T>)
1164 where
1165 T: for<'a> flatbuffers::Follow<'a, Inner = T>
1166 + flatbuffers::EndianScalar
1167 + flatbuffers::Push
1168 + ::std::fmt::Debug,
1169 {
1170 use flatbuffers::Follow;
1171
1172 let mut b = flatbuffers::FlatBufferBuilder::new();
1173 b.start_vector::<T>(xs.len());
1174 for i in (0..xs.len()).rev() {
1175 b.push::<T>(xs[i]);
1176 }
1177 let vecend = b.end_vector::<T>(xs.len());
1178 b.finish_minimal(vecend);
1179
1180 let buf = b.finished_data();
1181
1182 let got = <flatbuffers::ForwardsUOffset<flatbuffers::Vector<T>>>::follow(&buf[..], 0);
1183 let mut result_vec: Vec<T> = Vec::with_capacity(got.len());
1184 for i in 0..got.len() {
1185 result_vec.push(got.get(i));
1186 }
1187 assert_eq!(result_vec, xs);
1188
1189 let rust_vec_iter = got.iter().collect::<Vec<T>>();
1190 assert_eq!(rust_vec_iter, xs);
1191
1192 let mut rust_vec_rev_iter = got.iter().rev().collect::<Vec<T>>();
1193 rust_vec_rev_iter.reverse();
1194 assert_eq!(rust_vec_rev_iter, xs);
1195 }
1196
1197 #[test]
easy_u8()1198 fn easy_u8() {
1199 prop::<u8>(vec![]);
1200 prop::<u8>(vec![1u8]);
1201 prop::<u8>(vec![1u8, 2u8]);
1202 prop::<u8>(vec![1u8, 2u8, 3u8]);
1203 prop::<u8>(vec![1u8, 2u8, 3u8, 4u8]);
1204 }
1205
1206 #[test]
fuzz_bool()1207 fn fuzz_bool() { quickcheck::QuickCheck::new().max_tests(N).quickcheck(prop::<bool> as fn(Vec<_>)); }
1208 #[test]
fuzz_u8()1209 fn fuzz_u8() { quickcheck::QuickCheck::new().max_tests(N).quickcheck(prop::<u8> as fn(Vec<_>)); }
1210 #[test]
fuzz_i8()1211 fn fuzz_i8() { quickcheck::QuickCheck::new().max_tests(N).quickcheck(prop::<i8> as fn(Vec<_>)); }
1212 #[test]
fuzz_u16()1213 fn fuzz_u16() { quickcheck::QuickCheck::new().max_tests(N).quickcheck(prop::<u16> as fn(Vec<_>)); }
1214 #[test]
fuzz_i16()1215 fn fuzz_i16() { quickcheck::QuickCheck::new().max_tests(N).quickcheck(prop::<i16> as fn(Vec<_>)); }
1216 #[test]
fuzz_u32()1217 fn fuzz_u32() { quickcheck::QuickCheck::new().max_tests(N).quickcheck(prop::<u32> as fn(Vec<_>)); }
1218 #[test]
fuzz_i32()1219 fn fuzz_i32() { quickcheck::QuickCheck::new().max_tests(N).quickcheck(prop::<i32> as fn(Vec<_>)); }
1220 #[test]
fuzz_u64()1221 fn fuzz_u64() { quickcheck::QuickCheck::new().max_tests(N).quickcheck(prop::<u64> as fn(Vec<_>)); }
1222 #[test]
fuzz_i64()1223 fn fuzz_i64() { quickcheck::QuickCheck::new().max_tests(N).quickcheck(prop::<i64> as fn(Vec<_>)); }
1224 #[test]
fuzz_f32()1225 fn fuzz_f32() { quickcheck::QuickCheck::new().max_tests(N).quickcheck(prop::<f32> as fn(Vec<_>)); }
1226 #[test]
fuzz_f64()1227 fn fuzz_f64() { quickcheck::QuickCheck::new().max_tests(N).quickcheck(prop::<f64> as fn(Vec<_>)); }
1228 }
1229
1230 #[cfg(test)]
1231 mod create_vector_direct {
1232 #[cfg(not(miri))] // slow.
1233 extern crate quickcheck;
1234 extern crate flatbuffers;
1235
1236 const N: u64 = 20;
1237
1238 // This uses a macro because lifetimes for the trait-bounded function get too
1239 // complicated.
1240 macro_rules! impl_prop {
1241 ($test_name:ident, $fn_name:ident, $ty:ident) => (
1242 fn $fn_name(xs: Vec<$ty>) {
1243 use flatbuffers::Follow;
1244
1245 let mut b = flatbuffers::FlatBufferBuilder::new();
1246 b.create_vector_direct(&xs[..]);
1247 let buf = b.unfinished_data();
1248
1249 let got = <flatbuffers::Vector<$ty>>::follow(&buf[..], 0).safe_slice();
1250 assert_eq!(got, &xs[..]);
1251 }
1252 #[test]
1253 fn $test_name() { quickcheck::QuickCheck::new().max_tests(N).quickcheck($fn_name as fn(Vec<_>)); }
1254 )
1255 }
1256
1257 impl_prop!(test_bool, prop_bool, bool);
1258 impl_prop!(test_u8, prop_u8, u8);
1259 impl_prop!(test_i8, prop_i8, i8);
1260
1261 #[cfg(test)]
1262 #[cfg(target_endian = "little")]
1263 mod host_is_le {
1264 const N: u64 = 20;
1265 use super::flatbuffers;
1266 use super::quickcheck;
1267 impl_prop!(test_u16, prop_u16, u16);
1268 impl_prop!(test_u32, prop_u32, u32);
1269 impl_prop!(test_u64, prop_u64, u64);
1270 impl_prop!(test_i16, prop_i16, i16);
1271 impl_prop!(test_i32, prop_i32, i32);
1272 impl_prop!(test_i64, prop_i64, i64);
1273 impl_prop!(test_f32, prop_f32, f32);
1274 impl_prop!(test_f64, prop_f64, f64);
1275 }
1276 }
1277
1278 #[cfg(test)]
1279 mod string_manual_build {
1280 #[cfg(not(miri))] // slow.
1281 extern crate quickcheck;
1282 extern crate flatbuffers;
1283
prop(xs: Vec<String>)1284 fn prop(xs: Vec<String>) {
1285 use flatbuffers::Follow;
1286
1287 let mut b = flatbuffers::FlatBufferBuilder::new();
1288 let mut offsets = Vec::new();
1289 for s in xs.iter().rev() {
1290 offsets.push(b.create_string(s.as_str()));
1291 }
1292
1293 b.start_vector::<flatbuffers::WIPOffset<&str>>(xs.len());
1294 for &i in offsets.iter() {
1295 b.push(i);
1296 }
1297 let vecend = b.end_vector::<flatbuffers::WIPOffset<&str>>(xs.len());
1298
1299 b.finish_minimal(vecend);
1300
1301 let buf = b.finished_data();
1302 let got = <flatbuffers::ForwardsUOffset<flatbuffers::Vector<flatbuffers::ForwardsUOffset<&str>>>>::follow(buf, 0);
1303
1304 assert_eq!(got.len(), xs.len());
1305 for i in 0..xs.len() {
1306 assert_eq!(got.get(i), &xs[i][..]);
1307 }
1308 }
1309
1310 #[test]
fuzz()1311 fn fuzz() {
1312 quickcheck::QuickCheck::new().max_tests(20).quickcheck(prop as fn(Vec<_>));
1313 }
1314 }
1315
1316 #[cfg(test)]
1317 mod string_helper_build {
1318 #[cfg(not(miri))] // slow.
1319 extern crate quickcheck;
1320 extern crate flatbuffers;
1321
prop(input: Vec<String>)1322 fn prop(input: Vec<String>) {
1323 let xs: Vec<&str> = input.iter().map(|s: &String| &s[..]).collect();
1324
1325 use flatbuffers::Follow;
1326
1327 let mut b = flatbuffers::FlatBufferBuilder::new();
1328 let vecend = b.create_vector_of_strings(&xs[..]);
1329
1330 b.finish_minimal(vecend);
1331
1332 let buf = b.finished_data();
1333 let got = <flatbuffers::ForwardsUOffset<flatbuffers::Vector<flatbuffers::ForwardsUOffset<&str>>>>::follow(buf, 0);
1334
1335 assert_eq!(got.len(), xs.len());
1336 for i in 0..xs.len() {
1337 assert_eq!(got.get(i), &xs[i][..]);
1338 }
1339 }
1340
1341 #[test]
fuzz()1342 fn fuzz() {
1343 quickcheck::QuickCheck::new().max_tests(100).quickcheck(prop as fn(Vec<_>));
1344 }
1345 }
1346
1347 #[cfg(test)]
1348 mod ubyte {
1349 #[cfg(not(miri))] // slow.
1350 extern crate quickcheck;
1351 extern crate flatbuffers;
1352
1353 #[cfg(not(miri))] // slow.
1354 #[test]
fuzz_manual_build()1355 fn fuzz_manual_build() {
1356 fn prop(vec: Vec<u8>) {
1357 let xs = &vec[..];
1358
1359 let mut b1 = flatbuffers::FlatBufferBuilder::new();
1360 b1.start_vector::<u8>(xs.len());
1361
1362 for i in (0..xs.len()).rev() {
1363 b1.push(xs[i]);
1364 }
1365 b1.end_vector::<u8>(xs.len());
1366
1367 let mut b2 = flatbuffers::FlatBufferBuilder::new();
1368 b2.create_vector(xs);
1369 assert_eq!(b1.unfinished_data(), b2.unfinished_data());
1370 }
1371 quickcheck::QuickCheck::new().max_tests(100).quickcheck(prop as fn(Vec<_>));
1372 }
1373 }
1374 }
1375
1376 #[cfg(test)]
1377 mod framing_format {
1378 extern crate flatbuffers;
1379
1380 use super::my_game;
1381
1382 #[test]
test_size_prefixed_buffer()1383 fn test_size_prefixed_buffer() {
1384 // Create size prefixed buffer.
1385 let mut b = flatbuffers::FlatBufferBuilder::new();
1386 let args = &my_game::example::MonsterArgs{
1387 mana: 200,
1388 hp: 300,
1389 name: Some(b.create_string("bob")),
1390 ..Default::default()
1391 };
1392 let mon = my_game::example::Monster::create(&mut b, &args);
1393 b.finish_size_prefixed(mon, None);
1394
1395 // Access it.
1396 let buf = b.finished_data();
1397 let m = flatbuffers::size_prefixed_root::<my_game::example::Monster>(buf).unwrap();
1398 assert_eq!(m.mana(), 200);
1399 assert_eq!(m.hp(), 300);
1400 assert_eq!(m.name(), "bob");
1401 }
1402 }
1403
1404 #[cfg(test)]
1405 mod roundtrip_table {
1406 use std::collections::HashMap;
1407
1408 extern crate flatbuffers;
1409 #[cfg(not(miri))] // slow.
1410 extern crate quickcheck;
1411
1412 use super::LCG;
1413
1414 #[test]
1415 #[cfg(not(miri))] // slow.
table_of_mixed_scalars_fuzz()1416 fn table_of_mixed_scalars_fuzz() {
1417 // Values we're testing against: chosen to ensure no bits get chopped
1418 // off anywhere, and also be different from eachother.
1419 let bool_val: bool = true;
1420 let char_val: i8 = -127; // 0x81
1421 let uchar_val: u8 = 0xFF;
1422 let short_val: i16 = -32222; // 0x8222;
1423 let ushort_val: u16 = 0xFEEE;
1424 let int_val: i32 = unsafe { ::std::mem::transmute(0x83333333u32) };
1425 let uint_val: u32 = 0xFDDDDDDD;
1426 let long_val: i64 = unsafe { ::std::mem::transmute(0x8444444444444444u64) }; // TODO: byte literal?
1427 let ulong_val: u64 = 0xFCCCCCCCCCCCCCCCu64;
1428 let float_val: f32 = 3.14159;
1429 let double_val: f64 = 3.14159265359;
1430
1431 let test_value_types_max: isize = 11;
1432 let max_fields_per_object: flatbuffers::VOffsetT = 100;
1433 let num_fuzz_objects: isize = 1000; // The higher, the more thorough :)
1434
1435 let mut builder = flatbuffers::FlatBufferBuilder::new();
1436 let mut lcg = LCG::new();
1437
1438 let mut objects: Vec<flatbuffers::UOffsetT> = vec![0; num_fuzz_objects as usize];
1439
1440 // Generate num_fuzz_objects random objects each consisting of
1441 // fields_per_object fields, each of a random type.
1442 for i in 0..(num_fuzz_objects as usize) {
1443 let fields_per_object = (lcg.next() % (max_fields_per_object as u64)) as flatbuffers::VOffsetT;
1444 let start = builder.start_table();
1445
1446 for j in 0..fields_per_object {
1447 let choice = lcg.next() % (test_value_types_max as u64);
1448
1449 let f = flatbuffers::field_index_to_field_offset(j);
1450
1451 match choice {
1452 0 => {builder.push_slot::<bool>(f, bool_val, false);}
1453 1 => {builder.push_slot::<i8>(f, char_val, 0);}
1454 2 => {builder.push_slot::<u8>(f, uchar_val, 0);}
1455 3 => {builder.push_slot::<i16>(f, short_val, 0);}
1456 4 => {builder.push_slot::<u16>(f, ushort_val, 0);}
1457 5 => {builder.push_slot::<i32>(f, int_val, 0);}
1458 6 => {builder.push_slot::<u32>(f, uint_val, 0);}
1459 7 => {builder.push_slot::<i64>(f, long_val, 0);}
1460 8 => {builder.push_slot::<u64>(f, ulong_val, 0);}
1461 9 => {builder.push_slot::<f32>(f, float_val, 0.0);}
1462 10 => {builder.push_slot::<f64>(f, double_val, 0.0);}
1463 _ => { panic!("unknown choice: {}", choice); }
1464 }
1465 }
1466 objects[i] = builder.end_table(start).value();
1467 }
1468
1469 // Do some bookkeeping to generate stats on fuzzes:
1470 let mut stats: HashMap<u64, u64> = HashMap::new();
1471 let mut values_generated: u64 = 0;
1472
1473 // Embrace PRNG determinism:
1474 lcg.reset();
1475
1476 // Test that all objects we generated are readable and return the
1477 // expected values. We generate random objects in the same order
1478 // so this is deterministic:
1479 for i in 0..(num_fuzz_objects as usize) {
1480 let table = {
1481 let buf = builder.unfinished_data();
1482 let loc = buf.len() as flatbuffers::UOffsetT - objects[i];
1483 flatbuffers::Table::new(buf, loc as usize)
1484 };
1485
1486 let fields_per_object = (lcg.next() % (max_fields_per_object as u64)) as flatbuffers::VOffsetT;
1487 for j in 0..fields_per_object {
1488 let choice = lcg.next() % (test_value_types_max as u64);
1489
1490 *stats.entry(choice).or_insert(0) += 1;
1491 values_generated += 1;
1492
1493 let f = flatbuffers::field_index_to_field_offset(j);
1494
1495 match choice {
1496 0 => { assert_eq!(bool_val, table.get::<bool>(f, Some(false)).unwrap()); }
1497 1 => { assert_eq!(char_val, table.get::<i8>(f, Some(0)).unwrap()); }
1498 2 => { assert_eq!(uchar_val, table.get::<u8>(f, Some(0)).unwrap()); }
1499 3 => { assert_eq!(short_val, table.get::<i16>(f, Some(0)).unwrap()); }
1500 4 => { assert_eq!(ushort_val, table.get::<u16>(f, Some(0)).unwrap()); }
1501 5 => { assert_eq!(int_val, table.get::<i32>(f, Some(0)).unwrap()); }
1502 6 => { assert_eq!(uint_val, table.get::<u32>(f, Some(0)).unwrap()); }
1503 7 => { assert_eq!(long_val, table.get::<i64>(f, Some(0)).unwrap()); }
1504 8 => { assert_eq!(ulong_val, table.get::<u64>(f, Some(0)).unwrap()); }
1505 9 => { assert_eq!(float_val, table.get::<f32>(f, Some(0.0)).unwrap()); }
1506 10 => { assert_eq!(double_val, table.get::<f64>(f, Some(0.0)).unwrap()); }
1507 _ => { panic!("unknown choice: {}", choice); }
1508 }
1509 }
1510 }
1511
1512 // Assert that we tested all the fuzz cases enough:
1513 let min_tests_per_choice = 1000;
1514 assert!(values_generated > 0);
1515 assert!(min_tests_per_choice > 0);
1516 for i in 0..test_value_types_max as u64 {
1517 assert!(stats[&i] >= min_tests_per_choice, "inadequately-tested fuzz case: {}", i);
1518 }
1519 }
1520
1521 #[test]
1522 #[cfg(not(miri))] // slow.
table_of_byte_strings_fuzz()1523 fn table_of_byte_strings_fuzz() {
1524 fn prop(vec: Vec<Vec<u8>>) {
1525 use flatbuffers::field_index_to_field_offset as fi2fo;
1526 use flatbuffers::Follow;
1527
1528 let xs = &vec[..];
1529
1530 // build
1531 let mut b = flatbuffers::FlatBufferBuilder::new();
1532 let str_offsets: Vec<flatbuffers::WIPOffset<_>> = xs.iter().map(|s| b.create_byte_string(&s[..])).collect();
1533 let table_start = b.start_table();
1534
1535 for i in 0..xs.len() {
1536 b.push_slot_always(fi2fo(i as flatbuffers::VOffsetT), str_offsets[i]);
1537 }
1538 let root = b.end_table(table_start);
1539 b.finish_minimal(root);
1540
1541 // use
1542 let buf = b.finished_data();
1543 let tab = <flatbuffers::ForwardsUOffset<flatbuffers::Table>>::follow(buf, 0);
1544
1545 for i in 0..xs.len() {
1546 let v = tab.get::<flatbuffers::ForwardsUOffset<flatbuffers::Vector<u8>>>(fi2fo(i as flatbuffers::VOffsetT), None);
1547 assert!(v.is_some());
1548 let v2 = v.unwrap().safe_slice();
1549 assert_eq!(v2, &xs[i][..]);
1550 }
1551 }
1552 prop(vec![vec![1,2,3]]);
1553
1554 let n = 20;
1555 quickcheck::QuickCheck::new().max_tests(n).quickcheck(prop as fn(Vec<_>));
1556 }
1557
1558 #[test]
1559 #[cfg(not(miri))] // slow.
fuzz_table_of_strings()1560 fn fuzz_table_of_strings() {
1561 fn prop(vec: Vec<String>) {
1562 use flatbuffers::field_index_to_field_offset as fi2fo;
1563 use flatbuffers::Follow;
1564
1565 let xs = &vec[..];
1566
1567 // build
1568 let mut b = flatbuffers::FlatBufferBuilder::new();
1569 let str_offsets: Vec<flatbuffers::WIPOffset<_>> = xs.iter().map(|s| b.create_string(&s[..])).collect();
1570 let table_start = b.start_table();
1571
1572 for i in 0..xs.len() {
1573 b.push_slot_always(fi2fo(i as flatbuffers::VOffsetT), str_offsets[i]);
1574 }
1575 let root = b.end_table(table_start);
1576 b.finish_minimal(root);
1577
1578 // use
1579 let buf = b.finished_data();
1580 let tab = <flatbuffers::ForwardsUOffset<flatbuffers::Table>>::follow(buf, 0);
1581
1582 for i in 0..xs.len() {
1583 let v = tab.get::<flatbuffers::ForwardsUOffset<&str>>(fi2fo(i as flatbuffers::VOffsetT), None);
1584 assert_eq!(v, Some(&xs[i][..]));
1585 }
1586 }
1587 let n = 20;
1588 quickcheck::QuickCheck::new().max_tests(n).quickcheck(prop as fn(Vec<String>));
1589 }
1590
1591 #[cfg(not(miri))] // slow.
1592 mod table_of_vectors_of_scalars {
1593 extern crate flatbuffers;
1594 #[cfg(not(miri))] // slow.
1595 extern crate quickcheck;
1596
1597 const N: u64 = 20;
1598
prop<T>(vecs: Vec<Vec<T>>) where T: for<'a> flatbuffers::Follow<'a, Inner = T> + flatbuffers::EndianScalar + flatbuffers::Push + ::std::fmt::Debug,1599 fn prop<T>(vecs: Vec<Vec<T>>)
1600 where
1601 T: for<'a> flatbuffers::Follow<'a, Inner = T>
1602 + flatbuffers::EndianScalar
1603 + flatbuffers::Push
1604 + ::std::fmt::Debug,
1605 {
1606 use flatbuffers::field_index_to_field_offset as fi2fo;
1607 use flatbuffers::Follow;
1608
1609 // build
1610 let mut b = flatbuffers::FlatBufferBuilder::new();
1611 let mut offs = vec![];
1612 for vec in &vecs {
1613 b.start_vector::<T>(vec.len());
1614
1615 let xs = &vec[..];
1616 for i in (0..xs.len()).rev() {
1617 b.push::<T>(xs[i]);
1618 }
1619 let vecend = b.end_vector::<T>(xs.len());
1620 offs.push(vecend);
1621 }
1622
1623 let table_start = b.start_table();
1624
1625 for i in 0..vecs.len() {
1626 b.push_slot_always(fi2fo(i as flatbuffers::VOffsetT), offs[i]);
1627 }
1628 let root = b.end_table(table_start);
1629 b.finish_minimal(root);
1630
1631 // use
1632 let buf = b.finished_data();
1633 let tab = <flatbuffers::ForwardsUOffset<flatbuffers::Table>>::follow(buf, 0);
1634
1635 for i in 0..vecs.len() {
1636 let got = tab.get::<flatbuffers::ForwardsUOffset<flatbuffers::Vector<T>>>(fi2fo(i as flatbuffers::VOffsetT), None);
1637 assert!(got.is_some());
1638 let got2 = got.unwrap();
1639 let mut got3: Vec<T> = Vec::with_capacity(got2.len());
1640 for i in 0..got2.len() {
1641 got3.push(got2.get(i));
1642 }
1643 assert_eq!(vecs[i], got3);
1644 }
1645 }
1646
1647 #[test]
fuzz_bool()1648 fn fuzz_bool() { quickcheck::QuickCheck::new().max_tests(N).quickcheck(prop as fn(Vec<Vec<bool>>)); }
1649
1650 #[test]
fuzz_u8()1651 fn fuzz_u8() { quickcheck::QuickCheck::new().max_tests(N).quickcheck(prop as fn(Vec<Vec<u8>>)); }
1652 #[test]
fuzz_u16()1653 fn fuzz_u16() { quickcheck::QuickCheck::new().max_tests(N).quickcheck(prop as fn(Vec<Vec<u16>>)); }
1654 #[test]
fuzz_u32()1655 fn fuzz_u32() { quickcheck::QuickCheck::new().max_tests(N).quickcheck(prop as fn(Vec<Vec<u32>>)); }
1656 #[test]
fuzz_u64()1657 fn fuzz_u64() { quickcheck::QuickCheck::new().max_tests(N).quickcheck(prop as fn(Vec<Vec<u64>>)); }
1658
1659 #[test]
fuzz_i8()1660 fn fuzz_i8() { quickcheck::QuickCheck::new().max_tests(N).quickcheck(prop as fn(Vec<Vec<u8>>)); }
1661 #[test]
fuzz_i16()1662 fn fuzz_i16() { quickcheck::QuickCheck::new().max_tests(N).quickcheck(prop as fn(Vec<Vec<u16>>)); }
1663 #[test]
fuzz_i32()1664 fn fuzz_i32() { quickcheck::QuickCheck::new().max_tests(N).quickcheck(prop as fn(Vec<Vec<u32>>)); }
1665 #[test]
fuzz_i64()1666 fn fuzz_i64() { quickcheck::QuickCheck::new().max_tests(N).quickcheck(prop as fn(Vec<Vec<u64>>)); }
1667
1668 #[test]
fuzz_f32()1669 fn fuzz_f32() { quickcheck::QuickCheck::new().max_tests(N).quickcheck(prop as fn(Vec<Vec<f32>>)); }
1670 #[test]
fuzz_f64()1671 fn fuzz_f64() { quickcheck::QuickCheck::new().max_tests(N).quickcheck(prop as fn(Vec<Vec<f64>>)); }
1672 }
1673 }
1674
1675 #[cfg(not(miri))] // slow.
1676 #[cfg(test)]
1677 mod roundtrip_scalars {
1678 extern crate flatbuffers;
1679 #[cfg(not(miri))] // slow.
1680 extern crate quickcheck;
1681
1682 const N: u64 = 1000;
1683
prop<T: PartialEq + ::std::fmt::Debug + Copy + flatbuffers::EndianScalar>(x: T)1684 fn prop<T: PartialEq + ::std::fmt::Debug + Copy + flatbuffers::EndianScalar>(x: T) {
1685 let mut buf = vec![0u8; ::std::mem::size_of::<T>()];
1686 let y = unsafe {
1687 flatbuffers::emplace_scalar(&mut buf[..], x);
1688 flatbuffers::read_scalar(&buf[..])
1689 };
1690 assert_eq!(x, y);
1691 }
1692
1693 #[test]
fuzz_bool()1694 fn fuzz_bool() { quickcheck::QuickCheck::new().max_tests(N).quickcheck(prop::<bool> as fn(_)); }
1695 #[test]
fuzz_u8()1696 fn fuzz_u8() { quickcheck::QuickCheck::new().max_tests(N).quickcheck(prop::<u8> as fn(_)); }
1697 #[test]
fuzz_i8()1698 fn fuzz_i8() { quickcheck::QuickCheck::new().max_tests(N).quickcheck(prop::<i8> as fn(_)); }
1699
1700 #[test]
fuzz_u16()1701 fn fuzz_u16() { quickcheck::QuickCheck::new().max_tests(N).quickcheck(prop::<u16> as fn(_)); }
1702 #[test]
fuzz_i16()1703 fn fuzz_i16() { quickcheck::QuickCheck::new().max_tests(N).quickcheck(prop::<i16> as fn(_)); }
1704
1705 #[test]
fuzz_u32()1706 fn fuzz_u32() { quickcheck::QuickCheck::new().max_tests(N).quickcheck(prop::<u32> as fn(_)); }
1707 #[test]
fuzz_i32()1708 fn fuzz_i32() { quickcheck::QuickCheck::new().max_tests(N).quickcheck(prop::<i32> as fn(_)); }
1709
1710 #[test]
fuzz_u64()1711 fn fuzz_u64() { quickcheck::QuickCheck::new().max_tests(N).quickcheck(prop::<u64> as fn(_)); }
1712 #[test]
fuzz_i64()1713 fn fuzz_i64() { quickcheck::QuickCheck::new().max_tests(N).quickcheck(prop::<i64> as fn(_)); }
1714
1715 #[test]
fuzz_f32()1716 fn fuzz_f32() { quickcheck::QuickCheck::new().max_tests(N).quickcheck(prop::<f32> as fn(_)); }
1717 #[test]
fuzz_f64()1718 fn fuzz_f64() { quickcheck::QuickCheck::new().max_tests(N).quickcheck(prop::<f64> as fn(_)); }
1719 }
1720
1721 #[cfg(test)]
1722 #[cfg(not(miri))] // slow.
1723 mod roundtrip_push_follow_scalars {
1724 extern crate flatbuffers;
1725 #[cfg(not(miri))] // slow.
1726 extern crate quickcheck;
1727
1728 use flatbuffers::Push;
1729
1730 const N: u64 = 1000;
1731
1732 // This uses a macro because lifetimes for a trait-bounded function get too
1733 // complicated.
1734 macro_rules! impl_prop {
1735 ($fn_name:ident, $ty:ident) => (
1736 fn $fn_name(x: $ty) {
1737 let mut buf = vec![0u8; ::std::mem::size_of::<$ty>()];
1738 x.push(&mut buf[..], &[][..]);
1739 let fs: flatbuffers::FollowStart<$ty> = flatbuffers::FollowStart::new();
1740 assert_eq!(fs.self_follow(&buf[..], 0), x);
1741 }
1742 )
1743 }
1744
1745 impl_prop!(prop_bool, bool);
1746 impl_prop!(prop_u8, u8);
1747 impl_prop!(prop_i8, i8);
1748 impl_prop!(prop_u16, u16);
1749 impl_prop!(prop_i16, i16);
1750 impl_prop!(prop_u32, u32);
1751 impl_prop!(prop_i32, i32);
1752 impl_prop!(prop_u64, u64);
1753 impl_prop!(prop_i64, i64);
1754 impl_prop!(prop_f32, f32);
1755 impl_prop!(prop_f64, f64);
1756
1757 #[test]
fuzz_bool()1758 fn fuzz_bool() { quickcheck::QuickCheck::new().max_tests(N).quickcheck(prop_bool as fn(bool)); }
1759 #[test]
fuzz_u8()1760 fn fuzz_u8() { quickcheck::QuickCheck::new().max_tests(N).quickcheck(prop_u8 as fn(u8)); }
1761 #[test]
fuzz_i8()1762 fn fuzz_i8() { quickcheck::QuickCheck::new().max_tests(N).quickcheck(prop_i8 as fn(i8)); }
1763 #[test]
fuzz_u16()1764 fn fuzz_u16() { quickcheck::QuickCheck::new().max_tests(N).quickcheck(prop_u16 as fn(u16)); }
1765 #[test]
fuzz_i16()1766 fn fuzz_i16() { quickcheck::QuickCheck::new().max_tests(N).quickcheck(prop_i16 as fn(i16)); }
1767 #[test]
fuzz_u32()1768 fn fuzz_u32() { quickcheck::QuickCheck::new().max_tests(N).quickcheck(prop_u32 as fn(u32)); }
1769 #[test]
fuzz_i32()1770 fn fuzz_i32() { quickcheck::QuickCheck::new().max_tests(N).quickcheck(prop_i32 as fn(i32)); }
1771 #[test]
fuzz_u64()1772 fn fuzz_u64() { quickcheck::QuickCheck::new().max_tests(N).quickcheck(prop_u64 as fn(u64)); }
1773 #[test]
fuzz_i64()1774 fn fuzz_i64() { quickcheck::QuickCheck::new().max_tests(N).quickcheck(prop_i64 as fn(i64)); }
1775 #[test]
fuzz_f32()1776 fn fuzz_f32() { quickcheck::QuickCheck::new().max_tests(N).quickcheck(prop_f32 as fn(f32)); }
1777 #[test]
fuzz_f64()1778 fn fuzz_f64() { quickcheck::QuickCheck::new().max_tests(N).quickcheck(prop_f64 as fn(f64)); }
1779 }
1780
1781
1782 #[cfg(test)]
1783 mod write_and_read_examples {
1784 extern crate flatbuffers;
1785
1786 use super::create_serialized_example_with_library_code;
1787 use super::create_serialized_example_with_generated_code;
1788 use super::serialized_example_is_accessible_and_correct;
1789
1790 #[test]
generated_code_creates_correct_example()1791 fn generated_code_creates_correct_example() {
1792 let b = &mut flatbuffers::FlatBufferBuilder::new();
1793 create_serialized_example_with_generated_code(b);
1794 let buf = b.finished_data();
1795 serialized_example_is_accessible_and_correct(&buf[..], true, false).unwrap();
1796 }
1797
1798 #[test]
generated_code_debug_prints_correctly()1799 fn generated_code_debug_prints_correctly() {
1800 let b = &mut flatbuffers::FlatBufferBuilder::new();
1801 create_serialized_example_with_generated_code(b);
1802 let buf = b.finished_data();
1803 serialized_example_is_accessible_and_correct(&buf, true, false).unwrap();
1804 let m = super::my_game::example::root_as_monster(buf).unwrap();
1805 assert_eq!(
1806 format!("{:.5?}", &m),
1807 "Monster { pos: Some(Vec3 { x: 1.00000, y: 2.00000, z: 3.00000, \
1808 test1: 3.00000, test2: Green, test3: Test { a: 5, b: 6 } }), \
1809 mana: 150, hp: 80, name: \"MyMonster\", \
1810 inventory: Some([0, 1, 2, 3, 4]), color: Blue, test_type: Monster, \
1811 test: Monster { pos: None, mana: 150, hp: 100, name: \"Fred\", \
1812 inventory: None, color: Blue, test_type: NONE, test: None, \
1813 test4: None, testarrayofstring: None, testarrayoftables: None, \
1814 enemy: None, testnestedflatbuffer: None, testempty: None, \
1815 testbool: false, testhashs32_fnv1: 0, testhashu32_fnv1: 0, \
1816 testhashs64_fnv1: 0, testhashu64_fnv1: 0, testhashs32_fnv1a: 0, \
1817 testhashu32_fnv1a: 0, testhashs64_fnv1a: 0, testhashu64_fnv1a: 0, \
1818 testarrayofbools: None, testf: 3.14159, testf2: 3.00000, testf3: 0.00000, \
1819 testarrayofstring2: None, testarrayofsortedstruct: None, flex: None, \
1820 test5: None, vector_of_longs: None, vector_of_doubles: None, \
1821 parent_namespace_test: None, vector_of_referrables: None, \
1822 single_weak_reference: 0, vector_of_weak_references: None, \
1823 vector_of_strong_referrables: None, co_owning_reference: 0, \
1824 vector_of_co_owning_references: None, non_owning_reference: 0, \
1825 vector_of_non_owning_references: None, any_unique_type: NONE, \
1826 any_unique: None, any_ambiguous_type: NONE, any_ambiguous: None, \
1827 vector_of_enums: None, signed_enum: None, \
1828 testrequirednestedflatbuffer: None, scalar_key_sorted_tables: None }, \
1829 test4: Some([Test { a: 10, b: 20 }, Test { a: 30, b: 40 }]), \
1830 testarrayofstring: Some([\"test1\", \"test2\"]), \
1831 testarrayoftables: None, enemy: None, testnestedflatbuffer: None, \
1832 testempty: None, testbool: false, testhashs32_fnv1: 0, \
1833 testhashu32_fnv1: 0, testhashs64_fnv1: 0, testhashu64_fnv1: 0, \
1834 testhashs32_fnv1a: 0, testhashu32_fnv1a: 0, testhashs64_fnv1a: 0, \
1835 testhashu64_fnv1a: 0, testarrayofbools: None, testf: 3.14159, \
1836 testf2: 3.00000, testf3: 0.00000, testarrayofstring2: None, \
1837 testarrayofsortedstruct: None, flex: None, test5: None, \
1838 vector_of_longs: None, vector_of_doubles: None, \
1839 parent_namespace_test: None, vector_of_referrables: None, \
1840 single_weak_reference: 0, vector_of_weak_references: None, \
1841 vector_of_strong_referrables: None, co_owning_reference: 0, \
1842 vector_of_co_owning_references: None, non_owning_reference: 0, \
1843 vector_of_non_owning_references: None, any_unique_type: NONE, \
1844 any_unique: None, any_ambiguous_type: NONE, any_ambiguous: None, \
1845 vector_of_enums: None, signed_enum: None, \
1846 testrequirednestedflatbuffer: None, scalar_key_sorted_tables: None }"
1847 );
1848 }
1849
1850 #[test]
1851 #[cfg(not(miri))] // slow.
generated_code_creates_correct_example_repeatedly_with_reset()1852 fn generated_code_creates_correct_example_repeatedly_with_reset() {
1853 let b = &mut flatbuffers::FlatBufferBuilder::new();
1854 for _ in 0..100 {
1855 create_serialized_example_with_generated_code(b);
1856 {
1857 let buf = b.finished_data();
1858 serialized_example_is_accessible_and_correct(&buf[..], true, false).unwrap();
1859 }
1860 b.reset();
1861 }
1862 }
1863
1864 #[test]
library_code_creates_correct_example()1865 fn library_code_creates_correct_example() {
1866 let b = &mut flatbuffers::FlatBufferBuilder::new();
1867 create_serialized_example_with_library_code(b);
1868 let buf = b.finished_data();
1869 serialized_example_is_accessible_and_correct(&buf[..], true, false).unwrap();
1870 }
1871
1872 #[test]
1873 #[cfg(not(miri))] // slow.
library_code_creates_correct_example_repeatedly_with_reset()1874 fn library_code_creates_correct_example_repeatedly_with_reset() {
1875 let b = &mut flatbuffers::FlatBufferBuilder::new();
1876 for _ in 0..100 {
1877 create_serialized_example_with_library_code(b);
1878 {
1879 let buf = b.finished_data();
1880 serialized_example_is_accessible_and_correct(&buf[..], true, false).unwrap();
1881 }
1882 b.reset();
1883 }
1884 }
1885 }
1886
1887 #[cfg(test)]
1888 mod read_examples_from_other_language_ports {
1889 extern crate flatbuffers;
1890
1891 use super::load_file;
1892 use super::serialized_example_is_accessible_and_correct;
1893
1894 #[test]
gold_cpp_example_data_is_accessible_and_correct()1895 fn gold_cpp_example_data_is_accessible_and_correct() {
1896 let buf = load_file("../monsterdata_test.mon").expect("missing monsterdata_test.mon");
1897 serialized_example_is_accessible_and_correct(&buf[..], true, false).unwrap();
1898 }
1899 #[test]
java_wire_example_data_is_accessible_and_correct()1900 fn java_wire_example_data_is_accessible_and_correct() {
1901 let buf = load_file("../monsterdata_java_wire.mon");
1902 if buf.is_err() {
1903 println!("skipping java wire test because it is not present");
1904 return;
1905 }
1906 let buf = buf.unwrap();
1907 serialized_example_is_accessible_and_correct(&buf[..], true, false).unwrap();
1908 }
1909 #[test]
java_wire_size_prefixed_example_data_is_accessible_and_correct()1910 fn java_wire_size_prefixed_example_data_is_accessible_and_correct() {
1911 let buf = load_file("../monsterdata_java_wire_sp.mon");
1912 if buf.is_err() {
1913 println!("skipping java wire test because it is not present");
1914 return;
1915 }
1916 let buf = buf.unwrap();
1917 serialized_example_is_accessible_and_correct(&buf[..], true, true).unwrap();
1918 }
1919 }
1920
1921 #[cfg(test)]
1922 mod generated_code_asserts {
1923 extern crate flatbuffers;
1924
1925 use super::my_game;
1926
1927 #[test]
1928 #[should_panic]
monster_builder_fails_when_name_is_missing()1929 fn monster_builder_fails_when_name_is_missing() {
1930 let b = &mut flatbuffers::FlatBufferBuilder::new();
1931 my_game::example::Monster::create(b, &my_game::example::MonsterArgs{..Default::default()});
1932 }
1933 }
1934
1935 #[cfg(test)]
1936 mod generated_key_comparisons {
1937 extern crate flatbuffers;
1938
1939 use super::my_game;
1940
1941 #[test]
struct_ability_key_compare_less_than()1942 fn struct_ability_key_compare_less_than() {
1943 let a = my_game::example::Ability::new(1, 2);
1944 let b = my_game::example::Ability::new(2, 1);
1945 let c = my_game::example::Ability::new(3, 3);
1946
1947 assert_eq!(a.key_compare_less_than(&a), false);
1948 assert_eq!(b.key_compare_less_than(&b), false);
1949 assert_eq!(c.key_compare_less_than(&c), false);
1950
1951 assert_eq!(a.key_compare_less_than(&b), true);
1952 assert_eq!(a.key_compare_less_than(&c), true);
1953
1954 assert_eq!(b.key_compare_less_than(&a), false);
1955 assert_eq!(b.key_compare_less_than(&c), true);
1956
1957 assert_eq!(c.key_compare_less_than(&a), false);
1958 assert_eq!(c.key_compare_less_than(&b), false);
1959 }
1960
1961 #[test]
struct_key_compare_with_value()1962 fn struct_key_compare_with_value() {
1963 let a = my_game::example::Ability::new(1, 2);
1964
1965 assert_eq!(a.key_compare_with_value(0), ::std::cmp::Ordering::Greater);
1966 assert_eq!(a.key_compare_with_value(1), ::std::cmp::Ordering::Equal);
1967 assert_eq!(a.key_compare_with_value(2), ::std::cmp::Ordering::Less);
1968 }
1969
1970 #[test]
struct_key_compare_less_than()1971 fn struct_key_compare_less_than() {
1972 let a = my_game::example::Ability::new(1, 2);
1973 let b = my_game::example::Ability::new(2, 1);
1974 let c = my_game::example::Ability::new(3, 3);
1975
1976 assert_eq!(a.key_compare_less_than(&a), false);
1977 assert_eq!(b.key_compare_less_than(&b), false);
1978 assert_eq!(c.key_compare_less_than(&c), false);
1979
1980 assert_eq!(a.key_compare_less_than(&b), true);
1981 assert_eq!(a.key_compare_less_than(&c), true);
1982
1983 assert_eq!(b.key_compare_less_than(&a), false);
1984 assert_eq!(b.key_compare_less_than(&c), true);
1985
1986 assert_eq!(c.key_compare_less_than(&a), false);
1987 assert_eq!(c.key_compare_less_than(&b), false);
1988 }
1989
1990 #[test]
table_key_compare_with_value()1991 fn table_key_compare_with_value() {
1992 // setup
1993 let builder = &mut flatbuffers::FlatBufferBuilder::new();
1994 super::create_serialized_example_with_library_code(builder);
1995 let buf = builder.finished_data();
1996 let a = my_game::example::root_as_monster(buf).unwrap();
1997
1998 // preconditions
1999 assert_eq!(a.name(), "MyMonster");
2000
2001 assert_eq!(a.key_compare_with_value("AAA"), ::std::cmp::Ordering::Greater);
2002 assert_eq!(a.key_compare_with_value("MyMonster"), ::std::cmp::Ordering::Equal);
2003 assert_eq!(a.key_compare_with_value("ZZZ"), ::std::cmp::Ordering::Less);
2004 }
2005
2006 #[test]
table_key_compare_less_than()2007 fn table_key_compare_less_than() {
2008 // setup
2009 let builder = &mut flatbuffers::FlatBufferBuilder::new();
2010 super::create_serialized_example_with_library_code(builder);
2011 let buf = builder.finished_data();
2012 let a = my_game::example::root_as_monster(buf).unwrap();
2013 let b = a.test_as_monster().unwrap();
2014
2015 // preconditions
2016 assert_eq!(a.name(), "MyMonster");
2017 assert_eq!(b.name(), "Fred");
2018
2019 assert_eq!(a.key_compare_less_than(&a), false);
2020 assert_eq!(a.key_compare_less_than(&b), false);
2021
2022 assert_eq!(b.key_compare_less_than(&a), true);
2023 assert_eq!(b.key_compare_less_than(&b), false);
2024 }
2025 }
2026
2027 #[cfg(test)]
2028 mod included_schema_generated_code {
2029 extern crate flatbuffers;
2030
2031 //extern crate rust_usage_test;
2032
2033 // TODO(rw): make generated sub-namespace files importable
2034 //#[test]
2035 //fn namespace_test_mod_is_importable() {
2036 // use rust_usage_test::namespace_test;
2037 //}
2038 //#[test]
2039 //fn namespace_test1_mod_is_importable() {
2040 // use rust_usage_test::namespace_test::namespace_test1_generated;
2041 //}
2042 //#[test]
2043 //fn namespace_test2_mod_is_importable() {
2044 // use rust_usage_test::namespace_test::namespace_test2_generated;
2045 //}
2046 }
2047
2048 #[cfg(test)]
2049 mod builder_asserts {
2050 extern crate flatbuffers;
2051
2052 #[test]
2053 #[should_panic]
end_table_should_panic_when_not_in_table()2054 fn end_table_should_panic_when_not_in_table() {
2055 let mut b = flatbuffers::FlatBufferBuilder::new();
2056 b.end_table(flatbuffers::WIPOffset::new(0));
2057 }
2058
2059 #[test]
2060 #[should_panic]
create_string_should_panic_when_in_table()2061 fn create_string_should_panic_when_in_table() {
2062 let mut b = flatbuffers::FlatBufferBuilder::new();
2063 b.start_table();
2064 b.create_string("foo");
2065 }
2066
2067 #[test]
2068 #[should_panic]
create_byte_string_should_panic_when_in_table()2069 fn create_byte_string_should_panic_when_in_table() {
2070 let mut b = flatbuffers::FlatBufferBuilder::new();
2071 b.start_table();
2072 b.create_byte_string(b"foo");
2073 }
2074
2075 #[test]
2076 #[should_panic]
push_struct_slot_should_panic_when_not_in_table()2077 fn push_struct_slot_should_panic_when_not_in_table() {
2078 #[derive(Copy, Clone, Debug, PartialEq)]
2079 #[repr(C, packed)]
2080 struct foo { }
2081 impl<'b> flatbuffers::Push for &'b foo {
2082 type Output = foo;
2083 fn push<'a>(&'a self, _dst: &'a mut [u8], _rest: &'a [u8]) { }
2084 }
2085 let mut b = flatbuffers::FlatBufferBuilder::new();
2086 b.push_slot_always(0, &foo{});
2087 }
2088
2089 #[test]
2090 #[should_panic]
finished_bytes_should_panic_when_table_is_not_finished()2091 fn finished_bytes_should_panic_when_table_is_not_finished() {
2092 let mut b = flatbuffers::FlatBufferBuilder::new();
2093 b.start_table();
2094 b.finished_data();
2095 }
2096
2097 #[test]
2098 #[should_panic]
required_panics_when_field_not_set()2099 fn required_panics_when_field_not_set() {
2100 let mut b = flatbuffers::FlatBufferBuilder::new();
2101 let start = b.start_table();
2102 let o = b.end_table(start);
2103 b.required(o, 4 /* byte offset to first field */, "test field");
2104 }
2105 }
2106
2107 #[cfg(test)]
2108 mod follow_impls {
2109 extern crate flatbuffers;
2110 use flatbuffers::Follow;
2111 use flatbuffers::field_index_to_field_offset as fi2fo;
2112
2113 // Define a test struct to use in a few tests. This replicates the work that the code generator
2114 // would normally do when defining a FlatBuffer struct. For reference, compare the following
2115 // `FooStruct` code with the code generated for the `Vec3` struct in
2116 // `../../monster_test_generated.rs`.
2117 use flatbuffers::EndianScalar;
2118 #[derive(Copy, Clone, Debug, PartialEq)]
2119 #[repr(C, packed)]
2120 struct FooStruct {
2121 a: i8,
2122 b: u8,
2123 c: i16,
2124 }
2125 impl FooStruct {
new(_a: i8, _b: u8, _c: i16) -> Self2126 fn new(_a: i8, _b: u8, _c: i16) -> Self {
2127 FooStruct {
2128 a: _a.to_little_endian(),
2129 b: _b.to_little_endian(),
2130 c: _c.to_little_endian(),
2131 }
2132 }
2133 }
2134 impl flatbuffers::SafeSliceAccess for FooStruct {}
2135 impl<'a> flatbuffers::Follow<'a> for FooStruct {
2136 type Inner = &'a FooStruct;
2137 #[inline(always)]
follow(buf: &'a [u8], loc: usize) -> Self::Inner2138 fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
2139 <&'a FooStruct>::follow(buf, loc)
2140 }
2141 }
2142 impl<'a> flatbuffers::Follow<'a> for &'a FooStruct {
2143 type Inner = &'a FooStruct;
2144 #[inline(always)]
follow(buf: &'a [u8], loc: usize) -> Self::Inner2145 fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
2146 flatbuffers::follow_cast_ref::<FooStruct>(buf, loc)
2147 }
2148 }
2149
2150 #[test]
to_u8()2151 fn to_u8() {
2152 let vec: Vec<u8> = vec![255, 3];
2153 let fs: flatbuffers::FollowStart<u8> = flatbuffers::FollowStart::new();
2154 assert_eq!(fs.self_follow(&vec[..], 1), 3);
2155 }
2156
2157 #[test]
to_u16()2158 fn to_u16() {
2159 let vec: Vec<u8> = vec![255, 255, 3, 4];
2160 let fs: flatbuffers::FollowStart<u16> = flatbuffers::FollowStart::new();
2161 assert_eq!(fs.self_follow(&vec[..], 2), 1027);
2162 }
2163
2164 #[test]
to_f32()2165 fn to_f32() {
2166 let vec: Vec<u8> = vec![255, 255, 255, 255, /* start of value */ 208, 15, 73, 64];
2167 let fs: flatbuffers::FollowStart<f32> = flatbuffers::FollowStart::new();
2168 assert_eq!(fs.self_follow(&vec[..], 4), 3.14159);
2169 }
2170
2171 #[test]
to_string()2172 fn to_string() {
2173 let vec: Vec<u8> = vec![255,255,255,255, 3, 0, 0, 0, 'f' as u8, 'o' as u8, 'o' as u8, 0];
2174 let off: flatbuffers::FollowStart<&str> = flatbuffers::FollowStart::new();
2175 assert_eq!(off.self_follow(&vec[..], 4), "foo");
2176 }
2177
2178 #[test]
to_byte_slice()2179 fn to_byte_slice() {
2180 let vec: Vec<u8> = vec![255, 255, 255, 255, 4, 0, 0, 0, 1, 2, 3, 4];
2181 let off: flatbuffers::FollowStart<flatbuffers::Vector<u8>> = flatbuffers::FollowStart::new();
2182 assert_eq!(off.self_follow(&vec[..], 4).safe_slice(), &[1, 2, 3, 4][..]);
2183 }
2184
2185 #[test]
to_byte_vector()2186 fn to_byte_vector() {
2187 let vec: Vec<u8> = vec![255, 255, 255, 255, 4, 0, 0, 0, 1, 2, 3, 4];
2188 let off: flatbuffers::FollowStart<flatbuffers::Vector<u8>> = flatbuffers::FollowStart::new();
2189 assert_eq!(off.self_follow(&vec[..], 4).safe_slice(), &[1, 2, 3, 4][..]);
2190 }
2191
2192 #[test]
to_byte_string_zero_teriminated()2193 fn to_byte_string_zero_teriminated() {
2194 let vec: Vec<u8> = vec![255, 255, 255, 255, 3, 0, 0, 0, 1, 2, 3, 0];
2195 let off: flatbuffers::FollowStart<flatbuffers::Vector<u8>> = flatbuffers::FollowStart::new();
2196 assert_eq!(off.self_follow(&vec[..], 4).safe_slice(), &[1, 2, 3][..]);
2197 }
2198
2199 #[test]
to_vector_of_u16()2200 fn to_vector_of_u16() {
2201 let vec: Vec<u8> = vec![255, 255, 255, 255, 2, 0, 0, 0, 1, 2, 3, 4];
2202 let off: flatbuffers::FollowStart<flatbuffers::Vector<u16>> = flatbuffers::FollowStart::new();
2203 assert_eq!(off.self_follow(&vec[..], 4).len(), 2);
2204 assert_eq!(off.self_follow(&vec[..], 4).get(0), 513);
2205 assert_eq!(off.self_follow(&vec[..], 4).get(1), 1027);
2206 }
2207
2208 #[test]
to_struct()2209 fn to_struct() {
2210 let vec: Vec<u8> = vec![255, 255, 255, 255, 1, 2, 3, 4];
2211 let off: flatbuffers::FollowStart<&FooStruct> = flatbuffers::FollowStart::new();
2212 assert_eq!(*off.self_follow(&vec[..], 4), FooStruct::new(1, 2, 1027));
2213 }
2214
2215 #[test]
to_vector_of_offset_to_string_elements()2216 fn to_vector_of_offset_to_string_elements() {
2217 let buf: Vec<u8> = vec![/* vec len */ 1, 0, 0, 0, /* offset to string */ 4, 0, 0, 0, /* str length */ 3, 0, 0, 0, 'f' as u8, 'o' as u8, 'o' as u8, 0];
2218 let s: flatbuffers::FollowStart<flatbuffers::Vector<flatbuffers::ForwardsUOffset<&str>>> = flatbuffers::FollowStart::new();
2219 assert_eq!(s.self_follow(&buf[..], 0).len(), 1);
2220 assert_eq!(s.self_follow(&buf[..], 0).get(0), "foo");
2221 }
2222
2223 #[test]
to_slice_of_struct_elements()2224 fn to_slice_of_struct_elements() {
2225 let buf: Vec<u8> = vec![1, 0, 0, 0, /* struct data */ 1, 2, 3, 4];
2226 let fs: flatbuffers::FollowStart<flatbuffers::Vector<FooStruct>> = flatbuffers::FollowStart::new();
2227 assert_eq!(fs.self_follow(&buf[..], 0).safe_slice(), &vec![FooStruct::new(1, 2, 1027)][..]);
2228 }
2229
2230 #[test]
to_vector_of_struct_elements()2231 fn to_vector_of_struct_elements() {
2232 let buf: Vec<u8> = vec![1, 0, 0, 0, /* struct data */ 1, 2, 3, 4];
2233 let fs: flatbuffers::FollowStart<flatbuffers::Vector<FooStruct>> = flatbuffers::FollowStart::new();
2234 assert_eq!(fs.self_follow(&buf[..], 0).len(), 1);
2235 assert_eq!(fs.self_follow(&buf[..], 0).get(0), &FooStruct::new(1, 2, 1027));
2236 }
2237
2238 #[test]
to_root_to_empty_table()2239 fn to_root_to_empty_table() {
2240 let buf: Vec<u8> = vec![
2241 12, 0, 0, 0, // offset to root table
2242 // enter vtable
2243 4, 0, // vtable len
2244 0, 0, // inline size
2245 255, 255, 255, 255, // canary
2246 // enter table
2247 8, 0, 0, 0, // vtable location
2248 ];
2249 let fs: flatbuffers::FollowStart<flatbuffers::ForwardsUOffset<flatbuffers::Table>> = flatbuffers::FollowStart::new();
2250 assert_eq!(fs.self_follow(&buf[..], 0), flatbuffers::Table::new(&buf[..], 12));
2251 }
2252
2253 #[test]
to_root_table_get_slot_scalar_u8()2254 fn to_root_table_get_slot_scalar_u8() {
2255 let buf: Vec<u8> = vec![
2256 14, 0, 0, 0, // offset to root table
2257 // enter vtable
2258 6, 0, // vtable len
2259 2, 0, // inline size
2260 5, 0, // value loc
2261 255, 255, 255, 255, // canary
2262 // enter table
2263 10, 0, 0, 0, // vtable location
2264 0, 99 // value (with padding)
2265 ];
2266 let fs: flatbuffers::FollowStart<flatbuffers::ForwardsUOffset<flatbuffers::Table>> = flatbuffers::FollowStart::new();
2267 let tab = fs.self_follow(&buf[..], 0);
2268 assert_eq!(tab.get::<u8>(fi2fo(0), Some(123)), Some(99));
2269 }
2270
2271 #[test]
to_root_to_table_get_slot_scalar_u8_default_via_vtable_len()2272 fn to_root_to_table_get_slot_scalar_u8_default_via_vtable_len() {
2273 let buf: Vec<u8> = vec![
2274 12, 0, 0, 0, // offset to root table
2275 // enter vtable
2276 4, 0, // vtable len
2277 2, 0, // inline size
2278 255, 255, 255, 255, // canary
2279 // enter table
2280 8, 0, 0, 0, // vtable location
2281 ];
2282 let fs: flatbuffers::FollowStart<flatbuffers::ForwardsUOffset<flatbuffers::Table>> = flatbuffers::FollowStart::new();
2283 let tab = fs.self_follow(&buf[..], 0);
2284 assert_eq!(tab.get::<u8>(fi2fo(0), Some(123)), Some(123));
2285 }
2286
2287 #[test]
to_root_to_table_get_slot_scalar_u8_default_via_vtable_zero()2288 fn to_root_to_table_get_slot_scalar_u8_default_via_vtable_zero() {
2289 let buf: Vec<u8> = vec![
2290 14, 0, 0, 0, // offset to root table
2291 // enter vtable
2292 6, 0, // vtable len
2293 2, 0, // inline size
2294 0, 0, // zero means use the default value
2295 255, 255, 255, 255, // canary
2296 // enter table
2297 10, 0, 0, 0, // vtable location
2298 ];
2299 let fs: flatbuffers::FollowStart<flatbuffers::ForwardsUOffset<flatbuffers::Table>> = flatbuffers::FollowStart::new();
2300 let tab = fs.self_follow(&buf[..], 0);
2301 assert_eq!(tab.get::<u8>(fi2fo(0), Some(123)), Some(123));
2302 }
2303
2304 #[test]
to_root_to_table_get_slot_string_multiple_types()2305 fn to_root_to_table_get_slot_string_multiple_types() {
2306 let buf: Vec<u8> = vec![
2307 14, 0, 0, 0, // offset to root table
2308 // enter vtable
2309 6, 0, // vtable len
2310 2, 0, // inline size
2311 4, 0, // value loc
2312 255, 255, 255, 255, // canary
2313 // enter table
2314 10, 0, 0, 0, // vtable location
2315 8, 0, 0, 0, // offset to string
2316 // leave table
2317 255, 255, 255, 255, // canary
2318 // enter string
2319 3, 0, 0, 0, 109, 111, 111, 0 // string length and contents
2320 ];
2321 let tab = <flatbuffers::ForwardsUOffset<flatbuffers::Table>>::follow(&buf[..], 0);
2322 assert_eq!(tab.get::<flatbuffers::ForwardsUOffset<&str>>(fi2fo(0), None), Some("moo"));
2323 let byte_vec = tab.get::<flatbuffers::ForwardsUOffset<flatbuffers::Vector<u8>>>(fi2fo(0), None).unwrap().safe_slice();
2324 assert_eq!(byte_vec, &vec![109, 111, 111][..]);
2325 let v = tab.get::<flatbuffers::ForwardsUOffset<flatbuffers::Vector<u8>>>(fi2fo(0), None).unwrap();
2326 assert_eq!(v.len(), 3);
2327 assert_eq!(v.get(0), 109);
2328 assert_eq!(v.get(1), 111);
2329 assert_eq!(v.get(2), 111);
2330 }
2331
2332 #[test]
to_root_to_table_get_slot_string_multiple_types_default_via_vtable_len()2333 fn to_root_to_table_get_slot_string_multiple_types_default_via_vtable_len() {
2334 let buf: Vec<u8> = vec![
2335 12, 0, 0, 0, // offset to root table
2336 // enter vtable
2337 4, 0, // vtable len
2338 4, 0, // table inline len
2339 255, 255, 255, 255, // canary
2340 // enter table
2341 8, 0, 0, 0, // vtable location
2342 ];
2343 let tab = <flatbuffers::ForwardsUOffset<flatbuffers::Table>>::follow(&buf[..], 0);
2344 assert_eq!(tab.get::<flatbuffers::ForwardsUOffset<&str>>(fi2fo(0), Some("abc")), Some("abc"));
2345 #[cfg(target_endian = "little")]
2346 {
2347 assert_eq!(tab.get::<flatbuffers::ForwardsUOffset<&[u8]>>(fi2fo(0), Some(&vec![70, 71, 72][..])), Some(&vec![70, 71, 72][..]));
2348 }
2349
2350 let default_vec_buf: Vec<u8> = vec![3, 0, 0, 0, 70, 71, 72, 0];
2351 let default_vec = flatbuffers::Vector::new(&default_vec_buf[..], 0);
2352 let v = tab.get::<flatbuffers::ForwardsUOffset<flatbuffers::Vector<u8>>>(fi2fo(0), Some(default_vec)).unwrap();
2353 assert_eq!(v.len(), 3);
2354 assert_eq!(v.get(0), 70);
2355 assert_eq!(v.get(1), 71);
2356 assert_eq!(v.get(2), 72);
2357 }
2358
2359 #[test]
to_root_to_table_get_slot_string_multiple_types_default_via_vtable_zero()2360 fn to_root_to_table_get_slot_string_multiple_types_default_via_vtable_zero() {
2361 let buf: Vec<u8> = vec![
2362 14, 0, 0, 0, // offset to root table
2363 // enter vtable
2364 6, 0, // vtable len
2365 2, 0, // inline size
2366 0, 0, // value loc
2367 255, 255, 255, 255, // canary
2368 // enter table
2369 10, 0, 0, 0, // vtable location
2370 ];
2371 let tab = <flatbuffers::ForwardsUOffset<flatbuffers::Table>>::follow(&buf[..], 0);
2372 assert_eq!(tab.get::<flatbuffers::ForwardsUOffset<&str>>(fi2fo(0), Some("abc")), Some("abc"));
2373 #[cfg(target_endian = "little")]
2374 {
2375 assert_eq!(tab.get::<flatbuffers::ForwardsUOffset<&[u8]>>(fi2fo(0), Some(&vec![70, 71, 72][..])), Some(&vec![70, 71, 72][..]));
2376 }
2377
2378 let default_vec_buf: Vec<u8> = vec![3, 0, 0, 0, 70, 71, 72, 0];
2379 let default_vec = flatbuffers::Vector::new(&default_vec_buf[..], 0);
2380 let v = tab.get::<flatbuffers::ForwardsUOffset<flatbuffers::Vector<u8>>>(fi2fo(0), Some(default_vec)).unwrap();
2381 assert_eq!(v.len(), 3);
2382 assert_eq!(v.get(0), 70);
2383 assert_eq!(v.get(1), 71);
2384 assert_eq!(v.get(2), 72);
2385 }
2386 }
2387
2388 #[cfg(test)]
2389 mod push_impls {
2390 extern crate flatbuffers;
2391
2392 use super::my_game;
2393
check<'a>(b: &'a flatbuffers::FlatBufferBuilder, want: &'a [u8])2394 fn check<'a>(b: &'a flatbuffers::FlatBufferBuilder, want: &'a [u8]) {
2395 let got = b.unfinished_data();
2396 assert_eq!(want, got);
2397 }
2398
2399 #[test]
push_u8()2400 fn push_u8() {
2401 let mut b = flatbuffers::FlatBufferBuilder::new();
2402 b.push(123u8);
2403 check(&b, &[123]);
2404 }
2405
2406 #[test]
push_u64()2407 fn push_u64() {
2408 let mut b = flatbuffers::FlatBufferBuilder::new();
2409 b.push(0x12345678);
2410 check(&b, &[0x78, 0x56, 0x34, 0x12]);
2411 }
2412
2413 #[test]
push_f64()2414 fn push_f64() {
2415 let mut b = flatbuffers::FlatBufferBuilder::new();
2416 b.push(3.14159265359f64);
2417 check(&b, &[234, 46, 68, 84, 251, 33, 9, 64]);
2418 }
2419
2420 #[test]
push_generated_struct()2421 fn push_generated_struct() {
2422 let mut b = flatbuffers::FlatBufferBuilder::new();
2423 b.push(my_game::example::Test::new(10, 20));
2424 check(&b, &[10, 0, 20, 0]);
2425 }
2426
2427 #[test]
push_u8_vector_with_offset_with_alignment()2428 fn push_u8_vector_with_offset_with_alignment() {
2429 let mut b = flatbuffers::FlatBufferBuilder::new();
2430 let off = b.create_vector(&[1u8, 2, 3, 4, 5, 6, 7, 8, 9][..]);
2431 b.push(off);
2432 check(&b, &[/* loc */ 4, 0, 0, 0, /* len */ 9, 0, 0, 0, /* val */ 1, 2, 3, 4, 5, 6, 7, 8, 9, /* padding */ 0, 0, 0]);
2433 }
2434
2435 #[test]
push_u8_u16_alignment()2436 fn push_u8_u16_alignment() {
2437 let mut b = flatbuffers::FlatBufferBuilder::new();
2438 b.push(1u8);
2439 b.push(2u16);
2440 check(&b, &[2, 0, 0, 1]);
2441 }
2442
2443 #[test]
push_u8_u32_alignment()2444 fn push_u8_u32_alignment() {
2445 let mut b = flatbuffers::FlatBufferBuilder::new();
2446 b.push(1u8);
2447 b.push(2u32);
2448 check(&b, &[2, 0, 0, 0, 0, 0, 0, 1]);
2449 }
2450
2451 #[test]
push_u8_u64_alignment()2452 fn push_u8_u64_alignment() {
2453 let mut b = flatbuffers::FlatBufferBuilder::new();
2454 b.push(1u8);
2455 b.push(2u64);
2456 check(&b, &[2, 0, 0, 0,
2457 0, 0, 0, 0,
2458 0, 0, 0, 0,
2459 0, 0, 0, 1]);
2460 }
2461 }
2462
2463 #[cfg(test)]
2464 mod vtable_deduplication {
2465 extern crate flatbuffers;
2466 use flatbuffers::field_index_to_field_offset as fi2fo;
2467
check<'a>(b: &'a flatbuffers::FlatBufferBuilder, want: &'a [u8])2468 fn check<'a>(b: &'a flatbuffers::FlatBufferBuilder, want: &'a [u8]) {
2469 let got = b.unfinished_data();
2470 assert_eq!(want, got);
2471 }
2472
2473 #[test]
one_empty_table()2474 fn one_empty_table() {
2475 let mut b = flatbuffers::FlatBufferBuilder::new();
2476 let start0 = b.start_table();
2477 b.end_table(start0);
2478 check(&b, &[
2479 4, 0, // vtable size in bytes
2480 4, 0, // object inline data in bytes
2481
2482 4, 0, 0, 0, // backwards offset to vtable
2483 ]);
2484 }
2485
2486 #[test]
two_empty_tables_are_deduplicated()2487 fn two_empty_tables_are_deduplicated() {
2488 let mut b = flatbuffers::FlatBufferBuilder::new();
2489 let start0 = b.start_table();
2490 b.end_table(start0);
2491 let start1 = b.start_table();
2492 b.end_table(start1);
2493 check(&b, &[
2494 252, 255, 255, 255, // forwards offset to vtable
2495
2496 4, 0, // vtable size in bytes
2497 4, 0, // object inline data in bytes
2498
2499 4, 0, 0, 0, // backwards offset to vtable
2500 ]);
2501 }
2502
2503 #[test]
two_tables_with_two_conveniently_sized_inline_elements_are_deduplicated()2504 fn two_tables_with_two_conveniently_sized_inline_elements_are_deduplicated() {
2505 let mut b = flatbuffers::FlatBufferBuilder::new();
2506 let start0 = b.start_table();
2507 b.push_slot::<u64>(fi2fo(0), 100, 0);
2508 b.push_slot::<u32>(fi2fo(1), 101, 0);
2509 b.end_table(start0);
2510 let start1 = b.start_table();
2511 b.push_slot::<u64>(fi2fo(0), 200, 0);
2512 b.push_slot::<u32>(fi2fo(1), 201, 0);
2513 b.end_table(start1);
2514 check(&b, &[
2515 240, 255, 255, 255, // forwards offset to vtable
2516
2517 201, 0, 0, 0, // value #1
2518 200, 0, 0, 0, 0, 0, 0, 0, // value #0
2519
2520 8, 0, // vtable size in bytes
2521 16, 0, // object inline data in bytes
2522 8, 0, // offset in object for value #0
2523 4, 0, // offset in object for value #1
2524
2525 8, 0, 0, 0, // backwards offset to vtable
2526 101, 0, 0, 0, // value #1
2527 100, 0, 0, 0, 0, 0, 0, 0 // value #0
2528 ]);
2529 }
2530
2531 #[cfg(not(miri))] // slow.
2532 #[test]
many_identical_tables_use_few_vtables()2533 fn many_identical_tables_use_few_vtables() {
2534 let mut b = flatbuffers::FlatBufferBuilder::new();
2535 for _ in 0..1000 {
2536 let start = b.start_table();
2537 b.push_slot::<u8>(fi2fo(0), 100, 0);
2538 b.push_slot::<u32>(fi2fo(1), 101, 0);
2539 b.end_table(start);
2540 }
2541 assert!(b.num_written_vtables() <= 10);
2542 }
2543 }
2544
2545 #[cfg(test)]
2546 mod byte_layouts {
2547 extern crate flatbuffers;
2548 use flatbuffers::field_index_to_field_offset as fi2fo;
2549
check<'a>(b: &'a flatbuffers::FlatBufferBuilder, want: &'a [u8])2550 fn check<'a>(b: &'a flatbuffers::FlatBufferBuilder, want: &'a [u8]) {
2551 let got = b.unfinished_data();
2552 assert_eq!(want, got);
2553 }
2554
2555 #[test]
layout_01_basic_numbers()2556 fn layout_01_basic_numbers() {
2557 let mut b = flatbuffers::FlatBufferBuilder::new();
2558 b.push(true);
2559 check(&b, &[1]);
2560 b.push(-127i8);
2561 check(&b, &[129, 1]);
2562 b.push(255u8);
2563 check(&b, &[255, 129, 1]);
2564 b.push(-32222i16);
2565 check(&b, &[0x22, 0x82, 0, 255, 129, 1]); // first pad
2566 b.push(0xFEEEu16);
2567 check(&b, &[0xEE, 0xFE, 0x22, 0x82, 0, 255, 129, 1]); // no pad this time
2568 b.push(-53687092i32);
2569 check(&b, &[204, 204, 204, 252, 0xEE, 0xFE, 0x22, 0x82, 0, 255, 129, 1]);
2570 b.push(0x98765432u32);
2571 check(&b, &[0x32, 0x54, 0x76, 0x98, 204, 204, 204, 252, 0xEE, 0xFE, 0x22, 0x82, 0, 255, 129, 1]);
2572 }
2573
2574 #[test]
layout_01b_bigger_numbers()2575 fn layout_01b_bigger_numbers() {
2576 let mut b = flatbuffers::FlatBufferBuilder::new();
2577 b.push(0x1122334455667788u64);
2578 check(&b, &[0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11]);
2579 }
2580
2581 #[test]
layout_02_1xbyte_vector()2582 fn layout_02_1xbyte_vector() {
2583 let mut b = flatbuffers::FlatBufferBuilder::new();
2584 check(&b, &[]);
2585 b.start_vector::<u8>(1);
2586 check(&b, &[0, 0, 0]); // align to 4bytes
2587 b.push(1u8);
2588 check(&b, &[1, 0, 0, 0]);
2589 b.end_vector::<u8>(1);
2590 check(&b, &[1, 0, 0, 0, 1, 0, 0, 0]); // padding
2591 }
2592
2593 #[test]
layout_03_2xbyte_vector()2594 fn layout_03_2xbyte_vector() {
2595 let mut b = flatbuffers::FlatBufferBuilder::new();
2596 b.start_vector::<u8>(2);
2597 check(&b, &[0, 0]); // align to 4bytes
2598 b.push(1u8);
2599 check(&b, &[1, 0, 0]);
2600 b.push(2u8);
2601 check(&b, &[2, 1, 0, 0]);
2602 b.end_vector::<u8>(2);
2603 check(&b, &[2, 0, 0, 0, 2, 1, 0, 0]); // padding
2604 }
2605
2606 #[test]
layout_03b_11xbyte_vector_matches_builder_size()2607 fn layout_03b_11xbyte_vector_matches_builder_size() {
2608 let mut b = flatbuffers::FlatBufferBuilder::new_with_capacity(12);
2609 b.start_vector::<u8>(8);
2610
2611 let mut gold = vec![0u8; 0];
2612 check(&b, &gold[..]);
2613
2614 for i in 1u8..=8 {
2615 b.push(i);
2616 gold.insert(0, i);
2617 check(&b, &gold[..]);
2618 }
2619 b.end_vector::<u8>(8);
2620 let want = vec![8u8, 0, 0, 0, 8, 7, 6, 5, 4, 3, 2, 1];
2621 check(&b, &want[..]);
2622 }
2623 #[test]
layout_04_1xuint16_vector()2624 fn layout_04_1xuint16_vector() {
2625 let mut b = flatbuffers::FlatBufferBuilder::new();
2626 b.start_vector::<u16>(1);
2627 check(&b, &[0, 0]); // align to 4bytes
2628 b.push(1u16);
2629 check(&b, &[1, 0, 0, 0]);
2630 b.end_vector::<u16>(1);
2631 check(&b, &[1, 0, 0, 0, 1, 0, 0, 0]); // padding
2632 }
2633
2634 #[test]
layout_05_2xuint16_vector()2635 fn layout_05_2xuint16_vector() {
2636 let mut b = flatbuffers::FlatBufferBuilder::new();
2637 let _off = b.start_vector::<u16>(2);
2638 check(&b, &[]); // align to 4bytes
2639 b.push(0xABCDu16);
2640 check(&b, &[0xCD, 0xAB]);
2641 b.push(0xDCBAu16);
2642 check(&b, &[0xBA, 0xDC, 0xCD, 0xAB]);
2643 b.end_vector::<u16>(2);
2644 check(&b, &[2, 0, 0, 0, 0xBA, 0xDC, 0xCD, 0xAB]);
2645 }
2646
2647 #[test]
layout_06_create_string()2648 fn layout_06_create_string() {
2649 let mut b = flatbuffers::FlatBufferBuilder::new();
2650 let off0 = b.create_string("foo");
2651 assert_eq!(8, off0.value());
2652 check(&b, b"\x03\x00\x00\x00foo\x00"); // 0-terminated, no pad
2653 let off1 = b.create_string("moop");
2654 assert_eq!(20, off1.value());
2655 check(&b, b"\x04\x00\x00\x00moop\x00\x00\x00\x00\
2656 \x03\x00\x00\x00foo\x00"); // 0-terminated, 3-byte pad
2657 }
2658
2659 #[test]
layout_06b_create_string_unicode()2660 fn layout_06b_create_string_unicode() {
2661 let mut b = flatbuffers::FlatBufferBuilder::new();
2662 // These characters are chinese from blog.golang.org/strings
2663 // We use escape codes here so that editors without unicode support
2664 // aren't bothered:
2665 let uni_str = "\u{65e5}\u{672c}\u{8a9e}";
2666 let off0 = b.create_string(uni_str);
2667 assert_eq!(16, off0.value());
2668 check(&b, &[9, 0, 0, 0, 230, 151, 165, 230, 156, 172, 232, 170, 158, 0, // null-terminated, 2-byte pad
2669 0, 0]);
2670 }
2671
2672 #[test]
layout_06c_create_byte_string()2673 fn layout_06c_create_byte_string() {
2674 let mut b = flatbuffers::FlatBufferBuilder::new();
2675 let off0 = b.create_byte_string(b"foo");
2676 assert_eq!(8, off0.value());
2677 check(&b, b"\x03\x00\x00\x00foo\x00"); // 0-terminated, no pad
2678 let off1 = b.create_byte_string(b"moop");
2679 assert_eq!(20, off1.value());
2680 check(&b, b"\x04\x00\x00\x00moop\x00\x00\x00\x00\
2681 \x03\x00\x00\x00foo\x00"); // 0-terminated, 3-byte pad
2682 }
2683
2684 #[test]
layout_07_empty_vtable()2685 fn layout_07_empty_vtable() {
2686 let mut b = flatbuffers::FlatBufferBuilder::new();
2687 let off0 = b.start_table();
2688 check(&b, &[]);
2689 b.end_table(off0);
2690 check(&b, &[4, 0, // vtable length
2691 4, 0, // length of table including vtable offset
2692 4, 0, 0, 0]); // offset for start of vtable
2693 }
2694
2695 #[test]
layout_08_vtable_with_one_true_bool()2696 fn layout_08_vtable_with_one_true_bool() {
2697 let mut b = flatbuffers::FlatBufferBuilder::new();
2698 check(&b, &[]);
2699 let off0 = b.start_table();
2700 assert_eq!(0, off0.value());
2701 check(&b, &[]);
2702 b.push_slot(fi2fo(0), true, false);
2703 check(&b, &[1]);
2704 let off1 = b.end_table(off0);
2705 assert_eq!(8, off1.value());
2706 check(&b, &[
2707 6, 0, // vtable bytes
2708 8, 0, // length of object including vtable offset
2709 7, 0, // start of bool value
2710 6, 0, 0, 0, // offset for start of vtable (int32)
2711 0, 0, 0, // padded to 4 bytes
2712 1, // bool value
2713 ]);
2714 }
2715
2716 #[test]
layout_09_vtable_with_one_default_bool()2717 fn layout_09_vtable_with_one_default_bool() {
2718 let mut b = flatbuffers::FlatBufferBuilder::new();
2719 check(&b, &[]);
2720 let off = b.start_table();
2721 check(&b, &[]);
2722 b.push_slot(fi2fo(0), false, false);
2723 b.end_table(off);
2724 check(&b, &[
2725 4, 0, // vtable bytes
2726 4, 0, // end of object from here
2727 // entry 1 is zero and not stored.
2728 4, 0, 0, 0, // offset for start of vtable (int32)
2729 ]);
2730 }
2731
2732 #[test]
layout_09b_vtable_with_one_default_bool_force_defaults()2733 fn layout_09b_vtable_with_one_default_bool_force_defaults() {
2734 let mut b = flatbuffers::FlatBufferBuilder::new();
2735 check(&b, &[]);
2736 let off = b.start_table();
2737 check(&b, &[]);
2738 b.force_defaults(true);
2739 b.push_slot(fi2fo(0), false, false);
2740 b.end_table(off);
2741 check(&b, &[
2742 6, 0, // vtable bytes
2743 8, 0, // length of object including vtable offset
2744 7, 0, // start of bool value
2745 6, 0, 0, 0, // offset for start of vtable (int32)
2746 0, 0, 0, // padded to 4 bytes
2747 0, // bool value
2748 ]);
2749 }
2750
2751 #[test]
layout_10_vtable_with_one_int16()2752 fn layout_10_vtable_with_one_int16() {
2753 let mut b = flatbuffers::FlatBufferBuilder::new();
2754 check(&b, &[]);
2755 let off = b.start_table();
2756 b.push_slot(fi2fo(0), 0x789Ai16, 0);
2757 b.end_table(off);
2758 check(&b, &[
2759 6, 0, // vtable bytes
2760 8, 0, // end of object from here
2761 6, 0, // offset to value
2762 6, 0, 0, 0, // offset for start of vtable (int32)
2763 0, 0, // padding to 4 bytes
2764 0x9A, 0x78,
2765 ]);
2766 }
2767
2768 #[test]
layout_11_vtable_with_two_int16()2769 fn layout_11_vtable_with_two_int16() {
2770 let mut b = flatbuffers::FlatBufferBuilder::new();
2771 let off = b.start_table();
2772 b.push_slot(fi2fo(0), 0x3456i16, 0);
2773 b.push_slot(fi2fo(1), 0x789Ai16, 0);
2774 b.end_table(off);
2775 check(&b, &[
2776 8, 0, // vtable bytes
2777 8, 0, // end of object from here
2778 6, 0, // offset to value 0
2779 4, 0, // offset to value 1
2780 8, 0, 0, 0, // offset for start of vtable (int32)
2781 0x9A, 0x78, // value 1
2782 0x56, 0x34, // value 0
2783 ]);
2784 }
2785
2786 #[test]
layout_12_vtable_with_int16_and_bool()2787 fn layout_12_vtable_with_int16_and_bool() {
2788 let mut b = flatbuffers::FlatBufferBuilder::new();
2789 let off = b.start_table();
2790 b.push_slot(fi2fo(0), 0x3456i16, 0);
2791 b.push_slot(fi2fo(1), true, false);
2792 b.end_table(off);
2793 check(&b, &[
2794 8, 0, // vtable bytes
2795 8, 0, // end of object from here
2796 6, 0, // offset to value 0
2797 5, 0, // offset to value 1
2798 8, 0, 0, 0, // offset for start of vtable (int32)
2799 0, // padding
2800 1, // value 1
2801 0x56, 0x34, // value 0
2802 ]);
2803 }
2804
2805 #[test]
layout_12b_vtable_with_empty_vector()2806 fn layout_12b_vtable_with_empty_vector() {
2807 let mut b = flatbuffers::FlatBufferBuilder::new();
2808 b.start_vector::<u8>(0);
2809 let vecend = b.end_vector::<u8>(0);
2810 let off = b.start_table();
2811 b.push_slot_always(fi2fo(0), vecend);
2812 b.end_table(off);
2813 check(&b, &[
2814 6, 0, // vtable bytes
2815 8, 0,
2816 4, 0, // offset to vector offset
2817 6, 0, 0, 0, // offset for start of vtable (int32)
2818 4, 0, 0, 0,
2819 0, 0, 0, 0, // length of vector (not in struct)
2820 ]);
2821 }
2822
2823 #[test]
layout_12c_vtable_with_empty_vector_of_byte_and_some_scalars()2824 fn layout_12c_vtable_with_empty_vector_of_byte_and_some_scalars() {
2825 let mut b = flatbuffers::FlatBufferBuilder::new();
2826 b.start_vector::<u8>(0);
2827 let vecend = b.end_vector::<u8>(0);
2828 let off = b.start_table();
2829 b.push_slot::<i16>(fi2fo(0), 55i16, 0);
2830 b.push_slot_always::<flatbuffers::WIPOffset<_>>(fi2fo(1), vecend);
2831 b.end_table(off);
2832 check(&b, &[
2833 8, 0, // vtable bytes
2834 12, 0,
2835 10, 0, // offset to value 0
2836 4, 0, // offset to vector offset
2837 8, 0, 0, 0, // vtable loc
2838 8, 0, 0, 0, // value 1
2839 0, 0, 55, 0, // value 0
2840
2841 0, 0, 0, 0, // length of vector (not in struct)
2842 ]);
2843 }
2844 #[test]
layout_13_vtable_with_1_int16_and_2_vector_of_i16()2845 fn layout_13_vtable_with_1_int16_and_2_vector_of_i16() {
2846 let mut b = flatbuffers::FlatBufferBuilder::new();
2847 b.start_vector::<i16>(2);
2848 b.push(0x1234i16);
2849 b.push(0x5678i16);
2850 let vecend = b.end_vector::<i16>(2);
2851 let off = b.start_table();
2852 b.push_slot_always(fi2fo(1), vecend);
2853 b.push_slot(fi2fo(0), 55i16, 0);
2854 b.end_table(off);
2855 check(&b, &[
2856 8, 0, // vtable bytes
2857 12, 0, // length of object
2858 6, 0, // start of value 0 from end of vtable
2859 8, 0, // start of value 1 from end of buffer
2860 8, 0, 0, 0, // offset for start of vtable (int32)
2861 0, 0, // padding
2862 55, 0, // value 0
2863 4, 0, 0, 0, // vector position from here
2864 2, 0, 0, 0, // length of vector (uint32)
2865 0x78, 0x56, // vector value 1
2866 0x34, 0x12, // vector value 0
2867 ]);
2868 }
2869 #[test]
layout_14_vtable_with_1_struct_of_int8_and_int16_and_int32()2870 fn layout_14_vtable_with_1_struct_of_int8_and_int16_and_int32() {
2871 #[derive(Copy, Clone, Debug, Eq, PartialEq)]
2872 #[repr(C, packed)]
2873 struct foo {
2874 a: i32,
2875 _pad0: [u8; 2],
2876 b: i16,
2877 _pad1: [u8; 3],
2878 c: i8,
2879 _pad2: [u8; 4],
2880 }
2881 assert_eq!(::std::mem::size_of::<foo>(), 16);
2882 impl<'b> flatbuffers::Push for &'b foo {
2883 type Output = foo;
2884 fn push<'a>(&'a self, dst: &'a mut [u8], _rest: &'a [u8]) {
2885 let src = unsafe {
2886 ::std::slice::from_raw_parts(*self as *const foo as *const u8, ::std::mem::size_of::<foo>())
2887 };
2888 dst.copy_from_slice(src);
2889 }
2890 }
2891
2892 let mut b = flatbuffers::FlatBufferBuilder::new();
2893 let off = b.start_table();
2894 let x = foo{a: 0x12345678i32.to_le(), _pad0: [0,0], b: 0x1234i16.to_le(), _pad1: [0, 0, 0], c: 0x12i8.to_le(), _pad2: [0, 0, 0, 0]};
2895 b.push_slot_always(fi2fo(0), &x);
2896 b.end_table(off);
2897 check(&b, &[
2898 6, 0, // vtable bytes
2899 20, 0, // end of object from here
2900 4, 0, // start of struct from here
2901 6, 0, 0, 0, // offset for start of vtable (int32)
2902
2903 0x78, 0x56, 0x34, 0x12, // value a
2904 0, 0, // padding
2905 0x34, 0x12, // value b
2906 0, 0, 0, // padding
2907 0x12, // value c
2908 0, 0, 0, 0, // padding
2909 ]);
2910 }
2911 #[test]
layout_15_vtable_with_1_vector_of_4_int8()2912 fn layout_15_vtable_with_1_vector_of_4_int8() {
2913 let mut b = flatbuffers::FlatBufferBuilder::new();
2914 b.start_vector::<i8>(4);
2915 b.push(33i8);
2916 b.push(44i8);
2917 b.push(55i8);
2918 b.push(66i8);
2919 let vecend = b.end_vector::<i8>(4);
2920 let off = b.start_table();
2921 b.push_slot_always(fi2fo(0), vecend);
2922 b.end_table(off);
2923 check(&b, &[
2924 6, 0, // vtable bytes
2925 8, 0,
2926 4, 0, // offset of vector offset
2927 6, 0, 0, 0, // offset for start of vtable (int32)
2928 4, 0, 0, 0, // vector start offset
2929
2930 4, 0, 0, 0, // vector length
2931 66, // vector value 1,1
2932 55, // vector value 1,0
2933 44, // vector value 0,1
2934 33, // vector value 0,0
2935 ]);
2936 }
2937
2938 #[test]
layout_16_table_with_some_elements()2939 fn layout_16_table_with_some_elements() {
2940 let mut b = flatbuffers::FlatBufferBuilder::new();
2941 let off = b.start_table();
2942 b.push_slot(fi2fo(0), 33i8, 0);
2943 b.push_slot(fi2fo(1), 66i16, 0);
2944 let off2 = b.end_table(off);
2945 b.finish_minimal(off2);
2946
2947 check(&b, &[
2948 12, 0, 0, 0, // root of table: points to vtable offset
2949
2950 8, 0, // vtable bytes
2951 8, 0, // end of object from here
2952 7, 0, // start of value 0
2953 4, 0, // start of value 1
2954
2955 8, 0, 0, 0, // offset for start of vtable (int32)
2956
2957 66, 0, // value 1
2958 0, // padding
2959 33, // value 0
2960 ]);
2961 }
2962
2963 #[test]
layout_17_one_unfinished_table_and_one_finished_table()2964 fn layout_17_one_unfinished_table_and_one_finished_table() {
2965 let mut b = flatbuffers::FlatBufferBuilder::new();
2966 {
2967 let off = b.start_table();
2968 b.push_slot(fi2fo(0), 33i8, 0);
2969 b.push_slot(fi2fo(1), 44i8, 0);
2970 b.end_table(off);
2971 }
2972
2973 {
2974 let off = b.start_table();
2975 b.push_slot(fi2fo(0), 55i8, 0);
2976 b.push_slot(fi2fo(1), 66i8, 0);
2977 b.push_slot(fi2fo(2), 77i8, 0);
2978 let off2 = b.end_table(off);
2979 b.finish_minimal(off2);
2980 }
2981
2982 check(&b, &[
2983 16, 0, 0, 0, // root of table: points to object
2984 0, 0, // padding
2985
2986 10, 0, // vtable bytes
2987 8, 0, // size of object
2988 7, 0, // start of value 0
2989 6, 0, // start of value 1
2990 5, 0, // start of value 2
2991 10, 0, 0, 0, // offset for start of vtable (int32)
2992 0, // padding
2993 77, // value 2
2994 66, // value 1
2995 55, // value 0
2996
2997 //12, 0, 0, 0, // root of table: points to object
2998
2999 8, 0, // vtable bytes
3000 8, 0, // size of object
3001 7, 0, // start of value 0
3002 6, 0, // start of value 1
3003 8, 0, 0, 0, // offset for start of vtable (int32)
3004 0, 0, // padding
3005 44, // value 1
3006 33, // value 0
3007 ]);
3008 }
3009
3010 #[test]
layout_18_a_bunch_of_bools()3011 fn layout_18_a_bunch_of_bools() {
3012 let mut b = flatbuffers::FlatBufferBuilder::new();
3013 let off = b.start_table();
3014 b.push_slot(fi2fo(0), true, false);
3015 b.push_slot(fi2fo(1), true, false);
3016 b.push_slot(fi2fo(2), true, false);
3017 b.push_slot(fi2fo(3), true, false);
3018 b.push_slot(fi2fo(4), true, false);
3019 b.push_slot(fi2fo(5), true, false);
3020 b.push_slot(fi2fo(6), true, false);
3021 b.push_slot(fi2fo(7), true, false);
3022 let off2 = b.end_table(off);
3023 b.finish_minimal(off2);
3024
3025 check(&b, &[
3026 24, 0, 0, 0, // root of table: points to vtable offset
3027
3028 20, 0, // vtable bytes
3029 12, 0, // size of object
3030 11, 0, // start of value 0
3031 10, 0, // start of value 1
3032 9, 0, // start of value 2
3033 8, 0, // start of value 3
3034 7, 0, // start of value 4
3035 6, 0, // start of value 5
3036 5, 0, // start of value 6
3037 4, 0, // start of value 7
3038 20, 0, 0, 0, // vtable offset
3039
3040 1, // value 7
3041 1, // value 6
3042 1, // value 5
3043 1, // value 4
3044 1, // value 3
3045 1, // value 2
3046 1, // value 1
3047 1, // value 0
3048 ]);
3049 }
3050
3051 #[test]
layout_19_three_bools()3052 fn layout_19_three_bools() {
3053 let mut b = flatbuffers::FlatBufferBuilder::new();
3054 let off = b.start_table();
3055 b.push_slot(fi2fo(0), true, false);
3056 b.push_slot(fi2fo(1), true, false);
3057 b.push_slot(fi2fo(2), true, false);
3058 let off2 = b.end_table(off);
3059 b.finish_minimal(off2);
3060
3061 check(&b, &[
3062 16, 0, 0, 0, // root of table: points to vtable offset
3063
3064 0, 0, // padding
3065
3066 10, 0, // vtable bytes
3067 8, 0, // size of object
3068 7, 0, // start of value 0
3069 6, 0, // start of value 1
3070 5, 0, // start of value 2
3071 10, 0, 0, 0, // vtable offset from here
3072
3073 0, // padding
3074 1, // value 2
3075 1, // value 1
3076 1, // value 0
3077 ]);
3078 }
3079
3080 #[test]
layout_20_some_floats()3081 fn layout_20_some_floats() {
3082 let mut b = flatbuffers::FlatBufferBuilder::new();
3083 let off = b.start_table();
3084 b.push_slot(fi2fo(0), 1.0f32, 0.0);
3085 b.end_table(off);
3086
3087 check(&b, &[
3088 6, 0, // vtable bytes
3089 8, 0, // size of object
3090 4, 0, // start of value 0
3091 6, 0, 0, 0, // vtable offset
3092
3093 0, 0, 128, 63, // value 0
3094 ]);
3095 }
3096
3097 #[test]
layout_21_vtable_defaults()3098 fn layout_21_vtable_defaults() {
3099 let mut b = flatbuffers::FlatBufferBuilder::new();
3100 let off = b.start_table();
3101 b.push_slot::<i8>(fi2fo(0), 1, 1);
3102 b.push_slot::<i8>(fi2fo(1), 3, 2);
3103 b.push_slot::<i8>(fi2fo(2), 3, 3);
3104 b.end_table(off);
3105 check(&b, &[
3106 8, 0, // vtable size in bytes
3107 8, 0, // object inline data in bytes
3108 0, 0, // entry 1/3: 0 => default
3109 7, 0, // entry 2/3: 7 => table start + 7 bytes
3110 // entry 3/3: not present => default
3111 8, 0, 0, 0,
3112 0, 0, 0,
3113 3,
3114 ]);
3115 }
3116
3117 #[test]
layout_22_root()3118 fn layout_22_root() {
3119 let mut b = flatbuffers::FlatBufferBuilder::new();
3120 let off = b.start_table();
3121 // skipped: b.push_slot_scalar::<i16>(0, 1, 1);
3122 b.push_slot::<i16>(fi2fo(1), 3, 2);
3123 b.push_slot::<i16>(fi2fo(2), 3, 3);
3124 let table_end = b.end_table(off);
3125 b.finish_minimal(table_end);
3126 check(&b, &[
3127 12, 0, 0, 0, // root
3128
3129 8, 0, // vtable size in bytes
3130 8, 0, // object inline data in bytes
3131 0, 0, // entry 1/3: 0 => default
3132 6, 0, // entry 2/3: 6 => table start + 6 bytes
3133 // entry 3/3: not present => default
3134 8, 0, 0, 0, // size of table data in bytes
3135 0, 0, // padding
3136 3, 0, // value 2/3
3137 ]);
3138 }
3139 #[test]
layout_23_varied_slots_and_root()3140 fn layout_23_varied_slots_and_root() {
3141 let mut b = flatbuffers::FlatBufferBuilder::new();
3142 let off = b.start_table();
3143 b.push_slot::<i16>(fi2fo(0), 1, 0);
3144 b.push_slot::<u8>(fi2fo(1), 2, 0);
3145 b.push_slot::<f32>(fi2fo(2), 3.0, 0.0);
3146 let table_end = b.end_table(off);
3147 b.finish_minimal(table_end);
3148 check(&b, &[
3149 16, 0, 0, 0, // root
3150 0, 0, // padding
3151 10, 0, // vtable bytes
3152 12, 0, // object inline data size
3153 10, 0, // offset to value #1 (i16)
3154 9, 0, // offset to value #2 (u8)
3155 4, 0, // offset to value #3 (f32)
3156 10, 0, // offset to vtable
3157 0, 0, // padding
3158 0, 0, 64, 64, // value #3 => 3.0 (float32)
3159 0, 2, // value #1 => 2 (u8)
3160 1, 0, // value #0 => 1 (int16)
3161 ]);
3162 }
3163 }
3164
3165 #[cfg(test)]
3166 mod copy_clone_traits {
3167 #[test]
follow_types_implement_copy_and_clone()3168 fn follow_types_implement_copy_and_clone() {
3169 static_assertions::assert_impl_all!(flatbuffers::WIPOffset<u32>: Copy, Clone);
3170 static_assertions::assert_impl_all!(flatbuffers::WIPOffset<Vec<u32>>: Copy, Clone);
3171
3172 static_assertions::assert_impl_all!(flatbuffers::ForwardsUOffset<u32>: Copy, Clone);
3173 static_assertions::assert_impl_all!(flatbuffers::ForwardsUOffset<Vec<u32>>: Copy, Clone);
3174
3175 static_assertions::assert_impl_all!(flatbuffers::Vector<'static, u32>: Copy, Clone);
3176 static_assertions::assert_impl_all!(flatbuffers::Vector<'static, Vec<u32>>: Copy, Clone);
3177 }
3178 }
3179
3180 #[cfg(test)]
3181 mod fully_qualified_name {
3182 #[test]
fully_qualified_name_generated()3183 fn fully_qualified_name_generated() {
3184 assert!(check_eq!(::my_game::example::Monster::get_fully_qualified_name(), "MyGame.Example.Monster").is_ok());
3185 assert!(check_eq!(::my_game::example_2::Monster::get_fully_qualified_name(), "MyGame.Example2.Monster").is_ok());
3186
3187 assert!(check_eq!(::my_game::example::Vec3::get_fully_qualified_name(), "MyGame.Example.Vec3").is_ok());
3188 assert!(check_eq!(::my_game::example::Ability::get_fully_qualified_name(), "MyGame.Example.Ability").is_ok());
3189 }
3190 }
3191
3192 // this is not technically a test, but we want to always keep this generated
3193 // file up-to-date, and the simplest way to do that is to make sure that when
3194 // tests are run, the file is generated.
3195 #[test]
write_example_wire_data_to_file()3196 fn write_example_wire_data_to_file() {
3197 let b = &mut flatbuffers::FlatBufferBuilder::new();
3198 create_serialized_example_with_generated_code(b);
3199
3200 use ::std::io::Write;
3201 let mut f = std::fs::File::create("../monsterdata_rust_wire.mon").unwrap();
3202 f.write_all(b.finished_data()).unwrap();
3203 }
3204
load_file(filename: &str) -> Result<Vec<u8>, std::io::Error>3205 fn load_file(filename: &str) -> Result<Vec<u8>, std::io::Error> {
3206 use std::io::Read;
3207 let mut f = std::fs::File::open(filename)?;
3208 let mut buf = Vec::new();
3209 f.read_to_end(&mut buf)?;
3210 Ok(buf)
3211 }
3212
3213 #[test]
test_shared_strings()3214 fn test_shared_strings() {
3215 let mut builder = flatbuffers::FlatBufferBuilder::new();
3216 let offset1 = builder.create_shared_string("welcome to flatbuffers!!");
3217 let offset2 = builder.create_shared_string("welcome");
3218 let offset3 = builder.create_shared_string("welcome to flatbuffers!!");
3219 assert_ne!(offset2.value(), offset3.value());
3220 assert_eq!(offset1.value(), offset3.value());
3221 builder.reset();
3222 let offset4 = builder.create_shared_string("welcome");
3223 let offset5 = builder.create_shared_string("welcome to flatbuffers!!");
3224 assert_ne!(offset2.value(), offset4.value());
3225 assert_ne!(offset5.value(), offset1.value());
3226 builder.reset();
3227
3228 // Checks if the shared string function would always work with
3229 // an object in between the writes
3230 let name = builder.create_shared_string("foo");
3231 let enemy = my_game::example::Monster::create(&mut builder, &my_game::example::MonsterArgs {
3232 name: Some(name),
3233 ..Default::default()
3234 });
3235 let secondary_name = builder.create_shared_string("foo");
3236 assert_eq!(name.value(), secondary_name.value());
3237
3238 // Builds a new monster object and embeds enemy into it so we can verify
3239 // that shared strings are working.
3240 let args = my_game::example::MonsterArgs {
3241 name: Some(secondary_name),
3242 enemy: Some(enemy),
3243 testarrayofstring: Some(builder.create_vector(&[name, secondary_name])),
3244 ..Default::default()
3245 };
3246 // Building secondary monster
3247 let main_monster = my_game::example::Monster::create(&mut builder, &args);
3248 builder.finish(main_monster, None);
3249 let monster = my_game::example::root_as_monster(builder.finished_data()).unwrap();
3250
3251 // Checks if the embedded object (Enemy) name is foo
3252 assert_eq!(monster.enemy().unwrap().name(), "foo");
3253 let string_vector = monster.testarrayofstring().unwrap();
3254 // Check if the vector will have the same string
3255 assert_eq!(string_vector.get(0), "foo");
3256 assert_eq!(string_vector.get(1), "foo");
3257 }
3258
3259 }
3260