diff --git a/litebox/src/fd/mod.rs b/litebox/src/fd/mod.rs index aeef757dd..199b66137 100644 --- a/litebox/src/fd/mod.rs +++ b/litebox/src/fd/mod.rs @@ -414,7 +414,7 @@ impl Descriptors { ) -> Result where Subsystem: FdEnabledSubsystem, - T: core::any::Any + Send + Sync, + T: core::any::Any + Clone + Send + Sync, { let ind_entry = self.entries[fd.x.as_usize().ok_or(MetadataError::ClosedFd)?] .as_ref() @@ -442,7 +442,7 @@ impl Descriptors { ) -> Result where Subsystem: FdEnabledSubsystem, - T: core::any::Any + Send + Sync, + T: core::any::Any + Clone + Send + Sync, { let ind_entry = self.entries[fd.x.as_usize().ok_or(MetadataError::ClosedFd)?] .as_mut() @@ -477,7 +477,7 @@ impl Descriptors { ) -> Option where Subsystem: FdEnabledSubsystem, - T: core::any::Any + Send + Sync, + T: core::any::Any + Clone + Send + Sync, { self.entries[fd.x.as_usize()?] .as_ref() @@ -506,7 +506,7 @@ impl Descriptors { ) -> Option where Subsystem: FdEnabledSubsystem, - T: core::any::Any + Send + Sync, + T: core::any::Any + Clone + Send + Sync, { self.entries[fd.x.as_usize()?] .as_mut() diff --git a/litebox/src/utilities/anymap.rs b/litebox/src/utilities/anymap.rs index 68af3f8a6..b6e2887cc 100644 --- a/litebox/src/utilities/anymap.rs +++ b/litebox/src/utilities/anymap.rs @@ -11,17 +11,45 @@ //! to keep things largely consistent with the anymap crate. //! //! Due to how we're using it within LiteBox, what we are doing is something similar to -//! `anymap::Map` rather than a direct `anymap::AnyMap` (which would just be -//! equivalent to `anymap::Map`). +//! `anymap::Map` rather than a direct `anymap::AnyMap` (which would +//! just be equivalent to `anymap::Map`). use alloc::boxed::Box; -use core::any::{Any, TypeId}; +use core::any::Any; use hashbrown::HashMap; +/// Explicitly private module that prevents creating a [`Tid`] without confirming that the `T` +/// satisfies all the required properties. This allows our implementation of `Clone` for `AnyMap` to +/// be sound. +mod private { + #[derive(Clone, PartialEq, Eq, Hash)] + pub(super) struct Tid(core::any::TypeId); + impl Tid { + pub(super) fn of() -> Self { + Self(core::any::TypeId::of::()) + } + } +} +use private::Tid; + +trait AnyCloneSendSync: Any + Send + Sync { + fn clone_to_any(&self) -> Box; +} +impl AnyCloneSendSync for T { + fn clone_to_any(&self) -> Box { + Box::new(self.clone()) + } +} +impl Clone for Box { + fn clone(&self) -> Self { + (**self).clone_to_any() + } +} + /// A safe store of exactly one value of any type `T`. pub(crate) struct AnyMap { // Invariant: the value at a particular typeid is guaranteed to be the correct type boxed up. - storage: HashMap>, + storage: HashMap>, } const GUARANTEED: &str = "guaranteed correct type by invariant"; @@ -35,21 +63,22 @@ impl AnyMap { } /// Insert `v`, replacing and returning the old value if one existed already. - pub(crate) fn insert(&mut self, v: T) -> Option { - let old = self.storage.insert(TypeId::of::(), Box::new(v))?; + pub(crate) fn insert(&mut self, v: T) -> Option { + let old: Box = self.storage.insert(Tid::of::(), Box::new(v))?; + let old: Box = old; Some(*old.downcast().expect(GUARANTEED)) } /// Get a reference to a value of type `T` if it exists. - pub(crate) fn get(&self) -> Option<&T> { - let v = self.storage.get(&TypeId::of::())?; - Some(v.downcast_ref().expect(GUARANTEED)) + pub(crate) fn get(&self) -> Option<&T> { + let v = self.storage.get(&Tid::of::())?; + Some((&**v as &dyn Any).downcast_ref().expect(GUARANTEED)) } /// Get a mutable reference to a value of type `T` if it exists. - pub(crate) fn get_mut(&mut self) -> Option<&mut T> { - let v = self.storage.get_mut(&TypeId::of::())?; - Some(v.downcast_mut().expect(GUARANTEED)) + pub(crate) fn get_mut(&mut self) -> Option<&mut T> { + let v = self.storage.get_mut(&Tid::of::())?; + Some((&mut **v as &mut dyn Any).downcast_mut().expect(GUARANTEED)) } #[expect( @@ -57,8 +86,17 @@ impl AnyMap { reason = "currently unused, but perfectly reasonable to use in future" )] /// Remove and return the value of type `T` if it exists. - pub(crate) fn remove(&mut self) -> Option { - let v = self.storage.remove(&TypeId::of::())?; + pub(crate) fn remove(&mut self) -> Option { + let v: Box = self.storage.remove(&Tid::of::())?; + let v: Box = v; Some(*v.downcast().expect(GUARANTEED)) } } + +impl Clone for AnyMap { + fn clone(&self) -> Self { + Self { + storage: self.storage.clone(), + } + } +} diff --git a/litebox_shim_linux/src/lib.rs b/litebox_shim_linux/src/lib.rs index 2834f7b72..2026a0f15 100644 --- a/litebox_shim_linux/src/lib.rs +++ b/litebox_shim_linux/src/lib.rs @@ -343,9 +343,11 @@ fn default_fs( } // Special override so that `GETFL` can return stdio-specific flags +#[derive(Clone)] pub(crate) struct StdioStatusFlags(litebox::fs::OFlags); /// Status flags for pipes +#[derive(Clone)] pub(crate) struct PipeStatusFlags(pub litebox::fs::OFlags); impl syscalls::file::FilesState { diff --git a/litebox_shim_linux/src/syscalls/net.rs b/litebox_shim_linux/src/syscalls/net.rs index d1b04e894..9192971c1 100644 --- a/litebox_shim_linux/src/syscalls/net.rs +++ b/litebox_shim_linux/src/syscalls/net.rs @@ -155,7 +155,7 @@ impl SocketAddress { } } -#[derive(Default)] +#[derive(Default, Clone)] pub(super) struct SocketOptions { pub(super) reuse_address: bool, pub(super) keep_alive: bool, @@ -171,7 +171,9 @@ pub(super) struct SocketOptions { pub(super) linger_timeout: Option, } +#[derive(Clone)] pub(crate) struct SocketOFlags(pub OFlags); +#[derive(Clone)] pub(crate) struct SocketProxy(pub Arc>); pub(super) enum SocketOptionValue {