//! 当前slab分配器暂时不使用，等待后续完善后合并主线
#![allow(dead_code)]

use core::alloc::Layout;

// 定义Slab，用来存放空闲块
pub struct Slab {
    block_size: usize,
    free_block_list: FreeBlockList,
}

impl Slab {
    /// @brief: 初始化一个slab
    /// @param {usize} start_addr
    /// @param {usize} slab_size
    /// @param {usize} block_size
    pub unsafe fn new(start_addr: usize, slab_size: usize, block_size: usize) -> Slab {
        let blocks_num = slab_size / block_size;
        return Slab {
            block_size: block_size,
            free_block_list: FreeBlockList::new(start_addr, block_size, blocks_num),
        };
    }

    /// @brief: 获取slab中可用的block数
    pub fn used_blocks(&self) -> usize {
        return self.free_block_list.len();
    }

    /// @brief: 扩大free_block_list
    /// @param {*} mut
    /// @param {usize} start_addr
    /// @param {usize} slab_size
    pub fn grow(&mut self, start_addr: usize, slab_size: usize) {
        let num_of_blocks = slab_size / self.block_size;
        let mut block_list =
            unsafe { FreeBlockList::new(start_addr, self.block_size, num_of_blocks) };
        // 将新链表接到原链表的后面
        while let Some(block) = block_list.pop() {
            self.free_block_list.push(block);
        }
    }
    /// @brief: 从slab中分配一个block
    /// @return 分配的内存地址
    pub fn allocate(&mut self, _layout: Layout) -> Option<*mut u8> {
        match self.free_block_list.pop() {
            Some(block) => return Some(block.addr() as *mut u8),
            None => return None,
        }
    }
    /// @brief: 将block归还给slab
    pub fn free(&mut self, ptr: *mut u8) {
        let ptr = ptr as *mut FreeBlock;
        unsafe {
            self.free_block_list.push(&mut *ptr);
        }
    }
}
/// slab中的空闲块
struct FreeBlockList {
    len: usize,
    head: Option<&'static mut FreeBlock>,
}

impl FreeBlockList {
    unsafe fn new(start_addr: usize, block_size: usize, num_of_blocks: usize) -> FreeBlockList {
        let mut new_list = FreeBlockList::new_empty();
        for i in (0..num_of_blocks).rev() {
            // 从后往前分配，避免内存碎片
            let new_block = (start_addr + i * block_size) as *mut FreeBlock;
            new_list.push(&mut *new_block);
        }
        return new_list;
    }

    fn new_empty() -> FreeBlockList {
        return FreeBlockList { len: 0, head: None };
    }

    fn len(&self) -> usize {
        return self.len;
    }

    /// @brief: 将空闲块从链表中弹出
    fn pop(&mut self) -> Option<&'static mut FreeBlock> {
        // 从链表中弹出一个空闲块
        let block = self.head.take().map(|node| {
            self.head = node.next.take();
            self.len -= 1;
            node
        });
        return block;
    }

    /// @brief: 将空闲块压入链表
    fn push(&mut self, free_block: &'static mut FreeBlock) {
        free_block.next = self.head.take();
        self.len += 1;
        self.head = Some(free_block);
    }

    fn is_empty(&self) -> bool {
        return self.head.is_none();
    }
}

impl Drop for FreeBlockList {
    fn drop(&mut self) {
        while let Some(_) = self.pop() {}
    }
}

struct FreeBlock {
    next: Option<&'static mut FreeBlock>,
}

impl FreeBlock {
    /// @brief: 获取FreeBlock的地址
    /// @return {*}
    fn addr(&self) -> usize {
        return self as *const _ as usize;
    }
}
