diff --git a/crates/app/src/host/message.rs b/crates/app/src/host/message.rs index 9db1fde12..83eec67e9 100644 --- a/crates/app/src/host/message.rs +++ b/crates/app/src/host/message.rs @@ -85,9 +85,9 @@ pub struct PresetsImported { /// Import source recognized by the preset parser. #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum ImportFormat { - /// Native v1 Chipmunk named preset document. + /// Version 1 Chipmunk named preset document. Version1, - /// Native v2 Chipmunk named preset document. + /// Version 2 Chipmunk named preset document. Version2, /// Legacy Chipmunk V3 TypeScript frontend export. Legacy, diff --git a/crates/app/src/host/service/presets_io/legacy.rs b/crates/app/src/host/service/presets_io/legacy.rs index e28fa1521..fe45a7040 100644 --- a/crates/app/src/host/service/presets_io/legacy.rs +++ b/crates/app/src/host/service/presets_io/legacy.rs @@ -257,7 +257,7 @@ fn parse_legacy_collection(content: &str) -> Result Result { let value: Value = serde_json::from_str(payload)?; let filter = value @@ -292,7 +292,7 @@ fn parse_legacy_filter(payload: &str, index: usize) -> Result Result { let value: Value = serde_json::from_str(payload)?; let text = value @@ -300,7 +300,7 @@ fn parse_legacy_chart(payload: &str, index: usize) -> Result ColorPair { ColorPair::new(fg, bg) } -/// Reads a legacy chart color, defaulting to the native search-value palette. +/// Reads a legacy chart color, defaulting to the search-value palette. fn parse_legacy_chart_color(value: &Value, index: usize) -> Color32 { let default = colors::search_value_color(index); let Some(color) = value.get("color") else { @@ -387,7 +387,7 @@ fn parse_legacy_chart_color(value: &Value, index: usize) -> Color32 { }) } -/// Returns the native default filter color pair for a legacy row index. +/// Returns the default filter color pair for a legacy row index. fn default_filter_colors(index: usize) -> ColorPair { colors::FILTER_HIGHLIGHT_COLORS[index % colors::FILTER_HIGHLIGHT_COLORS.len()].clone() } diff --git a/crates/app/src/host/service/presets_io/mod.rs b/crates/app/src/host/service/presets_io/mod.rs index f6937ad71..26f477812 100644 --- a/crates/app/src/host/service/presets_io/mod.rs +++ b/crates/app/src/host/service/presets_io/mod.rs @@ -1,6 +1,6 @@ //! Service-side import and export for named preset documents. //! -//! This module owns the native on-disk JSON schema, parses the legacy export +//! This module owns the versioned on-disk JSON schema, parses the legacy export //! shape for backward compatibility, and validates imported filters before the //! UI applies them into the runtime preset registry. @@ -72,13 +72,13 @@ pub enum LegacyEntryKind { Unsupported(String), } -/// Validate then serializes a preset snapshot into the native named-presets +/// Validate then serializes a preset snapshot into the versioned named-presets /// JSON document. pub fn serialize_named_presets(presets: Vec) -> Result { - v2::serialize_native_v2_presets(presets) + v2::serialize_presets(presets) } -/// Parses a native preset document or a supported legacy export. +/// Parses a versioned preset document or a supported legacy export. /// /// Returned presets already have fresh runtime ids assigned so the UI can hand /// them to the registry import path directly. @@ -86,7 +86,7 @@ pub fn import_named_presets(text: &str) -> Result { let value = parse_root_value(text)?; let (format, presets, warnings) = match value { Value::Object(root) => { - let (format, presets) = parse_native_document_from_value(root)?; + let (format, presets) = parse_versioned_document(root)?; (format, presets, Vec::new()) } Value::Array(items) => { @@ -108,18 +108,18 @@ pub fn import_named_presets(text: &str) -> Result { fn parse_root_value(text: &str) -> Result { let trimmed = text.trim_start(); serde_json::from_str(text).map_err(|err| { - // The legacy export uses a top-level array while the native format uses + // The legacy export uses a top-level array while the versioned format uses // an object, so the first non-whitespace token is enough to classify // syntax failures for the user-facing error. if trimmed.starts_with('[') { format!("invalid legacy preset export: {err}") } else { - format!("invalid native preset document: {err}") + format!("invalid preset document: {err}") } }) } -fn parse_native_document_from_value( +fn parse_versioned_document( root: serde_json::Map, ) -> Result<(ImportFormat, Vec), String> { let kind = root @@ -138,18 +138,18 @@ fn parse_native_document_from_value( match version { 1 => { - let presets = v1::parse_native_v1_document(root)?; + let presets = v1::parse_document(root)?; Ok((ImportFormat::Version1, presets)) } DOCUMENT_VERSION => { - let presets = v2::parse_native_v2_document(root)?; + let presets = v2::parse_document(root)?; Ok((ImportFormat::Version2, presets)) } _ => Err(format!("unsupported preset document version: {version}")), } } -/// Validates that a preset name is usable in native imports and exports. +/// Validates that a preset name is usable in versioned imports and exports. pub fn validate_name(name: &str) -> Result<(), String> { if name.trim().is_empty() { return Err("preset name cannot be blank".to_owned()); @@ -218,18 +218,18 @@ mod tests { use super::*; #[test] - fn native_rejects_kind() { + fn rejects_unsupported_document_kind() { import_named_presets(r#"{"kind":"wrong","version":2,"presets":[]}"#).unwrap_err(); } #[test] - fn native_rejects_version() { + fn rejects_unsupported_document_version() { import_named_presets(r#"{"kind":"chipmunk_named_presets","version":3,"presets":[]}"#) .unwrap_err(); } #[test] - fn import_rejects_object_without_native_kind() { + fn import_rejects_object_without_document_kind() { import_named_presets(r#"{"presets":[]}"#).unwrap_err(); } } diff --git a/crates/app/src/host/service/presets_io/v1.rs b/crates/app/src/host/service/presets_io/v1.rs index d234c1ed3..484806f17 100644 --- a/crates/app/src/host/service/presets_io/v1.rs +++ b/crates/app/src/host/service/presets_io/v1.rs @@ -1,4 +1,4 @@ -//! Native v1 preset import compatibility. +//! Version 1 preset document import compatibility. //! //! Unlike v2, v1 stores only filter/search-value definitions. Row enabled //! state and colors are not present, so conversion immediately applies runtime @@ -29,38 +29,33 @@ use crate::host::ui::registry::presets::Preset; use super::{validate_filter_entry, validate_name, validate_search_value_entry}; -/// Preset payload stored in native v1 preset documents. +/// Preset payload stored in v1 preset documents. #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] -struct NativePresetV1 { +struct DocumentPreset { name: String, filters: Vec, search_values: Vec, } #[derive(Debug, Serialize, Deserialize)] -struct NativeDocumentV1 { +struct PresetDocument { kind: String, version: u8, - presets: Vec, + presets: Vec, } -/// Parses a native v1 document object into runtime presets with default row state. -pub fn parse_native_v1_document( - root: serde_json::Map, -) -> Result, String> { - let document: NativeDocumentV1 = serde_json::from_value(Value::Object(root)) - .map_err(|err| format!("invalid native preset document: {err}"))?; - document - .presets - .iter() - .try_for_each(validate_native_preset_v1)?; +/// Parses a v1 document object into runtime presets with default row state. +pub fn parse_document(root: serde_json::Map) -> Result, String> { + let document: PresetDocument = serde_json::from_value(Value::Object(root)) + .map_err(|err| format!("invalid preset document: {err}"))?; + document.presets.iter().try_for_each(validate_preset)?; let presets = document.presets.into_iter().map(Preset::from).collect(); Ok(presets) } -fn validate_native_preset_v1(preset: &NativePresetV1) -> Result<(), String> { - let NativePresetV1 { +fn validate_preset(preset: &DocumentPreset) -> Result<(), String> { + let DocumentPreset { name, filters, search_values, @@ -79,8 +74,8 @@ fn validate_native_preset_v1(preset: &NativePresetV1) -> Result<(), String> { Ok(()) } -impl From for Preset { - fn from(value: NativePresetV1) -> Self { +impl From for Preset { + fn from(value: DocumentPreset) -> Self { Preset::with_default_state( Uuid::new_v4(), value.name, diff --git a/crates/app/src/host/service/presets_io/v2.rs b/crates/app/src/host/service/presets_io/v2.rs index b94385020..6aab73b6d 100644 --- a/crates/app/src/host/service/presets_io/v2.rs +++ b/crates/app/src/host/service/presets_io/v2.rs @@ -1,6 +1,6 @@ -//! Current native preset document serialization and import. +//! Current preset document serialization and import. //! -//! Version 2 native documents store named filter and search-value row snapshots, +//! Version 2 documents store named filter and search-value row snapshots, //! including enabled state and colors. use egui::Color32; @@ -21,83 +21,77 @@ use super::{ type Rgba = [u8; 4]; -/// Preset payload stored in the current native preset document. +/// Preset payload stored in the current preset document. #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] -struct NativePresetV2 { +struct DocumentPreset { name: String, - filters: Vec, - search_values: Vec, + filters: Vec, + search_values: Vec, } -/// Filter row payload stored in the current native preset document. +/// Filter row payload stored in the current preset document. #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] -struct NativeFilterEntry { +struct DocumentFilterEntry { filter: SearchFilter, enabled: bool, - colors: NativeColorPair, + colors: DocumentColorPair, } -/// Chart/search-value row payload stored in the current native preset document. +/// Chart/search-value row payload stored in the current preset document. #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] -struct NativeSearchValueEntry { +struct DocumentSearchValueEntry { filter: SearchFilter, enabled: bool, color: Rgba, } #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] -struct NativeColorPair { +struct DocumentColorPair { fg: Rgba, bg: Rgba, } /// Versioned preset document stored on disk. #[derive(Debug, Serialize, Deserialize)] -struct NativeDocumentV2 { +struct PresetDocument { kind: String, version: u8, - presets: Vec, + presets: Vec, } -/// Serializes runtime presets into the native v2 document format. -pub fn serialize_native_v2_presets(presets: Vec) -> Result { +/// Serializes runtime presets into the v2 document format. +pub fn serialize_presets(presets: Vec) -> Result { // Runtime preset ids are intentionally ignored here because the file format // stores only named row snapshots. - let presets = presets.into_iter().map(NativePresetV2::from).collect(); + let presets = presets.into_iter().map(DocumentPreset::from).collect(); - serialize_native_v2_document(presets) + serialize_document(presets) } -fn serialize_native_v2_document(presets: Vec) -> Result { - presets.iter().try_for_each(validate_native_preset_v2)?; +fn serialize_document(presets: Vec) -> Result { + presets.iter().try_for_each(validate_preset)?; - let document = NativeDocumentV2 { + let document = PresetDocument { kind: DOCUMENT_KIND.to_owned(), version: DOCUMENT_VERSION, presets, }; - serde_json::to_string_pretty(&document) - .map_err(|err| format!("invalid native preset document: {err}")) + serde_json::to_string_pretty(&document).map_err(|err| format!("invalid preset document: {err}")) } -/// Parses a native v2 document object into runtime presets. -pub fn parse_native_v2_document( - root: serde_json::Map, -) -> Result, String> { - let document: NativeDocumentV2 = serde_json::from_value(Value::Object(root)) - .map_err(|err| format!("invalid native preset document: {err}"))?; - document - .presets - .iter() - .try_for_each(validate_native_preset_v2)?; +/// Parses a v2 document object into runtime presets. +pub fn parse_document(root: serde_json::Map) -> Result, String> { + let document: PresetDocument = serde_json::from_value(Value::Object(root)) + .map_err(|err| format!("invalid preset document: {err}"))?; + document.presets.iter().try_for_each(validate_preset)?; let presets = document.presets.into_iter().map(Preset::from).collect(); Ok(presets) } -fn validate_native_preset_v2(preset: &NativePresetV2) -> Result<(), String> { - let NativePresetV2 { +fn validate_preset(preset: &DocumentPreset) -> Result<(), String> { + let DocumentPreset { name, filters, search_values, @@ -106,7 +100,7 @@ fn validate_native_preset_v2(preset: &NativePresetV2) -> Result<(), String> { validate_name(name)?; for entry in filters { - let NativeFilterEntry { + let DocumentFilterEntry { filter, enabled: _, colors: _, @@ -115,7 +109,7 @@ fn validate_native_preset_v2(preset: &NativePresetV2) -> Result<(), String> { } for entry in search_values { - let NativeSearchValueEntry { + let DocumentSearchValueEntry { filter, enabled: _, color: _, @@ -126,35 +120,35 @@ fn validate_native_preset_v2(preset: &NativePresetV2) -> Result<(), String> { Ok(()) } -impl From for NativePresetV2 { +impl From for DocumentPreset { fn from(value: Preset) -> Self { Self { name: value.name, filters: value .filters .into_iter() - .map(NativeFilterEntry::from) + .map(DocumentFilterEntry::from) .collect(), search_values: value .search_values .into_iter() - .map(NativeSearchValueEntry::from) + .map(DocumentSearchValueEntry::from) .collect(), } } } -impl From for NativeFilterEntry { +impl From for DocumentFilterEntry { fn from(value: PresetFilterEntry) -> Self { Self { filter: value.filter, enabled: value.enabled, - colors: NativeColorPair::from(value.colors), + colors: DocumentColorPair::from(value.colors), } } } -impl From for NativeSearchValueEntry { +impl From for DocumentSearchValueEntry { fn from(value: PresetSearchValueEntry) -> Self { Self { filter: value.filter, @@ -164,7 +158,7 @@ impl From for NativeSearchValueEntry { } } -impl From for NativeColorPair { +impl From for DocumentColorPair { fn from(value: ColorPair) -> Self { Self { fg: color_to_rgba(value.fg), @@ -173,8 +167,8 @@ impl From for NativeColorPair { } } -impl From for Preset { - fn from(value: NativePresetV2) -> Self { +impl From for Preset { + fn from(value: DocumentPreset) -> Self { Self { // Import always creates fresh runtime ids. Name collision handling is // deferred to the UI registry import path. @@ -194,20 +188,20 @@ impl From for Preset { } } -impl From for PresetFilterEntry { - fn from(value: NativeFilterEntry) -> Self { +impl From for PresetFilterEntry { + fn from(value: DocumentFilterEntry) -> Self { Self::new(value.filter, value.enabled, ColorPair::from(value.colors)) } } -impl From for PresetSearchValueEntry { - fn from(value: NativeSearchValueEntry) -> Self { +impl From for PresetSearchValueEntry { + fn from(value: DocumentSearchValueEntry) -> Self { Self::new(value.filter, value.enabled, color_from_rgba(value.color)) } } -impl From for ColorPair { - fn from(value: NativeColorPair) -> Self { +impl From for ColorPair { + fn from(value: DocumentColorPair) -> Self { Self::new(color_from_rgba(value.fg), color_from_rgba(value.bg)) } } @@ -276,7 +270,7 @@ mod tests { } #[test] - fn native_v2_round_trip_preserves_state() { + fn v2_round_trip_preserves_state() { let source = vec![Preset { id: Uuid::new_v4(), name: "Errors".to_owned(), @@ -314,7 +308,7 @@ mod tests { } #[test] - fn native_rejects_blank_name() { + fn rejects_blank_name() { import_named_presets( r#"{"kind":"chipmunk_named_presets","version":2,"presets":[{"name":" ","filters":[],"search_values":[]}]}"#, ) @@ -322,7 +316,7 @@ mod tests { } #[test] - fn native_rejects_invalid_filter() { + fn rejects_invalid_filter() { import_named_presets( r#"{"kind":"chipmunk_named_presets","version":2,"presets":[{"name":"Broken","filters":[{"filter":{"value":"(","is_regex":true,"ignore_case":true,"is_word":false},"enabled":true,"colors":{"fg":[255,255,255,255],"bg":[0,0,0,255]}}],"search_values":[]}]}"#, ) @@ -330,7 +324,7 @@ mod tests { } #[test] - fn native_rejects_invalid_search_value() { + fn rejects_invalid_search_value() { import_named_presets( r#"{"kind":"chipmunk_named_presets","version":2,"presets":[{"name":"Broken","filters":[],"search_values":[{"filter":{"value":"cpu=(.+)","is_regex":true,"ignore_case":true,"is_word":false},"enabled":true,"color":[255,255,255,255]}]}]}"#, ) @@ -363,7 +357,7 @@ mod tests { } #[test] - fn import_native_document_preserves_duplicate_names() { + fn import_versioned_document_preserves_duplicate_names() { let json = r#" { "kind": "chipmunk_named_presets",