| 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(())}
 |