From ff26193e4847da8e18da601a2e051e964eecafce Mon Sep 17 00:00:00 2001 From: Vinzenz Schroeter Date: Fri, 13 Jun 2025 10:47:31 +0200 Subject: [PATCH 01/15] update to nixos 25.05 --- flake.lock | 8 ++++---- flake.nix | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/flake.lock b/flake.lock index 9e70e85..daf37b8 100644 --- a/flake.lock +++ b/flake.lock @@ -2,16 +2,16 @@ "nodes": { "nixpkgs": { "locked": { - "lastModified": 1739357830, - "narHash": "sha256-9xim3nJJUFbVbJCz48UP4fGRStVW5nv4VdbimbKxJ3I=", + "lastModified": 1758791193, + "narHash": "sha256-F8WmEwFoHsnix7rt290R0rFXNJiMbClMZyIC/e+HYf0=", "owner": "nixos", "repo": "nixpkgs", - "rev": "0ff09db9d034a04acd4e8908820ba0b410d7a33a", + "rev": "25e53aa156d47bad5082ff7618f5feb1f5e02d01", "type": "github" }, "original": { "owner": "nixos", - "ref": "nixos-24.11", + "ref": "nixos-25.05", "repo": "nixpkgs", "type": "github" } diff --git a/flake.nix b/flake.nix index f619fe0..60cfbb6 100644 --- a/flake.nix +++ b/flake.nix @@ -2,7 +2,7 @@ description = "Flake for the servicepoint library."; inputs = { - nixpkgs.url = "github:nixos/nixpkgs/nixos-24.11"; + nixpkgs.url = "github:nixos/nixpkgs/nixos-25.05"; }; outputs = From 27ffbaa080ace50edbe2f834fa1826a26928b05b Mon Sep 17 00:00:00 2001 From: Vinzenz Schroeter Date: Sun, 28 Sep 2025 22:53:29 +0200 Subject: [PATCH 02/15] change nix formatter to nixfmt-tree --- flake.nix | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/flake.nix b/flake.nix index 60cfbb6..4095ef3 100644 --- a/flake.nix +++ b/flake.nix @@ -6,7 +6,7 @@ }; outputs = - inputs@{ + { self, nixpkgs, }: @@ -28,11 +28,11 @@ } ); in - rec { + { devShells = forAllSystems ( { pkgs, system }: { - default = pkgs.mkShell rec { + default = pkgs.mkShell { packages = with pkgs; [ (pkgs.symlinkJoin { name = "rust-toolchain"; @@ -55,6 +55,6 @@ } ); - formatter = forAllSystems ({ pkgs, ... }: pkgs.nixfmt-rfc-style); + formatter = forAllSystems ({ pkgs, ... }: pkgs.nixfmt-tree); }; } From 421522d963733c5a80587e24b37cde05a0834458 Mon Sep 17 00:00:00 2001 From: Vinzenz Schroeter Date: Sun, 28 Sep 2025 23:07:29 +0200 Subject: [PATCH 03/15] add nix package --- flake.nix | 30 ++++++++++++++++++++++++++---- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/flake.nix b/flake.nix index 4095ef3..f58d403 100644 --- a/flake.nix +++ b/flake.nix @@ -24,15 +24,40 @@ system: f rec { pkgs = nixpkgs.legacyPackages.${system}; + selfPkgs = self.packages.${system}; inherit system; } ); in { + packages = forAllSystems ( + { pkgs, selfPkgs, ... }: + { + servicepoint-binding-uniffi = pkgs.rustPlatform.buildRustPackage { + pname = "servicepoint-binding-uniffi"; + version = "0.13.1"; + + src = ./.; + cargoDeps = pkgs.rustPlatform.importCargoLock { lockFile = ./Cargo.lock; }; + + nativeBuildInputs = with pkgs; [ + pkg-config + ]; + + buildInputs = with pkgs; [ + xe + xz + ]; + }; + default = selfPkgs.servicepoint-binding-uniffi; + } + ); + devShells = forAllSystems ( - { pkgs, system }: + { pkgs, selfPkgs, ... }: { default = pkgs.mkShell { + inputsFrom = [ selfPkgs.default ]; packages = with pkgs; [ (pkgs.symlinkJoin { name = "rust-toolchain"; @@ -46,9 +71,6 @@ cargo-tarpaulin ]; }) - xe - xz - pkg-config ]; RUST_SRC_PATH = "${pkgs.rust.packages.stable.rustPlatform.rustLibSrc}"; }; From 44ef4bb6d707c46af1bed6244f17a16f26f246c1 Mon Sep 17 00:00:00 2001 From: Vinzenz Schroeter Date: Sun, 28 Sep 2025 23:12:43 +0200 Subject: [PATCH 04/15] add pkgconfig --- flake.nix | 5 +++++ servicepoint-binding-uniffi.pc.in | 5 +++++ 2 files changed, 10 insertions(+) create mode 100644 servicepoint-binding-uniffi.pc.in diff --git a/flake.nix b/flake.nix index f58d403..9567822 100644 --- a/flake.nix +++ b/flake.nix @@ -48,6 +48,11 @@ xe xz ]; + + postInstall = '' + mkdir -p $out/lib/pkgconfig + sed "s:\$out:$out:g" ${./servicepoint-binding-uniffi.pc.in} | sed "s:\$version:$version:g" > $out/lib/pkgconfig/servicepoint-binding-uniffi.pc + ''; }; default = selfPkgs.servicepoint-binding-uniffi; } diff --git a/servicepoint-binding-uniffi.pc.in b/servicepoint-binding-uniffi.pc.in new file mode 100644 index 0000000..622867c --- /dev/null +++ b/servicepoint-binding-uniffi.pc.in @@ -0,0 +1,5 @@ +Name: servicepoint-binding-uniffi +Description: UniFFI bindings for the servicepoint library +Version: $version +URL: https://git.berlin.ccc.de/servicepoint/servicepoint-binding-uniffi +Libs: -L$out/lib -lservicepoint_binding_uniffi From f7cb5546b334717a5bef06b910475e98d1e0a96a Mon Sep 17 00:00:00 2001 From: Vinzenz Schroeter Date: Sun, 4 May 2025 18:55:19 +0200 Subject: [PATCH 05/15] update servicepoint library --- Cargo.lock | 89 +++++++++++++++++-------------- Cargo.toml | 6 +-- src/bitmap.rs | 4 +- src/bitvec.rs | 8 +-- src/brightness_grid.rs | 2 +- src/command.rs | 118 +++++++++++++++-------------------------- src/connection.rs | 28 +++++----- src/cp437_grid.rs | 2 +- 8 files changed, 116 insertions(+), 141 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 30036a5..930a6a9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -209,9 +209,9 @@ checksum = "a8d1add55171497b4705a648c6b583acafb01d58050a51727785f0b2c8e0a2b2" [[package]] name = "goblin" -version = "0.6.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d6b4de4a8eb6c46a8c77e1d3be942cb9a8bf073c22374578e5ba4b08ed0ff68" +checksum = "1b363a30c165f666402fe6a3024d3bec7ebc898f96a4a23bd1c99f8dbf3f4f47" dependencies = [ "log", "plain", @@ -220,9 +220,9 @@ dependencies = [ [[package]] name = "heck" -version = "0.4.1" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" [[package]] name = "itoa" @@ -304,12 +304,6 @@ version = "1.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" -[[package]] -name = "oneshot-uniffi" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c548d5c78976f6955d72d0ced18c48ca07030f7a1d4024529fedd7c1c01b29c" - [[package]] name = "paste" version = "1.0.15" @@ -370,18 +364,18 @@ checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" [[package]] name = "scroll" -version = "0.11.0" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04c565b551bafbef4157586fa379538366e4385d42082f255bfd96e4fe8519da" +checksum = "6ab8598aa408498679922eff7fa985c25d58a90771bd6be794434c5277eab1a6" dependencies = [ "scroll_derive", ] [[package]] name = "scroll_derive" -version = "0.11.1" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1db149f81d46d2deba7cd3c50772474707729550221e69588478ebf9ada425ae" +checksum = "1783eabc414609e28a5ba76aee5ddd52199f7107a0b24c2e9746a1ecc34a683d" dependencies = [ "proc-macro2", "quote", @@ -431,9 +425,9 @@ dependencies = [ [[package]] name = "servicepoint" -version = "0.13.1" +version = "0.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93b52049be55a15fe37c13249d7f96aa8a5de56e1a41838e74a822ee8316a0c4" +checksum = "f6bd5cfa49c73aeecb344680ffbf697abf73e0563a441b93b9723ae43867500f" dependencies = [ "bitvec", "bzip2", @@ -466,6 +460,12 @@ version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" +[[package]] +name = "smawk" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7c388c1b5e93756d0c740965c41e8822f866621d41acbdf6336a6a168f8840c" + [[package]] name = "static_assertions" version = "1.1.0" @@ -489,6 +489,15 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" +[[package]] +name = "textwrap" +version = "0.16.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c13547615a44dc9c452a8a534638acdf07120d4b6847c8178705da06306a3057" +dependencies = [ + "smawk", +] + [[package]] name = "thiserror" version = "1.0.69" @@ -552,11 +561,13 @@ checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" [[package]] name = "uniffi" -version = "0.25.3" +version = "0.28.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21345172d31092fd48c47fd56c53d4ae9e41c4b1f559fb8c38c1ab1685fd919f" +checksum = "4cb08c58c7ed7033150132febe696bef553f891b1ede57424b40d87a89e3c170" dependencies = [ "anyhow", + "cargo_metadata", + "uniffi_bindgen", "uniffi_build", "uniffi_core", "uniffi_macros", @@ -564,9 +575,9 @@ dependencies = [ [[package]] name = "uniffi_bindgen" -version = "0.25.3" +version = "0.28.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd992f2929a053829d5875af1eff2ee3d7a7001cb3b9a46cc7895f2caede6940" +checksum = "cade167af943e189a55020eda2c314681e223f1e42aca7c4e52614c2b627698f" dependencies = [ "anyhow", "askama", @@ -579,17 +590,17 @@ dependencies = [ "once_cell", "paste", "serde", + "textwrap", "toml", "uniffi_meta", - "uniffi_testing", "uniffi_udl", ] [[package]] name = "uniffi_build" -version = "0.25.3" +version = "0.28.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "001964dd3682d600084b3aaf75acf9c3426699bc27b65e96bb32d175a31c74e9" +checksum = "4c7cf32576e08104b7dc2a6a5d815f37616e66c6866c2a639fe16e6d2286b75b" dependencies = [ "anyhow", "camino", @@ -598,9 +609,9 @@ dependencies = [ [[package]] name = "uniffi_checksum_derive" -version = "0.25.3" +version = "0.28.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55137c122f712d9330fd985d66fa61bdc381752e89c35708c13ce63049a3002c" +checksum = "802d2051a700e3ec894c79f80d2705b69d85844dafbbe5d1a92776f8f48b563a" dependencies = [ "quote", "syn", @@ -608,25 +619,23 @@ dependencies = [ [[package]] name = "uniffi_core" -version = "0.25.3" +version = "0.28.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6121a127a3af1665cd90d12dd2b3683c2643c5103281d0fed5838324ca1fad5b" +checksum = "bc7687007d2546c454d8ae609b105daceb88175477dac280707ad6d95bcd6f1f" dependencies = [ "anyhow", "bytes", - "camino", "log", "once_cell", - "oneshot-uniffi", "paste", "static_assertions", ] [[package]] name = "uniffi_macros" -version = "0.25.3" +version = "0.28.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11cf7a58f101fcedafa5b77ea037999b88748607f0ef3a33eaa0efc5392e92e4" +checksum = "12c65a5b12ec544ef136693af8759fb9d11aefce740fb76916721e876639033b" dependencies = [ "bincode", "camino", @@ -637,15 +646,14 @@ dependencies = [ "serde", "syn", "toml", - "uniffi_build", "uniffi_meta", ] [[package]] name = "uniffi_meta" -version = "0.25.3" +version = "0.28.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71dc8573a7b1ac4b71643d6da34888273ebfc03440c525121f1b3634ad3417a2" +checksum = "4a74ed96c26882dac1ca9b93ca23c827e284bacbd7ec23c6f0b0372f747d59e4" dependencies = [ "anyhow", "bytes", @@ -655,9 +663,9 @@ dependencies = [ [[package]] name = "uniffi_testing" -version = "0.25.3" +version = "0.28.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "118448debffcb676ddbe8c5305fb933ab7e0123753e659a71dc4a693f8d9f23c" +checksum = "6a6f984f0781f892cc864a62c3a5c60361b1ccbd68e538e6c9fbced5d82268ac" dependencies = [ "anyhow", "camino", @@ -668,11 +676,12 @@ dependencies = [ [[package]] name = "uniffi_udl" -version = "0.25.3" +version = "0.28.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "889edb7109c6078abe0e53e9b4070cf74a6b3468d141bdf5ef1bd4d1dc24a1c3" +checksum = "037820a4cfc4422db1eaa82f291a3863c92c7d1789dc513489c36223f9b4cdfc" dependencies = [ "anyhow", + "textwrap", "uniffi_meta", "uniffi_testing", "weedle2", @@ -686,9 +695,9 @@ checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" [[package]] name = "weedle2" -version = "4.0.0" +version = "5.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e79c5206e1f43a2306fd64bdb95025ee4228960f2e6c5a8b173f3caaf807741" +checksum = "998d2c24ec099a87daf9467808859f9d82b61f1d9c9701251aea037f514eae0e" dependencies = [ "nom", ] diff --git a/Cargo.toml b/Cargo.toml index 516cbf5..c9f07fd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,14 +14,14 @@ keywords = ["cccb", "cccb-servicepoint", "uniffi"] crate-type = ["cdylib"] [build-dependencies] -uniffi = { version = "0.25.3", features = ["build"] } +uniffi = { version = "0.28.3", features = ["build"] } [dependencies] -uniffi = { version = "0.25.3" } +uniffi = { version = "0.28.3" } thiserror = "2.0" [dependencies.servicepoint] -version = "0.13.1" +version = "0.14.1" features = ["all_compressions"] [package.metadata.docs.rs] diff --git a/src/bitmap.rs b/src/bitmap.rs index 1291f7b..f658b85 100644 --- a/src/bitmap.rs +++ b/src/bitmap.rs @@ -21,7 +21,7 @@ impl Bitmap { Self::internal_new(servicepoint::Bitmap::new( width as usize, height as usize, - )) + ).unwrap()) } #[uniffi::constructor] @@ -35,7 +35,7 @@ impl Bitmap { width as usize, height as usize, &data, - )) + ).unwrap()) } #[uniffi::constructor] diff --git a/src/bitvec.rs b/src/bitvec.rs index 1ad7751..778b7bc 100644 --- a/src/bitvec.rs +++ b/src/bitvec.rs @@ -2,11 +2,11 @@ use std::sync::{Arc, RwLock}; #[derive(uniffi::Object)] pub struct BitVec { - pub(crate) actual: RwLock, + pub(crate) actual: RwLock, } impl BitVec { - fn internal_new(actual: servicepoint::BitVec) -> Arc { + fn internal_new(actual: servicepoint::DisplayBitVec) -> Arc { Arc::new(Self { actual: RwLock::new(actual), }) @@ -17,11 +17,11 @@ impl BitVec { impl BitVec { #[uniffi::constructor] pub fn new(size: u64) -> Arc { - Self::internal_new(servicepoint::BitVec::repeat(false, size as usize)) + Self::internal_new(servicepoint::DisplayBitVec::repeat(false, size as usize)) } #[uniffi::constructor] pub fn load(data: Vec) -> Arc { - Self::internal_new(servicepoint::BitVec::from_slice(&data)) + Self::internal_new(servicepoint::DisplayBitVec::from_slice(&data)) } #[uniffi::constructor] diff --git a/src/brightness_grid.rs b/src/brightness_grid.rs index afa0e3f..ba84cb4 100644 --- a/src/brightness_grid.rs +++ b/src/brightness_grid.rs @@ -30,7 +30,7 @@ impl BrightnessGrid { width as usize, height as usize, &data, - )) + ).unwrap()) } #[uniffi::constructor] diff --git a/src/command.rs b/src/command.rs index bb479ae..710aeab 100644 --- a/src/command.rs +++ b/src/command.rs @@ -5,16 +5,16 @@ use crate::char_grid::CharGrid; use crate::compression_code::CompressionCode; use crate::cp437_grid::Cp437Grid; use crate::errors::ServicePointError; -use servicepoint::Origin; +use servicepoint::{BitVecCommand, BrightnessGridCommand, CharGridCommand, ClearCommand, Cp437GridCommand, FadeOutCommand, GlobalBrightnessCommand, HardResetCommand, Origin}; use std::sync::Arc; #[derive(uniffi::Object)] pub struct Command { - pub(crate) actual: servicepoint::Command, + pub(crate) actual: servicepoint::TypedCommand, } impl Command { - fn internal_new(actual: servicepoint::Command) -> Arc { + fn internal_new(actual: servicepoint::TypedCommand) -> Arc { Arc::new(Command { actual }) } } @@ -23,27 +23,28 @@ impl Command { impl Command { #[uniffi::constructor] pub fn clear() -> Arc { - Self::internal_new(servicepoint::Command::Clear) + 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, + value }) - .map(servicepoint::Command::Brightness) + .map(GlobalBrightnessCommand::from) + .map(servicepoint::TypedCommand::Brightness) .map(Self::internal_new) } #[uniffi::constructor] pub fn fade_out() -> Arc { - Self::internal_new(servicepoint::Command::FadeOut) + Self::internal_new(FadeOutCommand.into()) } #[uniffi::constructor] pub fn hard_reset() -> Arc { - Self::internal_new(servicepoint::Command::HardReset) + Self::internal_new(HardResetCommand.into()) } #[uniffi::constructor] @@ -55,13 +56,13 @@ impl Command { ) -> Arc { let origin = Origin::new(offset_x as usize, offset_y as usize); let bitmap = bitmap.actual.read().unwrap().clone(); - let actual = servicepoint::Command::BitmapLinearWin( + let actual = servicepoint::BitmapCommand { origin, bitmap, - servicepoint::CompressionCode::try_from(compression as u16) + compression: servicepoint::CompressionCode::try_from(compression as u16) .unwrap(), - ); - Self::internal_new(actual) + }; + Self::internal_new(actual.into()) } #[uniffi::constructor] @@ -72,72 +73,31 @@ impl Command { ) -> Arc { let origin = Origin::new(offset_x as usize, offset_y as usize); let grid = grid.actual.read().unwrap().clone(); - let actual = servicepoint::Command::CharBrightness(origin, grid); - Self::internal_new(actual) + let actual = BrightnessGridCommand {origin, grid}; + Self::internal_new(actual.into()) } #[uniffi::constructor] pub fn bitmap_linear( offset: u64, - bitmap: &Arc, + bitvec: &Arc, compression: CompressionCode, + operation: BinaryOperation, ) -> Arc { - let bitmap = bitmap.actual.read().unwrap().clone(); - let actual = servicepoint::Command::BitmapLinear( - offset as usize, - bitmap, - servicepoint::CompressionCode::try_from(compression as u16) - .unwrap(), - ); - Self::internal_new(actual) - } - - #[uniffi::constructor] - pub fn bitmap_linear_and( - offset: u64, - bitmap: &Arc, - compression: CompressionCode, - ) -> Arc { - let bitmap = bitmap.actual.read().unwrap().clone(); - let actual = servicepoint::Command::BitmapLinearAnd( - offset as usize, - bitmap, - servicepoint::CompressionCode::try_from(compression as u16) - .unwrap(), - ); - Self::internal_new(actual) - } - - #[uniffi::constructor] - pub fn bitmap_linear_or( - offset: u64, - bitmap: &Arc, - compression: CompressionCode, - ) -> Arc { - let bitmap = bitmap.actual.read().unwrap().clone(); - let actual = servicepoint::Command::BitmapLinearOr( - offset as usize, - bitmap, - servicepoint::CompressionCode::try_from(compression as u16) - .unwrap(), - ); - Self::internal_new(actual) - } - - #[uniffi::constructor] - pub fn bitmap_linear_xor( - offset: u64, - bitmap: &Arc, - compression: CompressionCode, - ) -> Arc { - let bitmap = bitmap.actual.read().unwrap().clone(); - let actual = servicepoint::Command::BitmapLinearXor( - offset as usize, - bitmap, - servicepoint::CompressionCode::try_from(compression as u16) - .unwrap(), - ); - Self::internal_new(actual) + 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] @@ -148,8 +108,8 @@ impl Command { ) -> Arc { let origin = Origin::new(offset_x as usize, offset_y as usize); let grid = grid.actual.read().unwrap().clone(); - let actual = servicepoint::Command::Cp437Data(origin, grid); - Self::internal_new(actual) + let actual = Cp437GridCommand {origin, grid}; + Self::internal_new(actual.into()) } #[uniffi::constructor] @@ -160,8 +120,8 @@ impl Command { ) -> Arc { let origin = Origin::new(offset_x as usize, offset_y as usize); let grid = grid.actual.read().unwrap().clone(); - let actual = servicepoint::Command::Utf8Data(origin, grid); - Self::internal_new(actual) + let actual = CharGridCommand {origin, grid}; + Self::internal_new(actual.into()) } #[uniffi::constructor] @@ -173,3 +133,11 @@ impl Command { self.actual == other.actual } } + +#[derive(uniffi::Enum)] +pub enum BinaryOperation { + Overwrite, + And, + Or, + Xor, +} diff --git a/src/connection.rs b/src/connection.rs index 6ba4e07..9b0baea 100644 --- a/src/connection.rs +++ b/src/connection.rs @@ -1,35 +1,33 @@ -use std::sync::Arc; - -use crate::command::Command; -use crate::errors::ServicePointError; +use std::{ + net::UdpSocket, + sync::Arc +}; +use servicepoint::UdpSocketExt; +use crate::{ + command::Command, + errors::ServicePointError +}; #[derive(uniffi::Object)] pub struct Connection { - actual: servicepoint::Connection, + actual: UdpSocket, } #[uniffi::export] impl Connection { #[uniffi::constructor] pub fn new(host: String) -> Result, ServicePointError> { - servicepoint::Connection::open(host) + UdpSocket::bind_connect(host) .map(|actual| Arc::new(Connection { actual })) .map_err(|err| ServicePointError::IoError { error: err.to_string(), }) } - #[uniffi::constructor] - pub fn new_fake() -> Arc { - Arc::new(Self { - actual: servicepoint::Connection::Fake, - }) - } - pub fn send(&self, command: Arc) -> Result<(), ServicePointError> { - self.actual.send(command.actual.clone()).map_err(|err| { + self.actual.send_command(command.actual.clone()).ok_or_else(|| { ServicePointError::IoError { - error: format!("{err:?}"), + error: "send failed".to_string(), } }) } diff --git a/src/cp437_grid.rs b/src/cp437_grid.rs index b201238..89f9420 100644 --- a/src/cp437_grid.rs +++ b/src/cp437_grid.rs @@ -31,7 +31,7 @@ impl Cp437Grid { width as usize, height as usize, &data, - )) + ).unwrap()) } #[uniffi::constructor] From 14970c0ac41e4521e31c1964eed4cb06e32fa1bd Mon Sep 17 00:00:00 2001 From: Vinzenz Schroeter Date: Fri, 13 Jun 2025 01:09:31 +0200 Subject: [PATCH 06/15] declare wrapper types with macro --- src/bitmap.rs | 16 +++------------- src/bitvec.rs | 16 +++------------- src/brightness_grid.rs | 16 +++------------- src/char_grid.rs | 14 +++----------- src/command.rs | 18 +++++------------- src/connection.rs | 2 +- src/cp437_grid.rs | 16 +++------------- src/lib.rs | 1 + src/macros.rs | 22 ++++++++++++++++++++++ 9 files changed, 44 insertions(+), 77 deletions(-) create mode 100644 src/macros.rs diff --git a/src/bitmap.rs b/src/bitmap.rs index f658b85..c07fa07 100644 --- a/src/bitmap.rs +++ b/src/bitmap.rs @@ -1,18 +1,8 @@ use servicepoint::{DataRef, Grid}; -use std::sync::{Arc, RwLock}; +use std::sync::{Arc}; +use crate::macros::wrap_uniffi_object; -#[derive(uniffi::Object)] -pub struct Bitmap { - pub(crate) actual: RwLock, -} - -impl Bitmap { - fn internal_new(actual: servicepoint::Bitmap) -> Arc { - Arc::new(Self { - actual: RwLock::new(actual), - }) - } -} +wrap_uniffi_object!(Bitmap); #[uniffi::export] impl Bitmap { diff --git a/src/bitvec.rs b/src/bitvec.rs index 778b7bc..e9356fd 100644 --- a/src/bitvec.rs +++ b/src/bitvec.rs @@ -1,17 +1,7 @@ -use std::sync::{Arc, RwLock}; +use std::sync::{Arc}; +use crate::macros::wrap_uniffi_object; -#[derive(uniffi::Object)] -pub struct BitVec { - pub(crate) actual: RwLock, -} - -impl BitVec { - fn internal_new(actual: servicepoint::DisplayBitVec) -> Arc { - Arc::new(Self { - actual: RwLock::new(actual), - }) - } -} +wrap_uniffi_object!(DisplayBitVec, BitVec); #[uniffi::export] impl BitVec { diff --git a/src/brightness_grid.rs b/src/brightness_grid.rs index ba84cb4..ca64ebf 100644 --- a/src/brightness_grid.rs +++ b/src/brightness_grid.rs @@ -1,18 +1,8 @@ use servicepoint::{Brightness, DataRef, Grid}; -use std::sync::{Arc, RwLock}; +use std::sync::{Arc}; +use crate::macros::wrap_uniffi_object; -#[derive(uniffi::Object)] -pub struct BrightnessGrid { - pub(crate) actual: RwLock, -} - -impl BrightnessGrid { - fn internal_new(actual: servicepoint::BrightnessGrid) -> Arc { - Arc::new(Self { - actual: RwLock::new(actual), - }) - } -} +wrap_uniffi_object!(BrightnessGrid); #[uniffi::export] impl BrightnessGrid { diff --git a/src/char_grid.rs b/src/char_grid.rs index e5d59a8..8bf70ac 100644 --- a/src/char_grid.rs +++ b/src/char_grid.rs @@ -1,12 +1,10 @@ use crate::cp437_grid::Cp437Grid; use servicepoint::{Grid, SetValueSeriesError}; use std::convert::Into; -use std::sync::{Arc, RwLock}; +use std::sync::{Arc}; +use crate::macros::wrap_uniffi_object; -#[derive(uniffi::Object)] -pub struct CharGrid { - pub(crate) actual: RwLock, -} +wrap_uniffi_object!(CharGrid); #[derive(uniffi::Error, thiserror::Error, Debug)] pub enum CharGridError { @@ -133,12 +131,6 @@ impl CharGrid { } impl CharGrid { - pub(crate) fn internal_new(actual: servicepoint::CharGrid) -> Arc { - Arc::new(Self { - actual: RwLock::new(actual), - }) - } - fn str_to_char(value: String) -> Result { if value.len() != 1 { return Err(CharGridError::StringNotOneChar { value }); diff --git a/src/command.rs b/src/command.rs index 710aeab..5939761 100644 --- a/src/command.rs +++ b/src/command.rs @@ -1,4 +1,3 @@ -use crate::bitmap::Bitmap; use crate::bitvec::BitVec; use crate::brightness_grid::BrightnessGrid; use crate::char_grid::CharGrid; @@ -7,17 +6,10 @@ use crate::cp437_grid::Cp437Grid; use crate::errors::ServicePointError; use servicepoint::{BitVecCommand, BrightnessGridCommand, CharGridCommand, ClearCommand, Cp437GridCommand, FadeOutCommand, GlobalBrightnessCommand, HardResetCommand, Origin}; use std::sync::Arc; +use crate::bitmap::Bitmap; +use crate::macros::wrap_uniffi_object; -#[derive(uniffi::Object)] -pub struct Command { - pub(crate) actual: servicepoint::TypedCommand, -} - -impl Command { - fn internal_new(actual: servicepoint::TypedCommand) -> Arc { - Arc::new(Command { actual }) - } -} +wrap_uniffi_object!(TypedCommand, Command); #[uniffi::export] impl Command { @@ -126,11 +118,11 @@ impl Command { #[uniffi::constructor] pub fn clone(other: &Arc) -> Arc { - Self::internal_new(other.actual.clone()) + Self::internal_new(other.actual.read().unwrap().clone()) } pub fn equals(&self, other: &Command) -> bool { - self.actual == other.actual + *self.actual.read().unwrap() == *other.actual.read().unwrap() } } diff --git a/src/connection.rs b/src/connection.rs index 9b0baea..32c9b8a 100644 --- a/src/connection.rs +++ b/src/connection.rs @@ -25,7 +25,7 @@ impl Connection { } pub fn send(&self, command: Arc) -> Result<(), ServicePointError> { - self.actual.send_command(command.actual.clone()).ok_or_else(|| { + self.actual.send_command(command.actual.read().unwrap().clone()).ok_or_else(|| { ServicePointError::IoError { error: "send failed".to_string(), } diff --git a/src/cp437_grid.rs b/src/cp437_grid.rs index 89f9420..7ca1e62 100644 --- a/src/cp437_grid.rs +++ b/src/cp437_grid.rs @@ -1,19 +1,9 @@ use crate::char_grid::CharGrid; use servicepoint::{DataRef, Grid}; -use std::sync::{Arc, RwLock}; +use std::sync::{Arc}; +use crate::macros::wrap_uniffi_object; -#[derive(uniffi::Object)] -pub struct Cp437Grid { - pub(crate) actual: RwLock, -} - -impl Cp437Grid { - pub(crate) fn internal_new(actual: servicepoint::Cp437Grid) -> Arc { - Arc::new(Self { - actual: RwLock::new(actual), - }) - } -} +wrap_uniffi_object!(Cp437Grid); #[uniffi::export] impl Cp437Grid { diff --git a/src/lib.rs b/src/lib.rs index 2ecad45..b981f9d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -10,3 +10,4 @@ mod connection; mod constants; mod cp437_grid; mod errors; +mod macros; diff --git a/src/macros.rs b/src/macros.rs new file mode 100644 index 0000000..8f46c1c --- /dev/null +++ b/src/macros.rs @@ -0,0 +1,22 @@ + +macro_rules! wrap_uniffi_object { + ($orig_t:ident, $new_t:ident) => { + #[derive(uniffi::Object)] + pub struct $new_t { + pub(crate) actual: std::sync::RwLock, + } + + impl $new_t { + pub(crate) fn internal_new(actual: servicepoint::$orig_t) -> Arc { + Arc::new(Self { + actual: std::sync::RwLock::new(actual), + }) + } + } + }; + ($t:ident) => { + wrap_uniffi_object!($t, $t); + }; +} + +pub(crate) use wrap_uniffi_object; \ No newline at end of file From 9fa09fe33e95c09d79790295b4048e5a9c344464 Mon Sep 17 00:00:00 2001 From: Vinzenz Schroeter Date: Fri, 13 Jun 2025 01:13:51 +0200 Subject: [PATCH 07/15] add clone to macro --- src/bitmap.rs | 5 ----- src/bitvec.rs | 5 ----- src/brightness_grid.rs | 5 ----- src/char_grid.rs | 5 ----- src/command.rs | 5 ----- src/cp437_grid.rs | 5 ----- src/macros.rs | 8 ++++++++ 7 files changed, 8 insertions(+), 30 deletions(-) diff --git a/src/bitmap.rs b/src/bitmap.rs index c07fa07..aa2309c 100644 --- a/src/bitmap.rs +++ b/src/bitmap.rs @@ -28,11 +28,6 @@ impl Bitmap { ).unwrap()) } - #[uniffi::constructor] - pub fn clone(other: &Arc) -> Arc { - Self::internal_new(other.actual.read().unwrap().clone()) - } - pub fn set(&self, x: u64, y: u64, value: bool) { self.actual .write() diff --git a/src/bitvec.rs b/src/bitvec.rs index e9356fd..ef216f5 100644 --- a/src/bitvec.rs +++ b/src/bitvec.rs @@ -14,11 +14,6 @@ impl BitVec { Self::internal_new(servicepoint::DisplayBitVec::from_slice(&data)) } - #[uniffi::constructor] - pub fn clone(other: &Arc) -> Arc { - Self::internal_new(other.actual.read().unwrap().clone()) - } - pub fn set(&self, index: u64, value: bool) { self.actual.write().unwrap().set(index as usize, value) } diff --git a/src/brightness_grid.rs b/src/brightness_grid.rs index ca64ebf..956f139 100644 --- a/src/brightness_grid.rs +++ b/src/brightness_grid.rs @@ -23,11 +23,6 @@ impl BrightnessGrid { ).unwrap()) } - #[uniffi::constructor] - pub fn clone(other: &Arc) -> Arc { - Self::internal_new(other.actual.read().unwrap().clone()) - } - pub fn set(&self, x: u64, y: u64, value: u8) { self.actual.write().unwrap().set( x as usize, diff --git a/src/char_grid.rs b/src/char_grid.rs index 8bf70ac..1f39e1c 100644 --- a/src/char_grid.rs +++ b/src/char_grid.rs @@ -31,11 +31,6 @@ impl CharGrid { Self::internal_new(servicepoint::CharGrid::from(&*data)) } - #[uniffi::constructor] - pub fn clone(other: &Arc) -> Arc { - Self::internal_new(other.actual.read().unwrap().clone()) - } - pub fn set( &self, x: u64, diff --git a/src/command.rs b/src/command.rs index 5939761..aaf508c 100644 --- a/src/command.rs +++ b/src/command.rs @@ -116,11 +116,6 @@ impl Command { Self::internal_new(actual.into()) } - #[uniffi::constructor] - pub fn clone(other: &Arc) -> Arc { - Self::internal_new(other.actual.read().unwrap().clone()) - } - pub fn equals(&self, other: &Command) -> bool { *self.actual.read().unwrap() == *other.actual.read().unwrap() } diff --git a/src/cp437_grid.rs b/src/cp437_grid.rs index 7ca1e62..9db5d8e 100644 --- a/src/cp437_grid.rs +++ b/src/cp437_grid.rs @@ -24,11 +24,6 @@ impl Cp437Grid { ).unwrap()) } - #[uniffi::constructor] - pub fn clone(other: &Arc) -> Arc { - Self::internal_new(other.actual.read().unwrap().clone()) - } - pub fn set(&self, x: u64, y: u64, value: u8) { self.actual .write() diff --git a/src/macros.rs b/src/macros.rs index 8f46c1c..b22b12a 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -13,6 +13,14 @@ macro_rules! wrap_uniffi_object { }) } } + + #[uniffi::export] + impl $new_t { + #[uniffi::constructor] + pub fn clone(other: &Arc) -> Arc { + Self::internal_new(other.actual.read().unwrap().clone()) + } + } }; ($t:ident) => { wrap_uniffi_object!($t, $t); From 3c27917afac6ff898b8b89721aaeb63e94d178bf Mon Sep 17 00:00:00 2001 From: Vinzenz Schroeter Date: Fri, 13 Jun 2025 01:27:57 +0200 Subject: [PATCH 08/15] add width and height macro --- src/bitmap.rs | 12 +++--------- src/brightness_grid.rs | 10 ++-------- src/char_grid.rs | 11 ++--------- src/cp437_grid.rs | 10 ++-------- src/macros.rs | 21 +++++++++++++++++++-- 5 files changed, 28 insertions(+), 36 deletions(-) diff --git a/src/bitmap.rs b/src/bitmap.rs index aa2309c..de094d2 100644 --- a/src/bitmap.rs +++ b/src/bitmap.rs @@ -1,8 +1,9 @@ use servicepoint::{DataRef, Grid}; use std::sync::{Arc}; -use crate::macros::wrap_uniffi_object; +use crate::macros::{wrap_width_height, wrap_uniffi_object}; wrap_uniffi_object!(Bitmap); +wrap_width_height!(Bitmap); #[uniffi::export] impl Bitmap { @@ -42,14 +43,7 @@ impl Bitmap { pub fn fill(&self, value: bool) { self.actual.write().unwrap().fill(value) } - pub fn width(&self) -> u64 { - self.actual.read().unwrap().width() as u64 - } - - pub fn height(&self) -> u64 { - self.actual.read().unwrap().height() as u64 - } - + pub fn equals(&self, other: &Bitmap) -> bool { let a = self.actual.read().unwrap(); let b = other.actual.read().unwrap(); diff --git a/src/brightness_grid.rs b/src/brightness_grid.rs index 956f139..04f6321 100644 --- a/src/brightness_grid.rs +++ b/src/brightness_grid.rs @@ -1,8 +1,9 @@ use servicepoint::{Brightness, DataRef, Grid}; use std::sync::{Arc}; -use crate::macros::wrap_uniffi_object; +use crate::macros::{wrap_width_height, wrap_uniffi_object}; wrap_uniffi_object!(BrightnessGrid); +wrap_width_height!(BrightnessGrid); #[uniffi::export] impl BrightnessGrid { @@ -45,13 +46,6 @@ impl BrightnessGrid { .unwrap() .fill(Brightness::saturating_from(value)) } - pub fn width(&self) -> u64 { - self.actual.read().unwrap().width() as u64 - } - - pub fn height(&self) -> u64 { - self.actual.read().unwrap().height() as u64 - } pub fn equals(&self, other: &BrightnessGrid) -> bool { let a = self.actual.read().unwrap(); diff --git a/src/char_grid.rs b/src/char_grid.rs index 1f39e1c..ff27cd1 100644 --- a/src/char_grid.rs +++ b/src/char_grid.rs @@ -2,9 +2,10 @@ use crate::cp437_grid::Cp437Grid; use servicepoint::{Grid, SetValueSeriesError}; use std::convert::Into; use std::sync::{Arc}; -use crate::macros::wrap_uniffi_object; +use crate::macros::{wrap_width_height, wrap_uniffi_object}; wrap_uniffi_object!(CharGrid); +wrap_width_height!(CharGrid); #[derive(uniffi::Error, thiserror::Error, Debug)] pub enum CharGridError { @@ -59,14 +60,6 @@ impl CharGrid { Ok(()) } - pub fn width(&self) -> u64 { - self.actual.read().unwrap().width() as u64 - } - - pub fn height(&self) -> u64 { - self.actual.read().unwrap().height() as u64 - } - pub fn equals(&self, other: &CharGrid) -> bool { let a = self.actual.read().unwrap(); let b = other.actual.read().unwrap(); diff --git a/src/cp437_grid.rs b/src/cp437_grid.rs index 9db5d8e..b7ba623 100644 --- a/src/cp437_grid.rs +++ b/src/cp437_grid.rs @@ -1,9 +1,10 @@ use crate::char_grid::CharGrid; use servicepoint::{DataRef, Grid}; use std::sync::{Arc}; -use crate::macros::wrap_uniffi_object; +use crate::macros::{wrap_width_height, wrap_uniffi_object}; wrap_uniffi_object!(Cp437Grid); +wrap_width_height!(Cp437Grid); #[uniffi::export] impl Cp437Grid { @@ -38,13 +39,6 @@ impl Cp437Grid { pub fn fill(&self, value: u8) { self.actual.write().unwrap().fill(value) } - pub fn width(&self) -> u64 { - self.actual.read().unwrap().width() as u64 - } - - pub fn height(&self) -> u64 { - self.actual.read().unwrap().height() as u64 - } pub fn equals(&self, other: &Cp437Grid) -> bool { let a = self.actual.read().unwrap(); diff --git a/src/macros.rs b/src/macros.rs index b22b12a..9a4de90 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -13,7 +13,7 @@ macro_rules! wrap_uniffi_object { }) } } - + #[uniffi::export] impl $new_t { #[uniffi::constructor] @@ -27,4 +27,21 @@ macro_rules! wrap_uniffi_object { }; } -pub(crate) use wrap_uniffi_object; \ No newline at end of file +pub(crate) use wrap_uniffi_object; + +macro_rules! wrap_width_height { + ($t:ident) => { + #[uniffi::export] + impl $t { + pub fn width(&self) -> u64 { + self.actual.read().unwrap().width() as u64 + } + + pub fn height(&self) -> u64 { + self.actual.read().unwrap().height() as u64 + } + } + }; +} + +pub(crate) use wrap_width_height; \ No newline at end of file From 8d5e4086530bc1a6c86b06b20098a61e1f915ebf Mon Sep 17 00:00:00 2001 From: Vinzenz Schroeter Date: Fri, 13 Jun 2025 09:52:07 +0200 Subject: [PATCH 09/15] add get set fill macro --- src/bitmap.rs | 38 ++++++++++++-------------------------- src/brightness.rs | 19 +++++++++++++++++++ src/brightness_grid.rs | 41 ++++++++++++----------------------------- src/cp437_grid.rs | 33 +++++++++++---------------------- src/lib.rs | 1 + src/macros.rs | 37 +++++++++++++++++++++++++++++++------ 6 files changed, 86 insertions(+), 83 deletions(-) create mode 100644 src/brightness.rs diff --git a/src/bitmap.rs b/src/bitmap.rs index de094d2..d030ea8 100644 --- a/src/bitmap.rs +++ b/src/bitmap.rs @@ -1,18 +1,20 @@ +use crate::macros::{ + wrap_get_set_fill_2d, wrap_uniffi_object, wrap_width_height, +}; use servicepoint::{DataRef, Grid}; -use std::sync::{Arc}; -use crate::macros::{wrap_width_height, wrap_uniffi_object}; +use std::sync::Arc; wrap_uniffi_object!(Bitmap); wrap_width_height!(Bitmap); +wrap_get_set_fill_2d!(Bitmap, bool); #[uniffi::export] impl Bitmap { #[uniffi::constructor] pub fn new(width: u64, height: u64) -> Arc { - Self::internal_new(servicepoint::Bitmap::new( - width as usize, - height as usize, - ).unwrap()) + Self::internal_new( + servicepoint::Bitmap::new(width as usize, height as usize).unwrap(), + ) } #[uniffi::constructor] @@ -22,28 +24,12 @@ impl Bitmap { #[uniffi::constructor] pub fn load(width: u64, height: u64, data: Vec) -> Arc { - Self::internal_new(servicepoint::Bitmap::load( - width as usize, - height as usize, - &data, - ).unwrap()) + Self::internal_new( + servicepoint::Bitmap::load(width as usize, height as usize, &data) + .unwrap(), + ) } - pub fn set(&self, x: u64, y: u64, value: bool) { - self.actual - .write() - .unwrap() - .set(x as usize, y as usize, value) - } - - pub fn get(&self, x: u64, y: u64) -> bool { - self.actual.read().unwrap().get(x as usize, y as usize) - } - - pub fn fill(&self, value: bool) { - self.actual.write().unwrap().fill(value) - } - pub fn equals(&self, other: &Bitmap) -> bool { let a = self.actual.read().unwrap(); let b = other.actual.read().unwrap(); diff --git a/src/brightness.rs b/src/brightness.rs new file mode 100644 index 0000000..0ea4591 --- /dev/null +++ b/src/brightness.rs @@ -0,0 +1,19 @@ +use crate::UniffiCustomTypeConverter; +use servicepoint::Brightness; + +uniffi::custom_type!(Brightness, u8); + +impl UniffiCustomTypeConverter for Brightness { + type Builtin = u8; + + fn into_custom(val: Self::Builtin) -> uniffi::Result + where + Self: Sized, + { + Ok(Brightness::saturating_from(val)) + } + + fn from_custom(obj: Self) -> Self::Builtin { + obj.into() + } +} diff --git a/src/brightness_grid.rs b/src/brightness_grid.rs index 04f6321..697a71f 100644 --- a/src/brightness_grid.rs +++ b/src/brightness_grid.rs @@ -1,9 +1,12 @@ +use crate::macros::{ + wrap_get_set_fill_2d, wrap_uniffi_object, wrap_width_height, +}; use servicepoint::{Brightness, DataRef, Grid}; -use std::sync::{Arc}; -use crate::macros::{wrap_width_height, wrap_uniffi_object}; +use std::sync::Arc; wrap_uniffi_object!(BrightnessGrid); wrap_width_height!(BrightnessGrid); +wrap_get_set_fill_2d!(BrightnessGrid, Brightness); #[uniffi::export] impl BrightnessGrid { @@ -17,36 +20,16 @@ impl BrightnessGrid { #[uniffi::constructor] pub fn load(width: u64, height: u64, data: Vec) -> Arc { - Self::internal_new(servicepoint::BrightnessGrid::saturating_load( - width as usize, - height as usize, - &data, - ).unwrap()) - } - - pub fn set(&self, x: u64, y: u64, value: u8) { - self.actual.write().unwrap().set( - x as usize, - y as usize, - Brightness::saturating_from(value), + Self::internal_new( + servicepoint::BrightnessGrid::saturating_load( + width as usize, + height as usize, + &data, + ) + .unwrap(), ) } - pub fn get(&self, x: u64, y: u64) -> u8 { - self.actual - .read() - .unwrap() - .get(x as usize, y as usize) - .into() - } - - pub fn fill(&self, value: u8) { - self.actual - .write() - .unwrap() - .fill(Brightness::saturating_from(value)) - } - pub fn equals(&self, other: &BrightnessGrid) -> bool { let a = self.actual.read().unwrap(); let b = other.actual.read().unwrap(); diff --git a/src/cp437_grid.rs b/src/cp437_grid.rs index b7ba623..eeeb8b6 100644 --- a/src/cp437_grid.rs +++ b/src/cp437_grid.rs @@ -1,10 +1,11 @@ use crate::char_grid::CharGrid; +use crate::macros::{wrap_get_set_fill_2d, wrap_uniffi_object, wrap_width_height}; use servicepoint::{DataRef, Grid}; -use std::sync::{Arc}; -use crate::macros::{wrap_width_height, wrap_uniffi_object}; +use std::sync::Arc; wrap_uniffi_object!(Cp437Grid); wrap_width_height!(Cp437Grid); +wrap_get_set_fill_2d!(Cp437Grid, u8); #[uniffi::export] impl Cp437Grid { @@ -18,26 +19,14 @@ impl Cp437Grid { #[uniffi::constructor] pub fn load(width: u64, height: u64, data: Vec) -> Arc { - Self::internal_new(servicepoint::Cp437Grid::load( - width as usize, - height as usize, - &data, - ).unwrap()) - } - - pub fn set(&self, x: u64, y: u64, value: u8) { - self.actual - .write() - .unwrap() - .set(x as usize, y as usize, value) - } - - pub fn get(&self, x: u64, y: u64) -> u8 { - self.actual.read().unwrap().get(x as usize, y as usize) - } - - pub fn fill(&self, value: u8) { - self.actual.write().unwrap().fill(value) + Self::internal_new( + servicepoint::Cp437Grid::load( + width as usize, + height as usize, + &data, + ) + .unwrap(), + ) } pub fn equals(&self, other: &Cp437Grid) -> bool { diff --git a/src/lib.rs b/src/lib.rs index b981f9d..c116ccb 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2,6 +2,7 @@ uniffi::setup_scaffolding!(); mod bitmap; mod bitvec; +mod brightness; mod brightness_grid; mod char_grid; mod command; diff --git a/src/macros.rs b/src/macros.rs index 9a4de90..799a95f 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -1,13 +1,14 @@ - macro_rules! wrap_uniffi_object { - ($orig_t:ident, $new_t:ident) => { + ($orig_t:ident, $new_t:ident) => { #[derive(uniffi::Object)] pub struct $new_t { pub(crate) actual: std::sync::RwLock, } impl $new_t { - pub(crate) fn internal_new(actual: servicepoint::$orig_t) -> Arc { + pub(crate) fn internal_new( + actual: servicepoint::$orig_t, + ) -> Arc { Arc::new(Self { actual: std::sync::RwLock::new(actual), }) @@ -21,7 +22,7 @@ macro_rules! wrap_uniffi_object { Self::internal_new(other.actual.read().unwrap().clone()) } } - }; + }; ($t:ident) => { wrap_uniffi_object!($t, $t); }; @@ -36,7 +37,7 @@ macro_rules! wrap_width_height { pub fn width(&self) -> u64 { self.actual.read().unwrap().width() as u64 } - + pub fn height(&self) -> u64 { self.actual.read().unwrap().height() as u64 } @@ -44,4 +45,28 @@ macro_rules! wrap_width_height { }; } -pub(crate) use wrap_width_height; \ No newline at end of file +pub(crate) use wrap_width_height; + +macro_rules! wrap_get_set_fill_2d { + ($t:ident, $contained:ident) => { + #[uniffi::export] + impl $t { + pub fn set(&self, x: u64, y: u64, value: $contained) { + self.actual + .write() + .unwrap() + .set(x as usize, y as usize, value) + } + + pub fn get(&self, x: u64, y: u64) -> $contained { + self.actual.read().unwrap().get(x as usize, y as usize) + } + + pub fn fill(&self, value: $contained) { + self.actual.write().unwrap().fill(value) + } + } + }; +} + +pub(crate) use wrap_get_set_fill_2d; From 4cbf3784fc2a17e2380c7bb7e1c66812cb397534 Mon Sep 17 00:00:00 2001 From: Vinzenz Schroeter Date: Fri, 13 Jun 2025 10:17:59 +0200 Subject: [PATCH 10/15] update servicepoint, simplify copy_raw --- Cargo.lock | 8 ++++---- Cargo.toml | 4 ++-- src/bitmap.rs | 4 ++-- src/brightness_grid.rs | 13 +++++-------- src/cp437_grid.rs | 8 +++++--- 5 files changed, 18 insertions(+), 19 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 930a6a9..486957e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,6 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] name = "adler2" @@ -425,9 +425,9 @@ dependencies = [ [[package]] name = "servicepoint" -version = "0.14.1" +version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6bd5cfa49c73aeecb344680ffbf697abf73e0563a441b93b9723ae43867500f" +checksum = "91a33bff7f9db5008748b23ca0c906c276fe00694390b681f004a55968a42cfe" dependencies = [ "bitvec", "bzip2", @@ -441,7 +441,7 @@ dependencies = [ [[package]] name = "servicepoint_binding_uniffi" -version = "0.13.1" +version = "0.15.0" dependencies = [ "servicepoint", "thiserror 2.0.11", diff --git a/Cargo.toml b/Cargo.toml index c9f07fd..d6d0c18 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "servicepoint_binding_uniffi" -version = "0.13.1" +version = "0.15.0" publish = false edition = "2021" license = "GPL-3.0-or-later" @@ -21,7 +21,7 @@ uniffi = { version = "0.28.3" } thiserror = "2.0" [dependencies.servicepoint] -version = "0.14.1" +version = "0.15.0" features = ["all_compressions"] [package.metadata.docs.rs] diff --git a/src/bitmap.rs b/src/bitmap.rs index d030ea8..6c2f198 100644 --- a/src/bitmap.rs +++ b/src/bitmap.rs @@ -2,7 +2,7 @@ use crate::macros::{ wrap_get_set_fill_2d, wrap_uniffi_object, wrap_width_height, }; use servicepoint::{DataRef, Grid}; -use std::sync::Arc; +use std::{ops::Deref, sync::Arc}; wrap_uniffi_object!(Bitmap); wrap_width_height!(Bitmap); @@ -37,6 +37,6 @@ impl Bitmap { } pub fn copy_raw(&self) -> Vec { - self.actual.read().unwrap().data_ref().to_vec() + self.actual.read().unwrap().deref().into() } } diff --git a/src/brightness_grid.rs b/src/brightness_grid.rs index 697a71f..8cff1f8 100644 --- a/src/brightness_grid.rs +++ b/src/brightness_grid.rs @@ -2,7 +2,10 @@ use crate::macros::{ wrap_get_set_fill_2d, wrap_uniffi_object, wrap_width_height, }; use servicepoint::{Brightness, DataRef, Grid}; -use std::sync::Arc; +use std::{ + ops::Deref, + sync::{Arc, RwLockReadGuard}, +}; wrap_uniffi_object!(BrightnessGrid); wrap_width_height!(BrightnessGrid); @@ -37,12 +40,6 @@ impl BrightnessGrid { } pub fn copy_raw(&self) -> Vec { - self.actual - .read() - .unwrap() - .data_ref() - .iter() - .map(u8::from) - .collect() + self.actual.read().unwrap().deref().into() } } diff --git a/src/cp437_grid.rs b/src/cp437_grid.rs index eeeb8b6..9636b24 100644 --- a/src/cp437_grid.rs +++ b/src/cp437_grid.rs @@ -1,7 +1,9 @@ use crate::char_grid::CharGrid; -use crate::macros::{wrap_get_set_fill_2d, wrap_uniffi_object, wrap_width_height}; +use crate::macros::{ + wrap_get_set_fill_2d, wrap_uniffi_object, wrap_width_height, +}; use servicepoint::{DataRef, Grid}; -use std::sync::Arc; +use std::{ops::Deref, sync::Arc}; wrap_uniffi_object!(Cp437Grid); wrap_width_height!(Cp437Grid); @@ -36,7 +38,7 @@ impl Cp437Grid { } pub fn copy_raw(&self) -> Vec { - self.actual.read().unwrap().data_ref().to_vec() + self.actual.read().unwrap().deref().into() } pub fn to_utf8(&self) -> Arc { From 227db03d231ab3623cfa1394f3f11563ae2b9d7e Mon Sep 17 00:00:00 2001 From: Vinzenz Schroeter Date: Fri, 13 Jun 2025 11:45:11 +0200 Subject: [PATCH 11/15] move containers to module --- src/command.rs | 23 ++++++++++++++--------- src/{ => containers}/bitmap.rs | 6 ++---- src/{ => containers}/bitvec.rs | 7 +++++-- src/{ => containers}/brightness_grid.rs | 11 +++-------- src/{ => containers}/char_grid.rs | 6 ++---- src/{ => containers}/cp437_grid.rs | 7 ++----- src/containers/mod.rs | 5 +++++ src/lib.rs | 7 ++----- 8 files changed, 35 insertions(+), 37 deletions(-) rename src/{ => containers}/bitmap.rs (89%) rename src/{ => containers}/bitvec.rs (88%) rename src/{ => containers}/brightness_grid.rs (83%) rename src/{ => containers}/char_grid.rs (96%) rename src/{ => containers}/cp437_grid.rs (87%) create mode 100644 src/containers/mod.rs diff --git a/src/command.rs b/src/command.rs index aaf508c..bc59001 100644 --- a/src/command.rs +++ b/src/command.rs @@ -1,13 +1,18 @@ -use crate::bitvec::BitVec; -use crate::brightness_grid::BrightnessGrid; -use crate::char_grid::CharGrid; -use crate::compression_code::CompressionCode; -use crate::cp437_grid::Cp437Grid; -use crate::errors::ServicePointError; -use servicepoint::{BitVecCommand, BrightnessGridCommand, CharGridCommand, ClearCommand, Cp437GridCommand, FadeOutCommand, GlobalBrightnessCommand, HardResetCommand, Origin}; +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; -use crate::bitmap::Bitmap; -use crate::macros::wrap_uniffi_object; wrap_uniffi_object!(TypedCommand, Command); diff --git a/src/bitmap.rs b/src/containers/bitmap.rs similarity index 89% rename from src/bitmap.rs rename to src/containers/bitmap.rs index 6c2f198..01b99a4 100644 --- a/src/bitmap.rs +++ b/src/containers/bitmap.rs @@ -1,7 +1,5 @@ -use crate::macros::{ - wrap_get_set_fill_2d, wrap_uniffi_object, wrap_width_height, -}; -use servicepoint::{DataRef, Grid}; +use crate::macros::*; +use servicepoint::Grid; use std::{ops::Deref, sync::Arc}; wrap_uniffi_object!(Bitmap); diff --git a/src/bitvec.rs b/src/containers/bitvec.rs similarity index 88% rename from src/bitvec.rs rename to src/containers/bitvec.rs index ef216f5..17df9fd 100644 --- a/src/bitvec.rs +++ b/src/containers/bitvec.rs @@ -1,5 +1,5 @@ -use std::sync::{Arc}; use crate::macros::wrap_uniffi_object; +use std::sync::Arc; wrap_uniffi_object!(DisplayBitVec, BitVec); @@ -7,7 +7,10 @@ wrap_uniffi_object!(DisplayBitVec, BitVec); impl BitVec { #[uniffi::constructor] pub fn new(size: u64) -> Arc { - Self::internal_new(servicepoint::DisplayBitVec::repeat(false, size as usize)) + Self::internal_new(servicepoint::DisplayBitVec::repeat( + false, + size as usize, + )) } #[uniffi::constructor] pub fn load(data: Vec) -> Arc { diff --git a/src/brightness_grid.rs b/src/containers/brightness_grid.rs similarity index 83% rename from src/brightness_grid.rs rename to src/containers/brightness_grid.rs index 8cff1f8..dcfaa47 100644 --- a/src/brightness_grid.rs +++ b/src/containers/brightness_grid.rs @@ -1,11 +1,6 @@ -use crate::macros::{ - wrap_get_set_fill_2d, wrap_uniffi_object, wrap_width_height, -}; -use servicepoint::{Brightness, DataRef, Grid}; -use std::{ - ops::Deref, - sync::{Arc, RwLockReadGuard}, -}; +use crate::macros::*; +use servicepoint::{Brightness, Grid}; +use std::{ops::Deref, sync::Arc}; wrap_uniffi_object!(BrightnessGrid); wrap_width_height!(BrightnessGrid); diff --git a/src/char_grid.rs b/src/containers/char_grid.rs similarity index 96% rename from src/char_grid.rs rename to src/containers/char_grid.rs index ff27cd1..4300172 100644 --- a/src/char_grid.rs +++ b/src/containers/char_grid.rs @@ -1,8 +1,6 @@ -use crate::cp437_grid::Cp437Grid; +use crate::{containers::cp437_grid::Cp437Grid, macros::*}; use servicepoint::{Grid, SetValueSeriesError}; -use std::convert::Into; -use std::sync::{Arc}; -use crate::macros::{wrap_width_height, wrap_uniffi_object}; +use std::{convert::Into, sync::Arc}; wrap_uniffi_object!(CharGrid); wrap_width_height!(CharGrid); diff --git a/src/cp437_grid.rs b/src/containers/cp437_grid.rs similarity index 87% rename from src/cp437_grid.rs rename to src/containers/cp437_grid.rs index 9636b24..bf42122 100644 --- a/src/cp437_grid.rs +++ b/src/containers/cp437_grid.rs @@ -1,8 +1,5 @@ -use crate::char_grid::CharGrid; -use crate::macros::{ - wrap_get_set_fill_2d, wrap_uniffi_object, wrap_width_height, -}; -use servicepoint::{DataRef, Grid}; +use crate::{containers::char_grid::CharGrid, macros::*}; +use servicepoint::Grid; use std::{ops::Deref, sync::Arc}; wrap_uniffi_object!(Cp437Grid); diff --git a/src/containers/mod.rs b/src/containers/mod.rs new file mode 100644 index 0000000..7dce8bd --- /dev/null +++ b/src/containers/mod.rs @@ -0,0 +1,5 @@ +pub mod bitmap; +pub mod bitvec; +pub mod brightness_grid; +pub mod char_grid; +pub mod cp437_grid; diff --git a/src/lib.rs b/src/lib.rs index c116ccb..f491dbe 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,14 +1,11 @@ uniffi::setup_scaffolding!(); -mod bitmap; -mod bitvec; mod brightness; -mod brightness_grid; -mod char_grid; mod command; +mod commands; mod compression_code; mod connection; mod constants; -mod cp437_grid; +mod containers; mod errors; mod macros; From c29482ac562b7e04ed937d4f06767cd250bd3468 Mon Sep 17 00:00:00 2001 From: Vinzenz Schroeter Date: Fri, 13 Jun 2025 11:47:23 +0200 Subject: [PATCH 12/15] move command to module, first separate types --- src/commands/cc_only.rs | 23 +++++++++++++++++++++++ src/{ => commands}/command.rs | 24 +++++++++++++++--------- src/commands/mod.rs | 3 +++ src/connection.rs | 18 ++++++------------ src/lib.rs | 1 - 5 files changed, 47 insertions(+), 22 deletions(-) create mode 100644 src/commands/cc_only.rs rename src/{ => commands}/command.rs (89%) create mode 100644 src/commands/mod.rs diff --git a/src/commands/cc_only.rs b/src/commands/cc_only.rs new file mode 100644 index 0000000..634e7d0 --- /dev/null +++ b/src/commands/cc_only.rs @@ -0,0 +1,23 @@ +use std::sync::Arc; + +macro_rules! command_code_only_command { + ($command_struct:ident) => { + #[derive(uniffi::Object)] + pub struct $command_struct; + + #[uniffi::export] + impl $command_struct { + #[uniffi::constructor] + pub fn new() -> Arc { + const _: () = + assert!(size_of::() == 0); + Arc::new($command_struct) + } + } + }; +} + +command_code_only_command!(ClearCommand); +command_code_only_command!(HardResetCommand); +command_code_only_command!(BitmapLegacyCommand); +command_code_only_command!(FadeOutCommand); diff --git a/src/command.rs b/src/commands/command.rs similarity index 89% rename from src/command.rs rename to src/commands/command.rs index bc59001..9041b33 100644 --- a/src/command.rs +++ b/src/commands/command.rs @@ -27,7 +27,7 @@ impl Command { pub fn brightness(brightness: u8) -> Result, ServicePointError> { servicepoint::Brightness::try_from(brightness) .map_err(move |value| ServicePointError::InvalidBrightness { - value + value, }) .map(GlobalBrightnessCommand::from) .map(servicepoint::TypedCommand::Brightness) @@ -56,8 +56,10 @@ impl Command { let actual = servicepoint::BitmapCommand { origin, bitmap, - compression: servicepoint::CompressionCode::try_from(compression as u16) - .unwrap(), + compression: servicepoint::CompressionCode::try_from( + compression as u16, + ) + .unwrap(), }; Self::internal_new(actual.into()) } @@ -70,7 +72,7 @@ impl Command { ) -> 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}; + let actual = BrightnessGridCommand { origin, grid }; Self::internal_new(actual.into()) } @@ -85,14 +87,18 @@ impl Command { let actual = BitVecCommand { offset: offset as usize, bitvec, - compression: servicepoint::CompressionCode::try_from(compression as u16) + compression: servicepoint::CompressionCode::try_from( + compression as u16, + ) .unwrap(), operation: match operation { - BinaryOperation::Overwrite => servicepoint::BinaryOperation::Overwrite, + 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()) } @@ -105,7 +111,7 @@ impl Command { ) -> 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}; + let actual = Cp437GridCommand { origin, grid }; Self::internal_new(actual.into()) } @@ -117,7 +123,7 @@ impl Command { ) -> 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}; + let actual = CharGridCommand { origin, grid }; Self::internal_new(actual.into()) } diff --git a/src/commands/mod.rs b/src/commands/mod.rs new file mode 100644 index 0000000..4be7e73 --- /dev/null +++ b/src/commands/mod.rs @@ -0,0 +1,3 @@ +pub mod command; + +pub mod cc_only; diff --git a/src/connection.rs b/src/connection.rs index 32c9b8a..1e6a63b 100644 --- a/src/connection.rs +++ b/src/connection.rs @@ -1,12 +1,6 @@ -use std::{ - net::UdpSocket, - sync::Arc -}; +use crate::{commands::command::Command, errors::ServicePointError}; use servicepoint::UdpSocketExt; -use crate::{ - command::Command, - errors::ServicePointError -}; +use std::{net::UdpSocket, sync::Arc}; #[derive(uniffi::Object)] pub struct Connection { @@ -25,10 +19,10 @@ impl Connection { } pub fn send(&self, command: Arc) -> Result<(), ServicePointError> { - self.actual.send_command(command.actual.read().unwrap().clone()).ok_or_else(|| { - ServicePointError::IoError { + self.actual + .send_command(command.actual.read().unwrap().clone()) + .ok_or_else(|| ServicePointError::IoError { error: "send failed".to_string(), - } - }) + }) } } diff --git a/src/lib.rs b/src/lib.rs index f491dbe..c7addef 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,7 +1,6 @@ uniffi::setup_scaffolding!(); mod brightness; -mod command; mod commands; mod compression_code; mod connection; From bffc9052614e49f7706bd5565d357cd85c05e3a7 Mon Sep 17 00:00:00 2001 From: Vinzenz Schroeter Date: Mon, 16 Jun 2025 11:32:12 +0200 Subject: [PATCH 13/15] create separate types per command --- src/commands/bitmap.rs | 30 +++++++ src/commands/bitvec.rs | 52 +++++++++++ src/commands/brightness_grid.rs | 24 +++++ src/commands/cc_only.rs | 9 +- src/commands/char_grid.rs | 24 +++++ src/commands/command.rs | 141 ------------------------------ src/commands/cp437.rs | 24 +++++ src/commands/global_brightness.rs | 16 ++++ src/commands/mod.rs | 43 ++++++++- src/compression_code.rs | 12 +++ src/connection.rs | 9 +- src/containers/bitmap.rs | 8 +- src/containers/bitvec.rs | 12 +-- src/containers/brightness_grid.rs | 8 +- src/containers/char_grid.rs | 12 ++- src/containers/cp437_grid.rs | 12 ++- src/lib.rs | 17 ++-- src/macros.rs | 41 ++++++--- src/packet.rs | 12 +++ 19 files changed, 306 insertions(+), 200 deletions(-) create mode 100644 src/commands/bitmap.rs create mode 100644 src/commands/bitvec.rs create mode 100644 src/commands/brightness_grid.rs create mode 100644 src/commands/char_grid.rs delete mode 100644 src/commands/command.rs create mode 100644 src/commands/cp437.rs create mode 100644 src/commands/global_brightness.rs create mode 100644 src/packet.rs 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) + } +} From f4c75196587434b5a45f3903298e13dd766da4be Mon Sep 17 00:00:00 2001 From: Vinzenz Schroeter Date: Mon, 16 Jun 2025 14:56:24 +0200 Subject: [PATCH 14/15] export some builtin traits, brightness conversion fails for invalid values, macros for wrapping attrs --- Cargo.lock | 4 +- Cargo.toml | 3 + src/brightness.rs | 4 +- src/commands/bitmap.rs | 5 +- src/commands/bitvec.rs | 4 +- src/commands/brightness_grid.rs | 4 +- src/commands/cc_only.rs | 5 +- src/commands/char_grid.rs | 4 +- src/commands/cp437.rs | 4 +- src/commands/global_brightness.rs | 3 +- src/commands/mod.rs | 44 +++++++++--- src/connection.rs | 8 +++ src/containers/bitmap.rs | 12 ++-- src/containers/bitvec.rs | 16 +---- src/containers/brightness_grid.rs | 11 ++- src/containers/char_grid.rs | 40 +++-------- src/containers/cp437_grid.rs | 12 ++-- src/containers/mod.rs | 41 ++++++++++++ src/errors.rs | 2 + src/macros.rs | 107 +++++++++++++++++++++--------- src/packet.rs | 10 +-- 21 files changed, 210 insertions(+), 133 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 486957e..8dfbf55 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -426,8 +426,7 @@ dependencies = [ [[package]] name = "servicepoint" version = "0.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91a33bff7f9db5008748b23ca0c906c276fe00694390b681f004a55968a42cfe" +source = "git+https://git.berlin.ccc.de/servicepoint/servicepoint.git?branch=next#5b6f88b1682925b7669b25a7fb08806c4009bbfd" dependencies = [ "bitvec", "bzip2", @@ -443,6 +442,7 @@ dependencies = [ name = "servicepoint_binding_uniffi" version = "0.15.0" dependencies = [ + "paste", "servicepoint", "thiserror 2.0.11", "uniffi", diff --git a/Cargo.toml b/Cargo.toml index d6d0c18..bdc5b47 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,10 +19,13 @@ uniffi = { version = "0.28.3", features = ["build"] } [dependencies] uniffi = { version = "0.28.3" } thiserror = "2.0" +paste = "1.0.15" [dependencies.servicepoint] version = "0.15.0" features = ["all_compressions"] +git = "https://git.berlin.ccc.de/servicepoint/servicepoint.git" +branch = "next" [package.metadata.docs.rs] all-features = true diff --git a/src/brightness.rs b/src/brightness.rs index 0ea4591..8efba1e 100644 --- a/src/brightness.rs +++ b/src/brightness.rs @@ -1,3 +1,4 @@ +use crate::errors::ServicePointError; use crate::UniffiCustomTypeConverter; use servicepoint::Brightness; @@ -10,7 +11,8 @@ impl UniffiCustomTypeConverter for Brightness { where Self: Sized, { - Ok(Brightness::saturating_from(val)) + Ok(Brightness::try_from(val) + .map_err(|value| ServicePointError::InvalidBrightness { value })?) } fn from_custom(obj: Self) -> Self::Builtin { diff --git a/src/commands/bitmap.rs b/src/commands/bitmap.rs index 7cda71f..062f3dc 100644 --- a/src/commands/bitmap.rs +++ b/src/commands/bitmap.rs @@ -1,13 +1,14 @@ use crate::{ commands::wrap_command, compression_code::CompressionCode, - containers::bitmap::Bitmap, macros::wrap_object, + containers::bitmap::Bitmap, macros::wrap_object_attr_wrapped, }; use servicepoint::Origin; use std::sync::Arc; -wrap_object!(BitmapCommand); wrap_command!(BitmapCommand); +wrap_object_attr_wrapped!(BitmapCommand, bitmap, Bitmap); + #[uniffi::export] impl BitmapCommand { #[uniffi::constructor] diff --git a/src/commands/bitvec.rs b/src/commands/bitvec.rs index e449ea9..537f95f 100644 --- a/src/commands/bitvec.rs +++ b/src/commands/bitvec.rs @@ -1,11 +1,11 @@ use crate::{ commands::wrap_command, compression_code::CompressionCode, - containers::bitvec::BitVec, macros::wrap_object, + containers::bitvec::BitVec, macros::wrap_object_attr_wrapped, }; use std::sync::Arc; -wrap_object!(BitVecCommand); wrap_command!(BitVecCommand); +wrap_object_attr_wrapped!(BitVecCommand, bitvec, BitVec); #[uniffi::export] impl BitVecCommand { diff --git a/src/commands/brightness_grid.rs b/src/commands/brightness_grid.rs index 29c4e93..d48d8ee 100644 --- a/src/commands/brightness_grid.rs +++ b/src/commands/brightness_grid.rs @@ -1,12 +1,12 @@ use crate::{ commands::wrap_command, containers::brightness_grid::BrightnessGrid, - macros::wrap_object, + macros::wrap_object_attr_wrapped, }; use servicepoint::Origin; use std::sync::Arc; -wrap_object!(BrightnessGridCommand); wrap_command!(BrightnessGridCommand); +wrap_object_attr_wrapped!(BrightnessGridCommand, grid, BrightnessGrid); #[uniffi::export] impl BrightnessGridCommand { diff --git a/src/commands/cc_only.rs b/src/commands/cc_only.rs index b42a79e..576f1e2 100644 --- a/src/commands/cc_only.rs +++ b/src/commands/cc_only.rs @@ -1,10 +1,8 @@ -use crate::{commands::wrap_command, macros::wrap_object}; use std::sync::Arc; macro_rules! command_code_only_command { ($command_struct:ident) => { - wrap_object!($command_struct); - wrap_command!($command_struct); + crate::commands::wrap_command!($command_struct); #[uniffi::export] impl $command_struct { @@ -18,5 +16,4 @@ macro_rules! command_code_only_command { command_code_only_command!(ClearCommand); command_code_only_command!(HardResetCommand); -command_code_only_command!(BitmapLegacyCommand); command_code_only_command!(FadeOutCommand); diff --git a/src/commands/char_grid.rs b/src/commands/char_grid.rs index f02b93e..94da405 100644 --- a/src/commands/char_grid.rs +++ b/src/commands/char_grid.rs @@ -1,12 +1,12 @@ use crate::{ commands::wrap_command, containers::char_grid::CharGrid, - macros::wrap_object, + macros::wrap_object_attr_wrapped, }; use servicepoint::Origin; use std::sync::Arc; -wrap_object!(CharGridCommand); wrap_command!(CharGridCommand); +wrap_object_attr_wrapped!(CharGridCommand, grid, CharGrid); #[uniffi::export] impl CharGridCommand { diff --git a/src/commands/cp437.rs b/src/commands/cp437.rs index f4373c5..59d55a6 100644 --- a/src/commands/cp437.rs +++ b/src/commands/cp437.rs @@ -1,12 +1,12 @@ use crate::{ commands::wrap_command, containers::cp437_grid::Cp437Grid, - macros::wrap_object, + macros::wrap_object_attr_wrapped, }; use servicepoint::Origin; use std::sync::Arc; -wrap_object!(Cp437GridCommand); wrap_command!(Cp437GridCommand); +wrap_object_attr_wrapped!(Cp437GridCommand, grid, Cp437Grid); #[uniffi::export] impl Cp437GridCommand { diff --git a/src/commands/global_brightness.rs b/src/commands/global_brightness.rs index b95977e..5d626e5 100644 --- a/src/commands/global_brightness.rs +++ b/src/commands/global_brightness.rs @@ -1,8 +1,7 @@ -use crate::{commands::wrap_command, macros::wrap_object}; +use crate::commands::wrap_command; use servicepoint::Brightness; use std::sync::Arc; -wrap_object!(GlobalBrightnessCommand); wrap_command!(GlobalBrightnessCommand); #[uniffi::export] diff --git a/src/commands/mod.rs b/src/commands/mod.rs index 224c26d..0773b18 100644 --- a/src/commands/mod.rs +++ b/src/commands/mod.rs @@ -8,35 +8,59 @@ mod global_brightness; 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 cc_only::{ClearCommand, FadeOutCommand, HardResetCommand}; pub use char_grid::CharGridCommand; pub use cp437::Cp437GridCommand; #[uniffi::export] pub trait Command: Sync + Send { - fn as_packet(&self) -> Option>; + fn as_packet( + &self, + ) -> Result, crate::errors::ServicePointError>; } macro_rules! wrap_command { ($command:ident) => { - #[uniffi::export] - impl $command {} + crate::macros::wrap_object!($command); - impl crate::commands::Command for $command { - fn as_packet(&self) -> Option> { + #[uniffi::export] + impl $command { + fn as_packet( + &self, + ) -> Result< + Arc, + crate::errors::ServicePointError, + > { self.read() .clone() .try_into() .map(crate::packet::Packet::internal_new) - .ok() + .map_err(|_| { + crate::errors::ServicePointError::InvalidPacket + }) + } + + fn as_generic( + &self, + ) -> ::std::sync::Arc { + ::std::sync::Arc::new(self.clone()) + } + } + + impl crate::commands::Command for $command { + fn as_packet( + &self, + ) -> Result< + Arc, + crate::errors::ServicePointError, + > { + $command::as_packet(&self) } } }; } + pub(crate) use wrap_command; diff --git a/src/connection.rs b/src/connection.rs index 9f1f0e0..5b9ed52 100644 --- a/src/connection.rs +++ b/src/connection.rs @@ -1,3 +1,4 @@ +use crate::commands::Command; use crate::{errors::ServicePointError, packet::Packet}; use servicepoint::UdpSocketExt; use std::{net::UdpSocket, sync::Arc}; @@ -28,4 +29,11 @@ impl Connection { error: "send failed".to_string(), }) } + + pub fn send_command( + &self, + command: Arc, + ) -> Result<(), ServicePointError> { + self.send_packet(command.as_packet()?) + } } diff --git a/src/containers/bitmap.rs b/src/containers/bitmap.rs index 7598609..1418e5e 100644 --- a/src/containers/bitmap.rs +++ b/src/containers/bitmap.rs @@ -1,4 +1,7 @@ -use crate::macros::*; +use crate::{ + containers::{wrap_get_set_fill_2d, wrap_width_height}, + macros::wrap_object, +}; use servicepoint::Grid; use std::{ops::Deref, sync::Arc}; @@ -22,18 +25,13 @@ impl Bitmap { #[uniffi::constructor] pub fn load(width: u64, height: u64, data: Vec) -> Arc { + // TODO: throw exception Self::internal_new( servicepoint::Bitmap::load(width as usize, height as usize, &data) .unwrap(), ) } - pub fn equals(&self, other: &Bitmap) -> bool { - let a = self.read(); - let b = other.read(); - *a == *b - } - pub fn copy_raw(&self) -> Vec { self.read().deref().into() } diff --git a/src/containers/bitvec.rs b/src/containers/bitvec.rs index b5686d9..cd2c87d 100644 --- a/src/containers/bitvec.rs +++ b/src/containers/bitvec.rs @@ -18,31 +18,21 @@ impl BitVec { } pub fn set(&self, index: u64, value: bool) { - self.actual.write().unwrap().set(index as usize, value) + self.write().set(index as usize, value) } pub fn get(&self, index: u64) -> bool { - self.actual - .read() - .unwrap() - .get(index as usize) - .is_some_and(move |bit| *bit) + self.read().get(index as usize).is_some_and(move |bit| *bit) } pub fn fill(&self, value: bool) { - self.actual.write().unwrap().fill(value) + self.write().fill(value) } pub fn len(&self) -> u64 { self.read().len() as u64 } - pub fn equals(&self, other: &BitVec) -> bool { - let a = self.read(); - let b = other.read(); - *a == *b - } - pub fn copy_raw(&self) -> Vec { self.read().clone().into_vec() } diff --git a/src/containers/brightness_grid.rs b/src/containers/brightness_grid.rs index 6e99211..6bb3cbc 100644 --- a/src/containers/brightness_grid.rs +++ b/src/containers/brightness_grid.rs @@ -1,4 +1,7 @@ -use crate::macros::*; +use crate::{ + containers::{wrap_get_set_fill_2d, wrap_width_height}, + macros::wrap_object, +}; use servicepoint::{Brightness, Grid}; use std::{ops::Deref, sync::Arc}; @@ -28,12 +31,6 @@ impl BrightnessGrid { ) } - pub fn equals(&self, other: &BrightnessGrid) -> bool { - let a = self.read(); - let b = other.read(); - *a == *b - } - pub fn copy_raw(&self) -> Vec { self.read().deref().into() } diff --git a/src/containers/char_grid.rs b/src/containers/char_grid.rs index 2863282..387344c 100644 --- a/src/containers/char_grid.rs +++ b/src/containers/char_grid.rs @@ -1,4 +1,7 @@ -use crate::{containers::cp437_grid::Cp437Grid, macros::*}; +use crate::{ + containers::{cp437_grid::Cp437Grid, wrap_width_height}, + macros::wrap_object, +}; use servicepoint::{Grid, SetValueSeriesError}; use std::{convert::Into, sync::Arc}; @@ -37,58 +40,39 @@ impl CharGrid { value: String, ) -> Result<(), CharGridError> { let value = Self::str_to_char(value)?; - self.actual - .write() - .unwrap() - .set(x as usize, y as usize, value); + self.write().set(x as usize, y as usize, value); Ok(()) } pub fn get(&self, x: u64, y: u64) -> String { - self.actual - .read() - .unwrap() - .get(x as usize, y as usize) - .into() + self.read().get(x as usize, y as usize).into() } pub fn fill(&self, value: String) -> Result<(), CharGridError> { let value = Self::str_to_char(value)?; - self.actual.write().unwrap().fill(value); + self.write().fill(value); Ok(()) } - pub fn equals(&self, other: &CharGrid) -> bool { - let a = self.read(); - let b = other.read(); - *a == *b - } - pub fn as_string(&self) -> String { let grid = self.read(); String::from(&*grid) } pub fn set_row(&self, y: u64, row: String) -> Result<(), CharGridError> { - self.actual - .write() - .unwrap() + self.write() .set_row(y as usize, &row.chars().collect::>()) .map_err(CharGridError::from) } pub fn set_col(&self, x: u64, col: String) -> Result<(), CharGridError> { - self.actual - .write() - .unwrap() + self.write() .set_row(x as usize, &col.chars().collect::>()) .map_err(CharGridError::from) } pub fn get_row(&self, y: u64) -> Result { - self.actual - .read() - .unwrap() + self.read() .get_row(y as usize) .map(String::from_iter) .ok_or(CharGridError::OutOfBounds { @@ -98,9 +82,7 @@ impl CharGrid { } pub fn get_col(&self, x: u64) -> Result { - self.actual - .read() - .unwrap() + self.read() .get_col(x as usize) .map(String::from_iter) .ok_or(CharGridError::OutOfBounds { diff --git a/src/containers/cp437_grid.rs b/src/containers/cp437_grid.rs index bdcbfc1..fdd25e0 100644 --- a/src/containers/cp437_grid.rs +++ b/src/containers/cp437_grid.rs @@ -1,4 +1,8 @@ -use crate::{containers::char_grid::CharGrid, macros::*}; +use crate::{ + containers::char_grid::CharGrid, + containers::{wrap_get_set_fill_2d, wrap_width_height}, + macros::wrap_object, +}; use servicepoint::Grid; use std::{ops::Deref, sync::Arc}; @@ -28,12 +32,6 @@ impl Cp437Grid { ) } - pub fn equals(&self, other: &Cp437Grid) -> bool { - let a = self.read(); - let b = other.read(); - *a == *b - } - pub fn copy_raw(&self) -> Vec { self.read().deref().into() } diff --git a/src/containers/mod.rs b/src/containers/mod.rs index 7dce8bd..f1d4880 100644 --- a/src/containers/mod.rs +++ b/src/containers/mod.rs @@ -3,3 +3,44 @@ pub mod bitvec; pub mod brightness_grid; pub mod char_grid; pub mod cp437_grid; + +macro_rules! wrap_width_height { + ($t:ident) => { + #[uniffi::export] + impl $t { + pub fn width(&self) -> u64 { + self.read().width() as u64 + } + + pub fn height(&self) -> u64 { + self.read().height() as u64 + } + } + }; +} + +pub(crate) use wrap_width_height; + +macro_rules! wrap_get_set_fill_2d { + ($t:ident, $contained:ident) => { + #[uniffi::export] + impl $t { + pub fn set(&self, x: u64, y: u64, value: $contained) { + self.actual + .write() + .unwrap() + .set(x as usize, y as usize, value) + } + + pub fn get(&self, x: u64, y: u64) -> $contained { + self.read().get(x as usize, y as usize) + } + + pub fn fill(&self, value: $contained) { + self.actual.write().unwrap().fill(value) + } + } + }; +} + +pub(crate) use wrap_get_set_fill_2d; diff --git a/src/errors.rs b/src/errors.rs index 9c28f5f..03d05ba 100644 --- a/src/errors.rs +++ b/src/errors.rs @@ -4,4 +4,6 @@ pub enum ServicePointError { IoError { error: String }, #[error("The specified brightness value {value} is out of range")] InvalidBrightness { value: u8 }, + #[error("The provided packet is invalid or a conversion to packet failed")] + InvalidPacket, } diff --git a/src/macros.rs b/src/macros.rs index ee15b5e..140b42c 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -1,6 +1,7 @@ macro_rules! wrap_object { ($orig_t:ident, $new_t:ident) => { #[derive(uniffi::Object)] + #[uniffi::export(Debug, Eq, Hash)] pub struct $new_t { actual: ::std::sync::RwLock<::servicepoint::$orig_t>, } @@ -10,9 +11,15 @@ macro_rules! wrap_object { pub(crate) fn internal_new( actual: ::servicepoint::$orig_t, ) -> ::std::sync::Arc { - ::std::sync::Arc::new(Self { + ::std::sync::Arc::new(Self::internal_new_noarc(actual)) + } + + pub(crate) fn internal_new_noarc( + actual: ::servicepoint::$orig_t, + ) -> Self { + Self { actual: ::std::sync::RwLock::new(actual), - }) + } } pub(crate) fn read( @@ -37,51 +44,85 @@ macro_rules! wrap_object { Self::internal_new(other.read().clone()) } } + + impl Clone for $new_t { + fn clone(&self) -> Self { + Self::internal_new_noarc(self.read().clone()) + } + } + + impl ::std::fmt::Debug for $new_t { + fn fmt( + &self, + f: &mut ::std::fmt::Formatter, + ) -> Result<(), std::fmt::Error> { + f.write_fmt(format_args!("{:?}", self.read())) + } + } + + impl PartialEq for $new_t { + fn eq(&self, other: &$new_t) -> bool { + *self.read() == *other.read() + } + } + + impl Eq for $new_t {} + + impl ::std::hash::Hash for $new_t { + fn hash(&self, state: &mut H) { + ::std::hash::Hash::hash(&*self.read(), state) + } + } }; ($t:ident) => { - wrap_object!($t, $t); + crate::macros::wrap_object!($t, $t); }; } -pub(crate) use wrap_object; - -macro_rules! wrap_width_height { - ($t:ident) => { +macro_rules! wrap_object_attr_wrapped_get { + ($object:ident, $attr_name:ident, $attr_type:ident, $fun_name:ident) => { #[uniffi::export] - impl $t { - pub fn width(&self) -> u64 { - self.read().width() as u64 - } - - pub fn height(&self) -> u64 { - self.read().height() as u64 + impl $object { + pub fn $fun_name(&self) -> ::std::sync::Arc<$attr_type> { + $attr_type::internal_new(self.read().$attr_name.clone()) } } }; + ($object:ident, $attr_name:ident, $attr_type:ident) => { + paste::paste!{ + crate::macros::wrap_object_attr_wrapped_get!($object, $attr_name, $attr_type, []); + } + }; } -pub(crate) use wrap_width_height; - -macro_rules! wrap_get_set_fill_2d { - ($t:ident, $contained:ident) => { +macro_rules! wrap_object_attr_wrapped_set { + ($object:ident, $attr_name:ident, $attr_type:ident, $fun_name:ident) => { #[uniffi::export] - impl $t { - pub fn set(&self, x: u64, y: u64, value: $contained) { - self.actual - .write() - .unwrap() - .set(x as usize, y as usize, value) - } - - pub fn get(&self, x: u64, y: u64) -> $contained { - self.read().get(x as usize, y as usize) - } - - pub fn fill(&self, value: $contained) { - self.actual.write().unwrap().fill(value) + impl $object { + pub fn $fun_name(&self, $attr_name: ::std::sync::Arc<$attr_type>) { + self.write().$attr_name = $attr_name.read().clone(); } } }; + ($object:ident, $attr_name:ident, $attr_type:ident) => { + paste::paste!{ + crate::macros::wrap_object_attr_wrapped_set!($object, $attr_name, $attr_type, []); + } + }; } -pub(crate) use wrap_get_set_fill_2d; +macro_rules! wrap_object_attr_wrapped { + ($object:ident, $attr_name:ident, $attr_type:ident) => { + crate::macros::wrap_object_attr_wrapped_get!( + $object, $attr_name, $attr_type + ); + crate::macros::wrap_object_attr_wrapped_set!( + $object, $attr_name, $attr_type + ); + }; +} + +pub(crate) use { + wrap_object, wrap_object_attr_wrapped, wrap_object_attr_wrapped_get, + wrap_object_attr_wrapped_set, +}; diff --git a/src/packet.rs b/src/packet.rs index 5f769f1..ceaf052 100644 --- a/src/packet.rs +++ b/src/packet.rs @@ -1,12 +1,6 @@ -use crate::macros::wrap_object; -use std::sync::Arc; +use crate::macros::{wrap_object, wrap_object_attr_wrapped}; wrap_object!(Packet); wrap_object!(Header); -#[uniffi::export] -impl Packet { - pub fn get_header(&self) -> Arc
{ - Header::internal_new(self.read().header) - } -} +wrap_object_attr_wrapped!(Packet, header, Header); From 7e07a35472845e308587b1888c6ef4e61e4683e0 Mon Sep 17 00:00:00 2001 From: Vinzenz Schroeter Date: Mon, 16 Jun 2025 16:37:20 +0200 Subject: [PATCH 15/15] partially fix tests --- src/compression_code.rs | 20 +++++++++- src/containers/char_grid.rs | 76 ++++++++++++++++++------------------- src/errors.rs | 6 +++ src/packet.rs | 7 ++++ 4 files changed, 67 insertions(+), 42 deletions(-) diff --git a/src/compression_code.rs b/src/compression_code.rs index a3d332d..bf530f1 100644 --- a/src/compression_code.rs +++ b/src/compression_code.rs @@ -15,12 +15,28 @@ pub enum CompressionCode { impl From for CompressionCode { fn from(value: servicepoint::CompressionCode) -> Self { - value.into() + match value { + servicepoint::CompressionCode::Uncompressed => { + CompressionCode::Uncompressed + } + servicepoint::CompressionCode::Zlib => CompressionCode::Zlib, + servicepoint::CompressionCode::Bzip2 => CompressionCode::Bzip2, + servicepoint::CompressionCode::Lzma => CompressionCode::Lzma, + servicepoint::CompressionCode::Zstd => CompressionCode::Zstd, + } } } impl From for servicepoint::CompressionCode { fn from(value: CompressionCode) -> Self { - servicepoint::CompressionCode::try_from(value).unwrap() + match value { + CompressionCode::Uncompressed => { + servicepoint::CompressionCode::Uncompressed + } + CompressionCode::Zlib => servicepoint::CompressionCode::Zlib, + CompressionCode::Bzip2 => servicepoint::CompressionCode::Bzip2, + CompressionCode::Lzma => servicepoint::CompressionCode::Lzma, + CompressionCode::Zstd => servicepoint::CompressionCode::Zstd, + } } } diff --git a/src/containers/char_grid.rs b/src/containers/char_grid.rs index 387344c..28712be 100644 --- a/src/containers/char_grid.rs +++ b/src/containers/char_grid.rs @@ -1,23 +1,14 @@ use crate::{ containers::{cp437_grid::Cp437Grid, wrap_width_height}, + errors::ServicePointError, macros::wrap_object, }; use servicepoint::{Grid, SetValueSeriesError}; -use std::{convert::Into, sync::Arc}; +use std::sync::Arc; wrap_object!(CharGrid); wrap_width_height!(CharGrid); -#[derive(uniffi::Error, thiserror::Error, Debug)] -pub enum CharGridError { - #[error("Exactly one character was expected, but {value:?} was provided")] - StringNotOneChar { value: String }, - #[error("The provided series was expected to have a length of {expected}, but was {actual}")] - InvalidSeriesLength { actual: u64, expected: u64 }, - #[error("The index {index} was out of bounds for size {size}")] - OutOfBounds { index: u64, size: u64 }, -} - #[uniffi::export] impl CharGrid { #[uniffi::constructor] @@ -38,17 +29,23 @@ impl CharGrid { x: u64, y: u64, value: String, - ) -> Result<(), CharGridError> { + ) -> Result<(), ServicePointError> { let value = Self::str_to_char(value)?; - self.write().set(x as usize, y as usize, value); - Ok(()) + if self.write().set_optional(x as isize, y as isize, value) { + Ok(()) + } else { + Err(ServicePointError::OutOfBounds) + } } - pub fn get(&self, x: u64, y: u64) -> String { - self.read().get(x as usize, y as usize).into() + pub fn get(&self, x: u64, y: u64) -> Result { + self.read() + .get_optional(x as isize, y as isize) + .ok_or(ServicePointError::OutOfBounds) + .map(String::from) } - pub fn fill(&self, value: String) -> Result<(), CharGridError> { + pub fn fill(&self, value: String) -> Result<(), ServicePointError> { let value = Self::str_to_char(value)?; self.write().fill(value); Ok(()) @@ -59,36 +56,38 @@ impl CharGrid { String::from(&*grid) } - pub fn set_row(&self, y: u64, row: String) -> Result<(), CharGridError> { + pub fn set_row( + &self, + y: u64, + row: String, + ) -> Result<(), ServicePointError> { self.write() .set_row(y as usize, &row.chars().collect::>()) - .map_err(CharGridError::from) + .map_err(ServicePointError::from) } - pub fn set_col(&self, x: u64, col: String) -> Result<(), CharGridError> { + pub fn set_col( + &self, + x: u64, + col: String, + ) -> Result<(), ServicePointError> { self.write() .set_row(x as usize, &col.chars().collect::>()) - .map_err(CharGridError::from) + .map_err(ServicePointError::from) } - pub fn get_row(&self, y: u64) -> Result { + pub fn get_row(&self, y: u64) -> Result { self.read() .get_row(y as usize) .map(String::from_iter) - .ok_or(CharGridError::OutOfBounds { - index: y, - size: self.height(), - }) + .ok_or(ServicePointError::OutOfBounds) } - pub fn get_col(&self, x: u64) -> Result { + pub fn get_col(&self, x: u64) -> Result { self.read() .get_col(x as usize) .map(String::from_iter) - .ok_or(CharGridError::OutOfBounds { - index: x, - size: self.width(), - }) + .ok_or(ServicePointError::OutOfBounds) } pub fn to_cp437(&self) -> Arc { @@ -97,9 +96,9 @@ impl CharGrid { } impl CharGrid { - fn str_to_char(value: String) -> Result { + fn str_to_char(value: String) -> Result { if value.len() != 1 { - return Err(CharGridError::StringNotOneChar { value }); + return Err(ServicePointError::StringNotOneChar { value }); } let value = value.chars().nth(0).unwrap(); @@ -107,17 +106,14 @@ impl CharGrid { } } -impl From for CharGridError { +impl From for ServicePointError { fn from(e: SetValueSeriesError) -> Self { match e { - SetValueSeriesError::OutOfBounds { index, size } => { - CharGridError::OutOfBounds { - index: index as u64, - size: size as u64, - } + SetValueSeriesError::OutOfBounds { .. } => { + ServicePointError::OutOfBounds } SetValueSeriesError::InvalidLength { actual, expected } => { - CharGridError::InvalidSeriesLength { + ServicePointError::InvalidSeriesLength { actual: actual as u64, expected: expected as u64, } diff --git a/src/errors.rs b/src/errors.rs index 03d05ba..f234278 100644 --- a/src/errors.rs +++ b/src/errors.rs @@ -6,4 +6,10 @@ pub enum ServicePointError { InvalidBrightness { value: u8 }, #[error("The provided packet is invalid or a conversion to packet failed")] InvalidPacket, + #[error("Exactly one character was expected, but {value:?} was provided")] + StringNotOneChar { value: String }, + #[error("The provided series was expected to have a length of {expected}, but was {actual}")] + InvalidSeriesLength { actual: u64, expected: u64 }, + #[error("The index was out of bounds")] + OutOfBounds, } diff --git a/src/packet.rs b/src/packet.rs index ceaf052..bdfd0a8 100644 --- a/src/packet.rs +++ b/src/packet.rs @@ -4,3 +4,10 @@ wrap_object!(Packet); wrap_object!(Header); wrap_object_attr_wrapped!(Packet, header, Header); + +#[uniffi::export] +impl Packet { + pub fn as_bytes(&self) -> Vec { + Vec::from(&*self.read()) + } +}