aligned-array
This is a fork of Jorge Aparicio's lovely aligned crate, and provides a way to constrain a type to be over-aligned at some boundary.
The purpose of the fork is broadly to integrate better with generic-array, and in particular, to provide a general-purpose "aligned bytes" types, with safe, zero-overhead APIs for viewing them as sequences of smaller numbers of bytes / at a smaller alignment, or as native-endian integers. (This is not unlike how some rust SIMD intrinsics can be "viewed" in several ways without copying: https://doc.rust-lang.org/nightly/core/arch/x86/struct.__m256i.html)
For example, using the GenericArray::Split API, we can split a reference to a slice of known size
into two references to pieces, whose sizes are also known at compile time. But, if we use Split on an Aligned
generic-array, we lose the information we had about the alignment of those two pieces.
For some applications, that alignment information is critical to be able to go on to use the two pieces in a performant way, perhaps using SIMD instructions later. It also may enable the compiler to generate faster code simply for moving them around.
This crate offers implementations of Split API and others which return Aligned<GenericArray> instead
of GenericArray, without creating copies or extra instructions in the release mode binary.
Preserving alignment information in this way allows users to go on to solve complex
systems problems in a highly performant way, without compromising on safety.
We also integrate a little bit with subtle in order that aligned bytes implement ConstantTimeEq.
That function can be implemented faster sometimes when alignment information is available.
Specific list of differences with aligned crate:
- Extra alignment types:
A32,A64. - Better conversions between
Alignedobjects: e.g.Aligned<A8, T>implementsAsRef<Aligned<A4, T>>. This is permitted because objects aligned on a large boundary are also necessarily aligned on a smaller boundary. AlignedderivesEq, PartialEq, Hash, Ord, PartialOrdwhen possible.Alignedderivessubtle::ConstantTimeEqwhen possible.AlignedderivesFromIteratorandIntoIteratorwhen possible.Alignedderivesgeneric_array::sequence::GenericSequencewhen possible.Alignedimplementsgeneric_array::sequence::Splitin such a way that preserves alignment information. In particularAligned<GenericArray<u8, N>>can be split intoAligned<GenericArray<u8, M>>andAligned<GenericArray<u8, N - M>>ifMdivides the alignment value. This is only done for the typeu8right now but could be generalized.- Extra traits:
AsNeSliceandAsAlignedChunks, and implementations for aligned arrays of bytes. These allow aligned sequences of bytes to be interpretted, with no overhead, as slices of native-endian integers, or slices of smaller aligned byte chunks. as-slicedependency is removed. This crate is rarely useful in practice becauseAsRef<[u8]>and similar traits usually do the job just fine.as-slicealso unfortunately depends on multiple versions ofgeneric-arrayat once, bringing them all into the build plan, which is messy and makes some dependency mismatch problems harder to catch and solve in large projects. Making this crate optional doesn't fix that because Cargo adds them all to theCargo.lockregardless of feature configuration. We would consider bringing back theas-slicestuff if the maintainers release a version ofas-slicethat depends on only the most recent version ofgeneric-array.
Unsafe code
This crate contains a few more unsafe casts than the original aligned crate did.
This is needed to implement the integrations with generic-array.
These casts are similar to the casts that generic-array performs itself internally:
they generally are based on the assumption that GenericArray<T, N> is layout-compatible with [T; N].
All casts like this
- have their preconditions enforced by asserts, that llvm proves are true and strips out in release mode builds
- have detailed correctness notes,
- have been tested extensively in a large project.
This code was also covered as part of a formal audit by Trail of Bits.