basic functionality works

This commit is contained in:
cscherr 2025-04-16 15:10:58 +02:00
parent f8cf93fc92
commit 197ad9dabf
Signed by: cscherrNT
GPG key ID: 8E2B45BC51A27EA7
5 changed files with 221 additions and 0 deletions

1
.gitignore vendored Normal file
View file

@ -0,0 +1 @@
target

81
Cargo.lock generated Normal file
View file

@ -0,0 +1,81 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 4
[[package]]
name = "getopts"
version = "0.2.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "14dbbfd5c71d70241ecf9e6f13737f7b5ce823821063188d7e46c41d371eebd5"
dependencies = [
"unicode-width",
]
[[package]]
name = "proc-macro2"
version = "1.0.95"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d"
dependencies = [
"proc-macro2",
]
[[package]]
name = "syn"
version = "2.0.100"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b09a44accad81e1ba1cd74a32461ba89dee89095ba17b32f5d03683b1b1fc2a0"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "thiserror"
version = "2.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "2.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "timars"
version = "0.1.0"
dependencies = [
"getopts",
"thiserror",
]
[[package]]
name = "unicode-ident"
version = "1.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512"
[[package]]
name = "unicode-width"
version = "0.1.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af"

15
Cargo.toml Normal file
View file

@ -0,0 +1,15 @@
[package]
name = "timars"
version = "0.1.0"
edition = "2024"
publish = false
authors = ["Christoph J. Scherr <software@cscherr.de>"]
license = "MIT"
readme = "README.md"
homepage = "https://git.cscherr.de/PlexSheep/rs-base"
repository = "https://git.cscherr.de/PlexSheep/rs-base"
[dependencies]
getopts = "0.2.21"
thiserror = "2.0.12"

View file

@ -1,2 +1,5 @@
# timars # timars
Timars is two things at once: It lets you calculate time between two clock times,
and it lets you hide some secret beneath an intended binary exploitation.

121
src/main.rs Normal file
View file

@ -0,0 +1,121 @@
use std::fmt::Display;
use std::ops::Sub;
use std::str::FromStr;
use getopts::Options;
use thiserror::Error;
const FLAG: &str = "FlÂG{E1nb38V9a3V5e86HzlY27UFAErIP5mA34kES9fbu}";
fn options() -> Options {
let mut opts = Options::new();
opts.reqopt(
"f",
"from",
"calculate time starting from this time",
"HH:MM",
);
opts.reqopt("t", "to", "calculate time until this time", "HH:MM");
opts.optflag("h", "help", "print this help menu");
opts
}
struct Timestamp {
hour: i8,
minute: i8,
}
#[derive(Error, Debug)]
enum TimestampParseError {
#[error("Too many or too few separators ':'")]
BadAmountOfSeparators,
#[error("Time numbers t must fullfill 0 < t < 60 (was {0})")]
InvalidTimeNumber(i8),
#[error(transparent)]
ParseInt(#[from] std::num::ParseIntError),
}
impl Sub for Timestamp {
type Output = Self;
fn sub(self, rhs: Self) -> Self::Output {
if self.minute >= rhs.minute {
Timestamp {
hour: self.hour - rhs.hour,
minute: self.minute - rhs.minute,
}
} else {
Timestamp {
hour: self.hour - rhs.hour - 1,
minute: 60 + self.minute - rhs.minute,
}
}
}
}
impl Display for Timestamp {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{:02}:{:02}", self.hour, self.minute)
}
}
impl FromStr for Timestamp {
fn from_str(s: &str) -> Result<Self, Self::Err> {
let parts: Vec<&str> = s.split(":").collect();
if parts.len() != 2 {
return Err(TimestampParseError::BadAmountOfSeparators);
}
let hour: i8 = parts[0].parse()?;
let minute: i8 = parts[1].parse()?;
if hour > 59 {
return Err(TimestampParseError::InvalidTimeNumber(hour));
}
if minute > 59 {
return Err(TimestampParseError::InvalidTimeNumber(minute));
}
let t = Timestamp { hour, minute };
Ok(t)
}
type Err = TimestampParseError;
}
fn main() {
let args: Vec<String> = std::env::args().collect();
let program = args[0].clone();
let opts = options();
let matches = match opts.parse(&args[1..]) {
Ok(m) => m,
Err(f) => usage(&program, &opts),
};
let from_time: Timestamp = match matches.opt_str("from").expect("thats required").parse() {
Ok(t) => t,
Err(e) => {
eprintln!("{e}");
usage(&program, &opts)
}
};
let to_time: Timestamp = match matches.opt_str("to").expect("thats required").parse() {
Ok(t) => t,
Err(e) => {
eprintln!("{e}");
usage(&program, &opts)
}
};
println!("from\t\t: {from_time}");
println!("to\t\t: {to_time}");
println!("difference\t: {}", to_time - from_time)
}
fn usage(program: &str, opts: &Options) -> ! {
let brief = format!("Usage: {} FILE [options]", program);
print!("{}", opts.usage(&brief));
std::process::exit(1)
}