如何使Rust函数在u8 | u32切片上泛型?



我正在移植一个Typescript库,它具有以下类型别名和函数:

type GlkTypedArray = Uint8Array | Uint32Array
get_buffer(buf: GlkTypedArray): number

非常简单,它接受Uint8ArrayUint32Array

我现在正试图在Rust中做同样的事情,通过一个仅为u8u32定义的特性:

trait GlkInt: Sized {}
impl GlkInt for u8 {}
impl GlkInt for u32 {}
fn get_buffer(buf: &mut [dyn GlkInt]) -> u32;

但不幸的是,它不允许这样做,说性状不是Sized,尽管我认为性状定义意味着它应该是。

error[E0277]: the size for values of type `dyn misc::GlkInt` cannot be known at compilation time
--> remglk/src/glkapi/streams.rs:18:29
|
18 |     fn get_buffer(buf: &mut [dyn GlkInt]) -> u32;
|                             ^^^^^^^^^^^^ doesn't have a size known at compile-time
|
= help: the trait `Sized` is not implemented for `dyn misc::GlkInt`
= note: slice and array elements must have `Sized` type
error[E0038]: the trait `misc::GlkInt` cannot be made into an object
--> remglk/src/glkapi/streams.rs:18:30
|
18 |     fn get_buffer(buf: &mut [dyn GlkInt]) -> u32;
|                              ^^^^^^^^^^ `misc::GlkInt` cannot be made into an object
|
note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
--> remglk/src/common/misc.rs:13:19
|
13 | pub trait GlkInt: Sized {}
|           ------  ^^^^^ ...because it requires `Self: Sized`
|           |
|           this trait cannot be made into an object...

我需要做点别的吗,还是这整个方法都不起作用了?我还能尝试什么?

数组/切片元素的大小需要在编译时知道,以便编译器可以计算2项之间的距离进行索引。dyn GlkInt将是1或4字节宽,所以没有办法知道大小。

您可以使用泛型类型进行静态调度,在这种情况下,您可能希望在泛型(From<u8>,Into<u32>)上需要更多的特征:

trait GlkInt {}
impl GlkInt for u8 {}
impl GlkInt for u32 {}
fn get_buffer<T: GlkInt>(buf: &mut [T]) -> u32 {
0
}

或者使用枚举并自己实现不同的代码路径。

use GlkSlice::*;
enum GlkSlice<'a> {
U8(&'a mut [u8]),
U32(&'a mut [u32]),
}
fn get_buffer(buf: GlkSlice<'_>) -> u32 {
match buf {
U8(buf) => buf[0] as u32,
U32(buf) => buf[0],
}
}

最新更新