Skip to content

Commit 30324b2

Browse files
committed
impl Trace for arrayvec::ArrayVec
Of course this feature is optional :)
1 parent 7c5641d commit 30324b2

File tree

3 files changed

+80
-1
lines changed

3 files changed

+80
-1
lines changed

Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ scopeguard = "1.1"
1515
# gives zerogc batteries included support.
1616
indexmap = { version = "1.6", optional = true }
1717
parking_lot = { version = "0.11", optional = true }
18+
arrayvec = { version = "0.7", optional = true }
1819
# Serde support (optional)
1920
serde = { version = "1", optional = true, features = ["derive"] }
2021
# Used for macros
@@ -37,7 +38,7 @@ std = ["alloc"]
3738
# This implements `Trace` for `Box` and collections like `Vec`
3839
alloc = []
3940
# Serde support
40-
serde1 = ["serde", "zerogc-derive/__serde-internal", "indexmap/serde-1"]
41+
serde1 = ["serde", "zerogc-derive/__serde-internal", "arrayvec/serde", "indexmap/serde-1"]
4142
# Support the "epsilon" no-op collector
4243
epsilon = []
4344
# Configure the "epsilon" collector use arena allocation

src/manually_traced/arrayvec.rs

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
use arrayvec::{ArrayVec, ArrayString};
2+
3+
use crate::{GcRebrand, NullTrace};
4+
5+
use zerogc_derive::unsafe_gc_impl;
6+
7+
unsafe_gc_impl!(
8+
target => ArrayString<SIZE>,
9+
params => [const SIZE: usize],
10+
null_trace => always,
11+
NEEDS_TRACE => false,
12+
NEEDS_DROP => false,
13+
branded_type => ArrayString<SIZE>,
14+
trace_template => |self, visitor| { Ok(()) },
15+
deserialize => delegate
16+
);
17+
18+
unsafe_gc_impl!(
19+
target => ArrayVec<T, SIZE>,
20+
params => [T, const SIZE: usize],
21+
null_trace => { where T: NullTrace },
22+
NEEDS_TRACE => <T as Trace>::NEEDS_TRACE,
23+
NEEDS_DROP => <T as Trace>::NEEDS_DROP,
24+
bounds => {
25+
GcRebrand => { where T: GcRebrand<'new_gc, Id>, T::Branded: Sized },
26+
},
27+
branded_type => ArrayVec<T::Branded, SIZE>,
28+
trace_template => |self, visitor| {
29+
for val in self.#iter() {
30+
visitor.#trace_func(val)?;
31+
}
32+
Ok(())
33+
},
34+
deserialize => |ctx, deserializer| {
35+
use core::marker::PhantomData;
36+
use crate::{CollectorId, GcSystem};
37+
use crate::serde::{GcDeserialize, GcDeserializeSeed};
38+
use serde::de::{Visitor, Error, SeqAccess};
39+
struct ArrayVecVisitor<
40+
'gc, 'de, Id: CollectorId,
41+
T: GcDeserialize<'gc, 'de, Id>,
42+
const SIZE: usize
43+
> {
44+
ctx: &'gc <Id::System as GcSystem>::Context,
45+
marker: PhantomData<fn(&'de ()) -> ArrayVec<T, SIZE>>
46+
}
47+
impl<
48+
'gc, 'de, Id: CollectorId,
49+
T: GcDeserialize<'gc, 'de, Id>,
50+
const SIZE: usize
51+
> Visitor<'de> for ArrayVecVisitor<'gc, 'de, Id, T, SIZE> {
52+
type Value = ArrayVec<T, SIZE>;
53+
fn expecting(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
54+
write!(f, "a array with size <= {}", SIZE)
55+
}
56+
#[inline]
57+
fn visit_seq<A>(self, mut access: A) -> Result<Self::Value, A::Error>
58+
where A: SeqAccess<'de>, {
59+
let mut values = Self::Value::new();
60+
while let Some(value) = access.next_element_seed(
61+
GcDeserializeSeed::new(self.ctx)
62+
)? {
63+
match values.try_push(value) {
64+
Ok(()) => {},
65+
Err(_) => {
66+
return Err(A::Error::invalid_length(SIZE + 1, &self))
67+
}
68+
}
69+
}
70+
Ok(values)
71+
}
72+
}
73+
let visitor: ArrayVecVisitor<Id, T, SIZE> = ArrayVecVisitor { ctx, marker: PhantomData };
74+
deserializer.deserialize_seq(visitor)
75+
}
76+
);

src/manually_traced/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,3 +136,5 @@ mod stdlib;
136136
mod indexmap;
137137
#[cfg(feature = "parking_lot")]
138138
mod parking_lot;
139+
#[cfg(feature = "arrayvec")]
140+
mod arrayvec;

0 commit comments

Comments
 (0)