use static dispatch

This commit is contained in:
Y. T. Chung
2015-12-12 15:05:44 +08:00
parent bf127215cf
commit cea1e2a486
2 changed files with 63 additions and 11 deletions

View File

@@ -24,6 +24,7 @@
use std::str::FromStr;
use std::fmt::{Debug, Display, self};
use rand::{self, Rng};
use std::convert::From;
use crypto::openssl;
use crypto::table;
@@ -527,23 +528,74 @@ impl Display for CipherType {
}
}
macro_rules! define_ciphers {
($($name:ident => $cipher:ty,)+) => {
pub enum CipherVariant {
$(
$name($cipher),
)+
}
impl CipherVariant {
pub fn new<C>(cipher: C) -> CipherVariant
where CipherVariant: From<C>
{
From::from(cipher)
}
}
impl Cipher for CipherVariant {
fn update(&mut self, data: &[u8], out: &mut Vec<u8>) -> CipherResult<()> {
match *self {
$(
CipherVariant::$name(ref mut cipher) => cipher.update(data, out),
)+
}
}
fn finalize(&mut self, out: &mut Vec<u8>) -> CipherResult<()> {
match *self {
$(
CipherVariant::$name(ref mut cipher) => cipher.finalize(out),
)+
}
}
}
$(
impl From<$cipher> for CipherVariant {
fn from(cipher: $cipher) -> CipherVariant {
CipherVariant::$name(cipher)
}
}
)+
}
}
define_ciphers! {
TableCipher => table::TableCipher,
SodiumCipher => sodium::SodiumCipher,
Rc4Md5Cipher => rc4_md5::Rc4Md5Cipher,
OpenSSLCipher => openssl::OpenSSLCipher,
}
/// Generate a specific Cipher with key and initialize vector
pub fn with_type(t: CipherType, key: &[u8], iv: &[u8], mode: CryptoMode) -> Box<Cipher + Send> {
pub fn with_type(t: CipherType, key: &[u8], iv: &[u8], mode: CryptoMode) -> CipherVariant {
match t {
CipherType::Table => box table::TableCipher::new(key, mode) as Box<Cipher + Send>,
CipherType::Table => CipherVariant::new(table::TableCipher::new(key, mode)),
#[cfg(feature = "cipher-chacha20")]
CipherType::ChaCha20 =>
box sodium::SodiumCipher::new(t, key, iv) as Box<Cipher + Send>,
CipherVariant::new(sodium::SodiumCipher::new(t, key, iv)),
#[cfg(feature = "cipher-salsa20")]
CipherType::Salsa20 =>
box sodium::SodiumCipher::new(t, key, iv) as Box<Cipher + Send>,
CipherVariant::new(sodium::SodiumCipher::new(t, key, iv)),
#[cfg(feature = "cipher-rc4")]
CipherType::Rc4Md5 =>
box rc4_md5::Rc4Md5Cipher::new(key, iv, mode) as Box<Cipher + Send>,
CipherVariant::new(rc4_md5::Rc4Md5Cipher::new(key, iv, mode)),
_ => box openssl::OpenSSLCipher::new(t, key, iv, mode) as Box<Cipher + Send>,
_ => CipherVariant::new(openssl::OpenSSLCipher::new(t, key, iv, mode)),
}
}

View File

@@ -22,12 +22,12 @@
use std::io::{self, Read, BufRead, Write};
use std::cmp;
use crypto::cipher::Cipher;
use crypto::cipher::{Cipher, CipherVariant};
pub struct DecryptedReader<R: Read> {
reader: R,
buffer: Vec<u8>,
cipher: Box<Cipher + Send>,
cipher: CipherVariant,
pos: usize,
sent_final: bool,
}
@@ -35,7 +35,7 @@ pub struct DecryptedReader<R: Read> {
const BUFFER_SIZE: usize = 2048;
impl<R: Read> DecryptedReader<R> {
pub fn new(r: R, cipher: Box<Cipher + Send>) -> DecryptedReader<R> {
pub fn new(r: R, cipher: CipherVariant) -> DecryptedReader<R> {
DecryptedReader {
reader: r,
buffer: Vec::new(),
@@ -121,12 +121,12 @@ impl<R: Read> Read for DecryptedReader<R> {
pub struct EncryptedWriter<W: Write> {
writer: W,
cipher: Box<Cipher + Send>,
cipher: CipherVariant,
buffer: Vec<u8>,
}
impl<W: Write> EncryptedWriter<W> {
pub fn new(w: W, cipher: Box<Cipher + Send>) -> EncryptedWriter<W> {
pub fn new(w: W, cipher: CipherVariant) -> EncryptedWriter<W> {
EncryptedWriter {
writer: w,
cipher: cipher,