For fun I'm trying to figure out how to write a generic function that takes a std::fs::File and reads size <T> from the file into <T>. It feels a little strange to me that when trying to create a [u8] to fill that the Rust compiler complains that it doesn't know statically the size. It seems to me that it should know at compilation based on <T> though. I know this is easily possible. I'm just not that familiar with the language.
So I'm asking for help in understanding how I help the compiler understand. The code I have so far is
unsized locals are gated as an unstable feature [E0277]
all local variables must have a statically known size [E0277]
to learn more, visit <https://doc.rust-lang.org/book/second-edition/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait> [E0277]
the trait `std::marker::Sized` is not implemented for `[u8]` [E0277]
the size for values of type `[u8]` cannot be known at compilation time (doesn't have a size known at compile-time) [E0277]
This isn't just unsafe, it's catastrophically unsafe. You could use this to do write_to_type::<Box<i32>>(&some_file) to construct an owned pointer to an arbitrary memory location. Or write_to_type::<fn()>(&some_file) to execute arbitrary memory.
Frankly, this function probably shouldn't exist. Even marked as unsafe, it'd be way too easy to misuse. If you're going to do something like this, I would strongly recommend using an unsafe trait to constrain exactly which types you can use this with:
This way, you can individually enable the trait for the small set of types for which it is actually safe to use... which is probably limited to the built-in integer and float types, and composites of those which do not contain any padding.
But, really, you should probably just use serde plus bincode (for automated [de]serialisation) or byteorder (for manual [de]serialisation).
Thanks for the reply to both KrishnaSannasi and DanielKeep. I appreciate your concern in the safety of code like this. Like I mentioned above I'm just fiddling around, really just trying to learn the language and get a grasp of things. I am aware of byteorder but really am just figuring out ways of messing with memory.
I would plan on constraining this type of code to very specific types.
I am certainly still open to more thoughts and opinions.
Sorry to bring this up again, but I'm still confused. Fiddling around a bit more I have the following code, and complaint from the compiler. How is it possible a primitive type can have a varying size?