use std::{any::Any, fmt::Debug};
use tokio::sync::oneshot;
use crate::buffers::DynBuf;
pub struct Boomerang<T> {
inner: Option<(T, oneshot::Sender<T>)>,
}
impl<T> Boomerang<T> {
pub fn new(t: T) -> (Self, oneshot::Receiver<T>) {
let (sender, receiver) = oneshot::channel();
let boomerang = Self {
inner: Some((t, sender)),
};
(boomerang, receiver)
}
}
impl<T: Debug> Debug for Boomerang<T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Boomerang").field("inner", &self.inner).finish()
}
}
impl<T> Drop for Boomerang<T> {
fn drop(&mut self) {
let (t, sender) = self.inner.take().unwrap();
let _ = sender.send(t);
}
}
impl<T> DynBuf for Boomerang<T>
where
T: DynBuf + 'static,
{
fn as_slice(&self) -> &[u8] {
self.inner.as_ref().unwrap().0.as_slice()
}
fn as_any(&self) -> &dyn Any {
self
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_boomerang() {
let value = vec![1, 2, 3, 4, 5];
let (boomerang, mut receiver) = Boomerang::new(value.clone());
drop(boomerang);
let returned = receiver.try_recv().unwrap();
assert_eq!(returned, value);
let num = 42;
let (boomerang, mut receiver) = Boomerang::new(num);
drop(boomerang);
let returned = receiver.try_recv().unwrap();
assert_eq!(returned, num);
let text = String::from("hello world");
let (boomerang, mut receiver) = Boomerang::new(text.clone());
drop(boomerang);
let returned = receiver.try_recv().unwrap();
assert_eq!(returned, text);
let buffer = vec![0u8; 1024];
let (boomerang, mut receiver) = Boomerang::new(buffer);
drop(boomerang);
let returned = receiver.try_recv().unwrap();
assert_eq!(returned.len(), 1024);
assert!(returned.iter().all(|&x| x == 0));
let v1 = vec![1, 2];
let v2 = vec![3, 4];
let v3 = vec![5, 6];
let (b1, mut r1) = Boomerang::new(v1.clone());
let (b2, mut r2) = Boomerang::new(v2.clone());
let (b3, mut r3) = Boomerang::new(v3.clone());
drop(b1);
drop(b2);
drop(b3);
assert_eq!(r1.try_recv().unwrap(), v1);
assert_eq!(r2.try_recv().unwrap(), v2);
assert_eq!(r3.try_recv().unwrap(), v3);
}
#[test]
fn test_boomerang_with_dynbuf() {
let data = vec![1u8, 2, 3, 4, 5];
let (boomerang, mut receiver) = Boomerang::new(data.clone());
assert_eq!(boomerang.as_slice(), &[1, 2, 3, 4, 5]);
let _any = boomerang.as_any();
drop(boomerang);
let returned = receiver.try_recv().unwrap();
assert_eq!(returned, data);
let large_data = vec![42u8; 10000];
let (boomerang, mut receiver) = Boomerang::new(large_data.clone());
assert_eq!(boomerang.as_slice().len(), 10000);
assert!(boomerang.as_slice().iter().all(|&x| x == 42));
drop(boomerang);
let returned = receiver.try_recv().unwrap();
assert_eq!(returned.len(), 10000);
}
#[test]
fn test_boomerang_pool_pattern() {
let mut pool = Vec::new();
for _ in 0..3 {
pool.push(vec![0u8; 512]);
}
let buffer = pool.pop().unwrap();
let (boomerang, mut receiver) = Boomerang::new(buffer);
assert_eq!(boomerang.as_slice().len(), 512);
drop(boomerang);
let returned_buffer = receiver.try_recv().unwrap();
pool.push(returned_buffer);
assert_eq!(pool.len(), 3);
}
#[test]
fn test_boomerang_ordering() {
let (b1, mut r1) = Boomerang::new(1);
let (b2, mut r2) = Boomerang::new(2);
let (b3, mut r3) = Boomerang::new(3);
drop(b3);
drop(b2);
drop(b1);
let v1 = r1.try_recv().unwrap();
let v2 = r2.try_recv().unwrap();
let v3 = r3.try_recv().unwrap();
assert_eq!(v1, 1);
assert_eq!(v2, 2);
assert_eq!(v3, 3);
}
}