Skip to content

Commit 8773a0f

Browse files
authored
Merge pull request #7 from mwln/examples-lib
update `puz.md` and improve some code logic.
2 parents af05e91 + 1fdb2a6 commit 8773a0f

File tree

7 files changed

+185
-288
lines changed

7 files changed

+185
-288
lines changed

Cargo.lock

+2-3
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

+7-4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
2-
name = "puz"
3-
version = "0.1.0"
2+
name = "puz_rs"
3+
version = "0.1.2"
44
edition = "2021"
55

66
[lib]
@@ -10,7 +10,10 @@ crate-type = ["cdylib", "rlib"]
1010
wasm-bindgen-futures = "0.4.37"
1111
wasm-bindgen = "0.2.87"
1212
gloo-file = {version = "0.3.0", features = ['futures'] }
13-
js-sys = "0.3.64"
14-
web-sys = { version = "0.3.64", features = ['File', 'FileReader', 'Blob', 'console'] }
13+
web-sys = { version = "0.3.64", features = ['File'] }
1514
byteorder = "1.4.3"
1615
serde_json = "1.0.107"
16+
17+
[profile.release]
18+
lto = true
19+
opt-level = 's'

examples/data/misc.puz

2.84 KB
Binary file not shown.

examples/data/misc1.puz

2.55 KB
Binary file not shown.

examples/read-with-file.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use puz::parse_puz;
1+
use puz_rs::parse_puz;
22
use std::{
33
fs::File,
44
io::{ErrorKind, Write},

puz.md

+98-200
Large diffs are not rendered by default.

src/lib.rs

+77-80
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,8 @@ enum ExtraKind {
1515
GEXT,
1616
}
1717

18-
#[derive(Debug)]
19-
enum BoardKind {
20-
Blank,
21-
Solution,
22-
}
18+
const FREE_SQUARE: char = '-';
19+
const TAKEN_SQUARE: char = '.';
2320

2421
const EXTRAS: [(&str, ExtraKind); 3] = [
2522
("GRBS", ExtraKind::GRBS),
@@ -28,13 +25,13 @@ const EXTRAS: [(&str, ExtraKind); 3] = [
2825
];
2926

3027
#[wasm_bindgen]
31-
pub async fn read_file(file: web_sys::File) -> JsValue {
28+
pub async fn read_file(file: web_sys::File) -> String {
3229
let data = gloo_file::futures::read_as_bytes(&file.into())
3330
.await
3431
.expect_throw("Error while reading the file");
3532
return match parse_puz(data.as_slice()) {
36-
Ok(parsed) => JsValue::from_str(&parsed.to_string()),
37-
Err(e) => JsValue::from_str(&e.to_string()),
33+
Ok(parsed) => parsed.to_string(),
34+
Err(e) => e.to_string(),
3835
};
3936
}
4037

@@ -57,61 +54,55 @@ pub fn parse_puz(buffer: impl Read) -> std::io::Result<Value> {
5754
(0x02, None, "unknown_bitmask"),
5855
(0x02, None, "scrambled_tag"),
5956
];
60-
let mut header_data: Vec<(&str, String)> = vec![];
61-
for (offset, conversion, label) in header_offsets.iter() {
57+
58+
let mut header_data: Vec<usize> = vec![];
59+
for (offset, conversion, _) in header_offsets.iter() {
6260
let mut buffer = vec![0; *offset];
6361
reader.read_exact(&mut buffer)?;
6462
if let Some(c_type) = conversion {
6563
match c_type {
66-
PieceKind::Natural => header_data.push((label, buffer[0].to_string())),
67-
PieceKind::Number => {
68-
header_data.push((label, LittleEndian::read_u16(&buffer).to_string()))
69-
}
64+
PieceKind::Natural => header_data.push(buffer[0] as usize),
65+
PieceKind::Number => header_data.push(LittleEndian::read_u16(&buffer) as usize),
7066
}
7167
}
7268
}
7369

74-
let width = header_data[0]
75-
.1
76-
.parse::<usize>()
77-
.expect("Width was unable to be converted to a number.");
78-
let height = header_data[1]
79-
.1
80-
.parse::<usize>()
81-
.expect("Height was unable to be converted to a number.");
70+
let width = header_data[0];
71+
let height = header_data[1];
8272
let board_size = width * height;
8373

84-
let mut board_data: Vec<(&BoardKind, String)> = vec![];
85-
let boards = vec![BoardKind::Solution, BoardKind::Blank];
86-
for board in boards.iter() {
74+
let mut boards = Vec::new();
75+
// [solution, blank]
76+
for _ in 0..2 {
8777
let mut buffer = vec![0; board_size];
8878
reader.read_exact(&mut buffer)?;
8979
if let Ok(s) = std::str::from_utf8(&buffer) {
90-
board_data.push((board, s.to_owned()));
91-
} else {
92-
println!("Board (type: {:?}) could not read from the buffer.", board);
80+
boards.push(
81+
s.chars()
82+
.collect::<Vec<char>>()
83+
.chunks(width)
84+
.map(|chunk| chunk.iter().collect::<String>())
85+
.collect::<Vec<String>>(),
86+
)
9387
}
9488
}
9589

96-
let mut info_data: Vec<(&str, String)> = vec![];
97-
let info_items = vec!["title", "author", "copyright"];
98-
for item in info_items.iter() {
99-
info_data.push((item, read_string_till_nul(&mut reader)));
90+
// [title, author, copyright, note]
91+
let mut info_data = Vec::new();
92+
for _ in 0..3 {
93+
info_data.push(read_string_till_nul(&mut reader));
10094
}
10195

102-
let num_clues = header_data[2]
103-
.1
104-
.parse::<usize>()
105-
.expect("Cannot parse number of clues as a number.");
96+
let num_clues = header_data[2];
10697
let mut clue_data: Vec<String> = vec![];
10798
for _ in 1..=num_clues {
10899
clue_data.push(read_string_till_nul(&mut reader))
109100
}
110101

111-
// add in the note that's at the end of the clues
112-
info_data.push(("note", read_string_till_nul(&mut reader)));
102+
// add note after clues
103+
info_data.push(read_string_till_nul(&mut reader));
113104

114-
let mut extras_data: Vec<u8> = Vec::new();
105+
let mut extras_data = Vec::new();
115106
reader.read_to_end(&mut extras_data)?;
116107

117108
let mut grbs = Vec::new();
@@ -155,64 +146,34 @@ pub fn parse_puz(buffer: impl Read) -> std::io::Result<Value> {
155146
}
156147
}
157148

158-
let mut empty: Vec<String> = Vec::new();
159-
let mut solution: Vec<String> = Vec::new();
160149
let mut clues: Vec<Vec<Vec<String>>> =
161150
vec![vec![vec![String::new(), String::new()]; width]; height];
162151

163-
for (kind, data) in board_data.iter() {
164-
let mut board_rows = data
165-
.chars()
166-
.collect::<Vec<char>>()
167-
.chunks(15)
168-
.map(|chunk| chunk.iter().collect::<String>())
169-
.collect::<Vec<String>>();
170-
171-
match kind {
172-
BoardKind::Blank => empty.append(&mut board_rows),
173-
BoardKind::Solution => solution.append(&mut board_rows),
174-
}
175-
}
176-
177152
for (row, cols) in clues.iter_mut().enumerate() {
178153
for (col, clue_tuple) in cols.iter_mut().enumerate() {
179-
if let Some(current_tile) = empty[row].chars().nth(col) {
180-
if current_tile != '.' {
181-
if row == 0 {
182-
clue_tuple[0] = clue_data.remove(0);
183-
} else {
184-
if let Some(square) = empty[row - 1].chars().nth(col) {
185-
if square == '.' {
186-
clue_tuple[0] = clue_data.remove(0);
187-
}
188-
}
189-
}
190-
if col == 0 {
191-
clue_tuple[1] = clue_data.remove(0);
192-
} else {
193-
if let Some(square) = empty[row].chars().nth(col - 1) {
194-
if square == '.' {
195-
clue_tuple[1] = clue_data.remove(0);
196-
}
197-
}
198-
}
199-
}
154+
if cell_needs_across_clue(&boards[1], row, col) {
155+
clue_tuple[0] = clue_data.remove(0);
156+
}
157+
if cell_needs_down_clue(&boards[1], row, col) {
158+
clue_tuple[1] = clue_data.remove(0);
200159
}
201160
}
202161
}
203162

204163
let puz = json!({
205164
"info": {
206-
"title": info_data[0].1,
207-
"author": info_data[1].1,
165+
"title": info_data[0],
166+
"author": info_data[1],
167+
"copyright": info_data[2],
168+
"note": info_data[3],
208169
},
209170
"size": {
210171
"width": width,
211172
"height": height,
212173
},
213174
"boards": {
214-
"blank": empty,
215-
"solution": solution,
175+
"blank": boards[1],
176+
"solution": boards[0],
216177
},
217178
"clues": clues,
218179
"extras": {
@@ -225,6 +186,42 @@ pub fn parse_puz(buffer: impl Read) -> std::io::Result<Value> {
225186
Ok(puz)
226187
}
227188

189+
fn cell_needs_across_clue(board: &Vec<String>, row: usize, col: usize) -> bool {
190+
if let Some(this_square) = &board[row].chars().nth(col) {
191+
if this_square == &FREE_SQUARE {
192+
if let Some(next_square) = &board[row].chars().nth(col + 1) {
193+
if next_square == &FREE_SQUARE {
194+
if col == 0 {
195+
return true;
196+
} else if let Some(previous_square) = &board[row].chars().nth(col - 1) {
197+
return previous_square == &TAKEN_SQUARE;
198+
}
199+
}
200+
}
201+
}
202+
}
203+
false
204+
}
205+
206+
fn cell_needs_down_clue(board: &Vec<String>, row: usize, col: usize) -> bool {
207+
if let Some(this_square) = &board[row].chars().nth(col) {
208+
if this_square == &FREE_SQUARE {
209+
if let Some(next_row) = board.get(row + 1) {
210+
if let Some(next_square) = &next_row.chars().nth(col) {
211+
if next_square == &FREE_SQUARE {
212+
if row == 0 {
213+
return true;
214+
} else if let Some(previous_square) = &board[row - 1].chars().nth(col) {
215+
return previous_square == &TAKEN_SQUARE;
216+
}
217+
}
218+
}
219+
}
220+
}
221+
}
222+
false
223+
}
224+
228225
fn read_string_till_nul(reader: &mut BufReader<impl Read>) -> String {
229226
let mut text = String::new();
230227
loop {

0 commit comments

Comments
 (0)