Compare commits

..

No commits in common. "3589a90385b7bf33f165fe8fb663f2798bd523d7" and "b4eab85b199bef044cc33cff20c9bf44ee9d8c53" have entirely different histories.

19 changed files with 90 additions and 395 deletions

2
Cargo.lock generated
View file

@ -408,7 +408,7 @@ dependencies = [
[[package]] [[package]]
name = "servicepoint" name = "servicepoint"
version = "0.13.2" version = "0.13.2"
source = "git+https://git.berlin.ccc.de/servicepoint/servicepoint/?branch=next#114385868af03f8cba7c87a630b501bb0106d140" source = "git+https://git.berlin.ccc.de/servicepoint/servicepoint/?branch=next#531d4e6b4a368dc126cab9dc12b64d2ca8a81694"
dependencies = [ dependencies = [
"bitvec", "bitvec",
"bzip2", "bzip2",

View file

@ -33,9 +33,6 @@ default = ["full"]
missing-docs = "warn" missing-docs = "warn"
unsafe_op_in_unsafe_fn = "warn" unsafe_op_in_unsafe_fn = "warn"
[lints.clippy]
missing_safety_doc = "allow"
[package.metadata.docs.rs] [package.metadata.docs.rs]
all-features = true all-features = true

View file

@ -1,12 +1,9 @@
CC := gcc CC := gcc
CARGO := rustup run nightly cargo CARGO := rustup run nightly cargo
TARGET := x86_64-unknown-linux-musl
PROFILE := size-optimized
THIS_DIR := $(dir $(realpath $(lastword $(MAKEFILE_LIST)))) THIS_DIR := $(dir $(realpath $(lastword $(MAKEFILE_LIST))))
REPO_ROOT := $(THIS_DIR)/.. REPO_ROOT := $(THIS_DIR)/..
RUST_TARGET_DIR := $(REPO_ROOT)/target/$(TARGET)/$(PROFILE) RUST_TARGET_DIR := $(REPO_ROOT)/target/x86_64-unknown-linux-musl/size-optimized
export SERVICEPOINT_HEADER_OUT := $(REPO_ROOT)/include export SERVICEPOINT_HEADER_OUT := $(REPO_ROOT)/include
RUSTFLAGS := -Zlocation-detail=none \ RUSTFLAGS := -Zlocation-detail=none \
@ -20,9 +17,9 @@ RUSTFLAGS := -Zlocation-detail=none \
-C panic=abort -C panic=abort
CARGOFLAGS := --manifest-path=$(REPO_ROOT)/Cargo.toml \ CARGOFLAGS := --manifest-path=$(REPO_ROOT)/Cargo.toml \
--profile=$(PROFILE) \ --profile=size-optimized \
--no-default-features \ --no-default-features \
--target=$(TARGET) \ --target=x86_64-unknown-linux-musl \
-Zbuild-std="core,std,alloc,proc_macro,panic_abort" \ -Zbuild-std="core,std,alloc,proc_macro,panic_abort" \
-Zbuild-std-features="panic_immediate_abort" \ -Zbuild-std-features="panic_immediate_abort" \
@ -40,31 +37,28 @@ CCFLAGS := -static -Os \
-fvisibility=hidden \ -fvisibility=hidden \
-Bsymbolic \ -Bsymbolic \
-Wl,--exclude-libs,ALL \ -Wl,--exclude-libs,ALL \
-fno-ident \ -fno-ident
-Wall
#-fuse-ld=gold \ #-fuse-ld=gold \
-fno-exceptions -fno-exceptions
#-Wl,--icf=all \ #-Wl,--icf=all \
STRIPFLAGS := -s --strip-unneeded -R .comment -R .gnu.version -R .comment -R .note -R .note.gnu.build-id -R .note.ABI-tag STRIPFLAGS := -s --strip-unneeded -R .comment -R .gnu.version -R .comment -R .note -R .note.gnu.build-id -R .note.ABI-tag
_c_src := $(wildcard *.c) src := $(wildcard *.c)
_programs := $(basename $(_c_src)) programs := $(basename $(src))
_bins := $(addprefix out/, $(_programs)) bins := $(addprefix out/, $(programs))
_unstripped_bins := $(addsuffix _unstripped, $(_bins)) unstripped_bins := $(addsuffix _unstripped, $(bins))
_run_programs := $(addprefix run_, $(_programs))
_rs_src := $(wildcard ../src/**.rs) ../Cargo.lock
all: $(_bins) all: $(bins)
clean: clean:
rm -r out || true rm -r out || true
rm include/servicepoint.h || true rm include/servicepoint.h || true
cargo clean cargo clean
PHONY: all clean sizes $(_run_programs) PHONY: all clean analyze-size
$(_unstripped_bins): out/%_unstripped: %.c $(SERVICEPOINT_HEADER_OUT)/servicepoint.h $(RUST_TARGET_DIR)/libservicepoint_binding_c.a $(unstripped_bins): out/%_unstripped: %.c $(SERVICEPOINT_HEADER_OUT)/servicepoint.h
mkdir -p out || true mkdir -p out || true
${CC} $^ \ ${CC} $^ \
-I $(SERVICEPOINT_HEADER_OUT) \ -I $(SERVICEPOINT_HEADER_OUT) \
@ -72,23 +66,17 @@ $(_unstripped_bins): out/%_unstripped: %.c $(SERVICEPOINT_HEADER_OUT)/servicepoi
$(CCFLAGS) \ $(CCFLAGS) \
-o $@ -o $@
$(_bins): out/%: out/%_unstripped $(bins): out/%: out/%_unstripped
strip $(STRIPFLAGS) $^ -o $@ strip $(STRIPFLAGS) $^ -o $@
$(SERVICEPOINT_HEADER_OUT)/servicepoint.h $(RUST_TARGET_DIR)/libservicepoint_binding_c.a: $(_rs_src) $(SERVICEPOINT_HEADER_OUT)/servicepoint.h: FORCE
mkdir -p include || true mkdir -p include || true
# generate servicepoint header and binary to link against # generate servicepoint header and binary to link against
${CARGO} rustc $(CARGOFLAGS) -- $(RUSTFLAGS) ${CARGO} rustc $(CARGOFLAGS) -- $(RUSTFLAGS)
$(_run_programs): run_%: out/% FORCE analyze-size: out/example_unstripped
./$< nm --print-size --size-sort --reverse-sort --radix=d --demangle out/example_unstripped \
| awk '{size=$$2+0; print size "\t" $$4}' \
sizes: $(_bins) | less
ls -lB out
#analyze-size: out/example_unstripped
# nm --print-size --size-sort --reverse-sort --radix=d --demangle out/example_unstripped \
# | awk '{size=$$2+0; print size "\t" $$4}' \
# | less
FORCE: ; FORCE: ;

View file

@ -1,17 +1,17 @@
#include <stdio.h>
#include "servicepoint.h" #include "servicepoint.h"
int main(void) { int main(void) {
//UdpConnection *connection = sp_udp_open_ipv4(172, 23, 42, 29, 2342); UdpConnection *connection = sp_udp_open_ipv4(172, 23, 42, 29, 2342);
UdpConnection *connection = sp_udp_open_ipv4(127, 0, 0, 1, 2342);
if (connection == NULL) if (connection == NULL)
return 1; return 1;
sp_udp_send_header(connection, (Header) {.command_code = COMMAND_CODE_CLEAR}); sp_udp_send_command(connection, sp_command_clear());
CharGrid *grid = sp_char_grid_new(5, 2); CharGrid *grid = sp_char_grid_new(5,2);
if (grid == NULL) if (grid == NULL)
return 1; return 1;
sp_char_grid_set(grid, 0, 0, 'H'); sp_char_grid_set(grid, 0, 0, 'H');
sp_char_grid_set(grid, 1, 0, 'e'); sp_char_grid_set(grid, 1, 0, 'e');
sp_char_grid_set(grid, 2, 0, 'l'); sp_char_grid_set(grid, 2, 0, 'l');
@ -23,10 +23,9 @@ int main(void) {
sp_char_grid_set(grid, 3, 1, 'l'); sp_char_grid_set(grid, 3, 1, 'l');
sp_char_grid_set(grid, 4, 1, 'd'); sp_char_grid_set(grid, 4, 1, 'd');
Packet *packet = sp_char_grid_into_packet(grid, 0, 0);
if (packet == NULL) TypedCommand *command = sp_command_char_grid(0, 0, grid);
return 1; sp_udp_send_command(connection, command);
sp_udp_send_packet(connection, packet);
sp_udp_free(connection); sp_udp_free(connection);
return 0; return 0;

View file

@ -1,30 +0,0 @@
#include "servicepoint.h"
int main(void) {
// UdpConnection *connection = sp_udp_open_ipv4(172, 23, 42, 29, 2342);
UdpConnection *connection = sp_udp_open_ipv4(127, 0, 0, 1, 2342);
if (connection == NULL)
return -1;
Bitmap *all_on = sp_bitmap_new_max_sized();
sp_bitmap_fill(all_on, true);
Packet *packet = sp_bitmap_into_packet(all_on, 0, 0, COMPRESSION_CODE_UNCOMPRESSED);
if (packet == NULL)
return -1;
sp_udp_send_packet(connection, packet);
BrightnessGrid *grid = sp_brightness_grid_new(TILE_WIDTH, TILE_HEIGHT);
ByteSlice slice = sp_brightness_grid_unsafe_data_ref(grid);
for (size_t index = 0; index < slice.length; index++) {
slice.start[index] = (uint8_t) (index % ((size_t) Brightness_MAX));
}
packet = sp_brightness_grid_into_packet(grid, 0, 0);
sp_udp_send_packet(connection, packet);
sp_udp_free(connection);
return 0;
}

View file

@ -8,16 +8,18 @@ int main(void) {
Bitmap *pixels = sp_bitmap_new(PIXEL_WIDTH, PIXEL_HEIGHT); Bitmap *pixels = sp_bitmap_new(PIXEL_WIDTH, PIXEL_HEIGHT);
if (pixels == NULL) if (pixels == NULL)
return 1; return 1;
sp_bitmap_fill(pixels, true); sp_bitmap_fill(pixels, true);
Packet *packet = sp_bitmap_into_packet(pixels, 0, 0, COMPRESSION_CODE_UNCOMPRESSED); TypedCommand *command = sp_command_bitmap(0, 0, pixels, COMPRESSION_CODE_UNCOMPRESSED);
if (packet == NULL) if (command == NULL)
return 1; return 1;
Packet *packet = sp_packet_from_command(command);
Header *header = sp_packet_get_header(packet); Header *header = sp_packet_get_header(packet);
printf("[%d, %d, %d, %d, %d]\n", header->command_code, header->a, header->b, header->c, header->d); //printf("[%d, %d, %d, %d, %d]\n", header->command_code, header->a, header->b, header->c, header->d);
sp_udp_send_packet(connection, packet); sp_udp_send_packet(connection, packet);

View file

@ -59,6 +59,7 @@
gcc gcc
gnumake gnumake
pkg-config pkg-config
]; ];
RUST_SRC_PATH = "${pkgs.rust.packages.stable.rustPlatform.rustLibSrc}"; RUST_SRC_PATH = "${pkgs.rust.packages.stable.rustPlatform.rustLibSrc}";

View file

@ -95,36 +95,6 @@ enum BinaryOperation
typedef uint8_t BinaryOperation; typedef uint8_t BinaryOperation;
#endif // __cplusplus #endif // __cplusplus
/**
* The u16 command codes used for the [Command]s.
*/
enum CommandCode
#ifdef __cplusplus
: uint16_t
#endif // __cplusplus
{
COMMAND_CODE_CLEAR = 2,
COMMAND_CODE_CP437_DATA = 3,
COMMAND_CODE_CHAR_BRIGHTNESS = 5,
COMMAND_CODE_BRIGHTNESS = 7,
COMMAND_CODE_HARD_RESET = 11,
COMMAND_CODE_FADE_OUT = 13,
COMMAND_CODE_BITMAP_LEGACY = 16,
COMMAND_CODE_BITMAP_LINEAR = 18,
COMMAND_CODE_BITMAP_LINEAR_WIN_UNCOMPRESSED = 19,
COMMAND_CODE_BITMAP_LINEAR_AND = 20,
COMMAND_CODE_BITMAP_LINEAR_OR = 21,
COMMAND_CODE_BITMAP_LINEAR_XOR = 22,
COMMAND_CODE_BITMAP_LINEAR_WIN_ZLIB = 23,
COMMAND_CODE_BITMAP_LINEAR_WIN_BZIP2 = 24,
COMMAND_CODE_BITMAP_LINEAR_WIN_LZMA = 25,
COMMAND_CODE_UTF8_DATA = 32,
COMMAND_CODE_BITMAP_LINEAR_WIN_ZSTD = 26,
};
#ifndef __cplusplus
typedef uint16_t CommandCode;
#endif // __cplusplus
/** /**
* Specifies the kind of compression to use. Availability depends on features. * Specifies the kind of compression to use. Availability depends on features.
* *
@ -455,18 +425,6 @@ size_t sp_bitmap_height(Bitmap */*notnull*/ bitmap);
*/ */
SPBitVec */*notnull*/ sp_bitmap_into_bitvec(Bitmap */*notnull*/ bitmap); SPBitVec */*notnull*/ sp_bitmap_into_bitvec(Bitmap */*notnull*/ bitmap);
/**
* Creates a [BitmapCommand] and immediately turns that into a [Packet].
*
* The provided [Bitmap] gets consumed.
*
* Returns NULL in case of an error.
*/
Packet *sp_bitmap_into_packet(Bitmap */*notnull*/ bitmap,
size_t x,
size_t y,
CompressionCode compression);
/** /**
* Loads a [Bitmap] with the specified dimensions from the provided data. * Loads a [Bitmap] with the specified dimensions from the provided data.
* *
@ -592,18 +550,6 @@ void sp_bitvec_free(SPBitVec */*notnull*/ bit_vec);
*/ */
bool sp_bitvec_get(SPBitVec */*notnull*/ bit_vec, size_t index); bool sp_bitvec_get(SPBitVec */*notnull*/ bit_vec, size_t index);
/**
* Creates a [BitVecCommand] and immediately turns that into a [Packet].
*
* The provided [SPBitVec] gets consumed.
*
* Returns NULL in case of an error.
*/
Packet *sp_bitvec_into_packet(SPBitVec */*notnull*/ bitvec,
size_t offset,
BinaryOperation operation,
CompressionCode compression);
/** /**
* Returns true if length is 0. * Returns true if length is 0.
* *
@ -719,17 +665,6 @@ Brightness sp_brightness_grid_get(BrightnessGrid */*notnull*/ brightness_grid,
*/ */
size_t sp_brightness_grid_height(BrightnessGrid */*notnull*/ brightness_grid); size_t sp_brightness_grid_height(BrightnessGrid */*notnull*/ brightness_grid);
/**
* Creates a [BrightnessGridCommand] and immediately turns that into a [Packet].
*
* The provided [BrightnessGrid] gets consumed.
*
* Returns NULL in case of an error.
*/
Packet *sp_brightness_grid_into_packet(BrightnessGrid */*notnull*/ grid,
size_t x,
size_t y);
/** /**
* Loads a [BrightnessGrid] with the specified dimensions from the provided data. * Loads a [BrightnessGrid] with the specified dimensions from the provided data.
* *
@ -748,7 +683,7 @@ BrightnessGrid *sp_brightness_grid_load(size_t width,
* *
* # Examples * # Examples
* ```C * ```C
* UdpConnection connection = sp_udp_open("127.0.0.1:2342"); * UdpConnection connection = sp_connection_open("127.0.0.1:2342");
* if (connection == NULL) * if (connection == NULL)
* return 1; * return 1;
* *
@ -757,7 +692,7 @@ BrightnessGrid *sp_brightness_grid_load(size_t width,
* sp_brightness_grid_set(grid, 1, 1, 10); * sp_brightness_grid_set(grid, 1, 1, 10);
* *
* TypedCommand command = sp_command_char_brightness(grid); * TypedCommand command = sp_command_char_brightness(grid);
* sp_udp_free(connection); * sp_connection_free(connection);
* ``` * ```
*/ */
BrightnessGrid */*notnull*/ sp_brightness_grid_new(size_t width, size_t height); BrightnessGrid */*notnull*/ sp_brightness_grid_new(size_t width, size_t height);
@ -849,17 +784,6 @@ uint32_t sp_char_grid_get(CharGrid */*notnull*/ char_grid, size_t x, size_t y);
*/ */
size_t sp_char_grid_height(CharGrid */*notnull*/ char_grid); size_t sp_char_grid_height(CharGrid */*notnull*/ char_grid);
/**
* Creates a [CharGridCommand] and immediately turns that into a [Packet].
*
* The provided [CharGrid] gets consumed.
*
* Returns NULL in case of an error.
*/
Packet *sp_char_grid_into_packet(CharGrid */*notnull*/ grid,
size_t x,
size_t y);
/** /**
* Loads a [CharGrid] with the specified dimensions from the provided data. * Loads a [CharGrid] with the specified dimensions from the provided data.
* *
@ -975,7 +899,7 @@ TypedCommand */*notnull*/ sp_command_char_grid(size_t x,
* # Examples * # Examples
* *
* ```C * ```C
* sp_udp_send_command(connection, sp_command_clear()); * sp_connection_send_command(connection, sp_command_clear());
* ``` * ```
*/ */
TypedCommand */*notnull*/ sp_command_clear(void); TypedCommand */*notnull*/ sp_command_clear(void);
@ -1087,17 +1011,6 @@ uint8_t sp_cp437_grid_get(Cp437Grid */*notnull*/ cp437_grid,
*/ */
size_t sp_cp437_grid_height(Cp437Grid */*notnull*/ cp437_grid); size_t sp_cp437_grid_height(Cp437Grid */*notnull*/ cp437_grid);
/**
* Creates a [Cp437GridCommand] and immediately turns that into a [Packet].
*
* The provided [Cp437Grid] gets consumed.
*
* Returns NULL in case of an error.
*/
Packet *sp_cp437_grid_into_packet(Cp437Grid */*notnull*/ grid,
size_t x,
size_t y);
/** /**
* Loads a [Cp437Grid] with the specified dimensions from the provided data. * Loads a [Cp437Grid] with the specified dimensions from the provided data.
*/ */
@ -1209,14 +1122,6 @@ void sp_packet_set_payload(Packet */*notnull*/ packet, ByteSlice data);
*/ */
Packet *sp_packet_try_load(ByteSlice data); Packet *sp_packet_try_load(ByteSlice data);
/**
* Converts u16 into [CommandCode].
*
* If the provided value is not valid, false is returned and result is not changed.
*/
bool sp_u16_to_command_code(uint16_t code,
CommandCode *result);
/** /**
* Closes and deallocates a [UdpConnection]. * Closes and deallocates a [UdpConnection].
*/ */
@ -1230,9 +1135,9 @@ void sp_udp_free(UdpConnection */*notnull*/ connection);
* # Examples * # Examples
* *
* ```C * ```C
* UdpConnection connection = sp_udp_open("172.23.42.29:2342"); * UdpConnection connection = sp_connection_open("172.23.42.29:2342");
* if (connection != NULL) * if (connection != NULL)
* sp_udp_send_command(connection, sp_command_clear()); * sp_connection_send_command(connection, sp_command_clear());
* ``` * ```
*/ */
UdpConnection *sp_udp_open(char */*notnull*/ host); UdpConnection *sp_udp_open(char */*notnull*/ host);
@ -1245,9 +1150,9 @@ UdpConnection *sp_udp_open(char */*notnull*/ host);
* # Examples * # Examples
* *
* ```C * ```C
* UdpConnection connection = sp_udp_open_ipv4(172, 23, 42, 29, 2342); * UdpConnection connection = sp_connection_open_ipv4(172, 23, 42, 29, 2342);
* if (connection != NULL) * if (connection != NULL)
* sp_udp_send_command(connection, sp_command_clear()); * sp_connection_send_command(connection, sp_command_clear());
* ``` * ```
*/ */
UdpConnection *sp_udp_open_ipv4(uint8_t ip1, UdpConnection *sp_udp_open_ipv4(uint8_t ip1,
@ -1266,26 +1171,13 @@ UdpConnection *sp_udp_open_ipv4(uint8_t ip1,
* # Examples * # Examples
* *
* ```C * ```C
* sp_udp_send_command(connection, sp_command_brightness(5)); * sp_connection_send_command(connection, sp_command_clear());
* sp_connection_send_command(connection, sp_command_brightness(5));
* ``` * ```
*/ */
bool sp_udp_send_command(UdpConnection */*notnull*/ connection, bool sp_udp_send_command(UdpConnection */*notnull*/ connection,
TypedCommand */*notnull*/ command); TypedCommand */*notnull*/ command);
/**
* 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));
* ```
*/
bool sp_udp_send_header(UdpConnection */*notnull*/ udp_connection,
Header header);
/** /**
* Sends a [Packet] to the display using the [UdpConnection]. * Sends a [Packet] to the display using the [UdpConnection].
* *

View file

@ -1,6 +1,6 @@
use crate::byte_slice::ByteSlice; use crate::byte_slice::ByteSlice;
use crate::{heap_drop, heap_move, heap_move_nonnull, heap_remove, SPBitVec}; use crate::{heap_drop, heap_move, heap_move_nonnull, SPBitVec};
use servicepoint::{Bitmap, BitmapCommand, CompressionCode, DataRef, Grid, Origin, Packet}; use servicepoint::{Bitmap, DataRef, Grid};
use std::ptr::NonNull; use std::ptr::NonNull;
/// Creates a new [Bitmap] with the specified dimensions. /// Creates a new [Bitmap] with the specified dimensions.
@ -78,7 +78,7 @@ pub unsafe extern "C" fn sp_bitmap_from_bitvec(
width: usize, width: usize,
bitvec: NonNull<SPBitVec>, bitvec: NonNull<SPBitVec>,
) -> *mut Bitmap { ) -> *mut Bitmap {
let bitvec = unsafe { heap_remove(bitvec) }; let bitvec = unsafe { *Box::from_raw(bitvec.as_ptr()) };
if let Ok(bitmap) = Bitmap::from_bitvec(width, bitvec.0) { if let Ok(bitmap) = Bitmap::from_bitvec(width, bitvec.0) {
heap_move(bitmap) heap_move(bitmap)
} else { } else {
@ -196,29 +196,6 @@ pub unsafe extern "C" fn sp_bitmap_unsafe_data_ref(
pub unsafe extern "C" fn sp_bitmap_into_bitvec( pub unsafe extern "C" fn sp_bitmap_into_bitvec(
bitmap: NonNull<Bitmap>, bitmap: NonNull<Bitmap>,
) -> NonNull<SPBitVec> { ) -> NonNull<SPBitVec> {
let bitmap = unsafe { heap_remove(bitmap) }; let bitmap = unsafe { *Box::from_raw(bitmap.as_ptr()) };
heap_move_nonnull(SPBitVec(bitmap.into())) heap_move_nonnull(SPBitVec(bitmap.into()))
} }
/// Creates a [BitmapCommand] and immediately turns that into a [Packet].
///
/// The provided [Bitmap] gets consumed.
///
/// Returns NULL in case of an error.
#[no_mangle]
pub unsafe extern "C" fn sp_bitmap_into_packet(
bitmap: NonNull<Bitmap>,
x: usize,
y: usize,
compression: CompressionCode
) -> *mut Packet {
let bitmap = unsafe { heap_remove(bitmap) };
match Packet::try_from(BitmapCommand {
bitmap,
origin: Origin::new(x, y),
compression,
}) {
Ok(packet) => heap_move(packet),
Err(_) => std::ptr::null_mut(),
}
}

View file

@ -1,5 +1,5 @@
use crate::{heap_drop, heap_move, heap_move_nonnull, heap_remove, ByteSlice}; use crate::{heap_drop, heap_move_nonnull, ByteSlice};
use servicepoint::{BinaryOperation, BitVecCommand, BitVecU8Msb0, CompressionCode, Packet}; use servicepoint::BitVecU8Msb0;
use std::ptr::NonNull; use std::ptr::NonNull;
/// A vector of bits /// A vector of bits
@ -146,27 +146,3 @@ pub unsafe extern "C" fn sp_bitvec_unsafe_data_ref(
) -> ByteSlice { ) -> ByteSlice {
unsafe { ByteSlice::from_slice((*bit_vec.as_ptr()).0.as_raw_mut_slice()) } unsafe { ByteSlice::from_slice((*bit_vec.as_ptr()).0.as_raw_mut_slice()) }
} }
/// Creates a [BitVecCommand] and immediately turns that into a [Packet].
///
/// The provided [SPBitVec] gets consumed.
///
/// Returns NULL in case of an error.
#[no_mangle]
pub unsafe extern "C" fn sp_bitvec_into_packet(
bitvec: NonNull<SPBitVec>,
offset: usize,
operation: BinaryOperation,
compression: CompressionCode
) -> *mut Packet {
let bitvec = unsafe { heap_remove(bitvec) }.0;
match Packet::try_from(BitVecCommand {
bitvec,
offset,
operation,
compression,
}) {
Ok(packet) => heap_move(packet),
Err(_) => std::ptr::null_mut(),
}
}

View file

@ -1,8 +1,5 @@
use crate::{heap_drop, heap_move, heap_move_nonnull, heap_remove, ByteSlice}; use crate::{heap_drop, heap_move, heap_move_nonnull, ByteSlice};
use servicepoint::{ use servicepoint::{Brightness, BrightnessGrid, ByteGrid, DataRef, Grid};
Brightness, BrightnessGrid, BrightnessGridCommand, ByteGrid, DataRef, Grid,
Origin, Packet,
};
use std::mem::transmute; use std::mem::transmute;
use std::ptr::NonNull; use std::ptr::NonNull;
@ -12,7 +9,7 @@ use std::ptr::NonNull;
/// ///
/// # Examples /// # Examples
/// ```C /// ```C
/// UdpConnection connection = sp_udp_open("127.0.0.1:2342"); /// UdpConnection connection = sp_connection_open("127.0.0.1:2342");
/// if (connection == NULL) /// if (connection == NULL)
/// return 1; /// return 1;
/// ///
@ -21,7 +18,7 @@ use std::ptr::NonNull;
/// sp_brightness_grid_set(grid, 1, 1, 10); /// sp_brightness_grid_set(grid, 1, 1, 10);
/// ///
/// TypedCommand command = sp_command_char_brightness(grid); /// TypedCommand command = sp_command_char_brightness(grid);
/// sp_udp_free(connection); /// sp_connection_free(connection);
/// ``` /// ```
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn sp_brightness_grid_new( pub unsafe extern "C" fn sp_brightness_grid_new(
@ -170,28 +167,5 @@ pub unsafe extern "C" fn sp_brightness_grid_unsafe_data_ref(
const _: () = assert!(size_of::<Brightness>() == 1); const _: () = assert!(size_of::<Brightness>() == 1);
let data = unsafe { (*brightness_grid.as_ptr()).data_ref_mut() }; let data = unsafe { (*brightness_grid.as_ptr()).data_ref_mut() };
unsafe { unsafe { ByteSlice::from_slice(transmute(data)) }
ByteSlice::from_slice(transmute::<&mut [Brightness], &mut [u8]>(data))
}
}
/// Creates a [BrightnessGridCommand] and immediately turns that into a [Packet].
///
/// The provided [BrightnessGrid] gets consumed.
///
/// Returns NULL in case of an error.
#[no_mangle]
pub unsafe extern "C" fn sp_brightness_grid_into_packet(
grid: NonNull<BrightnessGrid>,
x: usize,
y: usize,
) -> *mut Packet {
let grid = unsafe { heap_remove(grid) };
match Packet::try_from(BrightnessGridCommand {
grid,
origin: Origin::new(x, y),
}) {
Ok(packet) => heap_move(packet),
Err(_) => std::ptr::null_mut(),
}
} }

View file

@ -24,7 +24,7 @@ impl ByteSlice {
unsafe { std::slice::from_raw_parts(self.start.as_ptr(), self.length) } unsafe { std::slice::from_raw_parts(self.start.as_ptr(), self.length) }
} }
pub(crate) unsafe fn as_slice_mut(&mut self) -> &mut [u8] { pub(crate) unsafe fn as_slice_mut(&self) -> &mut [u8] {
unsafe { unsafe {
std::slice::from_raw_parts_mut(self.start.as_ptr(), self.length) std::slice::from_raw_parts_mut(self.start.as_ptr(), self.length)
} }

View file

@ -1,5 +1,5 @@
use crate::{heap_drop, heap_move, heap_move_nonnull, heap_remove, ByteSlice}; use crate::{heap_drop, heap_move, heap_move_nonnull, ByteSlice};
use servicepoint::{CharGrid, CharGridCommand, Grid, Origin, Packet}; use servicepoint::{CharGrid, Grid};
use std::ptr::NonNull; use std::ptr::NonNull;
/// Creates a new [CharGrid] with the specified dimensions. /// Creates a new [CharGrid] with the specified dimensions.
@ -132,24 +132,3 @@ pub unsafe extern "C" fn sp_char_grid_height(
) -> usize { ) -> usize {
unsafe { char_grid.as_ref().height() } unsafe { char_grid.as_ref().height() }
} }
/// Creates a [CharGridCommand] and immediately turns that into a [Packet].
///
/// The provided [CharGrid] gets consumed.
///
/// Returns NULL in case of an error.
#[no_mangle]
pub unsafe extern "C" fn sp_char_grid_into_packet(
grid: NonNull<CharGrid>,
x: usize,
y: usize,
) -> *mut Packet {
let grid = unsafe { heap_remove(grid) };
match Packet::try_from(CharGridCommand {
grid,
origin: Origin::new(x, y),
}) {
Ok(packet) => heap_move(packet),
Err(_) => std::ptr::null_mut(),
}
}

View file

@ -40,7 +40,7 @@ pub unsafe extern "C" fn sp_command_clone(
/// # Examples /// # Examples
/// ///
/// ```C /// ```C
/// sp_udp_send_command(connection, sp_command_clear()); /// sp_connection_send_command(connection, sp_command_clear());
/// ``` /// ```
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn sp_command_clear() -> NonNull<TypedCommand> { pub unsafe extern "C" fn sp_command_clear() -> NonNull<TypedCommand> {
@ -115,6 +115,10 @@ pub unsafe extern "C" fn sp_command_bitvec(
operation: BinaryOperation, operation: BinaryOperation,
) -> *mut TypedCommand { ) -> *mut TypedCommand {
let bit_vec = unsafe { *Box::from_raw(bit_vec.as_ptr()) }; let bit_vec = unsafe { *Box::from_raw(bit_vec.as_ptr()) };
let compression = match compression.try_into() {
Ok(compression) => compression,
Err(_) => return std::ptr::null_mut(),
};
let command = servicepoint::BitVecCommand { let command = servicepoint::BitVecCommand {
offset, offset,
operation, operation,
@ -178,6 +182,10 @@ pub unsafe extern "C" fn sp_command_bitmap(
compression: CompressionCode, compression: CompressionCode,
) -> *mut TypedCommand { ) -> *mut TypedCommand {
let bitmap = unsafe { *Box::from_raw(bitmap.as_ptr()) }; let bitmap = unsafe { *Box::from_raw(bitmap.as_ptr()) };
let compression = match compression.try_into() {
Ok(compression) => compression,
Err(_) => return std::ptr::null_mut(),
};
let command = servicepoint::BitmapCommand { let command = servicepoint::BitmapCommand {
origin: servicepoint::Origin::new(x, y), origin: servicepoint::Origin::new(x, y),
bitmap, bitmap,

View file

@ -1,3 +0,0 @@
mod typed;
pub use typed::*;

View file

@ -1,5 +1,5 @@
use crate::{heap_drop, heap_move, heap_remove}; use crate::{heap_drop, heap_move};
use servicepoint::{Connection, Header, Packet, TypedCommand, UdpConnection}; use servicepoint::{Connection, Packet, TypedCommand, UdpConnection};
use std::ffi::{c_char, CStr}; use std::ffi::{c_char, CStr};
use std::net::{Ipv4Addr, SocketAddrV4}; use std::net::{Ipv4Addr, SocketAddrV4};
use std::ptr::NonNull; use std::ptr::NonNull;
@ -11,9 +11,9 @@ use std::ptr::NonNull;
/// # Examples /// # Examples
/// ///
/// ```C /// ```C
/// UdpConnection connection = sp_udp_open("172.23.42.29:2342"); /// UdpConnection connection = sp_connection_open("172.23.42.29:2342");
/// if (connection != NULL) /// if (connection != NULL)
/// sp_udp_send_command(connection, sp_command_clear()); /// sp_connection_send_command(connection, sp_command_clear());
/// ``` /// ```
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn sp_udp_open( pub unsafe extern "C" fn sp_udp_open(
@ -37,9 +37,9 @@ pub unsafe extern "C" fn sp_udp_open(
/// # Examples /// # Examples
/// ///
/// ```C /// ```C
/// UdpConnection connection = sp_udp_open_ipv4(172, 23, 42, 29, 2342); /// UdpConnection connection = sp_connection_open_ipv4(172, 23, 42, 29, 2342);
/// if (connection != NULL) /// if (connection != NULL)
/// sp_udp_send_command(connection, sp_command_clear()); /// sp_connection_send_command(connection, sp_command_clear());
/// ``` /// ```
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn sp_udp_open_ipv4( pub unsafe extern "C" fn sp_udp_open_ipv4(
@ -67,8 +67,8 @@ pub unsafe extern "C" fn sp_udp_send_packet(
connection: NonNull<UdpConnection>, connection: NonNull<UdpConnection>,
packet: NonNull<Packet>, packet: NonNull<Packet>,
) -> bool { ) -> bool {
let packet = unsafe { heap_remove(packet) }; let packet = unsafe { Box::from_raw(packet.as_ptr()) };
unsafe { connection.as_ref().send(packet) }.is_ok() unsafe { connection.as_ref().send(*packet) }.is_ok()
} }
/// Sends a [TypedCommand] to the display using the [UdpConnection]. /// Sends a [TypedCommand] to the display using the [UdpConnection].
@ -80,38 +80,18 @@ pub unsafe extern "C" fn sp_udp_send_packet(
/// # Examples /// # Examples
/// ///
/// ```C /// ```C
/// sp_udp_send_command(connection, sp_command_brightness(5)); /// sp_connection_send_command(connection, sp_command_clear());
/// sp_connection_send_command(connection, sp_command_brightness(5));
/// ``` /// ```
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn sp_udp_send_command( pub unsafe extern "C" fn sp_udp_send_command(
connection: NonNull<UdpConnection>, connection: NonNull<UdpConnection>,
command: NonNull<TypedCommand>, command: NonNull<TypedCommand>,
) -> bool { ) -> bool {
let command = unsafe { heap_remove(command) }; let command = *unsafe { Box::from_raw(command.as_ptr()) };
unsafe { connection.as_ref().send(command) }.is_ok() 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]. /// Closes and deallocates a [UdpConnection].
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn sp_udp_free(connection: NonNull<UdpConnection>) { pub unsafe extern "C" fn sp_udp_free(connection: NonNull<UdpConnection>) {

View file

@ -1,5 +1,5 @@
use crate::{heap_drop, heap_move, heap_move_nonnull, heap_remove, ByteSlice}; use crate::{heap_drop, heap_move, heap_move_nonnull, ByteSlice};
use servicepoint::{Cp437Grid, Cp437GridCommand, DataRef, Grid, Origin, Packet}; use servicepoint::{Cp437Grid, DataRef, Grid};
use std::ptr::NonNull; use std::ptr::NonNull;
/// Creates a new [Cp437Grid] with the specified dimensions. /// Creates a new [Cp437Grid] with the specified dimensions.
@ -132,24 +132,3 @@ pub unsafe extern "C" fn sp_cp437_grid_unsafe_data_ref(
) -> ByteSlice { ) -> ByteSlice {
unsafe { ByteSlice::from_slice((*cp437_grid.as_ptr()).data_ref_mut()) } unsafe { ByteSlice::from_slice((*cp437_grid.as_ptr()).data_ref_mut()) }
} }
/// Creates a [Cp437GridCommand] and immediately turns that into a [Packet].
///
/// The provided [Cp437Grid] gets consumed.
///
/// Returns NULL in case of an error.
#[no_mangle]
pub unsafe extern "C" fn sp_cp437_grid_into_packet(
grid: NonNull<Cp437Grid>,
x: usize,
y: usize,
) -> *mut Packet {
let grid = unsafe { heap_remove(grid) };
match Packet::try_from(Cp437GridCommand {
grid,
origin: Origin::new(x, y),
}) {
Ok(packet) => heap_move(packet),
Err(_) => std::ptr::null_mut(),
}
}

View file

@ -9,7 +9,7 @@
//! #include "servicepoint.h" //! #include "servicepoint.h"
//! //!
//! int main(void) { //! int main(void) {
//! UdpConnection *connection = sp_udp_open("172.23.42.29:2342"); //! UdpConnection *connection = sp_connection_open("172.23.42.29:2342");
//! if (connection == NULL) //! if (connection == NULL)
//! return 1; //! return 1;
//! //!
@ -17,10 +17,10 @@
//! sp_bitmap_fill(pixels, true); //! sp_bitmap_fill(pixels, true);
//! //!
//! TypedCommand *command = sp_command_bitmap_linear_win(0, 0, pixels, Uncompressed); //! TypedCommand *command = sp_command_bitmap_linear_win(0, 0, pixels, Uncompressed);
//! while (sp_udp_send_command(connection, sp_command_clone(command))); //! while (sp_connection_send_command(connection, sp_command_clone(command)));
//! //!
//! sp_command_free(command); //! sp_command_free(command);
//! sp_udp_free(connection); //! sp_connection_free(connection);
//! return 0; //! return 0;
//! } //! }
//! ``` //! ```
@ -30,11 +30,10 @@ pub use crate::bitvec::*;
pub use crate::brightness_grid::*; pub use crate::brightness_grid::*;
pub use crate::byte_slice::*; pub use crate::byte_slice::*;
pub use crate::char_grid::*; pub use crate::char_grid::*;
pub use crate::commands::*; pub use crate::command::*;
pub use crate::connection::*; pub use crate::connection::*;
pub use crate::cp437_grid::*; pub use crate::cp437_grid::*;
pub use crate::packet::*; pub use crate::packet::*;
pub use servicepoint::CommandCode;
use std::ptr::NonNull; use std::ptr::NonNull;
mod bitmap; mod bitmap;
@ -42,7 +41,7 @@ mod bitvec;
mod brightness_grid; mod brightness_grid;
mod byte_slice; mod byte_slice;
mod char_grid; mod char_grid;
mod commands; mod command;
mod connection; mod connection;
mod cp437_grid; mod cp437_grid;
mod packet; mod packet;
@ -61,9 +60,5 @@ pub(crate) fn heap_move_nonnull<T>(x: T) -> NonNull<T> {
} }
pub(crate) unsafe fn heap_drop<T>(x: NonNull<T>) { pub(crate) unsafe fn heap_drop<T>(x: NonNull<T>) {
drop(unsafe { heap_remove(x) }); drop(unsafe { Box::from_raw(x.as_ptr()) });
}
pub(crate) unsafe fn heap_remove<T>(x: NonNull<T>) -> T {
unsafe { *Box::from_raw(x.as_ptr()) }
} }

View file

@ -1,5 +1,5 @@
use crate::{heap_drop, heap_move, heap_move_nonnull, heap_remove, ByteSlice}; use crate::{heap_drop, heap_move, heap_move_nonnull, ByteSlice};
use servicepoint::{CommandCode, Header, Packet, TypedCommand}; use servicepoint::{Header, Packet, TypedCommand};
use std::ptr::NonNull; use std::ptr::NonNull;
/// Turns a [TypedCommand] into a [Packet]. /// Turns a [TypedCommand] into a [Packet].
@ -10,7 +10,7 @@ use std::ptr::NonNull;
pub unsafe extern "C" fn sp_packet_from_command( pub unsafe extern "C" fn sp_packet_from_command(
command: NonNull<TypedCommand>, command: NonNull<TypedCommand>,
) -> *mut Packet { ) -> *mut Packet {
let command = unsafe { heap_remove(command) }; let command = unsafe { *Box::from_raw(command.as_ptr()) };
if let Ok(packet) = command.try_into() { if let Ok(packet) = command.try_into() {
heap_move(packet) heap_move(packet)
} else { } else {
@ -65,7 +65,7 @@ pub unsafe extern "C" fn sp_packet_get_header(
pub unsafe extern "C" fn sp_packet_get_payload( pub unsafe extern "C" fn sp_packet_get_payload(
packet: NonNull<Packet>, packet: NonNull<Packet>,
) -> ByteSlice { ) -> ByteSlice {
unsafe { ByteSlice::from_slice(&mut (*packet.as_ptr()).payload) } unsafe { ByteSlice::from_slice(&mut *(*packet.as_ptr()).payload) }
} }
/// Sets the payload of the provided packet to the provided data. /// Sets the payload of the provided packet to the provided data.
@ -87,7 +87,7 @@ pub unsafe extern "C" fn sp_packet_set_payload(
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn sp_packet_serialize_to( pub unsafe extern "C" fn sp_packet_serialize_to(
packet: NonNull<Packet>, packet: NonNull<Packet>,
mut buffer: ByteSlice, buffer: ByteSlice,
) { ) {
unsafe { unsafe {
packet.as_ref().serialize_to(buffer.as_slice_mut()); packet.as_ref().serialize_to(buffer.as_slice_mut());
@ -107,22 +107,3 @@ pub unsafe extern "C" fn sp_packet_clone(
pub unsafe extern "C" fn sp_packet_free(packet: NonNull<Packet>) { pub unsafe extern "C" fn sp_packet_free(packet: NonNull<Packet>) {
unsafe { heap_drop(packet) } unsafe { heap_drop(packet) }
} }
/// Converts u16 into [CommandCode].
///
/// If the provided value is not valid, false is returned and result is not changed.
#[no_mangle]
pub unsafe extern "C" fn sp_u16_to_command_code(
code: u16,
result: *mut CommandCode,
) -> bool {
match CommandCode::try_from(code) {
Ok(code) => {
unsafe {
*result = code;
}
true
}
Err(_) => false,
}
}