From 9fd657d82b99d215600e42cc8a07b9d88ec2b64f Mon Sep 17 00:00:00 2001 From: Ian Jackson Date: Mon, 2 May 2022 11:31:43 +0100 Subject: [PATCH] svg size handling: Rename and move svg_parse_size Signed-off-by: Ian Jackson --- src/prelude.rs | 3 +++ src/shapelib.rs | 45 +-------------------------------------------- src/spec.rs | 3 ++- src/utils.rs | 44 ++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 50 insertions(+), 45 deletions(-) diff --git a/src/prelude.rs b/src/prelude.rs index 661c03a0..71f18b09 100644 --- a/src/prelude.rs +++ b/src/prelude.rs @@ -244,3 +244,6 @@ pub type PUO = PieceUpdateOp; pub type PUOs = PieceUpdateOps; pub type WRC = WhatResponseToClientOp; #[allow(non_camel_case_types)] pub type PUE_P = PreparedUpdateEntry_Piece; + +// utils.rs +pub use SVGSizeError as SvSE; diff --git a/src/shapelib.rs b/src/shapelib.rs index 9d555418..e10185d1 100644 --- a/src/shapelib.rs +++ b/src/shapelib.rs @@ -520,15 +520,6 @@ impl ItemSpec { } } -#[derive(Error,Clone,Serialize,Deserialize,Debug)] -pub enum SVGSizeError { - #[error("parse error: {0}")] ParseError(String), - #[error("attribute {0} repeated")] AttributeRepeated(String), - #[error("attribute {0} unparseable")] AttributeUnparseable(String), - #[error("specifies only one of width and height")] OneOfWidthHeight, -} -use SVGSizeError as SvSE; - impl Contents { #[throws(SpecError)] fn load_svg(&self, item_name: &SvgBaseName, @@ -547,41 +538,7 @@ impl Contents { SpE::InternalError(m.to_string()) })?; - #[throws(SVGSizeError)] - fn get_width_height(xml: &str) -> Option> { - use xmlparser::Token as Tk; - let mut in_svg_element = false; - let mut wh = [None; 2]; - for token in xmlparser::Tokenizer::from(xml) { - match token.map_err(|e| SvSE::ParseError(e.to_string()))? { - Tk::ElementStart{ local, .. } => { - in_svg_element = local.eq_ignore_ascii_case("svg"); - }, - Tk::ElementEnd{..} => { - if in_svg_element { return None } - }, - Tk::Attribute { local, value, .. } if in_svg_element => { - let i = - if local.eq_ignore_ascii_case("width" ) { 0 } else - if local.eq_ignore_ascii_case("height") { 1 } else { continue }; - if wh[i].is_some() { - throw!(SvSE::AttributeRepeated(local.to_string())) - } - let v: f64 = value.parse().map_err( - |_| SvSE::AttributeUnparseable(local.to_string()) - )?; - wh[i] = Some(v); - if wh.iter().all(Option::is_some) { break } - }, - _ => { }, - } - } - Some(PosC::try_from_iter_2( - wh.into_iter().map(|v| v.ok_or_else(|| SvSE::OneOfWidthHeight)) - )?) - } - - let _ = get_width_height(&svg_data).map_err(|error| SpE::SVGError { + let _ = svg_parse_size(&svg_data).map_err(|error| SpE::SVGError { error, item_name: item_name.as_str().into(), item_for_lib: lib_name_for.into(), diff --git a/src/spec.rs b/src/spec.rs index f79f8efd..9140795e 100644 --- a/src/spec.rs +++ b/src/spec.rs @@ -30,6 +30,7 @@ use crate::accounts::AccountName; use crate::error::UnsupportedColourSpec; use crate::gamestate::PieceSpec; use crate::prelude::default; +use crate::utils::SVGSizeError; pub use imp::PlayerAccessSpec; @@ -96,7 +97,7 @@ pub enum SpecError { item_name: String, item_for_lib: String, item_for_item: String, - error: crate::shapelib::SVGSizeError, // TODO it needs to move + error: SVGSizeError, }, #[error("image for supposedly-occultable piece \ is not itself occultable but has multiple faces")] diff --git a/src/utils.rs b/src/utils.rs index bfa18cd2..90a0903d 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -212,6 +212,50 @@ impl Index for OldNew { fn index(&self, i: OldNewIndex) -> &T { &self.0[i as usize] } } +//========== obtaining size from xml ========== + +#[derive(Error,Clone,Serialize,Deserialize,Debug)] +pub enum SVGSizeError { + #[error("parse error: {0}")] ParseError(String), + #[error("attribute {0} repeated")] AttributeRepeated(String), + #[error("attribute {0} unparseable")] AttributeUnparseable(String), + #[error("specifies only one of width and height")] OneOfWidthHeight, +} + +#[throws(SVGSizeError)] +pub fn svg_parse_size(xml: &str) -> Option> { + use xmlparser::Token as Tk; + let mut in_svg_element = false; + let mut wh = [None; 2]; + for token in xmlparser::Tokenizer::from(xml) { + match token.map_err(|e| SvSE::ParseError(e.to_string()))? { + Tk::ElementStart{ local, .. } => { + in_svg_element = local.eq_ignore_ascii_case("svg"); + }, + Tk::ElementEnd{..} => { + if in_svg_element { return None } + }, + Tk::Attribute { local, value, .. } if in_svg_element => { + let i = + if local.eq_ignore_ascii_case("width" ) { 0 } else + if local.eq_ignore_ascii_case("height") { 1 } else { continue }; + if wh[i].is_some() { + throw!(SvSE::AttributeRepeated(local.to_string())) + } + let v: f64 = value.parse().map_err( + |_| SvSE::AttributeUnparseable(local.to_string()) + )?; + wh[i] = Some(v); + if wh.iter().all(Option::is_some) { break } + }, + _ => { }, + } + } + Some(PosC::try_from_iter_2( + wh.into_iter().map(|v| v.ok_or_else(|| SvSE::OneOfWidthHeight)) + )?) +} + //========== Thunk ========== // todo #[derive(Clone)] -- 2.30.2