1use alloc::sync::Arc;
9use core::fmt;
10use core::ops::{Deref, DerefMut};
11use core::sync::atomic::{AtomicUsize, Ordering};
12
13use allocator_api2::collections::TryReserveErrorKind;
14use allocator_api2::vec::Vec;
15
16mod allocator;
17mod map;
18mod shared_string;
19mod sort;
20mod string;
21mod text;
22mod work;
23pub use map::{HashWork, MapExecution, OwnedMap, RetainError};
24pub use shared_string::SharedString;
25pub use sort::SortError;
26pub use string::OwnedString;
27pub use text::{OwnedText, TextError, TextErrorKind};
28pub use work::{Execution, Work};
29
30#[derive(Debug, Clone, Copy, PartialEq, Eq)]
32pub enum MemoryError {
33 LimitExceeded,
35 OutOfMemory,
37 CapacityOverflow,
39 WorkExceeded,
41}
42
43impl fmt::Display for MemoryError {
44 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
45 f.write_str(match self {
46 Self::LimitExceeded => "memory budget spent",
47 Self::OutOfMemory => "allocator could not supply storage",
48 Self::CapacityOverflow => "storage capacity overflow",
49 Self::WorkExceeded => "work budget spent",
50 })
51 }
52}
53
54#[cfg(feature = "std")]
55impl std::error::Error for MemoryError {}
56
57#[derive(Debug)]
62pub struct MemoryAccount {
63 limit: usize,
64 used: AtomicUsize,
65 work_limit: usize,
66 work: AtomicUsize,
67}
68
69impl MemoryAccount {
70 #[must_use]
72 pub const fn new(limit: usize, work_limit: usize) -> Self {
73 Self {
74 limit,
75 used: AtomicUsize::new(0),
76 work_limit,
77 work: AtomicUsize::new(0),
78 }
79 }
80
81 fn reserve(&self, bytes: usize) -> core::result::Result<Reservation<'_>, MemoryError> {
82 let mut used = self.used.load(Ordering::Relaxed);
83 loop {
84 debug_assert!(used <= self.limit);
85 if bytes > self.limit - used {
86 return Err(MemoryError::LimitExceeded);
87 }
88 match self.used.compare_exchange_weak(
89 used,
90 used + bytes,
91 Ordering::Relaxed,
92 Ordering::Relaxed,
93 ) {
94 Ok(_) => {
95 return Ok(Reservation {
96 account: self,
97 bytes,
98 });
99 }
100 Err(current) => used = current,
101 }
102 }
103 }
104
105 fn release(&self, bytes: usize) {
106 let previous = self.used.fetch_sub(bytes, Ordering::Relaxed);
107 debug_assert!(previous >= bytes);
108 }
109}
110
111struct Reservation<'a> {
112 account: &'a MemoryAccount,
113 bytes: usize,
114}
115
116impl Reservation<'_> {
117 fn commit(mut self) {
118 self.bytes = 0;
119 }
120}
121
122impl Drop for Reservation<'_> {
123 fn drop(&mut self) {
124 self.account.release(self.bytes);
125 }
126}
127
128#[derive(Debug, Clone)]
132pub struct Memory {
133 account: Arc<MemoryAccount>,
134}
135
136impl Memory {
137 #[must_use]
139 pub fn new(account: Arc<MemoryAccount>) -> Self {
140 Self { account }
141 }
142
143 #[must_use]
145 pub fn limit(&self) -> usize {
146 self.account.limit
147 }
148
149 #[must_use]
151 pub fn used(&self) -> usize {
152 self.account.used.load(Ordering::Relaxed)
153 }
154
155 #[must_use]
157 pub fn same_account(&self, other: &Self) -> bool {
158 Arc::ptr_eq(&self.account, &other.account)
159 }
160
161 #[must_use]
163 pub fn work_used(&self) -> usize {
164 self.account.work.load(Ordering::Relaxed)
165 }
166
167 #[must_use]
171 pub fn work_remaining(&self) -> usize {
172 let spent = self.account.work.load(Ordering::Relaxed);
173 debug_assert!(spent <= self.account.work_limit);
174 self.account.work_limit - spent
175 }
176
177 pub fn charge_work(&self, amount: u64) -> core::result::Result<(), MemoryError> {
182 let amount = usize::try_from(amount).map_err(|_| MemoryError::WorkExceeded)?;
183 let mut spent = self.account.work.load(Ordering::Relaxed);
184 loop {
185 debug_assert!(spent <= self.account.work_limit);
186 if amount > self.account.work_limit - spent {
187 return Err(MemoryError::WorkExceeded);
188 }
189 match self.account.work.compare_exchange_weak(
190 spent,
191 spent + amount,
192 Ordering::Relaxed,
193 Ordering::Relaxed,
194 ) {
195 Ok(_) => return Ok(()),
196 Err(current) => spent = current,
197 }
198 }
199 }
200
201 pub fn reserve(&self, bytes: usize) -> core::result::Result<MemoryReservation, MemoryError> {
207 let reservation = self.account.reserve(bytes)?;
208 reservation.commit();
209 Ok(MemoryReservation {
210 memory: self.clone(),
211 bytes,
212 })
213 }
214
215 #[must_use]
217 pub fn vector<T>(&self) -> OwnedVec<T> {
218 Work::vector(self)
219 }
220
221 #[must_use]
223 pub fn map<K: HashWork, V>(&self) -> OwnedMap<K, V> {
224 OwnedMap::new(self.clone())
225 }
226
227 #[must_use]
229 pub fn string(&self) -> OwnedString {
230 OwnedString::new(self)
231 }
232}
233
234#[derive(Debug)]
239#[must_use = "retain the reservation until its allocation has been deallocated"]
240pub struct MemoryReservation {
241 memory: Memory,
242 bytes: usize,
243}
244
245impl Drop for MemoryReservation {
246 fn drop(&mut self) {
247 self.memory.account.release(self.bytes);
248 }
249}
250
251pub struct OwnedVec<T, W: Work = Memory> {
259 values: Vec<T, allocator::AccountAllocator<W>>,
260}
261
262#[must_use]
265pub enum VecExecution<T, Old: Work, New: Work> {
266 Changed {
268 values: OwnedVec<T, New>,
270 previous: Old,
272 },
273 Foreign {
275 values: OwnedVec<T, Old>,
277 requested: New,
279 },
280}
281
282impl<T> OwnedVec<T> {
283 pub fn with_execution<W: Work>(self, execution: &W) -> Result<OwnedVec<T, W>, Self> {
292 if !self.memory().same_account(execution.memory()) {
293 return Err(self);
294 }
295 Ok(OwnedVec {
296 values: allocator::scope(self.values, execution),
297 })
298 }
299}
300
301impl<T, W: Work> OwnedVec<T, W> {
302 pub(crate) fn work(&self) -> &W {
303 self.values.allocator().work()
304 }
305
306 pub fn rebind<New: Work>(self, execution: New) -> VecExecution<T, W, New> {
310 if !self.memory().same_account(execution.memory()) {
311 return VecExecution::Foreign {
312 values: self,
313 requested: execution,
314 };
315 }
316 let (values, previous) = allocator::rebind(self.values, &execution);
317 VecExecution::Changed {
318 values: OwnedVec { values },
319 previous,
320 }
321 }
322 #[must_use]
350 pub fn into_owned(self) -> OwnedVec<T> {
351 OwnedVec {
352 values: allocator::retain(self.values),
353 }
354 }
355}
356
357impl<T: fmt::Debug, W: Work> fmt::Debug for OwnedVec<T, W> {
358 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
359 self.values.fmt(f)
360 }
361}
362
363impl<T: PartialEq, W: Work> PartialEq for OwnedVec<T, W> {
364 fn eq(&self, other: &Self) -> bool {
365 **self == **other
366 }
367}
368
369impl<T: Eq, W: Work> Eq for OwnedVec<T, W> {}
370
371impl<T: PartialEq, W: Work, const N: usize> PartialEq<[T; N]> for OwnedVec<T, W> {
372 fn eq(&self, other: &[T; N]) -> bool {
373 &**self == other
374 }
375}
376
377impl<T, W: Work> OwnedVec<T, W> {
378 #[must_use]
380 pub fn memory(&self) -> &Memory {
381 self.values.allocator().memory()
382 }
383 #[must_use]
385 pub fn capacity(&self) -> usize {
386 self.values.capacity()
387 }
388
389 pub fn try_reserve_exact(
391 &mut self,
392 additional: usize,
393 ) -> core::result::Result<(), MemoryError> {
394 self.values.allocator().clear_failure();
395 self.values
396 .try_reserve_exact(additional)
397 .map_err(|error| match error.kind() {
398 TryReserveErrorKind::CapacityOverflow => MemoryError::CapacityOverflow,
399 TryReserveErrorKind::AllocError { .. } => self.values.allocator().failure(),
400 })
401 }
402
403 pub fn try_reserve(&mut self, additional: usize) -> core::result::Result<(), MemoryError> {
405 self.values.allocator().clear_failure();
406 self.values
407 .try_reserve(additional)
408 .map_err(|error| match error.kind() {
409 TryReserveErrorKind::CapacityOverflow => MemoryError::CapacityOverflow,
410 TryReserveErrorKind::AllocError { .. } => self.values.allocator().failure(),
411 })
412 }
413
414 pub fn try_push(&mut self, value: T) -> core::result::Result<(), MemoryError> {
416 self.values.allocator().work().charge_work(1)?;
417 if self.values.len() == self.values.capacity() {
418 self.try_reserve(1)?;
419 }
420 self.values.push(value);
422 Ok(())
423 }
424
425 pub fn pop(&mut self) -> Option<T> {
427 self.values.pop()
428 }
429
430 pub fn clear(&mut self) {
432 self.values.clear();
433 }
434
435 pub fn try_drain_all(
449 &mut self,
450 ) -> Result<
451 impl DoubleEndedIterator<Item = T> + ExactSizeIterator + core::iter::FusedIterator + '_,
452 MemoryError,
453 > {
454 let work = self.values.len().max(core::mem::size_of_val(&**self));
455 self.values.allocator().work().charge_work(work as u64)?;
456 Ok(self.values.drain(..))
457 }
458
459 pub fn try_sort_unstable_by<E>(
465 &mut self,
466 compare: impl FnMut(&T, &T) -> core::result::Result<core::cmp::Ordering, E>,
467 ) -> core::result::Result<(), SortError<E>> {
468 let work = self.values.allocator().work().clone();
469 sort::sort(&mut self.values, &work, compare)
470 }
471}
472
473impl<T: Copy, W: Work> OwnedVec<T, W> {
474 pub fn try_extend_from_slice(&mut self, values: &[T]) -> core::result::Result<(), MemoryError> {
476 let work = values.len().max(core::mem::size_of_val(values));
477 self.values.allocator().work().charge_work(work as u64)?;
478 if self.values.capacity() == 0 {
479 self.try_reserve_exact(values.len())?;
480 } else {
481 self.try_reserve(values.len())?;
482 }
483 self.values.extend_from_slice(values);
484 Ok(())
485 }
486 pub fn try_copy(&self) -> core::result::Result<Self, MemoryError> {
488 let mut copy = self.values.allocator().work().vector();
489 let work = self.values.len().max(core::mem::size_of_val(&**self));
490 self.values.allocator().work().charge_work(work as u64)?;
491 copy.try_reserve_exact(self.values.len())?;
492 copy.values.extend_from_slice(&self.values);
494 Ok(copy)
495 }
496}
497
498impl<T, W: Work> Deref for OwnedVec<T, W> {
499 type Target = [T];
500 fn deref(&self) -> &[T] {
501 &self.values
502 }
503}
504
505impl<T, W: Work> DerefMut for OwnedVec<T, W> {
506 fn deref_mut(&mut self) -> &mut [T] {
507 &mut self.values
508 }
509}
510
511impl<'a, T, W: Work> IntoIterator for &'a OwnedVec<T, W> {
512 type Item = &'a T;
513 type IntoIter = core::slice::Iter<'a, T>;
514 fn into_iter(self) -> Self::IntoIter {
515 self.iter()
516 }
517}
518
519impl<'a, T, W: Work> IntoIterator for &'a mut OwnedVec<T, W> {
520 type Item = &'a mut T;
521 type IntoIter = core::slice::IterMut<'a, T>;
522 fn into_iter(self) -> Self::IntoIter {
523 self.iter_mut()
524 }
525}
526
527pub struct OwnedIter<T, W: Work = Memory> {
529 values: allocator_api2::vec::IntoIter<T, allocator::AccountAllocator<W>>,
530}
531
532impl<T, W: Work> Iterator for OwnedIter<T, W> {
533 type Item = T;
534 fn next(&mut self) -> Option<T> {
535 self.values.next()
536 }
537 fn size_hint(&self) -> (usize, Option<usize>) {
538 self.values.size_hint()
539 }
540}
541
542impl<T, W: Work> DoubleEndedIterator for OwnedIter<T, W> {
543 fn next_back(&mut self) -> Option<T> {
544 self.values.next_back()
545 }
546}
547
548impl<T, W: Work> ExactSizeIterator for OwnedIter<T, W> {}
549impl<T, W: Work> core::iter::FusedIterator for OwnedIter<T, W> {}
550
551impl<T, W: Work> IntoIterator for OwnedVec<T, W> {
552 type Item = T;
553 type IntoIter = OwnedIter<T, W>;
554 fn into_iter(self) -> Self::IntoIter {
555 OwnedIter {
556 values: self.values.into_iter(),
557 }
558 }
559}
560
561#[cfg(test)]
562mod tests;