繁体   English   中英

Rust generics 和编译时大小

[英]Rust generics and compile time size

我有一个类似于下面的 function:

fn write( data: u8, buf: &mut dyn Write )
{
    let bytes = data.to_ne_bytes();
    buf.write(&bytes);
}

我想将这个 function 用于所有固定大小的类型 u8、i8、u16、i16 等,类似于 C++ 中的重载。有没有办法用 Rust 中的 generics 做到这一点?

我试过以下,但是,它不编译:

use fixed::traits::Fixed;

fn write<T: Fixed<Bytes = [u8]> + Sized>( data: T, buf: &mut dyn Write )
{
    let bytes = data.to_ne_bytes();
    buf.write(&bytes);
}

我收到以下错误:

error[E0277]: the size for values of type `[u8]` cannot be known at compilation time

    |
4   |     let bytes = data.to_ne_bytes();
    |         ^^^^^ doesn't have a size known at compile-time
    |
    = help: the trait `Sized` is not implemented for `[u8]`
    = note: all local variables must have a statically known size
    = help: unsized locals are gated as an unstable feature

我也试过这样的事情:

fn write<T: Fixed<Bytes = [u8]> + Sized>( data: T, buf: &mut dyn Write )
{
    let bytes:[u8; mem::size_of_val(data)] = data.to_ne_bytes();
    buf.write(&bytes);
}

不幸的是,这也不起作用。 我得到这个编译错误:

error[E0435]: attempt to use a non-constant value in a constant

    |
146 | fn write<T: Fixed<Bytes = [u8]> + Sized>( data: T, buf: &mut dyn Write )
    |                                            ---- this would need to be a `const`
...
149 |     let bytes:[u8; mem::size_of_val(data)] = data.to_ne_bytes();
    |                                     ^^^^


编辑:

建议的副本在我的情况下不可用。 那里使用的特性不允许我拥有一个在编译时知道其大小的类型

这是一个使用自定义特征的示例:

use std::io::Write;

trait ToBytes {
    type Output;
    
    fn to_ne_bytes(self) -> Self::Output;
    
    // TODO: maybe add to_le_bytes and/or to_be_bytes?
}

impl ToBytes for u8 {
    type Output = [u8; 1];
    
    fn to_ne_bytes(self) -> Self::Output {
        [self]
    }
}
impl ToBytes for u16 {
    type Output = [u8; 2];
    
    fn to_ne_bytes(self) -> Self::Output {
        self.to_ne_bytes()
    }
}
impl ToBytes for u32 {
    type Output = [u8; 4];
    
    fn to_ne_bytes(self) -> Self::Output {
        self.to_ne_bytes()
    }
}
impl ToBytes for u64 {
    type Output = [u8; 8];
    
    fn to_ne_bytes(self) -> Self::Output {
        self.to_ne_bytes()
    }
}
// TODO: signed integers

fn write<T>(data: T, buf: &mut dyn Write)
where
    T: ToBytes,
    <T as ToBytes>::Output: AsRef<[u8]>,
{
    let bytes = data.to_ne_bytes();
    buf.write(bytes.as_ref());
}

fn main() {
    let x: u8 = 5;
    let mut buf: Vec<u8> = Vec::new();
    
    write(x, &mut buf);
}

操场

假设Fixed set Bytes的实现者是固定大小的u8 arrays ,您可以使用 const generics 并在Bytes中对u8数组的大小进行通用write

fn write<const N: usize, T: Fixed<Bytes = [u8; N]>>(data: T, buf: &mut dyn Write) {
    let bytes = data.to_ne_bytes();
    buf.write(&bytes);
}

操场

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM