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
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
use core::{
    borrow::Borrow,
    fmt,
    fmt::{Binary, Debug, Display, Formatter, LowerExp, LowerHex, Octal, UpperExp, UpperHex},
    num::NonZeroUsize,
    ops::Deref,
};

use crate::{FromIndex, Idx, IntoIndex, NewIndex};

/// This is partly like [`Cow`], but the 'owned' type is always the same as the
/// 'borrowed' type.
///
/// [`Cow`]: alloc::borrow::Cow
#[derive(Copy, Clone)]
pub enum Key<'a, T> {
    Owned(T),
    Borrowed(&'a T),
}

#[cfg(feature = "imm_gc")]
unsafe impl<T: imm_gc::Trace> imm_gc::Trace for Key<'_, T> {
    unsafe fn untrace(&self) {
        unsafe {
            match *self {
                Key::Owned(ref t) => t.untrace(),
                Key::Borrowed(ref t) => t.untrace(),
            }
        }
    }

    unsafe fn trace(&self) {
        unsafe {
            match *self {
                Key::Owned(ref t) => t.trace(),
                Key::Borrowed(ref t) => t.trace(),
            }
        }
    }

    unsafe fn set_undone(&self) {
        unsafe {
            match *self {
                Key::Owned(ref t) => t.set_undone(),
                Key::Borrowed(ref t) => t.set_undone(),
            }
        }
    }

    fn counts_match(&self) -> bool {
        match *self {
            Key::Owned(ref t) => t.counts_match(),
            Key::Borrowed(ref t) => t.counts_match(),
        }
    }
}

#[cfg(feature = "bacon_rajan_cc")]
impl<T: bacon_rajan_cc::Trace> bacon_rajan_cc::Trace for Key<'_, T> {
    fn trace(&self, t: &mut bacon_rajan_cc::Tracer) {
        match *self {
            Key::Owned(ref k) => k.trace(t),
            Key::Borrowed(ref k) => k.trace(t),
        }
    }
}

impl<T> Deref for Key<'_, T> {
    type Target = T;
    fn deref(&self) -> &T {
        match *self {
            Key::Owned(ref t) | Key::Borrowed(&ref t) => t,
        }
    }
}

impl<T> Borrow<T> for Key<'_, T> {
    fn borrow(&self) -> &T {
        self
    }
}

impl<T: IntoIndex> IntoIndex for Key<'_, T> {
    fn into_index(&self) -> Option<Idx<Self>> {
        Some(T::into_index(self)?.cast_safe())
    }
}

impl<T: FromIndex> FromIndex for Key<'_, T> {
    fn from_index(v: Idx<Self>) -> Self {
        Self::Owned(T::from_index(unsafe { v.cast() }))
    }
}

unsafe impl<T: NewIndex> NewIndex for Key<'_, T> {
    fn new_index_allowed(idx: NonZeroUsize) -> bool {
        T::new_index_allowed(idx)
    }
}

// All the formatting traits

impl<T: Display> Display for Key<'_, T> {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        Display::fmt(&**self, f)
    }
}

impl<T: Debug> Debug for Key<'_, T> {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        Debug::fmt(&**self, f)
    }
}

impl<T: Binary> Binary for Key<'_, T> {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        Binary::fmt(&**self, f)
    }
}

impl<T: LowerExp> LowerExp for Key<'_, T> {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        LowerExp::fmt(&**self, f)
    }
}

impl<T: LowerHex> LowerHex for Key<'_, T> {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        LowerHex::fmt(&**self, f)
    }
}

impl<T: Octal> Octal for Key<'_, T> {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        Octal::fmt(&**self, f)
    }
}

impl<T: UpperExp> UpperExp for Key<'_, T> {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        UpperExp::fmt(&**self, f)
    }
}

impl<T: UpperHex> UpperHex for Key<'_, T> {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        UpperHex::fmt(&**self, f)
    }
}