#![feature(min_specialization)]
#[derive(Debug, PartialEq)]
pub enum DataModel {
IP16, IP16L32, LP32, ILP32, LLP64, LP64, ILP64, SILP64, Unknown, }
pub enum Char {}
pub enum Short {}
pub enum Int {}
pub enum Long {}
pub enum LongLong {}
pub enum Pointer {}
trait SizeOf<T> {
fn size_of(self) -> usize;
}
impl DataModel {
pub fn new(int: usize, long: usize, pointer: usize) -> DataModel {
use DataModel::*;
match (int, long, pointer) {
(2, 0, 2) => IP16,
(2, 4, 2) => IP16L32,
(2, 4, 4) => LP32,
(4, 4, 4) => ILP32,
(4, 4, 8) => LLP64,
(4, 8, 8) => LP64,
(8, 8, 8) => ILP64,
_ => Unknown,
}
}
pub fn size_of<T>(self) -> usize {
<DataModel as SizeOf<T>>::size_of(self)
}
}
impl<T, U> SizeOf<T> for U {
default fn size_of(self) -> usize {
0
}
}
impl SizeOf<Char> for DataModel {
fn size_of(self) -> usize {
use DataModel::*;
match self {
IP16 | IP16L32 | LP32 | ILP32 | LLP64 | LP64 | ILP64 | SILP64 => 1,
Unknown => 0,
}
}
}
impl SizeOf<Short> for DataModel {
fn size_of(self) -> usize {
use DataModel::*;
match self {
IP16L32 | LP32 | ILP32 | LLP64 | LP64 | ILP64 => 2,
SILP64 => 8,
Unknown | IP16 => 0,
}
}
}
impl SizeOf<Int> for DataModel {
fn size_of(self) -> usize {
use DataModel::*;
match self {
IP16 | IP16L32 | LP32 => 2,
ILP32 | LLP64 | LP64 => 4,
ILP64 | SILP64 => 8,
Unknown => 0,
}
}
}
impl SizeOf<Long> for DataModel {
fn size_of(self) -> usize {
use DataModel::*;
match self {
IP16L32 | LP32 | ILP32 | LLP64 => 4,
LP64 | ILP64 | SILP64 => 8,
Unknown | IP16 => 0,
}
}
}
impl SizeOf<LongLong> for DataModel {
fn size_of(self) -> usize {
use DataModel::*;
match self {
LP32 | ILP32 | LLP64 | LP64 | ILP64 | SILP64 => 8,
Unknown | IP16 | IP16L32 => 0,
}
}
}
impl SizeOf<Pointer> for DataModel {
fn size_of(self) -> usize {
use DataModel::*;
match self {
IP16 | IP16L32 => 2,
LP32 | ILP32 => 4,
LLP64 | LP64 | ILP64 | SILP64 => 8,
Unknown => 0,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
macro_rules! sizeof_check {
(
$(
$model:ident: $type:path, $expect:expr
)
,
*
) => {
$(
let model = DataModel::$model;
let s = model.size_of::<$type>();
assert_eq!(s, $expect);
)*
}
}
#[test]
fn test_char() {
sizeof_check! {
IP16: Char, 1,
IP16L32: Char, 1,
LP32: Char, 1,
ILP32: Char, 1,
LLP64: Char, 1,
LP64: Char, 1,
ILP64: Char, 1,
SILP64: Char, 1,
Unknown: Char, 0
}
}
#[test]
fn test_short() {
sizeof_check! {
IP16: Short, 0,
IP16L32: Short, 2,
LP32: Short, 2,
ILP32: Short, 2,
LLP64: Short, 2,
LP64: Short, 2,
ILP64: Short, 2,
SILP64: Short, 8,
Unknown: Short, 0
}
}
#[test]
fn test_int() {
sizeof_check! {
IP16: Int, 2,
IP16L32: Int, 2,
LP32: Int, 2,
ILP32: Int, 4,
LLP64: Int, 4,
LP64: Int, 4,
ILP64: Int, 8,
SILP64: Int, 8,
Unknown: Int, 0
}
}
#[test]
fn test_long() {
sizeof_check! {
IP16: Long, 0,
IP16L32: Long, 4,
LP32: Long, 4,
ILP32: Long, 4,
LLP64: Long, 4,
LP64: Long, 8,
ILP64: Long, 8,
SILP64: Long, 8,
Unknown: Long, 0
}
}
#[test]
fn test_long_long() {
sizeof_check! {
IP16: LongLong, 0,
IP16L32: LongLong, 0,
LP32: LongLong, 8,
ILP32: LongLong, 8,
LLP64: LongLong, 8,
LP64: LongLong, 8,
ILP64: LongLong, 8,
SILP64: LongLong, 8,
Unknown: LongLong, 0
}
}
#[test]
fn test_pointer() {
sizeof_check! {
IP16: Pointer, 2,
IP16L32: Pointer, 2,
LP32: Pointer, 4,
ILP32: Pointer, 4,
LLP64: Pointer, 8,
LP64: Pointer, 8,
ILP64: Pointer, 8,
SILP64: Pointer, 8,
Unknown: Pointer, 0
}
}
#[test]
fn test_new() {
assert_eq!(DataModel::IP16, DataModel::new(2, 0, 2));
assert_eq!(DataModel::IP16L32, DataModel::new(2, 4, 2));
assert_eq!(DataModel::LP32, DataModel::new(2, 4, 4));
assert_eq!(DataModel::ILP32, DataModel::new(4, 4, 4));
assert_eq!(DataModel::LLP64, DataModel::new(4, 4, 8));
assert_eq!(DataModel::LP64, DataModel::new(4, 8, 8));
assert_eq!(DataModel::ILP64, DataModel::new(8, 8, 8));
}
}