Skip to main content

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}