unsafe-any-0.4.2/.gitignore01006440000765000002400000000207131116516710013773 0ustar0000000000000000.DS_Store *~ *# *.o *.so *.swp *.dylib *.dSYM *.dll *.rlib *.dummy *.exe *-test /doc/ /target/ /examples/* !/examples/*.rs Cargo.lock unsafe-any-0.4.2/.travis.yml01006440000765000002400000000133131116521360014107 0ustar0000000000000000language: rust script: - cargo build -v - cargo test -v - cargo doc -v os: - linux unsafe-any-0.4.2/Cargo.toml01006440000765000002400000001407131116526040013733 0ustar0000000000000000# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies. # # If you are reading this file be aware that the original Cargo.toml # will likely look very different (and much more reasonable). # See Cargo.toml.orig for the original contents. [package] name = "unsafe-any" version = "0.4.2" authors = ["Jonathan Reem "] description = "Traits and implementations for unchecked downcasting." readme = "README.md" license = "MIT" repository = "https://github.com/reem/rust-unsafe-any" [dependencies.traitobject] version = "0.1" unsafe-any-0.4.2/Cargo.toml.orig01006440000765000002400000000431131116526040014666 0ustar0000000000000000[package] name = "unsafe-any" version = "0.4.2" authors = ["Jonathan Reem "] description = "Traits and implementations for unchecked downcasting." repository = "https://github.com/reem/rust-unsafe-any" license = "MIT" [dependencies] traitobject = "0.1" unsafe-any-0.4.2/README.md01006440000765000002400000001331131116516710013261 0ustar0000000000000000# Unsafe-Any [![Build Status](https://travis-ci.org/reem/rust-unsafe-any.svg?branch=master)](https://travis-ci.org/reem/rust-unsafe-any) > Convenience traits for unsafe downcasting from trait objects to concrete types. ## Overview This crate defines two new traits `UncheckedAnyDowncast` and `UncheckedAnyMutDowncast`, which define methods for downcasting to any type that implements `Any` from implemented trait objects. It also defines two convenience implementations of these traits for `&'a Any` and `&'a mut Any`, which are the most common trait objects that you might downcast from. ## Example: ```rust let a = box 7u as Box; unsafe { assert_eq!(*a.downcast_ref_unchecked::(), 7u); } ``` ## License MIT unsafe-any-0.4.2/src/lib.rs01006440000765000002400000012043131116520370013704 0ustar0000000000000000#![deny(missing_docs, warnings)] //! Traits for unsafe downcasting from trait objects to & or &mut references of //! concrete types. These should only be used if you are absolutely certain of the //! type of the data in said trait object - there be dragons etc. //! //! Originally inspired by https://github.com/chris-morgan/anymap //! and the implementation of `std::any::Any`. extern crate traitobject; use std::any::Any; use std::mem; /// A trait providing unchecked downcasting to its contents when stored /// in a trait object. pub trait UnsafeAny: Any {} impl UnsafeAny for T {} impl UnsafeAny { /// Returns a reference to the contained value, assuming that it is of type `T`. /// /// ## Warning /// /// If you are not _absolutely certain_ of `T` you should _not_ call this! pub unsafe fn downcast_ref_unchecked(&self) -> &T { mem::transmute(traitobject::data(self)) } /// Returns a mutable reference to the contained value, assuming that it is of type `T`. /// /// ## Warning /// /// If you are not _absolutely certain_ of `T` you should _not_ call this! pub unsafe fn downcast_mut_unchecked(&mut self) -> &mut T { mem::transmute(traitobject::data_mut(self)) } /// Returns a the contained value, assuming that it is of type `T`. /// /// ## Warning /// /// If you are not _absolutely certain_ of `T` you should _not_ call this! pub unsafe fn downcast_unchecked(self: Box) -> Box { let raw: *mut UnsafeAny = mem::transmute(self); mem::transmute(traitobject::data_mut(raw)) } } /// An extension trait for unchecked downcasting of trait objects. pub unsafe trait UnsafeAnyExt { /// Returns a reference to the contained value, assuming that it is of type `T`. /// /// ## Warning /// /// If you are not _absolutely certain_ of `T` you should _not_ call this! unsafe fn downcast_ref_unchecked(&self) -> &T { mem::transmute(traitobject::data(self)) } /// Returns a mutable reference to the contained value, assuming that it is of type `T`. /// /// ## Warning /// /// If you are not _absolutely certain_ of `T` you should _not_ call this! unsafe fn downcast_mut_unchecked(&mut self) -> &mut T { mem::transmute(traitobject::data_mut(self)) } /// Returns a the contained value, assuming that it is of type `T`. /// /// ## Warning /// /// If you are not _absolutely certain_ of `T` you should _not_ call this! unsafe fn downcast_unchecked(self: Box) -> Box { let raw: *mut Self = mem::transmute(self); mem::transmute(traitobject::data_mut(raw)) } } unsafe impl UnsafeAnyExt for Any { } unsafe impl UnsafeAnyExt for UnsafeAny { } unsafe impl UnsafeAnyExt for Any + Send { } unsafe impl UnsafeAnyExt for Any + Sync { } unsafe impl UnsafeAnyExt for Any + Send + Sync { } unsafe impl UnsafeAnyExt for UnsafeAny + Send { } unsafe impl UnsafeAnyExt for UnsafeAny + Sync { } unsafe impl UnsafeAnyExt for UnsafeAny + Send + Sync { } #[cfg(test)] mod test { use super::{UnsafeAny, UnsafeAnyExt}; use std::any::Any; #[test] fn test_simple_downcast_ext() { let a = Box::new(7usize) as Box; unsafe { assert_eq!(*a.downcast_ref_unchecked::(), 7); } let mut a = Box::new(7usize) as Box; unsafe { assert_eq!(*a.downcast_mut_unchecked::(), 7); } let mut a = Box::new(7usize) as Box; unsafe { *a.downcast_mut_unchecked::() = 8; assert_eq!(*a.downcast_mut_unchecked::(), 8); } } #[test] fn test_simple_downcast_inherent() { let a = Box::new(7usize) as Box; unsafe { assert_eq!(*a.downcast_ref_unchecked::(), 7); } let mut a = Box::new(7usize) as Box; unsafe { assert_eq!(*a.downcast_mut_unchecked::(), 7); } let mut a = Box::new(7usize) as Box; unsafe { *a.downcast_mut_unchecked::() = 8; assert_eq!(*a.downcast_mut_unchecked::(), 8); } } #[test] fn test_box_downcast_no_double_free() { use std::sync::atomic::{AtomicUsize, Ordering}; use std::sync::Arc; struct Dropper { x: Arc } impl Drop for Dropper { fn drop(&mut self) { self.x.fetch_add(1, Ordering::SeqCst); } } let x = Arc::new(AtomicUsize::new(0)); let a = Box::new(Dropper { x: x.clone() }) as Box; let dropper = unsafe { a.downcast_unchecked::() }; drop(dropper); assert_eq!(x.load(Ordering::SeqCst), 1); // Test the UnsafeAnyExt implementation. let x = Arc::new(AtomicUsize::new(0)); let a = Box::new(Dropper { x: x.clone() }) as Box; let dropper = unsafe { a.downcast_unchecked::() }; drop(dropper); assert_eq!(x.load(Ordering::SeqCst), 1); } }