Skip to content

Commit a065e5d

Browse files
committed
examples added.
1 parent 8f69795 commit a065e5d

File tree

3 files changed

+185
-0
lines changed

3 files changed

+185
-0
lines changed

Cargo.toml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,3 +33,11 @@ memory-limit = ["deepsize"]
3333
[[example]]
3434
name = "quickstart"
3535
required-features = ["bytesize", "env_logger"]
36+
37+
[[example]]
38+
name = "custom_serializer"
39+
required-features = ["env_logger"]
40+
41+
[[example]]
42+
name = "custom_type"
43+
required-features = ["env_logger"]

examples/custom_serializer.rs

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
use std::fs;
2+
use std::fs::File;
3+
use std::io::{self, prelude::*, BufReader, BufWriter, Take};
4+
use std::path;
5+
6+
use env_logger;
7+
use log;
8+
9+
use ext_sort::{ExternalChunk, ExternalSorter, ExternalSorterBuilder, LimitedBufferBuilder};
10+
11+
struct CustomExternalChunk {
12+
reader: io::Take<io::BufReader<fs::File>>,
13+
}
14+
15+
impl ExternalChunk<u32> for CustomExternalChunk {
16+
type SerializationError = io::Error;
17+
type DeserializationError = io::Error;
18+
19+
fn new(reader: Take<BufReader<File>>) -> Self {
20+
CustomExternalChunk { reader }
21+
}
22+
23+
fn dump(
24+
chunk_writer: &mut BufWriter<File>,
25+
items: impl IntoIterator<Item = u32>,
26+
) -> Result<(), Self::SerializationError> {
27+
for item in items {
28+
chunk_writer.write_all(&item.to_le_bytes())?;
29+
}
30+
31+
return Ok(());
32+
}
33+
}
34+
35+
impl Iterator for CustomExternalChunk {
36+
type Item = Result<u32, io::Error>;
37+
38+
fn next(&mut self) -> Option<Self::Item> {
39+
if self.reader.limit() == 0 {
40+
None
41+
} else {
42+
let mut buf: [u8; 4] = [0; 4];
43+
match self.reader.read_exact(&mut buf.as_mut_slice()) {
44+
Ok(_) => Some(Ok(u32::from_le_bytes(buf))),
45+
Err(err) => Some(Err(err)),
46+
}
47+
}
48+
}
49+
}
50+
51+
fn main() {
52+
env_logger::Builder::new().filter_level(log::LevelFilter::Debug).init();
53+
54+
let input_reader = io::BufReader::new(fs::File::open("input.txt").unwrap());
55+
let mut output_writer = io::BufWriter::new(fs::File::create("output.txt").unwrap());
56+
57+
let sorter: ExternalSorter<u32, io::Error, LimitedBufferBuilder, CustomExternalChunk> =
58+
ExternalSorterBuilder::new()
59+
.with_tmp_dir(path::Path::new("./"))
60+
.with_buffer(LimitedBufferBuilder::new(1_000_000, true))
61+
.build()
62+
.unwrap();
63+
64+
let sorted = sorter
65+
.sort(input_reader.lines().map(|line| {
66+
let line = line.unwrap();
67+
let number = line.parse().unwrap();
68+
69+
return Ok(number);
70+
}))
71+
.unwrap();
72+
73+
for item in sorted.map(Result::unwrap) {
74+
output_writer.write_all(format!("{}\n", item).as_bytes()).unwrap();
75+
}
76+
output_writer.flush().unwrap();
77+
}

examples/custom_type.rs

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
use std::cmp::Ordering;
2+
use std::error::Error;
3+
use std::fmt::{Display, Formatter};
4+
use std::fs;
5+
use std::io::{self, prelude::*};
6+
use std::path;
7+
8+
use env_logger;
9+
use log;
10+
use serde;
11+
12+
use ext_sort::{ExternalSorter, ExternalSorterBuilder, LimitedBufferBuilder};
13+
14+
#[derive(Debug)]
15+
enum CsvParseError {
16+
RowError(String),
17+
ColumnError(String),
18+
}
19+
20+
impl Display for CsvParseError {
21+
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
22+
match self {
23+
CsvParseError::ColumnError(err) => write!(f, "column format error: {}", err),
24+
CsvParseError::RowError(err) => write!(f, "row format error: {}", err),
25+
}
26+
}
27+
}
28+
29+
impl Error for CsvParseError {}
30+
31+
#[derive(PartialEq, Eq, serde::Serialize, serde::Deserialize)]
32+
struct Person {
33+
name: String,
34+
surname: String,
35+
age: u8,
36+
}
37+
38+
impl Person {
39+
fn as_csv(&self) -> String {
40+
format!("{},{},{}", self.name, self.surname, self.age)
41+
}
42+
43+
fn from_str(s: &str) -> Result<Self, CsvParseError> {
44+
let parts: Vec<&str> = s.split(',').collect();
45+
if parts.len() != 3 {
46+
Err(CsvParseError::RowError("wrong columns number".to_string()))
47+
} else {
48+
Ok(Person {
49+
name: parts[0].to_string(),
50+
surname: parts[1].to_string(),
51+
age: parts[2]
52+
.parse()
53+
.map_err(|err| CsvParseError::ColumnError(format!("age field format error: {}", err)))?,
54+
})
55+
}
56+
}
57+
}
58+
59+
impl PartialOrd for Person {
60+
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
61+
Some(self.cmp(&other))
62+
}
63+
}
64+
65+
impl Ord for Person {
66+
fn cmp(&self, other: &Self) -> Ordering {
67+
self.surname
68+
.cmp(&other.surname)
69+
.then(self.name.cmp(&other.name))
70+
.then(self.age.cmp(&other.age))
71+
}
72+
}
73+
74+
fn main() {
75+
env_logger::Builder::new().filter_level(log::LevelFilter::Debug).init();
76+
77+
let input_reader = io::BufReader::new(fs::File::open("input.csv").unwrap());
78+
let mut output_writer = io::BufWriter::new(fs::File::create("output.csv").unwrap());
79+
80+
let sorter: ExternalSorter<Person, io::Error, LimitedBufferBuilder> = ExternalSorterBuilder::new()
81+
.with_tmp_dir(path::Path::new("./"))
82+
.with_buffer(LimitedBufferBuilder::new(1_000_000, true))
83+
.build()
84+
.unwrap();
85+
86+
let sorted = sorter
87+
.sort(
88+
input_reader
89+
.lines()
90+
.map(|line| line.map(|line| Person::from_str(&line).unwrap())),
91+
)
92+
.unwrap();
93+
94+
for item in sorted.map(Result::unwrap) {
95+
output_writer
96+
.write_all(format!("{}\n", item.as_csv()).as_bytes())
97+
.unwrap();
98+
}
99+
output_writer.flush().unwrap();
100+
}

0 commit comments

Comments
 (0)