Skip to main content

yolol_devices/devices/
mod.rs

1pub mod chip;
2mod rack;
3use std::ops::Index;
4
5use concat_idents::concat_idents;
6use convert_case::Case;
7use convert_case::Casing;
8use enum_dispatch::enum_dispatch;
9
10use self::chip::CodeRunner;
11pub use self::rack::Rack;
12use crate::deserializer::Deserializer;
13use crate::field::Field;
14use crate::value::YololValue;
15
16//thx https://github.com/martindevans/YololShipSystemSpec
17
18#[enum_dispatch]
19pub trait DeviceTrait {
20    fn get_field(&self, field: &str) -> Option<&YololValue>;
21    fn get_field_mut(&mut self, field: &str) -> Option<&mut YololValue>;
22    fn get_device_name(&self) -> String;
23    fn deserialize<D>(&mut self, deserializer: &D)
24    where
25        D: Deserializer<D, Output = D> + Index<String>;
26}
27
28#[allow(clippy::large_enum_variant)]
29#[enum_dispatch(DeviceTrait)]
30#[derive(Debug)]
31pub enum Device<R: CodeRunner + Default> {
32    Button(Button),
33    CargoBeam(CargoBeam),
34    CargoLockFrame(CargoLockFrame),
35    ChipSocket(ChipSocket),
36    FixedMount(FixedMount),
37    FlightControlUnit(FlightControlUnit),
38    Generator(Generator),
39    Hinge(Hinge),
40    InformationScreen(InformationScreen),
41    Lamp(Lamp),
42    Lever(Lever),
43    MainFlightComputer(MainFlightComputer),
44    MiningLaser(MiningLaser),
45    ModularDisplay(ModularDisplay),
46    Rack(Rack<R>),
47    RadioReceiver(RadioReceiver),
48    RadioTransmitter(RadioTransmitter),
49    RailRelay(RailRelay),
50    RailSensorStrip(RailSensorStrip),
51    RailTrigger(RailTrigger),
52    RangeFinder(RangeFinder),
53    Relay(Relay),
54    Tank(Tank),
55    Thruster(Thruster),
56    Turntable(Turntable),
57}
58
59impl<R: CodeRunner + Default> Device<R> {
60    pub fn deserialize<D>(deserializer: &D) -> Option<Self>
61    where
62        D: Deserializer<D, Output = D> + Index<String>,
63    {
64        let device_type = deserializer
65            .get_type()
66            .expect("Need a type for deserializing");
67        println!("trying to deserialize {}", device_type);
68
69        let device: Option<Device<R>> = match device_type.as_str() {
70            "!button" => Some(Button::default().into()),
71            "!cargo_beam" => Some(CargoBeam::default().into()),
72            "!cargo_lock_frame" => Some(CargoLockFrame::default().into()),
73            "!chip_socket" => Some(ChipSocket::default().into()),
74            "!fixed_mount" => Some(FixedMount::default().into()),
75            "!flight_control_unit" => Some(FlightControlUnit::default().into()),
76            "!generator" => Some(Generator::default().into()),
77            "!hinge" => Some(Hinge::default().into()),
78            "!information_screen" => Some(InformationScreen::default().into()),
79            "!lamp" => Some(Lamp::default().into()),
80            "!lever" => Some(Lever::default().into()),
81            "!main_flight_computer" => Some(MainFlightComputer::default().into()),
82            "!mining_laser" => Some(MiningLaser::default().into()),
83            "!modular_display" => Some(ModularDisplay::default().into()),
84            "!rack" => Some(Rack::default().into()),
85            "!radio_receiver" => Some(RadioReceiver::default().into()),
86            "!radio_transmitter" => Some(RadioTransmitter::default().into()),
87            "!rail_relay" => Some(RailRelay::default().into()),
88            "!rail_sensor_strip" => Some(RailSensorStrip::default().into()),
89            "!rail_trigger" => Some(RailTrigger::default().into()),
90            "!range_finder" => Some(RangeFinder::default().into()),
91            "!relay" => Some(RailRelay::default().into()),
92            "!tank" => Some(Tank::default().into()),
93            "!thruster" => Some(Thruster::default().into()),
94            "!turntable" => Some(Turntable::default().into()),
95            _ => None,
96        };
97
98        if let Some(mut device) = device {
99            device.deserialize(deserializer);
100            Some(device)
101        } else {
102            None
103        }
104    }
105}
106
107#[macro_export]
108macro_rules! deserialize_field_name {
109    ($device:ident, $name:ident, $deserializer:ident) => {{
110        use convert_case::Case;
111        use convert_case::Casing;
112        let name = stringify!($name).to_case(Case::Pascal);
113        $device.$name.set_name(
114            $deserializer[name.to_string()]
115                .as_str()
116                .unwrap_or(name.as_str())
117                .to_string(),
118        );
119    }};
120}
121
122macro_rules! make_device {
123    ($name:ident $(, $field:ident)+ $(,)?) => {
124        #[derive(Debug, Default)]
125        pub struct $name {
126            $($field:Field,)+
127        }
128
129        impl $name{
130            $(
131                pub fn $field(& self)->&Field{
132                    &self.$field
133                }
134                concat_idents!(fn_name = $field,_mut{
135                    pub fn fn_name (&mut self)->&mut Field{
136                        &mut self.$field
137                    }
138                });
139            )+
140        }
141
142        impl DeviceTrait for $name{
143            fn deserialize<D>(&mut self, deserializer: &D)
144            where
145                D: Deserializer<D, Output = D> + Index<String>,
146                <D as Index<String>>::Output: Deserializer<D, Output = D> + Index<String>,
147            {
148                $(deserialize_field_name!(self, $field, deserializer);)+
149            }
150
151            fn get_device_name(&self) -> String {
152                stringify!($name).to_string().to_case(Case::Snake)
153            }
154
155            fn get_field(&self, field: &str) -> Option<&YololValue>{
156                $(
157                    if self.$field.name() == field {
158                        return Some(&self.$field)
159                    }
160                )+
161                None
162            }
163
164            fn get_field_mut(&mut self, field: &str) -> Option<&mut YololValue>{
165                $(
166                    if self.$field.name() == field {
167                        return Some(&mut self.$field)
168                    }
169                )+
170                None
171            }
172        }
173    };
174}
175
176make_device!(
177    Button,
178    button_state,
179    button_on_state_value,
180    button_off_state_value,
181    button_style
182);
183make_device!(CargoBeam, cargo_beam_on_state, cargo_beam_search_length);
184make_device!(CargoLockFrame, cargo_frame_state);
185make_device!(
186    ChipSocket,
187    button_state,
188    button_on_state_value,
189    button_off_state_value,
190    button_style
191);
192make_device!(FixedMount, current_state, on_state, off_state, button_style);
193make_device!(
194    FlightControlUnit,
195    fcu_mfc_io,
196    fcu_general_multiplier,
197    fcu_forward,
198    fcu_backward,
199    fcu_rotational_pitch,
200    fcu_rotational_yaw,
201    fcu_rotational_roll,
202    fcu_up_down,
203    fcu_right_left,
204    fcu_fwd_bwd_pitch,
205    fcu_fwd_bwd_yaw,
206    fcu_fwd_bwd_roll
207);
208make_device!(
209    Generator,
210    fuel_chamber_fuel,
211    fuel_chamber_max_fuel,
212    fuel_chamber_unit_rate_limit,
213    fuel_chamber_unit_rate,
214    generator_unit_rate_limit,
215    generator_unit_rate,
216    stored_coolant,
217    max_coolant,
218    cooler_unit_rate_limit,
219    cooler_unit_rate,
220    socket_unit_rate_limit,
221    socket_unit_rate
222);
223make_device!(
224    Hinge,
225    door_open_state,
226    door_current_state,
227    end_rotation,
228    start_rotation,
229    target_velocity
230);
231make_device!(InformationScreen, info_screen_content);
232make_device!(
233    Lamp,
234    lamp_on,
235    lamp_lumens,
236    lamp_color_hue,
237    lamp_color_saturation,
238    lamp_color_value,
239    lamp_range
240);
241make_device!(
242    Lever,
243    lever_state,
244    lever_min_output,
245    lever_max_output,
246    lever_center_output,
247    lever_center_dead_zone,
248    lever_centering_speed,
249    lever_binds_move_speed
250);
251make_device!(
252    MainFlightComputer,
253    fcu_mfc_io1,
254    fcu_mfc_io2,
255    thruster_power_level01,
256    thruster_power_level02,
257    thruster_power_level03,
258    thruster_power_level04,
259    thruster_power_level05,
260    thruster_power_level06,
261    thruster_power_level07,
262    thruster_power_level08,
263    thruster_power_level09,
264    thruster_power_level10,
265    thruster_power_level11,
266    thruster_power_level12,
267    thruster_power_level13,
268    thruster_power_level14,
269    thruster_power_level15,
270    thruster_power_level16,
271    thruster_power_level17,
272    thruster_power_level18,
273    thruster_power_level19,
274    thruster_power_level20,
275    thruster_power_level21,
276    thruster_power_level22,
277    thruster_power_level23,
278    thruster_power_level24,
279    thruster_power_level25,
280    thruster_power_level26,
281    thruster_power_level27,
282    thruster_power_level28,
283    thruster_power_level29,
284    thruster_power_level30,
285    thruster_power_level31,
286    thruster_power_level32,
287    thruster_power_level33,
288    thruster_power_level34,
289    thruster_power_level35,
290    thruster_power_level36,
291    thruster_power_level37,
292    thruster_power_level38,
293    thruster_power_level39,
294    thruster_power_level40,
295    thruster_power_level41,
296    thruster_power_level42,
297    thruster_power_level43,
298    thruster_power_level44,
299    thruster_power_level45,
300    thruster_power_level46,
301    thruster_power_level47,
302    thruster_power_level48,
303    thruster_power_level49,
304    thruster_power_level50,
305);
306make_device!(MiningLaser, mining_laser_on, mining_laser_beam_length);
307make_device!(ModularDisplay, panel_value);
308make_device!(
309    RadioReceiver,
310    message,
311    signal_strength,
312    listen_angle,
313    target_message,
314    target_frequency,
315    frequency,
316    receiver_pitch,
317    receiver_current_pitch,
318    max_rotation,
319    min_rotation,
320    target_velocity
321);
322make_device!(
323    RadioTransmitter,
324    transmit_message,
325    transmit_range,
326    frequency
327);
328make_device!(RailRelay, is_enabled);
329make_device!(
330    RailSensorStrip,
331    rail_sensor_output,
332    rail_sensor_delta,
333    rail_sensor_mover_filter
334);
335make_device!(
336    RailTrigger,
337    rail_trigger_output,
338    rail_trigger_value,
339    rail_trigger_read_mover
340);
341make_device!(
342    RangeFinder,
343    range_finder_on_state,
344    range_finder_search_length,
345    range_finder_distance
346);
347make_device!(Relay, is_enabled);
348make_device!(
349    Tank,
350    gas_container_stored_resource,
351    gas_container_max_resource,
352    is_open_id,
353    flow_id
354);
355make_device!(Thruster, thruster_state, thruster_current_thrust);
356make_device!(
357    Turntable,
358    turret_rotation,
359    turret_current_rotation,
360    max_rotation,
361    min_rotation,
362    target_velocity
363);