Compare commits
2 commits
ece742a1e3
...
89f5d26cb3
| Author | SHA1 | Date | |
|---|---|---|---|
| 89f5d26cb3 | |||
| 6e553cc185 |
6 changed files with 91 additions and 31 deletions
|
|
@ -1,2 +1,6 @@
|
|||
[build]
|
||||
target = "x86_64-unknown-linux-musl"
|
||||
|
||||
rustflags = [
|
||||
"-C", "target-feature=+avx2,+sse4.1,+ssse3,+aes",
|
||||
]
|
||||
37
Cargo.lock
generated
37
Cargo.lock
generated
|
|
@ -67,18 +67,47 @@ dependencies = [
|
|||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "arrayref"
|
||||
version = "0.3.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb"
|
||||
|
||||
[[package]]
|
||||
name = "arrayvec"
|
||||
version = "0.7.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50"
|
||||
|
||||
[[package]]
|
||||
name = "base64"
|
||||
version = "0.22.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
|
||||
|
||||
[[package]]
|
||||
name = "base64ct"
|
||||
version = "1.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "55248b47b0caf0546f7988906588779981c43bb1bc9d0c44087278f80cdb44ba"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "2.9.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967"
|
||||
|
||||
[[package]]
|
||||
name = "blake2b_simd"
|
||||
version = "1.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "06e903a20b159e944f91ec8499fe1e55651480c541ea0a584f5d967c49ad9d99"
|
||||
dependencies = [
|
||||
"arrayref",
|
||||
"arrayvec",
|
||||
"constant_time_eq",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bumpalo"
|
||||
version = "3.17.0"
|
||||
|
|
@ -171,6 +200,12 @@ dependencies = [
|
|||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "constant_time_eq"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7c74b8349d32d297c9134b8c88677813a227df8f779daa29bfc29c183fe3dca6"
|
||||
|
||||
[[package]]
|
||||
name = "cookie"
|
||||
version = "0.18.1"
|
||||
|
|
@ -846,6 +881,8 @@ checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
|
|||
name = "shrupl"
|
||||
version = "0.1.0-alpha"
|
||||
dependencies = [
|
||||
"base64ct",
|
||||
"blake2b_simd",
|
||||
"clap",
|
||||
"console",
|
||||
"ctrlc",
|
||||
|
|
|
|||
|
|
@ -5,6 +5,8 @@ edition = "2024"
|
|||
description = "ShrUpl is a tool to upload files to a Sharry Instance through a public Alias, leveraging the tus protocol"
|
||||
|
||||
[dependencies]
|
||||
base64ct = { version = "1.8.0", default-features = false, features = ["alloc"] }
|
||||
blake2b_simd = "1.0.3"
|
||||
clap = { version = "4.5.38", features = ["derive"] }
|
||||
console = { version = "0.15.11", default-features = false }
|
||||
ctrlc = { version = "3.4.7", features = ["termination"] }
|
||||
|
|
@ -20,5 +22,11 @@ thiserror = "2.0.12"
|
|||
ureq = { version = "3.0.11", features = ["json"] }
|
||||
|
||||
[profile.release]
|
||||
# Optimize for speed even more aggressively
|
||||
opt-level = "z"
|
||||
# better inlining
|
||||
codegen-units = 1
|
||||
# linker‐time optimization
|
||||
lto = true
|
||||
debug = false
|
||||
panic = "abort"
|
||||
|
|
|
|||
37
src/cli.rs
37
src/cli.rs
|
|
@ -1,11 +1,7 @@
|
|||
use std::{
|
||||
convert::Infallible,
|
||||
fmt,
|
||||
hash::{DefaultHasher, Hash, Hasher},
|
||||
io,
|
||||
time::Duration,
|
||||
};
|
||||
use std::{convert::Infallible, fmt, io, time::Duration};
|
||||
|
||||
use base64ct::{Base64UrlUnpadded, Encoding};
|
||||
use blake2b_simd::Params as Blake2b;
|
||||
use clap::{
|
||||
Parser,
|
||||
builder::{PossibleValuesParser, TypedValueParser},
|
||||
|
|
@ -18,7 +14,7 @@ use crate::{
|
|||
sharry::{NewShareRequest, Uri},
|
||||
};
|
||||
|
||||
#[derive(Parser, Hash)]
|
||||
#[derive(Parser)]
|
||||
#[command(version, about, long_about = None)]
|
||||
pub struct Cli {
|
||||
/// Timeout in seconds for HTTP actions (set 0 or invalid to disable)
|
||||
|
|
@ -100,6 +96,16 @@ fn parse_sharry_file(data: &str) -> io::Result<Checked> {
|
|||
Checked::new(data)
|
||||
}
|
||||
|
||||
fn sorted<T>(values: &[T]) -> Vec<&T>
|
||||
where
|
||||
T: Ord,
|
||||
{
|
||||
let mut refs: Vec<_> = values.iter().collect();
|
||||
refs.sort_unstable();
|
||||
|
||||
refs
|
||||
}
|
||||
|
||||
impl Cli {
|
||||
pub fn get_timeout(&self) -> Option<Duration> {
|
||||
(!self.timeout.is_zero()).then_some(self.timeout)
|
||||
|
|
@ -135,16 +141,15 @@ impl Cli {
|
|||
}
|
||||
|
||||
pub fn get_hash(&self) -> String {
|
||||
let file_refs = {
|
||||
let mut refs: Vec<_> = self.files.iter().collect();
|
||||
refs.sort_unstable();
|
||||
let mut hasher = Blake2b::new().hash_length(64).to_state();
|
||||
|
||||
refs
|
||||
};
|
||||
hasher.update(self.get_uri().as_ref());
|
||||
hasher.update(self.alias.as_bytes());
|
||||
|
||||
let mut hasher = DefaultHasher::new();
|
||||
(self.get_uri(), &self.alias, file_refs).hash(&mut hasher);
|
||||
for chk in sorted(&self.files) {
|
||||
hasher.update(chk.as_ref());
|
||||
}
|
||||
|
||||
format!("{:x}", hasher.finish())
|
||||
Base64UrlUnpadded::encode_string(hasher.finalize().as_bytes())
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,10 +11,10 @@ use super::{FileTrait, Uploading};
|
|||
|
||||
/// Description of an existing, regular file
|
||||
///
|
||||
/// - impl Debug, Clone, Hash for `clap` compatibility
|
||||
/// - impl Clone for `clap` compatibility
|
||||
/// - impl serde for appstate caching
|
||||
/// - impl Ord to handle multiple files given
|
||||
#[derive(Debug, Clone, Hash, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord)]
|
||||
/// - impl PartialEq..Ord to handle multiple files given
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord)]
|
||||
pub struct Checked {
|
||||
/// canonical path to a regular file
|
||||
pub(super) path: PathBuf,
|
||||
|
|
@ -22,6 +22,12 @@ pub struct Checked {
|
|||
pub(super) size: u64,
|
||||
}
|
||||
|
||||
impl AsRef<[u8]> for Checked {
|
||||
fn as_ref(&self) -> &[u8] {
|
||||
self.path.as_os_str().as_encoded_bytes()
|
||||
}
|
||||
}
|
||||
|
||||
impl Checked {
|
||||
/// create a new checked file from some path reference
|
||||
///
|
||||
|
|
|
|||
|
|
@ -3,28 +3,28 @@ use std::fmt;
|
|||
use log::trace;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Hash)]
|
||||
pub struct Uri {
|
||||
protocol: String,
|
||||
base_url: String,
|
||||
}
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub struct Uri(String);
|
||||
|
||||
impl fmt::Display for Uri {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{}://{}", self.protocol, self.base_url)
|
||||
f.write_str(&self.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<[u8]> for Uri {
|
||||
fn as_ref(&self) -> &[u8] {
|
||||
self.0.as_bytes()
|
||||
}
|
||||
}
|
||||
|
||||
impl Uri {
|
||||
pub fn new(protocol: impl Into<String>, base_url: impl Into<String>) -> Self {
|
||||
Self {
|
||||
protocol: protocol.into(),
|
||||
base_url: base_url.into(),
|
||||
}
|
||||
pub fn new(protocol: impl fmt::Display, base_url: impl fmt::Display) -> Self {
|
||||
Self(format!("{}://{}", protocol, base_url))
|
||||
}
|
||||
|
||||
fn endpoint(&self, path: fmt::Arguments) -> String {
|
||||
let uri = format!("{}://{}/api/v2/{path}", self.protocol, self.base_url);
|
||||
let uri = format!("{}/api/v2/{path}", self.0);
|
||||
trace!("endpoint: {uri:?}");
|
||||
uri
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue