diff --git a/src/commands/bitmap.rs b/src/commands/bitmap.rs new file mode 100644 index 0000000..7cda71f --- /dev/null +++ b/src/commands/bitmap.rs @@ -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, + compression: CompressionCode, + ) -> Arc { + 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) + } +} diff --git a/src/commands/bitvec.rs b/src/commands/bitvec.rs new file mode 100644 index 0000000..e449ea9 --- /dev/null +++ b/src/commands/bitvec.rs @@ -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, + compression: CompressionCode, + operation: BinaryOperation, + ) -> Arc { + 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 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, + } + } +} diff --git a/src/commands/brightness_grid.rs b/src/commands/brightness_grid.rs new file mode 100644 index 0000000..29c4e93 --- /dev/null +++ b/src/commands/brightness_grid.rs @@ -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, + ) -> Arc { + 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) + } +} diff --git a/src/commands/cc_only.rs b/src/commands/cc_only.rs index 634e7d0..b42a79e 100644 --- a/src/commands/cc_only.rs +++ b/src/commands/cc_only.rs @@ -1,17 +1,16 @@ +use crate::{commands::wrap_command, macros::wrap_object}; use std::sync::Arc; macro_rules! command_code_only_command { ($command_struct:ident) => { - #[derive(uniffi::Object)] - pub struct $command_struct; + wrap_object!($command_struct); + wrap_command!($command_struct); #[uniffi::export] impl $command_struct { #[uniffi::constructor] pub fn new() -> Arc { - const _: () = - assert!(size_of::() == 0); - Arc::new($command_struct) + Self::internal_new(::servicepoint::$command_struct) } } }; diff --git a/src/commands/char_grid.rs b/src/commands/char_grid.rs new file mode 100644 index 0000000..f02b93e --- /dev/null +++ b/src/commands/char_grid.rs @@ -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, + ) -> Arc { + 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) + } +} diff --git a/src/commands/command.rs b/src/commands/command.rs deleted file mode 100644 index 9041b33..0000000 --- a/src/commands/command.rs +++ /dev/null @@ -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::internal_new(ClearCommand.into()) - } - - #[uniffi::constructor] - pub fn brightness(brightness: u8) -> Result, 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::internal_new(FadeOutCommand.into()) - } - - #[uniffi::constructor] - pub fn hard_reset() -> Arc { - Self::internal_new(HardResetCommand.into()) - } - - #[uniffi::constructor] - pub fn bitmap_linear_win( - offset_x: u64, - offset_y: u64, - bitmap: &Arc, - compression: CompressionCode, - ) -> Arc { - 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, - ) -> Arc { - 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, - compression: CompressionCode, - operation: BinaryOperation, - ) -> Arc { - 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, - ) -> Arc { - 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, - ) -> Arc { - 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, -} diff --git a/src/commands/cp437.rs b/src/commands/cp437.rs new file mode 100644 index 0000000..f4373c5 --- /dev/null +++ b/src/commands/cp437.rs @@ -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, + ) -> Arc { + 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) + } +} diff --git a/src/commands/global_brightness.rs b/src/commands/global_brightness.rs new file mode 100644 index 0000000..b95977e --- /dev/null +++ b/src/commands/global_brightness.rs @@ -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::internal_new(servicepoint::GlobalBrightnessCommand::from( + brightness, + )) + } +} diff --git a/src/commands/mod.rs b/src/commands/mod.rs index 4be7e73..224c26d 100644 --- a/src/commands/mod.rs +++ b/src/commands/mod.rs @@ -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>; +} + +macro_rules! wrap_command { + ($command:ident) => { + #[uniffi::export] + impl $command {} + + impl crate::commands::Command for $command { + fn as_packet(&self) -> Option> { + self.read() + .clone() + .try_into() + .map(crate::packet::Packet::internal_new) + .ok() + } + } + }; +} +pub(crate) use wrap_command; diff --git a/src/compression_code.rs b/src/compression_code.rs index 078230a..a3d332d 100644 --- a/src/compression_code.rs +++ b/src/compression_code.rs @@ -12,3 +12,15 @@ pub enum CompressionCode { /// compress using Zstandard Zstd = 0x7a73, } + +impl From for CompressionCode { + fn from(value: servicepoint::CompressionCode) -> Self { + value.into() + } +} + +impl From for servicepoint::CompressionCode { + fn from(value: CompressionCode) -> Self { + servicepoint::CompressionCode::try_from(value).unwrap() + } +} diff --git a/src/connection.rs b/src/connection.rs index 1e6a63b..9f1f0e0 100644 --- a/src/connection.rs +++ b/src/connection.rs @@ -1,4 +1,4 @@ -use crate::{commands::command::Command, errors::ServicePointError}; +use crate::{errors::ServicePointError, packet::Packet}; use servicepoint::UdpSocketExt; use std::{net::UdpSocket, sync::Arc}; @@ -18,9 +18,12 @@ impl Connection { }) } - pub fn send(&self, command: Arc) -> Result<(), ServicePointError> { + pub fn send_packet( + &self, + command: Arc, + ) -> Result<(), ServicePointError> { self.actual - .send_command(command.actual.read().unwrap().clone()) + .send_command(command.read().clone()) .ok_or_else(|| ServicePointError::IoError { error: "send failed".to_string(), }) diff --git a/src/containers/bitmap.rs b/src/containers/bitmap.rs index 01b99a4..7598609 100644 --- a/src/containers/bitmap.rs +++ b/src/containers/bitmap.rs @@ -2,7 +2,7 @@ use crate::macros::*; use servicepoint::Grid; use std::{ops::Deref, sync::Arc}; -wrap_uniffi_object!(Bitmap); +wrap_object!(Bitmap); wrap_width_height!(Bitmap); wrap_get_set_fill_2d!(Bitmap, bool); @@ -29,12 +29,12 @@ impl Bitmap { } pub fn equals(&self, other: &Bitmap) -> bool { - let a = self.actual.read().unwrap(); - let b = other.actual.read().unwrap(); + let a = self.read(); + let b = other.read(); *a == *b } pub fn copy_raw(&self) -> Vec { - self.actual.read().unwrap().deref().into() + self.read().deref().into() } } diff --git a/src/containers/bitvec.rs b/src/containers/bitvec.rs index 17df9fd..b5686d9 100644 --- a/src/containers/bitvec.rs +++ b/src/containers/bitvec.rs @@ -1,7 +1,7 @@ -use crate::macros::wrap_uniffi_object; +use crate::macros::wrap_object; use std::sync::Arc; -wrap_uniffi_object!(DisplayBitVec, BitVec); +wrap_object!(DisplayBitVec, BitVec); #[uniffi::export] impl BitVec { @@ -34,16 +34,16 @@ impl BitVec { } pub fn len(&self) -> u64 { - self.actual.read().unwrap().len() as u64 + self.read().len() as u64 } pub fn equals(&self, other: &BitVec) -> bool { - let a = self.actual.read().unwrap(); - let b = other.actual.read().unwrap(); + let a = self.read(); + let b = other.read(); *a == *b } pub fn copy_raw(&self) -> Vec { - self.actual.read().unwrap().clone().into_vec() + self.read().clone().into_vec() } } diff --git a/src/containers/brightness_grid.rs b/src/containers/brightness_grid.rs index dcfaa47..6e99211 100644 --- a/src/containers/brightness_grid.rs +++ b/src/containers/brightness_grid.rs @@ -2,7 +2,7 @@ use crate::macros::*; use servicepoint::{Brightness, Grid}; use std::{ops::Deref, sync::Arc}; -wrap_uniffi_object!(BrightnessGrid); +wrap_object!(BrightnessGrid); wrap_width_height!(BrightnessGrid); wrap_get_set_fill_2d!(BrightnessGrid, Brightness); @@ -29,12 +29,12 @@ impl BrightnessGrid { } pub fn equals(&self, other: &BrightnessGrid) -> bool { - let a = self.actual.read().unwrap(); - let b = other.actual.read().unwrap(); + let a = self.read(); + let b = other.read(); *a == *b } pub fn copy_raw(&self) -> Vec { - self.actual.read().unwrap().deref().into() + self.read().deref().into() } } diff --git a/src/containers/char_grid.rs b/src/containers/char_grid.rs index 4300172..2863282 100644 --- a/src/containers/char_grid.rs +++ b/src/containers/char_grid.rs @@ -2,7 +2,7 @@ use crate::{containers::cp437_grid::Cp437Grid, macros::*}; use servicepoint::{Grid, SetValueSeriesError}; use std::{convert::Into, sync::Arc}; -wrap_uniffi_object!(CharGrid); +wrap_object!(CharGrid); wrap_width_height!(CharGrid); #[derive(uniffi::Error, thiserror::Error, Debug)] @@ -59,13 +59,13 @@ impl CharGrid { } pub fn equals(&self, other: &CharGrid) -> bool { - let a = self.actual.read().unwrap(); - let b = other.actual.read().unwrap(); + let a = self.read(); + let b = other.read(); *a == *b } pub fn as_string(&self) -> String { - let grid = self.actual.read().unwrap(); + let grid = self.read(); String::from(&*grid) } @@ -110,9 +110,7 @@ impl CharGrid { } pub fn to_cp437(&self) -> Arc { - Cp437Grid::internal_new(servicepoint::Cp437Grid::from( - &*self.actual.read().unwrap(), - )) + Cp437Grid::internal_new(servicepoint::Cp437Grid::from(&*self.read())) } } diff --git a/src/containers/cp437_grid.rs b/src/containers/cp437_grid.rs index bf42122..bdcbfc1 100644 --- a/src/containers/cp437_grid.rs +++ b/src/containers/cp437_grid.rs @@ -2,7 +2,7 @@ use crate::{containers::char_grid::CharGrid, macros::*}; use servicepoint::Grid; use std::{ops::Deref, sync::Arc}; -wrap_uniffi_object!(Cp437Grid); +wrap_object!(Cp437Grid); wrap_width_height!(Cp437Grid); wrap_get_set_fill_2d!(Cp437Grid, u8); @@ -29,18 +29,16 @@ impl Cp437Grid { } pub fn equals(&self, other: &Cp437Grid) -> bool { - let a = self.actual.read().unwrap(); - let b = other.actual.read().unwrap(); + let a = self.read(); + let b = other.read(); *a == *b } pub fn copy_raw(&self) -> Vec { - self.actual.read().unwrap().deref().into() + self.read().deref().into() } pub fn to_utf8(&self) -> Arc { - CharGrid::internal_new(servicepoint::CharGrid::from( - &*self.actual.read().unwrap(), - )) + CharGrid::internal_new(servicepoint::CharGrid::from(&*self.read())) } } diff --git a/src/lib.rs b/src/lib.rs index c7addef..082ab6d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,10 +1,11 @@ uniffi::setup_scaffolding!(); -mod brightness; -mod commands; -mod compression_code; -mod connection; -mod constants; -mod containers; -mod errors; -mod macros; +pub mod brightness; +pub mod commands; +pub mod compression_code; +pub mod connection; +pub mod constants; +pub mod containers; +pub mod errors; +pub mod macros; +mod packet; diff --git a/src/macros.rs b/src/macros.rs index 799a95f..ee15b5e 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -1,45 +1,60 @@ -macro_rules! wrap_uniffi_object { +macro_rules! wrap_object { ($orig_t:ident, $new_t:ident) => { #[derive(uniffi::Object)] pub struct $new_t { - pub(crate) actual: std::sync::RwLock, + actual: ::std::sync::RwLock<::servicepoint::$orig_t>, } + #[allow(unused)] impl $new_t { pub(crate) fn internal_new( - actual: servicepoint::$orig_t, - ) -> Arc { - Arc::new(Self { - actual: std::sync::RwLock::new(actual), + actual: ::servicepoint::$orig_t, + ) -> ::std::sync::Arc { + ::std::sync::Arc::new(Self { + 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] impl $new_t { #[uniffi::constructor] - pub fn clone(other: &Arc) -> Arc { - Self::internal_new(other.actual.read().unwrap().clone()) + pub fn clone( + other: &::std::sync::Arc, + ) -> ::std::sync::Arc { + Self::internal_new(other.read().clone()) } } }; ($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 { ($t:ident) => { #[uniffi::export] impl $t { pub fn width(&self) -> u64 { - self.actual.read().unwrap().width() as u64 + self.read().width() as 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 { - 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) { diff --git a/src/packet.rs b/src/packet.rs new file mode 100644 index 0000000..5f769f1 --- /dev/null +++ b/src/packet.rs @@ -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::internal_new(self.read().header) + } +}