rpgm_common_types/
tone.rs1use ruby_marshal::FromValue;
2use ruby_marshal::FromValueContext;
3use ruby_marshal::FromValueError;
4use ruby_marshal::IntoValue;
5use ruby_marshal::IntoValueError;
6use ruby_marshal::SymbolValue;
7use ruby_marshal::UserDefinedValue;
8use ruby_marshal::Value;
9use ruby_marshal::ValueArena;
10use ruby_marshal::ValueHandle;
11
12pub const USER_DEFINED_NAME: &[u8] = b"Tone";
13
14const SIZE: usize = 8 * 4;
15
16#[derive(Debug)]
17pub enum ToneFromValueError {
18 InvalidSize { size: usize },
19}
20
21impl std::fmt::Display for ToneFromValueError {
22 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
23 match self {
24 Self::InvalidSize { size } => {
25 write!(f, "invalid Tone data size of {size}, expected {SIZE}")
26 }
27 }
28 }
29}
30
31impl std::error::Error for ToneFromValueError {}
32
33#[derive(Debug, serde::Serialize, serde::Deserialize)]
34pub struct Tone {
35 pub red: f64,
36 pub green: f64,
37 pub blue: f64,
38 pub gray: f64,
39}
40
41impl FromValue<'_> for Tone {
42 fn from_value(ctx: &FromValueContext, value: &Value) -> Result<Self, FromValueError> {
43 let user_defined: &UserDefinedValue = FromValue::from_value(ctx, value)?;
44 let name = user_defined.name();
45 let name: &SymbolValue = ctx.from_value(name.into())?;
46 let name = name.value();
47 if name != USER_DEFINED_NAME {
48 return Err(FromValueError::UnexpectedObjectName { name: name.into() });
49 }
50
51 let value = user_defined.value();
52
53 let value_len = value.len();
54 if value_len != SIZE {
55 return Err(FromValueError::new_other(ToneFromValueError::InvalidSize {
56 size: value_len,
57 }));
58 }
59
60 let (red, value) = value.split_at(8);
61 let (green, value) = value.split_at(8);
62 let (blue, value) = value.split_at(8);
63 let (gray, _value) = value.split_at(8);
64
65 let red = f64::from_le_bytes(red.try_into().unwrap());
66 let green = f64::from_le_bytes(green.try_into().unwrap());
67 let blue = f64::from_le_bytes(blue.try_into().unwrap());
68 let gray = f64::from_le_bytes(gray.try_into().unwrap());
69
70 Ok(Self {
71 red,
72 green,
73 blue,
74 gray,
75 })
76 }
77}
78
79impl IntoValue for Tone {
80 fn into_value(self, arena: &mut ValueArena) -> Result<ValueHandle, IntoValueError> {
81 let name = arena.create_symbol(USER_DEFINED_NAME.into());
82
83 let mut value = Vec::with_capacity(32);
84 value.extend(self.red.to_le_bytes());
85 value.extend(self.green.to_le_bytes());
86 value.extend(self.blue.to_le_bytes());
87 value.extend(self.gray.to_le_bytes());
88
89 Ok(arena.create_user_defined(name, value).into())
90 }
91}