Module fate::marker::fixed_consistent_repr
[−]
[src]
The FixedConsistentSize
and FixedConsistentRepr
marker traits.
See these traits' doc for explanations on their meaning.
Note: this module's name is not shortened to fixed
because it might be confused with a module
for fixed-point number data types.
As for FixedConsistentSize
's use cases : it is sometimes good to guarantee that some of your data
types have the exact same size across targets.
Is is true that, more often than not, data structures should be tuned for the target
hardware, with regards to cache size, CPU arch-specific instructions, etc.
However, there are cases where that reasoning is flawed : Why would your player's score be an
usize
when you know that it stores either 32 or 64 bits worth of integer data, depending on
the target ? You would basically be forbidding anyone running in 32-bit mode to beat Bob who
earned the title of world champion with his 4294967298 points.
Likewise, why would you represent the smoke particle count with an usize
when you know that
it'd be impossible for it to get past, say, 65535 ?
It is my opinion, for instance, that ::std::time::Instant
should meet
these requirements (today, it actually doesn't because of Redox
's libstd
implementation)
because there's no reason some platforms would be able to represent time more precisely
than others, not to mention the (tiny) extra memory differences - here, we'd make it consistent
by storing it in our side as :
```
fn main() {}
extern crate fate;
use fate::{FixedConsistentSize, FixedConsistentRepr};
#[allow(dead_code)]
[repr(C,packed)]
struct Time {
secs: i64,
nanosecs: u64,
}
// Now we know we can do this :
unsafe impl FixedConsistentSize for Time {}
unsafe impl FixedConsistentRepr for Time {}
``TODO: derive for
FixedConsistentReprand
FixedConsistentSize` !
Size consistency for a type often, but not always, implies representation consistency, which
is what one may actually be looking for: the FixedConsistentRepr
trait is a stronger
version of FixedConsistentSize
, which adds the requirement that the in-memory representation
of data is the same everywhere.
For instance, a hypothetical real32
type which may resolve to various real-number
implementations depending on the target, but is always 32 bits-wide, would be
FixedConsistentSize
but not FixedConsistentRepr
.
The main use case for FixedConsistentRepr
would be to help guaranteeing purity of bit-level
manipulations for some types.
Checklist for properly implementing FixedConsistentSize
:
- enum
s and struct
s MUST be #[repr(C,packed)]
(#[repr(C)]
alone is not enough because each target may have its alignment requirements);
- All members (if any) MUST be FixedConsistentSize
;
- The type is not dynamically-sized (counter-examples include Vec<T>
, String
, str
, [T]
, &[T]
, etc).
- The type is not machine-dependant (counter-examples include #[repr(simd)]
, isize
, usize
, *const T
, *mut T
).
All zero-sized types should implement FixedConsistentRepr
(which implies FixedConsistentSize
) when possible.
Rationales
char
isFixedConsistentRepr
because it is always 4 bytes-wide in Rust, in case you're coming from C, C++, Java, etc.bool
is notFixedConsistentRepr
because its representation is unspecified, AFAIK.- Tuples are not
FixedConsistentRepr
because their memory layout is unspecified, except the empty tuple which is zero-sized. Not even (T,T,T,T) would match, because the compiler is free to remove fields if it can prove they aren't used. f32
andf64
areFixedConsistentRepr
because, quoting the Rust spec, they always are "IEEE 754-2008binary32
andbinary64
" formats.Option<T>
andResult<T,E>
probably areFixedConsistentRepr
if both T and E areFixedConsistentRepr
, but I don't know for sure.
Traits
FixedConsistentRepr |
A type which in-memory representation is known at compile-time and guaranteed to be the same across operating systems, hardware, compilers and build settings. |
FixedConsistentSize |
A type which size is not only known at compile-time, but guaranteed to be the same across operating systems, hardware, compilers and build settings. |