static_id/
lib.rs

1//! # StaticId
2//!
3//! This library provides an extremely memory-efficient implementation of `StaticId`
4//! for handling interned identifiers with optimal performance.
5//!
6//! ## Features
7//!
8//! - `StaticId`: A highly optimized, interned identifier type combining a code and a venue.
9//! - Exceptional memory efficiency: Each `StaticId` is represented by a single 64-bit pointer.
10//! - Ultra-fast comparisons: Equality checks and hashing operations only compare 8 bytes,
11//!   regardless of the actual string length.
12//! - Lazy evaluation: The actual string data is only accessed during serialization.
13//!
14//! ## Limitations
15//! - The bound of `code` and `venue` are fixed: For StaticIdNxM, the maximum length of `code` and `venue` is N and M respectively. The exceeding characters will be truncated.
16//! - The given structs are:
17//!   * StaticId16x0
18//!   * StaticId16x16
19//!   * StaticId16x32
20//!   * StaticId16x64
21//!   * StaticId32x0
22//!   * StaticId32x16
23//!   * StaticId32x32 (=StaticId)
24//!   * StaticId32x64
25//!   * StaticId64x0
26//!   * StaticId64x16
27//!   * StaticId64x32
28//!   * StaticId64x64
29//! 
30//! ## Usage
31//!
32//! ```rust
33//! use static_id::StaticId;
34//!
35//! assert_eq!(size_of::<StaticId>(), 8);
36//! 
37//! let id = StaticId::from_str("AAPL", "NASDAQ");
38//! assert_eq!(id.get_id().code.as_str(), "AAPL");
39//! assert_eq!(id.get_id().venue.as_str(), "NASDAQ");
40//! 
41//! assert_eq!(id.code_str(), "AAPL");
42//! assert_eq!(id.venue_str(), "NASDAQ");
43//!
44//! // Fast equality check (compares only 8 bytes)
45//! let id2 = StaticId::from_str("AAPL", "NASDAQ");
46//! assert_eq!(id, id2);
47//! println!("ID: {}", id); // => AAPL@NASDAQ
48//! 
49//! 
50//! ```
51//!
52pub mod static_id;
53pub mod symbol;
54
55pub use symbol::Symbol;
56pub use crate::static_id::*;
57
58#[cfg(test)]
59mod tests {
60    use crate::{StaticId, StaticId64x64};
61    use std::mem::size_of;
62    use std::collections::HashMap;
63    use serde_json;
64    use deepsize::DeepSizeOf;
65
66    #[test]
67    fn test_mem_size() {
68        let size = std::mem::size_of::<StaticId>();
69        let id = StaticId::from_str("AAPL", "NASDAQ");
70        assert_eq!(size, 8, "StaticId should be 8 bytes");
71        assert_eq!(id.deep_size_of(), 8, "StaticId should be 8 bytes");
72
73        let id = StaticId64x64::from_str("AAPL", "NASDAQ");
74        assert_eq!(id.deep_size_of(), 8, "StaticId64x64 should be 16 bytes");
75    }
76
77    #[test]
78    fn test_serde() {
79        let id = StaticId::from_str("AAPL", "NASDAQ");
80        let serialized = serde_json::to_string(&id).unwrap();
81        println!("{}", serialized);
82        let deserde: StaticId = serde_json::from_str(&serialized).unwrap();
83        assert_eq!(id, deserde);
84
85        let mut map = HashMap::new();
86        map.insert(StaticId::from_str("AAPL", "NASDAQ"), 100);
87
88        let serialized = serde_json::to_string(&map).unwrap();
89        println!("{}", serialized);
90        let deserde: HashMap<StaticId, i32> = serde_json::from_str(&serialized).unwrap();
91        assert_eq!(map, deserde);
92    }
93    #[test]
94    fn test_static_id_equality() {
95        let id1 = StaticId::from_str("ABC", "NYSE");
96        let id2 = StaticId::from_str("ABC", "NYSE");
97        let id3 = StaticId::from_str("XYZ", "NASDAQ");
98
99        assert_eq!(id1, id2);
100        assert_ne!(id1, id3);
101    }
102
103    #[test]
104    fn test_static_id_reuse() {
105        let id1 = StaticId::from_str("ABC", "NYSE");
106        let id2 = StaticId::from_str("ABC", "NYSE");
107
108        assert!(std::ptr::eq(id1.id_ptr, id2.id_ptr));
109    }
110
111    #[test]
112    fn test_serialization() {
113        let id = StaticId::from_str("ABC", "NYSE");
114        let serialized = serde_json::to_string(&id).unwrap();
115       
116        let deserialized: StaticId = serde_json::from_str(&serialized).unwrap();
117
118        assert_eq!(id, deserialized);
119    }
120
121    #[test]
122    fn test_static_id_size() {
123        let size = size_of::<StaticId>();
124        println!("Size of StaticId: {} bytes", size);
125        
126        #[cfg(target_pointer_width = "64")]
127        assert_eq!(size, 8, "On 64-bit systems, StaticId should be 8 bytes");
128        
129        #[cfg(target_pointer_width = "32")]
130        assert_eq!(size, 4, "On 32-bit systems, StaticId should be 4 bytes");
131    }
132
133    #[test]
134    fn test_debug() {
135        let id = StaticId::from_str("ABC", "NYSE");
136        println!("{:?}", id);
137    }
138
139    #[test]
140    fn test_default() {
141        let id = StaticId::default();
142        println!("{:?}", id);
143        let expected_id = StaticId::from_str("", "");
144        assert_eq!(id, expected_id);
145    }
146
147    #[test]
148    fn test_hashmap() {
149        use std::collections::HashMap;
150
151        let mut map = HashMap::new();
152        map.insert(StaticId::from_str("AAPL", "NASDAQ"), 100);
153        map.insert(StaticId::from_str("GOOGL", "NASDAQ"), 200);
154
155        assert_eq!(map.get(&StaticId::from_str("AAPL", "NASDAQ")), Some(&100));
156        assert_eq!(map.get(&StaticId::from_str("GOOGL", "NASDAQ")), Some(&200));
157    }
158
159    #[test]
160    fn test_as_str() {
161        let id = StaticId::from_str("AAPL", "NASDAQ");
162        assert_eq!(id.code_str(), "AAPL");
163        assert_eq!(id.venue_str(), "NASDAQ");
164    }
165
166    #[test]
167    fn test_display() {
168        let id = StaticId::from_str("AAPL", "NASDAQ");
169        println!("{}", id);
170        assert_eq!(id.to_string(), "AAPL@NASDAQ");
171    }
172}