push_trait/
impls.rs

1use super::{Nothing, PushedVal};
2
3
4// TODO: this is a hack
5trait IntoPo {
6    type Po;
7    fn into_po(self) -> Option<Self::Po>;
8}
9impl<T> IntoPo for Option<T> {
10    type Po = T;
11
12    #[inline]
13    fn into_po(self) -> Option<T> {
14        self
15    }
16}
17impl IntoPo for bool {
18    type Po = PushedVal;
19
20    #[inline]
21    fn into_po(self) -> Option<PushedVal> {
22        if self { None } else { Some(PushedVal) }
23    }
24}
25impl IntoPo for () {
26    type Po = Nothing;
27
28    #[inline]
29    fn into_po(self) -> Option<Self::Po> {
30        None
31    }
32}
33
34
35#[cfg(feature = "alloc")]
36macro_rules! do_impl {
37    (CanPush for $impl_for:ty, $t:ty, $po:ty; $($gen:tt)*) => {
38        impl<$($gen)*> $crate::base::CanPush<$t> for $impl_for {
39            type PushedOut = $po;
40        }
41    };
42    (Push for $impl_for:ty, $method:path, $t:ty, $po:ty; $($gen:tt)*) => {
43        do_impl!(CanPush for $impl_for, $t, $po; $($gen)*);
44        impl<$($gen)*> $crate::base::Push<$t> for $impl_for {
45            fn push(&mut self, val: $t) -> Option<Self::PushedOut> {
46                $crate::impls::IntoPo::into_po($method(self, val))
47            }
48        }
49    };
50    (keyval Push for $impl_for:ty, $method:path, $t:ty, $po:ty; $($gen:tt)*) => {
51        do_impl!(CanPush for $impl_for, $t, $po; $($gen)*);
52        impl<$($gen)*> $crate::base::Push<$t> for $impl_for {
53            fn push(&mut self, (key, val): $t) -> Option<Self::PushedOut> {
54                $crate::impls::IntoPo::into_po($method(self, key, val))
55            }
56        }
57    };
58    (PushSorted for $impl_for:ty, $method:path, $t:ty, $po:ty; $($gen:tt)*) => {
59        do_impl!(CanPush for $impl_for, $t, $po; $($gen)*);
60        impl<$($gen)*> $crate::sorted::PushSorted<$t> for $impl_for {
61            fn push_sorted(&mut self, val: $t) -> Option<Self::PushedOut> {
62                $crate::impls::IntoPo::into_po($method(self, val))
63            }
64        }
65    };
66    (keyval PushSorted for $impl_for:ty, $method:path, $t:ty, $po:ty; $($gen:tt)*) => {
67        do_impl!(CanPush for $impl_for, $t, $po; $($gen)*);
68        impl<$($gen)*> $crate::sorted::PushSorted<$t> for $impl_for {
69            fn push_sorted(&mut self, (key, val): $t) -> Option<Self::PushedOut> {
70                $crate::impls::IntoPo::into_po($method(self, key, val))
71            }
72        }
73    };
74    (PushBack for $impl_for:ty, $method:path, $t:ty, $po:ty; $($gen:tt)*) => {
75        do_impl!(Push for $impl_for, $method, $t, $po; $($gen)*);
76        impl<$($gen)*> $crate::ordered::PushBack<$t> for $impl_for { }
77    };
78    (keyval PushBack for $impl_for:ty, $method:path, $t:ty, $po:ty; $($gen:tt)*) => {
79        do_impl!(keyval Push for $impl_for, $method, $t, $po; $($gen)*);
80        impl<$($gen)*> $crate::ordered::PushBack<$t> for $impl_for { }
81    };
82    (PushFront for $impl_for:ty, $method:path, $t:ty, $po:ty; $($gen:tt)*) => {
83        impl<$($gen)*> $crate::ordered::PushFront<$t> for $impl_for {
84            fn push_front(&mut self, val: $t) -> Option<Self::PushedOut> {
85                $crate::impls::IntoPo::into_po($method(self, val))
86            }
87        }
88    };
89    (Insert for $impl_for:ty, $method:path, $t:ty, $po:ty; $($gen:tt)*) => {
90        impl<$($gen)*> $crate::ordered::Insert<$t> for $impl_for {
91            fn insert(&mut self, index: usize, val: $t) -> Option<Self::PushedOut> {
92                $crate::impls::IntoPo::into_po($method(self, index, val))
93            }
94        }
95    };
96    (Append for $impl_for:ty, $method:path; $($gen:tt)*) => {
97        impl<$($gen)*> $crate::append::Append for $impl_for {
98            fn append(&mut self, val: &mut Self) {
99                $method(self, val)
100            }
101        }
102    };
103    (AppendBack for $impl_for:ty, $method:path; $($gen:tt)*) => {
104        do_impl!(Append for $impl_for, $method; $($gen)*);
105        impl<$($gen)*> $crate::append::AppendBack for $impl_for {}
106        impl<$($gen)*> $crate::append::AppendFront for $impl_for {}
107    };
108}
109
110#[cfg_attr(feature = "cargo-clippy", allow(linkedlist))]
111// TODO: https://github.com/Manishearth/rust-clippy/issues/1800
112cfg_if! {
113    if #[cfg(feature = "alloc")] {
114        cfg_if! {
115            if #[cfg(feature = "std")] {
116                use std::collections;
117            } else {
118                use alloc::{self as collections, String, Vec};
119            }
120        }
121        use self::collections::{BTreeMap, BTreeSet, BinaryHeap, LinkedList, VecDeque};
122
123        do_impl!(Append for BTreeSet<T>, BTreeSet::append; T: Ord);
124        do_impl!(PushSorted for BTreeSet<T>, BTreeSet::insert, T, super::PushedVal; T: Ord);
125
126        do_impl!(Append for BinaryHeap<T>, BinaryHeap::append; T: Ord);
127        do_impl!(PushSorted for BinaryHeap<T>, BinaryHeap::push, T, super::Nothing; T: Ord);
128
129        do_impl!(Append for BTreeMap<K, V>, BTreeMap::append; K: Ord, V);
130        do_impl!(keyval PushSorted for BTreeMap<K, V>, BTreeMap::insert, (K, V), V; K: Ord, V);
131
132        do_impl!(AppendBack for LinkedList<T>, LinkedList::append; T);
133        do_impl!(PushBack for LinkedList<T>, LinkedList::push_back, T, super::Nothing; T);
134        do_impl!(PushFront for LinkedList<T>, LinkedList::push_front, T, super::Nothing; T);
135
136        do_impl!(AppendBack for String, string_append; );
137        do_impl!(PushBack for String, String::push, char, super::Nothing; );
138        do_impl!(PushBack for String, String::push_str, &'a str, super::Nothing; 'a);
139        do_impl!(Insert for String, String::insert, char, super::Nothing; );
140        do_impl!(Insert for String, String::insert_str, &'a str, super::Nothing; 'a);
141        fn string_append(lhs: &mut String, rhs: &mut String) {
142            lhs.push_str(rhs);
143            rhs.clear();
144        }
145
146        do_impl!(AppendBack for Vec<T>, Vec::append; T);
147        do_impl!(PushBack for Vec<T>, Vec::push, T, super::Nothing; T);
148        do_impl!(PushBack for Vec<u8>, push_utf8_char, char, super::Nothing; );
149        do_impl!(PushBack for Vec<u16>, push_utf16_char, char, super::Nothing; );
150        do_impl!(PushBack for Vec<u32>, push_utf32_char, char, super::Nothing; );
151        do_impl!(PushBack for Vec<T>,
152                 Vec::extend_from_slice, &'a [T], super::Nothing; 'a, T: 'a + Clone);
153        do_impl!(Insert for Vec<T>, Vec::insert, T, super::Nothing; T);
154        do_impl!(Insert for Vec<u32>, insert_utf32_char, char, super::Nothing; );
155        fn push_utf8_char(lhs: &mut Vec<u8>, rhs: char) {
156            let mut buf = [0; 4];
157            Vec::extend_from_slice(lhs, rhs.encode_utf8(&mut buf).as_bytes())
158        }
159        fn push_utf16_char(lhs: &mut Vec<u16>, rhs: char) {
160            let mut buf = [0; 2];
161            Vec::extend_from_slice(lhs, rhs.encode_utf16(&mut buf))
162        }
163        fn push_utf32_char(lhs: &mut Vec<u32>, rhs: char) {
164            Vec::push(lhs, rhs as u32)
165        }
166        fn insert_utf32_char(lhs: &mut Vec<u32>, index: usize, rhs: char) {
167            Vec::insert(lhs, index, rhs as u32)
168        }
169
170        cfg_if! {
171            if #[cfg(feature = "nightly")] {
172                do_impl!(Insert for Vec<u8>, insert_utf8_char, char, super::Nothing; );
173                do_impl!(Insert for Vec<u16>, insert_utf16_char, char, super::Nothing; );
174                do_impl!(Insert for Vec<T>,
175                         insert_slice, &'a [T], super::Nothing; 'a, T: 'a + Clone);
176                fn insert_utf8_char(lhs: &mut Vec<u8>, index: usize, rhs: char) {
177                    let mut buf = [0; 4];
178                    Vec::splice(lhs, index..index, rhs.encode_utf8(&mut buf).bytes());
179                }
180                fn insert_utf16_char(lhs: &mut Vec<u16>, index: usize, rhs: char) {
181                    let mut buf = [0; 2];
182                    Vec::splice(lhs, index..index, rhs.encode_utf16(&mut buf).iter().cloned());
183                }
184                fn insert_slice<T: Clone>(lhs: &mut Vec<T>, index: usize, rhs: &[T]) {
185                    Vec::splice(lhs, index..index, rhs.iter().cloned());
186                }
187            }
188        }
189
190        do_impl!(AppendBack for VecDeque<T>, VecDeque::append; T);
191        do_impl!(PushBack for VecDeque<T>, VecDeque::push_back, T, super::Nothing; T);
192        do_impl!(PushFront for VecDeque<T>, VecDeque::push_front, T, super::Nothing; T);
193        do_impl!(Insert for VecDeque<T>, VecDeque::insert, T, super::Nothing; T);
194    }
195}
196
197cfg_if! {
198    if #[cfg(feature = "std")] {
199        use std::collections::{HashMap, HashSet};
200        use std::ffi::{OsStr, OsString};
201        use std::hash::Hash;
202
203        do_impl!(AppendBack for OsString, os_string_append; );
204        do_impl!(PushBack for OsString, OsString::push, &'a OsStr, super::Nothing; 'a);
205        do_impl!(PushBack for OsString, OsString::push, &'a str, super::Nothing; 'a);
206        fn os_string_append(lhs: &mut OsString, rhs: &mut OsString) {
207            lhs.push(&rhs);
208            rhs.clear();
209        }
210
211        do_impl!(keyval Push for HashMap<K, V>, HashMap::insert, (K, V), V; K: Hash + Eq, V);
212        do_impl!(Push for HashSet<T>, HashSet::insert, T, super::PushedVal; T: Hash + Eq);
213    }
214}