Fix rust crate for big-endian targets (#5229)

Thanks for tackling this, @tymcauley !

* big endian docker test -- wip

* tweaks

* tweaks

* tweaks

* docker tweaks

* fix conditional compilation issues

* reactivate other docker tests

* try some more cross-platform config (from tymcauley)

* Update tests/docker/languages/Dockerfile.testing.rust.big_endian.1_30_1

Co-Authored-By: rw <rw@users.noreply.github.com>

* Update tests/docker/languages/Dockerfile.testing.rust.big_endian.1_30_1

Co-Authored-By: rw <rw@users.noreply.github.com>

* Update tests/docker/languages/Dockerfile.testing.rust.big_endian.1_30_1

Co-Authored-By: rw <rw@users.noreply.github.com>

* Resolved Rust warnings during big-endian builds.

* Unify Rust test suites for x86 and MIPS builds.

Note that I had to add four extra packages to the MIPS `Dockerfile`:
`libexpat1`, `libmagic1`, `libmpdec2`, and `libreadline7`. For a reason
I couldn't identify, even the simplest Rust MIPS binaries run with
`qemu-mips` would fail with a segfault when run through this
`Dockerfile`. After installing the `gdb-multiarch` package to attempt to
debug the issue, the binaries ran successfully. I pared down the
packages installed by `gdb-multiarch`, and these four packages are the
minimum subset necessary to get Rust MIPS binaries running under
`qemu-mips`.

* Changed Rust tests to use `Vector`s instead of direct-slice-access.

The direct-slice-access method is not available on big-endian targets,
but `flatbuffers::Vector`s provide an array interface that is available
on all platforms.

* Resolved FooStruct endianness issues using explicit struct constructor.

This more closely resembles how FlatBuffers structs are constructed in
generated Rust code.

* Added explanation of how `FooStruct` parallels generated struct code.

Also collected duplicate implementations of `FooStruct` into a common
location.
This commit is contained in:
tymcauley
2019-03-08 04:06:25 -05:00
committed by Robert
parent e237f53bfc
commit 9e82ee2527
5 changed files with 117 additions and 72 deletions

View File

@@ -88,7 +88,7 @@ impl EndianScalar for f32 {
}
#[cfg(not(target_endian = "little"))]
{
byte_swap_f32(&self)
byte_swap_f32(self)
}
}
/// Convert f32 from little-endian to host endian-ness.
@@ -100,7 +100,7 @@ impl EndianScalar for f32 {
}
#[cfg(not(target_endian = "little"))]
{
byte_swap_f32(&self)
byte_swap_f32(self)
}
}
}
@@ -115,7 +115,7 @@ impl EndianScalar for f64 {
}
#[cfg(not(target_endian = "little"))]
{
byte_swap_f64(&self)
byte_swap_f64(self)
}
}
/// Convert f64 from little-endian to host endian-ness.
@@ -127,7 +127,7 @@ impl EndianScalar for f64 {
}
#[cfg(not(target_endian = "little"))]
{
byte_swap_f64(&self)
byte_swap_f64(self)
}
}
}

View File

@@ -19,7 +19,9 @@ use std::mem::size_of;
use std::slice::from_raw_parts;
use std::str::from_utf8_unchecked;
use endian_scalar::{EndianScalar, read_scalar};
#[cfg(target_endian = "little")]
use endian_scalar::EndianScalar;
use endian_scalar::read_scalar;
use follow::Follow;
use primitives::*;
@@ -85,6 +87,7 @@ mod le_safe_slice_impls {
impl super::SafeSliceAccess for f64 {}
}
#[cfg(target_endian = "little")]
pub use self::le_safe_slice_impls::*;
pub fn follow_cast_ref<'a, T: Sized + 'a>(buf: &'a [u8], loc: usize) -> &'a T {
@@ -104,6 +107,7 @@ impl<'a> Follow<'a> for &'a str {
}
}
#[cfg(target_endian = "little")]
fn follow_slice_helper<T>(buf: &[u8], loc: usize) -> &[T] {
let sz = size_of::<T>();
debug_assert!(sz > 0);