feat: implement FParkan architecture foundation
Add the modular fparkan workspace, domain crates, adapters, apps, xtask policy/CI, acceptance evidence, and licensed corpus gates for the macOS-focused roadmap foundation.
This commit is contained in:
@@ -0,0 +1,12 @@
|
||||
[package]
|
||||
name = "fparkan-platform-sdl"
|
||||
version.workspace = true
|
||||
edition.workspace = true
|
||||
license.workspace = true
|
||||
repository.workspace = true
|
||||
|
||||
[dependencies]
|
||||
fparkan-platform = { path = "../../crates/fparkan-platform" }
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
@@ -0,0 +1,123 @@
|
||||
#![forbid(unsafe_code)]
|
||||
//! SDL platform adapter proof behind safe `FParkan` ports.
|
||||
|
||||
use fparkan_platform::{
|
||||
EventSource, GraphicsContextRequest, GraphicsProfile, PhysicalSize, PlatformError,
|
||||
PlatformEvent, Version, WindowPort,
|
||||
};
|
||||
|
||||
/// Adapter capabilities compiled into this package.
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
pub struct SdlAdapterCapabilities {
|
||||
/// Supported graphics context requests in preference order.
|
||||
pub graphics: Vec<GraphicsContextRequest>,
|
||||
/// Whether adapter-owned code is free of `unsafe`.
|
||||
pub project_owned_unsafe_free: bool,
|
||||
}
|
||||
|
||||
impl Default for SdlAdapterCapabilities {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
graphics: vec![
|
||||
GraphicsContextRequest {
|
||||
profile: GraphicsProfile::DesktopCore,
|
||||
version: Version { major: 3, minor: 3 },
|
||||
},
|
||||
GraphicsContextRequest {
|
||||
profile: GraphicsProfile::Embedded,
|
||||
version: Version { major: 2, minor: 0 },
|
||||
},
|
||||
],
|
||||
project_owned_unsafe_free: true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns adapter readiness status for the safe project-owned layer.
|
||||
#[must_use]
|
||||
pub fn safe_adapter_ready() -> bool {
|
||||
SdlAdapterCapabilities::default().project_owned_unsafe_free
|
||||
}
|
||||
|
||||
/// In-memory event source used by adapter smoke tests and composition roots
|
||||
/// before a concrete SDL runtime is injected.
|
||||
#[derive(Clone, Debug, Default)]
|
||||
pub struct SdlEventSourceProof {
|
||||
pending: Vec<PlatformEvent>,
|
||||
}
|
||||
|
||||
impl SdlEventSourceProof {
|
||||
/// Creates an event source with deterministic pending events.
|
||||
#[must_use]
|
||||
pub fn new(pending: Vec<PlatformEvent>) -> Self {
|
||||
Self { pending }
|
||||
}
|
||||
}
|
||||
|
||||
impl EventSource for SdlEventSourceProof {
|
||||
fn poll(&mut self, out: &mut Vec<PlatformEvent>) -> Result<(), PlatformError> {
|
||||
out.append(&mut self.pending);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// Safe window-port proof with SDL-compatible drawable-size semantics.
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
pub struct SdlWindowProof {
|
||||
size: PhysicalSize,
|
||||
presents: u64,
|
||||
}
|
||||
|
||||
impl SdlWindowProof {
|
||||
/// Creates a proof window with a fixed drawable size.
|
||||
#[must_use]
|
||||
pub fn new(size: PhysicalSize) -> Self {
|
||||
Self { size, presents: 0 }
|
||||
}
|
||||
|
||||
/// Number of successful present calls.
|
||||
#[must_use]
|
||||
pub fn presents(&self) -> u64 {
|
||||
self.presents
|
||||
}
|
||||
}
|
||||
|
||||
impl WindowPort for SdlWindowProof {
|
||||
fn drawable_size(&self) -> PhysicalSize {
|
||||
self.size
|
||||
}
|
||||
|
||||
fn present(&mut self) -> Result<(), PlatformError> {
|
||||
self.presents = self.presents.saturating_add(1);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn adapter_reports_safe_project_layer_ready() {
|
||||
assert!(safe_adapter_ready());
|
||||
assert_eq!(SdlAdapterCapabilities::default().graphics.len(), 2);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn event_source_and_window_ports_are_deterministic() -> Result<(), PlatformError> {
|
||||
let mut source = SdlEventSourceProof::new(vec![PlatformEvent::Quit]);
|
||||
let mut events = Vec::new();
|
||||
source.poll(&mut events)?;
|
||||
source.poll(&mut events)?;
|
||||
assert_eq!(events, vec![PlatformEvent::Quit]);
|
||||
|
||||
let mut window = SdlWindowProof::new(PhysicalSize {
|
||||
width: 320,
|
||||
height: 240,
|
||||
});
|
||||
assert_eq!(window.drawable_size().width, 320);
|
||||
window.present()?;
|
||||
assert_eq!(window.presents(), 1);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user