rfcs
rfcs copied to clipboard
Match arrays against byte strings
Hi,
Today i have to do this:
const MVHD: [u8;4] = *b"mvhd";
match header.id {
BoxType::Id(BoxId(MVHD)) => self.mvhd = Some(MvhdBox::read(header, reader).await?),
// Or
BoxType::Id(BoxId([b'm', b'v', b'e', b'x'])) => self.mvex = Some(MvexBox::read(header, reader).await?),
...
}
When it would be reaonable and convenient to be able to do this:
match header.id {
BoxType::Id(BoxId(b"mvhd")) => self.mvhd = Some(MvhdBox::read(header, reader).await?),
BoxType::Id(BoxId(b"mvex")) => self.mvex = Some(MvexBox::read(header, reader).await?),
...
}
Today it gives:
BoxType::Id(BoxId(b"mvhd")) => self.mvhd = Some(MvhdBox::read(header, reader).await?),
^^^^^^^ expected array `[u8; 4]`, found `&[u8; 4]`
Any plans on implementing a solution ?
It will be at least easier with const
blocks.
an elegant way to get around that is to use associated consts in this way:
pub trait PartialBox {
const ID: BoxType;
}
impl PartialBox for MvhdBox {
const ID: BoxType = BoxType::Id(BoxId(*b"mvhd"));
}
impl PartialBox for MvexBox {
const ID: BoxType = BoxType::Id(BoxId(*b"mvex"));
}
// somewhere else
match header.id {
MvhdBox::ID => self.mvhd = Some(MvhdBox::read(header, reader).await?),
MvexBox::ID => self.mvex = Some(MvexBox::read(header, reader).await?),
_ => {}
}
this issue is still relevant nonetheless
thanks @ChayimFriedman2, you gave me the idea mentioning consts
I don't understand the issue; what's wrong with simply dereferencing the array?
match header.id {
BoxType::Id(BoxId(*b"mvhd")) => self.mvhd = Some(MvhdBox::read(header, reader).await?),
BoxType::Id(BoxId(*b"mvex")) => self.mvex = Some(MvexBox::read(header, reader).await?),
...
}
What you're doing is equivalent to passing &[b'm', b'v', b'e', b'x']
which is just erroneous?
I don't understand the issue; what's wrong with simply dereferencing the array?
match header.id { BoxType::Id(BoxId(*b"mvhd")) => self.mvhd = Some(MvhdBox::read(header, reader).await?), BoxType::Id(BoxId(*b"mvex")) => self.mvex = Some(MvexBox::read(header, reader).await?), ... }
Oh! I didn't think much of it being in a match position, that makes more sense. Got it.
For cases where it doesn't make sense to use/have associated consts, I end up placing const
values immediately above the match block, then matching against the const values. See
I've always wished the compiler could just do that for me, though. IMHO anything that can be stored as a local const
variable and then matched against should be fair to match against directly (unless it causes an ambiguous parse, of course).
Not very ergonomic, but it occurs to me that there's an RFC for inline const expressions, allowing:
match header.id {
BoxType::Id(BoxId(const { *b"mvhd") }) => self.mvhd = Some(MvhdBox::read(header, reader).await?),
BoxType::Id(BoxId(const { *b"mvex") }) => self.mvex = Some(MvexBox::read(header, reader).await?),
...
}