【问题标题】:Rust different return types with same base structureRust 具有相同基本结构的不同返回类型
【发布时间】:2017-08-28 21:18:51
【问题描述】:

我想根据secure 变量返回不同的IMAP 连接,但imap::client::Client 是否使用SSL 会返回不同的类型。 Client中的所有功能都由impl<T: Read + Write> Client<T>实现。

是否有更好、更有效的解决方案?

use error::*;
use imap::client::Client;
use openssl::ssl::{SslConnectorBuilder, SslMethod, SslStream};
use std::net::TcpStream;

pub enum ConnectionResult {
    Normal(Client<TcpStream>),
    Secure(Client<SslStream<TcpStream>>),
}

/// Mail account
#[derive(Debug, Deserialize)]
pub struct Account {
    pub username: String,
    pub password: String,
    pub domain: String,
    pub port: u16,
    pub secure: bool,
}

impl Account {
    pub fn connect(&self) -> Result<ConnectionResult> {
        if self.secure {
            let ssl_connector = SslConnectorBuilder::new(SslMethod::tls())
                .chain_err(|| "fail with ssl")?
                .build();
            let mut imap_socket = Client::secure_connect(
                (self.domain.as_str(), self.port),
                &self.domain,
                ssl_connector,
            );
            imap_socket
                .login(&self.username, &self.password)
                .chain_err(|| "fail when login")?;
            Ok(ConnectionResult::Secure(imap_socket))
        } else {
            let mut imap_socket = Client::connect((self.domain.as_str(), self.port))?;
            imap_socket
                .login(&self.username, &self.password)
                .chain_err(|| "fail when login")?;
            Ok(ConnectionResult::Normal(imap_socket))
        }
}

我只想返回一个 Client 结构,而不是包含不同 Clients 的枚举:

pub fn connect<T: Read + Write>(&self) -> Result<Client<T>> {
    // But this won't work
}

【问题讨论】:

  • 我只想返回一个客户端结构,而不是具有不同客户端的枚举

标签: rust


【解决方案1】:

您的方法似乎不错。我的建议是使用composition:将您的enum 封装在struct 中,并使用match 在每种方法中做您想做的事情:

enum ConnectionResult { // not pub because intern implementation
    Normal(Client<TcpStream>),
    Secure(Client<SslStream<TcpStream>>),
}

pub struct MyClient {
    connection_result: ConnectionResult,
    // other fields
}

impl MyClient {
    pub fn do_something(&self) {
        match connection_result {
            Normal(client) => // do something with normal client
            Secure(client) => // do something with secure client
        }
    }
}

从用户的角度来看,这两个客户端没有区别。

如果您不想要这个解决方案,您可以使用每晚的-&gt; impl 功能:

#![feature(conservative_impl_trait)]

trait MyClient {
    // the methods you need
}

struct NormalClient {
    client: Client<TcpStream>,
    /*etc.*/
}
struct SecureClient {
    client: Client<SslStream<TcpStream>>,
    /*etc.*/
}

impl MyClient for NormalClient { /*etc.*/ }
impl MyClient for SecureClient { /*etc.*/ }

fn get_client() -> impl MyClient { /*etc.*/ }

【讨论】:

    猜你喜欢
    • 2018-01-18
    • 1970-01-01
    • 1970-01-01
    • 2019-12-18
    • 2021-10-16
    • 1970-01-01
    • 2022-11-08
    • 2021-12-18
    • 1970-01-01
    相关资源
    最近更新 更多