Skip to content

Commit 31ad414

Browse files
committed
sort: isolate WASI sync code into sibling modules
1 parent 685a7be commit 31ad414

13 files changed

Lines changed: 1415 additions & 1284 deletions

File tree

src/uu/sort/src/check.rs

Lines changed: 0 additions & 217 deletions
This file was deleted.

src/uu/sort/src/check/mod.rs

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
// This file is part of the uutils coreutils package.
2+
//
3+
// For the full copyright and license information, please view the LICENSE
4+
// file that was distributed with this source code.
5+
6+
//! Check if a file is ordered.
7+
//!
8+
//! On most platforms this uses a multi-threaded reader. On WASI without
9+
//! atomics, a synchronous variant is used instead. The two implementations
10+
//! live in sibling modules and are selected via cfg at the module boundary.
11+
12+
use std::cmp::Ordering;
13+
use std::ffi::OsStr;
14+
15+
use uucore::error::UResult;
16+
17+
use crate::{GlobalSettings, open};
18+
19+
#[cfg(not(wasi_no_threads))]
20+
mod threaded;
21+
#[cfg(not(wasi_no_threads))]
22+
use threaded as runner;
23+
24+
#[cfg(wasi_no_threads)]
25+
mod sync;
26+
#[cfg(wasi_no_threads)]
27+
use sync as runner;
28+
29+
/// Check if the file at `path` is ordered.
30+
pub fn check(path: &OsStr, settings: &GlobalSettings) -> UResult<()> {
31+
let max_allowed_cmp = if settings.unique {
32+
Ordering::Less
33+
} else {
34+
Ordering::Equal
35+
};
36+
let file = open(path)?;
37+
let chunk_size = if settings.buffer_size < 100 * 1024 {
38+
settings.buffer_size
39+
} else {
40+
100 * 1024
41+
};
42+
43+
runner::check(path, settings, max_allowed_cmp, file, chunk_size)
44+
}

src/uu/sort/src/check/sync.rs

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
// This file is part of the uutils coreutils package.
2+
//
3+
// For the full copyright and license information, please view the LICENSE
4+
// file that was distributed with this source code.
5+
6+
//! Synchronous ordered-file check for targets without thread support.
7+
8+
use std::cmp::Ordering;
9+
use std::ffi::OsStr;
10+
use std::io::Read;
11+
use std::iter;
12+
13+
use itertools::Itertools;
14+
use uucore::error::UResult;
15+
16+
use crate::{
17+
GlobalSettings, SortError,
18+
chunks::{self, Chunk, RecycledChunk},
19+
compare_by,
20+
};
21+
22+
pub(super) fn check(
23+
path: &OsStr,
24+
settings: &GlobalSettings,
25+
max_allowed_cmp: Ordering,
26+
mut file: Box<dyn Read + Send>,
27+
chunk_size: usize,
28+
) -> UResult<()> {
29+
let separator = settings.line_ending.into();
30+
let mut carry_over = vec![];
31+
let mut prev_chunk: Option<Chunk> = None;
32+
let mut spare_recycled: Option<RecycledChunk> = None;
33+
let mut line_idx = 0;
34+
35+
loop {
36+
let recycled = spare_recycled
37+
.take()
38+
.unwrap_or_else(|| RecycledChunk::new(chunk_size));
39+
40+
let (chunk, should_continue) = chunks::read_to_chunk(
41+
recycled,
42+
None,
43+
&mut carry_over,
44+
&mut file,
45+
&mut iter::empty(),
46+
separator,
47+
settings,
48+
)?;
49+
50+
let Some(chunk) = chunk else {
51+
break;
52+
};
53+
54+
line_idx += 1;
55+
if let Some(prev) = prev_chunk.take() {
56+
let prev_last = prev.lines().last().unwrap();
57+
let new_first = chunk.lines().first().unwrap();
58+
59+
if compare_by(
60+
prev_last,
61+
new_first,
62+
settings,
63+
prev.line_data(),
64+
chunk.line_data(),
65+
) > max_allowed_cmp
66+
{
67+
return Err(SortError::Disorder {
68+
file: path.to_owned(),
69+
line_number: line_idx,
70+
line: String::from_utf8_lossy(new_first.line).into_owned(),
71+
silent: settings.check_silent,
72+
}
73+
.into());
74+
}
75+
spare_recycled = Some(prev.recycle());
76+
}
77+
78+
for (a, b) in chunk.lines().iter().tuple_windows() {
79+
line_idx += 1;
80+
if compare_by(a, b, settings, chunk.line_data(), chunk.line_data()) > max_allowed_cmp {
81+
return Err(SortError::Disorder {
82+
file: path.to_owned(),
83+
line_number: line_idx,
84+
line: String::from_utf8_lossy(b.line).into_owned(),
85+
silent: settings.check_silent,
86+
}
87+
.into());
88+
}
89+
}
90+
91+
prev_chunk = Some(chunk);
92+
93+
if !should_continue {
94+
break;
95+
}
96+
}
97+
Ok(())
98+
}

0 commit comments

Comments
 (0)