You are an expert in writing code in many different languages. Your goal is to perform code completion for the following code, keeping in mind the rest of the code and the file meta data.
    Metadata details:
    filename: config.rs
    path of file: ./repos/tunshell/tunshell-client/src
    
    the code of the file until where you have to start completion: use anyhow::Error;
use std::{convert::TryFrom, env, time::Duration};

const DEFAULT_SERVER_CONNECT_TIMEOUT: u64 = 10000; // ms
const DEFAULT_DIRECT_CONNECT_TIMEOUT: u64 = 3000; // ms

pub struct Config {
    mode: ClientMode,
    session_key: String,
    encryption_key: String,
    relay_host: String,
    relay_tls_port: u16,
    relay_ws_port: u16,
    server_connection_timeout: Duration,
    direct_connection_timeout: Duration,
    echo_stdout: bool,
    enable_direct_connection: bool,
    dangerous_disable_relay_server_verification: bool,
}

#[derive(PartialEq, Copy, Clone, Debug)]
pub enum ClientMode {
    Local,
    Target,
}

impl Config {
    pub fn new_from_env() -> Self {
        let mut args = env::args().into_iter();

        args.next().expect("first argument must be set");

        let mode =
            ClientMode::try_from(args.next().expect("mode arg (2) must be set").as_str()).unwrap();
        let session_key = args.next().expect("session key arg (3) must be set");
        let encryption_key = args.next().expect("encryption key arg (4) must be set");
        let relay_host = args.next().unwrap_or("relay.tunshell.com".to_owned());

    
    pub fn new_from_env() -> Self {
        let mut args = env::args().into_iter();

        args.next().expect("first argument must be set");

        let mode =
            ClientMode::try_from(args.next().expect("mode arg (2) must be set").as_str()).unwrap();
        let session_key = args.next().expect("session key arg (3) must be set");
        let encryption_key = args.next().expect("encryption key arg (4) must be set");
        let relay_host = args.next().unwrap_or("relay.tunshell.com".to_owned());
        let relay_tls_port = args
            .next()
            .unwrap_or("5000".to_owned())
            .parse::<u16>()
            .expect("could not parse arg (6) as TLS port");
        let relay_ws_port = args
            .next()
            .unwrap_or("443".to_owned())
            .parse::<u16>()
            .expect("could not parse arg (7) as WebSocket port");
        let mut echo_stdout = false;

        // Parse optional args
        while let Some(arg) = args.next() {
            match arg.as_str() {
                "--echo" => echo_stdout = true,
                arg @ _ => panic!("Unknown argument: {}", arg),
            }
        }

        if session_key.len() < 10 {
            panic!("session key is too short")
        }

        if encryption_key.len() < 10 {
            panic!("encryption key is too short")
        }

        Self {
            mode,
            session_key,
            relay_host,
            relay_tls_port,
            relay_ws_port,
            encryption_key,
            server_connection_timeout: Duration::from_millis(DEFAULT_SERVER_CONNECT_TIMEOUT),
            direct_connection_timeout: Duration::from_millis(DEFAULT_DIRECT_CONNECT_TIMEOUT),
            echo_stdout,
            enable_direct_connection: true,
            dangerous_disable_relay_server_verification: false,
        }
    }