mirror of
https://gitlab.cern.ch/wotsubo/endcap-sl-software-ri-generator.git
synced 2025-04-21 12:16:17 +09:00
Compare commits
1 commit
b0660212fc
...
220f294149
Author | SHA1 | Date | |
---|---|---|---|
220f294149 |
6 changed files with 46 additions and 111 deletions
11
Cargo.lock
generated
11
Cargo.lock
generated
|
@ -88,7 +88,6 @@ dependencies = [
|
||||||
"heck",
|
"heck",
|
||||||
"itertools",
|
"itertools",
|
||||||
"log",
|
"log",
|
||||||
"prettyplease",
|
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"roxmltree",
|
"roxmltree",
|
||||||
|
@ -164,16 +163,6 @@ version = "1.20.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775"
|
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]]
|
[[package]]
|
||||||
name = "proc-macro2"
|
name = "proc-macro2"
|
||||||
version = "1.0.93"
|
version = "1.0.93"
|
||||||
|
|
|
@ -17,7 +17,6 @@ env_logger = "0.11.6"
|
||||||
heck = "0.5"
|
heck = "0.5"
|
||||||
itertools = "0.14"
|
itertools = "0.14"
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
prettyplease = "0.2"
|
|
||||||
proc-macro2 = "1.0.93"
|
proc-macro2 = "1.0.93"
|
||||||
quote = "1.0"
|
quote = "1.0"
|
||||||
roxmltree = "0.20"
|
roxmltree = "0.20"
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
//! Generate register interface rust code from types in [`crate::types`].
|
//! Generate register interface rust code from types in [`crate::types`].
|
||||||
//!
|
//!
|
||||||
//! root: [`Module::generate_code`]
|
//! root: [`CodeGen`]
|
||||||
//!
|
//!
|
||||||
//! # For developers
|
//! # TODO
|
||||||
//! Pass `--document-private-items` to see non-public items.
|
//! add docs (especially fields and registers)
|
||||||
|
|
||||||
use std::{
|
use std::{
|
||||||
collections::HashMap,
|
collections::HashMap,
|
||||||
|
@ -15,14 +15,13 @@ use crate::{
|
||||||
types::{Block, Module, ModuleBlockElements, Register},
|
types::{Block, Module, ModuleBlockElements, Register},
|
||||||
};
|
};
|
||||||
use heck::{ToSnakeCase, ToUpperCamelCase};
|
use heck::{ToSnakeCase, ToUpperCamelCase};
|
||||||
use itertools::Itertools;
|
|
||||||
use quote::quote;
|
use quote::quote;
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
#[derive(Debug, Error)]
|
#[derive(Debug, Error)]
|
||||||
pub enum CodeGenError {
|
pub enum CodeGenError {
|
||||||
#[error("tokenization(syn) error: {0}")]
|
#[error("tokenization error: {0}")]
|
||||||
SynError(#[from] syn::Error),
|
TokenizeError(#[from] syn::Error),
|
||||||
#[error("failed to create file: {0}")]
|
#[error("failed to create file: {0}")]
|
||||||
FilePathError(String),
|
FilePathError(String),
|
||||||
#[error("parent is required for {module}")]
|
#[error("parent is required for {module}")]
|
||||||
|
@ -121,22 +120,7 @@ mod util {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Module {
|
pub trait CodeGen {
|
||||||
pub fn generate_code(self) -> Result<HashMap<path::PathBuf, syn::File>, 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 {
|
|
||||||
/// `parent_name` in UpperCamelCase.
|
/// `parent_name` in UpperCamelCase.
|
||||||
fn generate_register_interface(
|
fn generate_register_interface(
|
||||||
self,
|
self,
|
||||||
|
|
27
src/io.rs
27
src/io.rs
|
@ -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<path::PathBuf, syn::File>,
|
|
||||||
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(())
|
|
||||||
}
|
|
35
src/lib.rs
35
src/lib.rs
|
@ -1,27 +1,4 @@
|
||||||
//! Generate register interface software from register map in XML.
|
//! Root document [`types::Module::from_xml_dom`]
|
||||||
//!
|
|
||||||
//! # 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>(())
|
|
||||||
//! ```
|
|
||||||
//!
|
//!
|
||||||
//! # Overview
|
//! # Overview
|
||||||
//!
|
//!
|
||||||
|
@ -32,15 +9,13 @@
|
||||||
//!
|
//!
|
||||||
//! # modules
|
//! # modules
|
||||||
//! - [`types`]: type definitions of internal register map representation
|
//! - [`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
|
//! - [`converter`]: DOM to internal representation
|
||||||
//! - [`generator`]: internal representation to rust code
|
//! - [`generator`]: internal representation to rust code
|
||||||
//! - [`io`]: formatting and printing
|
|
||||||
|
|
||||||
pub mod converter;
|
pub mod converter;
|
||||||
pub mod generator;
|
pub mod generator;
|
||||||
pub mod io;
|
pub mod parser;
|
||||||
mod parser;
|
pub mod type_traits;
|
||||||
mod type_traits;
|
|
||||||
pub mod types;
|
pub mod types;
|
||||||
|
|
||||||
pub use io::write_to_files;
|
|
||||||
|
|
55
src/main.rs
55
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 anyhow::{anyhow, Context, Result};
|
||||||
use endcap_sl_software_ri_generator::types;
|
use endcap_sl_software_ri_generator::{generator::CodeGen, types};
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
|
|
||||||
fn main() -> Result<()> {
|
fn main() -> Result<()> {
|
||||||
env_logger::init();
|
env_logger::init();
|
||||||
log::debug!("logger enabled");
|
|
||||||
|
|
||||||
|
println!("Hello, world!");
|
||||||
let xmlfile = fs::read_to_string("./csr.xml")?;
|
let xmlfile = fs::read_to_string("./csr.xml")?;
|
||||||
let doc = roxmltree::Document::parse_with_options(
|
let doc = roxmltree::Document::parse_with_options(
|
||||||
&xmlfile,
|
&xmlfile,
|
||||||
|
@ -16,26 +18,39 @@ fn main() -> Result<()> {
|
||||||
nodes_limit: u32::MAX,
|
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())?;
|
let register_map = types::Module::from_xml_dom(doc.root_element())?;
|
||||||
log::info!("read: {:?}", register_map);
|
println!("read: {:#?}", register_map);
|
||||||
log::debug!("read: {:#?}", register_map);
|
|
||||||
|
|
||||||
let files = register_map.generate_code()?;
|
println!("===========================================");
|
||||||
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());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue