Add RepeatedMut::clear, free for owned Repeated

PiperOrigin-RevId: 591046913
pull/15080/head
Alyssa Haroldsen 1 year ago committed by Copybara-Service
parent 162908d05f
commit f51182b543
  1. 14
      rust/cpp.rs
  2. 8
      rust/cpp_kernel/cpp_api.cc
  3. 35
      rust/repeated.rs
  4. 14
      rust/upb.rs

@ -215,20 +215,23 @@ impl<'msg> InnerRepeatedMut<'msg> {
macro_rules! impl_repeated_primitives {
(@impl $($t:ty => [
$new_thunk:ident,
$free_thunk:ident,
$add_thunk:ident,
$size_thunk:ident,
$get_thunk:ident,
$set_thunk:ident,
$clear_thunk:ident,
$copy_from_thunk:ident $(,)?
]),* $(,)?) => {
$(
// TODO: Add clear, free
extern "C" {
fn $new_thunk() -> RawRepeatedField;
fn $free_thunk(f: RawRepeatedField);
fn $add_thunk(f: RawRepeatedField, v: $t);
fn $size_thunk(f: RawRepeatedField) -> usize;
fn $get_thunk(f: RawRepeatedField, i: usize) -> $t;
fn $set_thunk(f: RawRepeatedField, i: usize, v: $t);
fn $clear_thunk(f: RawRepeatedField);
fn $copy_from_thunk(src: RawRepeatedField, dst: RawRepeatedField);
}
@ -239,12 +242,19 @@ macro_rules! impl_repeated_primitives {
Repeated::from_inner(InnerRepeatedMut::new(Private, $new_thunk()))
}
}
#[allow(dead_code)]
unsafe fn repeated_free(_: Private, f: &mut Repeated<$t>) {
unsafe { $free_thunk(f.as_mut().as_raw(Private)) }
}
fn repeated_len(f: View<Repeated<$t>>) -> usize {
unsafe { $size_thunk(f.as_raw(Private)) }
}
fn repeated_push(mut f: Mut<Repeated<$t>>, v: View<$t>) {
unsafe { $add_thunk(f.as_raw(Private), v) }
}
fn repeated_clear(mut f: Mut<Repeated<$t>>) {
unsafe { $clear_thunk(f.as_raw(Private)) }
}
unsafe fn repeated_get_unchecked(f: View<Repeated<$t>>, i: usize) -> View<$t> {
unsafe { $get_thunk(f.as_raw(Private), i) }
}
@ -262,10 +272,12 @@ macro_rules! impl_repeated_primitives {
impl_repeated_primitives!(@impl $(
$t => [
[< __pb_rust_RepeatedField_ $t _new >],
[< __pb_rust_RepeatedField_ $t _free >],
[< __pb_rust_RepeatedField_ $t _add >],
[< __pb_rust_RepeatedField_ $t _size >],
[< __pb_rust_RepeatedField_ $t _get >],
[< __pb_rust_RepeatedField_ $t _set >],
[< __pb_rust_RepeatedField_ $t _clear >],
[< __pb_rust_RepeatedField_ $t _copy_from >],
],
)*);

@ -12,6 +12,10 @@ extern "C" {
google::protobuf::RepeatedField<ty>* __pb_rust_RepeatedField_##rust_ty##_new() { \
return new google::protobuf::RepeatedField<ty>(); \
} \
void __pb_rust_RepeatedField_##rust_ty##_free( \
google::protobuf::RepeatedField<ty>* r) { \
delete r; \
} \
void __pb_rust_RepeatedField_##rust_ty##_add(google::protobuf::RepeatedField<ty>* r, \
ty val) { \
r->Add(val); \
@ -31,6 +35,10 @@ extern "C" {
void __pb_rust_RepeatedField_##rust_ty##_copy_from( \
google::protobuf::RepeatedField<ty> const& src, google::protobuf::RepeatedField<ty>& dst) { \
dst.CopyFrom(src); \
} \
void __pb_rust_RepeatedField_##rust_ty##_clear( \
google::protobuf::RepeatedField<ty>* r) { \
r->Clear(); \
}
expose_repeated_field_methods(int32_t, i32);

@ -110,8 +110,6 @@ impl<'msg, T> RepeatedMut<'msg, T>
where
T: ProxiedInRepeated + ?Sized + 'msg,
{
// TODO: Add clear, free
/// # Safety
/// - `inner` must be valid to read and write from for `'msg`
/// - There must be no aliasing references or mutations on the same
@ -158,6 +156,11 @@ where
pub fn copy_from(&mut self, src: RepeatedView<'_, T>) {
T::repeated_copy_from(src, self.as_mut())
}
/// Clears the repeated field.
pub fn clear(&mut self) {
T::repeated_clear(self.as_mut())
}
}
/// Types that can appear in a `Repeated<T>`.
@ -171,19 +174,30 @@ where
/// - It must be sound to call `*_unchecked*(x)` with an `index` less than
/// `repeated_len(x)`.
pub unsafe trait ProxiedInRepeated: Proxied {
// TODO: Add clear, free
/// Constructs a new owned `Repeated` field.
#[doc(hidden)]
fn repeated_new(_private: Private) -> Repeated<Self> {
unimplemented!("not required")
}
/// Frees the repeated field in-place, for use in `Drop`.
///
/// # Safety
/// - After `repeated_free`, no other methods on the input are safe to call.
#[doc(hidden)]
unsafe fn repeated_free(_private: Private, _repeated: &mut Repeated<Self>) {
unimplemented!("not required")
}
/// Gets the length of the repeated field.
fn repeated_len(repeated: View<Repeated<Self>>) -> usize;
/// Appends a new element to the end of the repeated field.
fn repeated_push(repeated: Mut<Repeated<Self>>, val: View<Self>);
/// Clears the repeated field of elements.
fn repeated_clear(repeated: Mut<Repeated<Self>>);
/// # Safety
/// `index` must be less than `Self::repeated_len(repeated)`
unsafe fn repeated_get_unchecked(repeated: View<Repeated<Self>>, index: usize) -> View<Self>;
@ -235,8 +249,8 @@ pub struct Repeated<T: ?Sized + ProxiedInRepeated> {
_phantom: PhantomData<T>,
}
#[allow(dead_code)]
impl<T: ?Sized + ProxiedInRepeated> Repeated<T> {
#[allow(dead_code)]
pub(crate) fn new() -> Self {
T::repeated_new(Private)
}
@ -245,6 +259,7 @@ impl<T: ?Sized + ProxiedInRepeated> Repeated<T> {
Self { inner, _phantom: PhantomData }
}
#[allow(dead_code)]
pub(crate) fn inner(&mut self) -> InnerRepeatedMut<'static> {
self.inner
}
@ -254,6 +269,13 @@ impl<T: ?Sized + ProxiedInRepeated> Repeated<T> {
}
}
impl<T: ?Sized + ProxiedInRepeated> Drop for Repeated<T> {
fn drop(&mut self) {
// SAFETY: only called once
unsafe { T::repeated_free(Private, self) }
}
}
// SAFETY: `Repeated` does not allow for shared mutability.
unsafe impl<T: ProxiedInRepeated> Sync for Repeated<T> {}
@ -388,6 +410,11 @@ mod tests {
r.iter().collect::<Vec<$t>>(), elements_are![$(eq($vals)),*]);
r.set(0, <$t as Default>::default());
assert_that!(r.get(0).expect("elem 0"), eq(<$t as Default>::default()));
r.clear();
assert!(r.is_empty(), "is_empty after clear");
assert!(r.iter().next().is_none(), "iter empty after clear");
assert!(r.into_iter().next().is_none(), "mut iter empty after clear");
})*
}
}

@ -370,7 +370,6 @@ extern "C" {
macro_rules! impl_repeated_primitives {
($(($t:ty, $ufield:ident, $upb_tag:expr)),* $(,)?) => {
$(
// TODO: Add clear, free
unsafe impl ProxiedInRepeated for $t {
#[allow(dead_code)]
fn repeated_new(_: Private) -> Repeated<$t> {
@ -385,6 +384,16 @@ macro_rules! impl_repeated_primitives {
})
}
}
#[allow(dead_code)]
unsafe fn repeated_free(_: Private, f: &mut Repeated<$t>) {
// Freeing the array itself is handled by `Arena::Drop`
// SAFETY:
// - `f.raw_arena()` is a live `upb_Arena*` as
// - This function is only called once for `f`
unsafe {
upb_Arena_Free(f.inner().arena);
}
}
fn repeated_len(f: View<Repeated<$t>>) -> usize {
unsafe { upb_Array_Size(f.as_raw(Private)) }
}
@ -396,6 +405,9 @@ macro_rules! impl_repeated_primitives {
f.raw_arena(Private))
}
}
fn repeated_clear(mut f: Mut<Repeated<$t>>) {
unsafe { upb_Array_Resize(f.as_raw(Private), 0, f.raw_arena(Private)); }
}
unsafe fn repeated_get_unchecked(f: View<Repeated<$t>>, i: usize) -> View<$t> {
unsafe { upb_Array_Get(f.as_raw(Private), i).$ufield }
}

Loading…
Cancel
Save