Skip to content

Commit

Permalink
feat(links): impl Links for more types
Browse files Browse the repository at this point in the history
  • Loading branch information
SebastianSpeitel committed Jan 24, 2024
1 parent 30aed54 commit cf16ae3
Show file tree
Hide file tree
Showing 3 changed files with 192 additions and 15 deletions.
2 changes: 1 addition & 1 deletion src/data/unique.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ pub trait Unique: Data {
}

/// Wrapper for Data with or without an `ID` to make it always `Unique`
pub struct Fixed<D: Data + ?Sized, T: Borrow<D>> {
pub struct Fixed<D: Data + ?Sized, T: Borrow<D> = D> {
data: T,
id: ID,
pd: PhantomData<D>,
Expand Down
64 changes: 50 additions & 14 deletions src/links.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
use crate::data::{BoxedData, Data};

mod impls;

pub mod prelude {
pub use super::Link;
pub use super::LinkError;
Expand Down Expand Up @@ -66,17 +68,12 @@ pub trait LinksExt: Links {

impl<T: Links + ?Sized> LinksExt for T {}

impl Links for Vec<(Option<BoxedData>, BoxedData)> {
#[inline]
fn push(&mut self, target: BoxedData, key: Option<BoxedData>) -> Result {
self.push((key, target));
Ok(())
}
}

pub trait Link {
fn key(&self) -> Option<&dyn Data>;
fn target(&self) -> &dyn Data;
type Target: Data + 'static;
type Key: Data + 'static;

fn target(&self) -> &Self::Target;
fn key(&self) -> Option<&Self::Key>;

fn build_into(self, links: &mut (impl Links + ?Sized)) -> Result;
}
Expand All @@ -85,13 +82,16 @@ impl<T> Link for T
where
T: Data + 'static,
{
type Key = ();
type Target = T;

#[inline]
fn key(&self) -> Option<&dyn Data> {
fn key(&self) -> Option<&Self::Key> {
None
}

#[inline]
fn target(&self) -> &dyn Data {
fn target(&self) -> &Self::Target {
self
}

Expand All @@ -106,13 +106,16 @@ where
K: Data + 'static,
T: Data + 'static,
{
type Key = K;
type Target = T;

#[inline]
fn key(&self) -> Option<&dyn Data> {
fn key(&self) -> Option<&Self::Key> {
Some(&self.0)
}

#[inline]
fn target(&self) -> &dyn Data {
fn target(&self) -> &Self::Target {
&self.1
}

Expand All @@ -130,4 +133,37 @@ mod tests {
fn object_safety() {
fn _f(_l: &dyn Links) {}
}

#[test]
fn target_only() {
let mut links: Vec<BoxedData> = Vec::new();

let target = 42u32;
links.push_link(target).unwrap();
}

#[test]
fn target_and_key() {
let mut links: Vec<(BoxedData, BoxedData)> = Vec::new();

let target = 42u32;
let key = "foo";
links.push_link((key, target)).unwrap();
}

#[test]
fn ref_target() {
let mut links: Vec<BoxedData> = Vec::new();

let target = &42u32;
links.push_link(target).unwrap();
}

#[test]
fn option_target() {
let mut links: Vec<BoxedData> = Vec::new();

let target = Some(42u32);
links.push_link(target).unwrap();
}
}
141 changes: 141 additions & 0 deletions src/links/impls.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
use std::{
collections::{HashMap, HashSet},
hash::BuildHasher,
};

use super::{Links, Result};
use crate::data::{
unique::{Fixed, MaybeUnique},
BoxedData,
};

impl Links for Vec<(Option<BoxedData>, BoxedData)> {
#[inline]
fn push(&mut self, target: BoxedData, key: Option<BoxedData>) -> Result {
self.push((key, target));
Ok(())
}
}

impl Links for Vec<(BoxedData, BoxedData)> {
#[inline]
fn push(&mut self, target: BoxedData, key: Option<BoxedData>) -> Result {
if let Some(key) = key {
self.push((key, target));
}
Ok(())
}

#[inline]
fn push_unkeyed(&mut self, _target: BoxedData) -> Result {
Ok(())
}

#[inline]
fn push_keyed(&mut self, target: BoxedData, key: BoxedData) -> Result {
self.push((key, target));
Ok(())
}
}

impl Links for Vec<BoxedData> {
#[inline]
fn push(&mut self, target: BoxedData, _key: Option<BoxedData>) -> Result {
self.push(target);
Ok(())
}

#[inline]
fn push_unkeyed(&mut self, target: BoxedData) -> Result {
self.push(target);
Ok(())
}

#[inline]
fn push_keyed(&mut self, target: BoxedData, _key: BoxedData) -> Result {
self.push(target);
Ok(())
}
}

impl Links for Option<(BoxedData, BoxedData)> {
#[inline]
fn push(&mut self, target: BoxedData, key: Option<BoxedData>) -> Result {
if self.is_some() {
return Ok(());
}
if let Some(key) = key {
self.replace((key, target));
}
Ok(())
}
}

impl Links for Option<(Option<BoxedData>, BoxedData)> {
#[inline]
fn push(&mut self, target: BoxedData, key: Option<BoxedData>) -> Result {
if self.is_some() {
return Ok(());
}
self.replace((key, target));
Ok(())
}
}

impl Links for Option<BoxedData> {
#[inline]
fn push(&mut self, target: BoxedData, _key: Option<BoxedData>) -> Result {
if self.is_some() {
return Ok(());
}
self.replace(target);
Ok(())
}
}

impl<S: BuildHasher> Links for HashMap<Fixed<BoxedData>, BoxedData, S> {
#[inline]
fn push(&mut self, target: BoxedData, key: Option<BoxedData>) -> Result {
if let Some(key) = key {
if let Ok(key) = key.try_into_unique() {
self.insert(key, target);
}
}
Ok(())
}
#[inline]
fn push_unkeyed(&mut self, _target: BoxedData) -> Result {
Ok(())
}
#[inline]
fn push_keyed(&mut self, target: BoxedData, key: BoxedData) -> Result {
if let Ok(key) = key.try_into_unique() {
self.insert(key, target);
}
Ok(())
}
}

impl<S: BuildHasher> Links for HashSet<Fixed<BoxedData>, S> {
#[inline]
fn push(&mut self, target: BoxedData, _key: Option<BoxedData>) -> Result {
if let Ok(target) = target.try_into_unique() {
self.insert(target);
}
Ok(())
}
#[inline]
fn push_unkeyed(&mut self, target: BoxedData) -> Result {
if let Ok(target) = target.try_into_unique() {
self.insert(target);
}
Ok(())
}
#[inline]
fn push_keyed(&mut self, target: BoxedData, _key: BoxedData) -> Result {
if let Ok(target) = target.try_into_unique() {
self.insert(target);
}
Ok(())
}
}

0 comments on commit cf16ae3

Please sign in to comment.