nfs3_client 0.8.0

Provides an implementation of NFS3 client
Documentation
use std::env;

use nfs3_client::error::{Error, PortmapError};
use nfs3_client::nfs3_types::mount::{PROGRAM as MOUNT_PROGRAM, VERSION as MOUNT_VERSION};
use nfs3_client::nfs3_types::nfs3::{PROGRAM as NFS3_PROGRAM, VERSION as NFS3_VERSION};
use nfs3_client::nfs3_types::portmap::PMAP_PORT;
use nfs3_client::tokio::TokioIo;
use tokio::net::TcpStream;

#[tokio::main(flavor = "current_thread")]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let args = env::args().collect::<Vec<_>>();
    let ip = args.get(1).map_or("127.0.0.1", |ip| ip.as_str());
    let port = match args.get(2) {
        Some(port) => port.parse::<u16>()?,
        None => PMAP_PORT,
    };

    let stream = TcpStream::connect(format!("{ip}:{port}")).await?;
    println!("Connected to portmapper on {ip}:{port}");
    let rpc = TokioIo::new(stream);
    let mut portmapper = nfs3_client::PortmapperClient::new(rpc);

    portmapper.null().await?;

    let result = portmapper.getport(MOUNT_PROGRAM, MOUNT_VERSION).await;
    match result {
        Ok(port) => println!("Resolved MOUNT3 port: {port}"),
        Err(Error::Portmap(PortmapError::ProgramUnavailable)) => {
            eprintln!("MOUNT3 program is unavailable");
        }
        Err(e) => eprintln!("Failed to resolve MOUNT3 port: {e}"),
    }

    let result = portmapper.getport(NFS3_PROGRAM, NFS3_VERSION).await;
    match result {
        Ok(port) => println!("Resolved NFSv3 port: {port}"),
        Err(Error::Portmap(PortmapError::ProgramUnavailable)) => {
            eprintln!("NFSv3 program is unavailable");
        }
        Err(e) => eprintln!("Failed to resolve NFSv3 port: {e}"),
    }

    let dump = portmapper.dump().await?;
    println!("Portmap dump:");
    println!("Program | Version |  Port");
    for mapping in dump {
        println!(
            "{:>7}   {:>7}   {:>5}",
            mapping.prog, mapping.vers, mapping.port
        );
    }

    Ok(())
}