binator_core/
try_push.rs

1#[cfg(feature = "alloc")]
2use alloc::{
3  collections::{
4    BTreeMap,
5    BTreeSet,
6    BinaryHeap,
7    LinkedList,
8    TryReserveError,
9    VecDeque,
10  },
11  string::String,
12  vec::Vec,
13};
14use core::convert::Infallible;
15#[cfg(feature = "hashmap")]
16use core::hash::{
17  BuildHasher,
18  Hash,
19};
20#[cfg(feature = "hashmap")]
21use std::collections::{
22  HashMap,
23  HashSet,
24};
25
26#[cfg(feature = "smallvec")]
27use smallvec::{
28  CollectionAllocErr,
29  SmallVec,
30};
31
32/// Abstracts something you can try push item into `&mut self`
33// FIXME https://github.com/rust-lang/rust/issues/48043
34pub trait TryPush {
35  /// Item stocked in the collection
36  type Item;
37  /// The error returned by the collection if push fail
38  type Error;
39  /// Represent a way to access Item in the collection directly after push
40  type ItemView<'a>
41  where
42    Self: 'a;
43
44  /// Try to push an item into a collection, no guarantee on ordering.
45  fn try_push<'a>(&'a mut self, item: Self::Item) -> Result<Self::ItemView<'a>, Self::Error>;
46}
47
48#[cfg(feature = "alloc")]
49impl<Item> TryPush for Vec<Item> {
50  type Error = (Self::Item, TryReserveError);
51  type Item = Item;
52  type ItemView<'a> = &'a mut Self::Item
53  where
54    Self: 'a;
55
56  fn try_push<'a>(&'a mut self, item: Self::Item) -> Result<Self::ItemView<'a>, Self::Error> {
57    match self.try_reserve(1) {
58      Ok(_) => {
59        self.push(item);
60        Ok(self.last_mut().unwrap())
61      }
62      Err(e) => Err((item, e)),
63    }
64  }
65}
66
67#[cfg(feature = "alloc")]
68impl TryPush for String {
69  type Error = (Self::Item, TryReserveError);
70  type Item = char;
71  type ItemView<'a> = Self::Item;
72
73  fn try_push<'a>(&'a mut self, c: Self::Item) -> Result<Self::ItemView<'a>, Self::Error> {
74    match self.try_reserve(1) {
75      Ok(_) => {
76        self.push(c);
77        Ok(self.chars().next_back().unwrap())
78      }
79      Err(e) => Err((c, e)),
80    }
81  }
82}
83
84#[cfg(feature = "alloc")]
85impl<Item> TryPush for VecDeque<Item> {
86  type Error = (Self::Item, TryReserveError);
87  type Item = Item;
88  type ItemView<'a> = &'a mut Self::Item
89  where
90    Self: 'a;
91
92  fn try_push<'a>(&'a mut self, item: Self::Item) -> Result<Self::ItemView<'a>, Self::Error> {
93    match self.try_reserve(1) {
94      Ok(_) => {
95        self.push_back(item);
96        Ok(self.back_mut().unwrap())
97      }
98      Err(e) => Err((item, e)),
99    }
100  }
101}
102
103#[cfg(feature = "alloc")]
104impl<Key: Ord, Value> TryPush for BTreeMap<Key, Value> {
105  type Error = (Self::Item, TryReserveError);
106  type Item = (Key, Value);
107  // Not happy
108  type ItemView<'a> = Option<Value>
109  where
110    Self: 'a;
111
112  fn try_push<'a>(&'a mut self, item: Self::Item) -> Result<Self::ItemView<'a>, Self::Error> {
113    Ok(self.insert(item.0, item.1))
114  }
115}
116
117#[cfg(feature = "alloc")]
118impl<Item: Ord> TryPush for BinaryHeap<Item> {
119  type Error = (Self::Item, TryReserveError);
120  type Item = Item;
121  // not happy
122  type ItemView<'a> = ()
123  where
124    Self: 'a;
125
126  fn try_push<'a>(&'a mut self, item: Self::Item) -> Result<Self::ItemView<'a>, Self::Error> {
127    match self.try_reserve(1) {
128      Ok(_) => {
129        self.push(item);
130        Ok(())
131      }
132      Err(e) => Err((item, e)),
133    }
134  }
135}
136
137#[cfg(feature = "hashmap")]
138impl<Key: Eq + Hash, Value, Seed: BuildHasher> TryPush for HashMap<Key, Value, Seed> {
139  type Error = (Self::Item, TryReserveError);
140  type Item = (Key, Value);
141  // Not happy
142  type ItemView<'a> = Option<Value>
143  where
144    Self: 'a;
145
146  fn try_push<'a>(&'a mut self, item: Self::Item) -> Result<Self::ItemView<'a>, Self::Error> {
147    Ok(self.insert(item.0, item.1))
148  }
149}
150
151#[cfg(feature = "hashmap")]
152impl<Item: Eq + Hash, Seed: BuildHasher> TryPush for HashSet<Item, Seed> {
153  type Error = (Self::Item, TryReserveError);
154  type Item = Item;
155  // Not happy
156  type ItemView<'a> = bool
157  where
158    Self: 'a;
159
160  fn try_push<'a>(&'a mut self, item: Self::Item) -> Result<Self::ItemView<'a>, Self::Error> {
161    Ok(self.insert(item))
162  }
163}
164
165#[cfg(feature = "alloc")]
166impl<Item: Ord> TryPush for BTreeSet<Item> {
167  type Error = (Self::Item, TryReserveError);
168  type Item = Item;
169  // Not happy
170  type ItemView<'a> = bool
171  where
172    Self: 'a;
173
174  fn try_push(&mut self, item: Self::Item) -> Result<Self::ItemView<'_>, Self::Error> {
175    Ok(self.insert(item))
176  }
177}
178
179#[cfg(feature = "alloc")]
180impl<Item> TryPush for LinkedList<Item> {
181  type Error = (Self::Item, TryReserveError);
182  type Item = Item;
183  type ItemView<'a> = &'a mut Self::Item
184  where
185    Self: 'a;
186
187  fn try_push<'a>(&'a mut self, item: Self::Item) -> Result<Self::ItemView<'a>, Self::Error> {
188    self.push_back(item);
189    Ok(self.back_mut().unwrap())
190  }
191}
192
193#[cfg(feature = "smallvec")]
194impl<Item, const N: usize> TryPush for SmallVec<[Item; N]> {
195  type Error = (Self::Item, CollectionAllocErr);
196  type Item = Item;
197  type ItemView<'a> = &'a mut Self::Item
198  where
199    Self: 'a;
200
201  fn try_push<'a>(&'a mut self, item: Self::Item) -> Result<Self::ItemView<'a>, Self::Error> {
202    match self.try_reserve(1) {
203      Ok(_) => {
204        self.push(item);
205        Ok(self.last_mut().unwrap())
206      }
207      Err(e) => Err((item, e)),
208    }
209  }
210}
211
212impl TryPush for () {
213  type Error = Infallible;
214  type Item = ();
215  type ItemView<'a> = ();
216
217  fn try_push(&mut self, _: Self::Item) -> Result<Self::ItemView<'_>, Self::Error> {
218    Ok(())
219  }
220}