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: lib.rs
    path of file: ./repos/tiny/crates/libtiny_client/src
    
    the code of the file until where you have to start completion: #![allow(clippy::unneeded_field_pattern)]
#![allow(clippy::cognitive_complexity)]

mod pinger;
mod state;
mod stream;
mod utils;

use libtiny_common::{ChanName, ChanNameRef};
pub use libtiny_wire as wire;

use pinger::Pinger;
use state::State;
use stream::{Stream, StreamError};

use std::net::{SocketAddr, ToSocketAddrs};
use std::time::Duration;

use futures_util::future::FutureExt;
use tokio::io::{AsyncReadExt, AsyncWriteExt};
use tokio::sync::mpsc;
use tokio::{pin, select};
use tokio_stream::wrappers::ReceiverStream;
use tokio_stream::StreamExt;

#[macro_use]
extern crate log;

//
// Public API
//

/// `Client` tries to reconnect on error after this many seconds.
pub const RECONNECT_SECS: u64 = 30;

#[derive(Debug, Clone)]
pub struct ServerInfo {
    /// Server address
    pub addr: String,

    /// Server port
    pub port: u16,

    /// Use TLS?
    pub tls: bool,

    /// Server password.
    pub pass: Option<String>,

    pub realname: String,

    /// Nicks to select when logging in.
    pub nicks: Vec<String>,

    /// Channels to automatic
    
async fn wait_<S: StreamExt<Item = Cmd> + Unpin>(rcv_cmd: &mut S) -> TaskResult<()> {
    let delay = tokio::time::sleep(Duration::from_secs(RECONNECT_SECS)).fuse();
    pin!(delay);

    loop {
        select! {
            () = &mut delay => {
                return TaskResult::Done(());
            }
            cmd = rcv_cmd.next() => {
                // FIXME: This whole block is duplicated below, but it's hard to reuse because it
                // uses `continue` and `return`.
                match cmd {
                    None => {
                        // Channel closed, return from the main loop
                        return TaskResult::Return;
                    }
                    Some(Cmd::Msg(_)) => {
                        continue;
                    }
                    Some(Cmd::Reconnect(mb_port)) => {
                        return TaskResult::Reconnect(mb_port);
                    }
                    Some(Cmd::Quit(_)) => {
                        return TaskResult::Return;
                    }
                }
            }
        }
    }
}