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
150
151
152
153
154
155
156
157
158
159
use core::mem;

use crate::pointer::{
    Marked::{self, Null, Value},
    NonNullable,
};
use crate::MarkedPointer;

////////////////////////////////////////////////////////////////////////////////////////////////////
// impl inherent
////////////////////////////////////////////////////////////////////////////////////////////////////

impl<T: NonNullable> Marked<T> {
    /// Returns `true` if the marked value contains a [`Value`].
    #[inline]
    pub fn is_value(&self) -> bool {
        match *self {
            Value(_) => true,
            _ => false,
        }
    }

    /// Returns `true` if the marked value is a [`Null`].
    #[inline]
    pub fn is_null(&self) -> bool {
        match *self {
            Null(_) => true,
            _ => false,
        }
    }

    /// Converts from `Marked<T>` to `Marked<&T>`.
    #[inline]
    pub fn as_ref(&self) -> Marked<&T> {
        match self {
            Value(value) => Value(value),
            Null(tag) => Null(*tag),
        }
    }

    /// Converts from `Marked<T>` to `Marked<&mut T>`.
    #[inline]
    pub fn as_mut(&mut self) -> Marked<&mut T> {
        match self {
            Value(value) => Value(value),
            Null(tag) => Null(*tag),
        }
    }

    /// Moves the pointer out of the `Marked` if it is [`Value(ptr)`][Value].
    #[inline]
    pub fn unwrap_value(self) -> T {
        match self {
            Value(ptr) => ptr,
            _ => panic!("called `Marked::unwrap_value()` on a `Null` value"),
        }
    }

    /// Extracts the tag out of the `Marked` if it is [`Null(tag)`][Null].
    #[inline]
    pub fn unwrap_null(self) -> usize {
        match self {
            Null(tag) => tag,
            _ => panic!("called `Marked::unwrap_tag()` on a `Value`"),
        }
    }

    /// Returns the contained value or the result of the given `func`.
    #[inline]
    pub fn unwrap_value_or_else(self, func: impl (FnOnce(usize) -> T)) -> T {
        match self {
            Value(ptr) => ptr,
            Null(tag) => func(tag),
        }
    }

    /// Maps a `Marked<T>` to `Marked<U>` by applying a function to a contained
    /// value.
    #[inline]
    pub fn map<U: NonNullable>(self, func: impl (FnOnce(T) -> U)) -> Marked<U> {
        match self {
            Value(ptr) => Value(func(ptr)),
            Null(tag) => Null(tag),
        }
    }

    /// Applies a function to the contained value (if any), or computes a
    /// default value using `func`, if no value is contained.
    #[inline]
    pub fn map_or_else<U: NonNullable>(
        self,
        default: impl FnOnce(usize) -> U,
        func: impl FnOnce(T) -> U,
    ) -> U {
        match self {
            Value(ptr) => func(ptr),
            Null(tag) => default(tag),
        }
    }

    /// Converts `self` from `Marked<T>` to [`Option<T>`][Option].
    #[inline]
    pub fn value(self) -> Option<T> {
        match self {
            Value(ptr) => Some(ptr),
            _ => None,
        }
    }

    /// Takes the value of the [`Marked`], leaving a [`Null`] variant in its
    /// place.
    #[inline]
    pub fn take(&mut self) -> Self {
        mem::replace(self, Null(0))
    }

    /// Replaces the actual value in the [`Marked`] with the given `value`,
    /// returning the old value.
    #[inline]
    pub fn replace(&mut self, value: T) -> Self {
        mem::replace(self, Value(value))
    }
}

impl<T: NonNullable + MarkedPointer> Marked<T> {
    /// Decomposes the inner marked pointer, returning only the separated tag.
    #[inline]
    pub fn decompose_tag(&self) -> usize {
        match self {
            Value(ptr) => ptr.as_marked_ptr().decompose_tag(),
            Null(tag) => *tag,
        }
    }
}

////////////////////////////////////////////////////////////////////////////////////////////////////
// impl Default
////////////////////////////////////////////////////////////////////////////////////////////////////

impl<T: NonNullable> Default for Marked<T> {
    #[inline]
    fn default() -> Self {
        Null(0)
    }
}

////////////////////////////////////////////////////////////////////////////////////////////////////
// impl From
////////////////////////////////////////////////////////////////////////////////////////////////////

impl<T: NonNullable> From<Option<T>> for Marked<T> {
    #[inline]
    fn from(opt: Option<T>) -> Self {
        match opt {
            Some(ptr) => Value(ptr),
            None => Null(0),
        }
    }
}