How OpenLogi Core Serializes Rust Variant Names for TOML Configuration
OpenLogi Core uses Serde's default external tagging to serialize the Action enum, representing unit variants as bare strings and tuple or struct variants as single-key tables where the key matches the Rust variant name exactly.
The action catalog in openlogi-core manages user-defined automation behaviors through a strongly-typed Rust enum that persists to human-readable TOML configuration files. Located in crates/openlogi-core/src/binding/action.rs at lines 9–23, the Action enum leverages #[derive(Serialize, Deserialize)] at lines 11–14 and 22–23 to map Rust variant names directly to TOML keys, ensuring deterministic serialization without custom boilerplate.
The Action Enum Schema in openlogi-core
The Action enum in crates/openlogi-core/src/binding/action.rs defines the complete catalog of available automation actions. According to the source code at lines 11–14 and 22–23, the enum derives both serde::Serialize and serde::Deserialize, which instructs Serde to use external tagging by default. This means the variant name itself becomes the TOML key during serialization, creating a self-documenting configuration format where the Rust type system and the on-disk schema remain synchronized.
External Tagging Rules for TOML Serialization
Serde applies consistent external tagging rules when converting the Action enum to TOML. The specific representation depends on the variant type—unit, tuple, or struct-like—determining whether the output appears as a simple string or a nested table.
Unit Variants as Bare Strings
Unit variants containing no associated data serialize as bare string values. The TOML output consists solely of the variant name without braces or additional keys.
# Unit variant - simple string
action = "BrowserBack"
This matches Rust unit variants such as Action::BrowserBack directly, requiring no nested structure for empty payloads.
Tuple Variants as Single-Key Tables
Tuple variants carrying a single associated value serialize as single-key tables where the variant name becomes the table key and the inner data becomes the value.
# Tuple variant - single-key table
action = { SetDpiPreset = 3 }
This representation corresponds to Rust instantiations like Action::SetDpiPreset(3), wrapping the integer payload within a table keyed exactly to the variant name.
Struct-Like Variants with Nested Data
Struct-like variants containing named fields follow the same single-key table rule, but the value becomes a nested map of field names to values.
# Struct-like variant - nested table
action = { CustomShortcut = { modifiers = ["Ctrl", "Shift"], key = "A" } }
This structure accommodates complex data structures such as the KeyCombo type defined in crates/openlogi-core/src/binding/key_combo.rs, preserving field-level granularity within the TOML hierarchy.
String Payload Variants
Variants wrapping generic data like String follow the single-key table convention, with the string payload placed directly as the value.
# Variant with a string payload
action = { RunShellCommand = "notify-send \"Hello\"" }
This handles payloads such as Action::RunShellCommand("notify-send \"Hello\"".into()), storing shell commands or other string data as scalar values within the variant-keyed table.
Schema Stability and Migration Constraints
Because variant names constitute the on-disk schema, OpenLogi treats them as frozen identifiers. The source code comment at lines 15–17 of action.rs explicitly warns that adding new actions is permitted, but removing or renaming existing variants requires a schema_version bump and a migration script. This constraint ensures that user-provided config.toml files remain valid across software updates, as Serde relies on exact string matching to deserialize TOML keys back to Rust enum variants.
Practical Configuration Examples
When OpenLogi reads a config.toml file, Serde automatically maps these TOML representations back to the appropriate Rust enum variants. The mapping preserves exact spelling and case sensitivity, guaranteeing deterministic round-trip serialization.
TOML Configuration Samples
# Unit variant – simple string
action = "BrowserBack"
# Tuple variant – single-key table
action = { SetDpiPreset = 2 }
# Struct-like variant – nested table
action = { CustomShortcut = { modifiers = ["Ctrl", "Shift"], key = "A" } }
# Variant with a string payload
action = { RunShellCommand = "notify-send \"Hello\"" }
Equivalent Rust Constructions
These TOML structures correspond to the following Rust code using types from openlogi_core::binding:
use openlogi_core::binding::action::Action;
use openlogi_core::binding::key_combo::KeyCombo;
// Unit variant
let a = Action::BrowserBack;
// Tuple variant
let b = Action::SetDpiPreset(2);
// Struct-like variant with KeyCombo
let combo = KeyCombo::from_str("Ctrl+Shift+A").unwrap();
let c = Action::CustomShortcut(combo);
// String payload variant
let d = Action::RunShellCommand("notify-send \"Hello\"".into());
The KeyCombo parsing logic resides in crates/openlogi-core/src/binding/key_combo.rs, while the integration of Action into the broader configuration system appears in crates/openlogi-core/src/config/settings.rs.
Summary
- External tagging: Serde serializes the
Actionenum using the variant name as the TOML key, implemented via derived macros incrates/openlogi-core/src/binding/action.rsat lines 11–14. - Unit variants appear as bare strings (e.g.,
"BrowserBack"), while tuple and struct variants appear as single-key tables (e.g.,{ SetDpiPreset = 3 }). - Schema stability: Variant names are frozen to prevent configuration breakage; changes require explicit
schema_versionmigrations per lines 15–17 of the source. - Related files: Type definitions in
key_combo.rssupport complex variants likeCustomShortcut, whilesettings.rshandles integration into the main TOML configuration.
Frequently Asked Questions
What file defines the Action enum in openlogi-core?
The Action enum is defined in crates/openlogi-core/src/binding/action.rs at lines 9–23, where it derives Serialize and Deserialize at lines 11–14 and 22–23 to enable TOML serialization.
How does Serde serialize unit variants versus tuple variants in TOML?
Serde serializes unit variants as bare strings (e.g., action = "BrowserBack") and tuple variants as single-key tables where the key matches the variant name (e.g., action = { SetDpiPreset = 3 }). This follows Serde's default external tagging behavior.
Why are variant names frozen in OpenLogi's configuration schema?
Variant names are frozen because they form the structural keys in user config.toml files. Renaming or removing a variant would invalidate existing configurations, requiring a schema_version bump and migration script as noted in lines 15–17 of action.rs.
How can I construct Action variants directly in Rust code?
Import openlogi_core::binding::action::Action and instantiate variants using standard Rust enum syntax: Action::BrowserBack for units, Action::SetDpiPreset(2) for tuples, or Action::RunShellCommand("cmd".into()) for string payloads. Complex variants like Action::CustomShortcut require constructing a KeyCombo from openlogi_core::binding::key_combo::KeyCombo first.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →