1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
// SPDX-License-Identifier: Apache-2.0
// SPDX-FileCopyrightText: Copyright the Vortex contributors
use Arc;
use ;
use crateArrayRef;
use crateArrayStats;
/// An extension array that wraps another array with additional type information.
///
/// **⚠️ Unstable API**: This is an experimental feature that may change significantly
/// in future versions. The extension type system is still evolving.
///
/// Unlike Apache Arrow's extension arrays, Vortex extension arrays provide a more flexible
/// mechanism for adding semantic meaning to existing array types without requiring
/// changes to the core type system.
///
/// ## Design Philosophy
///
/// Extension arrays serve as a type-safe wrapper that:
/// - Preserves the underlying storage format and operations
/// - Adds semantic type information via `ExtDType`
/// - Enables custom serialization and deserialization logic
/// - Allows domain-specific interpretations of generic data
///
/// ## Storage and Type Relationship
///
/// The extension array maintains a strict contract:
/// - **Storage array**: Contains the actual data in a standard Vortex encoding
/// - **Extension type**: Defines how to interpret the storage data semantically
/// - **Type safety**: The storage array's dtype must match the extension type's storage dtype
///
/// ## Use Cases
///
/// Extension arrays are ideal for:
/// - **Custom numeric types**: Units of measurement, currencies
/// - **Temporal types**: Custom date/time formats, time zones, calendars
/// - **Domain-specific types**: UUIDs, IP addresses, geographic coordinates
/// - **Encoded types**: Base64 strings, compressed data, encrypted values
///
/// ## Validity and Operations
///
/// Extension arrays delegate validity and most operations to their storage array:
/// - Validity is inherited from the underlying storage
/// - Slicing preserves the extension type
/// - Scalar access wraps storage scalars with extension metadata
///
/// # Examples
///
/// ```
/// use std::sync::Arc;
/// use vortex_array::arrays::{ExtensionArray, PrimitiveArray};
/// use vortex_dtype::{ExtDType, ExtID, DType, Nullability, PType};
/// use vortex_array::validity::Validity;
/// use vortex_array::IntoArray;
/// use vortex_buffer::buffer;
///
/// // Define a custom extension type for representing currency values
/// let currency_id = ExtID::from("example.currency");
/// let currency_dtype = Arc::new(ExtDType::new(
/// currency_id,
/// Arc::new(DType::Primitive(PType::I64, Nullability::NonNullable)), // Storage as i64 cents
/// None, // No additional metadata needed
/// ));
///
/// // Create storage array with currency values in cents
/// let cents_storage = PrimitiveArray::new(
/// buffer![12345i64, 67890, 99999], // $123.45, $678.90, $999.99
/// Validity::NonNullable
/// );
///
/// // Wrap with extension type
/// let currency_array = ExtensionArray::new(
/// currency_dtype.clone(),
/// cents_storage.into_array()
/// );
///
/// assert_eq!(currency_array.len(), 3);
/// assert_eq!(currency_array.id().as_ref(), "example.currency");
///
/// // Access maintains extension type information
/// let first_value = currency_array.scalar_at(0);
/// assert!(first_value.as_extension_opt().is_some());
/// ```