diff --git a/crates/servicepoint/src/command.rs b/crates/servicepoint/src/command.rs index 930b5b2..3a5ab1c 100644 --- a/crates/servicepoint/src/command.rs +++ b/crates/servicepoint/src/command.rs @@ -190,10 +190,17 @@ impl TryFrom for Command { /// Try to interpret the `Packet` as one containing a `Command` fn try_from(packet: Packet) -> Result { - let Packet(Header(command_u16, a, _, _, _), _) = packet; - let command_code = match CommandCode::try_from(command_u16) { + let Packet { + header: Header { + command_code, + a, + .. + }, + .. + } = packet; + let command_code = match CommandCode::try_from(command_code) { Err(()) => { - return Err(TryFromPacketError::InvalidCommand(command_u16)); + return Err(TryFromPacketError::InvalidCommand(command_code)); } Ok(value) => value, }; @@ -266,8 +273,16 @@ impl Command { packet: Packet, compression: CompressionCode, ) -> Result { - let Packet(Header(_, tiles_x, pixels_y, tile_w, pixel_h), payload) = - packet; + let Packet { + header: Header { + command_code: _, + a: tiles_x, + b: pixels_y, + c: tile_w, + d: pixel_h, + }, + payload, + } = packet; let payload = match into_decompressed(compression, payload) { None => return Err(TryFromPacketError::DecompressionFailed), @@ -290,7 +305,16 @@ impl Command { packet: Packet, command: Command, ) -> Result { - let Packet(Header(_, a, b, c, d), payload) = packet; + let Packet { + header: Header { + command_code: _, + a, + b, + c, + d, + }, + payload, + } = packet; if !payload.is_empty() { Err(TryFromPacketError::UnexpectedPayloadSize(0, payload.len())) } else if a != 0 || b != 0 || c != 0 || d != 0 { @@ -304,7 +328,15 @@ impl Command { fn packet_into_linear_bitmap( packet: Packet, ) -> Result<(SpBitVec, CompressionCode), TryFromPacketError> { - let Packet(Header(_, _, length, sub, reserved), payload) = packet; + let Packet { + header: Header { + b: length, + c: sub, + d: reserved, + .. + }, + payload, + } = packet; if reserved != 0 { return Err(TryFromPacketError::ExtraneousHeaderValues); } @@ -330,7 +362,16 @@ impl Command { fn packet_into_char_brightness( packet: &Packet, ) -> Result { - let Packet(Header(_, x, y, width, height), payload) = packet; + let Packet { + header: Header { + command_code: _, + a: x, + b: y, + c: width, + d: height, + }, + payload, + } = packet; let grid = PrimitiveGrid::load(*width as usize, *height as usize, payload); @@ -348,7 +389,16 @@ impl Command { fn packet_into_brightness( packet: &Packet, ) -> Result { - let Packet(Header(_, a, b, c, d), payload) = packet; + let Packet { + header: Header { + command_code: _, + a, + b, + c, + d, + }, + payload, + } = packet; if payload.len() != 1 { return Err(TryFromPacketError::UnexpectedPayloadSize( 1, @@ -369,7 +419,16 @@ impl Command { fn packet_into_cp437( packet: &Packet, ) -> Result { - let Packet(Header(_, a, b, c, d), payload) = packet; + let Packet { + header: Header { + command_code: _, + a, + b, + c, + d, + }, + payload, + } = packet; Ok(Command::Cp437Data( Origin::new(*a as usize, *b as usize), Cp437Grid::load(*c as usize, *d as usize, payload), @@ -483,7 +542,16 @@ mod tests { #[test] fn error_invalid_command() { - let p = Packet(Header(0xFF, 0x00, 0x00, 0x00, 0x00), vec![]); + let p = Packet { + header: Header { + command_code: 0xFF, + a: 0x00, + b: 0x00, + c: 0x00, + d: 0x00, + }, + payload: vec![], + }; let result = Command::try_from(p); assert!(matches!( result, @@ -493,10 +561,16 @@ mod tests { #[test] fn error_extraneous_header_values_clear() { - let p = Packet( - Header(CommandCode::Clear.into(), 0x05, 0x00, 0x00, 0x00), - vec![], - ); + let p = Packet { + header: Header { + command_code: CommandCode::Clear.into(), + a: 0x05, + b: 0x00, + c: 0x00, + d: 0x00, + }, + payload: vec![], + }; let result = Command::try_from(p); assert!(matches!( result, @@ -506,10 +580,16 @@ mod tests { #[test] fn error_extraneous_header_values_brightness() { - let p = Packet( - Header(CommandCode::Brightness.into(), 0x00, 0x13, 0x37, 0x00), - vec![5], - ); + let p = Packet { + header: Header { + command_code: CommandCode::Brightness.into(), + a: 0x00, + b: 0x13, + c: 0x37, + d: 0x00, + }, + payload: vec![5], + }; let result = Command::try_from(p); assert!(matches!( result, @@ -519,10 +599,16 @@ mod tests { #[test] fn error_extraneous_header_hard_reset() { - let p = Packet( - Header(CommandCode::HardReset.into(), 0x00, 0x00, 0x00, 0x01), - vec![], - ); + let p = Packet { + header: Header { + command_code: CommandCode::HardReset.into(), + a: 0x00, + b: 0x00, + c: 0x00, + d: 0x01, + }, + payload: vec![], + }; let result = Command::try_from(p); assert!(matches!( result, @@ -532,10 +618,16 @@ mod tests { #[test] fn error_extraneous_header_fade_out() { - let p = Packet( - Header(CommandCode::FadeOut.into(), 0x10, 0x00, 0x00, 0x01), - vec![], - ); + let p = Packet { + header: Header { + command_code: CommandCode::FadeOut.into(), + a: 0x10, + b: 0x00, + c: 0x00, + d: 0x01, + }, + payload: vec![], + }; let result = Command::try_from(p); assert!(matches!( result, @@ -545,10 +637,16 @@ mod tests { #[test] fn error_unexpected_payload() { - let p = Packet( - Header(CommandCode::FadeOut.into(), 0x00, 0x00, 0x00, 0x00), - vec![5, 7], - ); + let p = Packet { + header: Header { + command_code: CommandCode::FadeOut.into(), + a: 0x00, + b: 0x00, + c: 0x00, + d: 0x00, + }, + payload: vec![5, 7], + }; let result = Command::try_from(p); assert!(matches!( result, @@ -564,15 +662,19 @@ mod tests { PixelGrid::new(8, 8), compression, ) - .into(); - let Packet(header, mut payload) = p; + .into(); + + let Packet { + header, + mut payload, + } = p; // mangle it for byte in payload.iter_mut() { *byte -= *byte / 2; } - let p = Packet(header, payload); + let p = Packet { header, payload }; let result = Command::try_from(p); if compression != CompressionCode::Uncompressed { assert_eq!(result, Err(TryFromPacketError::DecompressionFailed)) @@ -590,15 +692,18 @@ mod tests { BitVec::repeat(false, 8), compression, ) - .into(); - let Packet(header, mut payload) = p; + .into(); + let Packet { + header, + mut payload, + } = p; // mangle it for byte in payload.iter_mut() { *byte -= *byte / 2; } - let p = Packet(header, payload); + let p = Packet { header, payload }; let result = Command::try_from(p); if compression != CompressionCode::Uncompressed { assert_eq!(result, Err(TryFromPacketError::DecompressionFailed)) @@ -612,32 +717,59 @@ mod tests { #[test] fn unexpected_payload_size_brightness() { assert_eq!( - Command::try_from(Packet( - Header(CommandCode::Brightness.into(), 0, 0, 0, 0), - vec!(), - )), + Command::try_from(Packet { + header: Header { + command_code: CommandCode::Brightness.into(), + a: 0, + b: 0, + c: 0, + d: 0, + }, + payload: vec!() + }), Err(TryFromPacketError::UnexpectedPayloadSize(1, 0)) ); assert_eq!( - Command::try_from(Packet( - Header(CommandCode::Brightness.into(), 0, 0, 0, 0), - vec!(0, 0), - )), + Command::try_from(Packet { + header: Header { + command_code: CommandCode::Brightness.into(), + a: 0, + b: 0, + c: 0, + d: 0, + }, + payload: vec!(0, 0) + }), Err(TryFromPacketError::UnexpectedPayloadSize(1, 2)) ); } #[test] fn error_reserved_used() { - let Packet(header, payload) = Command::BitmapLinear( + let Packet { header, payload } = Command::BitmapLinear( 0, BitVec::repeat(false, 8), CompressionCode::Uncompressed, ) - .into(); - let Header(command, offset, length, sub, _reserved) = header; - let p = Packet(Header(command, offset, length, sub, 69), payload); + .into(); + let Header { + command_code: command, + a: offset, + b: length, + c: sub, + d: _reserved, + } = header; + let p = Packet { + header: Header { + command_code: command, + a: offset, + b: length, + c: sub, + d: 69, + }, + payload, + }; assert_eq!( Command::try_from(p), Err(TryFromPacketError::ExtraneousHeaderValues) @@ -646,14 +778,29 @@ mod tests { #[test] fn error_invalid_compression() { - let Packet(header, payload) = Command::BitmapLinear( + let Packet { header, payload } = Command::BitmapLinear( 0, BitVec::repeat(false, 8), CompressionCode::Uncompressed, ) - .into(); - let Header(command, offset, length, _sub, reserved) = header; - let p = Packet(Header(command, offset, length, 42, reserved), payload); + .into(); + let Header { + command_code: command, + a: offset, + b: length, + c: _sub, + d: reserved, + } = header; + let p = Packet { + header: Header { + command_code: command, + a: offset, + b: length, + c: 42, + d: reserved, + }, + payload, + }; assert_eq!( Command::try_from(p), Err(TryFromPacketError::InvalidCompressionCode(42)) @@ -662,17 +809,29 @@ mod tests { #[test] fn error_unexpected_size() { - let Packet(header, payload) = Command::BitmapLinear( + let Packet { header, payload } = Command::BitmapLinear( 0, BitVec::repeat(false, 8), CompressionCode::Uncompressed, ) - .into(); - let Header(command, offset, length, compression, reserved) = header; - let p = Packet( - Header(command, offset, 420, compression, reserved), + .into(); + let Header { + command_code: command, + a: offset, + b: length, + c: compression, + d: reserved, + } = header; + let p = Packet { + header: Header { + command_code: command, + a: offset, + b: 420, + c: compression, + d: reserved, + }, payload, - ); + }; assert_eq!( Command::try_from(p), Err(TryFromPacketError::UnexpectedPayloadSize( diff --git a/crates/servicepoint/src/connection.rs b/crates/servicepoint/src/connection.rs index 9237006..032ffeb 100644 --- a/crates/servicepoint/src/connection.rs +++ b/crates/servicepoint/src/connection.rs @@ -71,7 +71,7 @@ impl Connection { Connection::Udp(socket) => { socket .send(&data) - .map_err(move |io_err| SendError::IoError(io_err)) + .map_err(SendError::IoError) .map(move |_| ()) // ignore Ok value } Connection::Fake => Ok(()), diff --git a/crates/servicepoint/src/packet.rs b/crates/servicepoint/src/packet.rs index 3718e34..67c96b4 100644 --- a/crates/servicepoint/src/packet.rs +++ b/crates/servicepoint/src/packet.rs @@ -3,25 +3,84 @@ use std::mem::size_of; use crate::command_code::CommandCode; use crate::compression::into_compressed; use crate::{ - Command, CompressionCode, Grid, Offset, Origin, PixelGrid, Pixels, + Command, CompressionCode, Grid, Offset, Origin, PixelGrid, Pixels, Tiles, TILE_SIZE, }; -/// A raw header. Should probably not be used directly. +/// A raw header. +/// +/// The header specifies the kind of command, the size of the payload and where to display the +/// payload, where applicable. +/// +/// Because the meaning of most fields depend on the command, there are no speaking names for them. +/// +/// Should probably only be used directly to use features not exposed by the library. #[derive(Copy, Clone, Debug, PartialEq)] -pub struct Header(pub u16, pub u16, pub u16, pub u16, pub u16); +pub struct Header { + /// The first two bytes specify which command this packet represents. + pub command_code: u16, + /// First command-specific value + pub a: u16, + /// Second command-specific value + pub b: u16, + /// Third command-specific value + pub c: u16, + /// Fourth command-specific value + pub d: u16, +} -/// The raw payload. Should probably not be used directly. +/// The raw payload. +/// +/// Should probably only be used directly to use features not exposed by the library. pub type Payload = Vec; -/// The raw packet. Should probably not be used directly. +/// The raw packet. +/// +/// Contents should probably only be used directly to use features not exposed by the library. +/// +/// # Examples +/// +/// Converting a packet to a command and back: +/// +/// ```rust +/// # use servicepoint::{Command, Packet}; +/// # let command = Command::Clear; +/// let packet: Packet = command.into(); +/// let command: Command = Command::try_from(packet).expect("could not read packet"); +/// ``` +/// +/// Converting a packet to bytes and back: +/// +/// ```rust +/// # use servicepoint::{Command, Packet}; +/// # let command = Command::Clear; +/// # let packet: Packet = command.into(); +/// let bytes: Vec = packet.into(); +/// let packet = Packet::try_from(bytes).expect("could not read packet from bytes"); +/// ``` +/// #[derive(Clone, Debug, PartialEq)] -pub struct Packet(pub Header, pub Payload); +pub struct Packet { + /// Meta-information for the packed command + pub header: Header, + /// The data for the packed command + pub payload: Payload, +} impl From for Vec { /// Turn the packet into raw bytes ready to send fn from(value: Packet) -> Self { - let Packet(Header(mode, a, b, c, d), payload) = value; + let Packet { + header: + Header { + command_code: mode, + a, + b, + c, + d, + }, + payload, + } = value; let mut packet = vec![0u8; 10 + payload.len()]; packet[0..=1].copy_from_slice(&u16::to_be_bytes(mode)); @@ -36,13 +95,6 @@ impl From for Vec { } } -fn u16_from_be_slice(slice: &[u8]) -> u16 { - let mut bytes = [0u8; 2]; - bytes[0] = slice[0]; - bytes[1] = slice[1]; - u16::from_be_bytes(bytes) -} - impl TryFrom<&[u8]> for Packet { type Error = (); @@ -54,14 +106,31 @@ impl TryFrom<&[u8]> for Packet { return Err(()); } - let mode = u16_from_be_slice(&value[0..=1]); - let a = u16_from_be_slice(&value[2..=3]); - let b = u16_from_be_slice(&value[4..=5]); - let c = u16_from_be_slice(&value[6..=7]); - let d = u16_from_be_slice(&value[8..=9]); + let header = { + let command_code = Self::u16_from_be_slice(&value[0..=1]); + let a = Self::u16_from_be_slice(&value[2..=3]); + let b = Self::u16_from_be_slice(&value[4..=5]); + let c = Self::u16_from_be_slice(&value[6..=7]); + let d = Self::u16_from_be_slice(&value[8..=9]); + Header { + command_code, + a, + b, + c, + d, + } + }; let payload = value[10..].to_vec(); - Ok(Packet(Header(mode, a, b, c, d), payload)) + Ok(Packet { header, payload }) + } +} + +impl TryFrom> for Packet { + type Error = (); + + fn try_from(value: Vec) -> Result { + Self::try_from(value.as_slice()) } } @@ -79,26 +148,23 @@ impl From for Packet { Command::BitmapLegacy => { Self::command_code_only(CommandCode::BitmapLegacy) } - Command::CharBrightness(origin, grid) => Packet( - Header( - CommandCode::CharBrightness.into(), - origin.x as u16, - origin.y as u16, - grid.width() as u16, - grid.height() as u16, - ), - grid.into(), - ), - Command::Brightness(brightness) => Packet( - Header( - CommandCode::Brightness.into(), - 0x00000, - 0x0000, - 0x0000, - 0x0000, - ), - vec![brightness.into()], - ), + Command::CharBrightness(origin, grid) => { + Self::origin_grid_to_packet( + origin, + grid, + CommandCode::CharBrightness, + ) + } + Command::Brightness(brightness) => Packet { + header: Header { + command_code: CommandCode::Brightness.into(), + a: 0x00000, + b: 0x0000, + c: 0x0000, + d: 0x0000, + }, + payload: vec![brightness.into()], + }, Command::BitmapLinearWin(origin, pixels, compression) => { Self::bitmap_win_into_packet(origin, pixels, compression) } @@ -134,15 +200,10 @@ impl From for Packet { bits.into(), ) } - Command::Cp437Data(origin, grid) => Packet( - Header( - CommandCode::Cp437Data.into(), - origin.x as u16, - origin.y as u16, - grid.width() as u16, - grid.height() as u16, - ), - grid.into(), + Command::Cp437Data(origin, grid) => Self::origin_grid_to_packet( + origin, + grid, + CommandCode::Cp437Data, ), } } @@ -159,16 +220,16 @@ impl Packet { ) -> Packet { let length = payload.len() as u16; let payload = into_compressed(compression, payload); - Packet( - Header( - command.into(), - offset as u16, - length, - compression.into(), - 0, - ), + Packet { + header: Header { + command_code: command.into(), + a: offset as u16, + b: length, + c: compression.into(), + d: 0, + }, payload, - ) + } } #[allow(clippy::cast_possible_truncation)] @@ -198,15 +259,54 @@ impl Packet { CompressionCode::Zstd => CommandCode::BitmapLinearWinZstd, }; - Packet( - Header(command.into(), tile_x, origin.y as u16, tile_w, pixel_h), + Packet { + header: Header { + command_code: command.into(), + a: tile_x, + b: origin.y as u16, + c: tile_w, + d: pixel_h, + }, payload, - ) + } } /// Helper method for creating empty packets only containing the command code fn command_code_only(code: CommandCode) -> Packet { - Packet(Header(code.into(), 0x0000, 0x0000, 0x0000, 0x0000), vec![]) + Packet { + header: Header { + command_code: code.into(), + a: 0x0000, + b: 0x0000, + c: 0x0000, + d: 0x0000, + }, + payload: vec![], + } + } + + fn u16_from_be_slice(slice: &[u8]) -> u16 { + let mut bytes = [0u8; 2]; + bytes[0] = slice[0]; + bytes[1] = slice[1]; + u16::from_be_bytes(bytes) + } + + fn origin_grid_to_packet( + origin: Origin, + grid: impl Grid + Into, + command_code: CommandCode, + ) -> Packet { + Packet { + header: Header { + command_code: command_code.into(), + a: origin.x as u16, + b: origin.y as u16, + c: grid.width() as u16, + d: grid.height() as u16, + }, + payload: grid.into(), + } } } @@ -216,10 +316,31 @@ mod tests { #[test] fn round_trip() { - let p = Packet(Header(0, 1, 2, 3, 4), vec![42u8; 23]); + let p = Packet { + header: Header { + command_code: 0, + a: 1, + b: 2, + c: 3, + d: 4, + }, + payload: vec![42u8; 23], + }; let data: Vec = p.into(); let p = Packet::try_from(&*data).unwrap(); - assert_eq!(p, Packet(Header(0, 1, 2, 3, 4), vec![42u8; 23])); + assert_eq!( + p, + Packet { + header: Header { + command_code: 0, + a: 1, + b: 2, + c: 3, + d: 4 + }, + payload: vec![42u8; 23] + } + ); } #[test] diff --git a/crates/servicepoint_binding_c/examples/lang_c/include/servicepoint.h b/crates/servicepoint_binding_c/examples/lang_c/include/servicepoint.h index 960353e..0a6069f 100644 --- a/crates/servicepoint_binding_c/examples/lang_c/include/servicepoint.h +++ b/crates/servicepoint_binding_c/examples/lang_c/include/servicepoint.h @@ -105,7 +105,7 @@ typedef struct SPBrightnessGrid SPBrightnessGrid; * * This struct and associated functions implement the UDP protocol for the display. * - * To send a `CCommand`, use a `CConnection`. + * To send a `SPCommand`, use a `SPConnection`. * * # Examples * @@ -539,6 +539,13 @@ size_t sp_brightness_grid_width(const struct SPBrightnessGrid *this_); * Allocates a new `Command::BitmapLinear` instance. * The passed `BitVec` gets consumed. * + * 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 `BitVec` is always uncompressed. + * * # Safety * * The caller has to make sure that: @@ -557,6 +564,13 @@ struct SPCommand *sp_command_bitmap_linear(SPOffset offset, * Allocates a new `Command::BitmapLinearAnd` instance. * The passed `BitVec` gets consumed. * + * 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 `BitVec` is always uncompressed. + * * # Safety * * The caller has to make sure that: @@ -575,6 +589,13 @@ struct SPCommand *sp_command_bitmap_linear_and(SPOffset offset, * Allocates a new `Command::BitmapLinearOr` instance. * The passed `BitVec` gets consumed. * + * 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 `BitVec` is always uncompressed. + * * # Safety * * The caller has to make sure that: @@ -593,6 +614,8 @@ struct SPCommand *sp_command_bitmap_linear_or(SPOffset offset, * Allocates a new `Command::BitmapLinearWin` instance. * The passed `PixelGrid` gets consumed. * + * Sets a window of pixels to the specified values + * * # Safety * * The caller has to make sure that: @@ -612,6 +635,13 @@ struct SPCommand *sp_command_bitmap_linear_win(size_t x, * Allocates a new `Command::BitmapLinearXor` instance. * The passed `BitVec` gets consumed. * + * 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 `BitVec` is always uncompressed. + * * # Safety * * The caller has to make sure that: @@ -647,6 +677,8 @@ struct SPCommand *sp_command_brightness(uint8_t brightness); * Allocates a new `Command::CharBrightness` instance. * The passed `SPBrightnessGrid` gets consumed. * + * Set the brightness of individual tiles in a rectangular area of the display. + * * # Safety * * The caller has to make sure that: @@ -663,6 +695,14 @@ struct SPCommand *sp_command_char_brightness(size_t x, /** * Allocates a new `Command::Clear` instance. * + * Set all pixels to the off state. Does not affect brightness. + * + * # Examples + * + * ```C + * sp_connection_send(connection, sp_command_clear()); + * ``` + * * # Safety * * The caller has to make sure that: @@ -673,7 +713,7 @@ struct SPCommand *sp_command_char_brightness(size_t x, struct SPCommand *sp_command_clear(void); /** - * Clones a `Command` instance. + * Clones a `SPCommand` instance. * * # Safety * @@ -690,6 +730,13 @@ struct SPCommand *sp_command_clone(const struct SPCommand *original); * Allocates a new `Command::Cp437Data` instance. * The passed `ByteGrid` gets consumed. * + * Show text on the screen. + * + *
+ * The library does not currently convert between UTF-8 and CP-437. + * Because Rust expects UTF-8 strings, it might be necessary to only send ASCII for now. + *
+ * * # Safety * * The caller has to make sure that: @@ -706,6 +753,13 @@ struct SPCommand *sp_command_cp437_data(size_t x, /** * Deallocates a `Command`. * + * # Examples + * + * ```C + * SPCommand c = sp_command_clear(); + * sp_command_dealloc(c); + * ``` + * * # Safety * * The caller has to make sure that: @@ -731,6 +785,9 @@ struct SPCommand *sp_command_fade_out(void); /** * Allocates a new `Command::HardReset` instance. * + * Kills the udp daemon on the display, which usually results in a restart. + * Please do not send this in your normal program flow. + * * # Safety * * The caller has to make sure that: @@ -741,18 +798,18 @@ struct SPCommand *sp_command_fade_out(void); struct SPCommand *sp_command_hard_reset(void); /** - * Tries to turn a `Packet` into a `Command`. The packet is deallocated in the process. + * Tries to turn a `SPPacket` into a `SPCommand`. The packet is deallocated in the process. * - * Returns: pointer to new `Command` instance or NULL + * Returns: pointer to new `SPCommand` instance or NULL * * # Safety * * The caller has to make sure that: * - * - `packet` points to a valid instance of `Packet` + * - `packet` points to a valid instance of `SPPacket` * - `packet` is not used concurrently or after this call * - the result is checked for NULL - * - the returned `Command` instance is freed in some way, either by using a consuming function or + * - the returned `SPCommand` instance is freed in some way, either by using a consuming function or * by explicitly calling `sp_command_dealloc`. */ struct SPCommand *sp_command_try_from_packet(struct SPPacket *packet); diff --git a/crates/servicepoint_binding_cs/ServicePoint/BindGen/ServicePoint.g.cs b/crates/servicepoint_binding_cs/ServicePoint/BindGen/ServicePoint.g.cs index 49c4d25..cd73a1a 100644 --- a/crates/servicepoint_binding_cs/ServicePoint/BindGen/ServicePoint.g.cs +++ b/crates/servicepoint_binding_cs/ServicePoint/BindGen/ServicePoint.g.cs @@ -546,25 +546,25 @@ namespace ServicePoint.BindGen public static extern ByteSlice sp_cp437_grid_unsafe_data_ref(Cp437Grid* @this); /// - /// Tries to turn a `Packet` into a `Command`. The packet is deallocated in the process. + /// Tries to turn a `SPPacket` into a `SPCommand`. The packet is deallocated in the process. /// - /// Returns: pointer to new `Command` instance or NULL + /// Returns: pointer to new `SPCommand` instance or NULL /// /// # Safety /// /// The caller has to make sure that: /// - /// - `packet` points to a valid instance of `Packet` + /// - `packet` points to a valid instance of `SPPacket` /// - `packet` is not used concurrently or after this call /// - the result is checked for NULL - /// - the returned `Command` instance is freed in some way, either by using a consuming function or + /// - the returned `SPCommand` instance is freed in some way, either by using a consuming function or /// by explicitly calling `sp_command_dealloc`. /// [DllImport(__DllName, EntryPoint = "sp_command_try_from_packet", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] public static extern Command* sp_command_try_from_packet(Packet* packet); /// - /// Clones a `Command` instance. + /// Clones a `SPCommand` instance. /// /// # Safety /// @@ -581,6 +581,14 @@ namespace ServicePoint.BindGen /// /// Allocates a new `Command::Clear` instance. /// + /// Set all pixels to the off state. Does not affect brightness. + /// + /// # Examples + /// + /// ```C + /// sp_connection_send(connection, sp_command_clear()); + /// ``` + /// /// # Safety /// /// The caller has to make sure that: @@ -594,6 +602,9 @@ namespace ServicePoint.BindGen /// /// Allocates a new `Command::HardReset` instance. /// + /// Kills the udp daemon on the display, which usually results in a restart. + /// Please do not send this in your normal program flow. + /// /// # Safety /// /// The caller has to make sure that: @@ -639,6 +650,8 @@ namespace ServicePoint.BindGen /// Allocates a new `Command::CharBrightness` instance. /// The passed `SPBrightnessGrid` gets consumed. /// + /// Set the brightness of individual tiles in a rectangular area of the display. + /// /// # Safety /// /// The caller has to make sure that: @@ -655,6 +668,13 @@ namespace ServicePoint.BindGen /// Allocates a new `Command::BitmapLinear` instance. /// The passed `BitVec` gets consumed. /// + /// 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 `BitVec` is always uncompressed. + /// /// # Safety /// /// The caller has to make sure that: @@ -672,6 +692,13 @@ namespace ServicePoint.BindGen /// Allocates a new `Command::BitmapLinearAnd` instance. /// The passed `BitVec` gets consumed. /// + /// 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 `BitVec` is always uncompressed. + /// /// # Safety /// /// The caller has to make sure that: @@ -689,6 +716,13 @@ namespace ServicePoint.BindGen /// Allocates a new `Command::BitmapLinearOr` instance. /// The passed `BitVec` gets consumed. /// + /// 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 `BitVec` is always uncompressed. + /// /// # Safety /// /// The caller has to make sure that: @@ -706,6 +740,13 @@ namespace ServicePoint.BindGen /// Allocates a new `Command::BitmapLinearXor` instance. /// The passed `BitVec` gets consumed. /// + /// 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 `BitVec` is always uncompressed. + /// /// # Safety /// /// The caller has to make sure that: @@ -723,6 +764,13 @@ namespace ServicePoint.BindGen /// Allocates a new `Command::Cp437Data` instance. /// The passed `ByteGrid` gets consumed. /// + /// Show text on the screen. + /// + /// <div class="warning"> + /// The library does not currently convert between UTF-8 and CP-437. + /// Because Rust expects UTF-8 strings, it might be necessary to only send ASCII for now. + /// </div> + /// /// # Safety /// /// The caller has to make sure that: @@ -739,6 +787,8 @@ namespace ServicePoint.BindGen /// Allocates a new `Command::BitmapLinearWin` instance. /// The passed `PixelGrid` gets consumed. /// + /// Sets a window of pixels to the specified values + /// /// # Safety /// /// The caller has to make sure that: @@ -755,6 +805,13 @@ namespace ServicePoint.BindGen /// /// Deallocates a `Command`. /// + /// # Examples + /// + /// ```C + /// SPCommand c = sp_command_clear(); + /// sp_command_dealloc(c); + /// ``` + /// /// # Safety /// /// The caller has to make sure that: