Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make crate compatible with no_std #86

Merged
merged 5 commits into from
Nov 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 10 additions & 8 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,20 +11,22 @@ documentation = "https://docs.rs/spatial_led"
exclude = ["*.gif", "*.cast"]

[features]
default = ["drivers", "scheduler"]
default = ["drivers", "scheduler", "std"]
drivers = ["compact_str", "sled_driver_macros"]
scheduler = ["spin_sleep"]
scheduler = []
named_colors = []
std = ["glam/std", "palette/std"]
libm = ["glam/libm", "palette/libm"]
async = []
spin_sleep = ["std", "dep:spin_sleep"]

[dependencies]
glam = { version = "0.29" }
palette = { version = "0.7", default-features = false, features = [
"std",
"approx",
] }
glam = { version = "0.29", default-features = false, features = [] }
palette = { version = "0.7", default-features = false, features = ["approx"] }
smallvec = "1.13"
compact_str = { version = "0.8", optional = true }
compact_str = { version = "0.8", default-features = false, optional = true }
sled_driver_macros = { version = "0.1.2", optional = true }
num-traits = { version = "0.2", default-features = false }
spin_sleep = { version = "1.2", optional = true }

[dev-dependencies]
Expand Down
2 changes: 1 addition & 1 deletion examples/drivers/comet.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use spatial_led::driver_macros::*;
use spatial_led::driver::{Driver, TimeInfo};
use spatial_led::driver_macros::*;
use spatial_led::SledResult;
use spatial_led::{color::Rgb, Sled};

Expand Down
2 changes: 1 addition & 1 deletion examples/drivers/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
pub mod comet;
pub mod ripples;
pub mod scan;
pub mod warpspeed;
pub mod scan;
2 changes: 1 addition & 1 deletion examples/drivers/ripples.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use spatial_led::driver_macros::*;
use rand::Rng;
use spatial_led::driver::{BufferContainer, Driver, TimeInfo};
use spatial_led::driver_macros::*;
use spatial_led::SledResult;
use spatial_led::{color::Rgb, Sled, Vec2};
use std::ops::Range;
Expand Down
2 changes: 1 addition & 1 deletion examples/drivers/warpspeed.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use spatial_led::driver_macros::*;
use rand::Rng;
use spatial_led::driver::{BufferContainer, Driver, TimeInfo};
use spatial_led::driver_macros::*;
use spatial_led::SledResult;
use spatial_led::{color::Rgb, Sled, Vec2};

Expand Down
2 changes: 1 addition & 1 deletion src/color.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ pub mod consts {
//!
//! Adapted from palette's [named](https://docs.rs/palette/0.7.3/palette/named/index.html) module
//! but expressed as 32-bit rgb instead of 8-bit for better compatability with sled.
//!
//!
//! Colors are taken from the [SVG keyword
//! colors](https://www.w3.org/TR/SVG11/types.html#ColorKeywords) (same as in
//! CSS3) and they can be used as if they were pixel values:
Expand Down
17 changes: 13 additions & 4 deletions src/config.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,15 @@
use alloc::string::String;
use alloc::string::ToString as _;
use alloc::vec;
use alloc::vec::Vec;

use crate::error::SledError;
use core::str::Lines;
use glam::Vec2;
use smallvec::SmallVec;
use std::{fs, str::Lines};

#[cfg(not(feature = "std"))]
use num_traits::float::Float as _;

pub(crate) struct Config {
pub center_point: Vec2,
Expand Down Expand Up @@ -95,7 +103,7 @@ fn extract_segments_from_string(s: &str) -> Vec<LineSegment> {
}

impl Config {
pub fn from_string(string: String) -> Result<Self, SledError> {
pub fn from_string(string: &str) -> Result<Self, SledError> {
let mut lines = string.lines();

let (center, density) = extract_center_and_density_from_lines(&mut lines);
Expand All @@ -121,9 +129,10 @@ impl Config {
})
}

#[cfg(feature = "std")]
pub fn from_toml_file(path: &str) -> Result<Self, SledError> {
let as_string = fs::read_to_string(path).map_err(SledError::from_error)?;
Config::from_string(as_string)
let as_string = std::fs::read_to_string(path).map_err(SledError::from_error)?;
Config::from_string(&as_string)
}
}

Expand Down
26 changes: 15 additions & 11 deletions src/driver/buffers.rs
Original file line number Diff line number Diff line change
@@ -1,22 +1,26 @@
use std::{
use core::{
any::{type_name, Any},
fmt::Debug,
};

use alloc::boxed::Box;
use alloc::collections::BTreeMap;
use alloc::format;
use alloc::vec::Vec;

use compact_str::{CompactString, ToCompactString};
use std::collections::HashMap;

use crate::SledError;

#[derive(Debug)]
pub struct BufferContainer {
buffers: HashMap<CompactString, Box<dyn Buffer>>,
buffers: BTreeMap<CompactString, Box<dyn Buffer>>,
}

impl BufferContainer {
pub fn new() -> Self {
BufferContainer {
buffers: HashMap::new(),
buffers: BTreeMap::new(),
}
}

Expand Down Expand Up @@ -235,18 +239,18 @@ impl BufferContainer {
Ok(())
}

pub fn iter(&self) -> std::collections::hash_map::Iter<CompactString, Box<dyn Buffer>> {
pub fn iter(&self) -> alloc::collections::btree_map::Iter<CompactString, Box<dyn Buffer>> {
self.buffers.iter()
}

pub fn iter_mut(
&mut self,
) -> std::collections::hash_map::IterMut<CompactString, Box<dyn Buffer>> {
) -> alloc::collections::btree_map::IterMut<CompactString, Box<dyn Buffer>> {
self.buffers.iter_mut()
}
}

pub trait Buffer: std::fmt::Debug {
pub trait Buffer: core::fmt::Debug {
fn as_any(&self) -> &dyn Any;
fn as_any_mut(&mut self) -> &mut dyn Any;
}
Expand All @@ -264,16 +268,16 @@ impl<T: BufferableData + Debug> Buffer for Vec<T> {
}
}

impl std::iter::IntoIterator for BufferContainer {
impl core::iter::IntoIterator for BufferContainer {
type Item = (CompactString, Box<dyn Buffer>);
type IntoIter = std::collections::hash_map::IntoIter<CompactString, Box<dyn Buffer>>;
type IntoIter = alloc::collections::btree_map::IntoIter<CompactString, Box<dyn Buffer>>;

fn into_iter(self) -> Self::IntoIter {
self.buffers.into_iter()
}
}

impl std::iter::FromIterator<(CompactString, Box<dyn Buffer>)> for BufferContainer {
impl core::iter::FromIterator<(CompactString, Box<dyn Buffer>)> for BufferContainer {
fn from_iter<T: IntoIterator<Item = (CompactString, Box<dyn Buffer>)>>(iter: T) -> Self {
let mut bc = BufferContainer::new();

Expand All @@ -285,7 +289,7 @@ impl std::iter::FromIterator<(CompactString, Box<dyn Buffer>)> for BufferContain
}
}

impl std::iter::Extend<(CompactString, Box<dyn Buffer>)> for BufferContainer {
impl core::iter::Extend<(CompactString, Box<dyn Buffer>)> for BufferContainer {
fn extend<T: IntoIterator<Item = (CompactString, Box<dyn Buffer>)>>(&mut self, iter: T) {
for (key, value) in iter {
self.buffers.insert(key, value);
Expand Down
15 changes: 9 additions & 6 deletions src/driver/filters.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
use crate::{Filter, SledError};
use alloc::collections::BTreeMap;
use alloc::format;

use compact_str::{CompactString, ToCompactString};
use std::collections::HashMap;

use crate::{Filter, SledError};

#[derive(Clone, Debug)]
pub struct Filters {
map: HashMap<CompactString, Filter>,
map: BTreeMap<CompactString, Filter>,
}

impl Default for Filters {
Expand All @@ -16,7 +19,7 @@ impl Default for Filters {
impl Filters {
pub fn new() -> Self {
Filters {
map: HashMap::new(),
map: BTreeMap::new(),
}
}

Expand All @@ -30,14 +33,14 @@ impl Filters {
.ok_or_else(|| SledError::new(format!("No filter found with key '{}'", key)))
}

pub fn iter(&self) -> std::collections::hash_map::Iter<CompactString, Filter> {
pub fn iter(&self) -> alloc::collections::btree_map::Iter<CompactString, Filter> {
self.map.iter()
}
}

impl IntoIterator for Filters {
type Item = (CompactString, Filter);
type IntoIter = std::collections::hash_map::IntoIter<CompactString, Filter>;
type IntoIter = alloc::collections::btree_map::IntoIter<CompactString, Filter>;

fn into_iter(self) -> Self::IntoIter {
self.map.into_iter()
Expand Down
52 changes: 34 additions & 18 deletions src/driver/mod.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
use core::time::Duration;

use alloc::boxed::Box;

use crate::{
color::{Rgb, Srgb},
time::Instant,
Led, Sled, SledError, Vec2,
};

use std::time::{Duration, Instant};
/// A driver representing instants with `std::time::Instant`
#[cfg(feature = "std")]
pub type Driver = CustomDriver<std::time::Instant>;

mod filters;
// mod sliders;
Expand All @@ -26,26 +33,32 @@ type DrawCommands = Box<dyn Fn(&mut Sled, &BufferContainer, &Filters, &TimeInfo)
/// Drivers are useful for encapsulating everything you need to drive a complicated lighting effect all in one place.
///
/// Some [macros](driver_macros) have been provided to make authoring drivers a more ergonomic experience. See their doc comments for more information.
pub struct Driver {
pub struct CustomDriver<INSTANT>
where
INSTANT: Instant,
{
sled: Option<Sled>,
startup_commands: StartupCommands,
compute_commands: ComputeCommands,
draw_commands: DrawCommands,
startup: Instant,
last_update: Instant,
startup: INSTANT,
last_update: INSTANT,
buffers: BufferContainer,
filters: Filters,
}

impl Driver {
impl<INSTANT> CustomDriver<INSTANT>
where
INSTANT: Instant,
{
pub fn new() -> Self {
Driver {
CustomDriver {
sled: None,
startup_commands: Box::new(|_, _, _| Ok(())),
compute_commands: Box::new(|_, _, _, _| Ok(())),
draw_commands: Box::new(|_, _, _, _| Ok(())),
startup: Instant::now(),
last_update: Instant::now(),
startup: INSTANT::now(),
last_update: INSTANT::now(),
buffers: BufferContainer::new(),
filters: Filters::new(),
}
Expand All @@ -61,7 +74,7 @@ impl Driver {
self.startup.elapsed()
}

/// Define commands to be called as soon as a Sled is [mounted](Driver::mount) to the driver. This is a good place to initialize important buffer values.
/// Define commands to be called as soon as a Sled is [mounted](CustomDriver::mount) to the driver. This is a good place to initialize important buffer values.
/// ```rust
/// # use spatial_led::{Vec2, BufferContainer, SledResult, driver::Driver};
/// use spatial_led::driver_macros::*;
Expand Down Expand Up @@ -91,7 +104,7 @@ impl Driver {
self.startup_commands = Box::new(startup_commands);
}

/// Define commands to be called each time [Driver::step()] is called, right before we run [draw commands](Driver::set_draw_commands).
/// Define commands to be called each time [CustomDriver::step()] is called, right before we run [draw commands](CustomDriver::set_draw_commands).
/// ```rust
/// # use spatial_led::{Vec2, BufferContainer, TimeInfo, SledResult, driver::Driver};
/// use spatial_led::driver_macros::*;
Expand Down Expand Up @@ -122,7 +135,7 @@ impl Driver {
self.compute_commands = Box::new(compute_commands);
}

/// Define commands to be called each time [Driver::step()] is called, right after we run [compute commands](Driver::set_compute_commands).
/// Define commands to be called each time [CustomDriver::step()] is called, right after we run [compute commands](CustomDriver::set_compute_commands).
/// ```rust
/// # use spatial_led::{Sled, Vec2, color::Rgb, BufferContainer, TimeInfo, SledResult, driver::Driver};
/// use spatial_led::driver_macros::*;
Expand All @@ -131,7 +144,7 @@ impl Driver {
/// fn draw(sled: &mut Sled, buffers: &BufferContainer) -> SledResult {
/// // gradually fade all LEDs to black
/// sled.map(|led| led.color * 0.95);
///
///
/// // For each position in our buffer, draw white in the direction to it.
/// let streak_positions = buffers.get_buffer::<Vec2>("positions")?;
/// let center = sled.center_point();
Expand All @@ -157,23 +170,23 @@ impl Driver {
self.draw_commands = Box::new(draw_commands);
}

/// Takes ownership of the given Sled and runs the Driver's [startup commands](Driver::set_startup_commands).
/// Takes ownership of the given Sled and runs the Driver's [startup commands](CustomDriver::set_startup_commands).
pub fn mount(&mut self, mut sled: Sled) {
(self.startup_commands)(&mut sled, &mut self.buffers, &mut self.filters).unwrap();
self.startup = Instant::now();
self.startup = INSTANT::now();
self.last_update = self.startup;
self.sled = Some(sled);
}

/// Runs the Driver's [compute commands](Driver::set_compute_commands) first, and then runs its [draw commands](Driver::set_draw_commands).
/// Runs the Driver's [compute commands](CustomDriver::set_compute_commands) first, and then runs its [draw commands](CustomDriver::set_draw_commands).
pub fn step(&mut self) {
if let Some(sled) = &mut self.sled {
let time_info = TimeInfo {
elapsed: self.startup.elapsed(),
delta: self.last_update.elapsed(),
};

self.last_update = Instant::now();
self.last_update = INSTANT::now();
(self.compute_commands)(sled, &mut self.buffers, &mut self.filters, &time_info)
.unwrap();
(self.draw_commands)(sled, &self.buffers, &self.filters, &time_info).unwrap();
Expand All @@ -185,7 +198,7 @@ impl Driver {
self.step();
}

/// Returns full ownership over the Driver's assigned Sled. Panics if [Driver::mount()] was never called.
/// Returns full ownership over the Driver's assigned Sled. Panics if [CustomDriver::mount()] was never called.
pub fn dismount(&mut self) -> Sled {
self.sled.take().unwrap()
}
Expand Down Expand Up @@ -252,7 +265,10 @@ impl Driver {
}
}

impl Default for Driver {
impl<INSTANT> Default for CustomDriver<INSTANT>
where
INSTANT: Instant,
{
fn default() -> Self {
Self::new()
}
Expand Down
Loading
Loading