Feature Flags
All of CountryCode’s optional integrations are off by default and purely additive. Enabling one never changes what
counts as a valid country code, only what you can do with a CountryCode once you have one.
[dependencies]
ftracker-identifiers = { version = "0.0.1", features = ["serde", "schemars", "arbitrary", "proptest"] }
serde
(De)serializes CountryCode as its canonical two letter string (for example "US"), so it round trips as a plain
identifier in JSON, YAML, or config files.
Deserialization always re-runs full validation, including the membership check. An untrusted payload (a malformed API
request, a hand edited config file) can never produce an invalid CountryCode. A bad value fails to deserialize with a
descriptive error instead of silently producing garbage.
use ftracker_identifiers::CountryCode;
let code = CountryCode::parse("US").unwrap();
let json = serde_json::to_string(&code).unwrap();
assert_eq!(json, "\"US\"");
let back: CountryCode = serde_json::from_str(&json).unwrap();
assert_eq!(code, back);
// Invalid input is rejected at deserialization time, not silently accepted.
assert!(serde_json::from_str::<CountryCode>("\"ZZ\"").is_err());
schemars
Implements JsonSchema for CountryCode, so it can appear in a generated OpenAPI or JSON Schema document as a pattern
constrained string rather than an opaque string type. This feature implies serde.
The generated schema:
{
"type": "string",
"format": "iso3166-1-alpha2",
"minLength": 2,
"maxLength": 2,
"pattern": "^[A-Z]{2}$",
"description": "ISO 3166-1 alpha-2 country code. The pattern is structural; membership in the assigned set is enforced on deserialization."
}
The pattern only captures the two uppercase letter shape. A regex cannot express which two letter codes are
assigned. Schema validators outside this crate can reject malformed shapes, but true membership validation still
requires this crate.
arbitrary
Implements Arbitrary for CountryCode, so fuzz targets (for example via cargo fuzz) can generate assigned codes
directly, by choosing from the embedded set, instead of generating raw strings that mostly fail validation before
reaching the code under test.
proptest
Exposes reusable proptest strategies at ftracker_identifiers::country::proptest:
country::proptest::valid_country_code(): aStrategy<Value = CountryCode>producing valid values by choosing from the assigned set.country::proptest::valid_country_code_string(): the same, rendered as a canonicalString, useful for round trip through parsing property tests.
This is the recommended way to property test your own code that accepts a CountryCode, without hand rolling a
generator that only yields assigned codes:
use ftracker_identifiers::{country::proptest::valid_country_code, CountryCode};
use proptest::proptest;
proptest! {
#[test]
fn my_function_accepts_any_valid_country_code(code in valid_country_code()) {
// exercise your own code with `code` here
}
}