123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157 |
- // Read a Ksudoku's XML save file.
- use std::collections::HashMap;
- use std::error;
- use std::fmt;
- use std::fs::File;
- use std::io::BufReader;
- use xml::reader::{EventReader, XmlEvent};
- use xml::writer::XmlEvent as WrXmlEvent;
- use xml::EmitterConfig;
- #[derive(Debug, Clone)]
- struct UnsupportedGroup {
- message: String,
- }
- impl fmt::Display for UnsupportedGroup {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- write!(f, "Unsupported group: {}", self.message)
- }
- }
- impl error::Error for UnsupportedGroup {}
- pub fn load_ksudoku(filename: std::path::PathBuf) -> Result<String, Box<dyn error::Error>> {
- let fh = File::open(filename)?;
- let buffer = BufReader::new(fh);
- let parser = EventReader::new(buffer);
- // I'm interested in values and (maybe) solution
- let mut values: String = String::from("");
- let mut element_name: String = String::from("");
- for e in parser {
- match e {
- Ok(XmlEvent::StartElement {
- name, attributes, ..
- }) => {
- element_name = name.local_name.clone();
- if element_name == "graph" {
- // Check the attributes here
- // <graph specific-type="Plain" type="sudoku" order="9"/>
- // Verify these are correct / not some other puzzle type!
- // {"specific-type": "Plain", "type": "sudoku", "order": "9"}
- let mut attrs: HashMap<String, String> = HashMap::new();
- for a in attributes {
- attrs.insert(a.name.to_string(), a.value);
- }
- let blank = String::new();
- // Format in specific order here.
- let expected = format!(
- "{}-{}-{}",
- attrs.get(&"specific-type".to_string()).unwrap_or(&blank),
- attrs.get(&"type".to_string()).unwrap_or(&blank),
- attrs.get(&"order".to_string()).unwrap_or(&blank)
- );
-
- if expected != "Plain-sudoku-9" {
- // println!("Unknown ksudoku type! {}", expected);
- return Err(Box::new(UnsupportedGroup {
- message: format!("Unsupported Ksudoku game type: {}", expected),
- }));
- }
- println!("{:?}", attrs);
- }
- }
- Ok(XmlEvent::Characters(text)) => {
- if element_name == "values" {
- values = text.clone();
- }
- }
- Err(e) => {
- return Err(Box::new(e));
- }
- _ => {}
- }
- }
- Ok(values)
- }
- pub fn save_ksudoku(
- filename: std::path::PathBuf,
- puz: &String,
- sol: &String,
- ) -> Result<(), Box<dyn error::Error>> {
- let fh = File::create(filename)?;
- let mut writer = EmitterConfig::new().perform_indent(true).create_writer(fh);
- let mut event: WrXmlEvent = WrXmlEvent::start_element("ksudoku").into();
- writer.write(event)?;
- event = WrXmlEvent::start_element("game")
- .attr("had-help", "0")
- .attr("msecs-elapsed", "0")
- .into();
- writer.write(event)?;
- event = WrXmlEvent::start_element("puzzle").into();
- writer.write(event)?;
- event = WrXmlEvent::start_element("graph")
- .attr("specific-type", "Plain")
- .attr("type", "sudoku")
- .attr("order", "9")
- .into();
- writer.write(event)?;
- event = WrXmlEvent::end_element().into();
- writer.write(event)?;
- // values (puzzle)
- event = WrXmlEvent::start_element("values").into();
- writer.write(event)?;
- event = WrXmlEvent::characters(puz).into();
- writer.write(event)?;
- event = WrXmlEvent::end_element().into();
- writer.write(event)?;
- // solution
- event = WrXmlEvent::start_element("solution").into();
- writer.write(event)?;
- event = WrXmlEvent::characters(sol).into();
- writer.write(event)?;
- event = WrXmlEvent::end_element().into();
- writer.write(event)?;
- // Apparently, the events are consumed...
- event = WrXmlEvent::end_element().into();
- writer.write(event)?;
- event = WrXmlEvent::end_element().into();
- writer.write(event)?;
- event = WrXmlEvent::end_element().into();
- writer.write(event)?;
- /*
- let pStr: String = puzzle.save_to_tld(start_ch: 'b', blank: '_');
- let solStr: solution.save_to_tld(start_ch: 'b', blank: '_');
- let ksudoko = Ksudoku {
- game: Game {
- help: 0,
- elapsed: 0,
- puzzle: Puzzle {
- graph: Graph {
- order: 9,
- game_type: String::from("sudoku"),
- specific_type: String::from("Plain"),
- },
- values: puz.to_string(),
- solution: sol.to_string(),
- },
- },
- };
- let fh = File::create(filename)?;
- let _res = to_writer(fh, &ksudoko)?;
- */
- Ok(())
- }
|