mirror of https://github.com/dnaka91/obws
You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
262 lines
6.5 KiB
Rust
262 lines
6.5 KiB
Rust
use chrono::Duration;
|
|
use rgb::RGBA8;
|
|
use serde::ser::{self, Serializer};
|
|
|
|
#[derive(Debug, thiserror::Error)]
|
|
enum Error {
|
|
#[error("duration of {} days is too big to be serialized as nanoseconds", .0.num_days())]
|
|
DurationTooBig(Duration),
|
|
}
|
|
|
|
pub fn duration_millis_opt<S>(value: &Option<Duration>, serializer: S) -> Result<S::Ok, S::Error>
|
|
where
|
|
S: Serializer,
|
|
{
|
|
match value {
|
|
Some(duration) => serializer.serialize_some(&duration.num_milliseconds()),
|
|
None => serializer.serialize_none(),
|
|
}
|
|
}
|
|
|
|
pub fn duration_millis<S>(value: &Duration, serializer: S) -> Result<S::Ok, S::Error>
|
|
where
|
|
S: Serializer,
|
|
{
|
|
serializer.serialize_i64(value.num_milliseconds())
|
|
}
|
|
|
|
pub fn duration_nanos<S>(value: &Duration, serializer: S) -> Result<S::Ok, S::Error>
|
|
where
|
|
S: Serializer,
|
|
{
|
|
match value.num_nanoseconds() {
|
|
Some(nanos) => serializer.serialize_i64(nanos),
|
|
None => Err(ser::Error::custom(Error::DurationTooBig(*value))),
|
|
}
|
|
}
|
|
|
|
pub fn bitflags_u8_opt<S, T>(value: &Option<T>, serializer: S) -> Result<S::Ok, S::Error>
|
|
where
|
|
S: Serializer,
|
|
T: Into<u8> + Copy,
|
|
{
|
|
match value {
|
|
Some(flags) => serializer.serialize_some(&(*flags).into()),
|
|
None => serializer.serialize_none(),
|
|
}
|
|
}
|
|
|
|
pub fn rgba8_inverse_opt<S>(value: &Option<RGBA8>, serializer: S) -> Result<S::Ok, S::Error>
|
|
where
|
|
S: Serializer,
|
|
{
|
|
match value {
|
|
Some(rgba) => {
|
|
let abgr = (rgba.a as u32) << 24
|
|
| (rgba.b as u32) << 16
|
|
| (rgba.g as u32) << 8
|
|
| (rgba.r as u32);
|
|
serializer.serialize_some(&abgr)
|
|
}
|
|
None => serializer.serialize_none(),
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use bitflags::bitflags;
|
|
use serde::Serialize;
|
|
use serde_test::{assert_ser_tokens, assert_ser_tokens_error, Token};
|
|
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn ser_duration_millis_opt() {
|
|
#[derive(Serialize)]
|
|
struct SimpleDuration {
|
|
#[serde(serialize_with = "duration_millis_opt")]
|
|
value: Option<Duration>,
|
|
}
|
|
|
|
assert_ser_tokens(
|
|
&SimpleDuration {
|
|
value: Some(Duration::milliseconds(150)),
|
|
},
|
|
&[
|
|
Token::Struct {
|
|
name: "SimpleDuration",
|
|
len: 1,
|
|
},
|
|
Token::Str("value"),
|
|
Token::Some,
|
|
Token::I64(150),
|
|
Token::StructEnd,
|
|
],
|
|
);
|
|
|
|
assert_ser_tokens(
|
|
&SimpleDuration { value: None },
|
|
&[
|
|
Token::Struct {
|
|
name: "SimpleDuration",
|
|
len: 1,
|
|
},
|
|
Token::Str("value"),
|
|
Token::None,
|
|
Token::StructEnd,
|
|
],
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn ser_duration_millis() {
|
|
#[derive(Serialize)]
|
|
struct SimpleDuration {
|
|
#[serde(serialize_with = "duration_millis")]
|
|
value: Duration,
|
|
}
|
|
|
|
assert_ser_tokens(
|
|
&SimpleDuration {
|
|
value: Duration::milliseconds(150),
|
|
},
|
|
&[
|
|
Token::Struct {
|
|
name: "SimpleDuration",
|
|
len: 1,
|
|
},
|
|
Token::Str("value"),
|
|
Token::I64(150),
|
|
Token::StructEnd,
|
|
],
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn ser_duration_nanos() {
|
|
#[derive(Serialize)]
|
|
struct SimpleDuration {
|
|
#[serde(serialize_with = "duration_nanos")]
|
|
value: Duration,
|
|
}
|
|
|
|
assert_ser_tokens(
|
|
&SimpleDuration {
|
|
value: Duration::nanoseconds(150),
|
|
},
|
|
&[
|
|
Token::Struct {
|
|
name: "SimpleDuration",
|
|
len: 1,
|
|
},
|
|
Token::Str("value"),
|
|
Token::I64(150),
|
|
Token::StructEnd,
|
|
],
|
|
);
|
|
|
|
assert_ser_tokens_error(
|
|
&SimpleDuration {
|
|
value: Duration::days(365_000_000),
|
|
},
|
|
&[
|
|
Token::Struct {
|
|
name: "SimpleDuration",
|
|
len: 1,
|
|
},
|
|
Token::Str("value"),
|
|
],
|
|
"duration of 365000000 days is too big to be serialized as nanoseconds",
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn ser_bitflags_u8_opt() {
|
|
bitflags! {
|
|
struct Flags: u8 {
|
|
const ONE = 1;
|
|
const TWO = 2;
|
|
}
|
|
}
|
|
|
|
impl From<Flags> for u8 {
|
|
fn from(value: Flags) -> Self {
|
|
value.bits
|
|
}
|
|
}
|
|
|
|
#[derive(Serialize)]
|
|
struct SimpleFlags {
|
|
#[serde(serialize_with = "bitflags_u8_opt")]
|
|
value: Option<Flags>,
|
|
}
|
|
|
|
assert_ser_tokens(
|
|
&SimpleFlags {
|
|
value: Some(Flags::ONE | Flags::TWO),
|
|
},
|
|
&[
|
|
Token::Struct {
|
|
name: "SimpleFlags",
|
|
len: 1,
|
|
},
|
|
Token::Str("value"),
|
|
Token::Some,
|
|
Token::U8(3),
|
|
Token::StructEnd,
|
|
],
|
|
);
|
|
|
|
assert_ser_tokens(
|
|
&SimpleFlags { value: None },
|
|
&[
|
|
Token::Struct {
|
|
name: "SimpleFlags",
|
|
len: 1,
|
|
},
|
|
Token::Str("value"),
|
|
Token::None,
|
|
Token::StructEnd,
|
|
],
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn ser_rgba8_inverse_opt() {
|
|
#[derive(Serialize)]
|
|
struct SimpleDuration {
|
|
#[serde(serialize_with = "rgba8_inverse_opt")]
|
|
value: Option<RGBA8>,
|
|
}
|
|
|
|
assert_ser_tokens(
|
|
&SimpleDuration {
|
|
value: Some(RGBA8::new(1, 2, 3, 4)),
|
|
},
|
|
&[
|
|
Token::Struct {
|
|
name: "SimpleDuration",
|
|
len: 1,
|
|
},
|
|
Token::Str("value"),
|
|
Token::Some,
|
|
Token::U32(0x04030201),
|
|
Token::StructEnd,
|
|
],
|
|
);
|
|
|
|
assert_ser_tokens(
|
|
&SimpleDuration { value: None },
|
|
&[
|
|
Token::Struct {
|
|
name: "SimpleDuration",
|
|
len: 1,
|
|
},
|
|
Token::Str("value"),
|
|
Token::None,
|
|
Token::StructEnd,
|
|
],
|
|
);
|
|
}
|
|
}
|