From d889caad8f185ff8f3c58aaa2dc9554658b79e55 Mon Sep 17 00:00:00 2001 From: Dominik Nakamura Date: Thu, 22 Jun 2023 10:22:02 +0900 Subject: [PATCH] Fix bitflag structs not being serialized as number --- CHANGELOG.md | 4 + deny.toml | 3 - src/common.rs | 9 +- src/requests/custom/source_settings.rs | 1 - src/requests/mod.rs | 8 +- src/requests/ui.rs | 1 + src/responses/scene_items.rs | 4 +- src/serde/bitflags_u8.rs | 128 ------------------------- src/serde/mod.rs | 1 - tests/integration/client.rs | 13 +++ tests/integration/main.rs | 1 + 11 files changed, 34 insertions(+), 139 deletions(-) delete mode 100644 src/serde/bitflags_u8.rs create mode 100644 tests/integration/client.rs diff --git a/CHANGELOG.md b/CHANGELOG.md index e194cf9..f895c56 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] - ReleaseDate +### Fixed + +- Some of the bitflag values like `FontFlags`, `Alignment` and `EventSubscription` were not always serialized as numbers but their string form, causing errors in the respective request or response. + ## [0.11.1] - 2023-05-22 ### Added diff --git a/deny.toml b/deny.toml index acfc923..8d18dbd 100644 --- a/deny.toml +++ b/deny.toml @@ -22,6 +22,3 @@ version = "*" skip = [ { name = "regex-syntax", version = "=0.6.29" }, ] -skip-tree = [ - { name = "windows-sys", version = "=0.45.0", depth = 3 }, -] diff --git a/src/common.rs b/src/common.rs index 4a38b1a..e6f20ad 100644 --- a/src/common.rs +++ b/src/common.rs @@ -7,7 +7,7 @@ use crate::Error; /// Monitoring type for audio outputs. #[derive( - Clone, Copy, Debug, Default, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize, + Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd, Deserialize, Serialize, )] #[non_exhaustive] pub enum MonitorType { @@ -25,7 +25,10 @@ pub enum MonitorType { bitflags! { /// Different flags for font display that can be combined. - #[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] + #[derive( + Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd, Deserialize, Serialize, + )] + #[serde(try_from = "u8", into = "u8")] pub struct FontFlags: u8 { /// Make the text appear thicker. const BOLD = 1; @@ -62,7 +65,7 @@ bitflags! { #[derive( Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd, Deserialize, Serialize, )] - #[serde(transparent)] + #[serde(try_from = "u8", into = "u8")] pub struct Alignment: u8 { /// Align to the center. const CENTER = 0; diff --git a/src/requests/custom/source_settings.rs b/src/requests/custom/source_settings.rs index 66ef981..d80899c 100644 --- a/src/requests/custom/source_settings.rs +++ b/src/requests/custom/source_settings.rs @@ -532,7 +532,6 @@ pub struct Font<'a> { /// Font face. pub face: &'a str, /// Flags for different display styles. - #[serde(with = "crate::serde::bitflags_u8")] pub flags: FontFlags, /// Display size. pub size: u32, diff --git a/src/requests/mod.rs b/src/requests/mod.rs index 6c1d7c0..e55bf60 100644 --- a/src/requests/mod.rs +++ b/src/requests/mod.rs @@ -136,7 +136,7 @@ bitflags! { /// Bit flags for possible event subscriptions, that can be enabled when connecting to the OBS /// instance. #[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)] - #[serde(transparent)] + #[serde(into = "u32")] pub struct EventSubscription: u32 { /// Subscription value used to disable all events. const NONE = 0; @@ -198,6 +198,12 @@ bitflags! { } } +impl From for u32 { + fn from(value: EventSubscription) -> Self { + value.bits() + } +} + #[allow(dead_code)] #[derive(Serialize_repr)] #[repr(i8)] diff --git a/src/requests/ui.rs b/src/requests/ui.rs index 992840e..4955097 100644 --- a/src/requests/ui.rs +++ b/src/requests/ui.rs @@ -267,6 +267,7 @@ impl QtWindowState { /// │ bottom /// │ /// Y +/// ``` #[derive(Clone, Copy, Debug, Default)] pub struct QtRect { /// Left or X/horizontal position of the rectangle. diff --git a/src/responses/scene_items.rs b/src/responses/scene_items.rs index 920062d..87a8336 100644 --- a/src/responses/scene_items.rs +++ b/src/responses/scene_items.rs @@ -101,13 +101,13 @@ pub struct SceneItemTransform { #[serde(rename = "height")] pub height: f32, /// The point on the source that the item is manipulated from. - #[serde(rename = "alignment", with = "crate::serde::bitflags_u8")] + #[serde(rename = "alignment")] pub alignment: Alignment, /// Type of bounding box. #[serde(rename = "boundsType")] pub bounds_type: BoundsType, /// Alignment of the bounding box. - #[serde(rename = "boundsAlignment", with = "crate::serde::bitflags_u8")] + #[serde(rename = "boundsAlignment")] pub bounds_alignment: Alignment, /// Width of the bounding box. #[serde(rename = "boundsWidth")] diff --git a/src/serde/bitflags_u8.rs b/src/serde/bitflags_u8.rs deleted file mode 100644 index e05883a..0000000 --- a/src/serde/bitflags_u8.rs +++ /dev/null @@ -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(value: &T, serializer: S) -> Result -where - S: Serializer, - T: Into + Copy, -{ - serializer.serialize_u8((*value).into()) -} - -pub fn deserialize<'de, D, T, TE>(deserializer: D) -> Result -where - D: Deserializer<'de>, - T: TryFrom, - TE: Display, -{ - deserializer.deserialize_u8(BitflagsU8Visitor { flags: PhantomData }) -} - -struct BitflagsU8Visitor { - flags: PhantomData<(T, TE)>, -} - -impl<'de, T, TE> Visitor<'de> for BitflagsU8Visitor -where - T: TryFrom, - 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(self, v: i64) -> Result - 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(self, v: u8) -> Result - where - E: de::Error, - { - T::try_from(v).map_err(|e| de::Error::custom(Error::IntConversionFailed(e.to_string()))) - } - - fn visit_u64(self, v: u64) -> Result - 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 for u8 { - fn from(value: Flags) -> Self { - value.bits() - } - } - - impl TryFrom for Flags { - type Error = crate::Error; - - fn try_from(value: u8) -> Result { - 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, - ], - ); - } -} diff --git a/src/serde/mod.rs b/src/serde/mod.rs index 261cd07..e263cbb 100644 --- a/src/serde/mod.rs +++ b/src/serde/mod.rs @@ -1,5 +1,4 @@ pub mod audio_tracks; -pub mod bitflags_u8; pub mod duration_millis; pub mod duration_timecode; pub mod json_string; diff --git a/tests/integration/client.rs b/tests/integration/client.rs new file mode 100644 index 0000000..1a3fcbd --- /dev/null +++ b/tests/integration/client.rs @@ -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(()) +} diff --git a/tests/integration/main.rs b/tests/integration/main.rs index 0b1f8d0..4bea0bc 100644 --- a/tests/integration/main.rs +++ b/tests/integration/main.rs @@ -1,5 +1,6 @@ #![cfg(feature = "test-integration")] +mod client; mod common; mod config; mod filters;