From 202417dab3faf78e15de7117fe62b3a0ae2238fd Mon Sep 17 00:00:00 2001 From: storybored379 Date: Tue, 6 Oct 2026 09:58:59 -0700 Subject: [PATCH] Settings: handle invalid Unicode label colours gracefully Use checked hex slices so prefs.set follows the existing invalid-colour fallback when a component splits a UTF-8 character. Cover invalid Unicode placements and valid mixed-case colours through the command. Co-Authored-By: OpenAI Codex --- crates/engine/src/prefs.rs | 2 +- crates/engine/src/tests_settings.rs | 13 +++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/crates/engine/src/prefs.rs b/crates/engine/src/prefs.rs index e56867d6..a0d305e9 100644 --- a/crates/engine/src/prefs.rs +++ b/crates/engine/src/prefs.rs @@ -262,7 +262,7 @@ fn parse_hex(s: &str) -> Option<[u8; 3]> { if h.len() != 6 { return None; } - let p = |i: usize| u8::from_str_radix(&h[i..i + 2], 16).ok(); + let p = |i: usize| u8::from_str_radix(h.get(i..i + 2)?, 16).ok(); Some([p(0)?, p(2)?, p(4)?]) } diff --git a/crates/engine/src/tests_settings.rs b/crates/engine/src/tests_settings.rs index 8c2fcac5..4afa08fc 100644 --- a/crates/engine/src/tests_settings.rs +++ b/crates/engine/src/tests_settings.rs @@ -508,3 +508,16 @@ fn interface_language_is_validated_persisted_and_backward_compatible() { assert_eq!(Prefs::from_json(r#"{"general":{"undoLevels":17}}"#).general.language, "en"); assert_eq!(Prefs::from_json(r#"{"general":{"language":"unknown"}}"#).general.language, "en"); } + +#[test] +fn unicode_label_colors_fall_back_without_panicking() { + use effectcraft_color::Label; + let mut s = Session::default(); + let default = s.prefs.label_rgb(Label::Red); + for color in ["#€abc", "#a€bc", "#abc€"] { + s.execute("prefs.set", json!({"key": "labels.0.color", "value": color})).unwrap(); + assert_eq!(s.prefs.label_rgb(Label::Red), default); + } + s.execute("prefs.set", json!({"key": "labels.0.color", "value": "#aBcD09"})).unwrap(); + assert_eq!(s.prefs.label_rgb(Label::Red), [0xab, 0xcd, 9]); +}