# What Is the openlogi-core Crate in OpenLogi? The Foundation Data Layer

> Discover the openlogi-core crate, OpenLogi's platform-agnostic data foundation. It defines pure logic for device configurations, bindings, and actions for seamless WebAssembly and native use.

- Repository: [Xuan Zhang/OpenLogi](https://github.com/AprilNEA/OpenLogi)
- Tags: internals
- Published: 2026-08-27

---

**The `openlogi-core` crate serves as the platform-agnostic foundation of the AprilNEA/OpenLogi project, containing pure data structures and logic for device configurations, bindings, and actions while strictly excluding I/O and OS-specific code to ensure portability across WebAssembly and native targets.**

The `openlogi-core` crate establishes the shared vocabulary that powers the entire OpenLogi ecosystem. As implemented in the AprilNEA/OpenLogi repository, this Rust crate defines the data models for Logitech device descriptions, action catalogs, and on-disk configuration without coupling to any specific runtime environment. Every other component—including the desktop GUI, background agent, and HID++ communication layers—depends on this crate for type-safe data interchange.

## Core Responsibilities of the openlogi-core Crate

### Pure Data and Logic Definitions

At its heart, `openlogi-core` contains **only pure data and logic** that can be shared across all architectural layers. The crate defines the fundamental structures that describe Logitech hardware capabilities, user-configurable actions, and persistence schemas. According to the crate-level documentation in [`src/lib.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/src/lib.rs), it provides "Shared types and configuration for OpenLogi," ensuring that concepts like DPI settings, SmartShift parameters, and lighting profiles have a single source of truth.

### Platform Agnostic by Design

The crate deliberately **excludes any platform-specific code** such as `hidpp`, `async-hid`, or OS-specific event APIs. These implementation details live in sibling crates like `openlogi-hid`, `openlogi-agent`, and `openlogi-desktop`. This strict separation means `openlogi-core` never touches the host environment directly, making it suitable for targets where system access is restricted or unavailable. The project enforces this boundary through a "portable-crates" CI job that verifies the crate compiles correctly for WebAssembly.

### Optional Feature Gating

While the base crate contains only pure data, optional Cargo features extend its capabilities when the target platform permits:

- **`fs`**: Enables file system operations for reading and writing the TOML configuration file via the `paths` module
- **`locale`**: Adds locale negotiation logic for selecting UI language preferences

Both features are gated behind explicit flags, allowing the core crate to remain lean when compiled for constrained environments like WebAssembly.

## Key Source Files and Architecture

The crate's implementation is organized into focused modules that collectively form the model layer:

- **[`src/lib.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/src/lib.rs)** — Crate-level documentation and public module re-exports
- **[`src/config.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/src/config.rs)** — Defines the `Config` struct and device configuration schema
- **`src/binding/*.rs`** — Contains types for button bindings, gestures, and action mappings
- **[`src/device.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/src/device.rs)** — Represents Logitech HID++ device capabilities and metadata
- **[`src/action_ring.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/src/action_ring.rs)** — Implements the `ActionRing` data structure for the circular Actions Ring UI component
- **[`src/locale.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/src/locale.rs)** (feature-gated) — Handles user locale negotiation
- **[`src/paths.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/src/paths.rs)** (feature-gated) — Provides platform-agnostic configuration file paths

These files define the configuration schema and binding types that the rest of the application operates on, ensuring that [`openlogi-desktop/src/services/config.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/openlogi-desktop/src/services/config.rs) and [`openlogi-agent/src/main.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/openlogi-agent/src/main.rs) share identical data definitions.

## Cross-Crate Integration and Benefits

Because `openlogi-core` maintains strict separation from I/O concerns, downstream crates can import the same type definitions without pulling in heavy OS bindings. This architecture delivers three critical advantages:

1. **Portable** — Compiles for any Rust target, including WebAssembly, enabling future web-based configuration interfaces
2. **Stable** — Changes to the shared datamodel are confined to a single location in [`src/config.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/src/config.rs) and related files, preventing synchronization errors between the GUI and agent
3. **Reusable** — Both the GUI (`openlogi-desktop`) and background agent (`openlogi-agent`) depend on it for configuration handling, DPI settings, and action definitions

## Practical Usage Examples

### Loading Configuration Files

When the `fs` feature is enabled, applications can load user preferences from disk:

```rust
use openlogi_core::config::Config;

// Reads ~/.config/openlogi/config.toml
let cfg = Config::load().expect("Failed to read OpenLogi config");
println!("Configured DPI: {}", cfg.device.dpi);

```

### Defining Button Bindings

Create type-safe binding definitions that work across GUI and agent contexts:

```rust
use openlogi_core::binding::{Binding, Action};

let binding = Binding {
    button: openlogi_core::binding::button::Button::Left,
    modifiers: None,
    action: Action::KeyCombo(vec!['C', 'C', 'C']),
};

```

### Iterating Over Device Configurations

Process multiple device definitions using standard iterator patterns:

```rust
for dev in cfg.devices.iter() {
    println!("Device {} – DPI range {}–{}", dev.name, dev.dpi.min, dev.dpi.max);
}

```

### Managing the Action Ring

Manipulate the circular action selector used in the desktop interface:

```rust
use openlogi_core::action_ring::ActionRing;

let ring = ActionRing::default();
ring.select_next(); // Rotate the ring

```

## Summary

- The `openlogi-core` crate functions as the **model layer** of OpenLogi, containing pure data structures for devices, configurations, and actions
- It maintains **strict platform independence** by excluding I/O code and OS-specific APIs, enabling WebAssembly compilation
- Optional **`fs`** and **`locale`** features provide filesystem and internationalization capabilities when needed
- Sibling crates including `openlogi-desktop`, `openlogi-agent`, and `openlogi-hid` consume these types for consistent data interchange
- Key files like [`src/config.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/src/config.rs) and `src/binding/*.rs` serve as the single source of truth for the project's data schema

## Frequently Asked Questions

### What is the primary role of the openlogi-core crate in OpenLogi?

The crate serves as the foundational **data model layer** that defines shared types for device descriptions, button bindings, and configuration schemas. It enables the GUI, agent, and HID layers to communicate using identical data structures without duplicating type definitions across the codebase.

### How does openlogi-core maintain platform independence?

The crate deliberately excludes hardware communication libraries like `hidpp` or `async-hid`, containing only pure Rust data structures and logic. Platform-specific code resides in sibling crates, while `openlogi-core` remains compatible with WebAssembly and other constrained targets through its feature-gated design.

### Which OpenLogi components depend on openlogi-core?

Both the desktop GUI (`openlogi-desktop`) and the background service (`openlogi-agent`) import this crate to handle configuration parsing and device modeling. The HID++ communication layer also references these types when translating raw hardware events into the application's internal action representation.

### What optional features does openlogi-core provide?

The crate offers two primary optional features: **`fs`**, which adds filesystem operations for reading `~/.config/openlogi/config.toml`, and **`locale`**, which enables user language preference detection. Both are disabled by default to preserve portability when compiling for targets without standard filesystem access.