From fc0946e2960b778cb1095662a582ba6a4c61aceb Mon Sep 17 00:00:00 2001 From: Yagiz Nizipli Date: Sat, 26 Aug 2023 17:03:59 -0400 Subject: [PATCH] fix: properly `clone` url Co-authored-by: Steve Klabnik --- deps/ada.cpp | 7 ++++++- deps/ada.h | 6 +++--- deps/ada_c.h | 1 + src/ffi.rs | 1 + src/lib.rs | 23 ++++++++++++++++++++++- 5 files changed, 33 insertions(+), 5 deletions(-) diff --git a/deps/ada.cpp b/deps/ada.cpp index 0c07648..35f83ea 100644 --- a/deps/ada.cpp +++ b/deps/ada.cpp @@ -1,4 +1,4 @@ -/* auto-generated on 2023-08-25 15:25:45 -0400. Do not edit! */ +/* auto-generated on 2023-08-26 17:38:28 -0400. Do not edit! */ /* begin file src/ada.cpp */ #include "ada.h" /* begin file src/checkers.cpp */ @@ -14893,6 +14893,11 @@ void ada_free(ada_url result) noexcept { delete r; } +ada_url ada_copy(ada_url input) noexcept { + ada::result& r = get_instance(input); + return new ada::result(r); +} + bool ada_is_valid(ada_url result) noexcept { ada::result& r = get_instance(result); return r.has_value(); diff --git a/deps/ada.h b/deps/ada.h index ae660fe..caceff3 100644 --- a/deps/ada.h +++ b/deps/ada.h @@ -1,4 +1,4 @@ -/* auto-generated on 2023-08-25 15:25:45 -0400. Do not edit! */ +/* auto-generated on 2023-08-26 17:38:28 -0400. Do not edit! */ /* begin file include/ada.h */ /** * @file ada.h @@ -6922,14 +6922,14 @@ inline void url_search_params::sort() { #ifndef ADA_ADA_VERSION_H #define ADA_ADA_VERSION_H -#define ADA_VERSION "2.6.2" +#define ADA_VERSION "2.6.3" namespace ada { enum { ADA_VERSION_MAJOR = 2, ADA_VERSION_MINOR = 6, - ADA_VERSION_REVISION = 2, + ADA_VERSION_REVISION = 3, }; } // namespace ada diff --git a/deps/ada_c.h b/deps/ada_c.h index 2d192a5..170686b 100644 --- a/deps/ada_c.h +++ b/deps/ada_c.h @@ -51,6 +51,7 @@ bool ada_can_parse_with_base(const char* input, size_t input_length, void ada_free(ada_url result); void ada_free_owned_string(ada_owned_string owned); +ada_url ada_copy(ada_url input); bool ada_is_valid(ada_url result); diff --git a/src/ffi.rs b/src/ffi.rs index d696949..341a6d4 100644 --- a/src/ffi.rs +++ b/src/ffi.rs @@ -59,6 +59,7 @@ extern "C" { ) -> *mut ada_url; pub fn ada_free(url: *mut ada_url); pub fn ada_free_owned_string(url: *mut ada_owned_string); + pub fn ada_copy(url: *mut ada_url) -> *mut ada_url; pub fn ada_is_valid(url: *mut ada_url) -> bool; pub fn ada_can_parse(url: *const c_char, length: usize) -> bool; pub fn ada_can_parse_with_base( diff --git a/src/lib.rs b/src/lib.rs index d429a60..61490d9 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -39,6 +39,7 @@ use std::os::raw::c_uint; use std::{borrow, fmt, hash, ops}; use thiserror::Error; +extern crate alloc; #[cfg(feature = "serde")] extern crate serde; @@ -68,11 +69,21 @@ impl From for HostType { } /// A parsed URL struct according to WHATWG URL specification. -#[derive(Eq, Clone)] +#[derive(Eq)] pub struct Url { url: *mut ffi::ada_url, } +/// Clone trait by default uses bit-wise copy. +/// In Rust, FFI requires deep copy, which requires an additional/inexpensive FFI call. +impl Clone for Url { + fn clone(&self) -> Self { + Url { + url: unsafe { ffi::ada_copy(self.url) }, + } + } +} + impl Drop for Url { fn drop(&mut self) { unsafe { ffi::ada_free(self.url) } @@ -749,4 +760,14 @@ mod test { let deserialized: Url = serde_json::from_str(&output).unwrap(); assert_eq!(deserialized.href(), input.to_string() + "/"); } + + #[test] + fn should_clone() { + let first = Url::parse("https://lemire.me", None).unwrap(); + let mut second = first.clone(); + second.set_href("https://yagiz.co"); + assert_ne!(first.href(), second.href()); + assert_eq!(first.href(), "https://lemire.me/"); + assert_eq!(second.href(), "https://yagiz.co/"); + } }