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
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
//! # IP Flag (ipflag)
//!
//! IP Flag is a small, resolver-pluggable Rust crate that displays a human-friendly
//! country indicator for an IP address (flag emoji + country code).
//!
//! This crate is intentionally **not** a geolocation database and does **not**
//! contact external services. It only provides:
//!
//! - IP parsing (`parse_ip`)
//! - IP scope classification (`classify_ip`)
//! - A resolver interface (`IpResolver`) for IP β CountryCode lookup
//! - Display helpers (`IpTag`, `TagFormat`)
//!
//! ## Important concept: "Resolver"
//!
//! This crate does **not** know what country an IP belongs to by itself.
//! To get real country results, you must provide a resolver implementation.
//!
//! A resolver can be backed by anything:
//! - A local GeoIP database (e.g., MaxMind mmdb)
//! - A custom IP-to-country mapping
//! - A reverse-proxy header mapping (if you trust your infra)
//! - Any other internal source
//!
//! The core stays stable and maintenance-free; data sources can be built as separate crates.
//!
//! ## Quick start (no country resolution)
//!
//! Even without a resolver, IP Flag can still provide useful UI output for private/special IPs.
//!
//! ```rust
//! use ipflag::{tag_ip, NoopResolver};
//!
//! let t1 = tag_ip(&NoopResolver, "192.168.0.1").unwrap();
//! assert_eq!(t1.to_string(), "π PRIVATE");
//!
//! let t2 = tag_ip(&NoopResolver, "8.8.8.8").unwrap();
//! assert_eq!(t2.to_string(), "π UNKNOWN");
//! ```
//!
//! ## Quick start (with a resolver)
//!
//! You provide a resolver that returns a [`CountryCode`] for public IPs.
//! This example is intentionally hard-coded (demo only):
//!
//! ```rust
//! use ipflag::{CountryCode, IpResolver, tag_ip};
//! use std::net::IpAddr;
//!
//! struct DemoResolver;
//! impl IpResolver for DemoResolver {
//! type Error = core::convert::Infallible;
//! fn resolve(&self, _ip: IpAddr) -> Result<Option<CountryCode>, Self::Error> {
//! Ok(CountryCode::new("KR"))
//! }
//! }
//!
//! let t = tag_ip(&DemoResolver, "8.8.8.8").unwrap();
//! assert_eq!(t.to_string(), "π°π· KR");
//! ```
//!
//! In real usage, your resolver should consult real data (e.g., GeoIP database).
//!
//! ## Non-goals
//!
//! IP Flag does not:
//! - Detect manipulation / label behavior as suspicious
//! - Identify people or guarantee nationality
//! - Provide geolocation data by itself
//!
//! It only helps make IP-based patterns easier to scan visually.
pub use CountryCode;
pub use IpflagError;
pub use ;
pub use ;
pub use ;
use IpAddr;
/// Tag an IP string into an [`IpTag`].
///
/// This function:
/// 1) Parses the IP string
/// 2) Classifies it into [`IpScope`]
/// 3) Only if it is `Public`, asks the resolver for a [`CountryCode`]
///
/// Private and special IP ranges do not call the resolver (by design).
///
/// # Examples
///
/// ```rust
/// use ipflag::{tag_ip, NoopResolver};
///
/// let tag = tag_ip(&NoopResolver, "192.168.0.1").unwrap();
/// assert_eq!(tag.to_string(), "π PRIVATE");
/// ```
///
/// With a resolver:
///
/// ```rust
/// use ipflag::{tag_ip, CountryCode, IpResolver};
/// use std::net::IpAddr;
///
/// struct AlwaysUS;
/// impl IpResolver for AlwaysUS {
/// type Error = core::convert::Infallible;
/// fn resolve(&self, _ip: IpAddr) -> Result<Option<CountryCode>, Self::Error> {
/// Ok(CountryCode::new("US"))
/// }
/// }
///
/// let tag = tag_ip(&AlwaysUS, "8.8.8.8").unwrap();
/// assert_eq!(tag.to_string(), "πΊπΈ US");
/// ```
/// Tag an already-parsed [`IpAddr`] into an [`IpTag`].
///
/// See [`tag_ip`] for the high-level behavior.
///
/// # Notes
/// - `Private` / `Special` never calls the resolver.
/// - `Public` calls the resolver and returns either `Country(code)` or `Unknown`.