use crate::types::ViewportConfig;
use vize_l0::{Allocator, FxHashMap};
pub(super) fn parse_args_json<'a>(
allocator: &'a Allocator,
s: &str,
) -> Result<FxHashMap<&'a str, serde_json::Value>, serde_json::Error> {
let json_str: std::borrow::Cow<'_, str> = if s.contains('&') {
std::borrow::Cow::Owned(
s.replace(""", "\"")
.replace("'", "'")
.replace("<", "<")
.replace(">", ">")
.replace("&", "&"),
)
} else {
std::borrow::Cow::Borrowed(s)
};
#[expect(
clippy::disallowed_types,
reason = "serde_json maps are keyed by std String"
)]
let map: FxHashMap<std::string::String, serde_json::Value> = serde_json::from_str(&json_str)?;
Ok(map
.into_iter()
.map(|(k, v)| {
let key: &'a str = allocator.alloc_str(&k);
(key, v)
})
.collect())
}
pub(super) fn parse_viewport(viewport_str: &str) -> Option<ViewportConfig> {
if viewport_str.starts_with('{') {
let json_str = if viewport_str.contains('&') {
std::borrow::Cow::Owned(viewport_str.replace(""", "\"").replace("'", "'"))
} else {
std::borrow::Cow::Borrowed(viewport_str)
};
if let Ok(config) = serde_json::from_str::<ViewportConfig>(&json_str) {
return Some(config);
}
}
let (width, rest) = viewport_str.split_once('x')?;
let width: u32 = width.parse().ok()?;
let (height, device_scale_factor) = match rest.split_once('@') {
Some((height, scale)) => (height, Some(scale.parse::<f32>().ok()?)),
None => (rest, None),
};
Some(ViewportConfig {
width,
height: height.parse().ok()?,
device_scale_factor,
})
}
#[cfg(test)]
mod tests {
use super::parse_viewport;
use crate::types::ViewportConfig;
#[test]
fn viewport_forms() {
let cases = [
("375x667", Some((375, 667, None))),
("375x667@2", Some((375, 667, Some(2.0)))),
(r#"{"width":320,"height":480}"#, Some((320, 480, None))),
(
"{"width":320,"height":480,"deviceScaleFactor":3}",
Some((320, 480, Some(3.0))),
),
("{\"width\":1}x2", None),
("wide", None),
("375x", None),
("375x667@", None),
("375x667@2@3", None),
];
for (value, expected) in cases {
let actual = parse_viewport(value).map(
|ViewportConfig {
width,
height,
device_scale_factor,
}| (width, height, device_scale_factor),
);
assert_eq!(actual, expected, "{value}");
}
}
}