fat_type 0.3.0

A type which permits thin references to arrays and dynamic types.
Documentation
//
// Copyright (C) 2023 Nathan Sharp.
//
// This file is available under either the terms of the Apache License, Version
// 2.0 or the MIT License, at your discretion.
//

use crate::Fat;
use core::alloc::Layout;
use core::ops::Deref;

trait TestTrait {
    fn data_mut(&mut self) -> &mut usize;
}

#[repr(align(64))] // Use a large alignment to catch base pointer issues.
#[derive(Debug, Clone)]
struct TestStruct {
    pub data: usize,
}

impl TestStruct {
    pub fn new() -> Self {
        Self { data: 42 }
    }

    pub fn wrapped() -> Fat<dyn TestTrait, Self> {
        Fat::new(Self::new())
    }
}

impl TestTrait for TestStruct {
    fn data_mut(&mut self) -> &mut usize {
        &mut self.data
    }
}

#[test]
fn deref_fat() {
    let mut fat = TestStruct::wrapped();
    assert_eq!(*fat.data_mut(), 42);
    *fat.data_mut() = 43;
    assert_eq!(*fat.data_mut(), 43);
}

#[test]
fn deref_thin() {
    let mut fat = TestStruct::wrapped();
    let thin = Fat::erase_mut(&mut fat);

    assert_eq!(*thin.data_mut(), 42);
    *thin.data_mut() = 43;
    assert_eq!(*thin.data_mut(), 43);

    assert_eq!(*fat.data_mut(), 43);
}

#[test]
fn fat_layout() {
    assert_eq!(
        Fat::layout_of(&TestStruct::wrapped()).0,
        Layout::new::<Fat<dyn TestTrait, TestStruct>>()
    );
}

#[test]
fn thin_layout() {
    assert_eq!(
        Fat::layout_of(Fat::erase_ref(&TestStruct::wrapped())).0,
        Layout::new::<Fat<dyn TestTrait, TestStruct>>()
    );
}

#[test]
fn container_of() {
    let fat = TestStruct::wrapped();
    let thin = Fat::erase_ref(&fat);
    let ptr = unsafe { Fat::container_of(Deref::deref(thin)) };
    assert_eq!(thin as *const _, ptr.as_ptr());
}