Skip to content

Commit

Permalink
Require a DeferredWriter instead of impl Write in flussab-cnf
Browse files Browse the repository at this point in the history
This isn't really a restriction as you can build a DeferredWriter from
any impl Write. The upside is that this generates less code than generic
functions and allows us to do future optimizations that would not work
with arbitrary `Write` implementations.
  • Loading branch information
jix committed Dec 23, 2021
1 parent 7e758dd commit 0486834
Show file tree
Hide file tree
Showing 6 changed files with 42 additions and 44 deletions.
4 changes: 2 additions & 2 deletions flussab-cnf/examples/roundtrip_cnf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,11 @@ fn main_err() -> Result<(), ParseError> {
let mut cnf_writer = DeferredWriter::from_write(stdout.lock());

if let Some(header) = cnf_reader.header() {
cnf::write_header(&mut cnf_writer, header)?;
cnf::write_header(&mut cnf_writer, header);
}

while let Some(lits) = cnf_reader.next_clause()? {
cnf::write_clause(&mut cnf_writer, lits)?;
cnf::write_clause(&mut cnf_writer, lits);
}

cnf_writer.flush()?;
Expand Down
4 changes: 2 additions & 2 deletions flussab-cnf/examples/roundtrip_gcnf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,11 @@ fn main_err() -> Result<(), ParseError> {
let mut gcnf_writer = DeferredWriter::from_write(stdout.lock());

if let Some(header) = gcnf_reader.header() {
gcnf::write_header(&mut gcnf_writer, header)?;
gcnf::write_header(&mut gcnf_writer, header);
}

while let Some((group, lits)) = gcnf_reader.next_clause()? {
gcnf::write_clause(&mut gcnf_writer, group, lits)?;
gcnf::write_clause(&mut gcnf_writer, group, lits);
}

gcnf_writer.flush()?;
Expand Down
4 changes: 2 additions & 2 deletions flussab-cnf/examples/roundtrip_wcnf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,11 @@ fn main_err() -> Result<(), ParseError> {
let mut wcnf_writer = DeferredWriter::from_write(stdout.lock());

if let Some(header) = wcnf_reader.header() {
wcnf::write_header(&mut wcnf_writer, header)?;
wcnf::write_header(&mut wcnf_writer, header);
}

while let Some((weight, lits)) = wcnf_reader.next_clause()? {
wcnf::write_clause(&mut wcnf_writer, weight, lits)?;
wcnf::write_clause(&mut wcnf_writer, weight, lits);
}

wcnf_writer.flush()?;
Expand Down
26 changes: 16 additions & 10 deletions flussab-cnf/src/cnf.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//! Parsing and writing of the DIMACS CNF file format.
use std::io::{self, BufReader, Read, Write};

use flussab::{text::LineReader, DeferredReader};
use flussab::{text::LineReader, DeferredReader, DeferredWriter};

use crate::{error::ParseError, token, Dimacs};

Expand Down Expand Up @@ -212,17 +212,17 @@ where
}

/// Writes a DIMACS CNF header.
pub fn write_header(writer: &mut impl Write, header: Header) -> io::Result<()> {
writeln!(writer, "p cnf {} {}", header.var_count, header.clause_count)
pub fn write_header(writer: &mut DeferredWriter, header: Header) {
let _ = writeln!(writer, "p cnf {} {}", header.var_count, header.clause_count);
}

/// Writes a clause.
pub fn write_clause<L: Dimacs>(writer: &mut impl Write, clause_lits: &[L]) -> io::Result<()> {
pub fn write_clause<L: Dimacs>(writer: &mut DeferredWriter, clause_lits: &[L]) {
for lit in clause_lits {
itoa::write(&mut *writer, lit.dimacs())?;
writer.write_all(b" ")?;
let _ = itoa::write(&mut *writer, lit.dimacs());
writer.write_all_defer_err(b" ");
}
writer.write_all(b"0\n")
writer.write_all_defer_err(b"0\n")
}

#[cfg(test)]
Expand Down Expand Up @@ -570,10 +570,16 @@ mod tests {
let mut output = vec![];
let mut parser = Parser::<i32>::from_read(input.as_bytes(), true)?;

write_header(&mut output, parser.header().unwrap())?;
{
let mut writer = DeferredWriter::from_write(&mut output);

while let Some(clause) = parser.next_clause()? {
write_clause(&mut output, clause)?;
write_header(&mut writer, parser.header().unwrap());

while let Some(clause) = parser.next_clause()? {
write_clause(&mut writer, clause);
}

writer.flush()?;
}

assert_eq!(input.as_bytes(), output);
Expand Down
26 changes: 11 additions & 15 deletions flussab-cnf/src/gcnf.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//! Parsing and writing of the GCNF file format for group oriented CNF formulas.
use std::io::{self, BufReader, Read, Write};

use flussab::{text::LineReader, DeferredReader};
use flussab::{text::LineReader, DeferredReader, DeferredWriter};

use crate::{error::ParseError, token, Dimacs};

Expand Down Expand Up @@ -241,26 +241,22 @@ where
}

/// Writes a GCNF header.
pub fn write_header(writer: &mut impl Write, header: Header) -> io::Result<()> {
writeln!(
pub fn write_header(writer: &mut DeferredWriter, header: Header) {
let _ = writeln!(
writer,
"p gcnf {} {} {}",
header.var_count, header.clause_count, header.group_count
)
);
}

/// Writes a clause belonging to a group.
pub fn write_clause<L: Dimacs>(
writer: &mut impl Write,
group: usize,
clause_lits: &[L],
) -> io::Result<()> {
writer.write_all(b"{")?;
itoa::write(&mut *writer, group)?;
writer.write_all(b"} ")?;
pub fn write_clause<L: Dimacs>(writer: &mut DeferredWriter, group: usize, clause_lits: &[L]) {
writer.write_all_defer_err(b"{");
let _ = itoa::write(&mut *writer, group);
writer.write_all_defer_err(b"} ");
for lit in clause_lits {
itoa::write(&mut *writer, lit.dimacs())?;
writer.write_all(b" ")?;
let _ = itoa::write(&mut *writer, lit.dimacs());
writer.write_all_defer_err(b" ");
}
writer.write_all(b"0\n")
writer.write_all_defer_err(b"0\n");
}
22 changes: 9 additions & 13 deletions flussab-cnf/src/wcnf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
//! Also known as WDIMACS.
use std::io::{self, BufReader, Read, Write};

use flussab::{text::LineReader, DeferredReader};
use flussab::{text::LineReader, DeferredReader, DeferredWriter};

use crate::{error::ParseError, token, Dimacs};

Expand Down Expand Up @@ -233,24 +233,20 @@ where
}

/// Writes a WCNF header.
pub fn write_header(writer: &mut impl Write, header: Header) -> io::Result<()> {
writeln!(
pub fn write_header(writer: &mut DeferredWriter, header: Header) {
let _ = writeln!(
writer,
"p wcnf {} {} {}",
header.var_count, header.clause_count, header.top_weight
)
);
}

/// Writes a weighted clause.
pub fn write_clause<L: Dimacs>(
writer: &mut impl Write,
weight: u64,
clause_lits: &[L],
) -> io::Result<()> {
itoa::write(&mut *writer, weight)?;
pub fn write_clause<L: Dimacs>(writer: &mut DeferredWriter, weight: u64, clause_lits: &[L]) {
let _ = itoa::write(&mut *writer, weight);
for lit in clause_lits {
writer.write_all(b" ")?;
itoa::write(&mut *writer, lit.dimacs())?;
writer.write_all_defer_err(b" ");
let _ = itoa::write(&mut *writer, lit.dimacs());
}
writer.write_all(b" 0\n")
writer.write_all_defer_err(b" 0\n");
}

0 comments on commit 0486834

Please sign in to comment.