crustacean_states/lib.rs
1//! A NationStates API wrapper that takes full advantage of Rust's type system.
2//!
3//! Works with the current API (v12) as of 4 October 2023.
4//!
5//! Using the library usually takes three steps:
6//!
7//! 1. Creating a request
8//! (e.g. [`PublicNationRequest`])
9//! with the relevant shards.
10//! 2. Sending the request as a URL through a [`Client`][crate::client::Client].
11//! 3. Parsing the response using a parser in [`parsers`].
12//!
13//! Currently, the following requests can be formed and sent:
14//! - Nation (public shards only):
15//! [`PublicNationRequest::new`](shards::nation::PublicNationRequest::new),
16//! from [`PublicNationShards`](shards::nation::PublicNationShard);
17//! also, [`StandardPublicNationRequest`](shards::nation::StandardPublicNationRequest)
18//! - Region: [`RegionRequest::new`](shards::region::RegionRequest::new),
19//! from [`RegionShards`](shards::region::RegionShard);
20//! also, [`StandardRegionRequest`](shards::region::StandardRegionRequest)
21//! - World (except for `regionsfromtag`):
22//! [`WorldRequest::new`](shards::world::WorldRequest::new),
23//! from [`WorldShards`](shards::world::WorldShard)
24//! - WA (World Assembly): [`WAShard`](shards::wa::WARequest),
25//! from [`WAShards`](shards::wa::WAShard`)
26//!
27//! The following requests can be parsed:
28//! - [`Nation`](parsers::nation::Nation) (some fields still being finalized)
29//!
30//! The following functionality is planned, but is not implemented:
31//! - parsers for Region, World, and WA request responses
32//! - private shards
33//! - lighter-weight client using `hyper`
34//! - breaking crate into features
35//!
36//! ## Examples
37//! For a list of examples,
38//! see [the examples folder on GitHub](https://github.com/triskofwhaleisland/crustacean-states/tree/main/examples).
39//!
40//! [`PublicNationRequest`]: [crate::shards::nation::PublicNationRequest]
41
42// #![deny(missing_docs)]
43
44#[doc(hidden)]
45mod macros;
46
47pub mod client;
48pub mod models;
49pub mod parsers;
50pub mod shards;
51
52/// Takes a nation name with capital letters and spaces
53/// and turns it into a safe-to-send, lowercase name.
54pub fn safe_name(unsafe_name: impl ToString) -> String {
55 unsafe_name
56 .to_string()
57 .to_ascii_lowercase()
58 .replace(' ', "_")
59 .to_ascii_lowercase()
60}
61
62/// Takes a lowercase, web-safe name and replaces it with a name
63/// that should match the real name on NationStates.
64///
65/// Note: this will not always result in a name
66/// that is capitalized the same way as it is on NationStates.
67pub fn pretty_name<T: ToString>(safe_name: T) -> String {
68 safe_name
69 .to_string()
70 .replace('_', " ")
71 .chars()
72 .fold(String::new(), |s, c| {
73 format!(
74 "{s}{}",
75 if s.ends_with(' ') || s.is_empty() {
76 c.to_ascii_uppercase()
77 } else {
78 c
79 }
80 )
81 })
82}
83
84#[cfg(test)]
85mod tests {
86 #[test]
87 fn safe_name_unchanged() {
88 assert_eq!(super::safe_name("wow1"), String::from("wow1"));
89 }
90
91 #[test]
92 fn safe_name_lowercase() {
93 assert_eq!(super::safe_name("Exciting"), String::from("exciting"));
94 }
95
96 #[test]
97 fn safe_name_underscore() {
98 assert_eq!(
99 super::safe_name("wow1 exciting"),
100 String::from("wow1_exciting")
101 );
102 }
103
104 #[test]
105 fn safe_name_underscore_and_lowercase() {
106 assert_eq!(
107 super::safe_name("Wow1 Exciting"),
108 String::from("wow1_exciting")
109 );
110 }
111
112 #[test]
113 fn pretty_name_uppercase() {
114 assert_eq!(super::pretty_name("aramos"), String::from("Aramos"))
115 }
116
117 #[test]
118 fn pretty_name_multiword() {
119 assert_eq!(
120 super::pretty_name("the_greater_low_countries"),
121 String::from("The Greater Low Countries")
122 )
123 }
124}