Move the Rust `Arena` type which wraps a upb_Arena into the upb directory.

PiperOrigin-RevId: 625317910
diff --git a/rust/upb.rs b/rust/upb.rs
index eec3cc1..5a0c07e 100644
--- a/rust/upb.rs
+++ b/rust/upb.rs
@@ -13,12 +13,9 @@
     Repeated, RepeatedMut, RepeatedView, SettableValue, View, ViewProxy,
 };
 use core::fmt::Debug;
-use std::alloc;
 use std::alloc::Layout;
-use std::cell::UnsafeCell;
 use std::fmt;
-use std::marker::PhantomData;
-use std::mem::{align_of, size_of, ManuallyDrop, MaybeUninit};
+use std::mem::{size_of, ManuallyDrop, MaybeUninit};
 use std::ops::Deref;
 use std::ptr::{self, NonNull};
 use std::slice;
@@ -43,123 +40,6 @@
     }
 }
 
-/// See `upb/port/def.inc`.
-const UPB_MALLOC_ALIGN: usize = 8;
-const _CHECK_UPB_MALLOC_ALIGN_AT_LEAST_POINTER_ALIGNED: () =
-    assert!(UPB_MALLOC_ALIGN >= align_of::<*const ()>());
-
-/// A wrapper over a `upb_Arena`.
-///
-/// This is not a safe wrapper per se, because the allocation functions still
-/// have sharp edges (see their safety docs for more info).
-///
-/// This is an owning type and will automatically free the arena when
-/// dropped.
-///
-/// Note that this type is neither `Sync` nor `Send`.
-#[derive(Debug)]
-pub struct Arena {
-    // Safety invariant: this must always be a valid arena
-    raw: RawArena,
-    _not_sync: PhantomData<UnsafeCell<()>>,
-}
-
-impl Arena {
-    /// Allocates a fresh arena.
-    #[inline]
-    pub fn new() -> Self {
-        #[inline(never)]
-        #[cold]
-        fn arena_new_failed() -> ! {
-            panic!("Could not create a new UPB arena");
-        }
-
-        // SAFETY:
-        // - `upb_Arena_New` is assumed to be implemented correctly and always sound to
-        //   call; if it returned a non-null pointer, it is a valid arena.
-        unsafe {
-            let Some(raw) = upb_Arena_New() else { arena_new_failed() };
-            Self { raw, _not_sync: PhantomData }
-        }
-    }
-
-    /// # Safety
-    /// - The `raw_arena` must point to a valid arena.
-    /// - The caller must ensure that the Arena's destructor does not run.
-    unsafe fn from_raw(raw_arena: RawArena) -> Self {
-        Arena { raw: raw_arena, _not_sync: PhantomData }
-    }
-
-    /// Returns the raw, UPB-managed pointer to the arena.
-    #[inline]
-    pub fn raw(&self) -> RawArena {
-        self.raw
-    }
-
-    /// Allocates some memory on the arena.
-    ///
-    /// # Safety
-    ///
-    /// - `layout`'s alignment must be less than `UPB_MALLOC_ALIGN`.
-    #[inline]
-    pub unsafe fn alloc(&self, layout: Layout) -> &mut [MaybeUninit<u8>] {
-        debug_assert!(layout.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);
-        }
-
-        // 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()) }
-    }
-
-    /// Resizes some memory on the arena.
-    ///
-    /// # Safety
-    ///
-    /// - `ptr` must be the data pointer returned by a previous call to `alloc`
-    ///   or `resize` on `self`.
-    /// - After calling this function, `ptr` is no longer dereferencable - it is
-    ///   zapped.
-    /// - `old` must be the layout `ptr` was allocated with via `alloc` or
-    ///   `realloc`.
-    /// - `new`'s alignment must be less than `UPB_MALLOC_ALIGN`.
-    #[inline]
-    pub unsafe fn resize(&self, ptr: *mut u8, old: Layout, new: Layout) -> &mut [MaybeUninit<u8>] {
-        debug_assert!(new.align() <= UPB_MALLOC_ALIGN);
-        // SAFETY:
-        // - `self.raw` is a valid UPB arena
-        // - `ptr` was allocated by a previous call to `alloc` or `realloc` as promised
-        //   by the caller.
-        let ptr = unsafe { upb_Arena_Realloc(self.raw, ptr, old.size(), new.size()) };
-        if ptr.is_null() {
-            alloc::handle_alloc_error(new);
-        }
-
-        // SAFETY:
-        // - `upb_Arena_Realloc` promises that if the return pointer is non-null, it is
-        //   dereferencable for the new `size` in bytes 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(), new.size()) }
-    }
-}
-
-impl Drop for Arena {
-    #[inline]
-    fn drop(&mut self) {
-        unsafe {
-            upb_Arena_Free(self.raw);
-        }
-    }
-}
-
 /// The scratch size of 64 KiB matches the maximum supported size that a
 /// upb_Message can possibly be.
 const UPB_SCRATCH_SPACE_BYTES: usize = 65_536;
@@ -935,12 +815,6 @@
     use googletest::prelude::*;
 
     #[test]
-    fn test_arena_new_and_free() {
-        let arena = Arena::new();
-        drop(arena);
-    }
-
-    #[test]
     fn test_serialized_data_roundtrip() {
         let arena = Arena::new();
         let original_data = b"Hello world";
diff --git a/rust/upb/BUILD b/rust/upb/BUILD
index df43ce9..2c19acc 100644
--- a/rust/upb/BUILD
+++ b/rust/upb/BUILD
@@ -12,7 +12,11 @@
 
 rust_library(
     name = "upb",
-    srcs = ["shared.rs"],
+    srcs = [
+        "arena.rs",
+        "lib.rs",
+        "opaque_pointee.rs",
+    ],
     visibility = [
         "//rust:__subpackages__",
         "//src/google/protobuf:__subpackages__",
diff --git a/rust/upb/arena.rs b/rust/upb/arena.rs
new file mode 100644
index 0000000..51e8958
--- /dev/null
+++ b/rust/upb/arena.rs
@@ -0,0 +1,138 @@
+use crate::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::NonNull;
+use std::slice;
+
+opaque_pointee!(upb_Arena);
+pub type RawArena = NonNull<upb_Arena>;
+
+/// See `upb/port/def.inc`.
+const UPB_MALLOC_ALIGN: usize = 8;
+const _CHECK_UPB_MALLOC_ALIGN_AT_LEAST_POINTER_ALIGNED: () =
+    assert!(UPB_MALLOC_ALIGN >= align_of::<*const ()>());
+
+/// A wrapper over a `upb_Arena`.
+///
+/// This is not a safe wrapper per se, because the allocation functions still
+/// have sharp edges (see their safety docs for more info).
+///
+/// This is an owning type and will automatically free the arena when
+/// dropped.
+///
+/// Note that this type is neither `Sync` nor `Send`. The upb_Arena C object
+/// could be understood as being Sync (at least vacuously, as there are no
+/// const-ptr functions on upb_Arena's API), but the Rust Arena is
+/// necessarily expressed as interior mutability (&self rather than &mut self
+/// receivers) See https://doc.rust-lang.org/nomicon/lifetime-mismatch.html and
+/// https://blog.reverberate.org/2021/12/19/arenas-and-rust.html, and the
+/// 'known problems' section of https://rust-lang.github.io/rust-clippy/master/index.html#/mut_from_ref.
+#[derive(Debug)]
+pub struct Arena {
+    // Safety invariant: this must always be a valid arena
+    raw: RawArena,
+    _not_sync: PhantomData<UnsafeCell<()>>,
+}
+
+impl Arena {
+    /// Allocates a fresh arena.
+    #[inline]
+    pub fn new() -> Self {
+        #[inline(never)]
+        #[cold]
+        fn arena_new_failed() -> ! {
+            panic!("Could not create a new UPB arena");
+        }
+
+        // SAFETY:
+        // - `upb_Arena_New` is assumed to be implemented correctly and always sound to
+        //   call; if it returned a non-null pointer, it is a valid arena.
+        unsafe {
+            let Some(raw) = upb_Arena_New() else { arena_new_failed() };
+            Self { raw, _not_sync: PhantomData }
+        }
+    }
+
+    /// # Safety
+    /// - The `raw_arena` must point to a valid arena.
+    /// - The caller must ensure that the Arena's destructor does not run.
+    pub unsafe fn from_raw(raw_arena: RawArena) -> Self {
+        Arena { raw: raw_arena, _not_sync: PhantomData }
+    }
+
+    /// Returns the raw, UPB-managed pointer to the arena.
+    #[inline]
+    pub fn raw(&self) -> RawArena {
+        self.raw
+    }
+
+    /// Allocates some memory on the arena.
+    ///
+    /// # Safety
+    ///
+    /// - `layout`'s alignment 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);
+        // 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);
+        }
+
+        // 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()) }
+    }
+}
+
+impl Default for Arena {
+    fn default() -> Self {
+        Self::new()
+    }
+}
+
+impl Drop for Arena {
+    #[inline]
+    fn drop(&mut self) {
+        unsafe {
+            upb_Arena_Free(self.raw);
+        }
+    }
+}
+
+extern "C" {
+    // `Option<NonNull<T: Sized>>` is ABI-compatible with `*mut T`
+    fn upb_Arena_New() -> Option<RawArena>;
+    fn upb_Arena_Free(arena: RawArena);
+    fn upb_Arena_Malloc(arena: RawArena, size: usize) -> *mut u8;
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+
+    #[test]
+    fn raw_ffi_test() {
+        // SAFETY: FFI unit test uses C API under expected patterns.
+        unsafe {
+            let arena = upb_Arena_New().unwrap();
+            let bytes = upb_Arena_Malloc(arena, 3);
+            *bytes.add(2) = 7;
+            upb_Arena_Free(arena);
+        }
+    }
+
+    #[test]
+    fn test_arena_new_and_free() {
+        let arena = Arena::new();
+        drop(arena);
+    }
+}
diff --git a/rust/upb/shared.rs b/rust/upb/lib.rs
similarity index 81%
rename from rust/upb/shared.rs
rename to rust/upb/lib.rs
index b61028b..5698908 100644
--- a/rust/upb/shared.rs
+++ b/rust/upb/lib.rs
@@ -1,23 +1,11 @@
 use std::ptr::NonNull;
 use std::slice;
 
-// Macro to create structs that will act as opaque pointees. These structs are
-// never intended to be dereferenced in Rust.
-// This is a workaround until stabilization of [`extern type`].
-// TODO: convert to extern type once stabilized.
-// [`extern type`]: https://github.com/rust-lang/rust/issues/43467
-macro_rules! opaque_pointee {
-    ($name: ident) => {
-        #[repr(C)]
-        pub struct $name {
-            _data: [u8; 0],
-            _marker: std::marker::PhantomData<(*mut u8, std::marker::PhantomPinned)>,
-        }
-    };
-}
+mod opaque_pointee;
+use opaque_pointee::opaque_pointee;
 
-opaque_pointee!(upb_Arena);
-pub type RawArena = NonNull<upb_Arena>;
+mod arena;
+pub use arena::{upb_Arena, Arena, RawArena};
 
 opaque_pointee!(upb_Message);
 pub type RawMessage = NonNull<upb_Message>;
@@ -35,14 +23,6 @@
 pub type RawArray = NonNull<upb_Array>;
 
 extern "C" {
-    // `Option<NonNull<T: Sized>>` is ABI-compatible with `*mut T`
-    pub fn upb_Arena_New() -> Option<RawArena>;
-    pub fn upb_Arena_Free(arena: RawArena);
-    pub fn upb_Arena_Malloc(arena: RawArena, size: usize) -> *mut u8;
-    pub fn upb_Arena_Realloc(arena: RawArena, ptr: *mut u8, old: usize, new: usize) -> *mut u8;
-}
-
-extern "C" {
     pub fn upb_Message_DeepCopy(
         dst: RawMessage,
         src: RawMessage,
@@ -254,34 +234,21 @@
     use super::*;
 
     #[test]
-    fn arena_ffi_test() {
-        // SAFETY: FFI unit test uses C API under expected patterns.
-        unsafe {
-            let arena = upb_Arena_New().unwrap();
-            let bytes = upb_Arena_Malloc(arena, 3);
-            let bytes = upb_Arena_Realloc(arena, bytes, 3, 512);
-            *bytes.add(511) = 7;
-            upb_Arena_Free(arena);
-        }
-    }
-
-    #[test]
     fn array_ffi_test() {
         // SAFETY: FFI unit test uses C API under expected patterns.
         unsafe {
-            let arena = upb_Arena_New().unwrap();
-            let array = upb_Array_New(arena, CType::Float);
+            let arena = Arena::new();
+            let raw_arena = arena.raw();
+            let array = upb_Array_New(raw_arena, CType::Float);
 
-            assert!(upb_Array_Append(array, upb_MessageValue { float_val: 7.0 }, arena));
-            assert!(upb_Array_Append(array, upb_MessageValue { float_val: 42.0 }, arena));
+            assert!(upb_Array_Append(array, upb_MessageValue { float_val: 7.0 }, raw_arena));
+            assert!(upb_Array_Append(array, upb_MessageValue { float_val: 42.0 }, raw_arena));
             assert_eq!(upb_Array_Size(array), 2);
             assert!(matches!(upb_Array_Get(array, 1), upb_MessageValue { float_val: 42.0 }));
 
-            assert!(upb_Array_Resize(array, 3, arena));
+            assert!(upb_Array_Resize(array, 3, raw_arena));
             assert_eq!(upb_Array_Size(array), 3);
             assert!(matches!(upb_Array_Get(array, 2), upb_MessageValue { float_val: 0.0 }));
-
-            upb_Arena_Free(arena);
         }
     }
 
@@ -289,15 +256,16 @@
     fn map_ffi_test() {
         // SAFETY: FFI unit test uses C API under expected patterns.
         unsafe {
-            let arena = upb_Arena_New().unwrap();
-            let map = upb_Map_New(arena, CType::Bool, CType::Double);
+            let arena = Arena::new();
+            let raw_arena = arena.raw();
+            let map = upb_Map_New(raw_arena, CType::Bool, CType::Double);
             assert_eq!(upb_Map_Size(map), 0);
             assert_eq!(
                 upb_Map_Insert(
                     map,
                     upb_MessageValue { bool_val: true },
                     upb_MessageValue { double_val: 2.0 },
-                    arena
+                    raw_arena
                 ),
                 MapInsertStatus::Inserted
             );
@@ -306,7 +274,7 @@
                     map,
                     upb_MessageValue { bool_val: true },
                     upb_MessageValue { double_val: 3.0 },
-                    arena,
+                    raw_arena,
                 ),
                 MapInsertStatus::Replaced,
             );
@@ -318,7 +286,7 @@
                     map,
                     upb_MessageValue { bool_val: true },
                     upb_MessageValue { double_val: 4.0 },
-                    arena
+                    raw_arena
                 ),
                 MapInsertStatus::Inserted
             );
@@ -326,8 +294,6 @@
             let mut out = upb_MessageValue::zeroed();
             assert!(upb_Map_Get(map, upb_MessageValue { bool_val: true }, &mut out));
             assert!(matches!(out, upb_MessageValue { double_val: 4.0 }));
-
-            upb_Arena_Free(arena);
         }
     }
 }
diff --git a/rust/upb/opaque_pointee.rs b/rust/upb/opaque_pointee.rs
new file mode 100644
index 0000000..92bd4a2
--- /dev/null
+++ b/rust/upb/opaque_pointee.rs
@@ -0,0 +1,16 @@
+// Macro to create structs that will act as opaque pointees. These structs are
+// never intended to be dereferenced in Rust.
+// This is a workaround until stabilization of [`extern type`].
+// TODO: convert to extern type once stabilized.
+// [`extern type`]: https://github.com/rust-lang/rust/issues/43467
+macro_rules! opaque_pointee {
+    ($name: ident) => {
+        #[repr(C)]
+        pub struct $name {
+            _data: [u8; 0],
+            _marker: std::marker::PhantomData<(*mut u8, std::marker::PhantomPinned)>,
+        }
+    };
+}
+
+pub(crate) use opaque_pointee;