Files
zed/crates/picker/src/persistence.rs
T
Kirill Bulatovandzed-zippy[bot] 84148a0f73 Reduce LLVM IR bloat one last time (#63882)
I think this is the final attempt of mine to do anything about the
binary size, as those fixes become relatively intricate and I like them
less and less.

Each commit has its own improvement stats and mainly reduce generic-code
duplication through shared non-generic helpers and `#[inline(never)]`
boundaries.

Total reduction stats:

With sccache disabled, `cargo clean` and `cargo build --release -p zed`:
Before: zed binary 396716472 bytes
After: zed binary 359416504 bytes (-9.40%, -37.29MB)

Release Notes:

- N/A

---------

Co-authored-by: zed-zippy[bot] <234243425+zed-zippy[bot]@users.noreply.github.com>
2026-09-07 15:18:49 +00:00

151 lines
4.8 KiB
Rust

use anyhow::{Context, anyhow};
use db::kvp::KeyValueStore;
use gpui::App;
use ui::Window;
use crate::preview;
use crate::shape::{self, Centered, RelativeHeight, RelativeWidth, Shape, ViewportFraction};
const PICKERS_NAMESPACE: &str = "pickers_v2";
pub(crate) fn store_shape_for_this_layout(
picker_delegate: &'static str,
preview_layout: Option<preview::Layout>,
shape: shape::Centered,
window: &ui::Window,
cx: &App,
) {
let shape = PickerConfig::from_centered(shape, window);
let kvp = KeyValueStore::global(cx);
db::write_and_log(cx, async move || {
kvp.scoped(PICKERS_NAMESPACE)
.write(
shape_key(picker_delegate, preview_layout),
serde_json::to_string(&shape).context("Could not serialize size of picker")?,
)
.await?;
// Must be written after the shape or loading can break
// if this future is ever cancelled.
kvp.scoped(PICKERS_NAMESPACE)
.write(
last_layout_key(picker_delegate),
layout_as_str(preview_layout).to_string(),
)
.await
});
}
/// Persist the last-used preview layout without touching the stored shape.
///
/// Changing the preview position (e.g. right/below/hidden) without resizing
/// must still be remembered, so this is called whenever the layout changes.
pub(crate) fn store_last_layout(
picker_delegate: &'static str,
preview_layout: Option<preview::Layout>,
cx: &App,
) {
let kvp = KeyValueStore::global(cx);
db::write_and_log(cx, async move || {
kvp.scoped(PICKERS_NAMESPACE)
.write(
last_layout_key(picker_delegate),
layout_as_str(preview_layout).to_string(),
)
.await
});
}
pub(crate) fn try_load_shape(
picker_delegate: &'static str,
preview_layout: impl Into<Option<preview::Layout>>,
cx: &App,
) -> anyhow::Result<Option<Shape>> {
let Some(shape) = KeyValueStore::global(cx)
.scoped(PICKERS_NAMESPACE)
.read(&shape_key(picker_delegate, preview_layout.into()))
.context("Could not read picker shape from KeyValueStore")?
else {
return Ok(None);
};
let shape = parse_shape(&shape)?;
Ok(Some(Shape::HorizontallyCentered(shape)))
}
pub(crate) fn load_last_preview_layout(
picker_delegate: &'static str,
cx: &App,
) -> anyhow::Result<Option<preview::Layout>> {
let Some(last_layout) = KeyValueStore::global(cx)
.scoped(PICKERS_NAMESPACE)
.read(&last_layout_key(picker_delegate))
.context("Could not read last picker layout from KeyValueStore")?
else {
return Ok(None);
};
parse_layout(&last_layout)
}
#[inline(never)]
fn parse_shape(json: &str) -> anyhow::Result<Centered> {
Ok(serde_json::from_str::<PickerConfig>(json)
.context("Could not deserialize loaded picker shape from persistence")?
.into_centered())
}
fn shape_key(picker_delegate: &'static str, preview_layout: Option<preview::Layout>) -> String {
format!("{picker_delegate}/{}", layout_as_str(preview_layout))
}
fn last_layout_key(picker_delegate: &'static str) -> String {
format!("{picker_delegate}/LAST_PREVIEW_LAYOUT")
}
fn layout_as_str(layout: Option<preview::Layout>) -> &'static str {
match layout {
Some(preview::Layout::Hidden) => "hidden",
Some(preview::Layout::Below) => "below",
Some(preview::Layout::Right) => "right",
None => "none",
}
}
fn parse_layout(s: &str) -> anyhow::Result<Option<preview::Layout>> {
Ok(Some(match s {
"hidden" => preview::Layout::Hidden,
"below" => preview::Layout::Below,
"right" => preview::Layout::Right,
"none" => return Ok(None),
_ => return Err(anyhow!("Unknown layout: `{}`", s)),
}))
}
/// A resized picker for persisting its size. All values are stored as fractions
/// of the viewport so they remain meaningful across window sizes.
#[derive(Clone, Copy, serde::Serialize, serde::Deserialize)]
pub(crate) struct PickerConfig {
width: f32, // relative fraction of viewport
height: f32, // relative fraction of viewport
preview_size: f32, // relative fraction of viewport
}
impl PickerConfig {
pub(crate) fn from_centered(shape: Centered, window: &Window) -> Self {
PickerConfig {
width: shape.width.as_viewport_fraction(window).raw(),
height: shape.height.as_viewport_fraction(window).raw(),
preview_size: shape.preview_size.raw(),
}
}
pub(crate) fn into_centered(self) -> Centered {
Centered {
width: RelativeWidth::viewport(self.width.clamp(0.0, 1.0)),
height: RelativeHeight::viewport(self.height.clamp(0.0, 1.0)),
preview_size: ViewportFraction::fraction(self.preview_size.clamp(0.0, 1.0)),
}
}
}