@@ -39,6 +39,7 @@ use std::os::raw::c_uint;
39
39
use std:: { borrow, fmt, hash, ops} ;
40
40
use thiserror:: Error ;
41
41
42
+ extern crate alloc;
42
43
#[ cfg( feature = "serde" ) ]
43
44
extern crate serde;
44
45
@@ -68,11 +69,21 @@ impl From<c_uint> for HostType {
68
69
}
69
70
70
71
/// A parsed URL struct according to WHATWG URL specification.
71
- #[ derive( Eq , Clone ) ]
72
+ #[ derive( Eq ) ]
72
73
pub struct Url {
73
74
url : * mut ffi:: ada_url ,
74
75
}
75
76
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
+
76
87
impl Drop for Url {
77
88
fn drop ( & mut self ) {
78
89
unsafe { ffi:: ada_free ( self . url ) }
@@ -749,4 +760,14 @@ mod test {
749
760
let deserialized: Url = serde_json:: from_str ( & output) . unwrap ( ) ;
750
761
assert_eq ! ( deserialized. href( ) , input. to_string( ) + "/" ) ;
751
762
}
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
+ }
752
773
}
0 commit comments