add rayon

This commit is contained in:
sleptworld 2023-09-17 01:30:07 +08:00
parent f4d308fd53
commit ffedf08dfd
7 changed files with 154 additions and 32 deletions

28
Cargo.lock generated
View File

@ -56,6 +56,12 @@ dependencies = [
"windows-sys", "windows-sys",
] ]
[[package]]
name = "anyhow"
version = "1.0.75"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6"
[[package]] [[package]]
name = "autocfg" name = "autocfg"
version = "1.1.0" version = "1.1.0"
@ -386,6 +392,7 @@ dependencies = [
name = "rsParser-r" name = "rsParser-r"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"anyhow",
"clap", "clap",
"flate2", "flate2",
"indoc", "indoc",
@ -396,6 +403,7 @@ dependencies = [
"rayon", "rayon",
"serde", "serde",
"serde_json", "serde_json",
"thiserror",
] ]
[[package]] [[package]]
@ -475,6 +483,26 @@ dependencies = [
"unicode-ident", "unicode-ident",
] ]
[[package]]
name = "thiserror"
version = "1.0.48"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9d6d7a740b8a666a7e828dd00da9c0dc290dff53154ea77ac109281de90589b7"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "1.0.48"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49922ecae66cc8a249b77e68d1d0623c1b2c514f0060c27cdc68bd62a1219d35"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.33",
]
[[package]] [[package]]
name = "unicode-ident" name = "unicode-ident"
version = "1.0.12" version = "1.0.12"

View File

@ -17,3 +17,5 @@ serde_json = "1.0.107"
flate2 = "1.0.27" flate2 = "1.0.27"
indoc = "2.0.3" indoc = "2.0.3"
num-traits = "0.2.16" num-traits = "0.2.16"
thiserror = "1.0.48"
anyhow = "1.0.75"

View File

@ -1,11 +1,57 @@
use num_traits::Num; use crate::parse::{Parsed, parse};
use crate::error::{AResult, BrokenError};
use crate::utils::is_gz;
use rayon::prelude::{*, IndexedParallelIterator};
use flate2::read::GzDecoder;
use std::path::PathBuf;
use std::fs::File;
use std::io::{Read, Seek, SeekFrom};
use crate::parse::Parsed; type AAResult<O> = AResult<O,()>;
pub struct App{ pub struct App {
datas: Vec<Parsed> paths: Vec<PathBuf>,
config: AppConfig,
}
#[derive(Copy, Clone, Debug, PartialOrd, PartialEq)]
pub struct AppConfig {
pub only_header: bool,
pub multi_threading: bool,
} }
impl App { impl App {
pub fn new(paths: Vec<PathBuf>, config: AppConfig) -> Result<Self, BrokenError> {
Ok(Self { paths, config })
}
pub fn parse(&self) ->AAResult<Vec<Parsed>> {
let paths = &self.paths;
let config = &self.config;
let datas = paths.par_iter().map(|p| {
let d = Self::data_prepare(p);
match d {
Ok(_d) => parse(&_d, config.only_header).map(|(_,b)| b).map_err(|e| e.into()),
Err(e) => Err(e.into())
}
}).collect::<Result<Vec<_>, BrokenError>>()?;
Ok((datas,()))
}
fn data_prepare(path: &PathBuf) -> Result<Vec<u8>, std::io::Error> {
let mut f = File::open(path)?;
let mut buf = Vec::new();
{
let mut magic = [0; 2];
f.read_exact(&mut magic)?;
f.seek(SeekFrom::Start(0))?;
if is_gz(&magic) {
let mut d = GzDecoder::new(f);
d.read_to_end(&mut buf)?;
} else {
f.read_to_end(&mut buf)?;
}
}
Ok(buf)
}
} }

18
src/error.rs Normal file
View File

@ -0,0 +1,18 @@
use thiserror::Error;
use nom::Err;
#[derive(Error, Debug)]
pub enum BrokenError {
#[error("Can't Open file or file not exist.")]
IO(#[from] std::io::Error),
#[error("This file is not standard format.")]
ParseError,
}
impl<T> From<Err<T>> for BrokenError {
fn from(value: Err<T>) -> Self {
Self::ParseError
}
}
pub type AResult<O, E> = Result<(O, E), BrokenError>;

View File

@ -2,6 +2,8 @@ mod parse;
mod app; mod app;
mod printer; mod printer;
mod utils; mod utils;
mod error;
use std::io::prelude::*; use std::io::prelude::*;
use flate2::read::GzDecoder; use flate2::read::GzDecoder;
use std::fs::File; use std::fs::File;
@ -11,6 +13,8 @@ use std::path::PathBuf;
use clap::{Args, command, Parser, Subcommand, ValueEnum}; use clap::{Args, command, Parser, Subcommand, ValueEnum};
use parse::parse; use parse::parse;
use crate::app::{App, AppConfig};
/// A fictional versioning CLI /// A fictional versioning CLI
#[derive(Debug, Parser)] // requires `derive` feature #[derive(Debug, Parser)] // requires `derive` feature
#[command(name = "rsParser")] #[command(name = "rsParser")]
@ -76,12 +80,11 @@ fn main() {
let args = Cli::parse(); let args = Cli::parse();
match args.command { match args.command {
Commands::Parse { path, header } => { Commands::Parse { path, header } => {
let f = File::open(path).unwrap(); let config = AppConfig{
let mut d = GzDecoder::new(f); only_header:header,
let mut buf = Vec::new(); multi_threading:true
d.read_to_end(&mut buf).unwrap(); };
let (_, parsed) = parse(&buf, header).unwrap(); let app = App::new(vec![path], config).unwrap();
println!("{}", parsed);
} }
} }
} }

View File

@ -1,17 +1,12 @@
use ndarray::ArrayD;
use nom::bytes::complete::*; use nom::bytes::complete::*;
use nom::error::ParseError; use nom::error::{ParseError, ErrorKind};
use nom::multi::count; use nom::multi::count;
use nom::number::complete::{ use nom::number::complete::{be_f32, be_i32, be_i8, be_u32, be_u8, le_f32, le_i32, le_i8, le_u8, le_u32};
be_f32, be_f64, be_i16, be_i32, be_i8, be_u8, le_f32, le_f64, le_i16, le_i32, le_i8, le_u8,
};
use nom::sequence::tuple; use nom::sequence::tuple;
use nom::IResult; use nom::IResult;
use nom_derive;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::any::Any; use std::any::Any;
use std::str::from_utf8; use std::str::from_utf8;
use std::string;
#[derive(Deserialize, Serialize, Debug)] #[derive(Deserialize, Serialize, Debug)]
pub struct HeaderJson { pub struct HeaderJson {
@ -51,7 +46,7 @@ pub struct CommonHeader {
pub struct Block { pub struct Block {
pub block_info: BlockInfo, pub block_info: BlockInfo,
pub data: Option<Box<dyn Any>>, pub data: Option<Box<dyn Any + Sync + Send>>,
} }
pub struct Parsed { pub struct Parsed {
@ -93,7 +88,8 @@ fn common_parse(input: &[u8]) -> IResult<&[u8], CommonHeader> {
fn block_parse<'a, Error: ParseError<&'a [u8]>>( fn block_parse<'a, Error: ParseError<&'a [u8]>>(
only_header: bool, only_header: bool,
endian: Endian, endian: Endian,
) -> impl Fn(&'a [u8]) -> IResult<&'a [u8], Block, Error> { ) -> impl Fn(&'a [u8]) -> IResult<&'a [u8], Block, Error>
{
let l_p = match endian { let l_p = match endian {
Endian::Big => be_i32, Endian::Big => be_i32,
Endian::Little => le_i32, Endian::Little => le_i32,
@ -112,28 +108,57 @@ fn block_parse<'a, Error: ParseError<&'a [u8]>>(
let (next, l2) = l_p(next)?; let (next, l2) = l_p(next)?;
let (next, _data) = take(l2 as usize)(next)?; let (next, _data) = take(l2 as usize)(next)?;
let mut d: Option<Box<dyn Any + Send + Sync>> = None;
if !only_header { if !only_header {
let c = j.dimension_size.iter().fold(1, |i, j| i * (*j)) as usize; let c = j.dimension_size.iter().fold(1, |i, j| i * (*j)) as usize;
match j.value_type.as_str() { d = match j.value_type.as_str() {
"b" => { "b" => {
let (next,v) = count(match endian { let (_, v) = count(match endian {
Endian::Big => be_i8, Endian::Big => be_i8,
_ => le_i8 _ => le_i8
},c)(_data)?; }, c)(_data)?;
Some(Box::new(v))
} }
"B" => {} "B" => {
"h" => {} let (_, v) = count(match endian {
"f" => {} Endian::Big => be_u8,
_ => {} _ => le_u8
}, c)(_data)?;
Some(Box::new(v))
} }
"i" => {
let (_, v) = count(match endian {
Endian::Big => be_i32,
_ => le_i32
}, c)(_data)?;
Some(Box::new(v))
}
"u" => {
let (_, v) = count(match endian {
Endian::Big => be_u32,
_ => le_u32
}, c)(_data)?;
Some(Box::new(v))
}
"f" => {
let (_, v) = count(match endian {
Endian::Big => be_f32,
_ => le_f32
}, c)(_data)?;
Some(Box::new(v))
}
_ => {
return Err(nom::Err::Failure(Error::from_error_kind(next, ErrorKind::Alpha)));
}
};
} }
let (next, _) = take(8usize)(next)?; let (next, _) = take(8usize)(next)?;
Ok(( Ok((
next, next,
Block { Block {
block_info: j, block_info: j,
data: None, data: d,
}, },
)) ))
} }
@ -151,7 +176,7 @@ fn blocks_parse(
} }
pub fn parse<'a>(input: &'a [u8], only_header: bool) -> IResult<&'a [u8], Parsed> { pub fn parse<'a>(input: &'a [u8], only_header: bool) -> IResult<&'a [u8], Parsed> {
let (next, magic) = tag(b"UNI_DATA")(input)?; let (next, _) = tag(b"UNI_DATA")(input)?;
let (next, common_header) = common_parse(next)?; let (next, common_header) = common_parse(next)?;
let (next, blocks) = blocks_parse( let (next, blocks) = blocks_parse(
next, next,

View File

@ -1,3 +1,3 @@
fn is_gz(data:&[u8;2]) -> bool{ pub fn is_gz(data:&[u8;2]) -> bool{
*data == [0x1f, 0x8b] *data == [0x1f, 0x8b]
} }