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
use len_trait::LenZero;

/// A mutable collection onto which items can be added to an arbitrary location in the collection.
///
/// Pushing an item must never *decrease* the length of a collection, and it usually increases it.
/// Additionally, the push must take amortized O(n) time and space to complete with respect to the
/// length of the pushed value.
pub trait Push<T>: LenZero {
    /// Type of value that gets pushed out, if any.
    ///
    /// For some collections, a value may be "pushed out" after a value is pushed.
    type PushedOut;

    /// Adds the value to the collection.
    fn push(&mut self, val: T) -> Option<Self::PushedOut>;
}

/// A mutable collection onto which items can be added "at the beginning."
///
/// "At the beginning" is defined in a way such that truncating the collection to the item's length
/// after a push will retain the item.
pub trait PushFront<T>: Push<T> {
    /// Adds the value to the front of the collection.
    fn push_front(&mut self, val: T) -> Option<Self::PushedOut>;
}

/// A mutable collection onto which items can be added "at the end."
///
/// "At the end" is defined in a way such that truncating the collection down by the item's length
/// after a push will remove the item.
pub trait PushBack<T>: Push<T> {
    /// Adds the value to the back of the collection.
    fn push_back(&mut self, val: T) -> Option<Self::PushedOut>;
}

/// Alternative to `Push<&T>`.
pub trait PushRef<T: ?Sized> {
    /// Type of value that gets pushed out, if any.
    type PushedOut;

    /// Adds the value to the collection.
    fn push_ref(&mut self, val: &T) -> Option<Self::PushedOut>;
}

/// Alternative to `PushFront<&T>`.
pub trait PushRefFront<T: ?Sized>: PushRef<T> {
    /// Adds the value to the front of the collection.
    fn push_ref_front(&mut self, val: &T) -> Option<Self::PushedOut>;
}

/// Alternative to `PushBack<&T>`.
pub trait PushRefBack<T: ?Sized>: PushRef<T> {
    /// Adds the value to the back of the collection.
    fn push_ref_back(&mut self, val: &T) -> Option<Self::PushedOut>;
}

/// Represents a pushed value that has been dropped.
///
/// Some collections do not actually push a value if another value exists in this place. These
/// collections will return `Some(PushedVal)` to represent that, even though the pushed value was
/// dropped, it was "pushed out" instead of being pushed.
pub struct PushedVal;

#[cfg(feature = "nightly")]
type Nothing = !;

/// Represents that no value is ever pushed out on a push.
///
/// Currently, the `!` type is only available on nightly. As a result, when the `nightly` feature
/// isn't enabled, this enum is used in place of `!` to represent that no object can ever be pushed
/// out when a push happens.
#[cfg(not(feature = "nightly"))]
pub enum Nothing {}