Been playing around with PhantomData in rust. Example usage in Rust's documentation deals with unsafe code and referemces, but what follows is an example in deserialization that doesn't touch unsafe code at all.
Say I wanted to implement something like `TryFrom<&[u8]>` for u16. There's an issue here: is the u16 in little endian or in big endian order? The obvious (but dirty) answer is to pick an endian and swap when necessary.
What about newtype wrappers? I could create `LEu16` and `BEu16` and implement for these separately. However, this is mildly annoying.
However, what if we tied some extra data to a single wrapper? e.g. you deserialized a Wrappedu16<BigEndian>.
Of course Rust doesn't like unused template parameters, so PhantomData comes to the rescue:
```rust
struct Wrappedu16<Endian>(u16, PhantomData<Endian>)
```
and then I could implement TryFrom roughly like thus using the byteorder crate:
```rust
impl<'a, Endian> TryFrom<&'a [u8]> for Wrappedu16<Endian>
where Endian: byteorder::ByteOrder {
fn try_from(src: &'a [u8]) -> Result<Self, !> {
Ok(Endian::read_u16(src)) // panics, unfortunately
}
}
```
It's not perfect by any means, but I think it's pretty neat!
Why'd I decide to type this all out on my phone? >_>