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