Skip to content

Commit 8e17a00

Browse files
authored
feat: error type without allocation (#37)
* docs: fix typo * feat: error type without allocation * `thiserror` has been replaced with `derive_more` - `thiserror` cannot handle generic bounds * the `Error` type has been replaced with `ParseUrlError` - it only has one variant anyway * feat: expose `input` * docs: describe the error type
1 parent e1dbef5 commit 8e17a00

File tree

3 files changed

+72
-39
lines changed

3 files changed

+72
-39
lines changed

Cargo.lock

Lines changed: 42 additions & 17 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ libcpp = []
2828
serde = ["dep:serde"]
2929

3030
[dependencies]
31-
thiserror = "1"
31+
derive_more = "0.99.17"
3232
serde = { version = "1.0", optional = true, features = ["derive"] }
3333

3434
[dev-dependencies]

src/lib.rs

Lines changed: 29 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -35,17 +35,20 @@ pub mod ffi;
3535
mod idna;
3636
pub use idna::Idna;
3737

38+
use derive_more::{Display, Error};
3839
use std::{borrow, fmt, hash, ops, os::raw::c_uint};
39-
use thiserror::Error;
4040

4141
extern crate alloc;
4242
#[cfg(feature = "serde")]
4343
extern crate serde;
4444

45-
#[derive(Error, Debug, PartialEq, Eq)]
46-
pub enum Error {
47-
#[error("Invalid url: \"{0}\"")]
48-
ParseUrl(String),
45+
/// Error type of [`Url::parse`].
46+
#[derive(Debug, Display, Error, PartialEq, Eq)]
47+
#[display(bound = "Input: std::fmt::Debug")]
48+
#[display(fmt = "Invalid url: {input:?}")]
49+
pub struct ParseUrlError<Input> {
50+
/// The invalid input that caused the error.
51+
pub input: Input,
4952
}
5053

5154
/// Defines the type of the host.
@@ -161,23 +164,26 @@ impl Url {
161164
/// .expect("This is a valid URL. Should have parsed it.");
162165
/// assert_eq!(out.protocol(), "https:");
163166
/// ```
164-
pub fn parse(input: &str, base: Option<&str>) -> Result<Url, Error> {
167+
pub fn parse<Input>(input: Input, base: Option<&str>) -> Result<Url, ParseUrlError<Input>>
168+
where
169+
Input: AsRef<str>,
170+
{
165171
let url_aggregator = match base {
166172
Some(base) => unsafe {
167173
ffi::ada_parse_with_base(
168-
input.as_ptr().cast(),
169-
input.len(),
174+
input.as_ref().as_ptr().cast(),
175+
input.as_ref().len(),
170176
base.as_ptr().cast(),
171177
base.len(),
172178
)
173179
},
174-
None => unsafe { ffi::ada_parse(input.as_ptr().cast(), input.len()) },
180+
None => unsafe { ffi::ada_parse(input.as_ref().as_ptr().cast(), input.as_ref().len()) },
175181
};
176182

177183
if unsafe { ffi::ada_is_valid(url_aggregator) } {
178184
Ok(url_aggregator.into())
179185
} else {
180-
Err(Error::ParseUrl(input.to_owned()))
186+
Err(ParseUrlError { input })
181187
}
182188
}
183189

@@ -686,26 +692,26 @@ impl fmt::Debug for Url {
686692
}
687693
}
688694

689-
impl TryFrom<&str> for Url {
690-
type Error = Error;
695+
impl<'input> TryFrom<&'input str> for Url {
696+
type Error = ParseUrlError<&'input str>;
691697

692-
fn try_from(value: &str) -> Result<Self, Self::Error> {
698+
fn try_from(value: &'input str) -> Result<Self, Self::Error> {
693699
Self::parse(value, None)
694700
}
695701
}
696702

697703
impl TryFrom<String> for Url {
698-
type Error = Error;
704+
type Error = ParseUrlError<String>;
699705

700706
fn try_from(value: String) -> Result<Self, Self::Error> {
701-
Self::parse(&value, None)
707+
Self::parse(value, None)
702708
}
703709
}
704710

705-
impl TryFrom<&String> for Url {
706-
type Error = Error;
711+
impl<'input> TryFrom<&'input String> for Url {
712+
type Error = ParseUrlError<&'input String>;
707713

708-
fn try_from(value: &String) -> Result<Self, Self::Error> {
714+
fn try_from(value: &'input String) -> Result<Self, Self::Error> {
709715
Self::parse(value, None)
710716
}
711717
}
@@ -730,10 +736,12 @@ impl fmt::Display for Url {
730736
}
731737

732738
impl std::str::FromStr for Url {
733-
type Err = Error;
739+
type Err = ParseUrlError<Box<str>>;
734740

735741
fn from_str(s: &str) -> Result<Self, Self::Err> {
736-
Self::parse(s, None)
742+
Self::parse(s, None).map_err(|ParseUrlError { input }| ParseUrlError {
743+
input: input.into(),
744+
})
737745
}
738746
}
739747

@@ -789,7 +797,7 @@ mod test {
789797
dbg!(&url);
790798
let error = url.unwrap_err();
791799
assert_eq!(error.to_string(), r#"Invalid url: "this is not a url""#);
792-
assert!(matches!(error, Error::ParseUrl(_)));
800+
assert_eq!(error.input, "this is not a url");
793801
}
794802

795803
#[test]

0 commit comments

Comments
 (0)