-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
Make Headers::remove return the header #898
Conversation
d89a554
to
c389c48
Compare
@@ -82,6 +82,14 @@ impl Item { | |||
} | |||
self.typed.get_mut(tid).map(|typed| unsafe { typed.downcast_mut_unchecked() }) | |||
} | |||
|
|||
pub fn into_typed<H: Header>(self) -> Option<H> { |
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.
Because a H
may be unsized, I probably can only return Option<Box<Header + Send + Sync>>
here. However, then I'm unsure how I'd be casting the box to a concrete type.
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.
To be clear, I get a type conflict exactly at this spot: Expected H
, got Box<Header + Send + Sync>
. The first idea here is to add a new downcast_*
method to impl Header + Send + Sync
(again analogous to the get
methods), but I don't know how to implement such a method.
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.
Ah yes, of course, because the typed
is storing them as Box<Header>
. I think there is a way to add a downcast taking self by value, such as something like fn downcast(self: Box<Self>)
, but I'll toy on playground to find the right thing and report back.
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.
Adding this to the impl Header + Send + Sync
should do it:
#[inline]
unsafe fn downcast_unchecked<T: 'static>(self: Box<Self>) -> T {
*(mem::transmute::<*mut _, (*mut (), *mut ())>(Box::into_raw(self)).0 as *mut T)
}
Then you can call val.downcast_unchecked()
after having gotten the type from the TypeId.
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.
Unfortunately this doesn't work, apparently I can't deref *mut T
.
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.
Oh right. We can convert the *mut T
into a Box<T>
for free, with Box::from_raw
, and then we can deref move out of the box:
*Box::from_raw(mem::transmute::<*mut _, (*mut (), *mut ())>(Box::into_raw(self)).0 as *mut T)
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.
Amazing.
Oh woops, I didn't realize that the internal |
@@ -320,10 +320,11 @@ impl Headers { | |||
} | |||
|
|||
/// Removes a header from the map, if one existed. | |||
/// Returns true if a header has been removed. | |||
pub fn remove<H: Header>(&mut self) -> bool { | |||
/// Returns the header, if one has been removed. |
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.
This is actually incorrect. None
may also be returned if the removed header was not parseable.
I wonder if we should return Option<(Raw, Option<H>)>
or something like that instead, to enable as many usecases as possible.
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.
Hm, I don't love that the return value could be more complicated, but how about this crazy idea: Option<Result<H, Raw>>
...
I'd personally just drop it, but is there a convincing case where the raw is still needed to justify complicating the return type?
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.
I can't think of a reason why Raw
is needed, but with the current return type there is no upgrade path for people who were checking the boolean value, as .is_some()
is false
even if the header was removed, but could not be parsed.
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.
Therefore Option<Option<H>>
or Option<Result<H, ()>>
would be appropriate if we don't want to bother with Raw
.
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.
Both feel yucky. I'd still prefer to just have Option<H>
. The upgrade path could be to check headers.has()
before calling remove()
.
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.
Fair enough, I will update the docstring then.
2e29a3d
to
bc97d7b
Compare
bc97d7b
to
81e3cef
Compare
@seanmonstar This should be ready to merge. |
Looks right to me. Seems travis-ci's OSX containers are lagging, all the linux tests pass, so I'll merge anyways. |
Thanks! |
Fix #891