1use std::convert::TryFrom;
2use std::net::SocketAddr;
3use std::sync::Arc;
4
5use thiserror::Error;
6
7use super::types::i32_to_duration;
8
9use crate::{
10 component::ComponentName,
11 global::{
12 Global, InputMessage, InputMessageData, InputSourceHandle, InputSourceName, PriorityGuard,
13 },
14 image::{RawImage, RawImageError},
15 models::Color,
16};
17
18pub mod message;
20
21#[derive(Debug, Error)]
22pub enum FlatApiError {
23 #[error("error broadcasting update: {0}")]
24 Broadcast(#[from] tokio::sync::broadcast::error::SendError<InputMessage>),
25 #[error("source not registered")]
26 Unregistered,
27 #[error("invalid priority for registration, should be in [100, 200), got {0}")]
28 InvalidPriority(i32),
29 #[error("unknown command")]
30 UnknownCommand,
31 #[error("error decoding image: {0}")]
32 RawImageError(#[from] RawImageError),
33}
34
35async fn handle_register(
36 peer_addr: SocketAddr,
37 register: message::Register<'_>,
38 source: &mut Option<InputSourceHandle<InputMessage>>,
39 global: &Global,
40 priority_guard: &mut Option<PriorityGuard>,
41) -> Result<(), FlatApiError> {
42 let priority = register.priority();
43
44 if !(100..200).contains(&priority) {
45 return Err(FlatApiError::InvalidPriority(priority));
46 } else {
47 let new_source = global
49 .register_input_source(
50 InputSourceName::FlatBuffers {
51 peer_addr,
52 origin: register.origin().to_owned(),
53 },
54 Some(priority),
55 )
56 .await
57 .unwrap();
58
59 *priority_guard = Some(PriorityGuard::new_broadcast(&new_source));
61 *source = Some(new_source);
62 }
63
64 Ok(())
65}
66
67#[instrument(skip(request, source, global, priority_guard))]
68pub async fn handle_request(
69 peer_addr: SocketAddr,
70 request: message::Request<'_>,
71 source: &mut Option<InputSourceHandle<InputMessage>>,
72 global: &Global,
73 priority_guard: &mut Option<PriorityGuard>,
74) -> Result<(), FlatApiError> {
75 if let Some(handle) = source.as_ref() {
76 let priority = handle.priority().unwrap();
78
79 if let Some(clear) = request.command_as_clear() {
80 if clear.priority() < 0 {
82 handle.send(ComponentName::FlatbufServer, InputMessageData::ClearAll)?;
83 } else {
84 handle.send(
85 ComponentName::FlatbufServer,
86 InputMessageData::Clear {
87 priority: clear.priority(),
88 },
89 )?;
90 }
91 } else if let Some(color) = request.command_as_color() {
92 let rgb = color.data();
93 let rgb = (
94 (rgb & 0x000_000FF) as u8,
95 ((rgb & 0x0000_FF00) >> 8) as u8,
96 ((rgb & 0x00FF_0000) >> 16) as u8,
97 );
98
99 handle.send(
101 ComponentName::FlatbufServer,
102 InputMessageData::SolidColor {
103 priority: 0,
105 duration: i32_to_duration(Some(color.duration())),
106 color: Color::from_components(rgb),
107 },
108 )?;
109 } else if let Some(image) = request.command_as_image() {
110 let data = image
112 .data_as_raw_image()
113 .ok_or_else(|| RawImageError::RawImageMissing)?;
114
115 let duration = image.duration();
117 let width = data.width();
118 let height = data.height();
119 let data = data.data().ok_or_else(|| RawImageError::RawImageMissing)?;
120
121 let width = u32::try_from(width).map_err(|_| RawImageError::InvalidWidth)?;
123 let height = u32::try_from(height).map_err(|_| RawImageError::InvalidHeight)?;
124 let raw_image = RawImage::try_from((data.bytes().to_vec(), width, height))?;
125
126 handle.send(
128 ComponentName::FlatbufServer,
129 InputMessageData::Image {
130 priority,
131 duration: i32_to_duration(Some(duration)),
132 image: Arc::new(raw_image),
133 },
134 )?;
135 } else if let Some(register) = request.command_as_register() {
136 return handle_register(peer_addr, register, source, global, priority_guard).await;
137 } else {
138 return Err(FlatApiError::UnknownCommand);
139 }
140 } else if let Some(register) = request.command_as_register() {
141 return handle_register(peer_addr, register, source, global, priority_guard).await;
142 } else {
143 return Err(FlatApiError::Unregistered);
144 };
145
146 Ok(())
147}