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