Initial serialize documentation, showcasing XML attributes and children. Left to document or fix are: dependencies and pretty-printing
This commit is contained in:
parent
e326a978fd
commit
d8d84313df
13
examples/svd/Cargo.toml
Normal file
13
examples/svd/Cargo.toml
Normal file
@ -0,0 +1,13 @@
|
||||
[package]
|
||||
name = "v850-svd"
|
||||
version = "0.1.0"
|
||||
authors = ["Roman Valls Guimera <brainstorm@nopcode.org>"]
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
# serde = { version = "1.0.123", features = [ "derive" ] }
|
||||
# quick-xml = { version = "0.21.0", features = [ "serialize" ] }
|
||||
yaserde = "0.5.1"
|
||||
yaserde_derive = "0.5.1"
|
||||
xml-rs = "0.8.3"
|
||||
log = "0.4"
|
||||
184
examples/svd/main.rs
Normal file
184
examples/svd/main.rs
Normal file
@ -0,0 +1,184 @@
|
||||
use yaserde_derive::YaSerialize;
|
||||
|
||||
#[derive(Default, PartialEq, Debug, YaSerialize)]
|
||||
struct CpuDef {
|
||||
#[yaserde(child)]
|
||||
name: String,
|
||||
#[yaserde(child)]
|
||||
revision: String,
|
||||
#[yaserde(child)]
|
||||
endian: String, // enum {LE, BE, ME}
|
||||
#[yaserde(child)]
|
||||
mpupresent: bool,
|
||||
#[yaserde(child)]
|
||||
fpupresent: bool,
|
||||
//#[yaserde(child)]
|
||||
//nvicpriobits: enum {8, 16, 32, 64, 128},
|
||||
#[yaserde(child)]
|
||||
vendorsystickconfig: bool
|
||||
}
|
||||
|
||||
#[derive(Default, PartialEq, Debug, YaSerialize)]
|
||||
struct Field {
|
||||
name: String,
|
||||
#[yaserde(child)]
|
||||
description: String,
|
||||
#[yaserde(child)]
|
||||
bitrange: String,
|
||||
#[yaserde(child)]
|
||||
access: String,
|
||||
}
|
||||
|
||||
#[derive(Default, PartialEq, Debug, YaSerialize)]
|
||||
struct Register {
|
||||
#[yaserde(child)]
|
||||
name: String,
|
||||
#[yaserde(child)]
|
||||
description: String,
|
||||
#[yaserde(child)]
|
||||
addressoffset: String,
|
||||
#[yaserde(child)]
|
||||
size: u8,
|
||||
#[yaserde(child)]
|
||||
access: String,
|
||||
#[yaserde(child)]
|
||||
resetvalue: String,
|
||||
#[yaserde(child)]
|
||||
resetmask: String,
|
||||
#[yaserde(child)]
|
||||
fields: Vec<Field>
|
||||
}
|
||||
|
||||
#[derive(Default, PartialEq, Debug, YaSerialize)]
|
||||
struct Peripheral {
|
||||
#[yaserde(child)]
|
||||
name: String,
|
||||
#[yaserde(child)]
|
||||
version: String,
|
||||
#[yaserde(child)]
|
||||
description: String,
|
||||
#[yaserde(child)]
|
||||
groupname: String,
|
||||
#[yaserde(child)]
|
||||
baseaddress: String,
|
||||
#[yaserde(child)]
|
||||
size: u8,
|
||||
#[yaserde(child)]
|
||||
access: String,
|
||||
#[yaserde(child)]
|
||||
registers: Vec<Register>
|
||||
}
|
||||
|
||||
#[derive(Default, PartialEq, Debug, YaSerialize)]
|
||||
struct DevAttrs {
|
||||
#[yaserde(child)]
|
||||
vendor: String,
|
||||
#[yaserde(child)]
|
||||
vendorid: String,
|
||||
#[yaserde(child)]
|
||||
name: String,
|
||||
#[yaserde(child)]
|
||||
series: String,
|
||||
#[yaserde(child)]
|
||||
version: String,
|
||||
#[yaserde(child)]
|
||||
description: String,
|
||||
#[yaserde(child)]
|
||||
licensetext: String,
|
||||
#[yaserde(child)]
|
||||
cpu: CpuDef,
|
||||
#[yaserde(child)]
|
||||
addressunitbits: u8,
|
||||
#[yaserde(child)]
|
||||
width: u8,
|
||||
#[yaserde(child)]
|
||||
size: u8,
|
||||
#[yaserde(child)]
|
||||
access: String,
|
||||
#[yaserde(child)]
|
||||
resetvalue: String,
|
||||
#[yaserde(child)]
|
||||
resetmask: String,
|
||||
#[yaserde(child)]
|
||||
peripherals: Vec<Peripheral>
|
||||
}
|
||||
|
||||
#[derive(Default, PartialEq, Debug, YaSerialize)]
|
||||
#[yaserde(rename = "device")]
|
||||
struct Device {
|
||||
#[yaserde(attribute)]
|
||||
schemaversion: String,
|
||||
#[yaserde(attribute)]
|
||||
xmlns: String,
|
||||
#[yaserde(attribute)]
|
||||
xsnonamespaceschemalocation: String,
|
||||
#[yaserde(child)]
|
||||
devattributes: DevAttrs
|
||||
}
|
||||
|
||||
fn main() {
|
||||
|
||||
let mut vec_peripherals: Vec<Peripheral> = Vec::new();
|
||||
let mut vec_registers: Vec<Register> = Vec::new();
|
||||
let vec_fields: Vec<Field> = Vec::new();
|
||||
|
||||
let register = Register {
|
||||
name: "PRCMD".to_string(),
|
||||
description: "This command register (PRCMD) is to protect the registers that may have a significant influence on the application system (PSC, PSM) from an inadvertent write access, so that the system does not stop in case of a program hang-up.".to_string(),
|
||||
addressoffset: "0xFFFFF1FC".to_string(),
|
||||
size: 8,
|
||||
access: "read-write".to_string(),
|
||||
resetvalue: "0x0000".to_string(),
|
||||
resetmask: "0xFFFF".to_string(),
|
||||
fields: vec_fields
|
||||
};
|
||||
vec_registers.push(register);
|
||||
|
||||
let peripheral = Peripheral {
|
||||
name: "Specific Registers".to_string(),
|
||||
version: "1.0".to_string(),
|
||||
description: "Specific Registers".to_string(),
|
||||
groupname: "MCU".to_string(),
|
||||
baseaddress: "0xFFFFF1FC".to_string(),
|
||||
size: 16,
|
||||
access: "read-write".to_string(),
|
||||
registers: vec_registers
|
||||
};
|
||||
vec_peripherals.push(peripheral);
|
||||
|
||||
let cpu_def = CpuDef {
|
||||
name: "V850".to_string(),
|
||||
revision: "r1".to_string(),
|
||||
endian: "LE".to_string(), // enum {LE, BE, ME}
|
||||
mpupresent: false,
|
||||
fpupresent: false,
|
||||
//nvicpriobits: enum {8, 16, 32, 64, 128},
|
||||
vendorsystickconfig: false
|
||||
};
|
||||
|
||||
let dev_attrs = DevAttrs {
|
||||
vendor: "Renesas".to_string(),
|
||||
vendorid: "Renesas".to_string(),
|
||||
name: "V850".to_string(),
|
||||
series: "E1/E2/CA2".to_string(),
|
||||
version: "1.2".to_string(),
|
||||
description: "NEC/Renesas V850 automotive grade ICs".to_string(),
|
||||
licensetext: "GPLv3".to_string(),
|
||||
cpu: cpu_def,
|
||||
addressunitbits: 8,
|
||||
width: 32,
|
||||
size: 32,
|
||||
access: "read-write".to_string(),
|
||||
resetvalue: "0x00000000".to_string(),
|
||||
resetmask: "0xFFFFFFFF".to_string(),
|
||||
peripherals: vec_peripherals
|
||||
};
|
||||
|
||||
let dev = Device { schemaversion: "foo".to_string(),
|
||||
xmlns: "http://www.w3.org/2001/XMLSchema-instance".to_string(),
|
||||
xsnonamespaceschemalocation: "CMSIS-SVD.xsd".to_string(),
|
||||
devattributes: dev_attrs
|
||||
};
|
||||
|
||||
println!("{:?}", yaserde::ser::to_string(&dev).ok().unwrap());
|
||||
}
|
||||
@ -2,6 +2,78 @@
|
||||
//!
|
||||
//! YaSerDe is a framework for ***ser***ializing and ***de***serializing Rust data
|
||||
//! structures efficiently and generically from and into XML.
|
||||
//!
|
||||
//! YaSerDe makes it easy to serialize XML documents given an properly annotated struct.
|
||||
//! Please refer to the `examples` directory for the complete code shown below.
|
||||
//!
|
||||
//! # Serialize
|
||||
//!
|
||||
//! For instance, let's say that one wants to generate a XML file for the
|
||||
//! [Rust-Embedded community](https://github.com/rust-embedded/). A well known XML
|
||||
//! file for microcontrollers is called [SVD](https://github.com/rust-embedded/svd/)
|
||||
//! and it can be defined on YaSerDe via structs like so:
|
||||
//!
|
||||
//!```
|
||||
//! use yaserde_derive::YaSerialize;
|
||||
//!
|
||||
//! #[derive(Default, PartialEq, Debug, YaSerialize)]
|
||||
//! #[yaserde(rename = "device")]
|
||||
//! struct Device {
|
||||
//! #[yaserde(attribute)]
|
||||
//! schemaversion: String,
|
||||
//! #[yaserde(attribute)]
|
||||
//! xmlns: String,
|
||||
//! #[yaserde(attribute)]
|
||||
//! xsnonamespaceschemalocation: String,
|
||||
//! #[yaserde(child)]
|
||||
//! devattributes: DevAttrs
|
||||
//! }
|
||||
//! (...)
|
||||
//!```
|
||||
//!
|
||||
//! The interspersed `#[yaserde()]` macros give some indication of what the resulting XML
|
||||
//! Will look like, namely, a short snippet of the struct above in XML would be depending on
|
||||
//! concrete values passed to the struct (not shown):
|
||||
//!
|
||||
//!```
|
||||
//! <device schemaversion: "1.0-example", xmlns: "ns:.... example"
|
||||
//! xsnonamespaceschemalocation: "foo_bar_baz">
|
||||
//! <devattributes>
|
||||
//! </devattributes>
|
||||
//! (...)
|
||||
//!```
|
||||
//!
|
||||
//! Notice the important difference in **XML output representation between `attributes` vs
|
||||
//! `child`**, since SVD expects information in that particular arrangement. YaSerDe allows that
|
||||
//! serialized XML to be valid unlike other Rust XML (de)serialization crates (i.e quick-xml).
|
||||
//!
|
||||
//! Also the last `DevAttrs` struct field is indeed another struct, so one can chain several
|
||||
//! structs to compose the XML structure (again, see examples folder for the complete
|
||||
//! example).
|
||||
//!
|
||||
//! Be mindful that the **Cargo.toml** should not only include `yaserde` and
|
||||
//! `yaserde_derive`, but also a few necessary dependencies... [FIXME: THAT FOR SOME
|
||||
//! USER-UNFRIENDLY REASON ARE NOT AUTOMATICALLY PULLED IN AS ONE WOULD EXPECT ;P ;P
|
||||
//! ... I'm sure there are good reasons, just wanted to leave this like this so that the author
|
||||
//! can chip in and comment about the reasons behind that decision.](https://github.com/media-io/yaserde/issues/22) ... **I personally think that issue #22 should be reopened and fixed properly (as in only requiring yaserde as a dependency, adding yaserde_derive as a feature).**
|
||||
//!
|
||||
//! ```
|
||||
//! [dependencies]
|
||||
//! # serde = { version = "1.0.123", features = [ "derive" ] }
|
||||
//! # quick-xml = { version = "0.21.0", features = [ "serialize" ] }
|
||||
//! yaserde = "0.5.1"
|
||||
//! yaserde_derive = "0.5.1"
|
||||
//! xml-rs = "0.8.3"
|
||||
//! log = "0.4"
|
||||
//! ```
|
||||
//!
|
||||
//! Last but not least, in order to have a nice, pretty printed XML output one can do
|
||||
//!
|
||||
//! ```
|
||||
//! PLEASE LET THE USERS KNOW HOW TO DO THAT CLEARLY ON YASERDE???
|
||||
//! ```
|
||||
//!
|
||||
//! FIXME: For now I'm just resorting to online XML linters and formatters :_S
|
||||
|
||||
#[macro_use]
|
||||
extern crate log;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user