wip(converter): until Block converter (next: Register)

This commit is contained in:
Wataru Otsubo 2025-01-30 15:33:05 +09:00
parent a8071b359d
commit 8fee555860
5 changed files with 310 additions and 28 deletions

View file

@ -1,12 +1,15 @@
//! Convert DOM to register interface, complementing optional parameters.
use std::num;
use std::{num, str};
use roxmltree::{Node, TextPos};
use thiserror::Error;
use crate::parser::{ParseEnumError, ParsePrefixedU32, ParsePrefixedU32Error};
use crate::types::Module;
use crate::types::{
BitString, Block, DataType, Field, Fifo, Memory, Module, ModuleBlockElements, MultipleParams,
Register, Value,
};
#[derive(Debug, Error, PartialEq)]
pub enum DomConversionError {
@ -36,8 +39,13 @@ pub enum DomConversionError {
#[source]
source: ParseEnumError,
},
#[error("invalid dom structure: {0}")]
InvalidFormat(String),
#[error("invalid node {found}: {start} - {end}", start = pos.0, end = pos.1)]
InvalidNode {
pos: (TextPos, TextPos),
found: String,
},
#[error("other dom conversion error: {0}")]
OtherError(String),
}
impl DomConversionError {
@ -79,48 +87,278 @@ impl DomConversionError {
source: e,
}
}
fn invalid_node(found: String, node: Node) -> Self {
let range = node.range();
let doc = node.document();
Self::InvalidNode {
pos: (doc.text_pos_at(range.start), doc.text_pos_at(range.end)),
found,
}
}
}
mod util {
use roxmltree::Node;
use crate::types::{DataType, RwSpecifier};
use super::DomConversionError;
pub(crate) fn get_name(node: Node) -> Result<String, DomConversionError> {
match node.attribute("name") {
Some(name) => Ok(name.to_string()),
None => Err(DomConversionError::attr_not_found("name", node)),
}
}
pub(crate) fn get_type(node: Node) -> Option<Result<DataType, DomConversionError>> {
node.attribute("type").map(|x| {
x.parse()
.map_err(|e| DomConversionError::parse_enum_error(e, "type", node))
})
}
pub(crate) fn get_modf(node: Node) -> Option<Result<RwSpecifier, DomConversionError>> {
node.attribute("modf").map(|x| {
x.parse()
.map_err(|e| DomConversionError::parse_enum_error(e, "modf", node))
})
}
}
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");
pub fn from_xml_dom(node: Node) -> Result<Self, DomConversionError> {
assert!(node.parent().unwrap().is_root());
assert_eq!(node.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") {
let name = util::get_name(node)?;
let addr = match node.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)),
.map_err(|e| DomConversionError::parse_prefixed_u32_error(e, "addr", node))?,
None => return Err(DomConversionError::attr_not_found("addr", node)),
};
let size = match root.attribute("size") {
let size = match node.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)),
.map_err(|e| DomConversionError::parse_prefixed_u32_error(e, "size", node))?,
None => return Err(DomConversionError::attr_not_found("size", node)),
};
let amod = root
let amod = node
.attribute("amod")
.map(|amod| {
amod.parse()
.map_err(|e| DomConversionError::parse_enum_error(e, "amod", root))
.map_err(|e| DomConversionError::parse_enum_error(e, "amod", node))
})
.transpose()?;
let r#type = util::get_type(node).transpose()?;
let child_bitstrings = node
.children()
.filter(|node| node.is_element())
.filter(|node| node.tag_name().name().eq("bitstring"))
.map(|node| BitString::from_xml_dom(node))
.collect::<Result<_, _>>()?;
let child_other = node
.children()
.filter(|node| node.is_element())
.map(|node| ModuleBlockElements::from_xml_dom(node))
.collect::<Result<_, _>>()?;
Ok(Self {
name,
addr,
size,
amod,
r#type: todo!(),
desc: todo!(),
elements_bitstring: todo!(),
elements_other: todo!(),
r#type,
desc: node.attribute("desc").map(str::to_string),
elements_bitstring: child_bitstrings,
elements_other: child_other,
})
}
}
impl ModuleBlockElements {
pub(crate) fn from_xml_dom(node: Node) -> Result<Self, DomConversionError> {
match node.tag_name().name() {
"block" => Ok(Self::Block(Block::from_xml_dom(node)?)),
"register" => Ok(Self::Register(Register::from_xml_dom(node)?)),
"memory" => Ok(Self::Memory(Memory::from_xml_dom(node)?)),
"fifo" => Ok(Self::Fifo(Fifo::from_xml_dom(node)?)),
s => Err(DomConversionError::invalid_node(s.to_string(), node)),
}
}
}
impl BitString {
pub(crate) fn from_xml_dom(node: Node) -> Result<Self, DomConversionError> {
let name = util::get_name(node)?;
let size = node
.attribute("size")
.map(|addr| {
addr.parse_prefixed_u32()
.map_err(|e| DomConversionError::parse_prefixed_u32_error(e, "size", node))
})
.transpose()?;
let mask = node
.attribute("mask")
.map(|addr| {
addr.parse_prefixed_u32()
.map_err(|e| DomConversionError::parse_prefixed_u32_error(e, "mask", node))
})
.transpose()?;
let modf = node
.attribute("modf")
.map(|addr| {
addr.parse()
.map_err(|e| DomConversionError::parse_enum_error(e, "modf", node))
})
.transpose()?;
let children = node
.children()
.filter(|node| node.is_element() && node.tag_name().name().eq("field"))
.map(|node| Field::from_xml_dom(node))
.collect::<Result<_, _>>()?;
Ok(Self {
name,
size,
mask,
modf,
desc: node.attribute("desc").map(str::to_string),
elements_field: children,
})
}
}
impl Block {
pub(crate) fn from_xml_dom(node: Node) -> Result<Self, DomConversionError> {
let name = util::get_name(node)?;
let addr = match node.attribute("addr") {
Some(addr) => addr
.parse_prefixed_u32()
.map_err(|e| DomConversionError::parse_prefixed_u32_error(e, "addr", node))?,
None => {
// derive from parent
todo!("need to confirm")
}
};
let r#type = match util::get_type(node).transpose()? {
Some(x) => Some(x),
None => node
.ancestors()
.filter_map(util::get_type)
.next()
.transpose()?,
};
let modf = match util::get_modf(node).transpose()? {
Some(x) => Some(x),
None => node
.ancestors()
.filter_map(util::get_modf)
.next()
.transpose()?,
};
let multiple = MultipleParams::from_xml_dom(node)?;
let decoder = match node.attribute("decoder") {
Some(s) => s.to_string(),
None => match node
.ancestors()
.filter_map(|node| node.attribute("decoder"))
.next()
{
Some(s) => Ok(s.to_string()),
None => Err(DomConversionError::OtherError(
"decoder format is not yet fixed".to_string(),
)),
}?,
};
let size = match node.attribute("size") {
Some(addr) => addr
.parse_prefixed_u32()
.map_err(|e| DomConversionError::parse_prefixed_u32_error(e, "size", node))?,
None => return Err(DomConversionError::attr_not_found("size", node)),
};
let desc = node.attribute("desc").map(str::to_string);
let children = node
.children()
.filter(|node| node.is_element())
.map(|node| ModuleBlockElements::from_xml_dom(node))
.collect::<Result<_, _>>()?;
Ok(Block {
name,
addr,
r#type,
modf,
multiple,
decoder,
size,
desc,
elements: children,
})
}
}
impl Register {
pub(crate) fn from_xml_dom(node: Node) -> Result<Self, DomConversionError> {
todo!("do here next")
}
}
impl Memory {
pub(crate) fn from_xml_dom(node: Node) -> Result<Self, DomConversionError> {
todo!()
}
}
impl Fifo {
pub(crate) fn from_xml_dom(node: Node) -> Result<Self, DomConversionError> {
todo!()
}
}
impl Field {
pub(crate) fn from_xml_dom(node: Node) -> Result<Self, DomConversionError> {
todo!()
}
}
impl Value {
pub(crate) fn from_xml_dom(node: Node) -> Result<Self, DomConversionError> {
todo!()
}
}
impl MultipleParams {
pub(crate) fn from_xml_dom(node: Node) -> Result<Option<Self>, DomConversionError> {
let multiple = match node
.attribute("multiple")
.map(|x| {
x.parse_prefixed_u32()
.map_err(|e| DomConversionError::parse_prefixed_u32_error(e, "multiple", node))
})
.transpose()?
{
Some(x) => x,
None => return Ok(None),
};
let offset = match node
.attribute("offset")
.map(|x| {
x.parse_prefixed_u32()
.map_err(|e| DomConversionError::parse_prefixed_u32_error(e, "offset", node))
})
.transpose()?
{
Some(x) => x,
None => return Ok(None),
};
Ok(Some(MultipleParams { multiple, offset }))
}
}

View file

@ -1,3 +1,5 @@
//! Root document [`types::Module::from_xml_dom`]
pub mod types;
pub mod parser;
pub mod converter;

View file

@ -18,6 +18,8 @@ fn main() {
{
let root = doc.root_element();
println!("tag: {:?}", root.tag_name());
let root_childs = root.children().filter(|node| node.is_element());
println!("children: {:?}", root_childs);
}
let register_map = types::Module::from_xml_dom(doc.root_element()).unwrap();

View file

@ -109,3 +109,43 @@ mod parse_amodvalues {
}
}
}
mod parse_datatype {
use std::str::FromStr;
use crate::types::DataType;
use super::ParseEnumError;
impl FromStr for DataType {
type Err = ParseEnumError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"D32" => Ok(Self::D32),
s => Err(ParseEnumError::invalid_variant::<Self>(s.to_string())),
}
}
}
}
mod parse_rw_specifier {
use std::str::FromStr;
use crate::types::RwSpecifier;
use super::ParseEnumError;
impl FromStr for RwSpecifier {
type Err = ParseEnumError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"R" => Ok(Self::R),
"W" => Ok(Self::W),
"RW" => Ok(Self::RW),
s => Err(ParseEnumError::invalid_variant::<Self>(s.to_string())),
}
}
}
}

View file

@ -34,9 +34,9 @@ pub struct Block {
/// Fill this with proper calc.
pub addr: u32,
/// Fill this with proper calc.
pub r#type: DataType,
pub r#type: Option<DataType>,
/// Fill this with proper calc.
pub modf: RwSpecifier,
pub modf: Option<RwSpecifier>,
// TODO: should this be expanded?
pub multiple: Option<MultipleParams>,
// TODO