calcit_fingertrees/
reference.rs

1use std::ops::Deref;
2use std::rc::Rc;
3use std::sync::Arc;
4
5use crate::measure::Measured;
6use crate::node::NodeInner;
7use crate::tree::TreeInner;
8
9/// Interface that all reference types should impelmenet
10pub trait Ref: Clone + Deref
11where
12    Self::Target: Sized,
13{
14    /// Construct reference from target type
15    fn new(value: Self::Target) -> Self;
16}
17
18impl<T> Ref for Rc<T> {
19    fn new(value: Self::Target) -> Self {
20        Rc::new(value)
21    }
22}
23
24impl<T> Ref for Arc<T> {
25    fn new(value: Self::Target) -> Self {
26        Arc::new(value)
27    }
28}
29
30/// Interface which defines all reference types needed by finger tree implementation.
31///
32/// By implementing this interface for your reference type you can use finger treee
33/// with your reference type.
34///
35/// # Example:
36/// ```
37/// use std::rc::Rc;
38/// use std::ops::Deref;
39/// use calcit_fingertrees::measure::Size;
40/// use calcit_fingertrees::{FingerTree, Measured, Ref, fingertree_define_refs};
41///
42/// // your custom reference type
43/// struct MyRef<T>(Rc<T>);
44///
45/// impl<T> Clone for MyRef<T> {
46///     fn clone(&self) -> Self {
47///         MyRef(self.0.clone())
48///     }
49/// }
50///
51/// impl<T> Deref for MyRef<T> {
52///     type Target = T;
53///     fn deref(&self) -> &T {
54///         &*self.0
55///     }
56/// }
57///
58/// impl<T> Ref for MyRef<T> {
59///     fn new(value: T) -> Self {
60///         MyRef(Rc::new(value))
61///     }
62/// }
63///
64/// // define type family for your reference
65/// fingertree_define_refs!(MyRefs, MyRef);
66///
67/// // now you can construct fingertree using your reference type
68/// let _: FingerTree<MyRefs, _> = (0..128).map(Size).collect();
69/// ```
70pub trait Refs<V>: Sized
71where
72    V: Measured,
73{
74    /// Reference on a `Node`
75    type Node: Ref<Target = NodeInner<Self, V>>;
76    /// Reference on a `Tree`
77    type Tree: Ref<Target = TreeInner<Self, V>>;
78}
79
80/// Helper macro to define custom [`Refs`](trait.Refs.html) for `FingerTree`
81#[macro_export]
82macro_rules! fingertree_define_refs {
83    (pub $refs:ident, $ref:ident) => {
84        /// References type family
85        pub enum $refs {}
86        fingertree_define_refs!(@refs_impl $refs, $ref);
87    };
88
89    ($refs:ident, $ref:ident) => {
90        /// References type family
91        enum $refs {}
92        fingertree_define_refs!(@refs_impl $refs, $ref);
93    };
94
95    (@refs_impl $refs:ident, $ref:ident) => {
96        impl<V> $crate::Refs<V> for $refs
97        where
98            V: $crate::measure::Measured,
99        {
100            type Node = $ref<$crate::NodeInner<Self, V>>;
101            type Tree = $ref<$crate::TreeInner<Self, V>>;
102        }
103    };
104}
105
106fingertree_define_refs!(pub RcRefs, Rc);
107fingertree_define_refs!(pub ArcRefs, Arc);