Skip to content
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
3 changes: 3 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ Contributions are accepted in any form (issues, documentation, feature requests,

All creatures welcome.

If you have access, please contribute on the [CCCB Forgejo](https://git.berlin.ccc.de/servicepoint/servicepoint).
Contributions on GitHub will be copied over and merged there.

## Pull requests

Feel free to create a PR, even if your change is not done yet.
Expand Down
8 changes: 6 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ Display" or "Airport Display".
This repository contains a library for parsing, encoding and sending packets to this display via UDP in multiple
programming languages.

This repository will move to [git.berlin.ccc.de/servicepoint/servicepoint](https://git.berlin.ccc.de/servicepoint/servicepoint) soon.
This project moved to [git.berlin.ccc.de/servicepoint/servicepoint](https://git.berlin.ccc.de/servicepoint/servicepoint).
The [GitHub repository](https://github.com/cccb/servicepoint) remains available as a mirror.

Take a look at the contained crates for language specific information:

Expand All @@ -22,7 +23,7 @@ Take a look at the contained crates for language specific information:

## Projects using the library

- screen simulator (rust): [servicepoint-simulator](https://github.com/kaesaecracker/servicepoint-simulator)
- screen simulator (rust): [servicepoint-simulator](https://git.berlin.ccc.de/servicepoint/servicepoint-simulator)
- A bunch of projects (C): [arfst23/ServicePoint](https://github.com/arfst23/ServicePoint), including
- a CLI tool to display image files on the display or use the display as a TTY
- a BSD games robots clone
Expand All @@ -31,9 +32,12 @@ Take a look at the contained crates for language specific information:
- tanks game (C#): [servicepoint-tanks](https://github.com/kaesaecracker/cccb-tanks-cs)
- cellular automata slideshow (rust): [servicepoint-life](https://github.com/kaesaecracker/servicepoint-life)
- partial typescript implementation inspired by this library and browser stream: [cccb-servicepoint-browser](https://github.com/SamuelScheit/cccb-servicepoint-browser)
- a CLI: [servicepoint-cli](https://git.berlin.ccc.de/servicepoint/servicepoint-cli)

To add yourself to the list, open a pull request.

You can also check out [awesome-servicepoint](https://github.com/stars/kaesaecracker/lists/awesome-servicepoint) for a bigger collection of projects, including some not related to this library.

## Contributing

See [CONTRIBUTING.md](CONTRIBUTING.md).
Expand Down
3 changes: 2 additions & 1 deletion crates/servicepoint/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@ edition = "2021"
license = "GPL-3.0-or-later"
description = "A rust library for the CCCB Service Point Display."
homepage = "https://docs.rs/crate/servicepoint"
repository = "https://github.com/cccb/servicepoint"
repository = "https://git.berlin.ccc.de/servicepoint/servicepoint"
readme = "README.md"
keywords = ["cccb", "cccb-servicepoint"]

[lib]
crate-type = ["rlib"]
Expand Down
2 changes: 1 addition & 1 deletion crates/servicepoint/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,4 +64,4 @@ You can choose to (not) include them by toggling the related features.

## Everything else

Look at the main project [README](https://github.com/cccb/servicepoint/blob/main/README.md) for further information.
Look at the main project [README](https://git.berlin.ccc.de/servicepoint/servicepoint/src/branch/main/README.md) for further information.
21 changes: 19 additions & 2 deletions crates/servicepoint/src/bitmap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,15 +72,32 @@ impl Bitmap {
/// - when the width is not dividable by 8
#[must_use]
pub fn load(width: usize, height: usize, data: &[u8]) -> Self {
assert_eq!(width % 8, 0);
assert_eq!(data.len(), height * width / 8);
assert_eq!(width % 8, 0, "width must be a multiple of 8, but is {width}");
assert_eq!(data.len(), height * width / 8, "data length must match dimensions, with 8 pixels per byte.");
Self {
width,
height,
bit_vec: BitVec::from_slice(data),
}
}

/// Creates a [Bitmap] with the specified width from the provided [BitVec] without copying it.
///
/// returns: [Bitmap] that contains the provided data.
///
/// # Panics
///
/// - when the bitvec size is not dividable by the provided width
/// - when the width is not dividable by 8
#[must_use]
pub fn from_bitvec(width: usize, bit_vec: BitVec) -> Self {
assert_eq!(width % 8, 0, "width must be a multiple of 8, but is {width}");
let len = bit_vec.len();
let height = len / width;
assert_eq!(0, len % width, "dimension mismatch - len {len} is not dividable by {width}");
Self { width, height, bit_vec }
}

/// Iterate over all cells in [Bitmap].
///
/// Order is equivalent to the following loop:
Expand Down
7 changes: 7 additions & 0 deletions crates/servicepoint/src/brightness.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,4 +99,11 @@ mod tests {
assert_eq!(Brightness::MAX, Brightness::saturating_from(100));
assert_eq!(Brightness(5), Brightness::saturating_from(5));
}

#[test]
#[cfg(feature = "rand")]
fn test() {
let mut rng = rand::thread_rng();
assert_ne!(rng.gen::<Brightness>(), rng.gen());
}
}
4 changes: 2 additions & 2 deletions crates/servicepoint/src/brightness_grid.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ impl BrightnessGrid {
}

impl From<BrightnessGrid> for Vec<u8> {
fn from(value: ValueGrid<Brightness>) -> Self {
fn from(value: BrightnessGrid) -> Self {
value
.iter()
.map(|brightness| (*brightness).into())
Expand All @@ -35,7 +35,7 @@ impl From<BrightnessGrid> for Vec<u8> {
}

impl From<&BrightnessGrid> for ByteGrid {
fn from(value: &ValueGrid<Brightness>) -> Self {
fn from(value: &BrightnessGrid) -> Self {
let u8s = value
.iter()
.map(|brightness| (*brightness).into())
Expand Down
3 changes: 1 addition & 2 deletions crates/servicepoint/src/command.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
use crate::command_code::CommandCode;
use crate::compression::into_decompressed;
use crate::value_grid::ValueGrid;
use crate::*;

/// Type alias for documenting the meaning of the u16 in enum values
Expand Down Expand Up @@ -441,7 +440,7 @@ impl Command {
payload,
} = packet;

let grid = ValueGrid::load(*width as usize, *height as usize, payload);
let grid = ByteGrid::load(*width as usize, *height as usize, payload);
let grid = match BrightnessGrid::try_from(grid) {
Ok(grid) => grid,
Err(val) => return Err(TryFromPacketError::InvalidBrightness(val)),
Expand Down
113 changes: 112 additions & 1 deletion crates/servicepoint/src/command_code.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/// The u16 command codes used for the [Command]s.
#[repr(u16)]
#[derive(Debug, Copy, Clone)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub(crate) enum CommandCode {
Clear = 0x0002,
Cp437Data = 0x0003,
Expand Down Expand Up @@ -101,3 +101,114 @@ impl TryFrom<u16> for CommandCode {
}
}
}

#[cfg(test)]
mod tests {
use super::*;
#[test]
fn clear() {
assert_eq!(CommandCode::try_from(0x0002), Ok(CommandCode::Clear));
assert_eq!(u16::from(CommandCode::Clear), 0x0002);
}

#[test]
fn cp437_data() {
assert_eq!(CommandCode::try_from(0x0003), Ok(CommandCode::Cp437Data));
assert_eq!(u16::from(CommandCode::Cp437Data), 0x0003);
}

#[test]
fn char_brightness() {
assert_eq!(CommandCode::try_from(0x0005), Ok(CommandCode::CharBrightness));
assert_eq!(u16::from(CommandCode::CharBrightness), 0x0005);
}

#[test]
fn brightness() {
assert_eq!(CommandCode::try_from(0x0007), Ok(CommandCode::Brightness));
assert_eq!(u16::from(CommandCode::Brightness), 0x0007);
}

#[test]
fn hard_reset() {
assert_eq!(CommandCode::try_from(0x000b), Ok(CommandCode::HardReset));
assert_eq!(u16::from(CommandCode::HardReset), 0x000b);
}

#[test]
fn fade_out() {
assert_eq!(CommandCode::try_from(0x000d), Ok(CommandCode::FadeOut));
assert_eq!(u16::from(CommandCode::FadeOut), 0x000d);
}

#[test]
#[allow(deprecated)]
fn bitmap_legacy() {
assert_eq!(CommandCode::try_from(0x0010), Ok(CommandCode::BitmapLegacy));
assert_eq!(u16::from(CommandCode::BitmapLegacy), 0x0010);
}

#[test]
fn linear() {
assert_eq!(CommandCode::try_from(0x0012), Ok(CommandCode::BitmapLinear));
assert_eq!(u16::from(CommandCode::BitmapLinear), 0x0012);
}

#[test]
fn linear_and() {
assert_eq!(CommandCode::try_from(0x0014), Ok(CommandCode::BitmapLinearAnd));
assert_eq!(u16::from(CommandCode::BitmapLinearAnd), 0x0014);
}

#[test]
fn linear_xor() {
assert_eq!(CommandCode::try_from(0x0016), Ok(CommandCode::BitmapLinearXor));
assert_eq!(u16::from(CommandCode::BitmapLinearXor), 0x0016);
}

#[test]
#[cfg(feature = "compression_zlib")]
fn bitmap_win_zlib() {
assert_eq!(CommandCode::try_from(0x0017), Ok(CommandCode::BitmapLinearWinZlib));
assert_eq!(u16::from(CommandCode::BitmapLinearWinZlib), 0x0017);
}

#[test]
#[cfg(feature = "compression_bzip2")]
fn bitmap_win_bzip2() {
assert_eq!(CommandCode::try_from(0x0018), Ok(CommandCode::BitmapLinearWinBzip2));
assert_eq!(u16::from(CommandCode::BitmapLinearWinBzip2), 0x0018);
}

#[test]
#[cfg(feature = "compression_lzma")]
fn bitmap_win_lzma() {
assert_eq!(CommandCode::try_from(0x0019), Ok(CommandCode::BitmapLinearWinLzma));
assert_eq!(u16::from(CommandCode::BitmapLinearWinLzma), 0x0019);
}

#[test]
#[cfg(feature = "compression_zstd")]
fn bitmap_win_zstd() {
assert_eq!(CommandCode::try_from(0x001A), Ok(CommandCode::BitmapLinearWinZstd));
assert_eq!(u16::from(CommandCode::BitmapLinearWinZstd), 0x001A);
}

#[test]
fn bitmap_win_uncompressed() {
assert_eq!(CommandCode::try_from(0x0013), Ok(CommandCode::BitmapLinearWinUncompressed));
assert_eq!(u16::from(CommandCode::BitmapLinearWinUncompressed), 0x0013);
}

#[test]
fn utf8_data() {
assert_eq!(CommandCode::try_from(0x0020), Ok(CommandCode::Utf8Data));
assert_eq!(u16::from(CommandCode::Utf8Data), 0x0020);
}

#[test]
fn linear_or() {
assert_eq!(CommandCode::try_from(0x0015), Ok(CommandCode::BitmapLinearOr));
assert_eq!(u16::from(CommandCode::BitmapLinearOr), 0x0015);
}
}
53 changes: 53 additions & 0 deletions crates/servicepoint/src/compression_code.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,3 +65,56 @@ impl TryFrom<u16> for CompressionCode {
}
}
}

#[cfg(test)]
mod test {
use super::*;
#[test]
fn uncompressed() {
assert_eq!(
CompressionCode::try_from(0x0000),
Ok(CompressionCode::Uncompressed)
);
assert_eq!(u16::from(CompressionCode::Uncompressed), 0x0000);
}

#[test]
#[cfg(feature = "compression_zlib")]
fn zlib() {
assert_eq!(
CompressionCode::try_from(0x677a),
Ok(CompressionCode::Zlib)
);
assert_eq!(u16::from(CompressionCode::Zlib), 0x677a);
}

#[test]
#[cfg(feature = "compression_bzip2")]
fn bzip2() {
assert_eq!(
CompressionCode::try_from(0x627a),
Ok(CompressionCode::Bzip2)
);
assert_eq!(u16::from(CompressionCode::Bzip2), 0x627a);
}

#[test]
#[cfg(feature = "compression_lzma")]
fn lzma() {
assert_eq!(
CompressionCode::try_from(0x6c7a),
Ok(CompressionCode::Lzma)
);
assert_eq!(u16::from(CompressionCode::Lzma), 0x6c7a);
}

#[test]
#[cfg(feature = "compression_zstd")]
fn zstd() {
assert_eq!(
CompressionCode::try_from(0x7a73),
Ok(CompressionCode::Zstd)
);
assert_eq!(u16::from(CompressionCode::Zstd), 0x7a73);
}
}
24 changes: 22 additions & 2 deletions crates/servicepoint/src/value_grid.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,21 @@ impl<T: Value> ValueGrid<T> {
}
}

/// Creates a [ValueGrid] with the specified width from the provided data without copying it.
///
/// returns: [ValueGrid] that contains the provided data.
///
/// # Panics
///
/// - when the data size is not dividable by the width.
#[must_use]
pub fn from_vec(width: usize, data: Vec<T>) -> Self {
let len = data.len();
let height = len / width;
assert_eq!(0, len % width, "dimension mismatch - len {len} is not dividable by {width}");
Self { data, width, height }
}

/// Loads a [ValueGrid] with the specified width from the provided data, wrapping to as many rows as needed.
///
/// returns: [ValueGrid] that contains a copy of the provided data or [TryLoadValueGridError].
Expand Down Expand Up @@ -496,13 +511,18 @@ mod tests {

#[test]
fn ref_mut() {
let mut vec = ValueGrid::load(2, 2, &[0, 1, 2, 3]);
let mut vec = ValueGrid::from_vec(3, vec![0, 1, 2, 3,4,5,6,7,8]);

let top_left = vec.get_ref_mut(0, 0);
*top_left += 5;
let somewhere = vec.get_ref_mut(2, 1);
*somewhere = 42;

assert_eq!(None, vec.get_ref_mut_optional(2, 2));
assert_eq!(None, vec.get_ref_mut_optional(3, 2));
assert_eq!(None, vec.get_ref_mut_optional(2, 3));
assert_eq!(Some(&mut 5), vec.get_ref_mut_optional(0, 0));
assert_eq!(Some(&mut 42), vec.get_ref_mut_optional(2, 1));
assert_eq!(Some(&mut 8), vec.get_ref_mut_optional(2, 2));
}

#[test]
Expand Down
3 changes: 2 additions & 1 deletion crates/servicepoint_binding_c/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,10 @@ edition = "2021"
license = "GPL-3.0-or-later"
description = "C bindings for the servicepoint crate."
homepage = "https://docs.rs/crate/servicepoint_binding_c"
repository = "https://github.com/cccb/servicepoint"
repository = "https://git.berlin.ccc.de/servicepoint/servicepoint"
readme = "README.md"
links = "servicepoint"
keywords = ["cccb", "cccb-servicepoint", "cbindgen"]

[lib]
crate-type = ["staticlib", "cdylib", "rlib"]
Expand Down
2 changes: 1 addition & 1 deletion crates/servicepoint_binding_c/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,4 +60,4 @@ You have the choice of linking statically (recommended) or dynamically.

## Everything else

Look at the main project [README](https://github.com/cccb/servicepoint/blob/main/README.md) for further information.
Look at the main project [README](https://git.berlin.ccc.de/servicepoint/servicepoint/src/branch/main/README.md) for further information.
3 changes: 2 additions & 1 deletion crates/servicepoint_binding_uniffi/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@ edition = "2021"
license = "GPL-3.0-or-later"
description = "C bindings for the servicepoint crate."
homepage = "https://docs.rs/crate/servicepoint_binding_c"
repository = "https://github.com/cccb/servicepoint"
repository = "https://git.berlin.ccc.de/servicepoint/servicepoint"
#readme = "README.md"
keywords = ["cccb", "cccb-servicepoint", "uniffi"]

[lib]
crate-type = ["cdylib"]
Expand Down
Loading