blob: 82555fdc5eb171884dd9408417a87817f606b234 [file] [log] [blame]
// Copyright 2024 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//! Helpers to serialize fuchsia_audio types with serde.
use fidl_fuchsia_audio_device as fadevice;
use fuchsia_audio::{
dai::{DaiFormatSet, DaiFrameFormat, DaiSampleFormat},
device::{ClockDomain, GainCapabilities, GainState, PlugEvent, PlugState},
format::SampleType,
format_set::{ChannelAttributes, ChannelSet, PcmFormatSet},
};
use fuchsia_zircon_types as zx_types;
use serde::{
ser::{SerializeMap, SerializeSeq},
Serialize, Serializer,
};
use std::collections::BTreeMap;
/// Serialize an value that can be converted to a string to the string.
pub fn serialize_tostring<S>(value: &impl ToString, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
serializer.serialize_str(&value.to_string())
}
/// Serialize an optional value that can be converted to a string to either the string, or none.
pub fn serialize_option_tostring<S>(
value: &Option<impl ToString>,
serializer: S,
) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let Some(value) = value else { return serializer.serialize_none() };
serializer.serialize_str(&value.to_string())
}
/// Serialize a vector of values that can be converted to a string to either a sequence
/// of strings, or none.
pub fn serialize_vec_tostring<S>(
value: &Vec<impl ToString>,
serializer: S,
) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let mut seq = serializer.serialize_seq(Some(value.len()))?;
for item in value {
seq.serialize_element(&item.to_string())?;
}
seq.end()
}
/// Serialize an optional [ClockDomain] to its number value, or none.
pub fn serialize_option_clockdomain<S>(
clock_domain: &Option<ClockDomain>,
serializer: S,
) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let Some(clock_domain) = clock_domain else { return serializer.serialize_none() };
serializer.serialize_u32(clock_domain.0)
}
// Mirror type for serialization.
// This exists to avoid the fuchsia-audio library from depending on serde.
#[derive(Serialize)]
#[serde(remote = "GainState")]
pub struct GainStateDef {
pub gain_db: f32,
pub muted: Option<bool>,
pub agc_enabled: Option<bool>,
}
pub fn serialize_option_gainstate<S>(
gain_state: &Option<GainState>,
serializer: S,
) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let Some(gain_state) = gain_state else { return serializer.serialize_none() };
GainStateDef::serialize(gain_state, serializer)
}
// Mirror type for serialization.
// This exists to avoid the fuchsia-audio library from depending on serde.
#[derive(Serialize)]
#[serde(remote = "GainCapabilities")]
pub struct GainCapabilitiesDef {
pub min_gain_db: f32,
pub max_gain_db: f32,
pub gain_step_db: f32,
pub can_mute: Option<bool>,
pub can_agc: Option<bool>,
}
pub fn serialize_option_gaincapabilities<S>(
gain_caps: &Option<GainCapabilities>,
serializer: S,
) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let Some(gain_caps) = gain_caps else { return serializer.serialize_none() };
GainCapabilitiesDef::serialize(gain_caps, serializer)
}
// Mirror type for serialization.
// This exists to avoid the fuchsia-audio library from depending on serde.
#[derive(Serialize)]
#[serde(remote = "PcmFormatSet")]
pub struct PcmFormatSetDef {
#[serde(serialize_with = "serialize_vec_channelset")]
pub channel_sets: Vec<ChannelSet>,
#[serde(serialize_with = "serialize_vec_tostring")]
pub sample_types: Vec<SampleType>,
pub frame_rates: Vec<u32>,
}
pub fn serialize_vec_pcmformatset<S>(
pcm_format_sets: &Vec<PcmFormatSet>,
serializer: S,
) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
#[derive(Serialize)]
struct Wrapper<'a>(#[serde(with = "PcmFormatSetDef")] &'a PcmFormatSet);
let mut seq = serializer.serialize_seq(Some(pcm_format_sets.len()))?;
for pcm_format_set in pcm_format_sets {
seq.serialize_element(&Wrapper(pcm_format_set))?;
}
seq.end()
}
pub fn serialize_option_map_pcmformatset<S>(
format_set_map: &Option<BTreeMap<fadevice::ElementId, Vec<PcmFormatSet>>>,
serializer: S,
) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let Some(format_set_map) = format_set_map else { return serializer.serialize_none() };
#[derive(Serialize)]
struct Wrapper<'a>(
#[serde(serialize_with = "serialize_vec_pcmformatset")] &'a Vec<PcmFormatSet>,
);
let mut map = serializer.serialize_map(Some(format_set_map.len()))?;
for (key, value) in format_set_map {
map.serialize_entry(key, &Wrapper(value))?;
}
map.end()
}
// Mirror type for serialization.
// This exists to avoid the fuchsia-audio library from depending on serde.
#[derive(Serialize)]
#[serde(remote = "ChannelSet")]
pub struct ChannelSetDef {
#[serde(serialize_with = "serialize_vec_channelattributes")]
pub attributes: Vec<ChannelAttributes>,
}
pub fn serialize_vec_channelset<S>(
channel_sets: &Vec<ChannelSet>,
serializer: S,
) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
#[derive(Serialize)]
struct Wrapper<'a>(#[serde(with = "ChannelSetDef")] &'a ChannelSet);
let mut seq = serializer.serialize_seq(Some(channel_sets.len()))?;
for channel_set in channel_sets {
seq.serialize_element(&Wrapper(channel_set))?;
}
seq.end()
}
// Mirror type for serialization.
// This exists to avoid the fuchsia-audio library from depending on serde.
#[derive(Serialize)]
#[serde(remote = "ChannelAttributes")]
pub struct ChannelAttributesDef {
pub min_frequency: Option<u32>,
pub max_frequency: Option<u32>,
}
pub fn serialize_vec_channelattributes<S>(
channel_attributes: &Vec<ChannelAttributes>,
serializer: S,
) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
#[derive(Serialize)]
struct Wrapper<'a>(#[serde(with = "ChannelAttributesDef")] &'a ChannelAttributes);
let mut seq = serializer.serialize_seq(Some(channel_attributes.len()))?;
for attributes in channel_attributes {
seq.serialize_element(&Wrapper(attributes))?;
}
seq.end()
}
// Mirror type for serialization.
// This exists to avoid the fuchsia-audio library from depending on serde.
#[derive(Serialize)]
#[serde(remote = "DaiFormatSet")]
pub struct DaiFormatSetDef {
number_of_channels: Vec<u32>,
#[serde(serialize_with = "serialize_vec_tostring")]
sample_formats: Vec<DaiSampleFormat>,
#[serde(serialize_with = "serialize_vec_tostring")]
frame_formats: Vec<DaiFrameFormat>,
frame_rates: Vec<u32>,
bits_per_slot: Vec<u8>,
bits_per_sample: Vec<u8>,
}
pub fn serialize_vec_daiformatset<S>(
dai_format_sets: &Vec<DaiFormatSet>,
serializer: S,
) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
#[derive(Serialize)]
struct Wrapper<'a>(#[serde(with = "DaiFormatSetDef")] &'a DaiFormatSet);
let mut seq = serializer.serialize_seq(Some(dai_format_sets.len()))?;
for dai_format_set in dai_format_sets {
seq.serialize_element(&Wrapper(dai_format_set))?;
}
seq.end()
}
pub fn serialize_option_map_daiformatset<S>(
format_set_map: &Option<BTreeMap<fadevice::ElementId, Vec<DaiFormatSet>>>,
serializer: S,
) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let Some(format_set_map) = format_set_map else { return serializer.serialize_none() };
#[derive(Serialize)]
struct Wrapper<'a>(
#[serde(serialize_with = "serialize_vec_daiformatset")] &'a Vec<DaiFormatSet>,
);
let mut map = serializer.serialize_map(Some(format_set_map.len()))?;
for (key, value) in format_set_map {
map.serialize_entry(key, &Wrapper(value))?;
}
map.end()
}
// Mirror type for serialization.
// This exists to avoid the fuchsia-audio library from depending on serde.
#[derive(Serialize)]
#[serde(remote = "PlugEvent")]
pub struct PlugEventDef {
#[serde(serialize_with = "serialize_tostring")]
pub state: PlugState,
pub time: zx_types::zx_time_t,
}
pub fn serialize_option_plugevent<S>(
plug_event: &Option<PlugEvent>,
serializer: S,
) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let Some(plug_event) = plug_event else { return serializer.serialize_none() };
PlugEventDef::serialize(plug_event, serializer)
}