mirror of https://github.com/dnaka91/obws
Fix bitflag structs not being serialized as number
parent
62248b741c
commit
d889caad8f
@ -1,128 +0,0 @@
|
||||
use std::{
|
||||
fmt::{self, Display},
|
||||
marker::PhantomData,
|
||||
};
|
||||
|
||||
use serde::{
|
||||
de::{self, Deserializer, Visitor},
|
||||
ser::Serializer,
|
||||
};
|
||||
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
enum Error {
|
||||
#[error("value is too large for an u8: {0}")]
|
||||
ValueTooLarge(#[source] std::num::TryFromIntError),
|
||||
#[error("conversion from integer failed: {0}")]
|
||||
IntConversionFailed(String),
|
||||
}
|
||||
|
||||
pub fn serialize<S, T>(value: &T, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
T: Into<u8> + Copy,
|
||||
{
|
||||
serializer.serialize_u8((*value).into())
|
||||
}
|
||||
|
||||
pub fn deserialize<'de, D, T, TE>(deserializer: D) -> Result<T, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
T: TryFrom<u8, Error = TE>,
|
||||
TE: Display,
|
||||
{
|
||||
deserializer.deserialize_u8(BitflagsU8Visitor { flags: PhantomData })
|
||||
}
|
||||
|
||||
struct BitflagsU8Visitor<T, TE> {
|
||||
flags: PhantomData<(T, TE)>,
|
||||
}
|
||||
|
||||
impl<'de, T, TE> Visitor<'de> for BitflagsU8Visitor<T, TE>
|
||||
where
|
||||
T: TryFrom<u8, Error = TE>,
|
||||
TE: Display,
|
||||
{
|
||||
type Value = T;
|
||||
|
||||
fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
formatter.write_str("bitflags encoded as u8 integer")
|
||||
}
|
||||
|
||||
fn visit_i64<E>(self, v: i64) -> Result<Self::Value, E>
|
||||
where
|
||||
E: de::Error,
|
||||
{
|
||||
u8::try_from(v)
|
||||
.map_err(|e| de::Error::custom(Error::ValueTooLarge(e)))
|
||||
.and_then(|v| self.visit_u8(v))
|
||||
}
|
||||
|
||||
fn visit_u8<E>(self, v: u8) -> Result<Self::Value, E>
|
||||
where
|
||||
E: de::Error,
|
||||
{
|
||||
T::try_from(v).map_err(|e| de::Error::custom(Error::IntConversionFailed(e.to_string())))
|
||||
}
|
||||
|
||||
fn visit_u64<E>(self, v: u64) -> Result<Self::Value, E>
|
||||
where
|
||||
E: de::Error,
|
||||
{
|
||||
u8::try_from(v)
|
||||
.map_err(|e| de::Error::custom(Error::ValueTooLarge(e)))
|
||||
.and_then(|v| self.visit_u8(v))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use bitflags::bitflags;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_test::{assert_tokens, Token};
|
||||
|
||||
bitflags! {
|
||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||
struct Flags: u8 {
|
||||
const ONE = 1;
|
||||
const TWO = 2;
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Flags> for u8 {
|
||||
fn from(value: Flags) -> Self {
|
||||
value.bits()
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<u8> for Flags {
|
||||
type Error = crate::Error;
|
||||
|
||||
fn try_from(value: u8) -> Result<Self, Self::Error> {
|
||||
Self::from_bits(value).ok_or(Self::Error::UnknownFlags(value))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Serialize, Deserialize)]
|
||||
struct SimpleFlags {
|
||||
#[serde(with = "super")]
|
||||
value: Flags,
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn roundtrip() {
|
||||
assert_tokens(
|
||||
&SimpleFlags {
|
||||
value: Flags::ONE | Flags::TWO,
|
||||
},
|
||||
&[
|
||||
Token::Struct {
|
||||
name: "SimpleFlags",
|
||||
len: 1,
|
||||
},
|
||||
Token::Str("value"),
|
||||
Token::U8(3),
|
||||
Token::StructEnd,
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
use anyhow::Result;
|
||||
use obws::requests::EventSubscription;
|
||||
|
||||
use crate::common;
|
||||
|
||||
#[tokio::test]
|
||||
async fn client() -> Result<()> {
|
||||
let client = common::new_client().await?;
|
||||
|
||||
client.reidentify(EventSubscription::ALL).await?;
|
||||
|
||||
Ok(())
|
||||
}
|
Loading…
Reference in New Issue