Diffstat (limited to 'src/any/mut_any_unsized.rs')
-rw-r--r--src/any/mut_any_unsized.rs46
1 files changed, 46 insertions, 0 deletions
diff --git a/src/any/mut_any_unsized.rs b/src/any/mut_any_unsized.rs
new file mode 100644
index 0000000..e90659e
--- /dev/null
+++ b/src/any/mut_any_unsized.rs
@@ -0,0 +1,46 @@
+use crate::hkt::CovariantLt;
+
+use super::{erased::Erased, type_name, WithLtTypeId};
+
+/// Type erased mutable borrow of a unsized type.
+///
+/// This type acts like a `&'a mut dyn Trait<'ctx> + 'lt` with the `Trait` part erased.
+/// This type exists to get a mutable borrow of an arbitrary trait object out of a object safe method.
+/// However, it is not limited to storing mutable borrows of trait objects. It can be
+/// used to store a mutable borrow to any type including sized ones.
+pub struct MutAnyUnsized<'a, 'lt, 'ctx> {
+ /// As shown in the table at https://doc.rust-lang.org/nomicon/subtyping.html#variance
+ /// mutable borrows are covariant over their lifetime, so we are also.
+ _a: CovariantLt<'a>,
+
+ /// The type erased borrow.
+ ///
+ /// This should be able to store any unsized type in current Rust as all of
+ /// them are 2 usize in width.
+ borrow: Erased<{ core::mem::size_of::<&mut dyn core::any::Any>() }>,
+
+ /// We use a function here to reduce the size down to one usize.
+ /// This makes a RefAnyUnsized only 3 usize wide.
+ type_name_id: fn() -> WithLtTypeId<'lt, 'ctx>,
+}
+
+impl<'a, 'lt: 'a, 'ctx: 'lt> MutAnyUnsized<'a, 'lt, 'ctx> {
+ /// Create from a borrow.
+ pub fn new<T: ?Sized + type_name::WithLt<'lt, 'ctx>>(borrow: &'a mut T) -> Self {
+ Self {
+ _a: CovariantLt::NEW,
+ borrow: Erased::new::<&'a mut T>(borrow),
+ type_name_id: || WithLtTypeId::of::<T>(),
+ }
+ }
+
+ /// Downcast the type erased value back to its original type.
+ pub fn downcast<T: ?Sized + type_name::WithLt<'lt, 'ctx>>(self) -> Result<&'a mut T, Self> {
+ if (self.type_name_id)() == WithLtTypeId::of::<T>() {
+ #[allow(unsafe_code)]
+ Ok(unsafe { self.borrow.into_inner::<&'a mut T>() })
+ } else {
+ Err(self)
+ }
+ }
+}