Skip to content

Commit

Permalink
fix(jer): ENUMERATED values as strings (#242)
Browse files Browse the repository at this point in the history
  • Loading branch information
v0-e committed Apr 4, 2024
1 parent 285f004 commit b879375
Show file tree
Hide file tree
Showing 5 changed files with 52 additions and 18 deletions.
2 changes: 1 addition & 1 deletion src/error/decode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -571,7 +571,7 @@ pub enum JerDecodeErrorKind {
#[snafu(display("Failed to construct OID from value {value}",))]
InvalidOIDString { value: JsonValue },
#[snafu(display("Found invalid enumerated discriminant {discriminant}",))]
InvalidEnumDiscriminant { discriminant: isize },
InvalidEnumDiscriminant { discriminant: alloc::string::String },
}

impl JerDecodeErrorKind {
Expand Down
10 changes: 5 additions & 5 deletions src/jer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -231,11 +231,11 @@ mod tests {

#[test]
fn enumerated() {
round_trip_jer!(SimpleEnum, SimpleEnum::Test1, "5");
round_trip_jer!(SimpleEnum, SimpleEnum::Test2, "2");
round_trip_jer!(ExtEnum, ExtEnum::Test1, "5");
round_trip_jer!(ExtEnum, ExtEnum::Test2, "2");
round_trip_jer!(ExtEnum, ExtEnum::Test3, "-1");
round_trip_jer!(SimpleEnum, SimpleEnum::Test1, "\"Test1\"");
round_trip_jer!(SimpleEnum, SimpleEnum::Test2, "\"Test2\"");
round_trip_jer!(ExtEnum, ExtEnum::Test1, "\"Test1\"");
round_trip_jer!(ExtEnum, ExtEnum::Test2, "\"Test2\"");
round_trip_jer!(ExtEnum, ExtEnum::Test3, "\"Test3\"");
}

#[test]
Expand Down
20 changes: 9 additions & 11 deletions src/jer/de.rs
Original file line number Diff line number Diff line change
Expand Up @@ -408,19 +408,17 @@ impl Decoder {
}

fn enumerated_from_value<E: Enumerated>(value: JsonValue) -> Result<E, DecodeError> {
let discriminant = value
.as_i64()
let identifier = value
.as_str()
.ok_or_else(|| JerDecodeErrorKind::TypeMismatch {
needed: "enumerable index",
needed: "enumerated item as string",
found: alloc::format!("{value}"),
})?
.try_into()
.ok();
Ok(discriminant
.and_then(|i| E::from_discriminant(i))
.ok_or_else(|| JerDecodeErrorKind::InvalidEnumDiscriminant {
discriminant: discriminant.unwrap_or(isize::MIN),
})?)
})?;
Ok(E::from_identifier(identifier).ok_or_else(|| {
JerDecodeErrorKind::InvalidEnumDiscriminant {
discriminant: alloc::string::String::from(identifier),
}
})?)
}

fn integer_from_value(value: JsonValue) -> Result<Integer, DecodeError> {
Expand Down
4 changes: 3 additions & 1 deletion src/jer/enc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,9 @@ impl crate::Encoder for Encoder {
_: crate::Tag,
value: &E,
) -> Result<Self::Ok, Self::Error> {
self.update_root_or_constructed(JsonValue::Number(value.discriminant().into()))
self.update_root_or_constructed(JsonValue::String(alloc::string::String::from(
value.identifier(),
)))
}

fn encode_object_identifier(
Expand Down
34 changes: 34 additions & 0 deletions src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,40 @@ pub trait Enumerated: Sized + 'static + PartialEq + Copy + core::fmt::Debug {
fn from_extended_enumeration_index(index: usize) -> Option<Self> {
Self::EXTENDED_VARIANTS.and_then(|array| array.get(index).copied())
}

/// Returns the variant identifier
fn identifier(&self) -> &'static str {
let index = if self.is_extended_variant() {
Self::EXTENDED_VARIANTS
.unwrap()
.iter()
.position(|lhs| lhs == self)
.unwrap()
+ Self::VARIANTS.len()
} else {
Self::VARIANTS
.iter()
.position(|lhs| lhs == self)
.expect("Variant not defined in Enumerated::VARIANTS")
};
Self::IDENTIFIERS[index]
}

/// Returns a variant, if the provided identifier matches any variant.
fn from_identifier(identifier: &str) -> Option<Self> {
Self::IDENTIFIERS
.iter()
.enumerate()
.find(|id| id.1.eq(&identifier))
.and_then(|(i, _)| {
if i < Self::VARIANTS.len() {
Self::VARIANTS.get(i).copied()
} else {
Self::EXTENDED_VARIANTS
.and_then(|array| array.get(i - Self::VARIANTS.len()).copied())
}
})
}
}

/// A integer which has encoded constraint range between `START` and `END`.
Expand Down

0 comments on commit b879375

Please sign in to comment.