feat: reduce Debug format size for binary buffers (#13809)

* feat: reduce Image debug output

For example now:
`Image { rgba: Cow::Borrowed([u8; 4096]), width: 32, height: 32 }) }`

* feat: reduce EmbeddedAssets debug size

For example now:
```
EmbeddedAssets {
    assets: {
        "/index.html": [u8; 1835],
        "/index.js": [u8; 212],
    },
    global_hashes: [
        Script(
            "'sha256-EOd6N98xxmK5s7VvxV7W2w7YG+dmP52MqNiZUq1NLeE='",
        ),
        Style(
            "'sha256-YEercZJImS+vUX2bz7vkQ0aA4rtBIPLuCEWz+yraQ/g='",
        ),
    ],
    html_hashes: {
        "/index.html": [
            Script(
                "'sha256-3g8CfFrjFLGpwD2o+hwMt+lh/hsHbQ3XY+EPJ35fFKk='",
            ),
            Script(
                "'sha256-EOd6N98xxmK5s7VvxV7W2w7YG+dmP52MqNiZUq1NLeE='",
            ),
        ],
    },
}
```

* feat: reduce `app_icon` debug size

* chore: changelog

* chore: include tauri-utils in changelog

* doc: comment had extra closing brackets [skip ci]
This commit is contained in:
Robin van Boven
2025-07-25 12:55:00 +02:00
committed by GitHub
parent d6d941c3a7
commit 72b4226ee9
5 changed files with 85 additions and 6 deletions

View File

@@ -0,0 +1,6 @@
---
"tauri": patch:enhance
"tauri-utils": patch:enhance
---
Reduced `Debug` format size for binary buffers.

View File

@@ -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(

View File

@@ -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> {

View File

@@ -397,12 +397,32 @@ pub struct Context<R: Runtime> {
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<Vec<u8>>);
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<R: Runtime> fmt::Debug for Context<R> {
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);

View File

@@ -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<R: Runtime> fmt::Debug for AppManager<R> {
.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);