2015-02-09 77 views
1

有什麼辦法,使此代碼的工作,而無需使用Box ING:我是否需要在此框?

fn some_func(my_type: MyType, some_str: &str) -> bool { 
    let mut hmac = match my_type { 
    MyType::MyType1 => create_hmac(Sha256::new(), some_str), 
    MyType::MyType2 => create_hmac(Sha384::new(), some_str), 
    MyType::MyType3 => create_hmac(Sha512::new(), some_str), 
    _ => panic!() 
    }; 

    //some calculations goes HERE, NOT in create_hmac function... 
    hmac.input("fdsfdsfdsfd".to_string().as_bytes()); 

    //something else.... 
    true 
} 

fn create_hmac<D: Digest>(digest: D, some_str: &str) -> Hmac<D> { 
    Hmac::new(digest, some_str.to_string().as_bytes()) 
} 

它使用這個庫https://github.com/DaGenix/rust-crypto

+3

我一定是盲目的,因爲我沒有看到任何'Box'有 – 2015-02-09 06:36:56

+2

請創建一個最小的編譯例子 – 2015-02-09 07:44:23

+0

@JorgeIsraelPeña,沒有盒子在那裏。但Box可以用來使它工作。但我不想用它。 – 2015-02-09 08:00:19

回答

3

你需要或者盒或使用引用,作爲「特質對象」可以只在指針後面工作。

下面是一個非常簡化的代碼版本。您必須實現相同的特質三種不同的結構(摘要)

struct Sha256; 
struct Sha384; 
struct Sha512; 

trait Digest {} 
impl Digest for Sha256 {} 
impl Digest for Sha384 {} 
impl Digest for Sha512 {} 

struct HMac<D: Digest> { d: D } 

fn main() { 
    let a = 1; 

    // what you're trying to do 
    // (does not work, Sha256, Sha384 and Sha512 are different types) 
    //let _ = match a { 
    // 1 => Sha256, 
    // 2 => Sha384, 
    // 3 => Sha512, 
    // _ => unreachable!() 
    //}; 
} 

注意的是,在現實情況下,不僅所有ShaXXX類型是類型系統不同,它們具有不同的內存佈局以及(比較Engine256State例如Engine512State),所以這排除了不安全的技巧transmute

所以,說,你可以用盒子或引用(但你必須在比賽前預先創建一個具體的例子,如果你想使用的引用):

fn main() { 
    let a = 1; 

    let _ : Box<Digest> = match a { 
     1 => Box::new(Sha256), 
     2 => Box::new(Sha384), 
     3 => Box::new(Sha512), 
     _ => unreachable!() 
    }; 

    // to use references we need a pre-existing instance of all ShaXXX 
    let (sha256, sha384, sha512) = (Sha256, Sha384, Sha512); 

    let _ : &Digest = match a { 
     1 => &sha256, //... otherwise the reference wouldn't outlive the match 
     2 => &sha384, 
     3 => &sha512, 
     _ => unreachable!() 
    }; 
} 

。請注意,Box做相當於大多數垃圾收集語言在您想通過其界面使用對象時爲您提供的內容。有些內存是爲具體對象動態分配的,但只能真正允許傳遞一個指向內存的指針。

在你的情況(但我沒有測試過下面的代碼),你應該能夠做到:

//HMac implements a Mac trait, so we can return a Box<Mac> 
// (I'm assuming you only want to use HMac through its Mac trait) 
fn create_hmac<'a, D: Digest>(digest: D, some_str: &'a str) -> Box<Mac + 'a> { 
    Box::new(Hmac::new(digest, some_str.to_string().as_bytes())) 
} 

,並用它作爲:

let mut hmac: Box<Mac> = match my_type { 
    MyType::MyType1 => create_hmac(Sha256::new(), some_str), 
    MyType::MyType2 => create_hmac(Sha384::new(), some_str), 
    MyType::MyType3 => create_hmac(Sha512::new(), some_str), 
    _ => unreachable!() 
    }; 
+0

根據您的解決方案,我將如何創建Hmac'Hmac :: new(???,some_str.to_string()。as_bytes())'? – 2015-02-09 11:38:16

+0

什麼是'a',爲什麼它等於1? – 2015-02-09 11:41:09

+0

@AlexanderSupertramp'a'只代表你的'MyType'枚舉,以提供一個可編輯的例子。 – 2015-02-09 11:44:16

3

一次加法和一次澄清保羅的好回答。首先,你可以讓你的枚舉包含合適的Sha* struct,然後通過適當的委託來實現Digest。這可能沒有什麼意義在所有情況下,但如果概念那就是你在做什麼,這可能是有意義的:

struct Sha256; 
struct Sha384; 
struct Sha512; 

trait Digest { fn digest(&self); } 
impl Digest for Sha256 { fn digest(&self) {println!("256")} } 
impl Digest for Sha384 { fn digest(&self) {println!("384")} } 
impl Digest for Sha512 { fn digest(&self) {println!("512")} } 

enum MyType { 
    One(Sha256), 
    Two(Sha384), 
    Three(Sha512), 
} 

impl Digest for MyType { 
    fn digest(&self) { 
     use MyType::*; 

     match *self { 
      One(ref sha) => sha.digest(), 
      Two(ref sha) => sha.digest(), 
      Three(ref sha) => sha.digest(), 
     } 
    } 
} 

fn main() { 
    let a = MyType::Two(Sha384); 
    a.digest() 
} 

而且,你不必實際實例的類型所有如果你想使用參考資料,你只需要確保你使用的是可用的。你也必須有地方參考可以住超過match表達:

#![feature(std_misc)] 
#![feature(io)] 

use std::time::duration::Duration; 
use std::old_io::timer::sleep; 

struct Sha256(u8); 
struct Sha384(u8); 
struct Sha512(u8); 

impl Sha256 { fn new() -> Sha256 { sleep(Duration::seconds(1)); Sha256(1) }} 
impl Sha384 { fn new() -> Sha384 { sleep(Duration::seconds(2)); Sha384(2) }} 
impl Sha512 { fn new() -> Sha512 { sleep(Duration::seconds(3)); Sha512(3) }} 

trait Digest {} 
impl Digest for Sha256 {} 
impl Digest for Sha384 {} 
impl Digest for Sha512 {} 

fn main() { 
    let a = 1; 

    let sha256: Sha256; 
    let sha384: Sha384; 
    let sha512: Sha512; 

    let _ : &Digest = match a { 
     1 => { 
      sha256 = Sha256::new(); 
      &sha256 
     }, 
     2 => { 
      sha384 = Sha384::new(); 
      &sha384 
     }, 
     3 => { 
      sha512 = Sha512::new(); 
      &sha512 
     }, 
     _ => unreachable!() 
    }; 
} 
+0

'let mut hmac = Hmac :: new(* digest,「fdsfds」.to_string()。as_bytes());'===> 1) 2)'error:type crypto :: hmac :: Hmac 不會實現任何類型的密碼。方法在名爲input的作用域中 – 2015-02-10 14:07:17

相關問題