blob: 5b8f06227f575776bc8b9e1b2c45d1f5d135eb3d [file] [log] [blame] [edit]
use super::*;
/// The raw type-erased version of an owned `Repeated`.
#[derive(Debug)]
#[doc(hidden)]
pub struct InnerRepeated {
raw: RawRepeatedField,
arena: Arena,
}
impl InnerRepeated {
pub fn as_mut(&mut self) -> InnerRepeatedMut<'_> {
InnerRepeatedMut::new(self.raw, &self.arena)
}
pub fn raw(&self) -> RawRepeatedField {
self.raw
}
pub fn arena(&self) -> &Arena {
&self.arena
}
/// # Safety
/// - `raw` must be a valid `RawRepeatedField`
pub unsafe fn from_raw_parts(raw: RawRepeatedField, arena: Arena) -> Self {
Self { raw, arena }
}
}
/// The raw type-erased pointer version of `RepeatedMut`.
#[derive(Clone, Copy, Debug)]
#[doc(hidden)]
pub struct InnerRepeatedMut<'msg> {
pub(crate) raw: RawRepeatedField,
arena: &'msg Arena,
}
impl<'msg> InnerRepeatedMut<'msg> {
#[doc(hidden)]
pub fn new(raw: RawRepeatedField, arena: &'msg Arena) -> Self {
InnerRepeatedMut { raw, arena }
}
}
unsafe impl<T> Singular for T
where
T: EntityType + UpbTypeConversions<T::Tag>,
{
fn repeated_new(_private: Private) -> Repeated<Self> {
let arena = Arena::new();
Repeated::from_inner(Private, unsafe {
InnerRepeated::from_raw_parts(upb_Array_New(arena.raw(), T::upb_type()), arena)
})
}
unsafe fn repeated_free(_private: Private, _repeated: &mut Repeated<Self>) {
// No-op: the memory will be dropped by the arena.
}
fn repeated_len(_private: Private, repeated: View<Repeated<Self>>) -> usize {
// SAFETY: `repeated.as_raw()` is a valid `upb_Array*`.
unsafe { upb_Array_Size(repeated.as_raw(Private)) }
}
fn repeated_push(
_private: Private,
mut repeated: Mut<Repeated<Self>>,
val: impl IntoProxied<Self>,
) {
// SAFETY:
// - `repeated.as_raw()` is a valid `upb_Array*`.
// - `msg_ptr` is a valid `upb_Message*`.
unsafe {
upb_Array_Append(
repeated.as_raw(Private),
T::into_message_value_fuse_if_required(
repeated.raw_arena(Private),
val.into_proxied(Private),
),
repeated.raw_arena(Private),
);
};
}
fn repeated_clear(_private: Private, mut repeated: Mut<Repeated<Self>>) {
// SAFETY:
// - `repeated.as_raw()` is a valid `upb_Array*`.
unsafe { upb_Array_Resize(repeated.as_raw(Private), 0, repeated.raw_arena(Private)) };
}
unsafe fn repeated_get_unchecked<'a>(
_private: Private,
repeated: View<'a, Repeated<Self>>,
index: usize,
) -> View<'a, Self> {
// SAFETY:
// - `repeated.as_raw()` is a valid `const upb_Array*`.
// - `index < len(repeated)` is promised by the caller.
let val = unsafe { upb_Array_Get(repeated.as_raw(Private), index) };
// SAFETY:
// - `val` has the correct variant for Self.
// - `val` is valid for `'a` lifetime.
unsafe { Self::from_message_value(val) }
}
unsafe fn repeated_get_mut_unchecked<'a>(
_private: Private,
mut repeated: Mut<'a, Repeated<Self>>,
index: usize,
) -> Mut<'a, Self>
where
Self: Message,
{
// SAFETY:
// - `repeated.as_raw()` is a valid `upb_Array*`.
// - `repeated` is a an array of message-valued elements.
// - `index < len(repeated)` is promised by the caller.
let val = unsafe { upb_Array_GetMutable(repeated.as_raw(Private), index) };
// SAFETY:
// - `val` is the correct variant for `Self`.
// - `val` is valid for `'a` lifetime.
unsafe { Self::from_message_mut(val, repeated.arena(Private)) }
}
unsafe fn repeated_set_unchecked(
_private: Private,
mut repeated: Mut<Repeated<Self>>,
index: usize,
val: impl IntoProxied<Self>,
) {
unsafe {
upb_Array_Set(
repeated.as_raw(Private),
index,
T::into_message_value_fuse_if_required(
repeated.raw_arena(Private),
val.into_proxied(Private),
),
)
}
}
fn repeated_copy_from(
_private: Private,
src: View<Repeated<Self>>,
mut dest: Mut<Repeated<Self>>,
) {
// SAFETY:
// - `src.as_raw()` and `dest.as_raw()` are both valid arrays of `Self`.
// - `dest.as_raw()` is mutable.
// - `dest.raw_arena()` will outlive `dest.as_raw()`.
unsafe {
Self::copy_repeated(src.as_raw(Private), dest.as_raw(Private), dest.raw_arena(Private));
}
}
fn repeated_reserve(_private: Private, mut repeated: Mut<Repeated<Self>>, additional: usize) {
// SAFETY:
// - `repeated.as_raw()` is a valid `upb_Array*`.
unsafe {
let size = upb_Array_Size(repeated.as_raw(Private));
upb_Array_Reserve(
repeated.as_raw(Private),
size + additional,
repeated.raw_arena(Private),
);
}
}
}
impl<'msg, T> RepeatedMut<'msg, T> {
// Returns a `RawArena` which is live for at least `'msg`
#[doc(hidden)]
pub fn raw_arena(&mut self, _private: Private) -> RawArena {
self.inner.arena.raw()
}
// Returns an `Arena` which is live for at least `'msg`
#[doc(hidden)]
pub fn arena(&self, _private: Private) -> &'msg Arena {
self.inner.arena
}
}
/// Returns a static empty RepeatedView.
pub fn empty_array<T: Singular>() -> RepeatedView<'static, T> {
// TODO: Consider creating a static empty array in C.
// Use `i32` for a shared empty repeated for all repeated types in the program.
static EMPTY_REPEATED_VIEW: OnceLock<Repeated<i32>> = OnceLock::new();
// SAFETY:
// - Because the repeated is never mutated, the repeated type is unused and
// therefore valid for `T`.
unsafe {
RepeatedView::from_raw(
Private,
EMPTY_REPEATED_VIEW.get_or_init(Repeated::new).as_view().as_raw(Private),
)
}
}