blob: 12592926398ac53fa2bf68d0e569e4f28c9d4fdb [file] [log] [blame]
// Copyright 2019 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.
use anyhow::format_err;
use base64;
use fidl_fuchsia_images::{AlphaFormat, ColorSpace, ImageInfo, PixelFormat, Tiling, Transform};
use fidl_fuchsia_intl::{CalendarId, LocaleId, Profile, TemperatureUnit, TimeZoneId};
use fidl_fuchsia_mem::Buffer;
use fidl_fuchsia_ui_app::ViewConfig;
use fidl_fuchsia_ui_scenic::ScreenshotData;
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use std::collections::BTreeMap;
/// Enum for supported FIDL commands.
pub enum ScenicMethod {
TakeScreenshot,
PresentView,
}
impl std::str::FromStr for ScenicMethod {
type Err = anyhow::Error;
fn from_str(method: &str) -> Result<Self, Self::Err> {
match method {
"TakeScreenshot" => Ok(ScenicMethod::TakeScreenshot),
"PresentView" => Ok(ScenicMethod::PresentView),
_ => return Err(format_err!("invalid Scenic FIDL method: {}", method)),
}
}
}
#[derive(Serialize, Deserialize, Debug)]
#[serde(remote = "Transform")]
pub enum TransformDef {
Normal = 0,
FlipHorizontal = 1,
FlipVertical = 2,
FlipVerticalAndHorizontal = 3,
}
#[derive(Serialize, Deserialize, Debug)]
#[serde(remote = "PixelFormat")]
pub enum PixelFormatDef {
Bgra8 = 0,
Yuy2 = 1,
Nv12 = 2,
Yv12 = 3,
R8G8B8A8 = 4,
}
#[derive(Serialize, Deserialize, Debug)]
#[serde(remote = "ColorSpace")]
pub enum ColorSpaceDef {
Srgb = 0,
}
#[derive(Serialize, Deserialize, Debug)]
#[serde(remote = "Tiling")]
pub enum TilingDef {
Linear = 0,
GpuOptimal = 1,
}
#[derive(Serialize, Deserialize, Debug)]
#[serde(remote = "AlphaFormat")]
pub enum AlphaFormatDef {
Opaque = 0,
Premultiplied = 1,
NonPremultiplied = 2,
}
#[derive(Serialize, Deserialize, Debug)]
#[serde(remote = "ImageInfo")]
pub struct ImageInfoDef {
#[serde(with = "TransformDef")]
pub transform: Transform,
pub width: u32,
pub height: u32,
pub stride: u32,
#[serde(with = "PixelFormatDef")]
pub pixel_format: PixelFormat,
#[serde(with = "ColorSpaceDef")]
pub color_space: ColorSpace,
#[serde(with = "TilingDef")]
pub tiling: Tiling,
#[serde(with = "AlphaFormatDef")]
pub alpha_format: AlphaFormat,
}
fn serialize_buffer<S>(buffer: &Buffer, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let mut data = vec![0; buffer.size as usize];
use serde::ser::Error;
buffer.vmo.read(&mut data, 0).map_err(Error::custom)?;
serializer.serialize_str(&base64::encode(&data))
}
#[derive(Serialize, Debug)]
pub struct ScreenshotDataDef {
#[serde(with = "ImageInfoDef")]
pub info: ImageInfo,
#[serde(serialize_with = "serialize_buffer")]
pub data: Buffer,
}
impl ScreenshotDataDef {
pub fn new(screenshot_data: ScreenshotData) -> ScreenshotDataDef {
ScreenshotDataDef { info: screenshot_data.info, data: screenshot_data.data }
}
}
// https://github.com/serde-rs/serde/issues/723
macro_rules! remote_vec {
($remote:ident with=$def:ident) => {
impl $def {
fn opt_vec<'de, D>(deserializer: D) -> Result<Option<Vec<$remote>>, D::Error>
where
D: Deserializer<'de>,
{
#[derive(Deserialize)]
struct Wrapper(#[serde(deserialize_with = "deserialize_element")] $remote);
fn deserialize_element<'de, D>(deserializer: D) -> Result<$remote, D::Error>
where
D: Deserializer<'de>,
{
$def::deserialize(deserializer)
}
let o: Option<Vec<Wrapper>> = Deserialize::deserialize(deserializer)?;
Ok(o.map(|v| v.into_iter().map(|Wrapper(a)| a).collect()))
}
}
};
}
// https://github.com/serde-rs/serde/issues/723
macro_rules! remote_optional {
($remote:ident with=$def:ident) => {
impl $def {
fn deserialize_option<'de, D>(deserializer: D) -> Result<Option<$remote>, D::Error>
where
D: Deserializer<'de>,
{
use $def as Def;
#[derive(Deserialize)]
struct Wrapper(#[serde(with = "Def")] $remote);
let v: Option<Wrapper> = Option::deserialize(deserializer)?;
Ok(v.map(|Wrapper(a)| a))
}
}
};
}
#[derive(Serialize, Deserialize, Debug)]
#[serde(remote = "LocaleId")]
pub struct LocaleIdDef {
pub id: String,
}
#[derive(Serialize, Deserialize, Debug)]
#[serde(remote = "CalendarId")]
pub struct CalendarIdDef {
pub id: String,
}
#[derive(Serialize, Deserialize, Debug)]
#[serde(remote = "TimeZoneId")]
pub struct TimeZoneIdDef {
pub id: String,
}
#[derive(Serialize, Deserialize, Debug)]
#[serde(remote = "TemperatureUnit")]
pub enum TemperatureUnitDef {
Celsius = 0,
Fahrenheit = 1,
}
remote_vec!(LocaleId with=LocaleIdDef);
remote_vec!(CalendarId with=CalendarIdDef);
remote_vec!(TimeZoneId with=TimeZoneIdDef);
remote_optional!(TemperatureUnit with=TemperatureUnitDef);
remote_optional!(ViewConfig with=ViewConfigDef);
// TODO(fxbug.dev/59274): Do not use Serde remote for FIDL tables.
#[derive(Deserialize, Debug)]
#[serde(remote = "Profile")]
pub struct ProfileDef {
#[serde(default, deserialize_with = "LocaleIdDef::opt_vec")]
pub locales: Option<Vec<LocaleId>>,
#[serde(default, deserialize_with = "CalendarIdDef::opt_vec")]
pub calendars: Option<Vec<CalendarId>>,
#[serde(default, deserialize_with = "TimeZoneIdDef::opt_vec")]
pub time_zones: Option<Vec<TimeZoneId>>,
#[serde(default, deserialize_with = "TemperatureUnitDef::deserialize_option")]
pub temperature_unit: Option<TemperatureUnit>,
// These fields are needed to match the FIDL-generated struct exactly. They
// should be removed once we are no longer using Serde remote.
#[serde(skip)]
unknown_data: Option<BTreeMap<u64, Vec<u8>>>,
#[serde(skip)]
__non_exhaustive: (),
}
#[derive(Deserialize, Debug)]
#[serde(remote = "ViewConfig")]
pub struct ViewConfigDef {
#[serde(with = "ProfileDef")]
pub intl_profile: Profile,
}
#[derive(Deserialize, Debug)]
pub struct PresentViewRequest {
pub url: String,
#[serde(default, deserialize_with = "ViewConfigDef::deserialize_option")]
pub config: Option<ViewConfig>,
}