core/render/web: Make FromStr exclusively for snake_case

This commit is contained in:
sleepycatcoding 2024-05-13 22:34:35 +03:00
parent a5810b4703
commit be8cbd64d6
7 changed files with 106 additions and 30 deletions

View File

@ -1,4 +1,5 @@
use serde::{Deserialize, Serialize};
use std::str::FromStr;
/// Controls whether the content is letterboxed or pillarboxed when the
/// player's aspect ratio does not match the movie's aspect ratio.
@ -22,6 +23,22 @@ pub enum Letterbox {
On,
}
pub struct ParseEnumError;
impl FromStr for Letterbox {
type Err = ParseEnumError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let letterbox = match s {
"off" => Letterbox::Off,
"fullscreen" => Letterbox::Fullscreen,
"on" => Letterbox::On,
_ => return Err(ParseEnumError),
};
Ok(letterbox)
}
}
/// The networking API access mode of the Ruffle player.
/// This setting is only used on web.
#[derive(Clone, Copy, PartialEq, Serialize, Deserialize)]

View File

@ -970,11 +970,11 @@ impl FromStr for StageScaleMode {
type Err = ParseEnumError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let scale_mode = match s.to_ascii_lowercase().as_str() {
"exactfit" => StageScaleMode::ExactFit,
"noborder" => StageScaleMode::NoBorder,
"noscale" => StageScaleMode::NoScale,
"showall" => StageScaleMode::ShowAll,
let scale_mode = match s {
"exact_fit" => StageScaleMode::ExactFit,
"no_border" => StageScaleMode::NoBorder,
"no_scale" => StageScaleMode::NoScale,
"show_all" => StageScaleMode::ShowAll,
_ => return Err(ParseEnumError),
};
Ok(scale_mode)
@ -1082,21 +1082,21 @@ bitflags! {
}
impl FromStr for StageAlign {
type Err = std::convert::Infallible;
type Err = ParseEnumError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
// Chars get converted into flags.
// This means "tbbtlbltblbrllrbltlrtbl" is valid, resulting in "TBLR".
let mut align = StageAlign::default();
for c in s.bytes().map(|c| c.to_ascii_uppercase()) {
match c {
b'T' => align.insert(StageAlign::TOP),
b'B' => align.insert(StageAlign::BOTTOM),
b'L' => align.insert(StageAlign::LEFT),
b'R' => align.insert(StageAlign::RIGHT),
_ => (),
}
}
let align = match s {
"bottom" => StageAlign::BOTTOM,
"bottom_left" => StageAlign::BOTTOM | StageAlign::LEFT,
"bottom_right" => StageAlign::BOTTOM | StageAlign::RIGHT,
"left" => StageAlign::LEFT,
"right" => StageAlign::RIGHT,
"top" => StageAlign::TOP,
"top_left" => StageAlign::TOP | StageAlign::LEFT,
"top_right" => StageAlign::TOP | StageAlign::RIGHT,
"center" => StageAlign::empty(),
_ => return Err(ParseEnumError),
};
Ok(align)
}
}

View File

@ -36,6 +36,7 @@ use ruffle_render::utils::{determine_jpeg_tag_format, JpegTagFormat};
use slotmap::{new_key_type, SlotMap};
use std::borrow::Borrow;
use std::fmt;
use std::str::FromStr;
use std::sync::{Arc, Mutex, Weak};
use std::time::Duration;
use swf::read::{extract_swz, read_compression_type};
@ -74,6 +75,22 @@ pub enum LoadBehavior {
Blocking,
}
pub struct ParseEnumError;
impl FromStr for LoadBehavior {
type Err = ParseEnumError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let behavior = match s {
"streaming" => LoadBehavior::Streaming,
"delayed" => LoadBehavior::Delayed,
"blocking" => LoadBehavior::Blocking,
_ => return Err(ParseEnumError),
};
Ok(behavior)
}
}
/// Enumeration of all content types that `Loader` can handle.
///
/// This is a superset of `JpegTagFormat`.

View File

@ -2772,7 +2772,7 @@ impl FromStr for PlayerRuntime {
fn from_str(s: &str) -> Result<Self, Self::Err> {
let player_runtime = match s {
"air" => PlayerRuntime::AIR,
"flashPlayer" => PlayerRuntime::FlashPlayer,
"flash_player" => PlayerRuntime::FlashPlayer,
_ => return Err(ParseEnumError),
};
Ok(player_runtime)

View File

@ -84,7 +84,7 @@ pub struct Opt {
pub quality: Option<StageQuality>,
/// The alignment of the stage.
#[clap(long, short)]
#[clap(long, short, value_parser(parse_align))]
pub align: Option<StageAlign>,
/// Prevent movies from changing the stage alignment.
@ -218,6 +218,12 @@ fn parse_duration_seconds(value: &str) -> Result<Duration, Error> {
Ok(Duration::from_secs_f64(value.parse()?))
}
fn parse_align(value: &str) -> Result<StageAlign, Error> {
value
.parse()
.map_err(|_| anyhow::anyhow!("Invalid stage alignment"))
}
fn parse_gamepad_button(mapping: &str) -> Result<(GamepadButton, KeyCode), Error> {
let pos = mapping.find('=').ok_or_else(|| {
anyhow!("invalid <gamepad button>=<key name>: no `=` found in `{mapping}`")

View File

@ -99,15 +99,10 @@ impl FromStr for StageQuality {
type Err = StageQualityError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let quality = match s.to_ascii_lowercase().as_str() {
let quality = match s {
"low" => StageQuality::Low,
"medium" => StageQuality::Medium,
"high" => StageQuality::High,
"best" => StageQuality::Best,
"8x8" => StageQuality::High8x8,
"8x8linear" => StageQuality::High8x8Linear,
"16x16" => StageQuality::High16x16,
"16x16linear" => StageQuality::High16x16Linear,
_ => return Err(StageQualityError),
};
Ok(quality)

View File

@ -177,7 +177,11 @@ where
D: serde::Deserializer<'de>,
{
let value: String = serde::Deserialize::deserialize(deserializer)?;
Ok(PlayerRuntime::from_str(&value).unwrap_or_default())
Ok(match value.as_str() {
"air" => PlayerRuntime::AIR,
"flashPlayer" => PlayerRuntime::FlashPlayer,
_ => Default::default(),
})
}
fn deserialize_duration<'de, D>(deserializer: D) -> Result<Duration, D::Error>
@ -683,20 +687,57 @@ impl Ruffle {
.with_quality(
config
.quality
.and_then(|q| StageQuality::from_str(&q).ok())
.and_then(|q| {
let quality = match q.to_ascii_lowercase().as_str() {
"low" => StageQuality::Low,
"medium" => StageQuality::Medium,
"high" => StageQuality::High,
"best" => StageQuality::Best,
"8x8" => StageQuality::High8x8,
"8x8linear" => StageQuality::High8x8Linear,
"16x16" => StageQuality::High16x16,
"16x16linear" => StageQuality::High16x16Linear,
_ => return None,
};
Some(quality)
})
.unwrap_or(default_quality),
)
.with_align(
config
.salign
.and_then(|s| StageAlign::from_str(&s).ok())
.map(|s| {
// Chars get converted into flags.
// This means "tbbtlbltblbrllrbltlrtbl" is valid, resulting in "TBLR".
let mut align = StageAlign::default();
for c in s.bytes().map(|c| c.to_ascii_uppercase()) {
match c {
b'T' => align.insert(StageAlign::TOP),
b'B' => align.insert(StageAlign::BOTTOM),
b'L' => align.insert(StageAlign::LEFT),
b'R' => align.insert(StageAlign::RIGHT),
_ => (),
}
}
align
})
.unwrap_or_default(),
config.force_align,
)
.with_scale_mode(
config
.scale
.and_then(|s| StageScaleMode::from_str(&s).ok())
.and_then(|s| {
let scale_mode = match s.to_ascii_lowercase().as_str() {
"exactfit" => StageScaleMode::ExactFit,
"noborder" => StageScaleMode::NoBorder,
"noscale" => StageScaleMode::NoScale,
"showall" => StageScaleMode::ShowAll,
_ => return None,
};
Some(scale_mode)
})
.unwrap_or_default(),
config.force_scale,
)