Skip to content

Commit 833825b

Browse files
committed
chore: MSRV is 1.88, but we can use nightly rustfmt + clippy
1 parent 7cfcc8d commit 833825b

File tree

15 files changed

+198
-69
lines changed

15 files changed

+198
-69
lines changed

.clippy.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,4 @@ allow-expect-in-tests = true
22
allow-unwrap-in-tests = true
33
allow-dbg-in-tests = true
44
allow-print-in-tests = true
5+
allow-indexing-slicing-in-tests = true

.rustfmt.toml

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,30 @@
1+
# injects `rustfmt` formatter into code blocks in doc comments
2+
format_code_in_doc_comments = true
3+
# when blocky items are the last argument to a function, they can overflow
4+
overflow_delimited_expr = true
5+
# `Foo { x: x }` => `Foo { x }`
16
use_field_init_shorthand = true
7+
# `let (a, _, _) = ...` => `let (a, ..) => ...`
8+
condense_wildcard_suffixes = true
9+
# breaks up long string literals over several lines
10+
format_strings = true
11+
# This is the most merge-conflict-friendly option to organize imports
12+
# each `use` imports a single item
13+
imports_granularity = "Item"
14+
# converts `/* */` to `//`
15+
normalize_comments = true
16+
# converts `#[doc]` to `///`
17+
normalize_doc_attributes = true
18+
# use `0xdeadbeef` and not `0xDEADBEEF`
19+
hex_literal_case = "Lower"
20+
# Force multiline closure and match arm bodies to be wrapped in a block
21+
#
22+
# This makes it MUCH easier to then add more statements in the closure/match arm
23+
force_multiline_blocks = true
24+
# Comments longer than 80 characters are wrapped to the next line
25+
wrap_comments = true
26+
# always format struct, and enum variant with named fields
27+
# into multiple lines - makes refactoring easier
28+
struct_variant_width = 0
29+
# like above, but with literals
30+
struct_lit_width = 0

Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 35 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,15 @@ homepage = "https://github.com/nik-rev/countryfetch"
77
description = "A Command-line tool similar to Neofetch for obtaining information about your country"
88
license = "MIT OR Apache-2.0"
99

10+
# Our MSRV. We use nightly toolchain for better dev experience, but
11+
# this software must build with at least this version.
12+
#
13+
# More info in the comment in `rust-toolchain.toml`
14+
rust-version = "1.88"
15+
16+
[lints]
17+
workspace = true
18+
1019
[workspace]
1120
members = [".", "generate_country_data"]
1221
default-members = ["."]
@@ -56,18 +65,6 @@ inherits = "release"
5665
codegen-units = 1
5766
lto = true
5867

59-
# ============================
60-
#
61-
# Lints
62-
#
63-
# - strict set of lints for a
64-
# more consistent codebase
65-
#
66-
# - delegate as much as possible
67-
# to automated tooling
68-
#
69-
# ============================
70-
7168
[workspace.lints.rust]
7269
# do not import if its already in scope
7370
# e.g. `use std::option::Option::None`
@@ -80,20 +77,36 @@ unused_qualifications = "warn"
8077
unused_macro_rules = "warn"
8178
# lints against e.g. undefined meta variables
8279
meta_variable_misuse = "warn"
83-
# all types must `#[derive(Copy)]`
84-
missing_copy_implementations = "warn"
85-
# all types must `#[derive(Debug)]`
86-
missing_debug_implementations = "warn"
8780

8881
[workspace.lints.clippy]
8982
pedantic = { priority = -1, level = "warn" }
9083

84+
# --- allowed lints
85+
#
86+
# `$a * $b + $c` is slower and less precise than `$a.mul_add($b, $c)`
87+
# but it is more readable, the gain in speed / precision
88+
# will be negligible in most situations
89+
suboptimal_flops = "allow"
90+
# arbitrary limit imposes unnecessary
91+
# restriction and can make code harder to follow
92+
too_many_lines = "allow"
93+
# if we need it const, make it const.
94+
# no need to make everything that can be const, const
95+
missing_const_for_fn = "allow"
96+
# Too verbose.
97+
missing_errors_doc = "allow"
98+
# ---
99+
100+
# We use nightly Rust toolchain but want to guarantee that we
101+
# can build with a stable Rust compiler.
102+
#
103+
# See `rust-toolchain.toml` for more info.
104+
incompatible_msrv = "deny"
105+
91106
# --- more consistent ways of writing code
92107
#
93108
# `if $a { Some($b) } else { None }` => `$a.then(|| $b)`
94109
if_then_some_else_none = "warn"
95-
# `use Trait` => `use Trait as _`
96-
unused_trait_names = "warn"
97110
# `foo.rs` => `foo/mod.rs`
98111
self_named_module_files = "warn"
99112
# omit `test_` prefix in tests: `fn test_foo` => `fn foo`
@@ -135,6 +148,8 @@ multiple_unsafe_ops_per_block = "warn"
135148

136149
# --- explain more things
137150
#
151+
# `#[allow]` => `#[expect]`
152+
allow_attributes = "warn"
138153
# `#[allow]` => `#[allow, reason = "why"]`
139154
allow_attributes_without_reason = "warn"
140155
# `unsafe` blocks need a `SAFETY:` comment
@@ -159,34 +174,17 @@ dbg_macro = "warn"
159174
todo = "warn"
160175
use_debug = "warn"
161176
unimplemented = "warn"
162-
# explicitly `#[allow]` functions to print to stdout
177+
# must explicitly `#[allow]` functions to print to stdout
163178
print_stdout = "warn"
164-
# explicitly `#[allow]` functions to print to stderr
179+
# must explicitly `#[allow]` functions to print to stderr
165180
print_stderr = "warn"
166181
# ---
167182

168183
# --- prevent bugs
169-
# new variants added by libraries become errors
170-
# instead of being silently ignored
171-
wildcard_enum_match_arm = "warn"
172184
# if function and trait provide method of same name, it is confusing
173185
same_name_method = "warn"
174186
# `create_dir(...)` => `create_dir_all(...)`
175187
# usually, failing when dir already exists is
176188
# not what we want
177189
create_dir = "warn"
178190
# ---
179-
180-
# --- allowed lints
181-
#
182-
# `$a * $b + $c` is slower and less precise than `$a.mul_add($b, $c)`
183-
# but it is more readable, the gain in speed / precision
184-
# will be negligible in most situations
185-
suboptimal_flops = "allow"
186-
# arbitrary limit imposes unnecessary
187-
# restriction and can make code harder to follow
188-
too_many_lines = "allow"
189-
# if we need it const, make it const.
190-
# no need to make everything that can be const, const
191-
missing_const_for_fn = "allow"
192-
# ---

generate_country_data/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ reqwest = { version = "0.12", default-features = false, features = [
3232
futures = "0.3"
3333

3434
# NOTE: This must be the same version as what is required by `rascii_art`
35-
image = "0.25.6"
35+
image = "0.24.6"
3636

3737
rayon = "1.11"
3838

generate_country_data/src/codegen.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
//! Generate the entire Country enum and all methods associated with it
22
use core::fmt;
33

4-
use rayon::iter::{IntoParallelRefIterator as _, ParallelIterator as _};
4+
use rayon::iter::IntoParallelRefIterator as _;
5+
use rayon::iter::ParallelIterator as _;
56
use strum::IntoEnumIterator as _;
67

78
use crate::Country;
8-
use crate::country_parts::{self, CountryData};
9+
use crate::country_parts::CountryData;
10+
use crate::country_parts::{self};
911

1012
#[derive(strum::EnumIter, strum::Display)]
1113
#[strum(serialize_all = "snake_case")]
@@ -309,10 +311,8 @@ pub async fn generate_code(countries: &[Country]) -> (String, String) {
309311
let mut country_enum = Codegen {
310312
prefix: String::from(
311313
"// @generated
312-
#![allow(clippy::all)]
314+
#![allow(warnings)]
313315
#![cfg_attr(rustfmt, rustfmt_skip)]
314-
#![allow(clippy::should_implement_trait)]
315-
#![allow(clippy::needless_arbitrary_self_type)]
316316
317317
pub mod extras;
318318
pub use extras::*;

rust-toolchain.toml

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,20 @@
1-
toolchain.channel = "1.88"
2-
toolchain.components = ["rust-analyzer", "cargo", "rustfmt", "clippy", "rustc"]
1+
# We use nightly Rust toolchain but set `rust-version` in `Cargo.toml` to
2+
# a stable release.
3+
#
4+
# This allows us to use the latest versions of clippy, rustfmt and rust-analyzer.
5+
#
6+
# We can't use `#[feature(..)]` of course, and the `clippy::incompatible_msrv` lint ensures we
7+
# don't use any Rust features that were stabilized in a later version than `rust-version` set
8+
# in the `Cargo.toml`.
9+
#
10+
# We can use `#[feature(..)]` in tests which is nice - since tests aren't compiled with the main
11+
# crate so MSRV does not apply to them
12+
toolchain.channel = "nightly-2025-08-24"
13+
toolchain.components = [
14+
"rust-analyzer",
15+
"cargo",
16+
"rustfmt",
17+
"clippy",
18+
"rustc",
19+
"rust-src"
20+
]

src/cache.rs

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,23 @@
1-
use std::fs::{self, File};
1+
//! Cache
2+
3+
use std::fs;
4+
use std::fs::File;
25
use std::io::Read as _;
36
use std::path::PathBuf;
4-
use std::time::{SystemTime, UNIX_EPOCH};
7+
use std::time::SystemTime;
8+
use std::time::UNIX_EPOCH;
59

6-
use serde::{Deserialize, Serialize};
10+
use serde::Deserialize;
11+
use serde::Serialize;
712

813
/// Cache allows us to make less network request at the cost of inacurracy if
914
/// the user moves to another country within the `Cache::REFRESH_AFTER_SEC`
1015
/// period
1116
#[derive(Serialize, Deserialize)]
1217
pub struct Cache {
18+
/// When was the last time we modified the cache
1319
modified_time: u64,
20+
/// Country code stored
1421
pub country_code: String,
1522
}
1623

@@ -19,17 +26,20 @@ impl Cache {
1926
/// it will make another networkr request to the country API to get the
2027
/// user's current country
2128
const REFRESH_AFTER_SEC: u64 = 30 * 60;
29+
/// The file that we use for cache
2230
const CACHE_FILE: &str = "countryfetch.json";
2331

32+
/// If it is outdated
2433
fn is_outdated(&self) -> bool {
2534
(SystemTime::now()
2635
.duration_since(UNIX_EPOCH)
27-
.unwrap()
36+
.unwrap_or_default()
2837
.as_secs()
2938
.saturating_sub(self.modified_time))
3039
< Self::REFRESH_AFTER_SEC
3140
}
3241

42+
/// Returns the file of the cache
3343
fn cache_file() -> Option<PathBuf> {
3444
directories::BaseDirs::new().map(|b| b.cache_dir().join(Self::CACHE_FILE))
3545
}
@@ -47,16 +57,9 @@ impl Cache {
4757
}
4858

4959
/// Read the cache file if we can find it
50-
///
51-
/// # Panics
52-
///
53-
/// If the system clock is set to earlier than [`std::time::UNIX_EPOCH`]
5460
pub fn write(country_code: String) -> Result<(), Box<dyn core::error::Error>> {
5561
let serialized = serde_json::ser::to_vec(&Self {
56-
modified_time: SystemTime::now()
57-
.duration_since(UNIX_EPOCH)
58-
.unwrap()
59-
.as_secs(),
62+
modified_time: SystemTime::now().duration_since(UNIX_EPOCH)?.as_secs(),
6063
country_code,
6164
})?;
6265

src/cli.rs

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,17 @@
1+
//! The command-line interface
2+
13
use core::error;
24

3-
use anstyle::{AnsiColor, Effects};
4-
use clap::{Parser, ValueEnum as _};
5+
use anstyle::AnsiColor;
6+
use anstyle::Effects;
7+
use clap::Parser;
8+
use clap::ValueEnum as _;
59

10+
use crate::Country;
11+
use crate::Location;
612
use crate::cache::Cache;
713
use crate::country_format::format_country;
8-
use crate::{Country, Location, generated_country_data};
14+
use crate::generated_country_data;
915

1016
/// Styles for the CLI
1117
const STYLES: clap::builder::Styles = clap::builder::Styles::styled()
@@ -17,13 +23,16 @@ const STYLES: clap::builder::Styles = clap::builder::Styles::styled()
1723
.valid(AnsiColor::BrightCyan.on_default().effects(Effects::BOLD))
1824
.invalid(AnsiColor::BrightYellow.on_default().effects(Effects::BOLD));
1925

26+
/// Countryfetch's arguments
2027
#[derive(Parser, Debug)]
2128
#[command(version, author = "Nik Revenco", about, long_about = None, styles = STYLES)]
2229
#[expect(
2330
clippy::struct_excessive_bools,
2431
reason = "Clap is expected to have many command line arguments"
2532
)]
2633
pub struct Args {
34+
/// A list of countries to generate output for. If it's empty, detect the
35+
/// country
2736
#[clap(hide_possible_values = true, ignore_case = true)]
2837
pub country: Option<Vec<generated_country_data::Country>>,
2938
/// Print information about all countries
@@ -86,6 +95,7 @@ impl Args {
8695
/// # Panics
8796
///
8897
/// - Stored invalid 2 letter country code in the cache file
98+
#[expect(clippy::print_stdout, reason = "this is where we print the country")]
8999
pub async fn print(self) -> Result<(), Box<dyn error::Error>> {
90100
if self.list_countries {
91101
println!(

src/country.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
#![allow(
2+
clippy::missing_docs_in_private_items,
3+
missing_docs,
4+
reason = "this just models the JSON API"
5+
)]
16
use std::collections::HashMap;
27

38
use serde::Deserialize;
@@ -6,7 +11,9 @@ use serde::Deserialize;
611
#[derive(Default, Debug, Clone, PartialEq, Deserialize)]
712
#[serde(rename_all = "camelCase")]
813
pub struct Country {
14+
/// Name of the country
915
#[serde(rename = "name")]
16+
#[expect(clippy::struct_field_names, reason = "this is cleaner")]
1017
country_name: Name,
1118
#[serde(default)]
1219
#[serde(rename = "tld")]
@@ -102,12 +109,15 @@ impl Country {
102109
.await
103110
}
104111

112+
#[must_use]
105113
pub fn country_name(&self) -> &str {
106114
&self.country_name.common
107115
}
116+
#[must_use]
108117
pub fn driving_side(&self) -> &str {
109118
&self.car.side
110119
}
120+
#[must_use]
111121
pub fn dialing_code(&self) -> String {
112122
let codes = self
113123
.dialing_code

0 commit comments

Comments
 (0)