#![allow(clippy::manual_range_contains)] #![warn(rust_2018_idioms)] #![forbid(elided_lifetimes_in_paths, unsafe_code)] mod iotro; mod render; mod time; use crate::{ render::Renderer, time::{parse_date, parse_time, Date, Time} }; use camino::Utf8PathBuf as PathBuf; use clap::Parser; use rational::Rational; use serde::{Deserialize, Serialize}; use serde_with::{serde_as, DisplayFromStr}; use std::{ collections::BTreeSet, fmt::Display, fs, io::{self, BufRead as _, Write}, sync::RwLock }; static MEM_LIMIT: RwLock = RwLock::new(String::new()); #[derive(Debug, Parser)] struct Args { #[clap(short = 'C', long, default_value = ".")] directory: PathBuf, #[clap(short = 'c', long, default_value = "23ws-malo")] course: String, #[clap(short, long, default_value = "8G")] mem_limit: String } macro_rules! resolutions { ($($res:ident: $width:literal x $height:literal at $bitrate:literal),+) => { #[allow(non_camel_case_types, clippy::upper_case_acronyms)] #[derive(Clone, Copy, Deserialize, Eq, Ord, PartialEq, PartialOrd, Serialize)] enum Resolution { $( #[doc = concat!(stringify!($width), "x", stringify!($height))] $res ),+ } const NUM_RESOLUTIONS: usize = { let mut num = 0; $(num += 1; stringify!($res);)+ num }; impl Resolution { fn values() -> [Self; NUM_RESOLUTIONS] { [$(Self::$res),+] } fn width(self) -> usize { match self { $(Self::$res => $width),+ } } fn height(self) -> usize { match self { $(Self::$res => $height),+ } } fn bitrate(self) -> &'static str { match self { $(Self::$res => $bitrate),+ } } } } } resolutions! { nHD: 640 x 360 at "500k", HD: 1280 x 720 at "1M", FullHD: 1920 x 1080 at "2M", WQHD: 2560 x 1440 at "3M", // TODO qsx muss mal sagen wieviel bitrate für 4k UHD: 3840 x 2160 at "4M" } #[derive(Deserialize, Serialize)] struct Project { lecture: ProjectLecture, source: ProjectSource, progress: ProjectProgress } #[serde_as] #[derive(Deserialize, Serialize)] struct ProjectLecture { course: String, #[serde_as(as = "DisplayFromStr")] date: Date } #[serde_as] #[derive(Deserialize, Serialize)] struct ProjectSource { files: Vec, #[serde_as(as = "Option")] start: Option