Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions litebox/src/fd/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -414,7 +414,7 @@ impl<Platform: RawSyncPrimitivesProvider> Descriptors<Platform> {
) -> Result<R, MetadataError>
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()
Expand Down Expand Up @@ -442,7 +442,7 @@ impl<Platform: RawSyncPrimitivesProvider> Descriptors<Platform> {
) -> Result<R, MetadataError>
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()
Expand Down Expand Up @@ -477,7 +477,7 @@ impl<Platform: RawSyncPrimitivesProvider> Descriptors<Platform> {
) -> Option<T>
where
Subsystem: FdEnabledSubsystem,
T: core::any::Any + Send + Sync,
T: core::any::Any + Clone + Send + Sync,
{
self.entries[fd.x.as_usize()?]
.as_ref()
Expand Down Expand Up @@ -506,7 +506,7 @@ impl<Platform: RawSyncPrimitivesProvider> Descriptors<Platform> {
) -> Option<T>
where
Subsystem: FdEnabledSubsystem,
T: core::any::Any + Send + Sync,
T: core::any::Any + Clone + Send + Sync,
{
self.entries[fd.x.as_usize()?]
.as_mut()
Expand Down
66 changes: 52 additions & 14 deletions litebox/src/utilities/anymap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<dyn Any + Send + Sync>` rather than a direct `anymap::AnyMap` (which would just be
//! equivalent to `anymap::Map<dyn Any>`).
//! `anymap::Map<dyn CloneAny + Send + Sync>` rather than a direct `anymap::AnyMap` (which would
//! just be equivalent to `anymap::Map<dyn Any>`).

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<T: core::any::Any + Clone + Send + Sync>() -> Self {
Self(core::any::TypeId::of::<T>())
}
}
}
use private::Tid;

trait AnyCloneSendSync: Any + Send + Sync {
fn clone_to_any(&self) -> Box<dyn AnyCloneSendSync>;
}
impl<T: Any + Clone + Send + Sync> AnyCloneSendSync for T {
fn clone_to_any(&self) -> Box<dyn AnyCloneSendSync> {
Box::new(self.clone())
}
}
impl Clone for Box<dyn AnyCloneSendSync> {
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<TypeId, Box<dyn Any + Send + Sync>>,
storage: HashMap<Tid, Box<dyn AnyCloneSendSync>>,
}

const GUARANTEED: &str = "guaranteed correct type by invariant";
Expand All @@ -35,30 +63,40 @@ impl AnyMap {
}

/// Insert `v`, replacing and returning the old value if one existed already.
pub(crate) fn insert<T: Any + Send + Sync>(&mut self, v: T) -> Option<T> {
let old = self.storage.insert(TypeId::of::<T>(), Box::new(v))?;
pub(crate) fn insert<T: Any + Clone + Send + Sync>(&mut self, v: T) -> Option<T> {
let old: Box<dyn AnyCloneSendSync> = self.storage.insert(Tid::of::<T>(), Box::new(v))?;
let old: Box<dyn Any> = old;
Some(*old.downcast().expect(GUARANTEED))
}

/// Get a reference to a value of type `T` if it exists.
pub(crate) fn get<T: Any + Send + Sync>(&self) -> Option<&T> {
let v = self.storage.get(&TypeId::of::<T>())?;
Some(v.downcast_ref().expect(GUARANTEED))
pub(crate) fn get<T: Any + Clone + Send + Sync>(&self) -> Option<&T> {
let v = self.storage.get(&Tid::of::<T>())?;
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<T: Any + Send + Sync>(&mut self) -> Option<&mut T> {
let v = self.storage.get_mut(&TypeId::of::<T>())?;
Some(v.downcast_mut().expect(GUARANTEED))
pub(crate) fn get_mut<T: Any + Clone + Send + Sync>(&mut self) -> Option<&mut T> {
let v = self.storage.get_mut(&Tid::of::<T>())?;
Some((&mut **v as &mut dyn Any).downcast_mut().expect(GUARANTEED))
}

#[expect(
dead_code,
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<T: Any + Send + Sync>(&mut self) -> Option<T> {
let v = self.storage.remove(&TypeId::of::<T>())?;
pub(crate) fn remove<T: Any + Clone + Send + Sync>(&mut self) -> Option<T> {
let v: Box<dyn AnyCloneSendSync> = self.storage.remove(&Tid::of::<T>())?;
let v: Box<dyn Any> = v;
Some(*v.downcast().expect(GUARANTEED))
}
}

impl Clone for AnyMap {
fn clone(&self) -> Self {
Self {
storage: self.storage.clone(),
}
}
}
2 changes: 2 additions & 0 deletions litebox_shim_linux/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<FS: ShimFS> syscalls::file::FilesState<FS> {
Expand Down
4 changes: 3 additions & 1 deletion litebox_shim_linux/src/syscalls/net.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -171,7 +171,9 @@ pub(super) struct SocketOptions {
pub(super) linger_timeout: Option<core::time::Duration>,
}

#[derive(Clone)]
pub(crate) struct SocketOFlags(pub OFlags);
#[derive(Clone)]
pub(crate) struct SocketProxy(pub Arc<NetworkProxy<Platform>>);

pub(super) enum SocketOptionValue {
Expand Down
Loading