fixed_bump/
rc.rs

1/*
2 * Copyright (C) 2021-2022 taylor.fish <contact@taylor.fish>
3 *
4 * This file is part of fixed-bump.
5 *
6 * fixed-bump is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * fixed-bump is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with fixed-bump. If not, see <https://www.gnu.org/licenses/>.
18 */
19
20use super::Bump;
21use alloc::rc;
22use core::ops::Deref;
23#[cfg(any(feature = "allocator_api", feature = "allocator-fallback"))]
24use {
25    super::{AllocError, Allocator},
26    alloc::alloc::Layout,
27    core::ptr::NonNull,
28};
29
30/// A wrapper around [`Rc`](rc::Rc).
31///
32/// This type exists mainly so that [`Allocator`](alloc::alloc::Allocator)
33/// can be implemented for it:
34///
35/// ```
36/// # #![cfg_attr(feature = "allocator_api", feature(allocator_api))]
37/// use fixed_bump::Bump;
38/// let rc = std::rc::Rc::new(Bump::<[u32; 16]>::new());
39/// # #[cfg(feature = "allocator_api")]
40/// # {
41/// // Error: `std::rc::Rc<Bump<...>>` doesn't implement `Allocator`:
42/// //let b = Box::new_in(1_u32, rc);
43/// // Compiles: `fixed_bump::Rc<Bump<...>>` implements `Allocator`:
44/// let b = Box::new_in(1_u32, fixed_bump::Rc(rc));
45/// # }
46/// ```
47pub struct Rc<Bump>(pub rc::Rc<Bump>);
48
49impl<Bump> Rc<Bump> {
50    /// Creates a new [`Rc`]. This simply returns
51    /// <code>[Rc]\([rc::Rc::new]\(bump))</code>.
52    pub fn new(bump: Bump) -> Self {
53        Self(rc::Rc::new(bump))
54    }
55}
56
57impl<Bump: Default> Default for Rc<Bump> {
58    fn default() -> Self {
59        Self::new(Bump::default())
60    }
61}
62
63impl<Bump> Clone for Rc<Bump> {
64    fn clone(&self) -> Self {
65        Self(self.0.clone())
66    }
67}
68
69impl<Bump> Deref for Rc<Bump> {
70    type Target = Bump;
71
72    fn deref(&self) -> &Self::Target {
73        &self.0
74    }
75}
76
77#[cfg(any(feature = "allocator_api", feature = "allocator-fallback"))]
78#[cfg_attr(
79    feature = "doc_cfg",
80    doc(cfg(any(
81        feature = "allocator_api",
82        feature = "allocator-fallback",
83    )))
84)]
85// SAFETY: This impl simply forwards to `Bump`'s `Allocator` impl.
86//
87// `Rc` is a wrapper around `rc::Rc<Bump>`, so clones of `Rc` will behave
88// like the same allocator, and moving an `Rc` will not invalidate any
89// returned memory.
90unsafe impl<Bump: Allocator> Allocator for Rc<Bump> {
91    fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
92        Allocator::allocate(&*self.0, layout)
93    }
94
95    unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout) {
96        // SAFETY: We simply forward to `Bump`'s `Allocator` impl, which has
97        // the same safety requirements as this method. The caller of this
98        // method is responsible for ensuring those requirements are met.
99        unsafe { Allocator::deallocate(&*self.0, ptr, layout) };
100    }
101}
102
103#[doc(hidden)]
104#[deprecated = "use `fixed_bump::Rc<Bump<...>>` instead"]
105/// A wrapper around <code>[Rc](rc::Rc)<Bump<...>></code>.
106pub struct RcBump<Size, Align = Size>(pub rc::Rc<Bump<Size, Align>>);
107
108#[allow(deprecated)]
109impl<Size, Align> RcBump<Size, Align> {
110    /// Creates a new [`RcBump`]. This simply returns
111    /// <code>[RcBump]\([rc::Rc::new]\([Bump::new]\())</code>.
112    pub fn new() -> Self {
113        Self(rc::Rc::new(Bump::new()))
114    }
115}
116
117#[allow(deprecated)]
118impl<Size, Align> Default for RcBump<Size, Align> {
119    fn default() -> Self {
120        Self::new()
121    }
122}
123
124#[allow(deprecated)]
125impl<Size, Align> Clone for RcBump<Size, Align> {
126    fn clone(&self) -> Self {
127        Self(self.0.clone())
128    }
129}
130
131#[allow(deprecated)]
132impl<Size, Align> Deref for RcBump<Size, Align> {
133    type Target = Bump<Size, Align>;
134
135    fn deref(&self) -> &Self::Target {
136        &self.0
137    }
138}
139
140#[cfg(any(feature = "allocator_api", feature = "allocator-fallback"))]
141#[allow(deprecated)]
142// SAFETY: This impl simply forwards to `Bump`'s `Allocator` impl.
143//
144// `RcBump` is a wrapper around `rc::Rc<Bump<...>>`, so clones of `RcBump` will
145// behave like the same allocator, and moving an `RcBump` will not invalidate
146// any returned memory.
147unsafe impl<Size, Align> Allocator for RcBump<Size, Align> {
148    fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
149        Allocator::allocate(&*self.0, layout)
150    }
151
152    unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout) {
153        // SAFETY: We simply forward to `Bump`'s `Allocator` impl, which has
154        // the same safety requirements as this method. The caller of this
155        // method is responsible for ensuring those requirements are met.
156        unsafe { Allocator::deallocate(&*self.0, ptr, layout) };
157    }
158}