accept_encoding_preferred/
accept_encoding_preferred.rs

1//! Simple example demonstrating AcceptEncoding preferred() and preferred_allowed() methods with in-place sorting
2//!
3//! This example shows:
4//! - How to find the preferred encoding from an AcceptEncoding instance using preferred()
5//! - How to find the preferred encoding with server-side filtering using preferred_allowed()
6//! - How sorting affects the preferred encoding selection
7//! - In-place sorting with sort_descending() and sort_ascending()
8
9use http_encoding_headers::{AcceptEncoding, Encoding};
10
11fn main() {
12    println!("=== AcceptEncoding Preferred and Sorting Examples ===\n");
13
14    // Create an AcceptEncoding with different quality values
15    let encodings = vec![
16        (Encoding::Gzip, 0.7),
17        (Encoding::Deflate, 0.9), // This should be preferred (highest quality)
18        (Encoding::Br, 1.0),      // Highest quality, but might not be allowed by server
19        (Encoding::Identity, 0.1),
20        (Encoding::Zstd, 0.8), // High quality compression
21    ];
22
23    let mut accept_encoding = AcceptEncoding::new(encodings).unwrap();
24
25    println!("Original encodings:");
26    print_encodings(&accept_encoding);
27
28    // Find preferred encoding from unsorted list
29    println!("\n1. Finding preferred encoding (unsorted) - preferred():");
30    if let Some(preferred) = accept_encoding.preferred() {
31        println!(
32            "   Preferred: {} (finds highest quality from unsorted list)",
33            preferred
34        );
35    }
36
37    // Example server capabilities - let's say server only supports some encodings
38    let server_supported = vec![Encoding::Gzip, Encoding::Deflate, Encoding::Identity];
39
40    println!("\n2. Server-side filtering with preferred_allowed():");
41    println!("   Server supports: {:?}", server_supported);
42    if let Some(preferred_allowed) = accept_encoding.preferred_allowed(server_supported.iter()) {
43        println!(
44            "   Preferred (server filtered): {} (highest quality that server supports)",
45            preferred_allowed
46        );
47    }
48
49    // Compare different server capabilities
50    let limited_server = vec![Encoding::Identity]; // Very limited server
51    println!("\n   Limited server supports only: {:?}", limited_server);
52    if let Some(preferred_limited) = accept_encoding.preferred_allowed(limited_server.iter()) {
53        println!(
54            "   Preferred (limited server): {} (only available option)",
55            preferred_limited
56        );
57    } else {
58        println!("   No acceptable encoding found for limited server");
59    }
60
61    let advanced_server = vec![Encoding::Br, Encoding::Zstd, Encoding::Gzip]; // Advanced server
62    println!("\n   Advanced server supports: {:?}", advanced_server);
63    if let Some(preferred_advanced) = accept_encoding.preferred_allowed(advanced_server.iter()) {
64        println!(
65            "   Preferred (advanced server): {} (best match from advanced capabilities)",
66            preferred_advanced
67        );
68    }
69
70    // Sort descending (highest quality first) - modifies in place
71    println!("\n3. After sorting descending (in-place):");
72    accept_encoding.sort_descending();
73    print_encodings(&accept_encoding);
74
75    if let Some(preferred) = accept_encoding.preferred() {
76        println!(
77            "   Preferred: {} (first item when sorted descending)",
78            preferred
79        );
80    }
81
82    // Test preferred_allowed with sorted list
83    println!("\n   Server-side filtering after sorting descending:");
84    if let Some(preferred_allowed) = accept_encoding.preferred_allowed(server_supported.iter()) {
85        println!(
86            "   Preferred (server filtered): {} (efficiently finds first match in sorted list)",
87            preferred_allowed
88        );
89    }
90
91    // Sort ascending (lowest quality first) - modifies in place
92    println!("\n4. After sorting ascending (in-place):");
93    accept_encoding.sort_ascending();
94    print_encodings(&accept_encoding);
95
96    if let Some(preferred) = accept_encoding.preferred() {
97        println!(
98            "   Preferred: {} (last item when sorted ascending)",
99            preferred
100        );
101    }
102
103    // Test preferred_allowed with ascending sorted list
104    println!("\n   Server-side filtering after sorting ascending:");
105    if let Some(preferred_allowed) = accept_encoding.preferred_allowed(server_supported.iter()) {
106        println!(
107            "   Preferred (server filtered): {} (efficiently finds best match from end)",
108            preferred_allowed
109        );
110    }
111
112    // Demonstrate chaining - sort methods return &mut Self for chaining
113    println!("\n5. Method chaining example:");
114    let encodings2 = vec![
115        (Encoding::Gzip, 0.3),
116        (Encoding::Deflate, 0.8),
117        (Encoding::Br, 0.6),
118    ];
119
120    let mut accept_encoding2 = AcceptEncoding::new(encodings2).unwrap();
121
122    // Chain operations
123    let preferred_after_desc_sort = accept_encoding2.sort_descending().preferred().cloned(); // Clone the encoding to avoid borrowing issues
124
125    println!(
126        "   After chaining sort_descending().preferred(): {:?}",
127        preferred_after_desc_sort
128    );
129
130    // Sort back and get preferred
131    let preferred_after_asc_sort = accept_encoding2.sort_ascending().preferred().cloned();
132
133    println!(
134        "   After chaining sort_ascending().preferred(): {:?}",
135        preferred_after_asc_sort
136    );
137
138    // Demonstrate with equal quality values
139    println!("\n6. Equal quality values example:");
140    let equal_encodings = vec![
141        (Encoding::Gzip, 0.8),
142        (Encoding::Deflate, 0.8), // Same quality
143        (Encoding::Br, 0.8),      // Same quality
144    ];
145
146    let mut equal_accept = AcceptEncoding::new(equal_encodings).unwrap();
147    println!("   Original (all equal quality):");
148    print_encodings(&equal_accept);
149
150    if let Some(preferred) = equal_accept.preferred() {
151        println!(
152            "   Preferred from equal qualities: {} (first found with max quality)",
153            preferred
154        );
155    }
156
157    // Test server filtering with equal qualities
158    let partial_server = vec![Encoding::Deflate, Encoding::Br];
159    if let Some(preferred_filtered) = equal_accept.preferred_allowed(partial_server.iter()) {
160        println!(
161            "   Preferred (server filtered from equal qualities): {} (first allowed match)",
162            preferred_filtered
163        );
164    }
165
166    equal_accept.sort_descending();
167    println!("   After sort_descending (stable sort preserves original order for equal elements):");
168    print_encodings(&equal_accept);
169
170    // Demonstrate practical content negotiation scenario
171    println!("\n7. Practical content negotiation scenario:");
172    practical_negotiation_example();
173}
174
175fn print_encodings(accept_encoding: &AcceptEncoding) {
176    for (encoding, quality) in accept_encoding.items() {
177        println!("     {} (q={})", encoding, quality);
178    }
179}
180
181/// Demonstrates practical content negotiation comparing both methods
182fn practical_negotiation_example() {
183    println!(
184        "   Scenario: Client sends 'Accept-Encoding: br;q=1.0, zstd;q=0.9, gzip;q=0.7, deflate;q=0.5'"
185    );
186
187    let client_preferences = vec![
188        (Encoding::Br, 1.0),      // Client's top choice
189        (Encoding::Zstd, 0.9),    // Second choice
190        (Encoding::Gzip, 0.7),    // Third choice
191        (Encoding::Deflate, 0.5), // Fallback
192    ];
193
194    let accept_encoding = AcceptEncoding::new(client_preferences).unwrap();
195
196    // Method 1: preferred() - ignores server capabilities
197    if let Some(client_preferred) = accept_encoding.preferred() {
198        println!(
199            "   preferred(): {} (client's top choice, ignoring server)",
200            client_preferred
201        );
202    }
203
204    // Different server scenarios
205    let scenarios = vec![
206        (
207            "Basic server",
208            vec![Encoding::Gzip, Encoding::Deflate, Encoding::Identity],
209        ),
210        (
211            "Advanced server",
212            vec![Encoding::Br, Encoding::Zstd, Encoding::Gzip],
213        ),
214        ("Legacy server", vec![Encoding::Deflate, Encoding::Identity]),
215        (
216            "Modern server",
217            vec![
218                Encoding::Br,
219                Encoding::Zstd,
220                Encoding::Gzip,
221                Encoding::Deflate,
222            ],
223        ),
224    ];
225
226    for (server_name, server_caps) in scenarios {
227        print!("   {}: supports {:?}", server_name, server_caps);
228
229        if let Some(negotiated) = accept_encoding.preferred_allowed(server_caps.iter()) {
230            println!(" → selected: {}", negotiated);
231        } else {
232            println!(" → no acceptable encoding found");
233        }
234    }
235
236    println!("\n   Key difference:");
237    println!("   - preferred(): Returns client's top choice regardless of server capabilities");
238    println!("   - preferred_allowed(): Returns best mutually supported encoding");
239    println!("   - Both methods honor the current sorting state for efficiency");
240}