mirror of
https://gitee.com/openharmony/third_party_rust_memoffset
synced 2024-11-23 07:10:22 +00:00
Cleanup. Macors no longer thoretically allocate.
This commit is contained in:
parent
32cbbb79ac
commit
057a247d25
@ -4,6 +4,7 @@ version = "0.1.0"
|
|||||||
authors = ["Gilad Naaman <gilad.naaman@gmail.com>"]
|
authors = ["Gilad Naaman <gilad.naaman@gmail.com>"]
|
||||||
description="offset_of functionality for Rust structs."
|
description="offset_of functionality for Rust structs."
|
||||||
license="Apache-2.0"
|
license="Apache-2.0"
|
||||||
|
readme="README.md"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
|
||||||
|
43
README.md
Normal file
43
README.md
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
# memoffset #
|
||||||
|
|
||||||
|
[![](http://meritbadge.herokuapp.com/memoffset)](https://crates.io/crates/memoffset)
|
||||||
|
|
||||||
|
C-Like `offset_of` functionality for Rust structs.
|
||||||
|
|
||||||
|
Introduces the following macros:
|
||||||
|
* `offset_of!` for obtaining the offset of a member of a struct.
|
||||||
|
* `span_of!` for obtaining the range that a field, or fields, span.
|
||||||
|
|
||||||
|
## Usage ##
|
||||||
|
Add the following dependency to your `Cargo.toml`:
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[dependencies]
|
||||||
|
memoffset = "0.1"
|
||||||
|
```
|
||||||
|
|
||||||
|
Add the following lines at the top of your `main.rs` or `lib.rs` files.
|
||||||
|
|
||||||
|
```rust
|
||||||
|
#[macro_use]
|
||||||
|
extern crate memoffset;
|
||||||
|
```
|
||||||
|
|
||||||
|
## Examples ##
|
||||||
|
```rust
|
||||||
|
#[repr(C, packed)]
|
||||||
|
struct Foo {
|
||||||
|
a: u32,
|
||||||
|
b: u32,
|
||||||
|
c: [u8; 5],
|
||||||
|
d: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
assert_eq!(offset_of!(Foo, b), 4);
|
||||||
|
assert_eq!(offset_of!(Foo, c[3]), 11);
|
||||||
|
|
||||||
|
assert_eq!(span_of!(Foo, a), 0..4);
|
||||||
|
assert_eq!(span_of!(Foo, a .. c), 0..8);
|
||||||
|
assert_eq!(span_of!(Foo, a .. c[1]), 0..9);
|
||||||
|
assert_eq!(span_of!(Foo, a .. =c[1]), 0..10);
|
||||||
|
```
|
248
src/lib.rs
248
src/lib.rs
@ -1,3 +1,9 @@
|
|||||||
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||||
|
// option. This file may not be copied, modified, or distributed
|
||||||
|
// except according to those terms.
|
||||||
|
|
||||||
//! A crate used for calculating offsets of struct members and their spans.
|
//! A crate used for calculating offsets of struct members and their spans.
|
||||||
//!
|
//!
|
||||||
//! Some of the funcationality of the crate makes no sense when used along with structs that
|
//! Some of the funcationality of the crate makes no sense when used along with structs that
|
||||||
@ -42,243 +48,13 @@
|
|||||||
|
|
||||||
#[cfg(feature="std")]
|
#[cfg(feature="std")]
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub use std::mem;
|
pub use std::{mem, ptr};
|
||||||
|
|
||||||
#[cfg(not(feature="std"))]
|
#[cfg(not(feature="std"))]
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub use core::mem;
|
pub use core::{mem, ptr};
|
||||||
|
|
||||||
/// Calculates the offset of the specified field from the start of the struct.
|
#[macro_use]
|
||||||
/// This macro supports arbitrary amount of subscripts and recursive member-accesses.
|
mod offset_of;
|
||||||
///
|
#[macro_use]
|
||||||
/// *Note*: This macro may not make much sense when used on structs that are not `#[repr(C, packed)]`
|
mod span_of;
|
||||||
///
|
|
||||||
/// ## Examples - Simple
|
|
||||||
/// ```
|
|
||||||
/// #[macro_use]
|
|
||||||
/// extern crate memoffset;
|
|
||||||
///
|
|
||||||
/// #[repr(C, packed)]
|
|
||||||
/// struct Foo {
|
|
||||||
/// a: u32,
|
|
||||||
/// b: u64,
|
|
||||||
/// c: [u8; 5]
|
|
||||||
/// }
|
|
||||||
///
|
|
||||||
/// fn main() {
|
|
||||||
/// assert_eq!(offset_of!(Foo, a), 0);
|
|
||||||
/// assert_eq!(offset_of!(Foo, b), 4);
|
|
||||||
/// assert_eq!(offset_of!(Foo, c[2]), 14);
|
|
||||||
/// }
|
|
||||||
/// ```
|
|
||||||
///
|
|
||||||
/// ## Examples - Advanced
|
|
||||||
/// ```
|
|
||||||
/// #[macro_use]
|
|
||||||
/// extern crate memoffset;
|
|
||||||
///
|
|
||||||
/// #[repr(C, packed)]
|
|
||||||
/// struct UnnecessarilyComplicatedStruct {
|
|
||||||
/// member: [UnnecessarilyComplexStruct; 12]
|
|
||||||
/// }
|
|
||||||
///
|
|
||||||
/// #[repr(C, packed)]
|
|
||||||
/// struct UnnecessarilyComplexStruct {
|
|
||||||
/// a: u32,
|
|
||||||
/// b: u64,
|
|
||||||
/// c: [u8; 5]
|
|
||||||
/// }
|
|
||||||
///
|
|
||||||
///
|
|
||||||
/// fn main() {
|
|
||||||
/// assert_eq!(offset_of!(UnnecessarilyComplicatedStruct, member[3].c[3]), 66);
|
|
||||||
/// }
|
|
||||||
/// ```
|
|
||||||
#[macro_export]
|
|
||||||
macro_rules! offset_of {
|
|
||||||
($father:ty, $($field:tt)+) => ({
|
|
||||||
let root: $father = unsafe { $crate::mem::uninitialized() };
|
|
||||||
|
|
||||||
let base = &root as *const _ as usize;
|
|
||||||
let member = &root.$($field)+ as *const _ as usize;
|
|
||||||
|
|
||||||
$crate::mem::forget(root);
|
|
||||||
|
|
||||||
member - base
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Produces a range instance representing the sub-slice containing the specified member.
|
|
||||||
///
|
|
||||||
/// This macro provides 2 forms of differing functionalities.
|
|
||||||
///
|
|
||||||
/// The first form is identical to the appearance of the `offset_of!` macro,
|
|
||||||
/// and just like `offset_of!`, it has no limit on the depth of fields / subscripts used.
|
|
||||||
///
|
|
||||||
/// ```ignore
|
|
||||||
/// span_of!(Struct, member[index].field)
|
|
||||||
/// ```
|
|
||||||
///
|
|
||||||
/// The second form of `span_of!` returns a sub-slice which starts at one field, and ends at another.
|
|
||||||
/// The general pattern of this form is:
|
|
||||||
///
|
|
||||||
/// ```ignore
|
|
||||||
/// span_of!(Struct, member_a .. member_b)
|
|
||||||
/// ```
|
|
||||||
///
|
|
||||||
/// Due to `macro_rules`' parsing restrictions, the first expression - the start-anchor - is limited to subscripts,
|
|
||||||
/// with no sub-field access.
|
|
||||||
/// The second expression - the end anchor - has no such limitations.
|
|
||||||
///
|
|
||||||
/// By default this form excludes the end-anchor from the range, but inclusive ranges can be opted-in using "..=" instead.
|
|
||||||
///
|
|
||||||
/// *Note*: This macro may not make much sense when used on structs that are not `#[repr(C, packed)]`
|
|
||||||
///
|
|
||||||
/// ## Examples
|
|
||||||
/// ```
|
|
||||||
/// #[macro_use]
|
|
||||||
/// extern crate memoffset;
|
|
||||||
///
|
|
||||||
/// #[repr(C, packed)]
|
|
||||||
/// struct Florp {
|
|
||||||
/// a: u32
|
|
||||||
/// }
|
|
||||||
///
|
|
||||||
/// #[repr(C, packed)]
|
|
||||||
/// struct Blarg {
|
|
||||||
/// x: u64,
|
|
||||||
/// y: [u8; 56],
|
|
||||||
/// z: Florp,
|
|
||||||
/// egg: [[u8; 4]; 4]
|
|
||||||
/// }
|
|
||||||
///
|
|
||||||
/// fn main() {
|
|
||||||
/// assert_eq!(0..8, span_of!(Blarg, x));
|
|
||||||
/// assert_eq!(64..68, span_of!(Blarg, z.a));
|
|
||||||
/// assert_eq!(79..80, span_of!(Blarg, egg[2][3]));
|
|
||||||
///
|
|
||||||
/// assert_eq!(8..64, span_of!(Blarg, y[0] .. z));
|
|
||||||
/// assert_eq!(0..42, span_of!(Blarg, x .. y[34]));
|
|
||||||
/// assert_eq!(0..64, span_of!(Blarg, x ..= y));
|
|
||||||
/// assert_eq!(58..68, span_of!(Blarg, y[50] ..= z));
|
|
||||||
/// }
|
|
||||||
/// ```
|
|
||||||
#[macro_export]
|
|
||||||
macro_rules! span_of {
|
|
||||||
($father:ty, $field_a:ident $([$index:expr])* .. $($field_b:tt)+) => ({
|
|
||||||
let root: $father = unsafe { $crate::mem::uninitialized() };
|
|
||||||
|
|
||||||
let start = offset_of!($father, $field_a $([$index])*);
|
|
||||||
let end = offset_of!($father, $($field_b)+);
|
|
||||||
|
|
||||||
$crate::mem::forget(root);
|
|
||||||
|
|
||||||
start..end
|
|
||||||
});
|
|
||||||
|
|
||||||
($father:ty, $field_a:ident $([$index:expr])* ..= $($field_b:tt)+) => ({
|
|
||||||
let root: $father = unsafe { $crate::mem::uninitialized() };
|
|
||||||
|
|
||||||
let start = offset_of!($father, $field_a $([$index])*);
|
|
||||||
let end = offset_of!($father, $($field_b)+) +
|
|
||||||
$crate::mem::size_of_val(&root.$($field_b)+);
|
|
||||||
|
|
||||||
$crate::mem::forget(root);
|
|
||||||
|
|
||||||
start..end
|
|
||||||
});
|
|
||||||
|
|
||||||
($father:ty, $($field:tt)+) => ({
|
|
||||||
let root: $father = unsafe { $crate::mem::uninitialized() };
|
|
||||||
|
|
||||||
let start = offset_of!($father, $($field)+);
|
|
||||||
let end = start + $crate::mem::size_of_val(&root.$($field)+);
|
|
||||||
|
|
||||||
$crate::mem::forget(root);
|
|
||||||
|
|
||||||
start..end
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
#[repr(C, packed)]
|
|
||||||
struct Foo {
|
|
||||||
a: u32,
|
|
||||||
b: [u8; 4],
|
|
||||||
c: i64
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn offset_simple() {
|
|
||||||
assert_eq!(offset_of!(Foo, a), 0);
|
|
||||||
assert_eq!(offset_of!(Foo, b), 4);
|
|
||||||
assert_eq!(offset_of!(Foo, c), 8);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn offset_index() {
|
|
||||||
assert_eq!(offset_of!(Foo, b[2]), 6);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
#[should_panic]
|
|
||||||
fn offset_index_out_of_bounds() {
|
|
||||||
offset_of!(Foo, b[4]);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn span_simple() {
|
|
||||||
assert_eq!(span_of!(Foo, a), 0..4);
|
|
||||||
assert_eq!(span_of!(Foo, b), 4..8);
|
|
||||||
assert_eq!(span_of!(Foo, c), 8..16);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn span_index() {
|
|
||||||
assert_eq!(span_of!(Foo, b[1]), 5..6);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn huge() {
|
|
||||||
struct Huge {
|
|
||||||
preamble: [u8; 8192],
|
|
||||||
member: u8
|
|
||||||
}
|
|
||||||
|
|
||||||
assert_eq!(offset_of!(Huge, member), 8192);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn span_forms() {
|
|
||||||
#[repr(C, packed)]
|
|
||||||
struct Florp {
|
|
||||||
a: u32
|
|
||||||
}
|
|
||||||
|
|
||||||
#[repr(C, packed)]
|
|
||||||
struct Blarg {
|
|
||||||
x: u64,
|
|
||||||
y: [u8; 56],
|
|
||||||
z: Florp,
|
|
||||||
egg: [[u8; 4]; 4]
|
|
||||||
}
|
|
||||||
|
|
||||||
// Love me some brute force
|
|
||||||
assert_eq!(0..8, span_of!(Blarg, x));
|
|
||||||
assert_eq!(64..68, span_of!(Blarg, z.a));
|
|
||||||
assert_eq!(79..80, span_of!(Blarg, egg[2][3]));
|
|
||||||
|
|
||||||
assert_eq!(8..64, span_of!(Blarg, y[0] .. z));
|
|
||||||
assert_eq!(0..42, span_of!(Blarg, x .. y[34]));
|
|
||||||
assert_eq!(0..64, span_of!(Blarg, x ..= y));
|
|
||||||
assert_eq!(58..68, span_of!(Blarg, y[50] ..= z));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn tuple_struct() {
|
|
||||||
#[repr(C,packed)]
|
|
||||||
struct Tup(i32, i32);
|
|
||||||
assert_eq!(offset_of!(Tup, 0), 0);
|
|
||||||
}
|
|
||||||
}
|
|
99
src/offset_of.rs
Normal file
99
src/offset_of.rs
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||||
|
// option. This file may not be copied, modified, or distributed
|
||||||
|
// except according to those terms.
|
||||||
|
|
||||||
|
/// Calculates the offset of the specified field from the start of the struct.
|
||||||
|
/// This macro supports arbitrary amount of subscripts and recursive member-accesses.
|
||||||
|
///
|
||||||
|
/// *Note*: This macro may not make much sense when used on structs that are not `#[repr(C, packed)]`
|
||||||
|
///
|
||||||
|
/// ## Examples - Simple
|
||||||
|
/// ```
|
||||||
|
/// #[macro_use]
|
||||||
|
/// extern crate memoffset;
|
||||||
|
///
|
||||||
|
/// #[repr(C, packed)]
|
||||||
|
/// struct Foo {
|
||||||
|
/// a: u32,
|
||||||
|
/// b: u64,
|
||||||
|
/// c: [u8; 5]
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
/// fn main() {
|
||||||
|
/// assert_eq!(offset_of!(Foo, a), 0);
|
||||||
|
/// assert_eq!(offset_of!(Foo, b), 4);
|
||||||
|
/// assert_eq!(offset_of!(Foo, c[2]), 14);
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// ## Examples - Advanced
|
||||||
|
/// ```
|
||||||
|
/// #[macro_use]
|
||||||
|
/// extern crate memoffset;
|
||||||
|
///
|
||||||
|
/// #[repr(C, packed)]
|
||||||
|
/// struct UnnecessarilyComplicatedStruct {
|
||||||
|
/// member: [UnnecessarilyComplexStruct; 12]
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
/// #[repr(C, packed)]
|
||||||
|
/// struct UnnecessarilyComplexStruct {
|
||||||
|
/// a: u32,
|
||||||
|
/// b: u64,
|
||||||
|
/// c: [u8; 5]
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
///
|
||||||
|
/// fn main() {
|
||||||
|
/// assert_eq!(offset_of!(UnnecessarilyComplicatedStruct, member[3].c[3]), 66);
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! offset_of {
|
||||||
|
($father:ty, $($field:tt)+) => ({
|
||||||
|
let root: *const $father = $crate::ptr::null();
|
||||||
|
|
||||||
|
let base = root as usize;
|
||||||
|
let member = unsafe { &(*root).$($field)* } as *const _ as usize;
|
||||||
|
|
||||||
|
member - base
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
#[repr(C, packed)]
|
||||||
|
struct Foo {
|
||||||
|
a: u32,
|
||||||
|
b: [u8; 4],
|
||||||
|
c: i64
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn offset_simple() {
|
||||||
|
assert_eq!(offset_of!(Foo, a), 0);
|
||||||
|
assert_eq!(offset_of!(Foo, b), 4);
|
||||||
|
assert_eq!(offset_of!(Foo, c), 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn offset_index() {
|
||||||
|
assert_eq!(offset_of!(Foo, b[2]), 6);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[should_panic]
|
||||||
|
fn offset_index_out_of_bounds() {
|
||||||
|
offset_of!(Foo, b[4]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn tuple_struct() {
|
||||||
|
#[repr(C,packed)]
|
||||||
|
struct Tup(i32, i32);
|
||||||
|
|
||||||
|
assert_eq!(offset_of!(Tup, 0), 0);
|
||||||
|
}
|
||||||
|
}
|
137
src/span_of.rs
Normal file
137
src/span_of.rs
Normal file
@ -0,0 +1,137 @@
|
|||||||
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||||
|
// option. This file may not be copied, modified, or distributed
|
||||||
|
// except according to those terms.
|
||||||
|
|
||||||
|
/// Produces a range instance representing the sub-slice containing the specified member.
|
||||||
|
///
|
||||||
|
/// This macro provides 2 forms of differing functionalities.
|
||||||
|
///
|
||||||
|
/// The first form is identical to the appearance of the `offset_of!` macro,
|
||||||
|
/// and just like `offset_of!`, it has no limit on the depth of fields / subscripts used.
|
||||||
|
///
|
||||||
|
/// ```ignore
|
||||||
|
/// span_of!(Struct, member[index].field)
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// The second form of `span_of!` returns a sub-slice which starts at one field, and ends at another.
|
||||||
|
/// The general pattern of this form is:
|
||||||
|
///
|
||||||
|
/// ```ignore
|
||||||
|
/// span_of!(Struct, member_a .. member_b)
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// Due to `macro_rules`' parsing restrictions, the first expression - the start-anchor - is limited to subscripts,
|
||||||
|
/// with no sub-field access.
|
||||||
|
/// The second expression - the end anchor - has no such limitations.
|
||||||
|
///
|
||||||
|
/// By default this form excludes the end-anchor from the range, but inclusive ranges can be opted-in using "..=" instead.
|
||||||
|
///
|
||||||
|
/// *Note*: This macro may not make much sense when used on structs that are not `#[repr(C, packed)]`
|
||||||
|
///
|
||||||
|
/// ## Examples
|
||||||
|
/// ```
|
||||||
|
/// #[macro_use]
|
||||||
|
/// extern crate memoffset;
|
||||||
|
///
|
||||||
|
/// #[repr(C, packed)]
|
||||||
|
/// struct Florp {
|
||||||
|
/// a: u32
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
/// #[repr(C, packed)]
|
||||||
|
/// struct Blarg {
|
||||||
|
/// x: u64,
|
||||||
|
/// y: [u8; 56],
|
||||||
|
/// z: Florp,
|
||||||
|
/// egg: [[u8; 4]; 4]
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
/// fn main() {
|
||||||
|
/// assert_eq!(0..8, span_of!(Blarg, x));
|
||||||
|
/// assert_eq!(64..68, span_of!(Blarg, z.a));
|
||||||
|
/// assert_eq!(79..80, span_of!(Blarg, egg[2][3]));
|
||||||
|
///
|
||||||
|
/// assert_eq!(8..64, span_of!(Blarg, y[0] .. z));
|
||||||
|
/// assert_eq!(0..42, span_of!(Blarg, x .. y[34]));
|
||||||
|
/// assert_eq!(0..64, span_of!(Blarg, x ..= y));
|
||||||
|
/// assert_eq!(58..68, span_of!(Blarg, y[50] ..= z));
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! span_of {
|
||||||
|
($father:ty, $field_a:ident $([$index:expr])* .. $($field_b:tt)+) => ({
|
||||||
|
let start = offset_of!($father, $field_a $([$index])*);
|
||||||
|
let end = offset_of!($father, $($field_b)+);
|
||||||
|
|
||||||
|
start..end
|
||||||
|
});
|
||||||
|
|
||||||
|
($father:ty, $field_a:ident $([$index:expr])* ..= $($field_b:tt)+) => ({
|
||||||
|
let root: *const $father = $crate::ptr::null();
|
||||||
|
|
||||||
|
let start = offset_of!($father, $field_a $([$index])*);
|
||||||
|
let end = offset_of!($father, $($field_b)+) +
|
||||||
|
unsafe { $crate::mem::size_of_val(&(*root).$($field_b)+) };
|
||||||
|
|
||||||
|
start..end
|
||||||
|
});
|
||||||
|
($father:ty, $($field:tt)+) => ({
|
||||||
|
let root: *const $father = $crate::ptr::null();
|
||||||
|
|
||||||
|
let start = offset_of!($father, $($field)+);
|
||||||
|
let end = start +
|
||||||
|
unsafe { $crate::mem::size_of_val(&(*root).$($field)+) };
|
||||||
|
|
||||||
|
start..end
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
#[repr(C, packed)]
|
||||||
|
struct Foo {
|
||||||
|
a: u32,
|
||||||
|
b: [u8; 4],
|
||||||
|
c: i64
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn span_simple() {
|
||||||
|
assert_eq!(span_of!(Foo, a), 0..4);
|
||||||
|
assert_eq!(span_of!(Foo, b), 4..8);
|
||||||
|
assert_eq!(span_of!(Foo, c), 8..16);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn span_index() {
|
||||||
|
assert_eq!(span_of!(Foo, b[1]), 5..6);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn span_forms() {
|
||||||
|
#[repr(C, packed)]
|
||||||
|
struct Florp {
|
||||||
|
a: u32
|
||||||
|
}
|
||||||
|
|
||||||
|
#[repr(C, packed)]
|
||||||
|
struct Blarg {
|
||||||
|
x: u64,
|
||||||
|
y: [u8; 56],
|
||||||
|
z: Florp,
|
||||||
|
egg: [[u8; 4]; 4]
|
||||||
|
}
|
||||||
|
|
||||||
|
// Love me some brute force
|
||||||
|
assert_eq!(0..8, span_of!(Blarg, x));
|
||||||
|
assert_eq!(64..68, span_of!(Blarg, z.a));
|
||||||
|
assert_eq!(79..80, span_of!(Blarg, egg[2][3]));
|
||||||
|
|
||||||
|
assert_eq!(8..64, span_of!(Blarg, y[0] .. z));
|
||||||
|
assert_eq!(0..42, span_of!(Blarg, x .. y[34]));
|
||||||
|
assert_eq!(0..64, span_of!(Blarg, x ..= y));
|
||||||
|
assert_eq!(58..68, span_of!(Blarg, y[50] ..= z));
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user