Compare commits
19 commits
main
...
csbindgen-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b0bfd341b6 | ||
|
|
66823d0676 | ||
|
|
9cdb5e0dbf | ||
|
|
52b1ce83d9 | ||
|
|
bcd65fb4f0 | ||
|
|
474848e2ea | ||
|
|
05aff8b2dd | ||
|
|
240766dc11 | ||
|
|
c3022e567c | ||
|
|
0b80ce4968 | ||
|
|
f968f92917 | ||
|
|
f836220259 | ||
|
|
57c66d9d31 | ||
|
|
1f23bc8afc | ||
|
|
67969d5b43 | ||
|
|
91cc982394 | ||
|
|
01f2f90121 | ||
|
|
55aa7ecf4c | ||
|
|
db98709ca7 |
51 changed files with 2847 additions and 2158 deletions
2
.github/workflows/rust.yml
vendored
2
.github/workflows/rust.yml
vendored
|
|
@ -16,6 +16,8 @@ jobs:
|
|||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: 'true'
|
||||
|
||||
- name: build default features
|
||||
run: cargo build --all --verbose
|
||||
|
|
|
|||
4
.gitmodules
vendored
Normal file
4
.gitmodules
vendored
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
[submodule "crates/servicepoint_csbindgen"]
|
||||
path = crates/servicepoint_csbindgen
|
||||
url = https://github.com/kaesaecracker/servicepoint_csbindgen.git
|
||||
branch = "main"
|
||||
19
Cargo.lock
generated
19
Cargo.lock
generated
|
|
@ -208,6 +208,15 @@ version = "1.0.2"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d3fd119d74b830634cea2a0f58bbd0d54540518a14397557951e79340abc28c0"
|
||||
|
||||
[[package]]
|
||||
name = "convert_case"
|
||||
version = "0.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ec182b0ca2f35d8fc196cf3404988fd8b8c739a4d270ff118a398feb0cbec1ca"
|
||||
dependencies = [
|
||||
"unicode-segmentation",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cpufeatures"
|
||||
version = "0.2.14"
|
||||
|
|
@ -239,9 +248,8 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "csbindgen"
|
||||
version = "1.9.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c26b9831049b947d154bba920e4124053def72447be6fb106a96f483874b482a"
|
||||
dependencies = [
|
||||
"convert_case",
|
||||
"regex",
|
||||
"syn",
|
||||
]
|
||||
|
|
@ -636,6 +644,7 @@ dependencies = [
|
|||
name = "servicepoint_binding_cs"
|
||||
version = "0.10.0"
|
||||
dependencies = [
|
||||
"convert_case",
|
||||
"csbindgen",
|
||||
"servicepoint",
|
||||
"servicepoint_binding_c",
|
||||
|
|
@ -778,6 +787,12 @@ version = "1.0.13"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-segmentation"
|
||||
version = "1.12.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493"
|
||||
|
||||
[[package]]
|
||||
name = "utf-8"
|
||||
version = "0.7.6"
|
||||
|
|
|
|||
|
|
@ -1,8 +1,11 @@
|
|||
[workspace]
|
||||
resolver = "2"
|
||||
members = [
|
||||
"crates/*",
|
||||
"crates/servicepoint_binding_c/examples/lang_c"
|
||||
"crates/servicepoint",
|
||||
"crates/servicepoint_binding_c",
|
||||
"crates/servicepoint_binding_c/examples/lang_c",
|
||||
"crates/servicepoint_binding_cs",
|
||||
"crates/servicepoint_csbindgen/csbindgen"
|
||||
]
|
||||
|
||||
[workspace.package]
|
||||
|
|
|
|||
|
|
@ -31,11 +31,8 @@ fn main() {
|
|||
let mut filled_grid = Bitmap::max_sized();
|
||||
filled_grid.fill(true);
|
||||
|
||||
let command = BitmapLinearWin(
|
||||
Origin::ZERO,
|
||||
filled_grid,
|
||||
CompressionCode::Lzma,
|
||||
);
|
||||
let command =
|
||||
BitmapLinearWin(Origin::ZERO, filled_grid, CompressionCode::Lzma);
|
||||
connection.send(command).expect("send failed");
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -266,6 +266,8 @@ void sp_bitmap_fill(SPBitmap *bitmap, bool value);
|
|||
* - `bitmap` points to a valid [SPBitmap]
|
||||
* - `bitmap` is not used concurrently or after bitmap call
|
||||
* - `bitmap` was not passed to another consuming function, e.g. to create a [SPCommand]
|
||||
*
|
||||
* servicepoint_csbindgen_consumes: bitmap
|
||||
*/
|
||||
void sp_bitmap_free(SPBitmap *bitmap);
|
||||
|
||||
|
|
@ -363,6 +365,20 @@ SPBitmap *sp_bitmap_load(size_t width,
|
|||
SPBitmap *sp_bitmap_new(size_t width,
|
||||
size_t height);
|
||||
|
||||
/**
|
||||
* Creates a new [SPBitmap] with a size matching the screen.
|
||||
*
|
||||
* returns: [SPBitmap] initialized to all pixels off. Will never return NULL.
|
||||
*
|
||||
* # Safety
|
||||
*
|
||||
* The caller has to make sure that:
|
||||
*
|
||||
* - the returned instance is freed in some way, either by using a consuming function or
|
||||
* by explicitly calling `sp_bitmap_free`.
|
||||
*/
|
||||
SPBitmap *sp_bitmap_new_screen_sized(void);
|
||||
|
||||
/**
|
||||
* Sets the value of the specified position in the [SPBitmap].
|
||||
*
|
||||
|
|
@ -695,6 +711,8 @@ void sp_brightness_grid_fill(SPBrightnessGrid *brightness_grid, uint8_t value);
|
|||
* - `brightness_grid` points to a valid [SPBrightnessGrid]
|
||||
* - `brightness_grid` is not used concurrently or after this call
|
||||
* - `brightness_grid` was not passed to another consuming function, e.g. to create a [SPCommand]
|
||||
*
|
||||
* servicepoint_csbindgen_consumes: brightness_grid
|
||||
*/
|
||||
void sp_brightness_grid_free(SPBrightnessGrid *brightness_grid);
|
||||
|
||||
|
|
@ -883,6 +901,8 @@ size_t sp_brightness_grid_width(const SPBrightnessGrid *brightness_grid);
|
|||
* - `compression` matches one of the allowed enum values
|
||||
* - the returned [SPCommand] instance is freed in some way, either by using a consuming function or
|
||||
* by explicitly calling `sp_command_free`.
|
||||
*
|
||||
* servicepoint_csbindgen_consumes: bit_vec
|
||||
*/
|
||||
SPCommand *sp_command_bitmap_linear(size_t offset,
|
||||
SPBitVec *bit_vec,
|
||||
|
|
@ -914,6 +934,8 @@ SPCommand *sp_command_bitmap_linear(size_t offset,
|
|||
* - `compression` matches one of the allowed enum values
|
||||
* - the returned [SPCommand] instance is freed in some way, either by using a consuming function or
|
||||
* by explicitly calling `sp_command_free`.
|
||||
*
|
||||
* servicepoint_csbindgen_consumes: bit_vec
|
||||
*/
|
||||
SPCommand *sp_command_bitmap_linear_and(size_t offset,
|
||||
SPBitVec *bit_vec,
|
||||
|
|
@ -945,6 +967,8 @@ SPCommand *sp_command_bitmap_linear_and(size_t offset,
|
|||
* - `compression` matches one of the allowed enum values
|
||||
* - the returned [SPCommand] instance is freed in some way, either by using a consuming function or
|
||||
* by explicitly calling `sp_command_free`.
|
||||
*
|
||||
* servicepoint_csbindgen_consumes: bit_vec
|
||||
*/
|
||||
SPCommand *sp_command_bitmap_linear_or(size_t offset,
|
||||
SPBitVec *bit_vec,
|
||||
|
|
@ -971,6 +995,8 @@ SPCommand *sp_command_bitmap_linear_or(size_t offset,
|
|||
* - `compression` matches one of the allowed enum values
|
||||
* - the returned [SPCommand] instance is freed in some way, either by using a consuming function or
|
||||
* by explicitly calling `sp_command_free`.
|
||||
*
|
||||
* servicepoint_csbindgen_consumes: bitmap
|
||||
*/
|
||||
SPCommand *sp_command_bitmap_linear_win(size_t x,
|
||||
size_t y,
|
||||
|
|
@ -1003,6 +1029,8 @@ SPCommand *sp_command_bitmap_linear_win(size_t x,
|
|||
* - `compression` matches one of the allowed enum values
|
||||
* - the returned [SPCommand] instance is freed in some way, either by using a consuming function or
|
||||
* by explicitly calling `sp_command_free`.
|
||||
*
|
||||
* servicepoint_csbindgen_consumes: bit_vec
|
||||
*/
|
||||
SPCommand *sp_command_bitmap_linear_xor(size_t offset,
|
||||
SPBitVec *bit_vec,
|
||||
|
|
@ -1045,6 +1073,8 @@ SPCommand *sp_command_brightness(uint8_t brightness);
|
|||
* - `grid` is not used concurrently or after this call
|
||||
* - the returned [SPCommand] instance is freed in some way, either by using a consuming function or
|
||||
* by explicitly calling `sp_command_free`.
|
||||
*
|
||||
* servicepoint_csbindgen_consumes: grid
|
||||
*/
|
||||
SPCommand *sp_command_char_brightness(size_t x,
|
||||
size_t y,
|
||||
|
|
@ -1111,6 +1141,8 @@ SPCommand *sp_command_clone(const SPCommand *command);
|
|||
* - `grid` is not used concurrently or after this call
|
||||
* - the returned [SPCommand] instance is freed in some way, either by using a consuming function or
|
||||
* by explicitly calling `sp_command_free`.
|
||||
*
|
||||
* servicepoint_csbindgen_consumes: grid
|
||||
*/
|
||||
SPCommand *sp_command_cp437_data(size_t x,
|
||||
size_t y,
|
||||
|
|
@ -1151,6 +1183,8 @@ SPCommand *sp_command_fade_out(void);
|
|||
* - `command` points to a valid [SPCommand]
|
||||
* - `command` is not used concurrently or after this call
|
||||
* - `command` was not passed to another consuming function, e.g. to create a [SPPacket]
|
||||
*
|
||||
* servicepoint_csbindgen_consumes: command
|
||||
*/
|
||||
void sp_command_free(SPCommand *command);
|
||||
|
||||
|
|
@ -1190,9 +1224,25 @@ SPCommand *sp_command_hard_reset(void);
|
|||
* - the result is checked for NULL
|
||||
* - the returned [SPCommand] instance is freed in some way, either by using a consuming function or
|
||||
* by explicitly calling `sp_command_free`.
|
||||
*
|
||||
* servicepoint_csbindgen_consumes: packet
|
||||
*/
|
||||
SPCommand *sp_command_try_from_packet(SPPacket *packet);
|
||||
|
||||
/**
|
||||
* Creates a new instance of [SPConnection] for testing that does not actually send anything.
|
||||
*
|
||||
* returns: a new instance. Will never return NULL.
|
||||
*
|
||||
* # Safety
|
||||
*
|
||||
* The caller has to make sure that:
|
||||
*
|
||||
* - the returned instance is freed in some way, either by using a consuming function or
|
||||
* by explicitly calling `sp_connection_free`.
|
||||
*/
|
||||
SPConnection *sp_connection_fake(void);
|
||||
|
||||
/**
|
||||
* Closes and deallocates a [SPConnection].
|
||||
*
|
||||
|
|
@ -1206,11 +1256,13 @@ SPCommand *sp_command_try_from_packet(SPPacket *packet);
|
|||
*
|
||||
* - `connection` points to a valid [SPConnection]
|
||||
* - `connection` is not used concurrently or after this call
|
||||
*
|
||||
* servicepoint_csbindgen_consumes: connection
|
||||
*/
|
||||
void sp_connection_free(SPConnection *connection);
|
||||
|
||||
/**
|
||||
* Creates a new instance of [SPConnection].
|
||||
* Creates a new instance of [SPConnection] that uses UDP to send.
|
||||
*
|
||||
* returns: NULL if connection fails, or connected instance
|
||||
*
|
||||
|
|
@ -1246,6 +1298,8 @@ SPConnection *sp_connection_open(const char *host);
|
|||
* - `connection` points to a valid instance of [SPConnection]
|
||||
* - `command` points to a valid instance of [SPPacket]
|
||||
* - `command` is not used concurrently or after this call
|
||||
*
|
||||
* servicepoint_csbindgen_consumes: command
|
||||
*/
|
||||
bool sp_connection_send_command(const SPConnection *connection,
|
||||
SPCommand *command);
|
||||
|
|
@ -1269,6 +1323,8 @@ bool sp_connection_send_command(const SPConnection *connection,
|
|||
* - `connection` points to a valid instance of [SPConnection]
|
||||
* - `packet` points to a valid instance of [SPPacket]
|
||||
* - `packet` is not used concurrently or after this call
|
||||
*
|
||||
* servicepoint_csbindgen_consumes: packet
|
||||
*/
|
||||
bool sp_connection_send_packet(const SPConnection *connection,
|
||||
SPPacket *packet);
|
||||
|
|
@ -1328,6 +1384,8 @@ void sp_cp437_grid_fill(SPCp437Grid *cp437_grid, uint8_t value);
|
|||
* - `cp437_grid` points to a valid [SPCp437Grid]
|
||||
* - `cp437_grid` is not used concurrently or after cp437_grid call
|
||||
* - `cp437_grid` was not passed to another consuming function, e.g. to create a [SPCommand]
|
||||
*
|
||||
* servicepoint_csbindgen_consumes: cp437_grid
|
||||
*/
|
||||
void sp_cp437_grid_free(SPCp437Grid *cp437_grid);
|
||||
|
||||
|
|
@ -1502,7 +1560,7 @@ SPPacket *sp_packet_clone(const SPPacket *packet);
|
|||
*
|
||||
* # Panics
|
||||
*
|
||||
* - when `sp_packet_free` is NULL
|
||||
* - when `packet` is NULL
|
||||
*
|
||||
* # Safety
|
||||
*
|
||||
|
|
@ -1510,6 +1568,8 @@ SPPacket *sp_packet_clone(const SPPacket *packet);
|
|||
*
|
||||
* - `packet` points to a valid [SPPacket]
|
||||
* - `packet` is not used concurrently or after this call
|
||||
*
|
||||
* servicepoint_csbindgen_consumes: packet
|
||||
*/
|
||||
void sp_packet_free(SPPacket *packet);
|
||||
|
||||
|
|
@ -1531,9 +1591,45 @@ void sp_packet_free(SPPacket *packet);
|
|||
* - [SPCommand] is not used concurrently or after this call
|
||||
* - the returned [SPPacket] instance is freed in some way, either by using a consuming function or
|
||||
* by explicitly calling `sp_packet_free`.
|
||||
*
|
||||
* servicepoint_csbindgen_consumes: command
|
||||
*/
|
||||
SPPacket *sp_packet_from_command(SPCommand *command);
|
||||
|
||||
/**
|
||||
* Creates a raw [SPPacket] from parts.
|
||||
*
|
||||
* # Arguments
|
||||
*
|
||||
* - `command_code` specifies which command this packet contains
|
||||
* - `a`, `b`, `c` and `d` are command-specific header values
|
||||
* - `payload` is the optional data that is part of the command
|
||||
* - `payload_len` is the size of the payload
|
||||
*
|
||||
* returns: new instance. Will never return null.
|
||||
*
|
||||
* # Panics
|
||||
*
|
||||
* - when `payload` is null, but `payload_len` is not zero
|
||||
* - when `payload_len` is zero, but `payload` is nonnull
|
||||
*
|
||||
* # Safety
|
||||
*
|
||||
* The caller has to make sure that:
|
||||
*
|
||||
* - `payload` points to a valid memory region of at least `payload_len` bytes
|
||||
* - `payload` is not written to concurrently
|
||||
* - the returned [SPPacket] instance is freed in some way, either by using a consuming function or
|
||||
* by explicitly calling `sp_packet_free`.
|
||||
*/
|
||||
SPPacket *sp_packet_from_parts(uint16_t command_code,
|
||||
uint16_t a,
|
||||
uint16_t b,
|
||||
uint16_t c,
|
||||
uint16_t d,
|
||||
const uint8_t *payload,
|
||||
size_t payload_len);
|
||||
|
||||
/**
|
||||
* Tries to load a [SPPacket] from the passed array with the specified length.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -2,9 +2,9 @@
|
|||
//!
|
||||
//! prefix `sp_bitvec_`
|
||||
|
||||
use std::ptr::NonNull;
|
||||
use crate::SPByteSlice;
|
||||
use servicepoint::bitvec::prelude::{BitVec, Msb0};
|
||||
use std::ptr::NonNull;
|
||||
|
||||
/// A vector of bits
|
||||
///
|
||||
|
|
@ -2,8 +2,8 @@
|
|||
//!
|
||||
//! prefix `sp_bitmap_`
|
||||
|
||||
use std::ptr::NonNull;
|
||||
use servicepoint::{DataRef, Grid};
|
||||
use std::ptr::NonNull;
|
||||
|
||||
use crate::byte_slice::SPByteSlice;
|
||||
|
||||
|
|
@ -43,9 +43,23 @@ pub unsafe extern "C" fn sp_bitmap_new(
|
|||
width: usize,
|
||||
height: usize,
|
||||
) -> NonNull<SPBitmap> {
|
||||
let result = Box::new(SPBitmap(servicepoint::Bitmap::new(
|
||||
width, height,
|
||||
)));
|
||||
let result = Box::new(SPBitmap(servicepoint::Bitmap::new(width, height)));
|
||||
NonNull::from(Box::leak(result))
|
||||
}
|
||||
|
||||
/// Creates a new [SPBitmap] with a size matching the screen.
|
||||
///
|
||||
/// returns: [SPBitmap] initialized to all pixels off. Will never return NULL.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The caller has to make sure that:
|
||||
///
|
||||
/// - the returned instance is freed in some way, either by using a consuming function or
|
||||
/// by explicitly calling `sp_bitmap_free`.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sp_bitmap_new_screen_sized() -> NonNull<SPBitmap> {
|
||||
let result = Box::new(SPBitmap(servicepoint::Bitmap::max_sized()));
|
||||
NonNull::from(Box::leak(result))
|
||||
}
|
||||
|
||||
|
|
@ -80,9 +94,8 @@ pub unsafe extern "C" fn sp_bitmap_load(
|
|||
) -> NonNull<SPBitmap> {
|
||||
assert!(!data.is_null());
|
||||
let data = std::slice::from_raw_parts(data, data_length);
|
||||
let result = Box::new(SPBitmap(servicepoint::Bitmap::load(
|
||||
width, height, data,
|
||||
)));
|
||||
let result =
|
||||
Box::new(SPBitmap(servicepoint::Bitmap::load(width, height, data)));
|
||||
NonNull::from(Box::leak(result))
|
||||
}
|
||||
|
||||
|
|
@ -124,6 +137,8 @@ pub unsafe extern "C" fn sp_bitmap_clone(
|
|||
/// - `bitmap` points to a valid [SPBitmap]
|
||||
/// - `bitmap` is not used concurrently or after bitmap call
|
||||
/// - `bitmap` was not passed to another consuming function, e.g. to create a [SPCommand]
|
||||
///
|
||||
/// servicepoint_csbindgen_consumes: bitmap
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sp_bitmap_free(bitmap: *mut SPBitmap) {
|
||||
assert!(!bitmap.is_null());
|
||||
|
|
|
|||
|
|
@ -8,13 +8,6 @@ use std::convert::Into;
|
|||
use std::intrinsics::transmute;
|
||||
use std::ptr::NonNull;
|
||||
|
||||
/// see [Brightness::MIN]
|
||||
pub const SP_BRIGHTNESS_MIN: u8 = 0;
|
||||
/// see [Brightness::MAX]
|
||||
pub const SP_BRIGHTNESS_MAX: u8 = 11;
|
||||
/// Count of possible brightness values
|
||||
pub const SP_BRIGHTNESS_LEVELS: u8 = 12;
|
||||
|
||||
/// A grid containing brightness values.
|
||||
///
|
||||
/// # Examples
|
||||
|
|
@ -48,9 +41,9 @@ pub unsafe extern "C" fn sp_brightness_grid_new(
|
|||
width: usize,
|
||||
height: usize,
|
||||
) -> NonNull<SPBrightnessGrid> {
|
||||
let result = Box::new(SPBrightnessGrid(
|
||||
servicepoint::BrightnessGrid::new(width, height),
|
||||
));
|
||||
let result = Box::new(SPBrightnessGrid(servicepoint::BrightnessGrid::new(
|
||||
width, height,
|
||||
)));
|
||||
NonNull::from(Box::leak(result))
|
||||
}
|
||||
|
||||
|
|
@ -133,6 +126,8 @@ pub unsafe extern "C" fn sp_brightness_grid_clone(
|
|||
/// - `brightness_grid` points to a valid [SPBrightnessGrid]
|
||||
/// - `brightness_grid` is not used concurrently or after this call
|
||||
/// - `brightness_grid` was not passed to another consuming function, e.g. to create a [SPCommand]
|
||||
///
|
||||
/// servicepoint_csbindgen_consumes: brightness_grid
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sp_brightness_grid_free(
|
||||
brightness_grid: *mut SPBrightnessGrid,
|
||||
|
|
|
|||
|
|
@ -50,6 +50,8 @@ impl Clone for SPCommand {
|
|||
/// - the result is checked for NULL
|
||||
/// - the returned [SPCommand] instance is freed in some way, either by using a consuming function or
|
||||
/// by explicitly calling `sp_command_free`.
|
||||
///
|
||||
/// servicepoint_csbindgen_consumes: packet
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sp_command_try_from_packet(
|
||||
packet: *mut SPPacket,
|
||||
|
|
@ -164,9 +166,8 @@ pub unsafe extern "C" fn sp_command_brightness(
|
|||
) -> NonNull<SPCommand> {
|
||||
let brightness =
|
||||
Brightness::try_from(brightness).expect("invalid brightness");
|
||||
let result = Box::new(SPCommand(
|
||||
servicepoint::Command::Brightness(brightness),
|
||||
));
|
||||
let result =
|
||||
Box::new(SPCommand(servicepoint::Command::Brightness(brightness)));
|
||||
NonNull::from(Box::leak(result))
|
||||
}
|
||||
|
||||
|
|
@ -188,6 +189,8 @@ pub unsafe extern "C" fn sp_command_brightness(
|
|||
/// - `grid` is not used concurrently or after this call
|
||||
/// - the returned [SPCommand] instance is freed in some way, either by using a consuming function or
|
||||
/// by explicitly calling `sp_command_free`.
|
||||
///
|
||||
/// servicepoint_csbindgen_consumes: grid
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sp_command_char_brightness(
|
||||
x: usize,
|
||||
|
|
@ -196,9 +199,10 @@ pub unsafe extern "C" fn sp_command_char_brightness(
|
|||
) -> NonNull<SPCommand> {
|
||||
assert!(!grid.is_null());
|
||||
let byte_grid = *Box::from_raw(grid);
|
||||
let result = Box::new(SPCommand(
|
||||
servicepoint::Command::CharBrightness(Origin::new(x, y), byte_grid.0),
|
||||
));
|
||||
let result = Box::new(SPCommand(servicepoint::Command::CharBrightness(
|
||||
Origin::new(x, y),
|
||||
byte_grid.0,
|
||||
)));
|
||||
NonNull::from(Box::leak(result))
|
||||
}
|
||||
|
||||
|
|
@ -227,6 +231,8 @@ pub unsafe extern "C" fn sp_command_char_brightness(
|
|||
/// - `compression` matches one of the allowed enum values
|
||||
/// - the returned [SPCommand] instance is freed in some way, either by using a consuming function or
|
||||
/// by explicitly calling `sp_command_free`.
|
||||
///
|
||||
/// servicepoint_csbindgen_consumes: bit_vec
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sp_command_bitmap_linear(
|
||||
offset: usize,
|
||||
|
|
@ -235,13 +241,11 @@ pub unsafe extern "C" fn sp_command_bitmap_linear(
|
|||
) -> NonNull<SPCommand> {
|
||||
assert!(!bit_vec.is_null());
|
||||
let bit_vec = *Box::from_raw(bit_vec);
|
||||
let result = Box::new(SPCommand(
|
||||
servicepoint::Command::BitmapLinear(
|
||||
offset,
|
||||
bit_vec.into(),
|
||||
compression.try_into().expect("invalid compression code"),
|
||||
),
|
||||
));
|
||||
let result = Box::new(SPCommand(servicepoint::Command::BitmapLinear(
|
||||
offset,
|
||||
bit_vec.into(),
|
||||
compression.try_into().expect("invalid compression code"),
|
||||
)));
|
||||
NonNull::from(Box::leak(result))
|
||||
}
|
||||
|
||||
|
|
@ -270,6 +274,8 @@ pub unsafe extern "C" fn sp_command_bitmap_linear(
|
|||
/// - `compression` matches one of the allowed enum values
|
||||
/// - the returned [SPCommand] instance is freed in some way, either by using a consuming function or
|
||||
/// by explicitly calling `sp_command_free`.
|
||||
///
|
||||
/// servicepoint_csbindgen_consumes: bit_vec
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sp_command_bitmap_linear_and(
|
||||
offset: usize,
|
||||
|
|
@ -278,13 +284,11 @@ pub unsafe extern "C" fn sp_command_bitmap_linear_and(
|
|||
) -> NonNull<SPCommand> {
|
||||
assert!(!bit_vec.is_null());
|
||||
let bit_vec = *Box::from_raw(bit_vec);
|
||||
let result = Box::new(SPCommand(
|
||||
servicepoint::Command::BitmapLinearAnd(
|
||||
offset,
|
||||
bit_vec.into(),
|
||||
compression.try_into().expect("invalid compression code"),
|
||||
),
|
||||
));
|
||||
let result = Box::new(SPCommand(servicepoint::Command::BitmapLinearAnd(
|
||||
offset,
|
||||
bit_vec.into(),
|
||||
compression.try_into().expect("invalid compression code"),
|
||||
)));
|
||||
NonNull::from(Box::leak(result))
|
||||
}
|
||||
|
||||
|
|
@ -313,6 +317,8 @@ pub unsafe extern "C" fn sp_command_bitmap_linear_and(
|
|||
/// - `compression` matches one of the allowed enum values
|
||||
/// - the returned [SPCommand] instance is freed in some way, either by using a consuming function or
|
||||
/// by explicitly calling `sp_command_free`.
|
||||
///
|
||||
/// servicepoint_csbindgen_consumes: bit_vec
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sp_command_bitmap_linear_or(
|
||||
offset: usize,
|
||||
|
|
@ -321,13 +327,11 @@ pub unsafe extern "C" fn sp_command_bitmap_linear_or(
|
|||
) -> NonNull<SPCommand> {
|
||||
assert!(!bit_vec.is_null());
|
||||
let bit_vec = *Box::from_raw(bit_vec);
|
||||
let result = Box::new(SPCommand(
|
||||
servicepoint::Command::BitmapLinearOr(
|
||||
offset,
|
||||
bit_vec.into(),
|
||||
compression.try_into().expect("invalid compression code"),
|
||||
),
|
||||
));
|
||||
let result = Box::new(SPCommand(servicepoint::Command::BitmapLinearOr(
|
||||
offset,
|
||||
bit_vec.into(),
|
||||
compression.try_into().expect("invalid compression code"),
|
||||
)));
|
||||
NonNull::from(Box::leak(result))
|
||||
}
|
||||
|
||||
|
|
@ -356,6 +360,8 @@ pub unsafe extern "C" fn sp_command_bitmap_linear_or(
|
|||
/// - `compression` matches one of the allowed enum values
|
||||
/// - the returned [SPCommand] instance is freed in some way, either by using a consuming function or
|
||||
/// by explicitly calling `sp_command_free`.
|
||||
///
|
||||
/// servicepoint_csbindgen_consumes: bit_vec
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sp_command_bitmap_linear_xor(
|
||||
offset: usize,
|
||||
|
|
@ -364,13 +370,11 @@ pub unsafe extern "C" fn sp_command_bitmap_linear_xor(
|
|||
) -> NonNull<SPCommand> {
|
||||
assert!(!bit_vec.is_null());
|
||||
let bit_vec = *Box::from_raw(bit_vec);
|
||||
let result = Box::new(SPCommand(
|
||||
servicepoint::Command::BitmapLinearXor(
|
||||
offset,
|
||||
bit_vec.into(),
|
||||
compression.try_into().expect("invalid compression code"),
|
||||
),
|
||||
));
|
||||
let result = Box::new(SPCommand(servicepoint::Command::BitmapLinearXor(
|
||||
offset,
|
||||
bit_vec.into(),
|
||||
compression.try_into().expect("invalid compression code"),
|
||||
)));
|
||||
NonNull::from(Box::leak(result))
|
||||
}
|
||||
|
||||
|
|
@ -392,6 +396,8 @@ pub unsafe extern "C" fn sp_command_bitmap_linear_xor(
|
|||
/// - `grid` is not used concurrently or after this call
|
||||
/// - the returned [SPCommand] instance is freed in some way, either by using a consuming function or
|
||||
/// by explicitly calling `sp_command_free`.
|
||||
///
|
||||
/// servicepoint_csbindgen_consumes: grid
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sp_command_cp437_data(
|
||||
x: usize,
|
||||
|
|
@ -400,9 +406,10 @@ pub unsafe extern "C" fn sp_command_cp437_data(
|
|||
) -> NonNull<SPCommand> {
|
||||
assert!(!grid.is_null());
|
||||
let grid = *Box::from_raw(grid);
|
||||
let result = Box::new(SPCommand(
|
||||
servicepoint::Command::Cp437Data(Origin::new(x, y), grid.0),
|
||||
));
|
||||
let result = Box::new(SPCommand(servicepoint::Command::Cp437Data(
|
||||
Origin::new(x, y),
|
||||
grid.0,
|
||||
)));
|
||||
NonNull::from(Box::leak(result))
|
||||
}
|
||||
|
||||
|
|
@ -426,6 +433,8 @@ pub unsafe extern "C" fn sp_command_cp437_data(
|
|||
/// - `compression` matches one of the allowed enum values
|
||||
/// - the returned [SPCommand] instance is freed in some way, either by using a consuming function or
|
||||
/// by explicitly calling `sp_command_free`.
|
||||
///
|
||||
/// servicepoint_csbindgen_consumes: bitmap
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sp_command_bitmap_linear_win(
|
||||
x: usize,
|
||||
|
|
@ -435,15 +444,13 @@ pub unsafe extern "C" fn sp_command_bitmap_linear_win(
|
|||
) -> NonNull<SPCommand> {
|
||||
assert!(!bitmap.is_null());
|
||||
let byte_grid = (*Box::from_raw(bitmap)).0;
|
||||
let result = Box::new(SPCommand(
|
||||
servicepoint::Command::BitmapLinearWin(
|
||||
Origin::new(x, y),
|
||||
byte_grid,
|
||||
compression_code
|
||||
.try_into()
|
||||
.expect("invalid compression code"),
|
||||
),
|
||||
));
|
||||
let result = Box::new(SPCommand(servicepoint::Command::BitmapLinearWin(
|
||||
Origin::new(x, y),
|
||||
byte_grid,
|
||||
compression_code
|
||||
.try_into()
|
||||
.expect("invalid compression code"),
|
||||
)));
|
||||
NonNull::from(Box::leak(result))
|
||||
}
|
||||
|
||||
|
|
@ -467,6 +474,8 @@ pub unsafe extern "C" fn sp_command_bitmap_linear_win(
|
|||
/// - `command` points to a valid [SPCommand]
|
||||
/// - `command` is not used concurrently or after this call
|
||||
/// - `command` was not passed to another consuming function, e.g. to create a [SPPacket]
|
||||
///
|
||||
/// servicepoint_csbindgen_consumes: command
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sp_command_free(command: *mut SPCommand) {
|
||||
assert!(!command.is_null());
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
//! prefix `sp_connection_`
|
||||
|
||||
use std::ffi::{c_char, CStr};
|
||||
use std::ptr::null_mut;
|
||||
use std::ptr::{null_mut, NonNull};
|
||||
|
||||
use crate::{SPCommand, SPPacket};
|
||||
|
||||
|
|
@ -18,7 +18,7 @@ use crate::{SPCommand, SPPacket};
|
|||
/// ```
|
||||
pub struct SPConnection(pub(crate) servicepoint::Connection);
|
||||
|
||||
/// Creates a new instance of [SPConnection].
|
||||
/// Creates a new instance of [SPConnection] that uses UDP to send.
|
||||
///
|
||||
/// returns: NULL if connection fails, or connected instance
|
||||
///
|
||||
|
|
@ -46,6 +46,22 @@ pub unsafe extern "C" fn sp_connection_open(
|
|||
Box::into_raw(Box::new(SPConnection(connection)))
|
||||
}
|
||||
|
||||
/// Creates a new instance of [SPConnection] for testing that does not actually send anything.
|
||||
///
|
||||
/// returns: a new instance. Will never return NULL.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The caller has to make sure that:
|
||||
///
|
||||
/// - the returned instance is freed in some way, either by using a consuming function or
|
||||
/// by explicitly calling `sp_connection_free`.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sp_connection_fake() -> NonNull<SPConnection> {
|
||||
let result = Box::new(SPConnection(servicepoint::Connection::Fake));
|
||||
NonNull::from(Box::leak(result))
|
||||
}
|
||||
|
||||
/// Sends a [SPPacket] to the display using the [SPConnection].
|
||||
///
|
||||
/// The passed `packet` gets consumed.
|
||||
|
|
@ -64,6 +80,8 @@ pub unsafe extern "C" fn sp_connection_open(
|
|||
/// - `connection` points to a valid instance of [SPConnection]
|
||||
/// - `packet` points to a valid instance of [SPPacket]
|
||||
/// - `packet` is not used concurrently or after this call
|
||||
///
|
||||
/// servicepoint_csbindgen_consumes: packet
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sp_connection_send_packet(
|
||||
connection: *const SPConnection,
|
||||
|
|
@ -93,6 +111,8 @@ pub unsafe extern "C" fn sp_connection_send_packet(
|
|||
/// - `connection` points to a valid instance of [SPConnection]
|
||||
/// - `command` points to a valid instance of [SPPacket]
|
||||
/// - `command` is not used concurrently or after this call
|
||||
///
|
||||
/// servicepoint_csbindgen_consumes: command
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sp_connection_send_command(
|
||||
connection: *const SPConnection,
|
||||
|
|
@ -116,6 +136,8 @@ pub unsafe extern "C" fn sp_connection_send_command(
|
|||
///
|
||||
/// - `connection` points to a valid [SPConnection]
|
||||
/// - `connection` is not used concurrently or after this call
|
||||
///
|
||||
/// servicepoint_csbindgen_consumes: connection
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sp_connection_free(connection: *mut SPConnection) {
|
||||
assert!(!connection.is_null());
|
||||
|
|
|
|||
|
|
@ -24,6 +24,13 @@ pub const SP_PIXEL_COUNT: usize = SP_PIXEL_WIDTH * SP_PIXEL_HEIGHT;
|
|||
/// Actual hardware limit is around 28-29ms/frame. Rounded up for less dropped packets.
|
||||
pub const SP_FRAME_PACING_MS: u128 = Duration::from_millis(30).as_millis();
|
||||
|
||||
/// see [Brightness::MIN]
|
||||
pub const SP_BRIGHTNESS_MIN: u8 = 0;
|
||||
/// see [Brightness::MAX]
|
||||
pub const SP_BRIGHTNESS_MAX: u8 = 11;
|
||||
/// Count of possible brightness values
|
||||
pub const SP_BRIGHTNESS_LEVELS: u8 = 12;
|
||||
|
||||
/// Specifies the kind of compression to use.
|
||||
#[repr(u16)]
|
||||
pub enum SPCompressionCode {
|
||||
|
|
|
|||
|
|
@ -2,9 +2,9 @@
|
|||
//!
|
||||
//! prefix `sp_cp437_grid_`
|
||||
|
||||
use std::ptr::NonNull;
|
||||
use crate::SPByteSlice;
|
||||
use servicepoint::{DataRef, Grid};
|
||||
use std::ptr::NonNull;
|
||||
|
||||
/// A C-wrapper for grid containing codepage 437 characters.
|
||||
///
|
||||
|
|
@ -41,9 +41,8 @@ pub unsafe extern "C" fn sp_cp437_grid_new(
|
|||
width: usize,
|
||||
height: usize,
|
||||
) -> NonNull<SPCp437Grid> {
|
||||
let result = Box::new(SPCp437Grid(
|
||||
servicepoint::Cp437Grid::new(width, height),
|
||||
));
|
||||
let result =
|
||||
Box::new(SPCp437Grid(servicepoint::Cp437Grid::new(width, height)));
|
||||
NonNull::from(Box::leak(result))
|
||||
}
|
||||
|
||||
|
|
@ -71,11 +70,11 @@ pub unsafe extern "C" fn sp_cp437_grid_load(
|
|||
data: *const u8,
|
||||
data_length: usize,
|
||||
) -> NonNull<SPCp437Grid> {
|
||||
assert!(data.is_null());
|
||||
assert!(!data.is_null());
|
||||
let data = std::slice::from_raw_parts(data, data_length);
|
||||
let result = Box::new(SPCp437Grid(
|
||||
servicepoint::Cp437Grid::load(width, height, data),
|
||||
));
|
||||
let result = Box::new(SPCp437Grid(servicepoint::Cp437Grid::load(
|
||||
width, height, data,
|
||||
)));
|
||||
NonNull::from(Box::leak(result))
|
||||
}
|
||||
|
||||
|
|
@ -117,6 +116,8 @@ pub unsafe extern "C" fn sp_cp437_grid_clone(
|
|||
/// - `cp437_grid` points to a valid [SPCp437Grid]
|
||||
/// - `cp437_grid` is not used concurrently or after cp437_grid call
|
||||
/// - `cp437_grid` was not passed to another consuming function, e.g. to create a [SPCommand]
|
||||
///
|
||||
/// servicepoint_csbindgen_consumes: cp437_grid
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sp_cp437_grid_free(cp437_grid: *mut SPCp437Grid) {
|
||||
assert!(!cp437_grid.is_null());
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@
|
|||
//! }
|
||||
//! ```
|
||||
|
||||
pub use crate::bitvec::*;
|
||||
pub use crate::bit_vec::*;
|
||||
pub use crate::bitmap::*;
|
||||
pub use crate::brightness_grid::*;
|
||||
pub use crate::byte_slice::*;
|
||||
|
|
@ -35,7 +35,7 @@ pub use crate::constants::*;
|
|||
pub use crate::cp437_grid::*;
|
||||
pub use crate::packet::*;
|
||||
|
||||
mod bitvec;
|
||||
mod bit_vec;
|
||||
mod bitmap;
|
||||
mod brightness_grid;
|
||||
mod byte_slice;
|
||||
|
|
|
|||
|
|
@ -26,6 +26,8 @@ pub struct SPPacket(pub(crate) servicepoint::packet::Packet);
|
|||
/// - [SPCommand] is not used concurrently or after this call
|
||||
/// - the returned [SPPacket] instance is freed in some way, either by using a consuming function or
|
||||
/// by explicitly calling `sp_packet_free`.
|
||||
///
|
||||
/// servicepoint_csbindgen_consumes: command
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sp_packet_from_command(
|
||||
command: *mut SPCommand,
|
||||
|
|
@ -36,6 +38,63 @@ pub unsafe extern "C" fn sp_packet_from_command(
|
|||
NonNull::from(Box::leak(result))
|
||||
}
|
||||
|
||||
/// Creates a raw [SPPacket] from parts.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// - `command_code` specifies which command this packet contains
|
||||
/// - `a`, `b`, `c` and `d` are command-specific header values
|
||||
/// - `payload` is the optional data that is part of the command
|
||||
/// - `payload_len` is the size of the payload
|
||||
///
|
||||
/// returns: new instance. Will never return null.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// - when `payload` is null, but `payload_len` is not zero
|
||||
/// - when `payload_len` is zero, but `payload` is nonnull
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The caller has to make sure that:
|
||||
///
|
||||
/// - `payload` points to a valid memory region of at least `payload_len` bytes
|
||||
/// - `payload` is not written to concurrently
|
||||
/// - the returned [SPPacket] instance is freed in some way, either by using a consuming function or
|
||||
/// by explicitly calling `sp_packet_free`.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sp_packet_from_parts(
|
||||
command_code: u16,
|
||||
a: u16,
|
||||
b: u16,
|
||||
c: u16,
|
||||
d: u16,
|
||||
payload: *const u8,
|
||||
payload_len: usize,
|
||||
) -> NonNull<SPPacket> {
|
||||
assert_eq!(payload.is_null(), payload_len == 0);
|
||||
|
||||
let payload = if payload.is_null() {
|
||||
vec![]
|
||||
} else {
|
||||
let payload = std::slice::from_raw_parts(payload, payload_len);
|
||||
Vec::from(payload)
|
||||
};
|
||||
|
||||
let packet = servicepoint::packet::Packet {
|
||||
header: servicepoint::packet::Header {
|
||||
command_code,
|
||||
a,
|
||||
b,
|
||||
c,
|
||||
d,
|
||||
},
|
||||
payload,
|
||||
};
|
||||
let result = Box::new(SPPacket(packet));
|
||||
NonNull::from(Box::leak(result))
|
||||
}
|
||||
|
||||
/// Tries to load a [SPPacket] from the passed array with the specified length.
|
||||
///
|
||||
/// returns: NULL in case of an error, pointer to the allocated packet otherwise
|
||||
|
|
@ -94,7 +153,7 @@ pub unsafe extern "C" fn sp_packet_clone(
|
|||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// - when `sp_packet_free` is NULL
|
||||
/// - when `packet` is NULL
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
|
|
@ -102,6 +161,8 @@ pub unsafe extern "C" fn sp_packet_clone(
|
|||
///
|
||||
/// - `packet` points to a valid [SPPacket]
|
||||
/// - `packet` is not used concurrently or after this call
|
||||
///
|
||||
/// servicepoint_csbindgen_consumes: packet
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sp_packet_free(packet: *mut SPPacket) {
|
||||
assert!(!packet.is_null());
|
||||
|
|
|
|||
|
|
@ -10,7 +10,8 @@ crate-type = ["cdylib"]
|
|||
test = false
|
||||
|
||||
[build-dependencies]
|
||||
csbindgen = "1.9.3"
|
||||
csbindgen = { path = "../servicepoint_csbindgen/csbindgen" }
|
||||
convert_case = "0.6.0"
|
||||
|
||||
[dependencies]
|
||||
servicepoint_binding_c = { version = "0.10.0", path = "../servicepoint_binding_c" }
|
||||
|
|
|
|||
|
|
@ -9,9 +9,8 @@ This crate contains C# bindings for the `servicepoint` library, enabling users t
|
|||
```csharp
|
||||
using ServicePoint;
|
||||
|
||||
// using statement calls Dispose() on scope exit, which frees unmanaged instances
|
||||
using var connection = Connection.Open("127.0.0.1:2342");
|
||||
using var pixels = Bitmap.New(Constants.PixelWidth, Constants.PixelHeight);
|
||||
using var pixels = new Bitmap(Constants.PixelWidth, Constants.PixelHeight);
|
||||
|
||||
while (true)
|
||||
{
|
||||
|
|
@ -20,17 +19,14 @@ while (true)
|
|||
Thread.Sleep(5000);
|
||||
|
||||
pixels.Fill(false);
|
||||
connection.Send(Command.BitmapLinearWin(0, 0, pixels.Clone()));
|
||||
connection.Send(Command.BitmapLinearWin(0, 0, pixels));
|
||||
Thread.Sleep(5000);
|
||||
}
|
||||
```
|
||||
|
||||
A full example including project files is available as part of this crate.
|
||||
An example including project files is available as part of this crate.
|
||||
|
||||
## Note on stability
|
||||
|
||||
This library is still in early development.
|
||||
You can absolutely use it, and it works, but expect minor breaking changes with every version bump.
|
||||
You can also check out the unit tests for usage examples for some things.
|
||||
|
||||
## Installation
|
||||
|
||||
|
|
@ -43,22 +39,39 @@ git submodule add https://github.com/cccb/servicepoint.git
|
|||
git commit -m "add servicepoint submodule"
|
||||
```
|
||||
|
||||
You can now reference `servicepoint-bindings-cs/src/ServicePoint.csproj` in your project.
|
||||
You can now reference `servicepoint_binding_cs/src/ServicePoint.csproj` in your project.
|
||||
The rust library will automatically be built.
|
||||
|
||||
Please provide more information in the form of an issue if you need the build to copy a different library file for your platform.
|
||||
|
||||
## Notes on differences to rust library
|
||||
## Note on stability
|
||||
|
||||
Uses C bindings internally to provide a similar API to rust. Things to keep in mind:
|
||||
This library is still in early development.
|
||||
You can absolutely use it, and it works, but expect minor breaking changes with every version bump.
|
||||
|
||||
- You will get a `NullPointerException` when trying to call a method where the native instance has been consumed already (e.g. when `Send`ing a command instance twice). Send a clone instead of the original if you want to keep using it.
|
||||
- Some lower-level APIs _will_ panic in native code when used improperly.
|
||||
Example: manipulating the `Span<byte>` of an object after freeing the instance.
|
||||
- C# specifics are documented in the library. Use the rust documentation for everything else. Naming and semantics are the same apart from CamelCase instead of kebab_case.
|
||||
- You will only get rust backtraces in debug builds of the native code.
|
||||
- F# is not explicitly tested. If there are usability or functionality problems, please open an issue.
|
||||
- Reading and writing to instances concurrently is not safe. Only reading concurrently is safe.
|
||||
## Documentation
|
||||
|
||||
There are multiple suboptimal ways to read the documentation for this.
|
||||
|
||||
You can read the [rust docs](https://docs.rs/servicepoint/latest/servicepoint/), as the types and methods in C# should have the same names as those in rust.
|
||||
|
||||
You can also read the documentation comments on each method.
|
||||
Those are copied from the C API, which means they will include the `this` parameter in the description.
|
||||
They are markdown formatted and may render in one line in your IDE - this is a known [issue](https://github.com/cccb/servicepoint/issues/17).
|
||||
|
||||
### Differences to other supported languages
|
||||
|
||||
C# does have some differences, especially regarding safety.
|
||||
In rust, the compiler will tell you when trying to use an object that has already been dropped or moved.
|
||||
In the C API, the user promises to keep things like that in mind,
|
||||
and will get assertion failures or segmentation faults if you are lucky when doing something wrong.
|
||||
|
||||
The C# compiler will not help you to keep track of the lifetime of rust objects, but you also do not have to worry about
|
||||
unnoticed memory corruption in most cases, as the library knows when you pass objects to methods that consume them and
|
||||
raises a `NullReferenceException` instead.
|
||||
When objects are garbage collected on the C# side, the rust object is freed as well.
|
||||
|
||||
Currently, lifetime tracking may not work reliably in multithreaded code. You should prevent concurrent write access.
|
||||
|
||||
## Everything else
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,12 @@
|
|||
namespace ServicePoint.Tests;
|
||||
|
||||
public class BitVecTests
|
||||
{
|
||||
[Fact]
|
||||
public void UseAfterFree()
|
||||
{
|
||||
var bitvec = new BitVec(8);
|
||||
_ = Command.BitmapLinear(0, bitvec, CompressionCode.Uncompressed);
|
||||
Assert.Throws<NullReferenceException>(() => _ = Command.BitmapLinear(0, bitvec, CompressionCode.Uncompressed));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
namespace ServicePoint.Tests;
|
||||
|
||||
public class BitmapTests
|
||||
{
|
||||
[Fact]
|
||||
public void UseAfterFree()
|
||||
{
|
||||
var bitmap = Bitmap.NewScreenSized();
|
||||
_ = Command.BitmapLinearWin(0, 0, bitmap, CompressionCode.Uncompressed);
|
||||
Assert.Throws<NullReferenceException>(() => _ = Command.BitmapLinearWin(0, 0, bitmap, CompressionCode.Uncompressed));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
namespace ServicePoint.Tests;
|
||||
|
||||
public class BBrightnessGridTests
|
||||
{
|
||||
[Fact]
|
||||
public void UseAfterFree()
|
||||
{
|
||||
var grid = new BrightnessGrid(23, 42);
|
||||
_ = Command.CharBrightness(0, 0, grid);
|
||||
Assert.Throws<NullReferenceException>(() => _ = Command.CharBrightness(0, 0, grid));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
namespace ServicePoint.Tests;
|
||||
|
||||
public class CommandTests
|
||||
{
|
||||
private Connection _fakeConnection = Connection.Fake();
|
||||
|
||||
[Fact]
|
||||
public void UseAfterSend()
|
||||
{
|
||||
var command = Command.Clear();
|
||||
_fakeConnection.Send(command);
|
||||
Assert.Throws<NullReferenceException>(() => _fakeConnection.Send(command));
|
||||
_fakeConnection.Send(Command.Clear());
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace ServicePoint.Tests;
|
||||
|
||||
public class Cp437GridTests
|
||||
{
|
||||
[Fact]
|
||||
public void UseAfterFree()
|
||||
{
|
||||
var grid = new Cp437Grid(2, 3);
|
||||
_ = Command.Cp437Data(0, 0, grid.Clone());
|
||||
_ = Command.Cp437Data(0, 0, grid);
|
||||
Assert.Throws<NullReferenceException>(() => _ = Command.Cp437Data(0, 0, grid));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ReadAndWriteString()
|
||||
{
|
||||
var grid = new Cp437Grid(3, 2);
|
||||
grid[1] = "abc";
|
||||
Assert.Equal("abc", grid[1]);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void LoadSpan()
|
||||
{
|
||||
var ascii_str = "abc123"u8;
|
||||
var grid = Cp437Grid.Load(3, 2, ascii_str);
|
||||
Assert.Equal("abc", grid[0]);
|
||||
Assert.Equal("123", grid[1]);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
global using System;
|
||||
global using Xunit;
|
||||
global using ServicePoint;
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>disable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
|
||||
<IsPackable>false</IsPackable>
|
||||
<IsTestProject>true</IsTestProject>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="coverlet.collector" Version="6.0.0" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0" />
|
||||
<PackageReference Include="xunit" Version="2.5.3" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.5.3" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Using Include="Xunit" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\ServicePoint\ServicePoint.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
@ -1,8 +1,9 @@
|
|||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ServicePoint", "ServicePoint/ServicePoint.csproj", "{70EFFA3F-012A-4518-9627-466BEAE4252E}"
|
||||
#
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ServicePoint", "ServicePoint\ServicePoint.csproj", "{70EFFA3F-012A-4518-9627-466BEAE4252E}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "lang-cs", "examples/lang_cs/lang_cs.csproj", "{DA3B8B6E-993A-47DA-844B-F92AF520FF59}"
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "lang-cs", "examples\lang_cs\lang_cs.csproj", "{DA3B8B6E-993A-47DA-844B-F92AF520FF59}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "shared", "shared", "{C2F8EC4A-2426-4DC3-990F-C43810B183F5}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
|
|
@ -10,6 +11,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "shared", "shared", "{C2F8EC
|
|||
..\..\.envrc = ..\..\.envrc
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ServicePoint.Tests", "ServicePoint.Tests\ServicePoint.Tests.csproj", "{CDA70D8F-E0EC-46E3-AF96-511267DF0BA0}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
|
|
@ -24,5 +27,9 @@ Global
|
|||
{DA3B8B6E-993A-47DA-844B-F92AF520FF59}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{DA3B8B6E-993A-47DA-844B-F92AF520FF59}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{DA3B8B6E-993A-47DA-844B-F92AF520FF59}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{CDA70D8F-E0EC-46E3-AF96-511267DF0BA0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{CDA70D8F-E0EC-46E3-AF96-511267DF0BA0}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{CDA70D8F-E0EC-46E3-AF96-511267DF0BA0}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{CDA70D8F-E0EC-46E3-AF96-511267DF0BA0}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -1,88 +1,23 @@
|
|||
using ServicePoint.BindGen;
|
||||
|
||||
namespace ServicePoint;
|
||||
|
||||
public sealed class BitVec : SpNativeInstance<BindGen.BitVec>
|
||||
public sealed partial class BitVec
|
||||
{
|
||||
public static BitVec New(int size)
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
return new BitVec(NativeMethods.sp_bitvec_new((nuint)size));
|
||||
}
|
||||
}
|
||||
|
||||
public static BitVec Load(Span<byte> bytes)
|
||||
public static BitVec Load(ReadOnlySpan<byte> bytes)
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
fixed (byte* bytesPtr = bytes)
|
||||
{
|
||||
return new BitVec(NativeMethods.sp_bitvec_load(bytesPtr, (nuint)bytes.Length));
|
||||
return Load(bytesPtr, (nuint)bytes.Length);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public BitVec Clone()
|
||||
public bool this[nuint index]
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
return new BitVec(NativeMethods.sp_bitvec_clone(Instance));
|
||||
}
|
||||
get => Get(index);
|
||||
set => Set(index, value);
|
||||
}
|
||||
|
||||
public bool this[int index]
|
||||
{
|
||||
get
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
return NativeMethods.sp_bitvec_get(Instance, (nuint)index);
|
||||
}
|
||||
}
|
||||
set
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
NativeMethods.sp_bitvec_set(Instance, (nuint)index, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Fill(bool value)
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
NativeMethods.sp_bitvec_fill(Instance, value);
|
||||
}
|
||||
}
|
||||
|
||||
public int Length
|
||||
{
|
||||
get
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
return (int)NativeMethods.sp_bitvec_len(Instance);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Span<byte> Data
|
||||
{
|
||||
get
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
var slice = NativeMethods.sp_bitvec_unsafe_data_ref(Instance);
|
||||
return new Span<byte>(slice.start, (int)slice.length);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private unsafe BitVec(BindGen.BitVec* instance) : base(instance)
|
||||
{
|
||||
}
|
||||
|
||||
private protected override unsafe void Free() => NativeMethods.sp_bitvec_free(Instance);
|
||||
public Span<byte> Data => UnsafeDataRef().AsSpan();
|
||||
}
|
||||
|
|
|
|||
326
crates/servicepoint_binding_cs/ServicePoint/BitVec.g.cs
Normal file
326
crates/servicepoint_binding_cs/ServicePoint/BitVec.g.cs
Normal file
|
|
@ -0,0 +1,326 @@
|
|||
// <auto-generated>
|
||||
// This code is generated by csbindgen.
|
||||
// DON'T CHANGE THIS DIRECTLY.
|
||||
// </auto-generated>
|
||||
#pragma warning disable CS8500
|
||||
#pragma warning disable CS8981
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
|
||||
namespace ServicePoint
|
||||
{
|
||||
|
||||
public unsafe sealed partial class BitVec: IDisposable
|
||||
{
|
||||
#nullable enable
|
||||
/// <summary>
|
||||
/// Creates a new [SPBitVec] instance.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// - `size`: size in bits.
|
||||
///
|
||||
/// returns: [SPBitVec] with all bits set to false. Will never return NULL.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// - when `size` is not divisible by 8.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The caller has to make sure that:
|
||||
///
|
||||
/// - the returned instance is freed in some way, either by using a consuming function or
|
||||
/// by explicitly calling `sp_bitvec_free`.
|
||||
/// </summary>
|
||||
public BitVec(nuint size) : this(sp_bitvec_new(size)) {}
|
||||
|
||||
/// <summary>
|
||||
/// Interpret the data as a series of bits and load then into a new [SPBitVec] instance.
|
||||
///
|
||||
/// returns: [SPBitVec] instance containing data. Will never return NULL.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// - when `data` is NULL
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The caller has to make sure that:
|
||||
///
|
||||
/// - `data` points to a valid memory location of at least `data_length`
|
||||
/// bytes in size.
|
||||
/// - the returned instance is freed in some way, either by using a consuming function or
|
||||
/// by explicitly calling `sp_bitvec_free`.
|
||||
/// </summary>
|
||||
[System.Runtime.CompilerServices.MethodImplAttribute(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
|
||||
public static BitVec Load(byte* data, nuint data_length)
|
||||
{
|
||||
return new BitVec(BitVec.sp_bitvec_load(data, data_length));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clones a [SPBitVec].
|
||||
///
|
||||
/// returns: new [SPBitVec] instance. Will never return NULL.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// - when `bit_vec` is NULL
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The caller has to make sure that:
|
||||
///
|
||||
/// - `bit_vec` points to a valid [SPBitVec]
|
||||
/// - `bit_vec` is not written to concurrently
|
||||
/// - the returned instance is freed in some way, either by using a consuming function or
|
||||
/// by explicitly calling `sp_bitvec_free`.
|
||||
/// </summary>
|
||||
[System.Runtime.CompilerServices.MethodImplAttribute(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
|
||||
public BitVec Clone()
|
||||
{
|
||||
return new BitVec(BitVec.sp_bitvec_clone(this.__Instance));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the value of a bit from the [SPBitVec].
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// - `bit_vec`: instance to read from
|
||||
/// - `index`: the bit index to read
|
||||
///
|
||||
/// returns: value of the bit
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// - when `bit_vec` is NULL
|
||||
/// - when accessing `index` out of bounds
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The caller has to make sure that:
|
||||
///
|
||||
/// - `bit_vec` points to a valid [SPBitVec]
|
||||
/// - `bit_vec` is not written to concurrently
|
||||
/// </summary>
|
||||
[System.Runtime.CompilerServices.MethodImplAttribute(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
|
||||
public bool Get(nuint index)
|
||||
{
|
||||
return BitVec.sp_bitvec_get(this.__Instance, index);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the value of a bit in the [SPBitVec].
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// - `bit_vec`: instance to write to
|
||||
/// - `index`: the bit index to edit
|
||||
/// - `value`: the value to set the bit to
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// - when `bit_vec` is NULL
|
||||
/// - when accessing `index` out of bounds
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The caller has to make sure that:
|
||||
///
|
||||
/// - `bit_vec` points to a valid [SPBitVec]
|
||||
/// - `bit_vec` is not written to or read from concurrently
|
||||
/// </summary>
|
||||
[System.Runtime.CompilerServices.MethodImplAttribute(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
|
||||
public void Set(nuint index, bool value)
|
||||
{
|
||||
BitVec.sp_bitvec_set(this.__Instance, index, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the value of all bits in the [SPBitVec].
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// - `bit_vec`: instance to write to
|
||||
/// - `value`: the value to set all bits to
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// - when `bit_vec` is NULL
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The caller has to make sure that:
|
||||
///
|
||||
/// - `bit_vec` points to a valid [SPBitVec]
|
||||
/// - `bit_vec` is not written to or read from concurrently
|
||||
/// </summary>
|
||||
[System.Runtime.CompilerServices.MethodImplAttribute(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
|
||||
public void Fill(bool value)
|
||||
{
|
||||
BitVec.sp_bitvec_fill(this.__Instance, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the length of the [SPBitVec] in bits.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// - `bit_vec`: instance to write to
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// - when `bit_vec` is NULL
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The caller has to make sure that:
|
||||
///
|
||||
/// - `bit_vec` points to a valid [SPBitVec]
|
||||
/// </summary>
|
||||
[System.Runtime.CompilerServices.MethodImplAttribute(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
|
||||
public nuint Len()
|
||||
{
|
||||
return BitVec.sp_bitvec_len(this.__Instance);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if length is 0.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// - `bit_vec`: instance to write to
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// - when `bit_vec` is NULL
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The caller has to make sure that:
|
||||
///
|
||||
/// - `bit_vec` points to a valid [SPBitVec]
|
||||
/// </summary>
|
||||
[System.Runtime.CompilerServices.MethodImplAttribute(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
|
||||
public bool IsEmpty()
|
||||
{
|
||||
return BitVec.sp_bitvec_is_empty(this.__Instance);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets an unsafe reference to the data of the [SPBitVec] instance.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// - `bit_vec`: instance to write to
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// - when `bit_vec` is NULL
|
||||
///
|
||||
/// ## Safety
|
||||
///
|
||||
/// The caller has to make sure that:
|
||||
///
|
||||
/// - `bit_vec` points to a valid [SPBitVec]
|
||||
/// - the returned memory range is never accessed after the passed [SPBitVec] has been freed
|
||||
/// - the returned memory range is never accessed concurrently, either via the [SPBitVec] or directly
|
||||
/// </summary>
|
||||
[System.Runtime.CompilerServices.MethodImplAttribute(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
|
||||
public SPByteSlice UnsafeDataRef()
|
||||
{
|
||||
return BitVec.sp_bitvec_unsafe_data_ref(this.__Instance);
|
||||
}
|
||||
|
||||
|
||||
#region internal machinery
|
||||
private SPBitVec* _instance;
|
||||
internal SPBitVec* __Instance
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_instance == null)
|
||||
throw new NullReferenceException("instance is null");
|
||||
return _instance;
|
||||
}
|
||||
}
|
||||
|
||||
private BitVec(SPBitVec* instance)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(instance);
|
||||
_instance = instance;
|
||||
}
|
||||
|
||||
internal SPBitVec* __Into()
|
||||
{
|
||||
var instance = __Instance;
|
||||
_instance = null;
|
||||
return instance;
|
||||
}
|
||||
|
||||
private void __Free()
|
||||
{
|
||||
if (_instance != null)
|
||||
BitVec.sp_bitvec_free(__Into());
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
__Free();
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
~BitVec() => __Free();
|
||||
|
||||
#endregion
|
||||
|
||||
#nullable restore
|
||||
#region native methods
|
||||
const string __DllName = "servicepoint_binding_c";
|
||||
[DllImport(__DllName, EntryPoint = "sp_bitvec_new", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
private static extern SPBitVec* sp_bitvec_new(nuint size);
|
||||
|
||||
[DllImport(__DllName, EntryPoint = "sp_bitvec_load", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
private static extern SPBitVec* sp_bitvec_load(byte* data, nuint data_length);
|
||||
|
||||
[DllImport(__DllName, EntryPoint = "sp_bitvec_clone", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
private static extern SPBitVec* sp_bitvec_clone(SPBitVec* bit_vec);
|
||||
|
||||
[DllImport(__DllName, EntryPoint = "sp_bitvec_free", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
private static extern void sp_bitvec_free(SPBitVec* bit_vec);
|
||||
|
||||
[DllImport(__DllName, EntryPoint = "sp_bitvec_get", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
[return: MarshalAs(UnmanagedType.U1)]
|
||||
private static extern bool sp_bitvec_get(SPBitVec* bit_vec, nuint index);
|
||||
|
||||
[DllImport(__DllName, EntryPoint = "sp_bitvec_set", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
private static extern void sp_bitvec_set(SPBitVec* bit_vec, nuint index, [MarshalAs(UnmanagedType.U1)] bool value);
|
||||
|
||||
[DllImport(__DllName, EntryPoint = "sp_bitvec_fill", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
private static extern void sp_bitvec_fill(SPBitVec* bit_vec, [MarshalAs(UnmanagedType.U1)] bool value);
|
||||
|
||||
[DllImport(__DllName, EntryPoint = "sp_bitvec_len", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
private static extern nuint sp_bitvec_len(SPBitVec* bit_vec);
|
||||
|
||||
[DllImport(__DllName, EntryPoint = "sp_bitvec_is_empty", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
[return: MarshalAs(UnmanagedType.U1)]
|
||||
private static extern bool sp_bitvec_is_empty(SPBitVec* bit_vec);
|
||||
|
||||
[DllImport(__DllName, EntryPoint = "sp_bitvec_unsafe_data_ref", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
private static extern SPByteSlice sp_bitvec_unsafe_data_ref(SPBitVec* bit_vec);
|
||||
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public unsafe partial struct SPBitVec
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -1,100 +1,23 @@
|
|||
using ServicePoint.BindGen;
|
||||
|
||||
namespace ServicePoint;
|
||||
|
||||
public sealed class Bitmap : SpNativeInstance<BindGen.Bitmap>
|
||||
public sealed partial class Bitmap
|
||||
{
|
||||
public static Bitmap New(int width, int height)
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
return new Bitmap(NativeMethods.sp_bitmap_new((nuint)width, (nuint)height));
|
||||
}
|
||||
}
|
||||
|
||||
public static Bitmap Load(int width, int height, Span<byte> bytes)
|
||||
public static Bitmap Load(nuint width, nuint height, ReadOnlySpan<byte> bytes)
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
fixed (byte* bytesPtr = bytes)
|
||||
{
|
||||
return new Bitmap(NativeMethods.sp_bitmap_load((nuint)width, (nuint)height, bytesPtr,
|
||||
(nuint)bytes.Length));
|
||||
return Load(width, height, bytesPtr, (nuint)bytes.Length);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Bitmap Clone()
|
||||
public bool this[nuint x, nuint y]
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
return new Bitmap(NativeMethods.sp_bitmap_clone(Instance));
|
||||
}
|
||||
get => Get(x, y);
|
||||
set => Set(x, y, value);
|
||||
}
|
||||
|
||||
public bool this[int x, int y]
|
||||
{
|
||||
get
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
return NativeMethods.sp_bitmap_get(Instance, (nuint)x, (nuint)y);
|
||||
}
|
||||
}
|
||||
set
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
NativeMethods.sp_bitmap_set(Instance, (nuint)x, (nuint)y, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Fill(bool value)
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
NativeMethods.sp_bitmap_fill(Instance, value);
|
||||
}
|
||||
}
|
||||
|
||||
public int Width
|
||||
{
|
||||
get
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
return (int)NativeMethods.sp_bitmap_width(Instance);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int Height
|
||||
{
|
||||
get
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
return (int)NativeMethods.sp_bitmap_height(Instance);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Span<byte> Data
|
||||
{
|
||||
get
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
var slice = NativeMethods.sp_bitmap_unsafe_data_ref(Instance);
|
||||
return new Span<byte>(slice.start, (int)slice.length);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private unsafe Bitmap(BindGen.Bitmap* instance) : base(instance)
|
||||
{
|
||||
}
|
||||
|
||||
private protected override unsafe void Free() => NativeMethods.sp_bitmap_free(Instance);
|
||||
public Span<byte> Data => UnsafeDataRef().AsSpan();
|
||||
}
|
||||
|
|
|
|||
349
crates/servicepoint_binding_cs/ServicePoint/Bitmap.g.cs
Normal file
349
crates/servicepoint_binding_cs/ServicePoint/Bitmap.g.cs
Normal file
|
|
@ -0,0 +1,349 @@
|
|||
// <auto-generated>
|
||||
// This code is generated by csbindgen.
|
||||
// DON'T CHANGE THIS DIRECTLY.
|
||||
// </auto-generated>
|
||||
#pragma warning disable CS8500
|
||||
#pragma warning disable CS8981
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
|
||||
namespace ServicePoint
|
||||
{
|
||||
|
||||
public unsafe sealed partial class Bitmap: IDisposable
|
||||
{
|
||||
#nullable enable
|
||||
/// <summary>
|
||||
/// Creates a new [SPBitmap] with the specified dimensions.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// - `width`: size in pixels in x-direction
|
||||
/// - `height`: size in pixels in y-direction
|
||||
///
|
||||
/// returns: [SPBitmap] initialized to all pixels off. Will never return NULL.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// - when the width is not dividable by 8
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The caller has to make sure that:
|
||||
///
|
||||
/// - the returned instance is freed in some way, either by using a consuming function or
|
||||
/// by explicitly calling `sp_bitmap_free`.
|
||||
/// </summary>
|
||||
public Bitmap(nuint width, nuint height) : this(sp_bitmap_new(width, height)) {}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new [SPBitmap] with a size matching the screen.
|
||||
///
|
||||
/// returns: [SPBitmap] initialized to all pixels off. Will never return NULL.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The caller has to make sure that:
|
||||
///
|
||||
/// - the returned instance is freed in some way, either by using a consuming function or
|
||||
/// by explicitly calling `sp_bitmap_free`.
|
||||
/// </summary>
|
||||
[System.Runtime.CompilerServices.MethodImplAttribute(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
|
||||
public static Bitmap NewScreenSized()
|
||||
{
|
||||
return new Bitmap(Bitmap.sp_bitmap_new_screen_sized());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Loads a [SPBitmap] with the specified dimensions from the provided data.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// - `width`: size in pixels in x-direction
|
||||
/// - `height`: size in pixels in y-direction
|
||||
///
|
||||
/// returns: [SPBitmap] that contains a copy of the provided data. Will never return NULL.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// - when `data` is NULL
|
||||
/// - when the dimensions and data size do not match exactly.
|
||||
/// - when the width is not dividable by 8
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The caller has to make sure that:
|
||||
///
|
||||
/// - `data` points to a valid memory location of at least `data_length` bytes in size.
|
||||
/// - the returned instance is freed in some way, either by using a consuming function or
|
||||
/// by explicitly calling `sp_bitmap_free`.
|
||||
/// </summary>
|
||||
[System.Runtime.CompilerServices.MethodImplAttribute(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
|
||||
public static Bitmap Load(nuint width, nuint height, byte* data, nuint data_length)
|
||||
{
|
||||
return new Bitmap(Bitmap.sp_bitmap_load(width, height, data, data_length));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clones a [SPBitmap].
|
||||
///
|
||||
/// Will never return NULL.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// - when `bitmap` is NULL
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The caller has to make sure that:
|
||||
///
|
||||
/// - `bitmap` points to a valid [SPBitmap]
|
||||
/// - `bitmap` is not written to concurrently
|
||||
/// - the returned instance is freed in some way, either by using a consuming function or
|
||||
/// by explicitly calling `sp_bitmap_free`.
|
||||
/// </summary>
|
||||
[System.Runtime.CompilerServices.MethodImplAttribute(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
|
||||
public Bitmap Clone()
|
||||
{
|
||||
return new Bitmap(Bitmap.sp_bitmap_clone(this.__Instance));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current value at the specified position in the [SPBitmap].
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// - `bitmap`: instance to read from
|
||||
/// - `x` and `y`: position of the cell to read
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// - when `bitmap` is NULL
|
||||
/// - when accessing `x` or `y` out of bounds
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The caller has to make sure that:
|
||||
///
|
||||
/// - `bitmap` points to a valid [SPBitmap]
|
||||
/// - `bitmap` is not written to concurrently
|
||||
/// </summary>
|
||||
[System.Runtime.CompilerServices.MethodImplAttribute(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
|
||||
public bool Get(nuint x, nuint y)
|
||||
{
|
||||
return Bitmap.sp_bitmap_get(this.__Instance, x, y);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the value of the specified position in the [SPBitmap].
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// - `bitmap`: instance to write to
|
||||
/// - `x` and `y`: position of the cell
|
||||
/// - `value`: the value to write to the cell
|
||||
///
|
||||
/// returns: old value of the cell
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// - when `bitmap` is NULL
|
||||
/// - when accessing `x` or `y` out of bounds
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The caller has to make sure that:
|
||||
///
|
||||
/// - `bitmap` points to a valid [SPBitmap]
|
||||
/// - `bitmap` is not written to or read from concurrently
|
||||
/// </summary>
|
||||
[System.Runtime.CompilerServices.MethodImplAttribute(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
|
||||
public void Set(nuint x, nuint y, bool value)
|
||||
{
|
||||
Bitmap.sp_bitmap_set(this.__Instance, x, y, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the state of all pixels in the [SPBitmap].
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// - `bitmap`: instance to write to
|
||||
/// - `value`: the value to set all pixels to
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// - when `bitmap` is NULL
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The caller has to make sure that:
|
||||
///
|
||||
/// - `bitmap` points to a valid [SPBitmap]
|
||||
/// - `bitmap` is not written to or read from concurrently
|
||||
/// </summary>
|
||||
[System.Runtime.CompilerServices.MethodImplAttribute(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
|
||||
public void Fill(bool value)
|
||||
{
|
||||
Bitmap.sp_bitmap_fill(this.__Instance, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the width in pixels of the [SPBitmap] instance.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// - `bitmap`: instance to read from
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// - when `bitmap` is NULL
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The caller has to make sure that:
|
||||
///
|
||||
/// - `bitmap` points to a valid [SPBitmap]
|
||||
/// </summary>
|
||||
[System.Runtime.CompilerServices.MethodImplAttribute(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
|
||||
public nuint Width()
|
||||
{
|
||||
return Bitmap.sp_bitmap_width(this.__Instance);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the height in pixels of the [SPBitmap] instance.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// - `bitmap`: instance to read from
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// - when `bitmap` is NULL
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The caller has to make sure that:
|
||||
///
|
||||
/// - `bitmap` points to a valid [SPBitmap]
|
||||
/// </summary>
|
||||
[System.Runtime.CompilerServices.MethodImplAttribute(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
|
||||
public nuint Height()
|
||||
{
|
||||
return Bitmap.sp_bitmap_height(this.__Instance);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets an unsafe reference to the data of the [SPBitmap] instance.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// - when `bitmap` is NULL
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The caller has to make sure that:
|
||||
///
|
||||
/// - `bitmap` points to a valid [SPBitmap]
|
||||
/// - the returned memory range is never accessed after the passed [SPBitmap] has been freed
|
||||
/// - the returned memory range is never accessed concurrently, either via the [SPBitmap] or directly
|
||||
/// </summary>
|
||||
[System.Runtime.CompilerServices.MethodImplAttribute(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
|
||||
public SPByteSlice UnsafeDataRef()
|
||||
{
|
||||
return Bitmap.sp_bitmap_unsafe_data_ref(this.__Instance);
|
||||
}
|
||||
|
||||
|
||||
#region internal machinery
|
||||
private SPBitmap* _instance;
|
||||
internal SPBitmap* __Instance
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_instance == null)
|
||||
throw new NullReferenceException("instance is null");
|
||||
return _instance;
|
||||
}
|
||||
}
|
||||
|
||||
private Bitmap(SPBitmap* instance)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(instance);
|
||||
_instance = instance;
|
||||
}
|
||||
|
||||
internal SPBitmap* __Into()
|
||||
{
|
||||
var instance = __Instance;
|
||||
_instance = null;
|
||||
return instance;
|
||||
}
|
||||
|
||||
private void __Free()
|
||||
{
|
||||
if (_instance != null)
|
||||
Bitmap.sp_bitmap_free(__Into());
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
__Free();
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
~Bitmap() => __Free();
|
||||
|
||||
#endregion
|
||||
|
||||
#nullable restore
|
||||
#region native methods
|
||||
const string __DllName = "servicepoint_binding_c";
|
||||
[DllImport(__DllName, EntryPoint = "sp_bitmap_new", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
private static extern SPBitmap* sp_bitmap_new(nuint width, nuint height);
|
||||
|
||||
[DllImport(__DllName, EntryPoint = "sp_bitmap_new_screen_sized", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
private static extern SPBitmap* sp_bitmap_new_screen_sized();
|
||||
|
||||
[DllImport(__DllName, EntryPoint = "sp_bitmap_load", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
private static extern SPBitmap* sp_bitmap_load(nuint width, nuint height, byte* data, nuint data_length);
|
||||
|
||||
[DllImport(__DllName, EntryPoint = "sp_bitmap_clone", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
private static extern SPBitmap* sp_bitmap_clone(SPBitmap* bitmap);
|
||||
|
||||
[DllImport(__DllName, EntryPoint = "sp_bitmap_free", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
private static extern void sp_bitmap_free(SPBitmap* bitmap);
|
||||
|
||||
[DllImport(__DllName, EntryPoint = "sp_bitmap_get", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
[return: MarshalAs(UnmanagedType.U1)]
|
||||
private static extern bool sp_bitmap_get(SPBitmap* bitmap, nuint x, nuint y);
|
||||
|
||||
[DllImport(__DllName, EntryPoint = "sp_bitmap_set", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
private static extern void sp_bitmap_set(SPBitmap* bitmap, nuint x, nuint y, [MarshalAs(UnmanagedType.U1)] bool value);
|
||||
|
||||
[DllImport(__DllName, EntryPoint = "sp_bitmap_fill", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
private static extern void sp_bitmap_fill(SPBitmap* bitmap, [MarshalAs(UnmanagedType.U1)] bool value);
|
||||
|
||||
[DllImport(__DllName, EntryPoint = "sp_bitmap_width", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
private static extern nuint sp_bitmap_width(SPBitmap* bitmap);
|
||||
|
||||
[DllImport(__DllName, EntryPoint = "sp_bitmap_height", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
private static extern nuint sp_bitmap_height(SPBitmap* bitmap);
|
||||
|
||||
[DllImport(__DllName, EntryPoint = "sp_bitmap_unsafe_data_ref", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
private static extern SPByteSlice sp_bitmap_unsafe_data_ref(SPBitmap* bitmap);
|
||||
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public unsafe partial struct SPBitmap
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -1,100 +1,23 @@
|
|||
using ServicePoint.BindGen;
|
||||
|
||||
namespace ServicePoint;
|
||||
|
||||
public sealed class BrightnessGrid : SpNativeInstance<BindGen.BrightnessGrid>
|
||||
public sealed partial class BrightnessGrid
|
||||
{
|
||||
public static BrightnessGrid New(int width, int height)
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
return new BrightnessGrid(NativeMethods.sp_brightness_grid_new((nuint)width, (nuint)height));
|
||||
}
|
||||
}
|
||||
|
||||
public static BrightnessGrid Load(int width, int height, Span<byte> bytes)
|
||||
public static BrightnessGrid Load(nuint width, nuint height, ReadOnlySpan<byte> bytes)
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
fixed (byte* bytesPtr = bytes)
|
||||
{
|
||||
return new BrightnessGrid(NativeMethods.sp_brightness_grid_load((nuint)width, (nuint)height, bytesPtr,
|
||||
(nuint)bytes.Length));
|
||||
return Load(width, height, bytesPtr, (nuint)bytes.Length);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public BrightnessGrid Clone()
|
||||
public byte this[nuint x, nuint y]
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
return new BrightnessGrid(NativeMethods.sp_brightness_grid_clone(Instance));
|
||||
}
|
||||
get => Get(x, y);
|
||||
set => Set(x, y, value);
|
||||
}
|
||||
|
||||
public byte this[int x, int y]
|
||||
{
|
||||
get
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
return NativeMethods.sp_brightness_grid_get(Instance, (nuint)x, (nuint)y);
|
||||
}
|
||||
}
|
||||
set
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
NativeMethods.sp_brightness_grid_set(Instance, (nuint)x, (nuint)y, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Fill(byte value)
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
NativeMethods.sp_brightness_grid_fill(Instance, value);
|
||||
}
|
||||
}
|
||||
|
||||
public int Width
|
||||
{
|
||||
get
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
return (int)NativeMethods.sp_brightness_grid_width(Instance);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int Height
|
||||
{
|
||||
get
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
return (int)NativeMethods.sp_brightness_grid_height(Instance);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Span<byte> Data
|
||||
{
|
||||
get
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
var slice = NativeMethods.sp_brightness_grid_unsafe_data_ref(Instance);
|
||||
return new Span<byte>(slice.start, (int)slice.length);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private unsafe BrightnessGrid(BindGen.BrightnessGrid* instance) : base(instance)
|
||||
{
|
||||
}
|
||||
|
||||
private protected override unsafe void Free() => NativeMethods.sp_brightness_grid_free(Instance);
|
||||
public Span<byte> Data => UnsafeDataRef().AsSpan();
|
||||
}
|
||||
|
|
|
|||
331
crates/servicepoint_binding_cs/ServicePoint/BrightnessGrid.g.cs
Normal file
331
crates/servicepoint_binding_cs/ServicePoint/BrightnessGrid.g.cs
Normal file
|
|
@ -0,0 +1,331 @@
|
|||
// <auto-generated>
|
||||
// This code is generated by csbindgen.
|
||||
// DON'T CHANGE THIS DIRECTLY.
|
||||
// </auto-generated>
|
||||
#pragma warning disable CS8500
|
||||
#pragma warning disable CS8981
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
|
||||
namespace ServicePoint
|
||||
{
|
||||
|
||||
public unsafe sealed partial class BrightnessGrid: IDisposable
|
||||
{
|
||||
#nullable enable
|
||||
/// <summary>
|
||||
/// Creates a new [SPBrightnessGrid] with the specified dimensions.
|
||||
///
|
||||
/// returns: [SPBrightnessGrid] initialized to 0. Will never return NULL.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The caller has to make sure that:
|
||||
///
|
||||
/// - the returned instance is freed in some way, either by using a consuming function or
|
||||
/// by explicitly calling `sp_brightness_grid_free`.
|
||||
/// </summary>
|
||||
public BrightnessGrid(nuint width, nuint height) : this(sp_brightness_grid_new(width, height)) {}
|
||||
|
||||
/// <summary>
|
||||
/// Loads a [SPBrightnessGrid] with the specified dimensions from the provided data.
|
||||
///
|
||||
/// returns: new [SPBrightnessGrid] instance. Will never return NULL.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// - when `data` is NULL
|
||||
/// - when the provided `data_length` does not match `height` and `width`
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The caller has to make sure that:
|
||||
///
|
||||
/// - `data` points to a valid memory location of at least `data_length`
|
||||
/// bytes in size.
|
||||
/// - the returned instance is freed in some way, either by using a consuming function or
|
||||
/// by explicitly calling `sp_brightness_grid_free`.
|
||||
/// </summary>
|
||||
[System.Runtime.CompilerServices.MethodImplAttribute(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
|
||||
public static BrightnessGrid Load(nuint width, nuint height, byte* data, nuint data_length)
|
||||
{
|
||||
return new BrightnessGrid(BrightnessGrid.sp_brightness_grid_load(width, height, data, data_length));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clones a [SPBrightnessGrid].
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// - `brightness_grid`: instance to read from
|
||||
///
|
||||
/// returns: new [SPBrightnessGrid] instance. Will never return NULL.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// - when `brightness_grid` is NULL
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The caller has to make sure that:
|
||||
///
|
||||
/// - `brightness_grid` points to a valid [SPBrightnessGrid]
|
||||
/// - `brightness_grid` is not written to concurrently
|
||||
/// - the returned instance is freed in some way, either by using a consuming function or
|
||||
/// by explicitly calling `sp_brightness_grid_free`.
|
||||
/// </summary>
|
||||
[System.Runtime.CompilerServices.MethodImplAttribute(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
|
||||
public BrightnessGrid Clone()
|
||||
{
|
||||
return new BrightnessGrid(BrightnessGrid.sp_brightness_grid_clone(this.__Instance));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current value at the specified position.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// - `brightness_grid`: instance to read from
|
||||
/// - `x` and `y`: position of the cell to read
|
||||
///
|
||||
/// returns: value at position
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// - when `brightness_grid` is NULL
|
||||
/// - When accessing `x` or `y` out of bounds.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The caller has to make sure that:
|
||||
///
|
||||
/// - `brightness_grid` points to a valid [SPBrightnessGrid]
|
||||
/// - `brightness_grid` is not written to concurrently
|
||||
/// </summary>
|
||||
[System.Runtime.CompilerServices.MethodImplAttribute(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
|
||||
public byte Get(nuint x, nuint y)
|
||||
{
|
||||
return BrightnessGrid.sp_brightness_grid_get(this.__Instance, x, y);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the value of the specified position in the [SPBrightnessGrid].
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// - `brightness_grid`: instance to write to
|
||||
/// - `x` and `y`: position of the cell
|
||||
/// - `value`: the value to write to the cell
|
||||
///
|
||||
/// returns: old value of the cell
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// - when `brightness_grid` is NULL
|
||||
/// - When accessing `x` or `y` out of bounds.
|
||||
/// - When providing an invalid brightness value
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The caller has to make sure that:
|
||||
///
|
||||
/// - `brightness_grid` points to a valid [SPBitVec]
|
||||
/// - `brightness_grid` is not written to or read from concurrently
|
||||
/// </summary>
|
||||
[System.Runtime.CompilerServices.MethodImplAttribute(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
|
||||
public void Set(nuint x, nuint y, byte value)
|
||||
{
|
||||
BrightnessGrid.sp_brightness_grid_set(this.__Instance, x, y, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the value of all cells in the [SPBrightnessGrid].
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// - `brightness_grid`: instance to write to
|
||||
/// - `value`: the value to set all cells to
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// - when `brightness_grid` is NULL
|
||||
/// - When providing an invalid brightness value
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The caller has to make sure that:
|
||||
///
|
||||
/// - `brightness_grid` points to a valid [SPBrightnessGrid]
|
||||
/// - `brightness_grid` is not written to or read from concurrently
|
||||
/// </summary>
|
||||
[System.Runtime.CompilerServices.MethodImplAttribute(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
|
||||
public void Fill(byte value)
|
||||
{
|
||||
BrightnessGrid.sp_brightness_grid_fill(this.__Instance, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the width of the [SPBrightnessGrid] instance.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// - `brightness_grid`: instance to read from
|
||||
///
|
||||
/// returns: width
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// - when `brightness_grid` is NULL
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The caller has to make sure that:
|
||||
///
|
||||
/// - `brightness_grid` points to a valid [SPBrightnessGrid]
|
||||
/// </summary>
|
||||
[System.Runtime.CompilerServices.MethodImplAttribute(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
|
||||
public nuint Width()
|
||||
{
|
||||
return BrightnessGrid.sp_brightness_grid_width(this.__Instance);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the height of the [SPBrightnessGrid] instance.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// - `brightness_grid`: instance to read from
|
||||
///
|
||||
/// returns: height
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// - when `brightness_grid` is NULL
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The caller has to make sure that:
|
||||
///
|
||||
/// - `brightness_grid` points to a valid [SPBrightnessGrid]
|
||||
/// </summary>
|
||||
[System.Runtime.CompilerServices.MethodImplAttribute(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
|
||||
public nuint Height()
|
||||
{
|
||||
return BrightnessGrid.sp_brightness_grid_height(this.__Instance);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets an unsafe reference to the data of the [SPBrightnessGrid] instance.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// - `brightness_grid`: instance to read from
|
||||
///
|
||||
/// returns: slice of bytes underlying the `brightness_grid`.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// - when `brightness_grid` is NULL
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The caller has to make sure that:
|
||||
///
|
||||
/// - `brightness_grid` points to a valid [SPBrightnessGrid]
|
||||
/// - the returned memory range is never accessed after the passed [SPBrightnessGrid] has been freed
|
||||
/// - the returned memory range is never accessed concurrently, either via the [SPBrightnessGrid] or directly
|
||||
/// </summary>
|
||||
[System.Runtime.CompilerServices.MethodImplAttribute(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
|
||||
public SPByteSlice UnsafeDataRef()
|
||||
{
|
||||
return BrightnessGrid.sp_brightness_grid_unsafe_data_ref(this.__Instance);
|
||||
}
|
||||
|
||||
|
||||
#region internal machinery
|
||||
private SPBrightnessGrid* _instance;
|
||||
internal SPBrightnessGrid* __Instance
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_instance == null)
|
||||
throw new NullReferenceException("instance is null");
|
||||
return _instance;
|
||||
}
|
||||
}
|
||||
|
||||
private BrightnessGrid(SPBrightnessGrid* instance)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(instance);
|
||||
_instance = instance;
|
||||
}
|
||||
|
||||
internal SPBrightnessGrid* __Into()
|
||||
{
|
||||
var instance = __Instance;
|
||||
_instance = null;
|
||||
return instance;
|
||||
}
|
||||
|
||||
private void __Free()
|
||||
{
|
||||
if (_instance != null)
|
||||
BrightnessGrid.sp_brightness_grid_free(__Into());
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
__Free();
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
~BrightnessGrid() => __Free();
|
||||
|
||||
#endregion
|
||||
|
||||
#nullable restore
|
||||
#region native methods
|
||||
const string __DllName = "servicepoint_binding_c";
|
||||
[DllImport(__DllName, EntryPoint = "sp_brightness_grid_new", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
private static extern SPBrightnessGrid* sp_brightness_grid_new(nuint width, nuint height);
|
||||
|
||||
[DllImport(__DllName, EntryPoint = "sp_brightness_grid_load", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
private static extern SPBrightnessGrid* sp_brightness_grid_load(nuint width, nuint height, byte* data, nuint data_length);
|
||||
|
||||
[DllImport(__DllName, EntryPoint = "sp_brightness_grid_clone", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
private static extern SPBrightnessGrid* sp_brightness_grid_clone(SPBrightnessGrid* brightness_grid);
|
||||
|
||||
[DllImport(__DllName, EntryPoint = "sp_brightness_grid_free", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
private static extern void sp_brightness_grid_free(SPBrightnessGrid* brightness_grid);
|
||||
|
||||
[DllImport(__DllName, EntryPoint = "sp_brightness_grid_get", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
private static extern byte sp_brightness_grid_get(SPBrightnessGrid* brightness_grid, nuint x, nuint y);
|
||||
|
||||
[DllImport(__DllName, EntryPoint = "sp_brightness_grid_set", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
private static extern void sp_brightness_grid_set(SPBrightnessGrid* brightness_grid, nuint x, nuint y, byte value);
|
||||
|
||||
[DllImport(__DllName, EntryPoint = "sp_brightness_grid_fill", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
private static extern void sp_brightness_grid_fill(SPBrightnessGrid* brightness_grid, byte value);
|
||||
|
||||
[DllImport(__DllName, EntryPoint = "sp_brightness_grid_width", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
private static extern nuint sp_brightness_grid_width(SPBrightnessGrid* brightness_grid);
|
||||
|
||||
[DllImport(__DllName, EntryPoint = "sp_brightness_grid_height", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
private static extern nuint sp_brightness_grid_height(SPBrightnessGrid* brightness_grid);
|
||||
|
||||
[DllImport(__DllName, EntryPoint = "sp_brightness_grid_unsafe_data_ref", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
private static extern SPByteSlice sp_brightness_grid_unsafe_data_ref(SPBrightnessGrid* brightness_grid);
|
||||
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public unsafe partial struct SPBrightnessGrid
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
6
crates/servicepoint_binding_cs/ServicePoint/ByteSlice.cs
Normal file
6
crates/servicepoint_binding_cs/ServicePoint/ByteSlice.cs
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
namespace ServicePoint;
|
||||
|
||||
public partial struct SPByteSlice
|
||||
{
|
||||
public unsafe Span<byte> AsSpan() => new (start, (int)length);
|
||||
}
|
||||
24
crates/servicepoint_binding_cs/ServicePoint/ByteSlice.g.cs
Normal file
24
crates/servicepoint_binding_cs/ServicePoint/ByteSlice.g.cs
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
// <auto-generated>
|
||||
// This code is generated by csbindgen.
|
||||
// DON'T CHANGE THIS DIRECTLY.
|
||||
// </auto-generated>
|
||||
#pragma warning disable CS8500
|
||||
#pragma warning disable CS8981
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
|
||||
namespace ServicePoint
|
||||
{
|
||||
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public unsafe partial struct SPByteSlice
|
||||
{
|
||||
public byte* start;
|
||||
public nuint length;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -1,129 +1,16 @@
|
|||
using System.Diagnostics.CodeAnalysis;
|
||||
using ServicePoint.BindGen;
|
||||
|
||||
namespace ServicePoint;
|
||||
|
||||
public sealed class Command : SpNativeInstance<BindGen.Command>
|
||||
public sealed partial class Command
|
||||
{
|
||||
public static bool TryFromPacket(Packet packet, [MaybeNullWhen(false)] out Command command)
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
var result = NativeMethods.sp_command_try_from_packet(packet.Into());
|
||||
if (result == null)
|
||||
{
|
||||
command = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
command = new Command(result);
|
||||
return true;
|
||||
}
|
||||
return (command = TryFromPacket(packet)) != null;
|
||||
}
|
||||
|
||||
public Command Clone()
|
||||
public Packet IntoPacket()
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
return new Command(NativeMethods.sp_command_clone(Instance));
|
||||
}
|
||||
return Packet.FromCommand(this);
|
||||
}
|
||||
|
||||
public static Command Clear()
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
return new Command(NativeMethods.sp_command_clear());
|
||||
}
|
||||
}
|
||||
|
||||
public static Command HardReset()
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
return new Command(NativeMethods.sp_command_hard_reset());
|
||||
}
|
||||
}
|
||||
|
||||
public static Command FadeOut()
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
return new Command(NativeMethods.sp_command_fade_out());
|
||||
}
|
||||
}
|
||||
|
||||
public static Command Brightness(byte brightness)
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
return new Command(NativeMethods.sp_command_brightness(brightness));
|
||||
}
|
||||
}
|
||||
|
||||
public static Command CharBrightness(int x, int y, BrightnessGrid grid)
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
return new Command(NativeMethods.sp_command_char_brightness((ushort)x, (ushort)y, grid.Into()));
|
||||
}
|
||||
}
|
||||
|
||||
public static Command BitmapLinear(int offset, BitVec bitVec, CompressionCode compressionCode)
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
return new Command(
|
||||
NativeMethods.sp_command_bitmap_linear((ushort)offset, bitVec.Into(), compressionCode));
|
||||
}
|
||||
}
|
||||
|
||||
public static Command BitmapLinearAnd(int offset, BitVec bitVec, CompressionCode compressionCode)
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
return new Command(
|
||||
NativeMethods.sp_command_bitmap_linear_and((ushort)offset, bitVec.Into(), compressionCode));
|
||||
}
|
||||
}
|
||||
|
||||
public static Command BitmapLinearOr(int offset, BitVec bitVec, CompressionCode compressionCode)
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
return new Command(
|
||||
NativeMethods.sp_command_bitmap_linear_or((ushort)offset, bitVec.Into(), compressionCode));
|
||||
}
|
||||
}
|
||||
|
||||
public static Command BitmapLinearXor(int offset, BitVec bitVec, CompressionCode compressionCode)
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
return new Command(
|
||||
NativeMethods.sp_command_bitmap_linear_xor((ushort)offset, bitVec.Into(), compressionCode));
|
||||
}
|
||||
}
|
||||
|
||||
public static Command BitmapLinearWin(int x, int y, Bitmap bitmap, CompressionCode compression)
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
return new Command(NativeMethods.sp_command_bitmap_linear_win((ushort)x, (ushort)y, bitmap.Into(), compression));
|
||||
}
|
||||
}
|
||||
|
||||
public static Command Cp437Data(int x, int y, Cp437Grid byteGrid)
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
return new Command(NativeMethods.sp_command_cp437_data((ushort)x, (ushort)y, byteGrid.Into()));
|
||||
}
|
||||
}
|
||||
|
||||
private unsafe Command(BindGen.Command* instance) : base(instance)
|
||||
{
|
||||
}
|
||||
|
||||
private protected override unsafe void Free() => NativeMethods.sp_command_free(Instance);
|
||||
}
|
||||
|
|
|
|||
481
crates/servicepoint_binding_cs/ServicePoint/Command.g.cs
Normal file
481
crates/servicepoint_binding_cs/ServicePoint/Command.g.cs
Normal file
|
|
@ -0,0 +1,481 @@
|
|||
// <auto-generated>
|
||||
// This code is generated by csbindgen.
|
||||
// DON'T CHANGE THIS DIRECTLY.
|
||||
// </auto-generated>
|
||||
#pragma warning disable CS8500
|
||||
#pragma warning disable CS8981
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
|
||||
namespace ServicePoint
|
||||
{
|
||||
|
||||
public unsafe sealed partial class Command: IDisposable
|
||||
{
|
||||
#nullable enable
|
||||
/// <summary>
|
||||
/// Tries to turn a [SPPacket] into a [SPCommand].
|
||||
///
|
||||
/// The packet is deallocated in the process.
|
||||
///
|
||||
/// Returns: pointer to new [SPCommand] instance or NULL if parsing failed.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// - when `packet` is NULL
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The caller has to make sure that:
|
||||
///
|
||||
/// - [SPPacket] points to a valid instance of [SPPacket]
|
||||
/// - [SPPacket] is not used concurrently or after this call
|
||||
/// - the result is checked for NULL
|
||||
/// - the returned [SPCommand] instance is freed in some way, either by using a consuming function or
|
||||
/// by explicitly calling `sp_command_free`.
|
||||
///
|
||||
/// servicepoint_csbindgen_consumes: packet
|
||||
/// </summary>
|
||||
[System.Runtime.CompilerServices.MethodImplAttribute(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
|
||||
public static Command? TryFromPacket(Packet packet)
|
||||
{
|
||||
var native = Command.sp_command_try_from_packet(packet.__Into());
|
||||
return native == null ? null : new Command(native);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clones a [SPCommand] instance.
|
||||
///
|
||||
/// returns: new [SPCommand] instance. Will never return NULL.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// - when `command` is NULL
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The caller has to make sure that:
|
||||
///
|
||||
/// - `command` points to a valid instance of [SPCommand]
|
||||
/// - `command` is not written to concurrently
|
||||
/// - the returned [SPCommand] instance is freed in some way, either by using a consuming function or
|
||||
/// by explicitly calling `sp_command_free`.
|
||||
/// </summary>
|
||||
[System.Runtime.CompilerServices.MethodImplAttribute(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
|
||||
public Command Clone()
|
||||
{
|
||||
return new Command(Command.sp_command_clone(this.__Instance));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set all pixels to the off state.
|
||||
///
|
||||
/// Does not affect brightness.
|
||||
///
|
||||
/// Returns: a new [Command::Clear] instance. Will never return NULL.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```C
|
||||
/// sp_connection_send_command(connection, sp_command_clear());
|
||||
/// ```
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The caller has to make sure that:
|
||||
///
|
||||
/// - the returned [SPCommand] instance is freed in some way, either by using a consuming function or
|
||||
/// by explicitly calling `sp_command_free`.
|
||||
/// </summary>
|
||||
[System.Runtime.CompilerServices.MethodImplAttribute(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
|
||||
public static Command Clear()
|
||||
{
|
||||
return new Command(Command.sp_command_clear());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 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 [Command::HardReset] instance. Will never return NULL.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The caller has to make sure that:
|
||||
///
|
||||
/// - the returned [SPCommand] instance is freed in some way, either by using a consuming function or
|
||||
/// by explicitly calling `sp_command_free`.
|
||||
/// </summary>
|
||||
[System.Runtime.CompilerServices.MethodImplAttribute(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
|
||||
public static Command HardReset()
|
||||
{
|
||||
return new Command(Command.sp_command_hard_reset());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A yet-to-be-tested command.
|
||||
///
|
||||
/// Returns: a new `Command::FadeOut` instance. Will never return NULL.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The caller has to make sure that:
|
||||
///
|
||||
/// - the returned [SPCommand] instance is freed in some way, either by using a consuming function or
|
||||
/// by explicitly calling `sp_command_free`.
|
||||
/// </summary>
|
||||
[System.Runtime.CompilerServices.MethodImplAttribute(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
|
||||
public static Command FadeOut()
|
||||
{
|
||||
return new Command(Command.sp_command_fade_out());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the brightness of all tiles to the same value.
|
||||
///
|
||||
/// Returns: a new [Command::Brightness] instance. Will never return NULL.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// - When the provided brightness value is out of range (0-11).
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The caller has to make sure that:
|
||||
///
|
||||
/// - the returned [SPCommand] instance is freed in some way, either by using a consuming function or
|
||||
/// by explicitly calling `sp_command_free`.
|
||||
/// </summary>
|
||||
[System.Runtime.CompilerServices.MethodImplAttribute(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
|
||||
public static Command Brightness(byte brightness)
|
||||
{
|
||||
return new Command(Command.sp_command_brightness(brightness));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the brightness of individual tiles in a rectangular area of the display.
|
||||
///
|
||||
/// The passed [SPBrightnessGrid] gets consumed.
|
||||
///
|
||||
/// Returns: a new [Command::CharBrightness] instance. Will never return NULL.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// - when `grid` is NULL
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The caller has to make sure that:
|
||||
///
|
||||
/// - `grid` points to a valid instance of [SPBrightnessGrid]
|
||||
/// - `grid` is not used concurrently or after this call
|
||||
/// - the returned [SPCommand] instance is freed in some way, either by using a consuming function or
|
||||
/// by explicitly calling `sp_command_free`.
|
||||
///
|
||||
/// servicepoint_csbindgen_consumes: grid
|
||||
/// </summary>
|
||||
[System.Runtime.CompilerServices.MethodImplAttribute(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
|
||||
public static Command CharBrightness(nuint x, nuint y, BrightnessGrid grid)
|
||||
{
|
||||
return new Command(Command.sp_command_char_brightness(x, y, grid.__Into()));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 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 contained [SPBitVec] is always uncompressed.
|
||||
///
|
||||
/// The passed [SPBitVec] gets consumed.
|
||||
///
|
||||
/// Returns: a new [Command::BitmapLinear] instance. Will never return NULL.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// - when `bit_vec` is null
|
||||
/// - when `compression_code` is not a valid value
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The caller has to make sure that:
|
||||
///
|
||||
/// - `bit_vec` points to a valid instance of [SPBitVec]
|
||||
/// - `bit_vec` is not used concurrently or after this call
|
||||
/// - `compression` matches one of the allowed enum values
|
||||
/// - the returned [SPCommand] instance is freed in some way, either by using a consuming function or
|
||||
/// by explicitly calling `sp_command_free`.
|
||||
///
|
||||
/// servicepoint_csbindgen_consumes: bit_vec
|
||||
/// </summary>
|
||||
[System.Runtime.CompilerServices.MethodImplAttribute(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
|
||||
public static Command BitmapLinear(nuint offset, BitVec bit_vec, CompressionCode compression)
|
||||
{
|
||||
return new Command(Command.sp_command_bitmap_linear(offset, bit_vec.__Into(), compression));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set pixel data according to an and-mask starting at the offset.
|
||||
///
|
||||
/// 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 contained [SPBitVec] is always uncompressed.
|
||||
///
|
||||
/// The passed [SPBitVec] gets consumed.
|
||||
///
|
||||
/// Returns: a new [Command::BitmapLinearAnd] instance. Will never return NULL.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// - when `bit_vec` is null
|
||||
/// - when `compression_code` is not a valid value
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The caller has to make sure that:
|
||||
///
|
||||
/// - `bit_vec` points to a valid instance of [SPBitVec]
|
||||
/// - `bit_vec` is not used concurrently or after this call
|
||||
/// - `compression` matches one of the allowed enum values
|
||||
/// - the returned [SPCommand] instance is freed in some way, either by using a consuming function or
|
||||
/// by explicitly calling `sp_command_free`.
|
||||
///
|
||||
/// servicepoint_csbindgen_consumes: bit_vec
|
||||
/// </summary>
|
||||
[System.Runtime.CompilerServices.MethodImplAttribute(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
|
||||
public static Command BitmapLinearAnd(nuint offset, BitVec bit_vec, CompressionCode compression)
|
||||
{
|
||||
return new Command(Command.sp_command_bitmap_linear_and(offset, bit_vec.__Into(), compression));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set pixel data according to an or-mask starting at the offset.
|
||||
///
|
||||
/// 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 contained [SPBitVec] is always uncompressed.
|
||||
///
|
||||
/// The passed [SPBitVec] gets consumed.
|
||||
///
|
||||
/// Returns: a new [Command::BitmapLinearOr] instance. Will never return NULL.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// - when `bit_vec` is null
|
||||
/// - when `compression_code` is not a valid value
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The caller has to make sure that:
|
||||
///
|
||||
/// - `bit_vec` points to a valid instance of [SPBitVec]
|
||||
/// - `bit_vec` is not used concurrently or after this call
|
||||
/// - `compression` matches one of the allowed enum values
|
||||
/// - the returned [SPCommand] instance is freed in some way, either by using a consuming function or
|
||||
/// by explicitly calling `sp_command_free`.
|
||||
///
|
||||
/// servicepoint_csbindgen_consumes: bit_vec
|
||||
/// </summary>
|
||||
[System.Runtime.CompilerServices.MethodImplAttribute(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
|
||||
public static Command BitmapLinearOr(nuint offset, BitVec bit_vec, CompressionCode compression)
|
||||
{
|
||||
return new Command(Command.sp_command_bitmap_linear_or(offset, bit_vec.__Into(), compression));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set pixel data according to a xor-mask starting at the offset.
|
||||
///
|
||||
/// 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 contained [SPBitVec] is always uncompressed.
|
||||
///
|
||||
/// The passed [SPBitVec] gets consumed.
|
||||
///
|
||||
/// Returns: a new [Command::BitmapLinearXor] instance. Will never return NULL.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// - when `bit_vec` is null
|
||||
/// - when `compression_code` is not a valid value
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The caller has to make sure that:
|
||||
///
|
||||
/// - `bit_vec` points to a valid instance of [SPBitVec]
|
||||
/// - `bit_vec` is not used concurrently or after this call
|
||||
/// - `compression` matches one of the allowed enum values
|
||||
/// - the returned [SPCommand] instance is freed in some way, either by using a consuming function or
|
||||
/// by explicitly calling `sp_command_free`.
|
||||
///
|
||||
/// servicepoint_csbindgen_consumes: bit_vec
|
||||
/// </summary>
|
||||
[System.Runtime.CompilerServices.MethodImplAttribute(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
|
||||
public static Command BitmapLinearXor(nuint offset, BitVec bit_vec, CompressionCode compression)
|
||||
{
|
||||
return new Command(Command.sp_command_bitmap_linear_xor(offset, bit_vec.__Into(), compression));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Show text on the screen.
|
||||
///
|
||||
/// The passed [SPCp437Grid] gets consumed.
|
||||
///
|
||||
/// Returns: a new [Command::Cp437Data] instance. Will never return NULL.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// - when `grid` is null
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The caller has to make sure that:
|
||||
///
|
||||
/// - `grid` points to a valid instance of [SPCp437Grid]
|
||||
/// - `grid` is not used concurrently or after this call
|
||||
/// - the returned [SPCommand] instance is freed in some way, either by using a consuming function or
|
||||
/// by explicitly calling `sp_command_free`.
|
||||
///
|
||||
/// servicepoint_csbindgen_consumes: grid
|
||||
/// </summary>
|
||||
[System.Runtime.CompilerServices.MethodImplAttribute(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
|
||||
public static Command Cp437Data(nuint x, nuint y, Cp437Grid grid)
|
||||
{
|
||||
return new Command(Command.sp_command_cp437_data(x, y, grid.__Into()));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets a window of pixels to the specified values.
|
||||
///
|
||||
/// The passed [SPBitmap] gets consumed.
|
||||
///
|
||||
/// Returns: a new [Command::BitmapLinearWin] instance. Will never return NULL.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// - when `bitmap` is null
|
||||
/// - when `compression_code` is not a valid value
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The caller has to make sure that:
|
||||
///
|
||||
/// - `bitmap` points to a valid instance of [SPBitmap]
|
||||
/// - `bitmap` is not used concurrently or after this call
|
||||
/// - `compression` matches one of the allowed enum values
|
||||
/// - the returned [SPCommand] instance is freed in some way, either by using a consuming function or
|
||||
/// by explicitly calling `sp_command_free`.
|
||||
///
|
||||
/// servicepoint_csbindgen_consumes: bitmap
|
||||
/// </summary>
|
||||
[System.Runtime.CompilerServices.MethodImplAttribute(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
|
||||
public static Command BitmapLinearWin(nuint x, nuint y, Bitmap bitmap, CompressionCode compression_code)
|
||||
{
|
||||
return new Command(Command.sp_command_bitmap_linear_win(x, y, bitmap.__Into(), compression_code));
|
||||
}
|
||||
|
||||
|
||||
#region internal machinery
|
||||
private SPCommand* _instance;
|
||||
internal SPCommand* __Instance
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_instance == null)
|
||||
throw new NullReferenceException("instance is null");
|
||||
return _instance;
|
||||
}
|
||||
}
|
||||
|
||||
private Command(SPCommand* instance)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(instance);
|
||||
_instance = instance;
|
||||
}
|
||||
|
||||
internal SPCommand* __Into()
|
||||
{
|
||||
var instance = __Instance;
|
||||
_instance = null;
|
||||
return instance;
|
||||
}
|
||||
|
||||
private void __Free()
|
||||
{
|
||||
if (_instance != null)
|
||||
Command.sp_command_free(__Into());
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
__Free();
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
~Command() => __Free();
|
||||
|
||||
#endregion
|
||||
|
||||
#nullable restore
|
||||
#region native methods
|
||||
const string __DllName = "servicepoint_binding_c";
|
||||
[DllImport(__DllName, EntryPoint = "sp_command_try_from_packet", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
private static extern SPCommand* sp_command_try_from_packet(SPPacket* packet);
|
||||
|
||||
[DllImport(__DllName, EntryPoint = "sp_command_clone", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
private static extern SPCommand* sp_command_clone(SPCommand* command);
|
||||
|
||||
[DllImport(__DllName, EntryPoint = "sp_command_clear", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
private static extern SPCommand* sp_command_clear();
|
||||
|
||||
[DllImport(__DllName, EntryPoint = "sp_command_hard_reset", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
private static extern SPCommand* sp_command_hard_reset();
|
||||
|
||||
[DllImport(__DllName, EntryPoint = "sp_command_fade_out", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
private static extern SPCommand* sp_command_fade_out();
|
||||
|
||||
[DllImport(__DllName, EntryPoint = "sp_command_brightness", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
private static extern SPCommand* sp_command_brightness(byte brightness);
|
||||
|
||||
[DllImport(__DllName, EntryPoint = "sp_command_char_brightness", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
private static extern SPCommand* sp_command_char_brightness(nuint x, nuint y, SPBrightnessGrid* grid);
|
||||
|
||||
[DllImport(__DllName, EntryPoint = "sp_command_bitmap_linear", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
private static extern SPCommand* sp_command_bitmap_linear(nuint offset, SPBitVec* bit_vec, CompressionCode compression);
|
||||
|
||||
[DllImport(__DllName, EntryPoint = "sp_command_bitmap_linear_and", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
private static extern SPCommand* sp_command_bitmap_linear_and(nuint offset, SPBitVec* bit_vec, CompressionCode compression);
|
||||
|
||||
[DllImport(__DllName, EntryPoint = "sp_command_bitmap_linear_or", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
private static extern SPCommand* sp_command_bitmap_linear_or(nuint offset, SPBitVec* bit_vec, CompressionCode compression);
|
||||
|
||||
[DllImport(__DllName, EntryPoint = "sp_command_bitmap_linear_xor", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
private static extern SPCommand* sp_command_bitmap_linear_xor(nuint offset, SPBitVec* bit_vec, CompressionCode compression);
|
||||
|
||||
[DllImport(__DllName, EntryPoint = "sp_command_cp437_data", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
private static extern SPCommand* sp_command_cp437_data(nuint x, nuint y, SPCp437Grid* grid);
|
||||
|
||||
[DllImport(__DllName, EntryPoint = "sp_command_bitmap_linear_win", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
private static extern SPCommand* sp_command_bitmap_linear_win(nuint x, nuint y, SPBitmap* bitmap, CompressionCode compression_code);
|
||||
|
||||
[DllImport(__DllName, EntryPoint = "sp_command_free", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
private static extern void sp_command_free(SPCommand* command);
|
||||
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public unsafe partial struct SPCommand
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -1,40 +1,21 @@
|
|||
using System.Text;
|
||||
using ServicePoint.BindGen;
|
||||
|
||||
namespace ServicePoint;
|
||||
|
||||
public sealed class Connection : SpNativeInstance<BindGen.Connection>
|
||||
public sealed partial class Connection
|
||||
{
|
||||
public static Connection Open(string host)
|
||||
public static Connection? Open(string host)
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
fixed (byte* bytePtr = Encoding.UTF8.GetBytes(host))
|
||||
{
|
||||
return new Connection(NativeMethods.sp_connection_open(bytePtr));
|
||||
return Open(bytePtr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool Send(Packet packet)
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
return NativeMethods.sp_connection_send_packet(Instance, packet.Into());
|
||||
}
|
||||
}
|
||||
public bool Send(Packet packet) => SendPacket(packet);
|
||||
|
||||
public bool Send(Command command)
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
return NativeMethods.sp_connection_send_command(Instance, command.Into());
|
||||
}
|
||||
}
|
||||
|
||||
private protected override unsafe void Free() => NativeMethods.sp_connection_free(Instance);
|
||||
|
||||
private unsafe Connection(BindGen.Connection* instance) : base(instance)
|
||||
{
|
||||
}
|
||||
public bool Send(Command command) => SendCommand(command);
|
||||
}
|
||||
|
|
|
|||
187
crates/servicepoint_binding_cs/ServicePoint/Connection.g.cs
Normal file
187
crates/servicepoint_binding_cs/ServicePoint/Connection.g.cs
Normal file
|
|
@ -0,0 +1,187 @@
|
|||
// <auto-generated>
|
||||
// This code is generated by csbindgen.
|
||||
// DON'T CHANGE THIS DIRECTLY.
|
||||
// </auto-generated>
|
||||
#pragma warning disable CS8500
|
||||
#pragma warning disable CS8981
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
|
||||
namespace ServicePoint
|
||||
{
|
||||
|
||||
public unsafe sealed partial class Connection: IDisposable
|
||||
{
|
||||
#nullable enable
|
||||
/// <summary>
|
||||
/// Creates a new instance of [SPConnection] that uses UDP to send.
|
||||
///
|
||||
/// returns: NULL if connection fails, or connected instance
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// - when `host` is null or an invalid host
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The caller has to make sure that:
|
||||
///
|
||||
/// - the returned instance is freed in some way, either by using a consuming function or
|
||||
/// by explicitly calling `sp_connection_free`.
|
||||
/// </summary>
|
||||
[System.Runtime.CompilerServices.MethodImplAttribute(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
|
||||
public static Connection? Open(byte* host)
|
||||
{
|
||||
var native = Connection.sp_connection_open(host);
|
||||
return native == null ? null : new Connection(native);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of [SPConnection] for testing that does not actually send anything.
|
||||
///
|
||||
/// returns: a new instance. Will never return NULL.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The caller has to make sure that:
|
||||
///
|
||||
/// - the returned instance is freed in some way, either by using a consuming function or
|
||||
/// by explicitly calling `sp_connection_free`.
|
||||
/// </summary>
|
||||
[System.Runtime.CompilerServices.MethodImplAttribute(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
|
||||
public static Connection Fake()
|
||||
{
|
||||
return new Connection(Connection.sp_connection_fake());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sends a [SPPacket] to the display using the [SPConnection].
|
||||
///
|
||||
/// The passed `packet` gets consumed.
|
||||
///
|
||||
/// returns: true in case of success
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// - when `connection` is NULL
|
||||
/// - when `packet` is NULL
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The caller has to make sure that:
|
||||
///
|
||||
/// - `connection` points to a valid instance of [SPConnection]
|
||||
/// - `packet` points to a valid instance of [SPPacket]
|
||||
/// - `packet` is not used concurrently or after this call
|
||||
///
|
||||
/// servicepoint_csbindgen_consumes: packet
|
||||
/// </summary>
|
||||
[System.Runtime.CompilerServices.MethodImplAttribute(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
|
||||
public bool SendPacket(Packet packet)
|
||||
{
|
||||
return Connection.sp_connection_send_packet(this.__Instance, packet.__Into());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sends a [SPCommand] to the display using the [SPConnection].
|
||||
///
|
||||
/// The passed `command` gets consumed.
|
||||
///
|
||||
/// returns: true in case of success
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// - when `connection` is NULL
|
||||
/// - when `command` is NULL
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The caller has to make sure that:
|
||||
///
|
||||
/// - `connection` points to a valid instance of [SPConnection]
|
||||
/// - `command` points to a valid instance of [SPPacket]
|
||||
/// - `command` is not used concurrently or after this call
|
||||
///
|
||||
/// servicepoint_csbindgen_consumes: command
|
||||
/// </summary>
|
||||
[System.Runtime.CompilerServices.MethodImplAttribute(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
|
||||
public bool SendCommand(Command command)
|
||||
{
|
||||
return Connection.sp_connection_send_command(this.__Instance, command.__Into());
|
||||
}
|
||||
|
||||
|
||||
#region internal machinery
|
||||
private SPConnection* _instance;
|
||||
internal SPConnection* __Instance
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_instance == null)
|
||||
throw new NullReferenceException("instance is null");
|
||||
return _instance;
|
||||
}
|
||||
}
|
||||
|
||||
private Connection(SPConnection* instance)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(instance);
|
||||
_instance = instance;
|
||||
}
|
||||
|
||||
internal SPConnection* __Into()
|
||||
{
|
||||
var instance = __Instance;
|
||||
_instance = null;
|
||||
return instance;
|
||||
}
|
||||
|
||||
private void __Free()
|
||||
{
|
||||
if (_instance != null)
|
||||
Connection.sp_connection_free(__Into());
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
__Free();
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
~Connection() => __Free();
|
||||
|
||||
#endregion
|
||||
|
||||
#nullable restore
|
||||
#region native methods
|
||||
const string __DllName = "servicepoint_binding_c";
|
||||
[DllImport(__DllName, EntryPoint = "sp_connection_open", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
private static extern SPConnection* sp_connection_open(byte* host);
|
||||
|
||||
[DllImport(__DllName, EntryPoint = "sp_connection_fake", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
private static extern SPConnection* sp_connection_fake();
|
||||
|
||||
[DllImport(__DllName, EntryPoint = "sp_connection_send_packet", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
[return: MarshalAs(UnmanagedType.U1)]
|
||||
private static extern bool sp_connection_send_packet(SPConnection* connection, SPPacket* packet);
|
||||
|
||||
[DllImport(__DllName, EntryPoint = "sp_connection_send_command", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
[return: MarshalAs(UnmanagedType.U1)]
|
||||
private static extern bool sp_connection_send_command(SPConnection* connection, SPCommand* command);
|
||||
|
||||
[DllImport(__DllName, EntryPoint = "sp_connection_free", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
private static extern void sp_connection_free(SPConnection* connection);
|
||||
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public unsafe partial struct SPConnection
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -1,17 +1,15 @@
|
|||
using ServicePoint.BindGen;
|
||||
|
||||
namespace ServicePoint;
|
||||
|
||||
public static class Constants
|
||||
{
|
||||
/// size of a single tile in one dimension
|
||||
public const nuint TileSize = NativeMethods.SP_TILE_SIZE;
|
||||
public const nuint TileSize = ConstantsNative.SP_TILE_SIZE;
|
||||
|
||||
/// tile count in the x-direction
|
||||
public const nuint TileWidth = NativeMethods.SP_TILE_WIDTH;
|
||||
public const nuint TileWidth = ConstantsNative.SP_TILE_WIDTH;
|
||||
|
||||
/// tile count in the y-direction
|
||||
public const nuint TileHeight = NativeMethods.SP_TILE_SIZE;
|
||||
public const nuint TileHeight = ConstantsNative.SP_TILE_SIZE;
|
||||
|
||||
/// screen width in pixels
|
||||
public const nuint PixelWidth = TileWidth * TileSize;
|
||||
|
|
@ -21,4 +19,8 @@ public static class Constants
|
|||
|
||||
/// pixel count on whole screen
|
||||
public const nuint PixelCount = PixelWidth * PixelHeight;
|
||||
|
||||
public const byte MinBrightness = ConstantsNative.SP_BRIGHTNESS_MIN;
|
||||
public const byte MaxBrightness = ConstantsNative.SP_BRIGHTNESS_MAX;
|
||||
public const byte BrightnessLevels = ConstantsNative.SP_BRIGHTNESS_LEVELS;
|
||||
}
|
||||
|
|
|
|||
40
crates/servicepoint_binding_cs/ServicePoint/Constants.g.cs
Normal file
40
crates/servicepoint_binding_cs/ServicePoint/Constants.g.cs
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
// <auto-generated>
|
||||
// This code is generated by csbindgen.
|
||||
// DON'T CHANGE THIS DIRECTLY.
|
||||
// </auto-generated>
|
||||
#pragma warning disable CS8500
|
||||
#pragma warning disable CS8981
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
|
||||
namespace ServicePoint
|
||||
{
|
||||
public static unsafe partial class ConstantsNative
|
||||
{
|
||||
const string __DllName = "servicepoint_binding_c";
|
||||
|
||||
public const nuint SP_TILE_SIZE = 8;
|
||||
public const nuint SP_TILE_WIDTH = 56;
|
||||
public const nuint SP_TILE_HEIGHT = 20;
|
||||
public const byte SP_BRIGHTNESS_MIN = 0;
|
||||
public const byte SP_BRIGHTNESS_MAX = 11;
|
||||
public const byte SP_BRIGHTNESS_LEVELS = 12;
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
public enum CompressionCode : ushort
|
||||
{
|
||||
Uncompressed = 0,
|
||||
Zlib = 26490,
|
||||
Bzip2 = 25210,
|
||||
Lzma = 27770,
|
||||
Zstd = 31347,
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -1,66 +1,36 @@
|
|||
using System.Text;
|
||||
using ServicePoint.BindGen;
|
||||
|
||||
namespace ServicePoint;
|
||||
|
||||
public sealed class Cp437Grid : SpNativeInstance<BindGen.Cp437Grid>
|
||||
public sealed partial class Cp437Grid
|
||||
{
|
||||
public static Cp437Grid New(int width, int height)
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
return new Cp437Grid(NativeMethods.sp_cp437_grid_new((nuint)width, (nuint)height));
|
||||
}
|
||||
}
|
||||
|
||||
public static Cp437Grid Load(int width, int height, Span<byte> bytes)
|
||||
public static Cp437Grid Load(nuint width, nuint height, ReadOnlySpan<byte> bytes)
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
fixed (byte* bytesPtr = bytes)
|
||||
{
|
||||
return new Cp437Grid(NativeMethods.sp_cp437_grid_load((nuint)width, (nuint)height, bytesPtr,
|
||||
(nuint)bytes.Length));
|
||||
return Load(width, height, bytesPtr, (nuint)bytes.Length);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Cp437Grid Clone()
|
||||
public byte this[nuint x, nuint y]
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
return new Cp437Grid(NativeMethods.sp_cp437_grid_clone(Instance));
|
||||
}
|
||||
get => Get(x, y);
|
||||
set => Set(x, y, value);
|
||||
}
|
||||
|
||||
public byte this[int x, int y]
|
||||
{
|
||||
get
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
return NativeMethods.sp_cp437_grid_get(Instance, (nuint)x, (nuint)y);
|
||||
}
|
||||
}
|
||||
set
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
NativeMethods.sp_cp437_grid_set(Instance, (nuint)x, (nuint)y, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public string this[int y]
|
||||
public string this[nuint y]
|
||||
{
|
||||
set
|
||||
{
|
||||
var width = Width;
|
||||
ArgumentOutOfRangeException.ThrowIfGreaterThan(value.Length, width);
|
||||
var width = Width();
|
||||
ArgumentOutOfRangeException.ThrowIfGreaterThan((nuint)value.Length, width);
|
||||
|
||||
var x = 0;
|
||||
for (; x < value.Length; x++)
|
||||
this[x, y] = (byte)value[x];
|
||||
nuint x = 0;
|
||||
for (; x < (nuint)value.Length; x++)
|
||||
this[x, y] = (byte)value[(int)x];
|
||||
|
||||
for (; x < width; x++)
|
||||
this[x, y] = 0;
|
||||
|
|
@ -69,7 +39,8 @@ public sealed class Cp437Grid : SpNativeInstance<BindGen.Cp437Grid>
|
|||
get
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
for (int x = 0; x < Width; x++)
|
||||
var width = Width();
|
||||
for (nuint x = 0; x < width; x++)
|
||||
{
|
||||
var val = this[x, y];
|
||||
if (val == 0)
|
||||
|
|
@ -81,51 +52,5 @@ public sealed class Cp437Grid : SpNativeInstance<BindGen.Cp437Grid>
|
|||
}
|
||||
}
|
||||
|
||||
public void Fill(byte value)
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
NativeMethods.sp_cp437_grid_fill(Instance, value);
|
||||
}
|
||||
}
|
||||
|
||||
public int Width
|
||||
{
|
||||
get
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
return (int)NativeMethods.sp_cp437_grid_width(Instance);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int Height
|
||||
{
|
||||
get
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
return (int)NativeMethods.sp_cp437_grid_height(Instance);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Span<byte> Data
|
||||
{
|
||||
get
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
var slice = NativeMethods.sp_cp437_grid_unsafe_data_ref(Instance);
|
||||
return new Span<byte>(slice.start, (int)slice.length);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private unsafe Cp437Grid(BindGen.Cp437Grid* instance) : base(instance)
|
||||
{
|
||||
}
|
||||
|
||||
private protected override unsafe void Free() => NativeMethods.sp_cp437_grid_free(Instance);
|
||||
public Span<byte> Data => UnsafeDataRef().AsSpan();
|
||||
}
|
||||
|
|
|
|||
315
crates/servicepoint_binding_cs/ServicePoint/Cp437Grid.g.cs
Normal file
315
crates/servicepoint_binding_cs/ServicePoint/Cp437Grid.g.cs
Normal file
|
|
@ -0,0 +1,315 @@
|
|||
// <auto-generated>
|
||||
// This code is generated by csbindgen.
|
||||
// DON'T CHANGE THIS DIRECTLY.
|
||||
// </auto-generated>
|
||||
#pragma warning disable CS8500
|
||||
#pragma warning disable CS8981
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
|
||||
namespace ServicePoint
|
||||
{
|
||||
|
||||
public unsafe sealed partial class Cp437Grid: IDisposable
|
||||
{
|
||||
#nullable enable
|
||||
/// <summary>
|
||||
/// Creates a new [SPCp437Grid] with the specified dimensions.
|
||||
///
|
||||
/// returns: [SPCp437Grid] initialized to 0. Will never return NULL.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The caller has to make sure that:
|
||||
///
|
||||
/// - the returned instance is freed in some way, either by using a consuming function or
|
||||
/// by explicitly calling `sp_cp437_grid_free`.
|
||||
/// </summary>
|
||||
public Cp437Grid(nuint width, nuint height) : this(sp_cp437_grid_new(width, height)) {}
|
||||
|
||||
/// <summary>
|
||||
/// Loads a [SPCp437Grid] with the specified dimensions from the provided data.
|
||||
///
|
||||
/// Will never return NULL.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// - when `data` is NULL
|
||||
/// - when the provided `data_length` does not match `height` and `width`
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The caller has to make sure that:
|
||||
///
|
||||
/// - `data` points to a valid memory location of at least `data_length`
|
||||
/// bytes in size.
|
||||
/// - the returned instance is freed in some way, either by using a consuming function or
|
||||
/// by explicitly calling `sp_cp437_grid_free`.
|
||||
/// </summary>
|
||||
[System.Runtime.CompilerServices.MethodImplAttribute(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
|
||||
public static Cp437Grid Load(nuint width, nuint height, byte* data, nuint data_length)
|
||||
{
|
||||
return new Cp437Grid(Cp437Grid.sp_cp437_grid_load(width, height, data, data_length));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clones a [SPCp437Grid].
|
||||
///
|
||||
/// Will never return NULL.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// - when `cp437_grid` is NULL
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The caller has to make sure that:
|
||||
///
|
||||
/// - `cp437_grid` points to a valid [SPCp437Grid]
|
||||
/// - `cp437_grid` is not written to concurrently
|
||||
/// - the returned instance is freed in some way, either by using a consuming function or
|
||||
/// by explicitly calling `sp_cp437_grid_free`.
|
||||
/// </summary>
|
||||
[System.Runtime.CompilerServices.MethodImplAttribute(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
|
||||
public Cp437Grid Clone()
|
||||
{
|
||||
return new Cp437Grid(Cp437Grid.sp_cp437_grid_clone(this.__Instance));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current value at the specified position.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// - `cp437_grid`: instance to read from
|
||||
/// - `x` and `y`: position of the cell to read
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// - when `cp437_grid` is NULL
|
||||
/// - when accessing `x` or `y` out of bounds
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The caller has to make sure that:
|
||||
///
|
||||
/// - `cp437_grid` points to a valid [SPCp437Grid]
|
||||
/// - `cp437_grid` is not written to concurrently
|
||||
/// </summary>
|
||||
[System.Runtime.CompilerServices.MethodImplAttribute(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
|
||||
public byte Get(nuint x, nuint y)
|
||||
{
|
||||
return Cp437Grid.sp_cp437_grid_get(this.__Instance, x, y);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the value of the specified position in the [SPCp437Grid].
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// - `cp437_grid`: instance to write to
|
||||
/// - `x` and `y`: position of the cell
|
||||
/// - `value`: the value to write to the cell
|
||||
///
|
||||
/// returns: old value of the cell
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// - when `cp437_grid` is NULL
|
||||
/// - when accessing `x` or `y` out of bounds
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The caller has to make sure that:
|
||||
///
|
||||
/// - `cp437_grid` points to a valid [SPBitVec]
|
||||
/// - `cp437_grid` is not written to or read from concurrently
|
||||
/// </summary>
|
||||
[System.Runtime.CompilerServices.MethodImplAttribute(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
|
||||
public void Set(nuint x, nuint y, byte value)
|
||||
{
|
||||
Cp437Grid.sp_cp437_grid_set(this.__Instance, x, y, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the value of all cells in the [SPCp437Grid].
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// - `cp437_grid`: instance to write to
|
||||
/// - `value`: the value to set all cells to
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// - when `cp437_grid` is NULL
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The caller has to make sure that:
|
||||
///
|
||||
/// - `cp437_grid` points to a valid [SPCp437Grid]
|
||||
/// - `cp437_grid` is not written to or read from concurrently
|
||||
/// </summary>
|
||||
[System.Runtime.CompilerServices.MethodImplAttribute(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
|
||||
public void Fill(byte value)
|
||||
{
|
||||
Cp437Grid.sp_cp437_grid_fill(this.__Instance, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the width of the [SPCp437Grid] instance.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// - `cp437_grid`: instance to read from
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// - when `cp437_grid` is NULL
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The caller has to make sure that:
|
||||
///
|
||||
/// - `cp437_grid` points to a valid [SPCp437Grid]
|
||||
/// </summary>
|
||||
[System.Runtime.CompilerServices.MethodImplAttribute(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
|
||||
public nuint Width()
|
||||
{
|
||||
return Cp437Grid.sp_cp437_grid_width(this.__Instance);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the height of the [SPCp437Grid] instance.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// - `cp437_grid`: instance to read from
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// - when `cp437_grid` is NULL
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The caller has to make sure that:
|
||||
///
|
||||
/// - `cp437_grid` points to a valid [SPCp437Grid]
|
||||
/// </summary>
|
||||
[System.Runtime.CompilerServices.MethodImplAttribute(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
|
||||
public nuint Height()
|
||||
{
|
||||
return Cp437Grid.sp_cp437_grid_height(this.__Instance);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets an unsafe reference to the data of the [SPCp437Grid] instance.
|
||||
///
|
||||
/// Will never return NULL.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// - when `cp437_grid` is NULL
|
||||
///
|
||||
/// ## Safety
|
||||
///
|
||||
/// The caller has to make sure that:
|
||||
///
|
||||
/// - `cp437_grid` points to a valid [SPCp437Grid]
|
||||
/// - the returned memory range is never accessed after the passed [SPCp437Grid] has been freed
|
||||
/// - the returned memory range is never accessed concurrently, either via the [SPCp437Grid] or directly
|
||||
/// </summary>
|
||||
[System.Runtime.CompilerServices.MethodImplAttribute(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
|
||||
public SPByteSlice UnsafeDataRef()
|
||||
{
|
||||
return Cp437Grid.sp_cp437_grid_unsafe_data_ref(this.__Instance);
|
||||
}
|
||||
|
||||
|
||||
#region internal machinery
|
||||
private SPCp437Grid* _instance;
|
||||
internal SPCp437Grid* __Instance
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_instance == null)
|
||||
throw new NullReferenceException("instance is null");
|
||||
return _instance;
|
||||
}
|
||||
}
|
||||
|
||||
private Cp437Grid(SPCp437Grid* instance)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(instance);
|
||||
_instance = instance;
|
||||
}
|
||||
|
||||
internal SPCp437Grid* __Into()
|
||||
{
|
||||
var instance = __Instance;
|
||||
_instance = null;
|
||||
return instance;
|
||||
}
|
||||
|
||||
private void __Free()
|
||||
{
|
||||
if (_instance != null)
|
||||
Cp437Grid.sp_cp437_grid_free(__Into());
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
__Free();
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
~Cp437Grid() => __Free();
|
||||
|
||||
#endregion
|
||||
|
||||
#nullable restore
|
||||
#region native methods
|
||||
const string __DllName = "servicepoint_binding_c";
|
||||
[DllImport(__DllName, EntryPoint = "sp_cp437_grid_new", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
private static extern SPCp437Grid* sp_cp437_grid_new(nuint width, nuint height);
|
||||
|
||||
[DllImport(__DllName, EntryPoint = "sp_cp437_grid_load", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
private static extern SPCp437Grid* sp_cp437_grid_load(nuint width, nuint height, byte* data, nuint data_length);
|
||||
|
||||
[DllImport(__DllName, EntryPoint = "sp_cp437_grid_clone", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
private static extern SPCp437Grid* sp_cp437_grid_clone(SPCp437Grid* cp437_grid);
|
||||
|
||||
[DllImport(__DllName, EntryPoint = "sp_cp437_grid_free", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
private static extern void sp_cp437_grid_free(SPCp437Grid* cp437_grid);
|
||||
|
||||
[DllImport(__DllName, EntryPoint = "sp_cp437_grid_get", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
private static extern byte sp_cp437_grid_get(SPCp437Grid* cp437_grid, nuint x, nuint y);
|
||||
|
||||
[DllImport(__DllName, EntryPoint = "sp_cp437_grid_set", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
private static extern void sp_cp437_grid_set(SPCp437Grid* cp437_grid, nuint x, nuint y, byte value);
|
||||
|
||||
[DllImport(__DllName, EntryPoint = "sp_cp437_grid_fill", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
private static extern void sp_cp437_grid_fill(SPCp437Grid* cp437_grid, byte value);
|
||||
|
||||
[DllImport(__DllName, EntryPoint = "sp_cp437_grid_width", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
private static extern nuint sp_cp437_grid_width(SPCp437Grid* cp437_grid);
|
||||
|
||||
[DllImport(__DllName, EntryPoint = "sp_cp437_grid_height", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
private static extern nuint sp_cp437_grid_height(SPCp437Grid* cp437_grid);
|
||||
|
||||
[DllImport(__DllName, EntryPoint = "sp_cp437_grid_unsafe_data_ref", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
private static extern SPByteSlice sp_cp437_grid_unsafe_data_ref(SPCp437Grid* cp437_grid);
|
||||
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public unsafe partial struct SPCp437Grid
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -1 +1 @@
|
|||
global using System;
|
||||
global using System;
|
||||
|
|
|
|||
|
|
@ -1,36 +1,23 @@
|
|||
using System.Diagnostics.CodeAnalysis;
|
||||
using ServicePoint.BindGen;
|
||||
|
||||
namespace ServicePoint;
|
||||
|
||||
public sealed class Packet : SpNativeInstance<BindGen.Packet>
|
||||
public sealed partial class Packet
|
||||
{
|
||||
public static Packet FromCommand(Command command)
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
return new Packet(NativeMethods.sp_packet_from_command(command.Into()));
|
||||
}
|
||||
}
|
||||
|
||||
public static bool TryFromBytes(Span<byte> bytes, [MaybeNullWhen(false)] out Packet packet)
|
||||
public static bool TryLoad(ReadOnlySpan<byte> bytes, [MaybeNullWhen(false)] out Packet packet)
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
fixed (byte* bytesPtr = bytes)
|
||||
{
|
||||
var instance = NativeMethods.sp_packet_try_load(bytesPtr, (nuint)bytes.Length);
|
||||
packet = instance == null
|
||||
? null
|
||||
: new Packet(instance);
|
||||
packet = TryLoad(bytesPtr, (nuint)bytes.Length);
|
||||
return packet != null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private unsafe Packet(BindGen.Packet* instance) : base(instance)
|
||||
public bool TryIntoCommand([MaybeNullWhen(false)] out Command command)
|
||||
{
|
||||
return Command.TryFromPacket(this, out command);
|
||||
}
|
||||
|
||||
private protected override unsafe void Free() => NativeMethods.sp_packet_free(Instance);
|
||||
}
|
||||
|
|
|
|||
196
crates/servicepoint_binding_cs/ServicePoint/Packet.g.cs
Normal file
196
crates/servicepoint_binding_cs/ServicePoint/Packet.g.cs
Normal file
|
|
@ -0,0 +1,196 @@
|
|||
// <auto-generated>
|
||||
// This code is generated by csbindgen.
|
||||
// DON'T CHANGE THIS DIRECTLY.
|
||||
// </auto-generated>
|
||||
#pragma warning disable CS8500
|
||||
#pragma warning disable CS8981
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
|
||||
namespace ServicePoint
|
||||
{
|
||||
|
||||
public unsafe sealed partial class Packet: IDisposable
|
||||
{
|
||||
#nullable enable
|
||||
/// <summary>
|
||||
/// Turns a [SPCommand] into a [SPPacket].
|
||||
/// The [SPCommand] gets consumed.
|
||||
///
|
||||
/// Will never return NULL.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// - when `command` is NULL
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The caller has to make sure that:
|
||||
///
|
||||
/// - [SPCommand] points to a valid instance of [SPCommand]
|
||||
/// - [SPCommand] is not used concurrently or after this call
|
||||
/// - the returned [SPPacket] instance is freed in some way, either by using a consuming function or
|
||||
/// by explicitly calling `sp_packet_free`.
|
||||
///
|
||||
/// servicepoint_csbindgen_consumes: command
|
||||
/// </summary>
|
||||
[System.Runtime.CompilerServices.MethodImplAttribute(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
|
||||
public static Packet FromCommand(Command command)
|
||||
{
|
||||
return new Packet(Packet.sp_packet_from_command(command.__Into()));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a raw [SPPacket] from parts.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// - `command_code` specifies which command this packet contains
|
||||
/// - `a`, `b`, `c` and `d` are command-specific header values
|
||||
/// - `payload` is the optional data that is part of the command
|
||||
/// - `payload_len` is the size of the payload
|
||||
///
|
||||
/// returns: new instance. Will never return null.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// - when `payload` is null, but `payload_len` is not zero
|
||||
/// - when `payload_len` is zero, but `payload` is nonnull
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The caller has to make sure that:
|
||||
///
|
||||
/// - `payload` points to a valid memory region of at least `payload_len` bytes
|
||||
/// - `payload` is not written to concurrently
|
||||
/// - the returned [SPPacket] instance is freed in some way, either by using a consuming function or
|
||||
/// by explicitly calling `sp_packet_free`.
|
||||
/// </summary>
|
||||
[System.Runtime.CompilerServices.MethodImplAttribute(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
|
||||
public static Packet FromParts(ushort command_code, ushort a, ushort b, ushort c, ushort d, byte* payload, nuint payload_len)
|
||||
{
|
||||
return new Packet(Packet.sp_packet_from_parts(command_code, a, b, c, d, payload, payload_len));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tries to load a [SPPacket] from the passed array with the specified length.
|
||||
///
|
||||
/// returns: NULL in case of an error, pointer to the allocated packet otherwise
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// - when `data` is NULL
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The caller has to make sure that:
|
||||
///
|
||||
/// - `data` points to a valid memory region of at least `length` bytes
|
||||
/// - `data` is not written to concurrently
|
||||
/// - the returned [SPPacket] instance is freed in some way, either by using a consuming function or
|
||||
/// by explicitly calling `sp_packet_free`.
|
||||
/// </summary>
|
||||
[System.Runtime.CompilerServices.MethodImplAttribute(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
|
||||
public static Packet? TryLoad(byte* data, nuint length)
|
||||
{
|
||||
var native = Packet.sp_packet_try_load(data, length);
|
||||
return native == null ? null : new Packet(native);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clones a [SPPacket].
|
||||
///
|
||||
/// Will never return NULL.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// - when `packet` is NULL
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The caller has to make sure that:
|
||||
///
|
||||
/// - `packet` points to a valid [SPPacket]
|
||||
/// - `packet` is not written to concurrently
|
||||
/// - the returned instance is freed in some way, either by using a consuming function or
|
||||
/// by explicitly calling `sp_packet_free`.
|
||||
/// </summary>
|
||||
[System.Runtime.CompilerServices.MethodImplAttribute(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
|
||||
public Packet Clone()
|
||||
{
|
||||
return new Packet(Packet.sp_packet_clone(this.__Instance));
|
||||
}
|
||||
|
||||
|
||||
#region internal machinery
|
||||
private SPPacket* _instance;
|
||||
internal SPPacket* __Instance
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_instance == null)
|
||||
throw new NullReferenceException("instance is null");
|
||||
return _instance;
|
||||
}
|
||||
}
|
||||
|
||||
private Packet(SPPacket* instance)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(instance);
|
||||
_instance = instance;
|
||||
}
|
||||
|
||||
internal SPPacket* __Into()
|
||||
{
|
||||
var instance = __Instance;
|
||||
_instance = null;
|
||||
return instance;
|
||||
}
|
||||
|
||||
private void __Free()
|
||||
{
|
||||
if (_instance != null)
|
||||
Packet.sp_packet_free(__Into());
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
__Free();
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
~Packet() => __Free();
|
||||
|
||||
#endregion
|
||||
|
||||
#nullable restore
|
||||
#region native methods
|
||||
const string __DllName = "servicepoint_binding_c";
|
||||
[DllImport(__DllName, EntryPoint = "sp_packet_from_command", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
private static extern SPPacket* sp_packet_from_command(SPCommand* command);
|
||||
|
||||
[DllImport(__DllName, EntryPoint = "sp_packet_from_parts", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
private static extern SPPacket* sp_packet_from_parts(ushort command_code, ushort a, ushort b, ushort c, ushort d, byte* payload, nuint payload_len);
|
||||
|
||||
[DllImport(__DllName, EntryPoint = "sp_packet_try_load", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
private static extern SPPacket* sp_packet_try_load(byte* data, nuint length);
|
||||
|
||||
[DllImport(__DllName, EntryPoint = "sp_packet_clone", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
private static extern SPPacket* sp_packet_clone(SPPacket* packet);
|
||||
|
||||
[DllImport(__DllName, EntryPoint = "sp_packet_free", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||
private static extern void sp_packet_free(SPPacket* packet);
|
||||
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public unsafe partial struct SPPacket
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -9,6 +9,11 @@
|
|||
<DisableFastUpToDateCheck>true</DisableFastUpToDateCheck>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
|
||||
</PropertyGroup>
|
||||
|
||||
|
||||
<PropertyGroup>
|
||||
<PackageId>ServicePoint</PackageId>
|
||||
<Version>0.10.0</Version>
|
||||
|
|
@ -26,11 +31,11 @@
|
|||
</PropertyGroup>
|
||||
|
||||
<!-- generate C# bindings -->
|
||||
<Target Name="BuildBindings" Condition="'$(Configuration)'=='Release'" BeforeTargets="PrepareForBuild">
|
||||
<Target Name="BuildBindingsRelease" Condition="'$(Configuration)'=='Release'" BeforeTargets="PrepareForBuild">
|
||||
<Exec Command="cargo build --release"/>
|
||||
<Exec Command="cargo build --manifest-path ../../../crates/servicepoint_binding_c/Cargo.toml --release"/>
|
||||
</Target>
|
||||
<Target Name="BuildBindings" Condition="'$(Configuration)'=='Debug'" BeforeTargets="PrepareForBuild">
|
||||
<Target Name="BuildBindingsDebug" Condition="'$(Configuration)'=='Debug'" BeforeTargets="PrepareForBuild">
|
||||
<Exec Command="cargo build"/>
|
||||
<Exec Command="cargo build --manifest-path ../../../crates/servicepoint_binding_c/Cargo.toml"/>
|
||||
</Target>
|
||||
|
|
|
|||
|
|
@ -1,16 +0,0 @@
|
|||
using System.Diagnostics.CodeAnalysis;
|
||||
|
||||
namespace ServicePoint;
|
||||
|
||||
public static class ServicePointExtensions
|
||||
{
|
||||
public static Packet IntoPacket(this Command command)
|
||||
{
|
||||
return Packet.FromCommand(command);
|
||||
}
|
||||
|
||||
public static bool TryIntoCommand(this Packet packet, [MaybeNullWhen(false)] out Command command)
|
||||
{
|
||||
return Command.TryFromPacket(packet, out command);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,51 +0,0 @@
|
|||
namespace ServicePoint;
|
||||
|
||||
public abstract class SpNativeInstance<T>
|
||||
: IDisposable
|
||||
where T : unmanaged
|
||||
{
|
||||
private unsafe T* _instance;
|
||||
|
||||
internal unsafe T* Instance
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_instance == null)
|
||||
throw new NullReferenceException("instance is null");
|
||||
return _instance;
|
||||
}
|
||||
}
|
||||
|
||||
private protected unsafe SpNativeInstance(T* instance)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(instance);
|
||||
_instance = instance;
|
||||
}
|
||||
|
||||
private protected abstract void Free();
|
||||
|
||||
internal unsafe T* Into()
|
||||
{
|
||||
var instance = _instance;
|
||||
_instance = null;
|
||||
return instance;
|
||||
}
|
||||
|
||||
private unsafe void ReleaseUnmanagedResources()
|
||||
{
|
||||
if (_instance != null)
|
||||
Free();
|
||||
_instance = null;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
ReleaseUnmanagedResources();
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
~SpNativeInstance()
|
||||
{
|
||||
ReleaseUnmanagedResources();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,39 +1,59 @@
|
|||
//! Build script generating the C# code needed to call methods from the `servicepoint` C library.
|
||||
|
||||
use std::fs;
|
||||
use std::{fs, path::Path};
|
||||
|
||||
use convert_case::{Case, Casing};
|
||||
|
||||
fn main() {
|
||||
println!("cargo::rerun-if-changed=../servicepoint_binding_c/src");
|
||||
println!("cargo::rerun-if-changed=build.rs");
|
||||
|
||||
let mut builder = csbindgen::Builder::default();
|
||||
|
||||
let mut paths = fs::read_dir("../servicepoint_binding_c/src").unwrap()
|
||||
let mut paths = fs::read_dir("../servicepoint_binding_c/src")
|
||||
.unwrap()
|
||||
.map(|x| x.unwrap().path())
|
||||
.collect::<Vec<_>>();
|
||||
paths.sort();
|
||||
|
||||
for path in paths {
|
||||
for path in &paths {
|
||||
println!("cargo:rerun-if-changed={}", path.display());
|
||||
builder = builder.input_extern_file(path);
|
||||
}
|
||||
let file: &str = Path::new(path).file_stem().unwrap().to_str().unwrap();
|
||||
if file == "lib" {
|
||||
continue;
|
||||
}
|
||||
|
||||
builder
|
||||
.csharp_dll_name("servicepoint_binding_c")
|
||||
.csharp_namespace("ServicePoint.BindGen")
|
||||
.csharp_use_nint_types(true)
|
||||
.csharp_class_accessibility("public")
|
||||
.csharp_generate_const_filter(|_| true)
|
||||
.csharp_type_rename(move |name| {
|
||||
if name.len() > 2
|
||||
&& name.starts_with("SP")
|
||||
&& name.chars().nth(2).unwrap().is_uppercase()
|
||||
{
|
||||
name[2..].to_string()
|
||||
} else {
|
||||
name
|
||||
}
|
||||
})
|
||||
.generate_csharp_file("ServicePoint/BindGen/ServicePoint.g.cs")
|
||||
.unwrap();
|
||||
let class = file.to_case(Case::UpperCamel);
|
||||
csbindgen::Builder::default()
|
||||
.input_extern_file(path)
|
||||
.csharp_class_name(format!("{class}Native"))
|
||||
.csharp_dll_name("servicepoint_binding_c")
|
||||
.csharp_namespace("ServicePoint")
|
||||
.csharp_use_nint_types(true)
|
||||
.csharp_class_accessibility("public")
|
||||
.csharp_generate_const_filter(|_| true)
|
||||
.always_included_types(["SPByteSlice", "SPCompressionCode"])
|
||||
.csharp_group_methods("sp_bitmap_", "Bitmap", "SPBitmap")
|
||||
.csharp_group_methods("sp_bitvec_", "BitVec", "SPBitVec")
|
||||
.csharp_group_methods("sp_command_", "Command", "SPCommand")
|
||||
.csharp_group_methods(
|
||||
"sp_connection_",
|
||||
"Connection",
|
||||
"SPConnection",
|
||||
)
|
||||
.csharp_group_methods("sp_cp437_grid_", "Cp437Grid", "SPCp437Grid")
|
||||
.csharp_group_methods("sp_packet_", "Packet", "SPPacket")
|
||||
.csharp_group_methods(
|
||||
"sp_brightness_grid_",
|
||||
"BrightnessGrid",
|
||||
"SPBrightnessGrid",
|
||||
)
|
||||
.csharp_type_rename(move |name| {
|
||||
if name == "SPCompressionCode" {
|
||||
"CompressionCode".to_string()
|
||||
} else {
|
||||
name
|
||||
}
|
||||
})
|
||||
.generate_csharp_file(format!("ServicePoint/{class}.g.cs"))
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,20 +1,24 @@
|
|||
using ServicePoint;
|
||||
using CompressionCode = ServicePoint.BindGen.CompressionCode;
|
||||
|
||||
using var connection = Connection.Open("127.0.0.1:2342");
|
||||
if (connection == null)
|
||||
{
|
||||
Console.Error.WriteLine("could not connect");
|
||||
return;
|
||||
}
|
||||
|
||||
connection.Send(Command.Clear().IntoPacket());
|
||||
connection.Send(Command.Brightness(128).IntoPacket());
|
||||
connection.Send(Command.Clear());
|
||||
connection.Send(Command.Brightness(Constants.MaxBrightness));
|
||||
|
||||
using var pixels = Bitmap.New(Constants.PixelWidth, Constants.PixelHeight);
|
||||
using var pixels = new Bitmap(Constants.PixelWidth, Constants.PixelHeight);
|
||||
|
||||
for (var offset = 0; offset < int.MaxValue; offset++)
|
||||
for (nuint offset = 0; offset < nuint.MaxValue; offset++)
|
||||
{
|
||||
pixels.Fill(false);
|
||||
|
||||
for (var y = 0; y < pixels.Height; y++)
|
||||
for (nuint y = 0; y < pixels.Height(); y++)
|
||||
pixels[(y + offset) % Constants.PixelWidth, y] = true;
|
||||
|
||||
connection.Send(Command.BitmapLinearWin(0, 0, pixels.Clone(), CompressionCode.Lzma).IntoPacket());
|
||||
connection.Send(Command.BitmapLinearWin(0, 0, pixels.Clone(), CompressionCode.Lzma));
|
||||
Thread.Sleep(14);
|
||||
}
|
||||
|
|
|
|||
1
crates/servicepoint_csbindgen
Submodule
1
crates/servicepoint_csbindgen
Submodule
|
|
@ -0,0 +1 @@
|
|||
Subproject commit 55eb87936923e8fb3eb11cfc7be864c1f4833c98
|
||||
Loading…
Add table
Add a link
Reference in a new issue