diff --git a/Cargo.lock b/Cargo.lock index a1073c61..6c6a9450 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -17,15 +17,6 @@ dependencies = [ "memchr", ] -[[package]] -name = "android_system_properties" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" -dependencies = [ - "libc", -] - [[package]] name = "ash" version = "0.37.3+1.3.251" @@ -98,19 +89,6 @@ version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c00d31b1d19317b4777ec879192d3745bd97d05262b4b19cb1dda284b9d22f19" -[[package]] -name = "chrono" -version = "0.4.42" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "145052bdd345b87320e369255277e3fb5152762ad123a901ef5c262dd38fe8d2" -dependencies = [ - "iana-time-zone", - "js-sys", - "num-traits", - "wasm-bindgen", - "windows-link", -] - [[package]] name = "clap" version = "2.34.0" @@ -131,12 +109,6 @@ dependencies = [ "cc", ] -[[package]] -name = "core-foundation-sys" -version = "0.8.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" - [[package]] name = "crc32fast" version = "1.5.0" @@ -274,30 +246,6 @@ dependencies = [ "libc", ] -[[package]] -name = "iana-time-zone" -version = "0.1.64" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33e57f83510bb73707521ebaffa789ec8caf86f9657cad665b092b581d40e9fb" -dependencies = [ - "android_system_properties", - "core-foundation-sys", - "iana-time-zone-haiku", - "js-sys", - "log", - "wasm-bindgen", - "windows-core", -] - -[[package]] -name = "iana-time-zone-haiku" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" -dependencies = [ - "cc", -] - [[package]] name = "imgui" version = "0.11.0" @@ -614,7 +562,6 @@ name = "ris_core" version = "0.1.0" dependencies = [ "ash", - "chrono", "imgui", "ris_asset", "ris_asset_data", @@ -640,7 +587,6 @@ name = "ris_data" version = "0.1.0" dependencies = [ "ash", - "chrono", "imgui", "ris_asset_data", "ris_async", @@ -659,7 +605,6 @@ dependencies = [ name = "ris_debug" version = "0.1.0" dependencies = [ - "chrono", "ris_error", "ris_log", "ris_math", @@ -672,7 +617,6 @@ version = "0.1.0-dev" dependencies = [ "ash", "cfg-if", - "chrono", "criterion", "imgui", "libc", @@ -703,7 +647,6 @@ dependencies = [ name = "ris_error" version = "0.1.0" dependencies = [ - "chrono", "ris_log", "sdl2", ] @@ -760,7 +703,6 @@ dependencies = [ name = "ris_io" version = "0.1.0" dependencies = [ - "chrono", "ris_error", "ris_log", "ris_math", @@ -770,7 +712,6 @@ dependencies = [ name = "ris_log" version = "0.1.0" dependencies = [ - "chrono", "sdl2", ] @@ -1116,65 +1057,12 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" -[[package]] -name = "windows-core" -version = "0.62.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6844ee5416b285084d3d3fffd743b925a6c9385455f64f6d4fa3031c4c2749a9" -dependencies = [ - "windows-implement", - "windows-interface", - "windows-link", - "windows-result", - "windows-strings", -] - -[[package]] -name = "windows-implement" -version = "0.60.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edb307e42a74fb6de9bf3a02d9712678b22399c87e6fa869d6dfcd8c1b7754e0" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "windows-interface" -version = "0.59.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0abd1ddbc6964ac14db11c7213d6532ef34bd9aa042c2e5935f59d7908b46a5" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "windows-link" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "45e46c0661abb7180e7b9c281db115305d49ca1709ab8242adf09666d2173c65" -[[package]] -name = "windows-result" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7084dcc306f89883455a206237404d3eaf961e5bd7e0f312f7c91f57eb44167f" -dependencies = [ - "windows-link", -] - -[[package]] -name = "windows-strings" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7218c655a553b0bed4426cf54b20d7ba363ef543b52d515b3e48d7fd55318dda" -dependencies = [ - "windows-link", -] - [[package]] name = "windows-sys" version = "0.61.1" diff --git a/Cargo.toml b/Cargo.toml index 33a9f552..f77ca8ec 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -59,7 +59,6 @@ ris_gpu_renderers = { path = "crates/ris_gpu_renderers" } # external ash = "0.37.3" cfg-if = "1" -chrono = "0.4" imgui = { version = "0.11.0", features = ["docking"] } libc = "^0.2.30" # required for linux miniz_oxide = "=0.8.2" diff --git a/assets/in_use/scenes/new(1).ris_scene b/assets/in_use/scenes/new(1).ris_scene index 3038bf40..9cea7b47 100644 Binary files a/assets/in_use/scenes/new(1).ris_scene and b/assets/in_use/scenes/new(1).ris_scene differ diff --git a/crates/ris_asset/src/asset_importer.rs b/crates/ris_asset/src/asset_importer.rs index e9438252..254d9074 100644 --- a/crates/ris_asset/src/asset_importer.rs +++ b/crates/ris_asset/src/asset_importer.rs @@ -114,7 +114,7 @@ pub fn import_all( let mut target_path = PathBuf::new(); target_path.push(target_directory.clone()); target_path.push(&target_path_part); - let target_path = PathBuf::from(target_path.parent().unwrap()); + let target_path = PathBuf::from(target_path.parent().into_ris_error()?); ris_log::debug!( "import \"{}\" to \"{}\"", diff --git a/crates/ris_asset/src/codecs/json.rs b/crates/ris_asset/src/codecs/json.rs index 13174d07..7d95e1d7 100644 --- a/crates/ris_asset/src/codecs/json.rs +++ b/crates/ris_asset/src/codecs/json.rs @@ -200,13 +200,15 @@ impl TryFrom<&JsonValue> for i32 { type Error = JsonError; fn try_from(value: &JsonValue) -> Result { - match value { - JsonValue::Number(JsonNumber { inner }) => { - // safety: construction of invalid number should be impossible - Ok(inner.parse().unwrap()) - } - _ => Err(JsonError::InvalidCast), - } + let JsonValue::Number(JsonNumber { inner }) = value else { + return Err(JsonError::InvalidCast); + }; + + let Ok(number) = inner.parse() else { + return Err(JsonError::InvalidCast); + }; + + Ok(number) } } @@ -214,13 +216,15 @@ impl TryFrom<&JsonValue> for usize { type Error = JsonError; fn try_from(value: &JsonValue) -> Result { - match value { - JsonValue::Number(JsonNumber { inner }) => { - // safety: construction of invalid number should be impossible - Ok(inner.parse().unwrap()) - } - _ => Err(JsonError::InvalidCast), - } + let JsonValue::Number(JsonNumber { inner }) = value else { + return Err(JsonError::InvalidCast); + }; + + let Ok(number) = inner.parse() else { + return Err(JsonError::InvalidCast); + }; + + Ok(number) } } @@ -228,13 +232,15 @@ impl TryFrom<&JsonValue> for isize { type Error = JsonError; fn try_from(value: &JsonValue) -> Result { - match value { - JsonValue::Number(JsonNumber { inner }) => { - // safety: construction of invalid number should be impossible - Ok(inner.parse().unwrap()) - } - _ => Err(JsonError::InvalidCast), - } + let JsonValue::Number(JsonNumber { inner }) = value else { + return Err(JsonError::InvalidCast); + }; + + let Ok(number) = inner.parse() else { + return Err(JsonError::InvalidCast); + }; + + Ok(number) } } @@ -242,13 +248,15 @@ impl TryFrom<&JsonValue> for f32 { type Error = JsonError; fn try_from(value: &JsonValue) -> Result { - match value { - JsonValue::Number(JsonNumber { inner }) => { - // safety: construction of number that cannot be parsed should be impossible - Ok(inner.parse().unwrap()) - } - _ => Err(JsonError::InvalidCast), - } + let JsonValue::Number(JsonNumber { inner }) = value else { + return Err(JsonError::InvalidCast); + }; + + let Ok(number) = inner.parse() else { + return Err(JsonError::InvalidCast); + }; + + Ok(number) } } @@ -463,8 +471,14 @@ impl JsonValue { return Err(JsonError::SyntaxError); } - let first = first_token.chars().next().unwrap(); - let last = last_token.chars().next().unwrap(); + // these two should never be None, because of the asserts above. but we do error handling + // anyway, just in case + let Some(first) = first_token.chars().next() else { + return Err(JsonError::SyntaxError); + }; + let Some(last) = last_token.chars().next() else { + return Err(JsonError::SyntaxError); + }; let is_object = first == BEGIN_OBJECT && last == END_OBJECT; let is_array = first == BEGIN_ARRAY && last == END_ARRAY; @@ -483,18 +497,19 @@ impl JsonValue { for token in &tokens[start..end] { match token.len() { 0 => return Err(JsonError::SyntaxError), - 1 => match token.chars().next().unwrap() { - BEGIN_OBJECT => object_generation += 1, - BEGIN_ARRAY => array_generation += 1, - END_OBJECT => object_generation -= 1, - END_ARRAY => array_generation -= 1, - VALUE_SEPARATOR => { + 1 => match token.chars().next() { + Some(BEGIN_OBJECT) => object_generation += 1, + Some(BEGIN_ARRAY) => array_generation += 1, + Some(END_OBJECT) => object_generation -= 1, + Some(END_ARRAY) => array_generation -= 1, + Some(VALUE_SEPARATOR) => { if object_generation == 0 && array_generation == 0 { elements.push(Vec::new()); continue; } } - _ => {} + Some(_) => {} + None => return Err(JsonError::SyntaxError), }, _ => {} } @@ -638,7 +653,10 @@ impl JsonMember { return Err(JsonError::SyntaxError); } - let separator = separator_token.chars().next().unwrap(); + let Some(separator) = separator_token.chars().next() else { + return Err(JsonError::SyntaxError); + }; + if separator != NAME_SEPARATOR { return Err(JsonError::SyntaxError); } diff --git a/crates/ris_asset/src/lookup/ris_mesh_lookup.rs b/crates/ris_asset/src/lookup/ris_mesh_lookup.rs index fa796a04..c259eac4 100644 --- a/crates/ris_asset/src/lookup/ris_mesh_lookup.rs +++ b/crates/ris_asset/src/lookup/ris_mesh_lookup.rs @@ -75,7 +75,10 @@ impl MeshLookup { value: None, }; self.entries.push(entry); - let entry = self.entries.last_mut().unwrap(); + let entry = ris_error::unwrap!( + self.entries.last_mut().into_ris_error(), + "we just added the entry, thus this should never be None", + ); entry } } diff --git a/crates/ris_core/Cargo.toml b/crates/ris_core/Cargo.toml index cff1e650..8ff54b6c 100644 --- a/crates/ris_core/Cargo.toml +++ b/crates/ris_core/Cargo.toml @@ -7,7 +7,6 @@ edition = "2021" [dependencies] ash = "0.37.3" -chrono = "0.4" imgui = "0.11.0" sdl2 = "0.38.0" sdl2-sys = "0.38.0" diff --git a/crates/ris_core/src/log_appenders/console_appender.rs b/crates/ris_core/src/log_appenders/console_appender.rs index f2ca68aa..12b6bc05 100644 --- a/crates/ris_core/src/log_appenders/console_appender.rs +++ b/crates/ris_core/src/log_appenders/console_appender.rs @@ -1,3 +1,4 @@ +use ris_log::constructed_log_message::ConstructedLogFormatArgs; use ris_log::log::IAppender; use ris_log::log_message::LogMessage; @@ -5,6 +6,14 @@ pub struct ConsoleAppender; impl IAppender for ConsoleAppender { fn print(&mut self, message: &LogMessage) { - eprintln!("\n{}", message.fmt(true)); + let args = ConstructedLogFormatArgs { + ansi_support: true, + show_timestamp: false, + show_priority: true, + show_priority_padding: true, + show_foot: false, + }; + + eprintln!("{}", message.fmt(args)); } } diff --git a/crates/ris_core/src/log_appenders/file_appender.rs b/crates/ris_core/src/log_appenders/file_appender.rs index 079eceeb..77e1c145 100644 --- a/crates/ris_core/src/log_appenders/file_appender.rs +++ b/crates/ris_core/src/log_appenders/file_appender.rs @@ -5,6 +5,7 @@ use sdl2::messagebox::MessageBoxFlag; use ris_error::RisResult; use ris_io::fallback_file::FallbackFileAppend; +use ris_log::constructed_log_message::ConstructedLogFormatArgs; use ris_log::log::IAppender; use ris_log::log_message::LogMessage; @@ -25,10 +26,17 @@ impl FileAppender { impl IAppender for FileAppender { fn print(&mut self, message: &LogMessage) { - let to_log = message.fmt(false); + let args = ConstructedLogFormatArgs { + ansi_support: false, + show_timestamp: false, + show_priority: true, + show_priority_padding: true, + show_foot: false, + }; + let to_log = message.fmt(args); let file = self.fallback_file.current(); - let result = writeln!(file, "\n{}", to_log); + let result = writeln!(file, "{}", to_log); if result.is_err() { let error_message = format!("failed to log the following message: {}", to_log); diff --git a/crates/ris_core/src/ui_helper/modules/log.rs b/crates/ris_core/src/ui_helper/modules/log.rs index a40ebc85..a3990d8b 100644 --- a/crates/ris_core/src/ui_helper/modules/log.rs +++ b/crates/ris_core/src/ui_helper/modules/log.rs @@ -2,6 +2,7 @@ use std::ffi::CString; use ris_error::Extensions; use ris_error::RisResult; +use ris_log::constructed_log_message::ConstructedLogFormatArgs; use ris_log::log_level::LogLevel; use ris_log::log_message::LogMessage; @@ -106,7 +107,14 @@ impl LogModule { } }; - let formatted_message = message.fmt(false); + let args = ConstructedLogFormatArgs { + ansi_support: false, + show_timestamp: true, + show_priority: true, + show_priority_padding: false, + show_foot: true, + }; + let formatted_message = message.fmt(args); if !formatted_message .to_lowercase() .contains(&self.filter.to_lowercase()) diff --git a/crates/ris_core/src/ui_helper/modules/metrics.rs b/crates/ris_core/src/ui_helper/modules/metrics.rs index 861ce6dc..44b820ab 100644 --- a/crates/ris_core/src/ui_helper/modules/metrics.rs +++ b/crates/ris_core/src/ui_helper/modules/metrics.rs @@ -4,8 +4,7 @@ use std::time::Instant; use ris_data::gameloop::frame::Frame; use ris_debug::profiler::ProfilerState; -use ris_error::RisResult; -use ris_io::path::SanitizeInfo; +use ris_error::prelude::*; use crate::ui_helper::IUiHelperModule; use crate::ui_helper::SharedStateWeakPtr; @@ -140,13 +139,19 @@ impl IUiHelperModule for MetricsModule { if let Some(evaluations) = profiler_evaluations { let csv = ris_debug::profiler::generate_csv(&evaluations, ';'); - let filename = ris_io::path::sanitize( - chrono::Local::now().to_rfc3339(), - SanitizeInfo::RemoveInvalidCharsAndSlashes, - ); - let filename = format!("{}.csv", filename); - let filepath = PathBuf::from(&dir).join(filename); + let mut filepath = None; + + for i in 0..usize::MAX { + let filename = format!("{}.csv", i); + let candidate = PathBuf::from(&dir).join(filename); + + if !std::fs::exists(&candidate)? { + filepath = Some(candidate); + break; + } + } + let filepath = filepath.into_ris_error()?; std::fs::create_dir_all(&dir)?; let mut file = std::fs::File::create(&filepath)?; diff --git a/crates/ris_data/Cargo.toml b/crates/ris_data/Cargo.toml index 94e009e0..3f80b094 100644 --- a/crates/ris_data/Cargo.toml +++ b/crates/ris_data/Cargo.toml @@ -7,7 +7,6 @@ edition = "2021" [dependencies] ash = "0.37.3" -chrono = "0.4" imgui = "0.11.0" sdl2 = "0.38.0" ris_asset_data = { path = "../ris_asset_data" } diff --git a/crates/ris_data/src/info/build_info.rs b/crates/ris_data/src/info/build_info.rs index c865fa19..bc8b78bf 100644 --- a/crates/ris_data/src/info/build_info.rs +++ b/crates/ris_data/src/info/build_info.rs @@ -11,17 +11,18 @@ pub struct BuildInfo { impl BuildInfo { pub fn new() -> BuildInfo { + // the section below is modified by the cli build command. take care when modifying it //@@AUTO GENERATE START@@ BuildInfo { git_repo: String::from(r"https://github.com/Rismosch/ris_engine.git"), - git_commit: String::from(r"5acc3a14226e8525c9f0fea13c81c055ceb225b2"), + git_commit: String::from(r"7dff47b1a88175a76c88450c339fe873efd861c0"), git_branch: String::from(r"dev"), rustc_version: String::from(r"rustc 1.90.0 (1159e78c4 2025-09-14)"), rustup_toolchain: String::from( r"stable-x86_64-unknown-linux-gnu (overridden by environment variable RUSTUP_TOOLCHAIN)", ), build_profile: profile(), - build_date: String::from(r"2025-11-04T23:19:08.899928199+01:00"), + build_date: String::from(r"2025-11-23T23:14:03.366810690+01:00"), } //@@AUTO GENERATE END@@ } diff --git a/crates/ris_data/src/lib.rs b/crates/ris_data/src/lib.rs index e6e070a2..569eaabe 100644 --- a/crates/ris_data/src/lib.rs +++ b/crates/ris_data/src/lib.rs @@ -4,7 +4,6 @@ pub mod info; pub mod input; pub mod settings; -pub mod counter; pub mod god_state; pub mod ris_map; pub mod ris_yaml; diff --git a/crates/ris_data/src/settings/serializer.rs b/crates/ris_data/src/settings/serializer.rs index 8902f904..92a229dc 100644 --- a/crates/ris_data/src/settings/serializer.rs +++ b/crates/ris_data/src/settings/serializer.rs @@ -7,7 +7,6 @@ use crate::info::app_info::AppInfo; use crate::ris_yaml::RisYaml; use crate::settings::Settings; -//pub const DEFAULT: &str = "default"; pub const DIRECTORY_NAME: &str = "settings"; pub const EXTENSION: &str = ".ris_yaml"; @@ -54,7 +53,7 @@ impl SettingsSerializer { ris_log::debug!("deserializing settings..."); for available_path in self.fallback_file.available_paths() { - if let Some(bytes) = self.fallback_file.get_by_path(&available_path) { + if let Ok(bytes) = self.fallback_file.get_by_path(&available_path) { match deserialize(&bytes, app_info) { Ok(settings) => { ris_log::debug!("settings deserialized!"); diff --git a/crates/ris_debug/Cargo.toml b/crates/ris_debug/Cargo.toml index 45694bac..2a728898 100644 --- a/crates/ris_debug/Cargo.toml +++ b/crates/ris_debug/Cargo.toml @@ -7,7 +7,6 @@ edition = "2021" [dependencies] sdl2 = "0.38.0" -chrono = "0.4" ris_error = { path = "../ris_error" } ris_log = { path = "../ris_log" } ris_math = { path = "../ris_math" } diff --git a/crates/ris_error/Cargo.toml b/crates/ris_error/Cargo.toml index 1c5f5c74..d677e1b5 100644 --- a/crates/ris_error/Cargo.toml +++ b/crates/ris_error/Cargo.toml @@ -7,5 +7,4 @@ edition = "2021" [dependencies] sdl2 = "0.38.0" -chrono = "0.4" ris_log = { path = "../ris_log" } diff --git a/crates/ris_error/src/error.rs b/crates/ris_error/src/error.rs index e9a1a0c8..937e1a06 100644 --- a/crates/ris_error/src/error.rs +++ b/crates/ris_error/src/error.rs @@ -2,9 +2,6 @@ use std::backtrace::Backtrace; use std::error::Error; use std::sync::Arc; -use chrono::DateTime; -use chrono::Local; - pub static mut PRINT_WARNING_ON_BACKTRACE: bool = true; // useful, for finding errors that are not logged pub const PRINT_BACKTRACE_WHEN_GENERATED: bool = false; @@ -93,10 +90,6 @@ impl Extensions for Result { } } -pub fn get_timestamp() -> DateTime { - Local::now() -} - #[macro_export] macro_rules! new { ($($arg:tt)*) => {{ diff --git a/crates/ris_gpu_renderers/src/imgui/imgui_renderer.rs b/crates/ris_gpu_renderers/src/imgui/imgui_renderer.rs index 7ccc8547..fa4bab7e 100644 --- a/crates/ris_gpu_renderers/src/imgui/imgui_renderer.rs +++ b/crates/ris_gpu_renderers/src/imgui/imgui_renderer.rs @@ -130,7 +130,7 @@ impl ImguiRenderer { let fs_shader_module = unsafe { device.create_shader_module(&fs_shader_module_create_info, None) }?; - let main_function_name = CString::new("main").unwrap(); + let main_function_name = CString::new("main")?; let shader_stages = [ vk::PipelineShaderStageCreateInfo { diff --git a/crates/ris_io/Cargo.toml b/crates/ris_io/Cargo.toml index 27dcd549..2c3d0b53 100644 --- a/crates/ris_io/Cargo.toml +++ b/crates/ris_io/Cargo.toml @@ -6,7 +6,6 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -chrono = "0.4" ris_error = { path = "../ris_error" } ris_log = { path = "../ris_log" } ris_math = { path = "../ris_math" } diff --git a/crates/ris_io/src/fallback_file.rs b/crates/ris_io/src/fallback_file.rs index d3970fbe..ffd295d3 100644 --- a/crates/ris_io/src/fallback_file.rs +++ b/crates/ris_io/src/fallback_file.rs @@ -1,19 +1,19 @@ -use std::fs::File; use std::io::BufRead; +use std::io::Read; +use std::io::Seek; use std::io::SeekFrom; use std::io::Write; use std::path::Path; use std::path::PathBuf; -use chrono::DateTime; -use chrono::Local; - -use ris_error::RisResult; +use ris_error::prelude::*; +use ris_log::counter::Counter; use crate::path::SanitizeInfo; +use crate::FatPtr; pub struct FallbackFileAppend { - current_file: File, + current_file: std::fs::File, } impl FallbackFileAppend { @@ -21,13 +21,13 @@ impl FallbackFileAppend { let (current_path, old_directory) = generate_paths(directory, file_extension); std::fs::create_dir_all(&old_directory)?; delete_expired_files(&old_directory, old_file_count)?; - move_current_file(¤t_path, &old_directory, file_extension)?; - let current_file = create_current_file(¤t_path)?; + let counter = move_current_file(¤t_path, &old_directory, file_extension)?; + let current_file = create_current_file(¤t_path, counter)?; Ok(Self { current_file }) } - pub fn current(&mut self) -> &mut File { + pub fn current(&mut self) -> &mut std::fs::File { &mut self.current_file } } @@ -56,12 +56,12 @@ impl FallbackFileOverwrite { pub fn overwrite_current(&self, buf: &[u8]) -> RisResult<()> { std::fs::create_dir_all(&self.old_directory)?; delete_expired_files(&self.old_directory, self.old_file_count)?; - move_current_file( + let counter = move_current_file( &self.current_path, &self.old_directory, &self.file_extension, )?; - let mut current_file = create_current_file(&self.current_path)?; + let mut current_file = create_current_file(&self.current_path, counter)?; let written_bytes = current_file.write(buf)?; if written_bytes != buf.len() { @@ -89,20 +89,20 @@ impl FallbackFileOverwrite { result } - pub fn get_by_path(&self, path: &Path) -> Option> { - match File::open(path) { - Ok(mut file) => read_file_and_strip_date(&mut file).ok(), - Err(_) => None, - } + pub fn get_by_path(&self, path: &Path) -> RisResult> { + let FileStructure { + counter: _, + p_content, + } = parse_file_header(path)?; + let mut file = std::fs::File::open(path)?; + let bytes = crate::io::read_at(&mut file, p_content)?; + Ok(bytes) } - pub fn get_by_index(&self, index: usize) -> Option> { + pub fn get_by_index(&self, index: usize) -> RisResult> { let available_paths = self.available_paths(); - let path_option = available_paths.get(index); - match path_option { - Some(path_buf) => self.get_by_path(path_buf), - None => None, - } + let path = available_paths.get(index).into_ris_error()?; + self.get_by_path(path) } } @@ -141,12 +141,32 @@ fn get_sorted_entries(directory: &Path) -> RisResult> { let mut result: Vec<_> = entries .filter(|x| x.is_ok()) .map(|x| { - x.expect("somehow, x is Err, despite being filtered out previously") - .path() + let dir_entry = ris_error::unwrap!( + x, + "somehow, x is Err, despite being filtered out previously", + ); + dir_entry.path() }) .collect(); - result.sort_by(|left, right| right.cmp(left)); + result.sort_by(|left, right| { + let left = match parse_file_header(left) { + Ok(FileStructure { + counter: Some(counter), + p_content: _, + }) => counter, + _ => Counter::MAX, + }; + let right = match parse_file_header(right) { + Ok(FileStructure { + counter: Some(counter), + p_content: _, + }) => counter, + _ => Counter::MAX, + }; + + right.cmp(&left) + }); Ok(result) } @@ -155,30 +175,30 @@ fn move_current_file( current_path: &Path, old_directory: &Path, file_extension: &str, -) -> RisResult<()> { +) -> RisResult { if !current_path.exists() { - return Ok(()); + return Ok(Counter::default()); } - let file = File::open(current_path)?; + let file = std::fs::File::open(current_path)?; let mut lines = std::io::BufReader::new(file).lines(); - let previous_filename_unsanitized = match lines.next() { - Some(Ok(line)) => line, - _ => format!("{}", Local::now()), + let previous_counter = match lines.next() { + Some(Ok(line)) => match line.trim().parse::() { + Ok(n) => Counter::from_raw(n), + _ => Counter::MAX, + }, + _ => Counter::MAX, }; - let previous_filename_without_extension = crate::path::sanitize( - previous_filename_unsanitized, - SanitizeInfo::RemoveInvalidCharsAndSlashes, - ); + let previous_filename_without_extension = previous_counter.raw().to_string(); let mut previous_path = PathBuf::new(); previous_path.push(old_directory); - let previous_filename = format!("{}{}", previous_filename_without_extension, file_extension,); + let previous_filename = format!("{}{}", previous_filename_without_extension, file_extension); previous_path.push(previous_filename); let attempts = 100; - for _ in 0..attempts { + for i in 0..attempts { if !previous_path.exists() { break; } @@ -187,7 +207,15 @@ fn move_current_file( previous_path = PathBuf::new(); previous_path.push(old_directory); - let new_previous_filename = format!("{}{}", Local::now().to_rfc3339(), file_extension); + + let post_fix = if i == 0 { + String::new() + } else { + format!("({})", i) + }; + + let new_previous_filename = + format!("{}{}{}", previous_counter.raw(), post_fix, file_extension,); let sanitized_new_previous_filename = crate::path::sanitize( &new_previous_filename, SanitizeInfo::RemoveInvalidCharsAndSlashes, @@ -200,72 +228,85 @@ fn move_current_file( } else { std::fs::rename(current_path, &previous_path)?; - Ok(()) + let mut new_counter = previous_counter; + new_counter.increase(); + Ok(new_counter) } } -fn create_current_file(current_path: &Path) -> RisResult { - let mut current_file = File::create(current_path)?; - - writeln!(current_file, "{}\n", Local::now().to_rfc3339())?; - +fn create_current_file(current_path: &Path, counter: Counter) -> RisResult { + let mut current_file = std::fs::File::create(current_path)?; + writeln!(current_file, "{}\n", counter.raw())?; Ok(current_file) } -fn read_file_and_strip_date(file: &mut File) -> RisResult> { - let file_size = crate::seek(file, SeekFrom::End(0))?; +struct FileStructure { + counter: Option, + p_content: FatPtr, +} + +fn parse_file_header(path: impl AsRef) -> RisResult { + let mut file = std::fs::File::open(path.as_ref())?; + let file = &mut file; + + let mut begin = 0u64; + let end = crate::seek(file, SeekFrom::End(0))?; - let mut buf = vec![0u8; file_size as usize]; - crate::seek(file, SeekFrom::Start(0))?; - crate::read(file, &mut buf)?; + // max u32 `4294967295` has 10 character. plus two line breaks + // (assuming `\r\n`) gives us 14 character thus a buffer of size + // 2^5=16 should be enough to check whether the file header is + // correctly formatted or not + let mut buf = vec![0u8; 16]; + file.seek(SeekFrom::Start(0))?; + let read_bytes = file.read(&mut buf)?; - let mut first_new_line = None; - let mut second_new_line = None; - for (i, char) in buf.iter().enumerate().take(file_size as usize) { + let mut first_line_break_index = None; + let mut second_line_break_index = None; + for (i, char) in buf.iter().enumerate().take(read_bytes as usize) { if *char != b'\n' { continue; } - if first_new_line.is_none() { - first_new_line = Some(i); + if first_line_break_index.is_none() { + first_line_break_index = Some(i); } else { - second_new_line = Some(i); + second_line_break_index = Some(i); + begin = i as u64 + 1; break; } } - match (first_new_line, second_new_line) { - (Some(first_new_line), Some(second_new_line)) => { - // expect the second line to be empty - if first_new_line + 1 != second_new_line { - return Ok(buf); - } - - // expect the first line to be a string - let mut first_line_buf = vec![0u8; first_new_line]; - crate::seek(file, SeekFrom::Start(0))?; - crate::read(file, &mut first_line_buf)?; - let first_line_string = String::from_utf8(first_line_buf); - match first_line_string { - Ok(date_string) => { - // expect first line to be a valid date - let date = DateTime::parse_from_rfc3339(&date_string); - if date.is_err() { - return Ok(buf); - } - - // first two lines are as expected, we can strip them away - let content_addr = (second_new_line + 1) as u64; - let content_len = file_size - content_addr; - let mut content = vec![0; content_len as usize]; - crate::seek(file, SeekFrom::Start(content_addr))?; - crate::read(file, &mut content)?; - - Ok(content) - } - Err(_) => Ok(buf), - } - } - _ => Ok(buf), + let mut result = FileStructure { + counter: None, + p_content: FatPtr::begin_end(begin, end)?, + }; + + let (Some(first_line_break_index), Some(second_line_break_index)) = + (first_line_break_index, second_line_break_index) + else { + return Ok(result); + }; + + // expect the second line to be empty + if first_line_break_index + 1 != second_line_break_index { + return Ok(result); } + + // expect the first line to be a string + let first_line_bytes = &buf[0..first_line_break_index]; + let first_line = str::from_utf8(first_line_bytes); + let Ok(number_string) = first_line else { + return Ok(result); + }; + + // expect first line to be an unsigned integer + let Ok(integer) = number_string.parse::() else { + return Ok(result); + }; + + // first two lines are as expected, we can strip them away + result.counter = Some(Counter::from_raw(integer)); + result.p_content = FatPtr::begin_end(second_line_break_index as u64 + 1, end)?; + + Ok(result) } diff --git a/crates/ris_log/Cargo.toml b/crates/ris_log/Cargo.toml index e6a48360..45e0cb22 100644 --- a/crates/ris_log/Cargo.toml +++ b/crates/ris_log/Cargo.toml @@ -7,7 +7,6 @@ edition = "2021" [dependencies] sdl2 = "0.38.0" -chrono = "0.4" [features] logging_enabled = [] diff --git a/crates/ris_log/src/constructed_log_message.rs b/crates/ris_log/src/constructed_log_message.rs index a844a094..12491fee 100644 --- a/crates/ris_log/src/constructed_log_message.rs +++ b/crates/ris_log/src/constructed_log_message.rs @@ -1,8 +1,6 @@ -use chrono::DateTime; -use chrono::Local; - use crate::color_string::Color; use crate::color_string::ColorString; +use crate::counter::Counter; use crate::log_level::LogLevel; #[derive(Clone)] @@ -10,32 +8,64 @@ pub struct ConstructedLogMessage { pub package: String, pub file: String, pub line: u32, - pub timestamp: DateTime, + pub timestamp: Counter, pub priority: LogLevel, pub message: String, } +#[derive(Debug, Clone, Copy)] +pub struct ConstructedLogFormatArgs { + pub ansi_support: bool, + pub show_timestamp: bool, + pub show_priority: bool, + pub show_priority_padding: bool, + pub show_foot: bool, +} + impl ConstructedLogMessage { - pub fn fmt(&self, ansi_support: bool) -> String { - let timestamp = ColorString(&format!("[{}]", self.timestamp.format("%T")), Color::White) - .fmt(ansi_support); + pub fn fmt(&self, args: ConstructedLogFormatArgs) -> String { + let ConstructedLogFormatArgs { + ansi_support, + show_timestamp, + show_priority, + show_priority_padding, + show_foot, + } = args; - let priority_color_string = self.priority.to_color_string(); - let priority = priority_color_string.fmt(ansi_support); + let mut result = String::new(); - let colon = ColorString(":", Color::White).fmt(ansi_support); + if show_timestamp { + let timestamp = + ColorString(&format!("[{}]", self.timestamp.raw()), Color::White).fmt(ansi_support); + result.push_str(&format!("{} ", timestamp)); + } + + if show_priority { + let priority_color_string = self.priority.to_color_string(); + let priority = priority_color_string.fmt(ansi_support); + let colon = ColorString(":", Color::White).fmt(ansi_support); + let padding = if show_priority_padding { + self.priority.padding() + } else { + "" + }; + + result.push_str(&format!("{}{}{} ", priority, colon, padding,)); + } let message = ColorString(&self.message, Color::BrightWhite).fmt(ansi_support); + result.push_str(&message); + + if show_foot { + let foot = ColorString( + &format!("in {} at {}:{}", self.package, self.file, self.line), + Color::White, + ) + .fmt(ansi_support); - let foot = ColorString( - &format!("in {} at {}:{}", self.package, self.file, self.line), - Color::White, - ) - .fmt(ansi_support); + result.push_str(&format!("\n {}", foot)); + } - format!( - "{} {}{} {}\n {}", - timestamp, priority, colon, message, foot, - ) + result } } diff --git a/crates/ris_data/src/counter.rs b/crates/ris_log/src/counter.rs similarity index 78% rename from crates/ris_data/src/counter.rs rename to crates/ris_log/src/counter.rs index 458ce26b..bb070ecb 100644 --- a/crates/ris_data/src/counter.rs +++ b/crates/ris_log/src/counter.rs @@ -1,5 +1,7 @@ +const MAX_DISTANCE: u32 = 0x80000000; + #[derive(Default, Debug, Clone, Copy, PartialEq, Eq, Hash)] -pub struct Counter(usize); +pub struct Counter(u32); impl PartialOrd for Counter { fn partial_cmp(&self, other: &Self) -> Option { @@ -13,7 +15,6 @@ impl Ord for Counter { let rhs = other.0; let distance = lhs.abs_diff(rhs); - const MAX_DISTANCE: usize = 0x80usize.swap_bytes(); if distance < MAX_DISTANCE { lhs.cmp(&rhs) } else { @@ -23,11 +24,13 @@ impl Ord for Counter { } impl Counter { - pub fn raw(self) -> usize { + pub const MAX: Self = Counter(u32::MAX); + + pub fn raw(self) -> u32 { self.0 } - pub fn from_raw(value: usize) -> Self { + pub fn from_raw(value: u32) -> Self { Self(value) } diff --git a/crates/ris_log/src/lib.rs b/crates/ris_log/src/lib.rs index bca40e8f..bbc391ce 100644 --- a/crates/ris_log/src/lib.rs +++ b/crates/ris_log/src/lib.rs @@ -1,5 +1,6 @@ pub mod color_string; pub mod constructed_log_message; +pub mod counter; pub mod log; pub mod log_level; pub mod log_message; diff --git a/crates/ris_log/src/log.rs b/crates/ris_log/src/log.rs index 3e20688b..b123c914 100644 --- a/crates/ris_log/src/log.rs +++ b/crates/ris_log/src/log.rs @@ -7,9 +7,7 @@ use std::{ thread::JoinHandle, }; -use chrono::DateTime; -use chrono::Local; - +use crate::counter::Counter; use crate::log_level::LogLevel; use crate::log_message::LogMessage; @@ -36,6 +34,7 @@ impl Drop for LogGuard { #[cfg(feature = "logging_enabled")] pub struct Logger { + counter: Counter, log_level: LogLevel, sender: Option>, thread_handle: Option>, @@ -71,6 +70,7 @@ pub fn init(log_level: LogLevel, appenders: Vec>) -> L })); let logger = Logger { + counter: Counter::default(), log_level, sender, thread_handle, @@ -128,8 +128,22 @@ pub fn log_level() -> LogLevel { LogLevel::None } -pub fn get_timestamp() -> DateTime { - Local::now() +pub fn get_timestamp() -> Counter { + #[cfg(feature = "logging_enabled")] + { + match LOG.lock() { + Err(e) => eprintln!("error while getting log_level: {}", e), + Ok(mut log) => { + if let Some(logger) = log.as_mut() { + let previous = logger.counter; + logger.counter.increase(); + return previous; + } + } + } + } + + Counter::default() } pub fn can_log(log_level: LogLevel, message_priority: LogLevel) -> bool { diff --git a/crates/ris_log/src/log_level.rs b/crates/ris_log/src/log_level.rs index 6e34c5f2..07f6be5e 100644 --- a/crates/ris_log/src/log_level.rs +++ b/crates/ris_log/src/log_level.rs @@ -50,8 +50,8 @@ pub const FATAL_COLOR: Color = Color::BrightRed; pub const NONE_COLOR: Color = Color::BrightWhite; impl LogLevel { - pub fn to_color_string(&self) -> ColorString<'_> { - match *self { + pub fn to_color_string(self) -> ColorString<'static> { + match self { LogLevel::Trace => ColorString("Trace", TRACE_COLOR), LogLevel::Debug => ColorString("Debug", DEBUG_COLOR), LogLevel::Info => ColorString("Info", INFO_COLOR), @@ -61,4 +61,16 @@ impl LogLevel { LogLevel::None => ColorString("None", NONE_COLOR), } } + + pub fn padding(self) -> &'static str { + match self { + LogLevel::Trace => " ", + LogLevel::Debug => " ", + LogLevel::Info => " ", + LogLevel::Warning => "", + LogLevel::Error => " ", + LogLevel::Fatal => " ", + LogLevel::None => " ", + } + } } diff --git a/crates/ris_log/src/log_message.rs b/crates/ris_log/src/log_message.rs index 55c6a699..1371028f 100644 --- a/crates/ris_log/src/log_message.rs +++ b/crates/ris_log/src/log_message.rs @@ -1,3 +1,4 @@ +use crate::constructed_log_message::ConstructedLogFormatArgs; use crate::constructed_log_message::ConstructedLogMessage; #[derive(Clone)] @@ -7,9 +8,9 @@ pub enum LogMessage { } impl LogMessage { - pub fn fmt(&self, ansi_support: bool) -> String { + pub fn fmt(&self, args: ConstructedLogFormatArgs) -> String { match self { - Self::Constructed(message) => message.fmt(ansi_support), + Self::Constructed(message) => message.fmt(args), Self::Plain(message) => message.to_owned(), } } diff --git a/crates/ris_util/src/testing.rs b/crates/ris_util/src/testing.rs index 9ad045e4..646955e2 100644 --- a/crates/ris_util/src/testing.rs +++ b/crates/ris_util/src/testing.rs @@ -213,9 +213,11 @@ macro_rules! prep_test_dir { let sanitized_test_path = ris_io::path::sanitize(test_path, ris_io::path::SanitizeInfo::RemoveInvalidChars); - let executable_string = std::env::args().next().expect("no cli args"); + let executable_string = std::env::args().next().expect("cli args to exist"); let executable_path = std::path::PathBuf::from(executable_string); - let executable_directory = executable_path.parent().expect("executable has no parent"); + let executable_directory = executable_path + .parent() + .expect("executable to have a parent"); let mut result = std::path::PathBuf::new(); result.push(executable_directory); @@ -230,6 +232,8 @@ macro_rules! prep_test_dir { panic!("failed to create \"{:?}\"", &result); } + eprintln!("created dir \"{}\"", result.display()); + result }}; } diff --git a/src/cli/cmd.rs b/src/cli/cmd.rs index de36ab6e..4dca3e4b 100644 --- a/src/cli/cmd.rs +++ b/src/cli/cmd.rs @@ -36,8 +36,32 @@ where } let mut command = std::process::Command::new(splits[0]); + let mut complete_arg = String::new(); + for arg in &splits[1..] { - command.arg(arg); + let trimmed_arg = arg.trim(); + let is_combined_arg = !complete_arg.is_empty() || trimmed_arg.starts_with("\""); + if !is_combined_arg { + command.arg(trimmed_arg); + continue; + } + + complete_arg.push(' '); + complete_arg.push_str(trimmed_arg); + + let combined_arg_is_done = trimmed_arg.ends_with("\"") && !trimmed_arg.ends_with("\\\""); // an escaped `"` does not end the combined arg + + if combined_arg_is_done { + let trimmed = complete_arg.trim(); + let sub = &trimmed[1..(trimmed.len() - 1)]; + let cleaned = sub.replace("\\\"", "\""); + command.arg(cleaned); + complete_arg = String::new(); // reset complete_arg + } + } + + if !complete_arg.is_empty() { + return ris_error::new_result!("syntax error: failed to find closing quotation mark"); } if stdout.is_some() { diff --git a/src/cli/commands/build.rs b/src/cli/commands/build.rs index 80a0cba9..cf0f7008 100644 --- a/src/cli/commands/build.rs +++ b/src/cli/commands/build.rs @@ -99,7 +99,20 @@ impl ICommand for Build { cmd::run_with_stdout("rustc --version", &mut rustc_version)?; cmd::run_with_stdout("rustup show active-toolchain", &mut rustup_toolchain)?; - let build_date = chrono::Local::now().to_rfc3339(); + let mut build_date = String::new(); + + #[cfg(target_os = "windows")] + { + cmd::run_with_stdout("powershell (Get-Date).ToString(\"o\")", &mut build_date)?; + } + + #[cfg(target_os = "linux")] + { + cmd::run_with_stdout( + "bash -c \"date +\\\"%Y-%m-%dT%H:%M:%S.%N%:z\\\"\"", + &mut build_date, + )?; + } let git_repo = git_repo.trim(); let git_commit = git_commit.trim(); diff --git a/tests/suite/main.rs b/tests/suite/main.rs index 94cd1853..93c637b7 100644 --- a/tests/suite/main.rs +++ b/tests/suite/main.rs @@ -4,6 +4,7 @@ pub mod ris_data; pub mod ris_debug; pub mod ris_input; pub mod ris_io; +pub mod ris_log; pub mod ris_math; pub mod ris_rng; pub mod ris_util; diff --git a/tests/suite/ris_data/mod.rs b/tests/suite/ris_data/mod.rs index a10bd505..65ec4077 100644 --- a/tests/suite/ris_data/mod.rs +++ b/tests/suite/ris_data/mod.rs @@ -2,7 +2,6 @@ pub mod ecs; pub mod buttons; pub mod cell; -pub mod counter; pub mod keys; pub mod ptr; pub mod ris_map; diff --git a/tests/suite/ris_io/fallback_file_append.rs b/tests/suite/ris_io/fallback_file_append.rs index 95587542..0ba4ce28 100644 --- a/tests/suite/ris_io/fallback_file_append.rs +++ b/tests/suite/ris_io/fallback_file_append.rs @@ -4,10 +4,6 @@ use std::io::SeekFrom; use std::io::Write; use std::path::PathBuf; -use chrono::DateTime; -use chrono::Duration; -use chrono::Local; - use ris_io::fallback_file::FallbackFileAppend; #[test] @@ -47,7 +43,10 @@ fn should_delete_expired_files() { let mut file_path = PathBuf::from(&old_dir); file_path.push(format!("{}", i)); - std::fs::File::create(&file_path).unwrap(); + let mut file = std::fs::File::create(&file_path).unwrap(); + let content = format!("{}\n\nhello world", i); + ris_io::write(&mut file, content.as_bytes()).unwrap(); + file_paths.push(file_path); } @@ -66,26 +65,23 @@ fn should_delete_expired_files() { } #[test] -fn should_create_current_file_with_timestamp() { +fn should_create_current_file_with_counter() { let test_dir = ris_util::prep_test_dir!(); - FallbackFileAppend::new(&test_dir, ".test", 10).unwrap(); - let mut current_file_path = PathBuf::from(&test_dir); - current_file_path.push("current.test"); + for i in 0..10 { + FallbackFileAppend::new(&test_dir, ".test", 10).unwrap(); - let mut file = std::fs::File::open(current_file_path).unwrap(); - let mut content = String::new(); - file.read_to_string(&mut content).unwrap(); + let mut current_file_path = PathBuf::from(&test_dir); + current_file_path.push("current.test"); - let first_line = content.lines().next().unwrap(); - let file_date = DateTime::parse_from_rfc3339(first_line) - .unwrap() - .with_timezone(&Local); - let now = Local::now(); + let mut file = std::fs::File::open(current_file_path).unwrap(); + let mut content = String::new(); + file.read_to_string(&mut content).unwrap(); - let diff = now - file_date; - let one_second = Duration::seconds(1); - assert!(diff < one_second); + let first_line = content.lines().next().unwrap(); + let value = first_line.parse::().unwrap(); + assert_eq!(value, i); + } } #[test] @@ -99,62 +95,47 @@ fn should_move_current_file() { old_path.push("old"); // move file 1 - // should use first line as file name + // should use Counter::MAX when first line is not an unsigned integer std::fs::remove_file(¤t_path).unwrap(); let mut current_file = std::fs::File::create(¤t_path).unwrap(); - writeln!(current_file, "i am a unique file").unwrap(); + writeln!(current_file, "i am incorrectly formatted").unwrap(); FallbackFileAppend::new(&test_dir, ".test", 10).unwrap(); - let mut file_path = PathBuf::from(&old_path); - file_path.push("i am a unique file.test"); + let file_path = PathBuf::from(&old_path).join("4294967295.test"); let mut file = std::fs::File::open(&file_path).unwrap(); let mut content = String::new(); file.read_to_string(&mut content).unwrap(); assert!(file_path.exists()); - assert_eq!(content, "i am a unique file\n"); + assert_eq!(content, "i am incorrectly formatted\n"); // move file 2 - // should use first line as file name, sanitizing invalid chars - std::fs::remove_file(¤t_path).unwrap(); - let mut current_file = std::fs::File::create(¤t_path).unwrap(); - writeln!(current_file, "i am not unique :(").unwrap(); - FallbackFileAppend::new(&test_dir, ".test", 10).unwrap(); - let mut file_path = PathBuf::from(&old_path); - file_path.push("i am not unique _(.test"); - let mut file = std::fs::File::open(&file_path).unwrap(); - let mut content = String::new(); - file.read_to_string(&mut content).unwrap(); - assert!(file_path.exists()); - assert_eq!(content, "i am not unique :(\n"); + // should create a unique filename, when for some reason (ie user modifying the files) creates + // duplicated filenames + for i in 1..5 { + std::fs::remove_file(¤t_path).unwrap(); + let mut current_file = std::fs::File::create(¤t_path).unwrap(); + writeln!(current_file, "i am incorrectly formatted {}", i).unwrap(); + let mut fallback_file = FallbackFileAppend::new(&test_dir, ".test", 10).unwrap(); + write!(&mut fallback_file.current(), "i am correctly formatted").unwrap(); + let file_path = PathBuf::from(&old_path).join(format!("4294967295({}).test", i)); + let mut file = std::fs::File::open(&file_path).unwrap(); + let mut content = String::new(); + file.read_to_string(&mut content).unwrap(); + assert!(file_path.exists()); + assert_eq!(content, format!("i am incorrectly formatted {}\n", i)); + } // move file 3 - // should generate new unique filename, which does not correspont to its first line - std::fs::remove_file(¤t_path).unwrap(); - let mut current_file = std::fs::File::create(¤t_path).unwrap(); - writeln!(current_file, "i am not unique :(").unwrap(); - FallbackFileAppend::new(&test_dir, ".test", 10).unwrap(); - let entries = std::fs::read_dir(&old_path).unwrap(); - for entry in entries { - let unique_path = entry.unwrap().path(); - let mut file = std::fs::File::open(&unique_path).unwrap(); + // file is correctly formatted and uses the line as its filename + for i in 0..5 { + let mut fallback_file = FallbackFileAppend::new(&test_dir, ".test", 10).unwrap(); + write!(&mut fallback_file.current(), "i am correctly formatted").unwrap(); + let file_path = PathBuf::from(&old_path).join(format!("{}.test", i)); + let mut file = std::fs::File::open(&file_path).unwrap(); let mut content = String::new(); file.read_to_string(&mut content).unwrap(); - - if unique_path == file_path { - continue; - } - - if !unique_path.exists() { - continue; - } - - if content != "i am not unique :(\n" { - continue; - } - - return; // test passed + assert!(file_path.exists()); + assert_eq!(content, format!("{}\n\ni am correctly formatted", i)); } - - panic!("test failed, either because a unique path was not generated, or no entries exist"); } #[test] @@ -178,7 +159,7 @@ fn should_give_access_to_current_file() { let lines = content.lines().collect::>(); assert_eq!(lines.len(), 3); - assert!(DateTime::parse_from_rfc3339(lines[0]).is_ok()); + assert_eq!(lines[0], "0"); assert_eq!(lines[1], ""); assert_eq!(lines[2], "i am a very important message"); } diff --git a/tests/suite/ris_io/fallback_file_overwrite.rs b/tests/suite/ris_io/fallback_file_overwrite.rs index 3a662812..a8dbfbe2 100644 --- a/tests/suite/ris_io/fallback_file_overwrite.rs +++ b/tests/suite/ris_io/fallback_file_overwrite.rs @@ -2,10 +2,6 @@ use std::io::Read; use std::io::Write; use std::path::PathBuf; -use chrono::DateTime; -use chrono::Duration; -use chrono::Local; - use ris_io::fallback_file::FallbackFileOverwrite; #[test] @@ -54,17 +50,9 @@ fn should_write_file() { let lines = content.lines().collect::>(); assert_eq!(lines.len(), 3); + assert_eq!(lines[0], "0"); assert_eq!(lines[1], ""); assert_eq!(lines[2], "hello world"); - - let file_date = DateTime::parse_from_rfc3339(lines[0]) - .unwrap() - .with_timezone(&Local); - let now = Local::now(); - - let diff = now - file_date; - let one_second = Duration::seconds(1); - assert!(diff < one_second); } #[test] @@ -80,62 +68,52 @@ fn should_move_file() { overwriter.overwrite_current("zero".as_bytes()).unwrap(); // move file 1 - // should use first line as file name + // should use Counter::MAX when first line is not an unsigned integer std::fs::remove_file(¤t_path).unwrap(); let mut current_file = std::fs::File::create(¤t_path).unwrap(); - writeln!(current_file, "i am a unique file").unwrap(); + writeln!(current_file, "i am incorrectly formatted").unwrap(); overwriter.overwrite_current("un".as_bytes()).unwrap(); let mut file_path = PathBuf::from(&old_path); - file_path.push("i am a unique file.test"); + file_path.push("4294967295.test"); let mut file = std::fs::File::open(&file_path).unwrap(); let mut content = String::new(); file.read_to_string(&mut content).unwrap(); assert!(file_path.exists()); - assert_eq!(content, "i am a unique file\n"); + assert_eq!(content, "i am incorrectly formatted\n"); // move file 2 - // should use first line as file name, sanitizing invalid chars - std::fs::remove_file(¤t_path).unwrap(); - let mut current_file = std::fs::File::create(¤t_path).unwrap(); - writeln!(current_file, "i am not unique :(").unwrap(); - overwriter.overwrite_current("deux".as_bytes()).unwrap(); - let mut file_path = PathBuf::from(&old_path); - file_path.push("i am not unique _(.test"); - let mut file = std::fs::File::open(&file_path).unwrap(); - let mut content = String::new(); - file.read_to_string(&mut content).unwrap(); - assert!(file_path.exists()); - assert_eq!(content, "i am not unique :(\n"); + // should create a unique filename, when for some reason (ie user modifying the files) creates + // duplicated filenames + for i in 1..5 { + std::fs::remove_file(¤t_path).unwrap(); + let mut current_file = std::fs::File::create(¤t_path).unwrap(); + writeln!(current_file, "i am incorrectly formatted").unwrap(); + overwriter + .overwrite_current("i am correctly formatted".as_bytes()) + .unwrap(); + let mut file_path = PathBuf::from(&old_path); + file_path.push(format!("4294967295({}).test", i)); + let mut file = std::fs::File::open(&file_path).unwrap(); + let mut content = String::new(); + file.read_to_string(&mut content).unwrap(); + assert!(file_path.exists()); + assert_eq!(content, "i am incorrectly formatted\n"); + } // move file 3 - // should generate new unique filename, which does not correspont to its first line - std::fs::remove_file(¤t_path).unwrap(); - let mut current_file = std::fs::File::create(¤t_path).unwrap(); - writeln!(current_file, "i am not unique :(").unwrap(); - overwriter.overwrite_current("trois".as_bytes()).unwrap(); - let entries = std::fs::read_dir(&old_path).unwrap(); - for entry in entries { - let unique_path = entry.unwrap().path(); - let mut file = std::fs::File::open(&unique_path).unwrap(); + // file is correctly formatted and uses the line as its filename + for i in 0..5 { + overwriter + .overwrite_current("i am correctly formatted".as_bytes()) + .unwrap(); + let mut file_path = PathBuf::from(&old_path); + file_path.push(format!("{}.test", i)); + let mut file = std::fs::File::open(&file_path).unwrap(); let mut content = String::new(); file.read_to_string(&mut content).unwrap(); - - if unique_path == file_path { - continue; - } - - if !unique_path.exists() { - continue; - } - - if content != "i am not unique :(\n" { - continue; - } - - return; // test passed + assert!(file_path.exists()); + assert_eq!(content, format!("{}\n\ni am correctly formatted", i)); } - - panic!("test failed, either because a unique path was not generated, or no entries exist"); } #[test] @@ -151,7 +129,10 @@ fn should_delete_expired_files() { let mut file_path = PathBuf::from(&old_dir); file_path.push(format!("{}", i)); - std::fs::File::create(&file_path).unwrap(); + let mut file = std::fs::File::create(&file_path).unwrap(); + let content = format!("{}\n\nhello world", i); + ris_io::write(&mut file, content.as_bytes()).unwrap(); + file_paths.push(file_path); } @@ -182,11 +163,16 @@ fn should_get_available_files() { let mut file_path = PathBuf::from(&old_dir); file_path.push(format!("{}", i)); - std::fs::File::create(&file_path).unwrap(); + let mut file = std::fs::File::create(&file_path).unwrap(); + + let content = format!("{}\n\nhello world", i); + ris_io::write(&mut file, content.as_bytes()).unwrap(); file_paths.push(file_path); } let available_paths = overwriter.available_paths(); + println!("available_paths: {:#?}", available_paths); + println!("file_paths: {:#?}", file_paths); assert_eq!(available_paths.len(), 5); assert_eq!(available_paths[0], file_paths[0]); assert_eq!(available_paths[1], file_paths[1]); @@ -233,11 +219,11 @@ fn should_get_file_contents_by_path() { let result3 = overwriter.get_by_path(&available_args[3]); let result4 = overwriter.get_by_path(&available_args[4]); - assert!(result0.is_some()); - assert!(result1.is_none()); - assert!(result2.is_some()); - assert!(result3.is_none()); - assert!(result4.is_some()); + assert!(result0.is_ok()); + assert!(result1.is_err()); + assert!(result2.is_ok()); + assert!(result3.is_err()); + assert!(result4.is_ok()); let current = String::from_utf8(result0.unwrap()).unwrap(); let old2 = String::from_utf8(result2.unwrap()).unwrap(); @@ -253,7 +239,7 @@ fn should_get_file_contents_by_index() { let test_dir = ris_util::prep_test_dir!(); let overwriter = FallbackFileOverwrite::new(&test_dir, ".test", 10); - assert!(overwriter.get_by_index(0).is_none()); + assert!(overwriter.get_by_index(0).is_err()); overwriter.overwrite_current("un".as_bytes()).unwrap(); overwriter.overwrite_current("deux".as_bytes()).unwrap(); @@ -272,5 +258,5 @@ fn should_get_file_contents_by_index() { assert_eq!(old2, "trois"); assert_eq!(old3, "deux"); assert_eq!(old4, "un"); - assert!(overwriter.get_by_index(5).is_none()); + assert!(overwriter.get_by_index(5).is_err()); } diff --git a/tests/suite/ris_data/counter.rs b/tests/suite/ris_log/counter.rs similarity index 77% rename from tests/suite/ris_data/counter.rs rename to tests/suite/ris_log/counter.rs index 9f15a2b1..0ce363d9 100644 --- a/tests/suite/ris_data/counter.rs +++ b/tests/suite/ris_log/counter.rs @@ -1,4 +1,4 @@ -use ris_data::counter::Counter; +use ris_log::counter::Counter; #[test] fn should_should_add() { @@ -16,9 +16,9 @@ fn should_should_add() { #[test] fn should_overflow() { - let mut counter = Counter::from_raw(usize::MAX - 2); + let mut counter = Counter::from_raw(u32::MAX - 2); - assert_eq!(counter.raw(), usize::MAX - 2); + assert_eq!(counter.raw(), u32::MAX - 2); counter.increase(); counter.increase(); counter.increase(); @@ -68,13 +68,13 @@ fn should_sort_case_2() { Counter::from_raw(1), Counter::from_raw(5), Counter::from_raw(0), - Counter::from_raw(18446744073709551610), + Counter::from_raw(4294967290), Counter::from_raw(5), - Counter::from_raw(18446744073709551611), + Counter::from_raw(4294967291), Counter::from_raw(6), - Counter::from_raw(18446744073709551612), + Counter::from_raw(4294967292), Counter::from_raw(4), - Counter::from_raw(18446744073709551610), + Counter::from_raw(4294967290), ]; counters.sort(); @@ -82,10 +82,10 @@ fn should_sort_case_2() { assert_eq!( counters, vec![ - Counter::from_raw(18446744073709551610), - Counter::from_raw(18446744073709551610), - Counter::from_raw(18446744073709551611), - Counter::from_raw(18446744073709551612), + Counter::from_raw(4294967290), + Counter::from_raw(4294967290), + Counter::from_raw(4294967291), + Counter::from_raw(4294967292), Counter::from_raw(0), Counter::from_raw(1), Counter::from_raw(4), diff --git a/tests/suite/ris_log/mod.rs b/tests/suite/ris_log/mod.rs new file mode 100644 index 00000000..a33a516c --- /dev/null +++ b/tests/suite/ris_log/mod.rs @@ -0,0 +1 @@ +pub mod counter;