-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'main' of https:/E85Addict/cmpr
- Loading branch information
Showing
5 changed files
with
48 additions
and
42 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,4 @@ | ||
/target | ||
/test | ||
test* | ||
Cargo.lock |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,66 +1,66 @@ | ||
#![no_main] | ||
#![feature(slice_as_chunks)] | ||
#![feature(let_chains)] | ||
|
||
use cmpr::{cprintln, Mmap, RawArgs}; | ||
use std::{fs::File, os::unix::prelude::AsRawFd, path::Path}; | ||
|
||
mod cmperror { | ||
use std::io; | ||
pub enum Error { | ||
FileReadErr(io::Error), | ||
MmapErr, | ||
} | ||
|
||
impl From<io::Error> for Error { | ||
fn from(e: io::Error) -> Self { | ||
Self::FileReadErr(e) | ||
} | ||
} | ||
} | ||
#![feature(array_chunks, portable_simd, let_chains)] | ||
|
||
#[no_mangle] | ||
pub extern "C" fn main(argc: i32, argv: *const *const u8) -> i32 { | ||
let mut args = RawArgs::new(argc, argv); | ||
let _ = args.next().unwrap(); | ||
if args.len() < 2 { | ||
if let Some(arg) = args.next() && arg == "--version" { | ||
cprintln!("cmpr by j-hc (github.com/j-hc)\nLicense GPL-3.0"); | ||
} else { | ||
cprintln!("Usage: cmpr <file_path> <file_path>"); | ||
} | ||
return 1; | ||
cprintln!( | ||
"Usage: cmpr <file_path> <file_path>\ncmpr by j-hc (github.com/j-hc)\nLicense GPL-3.0" | ||
); | ||
} | ||
|
||
match run(args.next().unwrap(), args.next().unwrap()) { | ||
Ok(true) => 0, | ||
Err(e) => { | ||
match e { | ||
cmperror::Error::FileReadErr(_) => cprintln!("ERROR: File read failed"), | ||
cmperror::Error::MmapErr => cprintln!("ERROR: Memory mapping failed"), | ||
RunErr::IO => cprintln!("ERROR: could not read file"), | ||
RunErr::MMap => cprintln!("ERROR: could not mmap file"), | ||
} | ||
1 | ||
} | ||
_ => 1, | ||
} | ||
} | ||
|
||
fn run(f1_path: impl AsRef<Path>, f2_path: impl AsRef<Path>) -> Result<bool, cmperror::Error> { | ||
const CHUNK_SIZE: usize = 4096; | ||
enum RunErr { | ||
IO, | ||
MMap, | ||
} | ||
|
||
let f1 = File::open(f1_path)?; | ||
let f1_size = f1.metadata()?.len(); | ||
impl From<io::Error> for RunErr { | ||
fn from(_: io::Error) -> Self { | ||
Self::IO | ||
} | ||
} | ||
|
||
let f2 = File::open(f2_path)?; | ||
fn run(p1: &str, p2: &str) -> Result<bool, RunErr> { | ||
let f1 = File::open(p1)?; | ||
let f1_size = f1.metadata()?.len(); | ||
let f2 = File::open(p2)?; | ||
let f2_size = f2.metadata()?.len(); | ||
if f1_size != f2_size { | ||
return Ok(false); | ||
} | ||
let Some(fm1) = Mmap::new(f1.as_raw_fd(), f1_size as _) else { return Err(RunErr::MMap) }; | ||
let Some(fm2) = Mmap::new(f2.as_raw_fd(), f2_size as _) else { return Err(RunErr::MMap) }; | ||
|
||
let mmap1 = Mmap::new(f1.as_raw_fd(), f1_size as _).ok_or(cmperror::Error::MmapErr)?; | ||
let mmap2 = Mmap::new(f2.as_raw_fd(), f2_size as _).ok_or(cmperror::Error::MmapErr)?; | ||
Ok(compare(&fm1, &fm2)) | ||
} | ||
|
||
fn compare(fm1: &[u8], fm2: &[u8]) -> bool { | ||
const CHUNK_SIZE: usize = 16; | ||
let mut fm1 = fm1.array_chunks::<CHUNK_SIZE>(); | ||
let mut fm2 = fm2.array_chunks::<CHUNK_SIZE>(); | ||
|
||
let (chunks1, r1) = mmap1.as_chunks::<CHUNK_SIZE>(); | ||
let (chunks2, r2) = mmap2.as_chunks::<CHUNK_SIZE>(); | ||
Ok(chunks1.iter().zip(chunks2.iter()).all(|(b1, b2)| b1 == b2) && r1 == r2) | ||
iter::zip(fm1.by_ref(), fm2.by_ref()) | ||
.all(|(m1, m2)| u8x16::from_slice(m1) == u8x16::from_slice(m2)) | ||
&& iter::zip(fm1.remainder(), fm2.remainder()).all(|(m1, m2)| m1 == m2) | ||
} | ||
|
||
use cmpr::{cprintln, Mmap, RawArgs}; | ||
use std::fs::File; | ||
use std::os::fd::AsRawFd; | ||
use std::simd::u8x16; | ||
use std::{io, iter}; |