use std::{mem::transmute, ptr::NonNull};
use crate::{
mem::{header::LinksHeader, split::DataPart, traits::SplitList, LinksList, SplitUpdateMem},
split::IndexPart,
};
use data::LinkReference;
use trees::{AbsoluteCircularLinkedList, AbsoluteLinkedList, LinkedList};
pub struct UnusedLinks<T: LinkReference> {
links: NonNull<[DataPart<T>]>,
header: NonNull<[IndexPart<T>]>,
}
impl<T: LinkReference> UnusedLinks<T> {
#[must_use]
pub fn new(links: NonNull<[DataPart<T>]>, header: NonNull<[IndexPart<T>]>) -> Self {
Self { links, header }
}
fn get_header(&self) -> &LinksHeader<T> {
unsafe { transmute(&self.header.as_ref()[0]) }
}
fn get_mut_header(&mut self) -> &mut LinksHeader<T> {
unsafe { transmute(&mut self.header.as_mut()[0]) }
}
fn get_link(&self, link: T) -> &DataPart<T> {
unsafe { &self.links.as_ref()[link.as_()] }
}
fn get_mut_link(&mut self, link: T) -> &mut DataPart<T> {
unsafe { &mut self.links.as_mut()[link.as_()] }
}
}
impl<T: LinkReference> AbsoluteLinkedList<T> for UnusedLinks<T> {
fn get_first(&self) -> T {
self.get_header().first_free
}
fn get_last(&self) -> T {
self.get_header().last_free
}
fn get_size(&self) -> T {
self.get_header().free
}
fn set_first(&mut self, element: T) {
self.get_mut_header().first_free = element;
}
fn set_last(&mut self, element: T) {
self.get_mut_header().last_free = element;
}
fn set_size(&mut self, size: T) {
self.get_mut_header().free = size;
}
}
impl<T: LinkReference> LinkedList<T> for UnusedLinks<T> {
fn get_previous(&self, element: T) -> T {
self.get_link(element).source
}
fn get_next(&self, element: T) -> T {
self.get_link(element).target
}
fn set_previous(&mut self, element: T, previous: T) {
self.get_mut_link(element).source = previous;
}
fn set_next(&mut self, element: T, next: T) {
self.get_mut_link(element).target = next;
}
}
impl<T: LinkReference> AbsoluteCircularLinkedList<T> for UnusedLinks<T> {}
impl<T: LinkReference> SplitUpdateMem<T> for UnusedLinks<T> {
fn update_mem(&mut self, data: NonNull<[DataPart<T>]>, index: NonNull<[IndexPart<T>]>) {
self.links = data;
self.header = index;
}
}
impl<T: LinkReference> LinksList<T> for UnusedLinks<T> {
fn detach(&mut self, link: T) {
AbsoluteCircularLinkedList::detach(self, link);
}
fn attach_as_first(&mut self, link: T) {
AbsoluteCircularLinkedList::attach_as_first(self, link);
}
}
impl<T: LinkReference> SplitList<T> for UnusedLinks<T> {}