-
Notifications
You must be signed in to change notification settings - Fork 15
implements Deref<Target=str>
, Display
, AsRef
, FromStr
...
#16
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
std::ops::Deref<Target=str>
, std::fmt::Display
, `AsRef…Deref<Target=str>
, Display
, AsRef
, FromStr
...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good to me! Should we add any tests?
Absolutely. Sorry, I meant to that before sending it over to you! I'm going to go ahead and implement some more traits, such as I'll impl those along with tests shortly. |
I'm not sure if you're interested in a impl TryFrom<&[u8]> for Url {
type Error = Error;
fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
Self::parse(&String::from_utf8_lossy(value), None)
}
} impl<'a> TryFrom<&'a [u8]> for Url {
type Error = &'a [u8];
fn try_from(value: &'a [u8]) -> Result<Self, Self::Error> {
let s = std::str::from_utf8(value).map_err(|_| value)?;
Self::parse(s, None).map_err(|_| value)
}
} |
I don't have any strong preference. Although, which one is faster? |
In the event of a failure to convert to utf8, the first as it'll fail fast. Otherwise they should be about the same. In truth, it's probably best to omit the Should |
Also, what about case folding on equality of the scheme and authority? I'm guessing those should be folded but I'd rather not assume. |
I trust your word on this, and having an opaque error reporting seem like an issue we shouldn't omit.
According to WHATWG
What do you mean? I didn't understand. |
Ah, thank you! I've read through the spec a while back but I forgot the details on equality of hash vs null hash. My brain has a tendency of dumping specs pretty much instantaneously.
I meant case comparison, e.g. |
No worries at all. It's always good to receive feedback and talk about topics we're all interested in. Yes, according to spec, all characters need to be lowercased. |
@chanced If you want to dive into the |
@anonrig awesome, will do. Thanks! let components = unsafe { ffi::ada_get_url_components(self.url) };
f.debug_struct("Url")
.field("href", &self.href())
.field("protocol_end", &components.protocol_end)
.field("username_end", &components.username_end)
.field("host_start", &components.host_start)
.field("host_end", &components.host_end)
.field("port", &components.port)
.field("pathname_start", &components.pathname_start)
.field("search_start", &components.search_start)
.field("hash_start", &components.hash_start)
.finish() is producing the following error:
|
It seems we never really exposed this in C. We need to fix this in |
The traits include: - `std::fmt::Debug` - `std::cmp::PartialEq` - `std::cmp::Eq` - `std::cmp::PartialOrd` - `std::cmp::Ord` - `std::hash::Hash` - `std::borrow::Borrow<str>` - `std::borrow::Borrow<[u8]>` - `std::convert::AsRef<[u8]>` - `std::convert::TryFrom<&str>` - `std::convert::TryFrom<String>` - `std::convert::TryFrom<&String>`
|
We have tests in |
Awesome, I'll get that fixed and swapped out. The only thing I don't know how to do is clone. I haven't dealt with FFI in rust and my preliminary search on figuring it out has come up dry. I'll keep digging but it's definitely one of the more important traits to implement for a value data structure. |
Maybe @Boshen or @Brooooooklyn can help with it. |
So updating the function name worked, however the output is suspect. Input
OutputUrl {
href: "https://www.ada-url.com/playground",
protocol_end: 1863623904,
username_end: 1,
host_start: 15513396,
host_end: 1,
port: 1013989984,
pathname_start: 1,
search_start: 1,
hash_start: 0,
} Srcimpl std::fmt::Debug for Url {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let components = unsafe { ffi::ada_get_components(self.url) };
f.debug_struct("Url")
.field("href", &self.href())
.field("protocol_end", &components.protocol_end)
.field("username_end", &components.username_end)
.field("host_start", &components.host_start)
.field("host_end", &components.host_end)
.field("port", &components.port)
.field("pathname_start", &components.pathname_start)
.field("search_start", &components.search_start)
.field("hash_start", &components.hash_start)
.finish()
}
} Test #[test]
fn spike_debug() {
let tests = [("https://www.ada-url.com/playground")];
for value in tests {
let url = Url::parse(value, None).expect("Should have parsed url");
println!("{:#?}", url);
}
} |
@chanced --- a/src/lib.rs
+++ b/src/lib.rs
@@ -91,7 +91,7 @@ pub mod ffi {
base: *const c_char,
base_length: usize,
) -> bool;
- pub fn ada_get_components(url: *mut ada_url) -> ada_url_components;
+ pub fn ada_get_components(url: *mut ada_url) -> *mut ada_url_components;
// Getters
pub fn ada_get_origin(url: *mut ada_url) -> ada_owned_string;
@@ -502,7 +502,7 @@ impl std::convert::AsRef<[u8]> for Url {
impl std::fmt::Debug for Url {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
- let components = unsafe { ffi::ada_get_components(self.url) };
+ let components = unsafe { ffi::ada_get_components(self.url).as_ref().unwrap() };
f.debug_struct("Url")
.field("href", &self.href())
.field("protocol_end", &components.protocol_end) |
That's definitely closer! It seems that perhaps Url {
href: "https://www.ada-url.com/playground",
protocol_end: 6,
username_end: 8,
host_start: 8,
host_end: 23,
port: 4294967295,
pathname_start: 23,
search_start: 4294967295,
hash_start: 4294967295,
} |
That's the correct behaviour. |
@lemire makes sense I guess I should back up and ask if ya'll even want the positions in the debug output? If you do, do you want me to replace the |
@chanced For context, here is the type...
Here is the C interface...
There is no "null" value given a Note that the parser will not let you parse a URL that would span 0xffffffff bytes. |
Yea, I saw the |
@lemire sorry, meant to mention. |
This is by default a design choice. We have an omitted value which is equal to Uint32 max value. |
I updated Removing the logic and either outputting the string value or Currently, the output from Url {
href: "https://www.ada-url.com/playground",
protocol_end: 6,
host_start: 8,
host_end: 23,
port: None,
username_end: Some(
8,
),
search_start: None,
hash_start: None,
pathname_start: Some(
23,
),
} edit: woops, fixing port. |
Aside from any changes to It's quitting time for me at the moment. I'll probably circle back to this later tonight tho. Hopefully I'll have it wrapped up either tonight or tomorrow. |
Perfect. Thanks for doing this! |
Oh it's no trouble at all. Y'all have done the heavy lifting! :) |
I am absolutely not certain about this but there may need to be some sort of copy api endpoint on the C++ side of things to implement clone. I'll look a bit more; it seems like cxx may be able to pull off cloning so it could be possible. Anyway, here's a list of traits implemented and a note as to why:
|
Can you update README with this amazing table? It would be beneficial to have a |
We can implement Clone in a different PR, no rush. |
@anonrig absolutely |
Thank you. I’ll release a new version soon. |
This implements a few nice-to-haves for the
Url
type, such asDeref<Target=str>
so that&Url
can be passed anywhere that expects&str
plus all methods implemented forDeref<Target=str>
std::convert::AsRef<str>
std::fmt::Display
, so that formatting theUrl
works as expected, also providesto_string
.std::str::FromStr
forstr::parse
https://doc.rust-lang.org/std/primitive.str.html#method.parseIt also adds
as_str
, basically as an alias forhref
, for convention sake.