diff --git a/Cargo.lock b/Cargo.lock index c4bf18ec7e4b27d7ca94fd524514dc60853aa90f..c4a3210ab2d248d7ff3f1a0abf72f20d8ae68dbd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -153,7 +153,7 @@ dependencies = [ "db", "derive_more 0.99.20", "editor", - "encoding_rs", + "encodings", "env_logger 0.11.8", "fs", "futures 0.3.31", @@ -3355,7 +3355,7 @@ dependencies = [ "dashmap 6.1.0", "debugger_ui", "editor", - "encoding_rs", + "encodings", "envy", "extension", "file_finder", @@ -3722,7 +3722,7 @@ dependencies = [ "dirs 4.0.0", "edit_prediction", "editor", - "encoding_rs", + "encodings", "fs", "futures 0.3.31", "gpui", @@ -5928,7 +5928,7 @@ dependencies = [ "criterion", "ctor", "dap", - "encoding_rs", + "encodings", "extension", "fs", "futures 0.3.31", @@ -6428,7 +6428,7 @@ dependencies = [ "async-trait", "cocoa 0.26.0", "collections", - "encoding_rs", + "encodings", "fsevent", "futures 0.3.31", "git", @@ -7130,7 +7130,7 @@ dependencies = [ "ctor", "db", "editor", - "encoding_rs", + "encodings", "futures 0.3.31", "fuzzy", "git", @@ -8805,7 +8805,7 @@ dependencies = [ "ctor", "diffy", "ec4rs", - "encoding_rs", + "encodings", "fs", "futures 0.3.31", "fuzzy", @@ -13021,7 +13021,7 @@ dependencies = [ "context_server", "dap", "dap_adapters", - "encoding_rs", + "encodings", "extension", "fancy-regex 0.14.0", "fs", @@ -13997,7 +13997,7 @@ dependencies = [ "dap_adapters", "debug_adapter_extension", "editor", - "encoding_rs", + "encodings", "env_logger 0.11.8", "extension", "extension_host", @@ -20762,7 +20762,7 @@ dependencies = [ "component", "dap", "db", - "encoding_rs", + "encodings", "fs", "futures 0.3.31", "gpui", @@ -20805,7 +20805,7 @@ dependencies = [ "async-lock 2.8.0", "clock", "collections", - "encoding_rs", + "encodings", "fs", "futures 0.3.31", "fuzzy", @@ -21215,7 +21215,7 @@ dependencies = [ "diagnostics", "edit_prediction_button", "editor", - "encoding_rs", + "encodings", "encodings_ui", "env_logger 0.11.8", "extension", diff --git a/crates/agent/src/tools/edit_file_tool.rs b/crates/agent/src/tools/edit_file_tool.rs index 6764a1759e81d6b7574a2e81b8039f0723fa5b24..e7843d3388139f14aa1686fa0016dbfc5d9fdb48 100644 --- a/crates/agent/src/tools/edit_file_tool.rs +++ b/crates/agent/src/tools/edit_file_tool.rs @@ -563,8 +563,8 @@ mod tests { use super::*; use crate::{ContextServerRegistry, Templates}; use client::TelemetrySettings; - use encoding_rs::UTF_8; - use fs::{Fs, encodings::EncodingWrapper}; + use encodings::{Encoding, UTF_8}; + use fs::Fs; use gpui::{TestAppContext, UpdateGlobal}; use language_model::fake_provider::FakeLanguageModel; use prompt_store::ProjectContext; @@ -745,7 +745,7 @@ mod tests { path!("/root/src/main.rs").as_ref(), &Rope::from_str_small("initial content"), language::LineEnding::Unix, - EncodingWrapper::new(UTF_8), + Encoding::new(UTF_8), ) .await .unwrap(); @@ -913,7 +913,7 @@ mod tests { path!("/root/src/main.rs").as_ref(), &Rope::from_str_small("initial content"), language::LineEnding::Unix, - EncodingWrapper::new(UTF_8), + Encoding::default(), ) .await .unwrap(); diff --git a/crates/agent2/Cargo.toml b/crates/agent2/Cargo.toml index 4135f07710970a359dc083c122778fdc5505772e..e481af9c834424237b9c580c664f516f604aeb03 100644 --- a/crates/agent2/Cargo.toml +++ b/crates/agent2/Cargo.toml @@ -32,7 +32,7 @@ cloud_llm_client.workspace = true collections.workspace = true context_server.workspace = true db.workspace = true -encoding_rs.workspace = true +encodings.workspace = true fs.workspace = true futures.workspace = true git.workspace = true diff --git a/crates/assistant_tools/Cargo.toml b/crates/assistant_tools/Cargo.toml index dff6caccef9979fef7185db8da575aa9990c8b11..b31561305dec86bdbe829adcee5187463f454879 100644 --- a/crates/assistant_tools/Cargo.toml +++ b/crates/assistant_tools/Cargo.toml @@ -28,7 +28,7 @@ component.workspace = true derive_more.workspace = true diffy = "0.4.2" editor.workspace = true -encoding_rs.workspace = true +encodings.workspace = true feature_flags.workspace = true futures.workspace = true gpui.workspace = true diff --git a/crates/assistant_tools/src/edit_file_tool.rs b/crates/assistant_tools/src/edit_file_tool.rs index 4a3e755a35dc79dcaa80ecb29a96d73b52aff711..eea65b173ff3ca2c2b6d8663d77ac7013d9121aa 100644 --- a/crates/assistant_tools/src/edit_file_tool.rs +++ b/crates/assistant_tools/src/edit_file_tool.rs @@ -1229,9 +1229,10 @@ async fn build_buffer_diff( #[cfg(test)] mod tests { use super::*; - use ::fs::{Fs, encodings::EncodingWrapper}; + use ::fs::Fs; use client::TelemetrySettings; - use encoding_rs::UTF_8; + use encodings::Encoding; + use encodings::UTF_8; use gpui::{TestAppContext, UpdateGlobal}; use language_model::fake_provider::FakeLanguageModel; use serde_json::json; @@ -1500,7 +1501,7 @@ mod tests { path!("/root/src/main.rs").as_ref(), &"initial content".into(), language::LineEnding::Unix, - EncodingWrapper::new(UTF_8), + Encoding::new(UTF_8), ) .await .unwrap(); @@ -1670,7 +1671,7 @@ mod tests { path!("/root/src/main.rs").as_ref(), &"initial content".into(), language::LineEnding::Unix, - EncodingWrapper::new(UTF_8), + Encoding::default(), ) .await .unwrap(); diff --git a/crates/collab/Cargo.toml b/crates/collab/Cargo.toml index 82a0b7141e3b04f72d4d6d4d56bde3524a0473d1..01ef52291fa089fa5b3d211d3dde2e1a7de8112a 100644 --- a/crates/collab/Cargo.toml +++ b/crates/collab/Cargo.toml @@ -31,7 +31,7 @@ chrono.workspace = true clock.workspace = true collections.workspace = true dashmap.workspace = true -encoding_rs.workspace = true +encodings.workspace = true envy = "0.4.2" futures.workspace = true gpui.workspace = true diff --git a/crates/collab/src/tests/integration_tests.rs b/crates/collab/src/tests/integration_tests.rs index 0b65c91625801aa7d1e308d69d8c13c836a4a6cd..1adb2ae5fb65dc775918eb1774cb526e88c5f652 100644 --- a/crates/collab/src/tests/integration_tests.rs +++ b/crates/collab/src/tests/integration_tests.rs @@ -12,8 +12,8 @@ use buffer_diff::{DiffHunkSecondaryStatus, DiffHunkStatus, assert_hunks}; use call::{ActiveCall, ParticipantLocation, Room, room}; use client::{RECEIVE_TIMEOUT, User}; use collections::{HashMap, HashSet}; -use encoding_rs::UTF_8; -use fs::{FakeFs, Fs as _, RemoveOptions, encodings::EncodingWrapper}; +use encodings::Encoding; +use fs::{FakeFs, Fs as _, RemoveOptions}; use futures::{StreamExt as _, channel::mpsc}; use git::{ repository::repo_path, @@ -3702,7 +3702,7 @@ async fn test_buffer_reloading( path!("/dir/a.txt").as_ref(), &new_contents, LineEnding::Windows, - EncodingWrapper::new(UTF_8), + Encoding::default(), ) .await .unwrap(); @@ -4483,7 +4483,7 @@ async fn test_reloading_buffer_manually( path!("/a/a.rs").as_ref(), &Rope::from_str_small("let seven = 7;"), LineEnding::Unix, - EncodingWrapper::new(UTF_8), + Encoding::default(), ) .await .unwrap(); diff --git a/crates/collab/src/tests/random_project_collaboration_tests.rs b/crates/collab/src/tests/random_project_collaboration_tests.rs index c7571665574d6cd76f16f9ab265d05550a944548..9f0c47bcd722ef95af57b317b8e2e8cc9dfcb2f5 100644 --- a/crates/collab/src/tests/random_project_collaboration_tests.rs +++ b/crates/collab/src/tests/random_project_collaboration_tests.rs @@ -5,8 +5,8 @@ use async_trait::async_trait; use call::ActiveCall; use collections::{BTreeMap, HashMap}; use editor::Bias; -use encoding_rs::UTF_8; -use fs::{FakeFs, Fs as _, encodings::EncodingWrapper}; +use encodings::Encoding; +use fs::{FakeFs, Fs as _}; use git::status::{FileStatus, StatusCode, TrackedStatus, UnmergedStatus, UnmergedStatusCode}; use gpui::{BackgroundExecutor, Entity, TestAppContext}; use language::{ @@ -944,7 +944,7 @@ impl RandomizedTest for ProjectCollaborationTest { &path, &Rope::from_str_small(content.as_str()), text::LineEnding::Unix, - EncodingWrapper::new(UTF_8), + Encoding::default(), ) .await .unwrap(); diff --git a/crates/copilot/Cargo.toml b/crates/copilot/Cargo.toml index 129afaaffb13b3ce038856d86832ff22eabc6938..ba7209368a4f5aa156e9a4bab3837070d7d9aaef 100644 --- a/crates/copilot/Cargo.toml +++ b/crates/copilot/Cargo.toml @@ -30,7 +30,7 @@ client.workspace = true collections.workspace = true command_palette_hooks.workspace = true dirs.workspace = true -encoding_rs.workspace = true +encodings.workspace = true fs.workspace = true futures.workspace = true gpui.workspace = true diff --git a/crates/copilot/src/copilot.rs b/crates/copilot/src/copilot.rs index e5dca4d7b48be3ec45b821ce0a79c21ae8092a96..28828db43170b980b58e87bf718780b4b68e7826 100644 --- a/crates/copilot/src/copilot.rs +++ b/crates/copilot/src/copilot.rs @@ -1241,8 +1241,7 @@ async fn get_copilot_lsp(fs: Arc, node_runtime: NodeRuntime) -> anyhow:: #[cfg(test)] mod tests { use super::*; - use fs::encodings::EncodingWrapper; - use encoding_rs::Encoding; + use encodings::Encoding; use gpui::TestAppContext; use util::{path, paths::PathStyle, rel_path::rel_path}; @@ -1453,7 +1452,14 @@ mod tests { self.abs_path.clone() } - fn load(&self, _: &App, _: EncodingWrapper, _: bool, _: bool, _: Option>>) -> Task> { + fn load( + &self, + _: &App, + _: Encoding, + _: bool, + _: bool, + _: Option>, + ) -> Task> { unimplemented!() } diff --git a/crates/encodings/src/lib.rs b/crates/encodings/src/lib.rs index e3baad901670373ff0fb0586fbdd73ee7ef2aafb..556dfba766336fd6fd9f546ed4cd6cdfc2b34205 100644 --- a/crates/encodings/src/lib.rs +++ b/crates/encodings/src/lib.rs @@ -22,6 +22,12 @@ impl Debug for Encoding { } } +impl Clone for Encoding { + fn clone(&self) -> Self { + Encoding(Mutex::new(self.get())) + } +} + impl Default for Encoding { fn default() -> Self { Encoding(Mutex::new(UTF_8)) diff --git a/crates/encodings_ui/src/lib.rs b/crates/encodings_ui/src/lib.rs index 591d6e5349350b2b13aab4dd58623fdba6f23c90..2e01c41e08cd51df07b22813d1df7011a249a000 100644 --- a/crates/encodings_ui/src/lib.rs +++ b/crates/encodings_ui/src/lib.rs @@ -120,7 +120,7 @@ impl EncodingIndicator { let editor = editor.read(cx); if let Some((_, buffer, _)) = editor.active_excerpt(cx) { let encoding = buffer.read(cx).encoding.clone(); - self.encoding = Some(&*encoding.lock().unwrap()); + self.encoding = Some(encoding.get()); if let Some(_) = buffer.read(cx).file() { self.show_save_or_reopen_selector = true; @@ -140,7 +140,7 @@ impl EncodingIndicator { cx: &mut Context, ) { let encoding = buffer.read(cx).encoding.clone(); - self.encoding = Some(&*encoding.lock().unwrap()); + self.encoding = Some(encoding.get()); cx.notify(); } } diff --git a/crates/encodings_ui/src/selectors.rs b/crates/encodings_ui/src/selectors.rs index f3345c57299d6a89b1da17bc015332461049f770..b049c9583d4693daff95e9f319db3a561fcccad8 100644 --- a/crates/encodings_ui/src/selectors.rs +++ b/crates/encodings_ui/src/selectors.rs @@ -278,7 +278,6 @@ pub mod save_or_reopen { /// This module contains the encoding selector for choosing an encoding to save or reopen a file with. pub mod encoding { use editor::Editor; - use fs::encodings::EncodingWrapper; use std::{path::PathBuf, sync::atomic::AtomicBool}; use fuzzy::{StringMatch, StringMatchCandidate}; @@ -449,8 +448,9 @@ pub mod encoding { // By limiting the scope, we ensure that it is released { let buffer_encoding = buffer.encoding.clone(); - *buffer_encoding.lock().unwrap() = - encoding_from_name(self.matches[self.current_selection].string.as_str()); + buffer_encoding.set(encoding_from_name( + self.matches[self.current_selection].string.as_str(), + )); } self.dismissed(window, cx); @@ -481,8 +481,12 @@ pub mod encoding { encoding_from_name(self.matches[self.current_selection].string.as_str()); let open_task = workspace.update(cx, |workspace, cx| { - *workspace.encoding_options.encoding.lock().unwrap() = - EncodingWrapper::new(encoding); + workspace + .encoding_options + .encoding + .lock() + .unwrap() + .set(encoding); workspace.open_abs_path(path, OpenOptions::default(), window, cx) }); @@ -510,7 +514,7 @@ pub mod encoding { { buffer .read_with(cx, |buffer, _| { - *buffer.encoding.lock().unwrap() = encoding; + buffer.encoding.set(encoding); }) .log_err(); } diff --git a/crates/extension_host/Cargo.toml b/crates/extension_host/Cargo.toml index 4db3672bbd782e444ca3616f39e2b70a147e80d9..229f2e2d185c4bdf9271a594fa3daf49d122f954 100644 --- a/crates/extension_host/Cargo.toml +++ b/crates/extension_host/Cargo.toml @@ -23,7 +23,7 @@ async-trait.workspace = true client.workspace = true collections.workspace = true dap.workspace = true -encoding_rs.workspace = true +encodings.workspace = true extension.workspace = true fs.workspace = true futures.workspace = true diff --git a/crates/extension_host/src/extension_host.rs b/crates/extension_host/src/extension_host.rs index f79d4fd00ea0e4cdc0e42361f5b9fe09ec550d02..c58bce9d51a87729a04c6ddda3f4ba7fe47bdba1 100644 --- a/crates/extension_host/src/extension_host.rs +++ b/crates/extension_host/src/extension_host.rs @@ -12,7 +12,7 @@ use async_tar::Archive; use client::ExtensionProvides; use client::{Client, ExtensionMetadata, GetExtensionsResponse, proto, telemetry::Telemetry}; use collections::{BTreeMap, BTreeSet, HashMap, HashSet, btree_map}; -use encoding_rs::UTF_8; +use encodings::Encoding; pub use extension::ExtensionManifest; use extension::extension_builder::{CompileExtensionOptions, ExtensionBuilder}; use extension::{ @@ -21,7 +21,6 @@ use extension::{ ExtensionLanguageServerProxy, ExtensionSlashCommandProxy, ExtensionSnippetProxy, ExtensionThemeProxy, }; -use fs::encodings::EncodingWrapper; use fs::{Fs, RemoveOptions}; use futures::future::join_all; use futures::{ @@ -1508,7 +1507,7 @@ impl ExtensionStore { &index_path, &Rope::from_str(&index_json, &executor), Default::default(), - EncodingWrapper::new(UTF_8), + Encoding::default(), ) .await .context("failed to save extension index") @@ -1681,7 +1680,7 @@ impl ExtensionStore { &tmp_dir.join(EXTENSION_TOML), &Rope::from_str_small(&manifest_toml), language::LineEnding::Unix, - EncodingWrapper::new(UTF_8), + Encoding::default(), ) .await?; } else { diff --git a/crates/fs/Cargo.toml b/crates/fs/Cargo.toml index a9e1028f608d0741b47a7277066bb55e07ccb75a..25867218d57176407ea28c62774c7792993d57d4 100644 --- a/crates/fs/Cargo.toml +++ b/crates/fs/Cargo.toml @@ -16,7 +16,7 @@ anyhow.workspace = true async-tar.workspace = true async-trait.workspace = true collections.workspace = true -encoding_rs.workspace = true +encodings.workspace = true futures.workspace = true git.workspace = true gpui.workspace = true diff --git a/crates/fs/src/encodings.rs b/crates/fs/src/encodings.rs deleted file mode 100644 index 16aab79e77ad929a95b25ebd5976949ba03c933b..0000000000000000000000000000000000000000 --- a/crates/fs/src/encodings.rs +++ /dev/null @@ -1,152 +0,0 @@ -//! Encoding and decoding utilities using the `encoding_rs` crate. -use std::{ - fmt::Debug, - sync::{Arc, Mutex}, -}; - -use std::sync::atomic::AtomicBool; - -use anyhow::Result; -use encoding_rs::Encoding; - -/// A wrapper around `encoding_rs::Encoding` to implement `Send` and `Sync`. -/// Since the reference is static, it is safe to send it across threads. -#[derive(Copy)] -pub struct EncodingWrapper(pub &'static Encoding); - -impl Debug for EncodingWrapper { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.debug_tuple(&format!("EncodingWrapper{:?}", self.0)) - .field(&self.0.name()) - .finish() - } -} - -impl Default for EncodingWrapper { - fn default() -> Self { - EncodingWrapper(encoding_rs::UTF_8) - } -} - -impl PartialEq for EncodingWrapper { - fn eq(&self, other: &Self) -> bool { - self.0.name() == other.0.name() - } -} - -unsafe impl Send for EncodingWrapper {} -unsafe impl Sync for EncodingWrapper {} - -impl Clone for EncodingWrapper { - fn clone(&self) -> Self { - EncodingWrapper(self.0) - } -} - -impl EncodingWrapper { - pub fn new(encoding: &'static Encoding) -> EncodingWrapper { - EncodingWrapper(encoding) - } - - pub fn get_encoding(&self) -> &'static Encoding { - self.0 - } - - pub async fn decode( - &mut self, - input: Vec, - force: bool, - detect_utf16: bool, - buffer_encoding: Option>>, - ) -> Result { - // Check if the input starts with a BOM for UTF-16 encodings only if detect_utf16 is true. - if detect_utf16 { - if let Some(encoding) = match input.get(..2) { - Some([0xFF, 0xFE]) => Some(encoding_rs::UTF_16LE), - Some([0xFE, 0xFF]) => Some(encoding_rs::UTF_16BE), - _ => None, - } { - self.0 = encoding; - - if let Some(v) = buffer_encoding - && let Ok(mut v) = v.lock() - { - *v = encoding; - } - } - } - - let (cow, had_errors) = self.0.decode_with_bom_removal(&input); - - if force { - return Ok(cow.to_string()); - } - - if !had_errors { - Ok(cow.to_string()) - } else { - Err(anyhow::anyhow!( - "The file contains invalid bytes for the specified encoding: {}.\nThis usually means that the file is not a regular text file, or is encoded in a different encoding.\nContinuing to open it may result in data loss if saved.", - self.0.name() - )) - } - } - - pub async fn encode(&self, input: String) -> Result> { - if self.0 == encoding_rs::UTF_16BE { - let mut data = Vec::::with_capacity(input.len() * 2); - - // Convert the input string to UTF-16BE bytes - let utf16be_bytes = input.encode_utf16().flat_map(|u| u.to_be_bytes()); - - data.extend(utf16be_bytes); - return Ok(data); - } else if self.0 == encoding_rs::UTF_16LE { - let mut data = Vec::::with_capacity(input.len() * 2); - - // Convert the input string to UTF-16LE bytes - let utf16le_bytes = input.encode_utf16().flat_map(|u| u.to_le_bytes()); - - data.extend(utf16le_bytes); - return Ok(data); - } else { - let (cow, _encoding_used, _had_errors) = self.0.encode(&input); - - Ok(cow.into_owned()) - } - } -} - -/// Convert a byte vector from a specified encoding to a UTF-8 string. -pub async fn to_utf8( - input: Vec, - mut encoding: EncodingWrapper, - force: bool, - detect_utf16: bool, - buffer_encoding: Option>>, -) -> Result { - encoding - .decode(input, force, detect_utf16, buffer_encoding) - .await -} - -/// Convert a UTF-8 string to a byte vector in a specified encoding. -pub async fn from_utf8(input: String, target: EncodingWrapper) -> Result> { - target.encode(input).await -} - -pub struct EncodingOptions { - pub encoding: Arc>, - pub force: AtomicBool, - pub detect_utf16: AtomicBool, -} - -impl Default for EncodingOptions { - fn default() -> Self { - EncodingOptions { - encoding: Arc::new(Mutex::new(EncodingWrapper::default())), - force: AtomicBool::new(false), - detect_utf16: AtomicBool::new(true), - } - } -} diff --git a/crates/fs/src/fs.rs b/crates/fs/src/fs.rs index 344d9da893b0fb3bdab4f6962a6df72719175e87..00dd220fbaa16f82251150e1b8eb6470e4c4fee3 100644 --- a/crates/fs/src/fs.rs +++ b/crates/fs/src/fs.rs @@ -1,7 +1,6 @@ #[cfg(target_os = "macos")] mod mac_watcher; -pub mod encodings; #[cfg(not(target_os = "macos"))] pub mod fs_watcher; @@ -9,7 +8,7 @@ use anyhow::{Context as _, Result, anyhow}; #[cfg(any(target_os = "linux", target_os = "freebsd"))] use ashpd::desktop::trash; use futures::stream::iter; -use encoding_rs::Encoding; +use encodings::Encoding; use gpui::App; use gpui::BackgroundExecutor; use gpui::Global; @@ -62,9 +61,9 @@ use std::ffi::OsStr; #[cfg(any(test, feature = "test-support"))] pub use fake_git_repo::{LOAD_HEAD_TEXT_TASK, LOAD_INDEX_TEXT_TASK}; -use crate::encodings::EncodingWrapper; -use crate::encodings::from_utf8; -use crate::encodings::to_utf8; +use encodings::Encoding; +use encodings::from_utf8; +use encodings::to_utf8; pub trait Watcher: Send + Sync { fn add(&self, path: &Path) -> Result<()>; @@ -124,10 +123,10 @@ pub trait Fs: Send + Sync { async fn load_with_encoding( &self, path: &Path, - encoding: EncodingWrapper, + encoding: Encoding, force: bool, detect_utf16: bool, - buffer_encoding: Option>>, + buffer_encoding: Option>, ) -> Result { Ok(to_utf8( self.load_bytes(path).await?, @@ -146,7 +145,7 @@ pub trait Fs: Send + Sync { path: &Path, text: &Rope, line_ending: LineEnding, - encoding: EncodingWrapper, + encoding: Encoding, ) -> Result<()>; async fn write(&self, path: &Path, content: &[u8]) -> Result<()>; async fn canonicalize(&self, path: &Path) -> Result; @@ -693,7 +692,7 @@ impl Fs for RealFs { path: &Path, text: &Rope, line_ending: LineEnding, - encoding: EncodingWrapper, + encoding: Encoding, ) -> Result<()> { let buffer_size = text.summary().len.min(10 * 1024); if let Some(path) = path.parent() { @@ -704,18 +703,18 @@ impl Fs for RealFs { // BOM for UTF-16 is written at the start of the file here because // if BOM is written in the `encode` function of `fs::encodings`, it would be written - // for every chunk, resulting in multiple BOMs in the file. - if encoding.get_encoding() == encoding_rs::UTF_16BE { + // twice. Hence, it is written only here. + if encoding.get() == encodings::UTF_16BE { // Write BOM for UTF-16BE writer.write_all(&[0xFE, 0xFF]).await?; - } else if encoding.get_encoding() == encoding_rs::UTF_16LE { + } else if encoding.get() == encodings::UTF_16LE { // Write BOM for UTF-16LE writer.write_all(&[0xFF, 0xFE]).await?; } for chunk in chunks(text, line_ending) { writer - .write_all(&from_utf8(chunk.to_string(), encoding.clone()).await?) + .write_all(&from_utf8(chunk.to_string(), Encoding::new(encoding.get())).await?) .await? } @@ -2435,9 +2434,9 @@ impl Fs for FakeFs { path: &Path, text: &Rope, line_ending: LineEnding, - encoding: EncodingWrapper, + encoding: Encoding, ) -> Result<()> { - use crate::encodings::from_utf8; + use encodings::from_utf8; self.simulate_random_delay().await; let path = normalize_path(path); diff --git a/crates/git_ui/Cargo.toml b/crates/git_ui/Cargo.toml index 9ab0042edd81f10e760f32e63f00355fa9cabb29..6a8d9d3daf10b64d96aa9b92e7288e96b7b33939 100644 --- a/crates/git_ui/Cargo.toml +++ b/crates/git_ui/Cargo.toml @@ -29,7 +29,7 @@ command_palette_hooks.workspace = true component.workspace = true db.workspace = true editor.workspace = true -encoding_rs.workspace = true +encodings.workspace = true futures.workspace = true fuzzy.workspace = true git.workspace = true diff --git a/crates/git_ui/src/file_diff_view.rs b/crates/git_ui/src/file_diff_view.rs index a14524a2caff0b8ecebb0471ab9312e4dcf8e902..7746ac8519250d020299aa6b02807c8bea30f0c9 100644 --- a/crates/git_ui/src/file_diff_view.rs +++ b/crates/git_ui/src/file_diff_view.rs @@ -358,7 +358,7 @@ impl Render for FileDiffView { mod tests { use super::*; use editor::test::editor_test_context::assert_state_with_diff; - use encoding_rs::UTF_8; + use encodings::Encoding; use gpui::TestAppContext; use language::Rope; use project::{FakeFs, Fs, Project}; @@ -442,7 +442,7 @@ mod tests { ", )), Default::default(), - EncodingWrapper::new(UTF_8), + Encoding::default(), ) .await .unwrap(); @@ -477,7 +477,7 @@ mod tests { ", )), Default::default(), - EncodingWrapper::new(UTF_8), + Encoding::default(), ) .await .unwrap(); diff --git a/crates/language/Cargo.toml b/crates/language/Cargo.toml index 42610ce9c59983e4bd642658dfdfe50179428357..2afc02893fd6a78da4172ffd232d4118036007d9 100644 --- a/crates/language/Cargo.toml +++ b/crates/language/Cargo.toml @@ -32,7 +32,7 @@ clock.workspace = true collections.workspace = true diffy = "0.4.2" ec4rs.workspace = true -encoding_rs.workspace = true +encodings.workspace = true fs.workspace = true futures.workspace = true fuzzy.workspace = true diff --git a/crates/language/src/buffer.rs b/crates/language/src/buffer.rs index 2668e4dc75d41bf6a87aefada19b79aea3d99ba4..dd5569ce645b8be693d68c00db28c1afe81c8968 100644 --- a/crates/language/src/buffer.rs +++ b/crates/language/src/buffer.rs @@ -21,8 +21,8 @@ use anyhow::{Context as _, Result}; use clock::Lamport; pub use clock::ReplicaId; use collections::HashMap; -use encoding_rs::Encoding; -use fs::{MTime, encodings::EncodingWrapper}; +use encodings::Encoding; +use fs::MTime; use futures::channel::oneshot; use gpui::{ App, AppContext as _, BackgroundExecutor, Context, Entity, EventEmitter, HighlightStyle, @@ -127,7 +127,7 @@ pub struct Buffer { has_unsaved_edits: Cell<(clock::Global, bool)>, change_bits: Vec>>, _subscriptions: Vec, - pub encoding: Arc>, + pub encoding: Arc, pub observe_file_encoding: Option, } @@ -375,7 +375,7 @@ pub trait File: Send + Sync + Any { /// Return whether Zed considers this to be a private file. fn is_private(&self) -> bool; - fn encoding(&self) -> Option>> { + fn encoding(&self) -> Option> { unimplemented!() } } @@ -422,10 +422,10 @@ pub trait LocalFile: File { fn load( &self, cx: &App, - encoding: EncodingWrapper, + encoding: Encoding, force: bool, detect_utf16: bool, - buffer_encoding: Option>>, + buffer_encoding: Option>, ) -> Task>; /// Loads the file's contents from disk. @@ -1032,7 +1032,7 @@ impl Buffer { has_conflict: false, change_bits: Default::default(), _subscriptions: Vec::new(), - encoding: Arc::new(std::sync::Mutex::new(encoding_rs::UTF_8)), + encoding: Arc::new(Encoding::new(encodings::UTF_8)), observe_file_encoding: None, } } @@ -1369,7 +1369,8 @@ impl Buffer { /// Reloads the contents of the buffer from disk. pub fn reload(&mut self, cx: &Context) -> oneshot::Receiver> { let (tx, rx) = futures::channel::oneshot::channel(); - let encoding = EncodingWrapper::new(*(self.encoding.lock().unwrap())); + let encoding = self.encoding.clone(); + let buffer_encoding = self.encoding.clone(); let prev_version = self.text.version(); @@ -1377,7 +1378,7 @@ impl Buffer { let Some((new_mtime, new_text)) = this.update(cx, |this, cx| { let file = this.file.as_ref()?.as_local()?; Some((file.disk_state().mtime(), { - file.load(cx, encoding, false, true, Some(buffer_encoding)) + file.load(cx, (*encoding).clone(), false, true, Some(buffer_encoding)) })) })? else { @@ -2939,9 +2940,9 @@ impl Buffer { pub fn update_encoding(&mut self) { if let Some(file) = self.file() { if let Some(encoding) = file.encoding() { - *self.encoding.lock().unwrap() = *encoding.lock().unwrap(); + self.encoding.set(encoding.get()); } else { - *self.encoding.lock().unwrap() = encoding_rs::UTF_8; + self.encoding.set(encodings::UTF_8); }; } } @@ -5269,10 +5270,10 @@ impl LocalFile for TestFile { fn load( &self, _cx: &App, - _encoding: EncodingWrapper, + _encoding: Encoding, _force: bool, _detect_utf16: bool, - _buffer_encoding: Option>>, + _buffer_encoding: Option>, ) -> Task> { unimplemented!() } diff --git a/crates/project/Cargo.toml b/crates/project/Cargo.toml index d000a036ec76170e0516c28b480bfd49764f72f5..d05cdef0b3d1c7d612622910528cde3dd62108b2 100644 --- a/crates/project/Cargo.toml +++ b/crates/project/Cargo.toml @@ -39,7 +39,7 @@ clock.workspace = true collections.workspace = true context_server.workspace = true dap.workspace = true -encoding_rs.workspace = true +encodings.workspace = true extension.workspace = true fancy-regex.workspace = true fs.workspace = true diff --git a/crates/project/src/buffer_store.rs b/crates/project/src/buffer_store.rs index 4a8f5170451288b17f6dad62844aebc5695c1756..97cd401624b63f8c7146e9bf1906b4b81ba7e56b 100644 --- a/crates/project/src/buffer_store.rs +++ b/crates/project/src/buffer_store.rs @@ -7,9 +7,9 @@ use crate::{ use anyhow::{Context as _, Result, anyhow}; use client::Client; use collections::{HashMap, HashSet, hash_map}; +use encodings::Encoding; use fs::Fs; use futures::{Future, FutureExt as _, StreamExt, channel::oneshot, future::Shared}; -use fs::{Fs, encodings::EncodingWrapper}; use gpui::{ App, AppContext as _, AsyncApp, Context, Entity, EventEmitter, Subscription, Task, WeakEntity, }; @@ -398,13 +398,7 @@ impl LocalBufferStore { } let save = worktree.update(cx, |worktree, cx| { - worktree.write_file( - path.as_ref(), - text, - line_ending, - cx, - &encoding.lock().unwrap(), - ) + worktree.write_file(path.as_ref(), text, line_ending, cx, (*encoding).clone()) }); cx.spawn(async move |this, cx| { @@ -634,7 +628,7 @@ impl LocalBufferStore { &self, path: Arc, worktree: Entity, - encoding: Option, + encoding: Option, force: bool, detect_utf16: bool, cx: &mut Context, @@ -643,8 +637,14 @@ impl LocalBufferStore { let reservation = cx.reserve_entity(); let buffer_id = BufferId::from(reservation.entity_id().as_non_zero_u64()); - let load_file_task = - worktree.load_file(path.as_ref(), encoding, force, detect_utf16, None, cx); + let load_file_task = worktree.load_file( + path.as_ref(), + encoding.clone(), + force, + detect_utf16, + None, + cx, + ); cx.spawn(async move |_, cx| { let loaded_file = load_file_task.await?; @@ -681,13 +681,11 @@ impl LocalBufferStore { entry_id: None, is_local: true, is_private: false, - encoding: Some(Arc::new(std::sync::Mutex::new( - if let Some(encoding) = encoding { - encoding.0 - } else { - encoding_rs::UTF_8 - }, - ))), + encoding: Some(Arc::new(if let Some(encoding) = encoding { + encoding + } else { + Encoding::default() + })), })), Capability::ReadWrite, ) @@ -845,7 +843,7 @@ impl BufferStore { pub fn open_buffer( &mut self, project_path: ProjectPath, - encoding: Option, + encoding: Option, force: bool, detect_utf16: bool, cx: &mut Context, diff --git a/crates/project/src/prettier_store.rs b/crates/project/src/prettier_store.rs index ccdfb9661536a468ea3aae4f94280521e5a204c4..9539146ebb4029e07d40874f72db47cf03f7a6c6 100644 --- a/crates/project/src/prettier_store.rs +++ b/crates/project/src/prettier_store.rs @@ -7,8 +7,8 @@ use std::{ use anyhow::{Context as _, Result, anyhow}; use collections::{HashMap, HashSet}; -use encoding_rs::UTF_8; -use fs::{Fs, encodings::EncodingWrapper}; +use encodings::Encoding; +use fs::Fs; use futures::{ FutureExt, future::{self, Shared}, @@ -982,12 +982,12 @@ async fn save_prettier_server_file( executor: &BackgroundExecutor, ) -> anyhow::Result<()> { let prettier_wrapper_path = default_prettier_dir().join(prettier::PRETTIER_SERVER_FILE); - let encoding_wrapper = EncodingWrapper::new(UTF_8); + let encoding = Encoding::default(); fs.save( &prettier_wrapper_path, &text::Rope::from_str(prettier::PRETTIER_SERVER_JS, executor), text::LineEnding::Unix, - encoding_wrapper, + encoding, ) .await .with_context(|| { diff --git a/crates/project/src/project.rs b/crates/project/src/project.rs index cf3750462f583cdcd55ff443de6f13759dca75fe..5b3540e4e89c8543b9e4d2b0e87b1cdc27ece7d7 100644 --- a/crates/project/src/project.rs +++ b/crates/project/src/project.rs @@ -26,13 +26,11 @@ mod project_tests; mod environment; use buffer_diff::BufferDiff; use context_server_store::ContextServerStore; -use encoding_rs::Encoding; + +use encodings::EncodingOptions; pub use environment::ProjectEnvironmentEvent; -use fs::encodings::EncodingOptions; -use fs::encodings::EncodingWrapper; use git::repository::get_git_committer; use git_store::{Repository, RepositoryId}; -use std::sync::atomic::AtomicBool; pub mod search_history; mod yarn; @@ -1232,11 +1230,7 @@ impl Project { toolchain_store: Some(toolchain_store), agent_location: None, - encoding_options: EncodingOptions { - encoding: Arc::new(std::sync::Mutex::new(EncodingWrapper::default())), - force: AtomicBool::new(false), - detect_utf16: AtomicBool::new(true), - }, + encoding_options: EncodingOptions::default(), } }) } @@ -1422,11 +1416,7 @@ impl Project { toolchain_store: Some(toolchain_store), agent_location: None, - encoding_options: EncodingOptions { - encoding: Arc::new(std::sync::Mutex::new(EncodingWrapper::default())), - force: AtomicBool::new(false), - detect_utf16: AtomicBool::new(false), - }, + encoding_options: EncodingOptions::default(), }; // remote server -> local machine handlers @@ -1680,12 +1670,7 @@ impl Project { remotely_created_models: Arc::new(Mutex::new(RemotelyCreatedModels::default())), toolchain_store: None, agent_location: None, - encoding_options: EncodingOptions { - encoding: Arc::new(std::sync::Mutex::new(EncodingWrapper::default())), - - force: AtomicBool::new(false), - detect_utf16: AtomicBool::new(false), - }, + encoding_options: EncodingOptions::default(), }; project.set_role(role, cx); diff --git a/crates/project/src/project_tests.rs b/crates/project/src/project_tests.rs index ce70464eae1d38ab22a59faacfffa86a094e9825..8a78c3e0082b289ffc9e0ac04b69028fe39561e5 100644 --- a/crates/project/src/project_tests.rs +++ b/crates/project/src/project_tests.rs @@ -12,8 +12,8 @@ use buffer_diff::{ BufferDiffEvent, CALCULATE_DIFF_TASK, DiffHunkSecondaryStatus, DiffHunkStatus, DiffHunkStatusKind, assert_hunks, }; -use encoding_rs::UTF_8; -use fs::{FakeFs, encodings::EncodingWrapper}; +use encodings::{Encoding, UTF_8}; +use fs::FakeFs; use futures::{StreamExt, future}; use git::{ GitHostingProviderRegistry, @@ -1461,13 +1461,13 @@ async fn test_reporting_fs_changes_to_language_servers(cx: &mut gpui::TestAppCon .await .unwrap(); - let encoding_wrapper = EncodingWrapper::new(UTF_8); + let encoding = Encoding::default(); fs.save( path!("/the-root/Cargo.lock").as_ref(), &Rope::default(), Default::default(), - encoding_wrapper.clone(), + encoding.clone(), ) .await .unwrap(); @@ -1475,7 +1475,7 @@ async fn test_reporting_fs_changes_to_language_servers(cx: &mut gpui::TestAppCon path!("/the-stdlib/LICENSE").as_ref(), &Rope::default(), Default::default(), - encoding_wrapper.clone(), + encoding.clone(), ) .await .unwrap(); @@ -1483,7 +1483,7 @@ async fn test_reporting_fs_changes_to_language_servers(cx: &mut gpui::TestAppCon path!("/the/stdlib/src/string.rs").as_ref(), &Rope::default(), Default::default(), - encoding_wrapper, + encoding, ) .await .unwrap(); @@ -4075,7 +4075,7 @@ async fn test_file_changes_multiple_times_on_disk(cx: &mut gpui::TestAppContext) // the next file change occurs. cx.executor().deprioritize(*language::BUFFER_DIFF_TASK); - let encoding_wrapper = EncodingWrapper::new(UTF_8); + let encoding = Encoding::default(); // Change the buffer's file on disk, and then wait for the file change // to be detected by the worktree, so that the buffer starts reloading. @@ -4083,7 +4083,7 @@ async fn test_file_changes_multiple_times_on_disk(cx: &mut gpui::TestAppContext) path!("/dir/file1").as_ref(), &Rope::from_str("the first contents", cx.background_executor()), Default::default(), - encoding_wrapper.clone(), + encoding.clone(), ) .await .unwrap(); @@ -4095,7 +4095,7 @@ async fn test_file_changes_multiple_times_on_disk(cx: &mut gpui::TestAppContext) path!("/dir/file1").as_ref(), &Rope::from_str("the second contents", cx.background_executor()), Default::default(), - encoding_wrapper, + encoding, ) .await .unwrap(); @@ -4134,7 +4134,7 @@ async fn test_edit_buffer_while_it_reloads(cx: &mut gpui::TestAppContext) { // the next file change occurs. cx.executor().deprioritize(*language::BUFFER_DIFF_TASK); - let encoding_wrapper = EncodingWrapper::new(UTF_8); + let encoding = Encoding::new(UTF_8); // Change the buffer's file on disk, and then wait for the file change // to be detected by the worktree, so that the buffer starts reloading. @@ -4142,7 +4142,7 @@ async fn test_edit_buffer_while_it_reloads(cx: &mut gpui::TestAppContext) { path!("/dir/file1").as_ref(), &Rope::from_str("the first contents", cx.background_executor()), Default::default(), - encoding_wrapper, + encoding, ) .await .unwrap(); @@ -4818,13 +4818,13 @@ async fn test_buffer_file_changes_on_disk(cx: &mut gpui::TestAppContext) { let (new_contents, new_offsets) = marked_text_offsets("oneˇ\nthree ˇFOURˇ five\nsixtyˇ seven\n"); - let encoding_wrapper = EncodingWrapper::new(UTF_8); + let encoding = Encoding::new(UTF_8); fs.save( path!("/dir/the-file").as_ref(), &Rope::from_str(new_contents.as_str(), cx.background_executor()), LineEnding::Unix, - encoding_wrapper, + encoding, ) .await .unwrap(); @@ -4852,14 +4852,14 @@ async fn test_buffer_file_changes_on_disk(cx: &mut gpui::TestAppContext) { assert!(!buffer.has_conflict()); }); - let encoding_wrapper = EncodingWrapper::new(UTF_8); + let encoding = Encoding::new(UTF_8); // Change the file on disk again, adding blank lines to the beginning. fs.save( path!("/dir/the-file").as_ref(), &Rope::from_str("\n\n\nAAAA\naaa\nBB\nbbbbb\n", cx.background_executor()), LineEnding::Unix, - encoding_wrapper, + encoding, ) .await .unwrap(); @@ -4906,7 +4906,7 @@ async fn test_buffer_line_endings(cx: &mut gpui::TestAppContext) { assert_eq!(buffer.line_ending(), LineEnding::Windows); }); - let encoding_wrapper = EncodingWrapper::new(UTF_8); + let encoding = Encoding::new(UTF_8); // Change a file's line endings on disk from unix to windows. The buffer's // state updates correctly. @@ -4914,7 +4914,7 @@ async fn test_buffer_line_endings(cx: &mut gpui::TestAppContext) { path!("/dir/file1").as_ref(), &Rope::from_str("aaa\nb\nc\n", cx.background_executor()), LineEnding::Windows, - encoding_wrapper, + encoding, ) .await .unwrap(); diff --git a/crates/remote_server/Cargo.toml b/crates/remote_server/Cargo.toml index 9acb391e9f357d798ecbe637ed49f07ad3b424df..ac8c680d4e52181d8e1d382d3d1e6689fd97cea0 100644 --- a/crates/remote_server/Cargo.toml +++ b/crates/remote_server/Cargo.toml @@ -28,7 +28,7 @@ clap.workspace = true client.workspace = true dap_adapters.workspace = true debug_adapter_extension.workspace = true -encoding_rs.workspace = true +encodings.workspace = true env_logger.workspace = true extension.workspace = true extension_host.workspace = true diff --git a/crates/remote_server/src/remote_editing_tests.rs b/crates/remote_server/src/remote_editing_tests.rs index 4fff49de6af4b289733c38021edfbea427d1f109..aadf2c2376f360c4c99f2628e05bba9b2d7962a2 100644 --- a/crates/remote_server/src/remote_editing_tests.rs +++ b/crates/remote_server/src/remote_editing_tests.rs @@ -6,12 +6,12 @@ use agent::{AgentTool, ReadFileTool, ReadFileToolInput, ToolCallEventStream}; use client::{Client, UserStore}; use clock::FakeSystemClock; use collections::{HashMap, HashSet}; -use encoding_rs::UTF_8; use language_model::{LanguageModelRequest, fake_provider::FakeLanguageModel}; +use encodings::Encoding; use extension::ExtensionHostProxy; -use fs::{FakeFs, Fs, encodings::EncodingWrapper}; -use gpui::{AppContext as _, Entity, SemanticVersion, SharedString, TestAppContext}; +use fs::{FakeFs, Fs}; +use gpui::{AppContext as _, Entity, SemanticVersion, TestAppContext}; use http_client::{BlockedHttpClient, FakeHttpClient}; use language::{ Buffer, FakeLspAdapter, LanguageConfig, LanguageMatcher, LanguageRegistry, LineEnding, Rope, @@ -123,7 +123,7 @@ async fn test_basic_remote_editing(cx: &mut TestAppContext, server_cx: &mut Test path!("/code/project1/src/main.rs").as_ref(), &Rope::from_str_small("fn main() {}"), Default::default(), - EncodingWrapper::new(UTF_8), + Encoding::default(), ) .await .unwrap(); @@ -770,7 +770,7 @@ async fn test_remote_reload(cx: &mut TestAppContext, server_cx: &mut TestAppCont &PathBuf::from(path!("/code/project1/src/lib.rs")), &Rope::from_str_small("bangles"), LineEnding::Unix, - EncodingWrapper::new(UTF_8), + Encoding::default(), ) .await .unwrap(); @@ -786,7 +786,7 @@ async fn test_remote_reload(cx: &mut TestAppContext, server_cx: &mut TestAppCont &PathBuf::from(path!("/code/project1/src/lib.rs")), &Rope::from_str_small("bloop"), LineEnding::Unix, - EncodingWrapper::new(UTF_8), + Encoding::default(), ) .await .unwrap(); diff --git a/crates/workspace/Cargo.toml b/crates/workspace/Cargo.toml index 14ee5692d4b4eb109c5253b8ec9e28fe38f84a11..c1d0153fc08441b99997da7839c47c851755f53a 100644 --- a/crates/workspace/Cargo.toml +++ b/crates/workspace/Cargo.toml @@ -35,7 +35,7 @@ clock.workspace = true collections.workspace = true component.workspace = true db.workspace = true -encoding_rs.workspace = true +encodings.workspace = true fs.workspace = true futures.workspace = true gpui.workspace = true diff --git a/crates/workspace/src/workspace.rs b/crates/workspace/src/workspace.rs index 60111bf47dd498b520a2684a5cf884f733a74d00..68c7d704f757d72b4807d78f70458678d8ed81fd 100644 --- a/crates/workspace/src/workspace.rs +++ b/crates/workspace/src/workspace.rs @@ -19,8 +19,8 @@ mod workspace_settings; pub use crate::notifications::NotificationFrame; pub use dock::Panel; -use encoding_rs::UTF_8; -use fs::encodings::EncodingWrapper; +use encodings::Encoding; + pub use path_list::PathList; pub use toast_layer::{ToastAction, ToastLayer, ToastView}; @@ -32,7 +32,7 @@ use client::{ }; use collections::{HashMap, HashSet, hash_map}; use dock::{Dock, DockPosition, PanelButtons, PanelHandle, RESIZE_HANDLE_SIZE}; -use fs::encodings::EncodingOptions; +use encodings::EncodingOptions; use futures::{ Future, FutureExt, StreamExt, @@ -625,7 +625,7 @@ type BuildProjectItemForPathFn = fn( &Entity, &ProjectPath, - Option, + Option, &mut Window, &mut App, ) -> Option, WorkspaceItemBuilder)>>>; @@ -649,9 +649,9 @@ impl ProjectItemRegistry { self.build_project_item_for_path_fns .push(|project, project_path, encoding, window, cx| { let project_path = project_path.clone(); - let EncodingWrapper(encoding) = encoding.unwrap_or_default(); + let encoding = encoding.unwrap_or_default(); - project.update(cx, |project, _| {*project.encoding_options.encoding.lock().unwrap() = EncodingWrapper::new(encoding)}); + project.update(cx, |project, _| {project.encoding_options.encoding.lock().unwrap().set(encoding.get())}); let is_file = project .read(cx) @@ -721,7 +721,7 @@ impl ProjectItemRegistry { &self, project: &Entity, path: &ProjectPath, - encoding: Option, + encoding: Option, window: &mut Window, cx: &mut App, ) -> Task, WorkspaceItemBuilder)>> { @@ -1945,9 +1945,7 @@ impl Workspace { window: &mut Window, cx: &mut Context, ) -> Task> { - *self.encoding_options.force.get_mut() = false; - *self.encoding_options.detect_utf16.get_mut() = true; - *self.encoding_options.encoding.lock().unwrap() = EncodingWrapper::new(encoding_rs::UTF_8); + self.encoding_options.reset(); let to_load = if let Some(pane) = pane.upgrade() { pane.update(cx, |pane, cx| { @@ -3593,9 +3591,7 @@ impl Workspace { registry.open_path( project, &path, - Some(EncodingWrapper::new( - (self.encoding_options.encoding.lock().unwrap()).0, - )), + Some(self.encoding_options.encoding.lock().unwrap().clone()), window, cx, ) @@ -7622,12 +7618,11 @@ pub fn create_and_open_local_file( let fs = workspace.read_with(cx, |workspace, _| workspace.app_state().fs.clone())?; if !fs.is_file(path).await { fs.create_file(path, Default::default()).await?; - let encoding_wrapper = EncodingWrapper::new(UTF_8); fs.save( path, &default_content(), Default::default(), - encoding_wrapper, + Default::default(), ) .await?; } diff --git a/crates/worktree/Cargo.toml b/crates/worktree/Cargo.toml index 8166825a1c977508e06a94047cb8bfbfe8b4caf8..46ad794b2886a8b4cfd2178b8c362f5f78ce1345 100644 --- a/crates/worktree/Cargo.toml +++ b/crates/worktree/Cargo.toml @@ -27,7 +27,7 @@ anyhow.workspace = true async-lock.workspace = true clock.workspace = true collections.workspace = true -encoding_rs.workspace = true +encodings.workspace = true fs.workspace = true futures.workspace = true fuzzy.workspace = true diff --git a/crates/worktree/src/worktree.rs b/crates/worktree/src/worktree.rs index 2891a3975770f34c1c9b63d126d67ae3a0545e9c..a36a81f6d95ce5a8907a81e184722615e8baab93 100644 --- a/crates/worktree/src/worktree.rs +++ b/crates/worktree/src/worktree.rs @@ -7,11 +7,8 @@ use ::ignore::gitignore::{Gitignore, GitignoreBuilder}; use anyhow::{Context as _, Result, anyhow}; use clock::ReplicaId; use collections::{HashMap, HashSet, VecDeque}; -use encoding_rs::Encoding; -use fs::{ - Fs, MTime, PathEvent, RemoveOptions, Watcher, copy_recursive, encodings::EncodingWrapper, - read_dir_items, -}; +use encodings::Encoding; +use fs::{Fs, MTime, PathEvent, RemoveOptions, Watcher, copy_recursive, read_dir_items}; use futures::{ FutureExt as _, Stream, StreamExt, channel::{ @@ -710,10 +707,10 @@ impl Worktree { pub fn load_file( &self, path: &Path, - encoding: Option, + encoding: Option, force: bool, detect_utf16: bool, - buffer_encoding: Option>>, + buffer_encoding: Option>, cx: &Context, ) -> Task> { match self { @@ -745,7 +742,7 @@ impl Worktree { text: Rope, line_ending: LineEnding, cx: &Context, - encoding: &'static Encoding, + encoding: Encoding, ) -> Task>> { match self { Worktree::Local(this) => this.write_file(path, text, line_ending, cx, encoding), @@ -1330,10 +1327,10 @@ impl LocalWorktree { fn load_file( &self, path: &Path, - encoding: Option, + encoding: Option, force: bool, detect_utf16: bool, - buffer_encoding: Option>>, + buffer_encoding: Option>, cx: &Context, ) -> Task> { let path = Arc::from(path); @@ -1361,14 +1358,14 @@ impl LocalWorktree { let text = fs .load_with_encoding( &abs_path, - if let Some(encoding) = encoding { - encoding + if let Some(ref encoding) = encoding { + Encoding::new(encoding.get()) } else { - EncodingWrapper::new(encoding_rs::UTF_8) + Encoding::new(encodings::UTF_8) }, force, detect_utf16, - buffer_encoding, + buffer_encoding.clone(), ) .await?; @@ -1394,11 +1391,7 @@ impl LocalWorktree { }, is_local: true, is_private, - encoding: if let Some(encoding) = encoding { - Some(Arc::new(std::sync::Mutex::new(encoding.0))) - } else { - None - }, + encoding: encoding.map(|e| Arc::new(Encoding::new(e.get()))), }) } }; @@ -1487,20 +1480,18 @@ impl LocalWorktree { text: Rope, line_ending: LineEnding, cx: &Context, - encoding: &'static Encoding, + encoding: Encoding, ) -> Task>> { let fs = self.fs.clone(); let is_private = self.is_path_private(&path); let abs_path = self.absolutize(&path); - let encoding_wrapper = EncodingWrapper::new(encoding); - let write = cx.background_spawn({ let fs = fs.clone(); let abs_path = abs_path.clone(); - async move { - fs.save(&abs_path, &text, line_ending, encoding_wrapper) - .await + { + let encoding = encoding.clone(); + async move { fs.save(&abs_path, &text, line_ending, encoding).await } } }); @@ -1535,7 +1526,7 @@ impl LocalWorktree { entry_id: None, is_local: true, is_private, - encoding: Some(Arc::new(std::sync::Mutex::new(encoding))), + encoding: Some(Arc::new(encoding)), })) } }) @@ -3097,7 +3088,7 @@ pub struct File { pub entry_id: Option, pub is_local: bool, pub is_private: bool, - pub encoding: Option>>, + pub encoding: Option>, } impl PartialEq for File { @@ -3111,7 +3102,7 @@ impl PartialEq for File { && if let Some(encoding) = &self.encoding && let Some(other_encoding) = &other.encoding { - if *encoding.lock().unwrap() != *other_encoding.lock().unwrap() { + if encoding.get() != other_encoding.get() { false } else { true @@ -3171,7 +3162,8 @@ impl language::File for File { fn path_style(&self, cx: &App) -> PathStyle { self.worktree.read(cx).path_style() - fn encoding(&self) -> Option>> { + } + fn encoding(&self) -> Option> { if let Some(encoding) = &self.encoding { Some(encoding.clone()) } else { @@ -3188,10 +3180,10 @@ impl language::LocalFile for File { fn load( &self, cx: &App, - encoding: EncodingWrapper, + encoding: Encoding, force: bool, detect_utf16: bool, - buffer_encoding: Option>>, + buffer_encoding: Option>, ) -> Task> { let worktree = self.worktree.read(cx).as_local().unwrap(); let abs_path = worktree.absolutize(&self.path); diff --git a/crates/worktree/src/worktree_tests.rs b/crates/worktree/src/worktree_tests.rs index 954729ef9a343a382651f6be6a046db44efdfc19..69ee98f7bdf3bae64f7f9ac6d1474c158c8fdd57 100644 --- a/crates/worktree/src/worktree_tests.rs +++ b/crates/worktree/src/worktree_tests.rs @@ -3,8 +3,7 @@ use crate::{ worktree_settings::WorktreeSettings, }; use anyhow::Result; -use encoding_rs::UTF_8; -use fs::{FakeFs, Fs, RealFs, RemoveOptions, encodings::EncodingWrapper}; +use fs::{FakeFs, Fs, RealFs, RemoveOptions}; use git::GITIGNORE; use gpui::{AppContext as _, BackgroundExecutor, BorrowAppContext, Context, Task, TestAppContext}; use parking_lot::Mutex; @@ -666,7 +665,7 @@ async fn test_dirs_no_longer_ignored(cx: &mut TestAppContext) { "/root/.gitignore".as_ref(), &Rope::from_str("e", cx.background_executor()), Default::default(), - encoding_wrapper, + Default::default(), ) .await .unwrap(); @@ -740,7 +739,7 @@ async fn test_write_file(cx: &mut TestAppContext) { Rope::from_str("hello", cx.background_executor()), Default::default(), cx, - UTF_8, + Default::default(), ) }) .await @@ -752,7 +751,7 @@ async fn test_write_file(cx: &mut TestAppContext) { Rope::from_str("world", cx.background_executor()), Default::default(), cx, - UTF_8, + Default::default(), ) }) .await @@ -1787,7 +1786,7 @@ fn randomly_mutate_worktree( Rope::default(), Default::default(), cx, - UTF_8, + Default::default(), ); cx.background_spawn(async move { task.await?; @@ -1876,12 +1875,11 @@ async fn randomly_mutate_fs( ignore_path.strip_prefix(root_path).unwrap(), ignore_contents ); - let encoding_wrapper = EncodingWrapper::new(UTF_8); fs.save( &ignore_path, &Rope::from_str(ignore_contents.as_str(), executor), Default::default(), - encoding_wrapper, + Default::default(), ) .await .unwrap(); diff --git a/crates/zed/Cargo.toml b/crates/zed/Cargo.toml index 4bf7f2824e9d20f85c6cc9c74817fecfec9d63cd..139f1d63ae792a05a193b61a5ff9925796284cfa 100644 --- a/crates/zed/Cargo.toml +++ b/crates/zed/Cargo.toml @@ -52,7 +52,8 @@ debugger_ui.workspace = true diagnostics.workspace = true editor.workspace = true zeta2_tools.workspace = true -encoding.workspace = true +edit_prediction_tools.workspace = true +encodings.workspace = true encodings_ui.workspace = true env_logger.workspace = true extension.workspace = true diff --git a/crates/zed/src/zed.rs b/crates/zed/src/zed.rs index 2c5479f5b90316ebc4a8deff6d769ab3ff3050dd..134c0eb452fb52c8c2aa5b8ce18ebc6fc85560a8 100644 --- a/crates/zed/src/zed.rs +++ b/crates/zed/src/zed.rs @@ -2177,8 +2177,8 @@ mod tests { use assets::Assets; use collections::HashSet; use editor::{DisplayPoint, Editor, SelectionEffects, display_map::DisplayRow}; - use encoding_rs::UTF_8; - use fs::encodings::EncodingWrapper; + use encodings::Encoding; + use gpui::{ Action, AnyWindowHandle, App, AssetSource, BorrowAppContext, SemanticVersion, TestAppContext, UpdateGlobal, VisualTestContext, WindowHandle, actions, @@ -4384,7 +4384,7 @@ mod tests { "/settings.json".as_ref(), &Rope::from_str_small(r#"{"base_keymap": "Atom"}"#), Default::default(), - EncodingWrapper::new(UTF_8), + Encoding::default(), ) .await .unwrap(); @@ -4395,7 +4395,7 @@ mod tests { "/keymap.json".as_ref(), &Rope::from_str_small(r#"[{"bindings": {"backspace": "test_only::ActionA"}}]"#), Default::default(), - EncodingWrapper::new(UTF_8), + Encoding::default(), ) .await .unwrap(); @@ -4444,7 +4444,7 @@ mod tests { "/keymap.json".as_ref(), &Rope::from_str_small(r#"[{"bindings": {"backspace": "test_only::ActionB"}}]"#), Default::default(), - EncodingWrapper::new(UTF_8), + Encoding::default(), ) .await .unwrap(); @@ -4465,7 +4465,7 @@ mod tests { "/settings.json".as_ref(), &Rope::from_str_small(r#"{"base_keymap": "JetBrains"}"#), Default::default(), - EncodingWrapper::new(UTF_8), + Encoding::default(), ) .await .unwrap(); @@ -4506,7 +4506,7 @@ mod tests { "/settings.json".as_ref(), &Rope::from_str_small(r#"{"base_keymap": "Atom"}"#), Default::default(), - EncodingWrapper::new(UTF_8), + Encoding::default(), ) .await .unwrap(); @@ -4516,7 +4516,7 @@ mod tests { "/keymap.json".as_ref(), &Rope::from_str_small(r#"[{"bindings": {"backspace": "test_only::ActionA"}}]"#), Default::default(), - EncodingWrapper::new(UTF_8), + Encoding::default(), ) .await .unwrap(); @@ -4560,7 +4560,7 @@ mod tests { "/keymap.json".as_ref(), &Rope::from_str_small(r#"[{"bindings": {"backspace": null}}]"#), Default::default(), - EncodingWrapper::new(UTF_8), + Encoding::default(), ) .await .unwrap(); @@ -4581,7 +4581,7 @@ mod tests { "/settings.json".as_ref(), &Rope::from_str_small(r#"{"base_keymap": "JetBrains"}"#), Default::default(), - EncodingWrapper::new(UTF_8), + Encoding::default(), ) .await .unwrap();