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
//! Traits for moving data between collectinos without freeing resources.

cfg_if! {
    if #[cfg(feature = "std")] {
        use std::mem::swap;
    } else {
        use core::mem::swap;
    }
}

use len_trait::Clear;

use base::{CanPush, Push};
use ordered::{PushBack, PushFront};

/// A trait for moving data from one collection into another without freeing resources.
///
/// Conceptually, an `append` is equivalent to a [`push`], with the caveat that the data is "moved
/// out" of the pushed collection instead of being consumed. This allows reuse of the pushed
/// collection's resources.
///
/// [`push`]: ../base/trait.Push.html#tymethod.push
pub trait Append: Sized + Clear {
    /// Moves data out of `val` and into this collection.
    ///
    /// Invoking this method should make `val` empty without freeing any resources. Any data that
    /// would be pushed out of `self` should be retained in `val`.
    fn append(&mut self, val: &mut Self);
}
impl<T: Append> CanPush<T> for T {
    type PushedOut = T;
}
impl<T: Append> Push<T> for T {
    fn push(&mut self, mut val: T) -> Option<T> {
        self.append(&mut val);
        if val.is_empty() { None } else { Some(val) }
    }
}

/// A trait for moving data from one collection onto the back of another without freeing resources.
///
/// This trait is the [`PushBack`] analogue of [`Append`].
///
/// [`PushBack`]: ../ordered/trait.PushBack.html
/// [`Append`]: trait.Append.html
pub trait AppendBack: Append {
    /// Moves data out of `val` and onto the back of this collection.
    ///
    /// Invoking this method should make `val` empty without freeing any resources.
    fn append_back(&mut self, val: &mut Self) {
        self.append(val)
    }
}
impl<T: AppendBack> PushBack<T> for T {}

/// A trait for moving data from one collection onto the front of another without freeing resources.
///
/// This trait is the [`PushFront`] analogue of [`Append`].
///
/// [`PushFront`]: ../ordered/trait.PushBack.html
/// [`Append`]: trait.Append.html
pub trait AppendFront: AppendBack {
    /// Moves data out of `val` and onto the front of this collection.
    ///
    /// Invoking this method should make `val` empty without freeing any resources.
    fn append_front(&mut self, val: &mut Self) {
        swap(val, self);
        val.append_back(self)
    }
}
impl<T: AppendFront> PushFront<T> for T {
    fn push_front(&mut self, mut val: T) -> Option<T> {
        self.append_front(&mut val);
        if val.is_empty() { None } else { Some(val) }
    }
}