mod agent; mod editor; mod extension; mod language; mod language_model; mod project; mod terminal; mod theme; mod workspace; pub use agent::*; pub use editor::*; pub use extension::*; pub use language::*; pub use language_model::*; pub use project::*; pub use terminal::*; pub use theme::*; pub use workspace::*; use collections::{HashMap, IndexMap}; use gpui::{App, SharedString}; use release_channel::ReleaseChannel; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use settings_macros::{MergeFrom, with_fallible_options}; use std::collections::BTreeSet; use std::env; use std::sync::Arc; pub use util::serde::default_true; use crate::{ActiveSettingsProfileName, merge_from}; #[with_fallible_options] #[derive(Debug, PartialEq, Default, Clone, Serialize, Deserialize, JsonSchema, MergeFrom)] pub struct SettingsContent { #[serde(flatten)] pub project: ProjectSettingsContent, #[serde(flatten)] pub theme: Box, #[serde(flatten)] pub extension: ExtensionSettingsContent, #[serde(flatten)] pub workspace: WorkspaceSettingsContent, #[serde(flatten)] pub editor: EditorSettingsContent, #[serde(flatten)] pub remote: RemoteSettingsContent, /// Settings related to the file finder. pub file_finder: Option, pub git_panel: Option, pub tabs: Option, pub tab_bar: Option, pub status_bar: Option, pub preview_tabs: Option, pub agent: Option, pub agent_servers: Option, /// Configuration of audio in Zed. pub audio: Option, /// Whether or not to automatically check for updates. /// /// Default: true pub auto_update: Option, /// This base keymap settings adjusts the default keybindings in Zed to be similar /// to other common code editors. By default, Zed's keymap closely follows VSCode's /// keymap, with minor adjustments, this corresponds to the "VSCode" setting. /// /// Default: VSCode pub base_keymap: Option, /// Configuration for the collab panel visual settings. pub collaboration_panel: Option, pub debugger: Option, /// Configuration for Diagnostics-related features. pub diagnostics: Option, /// Configuration for Git-related features pub git: Option, /// Common language server settings. pub global_lsp_settings: Option, /// The settings for the image viewer. pub image_viewer: Option, pub repl: Option, /// Whether or not to enable Helix mode. /// /// Default: false pub helix_mode: Option, pub journal: Option, /// A map of log scopes to the desired log level. /// Useful for filtering out noisy logs or enabling more verbose logging. /// /// Example: {"log": {"client": "warn"}} pub log: Option>, pub line_indicator_format: Option, pub language_models: Option, pub outline_panel: Option, pub project_panel: Option, /// Configuration for the Message Editor pub message_editor: Option, /// Configuration for Node-related features pub node: Option, /// Configuration for the Notification Panel pub notification_panel: Option, pub proxy: Option, /// The URL of the Zed server to connect to. pub server_url: Option, /// Configuration for session-related features pub session: Option, /// Control what info is collected by Zed. pub telemetry: Option, /// Configuration of the terminal in Zed. pub terminal: Option, pub title_bar: Option, /// Whether or not to enable Vim mode. /// /// Default: false pub vim_mode: Option, // Settings related to calls in Zed pub calls: Option, /// Whether to disable all AI features in Zed. /// /// Default: false pub disable_ai: Option, /// Settings related to Vim mode in Zed. pub vim: Option, } impl SettingsContent { pub fn languages_mut(&mut self) -> &mut HashMap { &mut self.project.all_languages.languages.0 } } #[with_fallible_options] #[derive(Debug, Default, PartialEq, Clone, Serialize, Deserialize, JsonSchema, MergeFrom)] pub struct UserSettingsContent { #[serde(flatten)] pub content: Box, pub dev: Option>, pub nightly: Option>, pub preview: Option>, pub stable: Option>, pub macos: Option>, pub windows: Option>, pub linux: Option>, #[serde(default)] pub profiles: IndexMap, } pub struct ExtensionsSettingsContent { pub all_languages: AllLanguageSettingsContent, } impl UserSettingsContent { pub fn for_release_channel(&self) -> Option<&SettingsContent> { match *release_channel::RELEASE_CHANNEL { ReleaseChannel::Dev => self.dev.as_deref(), ReleaseChannel::Nightly => self.nightly.as_deref(), ReleaseChannel::Preview => self.preview.as_deref(), ReleaseChannel::Stable => self.stable.as_deref(), } } pub fn for_os(&self) -> Option<&SettingsContent> { match env::consts::OS { "macos" => self.macos.as_deref(), "linux" => self.linux.as_deref(), "windows" => self.windows.as_deref(), _ => None, } } pub fn for_profile(&self, cx: &App) -> Option<&SettingsContent> { let Some(active_profile) = cx.try_global::() else { return None; }; self.profiles.get(&active_profile.0) } } /// Base key bindings scheme. Base keymaps can be overridden with user keymaps. /// /// Default: VSCode #[derive( Copy, Clone, Debug, Serialize, Deserialize, JsonSchema, MergeFrom, PartialEq, Eq, Default, strum::VariantArray, )] pub enum BaseKeymapContent { #[default] VSCode, JetBrains, SublimeText, Atom, TextMate, Emacs, Cursor, None, } impl strum::VariantNames for BaseKeymapContent { const VARIANTS: &'static [&'static str] = &[ "VSCode", "JetBrains", "Sublime Text", "Atom", "TextMate", "Emacs", "Cursor", "None", ]; } #[with_fallible_options] #[derive(Clone, PartialEq, Default, Serialize, Deserialize, JsonSchema, MergeFrom, Debug)] pub struct TitleBarSettingsContent { /// Whether to show the branch icon beside branch switcher in the title bar. /// /// Default: false pub show_branch_icon: Option, /// Whether to show onboarding banners in the title bar. /// /// Default: true pub show_onboarding_banner: Option, /// Whether to show user avatar in the title bar. /// /// Default: true pub show_user_picture: Option, /// Whether to show the branch name button in the titlebar. /// /// Default: true pub show_branch_name: Option, /// Whether to show the project host and name in the titlebar. /// /// Default: true pub show_project_items: Option, /// Whether to show the sign in button in the title bar. /// /// Default: true pub show_sign_in: Option, /// Whether to show the user menu button in the title bar. /// /// Default: true pub show_user_menu: Option, /// Whether to show the menus in the title bar. /// /// Default: false pub show_menus: Option, } /// Configuration of audio in Zed. #[with_fallible_options] #[derive(Clone, PartialEq, Default, Serialize, Deserialize, JsonSchema, MergeFrom, Debug)] pub struct AudioSettingsContent { /// Opt into the new audio system. /// /// You need to rejoin a call for this setting to apply #[serde(rename = "experimental.rodio_audio")] pub rodio_audio: Option, // default is false /// Requires 'rodio_audio: true' /// /// Automatically increase or decrease you microphone's volume. This affects how /// loud you sound to others. /// /// Recommended: off (default) /// Microphones are too quite in zed, until everyone is on experimental /// audio and has auto speaker volume on this will make you very loud /// compared to other speakers. #[serde(rename = "experimental.auto_microphone_volume")] pub auto_microphone_volume: Option, /// Requires 'rodio_audio: true' /// /// Automatically increate or decrease the volume of other call members. /// This only affects how things sound for you. #[serde(rename = "experimental.auto_speaker_volume")] pub auto_speaker_volume: Option, /// Requires 'rodio_audio: true' /// /// Remove background noises. Works great for typing, cars, dogs, AC. Does /// not work well on music. #[serde(rename = "experimental.denoise")] pub denoise: Option, /// Requires 'rodio_audio: true' /// /// Use audio parameters compatible with the previous versions of /// experimental audio and non-experimental audio. When this is false you /// will sound strange to anyone not on the latest experimental audio. In /// the future we will migrate by setting this to false /// /// You need to rejoin a call for this setting to apply #[serde(rename = "experimental.legacy_audio_compatible")] pub legacy_audio_compatible: Option, } /// Control what info is collected by Zed. #[with_fallible_options] #[derive(Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema, Debug, MergeFrom)] pub struct TelemetrySettingsContent { /// Send debug info like crash reports. /// /// Default: true pub diagnostics: Option, /// Send anonymized usage data like what languages you're using Zed with. /// /// Default: true pub metrics: Option, } impl Default for TelemetrySettingsContent { fn default() -> Self { Self { diagnostics: Some(true), metrics: Some(true), } } } #[with_fallible_options] #[derive(Default, Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema, Clone, MergeFrom)] pub struct DebuggerSettingsContent { /// Determines the stepping granularity. /// /// Default: line pub stepping_granularity: Option, /// Whether the breakpoints should be reused across Zed sessions. /// /// Default: true pub save_breakpoints: Option, /// Whether to show the debug button in the status bar. /// /// Default: true pub button: Option, /// Time in milliseconds until timeout error when connecting to a TCP debug adapter /// /// Default: 2000ms pub timeout: Option, /// Whether to log messages between active debug adapters and Zed /// /// Default: true pub log_dap_communications: Option, /// Whether to format dap messages in when adding them to debug adapter logger /// /// Default: true pub format_dap_log_messages: Option, /// The dock position of the debug panel /// /// Default: Bottom pub dock: Option, } /// The granularity of one 'step' in the stepping requests `next`, `stepIn`, `stepOut`, and `stepBack`. #[derive( PartialEq, Eq, Debug, Hash, Clone, Copy, Deserialize, Serialize, JsonSchema, MergeFrom, strum::VariantArray, strum::VariantNames, )] #[serde(rename_all = "snake_case")] pub enum SteppingGranularity { /// The step should allow the program to run until the current statement has finished executing. /// The meaning of a statement is determined by the adapter and it may be considered equivalent to a line. /// For example 'for(int i = 0; i < 10; i++)' could be considered to have 3 statements 'int i = 0', 'i < 10', and 'i++'. Statement, /// The step should allow the program to run until the current source line has executed. Line, /// The step should allow one instruction to execute (e.g. one x86 instruction). Instruction, } #[derive( Copy, Clone, Debug, Serialize, Deserialize, JsonSchema, MergeFrom, PartialEq, Eq, strum::VariantArray, strum::VariantNames, )] #[serde(rename_all = "snake_case")] pub enum DockPosition { Left, Bottom, Right, } /// Settings for slash commands. #[with_fallible_options] #[derive(Deserialize, Serialize, Debug, Default, Clone, JsonSchema, MergeFrom, PartialEq, Eq)] pub struct SlashCommandSettings { /// Settings for the `/cargo-workspace` slash command. pub cargo_workspace: Option, } /// Settings for the `/cargo-workspace` slash command. #[with_fallible_options] #[derive(Deserialize, Serialize, Debug, Default, Clone, JsonSchema, MergeFrom, PartialEq, Eq)] pub struct CargoWorkspaceCommandSettings { /// Whether `/cargo-workspace` is enabled. pub enabled: Option, } /// Configuration of voice calls in Zed. #[with_fallible_options] #[derive(Clone, PartialEq, Default, Serialize, Deserialize, JsonSchema, MergeFrom, Debug)] pub struct CallSettingsContent { /// Whether the microphone should be muted when joining a channel or a call. /// /// Default: false pub mute_on_join: Option, /// Whether your current project should be shared when joining an empty channel. /// /// Default: false pub share_on_join: Option, } #[with_fallible_options] #[derive(Clone, PartialEq, Default, Serialize, Deserialize, JsonSchema, MergeFrom, Debug)] pub struct GitPanelSettingsContent { /// Whether to show the panel button in the status bar. /// /// Default: true pub button: Option, /// Where to dock the panel. /// /// Default: left pub dock: Option, /// Default width of the panel in pixels. /// /// Default: 360 #[serde(serialize_with = "crate::serialize_optional_f32_with_two_decimal_places")] pub default_width: Option, /// How entry statuses are displayed. /// /// Default: icon pub status_style: Option, /// How and when the scrollbar should be displayed. /// /// Default: inherits editor scrollbar settings pub scrollbar: Option, /// What the default branch name should be when /// `init.defaultBranch` is not set in git /// /// Default: main pub fallback_branch_name: Option, /// Whether to sort entries in the panel by path /// or by status (the default). /// /// Default: false pub sort_by_path: Option, /// Whether to collapse untracked files in the diff panel. /// /// Default: false pub collapse_untracked_diff: Option, /// Whether to show entries with tree or flat view in the panel /// /// Default: false pub tree_view: Option, } #[derive( Default, Copy, Clone, Debug, Serialize, Deserialize, JsonSchema, MergeFrom, PartialEq, Eq, strum::VariantArray, strum::VariantNames, )] #[serde(rename_all = "snake_case")] pub enum StatusStyle { #[default] Icon, LabelColor, } #[with_fallible_options] #[derive( Copy, Clone, Default, Debug, Serialize, Deserialize, JsonSchema, MergeFrom, PartialEq, Eq, )] pub struct ScrollbarSettings { pub show: Option, } #[with_fallible_options] #[derive(Clone, Default, Serialize, Deserialize, JsonSchema, MergeFrom, Debug, PartialEq)] pub struct NotificationPanelSettingsContent { /// Whether to show the panel button in the status bar. /// /// Default: true pub button: Option, /// Where to dock the panel. /// /// Default: right pub dock: Option, /// Default width of the panel in pixels. /// /// Default: 300 #[serde(serialize_with = "crate::serialize_optional_f32_with_two_decimal_places")] pub default_width: Option, } #[with_fallible_options] #[derive(Clone, Default, Serialize, Deserialize, JsonSchema, MergeFrom, Debug, PartialEq)] pub struct PanelSettingsContent { /// Whether to show the panel button in the status bar. /// /// Default: true pub button: Option, /// Where to dock the panel. /// /// Default: left pub dock: Option, /// Default width of the panel in pixels. /// /// Default: 240 #[serde(serialize_with = "crate::serialize_optional_f32_with_two_decimal_places")] pub default_width: Option, } #[with_fallible_options] #[derive(Clone, Default, Serialize, Deserialize, JsonSchema, MergeFrom, Debug, PartialEq)] pub struct MessageEditorSettings { /// Whether to automatically replace emoji shortcodes with emoji characters. /// For example: typing `:wave:` gets replaced with `👋`. /// /// Default: false pub auto_replace_emoji_shortcode: Option, } #[with_fallible_options] #[derive(Clone, Default, Serialize, Deserialize, JsonSchema, MergeFrom, Debug, PartialEq)] pub struct FileFinderSettingsContent { /// Whether to show file icons in the file finder. /// /// Default: true pub file_icons: Option, /// Determines how much space the file finder can take up in relation to the available window width. /// /// Default: small pub modal_max_width: Option, /// Determines whether the file finder should skip focus for the active file in search results. /// /// Default: true pub skip_focus_for_active_in_search: Option, /// Determines whether to show the git status in the file finder /// /// Default: true pub git_status: Option, /// Whether to use gitignored files when searching. /// Only the file Zed had indexed will be used, not necessary all the gitignored files. /// /// Default: Smart pub include_ignored: Option, } #[derive( Debug, PartialEq, Eq, Clone, Copy, Default, Serialize, Deserialize, JsonSchema, MergeFrom, strum::VariantArray, strum::VariantNames, )] #[serde(rename_all = "snake_case")] pub enum IncludeIgnoredContent { /// Use all gitignored files All, /// Use only the files Zed had indexed Indexed, /// Be smart and search for ignored when called from a gitignored worktree #[default] Smart, } #[derive( Debug, PartialEq, Eq, Clone, Copy, Default, Serialize, Deserialize, JsonSchema, MergeFrom, strum::VariantArray, strum::VariantNames, )] #[serde(rename_all = "lowercase")] pub enum FileFinderWidthContent { #[default] Small, Medium, Large, XLarge, Full, } #[with_fallible_options] #[derive(Clone, Default, Serialize, Deserialize, PartialEq, Debug, JsonSchema, MergeFrom)] pub struct VimSettingsContent { pub default_mode: Option, pub toggle_relative_line_numbers: Option, pub use_system_clipboard: Option, pub use_smartcase_find: Option, pub custom_digraphs: Option>>, pub highlight_on_yank_duration: Option, pub cursor_shape: Option, } #[derive(Copy, Clone, Default, Serialize, Deserialize, JsonSchema, MergeFrom, PartialEq, Debug)] #[serde(rename_all = "snake_case")] pub enum ModeContent { #[default] Normal, Insert, } /// Controls when to use system clipboard. #[derive(Copy, Clone, Debug, Serialize, Deserialize, PartialEq, Eq, JsonSchema, MergeFrom)] #[serde(rename_all = "snake_case")] pub enum UseSystemClipboard { /// Don't use system clipboard. Never, /// Use system clipboard. Always, /// Use system clipboard for yank operations. OnYank, } /// The settings for cursor shape. #[with_fallible_options] #[derive(Copy, Clone, Debug, Serialize, Deserialize, PartialEq, Eq, JsonSchema, MergeFrom)] pub struct CursorShapeSettings { /// Cursor shape for the normal mode. /// /// Default: block pub normal: Option, /// Cursor shape for the replace mode. /// /// Default: underline pub replace: Option, /// Cursor shape for the visual mode. /// /// Default: block pub visual: Option, /// Cursor shape for the insert mode. /// /// The default value follows the primary cursor_shape. pub insert: Option, } /// Settings specific to journaling #[with_fallible_options] #[derive(Clone, Debug, Serialize, Deserialize, JsonSchema, MergeFrom, PartialEq)] pub struct JournalSettingsContent { /// The path of the directory where journal entries are stored. /// /// Default: `~` pub path: Option, /// What format to display the hours in. /// /// Default: hour12 pub hour_format: Option, } #[derive(Clone, Debug, Default, Serialize, Deserialize, JsonSchema, MergeFrom, PartialEq)] #[serde(rename_all = "snake_case")] pub enum HourFormat { #[default] Hour12, Hour24, } #[with_fallible_options] #[derive(Clone, Default, Serialize, Deserialize, JsonSchema, MergeFrom, Debug, PartialEq)] pub struct OutlinePanelSettingsContent { /// Whether to show the outline panel button in the status bar. /// /// Default: true pub button: Option, /// Customize default width (in pixels) taken by outline panel /// /// Default: 240 #[serde(serialize_with = "crate::serialize_optional_f32_with_two_decimal_places")] pub default_width: Option, /// The position of outline panel /// /// Default: left pub dock: Option, /// Whether to show file icons in the outline panel. /// /// Default: true pub file_icons: Option, /// Whether to show folder icons or chevrons for directories in the outline panel. /// /// Default: true pub folder_icons: Option, /// Whether to show the git status in the outline panel. /// /// Default: true pub git_status: Option, /// Amount of indentation (in pixels) for nested items. /// /// Default: 20 #[serde(serialize_with = "crate::serialize_optional_f32_with_two_decimal_places")] pub indent_size: Option, /// Whether to reveal it in the outline panel automatically, /// when a corresponding project entry becomes active. /// Gitignored entries are never auto revealed. /// /// Default: true pub auto_reveal_entries: Option, /// Whether to fold directories automatically /// when directory has only one directory inside. /// /// Default: true pub auto_fold_dirs: Option, /// Settings related to indent guides in the outline panel. pub indent_guides: Option, /// Scrollbar-related settings pub scrollbar: Option, /// Default depth to expand outline items in the current file. /// The default depth to which outline entries are expanded on reveal. /// - Set to 0 to collapse all items that have children /// - Set to 1 or higher to collapse items at that depth or deeper /// /// Default: 100 pub expand_outlines_with_depth: Option, } #[derive( Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema, MergeFrom, strum::VariantArray, strum::VariantNames, )] #[serde(rename_all = "snake_case")] pub enum DockSide { Left, Right, } #[derive( Copy, Clone, Debug, PartialEq, Eq, Deserialize, Serialize, JsonSchema, MergeFrom, strum::VariantArray, strum::VariantNames, )] #[serde(rename_all = "snake_case")] pub enum ShowIndentGuides { Always, Never, } #[with_fallible_options] #[derive( Copy, Clone, Debug, Serialize, Deserialize, JsonSchema, MergeFrom, PartialEq, Eq, Default, )] pub struct IndentGuidesSettingsContent { /// When to show the scrollbar in the outline panel. pub show: Option, } #[derive(Clone, Copy, Default, PartialEq, Debug, JsonSchema, MergeFrom, Deserialize, Serialize)] #[serde(rename_all = "snake_case")] pub enum LineIndicatorFormat { Short, #[default] Long, } /// The settings for the image viewer. #[with_fallible_options] #[derive(Clone, Debug, Serialize, Deserialize, JsonSchema, MergeFrom, Default, PartialEq)] pub struct ImageViewerSettingsContent { /// The unit to use for displaying image file sizes. /// /// Default: "binary" pub unit: Option, } #[with_fallible_options] #[derive( Clone, Copy, Debug, Serialize, Deserialize, JsonSchema, MergeFrom, Default, PartialEq, strum::VariantArray, strum::VariantNames, )] #[serde(rename_all = "snake_case")] pub enum ImageFileSizeUnit { /// Displays file size in binary units (e.g., KiB, MiB). #[default] Binary, /// Displays file size in decimal units (e.g., KB, MB). Decimal, } #[with_fallible_options] #[derive(Clone, Debug, Default, Serialize, Deserialize, JsonSchema, MergeFrom, PartialEq)] pub struct RemoteSettingsContent { pub ssh_connections: Option>, pub wsl_connections: Option>, pub dev_container_connections: Option>, pub read_ssh_config: Option, } #[with_fallible_options] #[derive( Clone, Debug, Default, Serialize, Deserialize, PartialEq, Eq, JsonSchema, MergeFrom, Hash, )] pub struct DevContainerConnection { pub name: SharedString, pub container_id: SharedString, } #[with_fallible_options] #[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq, JsonSchema, MergeFrom)] pub struct SshConnection { pub host: SharedString, pub username: Option, pub port: Option, #[serde(default)] pub args: Vec, #[serde(default)] pub projects: collections::BTreeSet, /// Name to use for this server in UI. pub nickname: Option, // By default Zed will download the binary to the host directly. // If this is set to true, Zed will download the binary to your local machine, // and then upload it over the SSH connection. Useful if your SSH server has // limited outbound internet access. pub upload_binary_over_ssh: Option, pub port_forwards: Option>, /// Timeout in seconds for SSH connection and downloading the remote server binary. /// Defaults to 10 seconds if not specified. pub connection_timeout: Option, } #[derive(Clone, Default, Serialize, Deserialize, PartialEq, JsonSchema, MergeFrom, Debug)] pub struct WslConnection { pub distro_name: SharedString, pub user: Option, #[serde(default)] pub projects: BTreeSet, } #[with_fallible_options] #[derive( Clone, Debug, Default, Serialize, PartialEq, Eq, PartialOrd, Ord, Deserialize, JsonSchema, )] pub struct RemoteProject { pub paths: Vec, } #[with_fallible_options] #[derive(Debug, Clone, PartialEq, Eq, Hash, Deserialize, Serialize, JsonSchema, MergeFrom)] pub struct SshPortForwardOption { pub local_host: Option, pub local_port: u16, pub remote_host: Option, pub remote_port: u16, } /// Settings for configuring REPL display and behavior. #[with_fallible_options] #[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema, MergeFrom)] pub struct ReplSettingsContent { /// Maximum number of lines to keep in REPL's scrollback buffer. /// Clamped with [4, 256] range. /// /// Default: 32 pub max_lines: Option, /// Maximum number of columns to keep in REPL's scrollback buffer. /// Clamped with [20, 512] range. /// /// Default: 128 pub max_columns: Option, } #[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)] /// An ExtendingVec in the settings can only accumulate new values. /// /// This is useful for things like private files where you only want /// to allow new values to be added. /// /// Consider using a HashMap instead of this type /// (like auto_install_extensions) so that user settings files can both add /// and remove values from the set. pub struct ExtendingVec(pub Vec); impl Into> for ExtendingVec { fn into(self) -> Vec { self.0 } } impl From> for ExtendingVec { fn from(vec: Vec) -> Self { ExtendingVec(vec) } } impl merge_from::MergeFrom for ExtendingVec { fn merge_from(&mut self, other: &Self) { self.0.extend_from_slice(other.0.as_slice()); } } /// A SaturatingBool in the settings can only ever be set to true, /// later attempts to set it to false will be ignored. /// /// Used by `disable_ai`. #[derive(Debug, Default, Copy, Clone, PartialEq, Serialize, Deserialize, JsonSchema)] pub struct SaturatingBool(pub bool); impl From for SaturatingBool { fn from(value: bool) -> Self { SaturatingBool(value) } } impl From for bool { fn from(value: SaturatingBool) -> bool { value.0 } } impl merge_from::MergeFrom for SaturatingBool { fn merge_from(&mut self, other: &Self) { self.0 |= other.0 } } #[derive( Copy, Clone, Default, Debug, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize, MergeFrom, JsonSchema, derive_more::FromStr, )] #[serde(transparent)] pub struct DelayMs(pub u64); impl From for DelayMs { fn from(n: u64) -> Self { Self(n) } } impl std::fmt::Display for DelayMs { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "{}ms", self.0) } }