#[derive(Deserialize, Debug, Clone)]
struct AgentDetail
{
#[serde(rename = "browser")] name: String,
#[serde(rename = "abbr")] abbreviated_name: String,
prefix: Prefix,
#[serde(rename = "type")] agent_type: AgentType,
usage_global: BTreeMap<Version, UsagePercentage>,
#[serde(deserialize_with = "AgentDetail::deserialize_version_list")] version_list: BTreeMap<Version, VersionDetail>,
current_version: Version,
#[serde(default)] prefix_exceptions: BTreeMap<Version, Prefix>
}
impl AgentDetail
{
fn deserialize_version_list<'de, D: Deserializer<'de>>(deserializer: D) -> Result<BTreeMap<Version, VersionDetail>, D::Error>
{
use de::Error as SerdeError;
enum Field
{
version,
global_usage,
release_date,
era,
prefix,
}
const FieldNames: &'static [&'static str] = &
[
"version",
"global_usage",
"release_date",
"era",
"prefix",
];
impl<'de> Deserialize<'de> for Field
{
#[inline(always)]
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Field, D::Error>
{
struct FieldVisitor;
impl<'de> Visitor<'de> for FieldVisitor
{
type Value = Field;
fn expecting(&self, formatter: &mut Formatter) -> fmt::Result
{
formatter.write_str("one of version, global_usage, release_date, era or prefix")
}
fn visit_str<E: SerdeError>(self, value: &str) -> Result<Field, E>
{
match value
{
"version" => Ok(Field::version),
"global_usage" => Ok(Field::global_usage),
"release_date" => Ok(Field::release_date),
"era" => Ok(Field::era),
"prefix" => Ok(Field::prefix),
_ => Err(SerdeError::unknown_field(value, FieldNames)),
}
}
}
deserializer.deserialize_identifier(FieldVisitor)
}
}
struct VersionListEntryDeserializeSeed<'a>(&'a mut BTreeMap<Version, VersionDetail>);
impl<'a, 'de> DeserializeSeed<'de> for VersionListEntryDeserializeSeed<'a>
{
type Value = ();
#[inline(always)]
fn deserialize<D: Deserializer<'de>>(self, deserializer: D) -> Result<Self::Value, D::Error>
{
struct VersionListEntryVisitor<'a>(&'a mut BTreeMap<Version, VersionDetail>);
impl<'a, 'de> Visitor<'de> for VersionListEntryVisitor<'a>
{
type Value = ();
#[inline(always)]
fn expecting(&self, formatter: &mut Formatter) -> fmt::Result
{
formatter.write_str("a version list entry (Version, VersionDetail)")
}
fn visit_map<A: MapAccess<'de>>(self, mut map: A) -> Result<Self::Value, A::Error>
{
let mut version = None;
let mut global_usage = None;
let mut release_date: Option<Option<u64>> = None;
let mut era = None;
let mut prefix: Option<Option<Prefix>> = None;
while let Some(field) = map.next_key()?
{
match field
{
Field::version =>
{
version = Some(map.next_value()?);
}
Field::global_usage =>
{
global_usage = Some(map.next_value()?);
}
Field::release_date =>
{
release_date = Some(map.next_value()?);
}
Field::era =>
{
era = Some(map.next_value()?);
}
Field::prefix =>
{
struct PrefixSeed;
impl<'de> DeserializeSeed<'de> for PrefixSeed
{
type Value = Option<Prefix>;
#[inline(always)]
fn deserialize<D: Deserializer<'de>>(self, deserializer: D) -> Result<Self::Value, D::Error>
{
deserializer.deserialize_str(PrefixVisitor)
}
}
prefix = Some(map.next_value_seed(PrefixSeed)?);
}
}
}
let version = version.ok_or_else(|| SerdeError::missing_field("version"))?;
let global_usage = global_usage.ok_or_else(|| SerdeError::missing_field("global_usage"))?;
let release_date_u64_optional = release_date.ok_or_else(|| SerdeError::missing_field("release_date"))?;
let era = era.ok_or_else(|| SerdeError::missing_field("era"))?;
let prefix_override = prefix.ok_or_else(|| SerdeError::missing_field("prefix"))?;
let release_date = if let Some(release_date_u64) = release_date_u64_optional
{
Some(Utc.timestamp(release_date_u64 as i64, 0))
}
else
{
None
};
self.0.insert(version, VersionDetail
{
global_usage,
release_date,
era,
prefix_override,
});
Ok(())
}
}
deserializer.deserialize_map(VersionListEntryVisitor(self.0))
}
}
struct VersionListVisitor;
impl<'de> Visitor<'de> for VersionListVisitor
{
type Value = BTreeMap<Version, VersionDetail>;
#[inline(always)]
fn expecting(&self, formatter: &mut Formatter) -> fmt::Result
{
formatter.write_str("a version list (Version, VersionDetail)")
}
fn visit_seq<A: SeqAccess<'de>>(self, mut sequence: A) -> Result<Self::Value, A::Error>
{
let mut map = BTreeMap::new();
while let Some(()) = sequence.next_element_seed(VersionListEntryDeserializeSeed(&mut map))?
{
}
Ok(map)
}
}
deserializer.deserialize_seq(VersionListVisitor)
}
}