Skip to main content

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}