mirror of
https://github.com/starship/starship.git
synced 2026-06-21 02:02:14 +07:00
chore(serde): support enum deserialization (#3941)
This commit is contained in:
+101
-2
@@ -1,6 +1,6 @@
|
||||
use crate::module::ALL_MODULES;
|
||||
use serde::de::{
|
||||
Deserializer, Error, IntoDeserializer, Visitor,
|
||||
self, Deserializer, Error, IntoDeserializer, Visitor,
|
||||
value::{Error as ValueError, MapDeserializer, SeqDeserializer},
|
||||
};
|
||||
use std::{cmp::Ordering, fmt};
|
||||
@@ -100,6 +100,20 @@ impl ValueDeserializer<'_> {
|
||||
_ => ValueError::custom(msg),
|
||||
}
|
||||
}
|
||||
|
||||
/// Return the fitting `de::Unexpected` type description for the given value.
|
||||
/// For use with `Error::invalid_type`.
|
||||
fn serde_unexpected(&self) -> de::Unexpected<'_> {
|
||||
match self.value {
|
||||
ValueRef::Boolean(b) => de::Unexpected::Bool(b),
|
||||
ValueRef::Integer(i) => de::Unexpected::Signed(i),
|
||||
ValueRef::Float(f) => de::Unexpected::Float(f),
|
||||
ValueRef::String(s) => de::Unexpected::Str(s),
|
||||
ValueRef::Array(_v) => de::Unexpected::Other("array"),
|
||||
ValueRef::Table(_v) => de::Unexpected::Other("table"),
|
||||
ValueRef::Datetime(_v) => de::Unexpected::Other("datetime"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> IntoDeserializer<'de> for ValueDeserializer<'de> {
|
||||
@@ -215,10 +229,29 @@ impl<'de> Deserializer<'de> for ValueDeserializer<'de> {
|
||||
visitor.visit_newtype_struct(self)
|
||||
}
|
||||
|
||||
fn deserialize_enum<V>(
|
||||
self,
|
||||
_name: &'static str,
|
||||
_variants: &'static [&'static str],
|
||||
visitor: V,
|
||||
) -> Result<V::Value, Self::Error>
|
||||
where
|
||||
V: Visitor<'de>,
|
||||
{
|
||||
match self.value {
|
||||
// de::Value::StrDeserializer implements de::EnumAccess, so we can just use it.
|
||||
ValueRef::String(s) => visitor.visit_enum(s.into_deserializer()),
|
||||
_ => Err(Self::Error::invalid_type(
|
||||
self.serde_unexpected(),
|
||||
&"string",
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
// Handle most deserialization cases by deferring to `deserialize_any`.
|
||||
serde::forward_to_deserialize_any! {
|
||||
bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string unit seq
|
||||
bytes byte_buf map unit_struct tuple_struct enum tuple identifier
|
||||
bytes byte_buf map unit_struct tuple_struct tuple identifier
|
||||
}
|
||||
}
|
||||
|
||||
@@ -350,6 +383,72 @@ mod test {
|
||||
assert_eq!(result.foo.0, "bar".to_owned());
|
||||
}
|
||||
|
||||
#[derive(Deserialize, PartialEq, Debug)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
enum SampleEnum {
|
||||
FirstItem,
|
||||
Second,
|
||||
ThirdItem,
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_deserialize_enum() {
|
||||
#[derive(Deserialize)]
|
||||
struct Sample {
|
||||
foo: SampleEnum,
|
||||
}
|
||||
|
||||
let value = toml::toml! {
|
||||
foo = "first_item"
|
||||
};
|
||||
|
||||
let deserializer = ValueDeserializer::new(&value);
|
||||
|
||||
let result = Sample::deserialize(deserializer).unwrap();
|
||||
assert_eq!(result.foo, SampleEnum::FirstItem);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_deserialize_enum_unknown() {
|
||||
#[derive(Deserialize)]
|
||||
#[allow(dead_code)]
|
||||
struct Sample {
|
||||
foo: SampleEnum,
|
||||
}
|
||||
|
||||
let value = toml::toml! {
|
||||
foo = "unknown"
|
||||
};
|
||||
|
||||
let deserializer = ValueDeserializer::new(&value);
|
||||
|
||||
let result = Sample::deserialize(deserializer);
|
||||
assert!(result.is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_deserialize_enum_invalid_type() {
|
||||
#[derive(Deserialize, PartialEq, Debug)]
|
||||
#[allow(dead_code)]
|
||||
struct Sample {
|
||||
foo: SampleEnum,
|
||||
}
|
||||
|
||||
let value = toml::toml! {
|
||||
foo = 1
|
||||
};
|
||||
|
||||
let deserializer = ValueDeserializer::new(&value);
|
||||
|
||||
let result = Sample::deserialize(deserializer);
|
||||
assert_eq!(
|
||||
result,
|
||||
Err(serde::de::Error::custom(
|
||||
"invalid type: integer `1`, expected string"
|
||||
))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_deserialize_unknown() {
|
||||
let value = toml::toml! {
|
||||
|
||||
Reference in New Issue
Block a user