1use std::fmt;
40use std::num::NonZeroU32;
41use std::sync::Arc;
42use std::sync::atomic::{AtomicU32, Ordering};
43
44use serde::de::Error as DeError;
45use serde::{Deserialize, Deserializer, Serialize, Serializer};
46use uuid::Uuid;
47
48const SESSION_COUNTER_START: u32 = 1;
54
55static SESSION_COUNTER: AtomicU32 = AtomicU32::new(SESSION_COUNTER_START);
61
62#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
79pub struct SessionId(NonZeroU32);
80
81impl SessionId {
82 #[inline]
87 #[must_use]
88 pub fn next() -> Self {
89 loop {
90 let id = SESSION_COUNTER.fetch_add(1, Ordering::Relaxed);
91 if let Some(non_zero) = NonZeroU32::new(id) {
92 return Self(non_zero);
93 }
94 }
96 }
97
98 #[inline]
106 #[must_use]
107 pub fn from_u32(id: u32) -> Option<Self> {
108 NonZeroU32::new(id).map(Self)
109 }
110
111 #[inline]
113 #[must_use]
114 pub const fn as_u32(&self) -> u32 {
115 self.0.get()
116 }
117}
118
119impl fmt::Display for SessionId {
120 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
121 write!(f, "{}", self.0)
122 }
123}
124
125impl Serialize for SessionId {
126 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
127 where
128 S: Serializer,
129 {
130 serializer.serialize_u32(self.0.get())
131 }
132}
133
134impl<'de> Deserialize<'de> for SessionId {
135 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
136 where
137 D: Deserializer<'de>,
138 {
139 let id = u32::deserialize(deserializer)?;
140 NonZeroU32::new(id)
141 .map(Self)
142 .ok_or_else(|| DeError::custom("session_id cannot be 0"))
143 }
144}
145
146#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
164pub struct TabId(NonZeroU32);
165
166impl TabId {
167 #[inline]
177 #[must_use]
178 pub fn new(id: u32) -> Option<Self> {
179 NonZeroU32::new(id).map(Self)
180 }
181
182 #[inline]
184 #[must_use]
185 pub const fn as_u32(&self) -> u32 {
186 self.0.get()
187 }
188}
189
190impl fmt::Display for TabId {
191 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
192 write!(f, "{}", self.0)
193 }
194}
195
196impl Serialize for TabId {
197 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
198 where
199 S: Serializer,
200 {
201 serializer.serialize_u32(self.0.get())
202 }
203}
204
205impl<'de> Deserialize<'de> for TabId {
206 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
207 where
208 D: Deserializer<'de>,
209 {
210 let id = u32::deserialize(deserializer)?;
211 NonZeroU32::new(id)
212 .map(Self)
213 .ok_or_else(|| DeError::custom("tab_id cannot be 0"))
214 }
215}
216
217#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize)]
238pub struct FrameId(u64);
239
240impl FrameId {
241 #[inline]
243 #[must_use]
244 pub const fn new(id: u64) -> Self {
245 Self(id)
246 }
247
248 #[inline]
250 #[must_use]
251 pub const fn main() -> Self {
252 Self(0)
253 }
254
255 #[inline]
257 #[must_use]
258 pub const fn is_main(&self) -> bool {
259 self.0 == 0
260 }
261
262 #[inline]
264 #[must_use]
265 pub const fn as_u64(&self) -> u64 {
266 self.0
267 }
268}
269
270impl Default for FrameId {
271 #[inline]
272 fn default() -> Self {
273 Self::main()
274 }
275}
276
277impl fmt::Display for FrameId {
278 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
279 write!(f, "{}", self.0)
280 }
281}
282
283impl From<u64> for FrameId {
284 #[inline]
285 fn from(id: u64) -> Self {
286 Self(id)
287 }
288}
289
290#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
313pub struct RequestId(Uuid);
314
315impl RequestId {
316 #[inline]
318 #[must_use]
319 pub fn generate() -> Self {
320 Self(Uuid::new_v4())
321 }
322
323 #[inline]
327 #[must_use]
328 pub const fn ready() -> Self {
329 Self(Uuid::nil())
330 }
331
332 #[inline]
334 #[must_use]
335 pub fn is_ready(&self) -> bool {
336 self.0.is_nil()
337 }
338
339 #[inline]
341 #[must_use]
342 pub const fn as_uuid(&self) -> &Uuid {
343 &self.0
344 }
345}
346
347impl Default for RequestId {
348 #[inline]
349 fn default() -> Self {
350 Self::generate()
351 }
352}
353
354impl fmt::Display for RequestId {
355 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
356 fmt::Display::fmt(&self.0, f)
357 }
358}
359
360impl From<Uuid> for RequestId {
361 #[inline]
362 fn from(uuid: Uuid) -> Self {
363 Self(uuid)
364 }
365}
366
367#[derive(Debug, Clone, Hash, PartialEq, Eq)]
383pub struct ElementId(Arc<str>);
384
385impl ElementId {
386 #[inline]
388 #[must_use]
389 pub fn new(id: impl Into<Arc<str>>) -> Self {
390 Self(id.into())
391 }
392
393 #[inline]
395 #[must_use]
396 pub fn as_str(&self) -> &str {
397 &self.0
398 }
399}
400
401impl fmt::Display for ElementId {
402 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
403 fmt::Display::fmt(&self.0, f)
404 }
405}
406
407impl AsRef<str> for ElementId {
408 #[inline]
409 fn as_ref(&self) -> &str {
410 &self.0
411 }
412}
413
414impl Serialize for ElementId {
415 fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
416 where
417 S: Serializer,
418 {
419 serializer.serialize_str(&self.0)
420 }
421}
422
423impl<'de> Deserialize<'de> for ElementId {
424 fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
425 where
426 D: Deserializer<'de>,
427 {
428 let s = String::deserialize(deserializer)?;
429 Ok(Self(Arc::from(s)))
430 }
431}
432
433#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
442pub struct ScriptId(String);
443
444impl ScriptId {
445 #[inline]
447 #[must_use]
448 pub fn new(id: impl Into<String>) -> Self {
449 Self(id.into())
450 }
451
452 #[inline]
454 #[must_use]
455 pub fn as_str(&self) -> &str {
456 &self.0
457 }
458}
459
460impl fmt::Display for ScriptId {
461 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
462 fmt::Display::fmt(&self.0, f)
463 }
464}
465
466impl AsRef<str> for ScriptId {
467 #[inline]
468 fn as_ref(&self) -> &str {
469 &self.0
470 }
471}
472
473#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
482pub struct SubscriptionId(String);
483
484impl SubscriptionId {
485 #[inline]
487 #[must_use]
488 pub fn new(id: impl Into<String>) -> Self {
489 Self(id.into())
490 }
491
492 #[inline]
494 #[must_use]
495 pub fn as_str(&self) -> &str {
496 &self.0
497 }
498}
499
500impl fmt::Display for SubscriptionId {
501 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
502 fmt::Display::fmt(&self.0, f)
503 }
504}
505
506impl AsRef<str> for SubscriptionId {
507 #[inline]
508 fn as_ref(&self) -> &str {
509 &self.0
510 }
511}
512
513#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
522pub struct InterceptId(String);
523
524impl InterceptId {
525 #[inline]
527 #[must_use]
528 pub fn new(id: impl Into<String>) -> Self {
529 Self(id.into())
530 }
531
532 #[inline]
534 #[must_use]
535 pub fn as_str(&self) -> &str {
536 &self.0
537 }
538}
539
540impl fmt::Display for InterceptId {
541 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
542 fmt::Display::fmt(&self.0, f)
543 }
544}
545
546impl AsRef<str> for InterceptId {
547 #[inline]
548 fn as_ref(&self) -> &str {
549 &self.0
550 }
551}
552
553#[cfg(test)]
558mod tests {
559 use super::*;
560
561 #[test]
562 fn test_session_id_increments() {
563 let id1 = SessionId::next();
564 let id2 = SessionId::next();
565 assert!(id1.as_u32() < id2.as_u32());
566 }
567
568 #[test]
569 fn test_session_id_display() {
570 let id = SessionId::next();
571 let display = id.to_string();
572 assert!(!display.is_empty());
573 }
574
575 #[test]
576 fn test_session_id_from_u32() {
577 assert!(SessionId::from_u32(0).is_none());
578 assert!(SessionId::from_u32(1).is_some());
579 assert_eq!(SessionId::from_u32(42).unwrap().as_u32(), 42);
580 }
581
582 #[test]
583 fn test_tab_id_rejects_zero() {
584 assert!(TabId::new(0).is_none());
585 assert!(TabId::new(1).is_some());
586 }
587
588 #[test]
589 fn test_tab_id_value() {
590 let tab = TabId::new(42).expect("valid tab id");
591 assert_eq!(tab.as_u32(), 42);
592 }
593
594 #[test]
595 fn test_frame_id_main() {
596 let main = FrameId::main();
597 assert!(main.is_main());
598 assert_eq!(main.as_u64(), 0);
599 }
600
601 #[test]
602 fn test_frame_id_iframe() {
603 let iframe = FrameId::new(17179869185);
604 assert!(!iframe.is_main());
605 assert_eq!(iframe.as_u64(), 17179869185);
606 }
607
608 #[test]
609 fn test_frame_id_default() {
610 let default = FrameId::default();
611 assert!(default.is_main());
612 }
613
614 #[test]
615 fn test_frame_id_from_u64() {
616 let frame: FrameId = 123u64.into();
617 assert_eq!(frame.as_u64(), 123);
618 }
619
620 #[test]
621 fn test_request_id_ready() {
622 let ready = RequestId::ready();
623 assert!(ready.is_ready());
624 assert!(ready.as_uuid().is_nil());
625 }
626
627 #[test]
628 fn test_request_id_generated() {
629 let id = RequestId::generate();
630 assert!(!id.is_ready());
631 assert!(!id.as_uuid().is_nil());
632 }
633
634 #[test]
635 fn test_request_id_uniqueness() {
636 let id1 = RequestId::generate();
637 let id2 = RequestId::generate();
638 assert_ne!(id1, id2);
639 }
640
641 #[test]
642 fn test_element_id() {
643 let id = ElementId::new("test-uuid");
644 assert_eq!(id.as_str(), "test-uuid");
645 assert_eq!(id.as_ref(), "test-uuid");
646 assert_eq!(id.to_string(), "test-uuid");
647 }
648
649 #[test]
650 fn test_script_id() {
651 let id = ScriptId::new("script-123");
652 assert_eq!(id.as_str(), "script-123");
653 }
654
655 #[test]
656 fn test_subscription_id() {
657 let id = SubscriptionId::new("sub-456");
658 assert_eq!(id.as_str(), "sub-456");
659 assert_eq!(id.as_ref(), "sub-456");
660 }
661
662 #[test]
663 fn test_intercept_id() {
664 let id = InterceptId::new("intercept-789");
665 assert_eq!(id.as_str(), "intercept-789");
666 assert_eq!(id.as_ref(), "intercept-789");
667 }
668
669 #[test]
670 fn test_serde_session_id() {
671 let id = SessionId::next();
672 let json = serde_json::to_string(&id).expect("serialize");
673 let parsed: SessionId = serde_json::from_str(&json).expect("deserialize");
674 assert_eq!(id, parsed);
675 }
676
677 #[test]
678 fn test_serde_tab_id() {
679 let id = TabId::new(42).expect("valid");
680 let json = serde_json::to_string(&id).expect("serialize");
681 let parsed: TabId = serde_json::from_str(&json).expect("deserialize");
682 assert_eq!(id, parsed);
683 }
684
685 #[test]
686 fn test_serde_frame_id() {
687 let id = FrameId::new(12345);
688 let json = serde_json::to_string(&id).expect("serialize");
689 let parsed: FrameId = serde_json::from_str(&json).expect("deserialize");
690 assert_eq!(id, parsed);
691 }
692
693 #[test]
694 fn test_serde_element_id() {
695 let id = ElementId::new("elem-uuid");
696 let json = serde_json::to_string(&id).expect("serialize");
697 let parsed: ElementId = serde_json::from_str(&json).expect("deserialize");
698 assert_eq!(id, parsed);
699 }
700}