cf_colo_hint/lib.rs
1//! Cloudflare colo (data center) to Durable Objects location hint mapping.
2//!
3//! This library provides a mapping from Cloudflare edge locations (colos) to
4//! the recommended Durable Objects location hints. This is useful when you need
5//! to provide location hints for Durable Objects based on incoming request colos.
6//!
7//! # Example
8//!
9//! ```
10//! use cf_colo_hint::{Colo, LocationHint};
11//!
12//! // Parse a colo from the cf-ray header or request metadata
13//! let colo = Colo::from_code("LAX").expect("unknown colo");
14//!
15//! // Get the recommended location hint for Durable Objects
16//! if let Some(hint) = colo.location_hint() {
17//! println!("Use location hint: {}", hint.as_str());
18//! // Use hint.as_str() when calling the Durable Objects API
19//! }
20//!
21//! // You can also work with location hints directly
22//! let hint = LocationHint::WNam;
23//! assert_eq!(hint.as_str(), "wnam");
24//! assert_eq!(hint.name(), "Western North America");
25//! ```
26//!
27//! # Data Sources
28//!
29//! The colo data comes from:
30//! - `components.json`: Cloudflare status page data with colo names and regions
31//! - `where.durableobjects.live.json`: Measured latency data for DO region mapping
32//!
33//! Run `python3 codegen.py` to regenerate the Rust code from updated JSON files.
34
35#![no_std]
36
37mod generated;
38
39pub use generated::{Colo, LocationHint};
40
41#[cfg(test)]
42mod tests {
43 use super::*;
44
45 #[test]
46 fn test_location_hint_roundtrip() {
47 for hint in LocationHint::ALL {
48 let code = hint.as_str();
49 let parsed = LocationHint::parse(code);
50 assert_eq!(parsed, Some(*hint));
51 }
52 }
53
54 #[test]
55 fn test_colo_roundtrip() {
56 for colo in Colo::ALL {
57 let code = colo.code();
58 let parsed = Colo::from_code(code);
59 assert_eq!(parsed, Some(*colo));
60 }
61 }
62
63 #[test]
64 fn test_known_colos() {
65 // Test some well-known colos
66 let lax = Colo::from_code("LAX").unwrap();
67 assert_eq!(lax.name(), "Los Angeles, CA, United States");
68 assert_eq!(lax.location_hint(), Some(LocationHint::WNam));
69
70 let ams = Colo::from_code("AMS").unwrap();
71 assert_eq!(ams.name(), "Amsterdam, Netherlands");
72 // AMS may map to afr, weur, or eeur depending on measured latency
73
74 let sin = Colo::from_code("SIN").unwrap();
75 assert!(sin.name().contains("Singapore"));
76 assert_eq!(sin.location_hint(), Some(LocationHint::Apac));
77 }
78
79 #[test]
80 fn test_location_hint_names() {
81 assert_eq!(LocationHint::WNam.name(), "Western North America");
82 assert_eq!(LocationHint::ENam.name(), "Eastern North America");
83 assert_eq!(LocationHint::WEur.name(), "Western Europe");
84 assert_eq!(LocationHint::EEur.name(), "Eastern Europe");
85 assert_eq!(LocationHint::Apac.name(), "Asia-Pacific");
86 assert_eq!(LocationHint::Oc.name(), "Oceania");
87 assert_eq!(LocationHint::Sam.name(), "South America");
88 assert_eq!(LocationHint::Afr.name(), "Africa");
89 assert_eq!(LocationHint::Me.name(), "Middle East");
90 }
91
92 #[test]
93 fn test_display() {
94 // Display impl returns the code
95 assert_eq!(LocationHint::WNam.as_str(), "wnam");
96 assert_eq!(Colo::LAX.code(), "LAX");
97 }
98}