iab_specs_core/extension.rs
1//! Extension Trait
2//!
3//! This module defines the `Extension` trait that all extension objects must implement.
4//! The trait ensures that extension types are serializable, deserializable, cloneable,
5//! debuggable, and have default values.
6//!
7//! # Overview
8//!
9//! The `Extension` trait provides a flexible mechanism for adding custom fields to IAB
10//! specification objects. This is particularly useful for:
11//! - Vendor-specific data
12//! - Internal tracking information
13//! - Experimental features
14//! - Custom business logic fields
15
16use serde::{Deserialize, Serialize};
17
18/// Extension trait for extension objects.
19///
20/// This trait defines the requirements for any type that can be used as an extension
21/// field (`ext`). All extension types must be:
22///
23/// - **Serializable**: Can be converted to various formats (JSON, YAML, etc.)
24/// - **Deserializable**: Can be parsed from various formats
25/// - **Cloneable**: Can be duplicated
26/// - **Debuggable**: Can be formatted for debugging
27/// - **Default**: Has a sensible default value
28/// - **Comparable**: Can be compared for equality
29/// - **Send**: Can be transferred between threads
30/// - **Sync**: Can be shared between threads
31///
32/// # Automatic Implementation
33///
34/// Any type that implements `Serialize`, `Deserialize`, `Clone`, `Debug`, `Default`,
35/// `PartialEq`, `Send`, and `Sync` automatically implements `Extension`.
36pub trait Extension:
37 Serialize + for<'de> Deserialize<'de> + Clone + std::fmt::Debug + Default + PartialEq + Send + Sync
38{
39}
40
41// Blanket implementation for any type that satisfies the trait bounds
42impl<T> Extension for T where
43 T: Serialize
44 + for<'de> Deserialize<'de>
45 + Clone
46 + std::fmt::Debug
47 + Default
48 + PartialEq
49 + Send
50 + Sync
51{
52}
53
54/// Default extension type.
55///
56/// `Vec<u8>` is used as the default extension type, representing opaque bytes.
57/// This is serde-agnostic: callers choose the serialization format by specifying
58/// an explicit type parameter (e.g., `serde_json::Value` for JSON, or a custom
59/// protobuf-decoded type) when they need typed extensions.
60pub type DefaultExt = Vec<u8>;
61
62#[cfg(test)]
63mod tests {
64 use super::*;
65
66 #[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq)]
67 struct TestExtension {
68 field1: String,
69 field2: i32,
70 }
71
72 #[test]
73 fn test_custom_type_implements_extension() {
74 fn requires_extension<E: Extension>(_ext: E) {}
75
76 let ext = TestExtension {
77 field1: "test".to_string(),
78 field2: 42,
79 };
80
81 requires_extension(ext);
82 }
83
84 #[test]
85 fn test_json_value_implements_extension() {
86 fn requires_extension<E: Extension>(_ext: E) {}
87
88 let ext = serde_json::json!({"key": "value"});
89 requires_extension(ext);
90 }
91
92 #[test]
93 fn test_unit_type_implements_extension() {
94 fn requires_extension<E: Extension>(_ext: E) {}
95
96 requires_extension(());
97 }
98
99 #[test]
100 fn test_option_implements_extension() {
101 fn requires_extension<E: Extension>(_ext: Option<E>) {}
102
103 let ext: Option<TestExtension> = Some(TestExtension::default());
104 requires_extension(ext);
105 }
106
107 #[test]
108 fn test_vec_u8_implements_extension() {
109 fn requires_extension<E: Extension>(_ext: E) {}
110
111 let ext: Vec<u8> = vec![0x08, 0x96, 0x01];
112 requires_extension(ext);
113 }
114
115 #[test]
116 fn test_default_ext_is_vec_u8() {
117 let ext = DefaultExt::default();
118 assert!(ext.is_empty());
119 assert_eq!(ext, Vec::<u8>::new());
120 }
121}