Skip to content

Commit be572ae

Browse files
committed
Comments update.
1 parent d003f95 commit be572ae

File tree

4 files changed

+271
-297
lines changed

4 files changed

+271
-297
lines changed

crates/powerlink-rs-xdc/src/error.rs

Lines changed: 16 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,41 @@
1-
// crates/powerlink-rs-xdc/src/error.rs
2-
31
use alloc::fmt;
42
use alloc::string::String;
53
use core::num::ParseIntError;
64
use hex::FromHexError;
5+
use quick_xml::errors::serialize::{DeError, SeError};
76
use quick_xml::Error as XmlError;
8-
use quick_xml::errors::serialize::DeError;
9-
use quick_xml::errors::serialize::SeError;
107

11-
/// Errors that can occur during XDC parsing or serialization.
8+
/// Errors that can occur during XDC parsing, validation, or serialization.
129
#[derive(Debug)]
1310
pub enum XdcError {
14-
/// An error from the underlying `quick-xml` deserializer.
11+
/// An error occurred while deserializing the XML structure.
1512
XmlParsing(DeError),
1613

17-
/// An error from the underlying `quick-xml` serializer.
14+
/// An error occurred while serializing data to XML.
1815
XmlSerializing(SeError),
1916

20-
/// An error from the underlying `quick-xml` writer (e.g., I/O).
17+
/// An I/O or syntax error occurred in the underlying XML writer.
2118
XmlWriting(XmlError),
2219

23-
/// The `actualValue` or `defaultValue` attribute contained invalid hex.
20+
/// The `actualValue` or `defaultValue` attribute contained invalid hex data.
2421
HexParsing(FromHexError),
2522

26-
/// An error occurred during string formatting (e.g., in helpers).
23+
/// An error occurred during string formatting.
2724
FmtError(fmt::Error),
2825

29-
/// A required XML element was missing (e.g., ProfileBody).
26+
/// A mandatory XML element required by the POWERLINK profile (e.g., `ProfileBody`) was missing.
3027
MissingElement { element: &'static str },
3128

32-
/// A required attribute was missing (e.g., @index).
29+
/// A mandatory attribute (e.g., `@index`) was missing from an element.
3330
MissingAttribute { attribute: &'static str },
3431

35-
/// An attribute (e.g., @index) had an invalid format.
32+
/// An attribute (e.g., `@index`) existed but had an invalid format (e.g., non-hex string).
3633
InvalidAttributeFormat { attribute: &'static str },
3734

38-
/// A generic validation error.
35+
/// A generic validation error occurred during profile resolution.
3936
ValidationError(&'static str),
4037

41-
/// The parsed data length does not match the `dataType` attribute.
38+
/// The parsed data length does not match the definition provided in `dataType`.
4239
TypeValidationError {
4340
index: u16,
4441
sub_index: u8,
@@ -47,7 +44,7 @@ pub enum XdcError {
4744
actual_bytes: usize,
4845
},
4946

50-
/// Functionality is not yet implemented.
47+
/// The requested functionality is not yet implemented.
5148
NotImplemented,
5249
}
5350

@@ -81,7 +78,7 @@ impl From<fmt::Error> for XdcError {
8178
}
8279
}
8380

84-
/// Converts `ParseIntError` (typically from reading hex index/subindex) into a user-friendly error.
81+
/// Converts `ParseIntError` (typically from reading hex index/subindex) into a domain-specific error.
8582
impl From<ParseIntError> for XdcError {
8683
fn from(_: ParseIntError) -> Self {
8784
XdcError::InvalidAttributeFormat {
@@ -93,14 +90,13 @@ impl From<ParseIntError> for XdcError {
9390
#[cfg(test)]
9491
mod tests {
9592
use super::XdcError;
96-
use crate::model; // Import model for test
93+
use crate::model;
9794
use alloc::string::ToString;
9895
use hex;
9996
use quick_xml;
10097

10198
#[test]
10299
fn test_from_de_error() {
103-
// Create a dummy DeError by failing to parse a struct with required fields
104100
let xml_err =
105101
quick_xml::de::from_str::<model::header::ProfileHeader>("<Test></Test>").unwrap_err();
106102
let xdc_err: XdcError = xml_err.into();
@@ -109,39 +105,34 @@ mod tests {
109105

110106
#[test]
111107
fn test_from_se_error() {
112-
// Create a dummy SeError
113108
let xml_err = quick_xml::errors::serialize::SeError::Custom("test error".to_string());
114109
let xdc_err: XdcError = xml_err.into();
115110
assert!(matches!(xdc_err, XdcError::XmlSerializing(_)));
116111
}
117112

118113
#[test]
119114
fn test_from_xml_error() {
120-
// Create a dummy XmlError
121115
let xml_err = quick_xml::Error::Syntax(quick_xml::errors::SyntaxError::InvalidBangMarkup);
122116
let xdc_err: XdcError = xml_err.into();
123117
assert!(matches!(xdc_err, XdcError::XmlWriting(_)));
124118
}
125119

126120
#[test]
127121
fn test_from_hex_error() {
128-
// Create a dummy FromHexError by parsing invalid hex
129122
let hex_err = hex::decode("Z").unwrap_err();
130123
let xdc_err: XdcError = hex_err.into();
131124
assert!(matches!(xdc_err, XdcError::HexParsing(_)));
132125
}
133126

134127
#[test]
135128
fn test_from_fmt_error() {
136-
// Create a dummy fmt::Error
137129
let fmt_err = core::fmt::Error;
138130
let xdc_err: XdcError = fmt_err.into();
139131
assert!(matches!(xdc_err, XdcError::FmtError(_)));
140132
}
141133

142134
#[test]
143135
fn test_from_parse_int_error() {
144-
// Create a dummy ParseIntError
145136
let parse_err = "not a number".parse::<u16>().unwrap_err();
146137
let xdc_err: XdcError = parse_err.into();
147138
assert!(matches!(
@@ -151,4 +142,4 @@ mod tests {
151142
}
152143
));
153144
}
154-
}
145+
}

crates/powerlink-rs-xdc/src/lib.rs

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,17 @@
1-
// src/lib.rs
2-
31
#![no_std]
42
#![doc = "Parses and generates POWERLINK XDC (XML Device Configuration) files."]
53
#![doc = ""]
64
#![doc = "This `no_std + alloc` library provides type-safe parsing and serialization"]
7-
#![doc = "for POWERLINK XDC (Configuration Manager) data."]
5+
#![doc = "for POWERLINK XDC (Configuration Manager) data based on the EPSG DS 311 specification."]
86
#![doc = ""]
9-
#![doc = "It supports:"]
10-
#![doc = "- `load_xdc_from_str`: Parsing `actualValue` attributes from an XDC."]
11-
#![doc = "- `load_xdd_defaults_from_str`: Parsing `defaultValue` attributes from an XDD."]
12-
#![doc = "- `save_xdc_to_string`: Serializing configuration data back into a minimal XDC string."]
7+
#![doc = "It provides the following main capabilities:"]
8+
#![doc = "- **Parsing**: Loading `.xdc` or `.xdd` XML strings into strongly-typed Rust structures."]
9+
#![doc = "- **Resolution**: Resolving complex inheritance, `uniqueIDRef` links, and templates defined in the Application Process."]
10+
#![doc = "- **Serialization**: generating minimal valid XDC XML strings from Rust structures."]
11+
#![doc = "- **Core Integration**: Converting the parsed data into the `ObjectDictionary` format required by the `powerlink-rs` core stack."]
1312

1413
extern crate alloc;
1514

16-
// --- Crate Modules ---
17-
1815
mod builder;
1916
mod converter;
2017
mod error;
@@ -27,7 +24,7 @@ mod types;
2724

2825
// Functions
2926
pub use builder::save_xdc_to_string;
30-
pub use converter::{NmtSettings, extract_nmt_settings, to_core_od, xdc_to_storage_map};
27+
pub use converter::{extract_nmt_settings, to_core_od, xdc_to_storage_map, NmtSettings};
3128
pub use error::XdcError;
3229
pub use parser::{load_xdc_from_str, load_xdd_defaults_from_str};
3330

@@ -43,4 +40,4 @@ pub use types::{
4340
ParameterGroup, ParameterGroupItem, ParameterRef, ParameterSupport, Picture, ProfileHeader,
4441
Range, StandardCompliance, StaticErrorBit, StructMember, SubObject, Value, ValueRange,
4542
VarDeclaration, Version, VersionInfo, XdcFile,
46-
};
43+
};

crates/powerlink-rs-xdc/src/parser.rs

Lines changed: 34 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
1-
// crates/powerlink-rs-xdc/src/parser.rs
2-
3-
//! The internal XML parser and helper functions for parsing hex strings.
1+
//! The internal XML parser entry point.
2+
//!
3+
//! This module handles the raw XML deserialization using `quick-xml` and forwards
4+
//! the data to the `resolver` module for business logic processing.
45
56
use crate::error::XdcError;
67
use crate::model;
7-
use crate::resolver; // This module's functions are now called by `load_...`
8-
use crate::resolver::ValueMode; // Import the new ValueMode enum
8+
use crate::resolver;
9+
use crate::resolver::ValueMode;
910
use crate::types::XdcFile;
1011
use alloc::string::String;
1112
use alloc::vec::Vec;
@@ -15,62 +16,69 @@ use quick_xml::de::from_str;
1516

1617
// --- Public API Functions ---
1718

18-
/// Loads XDC data (using `actualValue`) from an XML string.
19+
/// Loads XDC data from an XML string, prioritizing `actualValue` attributes.
20+
///
21+
/// This function is intended for loading **Configuration** files (XDC). It will
22+
/// resolve object dictionary values by looking for `@actualValue` first. If not found,
23+
/// it falls back to `@defaultValue`.
1924
///
20-
/// This function parses the XML and resolves the data model by prioritizing
21-
/// the `actualValue` attributes, which is standard for XDC (Configuration) files.
25+
/// # Arguments
26+
/// * `s` - The raw XML string content.
27+
///
28+
/// # Returns
29+
/// * `Result<XdcFile, XdcError>` - The parsed and resolved file structure.
2230
pub fn load_xdc_from_str(s: &str) -> Result<XdcFile, XdcError> {
2331
let container = parse_xml_str(s)?;
24-
// Call the resolver with ValueMode::Actual
2532
resolver::resolve_data(container, ValueMode::Actual)
2633
}
2734

28-
/// Loads XDD default data (using `defaultValue`) from an XML string.
35+
/// Loads XDD data from an XML string, prioritizing `defaultValue` attributes.
36+
///
37+
/// This function is intended for loading **Device Description** files (XDD). It will
38+
/// resolve object dictionary values by looking for `@defaultValue` first.
2939
///
30-
/// This function parses the XML and resolves the data model by prioritizing
31-
/// the `defaultValue` attributes, which is standard for XDD (Device Description) files.
40+
/// # Arguments
41+
/// * `s` - The raw XML string content.
42+
///
43+
/// # Returns
44+
/// * `Result<XdcFile, XdcError>` - The parsed and resolved file structure.
3245
pub fn load_xdd_defaults_from_str(s: &str) -> Result<XdcFile, XdcError> {
3346
let container = parse_xml_str(s)?;
34-
// Call the resolver with ValueMode::Default
3547
resolver::resolve_data(container, ValueMode::Default)
3648
}
3749

3850
// --- Internal XML Deserialization ---
3951

40-
/// The core internal function that uses `quick-xml` to deserialize the string
41-
/// into the raw `model` structs.
52+
/// Deserializes the raw XML string into the internal `model` structs.
4253
pub(crate) fn parse_xml_str(s: &str) -> Result<model::Iso15745ProfileContainer, XdcError> {
43-
// quick-xml's deserializer is very efficient.
44-
// It maps the XML structure directly to our `model` structs.
4554
from_str(s).map_err(XdcError::from)
4655
}
4756

4857
// --- Hex String Parsing Helpers ---
49-
// These are used by the resolver.
5058

51-
/// Parses a "0x..." or "..." hex string into a `u32`.
59+
/// Parses a "0x..." or raw hex string into a `u32`.
5260
pub(crate) fn parse_hex_u32(s: &str) -> Result<u32, ParseIntError> {
5361
let s_no_prefix = s.strip_prefix("0x").unwrap_or(s);
5462
u32::from_str_radix(s_no_prefix, 16)
5563
}
5664

57-
/// Parses a "0x..." or "..." hex string into a `u16`.
65+
/// Parses a "0x..." or raw hex string into a `u16`.
5866
pub(crate) fn parse_hex_u16(s: &str) -> Result<u16, ParseIntError> {
5967
let s_no_prefix = s.strip_prefix("0x").unwrap_or(s);
6068
u16::from_str_radix(s_no_prefix, 16)
6169
}
6270

63-
/// Parses a "0x..." or "..." hex string into a `u8`.
71+
/// Parses a "0x..." or raw hex string into a `u8`.
6472
pub(crate) fn parse_hex_u8(s: &str) -> Result<u8, ParseIntError> {
6573
let s_no_prefix = s.strip_prefix("0x").unwrap_or(s);
6674
u8::from_str_radix(s_no_prefix, 16)
6775
}
6876

69-
/// Parses a "0x..." or "..." hex string into a byte vector.
77+
/// Parses a "0x..." or raw hex string into a byte vector.
78+
/// Handles odd-length strings by padding with a leading zero.
7079
pub(crate) fn parse_hex_string(s: &str) -> Result<Vec<u8>, FromHexError> {
7180
let s_no_prefix = s.strip_prefix("0x").unwrap_or(s);
7281

73-
// Handle odd-length strings by padding with a leading zero
7482
if s_no_prefix.len() % 2 != 0 {
7583
let mut padded_s = String::with_capacity(s_no_prefix.len() + 1);
7684
padded_s.push('0');
@@ -86,9 +94,8 @@ mod tests {
8694
use super::*;
8795
use crate::error::XdcError;
8896
use alloc::vec;
89-
use hex::FromHexError; // Import for invalid char test
97+
use hex::FromHexError;
9098

91-
// A minimal but complete XDC structure for testing.
9299
const MINIMAL_GOOD_XDC: &str = r#"<?xml version="1.0" encoding="UTF-8"?>
93100
<ISO15745ProfileContainer xmlns="http://www.ethernet-powerlink.org" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.ethernet-powerlink.org Powerlink_Main.xsd">
94101
<ISO15745Profile>
@@ -145,12 +152,10 @@ mod tests {
145152
let result = load_xdc_from_str(MINIMAL_GOOD_XDC);
146153
assert!(result.is_ok());
147154
let xdc_file = result.unwrap();
148-
// Fix: Use `name` field, not `profile_name`
149155
assert_eq!(xdc_file.header.name, "Test Profile");
150156
assert_eq!(xdc_file.identity.vendor_name, "TestVendor");
151157
assert_eq!(xdc_file.object_dictionary.objects.len(), 1);
152158
assert_eq!(xdc_file.object_dictionary.objects[0].index, 0x1000);
153-
// FIX: The value "0x1234" (U16) is parsed as LE, so it becomes [0x34, 0x12].
154159
assert_eq!(
155160
xdc_file.object_dictionary.objects[0].data.as_deref(),
156161
Some("0x1234")
@@ -164,7 +169,6 @@ mod tests {
164169
assert!(result.is_ok());
165170
let xdd_file = result.unwrap();
166171
assert_eq!(xdd_file.identity.vendor_name, "TestVendor");
167-
// FIX: The value "0x1234" (U16) is parsed as LE, so it becomes [0x34, 0x12].
168172
assert_eq!(
169173
xdd_file.object_dictionary.objects[0].data.as_deref(),
170174
Some("0x1234")
@@ -173,7 +177,7 @@ mod tests {
173177

174178
#[test]
175179
fn test_load_xdc_malformed_xml() {
176-
let malformed_xml = "<ISO15745ProfileContainer><ProfileHeader>"; // Missing closing tags
180+
let malformed_xml = "<ISO15745ProfileContainer><ProfileHeader>";
177181
let result = load_xdc_from_str(malformed_xml);
178182
assert!(matches!(result, Err(XdcError::XmlParsing(_))));
179183
}
@@ -225,8 +229,6 @@ mod tests {
225229
));
226230
}
227231

228-
// --- Unit Tests for Helpers ---
229-
230232
#[test]
231233
fn test_parse_hex_u32() {
232234
assert_eq!(parse_hex_u32("0x1A2B3C4D").unwrap(), 0x1A2B3C4D);
@@ -265,11 +267,8 @@ mod tests {
265267

266268
#[test]
267269
fn test_parse_hex_string_odd_length() {
268-
// Odd length string "1" becomes "01"
269270
assert_eq!(parse_hex_string("1").unwrap(), vec![0x01]);
270-
// Odd length string "0xABC" becomes "0ABC"
271271
assert_eq!(parse_hex_string("0xABC").unwrap(), vec![0x0A, 0xBC]);
272-
// Odd length string "123" becomes "0123"
273272
assert_eq!(parse_hex_string("123").unwrap(), vec![0x01, 0x23]);
274273
}
275274

@@ -287,4 +286,4 @@ mod tests {
287286
Err(FromHexError::InvalidHexCharacter { .. })
288287
));
289288
}
290-
}
289+
}

0 commit comments

Comments
 (0)