clap parsers for ips & paths
This commit is contained in:
parent
63de6d49cc
commit
213dd3124f
@ -3,3 +3,5 @@ pub mod comms;
|
|||||||
pub mod connector;
|
pub mod connector;
|
||||||
pub mod crypto;
|
pub mod crypto;
|
||||||
pub mod listener;
|
pub mod listener;
|
||||||
|
pub mod parsers;
|
||||||
|
pub mod ui;
|
||||||
|
23
src/main.rs
23
src/main.rs
@ -1,5 +1,6 @@
|
|||||||
use clap::{Parser, Subcommand};
|
use clap::{Parser, Subcommand};
|
||||||
use std::error::Error;
|
use contego::parsers::{addr_parser, dirpath_parser, filepath_parser};
|
||||||
|
use std::{error::Error, net::SocketAddr, path::PathBuf};
|
||||||
|
|
||||||
#[derive(Debug, Parser)]
|
#[derive(Debug, Parser)]
|
||||||
#[command(about, version)]
|
#[command(about, version)]
|
||||||
@ -11,8 +12,6 @@ struct Cli {
|
|||||||
quiet: bool,
|
quiet: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: add validators for infile, outdir & address (IPv4/6)
|
|
||||||
|
|
||||||
#[derive(Debug, Subcommand)]
|
#[derive(Debug, Subcommand)]
|
||||||
enum Commands {
|
enum Commands {
|
||||||
/// Host fileserver instance by providing JSON file with paths or list of paths
|
/// Host fileserver instance by providing JSON file with paths or list of paths
|
||||||
@ -20,19 +19,21 @@ enum Commands {
|
|||||||
/// Use IPv6 instead of IPv4
|
/// Use IPv6 instead of IPv4
|
||||||
#[clap(short = '6', long, default_value_t = false)]
|
#[clap(short = '6', long, default_value_t = false)]
|
||||||
ipv6: bool,
|
ipv6: bool,
|
||||||
/// Path to the inputfile (JSON)
|
/// Path to the inputfile
|
||||||
infile: Option<String>,
|
#[clap(short = 'i', long, value_parser = filepath_parser)]
|
||||||
/// Paths to the files
|
infile: Option<PathBuf>,
|
||||||
#[clap(short = 'f', long)]
|
/// Paths to the files (comma separated)
|
||||||
files: Option<Vec<String>>,
|
#[clap(short = 'f', long, num_args = 1.., value_parser = filepath_parser)]
|
||||||
|
files: Option<Vec<PathBuf>>,
|
||||||
},
|
},
|
||||||
/// Connect to hosted server by providing address, output folder and access key
|
/// Connect to hosted server by providing address, output folder and access key
|
||||||
Connect {
|
Connect {
|
||||||
/// IP address of the server (IPv4 or IPv6)
|
/// IP address of the server (IPv4 or IPv6)
|
||||||
address: String,
|
#[clap(short = 'a', long, value_parser = addr_parser)]
|
||||||
|
address: SocketAddr,
|
||||||
/// Path to the output folder
|
/// Path to the output folder
|
||||||
#[clap(short = 'o', long)]
|
#[clap(short = 'o', long, value_parser = dirpath_parser)]
|
||||||
outdir: String,
|
outdir: PathBuf,
|
||||||
/// Access key for the fileserver
|
/// Access key for the fileserver
|
||||||
#[clap(short = 'k', long)]
|
#[clap(short = 'k', long)]
|
||||||
key: String,
|
key: String,
|
||||||
|
83
src/parsers.rs
Normal file
83
src/parsers.rs
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
use std::{
|
||||||
|
io::{Error, ErrorKind::NotFound},
|
||||||
|
net::{AddrParseError, SocketAddr},
|
||||||
|
path::PathBuf,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub fn addr_parser(addr: &str) -> Result<SocketAddr, AddrParseError> {
|
||||||
|
let addr = addr
|
||||||
|
.parse::<SocketAddr>()
|
||||||
|
.expect("Failed to parse IP address");
|
||||||
|
|
||||||
|
Ok(addr)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn filepath_parser(path: &str) -> Result<PathBuf, Error> {
|
||||||
|
let path = path.parse::<PathBuf>().expect("Failed to parse path");
|
||||||
|
|
||||||
|
if path.exists() && path.is_file() {
|
||||||
|
Ok(path)
|
||||||
|
} else {
|
||||||
|
Err(Error::new(NotFound, "File not found"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn dirpath_parser(path: &str) -> Result<PathBuf, Error> {
|
||||||
|
let path = path.parse::<PathBuf>().expect("Failed to parse path");
|
||||||
|
|
||||||
|
if path.exists() && path.is_dir() {
|
||||||
|
Ok(path)
|
||||||
|
} else {
|
||||||
|
Err(Error::new(NotFound, "Directory not found"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn valid_ip() {
|
||||||
|
use std::net::Ipv6Addr;
|
||||||
|
|
||||||
|
let ipv4 = "10.1.2.3:8888";
|
||||||
|
let ipv6 = "[2001:db8::1]:8888";
|
||||||
|
|
||||||
|
let parsed_ipv4 = addr_parser(ipv4).unwrap();
|
||||||
|
let parsed_ipv6 = addr_parser(ipv6).unwrap();
|
||||||
|
|
||||||
|
assert_eq!(parsed_ipv4, SocketAddr::from(([10, 1, 2, 3], 8888)));
|
||||||
|
assert_eq!(
|
||||||
|
parsed_ipv6,
|
||||||
|
SocketAddr::from((Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1), 8888))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[should_panic]
|
||||||
|
fn short_ip() {
|
||||||
|
let ip = "10.1.2:8888";
|
||||||
|
addr_parser(ip).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[should_panic]
|
||||||
|
fn long_ip() {
|
||||||
|
let ip = "[2001:0db8:ac10:fe01:0000:0000:0000:0000:0000]:8888";
|
||||||
|
addr_parser(ip).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[should_panic]
|
||||||
|
fn ipv6_no_brackets() {
|
||||||
|
let ip = "2001:db8::1:8888";
|
||||||
|
addr_parser(ip).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[should_panic]
|
||||||
|
fn ip_missing_port() {
|
||||||
|
let ip = "10.1.2.3";
|
||||||
|
addr_parser(ip).unwrap();
|
||||||
|
}
|
||||||
|
}
|
17
src/ui.rs
Normal file
17
src/ui.rs
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
/*
|
||||||
|
TODO:
|
||||||
|
|
||||||
|
- suspend everything except errors and critical exceptions that lead to panic or abort
|
||||||
|
|
||||||
|
server:
|
||||||
|
- ip & access key on display
|
||||||
|
- commands to copy ip/key to clipboard
|
||||||
|
- updating list/log of connecting/disconnecting clients (?)
|
||||||
|
|
||||||
|
client:
|
||||||
|
- connection ip on display
|
||||||
|
- comamnds to download one or more files
|
||||||
|
- updating list of available/downloading/downloaded files (?)
|
||||||
|
|
||||||
|
* (?): maybe requires a separate UI thread for updates
|
||||||
|
*/
|
Loading…
Reference in New Issue
Block a user