mirror of
https://github.com/cccb/servicepoint.git
synced 2025-01-18 18:10:14 +01:00
named fields instead of tuple for Packet, doc adjustments
This commit is contained in:
parent
e54891e662
commit
e97418b51b
|
@ -190,10 +190,17 @@ impl TryFrom<Packet> for Command {
|
||||||
|
|
||||||
/// Try to interpret the `Packet` as one containing a `Command`
|
/// Try to interpret the `Packet` as one containing a `Command`
|
||||||
fn try_from(packet: Packet) -> Result<Self, Self::Error> {
|
fn try_from(packet: Packet) -> Result<Self, Self::Error> {
|
||||||
let Packet(Header(command_u16, a, _, _, _), _) = packet;
|
let Packet {
|
||||||
let command_code = match CommandCode::try_from(command_u16) {
|
header: Header {
|
||||||
|
command_code,
|
||||||
|
a,
|
||||||
|
..
|
||||||
|
},
|
||||||
|
..
|
||||||
|
} = packet;
|
||||||
|
let command_code = match CommandCode::try_from(command_code) {
|
||||||
Err(()) => {
|
Err(()) => {
|
||||||
return Err(TryFromPacketError::InvalidCommand(command_u16));
|
return Err(TryFromPacketError::InvalidCommand(command_code));
|
||||||
}
|
}
|
||||||
Ok(value) => value,
|
Ok(value) => value,
|
||||||
};
|
};
|
||||||
|
@ -266,8 +273,16 @@ impl Command {
|
||||||
packet: Packet,
|
packet: Packet,
|
||||||
compression: CompressionCode,
|
compression: CompressionCode,
|
||||||
) -> Result<Command, TryFromPacketError> {
|
) -> Result<Command, TryFromPacketError> {
|
||||||
let Packet(Header(_, tiles_x, pixels_y, tile_w, pixel_h), payload) =
|
let Packet {
|
||||||
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) {
|
let payload = match into_decompressed(compression, payload) {
|
||||||
None => return Err(TryFromPacketError::DecompressionFailed),
|
None => return Err(TryFromPacketError::DecompressionFailed),
|
||||||
|
@ -290,7 +305,16 @@ impl Command {
|
||||||
packet: Packet,
|
packet: Packet,
|
||||||
command: Command,
|
command: Command,
|
||||||
) -> Result<Command, TryFromPacketError> {
|
) -> Result<Command, TryFromPacketError> {
|
||||||
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() {
|
if !payload.is_empty() {
|
||||||
Err(TryFromPacketError::UnexpectedPayloadSize(0, payload.len()))
|
Err(TryFromPacketError::UnexpectedPayloadSize(0, payload.len()))
|
||||||
} else if a != 0 || b != 0 || c != 0 || d != 0 {
|
} else if a != 0 || b != 0 || c != 0 || d != 0 {
|
||||||
|
@ -304,7 +328,15 @@ impl Command {
|
||||||
fn packet_into_linear_bitmap(
|
fn packet_into_linear_bitmap(
|
||||||
packet: Packet,
|
packet: Packet,
|
||||||
) -> Result<(SpBitVec, CompressionCode), TryFromPacketError> {
|
) -> 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 {
|
if reserved != 0 {
|
||||||
return Err(TryFromPacketError::ExtraneousHeaderValues);
|
return Err(TryFromPacketError::ExtraneousHeaderValues);
|
||||||
}
|
}
|
||||||
|
@ -330,7 +362,16 @@ impl Command {
|
||||||
fn packet_into_char_brightness(
|
fn packet_into_char_brightness(
|
||||||
packet: &Packet,
|
packet: &Packet,
|
||||||
) -> Result<Command, TryFromPacketError> {
|
) -> Result<Command, TryFromPacketError> {
|
||||||
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 =
|
let grid =
|
||||||
PrimitiveGrid::load(*width as usize, *height as usize, payload);
|
PrimitiveGrid::load(*width as usize, *height as usize, payload);
|
||||||
|
@ -348,7 +389,16 @@ impl Command {
|
||||||
fn packet_into_brightness(
|
fn packet_into_brightness(
|
||||||
packet: &Packet,
|
packet: &Packet,
|
||||||
) -> Result<Command, TryFromPacketError> {
|
) -> Result<Command, TryFromPacketError> {
|
||||||
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 {
|
if payload.len() != 1 {
|
||||||
return Err(TryFromPacketError::UnexpectedPayloadSize(
|
return Err(TryFromPacketError::UnexpectedPayloadSize(
|
||||||
1,
|
1,
|
||||||
|
@ -369,7 +419,16 @@ impl Command {
|
||||||
fn packet_into_cp437(
|
fn packet_into_cp437(
|
||||||
packet: &Packet,
|
packet: &Packet,
|
||||||
) -> Result<Command, TryFromPacketError> {
|
) -> Result<Command, TryFromPacketError> {
|
||||||
let Packet(Header(_, a, b, c, d), payload) = packet;
|
let Packet {
|
||||||
|
header: Header {
|
||||||
|
command_code: _,
|
||||||
|
a,
|
||||||
|
b,
|
||||||
|
c,
|
||||||
|
d,
|
||||||
|
},
|
||||||
|
payload,
|
||||||
|
} = packet;
|
||||||
Ok(Command::Cp437Data(
|
Ok(Command::Cp437Data(
|
||||||
Origin::new(*a as usize, *b as usize),
|
Origin::new(*a as usize, *b as usize),
|
||||||
Cp437Grid::load(*c as usize, *d as usize, payload),
|
Cp437Grid::load(*c as usize, *d as usize, payload),
|
||||||
|
@ -483,7 +542,16 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn error_invalid_command() {
|
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);
|
let result = Command::try_from(p);
|
||||||
assert!(matches!(
|
assert!(matches!(
|
||||||
result,
|
result,
|
||||||
|
@ -493,10 +561,16 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn error_extraneous_header_values_clear() {
|
fn error_extraneous_header_values_clear() {
|
||||||
let p = Packet(
|
let p = Packet {
|
||||||
Header(CommandCode::Clear.into(), 0x05, 0x00, 0x00, 0x00),
|
header: Header {
|
||||||
vec![],
|
command_code: CommandCode::Clear.into(),
|
||||||
);
|
a: 0x05,
|
||||||
|
b: 0x00,
|
||||||
|
c: 0x00,
|
||||||
|
d: 0x00,
|
||||||
|
},
|
||||||
|
payload: vec![],
|
||||||
|
};
|
||||||
let result = Command::try_from(p);
|
let result = Command::try_from(p);
|
||||||
assert!(matches!(
|
assert!(matches!(
|
||||||
result,
|
result,
|
||||||
|
@ -506,10 +580,16 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn error_extraneous_header_values_brightness() {
|
fn error_extraneous_header_values_brightness() {
|
||||||
let p = Packet(
|
let p = Packet {
|
||||||
Header(CommandCode::Brightness.into(), 0x00, 0x13, 0x37, 0x00),
|
header: Header {
|
||||||
vec![5],
|
command_code: CommandCode::Brightness.into(),
|
||||||
);
|
a: 0x00,
|
||||||
|
b: 0x13,
|
||||||
|
c: 0x37,
|
||||||
|
d: 0x00,
|
||||||
|
},
|
||||||
|
payload: vec![5],
|
||||||
|
};
|
||||||
let result = Command::try_from(p);
|
let result = Command::try_from(p);
|
||||||
assert!(matches!(
|
assert!(matches!(
|
||||||
result,
|
result,
|
||||||
|
@ -519,10 +599,16 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn error_extraneous_header_hard_reset() {
|
fn error_extraneous_header_hard_reset() {
|
||||||
let p = Packet(
|
let p = Packet {
|
||||||
Header(CommandCode::HardReset.into(), 0x00, 0x00, 0x00, 0x01),
|
header: Header {
|
||||||
vec![],
|
command_code: CommandCode::HardReset.into(),
|
||||||
);
|
a: 0x00,
|
||||||
|
b: 0x00,
|
||||||
|
c: 0x00,
|
||||||
|
d: 0x01,
|
||||||
|
},
|
||||||
|
payload: vec![],
|
||||||
|
};
|
||||||
let result = Command::try_from(p);
|
let result = Command::try_from(p);
|
||||||
assert!(matches!(
|
assert!(matches!(
|
||||||
result,
|
result,
|
||||||
|
@ -532,10 +618,16 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn error_extraneous_header_fade_out() {
|
fn error_extraneous_header_fade_out() {
|
||||||
let p = Packet(
|
let p = Packet {
|
||||||
Header(CommandCode::FadeOut.into(), 0x10, 0x00, 0x00, 0x01),
|
header: Header {
|
||||||
vec![],
|
command_code: CommandCode::FadeOut.into(),
|
||||||
);
|
a: 0x10,
|
||||||
|
b: 0x00,
|
||||||
|
c: 0x00,
|
||||||
|
d: 0x01,
|
||||||
|
},
|
||||||
|
payload: vec![],
|
||||||
|
};
|
||||||
let result = Command::try_from(p);
|
let result = Command::try_from(p);
|
||||||
assert!(matches!(
|
assert!(matches!(
|
||||||
result,
|
result,
|
||||||
|
@ -545,10 +637,16 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn error_unexpected_payload() {
|
fn error_unexpected_payload() {
|
||||||
let p = Packet(
|
let p = Packet {
|
||||||
Header(CommandCode::FadeOut.into(), 0x00, 0x00, 0x00, 0x00),
|
header: Header {
|
||||||
vec![5, 7],
|
command_code: CommandCode::FadeOut.into(),
|
||||||
);
|
a: 0x00,
|
||||||
|
b: 0x00,
|
||||||
|
c: 0x00,
|
||||||
|
d: 0x00,
|
||||||
|
},
|
||||||
|
payload: vec![5, 7],
|
||||||
|
};
|
||||||
let result = Command::try_from(p);
|
let result = Command::try_from(p);
|
||||||
assert!(matches!(
|
assert!(matches!(
|
||||||
result,
|
result,
|
||||||
|
@ -564,15 +662,19 @@ mod tests {
|
||||||
PixelGrid::new(8, 8),
|
PixelGrid::new(8, 8),
|
||||||
compression,
|
compression,
|
||||||
)
|
)
|
||||||
.into();
|
.into();
|
||||||
let Packet(header, mut payload) = p;
|
|
||||||
|
let Packet {
|
||||||
|
header,
|
||||||
|
mut payload,
|
||||||
|
} = p;
|
||||||
|
|
||||||
// mangle it
|
// mangle it
|
||||||
for byte in payload.iter_mut() {
|
for byte in payload.iter_mut() {
|
||||||
*byte -= *byte / 2;
|
*byte -= *byte / 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
let p = Packet(header, payload);
|
let p = Packet { header, payload };
|
||||||
let result = Command::try_from(p);
|
let result = Command::try_from(p);
|
||||||
if compression != CompressionCode::Uncompressed {
|
if compression != CompressionCode::Uncompressed {
|
||||||
assert_eq!(result, Err(TryFromPacketError::DecompressionFailed))
|
assert_eq!(result, Err(TryFromPacketError::DecompressionFailed))
|
||||||
|
@ -590,15 +692,18 @@ mod tests {
|
||||||
BitVec::repeat(false, 8),
|
BitVec::repeat(false, 8),
|
||||||
compression,
|
compression,
|
||||||
)
|
)
|
||||||
.into();
|
.into();
|
||||||
let Packet(header, mut payload) = p;
|
let Packet {
|
||||||
|
header,
|
||||||
|
mut payload,
|
||||||
|
} = p;
|
||||||
|
|
||||||
// mangle it
|
// mangle it
|
||||||
for byte in payload.iter_mut() {
|
for byte in payload.iter_mut() {
|
||||||
*byte -= *byte / 2;
|
*byte -= *byte / 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
let p = Packet(header, payload);
|
let p = Packet { header, payload };
|
||||||
let result = Command::try_from(p);
|
let result = Command::try_from(p);
|
||||||
if compression != CompressionCode::Uncompressed {
|
if compression != CompressionCode::Uncompressed {
|
||||||
assert_eq!(result, Err(TryFromPacketError::DecompressionFailed))
|
assert_eq!(result, Err(TryFromPacketError::DecompressionFailed))
|
||||||
|
@ -612,32 +717,59 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn unexpected_payload_size_brightness() {
|
fn unexpected_payload_size_brightness() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Command::try_from(Packet(
|
Command::try_from(Packet {
|
||||||
Header(CommandCode::Brightness.into(), 0, 0, 0, 0),
|
header: Header {
|
||||||
vec!(),
|
command_code: CommandCode::Brightness.into(),
|
||||||
)),
|
a: 0,
|
||||||
|
b: 0,
|
||||||
|
c: 0,
|
||||||
|
d: 0,
|
||||||
|
},
|
||||||
|
payload: vec!()
|
||||||
|
}),
|
||||||
Err(TryFromPacketError::UnexpectedPayloadSize(1, 0))
|
Err(TryFromPacketError::UnexpectedPayloadSize(1, 0))
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Command::try_from(Packet(
|
Command::try_from(Packet {
|
||||||
Header(CommandCode::Brightness.into(), 0, 0, 0, 0),
|
header: Header {
|
||||||
vec!(0, 0),
|
command_code: CommandCode::Brightness.into(),
|
||||||
)),
|
a: 0,
|
||||||
|
b: 0,
|
||||||
|
c: 0,
|
||||||
|
d: 0,
|
||||||
|
},
|
||||||
|
payload: vec!(0, 0)
|
||||||
|
}),
|
||||||
Err(TryFromPacketError::UnexpectedPayloadSize(1, 2))
|
Err(TryFromPacketError::UnexpectedPayloadSize(1, 2))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn error_reserved_used() {
|
fn error_reserved_used() {
|
||||||
let Packet(header, payload) = Command::BitmapLinear(
|
let Packet { header, payload } = Command::BitmapLinear(
|
||||||
0,
|
0,
|
||||||
BitVec::repeat(false, 8),
|
BitVec::repeat(false, 8),
|
||||||
CompressionCode::Uncompressed,
|
CompressionCode::Uncompressed,
|
||||||
)
|
)
|
||||||
.into();
|
.into();
|
||||||
let Header(command, offset, length, sub, _reserved) = header;
|
let Header {
|
||||||
let p = Packet(Header(command, offset, length, sub, 69), payload);
|
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!(
|
assert_eq!(
|
||||||
Command::try_from(p),
|
Command::try_from(p),
|
||||||
Err(TryFromPacketError::ExtraneousHeaderValues)
|
Err(TryFromPacketError::ExtraneousHeaderValues)
|
||||||
|
@ -646,14 +778,29 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn error_invalid_compression() {
|
fn error_invalid_compression() {
|
||||||
let Packet(header, payload) = Command::BitmapLinear(
|
let Packet { header, payload } = Command::BitmapLinear(
|
||||||
0,
|
0,
|
||||||
BitVec::repeat(false, 8),
|
BitVec::repeat(false, 8),
|
||||||
CompressionCode::Uncompressed,
|
CompressionCode::Uncompressed,
|
||||||
)
|
)
|
||||||
.into();
|
.into();
|
||||||
let Header(command, offset, length, _sub, reserved) = header;
|
let Header {
|
||||||
let p = Packet(Header(command, offset, length, 42, reserved), payload);
|
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!(
|
assert_eq!(
|
||||||
Command::try_from(p),
|
Command::try_from(p),
|
||||||
Err(TryFromPacketError::InvalidCompressionCode(42))
|
Err(TryFromPacketError::InvalidCompressionCode(42))
|
||||||
|
@ -662,17 +809,29 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn error_unexpected_size() {
|
fn error_unexpected_size() {
|
||||||
let Packet(header, payload) = Command::BitmapLinear(
|
let Packet { header, payload } = Command::BitmapLinear(
|
||||||
0,
|
0,
|
||||||
BitVec::repeat(false, 8),
|
BitVec::repeat(false, 8),
|
||||||
CompressionCode::Uncompressed,
|
CompressionCode::Uncompressed,
|
||||||
)
|
)
|
||||||
.into();
|
.into();
|
||||||
let Header(command, offset, length, compression, reserved) = header;
|
let Header {
|
||||||
let p = Packet(
|
command_code: command,
|
||||||
Header(command, offset, 420, compression, reserved),
|
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,
|
payload,
|
||||||
);
|
};
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Command::try_from(p),
|
Command::try_from(p),
|
||||||
Err(TryFromPacketError::UnexpectedPayloadSize(
|
Err(TryFromPacketError::UnexpectedPayloadSize(
|
||||||
|
|
|
@ -71,7 +71,7 @@ impl Connection {
|
||||||
Connection::Udp(socket) => {
|
Connection::Udp(socket) => {
|
||||||
socket
|
socket
|
||||||
.send(&data)
|
.send(&data)
|
||||||
.map_err(move |io_err| SendError::IoError(io_err))
|
.map_err(SendError::IoError)
|
||||||
.map(move |_| ()) // ignore Ok value
|
.map(move |_| ()) // ignore Ok value
|
||||||
}
|
}
|
||||||
Connection::Fake => Ok(()),
|
Connection::Fake => Ok(()),
|
||||||
|
|
|
@ -3,25 +3,84 @@ use std::mem::size_of;
|
||||||
use crate::command_code::CommandCode;
|
use crate::command_code::CommandCode;
|
||||||
use crate::compression::into_compressed;
|
use crate::compression::into_compressed;
|
||||||
use crate::{
|
use crate::{
|
||||||
Command, CompressionCode, Grid, Offset, Origin, PixelGrid, Pixels,
|
Command, CompressionCode, Grid, Offset, Origin, PixelGrid, Pixels, Tiles,
|
||||||
TILE_SIZE,
|
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)]
|
#[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<u8>;
|
pub type Payload = Vec<u8>;
|
||||||
|
|
||||||
/// 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<u8> = packet.into();
|
||||||
|
/// let packet = Packet::try_from(bytes).expect("could not read packet from bytes");
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[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<Packet> for Vec<u8> {
|
impl From<Packet> for Vec<u8> {
|
||||||
/// Turn the packet into raw bytes ready to send
|
/// Turn the packet into raw bytes ready to send
|
||||||
fn from(value: Packet) -> Self {
|
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()];
|
let mut packet = vec![0u8; 10 + payload.len()];
|
||||||
packet[0..=1].copy_from_slice(&u16::to_be_bytes(mode));
|
packet[0..=1].copy_from_slice(&u16::to_be_bytes(mode));
|
||||||
|
@ -36,13 +95,6 @@ impl From<Packet> for Vec<u8> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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 {
|
impl TryFrom<&[u8]> for Packet {
|
||||||
type Error = ();
|
type Error = ();
|
||||||
|
|
||||||
|
@ -54,14 +106,31 @@ impl TryFrom<&[u8]> for Packet {
|
||||||
return Err(());
|
return Err(());
|
||||||
}
|
}
|
||||||
|
|
||||||
let mode = u16_from_be_slice(&value[0..=1]);
|
let header = {
|
||||||
let a = u16_from_be_slice(&value[2..=3]);
|
let command_code = Self::u16_from_be_slice(&value[0..=1]);
|
||||||
let b = u16_from_be_slice(&value[4..=5]);
|
let a = Self::u16_from_be_slice(&value[2..=3]);
|
||||||
let c = u16_from_be_slice(&value[6..=7]);
|
let b = Self::u16_from_be_slice(&value[4..=5]);
|
||||||
let d = u16_from_be_slice(&value[8..=9]);
|
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();
|
let payload = value[10..].to_vec();
|
||||||
|
|
||||||
Ok(Packet(Header(mode, a, b, c, d), payload))
|
Ok(Packet { header, payload })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryFrom<Vec<u8>> for Packet {
|
||||||
|
type Error = ();
|
||||||
|
|
||||||
|
fn try_from(value: Vec<u8>) -> Result<Self, Self::Error> {
|
||||||
|
Self::try_from(value.as_slice())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -79,26 +148,23 @@ impl From<Command> for Packet {
|
||||||
Command::BitmapLegacy => {
|
Command::BitmapLegacy => {
|
||||||
Self::command_code_only(CommandCode::BitmapLegacy)
|
Self::command_code_only(CommandCode::BitmapLegacy)
|
||||||
}
|
}
|
||||||
Command::CharBrightness(origin, grid) => Packet(
|
Command::CharBrightness(origin, grid) => {
|
||||||
Header(
|
Self::origin_grid_to_packet(
|
||||||
CommandCode::CharBrightness.into(),
|
origin,
|
||||||
origin.x as u16,
|
grid,
|
||||||
origin.y as u16,
|
CommandCode::CharBrightness,
|
||||||
grid.width() as u16,
|
)
|
||||||
grid.height() as u16,
|
}
|
||||||
),
|
Command::Brightness(brightness) => Packet {
|
||||||
grid.into(),
|
header: Header {
|
||||||
),
|
command_code: CommandCode::Brightness.into(),
|
||||||
Command::Brightness(brightness) => Packet(
|
a: 0x00000,
|
||||||
Header(
|
b: 0x0000,
|
||||||
CommandCode::Brightness.into(),
|
c: 0x0000,
|
||||||
0x00000,
|
d: 0x0000,
|
||||||
0x0000,
|
},
|
||||||
0x0000,
|
payload: vec![brightness.into()],
|
||||||
0x0000,
|
},
|
||||||
),
|
|
||||||
vec![brightness.into()],
|
|
||||||
),
|
|
||||||
Command::BitmapLinearWin(origin, pixels, compression) => {
|
Command::BitmapLinearWin(origin, pixels, compression) => {
|
||||||
Self::bitmap_win_into_packet(origin, pixels, compression)
|
Self::bitmap_win_into_packet(origin, pixels, compression)
|
||||||
}
|
}
|
||||||
|
@ -134,15 +200,10 @@ impl From<Command> for Packet {
|
||||||
bits.into(),
|
bits.into(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
Command::Cp437Data(origin, grid) => Packet(
|
Command::Cp437Data(origin, grid) => Self::origin_grid_to_packet(
|
||||||
Header(
|
origin,
|
||||||
CommandCode::Cp437Data.into(),
|
grid,
|
||||||
origin.x as u16,
|
CommandCode::Cp437Data,
|
||||||
origin.y as u16,
|
|
||||||
grid.width() as u16,
|
|
||||||
grid.height() as u16,
|
|
||||||
),
|
|
||||||
grid.into(),
|
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -159,16 +220,16 @@ impl Packet {
|
||||||
) -> Packet {
|
) -> Packet {
|
||||||
let length = payload.len() as u16;
|
let length = payload.len() as u16;
|
||||||
let payload = into_compressed(compression, payload);
|
let payload = into_compressed(compression, payload);
|
||||||
Packet(
|
Packet {
|
||||||
Header(
|
header: Header {
|
||||||
command.into(),
|
command_code: command.into(),
|
||||||
offset as u16,
|
a: offset as u16,
|
||||||
length,
|
b: length,
|
||||||
compression.into(),
|
c: compression.into(),
|
||||||
0,
|
d: 0,
|
||||||
),
|
},
|
||||||
payload,
|
payload,
|
||||||
)
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::cast_possible_truncation)]
|
#[allow(clippy::cast_possible_truncation)]
|
||||||
|
@ -198,15 +259,54 @@ impl Packet {
|
||||||
CompressionCode::Zstd => CommandCode::BitmapLinearWinZstd,
|
CompressionCode::Zstd => CommandCode::BitmapLinearWinZstd,
|
||||||
};
|
};
|
||||||
|
|
||||||
Packet(
|
Packet {
|
||||||
Header(command.into(), tile_x, origin.y as u16, tile_w, pixel_h),
|
header: Header {
|
||||||
|
command_code: command.into(),
|
||||||
|
a: tile_x,
|
||||||
|
b: origin.y as u16,
|
||||||
|
c: tile_w,
|
||||||
|
d: pixel_h,
|
||||||
|
},
|
||||||
payload,
|
payload,
|
||||||
)
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Helper method for creating empty packets only containing the command code
|
/// Helper method for creating empty packets only containing the command code
|
||||||
fn command_code_only(code: CommandCode) -> Packet {
|
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<T>(
|
||||||
|
origin: Origin<Tiles>,
|
||||||
|
grid: impl Grid<T> + Into<Payload>,
|
||||||
|
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]
|
#[test]
|
||||||
fn round_trip() {
|
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<u8> = p.into();
|
let data: Vec<u8> = p.into();
|
||||||
let p = Packet::try_from(&*data).unwrap();
|
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]
|
#[test]
|
||||||
|
|
|
@ -105,7 +105,7 @@ typedef struct SPBrightnessGrid SPBrightnessGrid;
|
||||||
*
|
*
|
||||||
* This struct and associated functions implement the UDP protocol for the display.
|
* 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
|
* # Examples
|
||||||
*
|
*
|
||||||
|
@ -539,6 +539,13 @@ size_t sp_brightness_grid_width(const struct SPBrightnessGrid *this_);
|
||||||
* Allocates a new `Command::BitmapLinear` instance.
|
* Allocates a new `Command::BitmapLinear` instance.
|
||||||
* The passed `BitVec` gets consumed.
|
* 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
|
* # Safety
|
||||||
*
|
*
|
||||||
* The caller has to make sure that:
|
* 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.
|
* Allocates a new `Command::BitmapLinearAnd` instance.
|
||||||
* The passed `BitVec` gets consumed.
|
* 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
|
* # Safety
|
||||||
*
|
*
|
||||||
* The caller has to make sure that:
|
* 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.
|
* Allocates a new `Command::BitmapLinearOr` instance.
|
||||||
* The passed `BitVec` gets consumed.
|
* 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
|
* # Safety
|
||||||
*
|
*
|
||||||
* The caller has to make sure that:
|
* 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.
|
* Allocates a new `Command::BitmapLinearWin` instance.
|
||||||
* The passed `PixelGrid` gets consumed.
|
* The passed `PixelGrid` gets consumed.
|
||||||
*
|
*
|
||||||
|
* Sets a window of pixels to the specified values
|
||||||
|
*
|
||||||
* # Safety
|
* # Safety
|
||||||
*
|
*
|
||||||
* The caller has to make sure that:
|
* 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.
|
* Allocates a new `Command::BitmapLinearXor` instance.
|
||||||
* The passed `BitVec` gets consumed.
|
* 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
|
* # Safety
|
||||||
*
|
*
|
||||||
* The caller has to make sure that:
|
* 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.
|
* Allocates a new `Command::CharBrightness` instance.
|
||||||
* The passed `SPBrightnessGrid` gets consumed.
|
* The passed `SPBrightnessGrid` gets consumed.
|
||||||
*
|
*
|
||||||
|
* Set the brightness of individual tiles in a rectangular area of the display.
|
||||||
|
*
|
||||||
* # Safety
|
* # Safety
|
||||||
*
|
*
|
||||||
* The caller has to make sure that:
|
* 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.
|
* 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
|
* # Safety
|
||||||
*
|
*
|
||||||
* The caller has to make sure that:
|
* 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);
|
struct SPCommand *sp_command_clear(void);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clones a `Command` instance.
|
* Clones a `SPCommand` instance.
|
||||||
*
|
*
|
||||||
* # Safety
|
* # Safety
|
||||||
*
|
*
|
||||||
|
@ -690,6 +730,13 @@ struct SPCommand *sp_command_clone(const struct SPCommand *original);
|
||||||
* Allocates a new `Command::Cp437Data` instance.
|
* Allocates a new `Command::Cp437Data` instance.
|
||||||
* The passed `ByteGrid` gets consumed.
|
* 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
|
* # Safety
|
||||||
*
|
*
|
||||||
* The caller has to make sure that:
|
* The caller has to make sure that:
|
||||||
|
@ -706,6 +753,13 @@ struct SPCommand *sp_command_cp437_data(size_t x,
|
||||||
/**
|
/**
|
||||||
* Deallocates a `Command`.
|
* Deallocates a `Command`.
|
||||||
*
|
*
|
||||||
|
* # Examples
|
||||||
|
*
|
||||||
|
* ```C
|
||||||
|
* SPCommand c = sp_command_clear();
|
||||||
|
* sp_command_dealloc(c);
|
||||||
|
* ```
|
||||||
|
*
|
||||||
* # Safety
|
* # Safety
|
||||||
*
|
*
|
||||||
* The caller has to make sure that:
|
* The caller has to make sure that:
|
||||||
|
@ -731,6 +785,9 @@ struct SPCommand *sp_command_fade_out(void);
|
||||||
/**
|
/**
|
||||||
* Allocates a new `Command::HardReset` instance.
|
* 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
|
* # Safety
|
||||||
*
|
*
|
||||||
* The caller has to make sure that:
|
* 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);
|
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
|
* # Safety
|
||||||
*
|
*
|
||||||
* The caller has to make sure that:
|
* 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
|
* - `packet` is not used concurrently or after this call
|
||||||
* - the result is checked for NULL
|
* - 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`.
|
* by explicitly calling `sp_command_dealloc`.
|
||||||
*/
|
*/
|
||||||
struct SPCommand *sp_command_try_from_packet(struct SPPacket *packet);
|
struct SPCommand *sp_command_try_from_packet(struct SPPacket *packet);
|
||||||
|
|
|
@ -546,25 +546,25 @@ namespace ServicePoint.BindGen
|
||||||
public static extern ByteSlice sp_cp437_grid_unsafe_data_ref(Cp437Grid* @this);
|
public static extern ByteSlice sp_cp437_grid_unsafe_data_ref(Cp437Grid* @this);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 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
|
/// # Safety
|
||||||
///
|
///
|
||||||
/// The caller has to make sure that:
|
/// 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
|
/// - `packet` is not used concurrently or after this call
|
||||||
/// - the result is checked for NULL
|
/// - 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`.
|
/// by explicitly calling `sp_command_dealloc`.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DllImport(__DllName, EntryPoint = "sp_command_try_from_packet", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
[DllImport(__DllName, EntryPoint = "sp_command_try_from_packet", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||||
public static extern Command* sp_command_try_from_packet(Packet* packet);
|
public static extern Command* sp_command_try_from_packet(Packet* packet);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Clones a `Command` instance.
|
/// Clones a `SPCommand` instance.
|
||||||
///
|
///
|
||||||
/// # Safety
|
/// # Safety
|
||||||
///
|
///
|
||||||
|
@ -581,6 +581,14 @@ namespace ServicePoint.BindGen
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Allocates a new `Command::Clear` instance.
|
/// 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
|
/// # Safety
|
||||||
///
|
///
|
||||||
/// The caller has to make sure that:
|
/// The caller has to make sure that:
|
||||||
|
@ -594,6 +602,9 @@ namespace ServicePoint.BindGen
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Allocates a new `Command::HardReset` instance.
|
/// 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
|
/// # Safety
|
||||||
///
|
///
|
||||||
/// The caller has to make sure that:
|
/// The caller has to make sure that:
|
||||||
|
@ -639,6 +650,8 @@ namespace ServicePoint.BindGen
|
||||||
/// Allocates a new `Command::CharBrightness` instance.
|
/// Allocates a new `Command::CharBrightness` instance.
|
||||||
/// The passed `SPBrightnessGrid` gets consumed.
|
/// The passed `SPBrightnessGrid` gets consumed.
|
||||||
///
|
///
|
||||||
|
/// Set the brightness of individual tiles in a rectangular area of the display.
|
||||||
|
///
|
||||||
/// # Safety
|
/// # Safety
|
||||||
///
|
///
|
||||||
/// The caller has to make sure that:
|
/// The caller has to make sure that:
|
||||||
|
@ -655,6 +668,13 @@ namespace ServicePoint.BindGen
|
||||||
/// Allocates a new `Command::BitmapLinear` instance.
|
/// Allocates a new `Command::BitmapLinear` instance.
|
||||||
/// The passed `BitVec` gets consumed.
|
/// 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
|
/// # Safety
|
||||||
///
|
///
|
||||||
/// The caller has to make sure that:
|
/// The caller has to make sure that:
|
||||||
|
@ -672,6 +692,13 @@ namespace ServicePoint.BindGen
|
||||||
/// Allocates a new `Command::BitmapLinearAnd` instance.
|
/// Allocates a new `Command::BitmapLinearAnd` instance.
|
||||||
/// The passed `BitVec` gets consumed.
|
/// 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
|
/// # Safety
|
||||||
///
|
///
|
||||||
/// The caller has to make sure that:
|
/// The caller has to make sure that:
|
||||||
|
@ -689,6 +716,13 @@ namespace ServicePoint.BindGen
|
||||||
/// Allocates a new `Command::BitmapLinearOr` instance.
|
/// Allocates a new `Command::BitmapLinearOr` instance.
|
||||||
/// The passed `BitVec` gets consumed.
|
/// 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
|
/// # Safety
|
||||||
///
|
///
|
||||||
/// The caller has to make sure that:
|
/// The caller has to make sure that:
|
||||||
|
@ -706,6 +740,13 @@ namespace ServicePoint.BindGen
|
||||||
/// Allocates a new `Command::BitmapLinearXor` instance.
|
/// Allocates a new `Command::BitmapLinearXor` instance.
|
||||||
/// The passed `BitVec` gets consumed.
|
/// 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
|
/// # Safety
|
||||||
///
|
///
|
||||||
/// The caller has to make sure that:
|
/// The caller has to make sure that:
|
||||||
|
@ -723,6 +764,13 @@ namespace ServicePoint.BindGen
|
||||||
/// Allocates a new `Command::Cp437Data` instance.
|
/// Allocates a new `Command::Cp437Data` instance.
|
||||||
/// The passed `ByteGrid` gets consumed.
|
/// 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
|
/// # Safety
|
||||||
///
|
///
|
||||||
/// The caller has to make sure that:
|
/// The caller has to make sure that:
|
||||||
|
@ -739,6 +787,8 @@ namespace ServicePoint.BindGen
|
||||||
/// Allocates a new `Command::BitmapLinearWin` instance.
|
/// Allocates a new `Command::BitmapLinearWin` instance.
|
||||||
/// The passed `PixelGrid` gets consumed.
|
/// The passed `PixelGrid` gets consumed.
|
||||||
///
|
///
|
||||||
|
/// Sets a window of pixels to the specified values
|
||||||
|
///
|
||||||
/// # Safety
|
/// # Safety
|
||||||
///
|
///
|
||||||
/// The caller has to make sure that:
|
/// The caller has to make sure that:
|
||||||
|
@ -755,6 +805,13 @@ namespace ServicePoint.BindGen
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Deallocates a `Command`.
|
/// Deallocates a `Command`.
|
||||||
///
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```C
|
||||||
|
/// SPCommand c = sp_command_clear();
|
||||||
|
/// sp_command_dealloc(c);
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
/// # Safety
|
/// # Safety
|
||||||
///
|
///
|
||||||
/// The caller has to make sure that:
|
/// The caller has to make sure that:
|
||||||
|
|
Loading…
Reference in a new issue