Skip to content

Commit c63b19b

Browse files
committed
Less terrible compat.
1 parent 42905be commit c63b19b

File tree

2 files changed

+99
-55
lines changed

2 files changed

+99
-55
lines changed

ahib-config/src/lib.rs

Lines changed: 75 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -108,16 +108,90 @@ impl TryFromSerdeDirectoryEntryWithContext<SerdePspDirectoryEntry>
108108
}
109109
}
110110

111-
// See <https://github.com/serde-rs/serde/issues/1799>
112111
#[derive(Clone, serde::Serialize, schemars::JsonSchema)]
113112
#[serde(rename = "SerdePspEntrySourceValue")]
114113
#[serde(deny_unknown_fields)]
115114
#[non_exhaustive]
116115
pub enum SerdePspEntrySourceValue {
117116
PspSoftFuseChain(PspSoftFuseChain),
117+
#[serde(deserialize_with = "deserialize_raw")]
118118
Unknown(u64),
119119
}
120120

121+
impl<'de> serde::de::Deserialize<'de> for SerdePspEntrySourceValue {
122+
fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
123+
where
124+
D: serde::de::Deserializer<'de>,
125+
{
126+
struct PspVisitor;
127+
128+
impl<'de> serde::de::Visitor<'de> for PspVisitor {
129+
type Value = SerdePspEntrySourceValue;
130+
131+
fn expecting(
132+
&self,
133+
formatter: &mut std::fmt::Formatter,
134+
) -> std::fmt::Result {
135+
formatter
136+
.write_str("a u64 or a SerdePspEntrySourceValue variant")
137+
}
138+
139+
fn visit_u64<E>(
140+
self,
141+
value: u64,
142+
) -> std::result::Result<Self::Value, E>
143+
where
144+
E: serde::de::Error,
145+
{
146+
Ok(SerdePspEntrySourceValue::Unknown(value))
147+
}
148+
149+
fn visit_i64<E>(
150+
self,
151+
value: i64,
152+
) -> std::result::Result<Self::Value, E>
153+
where
154+
E: serde::de::Error,
155+
{
156+
if value >= 0 {
157+
Ok(SerdePspEntrySourceValue::Unknown(value as u64))
158+
} else {
159+
Err(E::invalid_value(
160+
serde::de::Unexpected::Signed(value),
161+
&"a positive integer or SerdePspEntrySourceValue variant",
162+
))
163+
}
164+
}
165+
166+
fn visit_map<A>(
167+
self,
168+
mut map: A,
169+
) -> std::result::Result<Self::Value, A::Error>
170+
where
171+
A: serde::de::MapAccess<'de>,
172+
{
173+
while let Some(key) = map.next_key::<String>()? {
174+
if key == "PspSoftFuseChain" {
175+
let value = map.next_value::<PspSoftFuseChain>()?;
176+
return Ok(SerdePspEntrySourceValue::PspSoftFuseChain(
177+
value,
178+
));
179+
} else {
180+
return Err(serde::de::Error::custom(
181+
"expected SerdePspEntrySourceValue variant",
182+
));
183+
}
184+
}
185+
Err(serde::de::Error::custom(
186+
"expected SerdePspEntrySourceValue variant",
187+
))
188+
}
189+
}
190+
191+
deserializer.deserialize_any(PspVisitor)
192+
}
193+
}
194+
121195
impl SerdePspEntrySourceValue {
122196
pub fn from_u64(value: u64, typ: PspDirectoryEntryType) -> Result<Self> {
123197
match typ {
@@ -147,60 +221,6 @@ impl SerdePspEntrySourceValue {
147221
}
148222
}
149223

150-
impl<'de> serde::Deserialize<'de> for SerdePspEntrySourceValue {
151-
fn deserialize<D: serde::Deserializer<'de>>(
152-
deserializer: D,
153-
) -> std::result::Result<Self, D::Error> {
154-
struct ModeVisitor;
155-
impl<'de> serde::de::Visitor<'de> for ModeVisitor {
156-
type Value = SerdePspEntrySourceValue;
157-
fn expecting(
158-
&self,
159-
formatter: &mut core::fmt::Formatter<'_>,
160-
) -> core::fmt::Result {
161-
formatter.write_str("dict")
162-
}
163-
fn visit_map<A>(
164-
self,
165-
map: A,
166-
) -> std::result::Result<Self::Value, A::Error>
167-
where
168-
A: serde::de::MapAccess<'de>,
169-
{
170-
// Delegate to PspSoftFuseChain's deserializer
171-
let chain = PspSoftFuseChain::deserialize(
172-
serde::de::value::MapAccessDeserializer::new(map),
173-
)?;
174-
Ok(SerdePspEntrySourceValue::PspSoftFuseChain(chain))
175-
}
176-
fn visit_i64<E: serde::de::Error>(
177-
self,
178-
value: i64,
179-
) -> core::result::Result<Self::Value, E> {
180-
if value >= 0 {
181-
Ok(SerdePspEntrySourceValue::PspSoftFuseChain(
182-
PspSoftFuseChain::from(value as u64),
183-
))
184-
} else {
185-
Err(E::invalid_value(
186-
serde::de::Unexpected::Signed(value),
187-
&"a positive integer or PspSoftFuseChain",
188-
))
189-
}
190-
}
191-
fn visit_u64<E: serde::de::Error>(
192-
self,
193-
value: u64,
194-
) -> core::result::Result<Self::Value, E> {
195-
Ok(SerdePspEntrySourceValue::PspSoftFuseChain(
196-
PspSoftFuseChain::from(value),
197-
))
198-
}
199-
}
200-
deserializer.deserialize_any(ModeVisitor)
201-
}
202-
}
203-
204224
#[derive(Clone, serde::Serialize, serde::Deserialize, schemars::JsonSchema)]
205225
#[serde(rename = "PspEntrySource")]
206226
#[serde(deny_unknown_fields)]

src/main.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,30 @@ fn test_bitfield_serde() {
5757
assert_eq!(result.address_mode(), AddressMode::PhysicalAddress);
5858
}
5959

60+
#[test]
61+
fn test_valid_compat_serde_psp_entry_source_value_deserialization() {
62+
let json = "123";
63+
let _result = serde_json::from_str::<SerdePspEntrySourceValue>(json).unwrap();
64+
}
65+
66+
#[test]
67+
fn test_valid_serde_psp_entry_source_value_deserialization() {
68+
let json = r#"{"PspSoftFuseChain": {"early_secure_debug_unlock": true, "spi_decoding": "LowerHalf", "postcode_decoding": "Lpc"}}"#;
69+
let _result = serde_json::from_str::<SerdePspEntrySourceValue>(json).unwrap();
70+
}
71+
72+
#[test]
73+
fn test_invalid_string_deserialization() {
74+
let json = r#""x""#;
75+
assert!(serde_json::from_str::<SerdePspEntrySourceValue>(json).is_err());
76+
}
77+
78+
#[test]
79+
fn test_invalid_wrong_key_name() {
80+
let json = r#"{"WrongName": {"some": "data"}}"#;
81+
assert!(serde_json::from_str::<SerdePspEntrySourceValue>(json).is_err());
82+
}
83+
6084
mod hole;
6185
use hole::Hole;
6286

0 commit comments

Comments
 (0)