use alloc::borrow::Cow;
use alloc::sync::Arc;
use alloc::vec::Vec;
use core::any::Any;
use core::fmt;
#[derive(Clone)]
pub(crate) struct RefParam(pub(crate) Arc<dyn Any + Send + Sync>);
impl fmt::Debug for RefParam {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str("RefParam")
}
}
impl PartialEq for RefParam {
fn eq(&self, other: &Self) -> bool {
Arc::ptr_eq(&self.0, &other.0)
}
}
#[derive(Clone, Debug, Default, PartialEq)]
pub(crate) struct LocalParams {
pub(crate) ints: Cow<'static, [(i32, i32)]>,
pub(crate) copies: Vec<(i32, Arc<[u8]>)>,
pub(crate) refs: Vec<(i32, RefParam)>,
}
impl LocalParams {
pub(crate) const EMPTY: Self = Self {
ints: Cow::Borrowed(&[]),
copies: Vec::new(),
refs: Vec::new(),
};
pub(crate) fn is_empty(&self) -> bool {
self.ints.is_empty() && self.copies.is_empty() && self.refs.is_empty()
}
pub(crate) fn int(&self, id: i32) -> Option<i32> {
self.ints
.iter()
.find(|&&(key, _)| key == id)
.map(|&(_, value)| value)
}
pub(crate) fn copy(&self, id: i32) -> Option<&[u8]> {
self.copies
.iter()
.find(|(key, _)| *key == id)
.map(|(_, bytes)| &**bytes)
}
pub(crate) fn reference(&self, id: i32) -> Option<&(dyn Any + Send + Sync)> {
self.refs
.iter()
.find(|(key, _)| *key == id)
.map(|(_, object)| &*object.0)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn lookups_return_the_first_match() {
let object: Arc<dyn Any + Send + Sync> = Arc::new(7u32);
let params = LocalParams {
ints: Cow::Owned(alloc::vec![(1, 10), (1, 20), (2, 30)]),
copies: alloc::vec![(5, Arc::from(&b"xy"[..]))],
refs: alloc::vec![(9, RefParam(Arc::clone(&object)))],
};
assert!(!params.is_empty());
assert!(LocalParams::EMPTY.is_empty());
assert_eq!(
(params.int(1), params.int(2), params.int(3)),
(Some(10), Some(30), None)
);
assert_eq!(params.copy(5), Some(&b"xy"[..]));
assert_eq!(params.copy(6), None);
let found = params.reference(9).unwrap();
assert_eq!(found.downcast_ref::<u32>(), Some(&7));
assert!(params.reference(8).is_none());
assert_eq!(params.refs[0].1, RefParam(object));
assert_eq!(alloc::format!("{:?}", params.refs[0].1), "RefParam");
}
}