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.
obws/src/requests/ser.rs

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,
],
);
}
}