create separate types per command
Some checks failed
Rust / build (pull_request) Failing after 1m22s

This commit is contained in:
Vinzenz Schroeter 2025-06-16 11:32:12 +02:00
parent 635fef0244
commit b218bd6474
19 changed files with 306 additions and 200 deletions

30
src/commands/bitmap.rs Normal file
View file

@ -0,0 +1,30 @@
use crate::{
commands::wrap_command, compression_code::CompressionCode,
containers::bitmap::Bitmap, macros::wrap_object,
};
use servicepoint::Origin;
use std::sync::Arc;
wrap_object!(BitmapCommand);
wrap_command!(BitmapCommand);
#[uniffi::export]
impl BitmapCommand {
#[uniffi::constructor]
pub fn new(
offset_x: u64,
offset_y: u64,
bitmap: &Arc<Bitmap>,
compression: CompressionCode,
) -> Arc<Self> {
let origin = Origin::new(offset_x as usize, offset_y as usize);
let bitmap = bitmap.read().clone();
let compression = compression.into();
let actual = servicepoint::BitmapCommand {
origin,
bitmap,
compression,
};
Self::internal_new(actual)
}
}

52
src/commands/bitvec.rs Normal file
View file

@ -0,0 +1,52 @@
use crate::{
commands::wrap_command, compression_code::CompressionCode,
containers::bitvec::BitVec, macros::wrap_object,
};
use std::sync::Arc;
wrap_object!(BitVecCommand);
wrap_command!(BitVecCommand);
#[uniffi::export]
impl BitVecCommand {
#[uniffi::constructor]
pub fn new(
offset: u64,
bitvec: &Arc<BitVec>,
compression: CompressionCode,
operation: BinaryOperation,
) -> Arc<Self> {
let offset = offset as usize;
let bitvec = bitvec.read().clone();
let compression = compression.into();
let operation = operation.into();
let actual = servicepoint::BitVecCommand {
offset,
bitvec,
compression,
operation,
};
Self::internal_new(actual)
}
}
#[derive(uniffi::Enum)]
pub enum BinaryOperation {
Overwrite,
And,
Or,
Xor,
}
impl From<BinaryOperation> for servicepoint::BinaryOperation {
fn from(op: BinaryOperation) -> Self {
match op {
BinaryOperation::Overwrite => {
servicepoint::BinaryOperation::Overwrite
}
BinaryOperation::And => servicepoint::BinaryOperation::And,
BinaryOperation::Or => servicepoint::BinaryOperation::Or,
BinaryOperation::Xor => servicepoint::BinaryOperation::Xor,
}
}
}

View file

@ -0,0 +1,24 @@
use crate::{
commands::wrap_command, containers::brightness_grid::BrightnessGrid,
macros::wrap_object,
};
use servicepoint::Origin;
use std::sync::Arc;
wrap_object!(BrightnessGridCommand);
wrap_command!(BrightnessGridCommand);
#[uniffi::export]
impl BrightnessGridCommand {
#[uniffi::constructor]
pub fn new(
offset_x: u64,
offset_y: u64,
grid: &Arc<BrightnessGrid>,
) -> Arc<Self> {
let origin = Origin::new(offset_x as usize, offset_y as usize);
let grid = grid.read().clone();
let actual = servicepoint::BrightnessGridCommand { origin, grid };
Self::internal_new(actual)
}
}

View file

@ -1,17 +1,16 @@
use crate::{commands::wrap_command, macros::wrap_object};
use std::sync::Arc; use std::sync::Arc;
macro_rules! command_code_only_command { macro_rules! command_code_only_command {
($command_struct:ident) => { ($command_struct:ident) => {
#[derive(uniffi::Object)] wrap_object!($command_struct);
pub struct $command_struct; wrap_command!($command_struct);
#[uniffi::export] #[uniffi::export]
impl $command_struct { impl $command_struct {
#[uniffi::constructor] #[uniffi::constructor]
pub fn new() -> Arc<Self> { pub fn new() -> Arc<Self> {
const _: () = Self::internal_new(::servicepoint::$command_struct)
assert!(size_of::<servicepoint::$command_struct>() == 0);
Arc::new($command_struct)
} }
} }
}; };

24
src/commands/char_grid.rs Normal file
View file

@ -0,0 +1,24 @@
use crate::{
commands::wrap_command, containers::char_grid::CharGrid,
macros::wrap_object,
};
use servicepoint::Origin;
use std::sync::Arc;
wrap_object!(CharGridCommand);
wrap_command!(CharGridCommand);
#[uniffi::export]
impl CharGridCommand {
#[uniffi::constructor]
pub fn new(
offset_x: u64,
offset_y: u64,
grid: &Arc<CharGrid>,
) -> Arc<Self> {
let origin = Origin::new(offset_x as usize, offset_y as usize);
let grid = grid.read().clone();
let actual = servicepoint::CharGridCommand { origin, grid };
Self::internal_new(actual)
}
}

View file

@ -1,141 +0,0 @@
use crate::{
compression_code::CompressionCode,
containers::{
bitmap::Bitmap, bitvec::BitVec, brightness_grid::BrightnessGrid,
char_grid::CharGrid, cp437_grid::Cp437Grid,
},
errors::ServicePointError,
macros::wrap_uniffi_object,
};
use servicepoint::{
BitVecCommand, BrightnessGridCommand, CharGridCommand, ClearCommand,
Cp437GridCommand, FadeOutCommand, GlobalBrightnessCommand,
HardResetCommand, Origin,
};
use std::sync::Arc;
wrap_uniffi_object!(TypedCommand, Command);
#[uniffi::export]
impl Command {
#[uniffi::constructor]
pub fn clear() -> Arc<Self> {
Self::internal_new(ClearCommand.into())
}
#[uniffi::constructor]
pub fn brightness(brightness: u8) -> Result<Arc<Self>, ServicePointError> {
servicepoint::Brightness::try_from(brightness)
.map_err(move |value| ServicePointError::InvalidBrightness {
value,
})
.map(GlobalBrightnessCommand::from)
.map(servicepoint::TypedCommand::Brightness)
.map(Self::internal_new)
}
#[uniffi::constructor]
pub fn fade_out() -> Arc<Self> {
Self::internal_new(FadeOutCommand.into())
}
#[uniffi::constructor]
pub fn hard_reset() -> Arc<Self> {
Self::internal_new(HardResetCommand.into())
}
#[uniffi::constructor]
pub fn bitmap_linear_win(
offset_x: u64,
offset_y: u64,
bitmap: &Arc<Bitmap>,
compression: CompressionCode,
) -> Arc<Self> {
let origin = Origin::new(offset_x as usize, offset_y as usize);
let bitmap = bitmap.actual.read().unwrap().clone();
let actual = servicepoint::BitmapCommand {
origin,
bitmap,
compression: servicepoint::CompressionCode::try_from(
compression as u16,
)
.unwrap(),
};
Self::internal_new(actual.into())
}
#[uniffi::constructor]
pub fn char_brightness(
offset_x: u64,
offset_y: u64,
grid: &Arc<BrightnessGrid>,
) -> Arc<Self> {
let origin = Origin::new(offset_x as usize, offset_y as usize);
let grid = grid.actual.read().unwrap().clone();
let actual = BrightnessGridCommand { origin, grid };
Self::internal_new(actual.into())
}
#[uniffi::constructor]
pub fn bitmap_linear(
offset: u64,
bitvec: &Arc<BitVec>,
compression: CompressionCode,
operation: BinaryOperation,
) -> Arc<Self> {
let bitvec = bitvec.actual.read().unwrap().clone();
let actual = BitVecCommand {
offset: offset as usize,
bitvec,
compression: servicepoint::CompressionCode::try_from(
compression as u16,
)
.unwrap(),
operation: match operation {
BinaryOperation::Overwrite => {
servicepoint::BinaryOperation::Overwrite
}
BinaryOperation::And => servicepoint::BinaryOperation::And,
BinaryOperation::Or => servicepoint::BinaryOperation::Or,
BinaryOperation::Xor => servicepoint::BinaryOperation::Xor,
},
};
Self::internal_new(actual.into())
}
#[uniffi::constructor]
pub fn cp437_data(
offset_x: u64,
offset_y: u64,
grid: &Arc<Cp437Grid>,
) -> Arc<Self> {
let origin = Origin::new(offset_x as usize, offset_y as usize);
let grid = grid.actual.read().unwrap().clone();
let actual = Cp437GridCommand { origin, grid };
Self::internal_new(actual.into())
}
#[uniffi::constructor]
pub fn utf8_data(
offset_x: u64,
offset_y: u64,
grid: &Arc<CharGrid>,
) -> Arc<Self> {
let origin = Origin::new(offset_x as usize, offset_y as usize);
let grid = grid.actual.read().unwrap().clone();
let actual = CharGridCommand { origin, grid };
Self::internal_new(actual.into())
}
pub fn equals(&self, other: &Command) -> bool {
*self.actual.read().unwrap() == *other.actual.read().unwrap()
}
}
#[derive(uniffi::Enum)]
pub enum BinaryOperation {
Overwrite,
And,
Or,
Xor,
}

24
src/commands/cp437.rs Normal file
View file

@ -0,0 +1,24 @@
use crate::{
commands::wrap_command, containers::cp437_grid::Cp437Grid,
macros::wrap_object,
};
use servicepoint::Origin;
use std::sync::Arc;
wrap_object!(Cp437GridCommand);
wrap_command!(Cp437GridCommand);
#[uniffi::export]
impl Cp437GridCommand {
#[uniffi::constructor]
pub fn new(
offset_x: u64,
offset_y: u64,
grid: &Arc<Cp437Grid>,
) -> Arc<Self> {
let origin = Origin::new(offset_x as usize, offset_y as usize);
let grid = grid.read().clone();
let actual = servicepoint::Cp437GridCommand { origin, grid };
Self::internal_new(actual)
}
}

View file

@ -0,0 +1,16 @@
use crate::{commands::wrap_command, macros::wrap_object};
use servicepoint::Brightness;
use std::sync::Arc;
wrap_object!(GlobalBrightnessCommand);
wrap_command!(GlobalBrightnessCommand);
#[uniffi::export]
impl GlobalBrightnessCommand {
#[uniffi::constructor]
pub fn new(brightness: Brightness) -> Arc<Self> {
Self::internal_new(servicepoint::GlobalBrightnessCommand::from(
brightness,
))
}
}

View file

@ -1,3 +1,42 @@
pub mod command; mod bitmap;
mod bitvec;
mod brightness_grid;
mod cc_only;
mod char_grid;
mod cp437;
mod global_brightness;
pub mod cc_only; use std::sync::Arc;
use crate::packet::Packet;
pub use bitmap::BitmapCommand;
pub use bitvec::{BinaryOperation, BitVecCommand};
pub use brightness_grid::BrightnessGridCommand;
pub use cc_only::{
BitmapLegacyCommand, ClearCommand, FadeOutCommand, HardResetCommand,
};
pub use char_grid::CharGridCommand;
pub use cp437::Cp437GridCommand;
#[uniffi::export]
pub trait Command: Sync + Send {
fn as_packet(&self) -> Option<Arc<Packet>>;
}
macro_rules! wrap_command {
($command:ident) => {
#[uniffi::export]
impl $command {}
impl crate::commands::Command for $command {
fn as_packet(&self) -> Option<Arc<crate::packet::Packet>> {
self.read()
.clone()
.try_into()
.map(crate::packet::Packet::internal_new)
.ok()
}
}
};
}
pub(crate) use wrap_command;

View file

@ -12,3 +12,15 @@ pub enum CompressionCode {
/// compress using Zstandard /// compress using Zstandard
Zstd = 0x7a73, Zstd = 0x7a73,
} }
impl From<servicepoint::CompressionCode> for CompressionCode {
fn from(value: servicepoint::CompressionCode) -> Self {
value.into()
}
}
impl From<CompressionCode> for servicepoint::CompressionCode {
fn from(value: CompressionCode) -> Self {
servicepoint::CompressionCode::try_from(value).unwrap()
}
}

View file

@ -1,4 +1,4 @@
use crate::{commands::command::Command, errors::ServicePointError}; use crate::{errors::ServicePointError, packet::Packet};
use servicepoint::UdpSocketExt; use servicepoint::UdpSocketExt;
use std::{net::UdpSocket, sync::Arc}; use std::{net::UdpSocket, sync::Arc};
@ -18,9 +18,12 @@ impl Connection {
}) })
} }
pub fn send(&self, command: Arc<Command>) -> Result<(), ServicePointError> { pub fn send_packet(
&self,
command: Arc<Packet>,
) -> Result<(), ServicePointError> {
self.actual self.actual
.send_command(command.actual.read().unwrap().clone()) .send_command(command.read().clone())
.ok_or_else(|| ServicePointError::IoError { .ok_or_else(|| ServicePointError::IoError {
error: "send failed".to_string(), error: "send failed".to_string(),
}) })

View file

@ -2,7 +2,7 @@ use crate::macros::*;
use servicepoint::Grid; use servicepoint::Grid;
use std::{ops::Deref, sync::Arc}; use std::{ops::Deref, sync::Arc};
wrap_uniffi_object!(Bitmap); wrap_object!(Bitmap);
wrap_width_height!(Bitmap); wrap_width_height!(Bitmap);
wrap_get_set_fill_2d!(Bitmap, bool); wrap_get_set_fill_2d!(Bitmap, bool);
@ -29,12 +29,12 @@ impl Bitmap {
} }
pub fn equals(&self, other: &Bitmap) -> bool { pub fn equals(&self, other: &Bitmap) -> bool {
let a = self.actual.read().unwrap(); let a = self.read();
let b = other.actual.read().unwrap(); let b = other.read();
*a == *b *a == *b
} }
pub fn copy_raw(&self) -> Vec<u8> { pub fn copy_raw(&self) -> Vec<u8> {
self.actual.read().unwrap().deref().into() self.read().deref().into()
} }
} }

View file

@ -1,7 +1,7 @@
use crate::macros::wrap_uniffi_object; use crate::macros::wrap_object;
use std::sync::Arc; use std::sync::Arc;
wrap_uniffi_object!(DisplayBitVec, BitVec); wrap_object!(DisplayBitVec, BitVec);
#[uniffi::export] #[uniffi::export]
impl BitVec { impl BitVec {
@ -34,16 +34,16 @@ impl BitVec {
} }
pub fn len(&self) -> u64 { pub fn len(&self) -> u64 {
self.actual.read().unwrap().len() as u64 self.read().len() as u64
} }
pub fn equals(&self, other: &BitVec) -> bool { pub fn equals(&self, other: &BitVec) -> bool {
let a = self.actual.read().unwrap(); let a = self.read();
let b = other.actual.read().unwrap(); let b = other.read();
*a == *b *a == *b
} }
pub fn copy_raw(&self) -> Vec<u8> { pub fn copy_raw(&self) -> Vec<u8> {
self.actual.read().unwrap().clone().into_vec() self.read().clone().into_vec()
} }
} }

View file

@ -2,7 +2,7 @@ use crate::macros::*;
use servicepoint::{Brightness, Grid}; use servicepoint::{Brightness, Grid};
use std::{ops::Deref, sync::Arc}; use std::{ops::Deref, sync::Arc};
wrap_uniffi_object!(BrightnessGrid); wrap_object!(BrightnessGrid);
wrap_width_height!(BrightnessGrid); wrap_width_height!(BrightnessGrid);
wrap_get_set_fill_2d!(BrightnessGrid, Brightness); wrap_get_set_fill_2d!(BrightnessGrid, Brightness);
@ -29,12 +29,12 @@ impl BrightnessGrid {
} }
pub fn equals(&self, other: &BrightnessGrid) -> bool { pub fn equals(&self, other: &BrightnessGrid) -> bool {
let a = self.actual.read().unwrap(); let a = self.read();
let b = other.actual.read().unwrap(); let b = other.read();
*a == *b *a == *b
} }
pub fn copy_raw(&self) -> Vec<u8> { pub fn copy_raw(&self) -> Vec<u8> {
self.actual.read().unwrap().deref().into() self.read().deref().into()
} }
} }

View file

@ -2,7 +2,7 @@ use crate::{containers::cp437_grid::Cp437Grid, macros::*};
use servicepoint::{Grid, SetValueSeriesError}; use servicepoint::{Grid, SetValueSeriesError};
use std::{convert::Into, sync::Arc}; use std::{convert::Into, sync::Arc};
wrap_uniffi_object!(CharGrid); wrap_object!(CharGrid);
wrap_width_height!(CharGrid); wrap_width_height!(CharGrid);
#[derive(uniffi::Error, thiserror::Error, Debug)] #[derive(uniffi::Error, thiserror::Error, Debug)]
@ -59,13 +59,13 @@ impl CharGrid {
} }
pub fn equals(&self, other: &CharGrid) -> bool { pub fn equals(&self, other: &CharGrid) -> bool {
let a = self.actual.read().unwrap(); let a = self.read();
let b = other.actual.read().unwrap(); let b = other.read();
*a == *b *a == *b
} }
pub fn as_string(&self) -> String { pub fn as_string(&self) -> String {
let grid = self.actual.read().unwrap(); let grid = self.read();
String::from(&*grid) String::from(&*grid)
} }
@ -110,9 +110,7 @@ impl CharGrid {
} }
pub fn to_cp437(&self) -> Arc<Cp437Grid> { pub fn to_cp437(&self) -> Arc<Cp437Grid> {
Cp437Grid::internal_new(servicepoint::Cp437Grid::from( Cp437Grid::internal_new(servicepoint::Cp437Grid::from(&*self.read()))
&*self.actual.read().unwrap(),
))
} }
} }

View file

@ -2,7 +2,7 @@ use crate::{containers::char_grid::CharGrid, macros::*};
use servicepoint::Grid; use servicepoint::Grid;
use std::{ops::Deref, sync::Arc}; use std::{ops::Deref, sync::Arc};
wrap_uniffi_object!(Cp437Grid); wrap_object!(Cp437Grid);
wrap_width_height!(Cp437Grid); wrap_width_height!(Cp437Grid);
wrap_get_set_fill_2d!(Cp437Grid, u8); wrap_get_set_fill_2d!(Cp437Grid, u8);
@ -29,18 +29,16 @@ impl Cp437Grid {
} }
pub fn equals(&self, other: &Cp437Grid) -> bool { pub fn equals(&self, other: &Cp437Grid) -> bool {
let a = self.actual.read().unwrap(); let a = self.read();
let b = other.actual.read().unwrap(); let b = other.read();
*a == *b *a == *b
} }
pub fn copy_raw(&self) -> Vec<u8> { pub fn copy_raw(&self) -> Vec<u8> {
self.actual.read().unwrap().deref().into() self.read().deref().into()
} }
pub fn to_utf8(&self) -> Arc<CharGrid> { pub fn to_utf8(&self) -> Arc<CharGrid> {
CharGrid::internal_new(servicepoint::CharGrid::from( CharGrid::internal_new(servicepoint::CharGrid::from(&*self.read()))
&*self.actual.read().unwrap(),
))
} }
} }

View file

@ -1,10 +1,11 @@
uniffi::setup_scaffolding!(); uniffi::setup_scaffolding!();
mod brightness; pub mod brightness;
mod commands; pub mod commands;
mod compression_code; pub mod compression_code;
mod connection; pub mod connection;
mod constants; pub mod constants;
mod containers; pub mod containers;
mod errors; pub mod errors;
mod macros; pub mod macros;
mod packet;

View file

@ -1,45 +1,60 @@
macro_rules! wrap_uniffi_object { macro_rules! wrap_object {
($orig_t:ident, $new_t:ident) => { ($orig_t:ident, $new_t:ident) => {
#[derive(uniffi::Object)] #[derive(uniffi::Object)]
pub struct $new_t { pub struct $new_t {
pub(crate) actual: std::sync::RwLock<servicepoint::$orig_t>, actual: ::std::sync::RwLock<::servicepoint::$orig_t>,
} }
#[allow(unused)]
impl $new_t { impl $new_t {
pub(crate) fn internal_new( pub(crate) fn internal_new(
actual: servicepoint::$orig_t, actual: ::servicepoint::$orig_t,
) -> Arc<Self> { ) -> ::std::sync::Arc<Self> {
Arc::new(Self { ::std::sync::Arc::new(Self {
actual: std::sync::RwLock::new(actual), actual: ::std::sync::RwLock::new(actual),
}) })
} }
pub(crate) fn read(
&self,
) -> ::std::sync::RwLockReadGuard<::servicepoint::$orig_t> {
self.actual.read().unwrap()
}
pub(crate) fn write(
&self,
) -> ::std::sync::RwLockWriteGuard<::servicepoint::$orig_t> {
self.actual.write().unwrap()
}
} }
#[uniffi::export] #[uniffi::export]
impl $new_t { impl $new_t {
#[uniffi::constructor] #[uniffi::constructor]
pub fn clone(other: &Arc<Self>) -> Arc<Self> { pub fn clone(
Self::internal_new(other.actual.read().unwrap().clone()) other: &::std::sync::Arc<Self>,
) -> ::std::sync::Arc<Self> {
Self::internal_new(other.read().clone())
} }
} }
}; };
($t:ident) => { ($t:ident) => {
wrap_uniffi_object!($t, $t); wrap_object!($t, $t);
}; };
} }
pub(crate) use wrap_uniffi_object; pub(crate) use wrap_object;
macro_rules! wrap_width_height { macro_rules! wrap_width_height {
($t:ident) => { ($t:ident) => {
#[uniffi::export] #[uniffi::export]
impl $t { impl $t {
pub fn width(&self) -> u64 { pub fn width(&self) -> u64 {
self.actual.read().unwrap().width() as u64 self.read().width() as u64
} }
pub fn height(&self) -> u64 { pub fn height(&self) -> u64 {
self.actual.read().unwrap().height() as u64 self.read().height() as u64
} }
} }
}; };
@ -59,7 +74,7 @@ macro_rules! wrap_get_set_fill_2d {
} }
pub fn get(&self, x: u64, y: u64) -> $contained { pub fn get(&self, x: u64, y: u64) -> $contained {
self.actual.read().unwrap().get(x as usize, y as usize) self.read().get(x as usize, y as usize)
} }
pub fn fill(&self, value: $contained) { pub fn fill(&self, value: $contained) {

12
src/packet.rs Normal file
View file

@ -0,0 +1,12 @@
use crate::macros::wrap_object;
use std::sync::Arc;
wrap_object!(Packet);
wrap_object!(Header);
#[uniffi::export]
impl Packet {
pub fn get_header(&self) -> Arc<Header> {
Header::internal_new(self.read().header)
}
}