diff --git a/.changes/reduce-debug-format-size.md b/.changes/reduce-debug-format-size.md new file mode 100644 index 000000000000..b327b633164b --- /dev/null +++ b/.changes/reduce-debug-format-size.md @@ -0,0 +1,6 @@ +--- +"tauri": patch:enhance +"tauri-utils": patch:enhance +--- + +Reduced `Debug` format size for binary buffers. diff --git a/crates/tauri-utils/src/assets.rs b/crates/tauri-utils/src/assets.rs index c808d2228333..3d904cd1f39f 100644 --- a/crates/tauri-utils/src/assets.rs +++ b/crates/tauri-utils/src/assets.rs @@ -113,7 +113,6 @@ impl CspHash<'_> { } /// [`Assets`] implementation that only contains compile-time compressed and embedded assets. -#[derive(Debug)] pub struct EmbeddedAssets { assets: phf::Map<&'static str, &'static [u8]>, // Hashes that must be injected to the CSP of every HTML file. @@ -122,6 +121,36 @@ pub struct EmbeddedAssets { html_hashes: phf::Map<&'static str, &'static [CspHash<'static>]>, } +/// Temporary struct that overrides the Debug formatting for the `assets` field. +/// +/// It reduces the output size compared to the default, as that would format the binary +/// data as a slice of numbers like `[65, 66, 67]` for "ABC". This instead shows the length +/// of the slice. +/// +/// For example: `{"/index.html": [u8; 1835], "/index.js": [u8; 212]}` +struct DebugAssetMap<'a>(&'a phf::Map<&'static str, &'static [u8]>); + +impl std::fmt::Debug for DebugAssetMap<'_> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let mut map = f.debug_map(); + for (k, v) in self.0.entries() { + map.key(k); + map.value(&format_args!("[u8; {}]", v.len())); + } + map.finish() + } +} + +impl std::fmt::Debug for EmbeddedAssets { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("EmbeddedAssets") + .field("assets", &DebugAssetMap(&self.assets)) + .field("global_hashes", &self.global_hashes) + .field("html_hashes", &self.html_hashes) + .finish() + } +} + impl EmbeddedAssets { /// Creates a new instance from the given asset map and script hash list. pub const fn new( diff --git a/crates/tauri/src/image/mod.rs b/crates/tauri/src/image/mod.rs index 643125f183ee..9dec4165802b 100644 --- a/crates/tauri/src/image/mod.rs +++ b/crates/tauri/src/image/mod.rs @@ -12,13 +12,37 @@ use std::sync::Arc; use crate::{Resource, ResourceId, ResourceTable}; /// An RGBA Image in row-major order from top to bottom. -#[derive(Debug, Clone)] +#[derive(Clone)] pub struct Image<'a> { rgba: Cow<'a, [u8]>, width: u32, height: u32, } +impl std::fmt::Debug for Image<'_> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("Image") + .field( + "rgba", + // Reduces the debug size compared to the derived default, as the default + // would format the raw bytes as numbers `[0, 0, 0, 0]` for 1 pixel. + // The custom format doesn't grow as much with larger images: + // `Image { rgba: Cow::Borrowed([u8; 4096]), width: 32, height: 32 }` + &format_args!( + "Cow::{}([u8; {}])", + match &self.rgba { + Cow::Borrowed(_) => "Borrowed", + Cow::Owned(_) => "Owned", + }, + self.rgba.len() + ), + ) + .field("width", &self.width) + .field("height", &self.height) + .finish() + } +} + impl Resource for Image<'static> {} impl Image<'static> { diff --git a/crates/tauri/src/lib.rs b/crates/tauri/src/lib.rs index 979ebd5774c1..9d2b3f8a6fa9 100644 --- a/crates/tauri/src/lib.rs +++ b/crates/tauri/src/lib.rs @@ -397,12 +397,32 @@ pub struct Context { pub(crate) plugin_global_api_scripts: Option<&'static [&'static str]>, } +/// Temporary struct that overrides the Debug formatting for the `app_icon` field. +/// +/// It reduces the output size compared to the default, as that would format the binary +/// data as a slice of numbers `[65, 66, 67]`. This instead shows the length of the Vec. +/// +/// For example: `Some([u8; 493])` +pub(crate) struct DebugAppIcon<'a>(&'a Option>); + +impl std::fmt::Debug for DebugAppIcon<'_> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self.0 { + Option::None => f.write_str("None"), + Option::Some(icon) => f + .debug_tuple("Some") + .field(&format_args!("[u8; {}]", icon.len())) + .finish(), + } + } +} + impl fmt::Debug for Context { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let mut d = f.debug_struct("Context"); d.field("config", &self.config) .field("default_window_icon", &self.default_window_icon) - .field("app_icon", &self.app_icon) + .field("app_icon", &DebugAppIcon(&self.app_icon)) .field("package_info", &self.package_info) .field("pattern", &self.pattern) .field("plugin_global_api_scripts", &self.plugin_global_api_scripts); diff --git a/crates/tauri/src/manager/mod.rs b/crates/tauri/src/manager/mod.rs index d95f35dd335b..b97d9fbece6a 100644 --- a/crates/tauri/src/manager/mod.rs +++ b/crates/tauri/src/manager/mod.rs @@ -18,7 +18,6 @@ use tauri_utils::{ config::{Csp, CspDirectiveSources}, }; -use crate::resources::ResourceTable; use crate::{ app::{ AppHandle, ChannelInterceptor, GlobalWebviewEventListener, GlobalWindowEventListener, @@ -27,8 +26,9 @@ use crate::{ event::{EmitArgs, Event, EventId, EventTarget, Listeners}, ipc::{Invoke, InvokeHandler, RuntimeAuthority}, plugin::PluginStore, + resources::ResourceTable, utils::{config::Config, PackageInfo}, - Assets, Context, EventName, Pattern, Runtime, StateManager, Webview, Window, + Assets, Context, DebugAppIcon, EventName, Pattern, Runtime, StateManager, Webview, Window, }; #[cfg(desktop)] @@ -233,7 +233,7 @@ impl fmt::Debug for AppManager { .field("plugins", &self.plugins) .field("state", &self.state) .field("config", &self.config) - .field("app_icon", &self.app_icon) + .field("app_icon", &DebugAppIcon(&self.app_icon)) .field("package_info", &self.package_info) .field("pattern", &self.pattern);