-
Notifications
You must be signed in to change notification settings - Fork 1
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
Use const generics to implement Io trait for [T; N] #12
Comments
Is there a simple way to use endiannezz for [T; N]s without using const generics? |
@ahmed-masud const generics already in stable rust anyway |
Okay so something that produces something like this should do the trick correct? I am going to try and implement this :P wish me luck hehe use num_traits as traits; // 0.2.14
use traits::PrimInt;
use traits::Num;
use std::convert::TryInto;
trait Primitive {
type Buf;
fn to_be_bytes(&self) -> <Self as Primitive>::Buf;
}
impl Primitive for u64 {
type Buf = u64;
fn to_be_bytes(&self) -> <Self::Buf as Primitive>::Buf {
let primitive = *self as <Self as Primitive>::Buf;
primitive.to_be()
}
}
impl<T:PrimInt, const N: usize> Primitive for [T; N]
where
T: Primitive + Sized + Num + Copy
{
type Buf = [T; N];
fn to_be_bytes(&self) -> <Self::Buf as Primitive>::Buf {
let primitive = *self as <Self as Primitive>::Buf;
let _r: Vec<T> = primitive.iter().map(|x| {
x.to_be()
}).collect();
_r.try_into()
.unwrap_or_else(|v: Vec<T>|
panic!("Expected a Vec of length {} but it was {}", N, v.len()))
}
}
fn main() {
let a: [u64; 5] = [0xdead; 5];
println!("{:?}", a.to_be_bytes());
} |
@ahmed-masud collect allocates memory in heap anyway. Also don't forget about |
I'm going to reimplement this library without depending on |
That is a good point—Rust was complaining about not being able to figure out the type of _r—but I'll watch for double allocs.
Thank you, that makes sense. I am going to implement the related bits by hand first (without augmenting the derive for a simple case, I am also rather green with macros) and then see where it goes. |
Why it should be implemented without const generics? They are stable since rust 1.51. The only excuse I can make against the implementation it with const generics is generating a lot of same code for different types. |
Also I'd like to avoid panics and creating errors with messages using |
Oh I AM implementing it with const generics (but before i do the derive macro code generation, i wanted to do basically write out the code by hand).
Yeah I wasn't planning on sticking any panics in the library, I should've clarified my code above is just "toy code" to ask you if I was on the right path :) |
Would be nice to don't include any new deps such as num traits |
There is however a small issue that I am currently running into, may be you can give me your thoughts on this; So I am starting by this implementation in the impl<T, const N: usize> Primitive for [T; N]
where T: Sized + Copy + Primitive
{
type Buf = [u8; mem::size_of::<T>() * N];
^^^^^^^^^^^^^^^^^^
// I take it that T here should be limited to the
// numerical primitives and I should just stick this
// template up in the macro and delegate this out?
fn to_ne_bytes(self: Self) -> Self::Buf {
todo!()
}
fn to_le_bytes(self) -> Self::Buf {
todo!()
}
fn to_be_bytes(self) -> Self::Buf {
todo!()
}
fn from_ne_bytes(bytes: Self::Buf) -> Self {
todo!()
}
fn from_le_bytes(bytes: Self::Buf) -> Self {
todo!()
}
fn from_be_bytes(bytes: Self::Buf) -> Self {
todo!()
}
} |
I think the way to do it without Num (because that was what I was using to limit the T to numerical primitives, is to use a copy of the macro that you use and simply implement the const generic array types. Let me implement something (may be a bit crude to start with but we can tighten it up) ... |
You can implement Io for [T; N] instead of Primitive. E.g. bool doesn't have to_ne_bytes method and it's implemented as Io |
How would that deal with something like [u32; 5]? I would expect that to have to_le_bytes() and to_be_bytes() ... that is to say:
|
Hey boss, Check out the develop branch on my fork, https://github.com/safai-labs/endiannezz/tree/develop I have implemented const generics for all primitive types (it's not possible right now to do it for non-primitive types because of the missing features in Rust). There were some choices about inserting some Although the code may need some prettifying I think it is solid, and works rather nicely, and I am comfortable enough using it in production for a rather complex decentralized filesystem. I also added the ability to "skip" attributes inside structures to allow for skipping of a field in a struct. It's skipped for It was necessary to create internal traits for I've added my name to the LICENSE file to enable redistribution. You can do a pull request as you see fit. Cheers, A |
I did new branch that much simpler implements #[derive(Io, Debug, PartialEq)]
#[endian(big)]
struct ParseMe {
f: Seq<CountReader, Type>,
} but first of all need to solve the problem with specialization. |
Also can be used for slice and together with #11
The text was updated successfully, but these errors were encountered: