use std::marker::PhantomData;
use crate::{MasterHandle, PrivateHandle};
#[derive(Debug)]
pub(crate) struct MasterFrameResource<T, PH> {
next: Option<PH>,
resource: T,
}
impl<T, PH: Copy> MasterFrameResource<T, PH> {
pub(crate) fn resource(&self) -> &T {
&self.resource
}
pub(crate) fn resource_mut(&mut self) -> &mut T {
&mut self.resource
}
pub(crate) fn into_inner(self) -> T {
self.resource
}
}
#[derive(Debug)]
pub(crate) struct ResourceCollection<T, MH, PH> {
resources: Vec<MasterFrameResource<T, PH>>,
master_handle_type: PhantomData<MH>,
}
impl<T, MH, PH> Default for ResourceCollection<T, MH, PH> {
fn default() -> Self {
Self {
resources: Vec::new(),
master_handle_type: PhantomData,
}
}
}
impl<T, MH: MasterHandle, PH: PrivateHandle> ResourceCollection<T, MH, PH> {
pub(crate) fn new() -> Self {
Self {
resources: Vec::new(),
master_handle_type: PhantomData,
}
}
pub(crate) fn with_capacity(capacity: usize) -> Self {
Self {
resources: Vec::with_capacity(capacity),
master_handle_type: PhantomData,
}
}
pub(crate) fn add(&mut self, resource: T) -> (MH, PH) {
let i = self.resources.len() as u64;
let master_handle = MH::new(i);
let private_handle = PH::new(i);
self.resources.push(MasterFrameResource { next: None, resource });
(master_handle, private_handle)
}
pub(crate) fn add_with_master(&mut self, resource: T, master_handle: MH) -> PH {
let i = master_handle.index();
let private_handle = PH::new(i);
self.resources.push(MasterFrameResource { next: None, resource });
private_handle
}
pub(crate) fn set_next(&mut self, private_handle: PH, next: Option<PH>) {
self.entry_mut(private_handle).next = next;
}
fn entry(&self, private_handle: PH) -> &MasterFrameResource<T, PH> {
self.resources
.get(private_handle.index() as usize)
.expect("Invalid private handle. The most likely cause is that the handle was not created by this storage.")
}
fn entry_mut(&mut self, private_handle: PH) -> &mut MasterFrameResource<T, PH> {
self.resources
.get_mut(private_handle.index() as usize)
.expect("Invalid private handle. The most likely cause is that the handle was not created by this storage.")
}
pub(crate) fn resource(&self, private_handle: PH) -> &T {
&self.entry(private_handle).resource
}
pub(crate) fn resource_mut(&mut self, private_handle: PH) -> &mut T {
&mut self.entry_mut(private_handle).resource
}
pub(crate) fn get_single(&self, handle: MH) -> Option<&T> {
self.resources.get(handle.index() as usize).map(|r| &r.resource)
}
pub(crate) fn get_nth(&self, handle: MH, frame_offset: usize) -> Option<&T> {
self.nth_handle(handle, frame_offset).map(|handle| self.resource(handle))
}
pub(crate) fn nth_handle(&self, handle: MH, frame_offset: usize) -> Option<PH> {
let mut current = PH::new(handle.index());
let mut i = 0;
while i < frame_offset {
if let Some(next) = self.entry(current).next {
current = next;
} else {
break;
}
i += 1;
}
Some(current)
}
pub(crate) fn iter(&self) -> impl Iterator<Item = &T> {
self.resources.iter().map(|r| &r.resource)
}
pub(crate) fn creator<'a>(&'a mut self) -> Creator<'a, T, MH, PH> {
let mh = MH::new(self.resources.len() as _);
Creator::new(&mut self.resources, mh)
}
pub(crate) fn master(&self) -> MH {
MH::new(self.resources.len() as _)
}
}
pub(crate) struct Creator<'a, T, MH, PH> {
resources: &'a mut Vec<MasterFrameResource<T, PH>>,
handle: MH,
}
impl<'a, T, MH: MasterHandle, PH: PrivateHandle> Creator<'a, T, MH, PH> {
pub(crate) fn new(resources: &'a mut Vec<MasterFrameResource<T, PH>>, handle: MH) -> Self {
Self { resources, handle }
}
pub(crate) fn add(&mut self, resource: T) -> PH {
let private_handle = PH::new(self.resources.len() as u64);
self.resources.push(MasterFrameResource { next: None, resource });
let mut current = PH::new(self.handle.index());
while let Some(last) = self.resources.get_mut(current.index() as usize).unwrap().next {
current = last;
}
self.resources.get_mut(current.index() as usize).unwrap().next = Some(private_handle);
private_handle
}
pub(crate) fn into(self) -> MH {
self.handle
}
}
#[cfg(test)]
mod tests {
use crate::{MasterHandle, PrivateHandle};
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
struct TestMasterHandle(u64);
impl MasterHandle for TestMasterHandle {
fn new(i: u64) -> Self {
Self(i)
}
fn index(&self) -> u64 {
self.0
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
struct TestPrivateHandle(u64);
impl PrivateHandle for TestPrivateHandle {
fn new(i: u64) -> Self {
Self(i)
}
fn index(&self) -> u64 {
self.0
}
}
#[test]
fn nth_handle_returns_first_resource_for_frame_zero() {
let mut resources = super::ResourceCollection::<&'static str, TestMasterHandle, TestPrivateHandle>::new();
let (master, first) = resources.add("frame 0");
let (_, second) = resources.add("frame 1");
resources.set_next(first, Some(second));
assert_eq!(resources.get_nth(master, 0), Some(&"frame 0"));
assert_eq!(resources.get_nth(master, 1), Some(&"frame 1"));
}
#[test]
fn nth_handle_reuses_last_resource_when_chain_is_shorter_than_frames() {
let mut resources = super::ResourceCollection::<&'static str, TestMasterHandle, TestPrivateHandle>::new();
let (master, _) = resources.add("single");
assert_eq!(resources.get_nth(master, 0), Some(&"single"));
assert_eq!(resources.get_nth(master, 3), Some(&"single"));
}
}