@@ -1009,11 +1009,12 @@ trait ErasedPtr: std::any::Any {
10091009 fn memcpy ( & self , src : & dyn ErasedPtr , len : usize ) ;
10101010 fn as_any ( & self ) -> & dyn std:: any:: Any ;
10111011 fn equals ( & self , other : & dyn ErasedPtr ) -> Option < bool > ;
1012+ fn is_null ( & self ) -> bool ;
10121013}
10131014
10141015impl < T > ErasedPtr for Ptr < T >
10151016where
1016- T : Clone + ByteRepr + ' static ,
1017+ T : ByteRepr + ' static ,
10171018 Ptr < T > : PartialEq ,
10181019{
10191020 fn pointee_type_id ( & self ) -> std:: any:: TypeId {
@@ -1024,35 +1025,13 @@ where
10241025 if self . pointee_type_id ( ) != src. pointee_type_id ( ) {
10251026 panic ! ( "memcpy: type mismatch" ) ;
10261027 }
1027-
10281028 let src_ptr = src
10291029 . as_any ( )
10301030 . downcast_ref :: < Ptr < T > > ( )
10311031 . expect ( "memcpy: downcast to Ptr<T> failed" ) ;
1032-
1033- let elem = std:: mem:: size_of :: < T > ( ) ;
1034-
1035- if len == elem {
1036- self . write ( src_ptr. read ( ) ) ;
1037- return ;
1038- }
1039-
1040- if elem != 0 && len. is_multiple_of ( elem) {
1041- let mut dst = self . clone ( ) ;
1042- let mut src_it = src_ptr. clone ( ) ;
1043- for _ in 0 ..( len / elem) {
1044- dst. write ( src_it. read ( ) ) ;
1045- dst += 1 ;
1046- src_it += 1 ;
1047- }
1048-
1049- return ;
1050- }
1051-
1052- panic ! (
1053- "memcpy: len {} not compatible with element size {}" ,
1054- len, elem
1055- ) ;
1032+ let dst_bytes: Ptr < u8 > = self . reinterpret_cast ( ) ;
1033+ let src_bytes: Ptr < u8 > = src_ptr. reinterpret_cast ( ) ;
1034+ dst_bytes. memcpy ( & src_bytes, len) ;
10561035 }
10571036
10581037 fn as_any ( & self ) -> & dyn std:: any:: Any {
@@ -1070,14 +1049,18 @@ where
10701049
10711050 None
10721051 }
1052+
1053+ fn is_null ( & self ) -> bool {
1054+ Ptr :: is_null ( self )
1055+ }
10731056}
10741057
10751058#[ derive( Clone ) ]
10761059pub struct AnyPtr {
10771060 ptr : Rc < dyn ErasedPtr > ,
10781061}
10791062
1080- impl < T : Clone + ByteRepr + ' static > Ptr < T > {
1063+ impl < T : ByteRepr + ' static > Ptr < T > {
10811064 pub fn to_any ( & self ) -> AnyPtr {
10821065 AnyPtr {
10831066 ptr : Rc :: new ( self . clone ( ) ) ,
@@ -1093,6 +1076,9 @@ impl Default for AnyPtr {
10931076
10941077impl AnyPtr {
10951078 pub fn cast < T : ' static > ( & self ) -> Option < Ptr < T > > {
1079+ if self . ptr . is_null ( ) {
1080+ return Some ( Ptr :: < T > :: null ( ) ) ;
1081+ }
10961082 self . ptr . as_any ( ) . downcast_ref :: < Ptr < T > > ( ) . cloned ( )
10971083 }
10981084
@@ -1286,4 +1272,32 @@ mod tests {
12861272
12871273 p. delete ( ) ;
12881274 }
1275+
1276+ #[ test]
1277+ fn anyptr_null_cast ( ) {
1278+ // void* nullptr
1279+ let any = Ptr :: < ( ) > :: null ( ) . to_any ( ) ;
1280+ let p: Option < Ptr < u32 > > = any. cast :: < u32 > ( ) ;
1281+ assert ! ( p. is_some( ) ) ;
1282+ assert ! ( p. unwrap( ) . is_null( ) ) ;
1283+
1284+ let p2: Option < Ptr < u8 > > = any. cast :: < u8 > ( ) ;
1285+ assert ! ( p2. is_some( ) ) ;
1286+ assert ! ( p2. unwrap( ) . is_null( ) ) ;
1287+
1288+ // int* nullptr
1289+ let any2 = Ptr :: < i32 > :: null ( ) . to_any ( ) ;
1290+ let p3: Option < Ptr < f32 > > = any2. cast :: < f32 > ( ) ;
1291+ assert ! ( p3. is_some( ) ) ;
1292+ assert ! ( p3. unwrap( ) . is_null( ) ) ;
1293+ }
1294+
1295+ #[ test]
1296+ fn to_any_without_clone ( ) {
1297+ let p: Ptr < std:: fs:: File > = Ptr :: null ( ) ; // std::fs::File is not Clone
1298+ let any = p. to_any ( ) ;
1299+ let recovered = any. cast :: < std:: fs:: File > ( ) ;
1300+ assert ! ( recovered. is_some( ) ) ;
1301+ assert ! ( recovered. unwrap( ) . is_null( ) ) ;
1302+ }
12891303}
0 commit comments