state_store/property.rs
1//! Property trait for typed, watchable state values
2//!
3//! The Property trait defines the contract for values that can be stored,
4//! watched, and tracked for changes in a StateStore.
5//!
6//! # Example
7//!
8//! ```rust,ignore
9//! use state_store::Property;
10//!
11//! #[derive(Clone, PartialEq, Debug)]
12//! pub struct Temperature(pub f32);
13//!
14//! impl Property for Temperature {
15//! const KEY: &'static str = "temperature";
16//! }
17//! ```
18
19/// Marker trait for properties that can be stored and watched
20///
21/// Properties must be:
22/// - Clone: For copying values to watchers
23/// - Send + Sync: For thread-safe access
24/// - PartialEq: For change detection (only emit when value actually changes)
25/// - 'static: For type-erased storage using TypeId
26///
27/// The KEY constant provides a human-readable identifier for debugging,
28/// logging, and event filtering.
29pub trait Property: Clone + Send + Sync + PartialEq + 'static {
30 /// Unique key identifying this property type
31 ///
32 /// Used for debugging, logging, and filtering change events.
33 /// Should be unique within your application domain.
34 ///
35 /// # Examples
36 ///
37 /// - `"volume"` for audio volume
38 /// - `"temperature"` for sensor readings
39 /// - `"connection_state"` for network status
40 const KEY: &'static str;
41}
42
43#[cfg(test)]
44mod tests {
45 use super::*;
46
47 #[derive(Clone, PartialEq, Debug)]
48 struct TestProperty(i32);
49
50 impl Property for TestProperty {
51 const KEY: &'static str = "test_property";
52 }
53
54 #[test]
55 fn test_property_key() {
56 assert_eq!(TestProperty::KEY, "test_property");
57 }
58
59 #[test]
60 fn test_property_equality() {
61 let a = TestProperty(42);
62 let b = TestProperty(42);
63 let c = TestProperty(99);
64
65 assert_eq!(a, b);
66 assert_ne!(a, c);
67 }
68}