use alloc::boxed::Box;
#[cfg(feature = "std")]
use std::path::Path;
use concinnity_core::Driver;
use crate::{Error, World, driver};
pub struct App {
inner: Box<dyn Driver>,
}
impl core::fmt::Debug for App {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("App").finish_non_exhaustive()
}
}
impl App {
pub fn from_world(world: World) -> Self {
Self {
inner: driver::select(world.into_inner()),
}
}
#[cfg(feature = "std")]
pub fn from_blob(path: impl AsRef<Path>) -> Result<Self, Error> {
concinnity_engine::App::from_blob(path.as_ref())
.map(|app| Self {
inner: driver::adopt(app),
})
.map_err(crate::error::from_startup)
}
pub fn into_headless(self) -> Self {
Self {
inner: driver::headless(self.inner.into_world()),
}
}
pub fn run(self) -> Result<(), Error> {
self.inner.run().map_err(Error::from)
}
#[cfg(test)]
pub(crate) fn inner_mut(&mut self) -> &mut dyn Driver {
&mut *self.inner
}
}
#[cfg(all(test, feature = "cook"))]
mod tests {
use super::App;
use crate::components::DirectionalLight;
use crate::cook;
#[test]
fn a_written_blob_loads_back_into_a_runnable_app() {
let tree = concinnity_testing::TempTree::new();
let primary = tree.join("data/0");
cook::world()
.add(
"sun",
DirectionalLight {
intensity: 3.5,
..Default::default()
},
)
.write_blob(&primary)
.expect("the world is written");
let app = App::from_blob(&primary).expect("the written blob loads");
crate::test_support::assert_starts_headless(app);
}
#[test]
fn a_missing_blob_reports_the_path_it_could_not_read() {
let tree = concinnity_testing::TempTree::new();
let missing = tree.join("concinnity-no-such-blob/0");
let err = App::from_blob(&missing).expect_err("nothing to load");
assert!(matches!(err, crate::Error::MissingData { .. }), "{err:?}");
assert!(err.to_string().contains("concinnity-no-such-blob"), "{err}");
}
}