Deserialize Theme directly into the heap to avoid stack overflow

Co-Authored-By: Julia Risley <julia@zed.dev>
This commit is contained in:
Antonio Scandurra 2023-03-17 15:39:24 +01:00
parent 786d95b8c8
commit 1af8f4be19
32 changed files with 72 additions and 7 deletions

View file

@ -14,6 +14,7 @@ anyhow = "1.0.38"
indexmap = "1.6.2"
parking_lot = "0.11.1"
serde = { version = "1.0", features = ["derive", "rc"] }
serde_derive = { version = "1.0", features = ["deserialize_in_place"] }
serde_json = { version = "1.0", features = ["preserve_order"] }
serde_path_to_error = "0.1.4"
toml = "0.5"

View file

@ -2,6 +2,7 @@ use crate::{Theme, ThemeMeta};
use anyhow::{Context, Result};
use gpui::{fonts, AssetSource, FontCache};
use parking_lot::Mutex;
use serde::Deserialize;
use serde_json::Value;
use std::{collections::HashMap, sync::Arc};
@ -56,12 +57,16 @@ impl ThemeRegistry {
.with_context(|| format!("failed to load theme file {}", asset_path))?;
// Allocate into the heap directly, the Theme struct is too large to fit in the stack.
let mut theme: Arc<Theme> = fonts::with_font_cache(self.font_cache.clone(), || {
serde_path_to_error::deserialize(&mut serde_json::Deserializer::from_slice(&theme_json))
let mut theme = fonts::with_font_cache(self.font_cache.clone(), || {
let mut theme = Box::new(Theme::default());
let mut deserializer = serde_json::Deserializer::from_slice(&theme_json);
let result = Theme::deserialize_in_place(&mut deserializer, &mut theme);
result.map(|_| theme)
})?;
// Reset name to be the file path, so that we can use it to access the stored themes
Arc::get_mut(&mut theme).unwrap().meta.name = name.into();
theme.meta.name = name.into();
let theme: Arc<Theme> = theme.into();
self.themes.lock().insert(name.to_string(), theme.clone());
Ok(theme)
}