@@ -39,6 +39,7 @@ use std::os::raw::c_uint;
3939use std:: { borrow, fmt, hash, ops} ;
4040use thiserror:: Error ;
4141
42+ extern crate alloc;
4243#[ cfg( feature = "serde" ) ]
4344extern crate serde;
4445
@@ -68,11 +69,21 @@ impl From<c_uint> for HostType {
6869}
6970
7071/// A parsed URL struct according to WHATWG URL specification.
71- #[ derive( Eq , Clone ) ]
72+ #[ derive( Eq ) ]
7273pub struct Url {
7374 url : * mut ffi:: ada_url ,
7475}
7576
77+ /// Clone trait by default uses bit-wise copy.
78+ /// In Rust, FFI requires deep copy, which requires an additional/inexpensive FFI call.
79+ impl Clone for Url {
80+ fn clone ( & self ) -> Self {
81+ Url {
82+ url : unsafe { ffi:: ada_copy ( self . url ) } ,
83+ }
84+ }
85+ }
86+
7687impl Drop for Url {
7788 fn drop ( & mut self ) {
7889 unsafe { ffi:: ada_free ( self . url ) }
@@ -749,4 +760,14 @@ mod test {
749760 let deserialized: Url = serde_json:: from_str ( & output) . unwrap ( ) ;
750761 assert_eq ! ( deserialized. href( ) , input. to_string( ) + "/" ) ;
751762 }
763+
764+ #[ test]
765+ fn should_clone ( ) {
766+ let first = Url :: parse ( "https://lemire.me" , None ) . unwrap ( ) ;
767+ let mut second = first. clone ( ) ;
768+ second. set_href ( "https://yagiz.co" ) ;
769+ assert_ne ! ( first. href( ) , second. href( ) ) ;
770+ assert_eq ! ( first. href( ) , "https://lemire.me/" ) ;
771+ assert_eq ! ( second. href( ) , "https://yagiz.co/" ) ;
772+ }
752773}
0 commit comments