Finish up `ThemeRegistry` and remove `AnyAssetSource`

Marshall Bowers created

Change summary

crates/gpui2/src/app.rs             |  7 +++----
crates/gpui2/src/assets.rs          | 24 +++++-------------------
crates/gpui2/src/svg_renderer.rs    | 10 +++++-----
crates/storybook2/src/assets.rs     |  8 ++++----
crates/storybook2/src/storybook2.rs |  2 +-
crates/theme2/src/registry.rs       | 30 ++++++++++++++++--------------
crates/theme2/src/theme2.rs         |  1 +
crates/zed2/src/assets.rs           |  6 +++---
crates/zed2/src/main.rs             |  2 +-
9 files changed, 39 insertions(+), 51 deletions(-)

Detailed changes

crates/gpui2/src/app.rs 🔗

@@ -13,7 +13,7 @@ use crate::{
     ClipboardItem, Context, DispatchPhase, DisplayId, Executor, FocusEvent, FocusHandle, FocusId,
     KeyBinding, Keymap, LayoutId, MainThread, MainThreadOnly, Pixels, Platform, Point,
     SharedString, SubscriberSet, Subscription, SvgRenderer, Task, TextStyle, TextStyleRefinement,
-    TextSystem, View, Window, WindowContext, WindowHandle, WindowId, AnyAssetSource,
+    TextSystem, View, Window, WindowContext, WindowHandle, WindowId,
 };
 use anyhow::{anyhow, Result};
 use collections::{HashMap, HashSet, VecDeque};
@@ -66,7 +66,6 @@ impl App {
             os_version: platform.os_version().ok(),
             app_version: platform.app_version().ok(),
         };
-        let asset_source = AnyAssetSource(asset_source);
 
         Self(Arc::new_cyclic(|this| {
             Mutex::new(AppContext {
@@ -183,7 +182,7 @@ pub struct AppContext {
     pub(crate) next_frame_callbacks: HashMap<DisplayId, Vec<FrameCallback>>,
     pub(crate) executor: Executor,
     pub(crate) svg_renderer: SvgRenderer,
-    asset_source: AnyAssetSource,
+    asset_source: Arc<dyn AssetSource>,
     pub(crate) image_cache: ImageCache,
     pub(crate) text_style_stack: Vec<TextStyleRefinement>,
     pub(crate) globals_by_type: HashMap<TypeId, AnyBox>,
@@ -511,7 +510,7 @@ impl AppContext {
         });
     }
 
-    pub fn asset_source(&self) -> &AnyAssetSource {
+    pub fn asset_source(&self) -> &Arc<dyn AssetSource> {
         &self.asset_source
     }
 

crates/gpui2/src/assets.rs 🔗

@@ -5,37 +5,23 @@ use std::{
     borrow::Cow,
     fmt,
     hash::Hash,
-    sync::{atomic::{AtomicUsize, Ordering::SeqCst}, Arc},
+    sync::atomic::{AtomicUsize, Ordering::SeqCst},
 };
 
 pub trait AssetSource: 'static + Send + Sync {
-    fn load(&self, path: SharedString) -> Result<Cow<[u8]>>;
-    fn list(&self, path: SharedString) -> Result<Vec<SharedString>>;
+    fn load(&self, path: &str) -> Result<Cow<[u8]>>;
+    fn list(&self, path: &str) -> Result<Vec<SharedString>>;
 }
 
-#[derive(Clone)]
-pub struct AnyAssetSource(pub(crate) Arc<dyn AssetSource>);
-
-impl AnyAssetSource {
-    pub fn load(&self, path: impl Into<SharedString>) -> Result<Cow<[u8]>> {
-        self.0.load(path.into())
-    }
-
-    pub fn list(&self, path: impl Into<SharedString>) -> Result<Vec<SharedString>> {
-        self.0.list(path.into())
-    }
-}
-
-
 impl AssetSource for () {
-    fn load(&self, path: SharedString) -> Result<Cow<[u8]>> {
+    fn load(&self, path: &str) -> Result<Cow<[u8]>> {
         Err(anyhow!(
             "get called on empty asset provider with \"{}\"",
             path
         ))
     }
 
-    fn list(&self, _path: SharedString) -> Result<Vec<SharedString>> {
+    fn list(&self, _path: &str) -> Result<Vec<SharedString>> {
         Ok(vec![])
     }
 }

crates/gpui2/src/svg_renderer.rs 🔗

@@ -1,6 +1,6 @@
-use crate::{DevicePixels, IsZero, Result, SharedString, Size, AnyAssetSource};
+use crate::{DevicePixels, IsZero, Result, SharedString, Size, AssetSource};
 use anyhow::anyhow;
-use std::hash::Hash;
+use std::{hash::Hash, sync::Arc};
 
 #[derive(Clone, PartialEq, Hash, Eq)]
 pub struct RenderSvgParams {
@@ -9,11 +9,11 @@ pub struct RenderSvgParams {
 }
 
 pub struct SvgRenderer {
-    asset_source: AnyAssetSource,
+    asset_source: Arc<dyn AssetSource>,
 }
 
 impl SvgRenderer {
-    pub fn new(asset_source: AnyAssetSource) -> Self {
+    pub fn new(asset_source: Arc<dyn AssetSource>) -> Self {
         Self { asset_source }
     }
 
@@ -23,7 +23,7 @@ impl SvgRenderer {
         }
 
         // Load the tree.
-        let bytes = self.asset_source.load(params.path.clone())?;
+        let bytes = self.asset_source.load(&params.path)?;
         let tree = usvg::Tree::from_data(&bytes, &usvg::Options::default())?;
 
         // Render the SVG to a pixmap with the specified width and height.

crates/storybook2/src/assets.rs 🔗

@@ -15,15 +15,15 @@ use rust_embed::RustEmbed;
 pub struct Assets;
 
 impl AssetSource for Assets {
-    fn load(&self, path: SharedString) -> Result<Cow<[u8]>> {
-        Self::get(path.as_ref())
+    fn load(&self, path: &str) -> Result<Cow<[u8]>> {
+        Self::get(path)
             .map(|f| f.data)
             .ok_or_else(|| anyhow!("could not find asset at path \"{}\"", path))
     }
 
-    fn list(&self, path: SharedString) -> Result<Vec<SharedString>> {
+    fn list(&self, path: &str) -> Result<Vec<SharedString>> {
         Ok(Self::iter()
-            .filter(|p| p.starts_with(path.as_ref()))
+            .filter(|p| p.starts_with(path))
             .map(SharedString::from)
             .collect())
     }

crates/storybook2/src/storybook2.rs 🔗

@@ -108,7 +108,7 @@ fn load_embedded_fonts(cx: &AppContext) -> gpui2::Result<()> {
     let mut embedded_fonts = Vec::new();
     for font_path in font_paths {
         if font_path.ends_with(".ttf") {
-            let font_bytes = cx.asset_source().load(font_path)?.to_vec();
+            let font_bytes = cx.asset_source().load(&font_path)?.to_vec();
             embedded_fonts.push(Arc::from(font_bytes));
         }
     }

crates/theme2/src/registry.rs 🔗

@@ -1,17 +1,14 @@
-use crate::{Theme, ThemeMetadata, themes::one_dark};
-use anyhow::Result;
-use gpui2::{AnyAssetSource, SharedString};
-use std::{
-    collections::HashMap,
-    sync::Arc
-};
+use crate::{themes::one_dark, Theme, ThemeMetadata};
+use anyhow::{anyhow, Result};
+use gpui2::SharedString;
+use std::{collections::HashMap, sync::Arc};
 
 pub struct ThemeRegistry {
     themes: HashMap<SharedString, Arc<Theme>>,
 }
 
 impl ThemeRegistry {
-    pub fn new(assets: AnyAssetSource) -> Self {
+    pub fn new() -> Self {
         let mut this = Self {
             themes: HashMap::default(),
         };
@@ -23,19 +20,24 @@ impl ThemeRegistry {
 
     fn insert_themes(&mut self, themes: impl IntoIterator<Item = Theme>) {
         for theme in themes.into_iter() {
-            self.themes.insert(theme.metadata.name.clone(), Arc::new(theme));
+            self.themes
+                .insert(theme.metadata.name.clone(), Arc::new(theme));
         }
     }
 
-    pub fn list_names(&self, staff: bool) -> impl Iterator<Item = SharedString> + '_ {
-        None.into_iter()
+    pub fn list_names(&self, _staff: bool) -> impl Iterator<Item = SharedString> + '_ {
+        self.themes.keys().cloned()
     }
 
-    pub fn list(&self, staff: bool) -> impl Iterator<Item = ThemeMetadata> + '_ {
-        None.into_iter()
+    pub fn list(&self, _staff: bool) -> impl Iterator<Item = ThemeMetadata> + '_ {
+        self.themes.values().map(|theme| theme.metadata.clone())
     }
 
     pub fn get(&self, name: impl Into<SharedString>) -> Result<Arc<Theme>> {
-        todo!()
+        let name = name.into();
+        self.themes
+            .get(&name)
+            .ok_or_else(|| anyhow!("theme not found: {}", name))
+            .cloned()
     }
 }

crates/theme2/src/theme2.rs 🔗

@@ -93,6 +93,7 @@ pub struct PlayerTheme {
     pub selection: Hsla,
 }
 
+#[derive(Clone)]
 pub struct ThemeMetadata {
     pub name: SharedString,
     pub is_light: bool,

crates/zed2/src/assets.rs 🔗

@@ -13,16 +13,16 @@ use rust_embed::RustEmbed;
 pub struct Assets;
 
 impl AssetSource for Assets {
-    fn load(&self, path: &SharedString) -> Result<std::borrow::Cow<[u8]>> {
+    fn load(&self, path: &str) -> Result<std::borrow::Cow<[u8]>> {
         Self::get(path)
             .map(|f| f.data)
             .ok_or_else(|| anyhow!("could not find asset at path \"{}\"", path))
     }
 
-    fn list(&self, path: &SharedString) -> Result<Vec<SharedString>> {
+    fn list(&self, path: &str) -> Result<Vec<SharedString>> {
         Ok(Self::iter()
             .filter_map(|p| {
-                if p.starts_with(path.as_ref()) {
+                if p.starts_with(path) {
                     Some(p.into())
                 } else {
                     None

crates/zed2/src/main.rs 🔗

@@ -11,7 +11,7 @@ use cli::{
 use db2::kvp::KEY_VALUE_STORE;
 use fs::RealFs;
 use futures::{channel::mpsc, SinkExt, StreamExt};
-use gpui2::{App, AppContext, AssetSource, AsyncAppContext, SemanticVersion, Task};
+use gpui2::{App, AppContext, AsyncAppContext, SemanticVersion, Task};
 use isahc::{prelude::Configurable, Request};
 use language2::LanguageRegistry;
 use log::LevelFilter;