This document outlines the preferred dependencies and libraries to use in the Cyber Ware project.
Always use serde-saphyr for YAML serialization/deserialization, not serde_yaml.
- Package name in Cargo.toml:
serde-saphyr - Import in Rust code:
use serde_saphyr; - Reason:
serde_yamlis deprecated and unmaintained.serde-saphyris the actively maintained fork.
use serde_saphyr;
use std::collections::HashMap;
// Serialization
let data = HashMap::from([("key", "value")]);
let yaml_string = serde_saphyr::to_string(&data)?;
// Deserialization
let parsed: HashMap<String, String> = serde_saphyr::from_str(&yaml_string)?;Note: serde-saphyr does not provide a Value type like serde_yaml did. For generic YAML parsing, use HashMap<String, serde_json::Value> or define a specific struct.
Always use parking_lot::Mutex and parking_lot::RwLock for synchronous locks, not std::sync::Mutex / std::sync::RwLock.
- Reason:
parking_lotlocks are faster (no syscall on uncontended path), have smaller lock metadata thanstd, never poison on panic, and return the guard directly fromlock()— noResultunwrapping needed. - Workspace dep:
parking_lotis already declared in the workspaceCargo.toml.
use parking_lot::Mutex;
let data = Mutex::new(Vec::new());
// Blocking lock — returns MutexGuard directly, no unwrap needed
data.lock().push(42);Use tokio::sync::Mutex or tokio::sync::RwLock only when you need to hold the lock across an .await point. If the critical section is purely synchronous (no .await inside), prefer parking_lot even in async code — it avoids the overhead of the async mutex and won't block the executor as long as the critical section is short.
If a synchronous lock guard must be held while performing blocking I/O or expensive computation, wrap the call in tokio::task::spawn_blocking() to avoid stalling the async executor.