Skip to content

Instantly share code, notes, and snippets.

@Venryx
Forked from Kimundi/dynamic_typing.rs
Created July 12, 2022 21:40
Show Gist options
  • Save Venryx/c5b319cfcb3e8145b1e4a91bffba6bd8 to your computer and use it in GitHub Desktop.
Save Venryx/c5b319cfcb3e8145b1e4a91bffba6bd8 to your computer and use it in GitHub Desktop.

Revisions

  1. @Kimundi Kimundi revised this gist Oct 3, 2013. 1 changed file with 3 additions and 3 deletions.
    6 changes: 3 additions & 3 deletions dynamic_typing.rs
    Original file line number Diff line number Diff line change
    @@ -50,13 +50,13 @@ trait AnyRefExt {

    impl<'self> AnyRefExt for &'self Any {
    fn is<T>(&self) -> bool {
    // Get typedesc of the type this function is instantiated with
    // Get TypeId of the type this function is instantiated with
    let t = TypeId::of::<T>();

    // Get typedesc of the type in the trait object
    // Get TypeId of the type in the trait object
    let boxed = self.get_type_id();

    // Compare both typedescriptors on pointer equality
    // Compare both TypeIds on equality
    t == boxed
    }

  2. @Kimundi Kimundi revised this gist Oct 3, 2013. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion dynamic_typing.rs
    Original file line number Diff line number Diff line change
    @@ -50,7 +50,7 @@ trait AnyRefExt {

    impl<'self> AnyRefExt for &'self Any {
    fn is<T>(&self) -> bool {
    // Get typedesc of the type this function is instanciated with
    // Get typedesc of the type this function is instantiated with
    let t = TypeId::of::<T>();

    // Get typedesc of the type in the trait object
  3. @Kimundi Kimundi revised this gist Oct 3, 2013. 1 changed file with 2 additions and 2 deletions.
    4 changes: 2 additions & 2 deletions dynamic_typing.rs
    Original file line number Diff line number Diff line change
    @@ -106,10 +106,10 @@ impl AnyOwnExt for ~Any {
    fn identify(a: &Any) {
    if a.is::<uint>() {
    let v: uint = *a.opt_ref().unwrap();
    println!("{:?}: uint", v);
    println!("{}: uint", v);
    } else if a.is::<int>() {
    let v: int = *a.opt_ref().unwrap();
    println!("{:?}: int", v);
    println!("{}: int", v);
    } else {
    println("unhandled type!")
    }
  4. @Kimundi Kimundi revised this gist Oct 3, 2013. 1 changed file with 8 additions and 17 deletions.
    25 changes: 8 additions & 17 deletions dynamic_typing.rs
    Original file line number Diff line number Diff line change
    @@ -1,31 +1,25 @@
    use std::unstable::intrinsics::{TyDesc, forget};
    use std::unstable::intrinsics;
    use std::unstable::intrinsics::{TyDesc, get_tydesc, forget};
    use std::util::Void;
    use std::cast::transmute;
    use std::borrow::ref_eq;

    ///////////////////////////////////////////////////////////////////////////////
    // TypeId
    ///////////////////////////////////////////////////////////////////////////////

    fn get_tydesc<T>() -> &'static TyDesc {
    unsafe { transmute(intrinsics::get_tydesc::<T>()) }
    }

    /// `TypeId` represents a globally unique identifier for a type
    pub struct TypeId {
    priv t: &'static TyDesc
    priv t: *TyDesc
    }

    impl TypeId {
    pub fn of<T>() -> TypeId {
    TypeId{ t: get_tydesc::<T>() }
    TypeId{ t: unsafe { get_tydesc::<T>() } }
    }
    }

    impl Eq for TypeId {
    fn eq(&self, &other: &TypeId) -> bool {
    ref_eq(self.t, other.t)
    self.t == other.t
    }
    }

    @@ -35,17 +29,14 @@ impl Eq for TypeId {

    /// The `Any` trait is implemented by all types, and can be used for dynamic typing
    pub trait Any {
    fn get_type_id(&self) -> TypeId;
    fn get_type_id(&self) -> TypeId {
    TypeId::of::<Self>()
    }
    fn as_void_ptr(&self) -> *Void {
    self as *Self as *Void
    }
    }

    impl<T> Any for T {
    fn get_type_id(&self) -> TypeId {
    TypeId::of::<T>()
    }
    }
    impl<T> Any for T {}

    /// Extension methods for a borrowed `Any` trait object
    trait AnyRefExt {
  5. @Kimundi Kimundi revised this gist Oct 3, 2013. 1 changed file with 37 additions and 7 deletions.
    44 changes: 37 additions & 7 deletions dynamic_typing.rs
    Original file line number Diff line number Diff line change
    @@ -4,20 +4,48 @@ use std::util::Void;
    use std::cast::transmute;
    use std::borrow::ref_eq;

    ///////////////////////////////////////////////////////////////////////////////
    // TypeId
    ///////////////////////////////////////////////////////////////////////////////

    fn get_tydesc<T>() -> &'static TyDesc {
    unsafe { transmute(intrinsics::get_tydesc::<T>()) }
    }

    /// `TypeId` represents a globally unique identifier for a type
    pub struct TypeId {
    priv t: &'static TyDesc
    }

    impl TypeId {
    pub fn of<T>() -> TypeId {
    TypeId{ t: get_tydesc::<T>() }
    }
    }

    impl Eq for TypeId {
    fn eq(&self, &other: &TypeId) -> bool {
    ref_eq(self.t, other.t)
    }
    }

    ///////////////////////////////////////////////////////////////////////////////
    // Any trait
    ///////////////////////////////////////////////////////////////////////////////

    /// The `Any` trait is implemented by all types, and can be used for dynamic typing
    pub trait Any {
    fn get_tydesc(&self) -> &'static TyDesc {
    get_tydesc::<Self>()
    }
    fn get_type_id(&self) -> TypeId;
    fn as_void_ptr(&self) -> *Void {
    self as *Self as *Void
    }
    }
    impl<T> Any for T {}

    impl<T> Any for T {
    fn get_type_id(&self) -> TypeId {
    TypeId::of::<T>()
    }
    }

    /// Extension methods for a borrowed `Any` trait object
    trait AnyRefExt {
    @@ -32,13 +60,13 @@ trait AnyRefExt {
    impl<'self> AnyRefExt for &'self Any {
    fn is<T>(&self) -> bool {
    // Get typedesc of the type this function is instanciated with
    let t = get_tydesc::<T>();
    let t = TypeId::of::<T>();

    // Get typedesc of the type in the trait object
    let boxed = self.get_tydesc();
    let boxed = self.get_type_id();

    // Compare both typedescriptors on pointer equality
    ref_eq(t, boxed)
    t == boxed
    }

    fn opt_ref<'a, T>(&'a self) -> Option<&'a T> {
    @@ -80,6 +108,8 @@ impl AnyOwnExt for ~Any {
    }
    }

    ///////////////////////////////////////////////////////////////////////////////
    // Testing
    ///////////////////////////////////////////////////////////////////////////////

    fn identify(a: &Any) {
  6. @Kimundi Kimundi revised this gist Oct 3, 2013. 1 changed file with 8 additions and 6 deletions.
    14 changes: 8 additions & 6 deletions dynamic_typing.rs
    Original file line number Diff line number Diff line change
    @@ -65,13 +65,15 @@ trait AnyOwnExt {
    impl AnyOwnExt for ~Any {
    fn move<'a, T>(self) -> Option<~T> {
    if { let tmp: &Any = self; tmp.is::<T>() } {
    // Extract the pointer to the boxed value
    let boxed_ptr: ~T = unsafe {
    transmute(self.as_void_ptr())
    };
    unsafe { forget(self); }
    unsafe {
    // Extract the pointer to the boxed value, temporary alias with self
    let boxed_ptr: ~T = transmute(self.as_void_ptr());

    Some(boxed_ptr)
    // Prevent destructor on self being run
    forget(self);

    Some(boxed_ptr)
    }
    } else {
    None
    }
  7. @Kimundi Kimundi revised this gist Oct 3, 2013. 1 changed file with 12 additions and 7 deletions.
    19 changes: 12 additions & 7 deletions dynamic_typing.rs
    Original file line number Diff line number Diff line change
    @@ -1,4 +1,4 @@
    use std::unstable::intrinsics::TyDesc;
    use std::unstable::intrinsics::{TyDesc, forget};
    use std::unstable::intrinsics;
    use std::util::Void;
    use std::cast::transmute;
    @@ -44,9 +44,11 @@ impl<'self> AnyRefExt for &'self Any {
    fn opt_ref<'a, T>(&'a self) -> Option<&'a T> {
    if self.is::<T>() {
    // Extract the pointer to the boxed value
    let ptr_to_boxed_value: &'a T = unsafe { transmute(self.as_void_ptr()) };
    let boxed_ptr: &'a T = unsafe {
    transmute(self.as_void_ptr())
    };

    Some(ptr_to_boxed_value)
    Some(boxed_ptr)
    } else {
    None
    }
    @@ -64,9 +66,12 @@ impl AnyOwnExt for ~Any {
    fn move<'a, T>(self) -> Option<~T> {
    if { let tmp: &Any = self; tmp.is::<T>() } {
    // Extract the pointer to the boxed value
    let ptr_to_boxed_value: ~T = unsafe { transmute(self.as_void_ptr()) };
    let boxed_ptr: ~T = unsafe {
    transmute(self.as_void_ptr())
    };
    unsafe { forget(self); }

    Some(ptr_to_boxed_value)
    Some(boxed_ptr)
    } else {
    None
    }
    @@ -96,6 +101,6 @@ fn main() {
    identify(b);
    identify(c);

    let v: uint = *a.move().unwrap();
    assert_eq!(v, 1);
    let v: ~uint = a.move().unwrap();
    assert_eq!(v, ~1);
    }
  8. @Kimundi Kimundi revised this gist Oct 3, 2013. 1 changed file with 4 additions and 6 deletions.
    10 changes: 4 additions & 6 deletions dynamic_typing.rs
    Original file line number Diff line number Diff line change
    @@ -11,8 +11,6 @@ fn get_tydesc<T>() -> &'static TyDesc {
    /// The `Any` trait is implemented by all types, and can be used for dynamic typing
    pub trait Any {
    fn get_tydesc(&self) -> &'static TyDesc {
    // default method on trait objects
    // makes this work dynamically
    get_tydesc::<Self>()
    }
    fn as_void_ptr(&self) -> *Void {
    @@ -90,14 +88,14 @@ fn identify(a: &Any) {
    }

    fn main() {
    let a = ~5u as ~Any;
    let b = @5i as @Any;
    let c = &5u8 as &Any;
    let a = ~1u as ~Any;
    let b = @2i as @Any;
    let c = &3u8 as &Any;

    identify(a);
    identify(b);
    identify(c);

    let v: uint = *a.move().unwrap();
    assert_eq!(v, 5);
    assert_eq!(v, 1);
    }
  9. @Kimundi Kimundi revised this gist Oct 3, 2013. 1 changed file with 7 additions and 7 deletions.
    14 changes: 7 additions & 7 deletions dynamic_typing.rs
    Original file line number Diff line number Diff line change
    @@ -2,6 +2,7 @@ use std::unstable::intrinsics::TyDesc;
    use std::unstable::intrinsics;
    use std::util::Void;
    use std::cast::transmute;
    use std::borrow::ref_eq;

    fn get_tydesc<T>() -> &'static TyDesc {
    unsafe { transmute(intrinsics::get_tydesc::<T>()) }
    @@ -32,15 +33,14 @@ trait AnyRefExt {

    impl<'self> AnyRefExt for &'self Any {
    fn is<T>(&self) -> bool {
    // Get type name of the type this function is instanciated with
    let t_name = get_tydesc::<T>().name;
    // Get typedesc of the type this function is instanciated with
    let t = get_tydesc::<T>();

    // Get type name of the type in the trait object
    let boxed_name = self.get_tydesc().name;
    // Get typedesc of the type in the trait object
    let boxed = self.get_tydesc();

    // Compare both names on string equality.
    // This will fail if you have two different types with identical name and crate
    t_name == boxed_name
    // Compare both typedescriptors on pointer equality
    ref_eq(t, boxed)
    }

    fn opt_ref<'a, T>(&'a self) -> Option<&'a T> {
  10. @Kimundi Kimundi revised this gist Oct 3, 2013. 1 changed file with 8 additions and 10 deletions.
    18 changes: 8 additions & 10 deletions dynamic_typing.rs
    Original file line number Diff line number Diff line change
    @@ -78,16 +78,14 @@ impl AnyOwnExt for ~Any {
    ///////////////////////////////////////////////////////////////////////////////

    fn identify(a: &Any) {
    match a {
    a if a.is::<uint>() => {
    let v: uint = *a.opt_ref().unwrap();
    println!("{:?}: uint", v);
    }
    a if a.is::<int>() => {
    let v: int = *a.opt_ref().unwrap();
    println!("{:?}: int", v);
    }
    _ => println("unhandled type!")
    if a.is::<uint>() {
    let v: uint = *a.opt_ref().unwrap();
    println!("{:?}: uint", v);
    } else if a.is::<int>() {
    let v: int = *a.opt_ref().unwrap();
    println!("{:?}: int", v);
    } else {
    println("unhandled type!")
    }
    }

  11. @Kimundi Kimundi revised this gist Oct 3, 2013. 1 changed file with 5 additions and 7 deletions.
    12 changes: 5 additions & 7 deletions dynamic_typing.rs
    Original file line number Diff line number Diff line change
    @@ -1,8 +1,10 @@
    use std::unstable::intrinsics::TyDesc;
    use std::unstable::intrinsics;
    use std::util::Void;
    use std::cast::transmute;

    fn get_tydesc<T>() -> &'static TyDesc {
    unsafe { std::cast::transmute(std::unstable::intrinsics::get_tydesc::<T>()) }
    unsafe { transmute(intrinsics::get_tydesc::<T>()) }
    }

    /// The `Any` trait is implemented by all types, and can be used for dynamic typing
    @@ -44,9 +46,7 @@ impl<'self> AnyRefExt for &'self Any {
    fn opt_ref<'a, T>(&'a self) -> Option<&'a T> {
    if self.is::<T>() {
    // Extract the pointer to the boxed value
    let ptr_to_boxed_value: &'a T = unsafe {
    std::cast::transmute(self.as_void_ptr())
    };
    let ptr_to_boxed_value: &'a T = unsafe { transmute(self.as_void_ptr()) };

    Some(ptr_to_boxed_value)
    } else {
    @@ -66,9 +66,7 @@ impl AnyOwnExt for ~Any {
    fn move<'a, T>(self) -> Option<~T> {
    if { let tmp: &Any = self; tmp.is::<T>() } {
    // Extract the pointer to the boxed value
    let ptr_to_boxed_value: ~T = unsafe {
    std::cast::transmute(self.as_void_ptr())
    };
    let ptr_to_boxed_value: ~T = unsafe { transmute(self.as_void_ptr()) };

    Some(ptr_to_boxed_value)
    } else {
  12. @Kimundi Kimundi revised this gist Oct 3, 2013. 1 changed file with 7 additions and 5 deletions.
    12 changes: 7 additions & 5 deletions dynamic_typing.rs
    Original file line number Diff line number Diff line change
    @@ -1,4 +1,5 @@
    use std::unstable::intrinsics::TyDesc;
    use std::util::Void;

    fn get_tydesc<T>() -> &'static TyDesc {
    unsafe { std::cast::transmute(std::unstable::intrinsics::get_tydesc::<T>()) }
    @@ -11,6 +12,9 @@ pub trait Any {
    // makes this work dynamically
    get_tydesc::<Self>()
    }
    fn as_void_ptr(&self) -> *Void {
    self as *Self as *Void
    }
    }
    impl<T> Any for T {}

    @@ -41,8 +45,7 @@ impl<'self> AnyRefExt for &'self Any {
    if self.is::<T>() {
    // Extract the pointer to the boxed value
    let ptr_to_boxed_value: &'a T = unsafe {
    let (_, v): (**TyDesc, *T) = std::cast::transmute(*self);
    std::cast::transmute(v)
    std::cast::transmute(self.as_void_ptr())
    };

    Some(ptr_to_boxed_value)
    @@ -61,11 +64,10 @@ trait AnyOwnExt {

    impl AnyOwnExt for ~Any {
    fn move<'a, T>(self) -> Option<~T> {
    if { let self2: &Any = self; self2.is::<T>() } {
    if { let tmp: &Any = self; tmp.is::<T>() } {
    // Extract the pointer to the boxed value
    let ptr_to_boxed_value: ~T = unsafe {
    let (_, v): (**TyDesc, *T) = std::cast::transmute(self);
    std::cast::transmute(v)
    std::cast::transmute(self.as_void_ptr())
    };

    Some(ptr_to_boxed_value)
  13. @Kimundi Kimundi revised this gist Oct 3, 2013. 1 changed file with 50 additions and 20 deletions.
    70 changes: 50 additions & 20 deletions dynamic_typing.rs
    Original file line number Diff line number Diff line change
    @@ -1,41 +1,43 @@
    use std::unstable::intrinsics::get_tydesc;
    use std::unstable::intrinsics::TyDesc;

    fn get_tydesc<T>() -> &'static TyDesc {
    unsafe { std::cast::transmute(std::unstable::intrinsics::get_tydesc::<T>()) }
    }

    /// The `Any` trait is implemented by all types, and can be used for dynamic typing
    trait Any {}
    pub trait Any {
    fn get_tydesc(&self) -> &'static TyDesc {
    // default method on trait objects
    // makes this work dynamically
    get_tydesc::<Self>()
    }
    }
    impl<T> Any for T {}

    /// Extension methods for `Any` trait objects for querying and getting at
    /// the underlying type
    trait AnyExt {
    /// Extension methods for a borrowed `Any` trait object
    trait AnyRefExt {
    /// Returns true if the boxed type is the same as `T`
    fn is<T>(&self) -> bool;

    /// Returns an reference to the boxed value if it is of type `T`, or
    /// `None` if it isn't.
    fn ref_as<'a, T>(&'a self) -> Option<&'a T> ;
    fn opt_ref<'a, T>(&'a self) -> Option<&'a T> ;
    }

    impl<'self> AnyExt for &'self Any {
    impl<'self> AnyRefExt for &'self Any {
    fn is<T>(&self) -> bool {
    // Get type name of the type this function is instanciated with
    let t_name = unsafe { (*get_tydesc::<T>()).name };
    let t_name = get_tydesc::<T>().name;

    // Get type name of the type in the trait object
    let boxed_sigil_name = unsafe {
    let (t, _): (**TyDesc, *()) = std::cast::transmute(*self);
    (**t).name
    };

    // Cut of the leading '~', '@' or '&':
    let boxed_name = boxed_sigil_name.slice_from(1);
    let boxed_name = self.get_tydesc().name;

    // Compare both names on string equality.
    // This will fail if you have two different types with identical name and crate
    t_name == boxed_name
    }

    fn ref_as<'a, T>(&'a self) -> Option<&'a T> {
    fn opt_ref<'a, T>(&'a self) -> Option<&'a T> {
    if self.is::<T>() {
    // Extract the pointer to the boxed value
    let ptr_to_boxed_value: &'a T = unsafe {
    @@ -50,15 +52,40 @@ impl<'self> AnyExt for &'self Any {
    }
    }

    /// Extension methods for a owning `Any` trait object
    trait AnyOwnExt {
    /// Returns the boxed value if it is of type `T`, or
    /// `None` if it isn't.
    fn move<'a, T>(self) -> Option<~T>;
    }

    impl AnyOwnExt for ~Any {
    fn move<'a, T>(self) -> Option<~T> {
    if { let self2: &Any = self; self2.is::<T>() } {
    // Extract the pointer to the boxed value
    let ptr_to_boxed_value: ~T = unsafe {
    let (_, v): (**TyDesc, *T) = std::cast::transmute(self);
    std::cast::transmute(v)
    };

    Some(ptr_to_boxed_value)
    } else {
    None
    }
    }
    }

    ///////////////////////////////////////////////////////////////////////////////

    fn identify(a: &Any) {
    match a {
    a if a.is::<uint>() => {
    let v = a.ref_as::<uint>().unwrap();
    println!("{:?}: uint", *v);
    let v: uint = *a.opt_ref().unwrap();
    println!("{:?}: uint", v);
    }
    a if a.is::<int>() => {
    let v = a.ref_as::<int>().unwrap();
    println!("{:?}: int", *v);
    let v: int = *a.opt_ref().unwrap();
    println!("{:?}: int", v);
    }
    _ => println("unhandled type!")
    }
    @@ -72,4 +99,7 @@ fn main() {
    identify(a);
    identify(b);
    identify(c);

    let v: uint = *a.move().unwrap();
    assert_eq!(v, 5);
    }
  14. @Kimundi Kimundi renamed this gist Oct 2, 2013. 1 changed file with 0 additions and 0 deletions.
    File renamed without changes.
  15. @Kimundi Kimundi revised this gist Oct 2, 2013. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion dynamic_typng.rs
    Original file line number Diff line number Diff line change
    @@ -8,7 +8,7 @@ impl<T> Any for T {}
    /// Extension methods for `Any` trait objects for querying and getting at
    /// the underlying type
    trait AnyExt {
    /// Returns true if the boxed type isthe same as `T`
    /// Returns true if the boxed type is the same as `T`
    fn is<T>(&self) -> bool;

    /// Returns an reference to the boxed value if it is of type `T`, or
  16. @Kimundi Kimundi created this gist Oct 2, 2013.
    75 changes: 75 additions & 0 deletions dynamic_typng.rs
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,75 @@
    use std::unstable::intrinsics::get_tydesc;
    use std::unstable::intrinsics::TyDesc;

    /// The `Any` trait is implemented by all types, and can be used for dynamic typing
    trait Any {}
    impl<T> Any for T {}

    /// Extension methods for `Any` trait objects for querying and getting at
    /// the underlying type
    trait AnyExt {
    /// Returns true if the boxed type isthe same as `T`
    fn is<T>(&self) -> bool;

    /// Returns an reference to the boxed value if it is of type `T`, or
    /// `None` if it isn't.
    fn ref_as<'a, T>(&'a self) -> Option<&'a T> ;
    }

    impl<'self> AnyExt for &'self Any {
    fn is<T>(&self) -> bool {
    // Get type name of the type this function is instanciated with
    let t_name = unsafe { (*get_tydesc::<T>()).name };

    // Get type name of the type in the trait object
    let boxed_sigil_name = unsafe {
    let (t, _): (**TyDesc, *()) = std::cast::transmute(*self);
    (**t).name
    };

    // Cut of the leading '~', '@' or '&':
    let boxed_name = boxed_sigil_name.slice_from(1);

    // Compare both names on string equality.
    // This will fail if you have two different types with identical name and crate
    t_name == boxed_name
    }

    fn ref_as<'a, T>(&'a self) -> Option<&'a T> {
    if self.is::<T>() {
    // Extract the pointer to the boxed value
    let ptr_to_boxed_value: &'a T = unsafe {
    let (_, v): (**TyDesc, *T) = std::cast::transmute(*self);
    std::cast::transmute(v)
    };

    Some(ptr_to_boxed_value)
    } else {
    None
    }
    }
    }

    fn identify(a: &Any) {
    match a {
    a if a.is::<uint>() => {
    let v = a.ref_as::<uint>().unwrap();
    println!("{:?}: uint", *v);
    }
    a if a.is::<int>() => {
    let v = a.ref_as::<int>().unwrap();
    println!("{:?}: int", *v);
    }
    _ => println("unhandled type!")
    }
    }

    fn main() {
    let a = ~5u as ~Any;
    let b = @5i as @Any;
    let c = &5u8 as &Any;

    identify(a);
    identify(b);
    identify(c);
    }