diff --git a/Cargo.lock b/Cargo.lock index dff8e1c..c18c3b5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -88,7 +88,6 @@ dependencies = [ "heck", "itertools", "log", - "prettyplease", "proc-macro2", "quote", "roxmltree", @@ -164,16 +163,6 @@ version = "1.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" -[[package]] -name = "prettyplease" -version = "0.2.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6924ced06e1f7dfe3fa48d57b9f74f55d8915f5036121bef647ef4b204895fac" -dependencies = [ - "proc-macro2", - "syn", -] - [[package]] name = "proc-macro2" version = "1.0.93" diff --git a/Cargo.toml b/Cargo.toml index 6bd8bcc..755bd1c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,7 +17,6 @@ env_logger = "0.11.6" heck = "0.5" itertools = "0.14" log = "0.4" -prettyplease = "0.2" proc-macro2 = "1.0.93" quote = "1.0" roxmltree = "0.20" diff --git a/src/generator.rs b/src/generator.rs index a4c6d95..2ab6d5c 100644 --- a/src/generator.rs +++ b/src/generator.rs @@ -1,9 +1,9 @@ //! Generate register interface rust code from types in [`crate::types`]. //! -//! root: [`Module::generate_code`] +//! root: [`CodeGen`] //! -//! # For developers -//! Pass `--document-private-items` to see non-public items. +//! # TODO +//! add docs (especially fields and registers) use std::{ collections::HashMap, @@ -15,14 +15,13 @@ use crate::{ types::{Block, Module, ModuleBlockElements, Register}, }; use heck::{ToSnakeCase, ToUpperCamelCase}; -use itertools::Itertools; use quote::quote; use thiserror::Error; #[derive(Debug, Error)] pub enum CodeGenError { - #[error("tokenization(syn) error: {0}")] - SynError(#[from] syn::Error), + #[error("tokenization error: {0}")] + TokenizeError(#[from] syn::Error), #[error("failed to create file: {0}")] FilePathError(String), #[error("parent is required for {module}")] @@ -121,22 +120,7 @@ mod util { } } -impl Module { - pub fn generate_code(self) -> Result, CodeGenError> { - let files = self.generate_register_interface(None, None, HashMap::new())?; - Ok(files - .into_iter() - .map( - |(path, tokens)| -> Result<(PathBuf, syn::File), syn::Error> { - let file: syn::File = syn::parse2(tokens)?; - Ok((path, file)) - }, - ) - .process_results(|kv| HashMap::from_iter(kv))?) - } -} - -trait CodeGen { +pub trait CodeGen { /// `parent_name` in UpperCamelCase. fn generate_register_interface( self, diff --git a/src/io.rs b/src/io.rs deleted file mode 100644 index 2f345da..0000000 --- a/src/io.rs +++ /dev/null @@ -1,27 +0,0 @@ -//! File IO for generated codes. - -use std::{collections::HashMap, fs, io, path}; - -/// Write formatted codes generated with [`Module::generate_code`](crate::types::Module::generate_code). -pub fn write_to_files( - files: HashMap, - out_path: &path::Path, -) -> io::Result<()> { - if !out_path.is_dir() { - return Err(io::Error::from(io::ErrorKind::NotADirectory)); - } - if fs::read_dir(out_path)?.next().is_some() { - return Err(io::Error::new( - io::ErrorKind::AlreadyExists, - "out path is not empty", - )); - } - for (file_path, code) in files { - fs::DirBuilder::new() - .recursive(true) - .create(out_path.join(&file_path).parent().unwrap())?; - - fs::write(out_path.join(&file_path), prettyplease::unparse(&code))?; - } - Ok(()) -} diff --git a/src/lib.rs b/src/lib.rs index 4129c60..49b6578 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,27 +1,4 @@ -//! Generate register interface software from register map in XML. -//! -//! # Example -//! -//! Here's a typical usage: -//! ```no_run -//! use endcap_sl_software_ri_generator::types; -//! -//! let xmlfile = std::fs::read_to_string("./csr.xml")?; -//! let doc = roxmltree::Document::parse_with_options( -//! &xmlfile, -//! roxmltree::ParsingOptions { -//! allow_dtd: true, -//! nodes_limit: u32::MAX, -//! }, -//! )?; -//! -//! let register_map = types::Module::from_xml_dom(doc.root_element())?; -//! -//! let files = register_map.generate_code()?; -//! endcap_sl_software_ri_generator::write_to_files(files, &std::path::PathBuf::from("out"))?; -//! -//! # Ok::<(), anyhow::Error>(()) -//! ``` +//! Root document [`types::Module::from_xml_dom`] //! //! # Overview //! @@ -32,15 +9,13 @@ //! //! # modules //! - [`types`]: type definitions of internal register map representation +//! - [`type_traits`]: supplemental traits for types in [`types`] +//! - [`parser`]: supplemental parser (string to custom types) //! - [`converter`]: DOM to internal representation //! - [`generator`]: internal representation to rust code -//! - [`io`]: formatting and printing pub mod converter; pub mod generator; -pub mod io; -mod parser; -mod type_traits; +pub mod parser; +pub mod type_traits; pub mod types; - -pub use io::write_to_files; diff --git a/src/main.rs b/src/main.rs index a3a63bf..9b443de 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,13 +1,15 @@ -use std::fs; +use std::fs::DirBuilder; +use std::io::Write; +use std::{collections::HashMap, fs, io::BufWriter}; -use anyhow::Result; -use endcap_sl_software_ri_generator::types; +use anyhow::{anyhow, Context, Result}; +use endcap_sl_software_ri_generator::{generator::CodeGen, types}; use itertools::Itertools; fn main() -> Result<()> { env_logger::init(); - log::debug!("logger enabled"); + println!("Hello, world!"); let xmlfile = fs::read_to_string("./csr.xml")?; let doc = roxmltree::Document::parse_with_options( &xmlfile, @@ -16,26 +18,39 @@ fn main() -> Result<()> { nodes_limit: u32::MAX, }, )?; - log::debug!("Parsed: {:#?}", doc); + // println!("Parsed: {:#?}", doc); + // println!("Root: {:?}", doc.root_element()); let register_map = types::Module::from_xml_dom(doc.root_element())?; - log::info!("read: {:?}", register_map); - log::debug!("read: {:#?}", register_map); + println!("read: {:#?}", register_map); - let files = register_map.generate_code()?; - if log::log_enabled!(log::Level::Debug) { - for (path, code) in &files { - log::debug!("path: {:?}", path); - log::debug!("{}", prettyplease::unparse(code)); - } - } - if log::log_enabled!(log::Level::Info) { - for filepath in files.keys().sorted() { - log::info!("{}", filepath.display()); - } - } + println!("==========================================="); - endcap_sl_software_ri_generator::write_to_files(files, &std::path::PathBuf::from("out"))?; + let files = register_map.generate_register_interface(None, None, HashMap::new())?; + // println!("{:#?}", files); + for filepath in files.keys().sorted() { + println!("{}", filepath.display()); + } + if !std::fs::read_dir("register_interface") + .context("register_interface not found")? + .collect_vec() + .is_empty() + { + return Err(anyhow!("dir register_interface is not empty")); + }; + for (file, code) in files { + DirBuilder::new() + .recursive(true) + .create(file.parent().context("no parent")?)?; + let file = fs::OpenOptions::new() + .create(true) + .truncate(true) + .write(true) + .open(file) + .context("opening file")?; + let mut writer = BufWriter::new(file); + write!(writer, "{}", code)?; + } Ok(()) }