use crate::prelude::*;
use serde::ser::SerializeMap;
#[derive(Debug, PartialEq, Clone, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct Monitor {
pub id: Id,
pub mode: Mode,
pub opcode: OpCode<MonitorOpCode>,
#[serde(rename = "params")]
pub params: Parameter,
pub sprite_name: Option<Name>,
pub value: ListOrValue,
pub width: u64,
pub height: u64,
pub x: i64,
pub y: i64,
pub visible: bool,
#[serde(flatten)]
pub slider: Option<Slider>,
}
#[derive(Debug, PartialEq, Clone, Copy, Deserialize, Serialize)]
pub enum MonitorOpCode {
#[serde(rename = "data_variable")]
DataVariable,
#[serde(rename = "data_listcontents")]
DataListContents,
#[serde(rename = "motion_xposition")]
MotionXPostion,
#[serde(rename = "motion_yposition")]
MotionYPosition,
#[serde(rename = "motion_direction")]
MotionDirection,
#[serde(rename = "looks_costumenumbername")]
LooksCostume,
#[serde(rename = "looks_backdropnumbername")]
LooksBackdrop,
#[serde(rename = "looks_size")]
LooksSize,
#[serde(rename = "sensing_loudness")]
SensingLoudness,
#[serde(rename = "sensing_timer")]
SensingTimer,
#[serde(rename = "sensing_username")]
SensingUsername,
}
#[derive(Debug, PartialEq, Clone, Copy, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub enum Mode {
Default,
Large,
Slider,
List,
}
#[derive(Debug, PartialEq, Clone)]
pub enum Parameter {
None,
Variable(Name),
List(Name),
NumberName(NumberName),
}
#[derive(Debug, PartialEq, Clone, Deserialize, Serialize)]
#[serde(untagged)]
pub enum ListOrValue {
Value(Value),
List(Vec<Value>),
}
#[derive(Debug, PartialEq, Eq, Clone, Copy, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub enum NumberName {
Number,
Name,
}
#[derive(Debug, PartialEq, Eq, Clone, Copy, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct Slider {
slider_min: i64,
slider_max: i64,
is_discrete: bool,
}
struct ParameterVisitor;
impl<'de> Visitor<'de> for ParameterVisitor {
type Value = Parameter;
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
formatter.write_str("object that is a parameter")
}
fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
where
A: serde::de::MapAccess<'de>,
{
use serde::de::Error;
if let Some((k, v)) = map.next_entry::<&str, &str>()? {
Ok(match (k, v) {
("VARIABLE", v) => Parameter::Variable(v.to_owned()),
("LIST", v) => Parameter::List(v.into()),
("NUMBER_NAME", "name") => Parameter::NumberName(NumberName::Name),
("NUMBER_NAME", "number") => Parameter::NumberName(NumberName::Number),
(k, _) => {
return Err(A::Error::invalid_value(
serde::de::Unexpected::Str(k),
&"Expected either VARIABLE, LIST, or NUMBER_NAME",
))
}
})
} else {
Ok(Parameter::None)
}
}
}
impl<'de> Deserialize<'de> for Parameter {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
deserializer.deserialize_map(ParameterVisitor)
}
}
impl Serialize for Parameter {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
match self {
Parameter::None => serializer.serialize_map(Some(0))?.end(),
r => {
let mut s = serializer.serialize_map(Some(1))?;
match r {
Parameter::Variable(n) => s.serialize_entry("VARIABLE", n)?,
Parameter::List(n) => s.serialize_entry("LIST", n)?,
Parameter::NumberName(n) => s.serialize_entry("NUMBER_NAME", n)?,
Parameter::None => unreachable!("There cannot be none in here"),
};
s.end()
}
}
}
}