Co-authored-by: Copilot <copilot@github.com>
This commit is contained in:
11
crates/application/Cargo.toml
Normal file
11
crates/application/Cargo.toml
Normal file
@@ -0,0 +1,11 @@
|
||||
[package]
|
||||
name = "application"
|
||||
version.workspace = true
|
||||
edition.workspace = true
|
||||
license.workspace = true
|
||||
authors.workspace = true
|
||||
|
||||
[dependencies]
|
||||
domain = { workspace = true }
|
||||
heapless = { version = "0.9.3", default-features = false }
|
||||
thiserror = { workspace = true }
|
||||
55
crates/application/src/errors.rs
Normal file
55
crates/application/src/errors.rs
Normal file
@@ -0,0 +1,55 @@
|
||||
use core::fmt::{self, Display, Write};
|
||||
|
||||
pub type Message = heapless::String<104, u8>;
|
||||
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub enum ApplicationError {
|
||||
#[error("Failed to initialize display: {0}")]
|
||||
DisplayInitialization(Message),
|
||||
#[error("Display event loop failure: {0}")]
|
||||
EventLoop(Message),
|
||||
#[error("Render pipeline failure: {0}")]
|
||||
RenderingFailed(Message),
|
||||
#[error("Failed to load logo: {0}")]
|
||||
LogoSource(Message),
|
||||
#[error("Domain configuration error: {0}")]
|
||||
DomainError(#[from] domain::DomainError),
|
||||
}
|
||||
|
||||
impl ApplicationError {
|
||||
pub fn display_initialization(reason: impl Display) -> Self {
|
||||
Self::DisplayInitialization(message(reason))
|
||||
}
|
||||
|
||||
pub fn event_loop(reason: impl Display) -> Self {
|
||||
Self::EventLoop(message(reason))
|
||||
}
|
||||
|
||||
pub fn rendering_failed(reason: impl Display) -> Self {
|
||||
Self::RenderingFailed(message(reason))
|
||||
}
|
||||
|
||||
pub fn logo_source(reason: impl Display) -> Self {
|
||||
Self::LogoSource(message(reason))
|
||||
}
|
||||
}
|
||||
|
||||
fn message(reason: impl Display) -> Message {
|
||||
let mut buffer = Message::new();
|
||||
let _ = write!(Truncating(&mut buffer), "{reason}");
|
||||
buffer
|
||||
}
|
||||
|
||||
struct Truncating<'a>(&'a mut Message);
|
||||
|
||||
impl Write for Truncating<'_> {
|
||||
fn write_str(&mut self, text: &str) -> fmt::Result {
|
||||
for character in text.chars() {
|
||||
if self.0.push(character).is_err() {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
9
crates/application/src/lib.rs
Normal file
9
crates/application/src/lib.rs
Normal file
@@ -0,0 +1,9 @@
|
||||
#![no_std]
|
||||
|
||||
mod errors;
|
||||
mod ports;
|
||||
mod use_cases;
|
||||
|
||||
pub use errors::{ApplicationError, Message};
|
||||
pub use ports::{DisplayOverlayPort, LogoSourcePort, RendererPort};
|
||||
pub use use_cases::{run, step};
|
||||
20
crates/application/src/ports.rs
Normal file
20
crates/application/src/ports.rs
Normal file
@@ -0,0 +1,20 @@
|
||||
use domain::{Dimensions, ScreensaverScene};
|
||||
|
||||
use crate::ApplicationError;
|
||||
|
||||
pub trait DisplayOverlayPort {
|
||||
fn screen_dimensions(&self) -> Dimensions;
|
||||
fn wait_for_frame(&mut self) -> Result<bool, ApplicationError>;
|
||||
}
|
||||
|
||||
pub trait RendererPort {
|
||||
fn render_frame(
|
||||
&mut self,
|
||||
scene: &ScreensaverScene,
|
||||
screen_size: Dimensions,
|
||||
) -> Result<(), ApplicationError>;
|
||||
}
|
||||
|
||||
pub trait LogoSourcePort {
|
||||
fn load(&self) -> Result<Option<&[u8]>, ApplicationError>;
|
||||
}
|
||||
37
crates/application/src/use_cases.rs
Normal file
37
crates/application/src/use_cases.rs
Normal file
@@ -0,0 +1,37 @@
|
||||
use domain::ScreensaverScene;
|
||||
|
||||
use crate::{
|
||||
errors::ApplicationError,
|
||||
ports::{DisplayOverlayPort, RendererPort},
|
||||
};
|
||||
|
||||
pub fn step<D, R>(
|
||||
display: &mut D,
|
||||
renderer: &mut R,
|
||||
scene: &mut ScreensaverScene,
|
||||
) -> Result<(), ApplicationError>
|
||||
where
|
||||
D: DisplayOverlayPort,
|
||||
R: RendererPort,
|
||||
{
|
||||
let bounds = display.screen_dimensions();
|
||||
|
||||
scene.tick(bounds);
|
||||
renderer.render_frame(scene, bounds)
|
||||
}
|
||||
|
||||
pub fn run<D, R>(
|
||||
display: &mut D,
|
||||
renderer: &mut R,
|
||||
scene: &mut ScreensaverScene,
|
||||
) -> Result<(), ApplicationError>
|
||||
where
|
||||
D: DisplayOverlayPort,
|
||||
R: RendererPort,
|
||||
{
|
||||
while display.wait_for_frame()? {
|
||||
step(display, renderer, scene)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
Reference in New Issue
Block a user