简体   繁体   English

使用 bitvec 在 rust 中模板化输入和 output 类型

[英]Templating input and output type in rust with bitvec

Here I have two functions in rust which convert a bitvec into an integer.在这里,我在 rust 中有两个函数,它们将 bitvec 转换为 integer。 They are identical except for their types, so I'd like to template over both:除了它们的类型外,它们是相同的,所以我想对两者进行模板化:

  1. the input types BitVec and BitSlice输入类型BitVecBitSlice
  2. the return type u32 or u64返回类型u64u32
use bitvec::prelude::*; // bitvec = "0.22.3"

fn bslice_to_int(bv: &BitSlice::<Lsb0, u8>) -> u32 {
  let mut int = 0;
  for bit in bv {
    int = int << 1;
    if bit == true {
      int += 1;
    }
  }
  return int;
}

fn bv_to_int(bv: &BitVec::<Lsb0, u8>) -> u64 {
  let mut int = 0;
  for bit in bv {
    int = int << 1;
    if bit == true {
      int += 1;
    }
  }
  return int;
}

fn main() {
  let bits = bitvec![Lsb0, u8; 1,0,1,0];
  let val1 = bslice_to_int(&bits[0..2]);
  let val2 = bv_to_int(&bits);
  println!("{} {}", val1, val2); // "10 2"
}

I seem to have a different problem with each.我似乎对每个都有不同的问题。

Trying 1) to make the input type generic:尝试 1) 使输入类型通用:

fn bv_to_int_generic_in<T>(bv: &T) -> u64 {
  let mut int = 0;
  for bit in bv {
    int = int << 1;
    if bit == true {
      int += 1;
    }
  }
  return int;
}

fn main() {
  let bits = bitvec![Lsb0, u8; 1,0,1,0];
  let val1 = bv_to_int_generic_in::<BitSlice::<Lsb0, u8>>(&bits[0..2]);
  let val2 = bv_to_int_generic_in::<BitVec::<Lsb0, u8>>(&bits);
  println!("{} {}", val1, val2);
}

doesn't compile, and gives an error that the generic T doesn't have the Iterator trait implemented:不编译,并给出泛型T没有实现Iterator trait 的错误:

error[E0277]: `&T` is not an iterator
   --> src/main.rs:28:14
    |
28  |   for bit in bv {
    |              ^^ `&T` is not an iterator
    |
    = help: the trait `Iterator` is not implemented for `&T`
    = note: required because of the requirements on the impl of `IntoIterator` for `&T`
note: required by `into_iter`
   --> /Users/jlees/.rustup/toolchains/stable-x86_64-apple-darwin/lib/rustlib/src/rust/library/core/src/iter/traits/collect.rs:234:5
    |
234 |     fn into_iter(self) -> Self::IntoIter;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Trying 2) to make the return type generic:尝试 2) 使返回类型通用:

// Trying to template the output type
fn bv_to_int_generic_out<T>(bv: &BitVec::<Lsb0, u8>) -> T {
  let mut int: T = 0;
  for bit in bv {
    int = int << 1;
    if bit == true {
      int += 1;
    }
  }
  return int;
}

fn main() {
  let bits = bitvec![Lsb0, u8; 1,0,1,0];
  let val1: u32 = bv_to_int_generic_out::<u32>(&bits);
  let val2: u64 = bv_to_int_generic_out::<u64>(&bits);
  println!("{} {}", val1, val2);
}

also doesn't compile, and gives errors that T is not an {integer} :也不会编译,并给出T不是{integer}的错误:

error[E0308]: mismatched types
  --> src/main.rs:55:20
   |
54 | fn bv_to_int_generic_out<T>(bv: &BitVec::<Lsb0, u8>) -> T {
   |                          - this type parameter
55 |   let mut int: T = 0;
   |                -   ^ expected type parameter `T`, found integer
   |                |
   |                expected due to this
   |
   = note: expected type parameter `T`
                        found type `{integer}`

error[E0369]: no implementation for `T << {integer}`
  --> src/main.rs:57:15
   |
57 |     int = int << 1;
   |           --- ^^ - {integer}
   |           |
   |           T
   |
help: consider restricting type parameter `T`
   |
54 | fn bv_to_int_generic_out<T: std::ops::Shl<Output = {integer}>>(bv: &BitVec::<Lsb0, u8>) -> T {
   |                           +++++++++++++++++++++++++++++++++++

error[E0368]: binary assignment operation `+=` cannot be applied to type `T`
  --> src/main.rs:59:7
   |
59 |       int += 1;
   |       ---^^^^^
   |       |
   |       cannot use `+=` on type `T`
   |
help: consider restricting type parameter `T`
   |
54 | fn bv_to_int_generic_out<T: std::ops::AddAssign>(bv: &BitVec::<Lsb0, u8>) -> T {
   |                           +++++++++++++++++++++

See also this gist for the above code in one place: https://gist.github.com/johnlees/49e6a7bd85b3545bba20e8670180f24a有关上述代码,另请参阅此要点: https://gist.github.com/johnlees/49e6a7bd85b3545bba20e8670180f24a

I am new to rust, and I realise that I'm trying to write these like C++ templates which may well be the wrong approach.我是 rust 的新手,我意识到我正在尝试像 C++ 模板一样编写这些模板,这很可能是错误的方法。 Any advice on the correct rust approach for making either the input or output types generic would be appreciated!任何关于正确的 rust 方法的任何建议都将不胜感激!

You can create a simple macro to declare them:您可以创建一个简单的宏来声明它们:

use bitvec::prelude::*; // bitvec = "0.22.3"

macro_rules! bitvec_to {
    ($func_name:ident, $input_type:ty, $output_type:ty) => {
        fn $func_name(bv: &$input_type) ->  $output_type {
          let mut int = 0;
          for bit in bv {
            int = int << 1;
            if bit == true {
              int += 1;
            }
          }
          return int;
        }
    };
}

bitvec_to!(bslice_to_int, BitSlice::<Lsb0, u8>, u32);
bitvec_to!(bv_to_int, BitVec::<Lsb0, u8>, u64);

Playground 操场

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

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