Skip to content

Commit d25a30b

Browse files
author
Michael Rodler
committed
Enabled clippy in CI; added some safety comments; fixed some clippy warnings;
1 parent 4f28cbd commit d25a30b

File tree

11 files changed

+50
-7
lines changed

11 files changed

+50
-7
lines changed

.github/workflows/ci.yml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,17 @@ jobs:
4141
if: matrix.benches
4242
run: cargo test --benches ${{ matrix.features }}
4343

44+
45+
clippy_check:
46+
runs-on: ubuntu-latest
47+
# Make sure CI fails on all warnings, including Clippy lints
48+
env:
49+
RUSTFLAGS: "-Dwarnings"
50+
steps:
51+
- uses: actions/checkout@v3
52+
- name: Run Clippy
53+
run: cargo clippy --all-targets --all-features
54+
4455
msrv:
4556
name: Check MSRV
4657
runs-on: ubuntu-latest

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ A set of types for representing HTTP requests and responses.
2020
keywords = ["http"]
2121
categories = ["web-programming"]
2222
edition = "2018"
23-
# When updating this value, don't forget to also adjust the GitHub Actions config.
23+
# When updating this value, don't forget to also adjust the clippy config.
2424
rust-version = "1.49.0"
2525

2626
[workspace]

clippy.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
msrv="1.49"

src/extensions.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ impl Extensions {
6060
/// assert_eq!(ext.insert(9i32), Some(5i32));
6161
/// ```
6262
pub fn insert<T: Send + Sync + 'static>(&mut self, val: T) -> Option<T> {
63+
#[allow(clippy::box_default)]
6364
self.map
6465
.get_or_insert_with(|| Box::new(HashMap::default()))
6566
.insert(TypeId::of::<T>(), Box::new(val))

src/header/map.rs

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -961,6 +961,7 @@ impl<T> HeaderMap<T> {
961961
let entries = &mut self.entries[..] as *mut _;
962962
let extra_values = &mut self.extra_values as *mut _;
963963
let len = self.entries.len();
964+
// SAFETY: see comment above
964965
unsafe { self.entries.set_len(0); }
965966

966967
Drain {
@@ -2070,6 +2071,7 @@ impl<'a, T> Iterator for Iter<'a, T> {
20702071
fn next(&mut self) -> Option<Self::Item> {
20712072
self.inner
20722073
.next_unsafe()
2074+
// SAFETY: Iter invariant: only valid pointers
20732075
.map(|(key, ptr)| (key, unsafe { &*ptr }))
20742076
}
20752077

@@ -2090,6 +2092,7 @@ impl<'a, T> IterMut<'a, T> {
20902092
use self::Cursor::*;
20912093

20922094
if self.cursor.is_none() {
2095+
// SAFETY: invariant dereferencing the self.map pointer is always safe
20932096
if (self.entry + 1) >= unsafe { &*self.map }.entries.len() {
20942097
return None;
20952098
}
@@ -2098,6 +2101,7 @@ impl<'a, T> IterMut<'a, T> {
20982101
self.cursor = Some(Cursor::Head);
20992102
}
21002103

2104+
// SAFETY: invariant dereferencing the self.map pointer is always safe
21012105
let entry = unsafe { &(*self.map).entries[self.entry] };
21022106

21032107
match self.cursor.unwrap() {
@@ -2106,6 +2110,7 @@ impl<'a, T> IterMut<'a, T> {
21062110
Some((&entry.key, &entry.value as *const _ as *mut _))
21072111
}
21082112
Values(idx) => {
2113+
// SAFETY: invariant dereferencing the self.map pointer is always safe
21092114
let extra = unsafe { &(*self.map).extra_values[idx] };
21102115

21112116
match extra.next {
@@ -2128,6 +2133,7 @@ impl<'a, T> Iterator for IterMut<'a, T> {
21282133
}
21292134

21302135
fn size_hint(&self) -> (usize, Option<usize>) {
2136+
// SAFETY: invariant dereferencing the self.map pointer is always safe
21312137
let map = unsafe { &*self.map };
21322138
debug_assert!(map.entries.len() >= self.entry);
21332139

@@ -2204,9 +2210,8 @@ impl<'a, T> Iterator for Drain<'a, T> {
22042210
// Remove the extra value
22052211

22062212
let raw_links = RawLinks(self.entries);
2207-
let extra = unsafe {
2208-
remove_extra_value(raw_links, &mut *self.extra_values, next)
2209-
};
2213+
// SAFETY: dereferencing self.extra_values valid as long as self is alive.
2214+
let extra = remove_extra_value(raw_links, unsafe { &mut *self.extra_values } , next);
22102215

22112216
match extra.next {
22122217
Link::Extra(idx) => self.next = Some(idx),
@@ -2224,6 +2229,8 @@ impl<'a, T> Iterator for Drain<'a, T> {
22242229

22252230
self.idx += 1;
22262231

2232+
// SAFETY: pointer operation always valid, as `self` cannot outlive the HeaderMap it is
2233+
// referencing.
22272234
unsafe {
22282235
let entry = &(*self.entries)[idx];
22292236

@@ -2243,6 +2250,7 @@ impl<'a, T> Iterator for Drain<'a, T> {
22432250
// For instance, extending a new `HeaderMap` wouldn't need to
22442251
// reserve the upper-bound in `entries`, only the lower-bound.
22452252
let lower = self.len - self.idx;
2253+
// SAFETY: dereferencing self.extra_values valid as long as self is alive.
22462254
let upper = unsafe { (*self.extra_values).len() } + lower;
22472255
(lower, Some(upper))
22482256
}
@@ -2606,6 +2614,7 @@ impl<'a, T: 'a> Iterator for ValueIterMut<'a, T> {
26062614
fn next(&mut self) -> Option<Self::Item> {
26072615
use self::Cursor::*;
26082616

2617+
// SAFETY: dereferencing self.map valid as long as self is alive.
26092618
let entry = unsafe { &mut (*self.map).entries[self.index] };
26102619

26112620
match self.front {
@@ -2626,6 +2635,7 @@ impl<'a, T: 'a> Iterator for ValueIterMut<'a, T> {
26262635
Some(&mut entry.value)
26272636
}
26282637
Some(Values(idx)) => {
2638+
// SAFETY: dereferencing self.map valid as long as self is alive.
26292639
let extra = unsafe { &mut (*self.map).extra_values[idx] };
26302640

26312641
if self.front == self.back {
@@ -2649,6 +2659,7 @@ impl<'a, T: 'a> DoubleEndedIterator for ValueIterMut<'a, T> {
26492659
fn next_back(&mut self) -> Option<Self::Item> {
26502660
use self::Cursor::*;
26512661

2662+
// SAFETY: dereferencing self.map valid as long as self is alive.
26522663
let entry = unsafe { &mut (*self.map).entries[self.index] };
26532664

26542665
match self.back {
@@ -2658,6 +2669,7 @@ impl<'a, T: 'a> DoubleEndedIterator for ValueIterMut<'a, T> {
26582669
Some(&mut entry.value)
26592670
}
26602671
Some(Values(idx)) => {
2672+
// SAFETY: dereferencing self.map valid as long as self is alive.
26612673
let extra = unsafe { &mut (*self.map).extra_values[idx] };
26622674

26632675
if self.front == self.back {
@@ -2726,7 +2738,7 @@ impl<T> Drop for IntoIter<T> {
27262738
// Ensure the iterator is consumed
27272739
for _ in self.by_ref() {}
27282740

2729-
// All the values have already been yielded out.
2741+
// SAFETY: All the values have already been yielded out, once dropped.
27302742
unsafe {
27312743
self.extra_values.set_len(0);
27322744
}

src/header/name.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,8 +87,8 @@ macro_rules! standard_headers {
8787
#[inline]
8888
fn as_str(&self) -> &'static str {
8989
match *self {
90-
// Safety: test_parse_standard_headers ensures these &[u8]s are &str-safe.
9190
$(
91+
// SAFETY: test_parse_standard_headers ensures these &[u8]s are &str-safe.
9292
StandardHeader::$konst => unsafe { std::str::from_utf8_unchecked( $name_bytes ) },
9393
)+
9494
}
@@ -1267,6 +1267,7 @@ impl HeaderName {
12671267
i += 1;
12681268
}
12691269
} {
1270+
#[allow(clippy::no_effect)]
12701271
([] as [u8; 0])[0]; // Invalid header name
12711272
}
12721273

src/header/value.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ impl HeaderValue {
8585
let mut i = 0;
8686
while i < bytes.len() {
8787
if !is_visible_ascii(bytes[i]) {
88+
#[allow(clippy::no_effect)]
8889
([] as [u8; 0])[0]; // Invalid header value
8990
}
9091
i += 1;
@@ -191,6 +192,10 @@ impl HeaderValue {
191192
///
192193
/// This function does NOT validate that illegal bytes are not contained
193194
/// within the buffer.
195+
///
196+
/// ## Safety
197+
///
198+
/// The caller must ensure that `src` contains only legal utf-8.
194199
pub unsafe fn from_maybe_shared_unchecked<T>(src: T) -> HeaderValue
195200
where
196201
T: AsRef<[u8]> + 'static,

src/lib.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,10 @@
159159
//! ```
160160
161161
#![deny(warnings, missing_docs, missing_debug_implementations)]
162+
#![deny(
163+
clippy::missing_safety_doc,
164+
clippy::undocumented_unsafe_blocks
165+
)]
162166

163167
#[cfg(test)]
164168
#[macro_use]

src/status.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,8 @@ impl StatusCode {
143143
{ &CODE_DIGITS[offset..offset+3] }
144144

145145
#[cfg(not(debug_assertions))]
146+
// SAFETY: we assume `StatusCode` is constructed in a way that self.0 (the numerical status
147+
// code is >= 100 and also <= 1000, which makes any possible offset here valid.
146148
unsafe { CODE_DIGITS.get_unchecked(offset..offset+3) }
147149
}
148150

@@ -304,7 +306,9 @@ macro_rules! status_codes {
304306
impl StatusCode {
305307
$(
306308
$(#[$docs])*
307-
pub const $konst: StatusCode = StatusCode(unsafe { NonZeroU16::new_unchecked($num) });
309+
pub const $konst: StatusCode = StatusCode(
310+
// SAFETY: only called with constants
311+
unsafe { NonZeroU16::new_unchecked($num) });
308312
)+
309313

310314
}

src/uri/mod.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -837,6 +837,7 @@ fn parse_full(mut s: Bytes) -> Result<Uri, InvalidUri> {
837837
let _ = scheme.split_off(n);
838838

839839
// Allocate the ByteStr
840+
// SAFETY: previously verified by `Scheme2::parse`
840841
let val = unsafe { ByteStr::from_utf8_unchecked(scheme) };
841842

842843
Scheme2::Other(Box::new(val))
@@ -853,6 +854,7 @@ fn parse_full(mut s: Bytes) -> Result<Uri, InvalidUri> {
853854
}
854855

855856
let authority = Authority {
857+
// SAFETY: previously verified by `Authority::parse`
856858
data: unsafe { ByteStr::from_utf8_unchecked(s) },
857859
};
858860

@@ -870,6 +872,7 @@ fn parse_full(mut s: Bytes) -> Result<Uri, InvalidUri> {
870872

871873
let authority = s.split_to(authority_end);
872874
let authority = Authority {
875+
// SAFETY: previously verified by `Authority::parse`
873876
data: unsafe { ByteStr::from_utf8_unchecked(authority) },
874877
};
875878

0 commit comments

Comments
 (0)