use std::ops::{Deref, DerefMut};
pub struct SizedWrapper<SizeFunc, T>
where
SizeFunc: Fn(&T) -> usize,
{
pub key_func: SizeFunc,
pub item: T,
}
impl<SizeFunc, T> SizedWrapper<SizeFunc, T>
where
SizeFunc: Fn(&T) -> usize,
{
pub fn new(key_func: SizeFunc, item: T) -> Self {
Self { key_func, item }
}
pub fn take(self) -> T {
self.item
}
}
impl<SizeFunc, T> crate::Pack for SizedWrapper<SizeFunc, T>
where
SizeFunc: Fn(&T) -> usize,
{
fn size(&self) -> usize {
(self.key_func)(&self.item)
}
}
impl<F, T> Deref for SizedWrapper<F, T>
where
F: Fn(&T) -> usize,
{
type Target = T;
fn deref(&self) -> &Self::Target {
&self.item
}
}
impl<F, T> DerefMut for SizedWrapper<F, T>
where
F: Fn(&T) -> usize,
{
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.item
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn check_size_eq() {
let original = vec![1, 2, 3];
let wrapper = SizedWrapper::new(Vec::len, original.clone());
assert_eq!(
std::mem::size_of_val(&original),
std::mem::size_of_val(&wrapper)
);
let wrapper_weird = SizedWrapper::new(|_| 1, original.clone());
assert_eq!(
std::mem::size_of_val(&original),
std::mem::size_of_val(&wrapper_weird)
);
}
#[test]
fn check_size_when_combining() {
let original = vec![1, 2, 3];
let (sender, _recv) = std::sync::mpsc::channel();
let sender_size = std::mem::size_of_val(&sender);
let key_function = move |item: &Vec<i32>| {
sender.send(item.to_vec().clone()).unwrap();
item.iter().map(|v| *v as usize).sum()
};
let wrapper = SizedWrapper::new(key_function, original.clone());
assert_ne!(sender_size, 0);
assert_eq!(
std::mem::size_of_val(&original) + sender_size,
std::mem::size_of_val(&wrapper)
);
}
}