Skip to content

Commit f1bf053

Browse files
authored
In functions using ada_owned_string, return ada_owned_string instead of &str (#67)
* feat(idna-&-lib/&str->ada_owned_string): change return type to ada_owned_string ada_owned_string is supposed to be cleared manually. This was not being done currently. Instead an internal reference to the memory was being returned by these functions. This led to us being unable to delete the memory out of fear of invalidating the &str present in user space. By returning ada_owned_string, this issue is resolved and the memory leaks no longer happen in library space. Old &str can still be accessed using as_ref. BREAKING CHANGE: Functions using ada_owned_string now return ada_owned_string instead of &str. Memory leaks no longer happen in library space. Old &str can still be accessed using as_ref. * feat(ada_owned_string/Drop): add Clears the memory after the ada_owned_string goes out of scope. This ensures that ada_owned_string is cleared in user space. BREAKING CHANGE: ada_owned_string was previously not freed upon going out of scope. Now it is. * feat(ada_owned_string/ToString): add Makes it possible to convert ada_owned_string to ToString * refactor(ada_owned_string->String): change return type from ada_owned_string to String Ensures that ada_owned_string does not leak to user space and allows us to make internal breaking changes to its implementation. Fixes all leak issue. Causes small performance downgrades due to copies. Causes functions to be usable only if std is enabled. BREAKING CHANGE: Return type changed from ada_owned_string->String. Functions now work only with std feature enabled.
1 parent 57a3179 commit f1bf053

File tree

3 files changed

+51
-18
lines changed

3 files changed

+51
-18
lines changed

src/ffi.rs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
#![allow(non_camel_case_types)]
22
use core::ffi::{c_char, c_uint};
33

4+
#[cfg(feature = "std")]
5+
extern crate std;
6+
47
#[repr(C)]
58
pub struct ada_url {
69
_unused: [u8; 0],
@@ -38,6 +41,26 @@ impl AsRef<str> for ada_owned_string {
3841
}
3942
}
4043

44+
#[cfg(feature = "std")]
45+
impl ToString for ada_owned_string {
46+
fn to_string(&self) -> std::string::String {
47+
self.as_ref().to_owned()
48+
}
49+
}
50+
51+
impl Drop for ada_owned_string {
52+
fn drop(&mut self) {
53+
// @note This is needed because ada_free_owned_string accepts by value
54+
let copy = ada_owned_string {
55+
data: self.data,
56+
length: self.length,
57+
};
58+
unsafe {
59+
ada_free_owned_string(copy);
60+
};
61+
}
62+
}
63+
4164
#[repr(C)]
4265
pub struct ada_url_components {
4366
pub protocol_end: u32,

src/idna.rs

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
1+
#[cfg(feature = "std")]
2+
extern crate std;
3+
4+
#[cfg_attr(not(feature = "std"), allow(unused_imports))]
15
use crate::ffi;
26

7+
#[cfg(feature = "std")]
8+
use std::string::String;
9+
310
/// IDNA struct implements the `to_ascii` and `to_unicode` functions from the Unicode Technical
411
/// Standard supporting a wide range of systems. It is suitable for URL parsing.
512
/// For more information, [read the specification](https://www.unicode.org/reports/tr46/#ToUnicode)
@@ -16,12 +23,9 @@ impl Idna {
1623
/// assert_eq!(Idna::unicode("xn--meagefactory-m9a.ca"), "meßagefactory.ca");
1724
/// ```
1825
#[must_use]
19-
pub fn unicode(input: &str) -> &str {
20-
unsafe {
21-
let out = ffi::ada_idna_to_unicode(input.as_ptr().cast(), input.len());
22-
let slice = core::slice::from_raw_parts(out.data.cast(), out.length);
23-
core::str::from_utf8_unchecked(slice)
24-
}
26+
#[cfg(feature = "std")]
27+
pub fn unicode(input: &str) -> String {
28+
unsafe { ffi::ada_idna_to_unicode(input.as_ptr().cast(), input.len()) }.to_string()
2529
}
2630

2731
/// Process international domains according to the UTS #46 standard.
@@ -34,26 +38,26 @@ impl Idna {
3438
/// assert_eq!(Idna::ascii("meßagefactory.ca"), "xn--meagefactory-m9a.ca");
3539
/// ```
3640
#[must_use]
37-
pub fn ascii(input: &str) -> &str {
38-
unsafe {
39-
let out = ffi::ada_idna_to_ascii(input.as_ptr().cast(), input.len());
40-
let slice = core::slice::from_raw_parts(out.data.cast(), out.length);
41-
core::str::from_utf8_unchecked(slice)
42-
}
41+
#[cfg(feature = "std")]
42+
pub fn ascii(input: &str) -> String {
43+
unsafe { ffi::ada_idna_to_ascii(input.as_ptr().cast(), input.len()) }.to_string()
4344
}
4445
}
4546

4647
#[cfg(test)]
4748
mod tests {
49+
#[cfg_attr(not(feature = "std"), allow(unused_imports))]
4850
use crate::idna::*;
4951

5052
#[test]
5153
fn unicode_should_work() {
54+
#[cfg(feature = "std")]
5255
assert_eq!(Idna::unicode("xn--meagefactory-m9a.ca"), "meßagefactory.ca");
5356
}
5457

5558
#[test]
5659
fn ascii_should_work() {
60+
#[cfg(feature = "std")]
5761
assert_eq!(Idna::ascii("meßagefactory.ca"), "xn--meagefactory-m9a.ca");
5862
}
5963
}

src/lib.rs

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,12 @@ pub mod ffi;
4646
mod idna;
4747
pub use idna::Idna;
4848

49+
#[cfg(feature = "std")]
50+
extern crate std;
51+
52+
#[cfg(feature = "std")]
53+
use std::string::String;
54+
4955
use core::{borrow, ffi::c_uint, fmt, hash, ops};
5056
use derive_more::Display;
5157

@@ -270,12 +276,9 @@ impl Url {
270276
/// assert_eq!(url.origin(), "https://example.com");
271277
/// ```
272278
#[must_use]
273-
pub fn origin(&self) -> &str {
274-
unsafe {
275-
let out = ffi::ada_get_origin(self.0);
276-
let slice = core::slice::from_raw_parts(out.data.cast(), out.length);
277-
core::str::from_utf8_unchecked(slice)
278-
}
279+
#[cfg(feature = "std")]
280+
pub fn origin(&self) -> String {
281+
unsafe { ffi::ada_get_origin(self.0) }.to_string()
279282
}
280283

281284
/// Return the parsed version of the URL with all components.
@@ -949,7 +952,10 @@ mod test {
949952
None,
950953
)
951954
.expect("Should have parsed a simple url");
955+
956+
#[cfg(feature = "std")]
952957
assert_eq!(out.origin(), "https://google.com:9090");
958+
953959
assert_eq!(
954960
out.href(),
955961
"https://username:[email protected]:9090/search?query#hash"

0 commit comments

Comments
 (0)