use tokio::process::Command;
use super::code::Code;
use crate::{CrocChild, Result};
pub struct CrocSend<F>
where
F: AsRef<str>,
{
inner: Command,
files: Vec<F>,
zip: bool,
code: Code,
hash: HashKind,
local: bool,
multi: bool,
ignore_git: bool,
port: u16,
transfers: u8,
excluded_files: Vec<F>,
}
#[derive(Debug, Default)]
pub enum HashKind {
#[default]
Xxhash,
Imohash,
Md5,
}
impl<F> CrocSend<F>
where
F: AsRef<str>,
{
pub(crate) fn new(mut inner: Command) -> Self {
inner.arg("send");
Self {
inner,
zip: false,
code: Code::default(),
hash: HashKind::default(),
local: true,
multi: true,
ignore_git: false,
port: 9009,
transfers: 4,
files: Vec::new(),
excluded_files: Vec::new(),
}
}
pub fn zip(mut self, zip: bool) -> Self {
self.zip = zip;
self
}
pub fn code<S: ToString>(mut self, code: S) -> Self {
self.code = code.into();
self
}
pub fn hash(mut self, kind: HashKind) -> Self {
self.hash = kind;
self
}
pub fn local(mut self, local: bool) -> Self {
self.local = local;
self
}
pub fn multiplexing(mut self, multiplexing: bool) -> Self {
self.multi = multiplexing;
self
}
pub fn ignore_git(mut self, ignore_git: bool) -> Self {
self.ignore_git = ignore_git;
self
}
pub fn port(mut self, port: u16) -> Self {
self.port = port;
self
}
pub fn transfers(mut self, transfers: u8) -> Self {
self.transfers = transfers;
self
}
pub fn exclude(mut self, file: F) -> Self {
self.excluded_files.push(file);
self
}
pub fn exclude_many<I>(mut self, files: I) -> Self
where
I: IntoIterator<Item = F>,
{
self.excluded_files.extend(files);
self
}
pub fn file(mut self, file: F) -> Self {
self.files.push(file);
self
}
pub fn files<I>(mut self, files: I) -> Self
where
I: IntoIterator<Item = F>,
{
self.files.extend(files);
self
}
pub fn spawn(mut self) -> Result<CrocChild> {
self.parse_options();
for file in &self.files {
self.inner.arg(file.as_ref());
}
self.inner.spawn().map(CrocChild::new).map_err(Into::into)
}
fn parse_options(&mut self) {
self.inner.arg(format!("--hash={}", self.hash));
self.inner.arg(format!("--transfers={}", self.transfers));
self.inner.arg(format!("--port={}", self.port));
if self.zip {
self.inner.arg("--zip");
}
if !self.local {
self.inner.arg("--no-local");
}
if !self.multi {
self.inner.arg("--no-multi");
}
if self.ignore_git {
self.inner.arg("--git");
}
if let Code::Custom(ref code) = self.code {
#[cfg(target_os = "windows")]
self.inner.arg(format!("--code={}", code));
#[cfg(not(target_os = "windows"))]
self.inner.env("CROC_SECRET", code);
}
for file in &self.excluded_files {
self.inner.arg(format!("--exclude={}", file.as_ref()));
}
}
}
impl std::fmt::Display for HashKind {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
HashKind::Xxhash => write!(f, "xxhash"),
HashKind::Imohash => write!(f, "imohash"),
HashKind::Md5 => write!(f, "md5"),
}
}
}
impl<F: AsRef<str>> std::fmt::Debug for CrocSend<F> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
self.inner.fmt(f)
}
}