pbrs 0.2.0

Pure-Rust Protocol Buffers kernel with the Google protobuf v4 application API
Documentation
#![allow(
    clippy::unimplemented,
    clippy::unwrap_used,
    clippy::expect_used,
    reason = "null MiniTable/MessagePtr is a rust_out kernel invariant, not a user Result"
)]

use crate::string::{ProtoBytes, ProtoString};
use std::fmt::Debug;

use super::{
    Arena, FieldKind, RawRepeatedField, adopt_owned_msg, kernel_fieldkind_to_view,
    kernel_msg_ptr_to_mut, release_bytes, retain_bytes,
};

#[derive(Clone, Copy, Debug)]
pub struct InnerRepeatedMut<'msg> {
    pub raw: RawRepeatedField,
    pub arena: &'msg Arena,
}

impl<'msg> InnerRepeatedMut<'msg> {
    pub fn new(raw: RawRepeatedField, arena: &'msg Arena) -> Self {
        Self { raw, arena }
    }
}

pub fn empty_array<T>() -> crate::repeated::RepeatedView<'static, T> {
    crate::repeated::RepeatedView::from_slice(&[])
}

pub(crate) fn kernel_array_push<T: 'static>(
    raw: RawRepeatedField,
    value: T,
    arena: Option<&Arena>,
) {
    use std::any::TypeId;
    unsafe {
        let arr = &*raw;
        if TypeId::of::<T>() == TypeId::of::<ProtoString>() {
            let s = std::ptr::read(&value as *const T as *const ProtoString);
            std::mem::forget(value);
            arr.items.borrow_mut().push(FieldKind::Bytes(retain_bytes(
                &arr.strs,
                s.as_bytes().to_vec(),
            )));
        } else if TypeId::of::<T>() == TypeId::of::<i32>() {
            let v = std::ptr::read(&value as *const T as *const i32);
            std::mem::forget(value);
            arr.items.borrow_mut().push(FieldKind::I32(v));
        } else if TypeId::of::<T>() == TypeId::of::<i64>() {
            let v = std::ptr::read(&value as *const T as *const i64);
            std::mem::forget(value);
            arr.items.borrow_mut().push(FieldKind::I64(v));
        } else if TypeId::of::<T>() == TypeId::of::<bool>() {
            let v = std::ptr::read(&value as *const T as *const bool);
            std::mem::forget(value);
            arr.items.borrow_mut().push(FieldKind::Bool(v));
        } else if TypeId::of::<T>() == TypeId::of::<ProtoBytes>() {
            let s = std::ptr::read(&value as *const T as *const ProtoBytes);
            std::mem::forget(value);
            arr.items.borrow_mut().push(FieldKind::Bytes(retain_bytes(
                &arr.strs,
                s.as_bytes().to_vec(),
            )));
        } else if TypeId::of::<T>() == TypeId::of::<u32>() {
            let v = std::ptr::read(&value as *const T as *const u32);
            std::mem::forget(value);
            arr.items.borrow_mut().push(FieldKind::U32(v));
        } else if TypeId::of::<T>() == TypeId::of::<u64>() {
            let v = std::ptr::read(&value as *const T as *const u64);
            std::mem::forget(value);
            arr.items.borrow_mut().push(FieldKind::U64(v));
        } else if TypeId::of::<T>() == TypeId::of::<f32>() {
            let v = std::ptr::read(&value as *const T as *const f32);
            std::mem::forget(value);
            arr.items.borrow_mut().push(FieldKind::F32(v));
        } else if TypeId::of::<T>() == TypeId::of::<f64>() {
            let v = std::ptr::read(&value as *const T as *const f64);
            std::mem::forget(value);
            arr.items.borrow_mut().push(FieldKind::F64(v));
        } else if std::mem::size_of::<T>() == 4 && std::mem::align_of::<T>() == 4 {
            let v = std::ptr::read(&value as *const T as *const i32);
            std::mem::forget(value);
            arr.items.borrow_mut().push(FieldKind::I32(v));
        } else {
            arr.items
                .borrow_mut()
                .push(adopt_owned_msg(value, arena, &arr.owner));
        }
    }
}

pub(crate) unsafe fn kernel_repeated_get<'msg, T: crate::proxied::Proxied + 'static>(
    raw: RawRepeatedField,
    index: usize,
) -> Option<crate::proxied::View<'msg, T>> {
    let items = unsafe { (*raw).items.borrow() };
    let fk = *items.get(index)?;
    unsafe { kernel_fieldkind_to_view::<'msg, T>(fk) }
}

pub(crate) unsafe fn kernel_repeated_set<T: 'static>(
    raw: RawRepeatedField,
    index: usize,
    value: T,
) {
    let arr = unsafe { &*raw };
    let old = arr.items.borrow_mut().remove(index);
    release_bytes(&arr.strs, old);
    kernel_array_push(raw, value, None);
    let mut items = arr.items.borrow_mut();
    let last = items.pop().unwrap();
    items.insert(index, last);
}

pub(crate) unsafe fn kernel_repeated_get_mut<'msg, T: crate::proxied::MutProxied + 'static>(
    raw: RawRepeatedField,
    index: usize,
    arena: &'msg Arena,
) -> Option<crate::proxied::Mut<'msg, T>> {
    let items = unsafe { (*raw).items.borrow() };
    let FieldKind::Msg(p) = *items.get(index)? else {
        return None;
    };
    if p.is_null() {
        return None;
    }
    unsafe { kernel_msg_ptr_to_mut::<T>(p, arena) }
}