-
Notifications
You must be signed in to change notification settings - Fork 300
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
A method!
macro to define methods at build time
#587
Comments
I imagine a |
I tried making it Finally, I reached diff --git a/src/method.rs b/src/method.rs
index b7b3b35..a795208 100644
--- a/src/method.rs
+++ b/src/method.rs
@@ -97,7 +96,7 @@ impl Method {
pub const TRACE: Method = Method(Trace);
/// Converts a slice of bytes to an HTTP method.
- pub fn from_bytes(src: &[u8]) -> Result<Method, InvalidMethod> {
+ pub const fn from_bytes(src: &[u8]) -> Result<Method, InvalidMethod> {
match src.len() {
0 => Err(InvalidMethod::new()),
3 => match src {
@@ -128,7 +127,10 @@ impl Method {
if src.len() < InlineExtension::MAX {
Method::extension_inline(src)
} else {
- let allocated = AllocatedExtension::new(src)?;
+ let allocated = match AllocatedExtension::new(src) {
+ Ok(a) => a,
+ Err(e) => return Err(e),
+ };
Ok(Method(ExtensionAllocated(allocated)))
}
@@ -136,8 +138,11 @@ impl Method {
}
}
- fn extension_inline(src: &[u8]) -> Result<Method, InvalidMethod> {
- let inline = InlineExtension::new(src)?;
+ const fn extension_inline(src: &[u8]) -> Result<Method, InvalidMethod> {
+ let inline = match InlineExtension::new(src) {
+ Ok(i) => i,
+ Err(err) => return Err(err),
+ };
Ok(Method(ExtensionInline(inline)))
}
@@ -288,7 +293,7 @@ impl FromStr for Method {
}
impl InvalidMethod {
- fn new() -> InvalidMethod {
+ const fn new() -> InvalidMethod {
InvalidMethod { _priv: () }
}
}
@@ -325,10 +330,12 @@ mod extension {
// Method::from_bytes() assumes this is at least 7
pub const MAX: usize = 15;
- pub fn new(src: &[u8]) -> Result<InlineExtension, InvalidMethod> {
- let mut data: [u8; InlineExtension::MAX] = Default::default();
+ pub const fn new(src: &[u8]) -> Result<InlineExtension, InvalidMethod> {
+ let mut data: [u8; InlineExtension::MAX] = [0; 15];
- write_checked(src, &mut data)?;
+ if let Err(err) = write_checked(src, &mut data) {
+ return Err(err);
+ };
// Invariant: write_checked ensures that the first src.len() bytes
// of data are valid UTF-8.
@@ -339,15 +346,17 @@ mod extension {
let InlineExtension(ref data, len) = self;
// Safety: the invariant of InlineExtension ensures that the first
// len bytes of data contain valid UTF-8.
- unsafe {str::from_utf8_unchecked(&data[..*len as usize])}
+ unsafe { str::from_utf8_unchecked(&data[..*len as usize]) }
}
}
impl AllocatedExtension {
- pub fn new(src: &[u8]) -> Result<AllocatedExtension, InvalidMethod> {
+ pub const fn new(src: &[u8]) -> Result<AllocatedExtension, InvalidMethod> {
let mut data: Vec<u8> = vec![0; src.len()];
- write_checked(src, &mut data)?;
+ if let Err(err) = write_checked(src, &mut data) {
+ return Err(err);
+ };
// Invariant: data is exactly src.len() long and write_checked
// ensures that the first src.len() bytes of data are valid UTF-8.
|
Okay, my previous approach doesn't seem to be feasible.
Current I see two possible options:
|
@seanmonstar Any feedback on the above comment? I want to give this a shot, but both approaches are non-trivial so I'd rather hear from you before sinking time into the wrong one. |
I think keeping |
I'm not using custom methods; I'm using standardized methods like Whether they're uncommon depends on your field of work. Personally I find
You mean the |
Darn, I missed that |
I guess I'll try the |
Allows creating constant `Method` instances, e.g.: const PROPFIND: Method = Method::from_static(b"PROPFIND"); Fixes: hyperium#587
Allows creating constant `Method` instances, e.g.: const PROPFIND: Method = Method::from_static(b"PROPFIND"); Fixes: hyperium#587
Allows creating constant `Method` instances, e.g.: const PROPFIND: Method = Method::from_static(b"PROPFIND"); Fixes: hyperium#587
Allows creating constant `Method` instances, e.g.: const PROPFIND: Method = Method::from_static(b"PROPFIND"); Fixes: hyperium#587
Allows creating constant `Method` instances, e.g.: const PROPFIND: Method = Method::from_static(b"PROPFIND"); Fixes: hyperium#587
Allows creating constant `Method` instances, e.g.: const PROPFIND: Method = Method::from_static(b"PROPFIND"); Fixes: hyperium#587
Allows creating constant `Method` instances, e.g.: const PROPFIND: Method = Method::from_static(b"PROPFIND"); Fixes: hyperium#587
Allows creating constant `Method` instances, e.g.: const PROPFIND: Method = Method::from_static(b"PROPFIND"); Fixes: hyperium#587
Allows creating constant `Method` instances, e.g.: const PROPFIND: Method = Method::from_static(b"PROPFIND"); Fixes: hyperium#587
Using HTTP verbs / methods that are not defined in this crate has very ugly semantics, e.g.:
This
expect
adds a lot of noise all over the place, but it also can't be defined as aconst
. The following in invalid:At the same time, these verbs are something that can be validated at build time (rather than runtime). Do you think a macro to create methods would be reasonable? I'm thinking something along the lines of:
It would simply be replaced by the correct method, but a
proc_macro
could allow validating that the string is an acceptable verb at build time (hence, avoiding having aResult
for an operation that is known to be infallible).The text was updated successfully, but these errors were encountered: