Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

hex serde #278

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions svd-encoder/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ where
NumberFormat::UpperHex => format!("{:#X}", value),
NumberFormat::UpperHex8 => format!("{:#010X}", value),
NumberFormat::UpperHex16 => {
if value.into() > std::u32::MAX as u64 {
if value.into() > u32::MAX as u64 {
format!("{:#018X}", value)
} else {
format!("{:#010X}", value)
Expand All @@ -139,7 +139,7 @@ where
NumberFormat::LowerHex => format!("{:#x}", value),
NumberFormat::LowerHex8 => format!("{:#010x}", value),
NumberFormat::LowerHex16 => {
if value.into() > std::u32::MAX as u64 {
if value.into() > u32::MAX as u64 {
format!("{:#018x}", value)
} else {
format!("{:#010x}", value)
Expand Down
2 changes: 1 addition & 1 deletion svd-rs/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).

## Unreleased

- use `hex` format for address when serialize
- Revert the `riscv` elements, as well as the `unstable-riscv` feature.

## [v0.14.9] - 2024-08-20
Expand Down Expand Up @@ -143,4 +144,3 @@ Previous versions in common [changelog](../CHANGELOG.md).
[v0.11.2]: https://github.com/rust-embedded/svd/compare/svd-rs-v0.11.1...svd-rs-v0.11.2
[v0.11.1]: https://github.com/rust-embedded/svd/compare/v0.11.0...svd-rs-v0.11.1
[v0.11.0]: https://github.com/rust-embedded/svd/compare/v0.10.2...v0.11.0

2 changes: 2 additions & 0 deletions svd-rs/src/addressblock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@ use super::{BuildError, Protection, SvdError, ValidateLevel};
#[non_exhaustive]
pub struct AddressBlock {
/// Specifies the start address of an address block relative to the peripheral [`baseAddress`](crate::Peripheral::base_address).
#[cfg_attr(feature = "serde", serde(serialize_with = "crate::as_hex"))]
pub offset: u32,
/// Specifies the number of [`addressUnitBits`](crate::Device::address_unit_bits) being covered by this address block.
#[cfg_attr(feature = "serde", serde(serialize_with = "crate::as_hex"))]
pub size: u32,
/// Usage of the address block.
pub usage: AddressBlockUsage,
Expand Down
1 change: 1 addition & 0 deletions svd-rs/src/cluster.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ pub struct ClusterInfo {
pub header_struct_name: Option<String>,

/// Cluster address relative to the `baseAddress` of the peripheral
#[cfg_attr(feature = "serde", serde(serialize_with = "crate::as_hex"))]
pub address_offset: u32,

/// Default properties for all registers
Expand Down
85 changes: 78 additions & 7 deletions svd-rs/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,22 +95,17 @@ pub mod datatype;
pub use self::datatype::DataType;

/// Level of validation
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
pub enum ValidateLevel {
/// No validation.
Disabled,
/// Weak validation.
#[default]
Weak,
/// Strict validation.
Strict,
}

impl Default for ValidateLevel {
fn default() -> Self {
ValidateLevel::Weak
}
}

impl ValidateLevel {
/// Returns true if validation is disabled.
pub fn is_disabled(self) -> bool {
Expand Down Expand Up @@ -281,3 +276,79 @@ where
T::description(*self)
}
}

#[cfg(feature = "serde")]
struct Hex<T>(T);

#[cfg(feature = "serde")]
impl serde::Serialize for Hex<u64> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
let n = self.0;
let (h4, h3, h2, h1) = (
(n >> 48) & 0xffff,
(n >> 32) & 0xffff,
(n >> 16) & 0xffff,
n & 0xffff,
);
let f = if h4 != 0 {
format!("0x{h4:04x}{h3:04x}{h2:04x}{h1:04x}")
} else if h3 != 0 {
format!("0x{h3:04x}{h2:04x}{h1:04x}")
} else if h2 != 0 {
format!("0x{h2:04x}{h1:04x}")
} else if h1 & 0xff00 != 0 {
format!("0x{h1:04x}")
} else if h1 != 0 {
format!("0x{:02x}", h1 & 0xff)
} else {
"0".to_string()
};
serializer.serialize_str(&f)
Comment on lines +289 to +309
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this could be replaced with

let hex_length = ((64 - n.leading_zeros() + 3)/4) as usize;
let width = (4 - (hex_length % 4)) % 4 + hex_length;
format!("0x{:0width$x}", n)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Forgot about this. Thanks.

}
}

#[cfg(feature = "serde")]
impl serde::Serialize for Hex<u32> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
let n = self.0;
let (h2, h1) = ((n >> 16) & 0xffff, n & 0xffff);
let f = if h2 != 0 {
format!("0x{h2:04x}{h1:04x}")
} else if h1 & 0xff00 != 0 {
format!("0x{h1:04x}")
} else if h1 != 0 {
format!("0x{:02x}", h1 & 0xff)
} else {
"0".to_string()
};
serializer.serialize_str(&f)
}
}

#[cfg(feature = "serde")]
fn as_hex<T, S>(n: &T, s: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
T: Copy,
Hex<T>: serde::Serialize,
{
use serde::Serialize;
Hex(*n).serialize(s)
}

#[cfg(feature = "serde")]
fn as_opt_hex<T, S>(n: &Option<T>, s: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
T: Copy,
Hex<T>: serde::Serialize,
{
use serde::Serialize;
(*n).map(Hex).serialize(s)
}
1 change: 1 addition & 0 deletions svd-rs/src/peripheral.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ pub struct PeripheralInfo {
pub header_struct_name: Option<String>,

/// Lowest address reserved or used by the peripheral
#[cfg_attr(feature = "serde", serde(serialize_with = "crate::as_hex"))]
pub base_address: u64,

/// Default properties for all registers
Expand Down
1 change: 1 addition & 0 deletions svd-rs/src/register.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ pub struct RegisterInfo {
pub alternate_register: Option<String>,

/// Define the address offset relative to the enclosing element
#[cfg_attr(feature = "serde", serde(serialize_with = "crate::as_hex"))]
pub address_offset: u32,

/// Specifies register size, access permission and reset value
Expand Down
20 changes: 16 additions & 4 deletions svd-rs/src/registerproperties.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,11 @@ pub struct RegisterProperties {
/// Bit-width of register
#[cfg_attr(
feature = "serde",
serde(default, skip_serializing_if = "Option::is_none")
serde(
default,
skip_serializing_if = "Option::is_none",
serialize_with = "crate::as_opt_hex"
)
)]
pub size: Option<u32>,

Expand All @@ -47,14 +51,22 @@ pub struct RegisterProperties {
/// Register value at RESET
#[cfg_attr(
feature = "serde",
serde(default, skip_serializing_if = "Option::is_none")
serde(
default,
skip_serializing_if = "Option::is_none",
serialize_with = "crate::as_opt_hex"
)
)]
pub reset_value: Option<u64>,

/// Define which register bits have a defined reset value
#[cfg_attr(
feature = "serde",
serde(default, skip_serializing_if = "Option::is_none")
serde(
default,
skip_serializing_if = "Option::is_none",
serialize_with = "crate::as_opt_hex"
)
)]
pub reset_mask: Option<u64>,
}
Expand Down Expand Up @@ -133,7 +145,7 @@ pub(crate) fn check_reset_value(
mask: Option<u64>,
lvl: ValidateLevel,
) -> Result<(), Error> {
const MAX_BITS: u32 = core::u64::MAX.count_ones();
const MAX_BITS: u32 = u64::MAX.count_ones();

if let (Some(size), Some(value)) = (size, value) {
if MAX_BITS - value.leading_zeros() > size {
Expand Down