http icon indicating copy to clipboard operation
http copied to clipboard

Add Method::from_static

Open WhyNotHugo opened this issue 3 years ago • 18 comments

Allows creating constant Method instances, e.g.:

const PROPFIND: Method = Method::from_static(b"PROPFIND");

Fixes: https://github.com/hyperium/http/issues/587

WhyNotHugo avatar Mar 27 '23 17:03 WhyNotHugo

Oh, I just realised that CI failed due to panic! not being available on the MSRV. I'll try refactoring that.

WhyNotHugo avatar Apr 03 '23 17:04 WhyNotHugo

We could probably update the MSRV, depending on what the version required is and how old it is.

seanmonstar avatar Apr 03 '23 17:04 seanmonstar

Rust 1.57.0, from 2021-12-02

WhyNotHugo avatar Apr 03 '23 18:04 WhyNotHugo

For tokio, the current MSRV is 1.56.0.

WhyNotHugo avatar Apr 03 '23 18:04 WhyNotHugo

I've updated the PR to panic without panic!. I used ([] as [u8; 0])[0];, which is already used as a const panic! hack in a couple of other places in the codebase.

We can remove this hack (both this new instance and existing ones) once the MSRV is bumped to 1.57.0 or greater.

WhyNotHugo avatar Jun 29 '23 11:06 WhyNotHugo

I was wondering if we could add a variant StaticRef(&'static [u8]) to the Method Inner enum instead of panicking on longer than 15 byte methods?

lperlaki avatar Oct 25 '23 08:10 lperlaki

I don't know of any methods that are longer than 15 bytes, so I'm not sure that it's worth the effort.

WhyNotHugo avatar Oct 25 '23 12:10 WhyNotHugo

What's this stuck on?

dblsaiko avatar Feb 20 '24 02:02 dblsaiko

I would also like to see this being merged as it helps with implementing a webdav server base on hyper

I don't know of any methods that are longer than 15 bytes, so I'm not sure that it's worth the effort.

recently I stubbled over the BASELINE-CONTROL webdav method wich is longe than 15 bytes (16)

I was wondering if we could add a variant StaticRef(&'static [u8]) to the Method Inner enum instead of panicking on longer than 15 byte methods?

figured out that this wouldn't work with the current implementation since the equality also checks the enum variant wich is required that Method can support pattern matching

lperlaki avatar Feb 21 '24 19:02 lperlaki

@seanmonstar Anything that needs to be done to land this? Happy to help if there's anything to do.

orium avatar Nov 28 '24 16:11 orium

I was wondering if we could add a variant StaticRef(&'static [u8]) to the Method Inner enum instead of panicking on longer than 15 byte methods?

I explored this a bit further.

Adding a new enum variant won't increase the total size of Inner. The associated data is a single reference, so it's also not bigger than the largest of the existing variants.

I've implemented your suggestions. This remove the conditional (compile-time) panic if len > 15.

WhyNotHugo avatar Dec 18 '24 14:12 WhyNotHugo

At this point, waiting for feedback from the core devs.

WhyNotHugo avatar Dec 18 '24 14:12 WhyNotHugo

I found the Problem with ExtensionStatic is that

const BASELINE_CONTROL: Method = Method::from_static(„BASELINE-CONTROL“);

let m = Method::from_bytes(„BASELINE-CONTROL“);

let is_baseline = match m {
    BASELINE_CONTROL => true,
    _ => false,
};

will not match.

lperlaki avatar Dec 19 '24 19:12 lperlaki

I found the Problem with ExtensionStatic is that

const BASELINE_CONTROL: Method = Method::from_static(„BASELINE-CONTROL“);

let m = Method::from_bytes(„BASELINE-CONTROL“);

let is_baseline = match m {
    BASELINE_CONTROL => true,
    _ => false,
};

will not match.

I'll add a test for this case and figure out what's wrong.

WhyNotHugo avatar Dec 19 '24 23:12 WhyNotHugo

The derived implementation of PartialEq will consider Inner::ExtensionAllocated to always be different from Inner::ExtensionStatic, regardless of the value of their associated data.

Possible solutions:

  • Re-implement PartialEq por Inner. This is likely a lot of very verbose code, and the derived implementation has optimisations which I suspect the core devs will want to keep around.

  • Drop ExtensionInline(InlineExtension), which means that common short methods will always be behind a pointer dereference. Not a terrible performance drop, but given how much all the other variants are optimised, it seems non-ideal.

  • Drop ExtensionStatic(StaticExtension) entirely, and limit from_static to a maximum of 15 bytes, as originally implemented. This is probably the least ideal approach.

WhyNotHugo avatar Feb 17 '25 10:02 WhyNotHugo

  • Re-implement PartialEq por Inner. This is likely a lot of very verbose code, and the derived implementation has optimisations which I suspect the core devs will want to keep around.

Not deriving PartialEq will also not implement StructuralPartialEq which is needed if we want to keep the match functionality

  • Drop ExtensionInline(InlineExtension), which means that common short methods will always be behind a pointer dereference. Not a terrible performance drop, but given how much all the other variants are optimised, it seems non-ideal.

will not fix the PartialEq implementation between Static and Allocated variant if not by hand implemented and then we have the first problem again

  • Drop ExtensionStatic(StaticExtension) entirely, and limit from_static to a maximum of 15 bytes, as originally implemented. This is probably the least ideal approach.

I think this is the only viable solution if we want to keep the pattern matching behaviour

lperlaki avatar Feb 17 '25 10:02 lperlaki

I believe that you are correct in all points.

WhyNotHugo avatar Feb 17 '25 10:02 WhyNotHugo

Updated based on the latest discussion. I've reflected a short summary of the decision taken in the commit message.

WhyNotHugo avatar Feb 18 '25 16:02 WhyNotHugo