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
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
//! Optimization strategies for `Bytes`.
//!
//! This module provides two different optimization strategies that control how `Bytes`
//! manages the transition between inline (stack) storage and heap-allocated storage:
//!
//! - **[`shared`]** - Preserves heap allocations for fast conversions with `bytes::Bytes`
//! - **[`compact`]** - Aggressively inlines data to minimize memory usage
//!
//! # Quick Comparison
//!
//! | Feature | [`shared::Bytes`] | [`compact::Bytes`] |
//! |---------|----------------------|------------------------|
//! | **Heap→Inline** | Never converts | Converts when possible |
//! | **Bytes conversion** | Zero-copy (fast) | May copy data |
//! | **Memory usage** | Higher | Lower |
//! | **Best for** | Bytes interop, speed | Memory-constrained apps |
//! | **Default?** | ✅ Recommended | ⚠️ Special cases |
//!
//! # When to Use Which ImmutableStorage
//!
//! ## Use `shared::Bytes` (Default) when:
//!
//! - You frequently convert between `Bytes` and `bytes::Bytes`
//! - Performance is more important than memory overhead
//! - You want cheap clones via reference counting
//! - You're building network protocols or I/O-heavy applications
//!
//! ```rust
//! use smol_bytes::{shared::Bytes, Buf};
//!
//! let mut data = Bytes::from(vec![1u8; 100]);
//! data.advance(70);
//! // Still heap-allocated for fast Bytes conversion
//! assert!(data.is_heap());
//! ```
//!
//! ## Use `compact::Bytes` when:
//!
//! - Memory footprint is critical (embedded systems, memory-constrained environments)
//! - You're working with many small buffers that shrink over time
//! - Conversions to `Bytes` are rare
//! - You want to minimize heap allocations
//!
//! ```rust
//! use smol_bytes::{compact::Bytes, Buf};
//!
//! let mut data = Bytes::from(vec![1u8; 100]);
//! data.advance(70);
//! // Automatically converted to inline storage!
//! assert!(!data.is_heap());
//! ```
//!
//! # Examples
//!
//! ## Shared ImmutableStorage Example
//!
//! ```rust
//! use smol_bytes::shared::Bytes;
//!
//! // Small data is inline
//! let small = Bytes::from_static(b"hello");
//! assert!(!small.is_heap());
//!
//! // Large data is heap-allocated
//! let large = Bytes::from(vec![1u8; 100]);
//! assert!(large.is_heap());
//!
//! // Zero-copy conversion to Bytes
//! let bytes: bytes::Bytes = large.into();
//! ```
//!
//! ## Compact ImmutableStorage Example
//!
//! ```rust
//! use smol_bytes::{compact::Bytes, Buf};
//!
//! // Start with large heap allocation
//! let mut data = Bytes::from(vec![1u8; 64]);
//! assert!(data.is_heap());
//!
//! // Operations automatically convert to inline when possible
//! data.truncate(30); // Now fits inline!
//! assert!(!data.is_heap());
//! ```
//!
//! # Performance Characteristics
//!
//! ## Shared ImmutableStorage
//!
//! | Operation | Complexity | Allocation Behavior |
//! |-----------|------------|---------------------|
//! | `advance()` | O(1) | Preserves heap |
//! | `truncate()` | O(1) | Preserves heap |
//! | `split_to()` | O(1) or O(62)* | Preserves heap |
//! | `split_off()` | O(1) or O(62)* | Preserves heap |
//! | `into::<Bytes>()` | O(1) | Zero-copy if heap |
//!
//! *O(62) when result needs to be inline (copies up to 62 bytes)
//!
//! ## Compact ImmutableStorage
//!
//! | Operation | Complexity | Allocation Behavior |
//! |-----------|------------|---------------------|
//! | `advance()` | O(1) or O(62)* | May convert heap→inline |
//! | `truncate()` | O(1) or O(62)* | May convert heap→inline |
//! | `split_to()` | O(1) or O(62)* | May convert heap→inline |
//! | `split_off()` | O(1) or O(62)* | May convert heap→inline |
//! | `into::<Bytes>()` | O(1) or O(62) | May need to copy |
//!
//! *O(62) when conversion happens (copies up to 62 bytes)
//!
//! # Implementation Details
//!
//! The strategy pattern is implemented using a sealed trait to prevent external implementations.
//! The strategy is selected at compile-time via a zero-sized type parameter, resulting in
//! **zero runtime overhead**.
//!
//! Both strategies use the same internal storage type, with only the behavior
//! differing based on the strategy parameter.
pub use ImmutableStorage;
/// The **Compact** strategy: Aggressively inlines data to minimize memory usage.
///
/// This strategy automatically converts heap-allocated buffers to inline storage
/// whenever the data shrinks to fit within the inline capacity (62 bytes or less).
///
/// See [`compact::Bytes`] for usage examples and detailed documentation.
/// The **Shared** strategy: Preserves heap allocations for fast `Bytes` conversions.
///
/// This strategy keeps heap-allocated buffers on the heap even when they could fit
/// inline, enabling zero-copy conversions with `bytes::Bytes`.
///
/// See [`shared::Bytes`] for usage examples and detailed documentation.