Skip to content

Commit ed472d5

Browse files
committed
release:add more tests, tidy up API comments
1 parent 21467ba commit ed472d5

10 files changed

Lines changed: 74 additions & 24 deletions

File tree

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: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "fdf"
3-
version = "0.7.8"
3+
version = "0.7.7"
44
rust-version = "1.85.0"
55
edition = "2024"
66
license = "MIT"

benches/dirent_bench.rs

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use criterion::{BenchmarkId, Criterion, Throughput, criterion_group, criterion_main};
2+
use fdf::access_dirent;
23

34
use core::num::NonZeroU64;
45
use std::hint::black_box;
@@ -103,15 +104,19 @@ fn bench_strlen(c: &mut Criterion) {
103104
group.bench_with_input(
104105
BenchmarkId::new("const_time_swar", size_name),
105106
&entry,
106-
|b, e| b.iter(|| unsafe { black_box(dirent_const_time_strlen(black_box(e))) }),
107+
|b, e| {
108+
b.iter(|| unsafe {
109+
black_box(dirent_const_time_strlen(black_box(e as *const _)))
110+
})
111+
},
107112
);
108113

109114
group.bench_with_input(
110115
BenchmarkId::new("libc_strlen", size_name),
111116
&entry,
112117
|b, e| {
113118
b.iter(|| unsafe {
114-
black_box(libc::strlen(black_box(e.d_name.as_ptr() as *const _)))
119+
black_box(libc::strlen(black_box(access_dirent!(e, d_name).cast())))
115120
})
116121
},
117122
);
@@ -141,7 +146,9 @@ fn bench_strlen(c: &mut Criterion) {
141146
let mut total = 0;
142147
for entry in &all_entries {
143148
total += unsafe {
144-
black_box(libc::strlen(black_box(entry.d_name.as_ptr() as *const _)))
149+
black_box(libc::strlen(black_box(
150+
access_dirent!(entry, d_name).cast(),
151+
)))
145152
};
146153
}
147154
black_box(total) //make sure compiler does not optimise this away

build.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,5 +21,4 @@ fn main() {
2121
max_filename_len >= 255,
2222
"NAME_MAX is not appropriately set!"
2323
);
24-
2524
}

src/finderbuilder.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -102,15 +102,16 @@ impl FinderBuilder {
102102
self
103103
}
104104
#[must_use]
105-
/// Set whether to use short paths in regex matching, defaults to true
105+
/// Set whether to use short paths in regex/glob matching, defaults to true
106+
/// This is over-ridden if the search term contains a '/'
106107
pub const fn file_name_only(mut self, short_path: bool) -> Self {
107108
self.file_name_only = short_path;
108109
self
109110
}
110111
#[must_use]
111112
/// Set extension to match, defaults to no extension
112-
pub fn extension_match<C: AsRef<str>>(mut self, extension_match: C) -> Self {
113-
let ext = extension_match.as_ref().as_bytes();
113+
pub fn extension<C: AsRef<str>>(mut self, extension: C) -> Self {
114+
let ext = extension.as_ref().as_bytes();
114115

115116
if ext.is_empty() {
116117
self.extension_match = None;
@@ -147,8 +148,7 @@ impl FinderBuilder {
147148

148149
/// Sets whether to follow symlinks (default: false).
149150
///
150-
/// # Warning
151-
/// Enabling this may cause infinite recursion, although there are protections in place against it!
151+
/// This will not recurse infinitely but can provide more results than expected
152152
#[must_use]
153153
pub const fn follow_symlinks(mut self, follow_symlinks: bool) -> Self {
154154
self.follow_symlinks = follow_symlinks;

src/iter.rs

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -477,16 +477,13 @@ pub trait DirentConstructor {
477477
let path_buffer = self.path_buffer();
478478
// SAFETY: The `base_len` is guaranteed to be a valid index into `path_buffer`
479479
let buffer = unsafe { &mut path_buffer.get_unchecked_mut(base_len..) };
480-
// SAFETY:
481-
// - `d_name` and `buffer` don't overlap (different memory regions)
480+
481+
// SAFETY: `d_name` and `buffer` don't overlap (different memory regions)
482482
// - Both pointers are properly aligned for byte copying
483-
// - `name_len` is within `buffer` bounds (checked by debug assertion)
483+
// - `name_len` is within `buffer` bounds
484484
unsafe { core::ptr::copy_nonoverlapping(d_name, buffer.as_mut_ptr(), name_len) };
485-
486-
/*
487-
SAFETY: the buffer is guaranteed null terminated and we're accessing in bounds
488-
*/
489485
#[allow(clippy::multiple_unsafe_ops_per_block)]
486+
// SAFETY: the buffer is guaranteed null terminated and we're accessing in bounds
490487
unsafe {
491488
CStr::from_bytes_with_nul_unchecked(path_buffer.get_unchecked(..base_len + name_len))
492489
}

src/lib.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -455,9 +455,8 @@ impl Finder {
455455
.search_config
456456
.depth
457457
.is_some_and(|depth| dir.depth >= depth.get())
458-
459458
{
460-
if should_send{
459+
if should_send {
461460
let _ = sender.send(vec![dir.clone()]);
462461
} // cloning costs very little here.
463462
return false; // depth limit reached, stop processing

src/main.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -266,7 +266,7 @@ fn main() -> Result<(), SearchConfigError> {
266266
.fixed_string(args.fixed_string)
267267
.canonicalise_root(args.absolute_path)
268268
.file_name_only(!args.full_path)
269-
.extension_match(args.extension.unwrap_or_else(String::new))
269+
.extension(args.extension.unwrap_or_else(String::new))
270270
.max_depth(args.depth)
271271
.follow_symlinks(args.follow_symlinks)
272272
.filter_by_size(args.size)

src/test.rs

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ mod tests {
55
use crate::Finder;
66
use crate::cli_helpers::*;
77
use crate::{DirEntry, FileType};
8-
use crate::{find_char_in_word, find_zero_byte_u64};
8+
use crate::{find_char_in_word, find_last_char_in_word, find_zero_byte_u64};
99
use chrono::{Duration as ChronoDuration, Utc};
1010
use env_home::env_home_dir;
1111
use filetime::{FileTime, set_file_times};
@@ -464,6 +464,12 @@ mod tests {
464464
assert_eq!(find_char_in_word(b'o', bytes), Some(4));
465465
}
466466

467+
#[test]
468+
fn test_last_char_at_end() {
469+
let bytes = create_byte_array("hello");
470+
assert_eq!(find_last_char_in_word(b'l', bytes), Some(3));
471+
}
472+
467473
#[test]
468474
fn test_char_not_found() {
469475
let bytes = create_byte_array("hello");
@@ -1255,6 +1261,49 @@ mod tests {
12551261
}
12561262
}
12571263

1264+
#[test]
1265+
#[allow(unused)]
1266+
fn test_home_extension() {
1267+
let pattern: &str = ".";
1268+
1269+
let home_dir = env_home_dir();
1270+
if home_dir.is_some() {
1271+
let finder = Finder::init(home_dir.unwrap().as_os_str())
1272+
.pattern(&pattern)
1273+
.extension("c")
1274+
.keep_hidden(true)
1275+
.keep_dirs(true)
1276+
.build()
1277+
.unwrap();
1278+
1279+
let result = finder.traverse().unwrap().into_iter();
1280+
1281+
let collected: Vec<_> = std::hint::black_box(result.collect());
1282+
}
1283+
}
1284+
1285+
#[test]
1286+
#[allow(unused)]
1287+
fn test_home_extension_symlink() {
1288+
let pattern: &str = ".";
1289+
1290+
let home_dir = env_home_dir();
1291+
if home_dir.is_some() {
1292+
let finder = Finder::init(home_dir.unwrap().as_os_str())
1293+
.pattern(&pattern)
1294+
.follow_symlinks(true)
1295+
.extension("c")
1296+
.keep_hidden(true)
1297+
.keep_dirs(true)
1298+
.build()
1299+
.unwrap();
1300+
1301+
let result = finder.traverse().unwrap().into_iter();
1302+
1303+
let collected: Vec<_> = std::hint::black_box(result.collect());
1304+
}
1305+
}
1306+
12581307
#[test]
12591308
#[allow(unused)]
12601309
fn test_home_symlink() {

src/types.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,8 @@ const_from_env!(
1212
);
1313
//basically this is the should allow getdents to grab a lot of entries in one go
1414

15-
1615
#[cfg(any(target_os = "linux", target_os = "android"))]
17-
const_assert!(BUFFER_SIZE>=4096,"Buffer size too small!");
16+
const_assert!(BUFFER_SIZE >= 4096, "Buffer size too small!");
1817

1918
#[cfg(any(target_os = "linux", target_os = "android"))]
2019
//we only use a buffer for syscalls on linux because of stable ABI(because we don't need to use a buffer for `ReadDir`)

0 commit comments

Comments
 (0)