Skip to content

Commit

Permalink
hex serde
Browse files Browse the repository at this point in the history
  • Loading branch information
burrbull committed Nov 18, 2024
1 parent 909a68b commit 356f4ff
Show file tree
Hide file tree
Showing 8 changed files with 102 additions and 14 deletions.
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)
}
}

#[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

0 comments on commit 356f4ff

Please sign in to comment.