Change `upb` crate source to not use std or alloc
PiperOrigin-RevId: 671865731
diff --git a/rust/upb.rs b/rust/upb.rs
index 7ace10e..5cd4bb4 100644
--- a/rust/upb.rs
+++ b/rust/upb.rs
@@ -13,7 +13,6 @@
Proxied, ProxiedInMapValue, ProxiedInRepeated, Repeated, RepeatedMut, RepeatedView, View,
};
use core::fmt::Debug;
-use std::alloc::Layout;
use std::mem::{size_of, ManuallyDrop, MaybeUninit};
use std::ptr::{self, NonNull};
use std::slice;
@@ -133,21 +132,6 @@
}
}
-fn copy_bytes_in_arena<'msg>(arena: &'msg Arena, val: &'msg [u8]) -> &'msg [u8] {
- // SAFETY: the alignment of `[u8]` is less than `UPB_MALLOC_ALIGN`.
- let new_alloc = unsafe { arena.alloc(Layout::for_value(val)) };
- debug_assert_eq!(new_alloc.len(), val.len());
-
- let start: *mut u8 = new_alloc.as_mut_ptr().cast();
- // SAFETY:
- // - `new_alloc` is writeable for `val.len()` bytes.
- // - After the copy, `new_alloc` is initialized for `val.len()` bytes.
- unsafe {
- val.as_ptr().copy_to_nonoverlapping(start, val.len());
- &*(new_alloc as *mut _ as *mut [u8])
- }
-}
-
/// Kernel-specific owned `string` and `bytes` field type.
#[doc(hidden)]
pub struct InnerProtoString(OwnedArenaBox<[u8]>);
@@ -167,7 +151,7 @@
impl From<&[u8]> for InnerProtoString {
fn from(val: &[u8]) -> InnerProtoString {
let arena = Arena::new();
- let in_arena_copy = arena.copy_slice_in(val);
+ let in_arena_copy = arena.copy_slice_in(val).unwrap();
// SAFETY:
// - `in_arena_copy` is valid slice that will live for `arena`'s lifetime and
// this is the only reference in the program to it.
@@ -354,7 +338,7 @@
len
);
for (src_ptr, dest_ptr) in src_ptrs.iter().zip(dest_ptrs) {
- *dest_ptr = copy_bytes_in_arena(&arena, src_ptr.as_ref()).into();
+ *dest_ptr = arena.copy_slice_in(src_ptr.as_ref()).unwrap().into();
}
}
}
diff --git a/rust/upb/arena.rs b/rust/upb/arena.rs
index d4581ea..5f90c6b 100644
--- a/rust/upb/arena.rs
+++ b/rust/upb/arena.rs
@@ -6,12 +6,11 @@
// https://developers.google.com/open-source/licenses/bsd
use super::opaque_pointee::opaque_pointee;
-use std::alloc::{self, Layout};
-use std::cell::UnsafeCell;
-use std::marker::PhantomData;
-use std::mem::{align_of, MaybeUninit};
-use std::ptr::{self, NonNull};
-use std::slice;
+use core::cell::UnsafeCell;
+use core::marker::PhantomData;
+use core::mem::{align_of, align_of_val, size_of_val, MaybeUninit};
+use core::ptr::{self, NonNull};
+use core::slice;
opaque_pointee!(upb_Arena);
pub type RawArena = NonNull<upb_Arena>;
@@ -79,75 +78,85 @@
self.raw
}
- /// Allocates some memory on the arena.
+ /// Allocates some memory on the arena. Returns None if the allocation
+ /// failed.
///
/// # Safety
///
- /// - `layout`'s alignment must be less than `UPB_MALLOC_ALIGN`.
+ /// - `align` must be less than `UPB_MALLOC_ALIGN`.
#[allow(clippy::mut_from_ref)]
#[inline]
- pub unsafe fn alloc(&self, layout: Layout) -> &mut [MaybeUninit<u8>] {
- debug_assert!(layout.align() <= UPB_MALLOC_ALIGN);
+ pub unsafe fn alloc(&self, size: usize, align: usize) -> Option<&mut [MaybeUninit<u8>]> {
+ debug_assert!(align <= UPB_MALLOC_ALIGN);
// SAFETY: `self.raw` is a valid UPB arena
- let ptr = unsafe { upb_Arena_Malloc(self.raw, layout.size()) };
- if ptr.is_null() {
- alloc::handle_alloc_error(layout);
- }
+ let ptr = unsafe { upb_Arena_Malloc(self.raw, size) };
- // SAFETY:
- // - `upb_Arena_Malloc` promises that if the return pointer is non-null, it is
- // dereferencable for `size` bytes and has an alignment of `UPB_MALLOC_ALIGN`
- // until the arena is destroyed.
- // - `[MaybeUninit<u8>]` has no alignment requirement, and `ptr` is aligned to a
- // `UPB_MALLOC_ALIGN` boundary.
- unsafe { slice::from_raw_parts_mut(ptr.cast(), layout.size()) }
+ if ptr.is_null() {
+ None
+ } else {
+ // SAFETY:
+ // - `upb_Arena_Malloc` promises that if the return pointer is non-null, it is
+ // dereferencable for `size` bytes and has an alignment of `UPB_MALLOC_ALIGN`
+ // until the arena is destroyed.
+ // - `[MaybeUninit<u8>]` has no alignment requirement, and `ptr` is aligned to a
+ // `UPB_MALLOC_ALIGN` boundary.
+ Some(unsafe { slice::from_raw_parts_mut(ptr.cast(), size) })
+ }
}
- /// Same as alloc() but panics if `layout.align() > UPB_MALLOC_ALIGN`.
+ /// Same as alloc() but panics if `align > UPB_MALLOC_ALIGN`.
#[allow(clippy::mut_from_ref)]
#[inline]
- pub fn checked_alloc(&self, layout: Layout) -> &mut [MaybeUninit<u8>] {
- assert!(layout.align() <= UPB_MALLOC_ALIGN);
- // SAFETY: layout.align() <= UPB_MALLOC_ALIGN asserted.
- unsafe { self.alloc(layout) }
+ pub fn checked_alloc(&self, size: usize, align: usize) -> Option<&mut [MaybeUninit<u8>]> {
+ assert!(align <= UPB_MALLOC_ALIGN);
+ // SAFETY: align <= UPB_MALLOC_ALIGN asserted.
+ unsafe { self.alloc(size, align) }
}
/// Copies the T into this arena and returns a pointer to the T data inside
- /// the arena.
- pub fn copy_in<'a, T: Copy>(&'a self, data: &T) -> &'a T {
- let layout = Layout::for_value(data);
- let alloc = self.checked_alloc(layout);
+ /// the arena. Returns None if the allocation failed.
+ pub fn copy_in<'a, T: Copy>(&'a self, data: &T) -> Option<&'a T> {
+ let size = size_of_val(data);
+ let align = align_of_val(data);
- // SAFETY:
- // - alloc is valid for `layout.len()` bytes and is the uninit bytes are written
- // to not read from until written.
- // - T is copy so copying the bytes of the value is sound.
- unsafe {
- let alloc = alloc.as_mut_ptr().cast::<MaybeUninit<T>>();
- // let data = (data as *const T).cast::<MaybeUninit<T>>();
- (*alloc).write(*data)
- }
+ self.checked_alloc(size, align).map(|alloc| {
+ // SAFETY:
+ // - alloc is valid for `size` bytes and is the uninit bytes are written to not
+ // read from until written.
+ // - T is copy so copying the bytes of the value is sound.
+ unsafe {
+ let alloc = alloc.as_mut_ptr().cast::<MaybeUninit<T>>();
+ &*(*alloc).write(*data)
+ }
+ })
}
- pub fn copy_str_in<'a>(&'a self, s: &str) -> &'a str {
- let copied_bytes = self.copy_slice_in(s.as_bytes());
- // SAFETY: `copied_bytes` has same contents as `s` and so must meet &str
- // criteria.
- unsafe { std::str::from_utf8_unchecked(copied_bytes) }
+ /// Copies the str into this arena and returns a pointer to the T data
+ /// inside the arena. Returns None if the allocation failed.
+ pub fn copy_str_in<'a>(&'a self, s: &str) -> Option<&'a str> {
+ self.copy_slice_in(s.as_bytes()).map(|copied_bytes| {
+ // SAFETY: `copied_bytes` has same contents as `s` and so must meet &str
+ // criteria.
+ unsafe { core::str::from_utf8_unchecked(copied_bytes) }
+ })
}
- pub fn copy_slice_in<'a, T: Copy>(&'a self, data: &[T]) -> &'a [T] {
- let layout = Layout::for_value(data);
- let alloc: *mut T = self.checked_alloc(layout).as_mut_ptr().cast();
-
- // SAFETY:
- // - uninit_alloc is valid for `layout.len()` bytes and is the uninit bytes are
- // written to not read from until written.
- // - T is copy so copying the bytes of the values is sound.
- unsafe {
- ptr::copy_nonoverlapping(data.as_ptr(), alloc, data.len());
- slice::from_raw_parts_mut(alloc, data.len())
- }
+ /// Copies the slice into this arena and returns a pointer to the T data
+ /// inside the arena. Returns None if the allocation failed.
+ pub fn copy_slice_in<'a, T: Copy>(&'a self, data: &[T]) -> Option<&'a [T]> {
+ let size = size_of_val(data);
+ let align = align_of_val(data);
+ self.checked_alloc(size, align).map(|alloc| {
+ let alloc: *mut T = alloc.as_mut_ptr().cast();
+ // SAFETY:
+ // - uninit_alloc is valid for `layout.len()` bytes and is the uninit bytes are
+ // written to not read from until written.
+ // - T is copy so copying the bytes of the values is sound.
+ unsafe {
+ ptr::copy_nonoverlapping(data.as_ptr(), alloc, data.len());
+ slice::from_raw_parts(alloc, data.len())
+ }
+ })
}
/// Fuse two arenas so they share the same lifetime.
diff --git a/rust/upb/array.rs b/rust/upb/array.rs
index 1c42cef..6fb7c30 100644
--- a/rust/upb/array.rs
+++ b/rust/upb/array.rs
@@ -7,7 +7,7 @@
use super::opaque_pointee::opaque_pointee;
use super::{upb_MessageValue, upb_MutableMessageValue, CType, RawArena};
-use std::ptr::NonNull;
+use core::ptr::NonNull;
opaque_pointee!(upb_Array);
pub type RawArray = NonNull<upb_Array>;
@@ -20,8 +20,8 @@
pub fn upb_Array_Append(arr: RawArray, val: upb_MessageValue, arena: RawArena) -> bool;
pub fn upb_Array_Resize(arr: RawArray, size: usize, arena: RawArena) -> bool;
pub fn upb_Array_Reserve(arr: RawArray, size: usize, arena: RawArena) -> bool;
- pub fn upb_Array_MutableDataPtr(arr: RawArray) -> *mut std::ffi::c_void;
- pub fn upb_Array_DataPtr(arr: RawArray) -> *const std::ffi::c_void;
+ pub fn upb_Array_MutableDataPtr(arr: RawArray) -> *mut core::ffi::c_void;
+ pub fn upb_Array_DataPtr(arr: RawArray) -> *const core::ffi::c_void;
pub fn upb_Array_GetMutable(arr: RawArray, i: usize) -> upb_MutableMessageValue;
}
diff --git a/rust/upb/extension_registry.rs b/rust/upb/extension_registry.rs
index ce7fd26..a61c9eb 100644
--- a/rust/upb/extension_registry.rs
+++ b/rust/upb/extension_registry.rs
@@ -6,7 +6,7 @@
// https://developers.google.com/open-source/licenses/bsd
use super::opaque_pointee::opaque_pointee;
-use std::ptr::NonNull;
+use core::ptr::NonNull;
opaque_pointee!(upb_ExtensionRegistry);
pub type RawExtensionRegistry = NonNull<upb_ExtensionRegistry>;
diff --git a/rust/upb/map.rs b/rust/upb/map.rs
index 5b3a8d7..554b43c 100644
--- a/rust/upb/map.rs
+++ b/rust/upb/map.rs
@@ -7,7 +7,7 @@
use super::opaque_pointee::opaque_pointee;
use super::{upb_MessageValue, CType, RawArena};
-use std::ptr::NonNull;
+use core::ptr::NonNull;
opaque_pointee!(upb_Map);
pub type RawMap = NonNull<upb_Map>;
diff --git a/rust/upb/message.rs b/rust/upb/message.rs
index 9b5535f..8d39748 100644
--- a/rust/upb/message.rs
+++ b/rust/upb/message.rs
@@ -10,7 +10,7 @@
upb_ExtensionRegistry, upb_MiniTable, upb_MiniTableField, RawArena, RawArray, RawMap,
StringView,
};
-use std::ptr::NonNull;
+use core::ptr::NonNull;
opaque_pointee!(upb_Message);
pub type RawMessage = NonNull<upb_Message>;
@@ -215,7 +215,7 @@
pub fn upb_Message_SetBaseField(
m: RawMessage,
f: *const upb_MiniTableField,
- val: *const std::ffi::c_void,
+ val: *const core::ffi::c_void,
);
/// # Safety
diff --git a/rust/upb/message_value.rs b/rust/upb/message_value.rs
index 5cde4d6..2fdae9d 100644
--- a/rust/upb/message_value.rs
+++ b/rust/upb/message_value.rs
@@ -12,8 +12,8 @@
#[derive(Clone, Copy)]
pub union upb_MessageValue {
pub bool_val: bool,
- pub float_val: std::ffi::c_float,
- pub double_val: std::ffi::c_double,
+ pub float_val: core::ffi::c_float,
+ pub double_val: core::ffi::c_double,
pub uint32_val: u32,
pub int32_val: i32,
pub uint64_val: u64,
@@ -24,14 +24,14 @@
pub msg_val: Option<RawMessage>,
pub str_val: StringView,
- tagged_msg_val: *const std::ffi::c_void,
+ tagged_msg_val: *const core::ffi::c_void,
}
impl upb_MessageValue {
pub fn zeroed() -> Self {
// SAFETY: zero bytes is a valid representation for at least one value in the
// union (actually valid for all of them).
- unsafe { std::mem::zeroed() }
+ unsafe { core::mem::zeroed() }
}
}
diff --git a/rust/upb/mini_table.rs b/rust/upb/mini_table.rs
index 440a695..6261891 100644
--- a/rust/upb/mini_table.rs
+++ b/rust/upb/mini_table.rs
@@ -6,7 +6,7 @@
// https://developers.google.com/open-source/licenses/bsd
use super::opaque_pointee::opaque_pointee;
-use std::ptr::NonNull;
+use core::ptr::NonNull;
opaque_pointee!(upb_MiniTable);
pub type RawMiniTable = NonNull<upb_MiniTable>;
diff --git a/rust/upb/opaque_pointee.rs b/rust/upb/opaque_pointee.rs
index 90033f1..d89d5b1 100644
--- a/rust/upb/opaque_pointee.rs
+++ b/rust/upb/opaque_pointee.rs
@@ -15,7 +15,7 @@
#[repr(C)]
pub struct $name {
_data: [u8; 0],
- _marker: std::marker::PhantomData<(*mut u8, std::marker::PhantomPinned)>,
+ _marker: core::marker::PhantomData<(*mut u8, core::marker::PhantomPinned)>,
}
};
}
diff --git a/rust/upb/owned_arena_box.rs b/rust/upb/owned_arena_box.rs
index c4ff1ac..6cfc8e7 100644
--- a/rust/upb/owned_arena_box.rs
+++ b/rust/upb/owned_arena_box.rs
@@ -6,9 +6,9 @@
// https://developers.google.com/open-source/licenses/bsd
use super::Arena;
-use std::fmt::{self, Debug};
-use std::ops::{Deref, DerefMut};
-use std::ptr::NonNull;
+use core::fmt::{self, Debug};
+use core::ops::{Deref, DerefMut};
+use core::ptr::NonNull;
/// An 'owned' T, similar to a Box<T> where the T is data
/// held in a upb Arena. By holding the data pointer and a corresponding arena
@@ -18,7 +18,7 @@
/// inside `arena`. This avoids typical concerns of self-referential data
/// structures because `arena` modifications (other than drop) will never
/// invalidate `data`, and `data` and `arena` are both behind indirections which
-/// avoids any concern with std::mem::swap.
+/// avoids any concern with core::mem::swap.
pub struct OwnedArenaBox<T: ?Sized + 'static> {
data: NonNull<T>,
arena: Arena,
@@ -87,7 +87,7 @@
#[cfg(test)]
mod tests {
use super::*;
- use std::str;
+ use core::str;
#[test]
fn test_byte_slice_pointer_roundtrip() {
@@ -101,7 +101,7 @@
fn test_alloc_str_roundtrip() {
let arena = Arena::new();
let s: &str = "Hello";
- let arena_alloc_str: NonNull<str> = arena.copy_str_in(s).into();
+ let arena_alloc_str: NonNull<str> = arena.copy_str_in(s).unwrap().into();
let owned_data = unsafe { OwnedArenaBox::new(arena_alloc_str, arena) };
assert_eq!(&*owned_data, s);
}
@@ -109,7 +109,7 @@
#[test]
fn test_sized_type_roundtrip() {
let arena = Arena::new();
- let arena_alloc_u32: NonNull<u32> = arena.copy_in(&7u32).into();
+ let arena_alloc_u32: NonNull<u32> = arena.copy_in(&7u32).unwrap().into();
let mut owned_data = unsafe { OwnedArenaBox::new(arena_alloc_u32, arena) };
assert_eq!(*owned_data, 7);
*owned_data = 8;
diff --git a/rust/upb/string_view.rs b/rust/upb/string_view.rs
index 55c6042..c39b2b2 100644
--- a/rust/upb/string_view.rs
+++ b/rust/upb/string_view.rs
@@ -7,11 +7,11 @@
/// ABI compatible struct with upb_StringView.
///
-/// Note that this has semantics similar to `std::string_view` in C++ and
+/// Note that this has semantics similar to `core::string_view` in C++ and
/// `&[u8]` in Rust, but is not ABI-compatible with either.
///
/// If `len` is 0, then `ptr` is allowed to be either null or dangling. C++
-/// considers a dangling 0-len `std::string_view` to be invalid, and Rust
+/// considers a dangling 0-len `core::string_view` to be invalid, and Rust
/// considers a `&[u8]` with a null data pointer to be invalid.
#[repr(C)]
#[derive(Copy, Clone)]
@@ -38,7 +38,7 @@
// SAFETY:
// - `ptr` is non-null
// - `ptr` is valid for `len` bytes as promised by the caller.
- unsafe { std::slice::from_raw_parts(self.ptr, self.len) }
+ unsafe { core::slice::from_raw_parts(self.ptr, self.len) }
}
}
}
diff --git a/rust/upb/text.rs b/rust/upb/text.rs
index 2f1cf09..56dddb8 100644
--- a/rust/upb/text.rs
+++ b/rust/upb/text.rs
@@ -50,7 +50,7 @@
// `mt`
// - `buf` is nullptr and `buf_len` is 0
let len =
- unsafe { upb_DebugString(msg, mt, Options::NoSortMaps as i32, std::ptr::null_mut(), 0) };
+ unsafe { upb_DebugString(msg, mt, Options::NoSortMaps as i32, core::ptr::null_mut(), 0) };
assert!(len < isize::MAX as usize);
// +1 for the trailing NULL
let mut buf = vec![0u8; len + 1];
diff --git a/rust/upb/wire.rs b/rust/upb/wire.rs
index 75e666f..eb08e7b 100644
--- a/rust/upb/wire.rs
+++ b/rust/upb/wire.rs
@@ -50,7 +50,7 @@
mini_table: *const upb_MiniTable,
) -> Result<Vec<u8>, EncodeStatus> {
let arena = Arena::new();
- let mut buf: *mut u8 = std::ptr::null_mut();
+ let mut buf: *mut u8 = core::ptr::null_mut();
let mut len = 0usize;
// SAFETY:
@@ -61,7 +61,7 @@
if status == EncodeStatus::Ok {
assert!(!buf.is_null()); // EncodeStatus Ok should never return NULL data, even for len=0.
// SAFETY: upb guarantees that `buf` is valid to read for `len`.
- Ok(unsafe { &*std::ptr::slice_from_raw_parts(buf, len) }.to_vec())
+ Ok(unsafe { &*core::ptr::slice_from_raw_parts(buf, len) }.to_vec())
} else {
Err(status)
}
@@ -88,7 +88,7 @@
// - `buf` is legally readable for at least `buf_size` bytes.
// - `extreg` is null.
let status =
- unsafe { upb_Decode(buf, len, msg, mini_table, std::ptr::null(), options, arena.raw()) };
+ unsafe { upb_Decode(buf, len, msg, mini_table, core::ptr::null(), options, arena.raw()) };
match status {
DecodeStatus::Ok => Ok(()),
_ => Err(status),