features, cargo fmt
This commit is contained in:
parent
ef7690b6b2
commit
8ea511a33a
9 changed files with 25 additions and 15 deletions
|
|
@ -26,8 +26,9 @@ git = "https://git.berlin.ccc.de/servicepoint/servicepoint/"
|
|||
branch = "next"
|
||||
|
||||
[features]
|
||||
full = ["servicepoint/all_compressions", "servicepoint/default"]
|
||||
default = ["full"]
|
||||
protocol_udp = ["servicepoint/protocol_udp"]
|
||||
all_compressions = ["servicepoint/all_compressions"]
|
||||
default = ["all_compressions", "servicepoint/default", "protocol_udp"]
|
||||
|
||||
[lints.rust]
|
||||
missing-docs = "warn"
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ CARGO := rustup run nightly cargo
|
|||
|
||||
TARGET := x86_64-unknown-linux-musl
|
||||
PROFILE := size-optimized
|
||||
FEATURES := protocol_udp
|
||||
|
||||
THIS_DIR := $(dir $(realpath $(lastword $(MAKEFILE_LIST))))
|
||||
REPO_ROOT := $(THIS_DIR)/..
|
||||
|
|
@ -22,6 +23,7 @@ RUSTFLAGS := -Zlocation-detail=none \
|
|||
CARGOFLAGS := --manifest-path=$(REPO_ROOT)/Cargo.toml \
|
||||
--profile=$(PROFILE) \
|
||||
--no-default-features \
|
||||
--features=$(FEATURES) \
|
||||
--target=$(TARGET) \
|
||||
-Zbuild-std="core,std,alloc,proc_macro,panic_abort" \
|
||||
-Zbuild-std-features="panic_immediate_abort" \
|
||||
|
|
@ -53,7 +55,7 @@ _programs := $(basename $(_c_src))
|
|||
_bins := $(addprefix out/, $(_programs))
|
||||
_unstripped_bins := $(addsuffix _unstripped, $(_bins))
|
||||
_run_programs := $(addprefix run_, $(_programs))
|
||||
_rs_src := $(wildcard ../src/**.rs) ../Cargo.lock
|
||||
_rs_src := $(wildcard ../src/**.rs) ../Cargo.lock ../Cargo.toml ../cbindgen.toml
|
||||
|
||||
all: $(_bins)
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
use crate::byte_slice::ByteSlice;
|
||||
use crate::{heap_drop, heap_move, heap_move_nonnull, heap_remove, SPBitVec};
|
||||
use servicepoint::{Bitmap, BitmapCommand, CompressionCode, DataRef, Grid, Origin, Packet};
|
||||
use servicepoint::{
|
||||
Bitmap, BitmapCommand, CompressionCode, DataRef, Grid, Origin, Packet,
|
||||
};
|
||||
use std::ptr::NonNull;
|
||||
|
||||
/// Creates a new [Bitmap] with the specified dimensions.
|
||||
|
|
@ -210,7 +212,7 @@ pub unsafe extern "C" fn sp_bitmap_into_packet(
|
|||
bitmap: NonNull<Bitmap>,
|
||||
x: usize,
|
||||
y: usize,
|
||||
compression: CompressionCode
|
||||
compression: CompressionCode,
|
||||
) -> *mut Packet {
|
||||
let bitmap = unsafe { heap_remove(bitmap) };
|
||||
match Packet::try_from(BitmapCommand {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
use crate::{heap_drop, heap_move, heap_move_nonnull, heap_remove, ByteSlice};
|
||||
use servicepoint::{BinaryOperation, BitVecCommand, BitVecU8Msb0, CompressionCode, Packet};
|
||||
use servicepoint::{
|
||||
BinaryOperation, BitVecCommand, BitVecU8Msb0, CompressionCode, Packet,
|
||||
};
|
||||
use std::ptr::NonNull;
|
||||
|
||||
/// A vector of bits
|
||||
|
|
@ -157,7 +159,7 @@ pub unsafe extern "C" fn sp_bitvec_into_packet(
|
|||
bitvec: NonNull<SPBitVec>,
|
||||
offset: usize,
|
||||
operation: BinaryOperation,
|
||||
compression: CompressionCode
|
||||
compression: CompressionCode,
|
||||
) -> *mut Packet {
|
||||
let bitvec = unsafe { heap_remove(bitvec) }.0;
|
||||
match Packet::try_from(BitVecCommand {
|
||||
|
|
|
|||
|
|
@ -1,3 +0,0 @@
|
|||
mod typed;
|
||||
|
||||
pub use typed::*;
|
||||
|
|
@ -1,5 +1,7 @@
|
|||
use crate::{heap_drop, heap_move, heap_move_nonnull, heap_remove, ByteSlice};
|
||||
use servicepoint::{Cp437Grid, Cp437GridCommand, DataRef, Grid, Origin, Packet};
|
||||
use servicepoint::{
|
||||
Cp437Grid, Cp437GridCommand, DataRef, Grid, Origin, Packet,
|
||||
};
|
||||
use std::ptr::NonNull;
|
||||
|
||||
/// Creates a new [Cp437Grid] with the specified dimensions.
|
||||
|
|
|
|||
12
src/lib.rs
12
src/lib.rs
|
|
@ -30,22 +30,26 @@ pub use crate::bitvec::*;
|
|||
pub use crate::brightness_grid::*;
|
||||
pub use crate::byte_slice::*;
|
||||
pub use crate::char_grid::*;
|
||||
pub use crate::commands::*;
|
||||
pub use crate::connection::*;
|
||||
pub use crate::cp437_grid::*;
|
||||
pub use crate::packet::*;
|
||||
pub use servicepoint::CommandCode;
|
||||
use std::ptr::NonNull;
|
||||
pub use typed_command::*;
|
||||
|
||||
mod bitmap;
|
||||
mod bitvec;
|
||||
mod brightness_grid;
|
||||
mod byte_slice;
|
||||
mod char_grid;
|
||||
mod commands;
|
||||
mod connection;
|
||||
mod cp437_grid;
|
||||
mod packet;
|
||||
mod typed_command;
|
||||
|
||||
#[cfg(feature = "protocol_udp")]
|
||||
mod udp;
|
||||
|
||||
#[cfg(feature = "protocol_udp")]
|
||||
pub use udp::*;
|
||||
|
||||
use std::time::Duration;
|
||||
|
||||
|
|
|
|||
201
src/typed_command.rs
Normal file
201
src/typed_command.rs
Normal file
|
|
@ -0,0 +1,201 @@
|
|||
use crate::{heap_drop, heap_move, heap_move_nonnull, SPBitVec};
|
||||
use servicepoint::{
|
||||
BinaryOperation, Bitmap, Brightness, BrightnessGrid, CharGrid,
|
||||
CompressionCode, Cp437Grid, GlobalBrightnessCommand, Packet, TypedCommand,
|
||||
};
|
||||
use std::ptr::NonNull;
|
||||
|
||||
/// Tries to turn a [Packet] into a [TypedCommand].
|
||||
///
|
||||
/// The packet is deallocated in the process.
|
||||
///
|
||||
/// Returns: pointer to new [TypedCommand] instance or NULL if parsing failed.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sp_command_try_from_packet(
|
||||
packet: NonNull<Packet>,
|
||||
) -> *mut TypedCommand {
|
||||
let packet = *unsafe { Box::from_raw(packet.as_ptr()) };
|
||||
match servicepoint::TypedCommand::try_from(packet) {
|
||||
Err(_) => std::ptr::null_mut(),
|
||||
Ok(command) => heap_move(command),
|
||||
}
|
||||
}
|
||||
|
||||
/// Clones a [TypedCommand] instance.
|
||||
///
|
||||
/// returns: new [TypedCommand] instance.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sp_command_clone(
|
||||
command: NonNull<TypedCommand>,
|
||||
) -> NonNull<TypedCommand> {
|
||||
heap_move_nonnull(unsafe { command.as_ref().clone() })
|
||||
}
|
||||
|
||||
/// Set all pixels to the off state.
|
||||
///
|
||||
/// Does not affect brightness.
|
||||
///
|
||||
/// Returns: a new [servicepoint::Command::Clear] instance.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```C
|
||||
/// sp_udp_send_command(connection, sp_command_clear());
|
||||
/// ```
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sp_command_clear() -> NonNull<TypedCommand> {
|
||||
heap_move_nonnull(servicepoint::ClearCommand.into())
|
||||
}
|
||||
|
||||
/// Kills the udp daemon on the display, which usually results in a restart.
|
||||
///
|
||||
/// Please do not send this in your normal program flow.
|
||||
///
|
||||
/// Returns: a new [servicepoint::Command::HardReset] instance.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sp_command_hard_reset() -> NonNull<TypedCommand> {
|
||||
heap_move_nonnull(servicepoint::HardResetCommand.into())
|
||||
}
|
||||
|
||||
/// A yet-to-be-tested command.
|
||||
///
|
||||
/// Returns: a new [servicepoint::Command::FadeOut] instance.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sp_command_fade_out() -> NonNull<TypedCommand> {
|
||||
heap_move_nonnull(servicepoint::FadeOutCommand.into())
|
||||
}
|
||||
|
||||
/// Set the brightness of all tiles to the same value.
|
||||
///
|
||||
/// Returns: a new [servicepoint::Command::Brightness] instance.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sp_command_global_brightness(
|
||||
brightness: Brightness,
|
||||
) -> NonNull<TypedCommand> {
|
||||
heap_move_nonnull(GlobalBrightnessCommand::from(brightness).into())
|
||||
}
|
||||
|
||||
/// Set the brightness of individual tiles in a rectangular area of the display.
|
||||
///
|
||||
/// The passed [BrightnessGrid] gets consumed.
|
||||
///
|
||||
/// Returns: a new [servicepoint::Command::CharBrightness] instance.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sp_command_brightness_grid(
|
||||
x: usize,
|
||||
y: usize,
|
||||
grid: NonNull<BrightnessGrid>,
|
||||
) -> NonNull<TypedCommand> {
|
||||
let grid = unsafe { *Box::from_raw(grid.as_ptr()) };
|
||||
let result = servicepoint::BrightnessGridCommand {
|
||||
origin: servicepoint::Origin::new(x, y),
|
||||
grid,
|
||||
}
|
||||
.into();
|
||||
heap_move_nonnull(result)
|
||||
}
|
||||
|
||||
/// Set pixel data starting at the pixel offset on screen.
|
||||
///
|
||||
/// The screen will continuously overwrite more pixel data without regarding the offset, meaning
|
||||
/// once the starting row is full, overwriting will continue on column 0.
|
||||
///
|
||||
/// The [`BinaryOperation`] will be applied on the display comparing old and sent bit.
|
||||
///
|
||||
/// `new_bit = old_bit op sent_bit`
|
||||
///
|
||||
/// For example, [`BinaryOperation::Or`] can be used to turn on some pixels without affecting other pixels.
|
||||
///
|
||||
/// The contained [`BitVecU8Msb0`] is always uncompressed.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sp_command_bitvec(
|
||||
offset: usize,
|
||||
bit_vec: NonNull<SPBitVec>,
|
||||
compression: CompressionCode,
|
||||
operation: BinaryOperation,
|
||||
) -> *mut TypedCommand {
|
||||
let bit_vec = unsafe { *Box::from_raw(bit_vec.as_ptr()) };
|
||||
let command = servicepoint::BitVecCommand {
|
||||
offset,
|
||||
operation,
|
||||
bitvec: bit_vec.0,
|
||||
compression,
|
||||
}
|
||||
.into();
|
||||
heap_move(command)
|
||||
}
|
||||
|
||||
/// Show codepage 437 encoded text on the screen.
|
||||
///
|
||||
/// The passed [Cp437Grid] gets consumed.
|
||||
///
|
||||
/// Returns: a new [servicepoint::Cp437GridCommand] instance.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sp_command_cp437_grid(
|
||||
x: usize,
|
||||
y: usize,
|
||||
grid: NonNull<Cp437Grid>,
|
||||
) -> NonNull<TypedCommand> {
|
||||
let grid = *unsafe { Box::from_raw(grid.as_ptr()) };
|
||||
let result = servicepoint::Cp437GridCommand {
|
||||
origin: servicepoint::Origin::new(x, y),
|
||||
grid,
|
||||
}
|
||||
.into();
|
||||
heap_move_nonnull(result)
|
||||
}
|
||||
|
||||
/// Show UTF-8 encoded text on the screen.
|
||||
///
|
||||
/// The passed [CharGrid] gets consumed.
|
||||
///
|
||||
/// Returns: a new [servicepoint::CharGridCommand] instance.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sp_command_char_grid(
|
||||
x: usize,
|
||||
y: usize,
|
||||
grid: NonNull<CharGrid>,
|
||||
) -> NonNull<TypedCommand> {
|
||||
let grid = unsafe { *Box::from_raw(grid.as_ptr()) };
|
||||
let result = servicepoint::CharGridCommand {
|
||||
origin: servicepoint::Origin::new(x, y),
|
||||
grid,
|
||||
}
|
||||
.into();
|
||||
heap_move_nonnull(result)
|
||||
}
|
||||
|
||||
/// Sets a window of pixels to the specified values.
|
||||
///
|
||||
/// The passed [Bitmap] gets consumed.
|
||||
///
|
||||
/// Returns: a new [servicepoint::BitmapCommand] instance.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sp_command_bitmap(
|
||||
x: usize,
|
||||
y: usize,
|
||||
bitmap: NonNull<Bitmap>,
|
||||
compression: CompressionCode,
|
||||
) -> *mut TypedCommand {
|
||||
let bitmap = unsafe { *Box::from_raw(bitmap.as_ptr()) };
|
||||
let command = servicepoint::BitmapCommand {
|
||||
origin: servicepoint::Origin::new(x, y),
|
||||
bitmap,
|
||||
compression,
|
||||
}
|
||||
.into();
|
||||
heap_move(command)
|
||||
}
|
||||
|
||||
/// Deallocates a [TypedCommand].
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```C
|
||||
/// TypedCommand c = sp_command_clear();
|
||||
/// sp_command_free(c);
|
||||
/// ```
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sp_command_free(command: NonNull<TypedCommand>) {
|
||||
unsafe { heap_drop(command) }
|
||||
}
|
||||
119
src/udp.rs
Normal file
119
src/udp.rs
Normal file
|
|
@ -0,0 +1,119 @@
|
|||
use crate::{heap_drop, heap_move, heap_remove};
|
||||
use servicepoint::{Connection, Header, Packet, TypedCommand, UdpConnection};
|
||||
use std::ffi::{c_char, CStr};
|
||||
use std::net::{Ipv4Addr, SocketAddrV4};
|
||||
use std::ptr::NonNull;
|
||||
|
||||
/// Creates a new instance of [UdpConnection].
|
||||
///
|
||||
/// returns: NULL if connection fails, or connected instance
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```C
|
||||
/// UdpConnection connection = sp_udp_open("172.23.42.29:2342");
|
||||
/// if (connection != NULL)
|
||||
/// sp_udp_send_command(connection, sp_command_clear());
|
||||
/// ```
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sp_udp_open(
|
||||
host: NonNull<c_char>,
|
||||
) -> *mut UdpConnection {
|
||||
let host = unsafe { CStr::from_ptr(host.as_ptr()) }
|
||||
.to_str()
|
||||
.expect("Bad encoding");
|
||||
let connection = match UdpConnection::open(host) {
|
||||
Err(_) => return std::ptr::null_mut(),
|
||||
Ok(value) => value,
|
||||
};
|
||||
|
||||
heap_move(connection)
|
||||
}
|
||||
|
||||
/// Creates a new instance of [UdpConnection].
|
||||
///
|
||||
/// returns: NULL if connection fails, or connected instance
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```C
|
||||
/// UdpConnection connection = sp_udp_open_ipv4(172, 23, 42, 29, 2342);
|
||||
/// if (connection != NULL)
|
||||
/// sp_udp_send_command(connection, sp_command_clear());
|
||||
/// ```
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sp_udp_open_ipv4(
|
||||
ip1: u8,
|
||||
ip2: u8,
|
||||
ip3: u8,
|
||||
ip4: u8,
|
||||
port: u16,
|
||||
) -> *mut UdpConnection {
|
||||
let addr = SocketAddrV4::new(Ipv4Addr::from([ip1, ip2, ip3, ip4]), port);
|
||||
let connection = match UdpConnection::open(addr) {
|
||||
Err(_) => return std::ptr::null_mut(),
|
||||
Ok(value) => value,
|
||||
};
|
||||
heap_move(connection)
|
||||
}
|
||||
|
||||
/// Sends a [Packet] to the display using the [UdpConnection].
|
||||
///
|
||||
/// The passed `packet` gets consumed.
|
||||
///
|
||||
/// returns: true in case of success
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sp_udp_send_packet(
|
||||
connection: NonNull<UdpConnection>,
|
||||
packet: NonNull<Packet>,
|
||||
) -> bool {
|
||||
let packet = unsafe { heap_remove(packet) };
|
||||
unsafe { connection.as_ref().send(packet) }.is_ok()
|
||||
}
|
||||
|
||||
/// Sends a [TypedCommand] to the display using the [UdpConnection].
|
||||
///
|
||||
/// The passed `command` gets consumed.
|
||||
///
|
||||
/// returns: true in case of success
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```C
|
||||
/// sp_udp_send_command(connection, sp_command_brightness(5));
|
||||
/// ```
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sp_udp_send_command(
|
||||
connection: NonNull<UdpConnection>,
|
||||
command: NonNull<TypedCommand>,
|
||||
) -> bool {
|
||||
let command = unsafe { heap_remove(command) };
|
||||
unsafe { connection.as_ref().send(command) }.is_ok()
|
||||
}
|
||||
|
||||
/// Sends a [Header] to the display using the [UdpConnection].
|
||||
///
|
||||
/// returns: true in case of success
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```C
|
||||
/// sp_udp_send_header(connection, sp_command_brightness(5));
|
||||
/// ```
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sp_udp_send_header(
|
||||
udp_connection: NonNull<UdpConnection>,
|
||||
header: Header,
|
||||
) -> bool {
|
||||
let packet = Packet {
|
||||
header,
|
||||
payload: vec![],
|
||||
};
|
||||
unsafe { udp_connection.as_ref() }.send(packet).is_ok()
|
||||
}
|
||||
|
||||
/// Closes and deallocates a [UdpConnection].
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sp_udp_free(connection: NonNull<UdpConnection>) {
|
||||
unsafe { heap_drop(connection) }
|
||||
}
|
||||
Loading…
Reference in a new issue