mirror of
https://github.com/cccb/servicepoint.git
synced 2025-01-18 02:00:12 +01:00
reformat with max width
This commit is contained in:
parent
0a3f400e92
commit
362426c758
|
@ -1,4 +1,5 @@
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
|
|
||||||
use servicepoint2::{ByteGrid, Command, Connection, Origin};
|
use servicepoint2::{ByteGrid, Command, Connection, Origin};
|
||||||
|
|
||||||
#[derive(Parser, Debug)]
|
#[derive(Parser, Debug)]
|
||||||
|
@ -44,5 +45,7 @@ fn main() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
connection.send(Command::Cp437Data(Origin::top_left(), chars)).unwrap();
|
connection
|
||||||
|
.send(Command::Cp437Data(Origin::top_left(), chars))
|
||||||
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
use std::thread;
|
use std::thread;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use rand::{distributions, Rng};
|
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
use servicepoint2::{Connection, Origin, PixelGrid};
|
use rand::{distributions, Rng};
|
||||||
|
|
||||||
use servicepoint2::Command::BitmapLinearWin;
|
use servicepoint2::Command::BitmapLinearWin;
|
||||||
|
use servicepoint2::{Connection, Origin, PixelGrid};
|
||||||
|
|
||||||
#[derive(Parser, Debug)]
|
#[derive(Parser, Debug)]
|
||||||
struct Cli {
|
struct Cli {
|
||||||
|
@ -23,7 +25,9 @@ fn main() {
|
||||||
let mut field = make_random_field(cli.probability);
|
let mut field = make_random_field(cli.probability);
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
connection.send(BitmapLinearWin(Origin::top_left(), field.clone())).expect("could not send");
|
connection
|
||||||
|
.send(BitmapLinearWin(Origin::top_left(), field.clone()))
|
||||||
|
.expect("could not send");
|
||||||
thread::sleep(Duration::from_millis(14));
|
thread::sleep(Duration::from_millis(14));
|
||||||
field = iteration(field);
|
field = iteration(field);
|
||||||
}
|
}
|
||||||
|
@ -39,7 +43,7 @@ fn iteration(field: PixelGrid) -> PixelGrid {
|
||||||
(true, 2) => true,
|
(true, 2) => true,
|
||||||
(true, 3) => true,
|
(true, 3) => true,
|
||||||
(false, 3) => true,
|
(false, 3) => true,
|
||||||
_ => false
|
_ => false,
|
||||||
};
|
};
|
||||||
next.set(x, y, new_state);
|
next.set(x, y, new_state);
|
||||||
}
|
}
|
||||||
|
@ -55,7 +59,11 @@ fn count_neighbors(field: &PixelGrid, x: i32, y: i32) -> i32 {
|
||||||
continue; // the cell itself does not count
|
continue; // the cell itself does not count
|
||||||
}
|
}
|
||||||
|
|
||||||
if nx < 0 || ny < 0 || nx >= field.width as i32 || ny >= field.height as i32 {
|
if nx < 0
|
||||||
|
|| ny < 0
|
||||||
|
|| nx >= field.width as i32
|
||||||
|
|| ny >= field.height as i32
|
||||||
|
{
|
||||||
continue; // pixels outside the grid do not count
|
continue; // pixels outside the grid do not count
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
use std::thread;
|
use std::thread;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
use servicepoint2::{Connection, Origin, PIXEL_HEIGHT, PIXEL_WIDTH, PixelGrid};
|
|
||||||
use servicepoint2::Command::BitmapLinearWin;
|
use servicepoint2::Command::BitmapLinearWin;
|
||||||
|
use servicepoint2::{Connection, Origin, PixelGrid, PIXEL_HEIGHT, PIXEL_WIDTH};
|
||||||
|
|
||||||
#[derive(Parser, Debug)]
|
#[derive(Parser, Debug)]
|
||||||
struct Cli {
|
struct Cli {
|
||||||
|
@ -24,7 +26,9 @@ fn main() {
|
||||||
for y in 0..PIXEL_HEIGHT as usize {
|
for y in 0..PIXEL_HEIGHT as usize {
|
||||||
pixels.set((y + x_offset) % PIXEL_WIDTH as usize, y, true);
|
pixels.set((y + x_offset) % PIXEL_WIDTH as usize, y, true);
|
||||||
}
|
}
|
||||||
connection.send(BitmapLinearWin(Origin::top_left(), pixels.clone())).unwrap();
|
connection
|
||||||
|
.send(BitmapLinearWin(Origin::top_left(), pixels.clone()))
|
||||||
|
.unwrap();
|
||||||
thread::sleep(Duration::from_millis(14));
|
thread::sleep(Duration::from_millis(14));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,12 @@
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
use rand::Rng;
|
use rand::Rng;
|
||||||
use servicepoint2::{ByteGrid, Connection, Origin, PixelGrid, TILE_HEIGHT, TILE_WIDTH};
|
|
||||||
use servicepoint2::Command::{Brightness, CharBrightness, BitmapLinearWin};
|
use servicepoint2::Command::{BitmapLinearWin, Brightness, CharBrightness};
|
||||||
|
use servicepoint2::{
|
||||||
|
ByteGrid, Connection, Origin, PixelGrid, TILE_HEIGHT, TILE_WIDTH,
|
||||||
|
};
|
||||||
|
|
||||||
#[derive(Parser, Debug)]
|
#[derive(Parser, Debug)]
|
||||||
struct Cli {
|
struct Cli {
|
||||||
|
@ -27,7 +31,9 @@ fn main() {
|
||||||
if cli.enable_all {
|
if cli.enable_all {
|
||||||
let mut filled_grid = PixelGrid::max_sized();
|
let mut filled_grid = PixelGrid::max_sized();
|
||||||
filled_grid.fill(true);
|
filled_grid.fill(true);
|
||||||
connection.send(BitmapLinearWin(Origin::top_left(), filled_grid)).unwrap();
|
connection
|
||||||
|
.send(BitmapLinearWin(Origin::top_left(), filled_grid))
|
||||||
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
// set all pixels to the same random brightness
|
// set all pixels to the same random brightness
|
||||||
|
|
|
@ -3,8 +3,10 @@ use std::time::Duration;
|
||||||
|
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
|
|
||||||
use servicepoint2::{BitVec, CompressionCode, Connection, PIXEL_HEIGHT, PIXEL_WIDTH, PixelGrid};
|
|
||||||
use servicepoint2::Command::BitmapLinearAnd;
|
use servicepoint2::Command::BitmapLinearAnd;
|
||||||
|
use servicepoint2::{
|
||||||
|
BitVec, CompressionCode, Connection, PixelGrid, PIXEL_HEIGHT, PIXEL_WIDTH,
|
||||||
|
};
|
||||||
|
|
||||||
#[derive(Parser, Debug)]
|
#[derive(Parser, Debug)]
|
||||||
struct Cli {
|
struct Cli {
|
||||||
|
@ -21,7 +23,8 @@ fn main() {
|
||||||
let connection = Connection::open(cli.destination).unwrap();
|
let connection = Connection::open(cli.destination).unwrap();
|
||||||
let sleep_duration = Duration::from_millis(cli.time / PIXEL_WIDTH as u64);
|
let sleep_duration = Duration::from_millis(cli.time / PIXEL_WIDTH as u64);
|
||||||
|
|
||||||
let mut enabled_pixels = PixelGrid::new(PIXEL_WIDTH as usize, PIXEL_HEIGHT as usize);
|
let mut enabled_pixels =
|
||||||
|
PixelGrid::new(PIXEL_WIDTH as usize, PIXEL_HEIGHT as usize);
|
||||||
enabled_pixels.fill(true);
|
enabled_pixels.fill(true);
|
||||||
|
|
||||||
for x_offset in 0..PIXEL_WIDTH as usize {
|
for x_offset in 0..PIXEL_WIDTH as usize {
|
||||||
|
@ -33,7 +36,9 @@ fn main() {
|
||||||
let pixel_data: Vec<u8> = enabled_pixels.clone().into();
|
let pixel_data: Vec<u8> = enabled_pixels.clone().into();
|
||||||
let bit_vec = BitVec::load(&*pixel_data);
|
let bit_vec = BitVec::load(&*pixel_data);
|
||||||
|
|
||||||
connection.send(BitmapLinearAnd(0, bit_vec, CompressionCode::Gz)).unwrap();
|
connection
|
||||||
|
.send(BitmapLinearAnd(0, bit_vec, CompressionCode::Gz))
|
||||||
|
.unwrap();
|
||||||
thread::sleep(sleep_duration);
|
thread::sleep(sleep_duration);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
1
rustfmt.toml
Normal file
1
rustfmt.toml
Normal file
|
@ -0,0 +1 @@
|
||||||
|
max_width = 80
|
|
@ -7,11 +7,15 @@ pub struct BitVec {
|
||||||
impl BitVec {
|
impl BitVec {
|
||||||
pub fn new(size: usize) -> BitVec {
|
pub fn new(size: usize) -> BitVec {
|
||||||
assert_eq!(size % 8, 0);
|
assert_eq!(size % 8, 0);
|
||||||
Self { data: vec!(0; size / 8) }
|
Self {
|
||||||
|
data: vec![0; size / 8],
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn load(data: &[u8]) -> BitVec {
|
pub fn load(data: &[u8]) -> BitVec {
|
||||||
Self { data: Vec::from(data) }
|
Self {
|
||||||
|
data: Vec::from(data),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set(&mut self, index: usize, value: bool) -> bool {
|
pub fn set(&mut self, index: usize, value: bool) -> bool {
|
||||||
|
|
|
@ -31,7 +31,7 @@ impl ByteGrid {
|
||||||
self.data[x + y * self.width] = value;
|
self.data[x + y * self.width] = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn fill(&mut self, value: u8){
|
pub fn fill(&mut self, value: u8) {
|
||||||
self.data.fill(value)
|
self.data.fill(value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
179
src/command.rs
179
src/command.rs
|
@ -1,7 +1,6 @@
|
||||||
use crate::{BitVec, ByteGrid, Header, Packet, PixelGrid, TILE_SIZE};
|
|
||||||
use crate::command_codes::{CommandCode, CompressionCode};
|
use crate::command_codes::{CommandCode, CompressionCode};
|
||||||
use crate::compression::{into_compressed, into_decompressed};
|
use crate::compression::{into_compressed, into_decompressed};
|
||||||
|
use crate::{BitVec, ByteGrid, Header, Packet, PixelGrid, TILE_SIZE};
|
||||||
|
|
||||||
/// An origin marks the top left position of the
|
/// An origin marks the top left position of the
|
||||||
/// data sent to the display.
|
/// data sent to the display.
|
||||||
|
@ -46,45 +45,77 @@ impl Into<Packet> for Command {
|
||||||
Command::FadeOut => command_code_only(CommandCode::FadeOut),
|
Command::FadeOut => command_code_only(CommandCode::FadeOut),
|
||||||
Command::HardReset => command_code_only(CommandCode::HardReset),
|
Command::HardReset => command_code_only(CommandCode::HardReset),
|
||||||
#[allow(deprecated)]
|
#[allow(deprecated)]
|
||||||
Command::BitmapLegacy => command_code_only(CommandCode::BitmapLegacy),
|
Command::BitmapLegacy => {
|
||||||
Command::CharBrightness(origin, grid) => {
|
command_code_only(CommandCode::BitmapLegacy)
|
||||||
origin_size_payload(CommandCode::CharBrightness,
|
|
||||||
origin,
|
|
||||||
Size(grid.width as u16, grid.height as u16),
|
|
||||||
grid.into())
|
|
||||||
}
|
|
||||||
Command::Brightness(brightness) => {
|
|
||||||
Packet(Header(CommandCode::Brightness.to_primitive(), 0x00000, 0x0000, 0x0000, 0x0000), vec!(brightness))
|
|
||||||
}
|
}
|
||||||
|
Command::CharBrightness(origin, grid) => origin_size_payload(
|
||||||
|
CommandCode::CharBrightness,
|
||||||
|
origin,
|
||||||
|
Size(grid.width as u16, grid.height as u16),
|
||||||
|
grid.into(),
|
||||||
|
),
|
||||||
|
Command::Brightness(brightness) => Packet(
|
||||||
|
Header(
|
||||||
|
CommandCode::Brightness.to_primitive(),
|
||||||
|
0x00000,
|
||||||
|
0x0000,
|
||||||
|
0x0000,
|
||||||
|
0x0000,
|
||||||
|
),
|
||||||
|
vec![brightness],
|
||||||
|
),
|
||||||
Command::BitmapLinearWin(Origin(pixel_x, pixel_y), pixels) => {
|
Command::BitmapLinearWin(Origin(pixel_x, pixel_y), pixels) => {
|
||||||
debug_assert_eq!(pixel_x % 8, 0);
|
debug_assert_eq!(pixel_x % 8, 0);
|
||||||
debug_assert_eq!(pixels.width % 8, 0);
|
debug_assert_eq!(pixels.width % 8, 0);
|
||||||
Packet(
|
Packet(
|
||||||
Header(CommandCode::BitmapLinearWin.to_primitive(),
|
Header(
|
||||||
pixel_x / TILE_SIZE,
|
CommandCode::BitmapLinearWin.to_primitive(),
|
||||||
pixel_y,
|
pixel_x / TILE_SIZE,
|
||||||
pixels.width as u16 / TILE_SIZE,
|
pixel_y,
|
||||||
pixels.height as u16),
|
pixels.width as u16 / TILE_SIZE,
|
||||||
pixels.into())
|
pixels.height as u16,
|
||||||
|
),
|
||||||
|
pixels.into(),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
Command::BitmapLinear(offset, bits, compression) => {
|
Command::BitmapLinear(offset, bits, compression) => {
|
||||||
bitmap_linear_into_packet(CommandCode::BitmapLinear, offset, compression, bits.into())
|
bitmap_linear_into_packet(
|
||||||
|
CommandCode::BitmapLinear,
|
||||||
|
offset,
|
||||||
|
compression,
|
||||||
|
bits.into(),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
Command::BitmapLinearAnd(offset, bits, compression) => {
|
Command::BitmapLinearAnd(offset, bits, compression) => {
|
||||||
bitmap_linear_into_packet(CommandCode::BitmapLinearAnd, offset, compression, bits.into())
|
bitmap_linear_into_packet(
|
||||||
|
CommandCode::BitmapLinearAnd,
|
||||||
|
offset,
|
||||||
|
compression,
|
||||||
|
bits.into(),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
Command::BitmapLinearOr(offset, bits, compression) => {
|
Command::BitmapLinearOr(offset, bits, compression) => {
|
||||||
bitmap_linear_into_packet(CommandCode::BitmapLinearOr, offset, compression, bits.into())
|
bitmap_linear_into_packet(
|
||||||
|
CommandCode::BitmapLinearOr,
|
||||||
|
offset,
|
||||||
|
compression,
|
||||||
|
bits.into(),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
Command::BitmapLinearXor(offset, bits, compression) => {
|
Command::BitmapLinearXor(offset, bits, compression) => {
|
||||||
bitmap_linear_into_packet(CommandCode::BitmapLinearXor, offset, compression, bits.into())
|
bitmap_linear_into_packet(
|
||||||
}
|
CommandCode::BitmapLinearXor,
|
||||||
Command::Cp437Data(origin, grid) => {
|
offset,
|
||||||
origin_size_payload(CommandCode::Cp437Data,
|
compression,
|
||||||
origin,
|
bits.into(),
|
||||||
Size(grid.width as u16, grid.height as u16),
|
)
|
||||||
grid.into())
|
|
||||||
}
|
}
|
||||||
|
Command::Cp437Data(origin, grid) => origin_size_payload(
|
||||||
|
CommandCode::Cp437Data,
|
||||||
|
origin,
|
||||||
|
Size(grid.width as u16, grid.height as u16),
|
||||||
|
grid.into(),
|
||||||
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -104,21 +135,24 @@ impl TryFrom<Packet> for Command {
|
||||||
fn try_from(value: Packet) -> Result<Self, Self::Error> {
|
fn try_from(value: Packet) -> Result<Self, Self::Error> {
|
||||||
let Packet(Header(command_u16, a, b, c, d), _) = value;
|
let Packet(Header(command_u16, a, b, c, d), _) = value;
|
||||||
let command_code = match CommandCode::from_primitive(command_u16) {
|
let command_code = match CommandCode::from_primitive(command_u16) {
|
||||||
None => return Err(TryFromPacketError::InvalidCommand(command_u16)),
|
None => {
|
||||||
Some(value) => value
|
return Err(TryFromPacketError::InvalidCommand(command_u16))
|
||||||
|
}
|
||||||
|
Some(value) => value,
|
||||||
};
|
};
|
||||||
|
|
||||||
match command_code {
|
match command_code {
|
||||||
CommandCode::Clear => {
|
CommandCode::Clear => match check_command_only(value) {
|
||||||
match check_command_only(value) {
|
Some(err) => Err(err),
|
||||||
Some(err) => Err(err),
|
None => Ok(Command::Clear),
|
||||||
None => Ok(Command::Clear),
|
},
|
||||||
}
|
|
||||||
}
|
|
||||||
CommandCode::Brightness => {
|
CommandCode::Brightness => {
|
||||||
let Packet(header, payload) = value;
|
let Packet(header, payload) = value;
|
||||||
if payload.len() != 1 {
|
if payload.len() != 1 {
|
||||||
return Err(TryFromPacketError::UnexpectedPayloadSize(1, payload.len()));
|
return Err(TryFromPacketError::UnexpectedPayloadSize(
|
||||||
|
1,
|
||||||
|
payload.len(),
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
match check_empty_header(header) {
|
match check_empty_header(header) {
|
||||||
|
@ -126,18 +160,14 @@ impl TryFrom<Packet> for Command {
|
||||||
None => Ok(Command::Brightness(payload[0])),
|
None => Ok(Command::Brightness(payload[0])),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
CommandCode::HardReset => {
|
CommandCode::HardReset => match check_command_only(value) {
|
||||||
match check_command_only(value) {
|
Some(err) => Err(err),
|
||||||
Some(err) => Err(err),
|
None => Ok(Command::HardReset),
|
||||||
None => Ok(Command::HardReset),
|
},
|
||||||
}
|
CommandCode::FadeOut => match check_command_only(value) {
|
||||||
}
|
Some(err) => Err(err),
|
||||||
CommandCode::FadeOut => {
|
None => Ok(Command::FadeOut),
|
||||||
match check_command_only(value) {
|
},
|
||||||
Some(err) => Err(err),
|
|
||||||
None => Ok(Command::FadeOut),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
CommandCode::Cp437Data => {
|
CommandCode::Cp437Data => {
|
||||||
let Packet(_, payload) = value;
|
let Packet(_, payload) = value;
|
||||||
Ok(Command::Cp437Data(
|
Ok(Command::Cp437Data(
|
||||||
|
@ -153,14 +183,16 @@ impl TryFrom<Packet> for Command {
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
#[allow(deprecated)]
|
#[allow(deprecated)]
|
||||||
CommandCode::BitmapLegacy => {
|
CommandCode::BitmapLegacy => Ok(Command::BitmapLegacy),
|
||||||
Ok(Command::BitmapLegacy)
|
|
||||||
}
|
|
||||||
CommandCode::BitmapLinearWin => {
|
CommandCode::BitmapLinearWin => {
|
||||||
let Packet(_, payload) = value;
|
let Packet(_, payload) = value;
|
||||||
Ok(Command::BitmapLinearWin(
|
Ok(Command::BitmapLinearWin(
|
||||||
Origin(a * TILE_SIZE, b),
|
Origin(a * TILE_SIZE, b),
|
||||||
PixelGrid::load(c as usize * TILE_SIZE as usize, d as usize, &payload),
|
PixelGrid::load(
|
||||||
|
c as usize * TILE_SIZE as usize,
|
||||||
|
d as usize,
|
||||||
|
&payload,
|
||||||
|
),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
CommandCode::BitmapLinear => {
|
CommandCode::BitmapLinear => {
|
||||||
|
@ -183,20 +215,42 @@ impl TryFrom<Packet> for Command {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn bitmap_linear_into_packet(command: CommandCode, offset: Offset, compression: CompressionCode, payload: Vec<u8>) -> Packet {
|
fn bitmap_linear_into_packet(
|
||||||
|
command: CommandCode,
|
||||||
|
offset: Offset,
|
||||||
|
compression: CompressionCode,
|
||||||
|
payload: Vec<u8>,
|
||||||
|
) -> Packet {
|
||||||
let payload = into_compressed(compression, payload);
|
let payload = into_compressed(compression, payload);
|
||||||
let compression = CompressionCode::to_primitive(&compression);
|
let compression = CompressionCode::to_primitive(&compression);
|
||||||
Packet(Header(command.to_primitive(), offset, payload.len() as u16, compression, 0), payload)
|
Packet(
|
||||||
|
Header(
|
||||||
|
command.to_primitive(),
|
||||||
|
offset,
|
||||||
|
payload.len() as u16,
|
||||||
|
compression,
|
||||||
|
0,
|
||||||
|
),
|
||||||
|
payload,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn origin_size_payload(command: CommandCode, origin: Origin, size: Size, payload: Vec<u8>) -> Packet {
|
fn origin_size_payload(
|
||||||
|
command: CommandCode,
|
||||||
|
origin: Origin,
|
||||||
|
size: Size,
|
||||||
|
payload: Vec<u8>,
|
||||||
|
) -> Packet {
|
||||||
let Origin(x, y) = origin;
|
let Origin(x, y) = origin;
|
||||||
let Size(w, h) = size;
|
let Size(w, h) = size;
|
||||||
Packet(Header(command.to_primitive(), x, y, w, h), payload.into())
|
Packet(Header(command.to_primitive(), x, y, w, h), payload.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn command_code_only(code: CommandCode) -> Packet {
|
fn command_code_only(code: CommandCode) -> Packet {
|
||||||
Packet(Header(code.to_primitive(), 0x0000, 0x0000, 0x0000, 0x0000), vec!())
|
Packet(
|
||||||
|
Header(code.to_primitive(), 0x0000, 0x0000, 0x0000, 0x0000),
|
||||||
|
vec![],
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_empty_header(header: Header) -> Option<TryFromPacketError> {
|
fn check_empty_header(header: Header) -> Option<TryFromPacketError> {
|
||||||
|
@ -219,21 +273,26 @@ fn check_command_only(packet: Packet) -> Option<TryFromPacketError> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn packet_into_linear_bitmap(packet: Packet) -> Result<(BitVec, CompressionCode), TryFromPacketError> {
|
fn packet_into_linear_bitmap(
|
||||||
|
packet: Packet,
|
||||||
|
) -> Result<(BitVec, CompressionCode), TryFromPacketError> {
|
||||||
let Packet(Header(_, _, length, sub, reserved), payload) = packet;
|
let Packet(Header(_, _, length, sub, reserved), payload) = packet;
|
||||||
if reserved != 0 {
|
if reserved != 0 {
|
||||||
return Err(TryFromPacketError::ExtraneousHeaderValues);
|
return Err(TryFromPacketError::ExtraneousHeaderValues);
|
||||||
}
|
}
|
||||||
if payload.len() != length as usize {
|
if payload.len() != length as usize {
|
||||||
return Err(TryFromPacketError::UnexpectedPayloadSize(length as usize, payload.len()));
|
return Err(TryFromPacketError::UnexpectedPayloadSize(
|
||||||
|
length as usize,
|
||||||
|
payload.len(),
|
||||||
|
));
|
||||||
}
|
}
|
||||||
let sub = match CompressionCode::from_primitive(sub) {
|
let sub = match CompressionCode::from_primitive(sub) {
|
||||||
None => return Err(TryFromPacketError::InvalidCompressionCode(sub)),
|
None => return Err(TryFromPacketError::InvalidCompressionCode(sub)),
|
||||||
Some(value) => value
|
Some(value) => value,
|
||||||
};
|
};
|
||||||
let payload = match into_decompressed(sub, payload) {
|
let payload = match into_decompressed(sub, payload) {
|
||||||
None => return Err(TryFromPacketError::DecompressionFailed),
|
None => return Err(TryFromPacketError::DecompressionFailed),
|
||||||
Some(value) => value
|
Some(value) => value,
|
||||||
};
|
};
|
||||||
Ok((BitVec::load(&payload), sub))
|
Ok((BitVec::load(&payload), sub))
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,70 +1,78 @@
|
||||||
use crate::{CompressionCode, Payload};
|
|
||||||
use std::io::{Read, Write};
|
use std::io::{Read, Write};
|
||||||
|
|
||||||
#[cfg(feature = "compression-bz")]
|
#[cfg(feature = "compression-bz")]
|
||||||
use bzip2::read::{BzEncoder, BzDecoder};
|
use bzip2::read::{BzDecoder, BzEncoder};
|
||||||
#[cfg(feature = "compression-gz")]
|
#[cfg(feature = "compression-gz")]
|
||||||
use flate2::read::{GzEncoder, GzDecoder};
|
use flate2::read::{GzDecoder, GzEncoder};
|
||||||
#[cfg(feature = "compression-lz")]
|
#[cfg(feature = "compression-lz")]
|
||||||
use lz4::{EncoderBuilder as Lz4EncoderBuilder, Decoder as Lz4Decoder};
|
use lz4::{Decoder as Lz4Decoder, EncoderBuilder as Lz4EncoderBuilder};
|
||||||
#[cfg(feature = "compression-zs")]
|
#[cfg(feature = "compression-zs")]
|
||||||
use zstd::{Encoder as ZstdEncoder, Decoder as ZstdDecoder};
|
use zstd::{Decoder as ZstdDecoder, Encoder as ZstdEncoder};
|
||||||
|
|
||||||
pub(crate) fn into_decompressed(kind: CompressionCode, payload: Payload) -> Option<Payload> {
|
use crate::{CompressionCode, Payload};
|
||||||
|
|
||||||
|
pub(crate) fn into_decompressed(
|
||||||
|
kind: CompressionCode,
|
||||||
|
payload: Payload,
|
||||||
|
) -> Option<Payload> {
|
||||||
match kind {
|
match kind {
|
||||||
CompressionCode::None => Some(payload),
|
CompressionCode::None => Some(payload),
|
||||||
#[cfg(feature = "compression-gz")]
|
#[cfg(feature = "compression-gz")]
|
||||||
CompressionCode::Gz => {
|
CompressionCode::Gz => {
|
||||||
let mut decoder = GzDecoder::new(&*payload);
|
let mut decoder = GzDecoder::new(&*payload);
|
||||||
let mut decompressed = vec!();
|
let mut decompressed = vec![];
|
||||||
match decoder.read_to_end(&mut decompressed) {
|
match decoder.read_to_end(&mut decompressed) {
|
||||||
Err(_) => None,
|
Err(_) => None,
|
||||||
Ok(_) => Some(decompressed)
|
Ok(_) => Some(decompressed),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[cfg(feature = "compression-bz")]
|
#[cfg(feature = "compression-bz")]
|
||||||
CompressionCode::Bz => {
|
CompressionCode::Bz => {
|
||||||
let mut decoder = BzDecoder::new(&*payload);
|
let mut decoder = BzDecoder::new(&*payload);
|
||||||
let mut decompressed = vec!();
|
let mut decompressed = vec![];
|
||||||
match decoder.read_to_end(&mut decompressed) {
|
match decoder.read_to_end(&mut decompressed) {
|
||||||
Err(_) => None,
|
Err(_) => None,
|
||||||
Ok(_) => Some(decompressed)
|
Ok(_) => Some(decompressed),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[cfg(feature = "compression-lz")]
|
#[cfg(feature = "compression-lz")]
|
||||||
CompressionCode::Lz => {
|
CompressionCode::Lz => {
|
||||||
let mut decoder = match Lz4Decoder::new(&*payload) {
|
let mut decoder = match Lz4Decoder::new(&*payload) {
|
||||||
Err(_) => return None,
|
Err(_) => return None,
|
||||||
Ok(value) => value
|
Ok(value) => value,
|
||||||
};
|
};
|
||||||
let mut decompressed = vec!();
|
let mut decompressed = vec![];
|
||||||
match decoder.read_to_end(&mut decompressed) {
|
match decoder.read_to_end(&mut decompressed) {
|
||||||
Err(_) => None,
|
Err(_) => None,
|
||||||
Ok(_) => Some(decompressed)
|
Ok(_) => Some(decompressed),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[cfg(feature = "compression-zs")]
|
#[cfg(feature = "compression-zs")]
|
||||||
CompressionCode::Zs => {
|
CompressionCode::Zs => {
|
||||||
let mut decoder = match ZstdDecoder::new(&*payload) {
|
let mut decoder = match ZstdDecoder::new(&*payload) {
|
||||||
Err(_) => return None,
|
Err(_) => return None,
|
||||||
Ok(value) => value
|
Ok(value) => value,
|
||||||
};
|
};
|
||||||
let mut decompressed = vec!();
|
let mut decompressed = vec![];
|
||||||
match decoder.read_to_end(&mut decompressed) {
|
match decoder.read_to_end(&mut decompressed) {
|
||||||
Err(_) => None,
|
Err(_) => None,
|
||||||
Ok(_) => Some(decompressed)
|
Ok(_) => Some(decompressed),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn into_compressed(kind: CompressionCode, payload: Payload) -> Payload {
|
pub(crate) fn into_compressed(
|
||||||
|
kind: CompressionCode,
|
||||||
|
payload: Payload,
|
||||||
|
) -> Payload {
|
||||||
match kind {
|
match kind {
|
||||||
CompressionCode::None => payload,
|
CompressionCode::None => payload,
|
||||||
#[cfg(feature = "compression-gz")]
|
#[cfg(feature = "compression-gz")]
|
||||||
CompressionCode::Gz => {
|
CompressionCode::Gz => {
|
||||||
let mut encoder = GzEncoder::new(&*payload, flate2::Compression::fast());
|
let mut encoder =
|
||||||
let mut compressed = vec!();
|
GzEncoder::new(&*payload, flate2::Compression::fast());
|
||||||
|
let mut compressed = vec![];
|
||||||
match encoder.read_to_end(&mut compressed) {
|
match encoder.read_to_end(&mut compressed) {
|
||||||
Err(err) => panic!("could not compress payload: {}", err),
|
Err(err) => panic!("could not compress payload: {}", err),
|
||||||
Ok(_) => compressed,
|
Ok(_) => compressed,
|
||||||
|
@ -72,8 +80,9 @@ pub(crate) fn into_compressed(kind: CompressionCode, payload: Payload) -> Payloa
|
||||||
}
|
}
|
||||||
#[cfg(feature = "compression-bz")]
|
#[cfg(feature = "compression-bz")]
|
||||||
CompressionCode::Bz => {
|
CompressionCode::Bz => {
|
||||||
let mut encoder = BzEncoder::new(&*payload, bzip2::Compression::fast());
|
let mut encoder =
|
||||||
let mut compressed = vec!();
|
BzEncoder::new(&*payload, bzip2::Compression::fast());
|
||||||
|
let mut compressed = vec![];
|
||||||
match encoder.read_to_end(&mut compressed) {
|
match encoder.read_to_end(&mut compressed) {
|
||||||
Err(err) => panic!("could not compress payload: {}", err),
|
Err(err) => panic!("could not compress payload: {}", err),
|
||||||
Ok(_) => compressed,
|
Ok(_) => compressed,
|
||||||
|
@ -82,22 +91,21 @@ pub(crate) fn into_compressed(kind: CompressionCode, payload: Payload) -> Payloa
|
||||||
#[cfg(feature = "compression-lz")]
|
#[cfg(feature = "compression-lz")]
|
||||||
CompressionCode::Lz => {
|
CompressionCode::Lz => {
|
||||||
let mut encoder = Lz4EncoderBuilder::new()
|
let mut encoder = Lz4EncoderBuilder::new()
|
||||||
.build(vec!())
|
.build(vec![])
|
||||||
.expect("could not create encoder");
|
.expect("could not create encoder");
|
||||||
encoder.write(&*payload)
|
encoder.write(&*payload).expect("could not write payload");
|
||||||
.expect("could not write payload");
|
|
||||||
let (payload, _) = encoder.finish();
|
let (payload, _) = encoder.finish();
|
||||||
payload
|
payload
|
||||||
}
|
}
|
||||||
#[cfg(feature = "compression-zs")]
|
#[cfg(feature = "compression-zs")]
|
||||||
CompressionCode::Zs => {
|
CompressionCode::Zs => {
|
||||||
let mut encoder = ZstdEncoder::new(vec!(), zstd::DEFAULT_COMPRESSION_LEVEL)
|
let mut encoder =
|
||||||
.expect("could not create encoder");
|
ZstdEncoder::new(vec![], zstd::DEFAULT_COMPRESSION_LEVEL)
|
||||||
encoder.write(&*payload)
|
.expect("could not create encoder");
|
||||||
|
encoder
|
||||||
|
.write(&*payload)
|
||||||
.expect("could not compress payload");
|
.expect("could not compress payload");
|
||||||
encoder.finish()
|
encoder.finish().expect("could not finish encoding")
|
||||||
.expect("could not finish encoding")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
use std::net::{ToSocketAddrs, UdpSocket};
|
use std::net::{ToSocketAddrs, UdpSocket};
|
||||||
|
|
||||||
use log::{debug, info};
|
use log::{debug, info};
|
||||||
|
|
||||||
use crate::Packet;
|
use crate::Packet;
|
||||||
|
|
||||||
pub struct Connection {
|
pub struct Connection {
|
||||||
|
@ -17,7 +19,10 @@ impl Connection {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Send a command to the display
|
/// Send a command to the display
|
||||||
pub fn send(&self, packet: impl Into<Packet> + Debug) -> Result<(), std::io::Error> {
|
pub fn send(
|
||||||
|
&self,
|
||||||
|
packet: impl Into<Packet> + Debug,
|
||||||
|
) -> Result<(), std::io::Error> {
|
||||||
debug!("sending {packet:?}");
|
debug!("sending {packet:?}");
|
||||||
let packet: Packet = packet.into();
|
let packet: Packet = packet.into();
|
||||||
let data: Vec<u8> = packet.into();
|
let data: Vec<u8> = packet.into();
|
||||||
|
|
24
src/lib.rs
24
src/lib.rs
|
@ -1,19 +1,19 @@
|
||||||
mod connection;
|
pub use crate::bit_vec::BitVec;
|
||||||
mod pixel_grid;
|
pub use crate::byte_grid::ByteGrid;
|
||||||
|
pub use crate::command::{Command, Origin, Size};
|
||||||
|
pub use crate::command_codes::{CommandCode, CompressionCode};
|
||||||
|
pub use crate::connection::Connection;
|
||||||
|
pub use crate::packet::{Header, Packet, Payload};
|
||||||
|
pub use crate::pixel_grid::PixelGrid;
|
||||||
|
|
||||||
mod bit_vec;
|
mod bit_vec;
|
||||||
mod packet;
|
mod byte_grid;
|
||||||
mod command;
|
mod command;
|
||||||
mod command_codes;
|
mod command_codes;
|
||||||
mod byte_grid;
|
|
||||||
mod compression;
|
mod compression;
|
||||||
|
mod connection;
|
||||||
pub use crate::connection::Connection;
|
mod packet;
|
||||||
pub use crate::pixel_grid::PixelGrid;
|
mod pixel_grid;
|
||||||
pub use crate::bit_vec::BitVec;
|
|
||||||
pub use crate::packet::{Packet, Header, Payload};
|
|
||||||
pub use crate::command::{Command, Size, Origin};
|
|
||||||
pub use crate::command_codes::{CommandCode, CompressionCode};
|
|
||||||
pub use crate::byte_grid::ByteGrid;
|
|
||||||
|
|
||||||
pub const TILE_SIZE: u16 = 8;
|
pub const TILE_SIZE: u16 = 8;
|
||||||
pub const TILE_WIDTH: u16 = 56;
|
pub const TILE_WIDTH: u16 = 56;
|
||||||
|
|
|
@ -10,7 +10,7 @@ impl Into<Vec<u8>> for Packet {
|
||||||
fn into(self) -> Vec<u8> {
|
fn into(self) -> Vec<u8> {
|
||||||
let Packet(Header(mode, a, b, c, d), payload) = self;
|
let Packet(Header(mode, a, b, c, d), payload) = self;
|
||||||
|
|
||||||
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));
|
||||||
packet[2..=3].copy_from_slice(&u16::to_be_bytes(a));
|
packet[2..=3].copy_from_slice(&u16::to_be_bytes(a));
|
||||||
packet[4..=5].copy_from_slice(&u16::to_be_bytes(b));
|
packet[4..=5].copy_from_slice(&u16::to_be_bytes(b));
|
||||||
|
@ -41,4 +41,4 @@ impl From<Vec<u8>> for Packet {
|
||||||
|
|
||||||
Packet(Header(mode, a, b, c, d), payload)
|
Packet(Header(mode, a, b, c, d), payload)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue