1use std::alloc::{Allocator, Global};
2
3use crate::{
4 context::{Context, Pacing},
5 Collect, Mutation,
6};
7use alloc::boxed::Box;
8
9pub struct Arena<R: Rootable, A = Global>
11where
12 A: Allocator,
13{
14 context: Box<Context<A>>,
15 root: R::Root<'static>,
16}
17
18impl<R> Arena<R>
19where
20 R: Rootable,
21{
22 pub fn new<F>(f: F) -> Arena<R>
23 where
24 F: for<'b> FnOnce(&Mutation<'b>) -> R::Root<'b>,
25 {
26 Arena::new_in(f, Global)
27 }
28
29 pub fn new_paced<F>(f: F, pacing: Pacing) -> Arena<R>
30 where
31 F: for<'b> FnOnce(&Mutation<'b>) -> R::Root<'b>,
32 {
33 Arena::new_paced_in(f, pacing, Global)
34 }
35}
36
37impl<R, A> Arena<R, A>
38where
39 A: Allocator,
40 R: Rootable,
41{
42 pub fn new_in<F>(f: F, alloc: A) -> Arena<R, A>
43 where
44 F: for<'b> FnOnce(&Mutation<'b>) -> R::Root<'b>,
45 A: Allocator + 'static,
46 {
47 Arena::new_paced_in(f, Pacing::default(), alloc)
48 }
49
50 pub fn new_paced_in<F>(f: F, pacing: Pacing, alloc: A) -> Arena<R, A>
51 where
52 F: for<'b> FnOnce(&Mutation<'b>) -> R::Root<'b>,
53 A: Allocator + 'static,
54 {
55 let context: Box<Context<A>> = Box::new(Context::new_in(pacing, alloc));
56 let root = f(Mutation::new(&context));
57
58 Arena { context, root }
59 }
60
61 pub fn view<F, Ret>(&self, f: F) -> Ret
62 where
63 F: for<'b> FnOnce(&R::Root<'b>, &Mutation<'b>) -> Ret,
64 {
65 f(&self.root, Mutation::new(&self.context))
66 }
67
68 pub fn view_mut<F, Ret>(&mut self, f: F) -> Ret
69 where
70 F: for<'b> FnOnce(&mut R::Root<'b>, &Mutation<'b>) -> Ret,
71 {
72 self.context.set_root_untraced();
73 f(&mut self.root, Mutation::new(&self.context))
74 }
75
76 pub fn run_collection(&mut self) {
77 self.context.advance_collection(&self.root);
78 }
79
80 pub fn complete_collection(&mut self) {
81 self.context.run_full_cycle(&self.root);
82 }
83
84 pub fn allocations(&self) -> usize {
85 self.context.allocations()
86 }
87}
88
89pub trait Rootable {
90 type Root<'l>: Collect;
91}