mirror of
https://gitlab.cern.ch/wotsubo/endcap-sl-software-ri-generator.git
synced 2025-04-20 03:36:25 +09:00
127 lines
4 KiB
Rust
127 lines
4 KiB
Rust
use std::num;
|
|
|
|
use roxmltree::{Node, TextPos};
|
|
use thiserror::Error;
|
|
|
|
use crate::types::Module;
|
|
|
|
#[derive(Debug, Error)]
|
|
pub enum DomConversionError {
|
|
#[error("attribute {attr} not found in element: {start} - {end}", start = pos.0, end = pos.1)]
|
|
AttributeNotFound {
|
|
attr: &'static str,
|
|
pos: (TextPos, TextPos),
|
|
},
|
|
#[error("string conversion error: {start} - {end}", start = pos.0, end = pos.1)]
|
|
ParseIntError {
|
|
attr: &'static str,
|
|
pos: (TextPos, TextPos),
|
|
#[source]
|
|
source: num::ParseIntError,
|
|
},
|
|
#[error("string conversion error: {start} - {end}", start = pos.0, end = pos.1)]
|
|
ParsePrefixedU32Error {
|
|
attr: &'static str,
|
|
pos: (TextPos, TextPos),
|
|
#[source]
|
|
source: ParsePrefixedU32Error,
|
|
},
|
|
#[error("invalid dom structure: {0}")]
|
|
InvalidFormat(String),
|
|
}
|
|
|
|
impl DomConversionError {
|
|
fn attr_not_found(attr: &'static str, node: Node) -> Self {
|
|
let range = node.range();
|
|
let doc = node.document();
|
|
Self::AttributeNotFound {
|
|
attr,
|
|
pos: (doc.text_pos_at(range.start), doc.text_pos_at(range.end)),
|
|
}
|
|
}
|
|
|
|
fn parse_int_error(e: num::ParseIntError, attr: &'static str, node: Node) -> Self {
|
|
let range = node.range();
|
|
let doc = node.document();
|
|
Self::ParseIntError {
|
|
attr,
|
|
pos: (doc.text_pos_at(range.start), doc.text_pos_at(range.end)),
|
|
source: e,
|
|
}
|
|
}
|
|
|
|
fn parse_prefixed_u32_error(e: ParsePrefixedU32Error, attr: &'static str, node: Node) -> Self {
|
|
let range = node.range();
|
|
let doc = node.document();
|
|
Self::ParsePrefixedU32Error {
|
|
attr,
|
|
pos: (doc.text_pos_at(range.start), doc.text_pos_at(range.end)),
|
|
source: e,
|
|
}
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, Error)]
|
|
pub enum ParsePrefixedU32Error {
|
|
#[error("invalid prefix: found {found}")]
|
|
InvalidPrefix { found: char },
|
|
#[error("parse int error")]
|
|
ParseIntError(#[from] num::ParseIntError),
|
|
}
|
|
|
|
trait ParsePrefixedU32 {
|
|
fn parse_prefixed_u32(&self) -> Result<u32, ParsePrefixedU32Error>;
|
|
}
|
|
|
|
impl ParsePrefixedU32 for &str {
|
|
fn parse_prefixed_u32(&self) -> Result<u32, ParsePrefixedU32Error> {
|
|
let radix = match self.chars().nth(1) {
|
|
Some('x') => 16,
|
|
Some(c) if c.is_numeric() => 10,
|
|
Some(c) => return Err(ParsePrefixedU32Error::InvalidPrefix { found: c }),
|
|
None => return Err(ParsePrefixedU32Error::InvalidPrefix { found: ' ' }),
|
|
};
|
|
|
|
match radix {
|
|
10 => Ok(self.parse()?),
|
|
radix => Ok(u32::from_str_radix(&self[2..], radix)?),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Module {
|
|
pub fn from_xml_dom(root: Node) -> Result<Self, DomConversionError> {
|
|
assert!(root.parent().unwrap().is_root());
|
|
assert_eq!(root.tag_name().name(), "module");
|
|
|
|
let name = root.tag_name().name();
|
|
println!("{}", name);
|
|
|
|
let name = match root.attribute("name") {
|
|
Some(name) => name.to_string(),
|
|
None => return Err(DomConversionError::attr_not_found("name", root)),
|
|
};
|
|
let addr = match root.attribute("addr") {
|
|
Some(addr) => addr
|
|
.parse_prefixed_u32()
|
|
.map_err(|e| DomConversionError::parse_prefixed_u32_error(e, "addr", root))?,
|
|
None => return Err(DomConversionError::attr_not_found("addr", root)),
|
|
};
|
|
let size = match root.attribute("size") {
|
|
Some(addr) => addr
|
|
.parse_prefixed_u32()
|
|
.map_err(|e| DomConversionError::parse_prefixed_u32_error(e, "size", root))?,
|
|
None => return Err(DomConversionError::attr_not_found("size", root)),
|
|
};
|
|
Ok(Self {
|
|
name,
|
|
addr,
|
|
size,
|
|
amod: todo!(),
|
|
r#type: todo!(),
|
|
desc: todo!(),
|
|
elements_bitstring: todo!(),
|
|
elements_other: todo!(),
|
|
})
|
|
}
|
|
}
|