1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
/// A wrapper for a slice of references.
///
/// Available only through a (possibly mutable) reference.
///
/// ## Usage
///
/// Can be created from (a (possibly mutable) reference to) a slice 
/// of (possibly mutable) references by means of the `From` trait or 
/// with the help of [`new`](#method.new) and [`new_mut`](#method.new_mut) 
/// functions.
///
/// The current version of the crate provides only a minimal viable interface: 
/// the distributive laws and the [`modify`](#method.modify) method.
///
/// To get a concrete reference (or a sublice) out of the `Slice` 
/// you can write
///
/// ```
/// # use multiref::Slice;
/// let (mut a, mut b, mut c, mut d) = (1, 2, 3, 4);
/// let mut array = [&mut a, &mut b, &mut c, &mut d];
/// let slice = Slice::new_mut(&mut array[..]);
///
/// // Very clumsy but works!
/// *slice.as_mut()[0] = 4;
/// *((&mut slice.as_mut()[1..3])[0]) = 5;
///
/// // Continuation-passing style is a little more convenient:
/// let forty_two = slice.modify(|real_slice| { *real_slice[2] = 6; 42 });
/// assert!(forty_two == 42);
///
/// // Modifications can be chained:
/// slice.modify(|real_slice| {
///     *real_slice[3] += 1;
///     Slice::new_mut(real_slice)
/// }).modify(|real_slice| { 
///     *real_slice[3] += 2; 
/// });
///
/// assert!(a == 4);
/// assert!(b == 5);
/// assert!(c == 6);
/// assert!(d == 7);
/// ```
///
/// Next versions of the crate are expected to provide
/// an interface analogous to the one of standard slices (unfortunately, 
/// the lazy solution, i.e. implementing the `Deref` trait,
/// can't be used, because of the necessary &-head of the type). 
#[repr(transparent)]
pub struct Slice<T: ?Sized> {
    _slice: [*const T],
}

impl<'a, 'x: 'a, T> From<&'a [&'x T]> for &'a Slice<T> where
    T: ?Sized,
{
    fn from(slice: &'a [&'x T]) -> Self {
        unsafe { &*(slice as *const _ as *const _) }
    }
}

impl<'a, 'x: 'a, T> From<&'a mut [&'x mut T]> for &'a mut Slice<T> where
    T: ?Sized,
{
    fn from(slice: &'a mut [&'x mut T]) -> Self {
        unsafe { &mut *(slice as *mut _ as *mut _) }
    }
}

impl<'a, T: ?Sized> Slice<T> {
    /// The same as `slice.into()`.
    pub fn new<'x:'a>( slice: &'a [&'x T] ) -> &'a Self {
        slice.into()
    }

    /// The original slice.
    pub fn as_ref(&'a self) -> &'a [&'a T] {
        unsafe { &*(self as *const _ as *const _) }
    }
    
    /// The same as `pair_ref.into()`.
    pub fn new_mut<'x:'a>( slice: &'a mut [&'x mut T] ) -> &'a mut Self {
        slice.into()
    }

    /// The original slice, mutable version.
    pub fn as_mut(&'a mut self) -> &'a mut [&'a mut T] {
        unsafe { &mut *(self as *mut _ as *mut _) }
    }

    /// Provides an access to the underlying slice of references via CPS.
    pub fn modify<R, F>(&'a mut self, f: F) -> R where
        F: FnOnce(&'a mut[&'a mut T]) -> R
    {
        f(self.as_mut())
    }
}