use core::marker::PhantomData;
#[cfg(feature = "alloc")]
use alloc::collections::BTreeMap;
#[cfg(feature = "alloc")]
use alloc::vec::Vec;
pub trait Ad<I> {
type Value;
fn ad(&self, index: I) -> Option<&Self::Value>;
fn ad_mut(&mut self, index: I) -> Option<&mut Self::Value>;
#[inline]
fn continet(&self, index: I) -> bool {
self.ad(index).is_some()
}
}
pub trait AdRemovere<I>: Ad<I> {
fn removere(&mut self, index: I) -> Option<Self::Value>;
#[inline]
fn sine(&mut self, index: I) -> &mut Self
where
Self: Sized,
{
self.removere(index);
self
}
}
pub trait AdInserere<I>: Ad<I> {
fn inserere(&mut self, index: I, value: Self::Value) -> Option<Self::Value>;
}
#[cfg(feature = "alloc")]
impl<K: Ord, V> Ad<K> for BTreeMap<K, V> {
type Value = V;
#[inline]
fn ad(&self, index: K) -> Option<&Self::Value> {
self.get(&index)
}
#[inline]
fn ad_mut(&mut self, index: K) -> Option<&mut Self::Value> {
self.get_mut(&index)
}
#[inline]
fn continet(&self, index: K) -> bool {
self.contains_key(&index)
}
}
#[cfg(feature = "alloc")]
impl<K: Ord, V> AdRemovere<K> for BTreeMap<K, V> {
#[inline]
fn removere(&mut self, index: K) -> Option<Self::Value> {
self.remove(&index)
}
}
#[cfg(feature = "alloc")]
impl<K: Ord, V> AdInserere<K> for BTreeMap<K, V> {
#[inline]
fn inserere(&mut self, index: K, value: Self::Value) -> Option<Self::Value> {
self.insert(index, value)
}
}
#[cfg(feature = "alloc")]
impl<T> Ad<usize> for Vec<T> {
type Value = T;
#[inline]
fn ad(&self, index: usize) -> Option<&Self::Value> {
self.get(index)
}
#[inline]
fn ad_mut(&mut self, index: usize) -> Option<&mut Self::Value> {
self.get_mut(index)
}
#[inline]
fn continet(&self, index: usize) -> bool {
index < self.len()
}
}
impl<T> Ad<usize> for [T] {
type Value = T;
#[inline]
fn ad(&self, index: usize) -> Option<&Self::Value> {
self.get(index)
}
#[inline]
fn ad_mut(&mut self, index: usize) -> Option<&mut Self::Value> {
self.get_mut(index)
}
#[inline]
fn continet(&self, index: usize) -> bool {
index < self.len()
}
}
impl<T, const N: usize> Ad<usize> for [T; N] {
type Value = T;
#[inline]
fn ad(&self, index: usize) -> Option<&Self::Value> {
self.get(index)
}
#[inline]
fn ad_mut(&mut self, index: usize) -> Option<&mut Self::Value> {
self.get_mut(index)
}
#[inline]
fn continet(&self, index: usize) -> bool {
index < N
}
}
pub struct AspectusAd<C, I, V>
where
C: Ad<I, Value = V>,
I: Clone,
{
index: I,
_phantom: PhantomData<fn(C) -> V>,
}
impl<C, I, V> Clone for AspectusAd<C, I, V>
where
C: Ad<I, Value = V>,
I: Clone,
{
fn clone(&self) -> Self {
AspectusAd {
index: self.index.clone(),
_phantom: PhantomData,
}
}
}
impl<C, I, V> AspectusAd<C, I, V>
where
C: Ad<I, Value = V>,
I: Clone,
{
#[inline]
pub fn new(index: I) -> Self {
AspectusAd {
index,
_phantom: PhantomData,
}
}
#[inline]
pub fn index(&self) -> &I {
&self.index
}
#[inline]
pub fn preview<'a>(&self, container: &'a C) -> Option<&'a V> {
container.ad(self.index.clone())
}
#[inline]
pub fn preview_mut<'a>(&self, container: &'a mut C) -> Option<&'a mut V> {
container.ad_mut(self.index.clone())
}
#[inline]
pub fn has_value(&self, container: &C) -> bool {
container.continet(self.index.clone())
}
#[inline]
pub fn modify<F>(&self, container: &mut C, f: F)
where
F: FnOnce(&mut V),
{
if let Some(v) = container.ad_mut(self.index.clone()) {
f(v);
}
}
#[inline]
pub fn set(&self, container: &mut C, value: V) {
if let Some(v) = container.ad_mut(self.index.clone()) {
*v = value;
}
}
}
impl<C, I, V> AspectusAd<C, I, V>
where
C: AdInserere<I, Value = V>,
I: Clone,
{
#[inline]
pub fn upsert(&self, container: &mut C, value: V) {
container.inserere(self.index.clone(), value);
}
}
impl<C, I, V> AspectusAd<C, I, V>
where
C: AdRemovere<I, Value = V>,
I: Clone,
{
#[inline]
pub fn remove(&self, container: &mut C) -> Option<V> {
container.removere(self.index.clone())
}
}
#[inline]
pub fn aspectus_ad<C, I, V>(index: I) -> AspectusAd<C, I, V>
where
C: Ad<I, Value = V>,
I: Clone,
{
AspectusAd::new(index)
}
pub trait AdExt<I>: Ad<I> + Sized {
#[inline]
fn aspectus_at(index: I) -> AspectusAd<Self, I, Self::Value>
where
I: Clone,
{
AspectusAd::new(index)
}
}
impl<T, I> AdExt<I> for T where T: Ad<I> {}
pub trait Ix<I> {
type IxValue;
fn ix(&self, index: I) -> Option<&Self::IxValue>;
fn ix_mut(&mut self, index: I) -> Option<&mut Self::IxValue>;
}
impl<T, I> Ix<I> for T
where
T: Ad<I>,
{
type IxValue = T::Value;
fn ix(&self, index: I) -> Option<&Self::IxValue> {
self.ad(index)
}
fn ix_mut(&mut self, index: I) -> Option<&mut Self::IxValue> {
self.ad_mut(index)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[cfg(feature = "alloc")]
use alloc::vec;
#[test]
#[cfg(feature = "alloc")]
fn test_btree_map_ad() {
let mut map = BTreeMap::new();
map.insert("foo", 42);
map.insert("bar", 100);
assert_eq!(map.ad("foo"), Some(&42));
assert_eq!(map.ad("baz"), None);
assert!(map.continet("foo"));
assert!(!map.continet("baz"));
}
#[test]
#[cfg(feature = "alloc")]
fn test_btree_map_ad_mut() {
let mut map = BTreeMap::new();
map.insert("foo", 42);
if let Some(v) = map.ad_mut("foo") {
*v = 100;
}
assert_eq!(map.ad("foo"), Some(&100));
}
#[test]
#[cfg(feature = "alloc")]
fn test_btree_map_removere() {
let mut map = BTreeMap::new();
map.insert("foo", 42);
let removed = map.removere("foo");
assert_eq!(removed, Some(42));
assert!(!map.continet("foo"));
}
#[test]
#[cfg(feature = "alloc")]
fn test_btree_map_inserere() {
let mut map = BTreeMap::new();
map.insert("foo", 42);
let old = map.inserere("foo", 100);
assert_eq!(old, Some(42));
assert_eq!(map.ad("foo"), Some(&100));
let old2 = map.inserere("bar", 200);
assert_eq!(old2, None);
assert_eq!(map.ad("bar"), Some(&200));
}
#[test]
#[cfg(feature = "alloc")]
fn test_vec_ad() {
let vec = vec![10, 20, 30];
assert_eq!(vec.ad(0), Some(&10));
assert_eq!(vec.ad(1), Some(&20));
assert_eq!(vec.ad(3), None);
assert!(vec.continet(0));
assert!(!vec.continet(10));
}
#[test]
#[cfg(feature = "alloc")]
fn test_vec_ad_mut() {
let mut vec = vec![10, 20, 30];
if let Some(v) = vec.ad_mut(1) {
*v = 25;
}
assert_eq!(vec, vec![10, 25, 30]);
}
#[test]
fn test_slice_ad() {
let slice: &[i32] = &[10, 20, 30];
assert_eq!(slice.ad(0), Some(&10));
assert_eq!(slice.ad(3), None);
}
#[test]
fn test_array_ad() {
let arr = [10, 20, 30];
assert_eq!(arr.ad(0), Some(&10));
assert_eq!(arr.ad(3), None);
assert!(arr.continet(0));
assert!(!arr.continet(5));
}
#[test]
#[cfg(feature = "alloc")]
fn test_aspectus_ad_preview() {
let mut map = BTreeMap::new();
map.insert("key", 42);
let at_key = aspectus_ad::<BTreeMap<&str, i32>, &str, i32>("key");
assert_eq!(at_key.preview(&map), Some(&42));
let at_missing = aspectus_ad::<BTreeMap<&str, i32>, &str, i32>("missing");
assert_eq!(at_missing.preview(&map), None);
}
#[test]
#[cfg(feature = "alloc")]
fn test_aspectus_ad_modify() {
let mut map = BTreeMap::new();
map.insert("key", 42);
let at_key = aspectus_ad::<BTreeMap<&str, i32>, &str, i32>("key");
at_key.modify(&mut map, |v| *v *= 2);
assert_eq!(map.get("key"), Some(&84));
}
#[test]
#[cfg(feature = "alloc")]
fn test_aspectus_ad_upsert() {
let mut map: BTreeMap<&str, i32> = BTreeMap::new();
let at_key = aspectus_ad::<BTreeMap<&str, i32>, &str, i32>("key");
at_key.upsert(&mut map, 42);
assert_eq!(map.get("key"), Some(&42));
}
#[test]
#[cfg(feature = "alloc")]
fn test_aspectus_ad_remove() {
let mut map = BTreeMap::new();
map.insert("key", 42);
let at_key = aspectus_ad::<BTreeMap<&str, i32>, &str, i32>("key");
let removed = at_key.remove(&mut map);
assert_eq!(removed, Some(42));
assert!(!map.contains_key("key"));
}
#[test]
#[cfg(feature = "alloc")]
fn test_ix_trait() {
let vec = vec![10, 20, 30];
assert_eq!(vec.ix(0), Some(&10));
assert_eq!(vec.ix(5), None);
}
}