nlfmt-serve 0.5.3

quickly serve files from a directory in your local network
Documentation
use std::{
    net::{AddrParseError, IpAddr},
    path::Path,
    str::FromStr,
};

use clap::Parser;

use crate::auth::Auth;

#[derive(Parser, Debug)]
#[command(version, about, long_about = None)]
pub struct ServeArgs {
    #[arg(short, long, default_value_t = 3000)]
    pub port: u16,

    #[arg(
        short = 'i',
        long = "interface",
        value_parser(parse_interface),
        default_value_t = IpAddr::from_str("0.0.0.0").unwrap()
    )]
    pub interface: IpAddr,

    #[arg(short, long, default_value_t = false, help = "Show a connections QR code in the terminal")]
    pub qr: bool,

    #[arg(short = 'u', long, default_value_t = false, help = "Allow users to upload files to the served folder")]
    pub upload: bool,

    #[arg(short = 's', long, default_value_t = false, help = "Resolve symlinks instead of ignoring them (dangerous!)")]
    pub symlinks: bool,
    
    #[arg(short = 'o', long, default_value_t = false, help = "Allow users to overwrite files during upload")]
    pub overwrite: bool,
    #[arg(short = 'r', long, default_value_t = false, help = "Allow users to move & rename files/folders")]
    pub rename: bool,
    #[arg(short = 'd', long, default_value_t = false, help = "Allow users to delete files/folders")]
    pub delete: bool,
    #[arg(short = 'm', long, default_value_t = false, help = "Enables overwriting, renaming, moving and deleting")]
    pub modify: bool,


    #[arg(
        short,
        long,
        value_name = "USER:PASS",
        help = "Specify a username and password",
        value_parser(Auth::from)
    )]
    pub auth: Vec<Auth>,

    #[arg(
        long,
        help = "File with logins separated by newlines",
        value_parser(parse_auth_file)
    )]
    pub auth_file: Vec<Vec<Auth>>,
    
    #[arg(long, default_value_t = false, help = "Update serve")]
    pub update: bool,

    pub root_dir: Option<String>,
}

fn parse_interface(s: &str) -> Result<IpAddr, AddrParseError> {
    s.parse()
}

fn parse_auth_file(s: &str) -> Result<Vec<Auth>, anyhow::Error> {
    let path = Path::new(s);

    let contents = std::fs::read_to_string(path)?;
    let auths = contents
        .lines()
        .map(Auth::from)
        .collect::<Result<Vec<_>, _>>()?;

    Ok(auths)
}