diff --git a/.envrc.default b/.envrc.default deleted file mode 100644 index 3550a30..0000000 --- a/.envrc.default +++ /dev/null @@ -1 +0,0 @@ -use flake diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index fbf93a9..c706671 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -25,21 +25,14 @@ jobs: - name: Install rust toolchain run: sudo apt-get install -qy cargo rust-clippy - name: install lzma - run: sudo apt-get update && sudo apt-get install -y liblzma-dev + run: sudo apt-get install -qy liblzma-dev + - name: install ruby + run: sudo apt-get install -qy ruby - - name: Run Clippy - run: cargo clippy --all-targets --all-features + - name: generate bindings + run: ./generate-binding.sh + - name: check that generated files did not change + run: output=$(git status --porcelain) && [ -z "$output" ] - name: build default features run: cargo build --all --verbose - - name: build default features -- examples - run: cargo build --examples --verbose - - name: test default features - run: cargo test --all --verbose - - - name: build all features - run: cargo build --all-features --verbose - - name: build all features -- examples - run: cargo build --all-features --examples --verbose - - name: test all features - run: cargo test --all --all-features --verbose diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..9439604 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "servicepoint-binding-uniffi"] + path = servicepoint-binding-uniffi + url = https://git.berlin.ccc.de/servicepoint/servicepoint-binding-uniffi.git diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md deleted file mode 100644 index 36f8920..0000000 --- a/CONTRIBUTING.md +++ /dev/null @@ -1,31 +0,0 @@ -# Contributing - -Contributions are accepted in any form (issues, documentation, feature requests, code, review, ...). - -All creatures welcome. - -If you have access, please contribute on the [CCCB Forgejo](https://git.berlin.ccc.de/servicepoint/servicepoint). -Contributions on GitHub will be copied over and merged there. - -## Pull requests - -Feel free to create a PR, even if your change is not done yet. - -Mark your PR as a draft as long as you do not want it to be merged. - -The main branch is supposed to be a working version, including language bindings, -which means sometimes your PR may be merged into a temporary development branch. - -Unit tests and documentation are required for the core library. - -## Language bindings - -Pull requests for your preferred language will be accepted. -If there is no code generator, it should call the C ABI methods provided by `servicepoint_binding_c`. -It should be able to send most of the basic commands in a way the simulator accepts, receiving is -not required for the merge. - -It is okay for the feature set of a language binding to lag behind the one of the rust crate. -This also means you do not have to expose a feature to all the language bindings when adding something to the core. - -If your change may break other language bindings, please note that in your PR description so someone can check them. diff --git a/Cargo.lock b/Cargo.lock index 38b99d0..f744ab2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -63,38 +63,16 @@ version = "1.0.95" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34ac096ce696dc2fcabef30516bb13c0a68a11d30131d3df6f04711467681b04" -[[package]] -name = "askama" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb98f10f371286b177db5eeb9a6e5396609555686a35e1d4f7b9a9c6d8af0139" -dependencies = [ - "askama_derive 0.11.2", - "askama_escape", - "askama_shared", -] - [[package]] name = "askama" version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b79091df18a97caea757e28cd2d5fda49c6cd4bd01ddffd7ff01ace0c0ad2c28" dependencies = [ - "askama_derive 0.12.5", + "askama_derive", "askama_escape", ] -[[package]] -name = "askama_derive" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87bf87e6e8b47264efa9bde63d6225c6276a52e05e91bf37eaa8afd0032d6b71" -dependencies = [ - "askama_shared", - "proc-macro2", - "syn 1.0.109", -] - [[package]] name = "askama_derive" version = "0.12.5" @@ -108,7 +86,7 @@ dependencies = [ "proc-macro2", "quote", "serde", - "syn 2.0.96", + "syn", ] [[package]] @@ -126,34 +104,6 @@ dependencies = [ "nom", ] -[[package]] -name = "askama_shared" -version = "0.12.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf722b94118a07fcbc6640190f247334027685d4e218b794dbfe17c32bf38ed0" -dependencies = [ - "askama_escape", - "mime", - "mime_guess", - "nom", - "proc-macro2", - "quote", - "serde", - "syn 1.0.109", - "toml 0.5.11", -] - -[[package]] -name = "atty" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" -dependencies = [ - "hermit-abi", - "libc", - "winapi", -] - [[package]] name = "autocfg" version = "1.4.0" @@ -178,18 +128,6 @@ dependencies = [ "serde", ] -[[package]] -name = "bitflags" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - -[[package]] -name = "bitflags" -version = "2.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1be3f42a67d6d345ecd59f675f3f012d6974981560836e938c22b424b85ce1be" - [[package]] name = "bitvec" version = "1.0.1" @@ -202,21 +140,6 @@ dependencies = [ "wyz", ] -[[package]] -name = "block-buffer" -version = "0.10.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" -dependencies = [ - "generic-array", -] - -[[package]] -name = "byteorder" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" - [[package]] name = "bytes" version = "1.9.0" @@ -276,25 +199,6 @@ dependencies = [ "thiserror 1.0.69", ] -[[package]] -name = "cbindgen" -version = "0.27.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fce8dd7fcfcbf3a0a87d8f515194b49d6135acab73e18bd380d1d93bb1a15eb" -dependencies = [ - "clap 4.5.26", - "heck 0.4.1", - "indexmap 2.7.0", - "log", - "proc-macro2", - "quote", - "serde", - "serde_json", - "syn 2.0.96", - "tempfile", - "toml 0.8.19", -] - [[package]] name = "cc" version = "1.2.9" @@ -312,23 +216,6 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" -[[package]] -name = "clap" -version = "3.2.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ea181bf566f71cb9a5d17a59e1871af638180a18fb0035c92ae62b705207123" -dependencies = [ - "atty", - "bitflags 1.3.2", - "clap_derive 3.2.25", - "clap_lex 0.2.4", - "indexmap 1.9.3", - "once_cell", - "strsim 0.10.0", - "termcolor", - "textwrap", -] - [[package]] name = "clap" version = "4.5.26" @@ -336,7 +223,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a8eb5e908ef3a6efbe1ed62520fb7287959888c88485abe072543190ecc66783" dependencies = [ "clap_builder", - "clap_derive 4.5.24", + "clap_derive", ] [[package]] @@ -347,21 +234,8 @@ checksum = "96b01801b5fc6a0a232407abc821660c9c6d25a1cafc0d4f85f29fb8d9afc121" dependencies = [ "anstream", "anstyle", - "clap_lex 0.7.4", - "strsim 0.11.1", -] - -[[package]] -name = "clap_derive" -version = "3.2.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae6371b8bdc8b7d3959e9cf7b22d4435ef3e79e138688421ec654acf8c81b008" -dependencies = [ - "heck 0.4.1", - "proc-macro-error", - "proc-macro2", - "quote", - "syn 1.0.109", + "clap_lex", + "strsim", ] [[package]] @@ -373,16 +247,7 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.96", -] - -[[package]] -name = "clap_lex" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2850f2f5a82cbf437dd5af4d49848fbdfc27c157c3d010345776f952765261c5" -dependencies = [ - "os_str_bytes", + "syn", ] [[package]] @@ -397,15 +262,6 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" -[[package]] -name = "cpufeatures" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16b80225097f2e5ae4e7179dd2266824648f3e2f49d9134d584b76389d31c4c3" -dependencies = [ - "libc", -] - [[package]] name = "crc32fast" version = "1.4.2" @@ -415,65 +271,6 @@ dependencies = [ "cfg-if", ] -[[package]] -name = "crypto-common" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" -dependencies = [ - "generic-array", - "typenum", -] - -[[package]] -name = "data-encoding" -version = "2.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8566979429cf69b49a5c740c60791108e86440e8be149bbea4fe54d2c32d6e2" - -[[package]] -name = "digest" -version = "0.10.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" -dependencies = [ - "block-buffer", - "crypto-common", -] - -[[package]] -name = "equivalent" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" - -[[package]] -name = "errno" -version = "0.3.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d" -dependencies = [ - "libc", - "windows-sys", -] - -[[package]] -name = "extend" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "311a6d2f1f9d60bff73d2c78a0af97ed27f79672f15c238192a5bbb64db56d00" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.96", -] - -[[package]] -name = "fastrand" -version = "2.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" - [[package]] name = "flate2" version = "1.0.35" @@ -484,12 +281,6 @@ dependencies = [ "miniz_oxide", ] -[[package]] -name = "fnv" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" - [[package]] name = "fs-err" version = "2.11.0" @@ -505,27 +296,6 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" -[[package]] -name = "generic-array" -version = "0.14.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" -dependencies = [ - "typenum", - "version_check", -] - -[[package]] -name = "getrandom" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" -dependencies = [ - "cfg-if", - "libc", - "wasi", -] - [[package]] name = "glob" version = "0.3.2" @@ -543,18 +313,6 @@ dependencies = [ "scroll", ] -[[package]] -name = "hashbrown" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" - -[[package]] -name = "hashbrown" -version = "0.15.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" - [[package]] name = "heck" version = "0.4.1" @@ -567,52 +325,6 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" -[[package]] -name = "hermit-abi" -version = "0.1.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" -dependencies = [ - "libc", -] - -[[package]] -name = "http" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f16ca2af56261c99fba8bac40a10251ce8188205a4c448fbb745a2e4daa76fea" -dependencies = [ - "bytes", - "fnv", - "itoa", -] - -[[package]] -name = "httparse" -version = "1.9.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946" - -[[package]] -name = "indexmap" -version = "1.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" -dependencies = [ - "autocfg", - "hashbrown 0.12.3", -] - -[[package]] -name = "indexmap" -version = "2.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62f822373a4fe84d4bb149bf54e584a7f4abec90e072ed49cda0edea5b95471f" -dependencies = [ - "equivalent", - "hashbrown 0.15.2", -] - [[package]] name = "is_terminal_polyfill" version = "1.70.1" @@ -634,26 +346,12 @@ dependencies = [ "libc", ] -[[package]] -name = "lang_c" -version = "0.1.0" -dependencies = [ - "cc", - "servicepoint_binding_c", -] - [[package]] name = "libc" version = "0.2.169" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a" -[[package]] -name = "linux-raw-sys" -version = "0.4.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" - [[package]] name = "log" version = "0.4.22" @@ -719,12 +417,6 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c548d5c78976f6955d72d0ced18c48ca07030f7a1d4024529fedd7c1c01b29c" -[[package]] -name = "os_str_bytes" -version = "6.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2355d85b9a3786f481747ced0e0ff2ba35213a1f9bd406ed906554d7af805a1" - [[package]] name = "paste" version = "1.0.15" @@ -743,39 +435,6 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6" -[[package]] -name = "ppv-lite86" -version = "0.2.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" -dependencies = [ - "zerocopy", -] - -[[package]] -name = "proc-macro-error" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" -dependencies = [ - "proc-macro-error-attr", - "proc-macro2", - "quote", - "syn 1.0.109", - "version_check", -] - -[[package]] -name = "proc-macro-error-attr" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" -dependencies = [ - "proc-macro2", - "quote", - "version_check", -] - [[package]] name = "proc-macro2" version = "1.0.93" @@ -800,36 +459,6 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" -[[package]] -name = "rand" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" -dependencies = [ - "libc", - "rand_chacha", - "rand_core", -] - -[[package]] -name = "rand_chacha" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" -dependencies = [ - "ppv-lite86", - "rand_core", -] - -[[package]] -name = "rand_core" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" -dependencies = [ - "getrandom", -] - [[package]] name = "rust-lzma" version = "0.6.0" @@ -840,19 +469,6 @@ dependencies = [ "vcpkg", ] -[[package]] -name = "rustix" -version = "0.38.43" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a78891ee6bf2340288408954ac787aa063d8e8817e9f53abb37c695c6d834ef6" -dependencies = [ - "bitflags 2.7.0", - "errno", - "libc", - "linux-raw-sys", - "windows-sys", -] - [[package]] name = "ryu" version = "1.0.18" @@ -876,7 +492,7 @@ checksum = "1db149f81d46d2deba7cd3c50772474707729550221e69588478ebf9ada425ae" dependencies = [ "proc-macro2", "quote", - "syn 2.0.96", + "syn", ] [[package]] @@ -905,7 +521,7 @@ checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.96", + "syn", ] [[package]] @@ -920,40 +536,22 @@ dependencies = [ "serde", ] -[[package]] -name = "serde_spanned" -version = "0.6.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1" -dependencies = [ - "serde", -] - [[package]] name = "servicepoint" version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93b52049be55a15fe37c13249d7f96aa8a5de56e1a41838e74a822ee8316a0c4" dependencies = [ "bitvec", "bzip2", - "clap 4.5.26", "flate2", "log", "once_cell", - "rand", "rust-lzma", "thiserror 2.0.11", - "tungstenite", "zstd", ] -[[package]] -name = "servicepoint_binding_c" -version = "0.13.1" -dependencies = [ - "cbindgen", - "servicepoint", -] - [[package]] name = "servicepoint_binding_uniffi" version = "0.13.1" @@ -961,19 +559,6 @@ dependencies = [ "servicepoint", "thiserror 2.0.11", "uniffi", - "uniffi-bindgen-cs", - "uniffi-bindgen-go", -] - -[[package]] -name = "sha1" -version = "0.10.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" -dependencies = [ - "cfg-if", - "cpufeatures", - "digest", ] [[package]] @@ -988,41 +573,18 @@ 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" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" -[[package]] -name = "strsim" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" - [[package]] name = "strsim" version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" -[[package]] -name = "syn" -version = "1.0.109" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - [[package]] name = "syn" version = "2.0.96" @@ -1040,40 +602,6 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" -[[package]] -name = "tempfile" -version = "3.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a8a559c81686f576e8cd0290cd2a24a2a9ad80c98b3478856500fcbd7acd704" -dependencies = [ - "cfg-if", - "fastrand", - "getrandom", - "once_cell", - "rustix", - "windows-sys", -] - -[[package]] -name = "termcolor" -version = "1.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" -dependencies = [ - "winapi-util", -] - -[[package]] -name = "textwrap" -version = "0.16.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23d434d3f8967a09480fb04132ebe0a3e088c173e6d0ee7897abbdf4eab0f8b9" -dependencies = [ - "smawk", - "unicode-linebreak", - "unicode-width", -] - [[package]] name = "thiserror" version = "1.0.69" @@ -1100,7 +628,7 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.96", + "syn", ] [[package]] @@ -1111,7 +639,7 @@ checksum = "26afc1baea8a989337eeb52b6e72a039780ce45c3edfcc9c5b9d112feeb173c2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.96", + "syn", ] [[package]] @@ -1123,64 +651,6 @@ dependencies = [ "serde", ] -[[package]] -name = "toml" -version = "0.8.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1ed1f98e3fdc28d6d910e6737ae6ab1a93bf1985935a1193e68f93eeb68d24e" -dependencies = [ - "serde", - "serde_spanned", - "toml_datetime", - "toml_edit", -] - -[[package]] -name = "toml_datetime" -version = "0.6.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" -dependencies = [ - "serde", -] - -[[package]] -name = "toml_edit" -version = "0.22.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5" -dependencies = [ - "indexmap 2.7.0", - "serde", - "serde_spanned", - "toml_datetime", - "winnow", -] - -[[package]] -name = "tungstenite" -version = "0.26.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "413083a99c579593656008130e29255e54dcaae495be556cc26888f211648c24" -dependencies = [ - "byteorder", - "bytes", - "data-encoding", - "http", - "httparse", - "log", - "rand", - "sha1", - "thiserror 2.0.11", - "utf-8", -] - -[[package]] -name = "typenum" -version = "1.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" - [[package]] name = "unicase" version = "2.8.1" @@ -1193,18 +663,6 @@ version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" -[[package]] -name = "unicode-linebreak" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b09c83c3c29d37506a3e260c08c03743a6bb66a9cd432c6934ab501a190571f" - -[[package]] -name = "unicode-width" -version = "0.1.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" - [[package]] name = "uniffi" version = "0.25.3" @@ -1212,98 +670,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "21345172d31092fd48c47fd56c53d4ae9e41c4b1f559fb8c38c1ab1685fd919f" dependencies = [ "anyhow", + "camino", + "clap", + "uniffi_bindgen", "uniffi_build", "uniffi_core", "uniffi_macros", ] [[package]] -name = "uniffi-bindgen-cs" -version = "0.8.3+v0.25.0" -source = "git+https://github.com/NordSecurity/uniffi-bindgen-cs?rev=f68639fbc720b50ebe561ba75c66c84dc456bdce#f68639fbc720b50ebe561ba75c66c84dc456bdce" +name = "uniffi-bindgen" +version = "0.0.0" dependencies = [ - "anyhow", - "askama 0.11.1", - "camino", - "clap 3.2.25", - "extend", - "fs-err", - "heck 0.4.1", - "paste", - "serde", - "serde_json", - "textwrap", - "toml 0.5.11", - "uniffi_bindgen 0.25.0 (git+https://github.com/NordSecurity/uniffi-bindgen-cs?rev=f68639fbc720b50ebe561ba75c66c84dc456bdce)", -] - -[[package]] -name = "uniffi-bindgen-go" -version = "0.2.2+v0.25.0" -source = "git+https://github.com/NordSecurity/uniffi-bindgen-go.git?rev=ba23bab72f1a9bcc39ce81924d3d9265598e017c#ba23bab72f1a9bcc39ce81924d3d9265598e017c" -dependencies = [ - "anyhow", - "askama 0.12.1", - "camino", - "cargo_metadata", - "clap 3.2.25", - "extend", - "fs-err", - "heck 0.4.1", - "paste", - "serde", - "serde_json", - "textwrap", - "toml 0.5.11", - "uniffi_bindgen 0.25.0 (git+https://github.com/NordSecurity/uniffi-bindgen-go.git?rev=ba23bab72f1a9bcc39ce81924d3d9265598e017c)", - "uniffi_meta 0.25.0 (git+https://github.com/NordSecurity/uniffi-bindgen-go.git?rev=ba23bab72f1a9bcc39ce81924d3d9265598e017c)", - "uniffi_udl 0.25.0 (git+https://github.com/NordSecurity/uniffi-bindgen-go.git?rev=ba23bab72f1a9bcc39ce81924d3d9265598e017c)", -] - -[[package]] -name = "uniffi_bindgen" -version = "0.25.0" -source = "git+https://github.com/NordSecurity/uniffi-bindgen-go.git?rev=ba23bab72f1a9bcc39ce81924d3d9265598e017c#ba23bab72f1a9bcc39ce81924d3d9265598e017c" -dependencies = [ - "anyhow", - "askama 0.12.1", - "camino", - "cargo_metadata", - "fs-err", - "glob", - "goblin", - "heck 0.4.1", - "once_cell", - "paste", - "serde", - "textwrap", - "toml 0.5.11", - "uniffi_meta 0.25.0 (git+https://github.com/NordSecurity/uniffi-bindgen-go.git?rev=ba23bab72f1a9bcc39ce81924d3d9265598e017c)", - "uniffi_testing 0.25.0 (git+https://github.com/NordSecurity/uniffi-bindgen-go.git?rev=ba23bab72f1a9bcc39ce81924d3d9265598e017c)", - "uniffi_udl 0.25.0 (git+https://github.com/NordSecurity/uniffi-bindgen-go.git?rev=ba23bab72f1a9bcc39ce81924d3d9265598e017c)", -] - -[[package]] -name = "uniffi_bindgen" -version = "0.25.0" -source = "git+https://github.com/NordSecurity/uniffi-bindgen-cs?rev=f68639fbc720b50ebe561ba75c66c84dc456bdce#f68639fbc720b50ebe561ba75c66c84dc456bdce" -dependencies = [ - "anyhow", - "askama 0.12.1", - "camino", - "cargo_metadata", - "fs-err", - "glob", - "goblin", - "heck 0.4.1", - "once_cell", - "paste", - "serde", - "textwrap", - "toml 0.5.11", - "uniffi_meta 0.25.0 (git+https://github.com/NordSecurity/uniffi-bindgen-cs?rev=f68639fbc720b50ebe561ba75c66c84dc456bdce)", - "uniffi_testing 0.25.0 (git+https://github.com/NordSecurity/uniffi-bindgen-cs?rev=f68639fbc720b50ebe561ba75c66c84dc456bdce)", - "uniffi_udl 0.25.0 (git+https://github.com/NordSecurity/uniffi-bindgen-cs?rev=f68639fbc720b50ebe561ba75c66c84dc456bdce)", + "thiserror 2.0.11", + "uniffi", ] [[package]] @@ -1313,9 +693,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fd992f2929a053829d5875af1eff2ee3d7a7001cb3b9a46cc7895f2caede6940" dependencies = [ "anyhow", - "askama 0.12.1", + "askama", "camino", "cargo_metadata", + "clap", "fs-err", "glob", "goblin", @@ -1323,10 +704,10 @@ dependencies = [ "once_cell", "paste", "serde", - "toml 0.5.11", - "uniffi_meta 0.25.3", - "uniffi_testing 0.25.3", - "uniffi_udl 0.25.3", + "toml", + "uniffi_meta", + "uniffi_testing", + "uniffi_udl", ] [[package]] @@ -1337,25 +718,7 @@ checksum = "001964dd3682d600084b3aaf75acf9c3426699bc27b65e96bb32d175a31c74e9" dependencies = [ "anyhow", "camino", - "uniffi_bindgen 0.25.3", -] - -[[package]] -name = "uniffi_checksum_derive" -version = "0.25.0" -source = "git+https://github.com/NordSecurity/uniffi-bindgen-go.git?rev=ba23bab72f1a9bcc39ce81924d3d9265598e017c#ba23bab72f1a9bcc39ce81924d3d9265598e017c" -dependencies = [ - "quote", - "syn 2.0.96", -] - -[[package]] -name = "uniffi_checksum_derive" -version = "0.25.0" -source = "git+https://github.com/NordSecurity/uniffi-bindgen-cs?rev=f68639fbc720b50ebe561ba75c66c84dc456bdce#f68639fbc720b50ebe561ba75c66c84dc456bdce" -dependencies = [ - "quote", - "syn 2.0.96", + "uniffi_bindgen", ] [[package]] @@ -1365,7 +728,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "55137c122f712d9330fd985d66fa61bdc381752e89c35708c13ce63049a3002c" dependencies = [ "quote", - "syn 2.0.96", + "syn", ] [[package]] @@ -1397,32 +760,10 @@ dependencies = [ "proc-macro2", "quote", "serde", - "syn 2.0.96", - "toml 0.5.11", + "syn", + "toml", "uniffi_build", - "uniffi_meta 0.25.3", -] - -[[package]] -name = "uniffi_meta" -version = "0.25.0" -source = "git+https://github.com/NordSecurity/uniffi-bindgen-go.git?rev=ba23bab72f1a9bcc39ce81924d3d9265598e017c#ba23bab72f1a9bcc39ce81924d3d9265598e017c" -dependencies = [ - "anyhow", - "bytes", - "siphasher", - "uniffi_checksum_derive 0.25.0 (git+https://github.com/NordSecurity/uniffi-bindgen-go.git?rev=ba23bab72f1a9bcc39ce81924d3d9265598e017c)", -] - -[[package]] -name = "uniffi_meta" -version = "0.25.0" -source = "git+https://github.com/NordSecurity/uniffi-bindgen-cs?rev=f68639fbc720b50ebe561ba75c66c84dc456bdce#f68639fbc720b50ebe561ba75c66c84dc456bdce" -dependencies = [ - "anyhow", - "bytes", - "siphasher", - "uniffi_checksum_derive 0.25.0 (git+https://github.com/NordSecurity/uniffi-bindgen-cs?rev=f68639fbc720b50ebe561ba75c66c84dc456bdce)", + "uniffi_meta", ] [[package]] @@ -1434,31 +775,7 @@ dependencies = [ "anyhow", "bytes", "siphasher", - "uniffi_checksum_derive 0.25.3", -] - -[[package]] -name = "uniffi_testing" -version = "0.25.0" -source = "git+https://github.com/NordSecurity/uniffi-bindgen-go.git?rev=ba23bab72f1a9bcc39ce81924d3d9265598e017c#ba23bab72f1a9bcc39ce81924d3d9265598e017c" -dependencies = [ - "anyhow", - "camino", - "cargo_metadata", - "fs-err", - "once_cell", -] - -[[package]] -name = "uniffi_testing" -version = "0.25.0" -source = "git+https://github.com/NordSecurity/uniffi-bindgen-cs?rev=f68639fbc720b50ebe561ba75c66c84dc456bdce#f68639fbc720b50ebe561ba75c66c84dc456bdce" -dependencies = [ - "anyhow", - "camino", - "cargo_metadata", - "fs-err", - "once_cell", + "uniffi_checksum_derive", ] [[package]] @@ -1474,28 +791,6 @@ dependencies = [ "once_cell", ] -[[package]] -name = "uniffi_udl" -version = "0.25.0" -source = "git+https://github.com/NordSecurity/uniffi-bindgen-go.git?rev=ba23bab72f1a9bcc39ce81924d3d9265598e017c#ba23bab72f1a9bcc39ce81924d3d9265598e017c" -dependencies = [ - "anyhow", - "uniffi_meta 0.25.0 (git+https://github.com/NordSecurity/uniffi-bindgen-go.git?rev=ba23bab72f1a9bcc39ce81924d3d9265598e017c)", - "uniffi_testing 0.25.0 (git+https://github.com/NordSecurity/uniffi-bindgen-go.git?rev=ba23bab72f1a9bcc39ce81924d3d9265598e017c)", - "weedle2 4.0.0 (git+https://github.com/NordSecurity/uniffi-bindgen-go.git?rev=ba23bab72f1a9bcc39ce81924d3d9265598e017c)", -] - -[[package]] -name = "uniffi_udl" -version = "0.25.0" -source = "git+https://github.com/NordSecurity/uniffi-bindgen-cs?rev=f68639fbc720b50ebe561ba75c66c84dc456bdce#f68639fbc720b50ebe561ba75c66c84dc456bdce" -dependencies = [ - "anyhow", - "uniffi_meta 0.25.0 (git+https://github.com/NordSecurity/uniffi-bindgen-cs?rev=f68639fbc720b50ebe561ba75c66c84dc456bdce)", - "uniffi_testing 0.25.0 (git+https://github.com/NordSecurity/uniffi-bindgen-cs?rev=f68639fbc720b50ebe561ba75c66c84dc456bdce)", - "weedle2 4.0.0 (git+https://github.com/NordSecurity/uniffi-bindgen-cs?rev=f68639fbc720b50ebe561ba75c66c84dc456bdce)", -] - [[package]] name = "uniffi_udl" version = "0.25.3" @@ -1503,17 +798,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "889edb7109c6078abe0e53e9b4070cf74a6b3468d141bdf5ef1bd4d1dc24a1c3" dependencies = [ "anyhow", - "uniffi_meta 0.25.3", - "uniffi_testing 0.25.3", - "weedle2 4.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "uniffi_meta", + "uniffi_testing", + "weedle2", ] -[[package]] -name = "utf-8" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" - [[package]] name = "utf8parse" version = "0.2.2" @@ -1526,18 +815,6 @@ version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" -[[package]] -name = "version_check" -version = "0.9.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" - -[[package]] -name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" - [[package]] name = "weedle2" version = "4.0.0" @@ -1547,53 +824,6 @@ dependencies = [ "nom", ] -[[package]] -name = "weedle2" -version = "4.0.0" -source = "git+https://github.com/NordSecurity/uniffi-bindgen-go.git?rev=ba23bab72f1a9bcc39ce81924d3d9265598e017c#ba23bab72f1a9bcc39ce81924d3d9265598e017c" -dependencies = [ - "nom", -] - -[[package]] -name = "weedle2" -version = "4.0.0" -source = "git+https://github.com/NordSecurity/uniffi-bindgen-cs?rev=f68639fbc720b50ebe561ba75c66c84dc456bdce#f68639fbc720b50ebe561ba75c66c84dc456bdce" -dependencies = [ - "nom", -] - -[[package]] -name = "winapi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" -dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", -] - -[[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" - -[[package]] -name = "winapi-util" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" -dependencies = [ - "windows-sys", -] - -[[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" - [[package]] name = "windows-sys" version = "0.59.0" @@ -1667,15 +897,6 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" -[[package]] -name = "winnow" -version = "0.6.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8d71a593cc5c42ad7876e2c1fda56f314f3754c084128833e64f1345ff8a03a" -dependencies = [ - "memchr", -] - [[package]] name = "wyz" version = "0.5.1" @@ -1685,27 +906,6 @@ dependencies = [ "tap", ] -[[package]] -name = "zerocopy" -version = "0.7.35" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" -dependencies = [ - "byteorder", - "zerocopy-derive", -] - -[[package]] -name = "zerocopy-derive" -version = "0.7.35" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.96", -] - [[package]] name = "zstd" version = "0.13.2" diff --git a/Cargo.toml b/Cargo.toml index cef002d..4b7882e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,17 +1,7 @@ [workspace] resolver = "2" members = [ - "crates/servicepoint", - "crates/servicepoint_binding_c", - "crates/servicepoint_binding_c/examples/lang_c", - "crates/servicepoint_binding_uniffi" + "uniffi-bindgen", + "servicepoint-binding-uniffi" ] -[workspace.package] -version = "0.13.1" - -[workspace.lints.rust] -missing-docs = "warn" - -[workspace.dependencies] -thiserror = "2.0" diff --git a/README.md b/README.md index 958de0f..0377840 100644 --- a/README.md +++ b/README.md @@ -1,49 +1,34 @@ -# servicepoint - -[![crates.io](https://img.shields.io/crates/v/servicepoint.svg)](https://crates.io/crates/servicepoint) -[![Crates.io Total Downloads](https://img.shields.io/crates/d/servicepoint)](https://crates.io/crates/servicepoint) -[![docs.rs](https://img.shields.io/docsrs/servicepoint)](https://docs.rs/servicepoint/latest/servicepoint/) -[![GPLv3 licensed](https://img.shields.io/crates/l/servicepoint)](./LICENSE) +# ServicePoint In [CCCB](https://berlin.ccc.de/), there is a big pixel matrix hanging on the wall. It is called "Service Point Display" or "Airport Display". -This repository contains a library for parsing, encoding and sending packets to this display via UDP in multiple -programming languages. -This project moved to [git.berlin.ccc.de/servicepoint/servicepoint](https://git.berlin.ccc.de/servicepoint/servicepoint). -The [GitHub repository](https://github.com/cccb/servicepoint) remains available as a mirror. +This crate contains C# bindings for the [servicepoint](https://git.berlin.ccc.de/servicepoint/servicepoint) library based on [servicepoint-binding-uniffi](https://git.berlin.ccc.de/servicepoint/servicepoint-binding-uniffi). -Take a look at the contained crates for language specific information: +Also take a look at the main project [README](https://git.berlin.ccc.de/servicepoint/servicepoint/src/branch/main/README.md) for more +information. -| Crate | Languages | Readme | -|-----------------------------|-----------------------------------|-----------------------------------------------------------------------------| -| servicepoint | Rust | [servicepoint](crates/servicepoint/README.md) | -| servicepoint_binding_c | C / C++ | [servicepoint_binding_c](crates/servicepoint_binding_c/README.md) | -| servicepoint_binding_uniffi | C# / Python / Go / Kotlin / Swift | [servicepoint_binding_uniffi](crates/servicepoint_binding_uniffi/README.md) | +## Note on stability -## Projects using the library +This library is still in early development. +You can absolutely use it, and it works, but expect minor breaking changes with every version bump. -- screen simulator (rust): [servicepoint-simulator](https://git.berlin.ccc.de/servicepoint/servicepoint-simulator) -- A bunch of projects (C): [arfst23/ServicePoint](https://github.com/arfst23/ServicePoint), including - - a CLI tool to display image files on the display or use the display as a TTY - - a BSD games robots clone - - a split-flap-display simulator - - animations that play on the display -- tanks game (C#): [servicepoint-tanks](https://github.com/kaesaecracker/cccb-tanks-cs) -- cellular automata slideshow (rust): [servicepoint-life](https://github.com/kaesaecracker/servicepoint-life) -- partial typescript implementation inspired by this library and browser stream: [cccb-servicepoint-browser](https://github.com/SamuelScheit/cccb-servicepoint-browser) -- a CLI: [servicepoint-cli](https://git.berlin.ccc.de/servicepoint/servicepoint-cli) +## Notes on differences to rust library -To add yourself to the list, open a pull request. +- Performance will not be as good as the rust version: + - most objects are reference counted. + - objects with mutating methods will also have a MRSW lock +- You will not get rust backtraces in release builds of the native code +- Panic messages will work (PanicException) -You can also check out [awesome-servicepoint](https://github.com/stars/kaesaecracker/lists/awesome-servicepoint) for a bigger collection of projects, including some not related to this library. +## Installation -If you have access, there is even more software linked in [the wiki](https://wiki.berlin.ccc.de/LED-Riesendisplay). +Including this repository as a submodule and building from source is the recommended way of using the library. -## Contributing +```bash +git submodule add https://git.berlin.ccc.de/servicepoint/servicepoint.git +git commit -m "add servicepoint submodule" +``` -See [CONTRIBUTING.md](CONTRIBUTING.md). - -## What happened to servicepoint2? - -After `servicepoint2` has been merged into `servicepoint`, `servicepoint2` will not continue to get any updates. +Run `generate-binding.sh` to regenerate all bindings. This will also build `libservicepoint.so` (or equivalent on your +platform). diff --git a/about_display.md b/about_display.md deleted file mode 100644 index 4fe7911..0000000 --- a/about_display.md +++ /dev/null @@ -1,41 +0,0 @@ -# About the display - -- Resolution: 352x160=56,320 pixels -- Pixels are grouped into 44x20=880 tiles (8x8=64 pixels each) -- Smallest addressable unit: row of pixels inside of a tile (8 pixels = 1 byte) -- The brightness can only be set per tile -- Screen content can be changed using a simple UDP protocol -- Between each row of tiles, there is a gap of around 4 pixels size. This gap changes the aspect ratio of the display. - -### Binary format - -A UDP package sent to the display has a header size of 10 bytes. -Each header value has a size of two bytes (unsigned 16 bit integer). -Depending on the command, there can be a payload following the header. - -To change screen contents, these commands are the most relevant: - -1. Clear screen - - command: `0x0002` - - (rest does not matter) -2. Send CP437 data: render specified text into rectangular region - - command: `0x0003` - - top left tile x - - top left tile y - - width in tiles - - height in tiles - - payload: (width in tiles * height in tiles) bytes - - 1 byte = 1 character - - each character is rendered into one tile (mono-spaced) - - characters are encoded using code page 437 -3. Send bitmap window: set pixel states for a rectangular region - - command: `0x0013` - - top left tile x - - top left _pixel_ y - - width in tiles - - height in _pixels_ - - payload: (width in tiles * height in pixels) bytes - - network byte order - - 1 bit = 1 pixel - -There are other commands implemented as well, e.g. for changing the brightness. diff --git a/crates/servicepoint/Cargo.toml b/crates/servicepoint/Cargo.toml deleted file mode 100644 index 394aec4..0000000 --- a/crates/servicepoint/Cargo.toml +++ /dev/null @@ -1,60 +0,0 @@ -[package] -name = "servicepoint" -version.workspace = true -publish = true -edition = "2021" -license = "GPL-3.0-or-later" -description = "A rust library for the CCCB Service Point Display." -homepage = "https://docs.rs/crate/servicepoint" -repository = "https://git.berlin.ccc.de/servicepoint/servicepoint" -readme = "README.md" -keywords = ["cccb", "cccb-servicepoint"] - -[lib] -crate-type = ["rlib"] - -[dependencies] -log = "0.4" -bitvec = "1.0" -flate2 = { version = "1.0", optional = true } -bzip2 = { version = "0.5", optional = true } -zstd = { version = "0.13", optional = true } -rust-lzma = { version = "0.6", optional = true } -rand = { version = "0.8", optional = true } -tungstenite = { version = "0.26", optional = true } -once_cell = { version = "1.20", optional = true } -thiserror.workspace = true - -[features] -default = ["compression_lzma", "protocol_udp", "cp437"] -compression_zlib = ["dep:flate2"] -compression_bzip2 = ["dep:bzip2"] -compression_lzma = ["dep:rust-lzma"] -compression_zstd = ["dep:zstd"] -all_compressions = ["compression_zlib", "compression_bzip2", "compression_lzma", "compression_zstd"] -rand = ["dep:rand"] -protocol_udp = [] -protocol_websocket = ["dep:tungstenite"] -cp437 = ["dep:once_cell"] - -[[example]] -name = "random_brightness" -required-features = ["rand"] - -[[example]] -name = "game_of_life" -required-features = ["rand"] - -[[example]] -name = "websocket" -required-features = ["protocol_websocket"] - -[dev-dependencies] -# for examples -clap = { version = "4.5", features = ["derive"] } - -[lints] -workspace = true - -[package.metadata.docs.rs] -all-features = true diff --git a/crates/servicepoint/README.md b/crates/servicepoint/README.md deleted file mode 100644 index fe888a3..0000000 --- a/crates/servicepoint/README.md +++ /dev/null @@ -1,67 +0,0 @@ -# servicepoint - -[![crates.io](https://img.shields.io/crates/v/servicepoint.svg)](https://crates.io/crates/servicepoint) -[![Crates.io Total Downloads](https://img.shields.io/crates/d/servicepoint)](https://crates.io/crates/servicepoint) -[![docs.rs](https://img.shields.io/docsrs/servicepoint)](https://docs.rs/servicepoint/latest/servicepoint/) -[![GPLv3 licensed](https://img.shields.io/crates/l/servicepoint)](../../LICENSE) - -In [CCCB](https://berlin.ccc.de/), there is a big pixel matrix hanging on the wall. It is called "Service Point -Display" or "Airport Display". -This crate contains a library for parsing, encoding and sending packets to this display via UDP. - -## Installation - -```bash -cargo add servicepoint -``` -or -```toml -[dependencies] -servicepoint = "0.13.1" -``` - -## Examples - -```rust no_run -fn main() { - // establish connection - let connection = servicepoint::Connection::open("172.23.42.29:2342") - .expect("connection failed"); - - // clear screen content - connection.send(servicepoint::Command::Clear) - .expect("send failed"); -} -``` - -More examples are available in the crate. -Execute `cargo run --example` for a list of available examples and `cargo run --example ` to run one. - -## Note on stability - -This library can be used for creative project or just to play around with the display. -A decent coverage by unit tests prevents major problems and I also test this with my own projects, which mostly use up-to-date versions. - -That being said, the API is still being worked on. -Expect minor breaking changes with every version bump. -Please specify the full version including patch in your Cargo.toml until 1.0 is released. - -## Features - -This library has multiple optional dependencies. -You can choose to (not) include them by toggling the related features. - -| Name | Default | Description | -|--------------------|---------|--------------------------------------------| -| compression_zlib | false | Enable additional compression algo | -| compression_bzip2 | false | Enable additional compression algo | -| compression_lzma | true | Enable additional compression algo | -| compression_zstd | false | Enable additional compression algo | -| protocol_udp | true | Connection::Udp | -| protocol_websocket | false | Connection::WebSocket | -| rand | false | impl Distribution for Standard | -| cp437 | true | Conversion to and from CP-437 | - -## Everything else - -Look at the main project [README](https://git.berlin.ccc.de/servicepoint/servicepoint/src/branch/main/README.md) for further information. diff --git a/crates/servicepoint/examples/announce.rs b/crates/servicepoint/examples/announce.rs deleted file mode 100644 index 05d2b19..0000000 --- a/crates/servicepoint/examples/announce.rs +++ /dev/null @@ -1,48 +0,0 @@ -//! An example for how to send text to the display. - -use clap::Parser; -use servicepoint::*; - -#[derive(Parser, Debug)] -struct Cli { - #[arg( - short, - long, - default_value = "localhost:2342", - help = "Address of the display" - )] - destination: String, - #[arg(short, long, num_args = 1.., value_delimiter = '\n', - help = "Text to send - specify multiple times for multiple lines")] - text: Vec, - #[arg( - short, - long, - default_value_t = true, - help = "Clear screen before sending text" - )] - clear: bool, -} - -/// example: `cargo run -- --text "Hallo" --text "CCCB"` -fn main() { - let mut cli = Cli::parse(); - if cli.text.is_empty() { - cli.text.push("Hello, CCCB!".to_string()); - } - - let connection = Connection::open(&cli.destination) - .expect("could not connect to display"); - - if cli.clear { - connection - .send(Command::Clear) - .expect("sending clear failed"); - } - - let text = cli.text.join("\n"); - let grid = CharGrid::wrap_str(TILE_WIDTH, &text); - connection - .send(Command::Utf8Data(Origin::ZERO, grid)) - .expect("sending text failed"); -} diff --git a/crates/servicepoint/examples/brightness_tester.rs b/crates/servicepoint/examples/brightness_tester.rs deleted file mode 100644 index ec78415..0000000 --- a/crates/servicepoint/examples/brightness_tester.rs +++ /dev/null @@ -1,37 +0,0 @@ -//! Show a brightness level test pattern on screen - -use clap::Parser; -use servicepoint::*; - -#[derive(Parser, Debug)] -struct Cli { - #[arg(short, long, default_value = "localhost:2342")] - destination: String, -} - -fn main() { - let cli = Cli::parse(); - let connection = Connection::open(cli.destination) - .expect("could not connect to display"); - - let mut pixels = Bitmap::max_sized(); - pixels.fill(true); - - let command = Command::BitmapLinearWin( - Origin::ZERO, - pixels, - CompressionCode::Uncompressed, - ); - connection.send(command).expect("send failed"); - - let max_brightness: u8 = Brightness::MAX.into(); - let mut brightnesses = BrightnessGrid::new(TILE_WIDTH, TILE_HEIGHT); - for (index, byte) in brightnesses.data_ref_mut().iter_mut().enumerate() { - let level = index as u8 % max_brightness; - *byte = Brightness::try_from(level).unwrap(); - } - - connection - .send(Command::CharBrightness(Origin::ZERO, brightnesses)) - .expect("send failed"); -} diff --git a/crates/servicepoint/examples/game_of_life.rs b/crates/servicepoint/examples/game_of_life.rs deleted file mode 100644 index ab4f63b..0000000 --- a/crates/servicepoint/examples/game_of_life.rs +++ /dev/null @@ -1,89 +0,0 @@ -//! A simple game of life implementation to show how to render graphics to the display. - -use clap::Parser; -use rand::{distributions, Rng}; -use servicepoint::*; -use std::thread; - -#[derive(Parser, Debug)] -struct Cli { - #[arg(short, long, default_value = "localhost:2342")] - destination: String, - #[arg(short, long, default_value_t = 0.5f64)] - probability: f64, -} - -fn main() { - let cli = Cli::parse(); - - let connection = Connection::open(&cli.destination) - .expect("could not connect to display"); - let mut field = make_random_field(cli.probability); - - loop { - let command = Command::BitmapLinearWin( - Origin::ZERO, - field.clone(), - CompressionCode::Lzma, - ); - connection.send(command).expect("could not send"); - thread::sleep(FRAME_PACING); - field = iteration(field); - } -} - -fn iteration(field: Bitmap) -> Bitmap { - let mut next = field.clone(); - for x in 0..field.width() { - for y in 0..field.height() { - let old_state = field.get(x, y); - let neighbors = count_neighbors(&field, x as i32, y as i32); - - let new_state = matches!( - (old_state, neighbors), - (true, 2) | (true, 3) | (false, 3) - ); - next.set(x, y, new_state); - } - } - next -} - -fn count_neighbors(field: &Bitmap, x: i32, y: i32) -> i32 { - let mut count = 0; - for nx in x - 1..=x + 1 { - for ny in y - 1..=y + 1 { - if nx == x && ny == y { - continue; // the cell itself does not count - } - - if nx < 0 - || ny < 0 - || nx >= field.width() as i32 - || ny >= field.height() as i32 - { - continue; // pixels outside the grid do not count - } - - if !field.get(nx as usize, ny as usize) { - continue; // dead cells do not count - } - - count += 1; - } - } - - count -} - -fn make_random_field(probability: f64) -> Bitmap { - let mut field = Bitmap::max_sized(); - let mut rng = rand::thread_rng(); - let d = distributions::Bernoulli::new(probability).unwrap(); - for x in 0..field.width() { - for y in 0..field.height() { - field.set(x, y, rng.sample(d)); - } - } - field -} diff --git a/crates/servicepoint/examples/moving_line.rs b/crates/servicepoint/examples/moving_line.rs deleted file mode 100644 index 3ebd6b0..0000000 --- a/crates/servicepoint/examples/moving_line.rs +++ /dev/null @@ -1,33 +0,0 @@ -//! A simple example for how to send pixel data to the display. - -use clap::Parser; -use servicepoint::*; -use std::thread; - -#[derive(Parser, Debug)] -struct Cli { - #[arg(short, long, default_value = "localhost:2342")] - destination: String, -} - -fn main() { - let connection = Connection::open(Cli::parse().destination) - .expect("could not connect to display"); - - let mut pixels = Bitmap::max_sized(); - for x_offset in 0..usize::MAX { - pixels.fill(false); - - for y in 0..PIXEL_HEIGHT { - pixels.set((y + x_offset) % PIXEL_WIDTH, y, true); - } - - let command = Command::BitmapLinearWin( - Origin::ZERO, - pixels.clone(), - CompressionCode::Lzma, - ); - connection.send(command).expect("send failed"); - thread::sleep(FRAME_PACING); - } -} diff --git a/crates/servicepoint/examples/random_brightness.rs b/crates/servicepoint/examples/random_brightness.rs deleted file mode 100644 index 0f976c4..0000000 --- a/crates/servicepoint/examples/random_brightness.rs +++ /dev/null @@ -1,66 +0,0 @@ -//! A simple example for how to set brightnesses for tiles on the screen. -//! Continuously changes the tiles in a random window to random brightnesses. - -use clap::Parser; -use rand::Rng; -use servicepoint::*; -use std::time::Duration; - -#[derive(Parser, Debug)] -struct Cli { - #[arg(short, long, default_value = "localhost:2342")] - destination: String, - #[arg(short, long, default_value_t = true)] - enable_all: bool, - #[arg(short, long, default_value_t = 100, allow_negative_numbers = false)] - wait_ms: u64, -} - -fn main() { - let cli = Cli::parse(); - - let connection = Connection::open(cli.destination) - .expect("could not connect to display"); - let wait_duration = Duration::from_millis(cli.wait_ms); - - // put all pixels in on state - if cli.enable_all { - let mut filled_grid = Bitmap::max_sized(); - filled_grid.fill(true); - - let command = Command::BitmapLinearWin( - Origin::ZERO, - filled_grid, - CompressionCode::Lzma, - ); - connection.send(command).expect("send failed"); - } - - // set all pixels to the same random brightness - let mut rng = rand::thread_rng(); - connection.send(Command::Brightness(rng.gen())).unwrap(); - - // continuously update random windows to new random brightness - loop { - let min_size = 1; - let x = rng.gen_range(0..TILE_WIDTH - min_size); - let y = rng.gen_range(0..TILE_HEIGHT - min_size); - - let w = rng.gen_range(min_size..=TILE_WIDTH - x); - let h = rng.gen_range(min_size..=TILE_HEIGHT - y); - - let origin = Origin::new(x, y); - let mut luma = BrightnessGrid::new(w, h); - - for y in 0..h { - for x in 0..w { - luma.set(x, y, rng.gen()); - } - } - - connection - .send(Command::CharBrightness(origin, luma)) - .unwrap(); - std::thread::sleep(wait_duration); - } -} diff --git a/crates/servicepoint/examples/websocket.rs b/crates/servicepoint/examples/websocket.rs deleted file mode 100644 index 207609e..0000000 --- a/crates/servicepoint/examples/websocket.rs +++ /dev/null @@ -1,24 +0,0 @@ -//! Example for how to use the WebSocket connection - -use servicepoint::{ - Bitmap, Command, CompressionCode, Connection, Grid, Origin, -}; - -fn main() { - let connection = - Connection::open_websocket("ws://localhost:8080".parse().unwrap()) - .unwrap(); - - connection.send(Command::Clear).unwrap(); - - let mut pixels = Bitmap::max_sized(); - pixels.fill(true); - - connection - .send(Command::BitmapLinearWin( - Origin::ZERO, - pixels, - CompressionCode::Lzma, - )) - .unwrap(); -} diff --git a/crates/servicepoint/examples/wiping_clear.rs b/crates/servicepoint/examples/wiping_clear.rs deleted file mode 100644 index 101a9ae..0000000 --- a/crates/servicepoint/examples/wiping_clear.rs +++ /dev/null @@ -1,43 +0,0 @@ -//! An example on how to modify the image on screen without knowing the current content. -use clap::Parser; -use servicepoint::*; -use std::thread; -use std::time::Duration; - -#[derive(Parser, Debug)] -struct Cli { - #[arg(short, long, default_value = "localhost:2342")] - destination: String, - #[arg(short, long = "duration-ms", default_value_t = 5000)] - time: u64, -} - -fn main() { - let cli = Cli::parse(); - - let sleep_duration = Duration::max( - FRAME_PACING, - Duration::from_millis(cli.time / PIXEL_WIDTH as u64), - ); - - let connection = Connection::open(cli.destination) - .expect("could not connect to display"); - - let mut enabled_pixels = Bitmap::max_sized(); - enabled_pixels.fill(true); - - for x_offset in 0..PIXEL_WIDTH { - for y in 0..PIXEL_HEIGHT { - enabled_pixels.set(x_offset % PIXEL_WIDTH, y, false); - } - - connection - .send(Command::BitmapLinearWin( - Origin::ZERO, - enabled_pixels.clone(), - CompressionCode::Lzma, - )) - .expect("could not send command to display"); - thread::sleep(sleep_duration); - } -} diff --git a/crates/servicepoint/src/bit_vec.rs b/crates/servicepoint/src/bit_vec.rs deleted file mode 100644 index 2ece813..0000000 --- a/crates/servicepoint/src/bit_vec.rs +++ /dev/null @@ -1,10 +0,0 @@ -/// A byte-packed vector of booleans. -/// -/// The implementation is provided by [bitvec]. -/// This is an alias for the specific type of [bitvec::BitVec] used in this crate. -pub type BitVec = bitvec::BitVec; - -pub mod bitvec { - //! Re-export of the used library [mod@bitvec]. - pub use bitvec::prelude::*; -} diff --git a/crates/servicepoint/src/bitmap.rs b/crates/servicepoint/src/bitmap.rs deleted file mode 100644 index afa42f2..0000000 --- a/crates/servicepoint/src/bitmap.rs +++ /dev/null @@ -1,379 +0,0 @@ -use crate::data_ref::DataRef; -use crate::BitVec; -use crate::*; -use ::bitvec::order::Msb0; -use ::bitvec::prelude::BitSlice; -use ::bitvec::slice::IterMut; - -/// A fixed-size 2D grid of booleans. -/// -/// The values are stored in packed bytes (8 values per byte) in the same order as used by the display for storing pixels. -/// This means that no conversion is necessary for sending the data to the display. -/// The downside is that the width has to be a multiple of 8. -/// -/// # Examples -/// -/// ```rust -/// use servicepoint::Bitmap; -/// let mut bitmap = Bitmap::new(8, 2); -/// -/// ``` -#[derive(Debug, Clone, PartialEq, Eq)] -pub struct Bitmap { - width: usize, - height: usize, - bit_vec: BitVec, -} - -impl Bitmap { - /// Creates a new [Bitmap] with the specified dimensions. - /// - /// # Arguments - /// - /// - `width`: size in pixels in x-direction - /// - `height`: size in pixels in y-direction - /// - /// returns: [Bitmap] initialized to all pixels off - /// - /// # Panics - /// - /// - when the width is not dividable by 8 - pub fn new(width: usize, height: usize) -> Self { - assert_eq!( - width % 8, - 0, - "width must be a multiple of 8, but is {width}" - ); - Self { - width, - height, - bit_vec: BitVec::repeat(false, width * height), - } - } - - /// Creates a new pixel grid with the size of the whole screen. - #[must_use] - pub fn max_sized() -> Self { - Self::new(PIXEL_WIDTH, PIXEL_HEIGHT) - } - - /// Loads a [Bitmap] with the specified dimensions from the provided data. - /// - /// # Arguments - /// - /// - `width`: size in pixels in x-direction - /// - `height`: size in pixels in y-direction - /// - /// returns: [Bitmap] that contains a copy of the provided data - /// - /// # Panics - /// - /// - when the dimensions and data size do not match exactly. - /// - when the width is not dividable by 8 - #[must_use] - pub fn load(width: usize, height: usize, data: &[u8]) -> Self { - assert_eq!(width % 8, 0, "width must be a multiple of 8, but is {width}"); - assert_eq!(data.len(), height * width / 8, "data length must match dimensions, with 8 pixels per byte."); - Self { - width, - height, - bit_vec: BitVec::from_slice(data), - } - } - - /// Creates a [Bitmap] with the specified width from the provided [BitVec] without copying it. - /// - /// returns: [Bitmap] that contains the provided data. - /// - /// # Panics - /// - /// - when the bitvec size is not dividable by the provided width - /// - when the width is not dividable by 8 - #[must_use] - pub fn from_bitvec(width: usize, bit_vec: BitVec) -> Self { - assert_eq!(width % 8, 0, "width must be a multiple of 8, but is {width}"); - let len = bit_vec.len(); - let height = len / width; - assert_eq!(0, len % width, "dimension mismatch - len {len} is not dividable by {width}"); - Self { width, height, bit_vec } - } - - /// Iterate over all cells in [Bitmap]. - /// - /// Order is equivalent to the following loop: - /// ``` - /// # use servicepoint::{Bitmap, Grid}; - /// # let grid = Bitmap::new(8,2); - /// for y in 0..grid.height() { - /// for x in 0..grid.width() { - /// grid.get(x, y); - /// } - /// } - /// ``` - pub fn iter(&self) -> impl Iterator { - self.bit_vec.iter().by_refs() - } - - /// Iterate over all cells in [Bitmap] mutably. - /// - /// Order is equivalent to the following loop: - /// ``` - /// # use servicepoint::{Bitmap, Grid}; - /// # let mut grid = Bitmap::new(8,2); - /// # let value = false; - /// for y in 0..grid.height() { - /// for x in 0..grid.width() { - /// grid.set(x, y, value); - /// } - /// } - /// ``` - /// - /// # Example - /// ``` - /// # use servicepoint::{Bitmap, Grid}; - /// # let mut grid = Bitmap::new(8,2); - /// # let value = false; - /// for (index, mut pixel) in grid.iter_mut().enumerate() { - /// pixel.set(index % 2 == 0) - /// } - /// ``` - pub fn iter_mut(&mut self) -> IterMut { - self.bit_vec.iter_mut() - } - - /// Iterate over all rows in [Bitmap] top to bottom. - pub fn iter_rows(&self) -> IterRows { - IterRows { - bitmap: self, - row: 0, - } - } -} - -impl Grid for Bitmap { - /// Sets the value of the specified position in the [Bitmap]. - /// - /// # Arguments - /// - /// - `x` and `y`: position of the cell - /// - `value`: the value to write to the cell - /// - /// returns: old value of the cell - /// - /// # Panics - /// - /// When accessing `x` or `y` out of bounds. - fn set(&mut self, x: usize, y: usize, value: bool) { - self.assert_in_bounds(x, y); - self.bit_vec.set(x + y * self.width, value) - } - - fn get(&self, x: usize, y: usize) -> bool { - self.assert_in_bounds(x, y); - self.bit_vec[x + y * self.width] - } - - /// Sets the state of all pixels in the [Bitmap]. - /// - /// # Arguments - /// - /// - `this`: instance to write to - /// - `value`: the value to set all pixels to - fn fill(&mut self, value: bool) { - self.bit_vec.fill(value); - } - - fn width(&self) -> usize { - self.width - } - - fn height(&self) -> usize { - self.height - } -} - -impl DataRef for Bitmap { - fn data_ref_mut(&mut self) -> &mut [u8] { - self.bit_vec.as_raw_mut_slice() - } - - fn data_ref(&self) -> &[u8] { - self.bit_vec.as_raw_slice() - } -} - -impl From for Vec { - /// Turns a [Bitmap] into the underlying [`Vec`]. - fn from(value: Bitmap) -> Self { - value.bit_vec.into() - } -} - -impl From for BitVec { - /// Turns a [Bitmap] into the underlying [BitVec]. - fn from(value: Bitmap) -> Self { - value.bit_vec - } -} - -impl From<&ValueGrid> for Bitmap { - /// Converts a grid of [bool]s into a [Bitmap]. - /// - /// # Panics - /// - /// - when the width of `value` is not dividable by 8 - fn from(value: &ValueGrid) -> Self { - let mut result = Self::new(value.width(), value.height()); - for (mut to, from) in result.iter_mut().zip(value.iter()) { - *to = *from; - } - result - } -} - -impl From<&Bitmap> for ValueGrid { - /// Converts a [Bitmap] into a grid of [bool]s. - fn from(value: &Bitmap) -> Self { - let mut result = Self::new(value.width(), value.height()); - for (to, from) in result.iter_mut().zip(value.iter()) { - *to = *from; - } - result - } -} - -pub struct IterRows<'t> { - bitmap: &'t Bitmap, - row: usize, -} - -impl<'t> Iterator for IterRows<'t> { - type Item = &'t BitSlice; - - fn next(&mut self) -> Option { - if self.row >= self.bitmap.height { - return None; - } - - let start = self.row * self.bitmap.width; - let end = start + self.bitmap.width; - self.row += 1; - Some(&self.bitmap.bit_vec[start..end]) - } -} - -#[cfg(test)] -mod tests { - use crate::{BitVec, Bitmap, DataRef, Grid, ValueGrid}; - - #[test] - fn fill() { - let mut grid = Bitmap::new(8, 2); - assert_eq!(grid.data_ref(), [0x00, 0x00]); - - grid.fill(true); - assert_eq!(grid.data_ref(), [0xFF, 0xFF]); - - grid.fill(false); - assert_eq!(grid.data_ref(), [0x00, 0x00]); - } - - #[test] - fn get_set() { - let mut grid = Bitmap::new(8, 2); - assert!(!grid.get(0, 0)); - assert!(!grid.get(1, 1)); - - grid.set(5, 0, true); - grid.set(1, 1, true); - assert_eq!(grid.data_ref(), [0x04, 0x40]); - - assert!(grid.get(5, 0)); - assert!(grid.get(1, 1)); - assert!(!grid.get(1, 0)); - } - - #[test] - fn load() { - let mut grid = Bitmap::new(8, 3); - for x in 0..grid.width { - for y in 0..grid.height { - grid.set(x, y, (x + y) % 2 == 0); - } - } - - assert_eq!(grid.data_ref(), [0xAA, 0x55, 0xAA]); - - let data: Vec = grid.into(); - - let grid = Bitmap::load(8, 3, &data); - assert_eq!(grid.data_ref(), [0xAA, 0x55, 0xAA]); - } - - #[test] - #[should_panic] - fn out_of_bounds_x() { - let vec = Bitmap::new(8, 2); - vec.get(8, 1); - } - - #[test] - #[should_panic] - fn out_of_bounds_y() { - let mut vec = Bitmap::new(8, 2); - vec.set(1, 2, false); - } - - #[test] - fn iter() { - let grid = Bitmap::new(8, 2); - assert_eq!(16, grid.iter().count()) - } - - #[test] - fn iter_rows() { - let grid = Bitmap::load(8, 2, &[0x04, 0x40]); - let mut iter = grid.iter_rows(); - - assert_eq!(iter.next().unwrap().count_ones(), 1); - assert_eq!(iter.next().unwrap().count_ones(), 1); - assert_eq!(None, iter.next()); - } - - #[test] - fn iter_mut() { - let mut grid = Bitmap::new(8, 2); - for (index, mut pixel) in grid.iter_mut().enumerate() { - pixel.set(index % 2 == 0); - } - assert_eq!(grid.data_ref(), [0xAA, 0xAA]); - } - - #[test] - fn data_ref_mut() { - let mut grid = Bitmap::new(8, 2); - let data = grid.data_ref_mut(); - data[1] = 0x0F; - assert!(grid.get(7, 1)); - } - - #[test] - fn to_bitvec() { - let mut grid = Bitmap::new(8, 2); - grid.set(0, 0, true); - let bitvec: BitVec = grid.into(); - assert_eq!(bitvec.as_raw_slice(), [0x80, 0x00]); - } - - #[test] - fn from_bool_grid() { - let original = ValueGrid::load( - 8, - 1, - &[true, false, true, false, true, false, true, false], - ); - let converted = Bitmap::from(&original); - let reconverted = ValueGrid::from(&converted); - assert_eq!(original, reconverted); - } -} diff --git a/crates/servicepoint/src/brightness.rs b/crates/servicepoint/src/brightness.rs deleted file mode 100644 index 539a0a2..0000000 --- a/crates/servicepoint/src/brightness.rs +++ /dev/null @@ -1,109 +0,0 @@ -#[cfg(feature = "rand")] -use rand::{ - distributions::{Distribution, Standard}, - Rng, -}; - -/// A display brightness value, checked for correct value range -/// -/// # Examples -/// -/// ``` -/// # use servicepoint::{Brightness, Command, Connection}; -/// let b = Brightness::MAX; -/// let val: u8 = b.into(); -/// -/// let b = Brightness::try_from(7).unwrap(); -/// # let connection = Connection::open("127.0.0.1:2342").unwrap(); -/// let result = connection.send(Command::Brightness(b)); -/// ``` -#[derive(Debug, Copy, Clone, PartialEq, Eq, Ord, PartialOrd)] -pub struct Brightness(u8); - -impl From for u8 { - fn from(brightness: Brightness) -> Self { - Self::from(&brightness) - } -} - -impl From<&Brightness> for u8 { - fn from(brightness: &Brightness) -> Self { - brightness.0 - } -} - -impl TryFrom for Brightness { - type Error = u8; - - fn try_from(value: u8) -> Result { - if value > Self::MAX.0 { - Err(value) - } else { - Ok(Brightness(value)) - } - } -} - -impl Brightness { - /// highest possible brightness value, 11 - pub const MAX: Brightness = Brightness(11); - /// lowest possible brightness value, 0 - pub const MIN: Brightness = Brightness(0); - - /// Create a brightness value without returning an error for brightnesses above [Brightness::MAX]. - /// - /// returns: the specified value as a [Brightness], or [Brightness::MAX]. - pub fn saturating_from(value: u8) -> Brightness { - if value > Brightness::MAX.into() { - Brightness::MAX - } else { - Brightness(value) - } - } -} - -impl Default for Brightness { - fn default() -> Self { - Self::MAX - } -} - -#[cfg(feature = "rand")] -impl Distribution for Standard { - fn sample(&self, rng: &mut R) -> Brightness { - Brightness(rng.gen_range(Brightness::MIN.0..=Brightness::MAX.0)) - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn brightness_from_u8() { - assert_eq!(Err(100), Brightness::try_from(100)); - assert_eq!(Ok(Brightness(1)), Brightness::try_from(1)); - } - - #[test] - #[cfg(feature = "rand")] - fn rand_brightness() { - let mut rng = rand::thread_rng(); - for _ in 0..100 { - let _: Brightness = rng.gen(); - } - } - - #[test] - fn saturating_convert() { - assert_eq!(Brightness::MAX, Brightness::saturating_from(100)); - assert_eq!(Brightness(5), Brightness::saturating_from(5)); - } - - #[test] - #[cfg(feature = "rand")] - fn test() { - let mut rng = rand::thread_rng(); - assert_ne!(rng.gen::(), rng.gen()); - } -} diff --git a/crates/servicepoint/src/brightness_grid.rs b/crates/servicepoint/src/brightness_grid.rs deleted file mode 100644 index 5727e39..0000000 --- a/crates/servicepoint/src/brightness_grid.rs +++ /dev/null @@ -1,93 +0,0 @@ -use crate::brightness::Brightness; -use crate::grid::Grid; -use crate::value_grid::ValueGrid; -use crate::ByteGrid; - -/// A grid containing brightness values. -/// -/// # Examples -/// -/// ```rust -/// # use servicepoint::{Brightness, BrightnessGrid, Command, Connection, Grid, Origin}; -/// let mut grid = BrightnessGrid::new(2,2); -/// grid.set(0, 0, Brightness::MIN); -/// grid.set(1, 1, Brightness::MIN); -/// -/// # let connection = Connection::open("127.0.0.1:2342").unwrap(); -/// connection.send(Command::CharBrightness(Origin::new(3, 7), grid)).unwrap() -/// ``` -pub type BrightnessGrid = ValueGrid; - -impl BrightnessGrid { - /// Like [Self::load], but ignoring any out-of-range brightness values - pub fn saturating_load(width: usize, height: usize, data: &[u8]) -> Self { - ValueGrid::load(width, height, data).map(Brightness::saturating_from) - } -} - -impl From for Vec { - fn from(value: BrightnessGrid) -> Self { - value - .iter() - .map(|brightness| (*brightness).into()) - .collect() - } -} - -impl From<&BrightnessGrid> for ByteGrid { - fn from(value: &BrightnessGrid) -> Self { - let u8s = value - .iter() - .map(|brightness| (*brightness).into()) - .collect::>(); - ValueGrid::load(value.width(), value.height(), &u8s) - } -} - -impl TryFrom for BrightnessGrid { - type Error = u8; - - fn try_from(value: ByteGrid) -> Result { - let brightnesses = value - .iter() - .map(|b| Brightness::try_from(*b)) - .collect::, _>>()?; - Ok(BrightnessGrid::load( - value.width(), - value.height(), - &brightnesses, - )) - } -} - -#[cfg(test)] -mod tests { - use crate::value_grid::ValueGrid; - use crate::{Brightness, BrightnessGrid, DataRef, Grid}; - - #[test] - fn to_u8_grid() { - let mut grid = BrightnessGrid::new(2, 2); - grid.set(1, 0, Brightness::MIN); - grid.set(0, 1, Brightness::MAX); - let actual = ValueGrid::from(&grid); - assert_eq!(actual.data_ref(), &[11, 0, 11, 11]); - } - - #[test] - fn saturating_load() { - assert_eq!( - BrightnessGrid::load( - 2, - 2, - &[ - Brightness::MAX, - Brightness::MAX, - Brightness::MIN, - Brightness::MAX - ] - ), - BrightnessGrid::saturating_load(2, 2, &[255u8, 23, 0, 42]) - ); - } -} diff --git a/crates/servicepoint/src/byte_grid.rs b/crates/servicepoint/src/byte_grid.rs deleted file mode 100644 index 0a7fdae..0000000 --- a/crates/servicepoint/src/byte_grid.rs +++ /dev/null @@ -1,4 +0,0 @@ -use crate::ValueGrid; - -/// A 2d grid of bytes - see [ValueGrid]. -pub type ByteGrid = ValueGrid; diff --git a/crates/servicepoint/src/char_grid.rs b/crates/servicepoint/src/char_grid.rs deleted file mode 100644 index d1a3fd7..0000000 --- a/crates/servicepoint/src/char_grid.rs +++ /dev/null @@ -1,298 +0,0 @@ -use crate::{Grid, SetValueSeriesError, TryLoadValueGridError, ValueGrid}; -use std::string::FromUtf8Error; - -/// A grid containing UTF-8 characters. -/// -/// To send a CharGrid to the display, use [Command::Utf8Data](crate::Command::Utf8Data). -/// -/// Also see [ValueGrid] for the non-specialized operations and examples. -/// -/// # Examples -/// -/// ```rust -/// # use servicepoint::{CharGrid, Command, Connection, Origin}; -/// let grid = CharGrid::from("You can\nload multiline\nstrings directly"); -/// assert_eq!(grid.get_row_str(1), Some("load multiline\0\0".to_string())); -/// -/// # let connection = Connection::Fake; -/// let command = Command::Utf8Data(Origin::ZERO, grid); -/// ``` -pub type CharGrid = ValueGrid; - -impl CharGrid { - /// Loads a [CharGrid] with the specified width from the provided text, wrapping to as many rows as needed. - /// - /// The passed rows are extended with '\0' if needed. - /// - /// returns: [CharGrid] that contains a copy of the provided data. - /// - /// # Examples - /// - /// ``` - /// # use servicepoint::CharGrid; - /// let grid = CharGrid::wrap_str(2, "abc\ndef"); - /// ``` - pub fn wrap_str(width: usize, text: &str) -> Self { - let lines = text - .split('\n') - .flat_map(move |x| { - x.chars() - .collect::>() - .chunks(width) - .map(|c| { - let mut s = String::from_iter(c); - s.push_str(&"\0".repeat(width - s.chars().count())); - s - }) - .collect::>() - }) - .collect::>(); - let height = lines.len(); - let mut result = Self::new(width, height); - for (row, text_line) in lines.iter().enumerate() { - result.set_row_str(row, text_line).unwrap() - } - result - } - - /// Copies a column from the grid as a String. - /// - /// Returns [None] if x is out of bounds. - /// - /// # Examples - /// - /// ``` - /// # use servicepoint::CharGrid; - /// let grid = CharGrid::from("ab\ncd"); - /// let col = grid.get_col_str(0).unwrap(); // "ac" - /// ``` - pub fn get_col_str(&self, x: usize) -> Option { - Some(String::from_iter(self.get_col(x)?)) - } - - /// Copies a row from the grid as a String. - /// - /// Returns [None] if y is out of bounds. - /// - /// # Examples - /// - /// ``` - /// # use servicepoint::CharGrid; - /// let grid = CharGrid::from("ab\ncd"); - /// let row = grid.get_row_str(0).unwrap(); // "ab" - /// ``` - pub fn get_row_str(&self, y: usize) -> Option { - Some(String::from_iter(self.get_row(y)?)) - } - - /// Overwrites a row in the grid with a str. - /// - /// Returns [SetValueSeriesError] if y is out of bounds or `row` is not of the correct size. - /// - /// # Examples - /// - /// ``` - /// # use servicepoint::CharGrid; - /// let mut grid = CharGrid::from("ab\ncd"); - /// grid.set_row_str(0, "ef").unwrap(); - /// ``` - pub fn set_row_str( - &mut self, - y: usize, - value: &str, - ) -> Result<(), SetValueSeriesError> { - self.set_row(y, value.chars().collect::>().as_ref()) - } - - /// Overwrites a column in the grid with a str. - /// - /// Returns [SetValueSeriesError] if y is out of bounds or `row` is not of the correct size. - /// - /// # Examples - /// - /// ``` - /// # use servicepoint::CharGrid; - /// let mut grid = CharGrid::from("ab\ncd"); - /// grid.set_col_str(0, "ef").unwrap(); - /// ``` - pub fn set_col_str( - &mut self, - x: usize, - value: &str, - ) -> Result<(), SetValueSeriesError> { - self.set_col(x, value.chars().collect::>().as_ref()) - } - - /// Loads a [CharGrid] with the specified dimensions from the provided UTF-8 bytes. - /// - /// returns: [CharGrid] that contains the provided data, or [FromUtf8Error] if the data is invalid. - /// - /// # Examples - /// - /// ``` - /// # use servicepoint::CharGrid; - /// let grid = CharGrid::load_utf8(2, 2, [97u8, 98, 99, 100].to_vec()); - /// ``` - pub fn load_utf8( - width: usize, - height: usize, - bytes: Vec, - ) -> Result { - let s: Vec = String::from_utf8(bytes)?.chars().collect(); - Ok(CharGrid::try_load(width, height, s)?) - } -} - -#[derive(Debug, thiserror::Error)] -pub enum LoadUtf8Error { - #[error(transparent)] - FromUtf8Error(#[from] FromUtf8Error), - #[error(transparent)] - TryLoadError(#[from] TryLoadValueGridError), -} - -impl From<&str> for CharGrid { - fn from(value: &str) -> Self { - let value = value.replace("\r\n", "\n"); - let mut lines = value.split('\n').collect::>(); - let width = lines - .iter() - .fold(0, move |a, x| std::cmp::max(a, x.chars().count())); - - while lines.last().is_some_and(move |line| line.is_empty()) { - _ = lines.pop(); - } - - let mut grid = Self::new(width, lines.len()); - for (y, line) in lines.iter().enumerate() { - for (x, char) in line.chars().enumerate() { - grid.set(x, y, char); - } - } - - grid - } -} - -impl From for CharGrid { - fn from(value: String) -> Self { - CharGrid::from(&*value) - } -} - -impl From for String { - fn from(grid: CharGrid) -> Self { - String::from(&grid) - } -} - -impl From<&CharGrid> for String { - /// Converts a [CharGrid] into a [String]. - /// - /// Rows are separated by '\n'. - /// - /// # Examples - /// - /// ```rust - /// # use servicepoint::CharGrid; - /// let grid = CharGrid::from("ab\ncd"); - /// let string = String::from(grid); - /// let grid = CharGrid::from(string); - /// ``` - fn from(value: &CharGrid) -> Self { - value - .iter_rows() - .map(String::from_iter) - .collect::>() - .join("\n") - } -} - -impl From<&CharGrid> for Vec { - /// Converts a [CharGrid] into a [`Vec`]. - /// - /// Rows are not separated. - /// - /// # Examples - /// - /// ```rust - /// # use servicepoint::{CharGrid, Grid}; - /// let grid = CharGrid::from("ab\ncd"); - /// let height = grid.height(); - /// let width = grid.width(); - /// let grid = CharGrid::load_utf8(width, height, grid.into()); - /// ``` - fn from(value: &CharGrid) -> Self { - String::from_iter(value.iter()).into_bytes() - } -} - -impl From for Vec { - /// See [`From<&CharGrid>::from`]. - fn from(value: CharGrid) -> Self { - Self::from(&value) - } -} - -#[cfg(test)] -mod test { - use super::*; - #[test] - fn col_str() { - let mut grid = CharGrid::new(2, 3); - assert_eq!(grid.get_col_str(2), None); - assert_eq!(grid.get_col_str(1), Some(String::from("\0\0\0"))); - assert_eq!(grid.set_col_str(1, "abc"), Ok(())); - assert_eq!(grid.get_col_str(1), Some(String::from("abc"))); - } - - #[test] - fn row_str() { - let mut grid = CharGrid::new(2, 3); - assert_eq!(grid.get_row_str(3), None); - assert_eq!(grid.get_row_str(1), Some(String::from("\0\0"))); - assert_eq!( - grid.set_row_str(1, "abc"), - Err(SetValueSeriesError::InvalidLength { - expected: 2, - actual: 3 - }) - ); - assert_eq!(grid.set_row_str(1, "ab"), Ok(())); - assert_eq!(grid.get_row_str(1), Some(String::from("ab"))); - } - - #[test] - fn str_to_char_grid() { - // conversion with .to_string() covers one more line - let original = "Hello\r\nWorld!\n...\n".to_string(); - - let grid = CharGrid::from(original); - assert_eq!(3, grid.height()); - assert_eq!("Hello\0\nWorld!\n...\0\0\0", String::from(grid)); - } - - #[test] - fn round_trip_bytes() { - let grid = CharGrid::from("Hello\0\nWorld!\n...\0\0\0"); - let bytes: Vec = grid.clone().into(); - let copy = - CharGrid::load_utf8(grid.width(), grid.height(), bytes).unwrap(); - assert_eq!(grid, copy); - } - - #[test] - fn round_trip_string() { - let grid = CharGrid::from("Hello\0\nWorld!\n...\0\0\0"); - let str: String = grid.clone().into(); - let copy = CharGrid::from(str); - assert_eq!(grid, copy); - } - - #[test] - fn wrap_str() { - let grid = CharGrid::wrap_str(2, "abc\ndef"); - assert_eq!(4, grid.height()); - assert_eq!("ab\nc\0\nde\nf\0", String::from(grid)); - } -} diff --git a/crates/servicepoint/src/command.rs b/crates/servicepoint/src/command.rs deleted file mode 100644 index 4efda1f..0000000 --- a/crates/servicepoint/src/command.rs +++ /dev/null @@ -1,968 +0,0 @@ -use crate::command_code::CommandCode; -use crate::compression::into_decompressed; -use crate::*; - -/// Type alias for documenting the meaning of the u16 in enum values -pub type Offset = usize; - -/// A low-level display command. -/// -/// This struct and associated functions implement the UDP protocol for the display. -/// -/// To send a [Command], use a [connection][crate::Connection]. -/// -/// # Available commands -/// -/// To send text, take a look at [Command::Cp437Data]. -/// -/// To draw pixels, the easiest command to use is [Command::BitmapLinearWin]. -/// -/// The other BitmapLinear-Commands operate on a region of pixel memory directly. -/// [Command::BitmapLinear] overwrites a region. -/// [Command::BitmapLinearOr], [Command::BitmapLinearAnd] and [Command::BitmapLinearXor] apply logical operations per pixel. -/// -/// Out of bounds operations may be truncated or ignored by the display. -/// -/// # Compression -/// -/// Some commands can contain compressed payloads. -/// To get started, use [CompressionCode::Uncompressed]. -/// -/// If you want to archive the best performance (e.g. latency), -/// you can try the different compression algorithms for your hardware and use case. -/// -/// In memory, the payload is not compressed in the [Command]. -/// Payload (de-)compression happens when converting the [Command] into a [Packet] or vice versa. -/// -/// # Examples -/// -/// ```rust -/// use servicepoint::{Brightness, Command, Connection, Packet}; -/// # -/// // create command -/// let command = Command::Brightness(Brightness::MAX); -/// -/// // turn command into Packet -/// let packet: Packet = command.clone().into(); -/// -/// // read command from packet -/// let round_tripped = Command::try_from(packet).unwrap(); -/// -/// // round tripping produces exact copy -/// assert_eq!(command, round_tripped); -/// -/// // send command -/// # let connection = Connection::open("127.0.0.1:2342").unwrap(); -/// connection.send(command).unwrap(); -/// ``` -#[derive(Debug, Clone, PartialEq)] -pub enum Command { - /// Set all pixels to the off state. Does not affect brightness. - /// - /// # Examples - /// - /// ```rust - /// # use servicepoint::{Command, Connection}; - /// # let connection = Connection::open("127.0.0.1:2342").unwrap(); - /// connection.send(Command::Clear).unwrap(); - /// ``` - Clear, - - /// Show text on the screen. - /// - /// The text is sent in the form of a 2D grid of UTF-8 encoded characters (the default encoding in rust). - /// - /// # Examples - /// - /// ```rust - /// # use servicepoint::{Command, Connection, Origin, CharGrid}; - /// # let connection = Connection::Fake; - /// let grid = CharGrid::from("Hello,\nWorld!"); - /// connection.send(Command::Utf8Data(Origin::ZERO, grid)).expect("send failed"); - /// ``` - Utf8Data(Origin, CharGrid), - - /// Show text on the screen. - /// - /// The text is sent in the form of a 2D grid of [CP-437] encoded characters. - /// - ///
You probably want to use [Command::Utf8Data] instead
- /// - /// # Examples - /// - /// ```rust - /// # use servicepoint::{Command, Connection, Origin, CharGrid, Cp437Grid}; - /// # let connection = Connection::Fake; - /// let grid = CharGrid::from("Hello,\nWorld!"); - /// let grid = Cp437Grid::from(&grid); - /// connection.send(Command::Cp437Data(Origin::ZERO, grid)).expect("send failed"); - /// ``` - /// - /// ```rust - /// # use servicepoint::{Command, Connection, Cp437Grid, Origin}; - /// # let connection = Connection::Fake; - /// let grid = Cp437Grid::load_ascii("Hello\nWorld", 5, false).unwrap(); - /// connection.send(Command::Cp437Data(Origin::new(2, 2), grid)).unwrap(); - /// ``` - /// [CP-437]: https://en.wikipedia.org/wiki/Code_page_437 - Cp437Data(Origin, Cp437Grid), - - /// Overwrites a rectangular region of pixels. - /// - /// Origin coordinates must be divisible by 8. - /// - /// # Examples - /// - /// ```rust - /// # use servicepoint::{Command, CompressionCode, Grid, Bitmap}; - /// # let connection = servicepoint::Connection::Fake; - /// # - /// let mut pixels = Bitmap::max_sized(); - /// // draw something to the pixels here - /// # pixels.set(2, 5, true); - /// - /// // create command to send pixels - /// let command = Command::BitmapLinearWin( - /// servicepoint::Origin::ZERO, - /// pixels, - /// CompressionCode::Uncompressed - /// ); - /// - /// connection.send(command).expect("send failed"); - /// ``` - BitmapLinearWin(Origin, Bitmap, CompressionCode), - - /// Set the brightness of all tiles to the same value. - /// - /// # Examples - /// - /// ```rust - /// # use servicepoint::{Brightness, Command, Connection}; - /// # let connection = Connection::open("127.0.0.1:2342").unwrap(); - /// let command = Command::Brightness(Brightness::MAX); - /// connection.send(command).unwrap(); - /// ``` - Brightness(Brightness), - - /// Set the brightness of individual tiles in a rectangular area of the display. - CharBrightness(Origin, BrightnessGrid), - - /// Set pixel data starting at the pixel offset on screen. - /// - /// The screen will continuously overwrite more pixel data without regarding the offset, meaning - /// once the starting row is full, overwriting will continue on column 0. - /// - /// The contained [BitVec] is always uncompressed. - BitmapLinear(Offset, BitVec, CompressionCode), - - /// Set pixel data according to an and-mask starting at the offset. - /// - /// The screen will continuously overwrite more pixel data without regarding the offset, meaning - /// once the starting row is full, overwriting will continue on column 0. - /// - /// The contained [BitVec] is always uncompressed. - BitmapLinearAnd(Offset, BitVec, CompressionCode), - - /// Set pixel data according to an or-mask starting at the offset. - /// - /// The screen will continuously overwrite more pixel data without regarding the offset, meaning - /// once the starting row is full, overwriting will continue on column 0. - /// - /// The contained [BitVec] is always uncompressed. - BitmapLinearOr(Offset, BitVec, CompressionCode), - - /// Set pixel data according to a xor-mask starting at the offset. - /// - /// The screen will continuously overwrite more pixel data without regarding the offset, meaning - /// once the starting row is full, overwriting will continue on column 0. - /// - /// The contained [BitVec] is always uncompressed. - BitmapLinearXor(Offset, BitVec, CompressionCode), - - /// Kills the udp daemon on the display, which usually results in a restart. - /// - /// Please do not send this in your normal program flow. - /// - /// # Examples - /// - /// ```rust - /// # use servicepoint::{Command, Connection}; - /// # let connection = Connection::open("127.0.0.1:2342").unwrap(); - /// connection.send(Command::HardReset).unwrap(); - /// ``` - HardReset, - - ///
Untested
- /// - /// Slowly decrease brightness until off or something like that? - /// - /// # Examples - /// - /// ```rust - /// # use servicepoint::{Command, Connection}; - /// # let connection = Connection::open("127.0.0.1:2342").unwrap(); - /// connection.send(Command::FadeOut).unwrap(); - /// ``` - FadeOut, - - /// Legacy command code, gets ignored by the real display. - /// - /// Might be useful as a noop package. - /// - /// # Examples - /// - /// ```rust - /// # use servicepoint::{Command, Connection}; - /// # let connection = Connection::open("127.0.0.1:2342").unwrap(); - /// // this sends a packet that does nothing - /// # #[allow(deprecated)] - /// connection.send(Command::BitmapLegacy).unwrap(); - /// ``` - #[deprecated] - BitmapLegacy, -} - -/// Err values for [Command::try_from]. -#[derive(Debug, PartialEq, thiserror::Error)] -pub enum TryFromPacketError { - /// the contained command code does not correspond to a known command - #[error("The command code {0:?} does not correspond to a known command")] - InvalidCommand(u16), - /// the expected payload size was n, but size m was found - #[error("the expected payload size was {0}, but size {1} was found")] - UnexpectedPayloadSize(usize, usize), - /// Header fields not needed for the command have been used. - /// - /// Note that these commands would usually still work on the actual display. - #[error("Header fields not needed for the command have been used")] - ExtraneousHeaderValues, - /// The contained compression code is not known. This could be of disabled features. - #[error("The compression code {0:?} does not correspond to a known compression algorithm.")] - InvalidCompressionCode(u16), - /// Decompression of the payload failed. This can be caused by corrupted packets. - #[error("The decompression of the payload failed")] - DecompressionFailed, - /// The given brightness value is out of bounds - #[error("The given brightness value {0} is out of bounds.")] - InvalidBrightness(u8), - #[error(transparent)] - InvalidUtf8(#[from] std::string::FromUtf8Error), -} - -impl TryFrom for Command { - type Error = TryFromPacketError; - - /// Try to interpret the [Packet] as one containing a [Command] - fn try_from(packet: Packet) -> Result { - let Packet { - header: Header { - command_code, a, .. - }, - .. - } = packet; - let command_code = match CommandCode::try_from(command_code) { - Err(()) => { - return Err(TryFromPacketError::InvalidCommand(command_code)); - } - Ok(value) => value, - }; - - match command_code { - CommandCode::Clear => { - Self::packet_into_command_only(packet, Command::Clear) - } - CommandCode::Brightness => Self::packet_into_brightness(&packet), - CommandCode::HardReset => { - Self::packet_into_command_only(packet, Command::HardReset) - } - CommandCode::FadeOut => { - Self::packet_into_command_only(packet, Command::FadeOut) - } - CommandCode::Cp437Data => Self::packet_into_cp437(&packet), - CommandCode::CharBrightness => { - Self::packet_into_char_brightness(&packet) - } - CommandCode::Utf8Data => Self::packet_into_utf8(&packet), - #[allow(deprecated)] - CommandCode::BitmapLegacy => Ok(Command::BitmapLegacy), - CommandCode::BitmapLinear => { - let (vec, compression) = - Self::packet_into_linear_bitmap(packet)?; - Ok(Command::BitmapLinear(a as Offset, vec, compression)) - } - CommandCode::BitmapLinearAnd => { - let (vec, compression) = - Self::packet_into_linear_bitmap(packet)?; - Ok(Command::BitmapLinearAnd(a as Offset, vec, compression)) - } - CommandCode::BitmapLinearOr => { - let (vec, compression) = - Self::packet_into_linear_bitmap(packet)?; - Ok(Command::BitmapLinearOr(a as Offset, vec, compression)) - } - CommandCode::BitmapLinearXor => { - let (vec, compression) = - Self::packet_into_linear_bitmap(packet)?; - Ok(Command::BitmapLinearXor(a as Offset, vec, compression)) - } - CommandCode::BitmapLinearWinUncompressed => { - Self::packet_into_bitmap_win( - packet, - CompressionCode::Uncompressed, - ) - } - #[cfg(feature = "compression_zlib")] - CommandCode::BitmapLinearWinZlib => { - Self::packet_into_bitmap_win(packet, CompressionCode::Zlib) - } - #[cfg(feature = "compression_bzip2")] - CommandCode::BitmapLinearWinBzip2 => { - Self::packet_into_bitmap_win(packet, CompressionCode::Bzip2) - } - #[cfg(feature = "compression_lzma")] - CommandCode::BitmapLinearWinLzma => { - Self::packet_into_bitmap_win(packet, CompressionCode::Lzma) - } - #[cfg(feature = "compression_zstd")] - CommandCode::BitmapLinearWinZstd => { - Self::packet_into_bitmap_win(packet, CompressionCode::Zstd) - } - } - } -} - -impl Command { - fn packet_into_bitmap_win( - packet: Packet, - compression: CompressionCode, - ) -> Result { - let Packet { - header: - Header { - command_code: _, - a: tiles_x, - b: pixels_y, - c: tile_w, - d: pixel_h, - }, - payload, - } = packet; - - let payload = match into_decompressed(compression, payload) { - None => return Err(TryFromPacketError::DecompressionFailed), - Some(decompressed) => decompressed, - }; - - Ok(Command::BitmapLinearWin( - Origin::new(tiles_x as usize * TILE_SIZE, pixels_y as usize), - Bitmap::load( - tile_w as usize * TILE_SIZE, - pixel_h as usize, - &payload, - ), - compression, - )) - } - - /// Helper method for checking that a packet is empty and only contains a command code - fn packet_into_command_only( - packet: Packet, - command: Command, - ) -> Result { - let Packet { - header: - Header { - command_code: _, - a, - b, - c, - d, - }, - payload, - } = packet; - if !payload.is_empty() { - Err(TryFromPacketError::UnexpectedPayloadSize(0, payload.len())) - } else if a != 0 || b != 0 || c != 0 || d != 0 { - Err(TryFromPacketError::ExtraneousHeaderValues) - } else { - Ok(command) - } - } - - /// Helper method for Packets into `BitmapLinear*`-Commands - fn packet_into_linear_bitmap( - packet: Packet, - ) -> Result<(BitVec, CompressionCode), TryFromPacketError> { - let Packet { - header: - Header { - b: length, - c: sub, - d: reserved, - .. - }, - payload, - } = packet; - if reserved != 0 { - return Err(TryFromPacketError::ExtraneousHeaderValues); - } - let sub = match CompressionCode::try_from(sub) { - Err(()) => { - return Err(TryFromPacketError::InvalidCompressionCode(sub)); - } - Ok(value) => value, - }; - let payload = match into_decompressed(sub, payload) { - None => return Err(TryFromPacketError::DecompressionFailed), - Some(value) => value, - }; - if payload.len() != length as usize { - return Err(TryFromPacketError::UnexpectedPayloadSize( - length as usize, - payload.len(), - )); - } - Ok((BitVec::from_vec(payload), sub)) - } - - fn packet_into_char_brightness( - packet: &Packet, - ) -> Result { - let Packet { - header: - Header { - command_code: _, - a: x, - b: y, - c: width, - d: height, - }, - payload, - } = packet; - - let grid = ByteGrid::load(*width as usize, *height as usize, payload); - let grid = match BrightnessGrid::try_from(grid) { - Ok(grid) => grid, - Err(val) => return Err(TryFromPacketError::InvalidBrightness(val)), - }; - - Ok(Command::CharBrightness( - Origin::new(*x as usize, *y as usize), - grid, - )) - } - - fn packet_into_brightness( - packet: &Packet, - ) -> Result { - let Packet { - header: - Header { - command_code: _, - a, - b, - c, - d, - }, - payload, - } = packet; - if payload.len() != 1 { - return Err(TryFromPacketError::UnexpectedPayloadSize( - 1, - payload.len(), - )); - } - - if *a != 0 || *b != 0 || *c != 0 || *d != 0 { - return Err(TryFromPacketError::ExtraneousHeaderValues); - } - - match Brightness::try_from(payload[0]) { - Ok(b) => Ok(Command::Brightness(b)), - Err(_) => Err(TryFromPacketError::InvalidBrightness(payload[0])), - } - } - - fn packet_into_cp437( - packet: &Packet, - ) -> Result { - let Packet { - header: - Header { - command_code: _, - a, - b, - c, - d, - }, - payload, - } = packet; - Ok(Command::Cp437Data( - Origin::new(*a as usize, *b as usize), - Cp437Grid::load(*c as usize, *d as usize, payload), - )) - } - - fn packet_into_utf8( - packet: &Packet, - ) -> Result { - let Packet { - header: - Header { - command_code: _, - a, - b, - c, - d, - }, - payload, - } = packet; - let payload: Vec<_> = - String::from_utf8(payload.clone())?.chars().collect(); - Ok(Command::Utf8Data( - Origin::new(*a as usize, *b as usize), - CharGrid::load(*c as usize, *d as usize, &payload), - )) - } -} - -#[cfg(test)] -mod tests { - use crate::command::TryFromPacketError; - use crate::command_code::CommandCode; - use crate::{ - BitVec, Bitmap, Brightness, BrightnessGrid, CharGrid, Command, - CompressionCode, Cp437Grid, Header, Origin, Packet, Pixels, - }; - - fn round_trip(original: Command) { - let packet: Packet = original.clone().into(); - let copy: Command = match Command::try_from(packet) { - Ok(command) => command, - Err(err) => panic!("could not reload {original:?}: {err:?}"), - }; - assert_eq!(copy, original); - } - - fn all_compressions<'t>() -> &'t [CompressionCode] { - &[ - CompressionCode::Uncompressed, - #[cfg(feature = "compression_lzma")] - CompressionCode::Lzma, - #[cfg(feature = "compression_bzip2")] - CompressionCode::Bzip2, - #[cfg(feature = "compression_zlib")] - CompressionCode::Zlib, - #[cfg(feature = "compression_zstd")] - CompressionCode::Zstd, - ] - } - - #[test] - fn round_trip_clear() { - round_trip(Command::Clear); - } - - #[test] - fn round_trip_hard_reset() { - round_trip(Command::HardReset); - } - - #[test] - fn round_trip_fade_out() { - round_trip(Command::FadeOut); - } - - #[test] - fn round_trip_brightness() { - round_trip(Command::Brightness(Brightness::try_from(6).unwrap())); - } - - #[test] - #[allow(deprecated)] - fn round_trip_bitmap_legacy() { - round_trip(Command::BitmapLegacy); - } - - #[test] - fn round_trip_char_brightness() { - round_trip(Command::CharBrightness( - Origin::new(5, 2), - BrightnessGrid::new(7, 5), - )); - } - - #[test] - fn round_trip_cp437_data() { - round_trip(Command::Cp437Data(Origin::new(5, 2), Cp437Grid::new(7, 5))); - } - - #[test] - fn round_trip_utf8_data() { - round_trip(Command::Utf8Data(Origin::new(5, 2), CharGrid::new(7, 5))); - } - - #[test] - fn round_trip_bitmap_linear() { - for compression in all_compressions().iter().copied() { - round_trip(Command::BitmapLinear( - 23, - BitVec::repeat(false, 40), - compression, - )); - round_trip(Command::BitmapLinearAnd( - 23, - BitVec::repeat(false, 40), - compression, - )); - round_trip(Command::BitmapLinearOr( - 23, - BitVec::repeat(false, 40), - compression, - )); - round_trip(Command::BitmapLinearXor( - 23, - BitVec::repeat(false, 40), - compression, - )); - round_trip(Command::BitmapLinearWin( - Origin::ZERO, - Bitmap::max_sized(), - compression, - )); - } - } - - #[test] - fn error_invalid_command() { - let p = Packet { - header: Header { - command_code: 0xFF, - a: 0x00, - b: 0x00, - c: 0x00, - d: 0x00, - }, - payload: vec![], - }; - let result = Command::try_from(p); - assert!(matches!( - result, - Err(TryFromPacketError::InvalidCommand(0xFF)) - )) - } - - #[test] - fn error_extraneous_header_values_clear() { - let p = Packet { - header: Header { - command_code: CommandCode::Clear.into(), - a: 0x05, - b: 0x00, - c: 0x00, - d: 0x00, - }, - payload: vec![], - }; - let result = Command::try_from(p); - assert!(matches!( - result, - Err(TryFromPacketError::ExtraneousHeaderValues) - )) - } - - #[test] - fn error_extraneous_header_values_brightness() { - let p = Packet { - header: Header { - command_code: CommandCode::Brightness.into(), - a: 0x00, - b: 0x13, - c: 0x37, - d: 0x00, - }, - payload: vec![5], - }; - let result = Command::try_from(p); - assert!(matches!( - result, - Err(TryFromPacketError::ExtraneousHeaderValues) - )) - } - - #[test] - fn error_extraneous_header_hard_reset() { - let p = Packet { - header: Header { - command_code: CommandCode::HardReset.into(), - a: 0x00, - b: 0x00, - c: 0x00, - d: 0x01, - }, - payload: vec![], - }; - let result = Command::try_from(p); - assert!(matches!( - result, - Err(TryFromPacketError::ExtraneousHeaderValues) - )) - } - - #[test] - fn error_extraneous_header_fade_out() { - let p = Packet { - header: Header { - command_code: CommandCode::FadeOut.into(), - a: 0x10, - b: 0x00, - c: 0x00, - d: 0x01, - }, - payload: vec![], - }; - let result = Command::try_from(p); - assert!(matches!( - result, - Err(TryFromPacketError::ExtraneousHeaderValues) - )) - } - - #[test] - fn error_unexpected_payload() { - let p = Packet { - header: Header { - command_code: CommandCode::FadeOut.into(), - a: 0x00, - b: 0x00, - c: 0x00, - d: 0x00, - }, - payload: vec![5, 7], - }; - let result = Command::try_from(p); - assert!(matches!( - result, - Err(TryFromPacketError::UnexpectedPayloadSize(0, 2)) - )) - } - - #[test] - fn error_decompression_failed_win() { - for compression in all_compressions().iter().copied() { - let p: Packet = Command::BitmapLinearWin( - Origin::new(16, 8), - Bitmap::new(8, 8), - compression, - ) - .into(); - - let Packet { - header, - mut payload, - } = p; - - // mangle it - for byte in payload.iter_mut() { - *byte -= *byte / 2; - } - - let p = Packet { header, payload }; - let result = Command::try_from(p); - if compression != CompressionCode::Uncompressed { - assert_eq!(result, Err(TryFromPacketError::DecompressionFailed)) - } else { - assert!(result.is_ok()); - } - } - } - - #[test] - fn error_decompression_failed_and() { - for compression in all_compressions().iter().copied() { - let p: Packet = Command::BitmapLinearAnd( - 0, - BitVec::repeat(false, 8), - compression, - ) - .into(); - let Packet { - header, - mut payload, - } = p; - - // mangle it - for byte in payload.iter_mut() { - *byte -= *byte / 2; - } - - let p = Packet { header, payload }; - let result = Command::try_from(p); - if compression != CompressionCode::Uncompressed { - assert_eq!(result, Err(TryFromPacketError::DecompressionFailed)) - } else { - // when not compressing, there is no way to detect corrupted data - assert!(result.is_ok()); - } - } - } - - #[test] - fn unexpected_payload_size_brightness() { - assert_eq!( - Command::try_from(Packet { - header: Header { - command_code: CommandCode::Brightness.into(), - a: 0, - b: 0, - c: 0, - d: 0, - }, - payload: vec!() - }), - Err(TryFromPacketError::UnexpectedPayloadSize(1, 0)) - ); - - assert_eq!( - Command::try_from(Packet { - header: Header { - command_code: CommandCode::Brightness.into(), - a: 0, - b: 0, - c: 0, - d: 0, - }, - payload: vec!(0, 0) - }), - Err(TryFromPacketError::UnexpectedPayloadSize(1, 2)) - ); - } - - #[test] - fn error_reserved_used() { - let Packet { header, payload } = Command::BitmapLinear( - 0, - BitVec::repeat(false, 8), - CompressionCode::Uncompressed, - ) - .into(); - let Header { - command_code: command, - a: offset, - b: length, - c: sub, - d: _reserved, - } = header; - let p = Packet { - header: Header { - command_code: command, - a: offset, - b: length, - c: sub, - d: 69, - }, - payload, - }; - assert_eq!( - Command::try_from(p), - Err(TryFromPacketError::ExtraneousHeaderValues) - ); - } - - #[test] - fn error_invalid_compression() { - let Packet { header, payload } = Command::BitmapLinear( - 0, - BitVec::repeat(false, 8), - CompressionCode::Uncompressed, - ) - .into(); - let Header { - command_code: command, - a: offset, - b: length, - c: _sub, - d: reserved, - } = header; - let p = Packet { - header: Header { - command_code: command, - a: offset, - b: length, - c: 42, - d: reserved, - }, - payload, - }; - assert_eq!( - Command::try_from(p), - Err(TryFromPacketError::InvalidCompressionCode(42)) - ); - } - - #[test] - fn error_unexpected_size() { - let Packet { header, payload } = Command::BitmapLinear( - 0, - BitVec::repeat(false, 8), - CompressionCode::Uncompressed, - ) - .into(); - let Header { - command_code: command, - a: offset, - b: length, - c: compression, - d: reserved, - } = header; - let p = Packet { - header: Header { - command_code: command, - a: offset, - b: 420, - c: compression, - d: reserved, - }, - payload, - }; - assert_eq!( - Command::try_from(p), - Err(TryFromPacketError::UnexpectedPayloadSize( - 420, - length as usize, - )) - ); - } - - #[test] - fn origin_add() { - assert_eq!( - Origin::::new(4, 2), - Origin::new(1, 0) + Origin::new(3, 2) - ); - } - - #[test] - fn packet_into_char_brightness_invalid() { - let grid = BrightnessGrid::new(2, 2); - let command = Command::CharBrightness(Origin::ZERO, grid); - let mut packet: Packet = command.into(); - let slot = packet.payload.get_mut(1).unwrap(); - *slot = 23; - assert_eq!( - Command::try_from(packet), - Err(TryFromPacketError::InvalidBrightness(23)) - ); - } - - #[test] - fn packet_into_brightness_invalid() { - let mut packet: Packet = Command::Brightness(Brightness::MAX).into(); - let slot = packet.payload.get_mut(0).unwrap(); - *slot = 42; - assert_eq!( - Command::try_from(packet), - Err(TryFromPacketError::InvalidBrightness(42)) - ); - } -} diff --git a/crates/servicepoint/src/command_code.rs b/crates/servicepoint/src/command_code.rs deleted file mode 100644 index a105522..0000000 --- a/crates/servicepoint/src/command_code.rs +++ /dev/null @@ -1,214 +0,0 @@ -/// The u16 command codes used for the [Command]s. -#[repr(u16)] -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub(crate) enum CommandCode { - Clear = 0x0002, - Cp437Data = 0x0003, - CharBrightness = 0x0005, - Brightness = 0x0007, - HardReset = 0x000b, - FadeOut = 0x000d, - #[deprecated] - BitmapLegacy = 0x0010, - BitmapLinear = 0x0012, - BitmapLinearWinUncompressed = 0x0013, - BitmapLinearAnd = 0x0014, - BitmapLinearOr = 0x0015, - BitmapLinearXor = 0x0016, - #[cfg(feature = "compression_zlib")] - BitmapLinearWinZlib = 0x0017, - #[cfg(feature = "compression_bzip2")] - BitmapLinearWinBzip2 = 0x0018, - #[cfg(feature = "compression_lzma")] - BitmapLinearWinLzma = 0x0019, - Utf8Data = 0x0020, - #[cfg(feature = "compression_zstd")] - BitmapLinearWinZstd = 0x001A, -} - -impl From for u16 { - /// returns the u16 command code corresponding to the enum value - fn from(value: CommandCode) -> Self { - value as u16 - } -} - -impl TryFrom for CommandCode { - type Error = (); - - /// Returns the enum value for the specified `u16` or `Error` if the code is unknown. - fn try_from(value: u16) -> Result { - match value { - value if value == CommandCode::Clear as u16 => { - Ok(CommandCode::Clear) - } - value if value == CommandCode::Cp437Data as u16 => { - Ok(CommandCode::Cp437Data) - } - value if value == CommandCode::CharBrightness as u16 => { - Ok(CommandCode::CharBrightness) - } - value if value == CommandCode::Brightness as u16 => { - Ok(CommandCode::Brightness) - } - value if value == CommandCode::HardReset as u16 => { - Ok(CommandCode::HardReset) - } - value if value == CommandCode::FadeOut as u16 => { - Ok(CommandCode::FadeOut) - } - #[allow(deprecated)] - value if value == CommandCode::BitmapLegacy as u16 => { - Ok(CommandCode::BitmapLegacy) - } - value if value == CommandCode::BitmapLinear as u16 => { - Ok(CommandCode::BitmapLinear) - } - value - if value == CommandCode::BitmapLinearWinUncompressed as u16 => - { - Ok(CommandCode::BitmapLinearWinUncompressed) - } - value if value == CommandCode::BitmapLinearAnd as u16 => { - Ok(CommandCode::BitmapLinearAnd) - } - value if value == CommandCode::BitmapLinearOr as u16 => { - Ok(CommandCode::BitmapLinearOr) - } - value if value == CommandCode::BitmapLinearXor as u16 => { - Ok(CommandCode::BitmapLinearXor) - } - #[cfg(feature = "compression_zstd")] - value if value == CommandCode::BitmapLinearWinZstd as u16 => { - Ok(CommandCode::BitmapLinearWinZstd) - } - #[cfg(feature = "compression_lzma")] - value if value == CommandCode::BitmapLinearWinLzma as u16 => { - Ok(CommandCode::BitmapLinearWinLzma) - } - #[cfg(feature = "compression_zlib")] - value if value == CommandCode::BitmapLinearWinZlib as u16 => { - Ok(CommandCode::BitmapLinearWinZlib) - } - #[cfg(feature = "compression_bzip2")] - value if value == CommandCode::BitmapLinearWinBzip2 as u16 => { - Ok(CommandCode::BitmapLinearWinBzip2) - } - value if value == CommandCode::Utf8Data as u16 => { - Ok(CommandCode::Utf8Data) - } - _ => Err(()), - } - } -} - -#[cfg(test)] -mod tests { - use super::*; - #[test] - fn clear() { - assert_eq!(CommandCode::try_from(0x0002), Ok(CommandCode::Clear)); - assert_eq!(u16::from(CommandCode::Clear), 0x0002); - } - - #[test] - fn cp437_data() { - assert_eq!(CommandCode::try_from(0x0003), Ok(CommandCode::Cp437Data)); - assert_eq!(u16::from(CommandCode::Cp437Data), 0x0003); - } - - #[test] - fn char_brightness() { - assert_eq!(CommandCode::try_from(0x0005), Ok(CommandCode::CharBrightness)); - assert_eq!(u16::from(CommandCode::CharBrightness), 0x0005); - } - - #[test] - fn brightness() { - assert_eq!(CommandCode::try_from(0x0007), Ok(CommandCode::Brightness)); - assert_eq!(u16::from(CommandCode::Brightness), 0x0007); - } - - #[test] - fn hard_reset() { - assert_eq!(CommandCode::try_from(0x000b), Ok(CommandCode::HardReset)); - assert_eq!(u16::from(CommandCode::HardReset), 0x000b); - } - - #[test] - fn fade_out() { - assert_eq!(CommandCode::try_from(0x000d), Ok(CommandCode::FadeOut)); - assert_eq!(u16::from(CommandCode::FadeOut), 0x000d); - } - - #[test] - #[allow(deprecated)] - fn bitmap_legacy() { - assert_eq!(CommandCode::try_from(0x0010), Ok(CommandCode::BitmapLegacy)); - assert_eq!(u16::from(CommandCode::BitmapLegacy), 0x0010); - } - - #[test] - fn linear() { - assert_eq!(CommandCode::try_from(0x0012), Ok(CommandCode::BitmapLinear)); - assert_eq!(u16::from(CommandCode::BitmapLinear), 0x0012); - } - - #[test] - fn linear_and() { - assert_eq!(CommandCode::try_from(0x0014), Ok(CommandCode::BitmapLinearAnd)); - assert_eq!(u16::from(CommandCode::BitmapLinearAnd), 0x0014); - } - - #[test] - fn linear_xor() { - assert_eq!(CommandCode::try_from(0x0016), Ok(CommandCode::BitmapLinearXor)); - assert_eq!(u16::from(CommandCode::BitmapLinearXor), 0x0016); - } - - #[test] - #[cfg(feature = "compression_zlib")] - fn bitmap_win_zlib() { - assert_eq!(CommandCode::try_from(0x0017), Ok(CommandCode::BitmapLinearWinZlib)); - assert_eq!(u16::from(CommandCode::BitmapLinearWinZlib), 0x0017); - } - - #[test] - #[cfg(feature = "compression_bzip2")] - fn bitmap_win_bzip2() { - assert_eq!(CommandCode::try_from(0x0018), Ok(CommandCode::BitmapLinearWinBzip2)); - assert_eq!(u16::from(CommandCode::BitmapLinearWinBzip2), 0x0018); - } - - #[test] - #[cfg(feature = "compression_lzma")] - fn bitmap_win_lzma() { - assert_eq!(CommandCode::try_from(0x0019), Ok(CommandCode::BitmapLinearWinLzma)); - assert_eq!(u16::from(CommandCode::BitmapLinearWinLzma), 0x0019); - } - - #[test] - #[cfg(feature = "compression_zstd")] - fn bitmap_win_zstd() { - assert_eq!(CommandCode::try_from(0x001A), Ok(CommandCode::BitmapLinearWinZstd)); - assert_eq!(u16::from(CommandCode::BitmapLinearWinZstd), 0x001A); - } - - #[test] - fn bitmap_win_uncompressed() { - assert_eq!(CommandCode::try_from(0x0013), Ok(CommandCode::BitmapLinearWinUncompressed)); - assert_eq!(u16::from(CommandCode::BitmapLinearWinUncompressed), 0x0013); - } - - #[test] - fn utf8_data() { - assert_eq!(CommandCode::try_from(0x0020), Ok(CommandCode::Utf8Data)); - assert_eq!(u16::from(CommandCode::Utf8Data), 0x0020); - } - - #[test] - fn linear_or() { - assert_eq!(CommandCode::try_from(0x0015), Ok(CommandCode::BitmapLinearOr)); - assert_eq!(u16::from(CommandCode::BitmapLinearOr), 0x0015); - } -} \ No newline at end of file diff --git a/crates/servicepoint/src/compression.rs b/crates/servicepoint/src/compression.rs deleted file mode 100644 index 2e78073..0000000 --- a/crates/servicepoint/src/compression.rs +++ /dev/null @@ -1,115 +0,0 @@ -#[allow(unused)] -use std::io::{Read, Write}; - -#[cfg(feature = "compression_bzip2")] -use bzip2::read::{BzDecoder, BzEncoder}; -#[cfg(feature = "compression_zlib")] -use flate2::{FlushCompress, FlushDecompress, Status}; -#[cfg(feature = "compression_zstd")] -use zstd::{Decoder as ZstdDecoder, Encoder as ZstdEncoder}; - -use crate::{CompressionCode, Payload}; - -pub(crate) fn into_decompressed( - kind: CompressionCode, - payload: Payload, -) -> Option { - match kind { - CompressionCode::Uncompressed => Some(payload), - #[cfg(feature = "compression_zlib")] - CompressionCode::Zlib => { - let mut decompress = flate2::Decompress::new(true); - let mut buffer = [0u8; 10000]; - - let status = match decompress.decompress( - &payload, - &mut buffer, - FlushDecompress::Finish, - ) { - Err(_) => return None, - Ok(status) => status, - }; - - match status { - Status::Ok => None, - Status::BufError => None, - Status::StreamEnd => Some( - buffer[0..(decompress.total_out() as usize)].to_owned(), - ), - } - } - #[cfg(feature = "compression_bzip2")] - CompressionCode::Bzip2 => { - let mut decoder = BzDecoder::new(&*payload); - let mut decompressed = vec![]; - match decoder.read_to_end(&mut decompressed) { - Err(_) => None, - Ok(_) => Some(decompressed), - } - } - #[cfg(feature = "compression_lzma")] - CompressionCode::Lzma => match lzma::decompress(&payload) { - Err(_) => None, - Ok(decompressed) => Some(decompressed), - }, - #[cfg(feature = "compression_zstd")] - CompressionCode::Zstd => { - let mut decoder = match ZstdDecoder::new(&*payload) { - Err(_) => return None, - Ok(value) => value, - }; - let mut decompressed = vec![]; - match decoder.read_to_end(&mut decompressed) { - Err(_) => None, - Ok(_) => Some(decompressed), - } - } - } -} - -pub(crate) fn into_compressed( - kind: CompressionCode, - payload: Payload, -) -> Payload { - match kind { - CompressionCode::Uncompressed => payload, - #[cfg(feature = "compression_zlib")] - CompressionCode::Zlib => { - let mut compress = - flate2::Compress::new(flate2::Compression::fast(), true); - let mut buffer = [0u8; 10000]; - - match compress - .compress(&payload, &mut buffer, FlushCompress::Finish) - .expect("compress failed") - { - Status::Ok => panic!("buffer should be big enough"), - Status::BufError => panic!("BufError"), - Status::StreamEnd => {} - }; - buffer[..compress.total_out() as usize].to_owned() - } - #[cfg(feature = "compression_bzip2")] - CompressionCode::Bzip2 => { - let mut encoder = - BzEncoder::new(&*payload, bzip2::Compression::fast()); - let mut compressed = vec![]; - match encoder.read_to_end(&mut compressed) { - Err(err) => panic!("could not compress payload: {}", err), - Ok(_) => compressed, - } - } - #[cfg(feature = "compression_lzma")] - CompressionCode::Lzma => lzma::compress(&payload, 6).unwrap(), - #[cfg(feature = "compression_zstd")] - CompressionCode::Zstd => { - let mut encoder = - ZstdEncoder::new(vec![], zstd::DEFAULT_COMPRESSION_LEVEL) - .expect("could not create encoder"); - encoder - .write_all(&payload) - .expect("could not compress payload"); - encoder.finish().expect("could not finish encoding") - } - } -} diff --git a/crates/servicepoint/src/compression_code.rs b/crates/servicepoint/src/compression_code.rs deleted file mode 100644 index db25221..0000000 --- a/crates/servicepoint/src/compression_code.rs +++ /dev/null @@ -1,120 +0,0 @@ -/// Specifies the kind of compression to use. Availability depends on features. -/// -/// # Examples -/// -/// ```rust -/// # use servicepoint::{Command, CompressionCode, Origin, Bitmap}; -/// // create command without payload compression -/// # let pixels = Bitmap::max_sized(); -/// _ = Command::BitmapLinearWin(Origin::ZERO, pixels, CompressionCode::Uncompressed); -/// -/// // create command with payload compressed with lzma and appropriate header flags -/// # let pixels = Bitmap::max_sized(); -/// _ = Command::BitmapLinearWin(Origin::ZERO, pixels, CompressionCode::Lzma); -/// ``` -#[repr(u16)] -#[derive(Debug, Clone, Copy, PartialEq)] -pub enum CompressionCode { - /// no compression - Uncompressed = 0x0, - #[cfg(feature = "compression_zlib")] - /// compress using flate2 with zlib header - Zlib = 0x677a, - #[cfg(feature = "compression_bzip2")] - /// compress using bzip2 - Bzip2 = 0x627a, - #[cfg(feature = "compression_lzma")] - /// compress using lzma - Lzma = 0x6c7a, - #[cfg(feature = "compression_zstd")] - /// compress using Zstandard - Zstd = 0x7a73, -} - -impl From for u16 { - fn from(value: CompressionCode) -> Self { - value as u16 - } -} - -impl TryFrom for CompressionCode { - type Error = (); - - fn try_from(value: u16) -> Result { - match value { - value if value == CompressionCode::Uncompressed as u16 => { - Ok(CompressionCode::Uncompressed) - } - #[cfg(feature = "compression_zlib")] - value if value == CompressionCode::Zlib as u16 => { - Ok(CompressionCode::Zlib) - } - #[cfg(feature = "compression_bzip2")] - value if value == CompressionCode::Bzip2 as u16 => { - Ok(CompressionCode::Bzip2) - } - #[cfg(feature = "compression_lzma")] - value if value == CompressionCode::Lzma as u16 => { - Ok(CompressionCode::Lzma) - } - #[cfg(feature = "compression_zstd")] - value if value == CompressionCode::Zstd as u16 => { - Ok(CompressionCode::Zstd) - } - _ => Err(()), - } - } -} - -#[cfg(test)] -mod test { - use super::*; - #[test] - fn uncompressed() { - assert_eq!( - CompressionCode::try_from(0x0000), - Ok(CompressionCode::Uncompressed) - ); - assert_eq!(u16::from(CompressionCode::Uncompressed), 0x0000); - } - - #[test] - #[cfg(feature = "compression_zlib")] - fn zlib() { - assert_eq!( - CompressionCode::try_from(0x677a), - Ok(CompressionCode::Zlib) - ); - assert_eq!(u16::from(CompressionCode::Zlib), 0x677a); - } - - #[test] - #[cfg(feature = "compression_bzip2")] - fn bzip2() { - assert_eq!( - CompressionCode::try_from(0x627a), - Ok(CompressionCode::Bzip2) - ); - assert_eq!(u16::from(CompressionCode::Bzip2), 0x627a); - } - - #[test] - #[cfg(feature = "compression_lzma")] - fn lzma() { - assert_eq!( - CompressionCode::try_from(0x6c7a), - Ok(CompressionCode::Lzma) - ); - assert_eq!(u16::from(CompressionCode::Lzma), 0x6c7a); - } - - #[test] - #[cfg(feature = "compression_zstd")] - fn zstd() { - assert_eq!( - CompressionCode::try_from(0x7a73), - Ok(CompressionCode::Zstd) - ); - assert_eq!(u16::from(CompressionCode::Zstd), 0x7a73); - } -} diff --git a/crates/servicepoint/src/connection.rs b/crates/servicepoint/src/connection.rs deleted file mode 100644 index 417fd1d..0000000 --- a/crates/servicepoint/src/connection.rs +++ /dev/null @@ -1,175 +0,0 @@ -use crate::packet::Packet; -use std::fmt::Debug; - -/// A connection to the display. -/// -/// Used to send [Packets][Packet] or [Commands][crate::Command]. -/// -/// # Examples -/// ```rust -/// let connection = servicepoint::Connection::open("127.0.0.1:2342") -/// .expect("connection failed"); -/// connection.send(servicepoint::Command::Clear) -/// .expect("send failed"); -/// ``` -#[derive(Debug)] -pub enum Connection { - /// A connection using the UDP protocol. - /// - /// Use this when sending commands directly to the display. - /// - /// Requires the feature "protocol_udp" which is enabled by default. - #[cfg(feature = "protocol_udp")] - Udp(std::net::UdpSocket), - - /// A connection using the WebSocket protocol. - /// - /// Note that you will need to forward the WebSocket messages via UDP to the display. - /// You can use [servicepoint-websocket-relay] for this. - /// - /// To create a new WebSocket automatically, use [Connection::open_websocket]. - /// - /// Requires the feature "protocol_websocket" which is disabled by default. - /// - /// [servicepoint-websocket-relay]: https://github.com/kaesaecracker/servicepoint-websocket-relay - #[cfg(feature = "protocol_websocket")] - WebSocket( - std::sync::Mutex< - tungstenite::WebSocket< - tungstenite::stream::MaybeTlsStream, - >, - >, - ), - - /// A fake connection for testing that does not actually send anything. - Fake, -} - -#[derive(Debug, thiserror::Error)] -pub enum SendError { - #[error("IO error occurred while sending")] - IoError(#[from] std::io::Error), - #[cfg(feature = "protocol_websocket")] - #[error("WebSocket error occurred while sending")] - WebsocketError(#[from] tungstenite::Error), -} - -impl Connection { - /// Open a new UDP socket and connect to the provided host. - /// - /// Note that this is UDP, which means that the open call can succeed even if the display is unreachable. - /// - /// The address of the display in CCCB is `172.23.42.29:2342`. - /// - /// # Errors - /// - /// Any errors resulting from binding the udp socket. - /// - /// # Examples - /// ```rust - /// let connection = servicepoint::Connection::open("127.0.0.1:2342") - /// .expect("connection failed"); - /// ``` - #[cfg(feature = "protocol_udp")] - pub fn open( - addr: impl std::net::ToSocketAddrs + Debug, - ) -> std::io::Result { - log::info!("connecting to {addr:?}"); - let socket = std::net::UdpSocket::bind("0.0.0.0:0")?; - socket.connect(addr)?; - Ok(Self::Udp(socket)) - } - - /// Open a new WebSocket and connect to the provided host. - /// - /// Requires the feature "protocol_websocket" which is disabled by default. - /// - /// # Examples - /// - /// ```no_run - /// use tungstenite::http::Uri; - /// use servicepoint::{Command, Connection}; - /// let uri = "ws://localhost:8080".parse().unwrap(); - /// let mut connection = Connection::open_websocket(uri) - /// .expect("could not connect"); - /// connection.send(Command::Clear) - /// .expect("send failed"); - /// ``` - #[cfg(feature = "protocol_websocket")] - pub fn open_websocket( - uri: tungstenite::http::Uri, - ) -> tungstenite::Result { - use tungstenite::{ - client::IntoClientRequest, connect, ClientRequestBuilder, - }; - - log::info!("connecting to {uri:?}"); - - let request = ClientRequestBuilder::new(uri).into_client_request()?; - let (sock, _) = connect(request)?; - Ok(Self::WebSocket(std::sync::Mutex::new(sock))) - } - - /// Send something packet-like to the display. Usually this is in the form of a Command. - /// - /// # Arguments - /// - /// - `packet`: the packet-like to send - /// - /// returns: true if packet was sent, otherwise false - /// - /// # Examples - /// - /// ```rust - /// let connection = servicepoint::Connection::Fake; - /// // turn off all pixels on display - /// connection.send(servicepoint::Command::Clear) - /// .expect("send failed"); - /// ``` - pub fn send(&self, packet: impl Into) -> Result<(), SendError> { - let packet = packet.into(); - log::debug!("sending {packet:?}"); - let data: Vec = packet.into(); - match self { - #[cfg(feature = "protocol_udp")] - Connection::Udp(socket) => { - socket - .send(&data) - .map_err(SendError::IoError) - .map(move |_| ()) // ignore Ok value - } - #[cfg(feature = "protocol_websocket")] - Connection::WebSocket(socket) => { - let mut socket = socket.lock().unwrap(); - socket - .send(tungstenite::Message::Binary(data.into())) - .map_err(SendError::WebsocketError) - } - Connection::Fake => { - let _ = data; - Ok(()) - } - } - } -} - -impl Drop for Connection { - fn drop(&mut self) { - #[cfg(feature = "protocol_websocket")] - if let Connection::WebSocket(sock) = self { - _ = sock.try_lock().map(move |mut sock| sock.close(None)); - } - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn send_fake() { - let data: &[u8] = &[0u8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; - let packet = Packet::try_from(data).unwrap(); - Connection::Fake.send(packet).unwrap() - } -} diff --git a/crates/servicepoint/src/constants.rs b/crates/servicepoint/src/constants.rs deleted file mode 100644 index 95c8684..0000000 --- a/crates/servicepoint/src/constants.rs +++ /dev/null @@ -1,75 +0,0 @@ -use std::time::Duration; - -/// size of a single tile in one dimension -pub const TILE_SIZE: usize = 8; - -/// Display tile count in the x-direction -/// -/// # Examples -/// -/// ```rust -/// # use servicepoint::{Cp437Grid, TILE_HEIGHT, TILE_WIDTH}; -/// let grid = Cp437Grid::new(TILE_WIDTH, TILE_HEIGHT); -/// ``` -pub const TILE_WIDTH: usize = 56; - -/// Display tile count in the y-direction -/// -/// # Examples -/// -/// ```rust -/// # use servicepoint::{Cp437Grid, TILE_HEIGHT, TILE_WIDTH}; -/// let grid = Cp437Grid::new(TILE_WIDTH, TILE_HEIGHT); -/// ``` -pub const TILE_HEIGHT: usize = 20; - -/// Display width in pixels -/// -/// # Examples -/// -/// ```rust -/// # use servicepoint::{PIXEL_HEIGHT, PIXEL_WIDTH, Bitmap}; -/// let grid = Bitmap::new(PIXEL_WIDTH, PIXEL_HEIGHT); -/// ``` -pub const PIXEL_WIDTH: usize = TILE_WIDTH * TILE_SIZE; - -/// Display height in pixels -/// -/// # Examples -/// -/// ```rust -/// # use servicepoint::{PIXEL_HEIGHT, PIXEL_WIDTH, Bitmap}; -/// let grid = Bitmap::new(PIXEL_WIDTH, PIXEL_HEIGHT); -/// ``` -pub const PIXEL_HEIGHT: usize = TILE_HEIGHT * TILE_SIZE; - -/// pixel count on whole screen -pub const PIXEL_COUNT: usize = PIXEL_WIDTH * PIXEL_HEIGHT; - -/// Actual hardware limit is around 28-29ms/frame. Rounded up for less dropped packets. -/// -/// # Examples -/// -/// ```rust -/// # use std::time::Instant; -/// # use servicepoint::{Command, CompressionCode, FRAME_PACING, Origin, Bitmap}; -/// # let connection = servicepoint::Connection::Fake; -/// # let pixels = Bitmap::max_sized(); -/// loop { -/// let start = Instant::now(); -/// -/// // Change pixels here -/// -/// connection.send(Command::BitmapLinearWin( -/// Origin::new(0,0), -/// pixels, -/// CompressionCode::Lzma -/// )) -/// .expect("send failed"); -/// -/// // warning: will crash if resulting duration is negative, e.g. when resuming from standby -/// std::thread::sleep(FRAME_PACING - start.elapsed()); -/// # break; // prevent doctest from hanging -/// } -/// ``` -pub const FRAME_PACING: Duration = Duration::from_millis(30); diff --git a/crates/servicepoint/src/cp437.rs b/crates/servicepoint/src/cp437.rs deleted file mode 100644 index cb9b945..0000000 --- a/crates/servicepoint/src/cp437.rs +++ /dev/null @@ -1,115 +0,0 @@ -use std::collections::HashMap; - -/// Contains functions to convert between UTF-8 and Codepage 437. -/// -/// See -pub struct Cp437Converter; - -/// An array of 256 elements, mapping most of the CP437 values to UTF-8 characters -/// -/// Mostly follows CP437, except 0x0A, which is kept for use as line ending. -/// -/// See -/// -/// Mostly copied from . License: GPL-3.0 -#[rustfmt::skip] -const CP437_TO_UTF8: [char; 256] = [ - /* 0X */ '\0', '☺', '☻', '♥', '♦', '♣', '♠', '•', '◘', '○', '\n', '♂', '♀', '♪', '♫', '☼', - /* 1X */ '►', '◄', '↕', '‼', '¶', '§', '▬', '↨', '↑', '↓', '→', '←', '∟', '↔', '▲', '▼', - /* 2X */ ' ', '!', '"', '#', '$', '%', '&', '\'','(', ')', '*', '+', ',', '-', '.', '/', - /* 3X */ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ':', ';', '<', '=', '>', '?', - /* 4X */ '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', - /* 5X */ 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '[', '\\',']', '^', '_', - /* 6X */ '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', - /* 7X */ 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '{', '|', '}', '~', '⌂', - /* 8X */ 'Ç', 'ü', 'é', 'â', 'ä', 'à', 'å', 'ç', 'ê', 'ë', 'è', 'ï', 'î', 'ì', 'Ä', 'Å', - /* 9X */ 'É', 'æ', 'Æ', 'ô', 'ö', 'ò', 'û', 'ù', 'ÿ', 'Ö', 'Ü', '¢', '£', '¥', '₧', 'ƒ', - /* AX */ 'á', 'í', 'ó', 'ú', 'ñ', 'Ñ', 'ª', 'º', '¿', '⌐', '¬', '½', '¼', '¡', '«', '»', - /* BX */ '░', '▒', '▓', '│', '┤', '╡', '╢', '╖', '╕', '╣', '║', '╗', '╝', '╜', '╛', '┐', - /* CX */ '└', '┴', '┬', '├', '─', '┼', '╞', '╟', '╚', '╔', '╩', '╦', '╠', '═', '╬', '╧', - /* DX */ '╨', '╤', '╥', '╙', '╘', '╒', '╓', '╫', '╪', '┘', '┌', '█', '▄', '▌', '▐', '▀', - /* EX */ 'α', 'ß', 'Γ', 'π', 'Σ', 'σ', 'µ', 'τ', 'Φ', 'Θ', 'Ω', 'δ', '∞', 'φ', 'ε', '∩', - /* FX */ '≡', '±', '≥', '≤', '⌠', '⌡', '÷', '≈', '°', '∙', '·', '√', 'ⁿ', '²', '■', ' ', -]; -static UTF8_TO_CP437: once_cell::sync::Lazy> = - once_cell::sync::Lazy::new(|| { - let pairs = CP437_TO_UTF8 - .iter() - .enumerate() - .map(move |(index, char)| (*char, index as u8)); - HashMap::from_iter(pairs) - }); - -impl Cp437Converter { - const MISSING_CHAR_CP437: u8 = 0x3F; // '?' - - /// Convert the provided bytes to UTF-8. - pub fn cp437_to_str(cp437: &[u8]) -> String { - cp437 - .iter() - .map(move |char| Self::cp437_to_char(*char)) - .collect() - } - - /// Convert a single CP-437 character to UTF-8. - pub fn cp437_to_char(cp437: u8) -> char { - CP437_TO_UTF8[cp437 as usize] - } - - /// Convert the provided text to CP-437 bytes. - /// - /// Characters that are not available are mapped to '?'. - pub fn str_to_cp437(utf8: &str) -> Vec { - utf8.chars().map(Self::char_to_cp437).collect() - } - - /// Convert a single UTF-8 character to CP-437. - pub fn char_to_cp437(utf8: char) -> u8 { - *UTF8_TO_CP437 - .get(&utf8) - .unwrap_or(&Self::MISSING_CHAR_CP437) - } -} - -#[cfg(test)] -mod tests_feature_cp437 { - use super::*; - - #[test] - fn convert_str() { - // test text from https://int10h.org/oldschool-pc-fonts/fontlist/font?ibm_bios - let utf8 = r#"A quick brown fox jumps over the lazy dog. - 0123456789 ¿?¡!`'"., <>()[]{} &@%*^#$\/ - - * Wieniläinen sioux'ta puhuva ökyzombie diggaa Åsan roquefort-tacoja. - * Ça me fait peur de fêter noël là, sur cette île bizarroïde où une mère et sa môme essaient de me tuer avec un gâteau à la cigüe brûlé. - * Zwölf Boxkämpfer jagten Eva quer über den Sylter Deich. - * El pingüino Wenceslao hizo kilómetros bajo exhaustiva lluvia y frío, añoraba a su querido cachorro. - - ┌─┬─┐ ╔═╦═╗ ╒═╤═╕ ╓─╥─╖ - │ │ │ ║ ║ ║ │ │ │ ║ ║ ║ - ├─┼─┤ ╠═╬═╣ ╞═╪═╡ ╟─╫─╢ - └─┴─┘ ╚═╩═╝ ╘═╧═╛ ╙─╨─╜ - - ░░░░░ ▐▀█▀▌ .·∙•○°○•∙·. - ▒▒▒▒▒ ▐ █ ▌ ☺☻ ♥♦♣♠ ♪♫☼ - ▓▓▓▓▓ ▐▀█▀▌ $ ¢ £ ¥ ₧ - █████ ▐▄█▄▌ ◄►▲▼ ←→↑↓↕↨ - - ⌠ - │dx ≡ Σ √x²ⁿ·δx - ⌡"#; - - let cp437 = Cp437Converter::str_to_cp437(utf8); - let actual = Cp437Converter::cp437_to_str(&cp437); - assert_eq!(utf8, actual) - } - - #[test] - fn convert_invalid() { - assert_eq!( - Cp437Converter::cp437_to_char(Cp437Converter::char_to_cp437('😜')), - '?' - ); - } -} diff --git a/crates/servicepoint/src/cp437_grid.rs b/crates/servicepoint/src/cp437_grid.rs deleted file mode 100644 index 99506bc..0000000 --- a/crates/servicepoint/src/cp437_grid.rs +++ /dev/null @@ -1,163 +0,0 @@ -/// A grid containing codepage 437 characters. -/// -/// The encoding is currently not enforced. -pub type Cp437Grid = crate::value_grid::ValueGrid; - -/// The error occurring when loading an invalid character -#[derive(Debug, PartialEq, thiserror::Error)] -#[error( - "The character {char:?} at position {index} is not a valid CP437 character" -)] -pub struct InvalidCharError { - /// invalid character is at this position in input - index: usize, - /// the invalid character - char: char, -} - -impl Cp437Grid { - /// Load an ASCII-only [&str] into a [Cp437Grid] of specified width. - /// - /// # Panics - /// - /// - for width == 0 - /// - on empty strings - pub fn load_ascii( - value: &str, - width: usize, - wrap: bool, - ) -> Result { - assert!(width > 0); - assert!(!value.is_empty()); - - let mut chars = { - let mut x = 0; - let mut y = 0; - - for (index, char) in value.chars().enumerate() { - if !char.is_ascii() { - return Err(InvalidCharError { index, char }); - } - - let is_lf = char == '\n'; - if is_lf || (wrap && x == width) { - y += 1; - x = 0; - if is_lf { - continue; - } - } - - x += 1; - } - - Cp437Grid::new(width, y + 1) - }; - - let mut x = 0; - let mut y = 0; - for char in value.chars().map(move |c| c as u8) { - let is_lf = char == b'\n'; - if is_lf || (wrap && x == width) { - y += 1; - x = 0; - if is_lf { - continue; - } - } - - if wrap || x < width { - chars.set(x, y, char); - } - x += 1; - } - - Ok(chars) - } -} - -use crate::Grid; -#[allow(unused)] // depends on features -pub use feature_cp437::*; - -#[cfg(feature = "cp437")] -mod feature_cp437 { - use super::*; - use crate::{CharGrid, Cp437Converter}; - - impl From<&Cp437Grid> for CharGrid { - fn from(value: &Cp437Grid) -> Self { - value.map(Cp437Converter::cp437_to_char) - } - } - - impl From for CharGrid { - fn from(value: Cp437Grid) -> Self { - Self::from(&value) - } - } - - impl From<&CharGrid> for Cp437Grid { - fn from(value: &CharGrid) -> Self { - value.map(Cp437Converter::char_to_cp437) - } - } - - impl From for Cp437Grid { - fn from(value: CharGrid) -> Self { - Self::from(&value) - } - } -} -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn load_ascii_nowrap() { - let chars = ['H', 'e', 'l', 'l', 'o', 'W', 'o', 'r', 'l', 'd'] - .map(move |c| c as u8); - let expected = Cp437Grid::load(5, 2, &chars); - - let actual = Cp437Grid::load_ascii("Hello,\nWorld!", 5, false).unwrap(); - // comma will be removed because line is too long and wrap is off - assert_eq!(actual, expected); - } - - #[test] - fn load_ascii_wrap() { - let chars = ['H', 'e', 'l', 'l', 'o', 'W', 'o', 'r', 'l', 'd'] - .map(move |c| c as u8); - let expected = Cp437Grid::load(5, 2, &chars); - - let actual = Cp437Grid::load_ascii("HelloWorld", 5, true).unwrap(); - // line break will be added - assert_eq!(actual, expected); - } - - #[test] - fn load_ascii_invalid() { - assert_eq!( - Err(InvalidCharError { - char: '🥶', - index: 2 - }), - Cp437Grid::load_ascii("?#🥶42", 3, false) - ); - } -} - -#[cfg(test)] -#[cfg(feature = "cp437")] -mod tests_feature_cp437 { - use super::*; - use crate::CharGrid; - - #[test] - fn round_trip_cp437() { - let utf8 = CharGrid::load(2, 2, &['Ä', 'x', '\n', '$']); - let cp437 = Cp437Grid::from(utf8.clone()); - let actual = CharGrid::from(cp437); - assert_eq!(actual, utf8); - } -} diff --git a/crates/servicepoint/src/data_ref.rs b/crates/servicepoint/src/data_ref.rs deleted file mode 100644 index b8ff624..0000000 --- a/crates/servicepoint/src/data_ref.rs +++ /dev/null @@ -1,14 +0,0 @@ -/// A trait for getting the underlying raw byte slices of data containers. -/// -/// The expectation is that you can create an equal instance with this data given the additional -/// metadata needed. -pub trait DataRef { - /// Get the underlying bytes writable. - /// - /// Note that depending on the struct this is implemented on, writing invalid values here might - /// lead to panics later in the lifetime of the program or on the receiving side. - fn data_ref_mut(&mut self) -> &mut [T]; - - /// Get the underlying bytes read-only. - fn data_ref(&self) -> &[T]; -} diff --git a/crates/servicepoint/src/grid.rs b/crates/servicepoint/src/grid.rs deleted file mode 100644 index 68fe102..0000000 --- a/crates/servicepoint/src/grid.rs +++ /dev/null @@ -1,84 +0,0 @@ -/// A two-dimensional grid of `T` -pub trait Grid { - /// Sets the value at the specified position - /// - /// # Arguments - /// - /// - `x` and `y`: position of the cell to read - /// - /// # Panics - /// - /// When accessing `x` or `y` out of bounds. - fn set(&mut self, x: usize, y: usize, value: T); - - /// Get the current value at the specified position - /// - /// # Arguments - /// - /// - `x` and `y`: position of the cell to read - /// - /// # Panics - /// - /// When accessing `x` or `y` out of bounds. - fn get(&self, x: usize, y: usize) -> T; - - /// Get the current value at the specified position if the position is inside of bounds - /// - /// # Arguments - /// - /// - `x` and `y`: position of the cell to read - /// - /// returns: Value at position or None - fn get_optional(&self, x: isize, y: isize) -> Option { - if self.is_in_bounds(x, y) { - Some(self.get(x as usize, y as usize)) - } else { - None - } - } - - /// Sets the value at the specified position if the position is inside of bounds - /// - /// # Arguments - /// - /// - `x` and `y`: position of the cell to read - /// - /// returns: the old value or None - fn set_optional(&mut self, x: isize, y: isize, value: T) -> bool { - if self.is_in_bounds(x, y) { - self.set(x as usize, y as usize, value); - true - } else { - false - } - } - - /// Sets all cells in the grid to the specified value - fn fill(&mut self, value: T); - - /// the size in x-direction - fn width(&self) -> usize; - - /// the height in y-direction - fn height(&self) -> usize; - - /// Checks whether the specified signed position is in grid bounds - fn is_in_bounds(&self, x: isize, y: isize) -> bool { - x >= 0 - && x < self.width() as isize - && y >= 0 - && y < self.height() as isize - } - - /// Asserts that the specified unsigned position is in grid bounds. - /// - /// # Panics - /// - /// When the specified position is out of bounds for this grid. - fn assert_in_bounds(&self, x: usize, y: usize) { - let width = self.width(); - assert!(x < width, "cannot access index [{x}, {y}] because x is outside of bounds [0..{width})"); - let height = self.height(); - assert!(y < height, "cannot access index [{x}, {y}] because x is outside of bounds [0..{height})"); - } -} diff --git a/crates/servicepoint/src/lib.rs b/crates/servicepoint/src/lib.rs deleted file mode 100644 index 790751a..0000000 --- a/crates/servicepoint/src/lib.rs +++ /dev/null @@ -1,103 +0,0 @@ -//! Abstractions for the UDP protocol of the CCCB servicepoint display. -//! -//! Your starting point is a [Connection] to the display. -//! With a connection, you can send [Command]s. -//! When received, the display will update the state of its pixels. -//! -//! # Examples -//! -//! ### Clear display -//! -//! ```rust -//! use servicepoint::{Connection, Command}; -//! -//! // establish a connection -//! let connection = Connection::open("127.0.0.1:2342") -//! .expect("connection failed"); -//! -//! // turn off all pixels on display -//! connection.send(Command::Clear) -//! .expect("send failed"); -//! ``` -//! -//! ### Set all pixels to on -//! -//! ```rust -//! # use servicepoint::{Command, CompressionCode, Grid, Bitmap}; -//! # let connection = servicepoint::Connection::open("127.0.0.1:2342").expect("connection failed"); -//! // turn on all pixels in a grid -//! let mut pixels = Bitmap::max_sized(); -//! pixels.fill(true); -//! -//! // create command to send pixels -//! let command = Command::BitmapLinearWin( -//! servicepoint::Origin::ZERO, -//! pixels, -//! CompressionCode::Uncompressed -//! ); -//! -//! // send command to display -//! connection.send(command).expect("send failed"); -//! ``` -//! -//! ### Send text -//! -//! ```rust -//! # use servicepoint::{Command, CompressionCode, Grid, Bitmap, CharGrid}; -//! # let connection = servicepoint::Connection::open("127.0.0.1:2342").expect("connection failed"); -//! // create a text grid -//! let mut grid = CharGrid::from("Hello\nCCCB?"); -//! // modify the grid -//! grid.set(grid.width() - 1, 1, '!'); -//! // create the command to send the data -//! let command = Command::Utf8Data(servicepoint::Origin::ZERO, grid); -//! // send command to display -//! connection.send(command).expect("send failed"); -//! ``` - -pub use crate::bit_vec::{bitvec, BitVec}; -pub use crate::bitmap::Bitmap; -pub use crate::brightness::Brightness; -pub use crate::brightness_grid::BrightnessGrid; -pub use crate::byte_grid::ByteGrid; -pub use crate::char_grid::CharGrid; -pub use crate::command::{Command, Offset}; -pub use crate::compression_code::CompressionCode; -pub use crate::connection::Connection; -pub use crate::constants::*; -pub use crate::cp437::Cp437Converter; -pub use crate::cp437_grid::Cp437Grid; -pub use crate::data_ref::DataRef; -pub use crate::grid::Grid; -pub use crate::origin::{Origin, Pixels, Tiles}; -pub use crate::packet::{Header, Packet, Payload}; -pub use crate::value_grid::{ - IterGridRows, SetValueSeriesError, TryLoadValueGridError, Value, ValueGrid, -}; - -mod bit_vec; -mod bitmap; -mod brightness; -mod brightness_grid; -mod byte_grid; -mod char_grid; -mod command; -mod command_code; -mod compression; -mod compression_code; -mod connection; -mod constants; -mod cp437_grid; -mod data_ref; -mod grid; -mod origin; -mod packet; -mod value_grid; - -#[cfg(feature = "cp437")] -mod cp437; - -// include README.md in doctest -#[doc = include_str!("../README.md")] -#[cfg(doctest)] -pub struct ReadmeDocTests; diff --git a/crates/servicepoint/src/origin.rs b/crates/servicepoint/src/origin.rs deleted file mode 100644 index 345b89e..0000000 --- a/crates/servicepoint/src/origin.rs +++ /dev/null @@ -1,122 +0,0 @@ -use crate::TILE_SIZE; -use std::marker::PhantomData; - -/// An origin marks the top left position of a window sent to the display. -#[derive(Debug, Copy, Clone, PartialEq)] -pub struct Origin { - /// position in the width direction - pub x: usize, - /// position in the height direction - pub y: usize, - phantom_data: PhantomData, -} - -impl Origin { - /// Top-left. Equivalent to `Origin::ZERO`. - pub const ZERO: Self = Self { - x: 0, - y: 0, - phantom_data: PhantomData, - }; - - /// Create a new [Origin] instance for the provided position. - pub fn new(x: usize, y: usize) -> Self { - Self { - x, - y, - phantom_data: PhantomData, - } - } -} - -impl std::ops::Add> for Origin { - type Output = Origin; - - fn add(self, rhs: Origin) -> Self::Output { - Origin { - x: self.x + rhs.x, - y: self.y + rhs.y, - phantom_data: PhantomData, - } - } -} - -pub trait DisplayUnit {} - -/// Marks something to be measured in number of pixels. -#[derive(Debug, Copy, Clone, PartialEq)] -pub struct Pixels(); - -/// Marks something to be measured in number of iles. -#[derive(Debug, Copy, Clone, PartialEq)] -pub struct Tiles(); - -impl DisplayUnit for Pixels {} - -impl DisplayUnit for Tiles {} - -impl From<&Origin> for Origin { - fn from(value: &Origin) -> Self { - Self { - x: value.x * TILE_SIZE, - y: value.y * TILE_SIZE, - phantom_data: PhantomData, - } - } -} - -impl TryFrom<&Origin> for Origin { - type Error = (); - - fn try_from(value: &Origin) -> Result { - let (x, x_rem) = (value.x / TILE_SIZE, value.x % TILE_SIZE); - if x_rem != 0 { - return Err(()); - } - let (y, y_rem) = (value.y / TILE_SIZE, value.y % TILE_SIZE); - if y_rem != 0 { - return Err(()); - } - - Ok(Self { - x, - y, - phantom_data: PhantomData, - }) - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn origin_tile_to_pixel() { - let tile: Origin = Origin::new(1, 2); - let actual: Origin = Origin::from(&tile); - let expected: Origin = Origin::new(8, 16); - assert_eq!(actual, expected); - } - - #[test] - fn origin_pixel_to_tile() { - let pixel: Origin = Origin::new(8, 16); - let actual: Origin = Origin::try_from(&pixel).unwrap(); - let expected: Origin = Origin::new(1, 2); - assert_eq!(actual, expected); - } - - #[test] - #[should_panic] - fn origin_pixel_to_tile_fail_y() { - let pixel: Origin = Origin::new(8, 15); - let _: Origin = Origin::try_from(&pixel).unwrap(); - } - - #[test] - #[should_panic] - fn origin_pixel_to_tile_fail_x() { - let pixel: Origin = Origin::new(7, 16); - let _: Origin = Origin::try_from(&pixel).unwrap(); - } -} diff --git a/crates/servicepoint/src/packet.rs b/crates/servicepoint/src/packet.rs deleted file mode 100644 index 099c50c..0000000 --- a/crates/servicepoint/src/packet.rs +++ /dev/null @@ -1,358 +0,0 @@ -//! Raw packet manipulation. -//! -//! Should probably only be used directly to use features not exposed by the library. -//! -//! # Examples -//! -//! Converting a packet to a command and back: -//! -//! ```rust -//! use servicepoint::{Command, Packet}; -//! # let command = Command::Clear; -//! let packet: Packet = command.into(); -//! let command: Command = Command::try_from(packet).expect("could not read command from packet"); -//! ``` -//! -//! Converting a packet to bytes and back: -//! -//! ```rust -//! use servicepoint::{Command, Packet}; -//! # let command = Command::Clear; -//! # let packet: Packet = command.into(); -//! let bytes: Vec = packet.into(); -//! let packet = Packet::try_from(bytes).expect("could not read packet from bytes"); -//! ``` - -use crate::command_code::CommandCode; -use crate::compression::into_compressed; -use crate::{ - Bitmap, Command, CompressionCode, Grid, Offset, Origin, Pixels, Tiles, - TILE_SIZE, -}; -use std::mem::size_of; - -/// A raw header. -/// -/// The header specifies the kind of command, the size of the payload and where to display the -/// payload, where applicable. -/// -/// Because the meaning of most fields depend on the command, there are no speaking names for them. -#[derive(Copy, Clone, Debug, PartialEq)] -pub struct Header { - /// The first two bytes specify which command this packet represents. - pub command_code: u16, - /// First command-specific value - pub a: u16, - /// Second command-specific value - pub b: u16, - /// Third command-specific value - pub c: u16, - /// Fourth command-specific value - pub d: u16, -} - -/// The raw payload. -/// -/// Should probably only be used directly to use features not exposed by the library. -pub type Payload = Vec; - -/// The raw packet. -/// -/// Contents should probably only be used directly to use features not exposed by the library. -/// -/// You may want to use [Command] instead. -/// -/// -#[derive(Clone, Debug, PartialEq)] -pub struct Packet { - /// Meta-information for the packed command - pub header: Header, - /// The data for the packed command - pub payload: Payload, -} - -impl From for Vec { - /// Turn the packet into raw bytes ready to send - fn from(value: Packet) -> Self { - let Packet { - header: - Header { - command_code: mode, - a, - b, - c, - d, - }, - payload, - } = value; - - let mut packet = vec![0u8; 10 + payload.len()]; - packet[0..=1].copy_from_slice(&u16::to_be_bytes(mode)); - packet[2..=3].copy_from_slice(&u16::to_be_bytes(a)); - packet[4..=5].copy_from_slice(&u16::to_be_bytes(b)); - packet[6..=7].copy_from_slice(&u16::to_be_bytes(c)); - packet[8..=9].copy_from_slice(&u16::to_be_bytes(d)); - - packet[10..].copy_from_slice(&payload); - - packet - } -} - -impl TryFrom<&[u8]> for Packet { - type Error = (); - - /// Tries to interpret the bytes as a [Packet]. - /// - /// returns: `Error` if slice is not long enough to be a [Packet] - fn try_from(value: &[u8]) -> Result { - if value.len() < size_of::
() { - return Err(()); - } - - let header = { - let command_code = Self::u16_from_be_slice(&value[0..=1]); - let a = Self::u16_from_be_slice(&value[2..=3]); - let b = Self::u16_from_be_slice(&value[4..=5]); - let c = Self::u16_from_be_slice(&value[6..=7]); - let d = Self::u16_from_be_slice(&value[8..=9]); - Header { - command_code, - a, - b, - c, - d, - } - }; - let payload = value[10..].to_vec(); - - Ok(Packet { header, payload }) - } -} - -impl TryFrom> for Packet { - type Error = (); - - fn try_from(value: Vec) -> Result { - Self::try_from(value.as_slice()) - } -} - -impl From for Packet { - /// Move the [Command] into a [Packet] instance for sending. - #[allow(clippy::cast_possible_truncation)] - fn from(value: Command) -> Self { - match value { - Command::Clear => Self::command_code_only(CommandCode::Clear), - Command::FadeOut => Self::command_code_only(CommandCode::FadeOut), - Command::HardReset => { - Self::command_code_only(CommandCode::HardReset) - } - #[allow(deprecated)] - Command::BitmapLegacy => { - Self::command_code_only(CommandCode::BitmapLegacy) - } - Command::CharBrightness(origin, grid) => { - Self::origin_grid_to_packet( - origin, - grid, - CommandCode::CharBrightness, - ) - } - Command::Brightness(brightness) => Packet { - header: Header { - command_code: CommandCode::Brightness.into(), - a: 0x00000, - b: 0x0000, - c: 0x0000, - d: 0x0000, - }, - payload: vec![brightness.into()], - }, - Command::BitmapLinearWin(origin, pixels, compression) => { - Self::bitmap_win_into_packet(origin, pixels, compression) - } - Command::BitmapLinear(offset, bits, compression) => { - Self::bitmap_linear_into_packet( - CommandCode::BitmapLinear, - offset, - compression, - bits.into(), - ) - } - Command::BitmapLinearAnd(offset, bits, compression) => { - Self::bitmap_linear_into_packet( - CommandCode::BitmapLinearAnd, - offset, - compression, - bits.into(), - ) - } - Command::BitmapLinearOr(offset, bits, compression) => { - Self::bitmap_linear_into_packet( - CommandCode::BitmapLinearOr, - offset, - compression, - bits.into(), - ) - } - Command::BitmapLinearXor(offset, bits, compression) => { - Self::bitmap_linear_into_packet( - CommandCode::BitmapLinearXor, - offset, - compression, - bits.into(), - ) - } - Command::Cp437Data(origin, grid) => Self::origin_grid_to_packet( - origin, - grid, - CommandCode::Cp437Data, - ), - Command::Utf8Data(origin, grid) => { - Self::origin_grid_to_packet(origin, grid, CommandCode::Utf8Data) - } - } - } -} - -impl Packet { - /// Helper method for `BitmapLinear*`-Commands into [Packet] - #[allow(clippy::cast_possible_truncation)] - fn bitmap_linear_into_packet( - command: CommandCode, - offset: Offset, - compression: CompressionCode, - payload: Vec, - ) -> Packet { - let length = payload.len() as u16; - let payload = into_compressed(compression, payload); - Packet { - header: Header { - command_code: command.into(), - a: offset as u16, - b: length, - c: compression.into(), - d: 0, - }, - payload, - } - } - - #[allow(clippy::cast_possible_truncation)] - fn bitmap_win_into_packet( - origin: Origin, - pixels: Bitmap, - compression: CompressionCode, - ) -> Packet { - debug_assert_eq!(origin.x % 8, 0); - debug_assert_eq!(pixels.width() % 8, 0); - - let tile_x = (origin.x / TILE_SIZE) as u16; - let tile_w = (pixels.width() / TILE_SIZE) as u16; - let pixel_h = pixels.height() as u16; - let payload = into_compressed(compression, pixels.into()); - let command = match compression { - CompressionCode::Uncompressed => { - CommandCode::BitmapLinearWinUncompressed - } - #[cfg(feature = "compression_zlib")] - CompressionCode::Zlib => CommandCode::BitmapLinearWinZlib, - #[cfg(feature = "compression_bzip2")] - CompressionCode::Bzip2 => CommandCode::BitmapLinearWinBzip2, - #[cfg(feature = "compression_lzma")] - CompressionCode::Lzma => CommandCode::BitmapLinearWinLzma, - #[cfg(feature = "compression_zstd")] - CompressionCode::Zstd => CommandCode::BitmapLinearWinZstd, - }; - - Packet { - header: Header { - command_code: command.into(), - a: tile_x, - b: origin.y as u16, - c: tile_w, - d: pixel_h, - }, - payload, - } - } - - /// Helper method for creating empty packets only containing the command code - fn command_code_only(code: CommandCode) -> Packet { - Packet { - header: Header { - command_code: code.into(), - a: 0x0000, - b: 0x0000, - c: 0x0000, - d: 0x0000, - }, - payload: vec![], - } - } - - fn u16_from_be_slice(slice: &[u8]) -> u16 { - let mut bytes = [0u8; 2]; - bytes[0] = slice[0]; - bytes[1] = slice[1]; - u16::from_be_bytes(bytes) - } - - fn origin_grid_to_packet( - origin: Origin, - grid: impl Grid + Into, - command_code: CommandCode, - ) -> Packet { - Packet { - header: Header { - command_code: command_code.into(), - a: origin.x as u16, - b: origin.y as u16, - c: grid.width() as u16, - d: grid.height() as u16, - }, - payload: grid.into(), - } - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn round_trip() { - let p = Packet { - header: Header { - command_code: 0, - a: 1, - b: 2, - c: 3, - d: 4, - }, - payload: vec![42u8; 23], - }; - let data: Vec = p.into(); - let p = Packet::try_from(data).unwrap(); - assert_eq!( - p, - Packet { - header: Header { - command_code: 0, - a: 1, - b: 2, - c: 3, - d: 4 - }, - payload: vec![42u8; 23] - } - ); - } - - #[test] - fn too_small() { - let data = vec![0u8; 4]; - assert_eq!(Packet::try_from(data.as_slice()), Err(())) - } -} diff --git a/crates/servicepoint/src/value_grid.rs b/crates/servicepoint/src/value_grid.rs deleted file mode 100644 index b9cfea5..0000000 --- a/crates/servicepoint/src/value_grid.rs +++ /dev/null @@ -1,590 +0,0 @@ -use std::fmt::Debug; -use std::slice::{Iter, IterMut}; - -use crate::*; - -/// A type that can be stored in a [ValueGrid], e.g. [char], [u8]. -pub trait Value: Sized + Default + Copy + Clone + Debug {} -impl Value for T {} - -/// A 2D grid of values. -/// -/// The memory layout is the one the display expects in [Command]s. -/// -/// This structure can be used with any type that implements the [Value] trait. -/// You can also use the concrete type aliases provided in this crate, e.g. [CharGrid] and [ByteGrid]. -#[derive(Debug, Clone, PartialEq)] -pub struct ValueGrid { - width: usize, - height: usize, - data: Vec, -} - -/// Error type for methods that change a whole column or row at once -#[derive(thiserror::Error, Debug, PartialEq)] -pub enum SetValueSeriesError { - #[error("The index {index} was out of bounds for size {size}")] - /// The index {index} was out of bounds for size {size} - OutOfBounds { - /// the index where access was tried - index: usize, - /// the size in that direction - size: usize, - }, - #[error("The provided series was expected to have a length of {expected}, but was {actual}")] - /// The provided series was expected to have a length of {expected}, but was {actual} - InvalidLength { - /// actual size of the provided series - actual: usize, - /// expected size - expected: usize, - }, -} - -impl ValueGrid { - /// Creates a new [ValueGrid] with the specified dimensions. - /// - /// # Arguments - /// - /// - width: size in x-direction - /// - height: size in y-direction - /// - /// returns: [ValueGrid] initialized to default value. - pub fn new(width: usize, height: usize) -> Self { - Self { - data: vec![Default::default(); width * height], - width, - height, - } - } - - /// Loads a [ValueGrid] with the specified dimensions from the provided data. - /// - /// returns: [ValueGrid] that contains a copy of the provided data - /// - /// # Panics - /// - /// - when the dimensions and data size do not match exactly. - #[must_use] - pub fn load(width: usize, height: usize, data: &[T]) -> Self { - assert_eq!( - width * height, - data.len(), - "dimension mismatch for data {data:?}" - ); - Self { - data: Vec::from(data), - width, - height, - } - } - - /// Creates a [ValueGrid] with the specified width from the provided data without copying it. - /// - /// returns: [ValueGrid] that contains the provided data. - /// - /// # Panics - /// - /// - when the data size is not dividable by the width. - #[must_use] - pub fn from_vec(width: usize, data: Vec) -> Self { - let len = data.len(); - let height = len / width; - assert_eq!(0, len % width, "dimension mismatch - len {len} is not dividable by {width}"); - Self { data, width, height } - } - - /// Loads a [ValueGrid] with the specified width from the provided data, wrapping to as many rows as needed. - /// - /// returns: [ValueGrid] that contains a copy of the provided data or [TryLoadValueGridError]. - /// - /// # Examples - /// - /// ``` - /// # use servicepoint::ValueGrid; - /// let grid = ValueGrid::wrap(2, &[0, 1, 2, 3, 4, 5]).unwrap(); - /// ``` - pub fn wrap( - width: usize, - data: &[T], - ) -> Result { - let len = data.len(); - if len % width != 0 { - return Err(TryLoadValueGridError::InvalidDimensions); - } - Ok(Self::load(width, len / width, data)) - } - - /// Loads a [ValueGrid] with the specified dimensions from the provided data. - /// - /// returns: [ValueGrid] that contains a copy of the provided data or [TryLoadValueGridError]. - pub fn try_load( - width: usize, - height: usize, - data: Vec, - ) -> Result { - if width * height != data.len() { - return Err(TryLoadValueGridError::InvalidDimensions); - } - - Ok(Self { - data, - width, - height, - }) - } - - /// Iterate over all cells in [ValueGrid]. - /// - /// Order is equivalent to the following loop: - /// ``` - /// # use servicepoint::{ByteGrid, Grid}; - /// # let grid = ByteGrid::new(2,2); - /// for y in 0..grid.height() { - /// for x in 0..grid.width() { - /// grid.get(x, y); - /// } - /// } - /// ``` - pub fn iter(&self) -> Iter { - self.data.iter() - } - - /// Iterate over all rows in [ValueGrid] top to bottom. - pub fn iter_rows(&self) -> IterGridRows { - IterGridRows { - byte_grid: self, - row: 0, - } - } - - /// Returns an iterator that allows modifying each value. - /// - /// The iterator yields all cells from top left to bottom right. - pub fn iter_mut(&mut self) -> IterMut { - self.data.iter_mut() - } - - /// Get a mutable reference to the current value at the specified position. - /// - /// # Arguments - /// - /// - `x` and `y`: position of the cell - /// - /// # Panics - /// - /// When accessing `x` or `y` out of bounds. - pub fn get_ref_mut(&mut self, x: usize, y: usize) -> &mut T { - self.assert_in_bounds(x, y); - &mut self.data[x + y * self.width] - } - - /// Get a mutable reference to the current value at the specified position if position is in bounds. - /// - /// # Arguments - /// - /// - `x` and `y`: position of the cell - /// - /// returns: Reference to cell or None - pub fn get_ref_mut_optional( - &mut self, - x: isize, - y: isize, - ) -> Option<&mut T> { - if self.is_in_bounds(x, y) { - Some(&mut self.data[x as usize + y as usize * self.width]) - } else { - None - } - } - - /// Convert between ValueGrid types. - /// - /// See also [Iterator::map]. - /// - /// # Examples - /// - /// Use logic written for u8s and then convert to [Brightness] values for sending in a [Command]. - /// ``` - /// # fn foo(grid: &mut ByteGrid) {} - /// # use servicepoint::{Brightness, BrightnessGrid, ByteGrid, Command, Origin, TILE_HEIGHT, TILE_WIDTH}; - /// let mut grid: ByteGrid = ByteGrid::new(TILE_WIDTH, TILE_HEIGHT); - /// foo(&mut grid); - /// let grid: BrightnessGrid = grid.map(Brightness::saturating_from); - /// let command = Command::CharBrightness(Origin::ZERO, grid); - /// ``` - /// [Brightness]: [crate::Brightness] - /// [Command]: [crate::Command] - pub fn map(&self, f: F) -> ValueGrid - where - TConverted: Value, - F: Fn(T) -> TConverted, - { - let data = self - .data_ref() - .iter() - .map(|elem| f(*elem)) - .collect::>(); - ValueGrid::load(self.width(), self.height(), &data) - } - - /// Copies a row from the grid. - /// - /// Returns [None] if y is out of bounds. - pub fn get_row(&self, y: usize) -> Option> { - self.data - .chunks_exact(self.width()) - .nth(y) - .map(|row| row.to_vec()) - } - - /// Copies a column from the grid. - /// - /// Returns [None] if x is out of bounds. - pub fn get_col(&self, x: usize) -> Option> { - self.data - .chunks_exact(self.width()) - .map(|row| row.get(x).copied()) - .collect() - } - - /// Overwrites a column in the grid. - /// - /// Returns [Err] if x is out of bounds or `col` is not of the correct size. - pub fn set_col( - &mut self, - x: usize, - col: &[T], - ) -> Result<(), SetValueSeriesError> { - if col.len() != self.height() { - return Err(SetValueSeriesError::InvalidLength { - expected: self.height(), - actual: col.len(), - }); - } - let width = self.width(); - if self - .data - .chunks_exact_mut(width) - .zip(col.iter()) - .map(|(row, column_value)| { - row.get_mut(x).map(move |cell| *cell = *column_value) - }) - .all(|cell| cell.is_some()) - { - Ok(()) - } else { - Err(SetValueSeriesError::OutOfBounds { - index: x, - size: width, - }) - } - } - - /// Overwrites a row in the grid. - /// - /// Returns [Err] if y is out of bounds or `row` is not of the correct size. - pub fn set_row( - &mut self, - y: usize, - row: &[T], - ) -> Result<(), SetValueSeriesError> { - let width = self.width(); - if row.len() != width { - return Err(SetValueSeriesError::InvalidLength { - expected: width, - actual: row.len(), - }); - } - - let chunk = match self.data.chunks_exact_mut(width).nth(y) { - Some(row) => row, - None => { - return Err(SetValueSeriesError::OutOfBounds { - size: self.height(), - index: y, - }) - } - }; - - chunk.copy_from_slice(row); - Ok(()) - } -} - -/// Errors that can occur when loading a grid -#[derive(Debug, thiserror::Error, PartialEq)] -pub enum TryLoadValueGridError { - #[error("The provided dimensions do not match with the data size")] - /// The provided dimensions do not match with the data size - InvalidDimensions, -} - -impl Grid for ValueGrid { - /// Sets the value of the cell at the specified position in the `ValueGrid. - /// - /// # Arguments - /// - /// - `x` and `y`: position of the cell - /// - `value`: the value to write to the cell - /// - /// # Panics - /// - /// When accessing `x` or `y` out of bounds. - fn set(&mut self, x: usize, y: usize, value: T) { - self.assert_in_bounds(x, y); - self.data[x + y * self.width] = value; - } - - /// Gets the current value at the specified position. - /// - /// # Arguments - /// - /// - `x` and `y`: position of the cell to read - /// - /// # Panics - /// - /// When accessing `x` or `y` out of bounds. - fn get(&self, x: usize, y: usize) -> T { - self.assert_in_bounds(x, y); - self.data[x + y * self.width] - } - - fn fill(&mut self, value: T) { - self.data.fill(value); - } - - fn width(&self) -> usize { - self.width - } - - fn height(&self) -> usize { - self.height - } -} - -impl DataRef for ValueGrid { - /// Get the underlying byte rows mutable - fn data_ref_mut(&mut self) -> &mut [T] { - self.data.as_mut_slice() - } - - /// Get the underlying byte rows read only - fn data_ref(&self) -> &[T] { - self.data.as_slice() - } -} - -impl From> for Vec { - /// Turn into the underlying [`Vec`] containing the rows of bytes. - fn from(value: ValueGrid) -> Self { - value.data - } -} - -/// An iterator iver the rows in a [ValueGrid] -pub struct IterGridRows<'t, T: Value> { - byte_grid: &'t ValueGrid, - row: usize, -} - -impl<'t, T: Value> Iterator for IterGridRows<'t, T> { - type Item = Iter<'t, T>; - - fn next(&mut self) -> Option { - if self.row >= self.byte_grid.height { - return None; - } - - let start = self.row * self.byte_grid.width; - let end = start + self.byte_grid.width; - let result = self.byte_grid.data[start..end].iter(); - self.row += 1; - Some(result) - } -} - -#[cfg(test)] -mod tests { - use crate::{ - value_grid::{SetValueSeriesError, ValueGrid}, - *, - }; - - #[test] - fn fill() { - let mut grid = ValueGrid::::new(2, 2); - assert_eq!(grid.data, [0x00, 0x00, 0x00, 0x00]); - - grid.fill(42); - assert_eq!(grid.data, [42; 4]); - } - - #[test] - fn get_set() { - let mut grid = ValueGrid::new(2, 2); - assert_eq!(grid.get(0, 0), 0); - assert_eq!(grid.get(1, 1), 0); - - grid.set(0, 0, 42); - grid.set(1, 0, 23); - assert_eq!(grid.data, [42, 23, 0, 0]); - - assert_eq!(grid.get(0, 0), 42); - assert_eq!(grid.get(1, 0), 23); - assert_eq!(grid.get(1, 1), 0); - } - - #[test] - fn load() { - let mut grid = ValueGrid::new(2, 3); - for x in 0..grid.width { - for y in 0..grid.height { - grid.set(x, y, (x + y) as u8); - } - } - - assert_eq!(grid.data, [0, 1, 1, 2, 2, 3]); - - let data: Vec = grid.into(); - - let grid = ValueGrid::load(2, 3, &data); - assert_eq!(grid.data, [0, 1, 1, 2, 2, 3]); - } - - #[test] - fn mut_data_ref() { - let mut vec = ValueGrid::new(2, 2); - - let data_ref = vec.data_ref_mut(); - data_ref.copy_from_slice(&[1, 2, 3, 4]); - - assert_eq!(vec.data, [1, 2, 3, 4]); - assert_eq!(vec.get(1, 0), 2) - } - - #[test] - fn iter() { - let mut vec = ValueGrid::new(2, 2); - vec.set(1, 1, 5); - - let mut iter = vec.iter(); - assert_eq!(*iter.next().unwrap(), 0); - assert_eq!(*iter.next().unwrap(), 0); - assert_eq!(*iter.next().unwrap(), 0); - assert_eq!(*iter.next().unwrap(), 5); - } - - #[test] - fn iter_mut() { - let mut vec = ValueGrid::new(2, 3); - for (index, cell) in vec.iter_mut().enumerate() { - *cell = index as u8; - } - - assert_eq!(vec.data_ref(), [0, 1, 2, 3, 4, 5]); - } - - #[test] - fn iter_rows() { - let vec = ValueGrid::load(2, 3, &[0, 1, 1, 2, 2, 3]); - for (y, row) in vec.iter_rows().enumerate() { - for (x, val) in row.enumerate() { - assert_eq!(*val, (x + y) as u8); - } - } - } - - #[test] - #[should_panic] - fn out_of_bounds_x() { - let mut vec = ValueGrid::load(2, 2, &[0, 1, 2, 3]); - vec.set(2, 1, 5); - } - - #[test] - #[should_panic] - fn out_of_bounds_y() { - let vec = ValueGrid::load(2, 2, &[0, 1, 2, 3]); - vec.get(1, 2); - } - - #[test] - fn ref_mut() { - let mut vec = ValueGrid::from_vec(3, vec![0, 1, 2, 3,4,5,6,7,8]); - - let top_left = vec.get_ref_mut(0, 0); - *top_left += 5; - let somewhere = vec.get_ref_mut(2, 1); - *somewhere = 42; - - assert_eq!(None, vec.get_ref_mut_optional(3, 2)); - assert_eq!(None, vec.get_ref_mut_optional(2, 3)); - assert_eq!(Some(&mut 5), vec.get_ref_mut_optional(0, 0)); - assert_eq!(Some(&mut 42), vec.get_ref_mut_optional(2, 1)); - assert_eq!(Some(&mut 8), vec.get_ref_mut_optional(2, 2)); - } - - #[test] - fn optional() { - let mut grid = ValueGrid::load(2, 2, &[0, 1, 2, 3]); - grid.set_optional(0, 0, 5); - grid.set_optional(-1, 0, 8); - grid.set_optional(0, 8, 42); - assert_eq!(grid.data, [5, 1, 2, 3]); - - assert_eq!(grid.get_optional(0, 0), Some(5)); - assert_eq!(grid.get_optional(0, 8), None); - } - - #[test] - fn col() { - let mut grid = ValueGrid::load(2, 3, &[0, 1, 2, 3, 4, 5]); - assert_eq!(grid.get_col(0), Some(vec![0, 2, 4])); - assert_eq!(grid.get_col(1), Some(vec![1, 3, 5])); - assert_eq!(grid.get_col(2), None); - assert_eq!(grid.set_col(0, &[5, 7, 9]), Ok(())); - assert_eq!( - grid.set_col(2, &[5, 7, 9]), - Err(SetValueSeriesError::OutOfBounds { size: 2, index: 2 }) - ); - assert_eq!( - grid.set_col(0, &[5, 7]), - Err(SetValueSeriesError::InvalidLength { - expected: 3, - actual: 2 - }) - ); - assert_eq!(grid.get_col(0), Some(vec![5, 7, 9])); - } - - #[test] - fn row() { - let mut grid = ValueGrid::load(2, 3, &[0, 1, 2, 3, 4, 5]); - assert_eq!(grid.get_row(0), Some(vec![0, 1])); - assert_eq!(grid.get_row(2), Some(vec![4, 5])); - assert_eq!(grid.get_row(3), None); - assert_eq!(grid.set_row(0, &[5, 7]), Ok(())); - assert_eq!(grid.get_row(0), Some(vec![5, 7])); - assert_eq!( - grid.set_row(3, &[5, 7]), - Err(SetValueSeriesError::OutOfBounds { size: 3, index: 3 }) - ); - assert_eq!( - grid.set_row(2, &[5, 7, 3]), - Err(SetValueSeriesError::InvalidLength { - expected: 2, - actual: 3 - }) - ); - } - - #[test] - fn wrap() { - let grid = ValueGrid::wrap(2, &[0, 1, 2, 3, 4, 5]).unwrap(); - assert_eq!(grid.height(), 3); - - let grid = ValueGrid::wrap(4, &[0, 1, 2, 3, 4, 5]); - assert_eq!(grid.err(), Some(TryLoadValueGridError::InvalidDimensions)); - } -} diff --git a/crates/servicepoint_binding_c/Cargo.toml b/crates/servicepoint_binding_c/Cargo.toml deleted file mode 100644 index e93d2f1..0000000 --- a/crates/servicepoint_binding_c/Cargo.toml +++ /dev/null @@ -1,29 +0,0 @@ -[package] -name = "servicepoint_binding_c" -version.workspace = true -publish = true -edition = "2021" -license = "GPL-3.0-or-later" -description = "C bindings for the servicepoint crate." -homepage = "https://docs.rs/crate/servicepoint_binding_c" -repository = "https://git.berlin.ccc.de/servicepoint/servicepoint" -readme = "README.md" -links = "servicepoint" -keywords = ["cccb", "cccb-servicepoint", "cbindgen"] - -[lib] -crate-type = ["staticlib", "cdylib", "rlib"] - -[build-dependencies] -cbindgen = "0.27.0" - -[dependencies.servicepoint] -version = "0.13.1" -path = "../servicepoint" -features = ["all_compressions"] - -[lints] -workspace = true - -[package.metadata.docs.rs] -all-features = true diff --git a/crates/servicepoint_binding_c/README.md b/crates/servicepoint_binding_c/README.md deleted file mode 100644 index 892c9e5..0000000 --- a/crates/servicepoint_binding_c/README.md +++ /dev/null @@ -1,63 +0,0 @@ -# servicepoint_binding_c - -[![crates.io](https://img.shields.io/crates/v/servicepoint_binding_c.svg)](https://crates.io/crates/servicepoint) -[![Crates.io Total Downloads](https://img.shields.io/crates/d/servicepoint_binding_c)](https://crates.io/crates/servicepoint) -[![docs.rs](https://img.shields.io/docsrs/servicepoint_binding_c)](https://docs.rs/servicepoint/latest/servicepoint/) -[![GPLv3 licensed](https://img.shields.io/crates/l/servicepoint_binding_c)](../../LICENSE) - -In [CCCB](https://berlin.ccc.de/), there is a big pixel matrix hanging on the wall. -It is called "Service Point Display" or "Airport Display". - -This crate contains C bindings for the `servicepoint` library, enabling users to parse, encode and send packets to this display via UDP. - -## Examples - -```c++ -#include -#include "servicepoint.h" - -int main(void) { - SPConnection *connection = sp_connection_open("172.23.42.29:2342"); - if (connection == NULL) - return 1; - - SPBitmap *pixels = sp_bitmap_new(SP_PIXEL_WIDTH, SP_PIXEL_HEIGHT); - sp_bitmap_fill(pixels, true); - - SPCommand *command = sp_command_bitmap_linear_win(0, 0, pixels, Uncompressed); - while (sp_connection_send_command(connection, sp_command_clone(command))); - - sp_command_free(command); - sp_connection_free(connection); - return 0; -} -``` - -A full example including Makefile is available as part of this crate. - -## Note on stability - -This library is still in early development. -You can absolutely use it, and it works, but expect minor breaking changes with every version bump. -Please specify the full version including patch in your Cargo.toml until 1.0 is released. - -## Installation - -Copy the header to your project and compile against. - -You have the choice of linking statically (recommended) or dynamically. -- The C example shows how to link statically against the `staticlib` variant. -- When linked dynamically, you have to provide the `cdylib` at runtime in the _same_ version, as there are no API/ABI guarantees yet. - -## Notes on differences to rust library - -- function names are: `sp_` \ \. -- Instances get consumed in the same way they do when writing rust code. Do not use an instance after an (implicit!) free. -- Option or Result turn into nullable return values - check for NULL! -- There are no specifics for C++ here yet. You might get a nicer header when generating directly for C++, but it should be usable. -- Reading and writing to instances concurrently is not safe. Only reading concurrently is safe. -- documentation is included in the header and available [online](https://docs.rs/servicepoint_binding_c/latest/servicepoint_binding_c/) - -## Everything else - -Look at the main project [README](https://git.berlin.ccc.de/servicepoint/servicepoint/src/branch/main/README.md) for further information. diff --git a/crates/servicepoint_binding_c/build.rs b/crates/servicepoint_binding_c/build.rs deleted file mode 100644 index 93bf703..0000000 --- a/crates/servicepoint_binding_c/build.rs +++ /dev/null @@ -1,33 +0,0 @@ -//! Build script generating the header for the `servicepoint` C library. -//! -//! When the environment variable `SERVICEPOINT_HEADER_OUT` is set, the header is copied there from -//! the out directory. This can be used to use the build script as a command line tool from other -//! build tools. - -use std::{env, fs::copy}; - -use cbindgen::{generate_with_config, Config}; - -fn main() { - let crate_dir = env::var("CARGO_MANIFEST_DIR").unwrap(); - println!("cargo::rerun-if-changed={crate_dir}"); - - let config = - Config::from_file(crate_dir.clone() + "/cbindgen.toml").unwrap(); - - let output_dir = env::var("OUT_DIR").unwrap(); - let header_file = output_dir.clone() + "/servicepoint.h"; - - generate_with_config(crate_dir, config) - .unwrap() - .write_to_file(&header_file); - println!("cargo:include={output_dir}"); - - println!("cargo::rerun-if-env-changed=SERVICEPOINT_HEADER_OUT"); - if let Ok(header_out) = env::var("SERVICEPOINT_HEADER_OUT") { - let header_copy = header_out + "/servicepoint.h"; - println!("cargo:warning=Copying header to {header_copy}"); - copy(header_file, &header_copy).unwrap(); - println!("cargo::rerun-if-changed={header_copy}"); - } -} diff --git a/crates/servicepoint_binding_c/cbindgen.toml b/crates/servicepoint_binding_c/cbindgen.toml deleted file mode 100644 index 7fc0fdf..0000000 --- a/crates/servicepoint_binding_c/cbindgen.toml +++ /dev/null @@ -1,36 +0,0 @@ -language = "C" -include_version = true -cpp_compat = true - -autogen_warning = "/* Warning, this file is autogenerated by cbindgen. Don't modify this manually. */" - -############################ Code Style Options ################################ - -braces = "SameLine" -line_length = 80 -tab_width = 4 -documentation = true -documentation_style = "auto" -documentation_length = "full" -line_endings = "LF" - -############################# Codegen Options ################################## - -style = "type" -usize_is_size_t = true - -# this is needed because otherwise the order in the C# bindings is different on different machines -sort_by = "Name" - -[parse] -parse_deps = false - -[parse.expand] -all_features = true - -[export] -include = [] -exclude = [] - -[enum] -rename_variants = "QualifiedScreamingSnakeCase" diff --git a/crates/servicepoint_binding_c/examples/lang_c/Cargo.toml b/crates/servicepoint_binding_c/examples/lang_c/Cargo.toml deleted file mode 100644 index 2231f3c..0000000 --- a/crates/servicepoint_binding_c/examples/lang_c/Cargo.toml +++ /dev/null @@ -1,14 +0,0 @@ -[package] -name = "lang_c" -version = "0.1.0" -edition = "2021" -publish = false - -[lib] -test = false - -[build-dependencies] -cc = "1.2" - -[dependencies] -servicepoint_binding_c = { path = "../.." } diff --git a/crates/servicepoint_binding_c/examples/lang_c/Makefile b/crates/servicepoint_binding_c/examples/lang_c/Makefile deleted file mode 100644 index 6b15722..0000000 --- a/crates/servicepoint_binding_c/examples/lang_c/Makefile +++ /dev/null @@ -1,34 +0,0 @@ -CC := gcc - -THIS_DIR := $(dir $(realpath $(lastword $(MAKEFILE_LIST)))) -REPO_ROOT := $(THIS_DIR)/../../../.. - -build: out/lang_c - -clean: - rm -r out || true - rm include/servicepoint.h || true - cargo clean - -run: out/lang_c - out/lang_c - -PHONY: build clean dependencies run - -out/lang_c: dependencies src/main.c - mkdir -p out || true - ${CC} src/main.c \ - -I include \ - -L $(REPO_ROOT)/target/release \ - -Wl,-Bstatic -lservicepoint_binding_c \ - -Wl,-Bdynamic -llzma \ - -o out/lang_c - -dependencies: FORCE - mkdir -p include || true - # generate servicepoint header and binary to link against - SERVICEPOINT_HEADER_OUT=$(THIS_DIR)/include cargo build \ - --manifest-path=$(REPO_ROOT)/crates/servicepoint_binding_c/Cargo.toml \ - --release - -FORCE: ; diff --git a/crates/servicepoint_binding_c/examples/lang_c/build.rs b/crates/servicepoint_binding_c/examples/lang_c/build.rs deleted file mode 100644 index 4f92e1d..0000000 --- a/crates/servicepoint_binding_c/examples/lang_c/build.rs +++ /dev/null @@ -1,17 +0,0 @@ -const SP_INCLUDE: &str = "DEP_SERVICEPOINT_INCLUDE"; - -fn main() { - println!("cargo::rerun-if-changed=src/main.c"); - println!("cargo::rerun-if-changed=build.rs"); - println!("cargo::rerun-if-env-changed={SP_INCLUDE}"); - - let sp_include = - std::env::var_os(SP_INCLUDE).unwrap().into_string().unwrap(); - - // this builds a lib, this is only to check that the example compiles - let mut cc = cc::Build::new(); - cc.file("src/main.c"); - cc.include(&sp_include); - cc.opt_level(2); - cc.compile("lang_c"); -} diff --git a/crates/servicepoint_binding_c/examples/lang_c/include/servicepoint.h b/crates/servicepoint_binding_c/examples/lang_c/include/servicepoint.h deleted file mode 100644 index d9cbe57..0000000 --- a/crates/servicepoint_binding_c/examples/lang_c/include/servicepoint.h +++ /dev/null @@ -1,1867 +0,0 @@ -/* Generated with cbindgen:0.27.0 */ - -/* Warning, this file is autogenerated by cbindgen. Don't modify this manually. */ - -#include -#include -#include -#include -#include - -/** - * Count of possible brightness values - */ -#define SP_BRIGHTNESS_LEVELS 12 - -/** - * see [servicepoint::Brightness::MAX] - */ -#define SP_BRIGHTNESS_MAX 11 - -/** - * see [servicepoint::Brightness::MIN] - */ -#define SP_BRIGHTNESS_MIN 0 - -/** - * pixel count on whole screen - */ -#define SP_PIXEL_COUNT (SP_PIXEL_WIDTH * SP_PIXEL_HEIGHT) - -/** - * Display height in pixels - */ -#define SP_PIXEL_HEIGHT (SP_TILE_HEIGHT * SP_TILE_SIZE) - -/** - * Display width in pixels - */ -#define SP_PIXEL_WIDTH (SP_TILE_WIDTH * SP_TILE_SIZE) - -/** - * Display tile count in the y-direction - */ -#define SP_TILE_HEIGHT 20 - -/** - * size of a single tile in one dimension - */ -#define SP_TILE_SIZE 8 - -/** - * Display tile count in the x-direction - */ -#define SP_TILE_WIDTH 56 - -/** - * Specifies the kind of compression to use. - */ -enum SPCompressionCode -#ifdef __cplusplus - : uint16_t -#endif // __cplusplus - { - /** - * no compression - */ - SP_COMPRESSION_CODE_UNCOMPRESSED = 0, - /** - * compress using flate2 with zlib header - */ - SP_COMPRESSION_CODE_ZLIB = 26490, - /** - * compress using bzip2 - */ - SP_COMPRESSION_CODE_BZIP2 = 25210, - /** - * compress using lzma - */ - SP_COMPRESSION_CODE_LZMA = 27770, - /** - * compress using Zstandard - */ - SP_COMPRESSION_CODE_ZSTD = 31347, -}; -#ifndef __cplusplus -typedef uint16_t SPCompressionCode; -#endif // __cplusplus - -/** - * A vector of bits - * - * # Examples - * ```C - * SPBitVec vec = sp_bitvec_new(8); - * sp_bitvec_set(vec, 5, true); - * sp_bitvec_free(vec); - * ``` - */ -typedef struct SPBitVec SPBitVec; - -/** - * A grid of pixels. - * - * # Examples - * - * ```C - * Cp437Grid grid = sp_bitmap_new(8, 3); - * sp_bitmap_fill(grid, true); - * sp_bitmap_set(grid, 0, 0, false); - * sp_bitmap_free(grid); - * ``` - */ -typedef struct SPBitmap SPBitmap; - -/** - * A grid containing brightness values. - * - * # Examples - * ```C - * SPConnection connection = sp_connection_open("127.0.0.1:2342"); - * if (connection == NULL) - * return 1; - * - * SPBrightnessGrid grid = sp_brightness_grid_new(2, 2); - * sp_brightness_grid_set(grid, 0, 0, 0); - * sp_brightness_grid_set(grid, 1, 1, 10); - * - * SPCommand command = sp_command_char_brightness(grid); - * sp_connection_free(connection); - * ``` - */ -typedef struct SPBrightnessGrid SPBrightnessGrid; - -/** - * A C-wrapper for grid containing UTF-8 characters. - * - * As the rust [char] type is not FFI-safe, characters are passed in their UTF-32 form as 32bit unsigned integers. - * - * The encoding is enforced in most cases by the rust standard library - * and will panic when provided with illegal characters. - * - * # Examples - * - * ```C - * CharGrid grid = sp_char_grid_new(4, 3); - * sp_char_grid_fill(grid, '?'); - * sp_char_grid_set(grid, 0, 0, '!'); - * sp_char_grid_free(grid); - * ``` - */ -typedef struct SPCharGrid SPCharGrid; - -/** - * A low-level display command. - * - * This struct and associated functions implement the UDP protocol for the display. - * - * To send a [SPCommand], use a [SPConnection]. - * - * # Examples - * - * ```C - * sp_connection_send_command(connection, sp_command_clear()); - * sp_connection_send_command(connection, sp_command_brightness(5)); - * ``` - * - * [SPConnection]: [crate::SPConnection] - */ -typedef struct SPCommand SPCommand; - -/** - * A connection to the display. - * - * # Examples - * - * ```C - * CConnection connection = sp_connection_open("172.23.42.29:2342"); - * if (connection != NULL) - * sp_connection_send_command(connection, sp_command_clear()); - * ``` - */ -typedef struct SPConnection SPConnection; - -/** - * A C-wrapper for grid containing codepage 437 characters. - * - * The encoding is currently not enforced. - * - * # Examples - * - * ```C - * Cp437Grid grid = sp_cp437_grid_new(4, 3); - * sp_cp437_grid_fill(grid, '?'); - * sp_cp437_grid_set(grid, 0, 0, '!'); - * sp_cp437_grid_free(grid); - * ``` - */ -typedef struct SPCp437Grid SPCp437Grid; - -/** - * The raw packet - */ -typedef struct SPPacket SPPacket; - -/** - * Represents a span of memory (`&mut [u8]` ) as a struct usable by C code. - * - * You should not create an instance of this type in your C code. - * - * # Safety - * - * The caller has to make sure that: - * - * - accesses to the memory pointed to with `start` is never accessed outside `length` - * - the lifetime of the `CByteSlice` does not outlive the memory it points to, as described in - * the function returning this type. - * - an instance of this created from C is never passed to a consuming function, as the rust code - * will try to free the memory of a potentially separate allocator. - */ -typedef struct { - /** - * The start address of the memory - */ - uint8_t *start; - /** - * The amount of memory in bytes - */ - size_t length; -} SPByteSlice; - -#ifdef __cplusplus -extern "C" { -#endif // __cplusplus - -/** - * Clones a [SPBitmap]. - * - * Will never return NULL. - * - * # Panics - * - * - when `bitmap` is NULL - * - * # Safety - * - * The caller has to make sure that: - * - * - `bitmap` points to a valid [SPBitmap] - * - `bitmap` is not written to concurrently - * - the returned instance is freed in some way, either by using a consuming function or - * by explicitly calling `sp_bitmap_free`. - */ -SPBitmap *sp_bitmap_clone(const SPBitmap *bitmap); - -/** - * Sets the state of all pixels in the [SPBitmap]. - * - * # Arguments - * - * - `bitmap`: instance to write to - * - `value`: the value to set all pixels to - * - * # Panics - * - * - when `bitmap` is NULL - * - * # Safety - * - * The caller has to make sure that: - * - * - `bitmap` points to a valid [SPBitmap] - * - `bitmap` is not written to or read from concurrently - */ -void sp_bitmap_fill(SPBitmap *bitmap, bool value); - -/** - * Deallocates a [SPBitmap]. - * - * # Panics - * - * - when `bitmap` is NULL - * - * # Safety - * - * The caller has to make sure that: - * - * - `bitmap` points to a valid [SPBitmap] - * - `bitmap` is not used concurrently or after bitmap call - * - `bitmap` was not passed to another consuming function, e.g. to create a [SPCommand] - * - * [SPCommand]: [crate::SPCommand] - */ -void sp_bitmap_free(SPBitmap *bitmap); - -/** - * Gets the current value at the specified position in the [SPBitmap]. - * - * # Arguments - * - * - `bitmap`: instance to read from - * - `x` and `y`: position of the cell to read - * - * # Panics - * - * - when `bitmap` is NULL - * - when accessing `x` or `y` out of bounds - * - * # Safety - * - * The caller has to make sure that: - * - * - `bitmap` points to a valid [SPBitmap] - * - `bitmap` is not written to concurrently - */ -bool sp_bitmap_get(const SPBitmap *bitmap, size_t x, size_t y); - -/** - * Gets the height in pixels of the [SPBitmap] instance. - * - * # Arguments - * - * - `bitmap`: instance to read from - * - * # Panics - * - * - when `bitmap` is NULL - * - * # Safety - * - * The caller has to make sure that: - * - * - `bitmap` points to a valid [SPBitmap] - */ -size_t sp_bitmap_height(const SPBitmap *bitmap); - -/** - * Loads a [SPBitmap] with the specified dimensions from the provided data. - * - * # Arguments - * - * - `width`: size in pixels in x-direction - * - `height`: size in pixels in y-direction - * - * returns: [SPBitmap] that contains a copy of the provided data. Will never return NULL. - * - * # Panics - * - * - when `data` is NULL - * - when the dimensions and data size do not match exactly. - * - when the width is not dividable by 8 - * - * # Safety - * - * The caller has to make sure that: - * - * - `data` points to a valid memory location of at least `data_length` bytes in size. - * - the returned instance is freed in some way, either by using a consuming function or - * by explicitly calling `sp_bitmap_free`. - */ -SPBitmap *sp_bitmap_load(size_t width, - size_t height, - const uint8_t *data, - size_t data_length); - -/** - * Creates a new [SPBitmap] with the specified dimensions. - * - * # Arguments - * - * - `width`: size in pixels in x-direction - * - `height`: size in pixels in y-direction - * - * returns: [SPBitmap] initialized to all pixels off. Will never return NULL. - * - * # Panics - * - * - when the width is not dividable by 8 - * - * # Safety - * - * The caller has to make sure that: - * - * - the returned instance is freed in some way, either by using a consuming function or - * by explicitly calling `sp_bitmap_free`. - */ -SPBitmap *sp_bitmap_new(size_t width, - size_t height); - -/** - * Creates a new [SPBitmap] with a size matching the screen. - * - * returns: [SPBitmap] initialized to all pixels off. Will never return NULL. - * - * # Safety - * - * The caller has to make sure that: - * - * - the returned instance is freed in some way, either by using a consuming function or - * by explicitly calling [sp_bitmap_free]. - */ -SPBitmap *sp_bitmap_new_screen_sized(void); - -/** - * Sets the value of the specified position in the [SPBitmap]. - * - * # Arguments - * - * - `bitmap`: instance to write to - * - `x` and `y`: position of the cell - * - `value`: the value to write to the cell - * - * returns: old value of the cell - * - * # Panics - * - * - when `bitmap` is NULL - * - when accessing `x` or `y` out of bounds - * - * # Safety - * - * The caller has to make sure that: - * - * - `bitmap` points to a valid [SPBitmap] - * - `bitmap` is not written to or read from concurrently - */ -void sp_bitmap_set(SPBitmap *bitmap, size_t x, size_t y, bool value); - -/** - * Gets an unsafe reference to the data of the [SPBitmap] instance. - * - * # Panics - * - * - when `bitmap` is NULL - * - * # Safety - * - * The caller has to make sure that: - * - * - `bitmap` points to a valid [SPBitmap] - * - the returned memory range is never accessed after the passed [SPBitmap] has been freed - * - the returned memory range is never accessed concurrently, either via the [SPBitmap] or directly - */ -SPByteSlice sp_bitmap_unsafe_data_ref(SPBitmap *bitmap); - -/** - * Gets the width in pixels of the [SPBitmap] instance. - * - * # Arguments - * - * - `bitmap`: instance to read from - * - * # Panics - * - * - when `bitmap` is NULL - * - * # Safety - * - * The caller has to make sure that: - * - * - `bitmap` points to a valid [SPBitmap] - */ -size_t sp_bitmap_width(const SPBitmap *bitmap); - -/** - * Clones a [SPBitVec]. - * - * returns: new [SPBitVec] instance. Will never return NULL. - * - * # Panics - * - * - when `bit_vec` is NULL - * - * # Safety - * - * The caller has to make sure that: - * - * - `bit_vec` points to a valid [SPBitVec] - * - `bit_vec` is not written to concurrently - * - the returned instance is freed in some way, either by using a consuming function or - * by explicitly calling `sp_bitvec_free`. - */ -SPBitVec *sp_bitvec_clone(const SPBitVec *bit_vec); - -/** - * Sets the value of all bits in the [SPBitVec]. - * - * # Arguments - * - * - `bit_vec`: instance to write to - * - `value`: the value to set all bits to - * - * # Panics - * - * - when `bit_vec` is NULL - * - * # Safety - * - * The caller has to make sure that: - * - * - `bit_vec` points to a valid [SPBitVec] - * - `bit_vec` is not written to or read from concurrently - */ -void sp_bitvec_fill(SPBitVec *bit_vec, bool value); - -/** - * Deallocates a [SPBitVec]. - * - * # Panics - * - * - when `but_vec` is NULL - * - * # Safety - * - * The caller has to make sure that: - * - * - `bit_vec` points to a valid [SPBitVec] - * - `bit_vec` is not used concurrently or after this call - * - `bit_vec` was not passed to another consuming function, e.g. to create a [SPCommand] - * - * [SPCommand]: [crate::SPCommand] - */ -void sp_bitvec_free(SPBitVec *bit_vec); - -/** - * Gets the value of a bit from the [SPBitVec]. - * - * # Arguments - * - * - `bit_vec`: instance to read from - * - `index`: the bit index to read - * - * returns: value of the bit - * - * # Panics - * - * - when `bit_vec` is NULL - * - when accessing `index` out of bounds - * - * # Safety - * - * The caller has to make sure that: - * - * - `bit_vec` points to a valid [SPBitVec] - * - `bit_vec` is not written to concurrently - */ -bool sp_bitvec_get(const SPBitVec *bit_vec, size_t index); - -/** - * Returns true if length is 0. - * - * # Arguments - * - * - `bit_vec`: instance to write to - * - * # Panics - * - * - when `bit_vec` is NULL - * - * # Safety - * - * The caller has to make sure that: - * - * - `bit_vec` points to a valid [SPBitVec] - */ -bool sp_bitvec_is_empty(const SPBitVec *bit_vec); - -/** - * Gets the length of the [SPBitVec] in bits. - * - * # Arguments - * - * - `bit_vec`: instance to write to - * - * # Panics - * - * - when `bit_vec` is NULL - * - * # Safety - * - * The caller has to make sure that: - * - * - `bit_vec` points to a valid [SPBitVec] - */ -size_t sp_bitvec_len(const SPBitVec *bit_vec); - -/** - * Interpret the data as a series of bits and load then into a new [SPBitVec] instance. - * - * returns: [SPBitVec] instance containing data. Will never return NULL. - * - * # Panics - * - * - when `data` is NULL - * - * # Safety - * - * The caller has to make sure that: - * - * - `data` points to a valid memory location of at least `data_length` - * bytes in size. - * - the returned instance is freed in some way, either by using a consuming function or - * by explicitly calling `sp_bitvec_free`. - */ -SPBitVec *sp_bitvec_load(const uint8_t *data, - size_t data_length); - -/** - * Creates a new [SPBitVec] instance. - * - * # Arguments - * - * - `size`: size in bits. - * - * returns: [SPBitVec] with all bits set to false. Will never return NULL. - * - * # Panics - * - * - when `size` is not divisible by 8. - * - * # Safety - * - * The caller has to make sure that: - * - * - the returned instance is freed in some way, either by using a consuming function or - * by explicitly calling `sp_bitvec_free`. - */ -SPBitVec *sp_bitvec_new(size_t size); - -/** - * Sets the value of a bit in the [SPBitVec]. - * - * # Arguments - * - * - `bit_vec`: instance to write to - * - `index`: the bit index to edit - * - `value`: the value to set the bit to - * - * # Panics - * - * - when `bit_vec` is NULL - * - when accessing `index` out of bounds - * - * # Safety - * - * The caller has to make sure that: - * - * - `bit_vec` points to a valid [SPBitVec] - * - `bit_vec` is not written to or read from concurrently - */ -void sp_bitvec_set(SPBitVec *bit_vec, size_t index, bool value); - -/** - * Gets an unsafe reference to the data of the [SPBitVec] instance. - * - * # Arguments - * - * - `bit_vec`: instance to write to - * - * # Panics - * - * - when `bit_vec` is NULL - * - * ## Safety - * - * The caller has to make sure that: - * - * - `bit_vec` points to a valid [SPBitVec] - * - the returned memory range is never accessed after the passed [SPBitVec] has been freed - * - the returned memory range is never accessed concurrently, either via the [SPBitVec] or directly - */ -SPByteSlice sp_bitvec_unsafe_data_ref(SPBitVec *bit_vec); - -/** - * Clones a [SPBrightnessGrid]. - * - * # Arguments - * - * - `brightness_grid`: instance to read from - * - * returns: new [SPBrightnessGrid] instance. Will never return NULL. - * - * # Panics - * - * - when `brightness_grid` is NULL - * - * # Safety - * - * The caller has to make sure that: - * - * - `brightness_grid` points to a valid [SPBrightnessGrid] - * - `brightness_grid` is not written to concurrently - * - the returned instance is freed in some way, either by using a consuming function or - * by explicitly calling `sp_brightness_grid_free`. - */ -SPBrightnessGrid *sp_brightness_grid_clone(const SPBrightnessGrid *brightness_grid); - -/** - * Sets the value of all cells in the [SPBrightnessGrid]. - * - * # Arguments - * - * - `brightness_grid`: instance to write to - * - `value`: the value to set all cells to - * - * # Panics - * - * - when `brightness_grid` is NULL - * - When providing an invalid brightness value - * - * # Safety - * - * The caller has to make sure that: - * - * - `brightness_grid` points to a valid [SPBrightnessGrid] - * - `brightness_grid` is not written to or read from concurrently - */ -void sp_brightness_grid_fill(SPBrightnessGrid *brightness_grid, uint8_t value); - -/** - * Deallocates a [SPBrightnessGrid]. - * - * # Arguments - * - * - `brightness_grid`: instance to read from - * - * # Panics - * - * - when `brightness_grid` is NULL - * - * # Safety - * - * The caller has to make sure that: - * - * - `brightness_grid` points to a valid [SPBrightnessGrid] - * - `brightness_grid` is not used concurrently or after this call - * - `brightness_grid` was not passed to another consuming function, e.g. to create a [SPCommand] - * - * [SPCommand]: [crate::SPCommand] - */ -void sp_brightness_grid_free(SPBrightnessGrid *brightness_grid); - -/** - * Gets the current value at the specified position. - * - * # Arguments - * - * - `brightness_grid`: instance to read from - * - `x` and `y`: position of the cell to read - * - * returns: value at position - * - * # Panics - * - * - when `brightness_grid` is NULL - * - When accessing `x` or `y` out of bounds. - * - * # Safety - * - * The caller has to make sure that: - * - * - `brightness_grid` points to a valid [SPBrightnessGrid] - * - `brightness_grid` is not written to concurrently - */ -uint8_t sp_brightness_grid_get(const SPBrightnessGrid *brightness_grid, - size_t x, - size_t y); - -/** - * Gets the height of the [SPBrightnessGrid] instance. - * - * # Arguments - * - * - `brightness_grid`: instance to read from - * - * returns: height - * - * # Panics - * - * - when `brightness_grid` is NULL - * - * # Safety - * - * The caller has to make sure that: - * - * - `brightness_grid` points to a valid [SPBrightnessGrid] - */ -size_t sp_brightness_grid_height(const SPBrightnessGrid *brightness_grid); - -/** - * Loads a [SPBrightnessGrid] with the specified dimensions from the provided data. - * - * returns: new [SPBrightnessGrid] instance. Will never return NULL. - * - * # Panics - * - * - when `data` is NULL - * - when the provided `data_length` does not match `height` and `width` - * - * # Safety - * - * The caller has to make sure that: - * - * - `data` points to a valid memory location of at least `data_length` - * bytes in size. - * - the returned instance is freed in some way, either by using a consuming function or - * by explicitly calling `sp_brightness_grid_free`. - */ -SPBrightnessGrid *sp_brightness_grid_load(size_t width, - size_t height, - const uint8_t *data, - size_t data_length); - -/** - * Creates a new [SPBrightnessGrid] with the specified dimensions. - * - * returns: [SPBrightnessGrid] initialized to 0. Will never return NULL. - * - * # Safety - * - * The caller has to make sure that: - * - * - the returned instance is freed in some way, either by using a consuming function or - * by explicitly calling `sp_brightness_grid_free`. - */ -SPBrightnessGrid *sp_brightness_grid_new(size_t width, - size_t height); - -/** - * Sets the value of the specified position in the [SPBrightnessGrid]. - * - * # Arguments - * - * - `brightness_grid`: instance to write to - * - `x` and `y`: position of the cell - * - `value`: the value to write to the cell - * - * returns: old value of the cell - * - * # Panics - * - * - when `brightness_grid` is NULL - * - When accessing `x` or `y` out of bounds. - * - When providing an invalid brightness value - * - * # Safety - * - * The caller has to make sure that: - * - * - `brightness_grid` points to a valid [SPBrightnessGrid] - * - `brightness_grid` is not written to or read from concurrently - */ -void sp_brightness_grid_set(SPBrightnessGrid *brightness_grid, - size_t x, - size_t y, - uint8_t value); - -/** - * Gets an unsafe reference to the data of the [SPBrightnessGrid] instance. - * - * # Arguments - * - * - `brightness_grid`: instance to read from - * - * returns: slice of bytes underlying the `brightness_grid`. - * - * # Panics - * - * - when `brightness_grid` is NULL - * - * # Safety - * - * The caller has to make sure that: - * - * - `brightness_grid` points to a valid [SPBrightnessGrid] - * - the returned memory range is never accessed after the passed [SPBrightnessGrid] has been freed - * - the returned memory range is never accessed concurrently, either via the [SPBrightnessGrid] or directly - */ -SPByteSlice sp_brightness_grid_unsafe_data_ref(SPBrightnessGrid *brightness_grid); - -/** - * Gets the width of the [SPBrightnessGrid] instance. - * - * # Arguments - * - * - `brightness_grid`: instance to read from - * - * returns: width - * - * # Panics - * - * - when `brightness_grid` is NULL - * - * # Safety - * - * The caller has to make sure that: - * - * - `brightness_grid` points to a valid [SPBrightnessGrid] - */ -size_t sp_brightness_grid_width(const SPBrightnessGrid *brightness_grid); - -/** - * Clones a [SPCharGrid]. - * - * Will never return NULL. - * - * # Panics - * - * - when `char_grid` is NULL - * - * # Safety - * - * The caller has to make sure that: - * - * - `char_grid` points to a valid [SPCharGrid] - * - `char_grid` is not written to concurrently - * - the returned instance is freed in some way, either by using a consuming function or - * by explicitly calling `sp_char_grid_free`. - */ -SPCharGrid *sp_char_grid_clone(const SPCharGrid *char_grid); - -/** - * Sets the value of all cells in the [SPCharGrid]. - * - * # Arguments - * - * - `char_grid`: instance to write to - * - `value`: the value to set all cells to - * - * # Panics - * - * - when `char_grid` is NULL - * - * # Safety - * - * The caller has to make sure that: - * - * - `char_grid` points to a valid [SPCharGrid] - * - `char_grid` is not written to or read from concurrently - */ -void sp_char_grid_fill(SPCharGrid *char_grid, uint32_t value); - -/** - * Deallocates a [SPCharGrid]. - * - * # Panics - * - * - when `char_grid` is NULL - * - * # Safety - * - * The caller has to make sure that: - * - * - `char_grid` points to a valid [SPCharGrid] - * - `char_grid` is not used concurrently or after char_grid call - * - `char_grid` was not passed to another consuming function, e.g. to create a [SPCommand] - * - * [SPCommand]: [crate::SPCommand] - */ -void sp_char_grid_free(SPCharGrid *char_grid); - -/** - * Gets the current value at the specified position. - * - * # Arguments - * - * - `char_grid`: instance to read from - * - `x` and `y`: position of the cell to read - * - * # Panics - * - * - when `char_grid` is NULL - * - when accessing `x` or `y` out of bounds - * - * # Safety - * - * The caller has to make sure that: - * - * - `char_grid` points to a valid [SPCharGrid] - * - `char_grid` is not written to concurrently - */ -uint32_t sp_char_grid_get(const SPCharGrid *char_grid, size_t x, size_t y); - -/** - * Gets the height of the [SPCharGrid] instance. - * - * # Arguments - * - * - `char_grid`: instance to read from - * - * # Panics - * - * - when `char_grid` is NULL - * - * # Safety - * - * The caller has to make sure that: - * - * - `char_grid` points to a valid [SPCharGrid] - */ -size_t sp_char_grid_height(const SPCharGrid *char_grid); - -/** - * Loads a [SPCharGrid] with the specified dimensions from the provided data. - * - * Will never return NULL. - * - * # Panics - * - * - when `data` is NULL - * - when the provided `data_length` does not match `height` and `width` - * - when `data` is not valid UTF-8 - * - * # Safety - * - * The caller has to make sure that: - * - * - `data` points to a valid memory location of at least `data_length` - * bytes in size. - * - the returned instance is freed in some way, either by using a consuming function or - * by explicitly calling `sp_char_grid_free`. - */ -SPCharGrid *sp_char_grid_load(size_t width, - size_t height, - const uint8_t *data, - size_t data_length); - -/** - * Creates a new [SPCharGrid] with the specified dimensions. - * - * returns: [SPCharGrid] initialized to 0. Will never return NULL. - * - * # Safety - * - * The caller has to make sure that: - * - * - the returned instance is freed in some way, either by using a consuming function or - * by explicitly calling `sp_char_grid_free`. - */ -SPCharGrid *sp_char_grid_new(size_t width, - size_t height); - -/** - * Sets the value of the specified position in the [SPCharGrid]. - * - * # Arguments - * - * - `char_grid`: instance to write to - * - `x` and `y`: position of the cell - * - `value`: the value to write to the cell - * - * returns: old value of the cell - * - * # Panics - * - * - when `char_grid` is NULL - * - when accessing `x` or `y` out of bounds - * - * # Safety - * - * The caller has to make sure that: - * - * - `char_grid` points to a valid [SPBitVec] - * - `char_grid` is not written to or read from concurrently - * - * [SPBitVec]: [crate::SPBitVec] - */ -void sp_char_grid_set(SPCharGrid *char_grid, - size_t x, - size_t y, - uint32_t value); - -/** - * Gets the width of the [SPCharGrid] instance. - * - * # Arguments - * - * - `char_grid`: instance to read from - * - * # Panics - * - * - when `char_grid` is NULL - * - * # Safety - * - * The caller has to make sure that: - * - * - `char_grid` points to a valid [SPCharGrid] - */ -size_t sp_char_grid_width(const SPCharGrid *char_grid); - -/** - * Set pixel data starting at the pixel offset on screen. - * - * The screen will continuously overwrite more pixel data without regarding the offset, meaning - * once the starting row is full, overwriting will continue on column 0. - * - * The contained [SPBitVec] is always uncompressed. - * - * The passed [SPBitVec] gets consumed. - * - * Returns: a new [servicepoint::Command::BitmapLinear] instance. Will never return NULL. - * - * # Panics - * - * - when `bit_vec` is null - * - when `compression_code` is not a valid value - * - * # Safety - * - * The caller has to make sure that: - * - * - `bit_vec` points to a valid instance of [SPBitVec] - * - `bit_vec` is not used concurrently or after this call - * - `compression` matches one of the allowed enum values - * - the returned [SPCommand] instance is freed in some way, either by using a consuming function or - * by explicitly calling `sp_command_free`. - */ -SPCommand *sp_command_bitmap_linear(size_t offset, - SPBitVec *bit_vec, - SPCompressionCode compression); - -/** - * Set pixel data according to an and-mask starting at the offset. - * - * The screen will continuously overwrite more pixel data without regarding the offset, meaning - * once the starting row is full, overwriting will continue on column 0. - * - * The contained [SPBitVec] is always uncompressed. - * - * The passed [SPBitVec] gets consumed. - * - * Returns: a new [servicepoint::Command::BitmapLinearAnd] instance. Will never return NULL. - * - * # Panics - * - * - when `bit_vec` is null - * - when `compression_code` is not a valid value - * - * # Safety - * - * The caller has to make sure that: - * - * - `bit_vec` points to a valid instance of [SPBitVec] - * - `bit_vec` is not used concurrently or after this call - * - `compression` matches one of the allowed enum values - * - the returned [SPCommand] instance is freed in some way, either by using a consuming function or - * by explicitly calling `sp_command_free`. - */ -SPCommand *sp_command_bitmap_linear_and(size_t offset, - SPBitVec *bit_vec, - SPCompressionCode compression); - -/** - * Set pixel data according to an or-mask starting at the offset. - * - * The screen will continuously overwrite more pixel data without regarding the offset, meaning - * once the starting row is full, overwriting will continue on column 0. - * - * The contained [SPBitVec] is always uncompressed. - * - * The passed [SPBitVec] gets consumed. - * - * Returns: a new [servicepoint::Command::BitmapLinearOr] instance. Will never return NULL. - * - * # Panics - * - * - when `bit_vec` is null - * - when `compression_code` is not a valid value - * - * # Safety - * - * The caller has to make sure that: - * - * - `bit_vec` points to a valid instance of [SPBitVec] - * - `bit_vec` is not used concurrently or after this call - * - `compression` matches one of the allowed enum values - * - the returned [SPCommand] instance is freed in some way, either by using a consuming function or - * by explicitly calling `sp_command_free`. - */ -SPCommand *sp_command_bitmap_linear_or(size_t offset, - SPBitVec *bit_vec, - SPCompressionCode compression); - -/** - * Sets a window of pixels to the specified values. - * - * The passed [SPBitmap] gets consumed. - * - * Returns: a new [servicepoint::Command::BitmapLinearWin] instance. Will never return NULL. - * - * # Panics - * - * - when `bitmap` is null - * - when `compression_code` is not a valid value - * - * # Safety - * - * The caller has to make sure that: - * - * - `bitmap` points to a valid instance of [SPBitmap] - * - `bitmap` is not used concurrently or after this call - * - `compression` matches one of the allowed enum values - * - the returned [SPCommand] instance is freed in some way, either by using a consuming function or - * by explicitly calling `sp_command_free`. - */ -SPCommand *sp_command_bitmap_linear_win(size_t x, - size_t y, - SPBitmap *bitmap, - SPCompressionCode compression_code); - -/** - * Set pixel data according to a xor-mask starting at the offset. - * - * The screen will continuously overwrite more pixel data without regarding the offset, meaning - * once the starting row is full, overwriting will continue on column 0. - * - * The contained [SPBitVec] is always uncompressed. - * - * The passed [SPBitVec] gets consumed. - * - * Returns: a new [servicepoint::Command::BitmapLinearXor] instance. Will never return NULL. - * - * # Panics - * - * - when `bit_vec` is null - * - when `compression_code` is not a valid value - * - * # Safety - * - * The caller has to make sure that: - * - * - `bit_vec` points to a valid instance of [SPBitVec] - * - `bit_vec` is not used concurrently or after this call - * - `compression` matches one of the allowed enum values - * - the returned [SPCommand] instance is freed in some way, either by using a consuming function or - * by explicitly calling `sp_command_free`. - */ -SPCommand *sp_command_bitmap_linear_xor(size_t offset, - SPBitVec *bit_vec, - SPCompressionCode compression); - -/** - * Set the brightness of all tiles to the same value. - * - * Returns: a new [servicepoint::Command::Brightness] instance. Will never return NULL. - * - * # Panics - * - * - When the provided brightness value is out of range (0-11). - * - * # Safety - * - * The caller has to make sure that: - * - * - the returned [SPCommand] instance is freed in some way, either by using a consuming function or - * by explicitly calling `sp_command_free`. - */ -SPCommand *sp_command_brightness(uint8_t brightness); - -/** - * Set the brightness of individual tiles in a rectangular area of the display. - * - * The passed [SPBrightnessGrid] gets consumed. - * - * Returns: a new [servicepoint::Command::CharBrightness] instance. Will never return NULL. - * - * # Panics - * - * - when `grid` is NULL - * - * # Safety - * - * The caller has to make sure that: - * - * - `grid` points to a valid instance of [SPBrightnessGrid] - * - `grid` is not used concurrently or after this call - * - the returned [SPCommand] instance is freed in some way, either by using a consuming function or - * by explicitly calling `sp_command_free`. - */ -SPCommand *sp_command_char_brightness(size_t x, - size_t y, - SPBrightnessGrid *grid); - -/** - * Set all pixels to the off state. - * - * Does not affect brightness. - * - * Returns: a new [servicepoint::Command::Clear] instance. Will never return NULL. - * - * # Examples - * - * ```C - * sp_connection_send_command(connection, sp_command_clear()); - * ``` - * - * # Safety - * - * The caller has to make sure that: - * - * - the returned [SPCommand] instance is freed in some way, either by using a consuming function or - * by explicitly calling `sp_command_free`. - */ -SPCommand *sp_command_clear(void); - -/** - * Clones a [SPCommand] instance. - * - * returns: new [SPCommand] instance. Will never return NULL. - * - * # Panics - * - * - when `command` is NULL - * - * # Safety - * - * The caller has to make sure that: - * - * - `command` points to a valid instance of [SPCommand] - * - `command` is not written to concurrently - * - the returned [SPCommand] instance is freed in some way, either by using a consuming function or - * by explicitly calling `sp_command_free`. - */ -SPCommand *sp_command_clone(const SPCommand *command); - -/** - * Show codepage 437 encoded text on the screen. - * - * The passed [SPCp437Grid] gets consumed. - * - * Returns: a new [servicepoint::Command::Cp437Data] instance. Will never return NULL. - * - * # Panics - * - * - when `grid` is null - * - * # Safety - * - * The caller has to make sure that: - * - * - `grid` points to a valid instance of [SPCp437Grid] - * - `grid` is not used concurrently or after this call - * - the returned [SPCommand] instance is freed in some way, either by using a consuming function or - * by explicitly calling `sp_command_free`. - */ -SPCommand *sp_command_cp437_data(size_t x, - size_t y, - SPCp437Grid *grid); - -/** - * A yet-to-be-tested command. - * - * Returns: a new [servicepoint::Command::FadeOut] instance. Will never return NULL. - * - * # Safety - * - * The caller has to make sure that: - * - * - the returned [SPCommand] instance is freed in some way, either by using a consuming function or - * by explicitly calling `sp_command_free`. - */ -SPCommand *sp_command_fade_out(void); - -/** - * Deallocates a [SPCommand]. - * - * # Examples - * - * ```C - * SPCommand c = sp_command_clear(); - * sp_command_free(c); - * ``` - * - * # Panics - * - * - when `command` is NULL - * - * # Safety - * - * The caller has to make sure that: - * - * - `command` points to a valid [SPCommand] - * - `command` is not used concurrently or after this call - * - `command` was not passed to another consuming function, e.g. to create a [SPPacket] - */ -void sp_command_free(SPCommand *command); - -/** - * Kills the udp daemon on the display, which usually results in a restart. - * - * Please do not send this in your normal program flow. - * - * Returns: a new [servicepoint::Command::HardReset] instance. Will never return NULL. - * - * # Safety - * - * The caller has to make sure that: - * - * - the returned [SPCommand] instance is freed in some way, either by using a consuming function or - * by explicitly calling `sp_command_free`. - */ -SPCommand *sp_command_hard_reset(void); - -/** - * Tries to turn a [SPPacket] into a [SPCommand]. - * - * The packet is deallocated in the process. - * - * Returns: pointer to new [SPCommand] instance or NULL if parsing failed. - * - * # Panics - * - * - when `packet` is NULL - * - * # Safety - * - * The caller has to make sure that: - * - * - [SPPacket] points to a valid instance of [SPPacket] - * - [SPPacket] is not used concurrently or after this call - * - the result is checked for NULL - * - the returned [SPCommand] instance is freed in some way, either by using a consuming function or - * by explicitly calling `sp_command_free`. - */ -SPCommand *sp_command_try_from_packet(SPPacket *packet); - -/** - * Show UTF-8 encoded text on the screen. - * - * The passed [SPCharGrid] gets consumed. - * - * Returns: a new [servicepoint::Command::Utf8Data] instance. Will never return NULL. - * - * # Panics - * - * - when `grid` is null - * - * # Safety - * - * The caller has to make sure that: - * - * - `grid` points to a valid instance of [SPCharGrid] - * - `grid` is not used concurrently or after this call - * - the returned [SPCommand] instance is freed in some way, either by using a consuming function or - * by explicitly calling `sp_command_free`. - */ -SPCommand *sp_command_utf8_data(size_t x, - size_t y, - SPCharGrid *grid); - -/** - * Creates a new instance of [SPConnection] for testing that does not actually send anything. - * - * returns: a new instance. Will never return NULL. - * - * # Safety - * - * The caller has to make sure that: - * - * - the returned instance is freed in some way, either by using a consuming function or - * by explicitly calling `sp_connection_free`. - */ -SPConnection *sp_connection_fake(void); - -/** - * Closes and deallocates a [SPConnection]. - * - * # Panics - * - * - when `connection` is NULL - * - * # Safety - * - * The caller has to make sure that: - * - * - `connection` points to a valid [SPConnection] - * - `connection` is not used concurrently or after this call - */ -void sp_connection_free(SPConnection *connection); - -/** - * Creates a new instance of [SPConnection]. - * - * returns: NULL if connection fails, or connected instance - * - * # Panics - * - * - when `host` is null or an invalid host - * - * # Safety - * - * The caller has to make sure that: - * - * - the returned instance is freed in some way, either by using a consuming function or - * by explicitly calling `sp_connection_free`. - */ -SPConnection *sp_connection_open(const char *host); - -/** - * Sends a [SPCommand] to the display using the [SPConnection]. - * - * The passed `command` gets consumed. - * - * returns: true in case of success - * - * # Panics - * - * - when `connection` is NULL - * - when `command` is NULL - * - * # Safety - * - * The caller has to make sure that: - * - * - `connection` points to a valid instance of [SPConnection] - * - `command` points to a valid instance of [SPPacket] - * - `command` is not used concurrently or after this call - */ -bool sp_connection_send_command(const SPConnection *connection, - SPCommand *command); - -/** - * Sends a [SPPacket] to the display using the [SPConnection]. - * - * The passed `packet` gets consumed. - * - * returns: true in case of success - * - * # Panics - * - * - when `connection` is NULL - * - when `packet` is NULL - * - * # Safety - * - * The caller has to make sure that: - * - * - `connection` points to a valid instance of [SPConnection] - * - `packet` points to a valid instance of [SPPacket] - * - `packet` is not used concurrently or after this call - */ -bool sp_connection_send_packet(const SPConnection *connection, - SPPacket *packet); - -/** - * Clones a [SPCp437Grid]. - * - * Will never return NULL. - * - * # Panics - * - * - when `cp437_grid` is NULL - * - * # Safety - * - * The caller has to make sure that: - * - * - `cp437_grid` points to a valid [SPCp437Grid] - * - `cp437_grid` is not written to concurrently - * - the returned instance is freed in some way, either by using a consuming function or - * by explicitly calling `sp_cp437_grid_free`. - */ -SPCp437Grid *sp_cp437_grid_clone(const SPCp437Grid *cp437_grid); - -/** - * Sets the value of all cells in the [SPCp437Grid]. - * - * # Arguments - * - * - `cp437_grid`: instance to write to - * - `value`: the value to set all cells to - * - * # Panics - * - * - when `cp437_grid` is NULL - * - * # Safety - * - * The caller has to make sure that: - * - * - `cp437_grid` points to a valid [SPCp437Grid] - * - `cp437_grid` is not written to or read from concurrently - */ -void sp_cp437_grid_fill(SPCp437Grid *cp437_grid, uint8_t value); - -/** - * Deallocates a [SPCp437Grid]. - * - * # Panics - * - * - when `cp437_grid` is NULL - * - * # Safety - * - * The caller has to make sure that: - * - * - `cp437_grid` points to a valid [SPCp437Grid] - * - `cp437_grid` is not used concurrently or after cp437_grid call - * - `cp437_grid` was not passed to another consuming function, e.g. to create a [SPCommand] - * - * [SPCommand]: [crate::SPCommand] - */ -void sp_cp437_grid_free(SPCp437Grid *cp437_grid); - -/** - * Gets the current value at the specified position. - * - * # Arguments - * - * - `cp437_grid`: instance to read from - * - `x` and `y`: position of the cell to read - * - * # Panics - * - * - when `cp437_grid` is NULL - * - when accessing `x` or `y` out of bounds - * - * # Safety - * - * The caller has to make sure that: - * - * - `cp437_grid` points to a valid [SPCp437Grid] - * - `cp437_grid` is not written to concurrently - */ -uint8_t sp_cp437_grid_get(const SPCp437Grid *cp437_grid, size_t x, size_t y); - -/** - * Gets the height of the [SPCp437Grid] instance. - * - * # Arguments - * - * - `cp437_grid`: instance to read from - * - * # Panics - * - * - when `cp437_grid` is NULL - * - * # Safety - * - * The caller has to make sure that: - * - * - `cp437_grid` points to a valid [SPCp437Grid] - */ -size_t sp_cp437_grid_height(const SPCp437Grid *cp437_grid); - -/** - * Loads a [SPCp437Grid] with the specified dimensions from the provided data. - * - * Will never return NULL. - * - * # Panics - * - * - when `data` is NULL - * - when the provided `data_length` does not match `height` and `width` - * - * # Safety - * - * The caller has to make sure that: - * - * - `data` points to a valid memory location of at least `data_length` - * bytes in size. - * - the returned instance is freed in some way, either by using a consuming function or - * by explicitly calling `sp_cp437_grid_free`. - */ -SPCp437Grid *sp_cp437_grid_load(size_t width, - size_t height, - const uint8_t *data, - size_t data_length); - -/** - * Creates a new [SPCp437Grid] with the specified dimensions. - * - * returns: [SPCp437Grid] initialized to 0. Will never return NULL. - * - * # Safety - * - * The caller has to make sure that: - * - * - the returned instance is freed in some way, either by using a consuming function or - * by explicitly calling `sp_cp437_grid_free`. - */ -SPCp437Grid *sp_cp437_grid_new(size_t width, - size_t height); - -/** - * Sets the value of the specified position in the [SPCp437Grid]. - * - * # Arguments - * - * - `cp437_grid`: instance to write to - * - `x` and `y`: position of the cell - * - `value`: the value to write to the cell - * - * returns: old value of the cell - * - * # Panics - * - * - when `cp437_grid` is NULL - * - when accessing `x` or `y` out of bounds - * - * # Safety - * - * The caller has to make sure that: - * - * - `cp437_grid` points to a valid [SPBitVec] - * - `cp437_grid` is not written to or read from concurrently - * - * [SPBitVec]: [crate::SPBitVec] - */ -void sp_cp437_grid_set(SPCp437Grid *cp437_grid, - size_t x, - size_t y, - uint8_t value); - -/** - * Gets an unsafe reference to the data of the [SPCp437Grid] instance. - * - * Will never return NULL. - * - * # Panics - * - * - when `cp437_grid` is NULL - * - * ## Safety - * - * The caller has to make sure that: - * - * - `cp437_grid` points to a valid [SPCp437Grid] - * - the returned memory range is never accessed after the passed [SPCp437Grid] has been freed - * - the returned memory range is never accessed concurrently, either via the [SPCp437Grid] or directly - */ -SPByteSlice sp_cp437_grid_unsafe_data_ref(SPCp437Grid *cp437_grid); - -/** - * Gets the width of the [SPCp437Grid] instance. - * - * # Arguments - * - * - `cp437_grid`: instance to read from - * - * # Panics - * - * - when `cp437_grid` is NULL - * - * # Safety - * - * The caller has to make sure that: - * - * - `cp437_grid` points to a valid [SPCp437Grid] - */ -size_t sp_cp437_grid_width(const SPCp437Grid *cp437_grid); - -/** - * Clones a [SPPacket]. - * - * Will never return NULL. - * - * # Panics - * - * - when `packet` is NULL - * - * # Safety - * - * The caller has to make sure that: - * - * - `packet` points to a valid [SPPacket] - * - `packet` is not written to concurrently - * - the returned instance is freed in some way, either by using a consuming function or - * by explicitly calling `sp_packet_free`. - */ -SPPacket *sp_packet_clone(const SPPacket *packet); - -/** - * Deallocates a [SPPacket]. - * - * # Panics - * - * - when `packet` is NULL - * - * # Safety - * - * The caller has to make sure that: - * - * - `packet` points to a valid [SPPacket] - * - `packet` is not used concurrently or after this call - */ -void sp_packet_free(SPPacket *packet); - -/** - * Turns a [SPCommand] into a [SPPacket]. - * The [SPCommand] gets consumed. - * - * Will never return NULL. - * - * # Panics - * - * - when `command` is NULL - * - * # Safety - * - * The caller has to make sure that: - * - * - [SPCommand] points to a valid instance of [SPCommand] - * - [SPCommand] is not used concurrently or after this call - * - the returned [SPPacket] instance is freed in some way, either by using a consuming function or - * by explicitly calling `sp_packet_free`. - */ -SPPacket *sp_packet_from_command(SPCommand *command); - -/** - * Creates a raw [SPPacket] from parts. - * - * # Arguments - * - * - `command_code` specifies which command this packet contains - * - `a`, `b`, `c` and `d` are command-specific header values - * - `payload` is the optional data that is part of the command - * - `payload_len` is the size of the payload - * - * returns: new instance. Will never return null. - * - * # Panics - * - * - when `payload` is null, but `payload_len` is not zero - * - when `payload_len` is zero, but `payload` is nonnull - * - * # Safety - * - * The caller has to make sure that: - * - * - `payload` points to a valid memory region of at least `payload_len` bytes - * - `payload` is not written to concurrently - * - the returned [SPPacket] instance is freed in some way, either by using a consuming function or - * by explicitly calling [sp_packet_free]. - */ -SPPacket *sp_packet_from_parts(uint16_t command_code, - uint16_t a, - uint16_t b, - uint16_t c, - uint16_t d, - const uint8_t *payload, - size_t payload_len); - -/** - * Tries to load a [SPPacket] from the passed array with the specified length. - * - * returns: NULL in case of an error, pointer to the allocated packet otherwise - * - * # Panics - * - * - when `data` is NULL - * - * # Safety - * - * The caller has to make sure that: - * - * - `data` points to a valid memory region of at least `length` bytes - * - `data` is not written to concurrently - * - the returned [SPPacket] instance is freed in some way, either by using a consuming function or - * by explicitly calling `sp_packet_free`. - */ -SPPacket *sp_packet_try_load(const uint8_t *data, - size_t length); - -#ifdef __cplusplus -} // extern "C" -#endif // __cplusplus diff --git a/crates/servicepoint_binding_c/examples/lang_c/src/lib.rs b/crates/servicepoint_binding_c/examples/lang_c/src/lib.rs deleted file mode 100644 index 8b13789..0000000 --- a/crates/servicepoint_binding_c/examples/lang_c/src/lib.rs +++ /dev/null @@ -1 +0,0 @@ - diff --git a/crates/servicepoint_binding_c/examples/lang_c/src/main.c b/crates/servicepoint_binding_c/examples/lang_c/src/main.c deleted file mode 100644 index 1454804..0000000 --- a/crates/servicepoint_binding_c/examples/lang_c/src/main.c +++ /dev/null @@ -1,17 +0,0 @@ -#include -#include "servicepoint.h" - -int main(void) { - SPConnection *connection = sp_connection_open("localhost:2342"); - if (connection == NULL) - return 1; - - SPBitmap *pixels = sp_bitmap_new(SP_PIXEL_WIDTH, SP_PIXEL_HEIGHT); - sp_bitmap_fill(pixels, true); - - SPCommand *command = sp_command_bitmap_linear_win(0, 0, pixels, SP_COMPRESSION_CODE_UNCOMPRESSED); - sp_connection_send_command(connection, command); - - sp_connection_free(connection); - return 0; -} diff --git a/crates/servicepoint_binding_c/src/bitmap.rs b/crates/servicepoint_binding_c/src/bitmap.rs deleted file mode 100644 index 3313385..0000000 --- a/crates/servicepoint_binding_c/src/bitmap.rs +++ /dev/null @@ -1,296 +0,0 @@ -//! C functions for interacting with [SPBitmap]s -//! -//! prefix `sp_bitmap_` - -use servicepoint::{DataRef, Grid}; -use std::ptr::NonNull; - -use crate::byte_slice::SPByteSlice; - -/// A grid of pixels. -/// -/// # Examples -/// -/// ```C -/// Cp437Grid grid = sp_bitmap_new(8, 3); -/// sp_bitmap_fill(grid, true); -/// sp_bitmap_set(grid, 0, 0, false); -/// sp_bitmap_free(grid); -/// ``` -pub struct SPBitmap(pub(crate) servicepoint::Bitmap); - -/// Creates a new [SPBitmap] with the specified dimensions. -/// -/// # Arguments -/// -/// - `width`: size in pixels in x-direction -/// - `height`: size in pixels in y-direction -/// -/// returns: [SPBitmap] initialized to all pixels off. Will never return NULL. -/// -/// # Panics -/// -/// - when the width is not dividable by 8 -/// -/// # Safety -/// -/// The caller has to make sure that: -/// -/// - the returned instance is freed in some way, either by using a consuming function or -/// by explicitly calling `sp_bitmap_free`. -#[no_mangle] -pub unsafe extern "C" fn sp_bitmap_new( - width: usize, - height: usize, -) -> NonNull { - let result = Box::new(SPBitmap(servicepoint::Bitmap::new(width, height))); - NonNull::from(Box::leak(result)) -} - -/// Creates a new [SPBitmap] with a size matching the screen. -/// -/// returns: [SPBitmap] initialized to all pixels off. Will never return NULL. -/// -/// # Safety -/// -/// The caller has to make sure that: -/// -/// - the returned instance is freed in some way, either by using a consuming function or -/// by explicitly calling [sp_bitmap_free]. -#[no_mangle] -pub unsafe extern "C" fn sp_bitmap_new_screen_sized() -> NonNull { - let result = Box::new(SPBitmap(servicepoint::Bitmap::max_sized())); - NonNull::from(Box::leak(result)) -} - -/// Loads a [SPBitmap] with the specified dimensions from the provided data. -/// -/// # Arguments -/// -/// - `width`: size in pixels in x-direction -/// - `height`: size in pixels in y-direction -/// -/// returns: [SPBitmap] that contains a copy of the provided data. Will never return NULL. -/// -/// # Panics -/// -/// - when `data` is NULL -/// - when the dimensions and data size do not match exactly. -/// - when the width is not dividable by 8 -/// -/// # Safety -/// -/// The caller has to make sure that: -/// -/// - `data` points to a valid memory location of at least `data_length` bytes in size. -/// - the returned instance is freed in some way, either by using a consuming function or -/// by explicitly calling `sp_bitmap_free`. -#[no_mangle] -pub unsafe extern "C" fn sp_bitmap_load( - width: usize, - height: usize, - data: *const u8, - data_length: usize, -) -> NonNull { - assert!(!data.is_null()); - let data = std::slice::from_raw_parts(data, data_length); - let result = - Box::new(SPBitmap(servicepoint::Bitmap::load(width, height, data))); - NonNull::from(Box::leak(result)) -} - -/// Clones a [SPBitmap]. -/// -/// Will never return NULL. -/// -/// # Panics -/// -/// - when `bitmap` is NULL -/// -/// # Safety -/// -/// The caller has to make sure that: -/// -/// - `bitmap` points to a valid [SPBitmap] -/// - `bitmap` is not written to concurrently -/// - the returned instance is freed in some way, either by using a consuming function or -/// by explicitly calling `sp_bitmap_free`. -#[no_mangle] -pub unsafe extern "C" fn sp_bitmap_clone( - bitmap: *const SPBitmap, -) -> NonNull { - assert!(!bitmap.is_null()); - let result = Box::new(SPBitmap((*bitmap).0.clone())); - NonNull::from(Box::leak(result)) -} - -/// Deallocates a [SPBitmap]. -/// -/// # Panics -/// -/// - when `bitmap` is NULL -/// -/// # Safety -/// -/// The caller has to make sure that: -/// -/// - `bitmap` points to a valid [SPBitmap] -/// - `bitmap` is not used concurrently or after bitmap call -/// - `bitmap` was not passed to another consuming function, e.g. to create a [SPCommand] -/// -/// [SPCommand]: [crate::SPCommand] -#[no_mangle] -pub unsafe extern "C" fn sp_bitmap_free(bitmap: *mut SPBitmap) { - assert!(!bitmap.is_null()); - _ = Box::from_raw(bitmap); -} - -/// Gets the current value at the specified position in the [SPBitmap]. -/// -/// # Arguments -/// -/// - `bitmap`: instance to read from -/// - `x` and `y`: position of the cell to read -/// -/// # Panics -/// -/// - when `bitmap` is NULL -/// - when accessing `x` or `y` out of bounds -/// -/// # Safety -/// -/// The caller has to make sure that: -/// -/// - `bitmap` points to a valid [SPBitmap] -/// - `bitmap` is not written to concurrently -#[no_mangle] -pub unsafe extern "C" fn sp_bitmap_get( - bitmap: *const SPBitmap, - x: usize, - y: usize, -) -> bool { - assert!(!bitmap.is_null()); - (*bitmap).0.get(x, y) -} - -/// Sets the value of the specified position in the [SPBitmap]. -/// -/// # Arguments -/// -/// - `bitmap`: instance to write to -/// - `x` and `y`: position of the cell -/// - `value`: the value to write to the cell -/// -/// returns: old value of the cell -/// -/// # Panics -/// -/// - when `bitmap` is NULL -/// - when accessing `x` or `y` out of bounds -/// -/// # Safety -/// -/// The caller has to make sure that: -/// -/// - `bitmap` points to a valid [SPBitmap] -/// - `bitmap` is not written to or read from concurrently -#[no_mangle] -pub unsafe extern "C" fn sp_bitmap_set( - bitmap: *mut SPBitmap, - x: usize, - y: usize, - value: bool, -) { - assert!(!bitmap.is_null()); - (*bitmap).0.set(x, y, value); -} - -/// Sets the state of all pixels in the [SPBitmap]. -/// -/// # Arguments -/// -/// - `bitmap`: instance to write to -/// - `value`: the value to set all pixels to -/// -/// # Panics -/// -/// - when `bitmap` is NULL -/// -/// # Safety -/// -/// The caller has to make sure that: -/// -/// - `bitmap` points to a valid [SPBitmap] -/// - `bitmap` is not written to or read from concurrently -#[no_mangle] -pub unsafe extern "C" fn sp_bitmap_fill(bitmap: *mut SPBitmap, value: bool) { - assert!(!bitmap.is_null()); - (*bitmap).0.fill(value); -} - -/// Gets the width in pixels of the [SPBitmap] instance. -/// -/// # Arguments -/// -/// - `bitmap`: instance to read from -/// -/// # Panics -/// -/// - when `bitmap` is NULL -/// -/// # Safety -/// -/// The caller has to make sure that: -/// -/// - `bitmap` points to a valid [SPBitmap] -#[no_mangle] -pub unsafe extern "C" fn sp_bitmap_width(bitmap: *const SPBitmap) -> usize { - assert!(!bitmap.is_null()); - (*bitmap).0.width() -} - -/// Gets the height in pixels of the [SPBitmap] instance. -/// -/// # Arguments -/// -/// - `bitmap`: instance to read from -/// -/// # Panics -/// -/// - when `bitmap` is NULL -/// -/// # Safety -/// -/// The caller has to make sure that: -/// -/// - `bitmap` points to a valid [SPBitmap] -#[no_mangle] -pub unsafe extern "C" fn sp_bitmap_height(bitmap: *const SPBitmap) -> usize { - assert!(!bitmap.is_null()); - (*bitmap).0.height() -} - -/// Gets an unsafe reference to the data of the [SPBitmap] instance. -/// -/// # Panics -/// -/// - when `bitmap` is NULL -/// -/// # Safety -/// -/// The caller has to make sure that: -/// -/// - `bitmap` points to a valid [SPBitmap] -/// - the returned memory range is never accessed after the passed [SPBitmap] has been freed -/// - the returned memory range is never accessed concurrently, either via the [SPBitmap] or directly -#[no_mangle] -pub unsafe extern "C" fn sp_bitmap_unsafe_data_ref( - bitmap: *mut SPBitmap, -) -> SPByteSlice { - assert!(!bitmap.is_null()); - let data = (*bitmap).0.data_ref_mut(); - SPByteSlice { - start: NonNull::new(data.as_mut_ptr_range().start).unwrap(), - length: data.len(), - } -} diff --git a/crates/servicepoint_binding_c/src/bitvec.rs b/crates/servicepoint_binding_c/src/bitvec.rs deleted file mode 100644 index 484e849..0000000 --- a/crates/servicepoint_binding_c/src/bitvec.rs +++ /dev/null @@ -1,283 +0,0 @@ -//! C functions for interacting with [SPBitVec]s -//! -//! prefix `sp_bitvec_` - -use crate::SPByteSlice; -use std::ptr::NonNull; - -/// A vector of bits -/// -/// # Examples -/// ```C -/// SPBitVec vec = sp_bitvec_new(8); -/// sp_bitvec_set(vec, 5, true); -/// sp_bitvec_free(vec); -/// ``` -pub struct SPBitVec(servicepoint::BitVec); - -impl From for SPBitVec { - fn from(actual: servicepoint::BitVec) -> Self { - Self(actual) - } -} - -impl From for servicepoint::BitVec { - fn from(value: SPBitVec) -> Self { - value.0 - } -} - -impl Clone for SPBitVec { - fn clone(&self) -> Self { - SPBitVec(self.0.clone()) - } -} - -/// Creates a new [SPBitVec] instance. -/// -/// # Arguments -/// -/// - `size`: size in bits. -/// -/// returns: [SPBitVec] with all bits set to false. Will never return NULL. -/// -/// # Panics -/// -/// - when `size` is not divisible by 8. -/// -/// # Safety -/// -/// The caller has to make sure that: -/// -/// - the returned instance is freed in some way, either by using a consuming function or -/// by explicitly calling `sp_bitvec_free`. -#[no_mangle] -pub unsafe extern "C" fn sp_bitvec_new(size: usize) -> NonNull { - let result = Box::new(SPBitVec(servicepoint::BitVec::repeat(false, size))); - NonNull::from(Box::leak(result)) -} - -/// Interpret the data as a series of bits and load then into a new [SPBitVec] instance. -/// -/// returns: [SPBitVec] instance containing data. Will never return NULL. -/// -/// # Panics -/// -/// - when `data` is NULL -/// -/// # Safety -/// -/// The caller has to make sure that: -/// -/// - `data` points to a valid memory location of at least `data_length` -/// bytes in size. -/// - the returned instance is freed in some way, either by using a consuming function or -/// by explicitly calling `sp_bitvec_free`. -#[no_mangle] -pub unsafe extern "C" fn sp_bitvec_load( - data: *const u8, - data_length: usize, -) -> NonNull { - assert!(!data.is_null()); - let data = std::slice::from_raw_parts(data, data_length); - let result = Box::new(SPBitVec(servicepoint::BitVec::from_slice(data))); - NonNull::from(Box::leak(result)) -} - -/// Clones a [SPBitVec]. -/// -/// returns: new [SPBitVec] instance. Will never return NULL. -/// -/// # Panics -/// -/// - when `bit_vec` is NULL -/// -/// # Safety -/// -/// The caller has to make sure that: -/// -/// - `bit_vec` points to a valid [SPBitVec] -/// - `bit_vec` is not written to concurrently -/// - the returned instance is freed in some way, either by using a consuming function or -/// by explicitly calling `sp_bitvec_free`. -#[no_mangle] -pub unsafe extern "C" fn sp_bitvec_clone( - bit_vec: *const SPBitVec, -) -> NonNull { - assert!(!bit_vec.is_null()); - let result = Box::new((*bit_vec).clone()); - NonNull::from(Box::leak(result)) -} - -/// Deallocates a [SPBitVec]. -/// -/// # Panics -/// -/// - when `but_vec` is NULL -/// -/// # Safety -/// -/// The caller has to make sure that: -/// -/// - `bit_vec` points to a valid [SPBitVec] -/// - `bit_vec` is not used concurrently or after this call -/// - `bit_vec` was not passed to another consuming function, e.g. to create a [SPCommand] -/// -/// [SPCommand]: [crate::SPCommand] -#[no_mangle] -pub unsafe extern "C" fn sp_bitvec_free(bit_vec: *mut SPBitVec) { - assert!(!bit_vec.is_null()); - _ = Box::from_raw(bit_vec); -} - -/// Gets the value of a bit from the [SPBitVec]. -/// -/// # Arguments -/// -/// - `bit_vec`: instance to read from -/// - `index`: the bit index to read -/// -/// returns: value of the bit -/// -/// # Panics -/// -/// - when `bit_vec` is NULL -/// - when accessing `index` out of bounds -/// -/// # Safety -/// -/// The caller has to make sure that: -/// -/// - `bit_vec` points to a valid [SPBitVec] -/// - `bit_vec` is not written to concurrently -#[no_mangle] -pub unsafe extern "C" fn sp_bitvec_get( - bit_vec: *const SPBitVec, - index: usize, -) -> bool { - assert!(!bit_vec.is_null()); - *(*bit_vec).0.get(index).unwrap() -} - -/// Sets the value of a bit in the [SPBitVec]. -/// -/// # Arguments -/// -/// - `bit_vec`: instance to write to -/// - `index`: the bit index to edit -/// - `value`: the value to set the bit to -/// -/// # Panics -/// -/// - when `bit_vec` is NULL -/// - when accessing `index` out of bounds -/// -/// # Safety -/// -/// The caller has to make sure that: -/// -/// - `bit_vec` points to a valid [SPBitVec] -/// - `bit_vec` is not written to or read from concurrently -#[no_mangle] -pub unsafe extern "C" fn sp_bitvec_set( - bit_vec: *mut SPBitVec, - index: usize, - value: bool, -) { - assert!(!bit_vec.is_null()); - (*bit_vec).0.set(index, value) -} - -/// Sets the value of all bits in the [SPBitVec]. -/// -/// # Arguments -/// -/// - `bit_vec`: instance to write to -/// - `value`: the value to set all bits to -/// -/// # Panics -/// -/// - when `bit_vec` is NULL -/// -/// # Safety -/// -/// The caller has to make sure that: -/// -/// - `bit_vec` points to a valid [SPBitVec] -/// - `bit_vec` is not written to or read from concurrently -#[no_mangle] -pub unsafe extern "C" fn sp_bitvec_fill(bit_vec: *mut SPBitVec, value: bool) { - assert!(!bit_vec.is_null()); - (*bit_vec).0.fill(value) -} - -/// Gets the length of the [SPBitVec] in bits. -/// -/// # Arguments -/// -/// - `bit_vec`: instance to write to -/// -/// # Panics -/// -/// - when `bit_vec` is NULL -/// -/// # Safety -/// -/// The caller has to make sure that: -/// -/// - `bit_vec` points to a valid [SPBitVec] -#[no_mangle] -pub unsafe extern "C" fn sp_bitvec_len(bit_vec: *const SPBitVec) -> usize { - assert!(!bit_vec.is_null()); - (*bit_vec).0.len() -} - -/// Returns true if length is 0. -/// -/// # Arguments -/// -/// - `bit_vec`: instance to write to -/// -/// # Panics -/// -/// - when `bit_vec` is NULL -/// -/// # Safety -/// -/// The caller has to make sure that: -/// -/// - `bit_vec` points to a valid [SPBitVec] -#[no_mangle] -pub unsafe extern "C" fn sp_bitvec_is_empty(bit_vec: *const SPBitVec) -> bool { - assert!(!bit_vec.is_null()); - (*bit_vec).0.is_empty() -} - -/// Gets an unsafe reference to the data of the [SPBitVec] instance. -/// -/// # Arguments -/// -/// - `bit_vec`: instance to write to -/// -/// # Panics -/// -/// - when `bit_vec` is NULL -/// -/// ## Safety -/// -/// The caller has to make sure that: -/// -/// - `bit_vec` points to a valid [SPBitVec] -/// - the returned memory range is never accessed after the passed [SPBitVec] has been freed -/// - the returned memory range is never accessed concurrently, either via the [SPBitVec] or directly -#[no_mangle] -pub unsafe extern "C" fn sp_bitvec_unsafe_data_ref( - bit_vec: *mut SPBitVec, -) -> SPByteSlice { - assert!(!bit_vec.is_null()); - let data = (*bit_vec).0.as_raw_mut_slice(); - SPByteSlice { - start: NonNull::new(data.as_mut_ptr_range().start).unwrap(), - length: data.len(), - } -} diff --git a/crates/servicepoint_binding_c/src/brightness_grid.rs b/crates/servicepoint_binding_c/src/brightness_grid.rs deleted file mode 100644 index 83af008..0000000 --- a/crates/servicepoint_binding_c/src/brightness_grid.rs +++ /dev/null @@ -1,322 +0,0 @@ -//! C functions for interacting with [SPBrightnessGrid]s -//! -//! prefix `sp_brightness_grid_` - -use crate::SPByteSlice; -use servicepoint::{DataRef, Grid}; -use std::convert::Into; -use std::intrinsics::transmute; -use std::ptr::NonNull; - -/// see [servicepoint::Brightness::MIN] -pub const SP_BRIGHTNESS_MIN: u8 = 0; -/// see [servicepoint::Brightness::MAX] -pub const SP_BRIGHTNESS_MAX: u8 = 11; -/// Count of possible brightness values -pub const SP_BRIGHTNESS_LEVELS: u8 = 12; - -/// A grid containing brightness values. -/// -/// # Examples -/// ```C -/// SPConnection connection = sp_connection_open("127.0.0.1:2342"); -/// if (connection == NULL) -/// return 1; -/// -/// SPBrightnessGrid grid = sp_brightness_grid_new(2, 2); -/// sp_brightness_grid_set(grid, 0, 0, 0); -/// sp_brightness_grid_set(grid, 1, 1, 10); -/// -/// SPCommand command = sp_command_char_brightness(grid); -/// sp_connection_free(connection); -/// ``` -#[derive(Clone)] -pub struct SPBrightnessGrid(pub(crate) servicepoint::BrightnessGrid); - -/// Creates a new [SPBrightnessGrid] with the specified dimensions. -/// -/// returns: [SPBrightnessGrid] initialized to 0. Will never return NULL. -/// -/// # Safety -/// -/// The caller has to make sure that: -/// -/// - the returned instance is freed in some way, either by using a consuming function or -/// by explicitly calling `sp_brightness_grid_free`. -#[no_mangle] -pub unsafe extern "C" fn sp_brightness_grid_new( - width: usize, - height: usize, -) -> NonNull { - let result = Box::new(SPBrightnessGrid(servicepoint::BrightnessGrid::new( - width, height, - ))); - NonNull::from(Box::leak(result)) -} - -/// Loads a [SPBrightnessGrid] with the specified dimensions from the provided data. -/// -/// returns: new [SPBrightnessGrid] instance. Will never return NULL. -/// -/// # Panics -/// -/// - when `data` is NULL -/// - when the provided `data_length` does not match `height` and `width` -/// -/// # Safety -/// -/// The caller has to make sure that: -/// -/// - `data` points to a valid memory location of at least `data_length` -/// bytes in size. -/// - the returned instance is freed in some way, either by using a consuming function or -/// by explicitly calling `sp_brightness_grid_free`. -#[no_mangle] -pub unsafe extern "C" fn sp_brightness_grid_load( - width: usize, - height: usize, - data: *const u8, - data_length: usize, -) -> NonNull { - assert!(!data.is_null()); - let data = std::slice::from_raw_parts(data, data_length); - let grid = servicepoint::ByteGrid::load(width, height, data); - let grid = servicepoint::BrightnessGrid::try_from(grid) - .expect("invalid brightness value"); - let result = Box::new(SPBrightnessGrid(grid)); - NonNull::from(Box::leak(result)) -} - -/// Clones a [SPBrightnessGrid]. -/// -/// # Arguments -/// -/// - `brightness_grid`: instance to read from -/// -/// returns: new [SPBrightnessGrid] instance. Will never return NULL. -/// -/// # Panics -/// -/// - when `brightness_grid` is NULL -/// -/// # Safety -/// -/// The caller has to make sure that: -/// -/// - `brightness_grid` points to a valid [SPBrightnessGrid] -/// - `brightness_grid` is not written to concurrently -/// - the returned instance is freed in some way, either by using a consuming function or -/// by explicitly calling `sp_brightness_grid_free`. -#[no_mangle] -pub unsafe extern "C" fn sp_brightness_grid_clone( - brightness_grid: *const SPBrightnessGrid, -) -> NonNull { - assert!(!brightness_grid.is_null()); - let result = Box::new((*brightness_grid).clone()); - NonNull::from(Box::leak(result)) -} - -/// Deallocates a [SPBrightnessGrid]. -/// -/// # Arguments -/// -/// - `brightness_grid`: instance to read from -/// -/// # Panics -/// -/// - when `brightness_grid` is NULL -/// -/// # Safety -/// -/// The caller has to make sure that: -/// -/// - `brightness_grid` points to a valid [SPBrightnessGrid] -/// - `brightness_grid` is not used concurrently or after this call -/// - `brightness_grid` was not passed to another consuming function, e.g. to create a [SPCommand] -/// -/// [SPCommand]: [crate::SPCommand] -#[no_mangle] -pub unsafe extern "C" fn sp_brightness_grid_free( - brightness_grid: *mut SPBrightnessGrid, -) { - assert!(!brightness_grid.is_null()); - _ = Box::from_raw(brightness_grid); -} - -/// Gets the current value at the specified position. -/// -/// # Arguments -/// -/// - `brightness_grid`: instance to read from -/// - `x` and `y`: position of the cell to read -/// -/// returns: value at position -/// -/// # Panics -/// -/// - when `brightness_grid` is NULL -/// - When accessing `x` or `y` out of bounds. -/// -/// # Safety -/// -/// The caller has to make sure that: -/// -/// - `brightness_grid` points to a valid [SPBrightnessGrid] -/// - `brightness_grid` is not written to concurrently -#[no_mangle] -pub unsafe extern "C" fn sp_brightness_grid_get( - brightness_grid: *const SPBrightnessGrid, - x: usize, - y: usize, -) -> u8 { - assert!(!brightness_grid.is_null()); - (*brightness_grid).0.get(x, y).into() -} - -/// Sets the value of the specified position in the [SPBrightnessGrid]. -/// -/// # Arguments -/// -/// - `brightness_grid`: instance to write to -/// - `x` and `y`: position of the cell -/// - `value`: the value to write to the cell -/// -/// returns: old value of the cell -/// -/// # Panics -/// -/// - when `brightness_grid` is NULL -/// - When accessing `x` or `y` out of bounds. -/// - When providing an invalid brightness value -/// -/// # Safety -/// -/// The caller has to make sure that: -/// -/// - `brightness_grid` points to a valid [SPBrightnessGrid] -/// - `brightness_grid` is not written to or read from concurrently -#[no_mangle] -pub unsafe extern "C" fn sp_brightness_grid_set( - brightness_grid: *mut SPBrightnessGrid, - x: usize, - y: usize, - value: u8, -) { - assert!(!brightness_grid.is_null()); - let brightness = servicepoint::Brightness::try_from(value) - .expect("invalid brightness value"); - (*brightness_grid).0.set(x, y, brightness); -} - -/// Sets the value of all cells in the [SPBrightnessGrid]. -/// -/// # Arguments -/// -/// - `brightness_grid`: instance to write to -/// - `value`: the value to set all cells to -/// -/// # Panics -/// -/// - when `brightness_grid` is NULL -/// - When providing an invalid brightness value -/// -/// # Safety -/// -/// The caller has to make sure that: -/// -/// - `brightness_grid` points to a valid [SPBrightnessGrid] -/// - `brightness_grid` is not written to or read from concurrently -#[no_mangle] -pub unsafe extern "C" fn sp_brightness_grid_fill( - brightness_grid: *mut SPBrightnessGrid, - value: u8, -) { - assert!(!brightness_grid.is_null()); - let brightness = servicepoint::Brightness::try_from(value) - .expect("invalid brightness value"); - (*brightness_grid).0.fill(brightness); -} - -/// Gets the width of the [SPBrightnessGrid] instance. -/// -/// # Arguments -/// -/// - `brightness_grid`: instance to read from -/// -/// returns: width -/// -/// # Panics -/// -/// - when `brightness_grid` is NULL -/// -/// # Safety -/// -/// The caller has to make sure that: -/// -/// - `brightness_grid` points to a valid [SPBrightnessGrid] -#[no_mangle] -pub unsafe extern "C" fn sp_brightness_grid_width( - brightness_grid: *const SPBrightnessGrid, -) -> usize { - assert!(!brightness_grid.is_null()); - (*brightness_grid).0.width() -} - -/// Gets the height of the [SPBrightnessGrid] instance. -/// -/// # Arguments -/// -/// - `brightness_grid`: instance to read from -/// -/// returns: height -/// -/// # Panics -/// -/// - when `brightness_grid` is NULL -/// -/// # Safety -/// -/// The caller has to make sure that: -/// -/// - `brightness_grid` points to a valid [SPBrightnessGrid] -#[no_mangle] -pub unsafe extern "C" fn sp_brightness_grid_height( - brightness_grid: *const SPBrightnessGrid, -) -> usize { - assert!(!brightness_grid.is_null()); - (*brightness_grid).0.height() -} - -/// Gets an unsafe reference to the data of the [SPBrightnessGrid] instance. -/// -/// # Arguments -/// -/// - `brightness_grid`: instance to read from -/// -/// returns: slice of bytes underlying the `brightness_grid`. -/// -/// # Panics -/// -/// - when `brightness_grid` is NULL -/// -/// # Safety -/// -/// The caller has to make sure that: -/// -/// - `brightness_grid` points to a valid [SPBrightnessGrid] -/// - the returned memory range is never accessed after the passed [SPBrightnessGrid] has been freed -/// - the returned memory range is never accessed concurrently, either via the [SPBrightnessGrid] or directly -#[no_mangle] -pub unsafe extern "C" fn sp_brightness_grid_unsafe_data_ref( - brightness_grid: *mut SPBrightnessGrid, -) -> SPByteSlice { - assert!(!brightness_grid.is_null()); - assert_eq!(core::mem::size_of::(), 1); - let data = (*brightness_grid).0.data_ref_mut(); - // this assumes more about the memory layout than rust guarantees. yikes! - let data: &mut [u8] = transmute(data); - SPByteSlice { - start: NonNull::new(data.as_mut_ptr_range().start).unwrap(), - length: data.len(), - } -} diff --git a/crates/servicepoint_binding_c/src/byte_slice.rs b/crates/servicepoint_binding_c/src/byte_slice.rs deleted file mode 100644 index 678a5d7..0000000 --- a/crates/servicepoint_binding_c/src/byte_slice.rs +++ /dev/null @@ -1,24 +0,0 @@ -//! FFI slice helper - -use std::ptr::NonNull; - -#[repr(C)] -/// Represents a span of memory (`&mut [u8]` ) as a struct usable by C code. -/// -/// You should not create an instance of this type in your C code. -/// -/// # Safety -/// -/// The caller has to make sure that: -/// -/// - accesses to the memory pointed to with `start` is never accessed outside `length` -/// - the lifetime of the `CByteSlice` does not outlive the memory it points to, as described in -/// the function returning this type. -/// - an instance of this created from C is never passed to a consuming function, as the rust code -/// will try to free the memory of a potentially separate allocator. -pub struct SPByteSlice { - /// The start address of the memory - pub start: NonNull, - /// The amount of memory in bytes - pub length: usize, -} diff --git a/crates/servicepoint_binding_c/src/char_grid.rs b/crates/servicepoint_binding_c/src/char_grid.rs deleted file mode 100644 index dfaf225..0000000 --- a/crates/servicepoint_binding_c/src/char_grid.rs +++ /dev/null @@ -1,263 +0,0 @@ -//! C functions for interacting with [SPCharGrid]s -//! -//! prefix `sp_char_grid_` - -use servicepoint::Grid; -use std::ptr::NonNull; - -/// A C-wrapper for grid containing UTF-8 characters. -/// -/// As the rust [char] type is not FFI-safe, characters are passed in their UTF-32 form as 32bit unsigned integers. -/// -/// The encoding is enforced in most cases by the rust standard library -/// and will panic when provided with illegal characters. -/// -/// # Examples -/// -/// ```C -/// CharGrid grid = sp_char_grid_new(4, 3); -/// sp_char_grid_fill(grid, '?'); -/// sp_char_grid_set(grid, 0, 0, '!'); -/// sp_char_grid_free(grid); -/// ``` -pub struct SPCharGrid(pub(crate) servicepoint::CharGrid); - -impl Clone for SPCharGrid { - fn clone(&self) -> Self { - SPCharGrid(self.0.clone()) - } -} - -/// Creates a new [SPCharGrid] with the specified dimensions. -/// -/// returns: [SPCharGrid] initialized to 0. Will never return NULL. -/// -/// # Safety -/// -/// The caller has to make sure that: -/// -/// - the returned instance is freed in some way, either by using a consuming function or -/// by explicitly calling `sp_char_grid_free`. -#[no_mangle] -pub unsafe extern "C" fn sp_char_grid_new( - width: usize, - height: usize, -) -> NonNull { - let result = - Box::new(SPCharGrid(servicepoint::CharGrid::new(width, height))); - NonNull::from(Box::leak(result)) -} - -/// Loads a [SPCharGrid] with the specified dimensions from the provided data. -/// -/// Will never return NULL. -/// -/// # Panics -/// -/// - when `data` is NULL -/// - when the provided `data_length` does not match `height` and `width` -/// - when `data` is not valid UTF-8 -/// -/// # Safety -/// -/// The caller has to make sure that: -/// -/// - `data` points to a valid memory location of at least `data_length` -/// bytes in size. -/// - the returned instance is freed in some way, either by using a consuming function or -/// by explicitly calling `sp_char_grid_free`. -#[no_mangle] -pub unsafe extern "C" fn sp_char_grid_load( - width: usize, - height: usize, - data: *const u8, - data_length: usize, -) -> NonNull { - assert!(data.is_null()); - let data = std::slice::from_raw_parts(data, data_length); - let result = Box::new(SPCharGrid( - servicepoint::CharGrid::load_utf8(width, height, data.to_vec()) - .unwrap(), - )); - NonNull::from(Box::leak(result)) -} - -/// Clones a [SPCharGrid]. -/// -/// Will never return NULL. -/// -/// # Panics -/// -/// - when `char_grid` is NULL -/// -/// # Safety -/// -/// The caller has to make sure that: -/// -/// - `char_grid` points to a valid [SPCharGrid] -/// - `char_grid` is not written to concurrently -/// - the returned instance is freed in some way, either by using a consuming function or -/// by explicitly calling `sp_char_grid_free`. -#[no_mangle] -pub unsafe extern "C" fn sp_char_grid_clone( - char_grid: *const SPCharGrid, -) -> NonNull { - assert!(!char_grid.is_null()); - let result = Box::new((*char_grid).clone()); - NonNull::from(Box::leak(result)) -} - -/// Deallocates a [SPCharGrid]. -/// -/// # Panics -/// -/// - when `char_grid` is NULL -/// -/// # Safety -/// -/// The caller has to make sure that: -/// -/// - `char_grid` points to a valid [SPCharGrid] -/// - `char_grid` is not used concurrently or after char_grid call -/// - `char_grid` was not passed to another consuming function, e.g. to create a [SPCommand] -/// -/// [SPCommand]: [crate::SPCommand] -#[no_mangle] -pub unsafe extern "C" fn sp_char_grid_free(char_grid: *mut SPCharGrid) { - assert!(!char_grid.is_null()); - _ = Box::from_raw(char_grid); -} - -/// Gets the current value at the specified position. -/// -/// # Arguments -/// -/// - `char_grid`: instance to read from -/// - `x` and `y`: position of the cell to read -/// -/// # Panics -/// -/// - when `char_grid` is NULL -/// - when accessing `x` or `y` out of bounds -/// -/// # Safety -/// -/// The caller has to make sure that: -/// -/// - `char_grid` points to a valid [SPCharGrid] -/// - `char_grid` is not written to concurrently -#[no_mangle] -pub unsafe extern "C" fn sp_char_grid_get( - char_grid: *const SPCharGrid, - x: usize, - y: usize, -) -> u32 { - assert!(!char_grid.is_null()); - (*char_grid).0.get(x, y) as u32 -} - -/// Sets the value of the specified position in the [SPCharGrid]. -/// -/// # Arguments -/// -/// - `char_grid`: instance to write to -/// - `x` and `y`: position of the cell -/// - `value`: the value to write to the cell -/// -/// returns: old value of the cell -/// -/// # Panics -/// -/// - when `char_grid` is NULL -/// - when accessing `x` or `y` out of bounds -/// -/// # Safety -/// -/// The caller has to make sure that: -/// -/// - `char_grid` points to a valid [SPBitVec] -/// - `char_grid` is not written to or read from concurrently -/// -/// [SPBitVec]: [crate::SPBitVec] -#[no_mangle] -pub unsafe extern "C" fn sp_char_grid_set( - char_grid: *mut SPCharGrid, - x: usize, - y: usize, - value: u32, -) { - assert!(!char_grid.is_null()); - (*char_grid).0.set(x, y, char::from_u32(value).unwrap()); -} - -/// Sets the value of all cells in the [SPCharGrid]. -/// -/// # Arguments -/// -/// - `char_grid`: instance to write to -/// - `value`: the value to set all cells to -/// -/// # Panics -/// -/// - when `char_grid` is NULL -/// -/// # Safety -/// -/// The caller has to make sure that: -/// -/// - `char_grid` points to a valid [SPCharGrid] -/// - `char_grid` is not written to or read from concurrently -#[no_mangle] -pub unsafe extern "C" fn sp_char_grid_fill( - char_grid: *mut SPCharGrid, - value: u32, -) { - assert!(!char_grid.is_null()); - (*char_grid).0.fill(char::from_u32(value).unwrap()); -} - -/// Gets the width of the [SPCharGrid] instance. -/// -/// # Arguments -/// -/// - `char_grid`: instance to read from -/// -/// # Panics -/// -/// - when `char_grid` is NULL -/// -/// # Safety -/// -/// The caller has to make sure that: -/// -/// - `char_grid` points to a valid [SPCharGrid] -#[no_mangle] -pub unsafe extern "C" fn sp_char_grid_width( - char_grid: *const SPCharGrid, -) -> usize { - assert!(!char_grid.is_null()); - (*char_grid).0.width() -} - -/// Gets the height of the [SPCharGrid] instance. -/// -/// # Arguments -/// -/// - `char_grid`: instance to read from -/// -/// # Panics -/// -/// - when `char_grid` is NULL -/// -/// # Safety -/// -/// The caller has to make sure that: -/// -/// - `char_grid` points to a valid [SPCharGrid] -#[no_mangle] -pub unsafe extern "C" fn sp_char_grid_height( - char_grid: *const SPCharGrid, -) -> usize { - assert!(!char_grid.is_null()); - (*char_grid).0.height() -} diff --git a/crates/servicepoint_binding_c/src/command.rs b/crates/servicepoint_binding_c/src/command.rs deleted file mode 100644 index f7e50ea..0000000 --- a/crates/servicepoint_binding_c/src/command.rs +++ /dev/null @@ -1,498 +0,0 @@ -//! C functions for interacting with [SPCommand]s -//! -//! prefix `sp_command_` - -use std::ptr::{null_mut, NonNull}; - -use crate::{ - SPBitVec, SPBitmap, SPBrightnessGrid, SPCharGrid, SPCompressionCode, - SPCp437Grid, SPPacket, -}; - -/// A low-level display command. -/// -/// This struct and associated functions implement the UDP protocol for the display. -/// -/// To send a [SPCommand], use a [SPConnection]. -/// -/// # Examples -/// -/// ```C -/// sp_connection_send_command(connection, sp_command_clear()); -/// sp_connection_send_command(connection, sp_command_brightness(5)); -/// ``` -/// -/// [SPConnection]: [crate::SPConnection] -pub struct SPCommand(pub(crate) servicepoint::Command); - -impl Clone for SPCommand { - fn clone(&self) -> Self { - SPCommand(self.0.clone()) - } -} - -/// Tries to turn a [SPPacket] into a [SPCommand]. -/// -/// The packet is deallocated in the process. -/// -/// Returns: pointer to new [SPCommand] instance or NULL if parsing failed. -/// -/// # Panics -/// -/// - when `packet` is NULL -/// -/// # Safety -/// -/// The caller has to make sure that: -/// -/// - [SPPacket] points to a valid instance of [SPPacket] -/// - [SPPacket] is not used concurrently or after this call -/// - the result is checked for NULL -/// - the returned [SPCommand] instance is freed in some way, either by using a consuming function or -/// by explicitly calling `sp_command_free`. -#[no_mangle] -pub unsafe extern "C" fn sp_command_try_from_packet( - packet: *mut SPPacket, -) -> *mut SPCommand { - let packet = *Box::from_raw(packet); - match servicepoint::Command::try_from(packet.0) { - Err(_) => null_mut(), - Ok(command) => Box::into_raw(Box::new(SPCommand(command))), - } -} - -/// Clones a [SPCommand] instance. -/// -/// returns: new [SPCommand] instance. Will never return NULL. -/// -/// # Panics -/// -/// - when `command` is NULL -/// -/// # Safety -/// -/// The caller has to make sure that: -/// -/// - `command` points to a valid instance of [SPCommand] -/// - `command` is not written to concurrently -/// - the returned [SPCommand] instance is freed in some way, either by using a consuming function or -/// by explicitly calling `sp_command_free`. -#[no_mangle] -pub unsafe extern "C" fn sp_command_clone( - command: *const SPCommand, -) -> NonNull { - assert!(!command.is_null()); - let result = Box::new((*command).clone()); - NonNull::from(Box::leak(result)) -} - -/// Set all pixels to the off state. -/// -/// Does not affect brightness. -/// -/// Returns: a new [servicepoint::Command::Clear] instance. Will never return NULL. -/// -/// # Examples -/// -/// ```C -/// sp_connection_send_command(connection, sp_command_clear()); -/// ``` -/// -/// # Safety -/// -/// The caller has to make sure that: -/// -/// - the returned [SPCommand] instance is freed in some way, either by using a consuming function or -/// by explicitly calling `sp_command_free`. -#[no_mangle] -pub unsafe extern "C" fn sp_command_clear() -> NonNull { - let result = Box::new(SPCommand(servicepoint::Command::Clear)); - NonNull::from(Box::leak(result)) -} - -/// Kills the udp daemon on the display, which usually results in a restart. -/// -/// Please do not send this in your normal program flow. -/// -/// Returns: a new [servicepoint::Command::HardReset] instance. Will never return NULL. -/// -/// # Safety -/// -/// The caller has to make sure that: -/// -/// - the returned [SPCommand] instance is freed in some way, either by using a consuming function or -/// by explicitly calling `sp_command_free`. -#[no_mangle] -pub unsafe extern "C" fn sp_command_hard_reset() -> NonNull { - let result = Box::new(SPCommand(servicepoint::Command::HardReset)); - NonNull::from(Box::leak(result)) -} - -/// A yet-to-be-tested command. -/// -/// Returns: a new [servicepoint::Command::FadeOut] instance. Will never return NULL. -/// -/// # Safety -/// -/// The caller has to make sure that: -/// -/// - the returned [SPCommand] instance is freed in some way, either by using a consuming function or -/// by explicitly calling `sp_command_free`. -#[no_mangle] -pub unsafe extern "C" fn sp_command_fade_out() -> NonNull { - let result = Box::new(SPCommand(servicepoint::Command::FadeOut)); - NonNull::from(Box::leak(result)) -} - -/// Set the brightness of all tiles to the same value. -/// -/// Returns: a new [servicepoint::Command::Brightness] instance. Will never return NULL. -/// -/// # Panics -/// -/// - When the provided brightness value is out of range (0-11). -/// -/// # Safety -/// -/// The caller has to make sure that: -/// -/// - the returned [SPCommand] instance is freed in some way, either by using a consuming function or -/// by explicitly calling `sp_command_free`. -#[no_mangle] -pub unsafe extern "C" fn sp_command_brightness( - brightness: u8, -) -> NonNull { - let brightness = servicepoint::Brightness::try_from(brightness) - .expect("invalid brightness"); - let result = - Box::new(SPCommand(servicepoint::Command::Brightness(brightness))); - NonNull::from(Box::leak(result)) -} - -/// Set the brightness of individual tiles in a rectangular area of the display. -/// -/// The passed [SPBrightnessGrid] gets consumed. -/// -/// Returns: a new [servicepoint::Command::CharBrightness] instance. Will never return NULL. -/// -/// # Panics -/// -/// - when `grid` is NULL -/// -/// # Safety -/// -/// The caller has to make sure that: -/// -/// - `grid` points to a valid instance of [SPBrightnessGrid] -/// - `grid` is not used concurrently or after this call -/// - the returned [SPCommand] instance is freed in some way, either by using a consuming function or -/// by explicitly calling `sp_command_free`. -#[no_mangle] -pub unsafe extern "C" fn sp_command_char_brightness( - x: usize, - y: usize, - grid: *mut SPBrightnessGrid, -) -> NonNull { - assert!(!grid.is_null()); - let byte_grid = *Box::from_raw(grid); - let result = Box::new(SPCommand(servicepoint::Command::CharBrightness( - servicepoint::Origin::new(x, y), - byte_grid.0, - ))); - NonNull::from(Box::leak(result)) -} - -/// Set pixel data starting at the pixel offset on screen. -/// -/// The screen will continuously overwrite more pixel data without regarding the offset, meaning -/// once the starting row is full, overwriting will continue on column 0. -/// -/// The contained [SPBitVec] is always uncompressed. -/// -/// The passed [SPBitVec] gets consumed. -/// -/// Returns: a new [servicepoint::Command::BitmapLinear] instance. Will never return NULL. -/// -/// # Panics -/// -/// - when `bit_vec` is null -/// - when `compression_code` is not a valid value -/// -/// # Safety -/// -/// The caller has to make sure that: -/// -/// - `bit_vec` points to a valid instance of [SPBitVec] -/// - `bit_vec` is not used concurrently or after this call -/// - `compression` matches one of the allowed enum values -/// - the returned [SPCommand] instance is freed in some way, either by using a consuming function or -/// by explicitly calling `sp_command_free`. -#[no_mangle] -pub unsafe extern "C" fn sp_command_bitmap_linear( - offset: usize, - bit_vec: *mut SPBitVec, - compression: SPCompressionCode, -) -> NonNull { - assert!(!bit_vec.is_null()); - let bit_vec = *Box::from_raw(bit_vec); - let result = Box::new(SPCommand(servicepoint::Command::BitmapLinear( - offset, - bit_vec.into(), - compression.try_into().expect("invalid compression code"), - ))); - NonNull::from(Box::leak(result)) -} - -/// Set pixel data according to an and-mask starting at the offset. -/// -/// The screen will continuously overwrite more pixel data without regarding the offset, meaning -/// once the starting row is full, overwriting will continue on column 0. -/// -/// The contained [SPBitVec] is always uncompressed. -/// -/// The passed [SPBitVec] gets consumed. -/// -/// Returns: a new [servicepoint::Command::BitmapLinearAnd] instance. Will never return NULL. -/// -/// # Panics -/// -/// - when `bit_vec` is null -/// - when `compression_code` is not a valid value -/// -/// # Safety -/// -/// The caller has to make sure that: -/// -/// - `bit_vec` points to a valid instance of [SPBitVec] -/// - `bit_vec` is not used concurrently or after this call -/// - `compression` matches one of the allowed enum values -/// - the returned [SPCommand] instance is freed in some way, either by using a consuming function or -/// by explicitly calling `sp_command_free`. -#[no_mangle] -pub unsafe extern "C" fn sp_command_bitmap_linear_and( - offset: usize, - bit_vec: *mut SPBitVec, - compression: SPCompressionCode, -) -> NonNull { - assert!(!bit_vec.is_null()); - let bit_vec = *Box::from_raw(bit_vec); - let result = Box::new(SPCommand(servicepoint::Command::BitmapLinearAnd( - offset, - bit_vec.into(), - compression.try_into().expect("invalid compression code"), - ))); - NonNull::from(Box::leak(result)) -} - -/// Set pixel data according to an or-mask starting at the offset. -/// -/// The screen will continuously overwrite more pixel data without regarding the offset, meaning -/// once the starting row is full, overwriting will continue on column 0. -/// -/// The contained [SPBitVec] is always uncompressed. -/// -/// The passed [SPBitVec] gets consumed. -/// -/// Returns: a new [servicepoint::Command::BitmapLinearOr] instance. Will never return NULL. -/// -/// # Panics -/// -/// - when `bit_vec` is null -/// - when `compression_code` is not a valid value -/// -/// # Safety -/// -/// The caller has to make sure that: -/// -/// - `bit_vec` points to a valid instance of [SPBitVec] -/// - `bit_vec` is not used concurrently or after this call -/// - `compression` matches one of the allowed enum values -/// - the returned [SPCommand] instance is freed in some way, either by using a consuming function or -/// by explicitly calling `sp_command_free`. -#[no_mangle] -pub unsafe extern "C" fn sp_command_bitmap_linear_or( - offset: usize, - bit_vec: *mut SPBitVec, - compression: SPCompressionCode, -) -> NonNull { - assert!(!bit_vec.is_null()); - let bit_vec = *Box::from_raw(bit_vec); - let result = Box::new(SPCommand(servicepoint::Command::BitmapLinearOr( - offset, - bit_vec.into(), - compression.try_into().expect("invalid compression code"), - ))); - NonNull::from(Box::leak(result)) -} - -/// Set pixel data according to a xor-mask starting at the offset. -/// -/// The screen will continuously overwrite more pixel data without regarding the offset, meaning -/// once the starting row is full, overwriting will continue on column 0. -/// -/// The contained [SPBitVec] is always uncompressed. -/// -/// The passed [SPBitVec] gets consumed. -/// -/// Returns: a new [servicepoint::Command::BitmapLinearXor] instance. Will never return NULL. -/// -/// # Panics -/// -/// - when `bit_vec` is null -/// - when `compression_code` is not a valid value -/// -/// # Safety -/// -/// The caller has to make sure that: -/// -/// - `bit_vec` points to a valid instance of [SPBitVec] -/// - `bit_vec` is not used concurrently or after this call -/// - `compression` matches one of the allowed enum values -/// - the returned [SPCommand] instance is freed in some way, either by using a consuming function or -/// by explicitly calling `sp_command_free`. -#[no_mangle] -pub unsafe extern "C" fn sp_command_bitmap_linear_xor( - offset: usize, - bit_vec: *mut SPBitVec, - compression: SPCompressionCode, -) -> NonNull { - assert!(!bit_vec.is_null()); - let bit_vec = *Box::from_raw(bit_vec); - let result = Box::new(SPCommand(servicepoint::Command::BitmapLinearXor( - offset, - bit_vec.into(), - compression.try_into().expect("invalid compression code"), - ))); - NonNull::from(Box::leak(result)) -} - -/// Show codepage 437 encoded text on the screen. -/// -/// The passed [SPCp437Grid] gets consumed. -/// -/// Returns: a new [servicepoint::Command::Cp437Data] instance. Will never return NULL. -/// -/// # Panics -/// -/// - when `grid` is null -/// -/// # Safety -/// -/// The caller has to make sure that: -/// -/// - `grid` points to a valid instance of [SPCp437Grid] -/// - `grid` is not used concurrently or after this call -/// - the returned [SPCommand] instance is freed in some way, either by using a consuming function or -/// by explicitly calling `sp_command_free`. -#[no_mangle] -pub unsafe extern "C" fn sp_command_cp437_data( - x: usize, - y: usize, - grid: *mut SPCp437Grid, -) -> NonNull { - assert!(!grid.is_null()); - let grid = *Box::from_raw(grid); - let result = Box::new(SPCommand(servicepoint::Command::Cp437Data( - servicepoint::Origin::new(x, y), - grid.0, - ))); - NonNull::from(Box::leak(result)) -} - -/// Show UTF-8 encoded text on the screen. -/// -/// The passed [SPCharGrid] gets consumed. -/// -/// Returns: a new [servicepoint::Command::Utf8Data] instance. Will never return NULL. -/// -/// # Panics -/// -/// - when `grid` is null -/// -/// # Safety -/// -/// The caller has to make sure that: -/// -/// - `grid` points to a valid instance of [SPCharGrid] -/// - `grid` is not used concurrently or after this call -/// - the returned [SPCommand] instance is freed in some way, either by using a consuming function or -/// by explicitly calling `sp_command_free`. -#[no_mangle] -pub unsafe extern "C" fn sp_command_utf8_data( - x: usize, - y: usize, - grid: *mut SPCharGrid, -) -> NonNull { - assert!(!grid.is_null()); - let grid = *Box::from_raw(grid); - let result = Box::new(SPCommand(servicepoint::Command::Utf8Data( - servicepoint::Origin::new(x, y), - grid.0, - ))); - NonNull::from(Box::leak(result)) -} - -/// Sets a window of pixels to the specified values. -/// -/// The passed [SPBitmap] gets consumed. -/// -/// Returns: a new [servicepoint::Command::BitmapLinearWin] instance. Will never return NULL. -/// -/// # Panics -/// -/// - when `bitmap` is null -/// - when `compression_code` is not a valid value -/// -/// # Safety -/// -/// The caller has to make sure that: -/// -/// - `bitmap` points to a valid instance of [SPBitmap] -/// - `bitmap` is not used concurrently or after this call -/// - `compression` matches one of the allowed enum values -/// - the returned [SPCommand] instance is freed in some way, either by using a consuming function or -/// by explicitly calling `sp_command_free`. -#[no_mangle] -pub unsafe extern "C" fn sp_command_bitmap_linear_win( - x: usize, - y: usize, - bitmap: *mut SPBitmap, - compression_code: SPCompressionCode, -) -> NonNull { - assert!(!bitmap.is_null()); - let byte_grid = (*Box::from_raw(bitmap)).0; - let result = Box::new(SPCommand(servicepoint::Command::BitmapLinearWin( - servicepoint::Origin::new(x, y), - byte_grid, - compression_code - .try_into() - .expect("invalid compression code"), - ))); - NonNull::from(Box::leak(result)) -} - -/// Deallocates a [SPCommand]. -/// -/// # Examples -/// -/// ```C -/// SPCommand c = sp_command_clear(); -/// sp_command_free(c); -/// ``` -/// -/// # Panics -/// -/// - when `command` is NULL -/// -/// # Safety -/// -/// The caller has to make sure that: -/// -/// - `command` points to a valid [SPCommand] -/// - `command` is not used concurrently or after this call -/// - `command` was not passed to another consuming function, e.g. to create a [SPPacket] -#[no_mangle] -pub unsafe extern "C" fn sp_command_free(command: *mut SPCommand) { - assert!(!command.is_null()); - _ = Box::from_raw(command); -} diff --git a/crates/servicepoint_binding_c/src/connection.rs b/crates/servicepoint_binding_c/src/connection.rs deleted file mode 100644 index 8b31243..0000000 --- a/crates/servicepoint_binding_c/src/connection.rs +++ /dev/null @@ -1,139 +0,0 @@ -//! C functions for interacting with [SPConnection]s -//! -//! prefix `sp_connection_` - -use std::ffi::{c_char, CStr}; -use std::ptr::{null_mut, NonNull}; - -use crate::{SPCommand, SPPacket}; - -/// A connection to the display. -/// -/// # Examples -/// -/// ```C -/// CConnection connection = sp_connection_open("172.23.42.29:2342"); -/// if (connection != NULL) -/// sp_connection_send_command(connection, sp_command_clear()); -/// ``` -pub struct SPConnection(pub(crate) servicepoint::Connection); - -/// Creates a new instance of [SPConnection]. -/// -/// returns: NULL if connection fails, or connected instance -/// -/// # Panics -/// -/// - when `host` is null or an invalid host -/// -/// # Safety -/// -/// The caller has to make sure that: -/// -/// - the returned instance is freed in some way, either by using a consuming function or -/// by explicitly calling `sp_connection_free`. -#[no_mangle] -pub unsafe extern "C" fn sp_connection_open( - host: *const c_char, -) -> *mut SPConnection { - assert!(!host.is_null()); - let host = CStr::from_ptr(host).to_str().expect("Bad encoding"); - let connection = match servicepoint::Connection::open(host) { - Err(_) => return null_mut(), - Ok(value) => value, - }; - - Box::into_raw(Box::new(SPConnection(connection))) -} - -/// Creates a new instance of [SPConnection] for testing that does not actually send anything. -/// -/// returns: a new instance. Will never return NULL. -/// -/// # Safety -/// -/// The caller has to make sure that: -/// -/// - the returned instance is freed in some way, either by using a consuming function or -/// by explicitly calling `sp_connection_free`. -#[no_mangle] -pub unsafe extern "C" fn sp_connection_fake() -> NonNull { - let result = Box::new(SPConnection(servicepoint::Connection::Fake)); - NonNull::from(Box::leak(result)) -} - -/// Sends a [SPPacket] to the display using the [SPConnection]. -/// -/// The passed `packet` gets consumed. -/// -/// returns: true in case of success -/// -/// # Panics -/// -/// - when `connection` is NULL -/// - when `packet` is NULL -/// -/// # Safety -/// -/// The caller has to make sure that: -/// -/// - `connection` points to a valid instance of [SPConnection] -/// - `packet` points to a valid instance of [SPPacket] -/// - `packet` is not used concurrently or after this call -#[no_mangle] -pub unsafe extern "C" fn sp_connection_send_packet( - connection: *const SPConnection, - packet: *mut SPPacket, -) -> bool { - assert!(!connection.is_null()); - assert!(!packet.is_null()); - let packet = Box::from_raw(packet); - (*connection).0.send((*packet).0).is_ok() -} - -/// Sends a [SPCommand] to the display using the [SPConnection]. -/// -/// The passed `command` gets consumed. -/// -/// returns: true in case of success -/// -/// # Panics -/// -/// - when `connection` is NULL -/// - when `command` is NULL -/// -/// # Safety -/// -/// The caller has to make sure that: -/// -/// - `connection` points to a valid instance of [SPConnection] -/// - `command` points to a valid instance of [SPPacket] -/// - `command` is not used concurrently or after this call -#[no_mangle] -pub unsafe extern "C" fn sp_connection_send_command( - connection: *const SPConnection, - command: *mut SPCommand, -) -> bool { - assert!(!connection.is_null()); - assert!(!command.is_null()); - let command = (*Box::from_raw(command)).0; - (*connection).0.send(command).is_ok() -} - -/// Closes and deallocates a [SPConnection]. -/// -/// # Panics -/// -/// - when `connection` is NULL -/// -/// # Safety -/// -/// The caller has to make sure that: -/// -/// - `connection` points to a valid [SPConnection] -/// - `connection` is not used concurrently or after this call -#[no_mangle] -pub unsafe extern "C" fn sp_connection_free(connection: *mut SPConnection) { - assert!(!connection.is_null()); - _ = Box::from_raw(connection); -} diff --git a/crates/servicepoint_binding_c/src/constants.rs b/crates/servicepoint_binding_c/src/constants.rs deleted file mode 100644 index 1a268f4..0000000 --- a/crates/servicepoint_binding_c/src/constants.rs +++ /dev/null @@ -1,48 +0,0 @@ -//! re-exported constants for use in C - -use servicepoint::CompressionCode; -use std::time::Duration; - -/// size of a single tile in one dimension -pub const SP_TILE_SIZE: usize = 8; - -/// Display tile count in the x-direction -pub const SP_TILE_WIDTH: usize = 56; - -/// Display tile count in the y-direction -pub const SP_TILE_HEIGHT: usize = 20; - -/// Display width in pixels -pub const SP_PIXEL_WIDTH: usize = SP_TILE_WIDTH * SP_TILE_SIZE; - -/// Display height in pixels -pub const SP_PIXEL_HEIGHT: usize = SP_TILE_HEIGHT * SP_TILE_SIZE; - -/// pixel count on whole screen -pub const SP_PIXEL_COUNT: usize = SP_PIXEL_WIDTH * SP_PIXEL_HEIGHT; - -/// Actual hardware limit is around 28-29ms/frame. Rounded up for less dropped packets. -pub const SP_FRAME_PACING_MS: u128 = Duration::from_millis(30).as_millis(); - -/// Specifies the kind of compression to use. -#[repr(u16)] -pub enum SPCompressionCode { - /// no compression - Uncompressed = 0x0, - /// compress using flate2 with zlib header - Zlib = 0x677a, - /// compress using bzip2 - Bzip2 = 0x627a, - /// compress using lzma - Lzma = 0x6c7a, - /// compress using Zstandard - Zstd = 0x7a73, -} - -impl TryFrom for CompressionCode { - type Error = (); - - fn try_from(value: SPCompressionCode) -> Result { - CompressionCode::try_from(value as u16) - } -} diff --git a/crates/servicepoint_binding_c/src/cp437_grid.rs b/crates/servicepoint_binding_c/src/cp437_grid.rs deleted file mode 100644 index 9b366c8..0000000 --- a/crates/servicepoint_binding_c/src/cp437_grid.rs +++ /dev/null @@ -1,285 +0,0 @@ -//! C functions for interacting with [SPCp437Grid]s -//! -//! prefix `sp_cp437_grid_` - -use crate::SPByteSlice; -use servicepoint::{DataRef, Grid}; -use std::ptr::NonNull; - -/// A C-wrapper for grid containing codepage 437 characters. -/// -/// The encoding is currently not enforced. -/// -/// # Examples -/// -/// ```C -/// Cp437Grid grid = sp_cp437_grid_new(4, 3); -/// sp_cp437_grid_fill(grid, '?'); -/// sp_cp437_grid_set(grid, 0, 0, '!'); -/// sp_cp437_grid_free(grid); -/// ``` -pub struct SPCp437Grid(pub(crate) servicepoint::Cp437Grid); - -impl Clone for SPCp437Grid { - fn clone(&self) -> Self { - SPCp437Grid(self.0.clone()) - } -} - -/// Creates a new [SPCp437Grid] with the specified dimensions. -/// -/// returns: [SPCp437Grid] initialized to 0. Will never return NULL. -/// -/// # Safety -/// -/// The caller has to make sure that: -/// -/// - the returned instance is freed in some way, either by using a consuming function or -/// by explicitly calling `sp_cp437_grid_free`. -#[no_mangle] -pub unsafe extern "C" fn sp_cp437_grid_new( - width: usize, - height: usize, -) -> NonNull { - let result = - Box::new(SPCp437Grid(servicepoint::Cp437Grid::new(width, height))); - NonNull::from(Box::leak(result)) -} - -/// Loads a [SPCp437Grid] with the specified dimensions from the provided data. -/// -/// Will never return NULL. -/// -/// # Panics -/// -/// - when `data` is NULL -/// - when the provided `data_length` does not match `height` and `width` -/// -/// # Safety -/// -/// The caller has to make sure that: -/// -/// - `data` points to a valid memory location of at least `data_length` -/// bytes in size. -/// - the returned instance is freed in some way, either by using a consuming function or -/// by explicitly calling `sp_cp437_grid_free`. -#[no_mangle] -pub unsafe extern "C" fn sp_cp437_grid_load( - width: usize, - height: usize, - data: *const u8, - data_length: usize, -) -> NonNull { - assert!(data.is_null()); - let data = std::slice::from_raw_parts(data, data_length); - let result = Box::new(SPCp437Grid(servicepoint::Cp437Grid::load( - width, height, data, - ))); - NonNull::from(Box::leak(result)) -} - -/// Clones a [SPCp437Grid]. -/// -/// Will never return NULL. -/// -/// # Panics -/// -/// - when `cp437_grid` is NULL -/// -/// # Safety -/// -/// The caller has to make sure that: -/// -/// - `cp437_grid` points to a valid [SPCp437Grid] -/// - `cp437_grid` is not written to concurrently -/// - the returned instance is freed in some way, either by using a consuming function or -/// by explicitly calling `sp_cp437_grid_free`. -#[no_mangle] -pub unsafe extern "C" fn sp_cp437_grid_clone( - cp437_grid: *const SPCp437Grid, -) -> NonNull { - assert!(!cp437_grid.is_null()); - let result = Box::new((*cp437_grid).clone()); - NonNull::from(Box::leak(result)) -} - -/// Deallocates a [SPCp437Grid]. -/// -/// # Panics -/// -/// - when `cp437_grid` is NULL -/// -/// # Safety -/// -/// The caller has to make sure that: -/// -/// - `cp437_grid` points to a valid [SPCp437Grid] -/// - `cp437_grid` is not used concurrently or after cp437_grid call -/// - `cp437_grid` was not passed to another consuming function, e.g. to create a [SPCommand] -/// -/// [SPCommand]: [crate::SPCommand] -#[no_mangle] -pub unsafe extern "C" fn sp_cp437_grid_free(cp437_grid: *mut SPCp437Grid) { - assert!(!cp437_grid.is_null()); - _ = Box::from_raw(cp437_grid); -} - -/// Gets the current value at the specified position. -/// -/// # Arguments -/// -/// - `cp437_grid`: instance to read from -/// - `x` and `y`: position of the cell to read -/// -/// # Panics -/// -/// - when `cp437_grid` is NULL -/// - when accessing `x` or `y` out of bounds -/// -/// # Safety -/// -/// The caller has to make sure that: -/// -/// - `cp437_grid` points to a valid [SPCp437Grid] -/// - `cp437_grid` is not written to concurrently -#[no_mangle] -pub unsafe extern "C" fn sp_cp437_grid_get( - cp437_grid: *const SPCp437Grid, - x: usize, - y: usize, -) -> u8 { - assert!(!cp437_grid.is_null()); - (*cp437_grid).0.get(x, y) -} - -/// Sets the value of the specified position in the [SPCp437Grid]. -/// -/// # Arguments -/// -/// - `cp437_grid`: instance to write to -/// - `x` and `y`: position of the cell -/// - `value`: the value to write to the cell -/// -/// returns: old value of the cell -/// -/// # Panics -/// -/// - when `cp437_grid` is NULL -/// - when accessing `x` or `y` out of bounds -/// -/// # Safety -/// -/// The caller has to make sure that: -/// -/// - `cp437_grid` points to a valid [SPBitVec] -/// - `cp437_grid` is not written to or read from concurrently -/// -/// [SPBitVec]: [crate::SPBitVec] -#[no_mangle] -pub unsafe extern "C" fn sp_cp437_grid_set( - cp437_grid: *mut SPCp437Grid, - x: usize, - y: usize, - value: u8, -) { - assert!(!cp437_grid.is_null()); - (*cp437_grid).0.set(x, y, value); -} - -/// Sets the value of all cells in the [SPCp437Grid]. -/// -/// # Arguments -/// -/// - `cp437_grid`: instance to write to -/// - `value`: the value to set all cells to -/// -/// # Panics -/// -/// - when `cp437_grid` is NULL -/// -/// # Safety -/// -/// The caller has to make sure that: -/// -/// - `cp437_grid` points to a valid [SPCp437Grid] -/// - `cp437_grid` is not written to or read from concurrently -#[no_mangle] -pub unsafe extern "C" fn sp_cp437_grid_fill( - cp437_grid: *mut SPCp437Grid, - value: u8, -) { - assert!(!cp437_grid.is_null()); - (*cp437_grid).0.fill(value); -} - -/// Gets the width of the [SPCp437Grid] instance. -/// -/// # Arguments -/// -/// - `cp437_grid`: instance to read from -/// -/// # Panics -/// -/// - when `cp437_grid` is NULL -/// -/// # Safety -/// -/// The caller has to make sure that: -/// -/// - `cp437_grid` points to a valid [SPCp437Grid] -#[no_mangle] -pub unsafe extern "C" fn sp_cp437_grid_width( - cp437_grid: *const SPCp437Grid, -) -> usize { - assert!(!cp437_grid.is_null()); - (*cp437_grid).0.width() -} - -/// Gets the height of the [SPCp437Grid] instance. -/// -/// # Arguments -/// -/// - `cp437_grid`: instance to read from -/// -/// # Panics -/// -/// - when `cp437_grid` is NULL -/// -/// # Safety -/// -/// The caller has to make sure that: -/// -/// - `cp437_grid` points to a valid [SPCp437Grid] -#[no_mangle] -pub unsafe extern "C" fn sp_cp437_grid_height( - cp437_grid: *const SPCp437Grid, -) -> usize { - assert!(!cp437_grid.is_null()); - (*cp437_grid).0.height() -} - -/// Gets an unsafe reference to the data of the [SPCp437Grid] instance. -/// -/// Will never return NULL. -/// -/// # Panics -/// -/// - when `cp437_grid` is NULL -/// -/// ## Safety -/// -/// The caller has to make sure that: -/// -/// - `cp437_grid` points to a valid [SPCp437Grid] -/// - the returned memory range is never accessed after the passed [SPCp437Grid] has been freed -/// - the returned memory range is never accessed concurrently, either via the [SPCp437Grid] or directly -#[no_mangle] -pub unsafe extern "C" fn sp_cp437_grid_unsafe_data_ref( - cp437_grid: *mut SPCp437Grid, -) -> SPByteSlice { - let data = (*cp437_grid).0.data_ref_mut(); - SPByteSlice { - start: NonNull::new(data.as_mut_ptr_range().start).unwrap(), - length: data.len(), - } -} diff --git a/crates/servicepoint_binding_c/src/lib.rs b/crates/servicepoint_binding_c/src/lib.rs deleted file mode 100644 index 887fb40..0000000 --- a/crates/servicepoint_binding_c/src/lib.rs +++ /dev/null @@ -1,48 +0,0 @@ -//! C API wrapper for the [servicepoint](https://docs.rs/servicepoint/latest/servicepoint/) crate. -//! -//! # Examples -//! -//! Make sure to check out [this GitHub repo](https://github.com/arfst23/ServicePoint) as well! -//! -//! ```C -//! #include -//! #include "servicepoint.h" -//! -//! int main(void) { -//! SPConnection *connection = sp_connection_open("172.23.42.29:2342"); -//! if (connection == NULL) -//! return 1; -//! -//! SPBitmap *pixels = sp_bitmap_new(SP_PIXEL_WIDTH, SP_PIXEL_HEIGHT); -//! sp_bitmap_fill(pixels, true); -//! -//! SPCommand *command = sp_command_bitmap_linear_win(0, 0, pixels, Uncompressed); -//! while (sp_connection_send_command(connection, sp_command_clone(command))); -//! -//! sp_command_free(command); -//! sp_connection_free(connection); -//! return 0; -//! } -//! ``` - -pub use crate::bitmap::*; -pub use crate::bitvec::*; -pub use crate::brightness_grid::*; -pub use crate::byte_slice::*; -pub use crate::char_grid::*; -pub use crate::command::*; -pub use crate::connection::*; -pub use crate::constants::*; -pub use crate::cp437_grid::*; -pub use crate::packet::*; - -mod bitmap; -mod bitvec; -mod brightness_grid; -mod byte_slice; -mod char_grid; -mod command; -mod connection; -mod constants; -mod cp437_grid; -mod packet; diff --git a/crates/servicepoint_binding_c/src/packet.rs b/crates/servicepoint_binding_c/src/packet.rs deleted file mode 100644 index 9293a8a..0000000 --- a/crates/servicepoint_binding_c/src/packet.rs +++ /dev/null @@ -1,166 +0,0 @@ -//! C functions for interacting with [SPPacket]s -//! -//! prefix `sp_packet_` - -use std::ptr::{null_mut, NonNull}; - -use crate::SPCommand; - -/// The raw packet -pub struct SPPacket(pub(crate) servicepoint::Packet); - -/// Turns a [SPCommand] into a [SPPacket]. -/// The [SPCommand] gets consumed. -/// -/// Will never return NULL. -/// -/// # Panics -/// -/// - when `command` is NULL -/// -/// # Safety -/// -/// The caller has to make sure that: -/// -/// - [SPCommand] points to a valid instance of [SPCommand] -/// - [SPCommand] is not used concurrently or after this call -/// - the returned [SPPacket] instance is freed in some way, either by using a consuming function or -/// by explicitly calling `sp_packet_free`. -#[no_mangle] -pub unsafe extern "C" fn sp_packet_from_command( - command: *mut SPCommand, -) -> NonNull { - assert!(!command.is_null()); - let command = *Box::from_raw(command); - let result = Box::new(SPPacket(command.0.into())); - NonNull::from(Box::leak(result)) -} - -/// Tries to load a [SPPacket] from the passed array with the specified length. -/// -/// returns: NULL in case of an error, pointer to the allocated packet otherwise -/// -/// # Panics -/// -/// - when `data` is NULL -/// -/// # Safety -/// -/// The caller has to make sure that: -/// -/// - `data` points to a valid memory region of at least `length` bytes -/// - `data` is not written to concurrently -/// - the returned [SPPacket] instance is freed in some way, either by using a consuming function or -/// by explicitly calling `sp_packet_free`. -#[no_mangle] -pub unsafe extern "C" fn sp_packet_try_load( - data: *const u8, - length: usize, -) -> *mut SPPacket { - assert!(!data.is_null()); - let data = std::slice::from_raw_parts(data, length); - match servicepoint::Packet::try_from(data) { - Err(_) => null_mut(), - Ok(packet) => Box::into_raw(Box::new(SPPacket(packet))), - } -} - -/// Creates a raw [SPPacket] from parts. -/// -/// # Arguments -/// -/// - `command_code` specifies which command this packet contains -/// - `a`, `b`, `c` and `d` are command-specific header values -/// - `payload` is the optional data that is part of the command -/// - `payload_len` is the size of the payload -/// -/// returns: new instance. Will never return null. -/// -/// # Panics -/// -/// - when `payload` is null, but `payload_len` is not zero -/// - when `payload_len` is zero, but `payload` is nonnull -/// -/// # Safety -/// -/// The caller has to make sure that: -/// -/// - `payload` points to a valid memory region of at least `payload_len` bytes -/// - `payload` is not written to concurrently -/// - the returned [SPPacket] instance is freed in some way, either by using a consuming function or -/// by explicitly calling [sp_packet_free]. -#[no_mangle] -pub unsafe extern "C" fn sp_packet_from_parts( - command_code: u16, - a: u16, - b: u16, - c: u16, - d: u16, - payload: *const u8, - payload_len: usize, -) -> NonNull { - assert_eq!(payload.is_null(), payload_len == 0); - - let payload = if payload.is_null() { - vec![] - } else { - let payload = std::slice::from_raw_parts(payload, payload_len); - Vec::from(payload) - }; - - let packet = servicepoint::Packet { - header: servicepoint::Header { - command_code, - a, - b, - c, - d, - }, - payload, - }; - let result = Box::new(SPPacket(packet)); - NonNull::from(Box::leak(result)) -} - -/// Clones a [SPPacket]. -/// -/// Will never return NULL. -/// -/// # Panics -/// -/// - when `packet` is NULL -/// -/// # Safety -/// -/// The caller has to make sure that: -/// -/// - `packet` points to a valid [SPPacket] -/// - `packet` is not written to concurrently -/// - the returned instance is freed in some way, either by using a consuming function or -/// by explicitly calling `sp_packet_free`. -#[no_mangle] -pub unsafe extern "C" fn sp_packet_clone( - packet: *const SPPacket, -) -> NonNull { - assert!(!packet.is_null()); - let result = Box::new(SPPacket((*packet).0.clone())); - NonNull::from(Box::leak(result)) -} - -/// Deallocates a [SPPacket]. -/// -/// # Panics -/// -/// - when `packet` is NULL -/// -/// # Safety -/// -/// The caller has to make sure that: -/// -/// - `packet` points to a valid [SPPacket] -/// - `packet` is not used concurrently or after this call -#[no_mangle] -pub unsafe extern "C" fn sp_packet_free(packet: *mut SPPacket) { - assert!(!packet.is_null()); - _ = Box::from_raw(packet) -} diff --git a/crates/servicepoint_binding_uniffi/Cargo.toml b/crates/servicepoint_binding_uniffi/Cargo.toml deleted file mode 100644 index 0af1af9..0000000 --- a/crates/servicepoint_binding_uniffi/Cargo.toml +++ /dev/null @@ -1,61 +0,0 @@ -[package] -name = "servicepoint_binding_uniffi" -version.workspace = true -publish = false -edition = "2021" -license = "GPL-3.0-or-later" -description = "C bindings for the servicepoint crate." -homepage = "https://docs.rs/crate/servicepoint_binding_c" -repository = "https://git.berlin.ccc.de/servicepoint/servicepoint" -#readme = "README.md" -keywords = ["cccb", "cccb-servicepoint", "uniffi"] - -[lib] -crate-type = ["cdylib"] - -[build-dependencies] -uniffi = { version = "0.25.3", features = ["build"] } - -[dependencies] -uniffi = { version = "0.25.3" } -thiserror.workspace = true - -[dependencies.servicepoint] -version = "0.13.1" -path = "../servicepoint" -features = ["all_compressions"] - -[dependencies.uniffi-bindgen-cs] -git = "https://github.com/NordSecurity/uniffi-bindgen-cs" -# tag="v0.8.3+v0.25.0" -rev = "f68639fbc720b50ebe561ba75c66c84dc456bdce" -optional = true - -[dependencies.uniffi-bindgen-go] -git = "https://github.com/NordSecurity/uniffi-bindgen-go.git" -# tag = "0.2.2+v0.25.0" -rev = "ba23bab72f1a9bcc39ce81924d3d9265598e017c" -optional = true - -[lints] -#workspace = true - -[package.metadata.docs.rs] -all-features = true - -[[bin]] -name = "uniffi-bindgen" -required-features = ["uniffi/cli"] - -[[bin]] -name = "uniffi-bindgen-cs" -required-features = ["cs"] - -[[bin]] -name = "uniffi-bindgen-go" -required-features = ["go"] - -[features] -default = [] -cs = ["dep:uniffi-bindgen-cs"] -go = ["dep:uniffi-bindgen-go"] diff --git a/crates/servicepoint_binding_uniffi/README.md b/crates/servicepoint_binding_uniffi/README.md deleted file mode 100644 index 27d05ed..0000000 --- a/crates/servicepoint_binding_uniffi/README.md +++ /dev/null @@ -1,90 +0,0 @@ -# ServicePoint - -In [CCCB](https://berlin.ccc.de/), there is a big pixel matrix hanging on the wall. It is called "Service Point -Display" or "Airport Display". - -This crate contains bindings for multiple programming languages, enabling non-rust-developers to use the library. - -Also take a look at the main project [README](https://git.berlin.ccc.de/servicepoint/servicepoint/src/branch/main/README.md) for more -information. - -## Note on stability - -This library is still in early development. -You can absolutely use it, and it works, but expect minor breaking changes with every version bump. - -## Notes on differences to rust library - -- Performance will not be as good as the rust version: - - most objects are reference counted. - - objects with mutating methods will also have a MRSW lock -- You will not get rust backtraces in release builds of the native code -- Panic messages will work (PanicException) - -## Supported languages - -| Language | Support level | Notes | -|-----------|---------------|-------------------------------------------------------------------------------------------------| -| .NET (C#) | Full | see dedicated section | -| Ruby | Working | LD_LIBRARY_PATH has to be set, see example project | -| Python | Tested once | Required project file not included. The shared library will be loaded from the script location. | -| Go | untested | | -| Kotlin | untested | | -| Swift | untested | | - -## Installation - -Including this repository as a submodule and building from source is the recommended way of using the library. - -```bash -git submodule add https://git.berlin.ccc.de/servicepoint/servicepoint.git -git commit -m "add servicepoint submodule" -``` - -Run `generate-bindings.sh` to regenerate all bindings. This will also build `libservicepoint.so` (or equivalent on your -platform). - -For languages not fully supported, there will be no project file for the library, just the naked source file(s). -If you successfully use a language, please open an issue or PR to add the missing ones. - -## .NET (C#) - -This is the best supported language. - -F# is not tested. If there are usability or functionality problems, please open an issue. - -Currently, the project file is hard-coded for Linux and will need tweaks for other platforms (e.g. `.dylib` instead of `.so`). - -You do not have to compile or copy the rust crate manually, as building `ServicePoint.csproj` also builds it. - -### Example - -```csharp -using System.Threading; -using ServicePoint; - -var connection = new Connection("127.0.0.1:2342"); -connection.Send(Command.Clear()); - -connection.Send(Command.Brightness(5)); - -var pixels = Bitmap.NewMaxSized(); -for (ulong offset = 0; offset < ulong.MaxValue; offset++) -{ - pixels.Fill(false); - - for (ulong y = 0; y < pixels.Height(); y++) - pixels.Set((y + offset) % pixels.Width(), y, true); - - connection.Send(Command.BitmapLinearWin(0, 0, pixels)); - Thread.Sleep(14); -} -``` - -A full example including project files is available as part of this crate. - -### Why is there no NuGet-Package? - -NuGet packages are not a good way to distribute native -binaries ([relevant issue](https://github.com/dotnet/sdk/issues/33845)). -Because of that, there is no NuGet package you can use directly. diff --git a/crates/servicepoint_binding_uniffi/generate-bindings.sh b/crates/servicepoint_binding_uniffi/generate-bindings.sh deleted file mode 100755 index bfb571c..0000000 --- a/crates/servicepoint_binding_uniffi/generate-bindings.sh +++ /dev/null @@ -1,24 +0,0 @@ -#!/usr/bin/env bash -set -e - -cargo build --release - -SCRIPT_PATH="$( cd -- "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P )" -TARGET_PATH="$(realpath "$SCRIPT_PATH"/../../target/release)" -SERVICEPOINT_SO="$TARGET_PATH/libservicepoint_binding_uniffi.so" -LIBRARIES_PATH="$SCRIPT_PATH/libraries" - -echo "Source: $SERVICEPOINT_SO" -echo "Output: $LIBRARIES_PATH" - -BINDGEN="cargo run --features=uniffi/cli --bin uniffi-bindgen -- " -BINDGEN_CS="cargo run --features=cs --bin uniffi-bindgen-cs -- " -BINDGEN_GO="cargo run --features=go --bin uniffi-bindgen-go -- " -COMMON_ARGS="--library $SERVICEPOINT_SO" - -${BINDGEN} generate $COMMON_ARGS --language python --out-dir "$LIBRARIES_PATH/python" -${BINDGEN} generate $COMMON_ARGS --language kotlin --out-dir "$LIBRARIES_PATH/kotlin" -${BINDGEN} generate $COMMON_ARGS --language swift --out-dir "$LIBRARIES_PATH/swift" -${BINDGEN} generate $COMMON_ARGS --language ruby --out-dir "$LIBRARIES_PATH/ruby/lib" -${BINDGEN_CS} $COMMON_ARGS --out-dir "$LIBRARIES_PATH/csharp/ServicePoint" -${BINDGEN_GO} $COMMON_ARGS --out-dir "$LIBRARIES_PATH/go/" diff --git a/crates/servicepoint_binding_uniffi/libraries/.gitignore b/crates/servicepoint_binding_uniffi/libraries/.gitignore deleted file mode 100644 index a875c72..0000000 --- a/crates/servicepoint_binding_uniffi/libraries/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -go -kotlin -python -swift \ No newline at end of file diff --git a/crates/servicepoint_binding_uniffi/libraries/csharp/.gitignore b/crates/servicepoint_binding_uniffi/libraries/csharp/.gitignore deleted file mode 100644 index 1746e32..0000000 --- a/crates/servicepoint_binding_uniffi/libraries/csharp/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -bin -obj diff --git a/crates/servicepoint_binding_uniffi/libraries/csharp/ServicePoint.Example/.gitignore b/crates/servicepoint_binding_uniffi/libraries/csharp/ServicePoint.Example/.gitignore deleted file mode 100644 index 1746e32..0000000 --- a/crates/servicepoint_binding_uniffi/libraries/csharp/ServicePoint.Example/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -bin -obj diff --git a/crates/servicepoint_binding_uniffi/libraries/csharp/ServicePoint.Example/Program.cs b/crates/servicepoint_binding_uniffi/libraries/csharp/ServicePoint.Example/Program.cs deleted file mode 100644 index 48462a5..0000000 --- a/crates/servicepoint_binding_uniffi/libraries/csharp/ServicePoint.Example/Program.cs +++ /dev/null @@ -1,19 +0,0 @@ -using System.Threading; -using ServicePoint; - -var connection = new Connection("127.0.0.1:2342"); -connection.Send(Command.Clear()); - -connection.Send(Command.Brightness(5)); - -var pixels = Bitmap.NewMaxSized(); -for (ulong offset = 0; offset < ulong.MaxValue; offset++) -{ - pixels.Fill(false); - - for (ulong y = 0; y < pixels.Height(); y++) - pixels.Set((y + offset) % pixels.Width(), y, true); - - connection.Send(Command.BitmapLinearWin(0, 0, pixels)); - Thread.Sleep(14); -} diff --git a/crates/servicepoint_binding_uniffi/libraries/csharp/ServicePoint.Example/ServicePoint.Example.csproj b/crates/servicepoint_binding_uniffi/libraries/csharp/ServicePoint.Example/ServicePoint.Example.csproj deleted file mode 100644 index 3e99664..0000000 --- a/crates/servicepoint_binding_uniffi/libraries/csharp/ServicePoint.Example/ServicePoint.Example.csproj +++ /dev/null @@ -1,15 +0,0 @@ - - - - Exe - net8.0 - ServicePoint.Example - disable - enable - - - - - - - diff --git a/crates/servicepoint_binding_uniffi/libraries/csharp/ServicePoint.Tests/BitmapTests.cs b/crates/servicepoint_binding_uniffi/libraries/csharp/ServicePoint.Tests/BitmapTests.cs deleted file mode 100644 index 9e55a80..0000000 --- a/crates/servicepoint_binding_uniffi/libraries/csharp/ServicePoint.Tests/BitmapTests.cs +++ /dev/null @@ -1,16 +0,0 @@ -namespace ServicePoint.Tests; - -public class BitmapTests -{ - [Fact] - public void BasicFunctions() - { - var bitmap = new Bitmap(8, 2); - Assert.False(bitmap.Get(0, 0)); - Assert.False(bitmap.Get(bitmap.Width() - 1, bitmap.Height() - 1)); - bitmap.Fill(true); - Assert.True(bitmap.Get(1, 1)); - bitmap.Set(1, 1, false); - Assert.False(bitmap.Get(1, 1)); - } -} diff --git a/crates/servicepoint_binding_uniffi/libraries/csharp/ServicePoint.Tests/CharGridTests.cs b/crates/servicepoint_binding_uniffi/libraries/csharp/ServicePoint.Tests/CharGridTests.cs deleted file mode 100644 index de849c6..0000000 --- a/crates/servicepoint_binding_uniffi/libraries/csharp/ServicePoint.Tests/CharGridTests.cs +++ /dev/null @@ -1,31 +0,0 @@ -namespace ServicePoint.Tests; - -public class CharGridTests -{ - [Fact] - public void BasicFunctions() - { - var grid = new CharGrid(8, 2); - Assert.Equal("\0", grid.Get(0, 0)); - Assert.Equal("\0", grid.Get(grid.Width() - 1, grid.Height() - 1)); - grid.Fill(" "); - Assert.Equal(" ", grid.Get(1, 1)); - grid.Set(1, 1, "-"); - Assert.Equal("-", grid.Get(1, 1)); - Assert.Throws(() => grid.Get(8, 2)); - } - - [Fact] - public void RowAndCol() - { - var grid = new CharGrid(3, 2); - Assert.Equal("\0\0\0", grid.GetRow(0)); - grid.Fill(" "); - Assert.Equal(" ", grid.GetCol(1)); - Assert.Throws(() => grid.GetCol(3)); - Assert.Throws(() => grid.SetRow(1, "Text")); - grid.SetRow(1, "Foo"); - Assert.Equal("Foo", grid.GetRow(1)); - Assert.Equal(" o", grid.GetCol(2)); - } -} diff --git a/crates/servicepoint_binding_uniffi/libraries/csharp/ServicePoint.Tests/CommandTests.cs b/crates/servicepoint_binding_uniffi/libraries/csharp/ServicePoint.Tests/CommandTests.cs deleted file mode 100644 index 4687162..0000000 --- a/crates/servicepoint_binding_uniffi/libraries/csharp/ServicePoint.Tests/CommandTests.cs +++ /dev/null @@ -1,42 +0,0 @@ -namespace ServicePoint.Tests; - -public class CommandTests -{ - private Connection _connection = Connection.NewFake(); - - [Fact] - public void ClearSendable() - { - _connection.Send(Command.Clear()); - } - - [Fact] - public void BrightnessSendable() - { - _connection.Send(Command.Brightness(5)); - } - - [Fact] - public void InvalidBrightnessThrows() - { - Assert.Throws(() => Command.Brightness(42)); - } - - [Fact] - public void FadeOutSendable() - { - _connection.Send(Command.FadeOut()); - } - - [Fact] - public void HardResetSendable() - { - _connection.Send(Command.HardReset()); - } - - [Fact] - public void BitmapLinearWinSendable() - { - _connection.Send(Command.BitmapLinearWin(0, 0, Bitmap.NewMaxSized(), CompressionCode.Uncompressed)); - } -} diff --git a/crates/servicepoint_binding_uniffi/libraries/csharp/ServicePoint.Tests/ConnectionTests.cs b/crates/servicepoint_binding_uniffi/libraries/csharp/ServicePoint.Tests/ConnectionTests.cs deleted file mode 100644 index be0000f..0000000 --- a/crates/servicepoint_binding_uniffi/libraries/csharp/ServicePoint.Tests/ConnectionTests.cs +++ /dev/null @@ -1,11 +0,0 @@ -namespace ServicePoint.Tests; - -public class ConnectionTests -{ - [Fact] - public void InvalidHostnameThrows() - { - Assert.Throws(() => new Connection("")); - Assert.Throws(() => new Connection("-%6$§")); - } -} diff --git a/crates/servicepoint_binding_uniffi/libraries/csharp/ServicePoint.Tests/GlobalUsings.cs b/crates/servicepoint_binding_uniffi/libraries/csharp/ServicePoint.Tests/GlobalUsings.cs deleted file mode 100644 index a09810b..0000000 --- a/crates/servicepoint_binding_uniffi/libraries/csharp/ServicePoint.Tests/GlobalUsings.cs +++ /dev/null @@ -1,2 +0,0 @@ -global using Xunit; -global using ServicePoint; diff --git a/crates/servicepoint_binding_uniffi/libraries/csharp/ServicePoint.Tests/ServicePoint.Tests.csproj b/crates/servicepoint_binding_uniffi/libraries/csharp/ServicePoint.Tests/ServicePoint.Tests.csproj deleted file mode 100644 index 50500b6..0000000 --- a/crates/servicepoint_binding_uniffi/libraries/csharp/ServicePoint.Tests/ServicePoint.Tests.csproj +++ /dev/null @@ -1,27 +0,0 @@ - - - - net8.0 - disable - enable - - false - true - - - - - - - - - - - - - - - - - - diff --git a/crates/servicepoint_binding_uniffi/libraries/csharp/ServicePoint/Constants.cs b/crates/servicepoint_binding_uniffi/libraries/csharp/ServicePoint/Constants.cs deleted file mode 100644 index 58cf560..0000000 --- a/crates/servicepoint_binding_uniffi/libraries/csharp/ServicePoint/Constants.cs +++ /dev/null @@ -1,14 +0,0 @@ - -using ServicePoint; - -public static class ServicePointConstants -{ - private static readonly Constants _instance = ServicepointBindingUniffiMethods.GetConstants(); - - public static readonly ulong PixelWidth = _instance.pixelWidth; - public static readonly ulong PixelHeight = _instance.pixelHeight; - public static readonly ulong PixelCount = _instance.pixelCount; - public static readonly ulong TileWidth = _instance.tileWidth; - public static readonly ulong TileHeight = _instance.tileHeight; - public static readonly ulong TileSize = _instance.tileSize; -} diff --git a/crates/servicepoint_binding_uniffi/libraries/csharp/ServicePoint/ServicePoint.csproj b/crates/servicepoint_binding_uniffi/libraries/csharp/ServicePoint/ServicePoint.csproj deleted file mode 100644 index 70d12b3..0000000 --- a/crates/servicepoint_binding_uniffi/libraries/csharp/ServicePoint/ServicePoint.csproj +++ /dev/null @@ -1,53 +0,0 @@ - - - - net8.0 - disable - enable - true - - - - ServicePoint - 0.13.1 - Repository Authors - None - ServicePoint - CCCB - - C# bindings for the rust crate servicepoint. You will need a suitable native shared library to use this. - For documentation, see the rust documentation: https://docs.rs/servicepoint/latest/servicepoint/. - Note that this library is still in early development. Breaking changes are expected before 1.0 is released. - - README.md - true - - - - - - - - - - - - - - libservicepoint_binding_uniffi.so - - - - - libservicepoint_binding_uniffi.so - - - - - - - - - - - diff --git a/crates/servicepoint_binding_uniffi/libraries/csharp/ServicePoint/servicepoint_binding_uniffi.cs b/crates/servicepoint_binding_uniffi/libraries/csharp/ServicePoint/servicepoint_binding_uniffi.cs deleted file mode 100644 index 2039307..0000000 --- a/crates/servicepoint_binding_uniffi/libraries/csharp/ServicePoint/servicepoint_binding_uniffi.cs +++ /dev/null @@ -1,3225 +0,0 @@ -// -// This file was generated by uniffi-bindgen-cs v0.8.3+v0.25.0 -// See https://github.com/NordSecurity/uniffi-bindgen-cs for more information. -// - -#nullable enable - - - - -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Runtime.InteropServices; -namespace ServicePoint; - - - -// This is a helper for safely working with byte buffers returned from the Rust code. -// A rust-owned buffer is represented by its capacity, its current length, and a -// pointer to the underlying data. - -[StructLayout(LayoutKind.Sequential)] -internal struct RustBuffer { - public int capacity; - public int len; - public IntPtr data; - - public static RustBuffer Alloc(int size) { - return _UniffiHelpers.RustCall((ref RustCallStatus status) => { - var buffer = _UniFFILib.ffi_servicepoint_binding_uniffi_rustbuffer_alloc(size, ref status); - if (buffer.data == IntPtr.Zero) { - throw new AllocationException($"RustBuffer.Alloc() returned null data pointer (size={size})"); - } - return buffer; - }); - } - - public static void Free(RustBuffer buffer) { - _UniffiHelpers.RustCall((ref RustCallStatus status) => { - _UniFFILib.ffi_servicepoint_binding_uniffi_rustbuffer_free(buffer, ref status); - }); - } - - public static BigEndianStream MemoryStream(IntPtr data, int length) { - unsafe { - return new BigEndianStream(new UnmanagedMemoryStream((byte*)data.ToPointer(), length)); - } - } - - public BigEndianStream AsStream() { - unsafe { - return new BigEndianStream(new UnmanagedMemoryStream((byte*)data.ToPointer(), len)); - } - } - - public BigEndianStream AsWriteableStream() { - unsafe { - return new BigEndianStream(new UnmanagedMemoryStream((byte*)data.ToPointer(), capacity, capacity, FileAccess.Write)); - } - } -} - -// This is a helper for safely passing byte references into the rust code. -// It's not actually used at the moment, because there aren't many things that you -// can take a direct pointer to managed memory, and if we're going to copy something -// then we might as well copy it into a `RustBuffer`. But it's here for API -// completeness. - -[StructLayout(LayoutKind.Sequential)] -internal struct ForeignBytes { - public int length; - public IntPtr data; -} - - -// The FfiConverter interface handles converter types to and from the FFI -// -// All implementing objects should be public to support external types. When a -// type is external we need to import it's FfiConverter. -internal abstract class FfiConverter { - // Convert an FFI type to a C# type - public abstract CsType Lift(FfiType value); - - // Convert C# type to an FFI type - public abstract FfiType Lower(CsType value); - - // Read a C# type from a `ByteBuffer` - public abstract CsType Read(BigEndianStream stream); - - // Calculate bytes to allocate when creating a `RustBuffer` - // - // This must return at least as many bytes as the write() function will - // write. It can return more bytes than needed, for example when writing - // Strings we can't know the exact bytes needed until we the UTF-8 - // encoding, so we pessimistically allocate the largest size possible (3 - // bytes per codepoint). Allocating extra bytes is not really a big deal - // because the `RustBuffer` is short-lived. - public abstract int AllocationSize(CsType value); - - // Write a C# type to a `ByteBuffer` - public abstract void Write(CsType value, BigEndianStream stream); - - // Lower a value into a `RustBuffer` - // - // This method lowers a value into a `RustBuffer` rather than the normal - // FfiType. It's used by the callback interface code. Callback interface - // returns are always serialized into a `RustBuffer` regardless of their - // normal FFI type. - public RustBuffer LowerIntoRustBuffer(CsType value) { - var rbuf = RustBuffer.Alloc(AllocationSize(value)); - try { - var stream = rbuf.AsWriteableStream(); - Write(value, stream); - rbuf.len = Convert.ToInt32(stream.Position); - return rbuf; - } catch { - RustBuffer.Free(rbuf); - throw; - } - } - - // Lift a value from a `RustBuffer`. - // - // This here mostly because of the symmetry with `lowerIntoRustBuffer()`. - // It's currently only used by the `FfiConverterRustBuffer` class below. - protected CsType LiftFromRustBuffer(RustBuffer rbuf) { - var stream = rbuf.AsStream(); - try { - var item = Read(stream); - if (stream.HasRemaining()) { - throw new InternalException("junk remaining in buffer after lifting, something is very wrong!!"); - } - return item; - } finally { - RustBuffer.Free(rbuf); - } - } -} - -// FfiConverter that uses `RustBuffer` as the FfiType -internal abstract class FfiConverterRustBuffer: FfiConverter { - public override CsType Lift(RustBuffer value) { - return LiftFromRustBuffer(value); - } - public override RustBuffer Lower(CsType value) { - return LowerIntoRustBuffer(value); - } -} - - -// A handful of classes and functions to support the generated data structures. -// This would be a good candidate for isolating in its own ffi-support lib. -// Error runtime. -[StructLayout(LayoutKind.Sequential)] -struct RustCallStatus { - public sbyte code; - public RustBuffer error_buf; - - public bool IsSuccess() { - return code == 0; - } - - public bool IsError() { - return code == 1; - } - - public bool IsPanic() { - return code == 2; - } -} - -// Base class for all uniffi exceptions -public class UniffiException: Exception { - public UniffiException(): base() {} - public UniffiException(string message): base(message) {} -} - -public class UndeclaredErrorException: UniffiException { - public UndeclaredErrorException(string message): base(message) {} -} - -public class PanicException: UniffiException { - public PanicException(string message): base(message) {} -} - -public class AllocationException: UniffiException { - public AllocationException(string message): base(message) {} -} - -public class InternalException: UniffiException { - public InternalException(string message): base(message) {} -} - -public class InvalidEnumException: InternalException { - public InvalidEnumException(string message): base(message) { - } -} - -public class UniffiContractVersionException: UniffiException { - public UniffiContractVersionException(string message): base(message) { - } -} - -public class UniffiContractChecksumException: UniffiException { - public UniffiContractChecksumException(string message): base(message) { - } -} - -// Each top-level error class has a companion object that can lift the error from the call status's rust buffer -interface CallStatusErrorHandler where E: Exception { - E Lift(RustBuffer error_buf); -} - -// CallStatusErrorHandler implementation for times when we don't expect a CALL_ERROR -class NullCallStatusErrorHandler: CallStatusErrorHandler { - public static NullCallStatusErrorHandler INSTANCE = new NullCallStatusErrorHandler(); - - public UniffiException Lift(RustBuffer error_buf) { - RustBuffer.Free(error_buf); - return new UndeclaredErrorException("library has returned an error not declared in UNIFFI interface file"); - } -} - -// Helpers for calling Rust -// In practice we usually need to be synchronized to call this safely, so it doesn't -// synchronize itself -class _UniffiHelpers { - public delegate void RustCallAction(ref RustCallStatus status); - public delegate U RustCallFunc(ref RustCallStatus status); - - // Call a rust function that returns a Result<>. Pass in the Error class companion that corresponds to the Err - public static U RustCallWithError(CallStatusErrorHandler errorHandler, RustCallFunc callback) - where E: UniffiException - { - var status = new RustCallStatus(); - var return_value = callback(ref status); - if (status.IsSuccess()) { - return return_value; - } else if (status.IsError()) { - throw errorHandler.Lift(status.error_buf); - } else if (status.IsPanic()) { - // when the rust code sees a panic, it tries to construct a rustbuffer - // with the message. but if that code panics, then it just sends back - // an empty buffer. - if (status.error_buf.len > 0) { - throw new PanicException(FfiConverterString.INSTANCE.Lift(status.error_buf)); - } else { - throw new PanicException("Rust panic"); - } - } else { - throw new InternalException($"Unknown rust call status: {status.code}"); - } - } - - // Call a rust function that returns a Result<>. Pass in the Error class companion that corresponds to the Err - public static void RustCallWithError(CallStatusErrorHandler errorHandler, RustCallAction callback) - where E: UniffiException - { - _UniffiHelpers.RustCallWithError(errorHandler, (ref RustCallStatus status) => { - callback(ref status); - return 0; - }); - } - - // Call a rust function that returns a plain value - public static U RustCall(RustCallFunc callback) { - return _UniffiHelpers.RustCallWithError(NullCallStatusErrorHandler.INSTANCE, callback); - } - - // Call a rust function that returns a plain value - public static void RustCall(RustCallAction callback) { - _UniffiHelpers.RustCall((ref RustCallStatus status) => { - callback(ref status); - return 0; - }); - } -} - - -// Big endian streams are not yet available in dotnet :'( -// https://github.com/dotnet/runtime/issues/26904 - -class StreamUnderflowException: Exception { - public StreamUnderflowException() { - } -} - -class BigEndianStream { - Stream stream; - public BigEndianStream(Stream stream) { - this.stream = stream; - } - - public bool HasRemaining() { - return (stream.Length - stream.Position) > 0; - } - - public long Position { - get => stream.Position; - set => stream.Position = value; - } - - public void WriteBytes(byte[] value) { - stream.Write(value, 0, value.Length); - } - - public void WriteByte(byte value) { - stream.WriteByte(value); - } - - public void WriteUShort(ushort value) { - stream.WriteByte((byte)(value >> 8)); - stream.WriteByte((byte)value); - } - - public void WriteUInt(uint value) { - stream.WriteByte((byte)(value >> 24)); - stream.WriteByte((byte)(value >> 16)); - stream.WriteByte((byte)(value >> 8)); - stream.WriteByte((byte)value); - } - - public void WriteULong(ulong value) { - WriteUInt((uint)(value >> 32)); - WriteUInt((uint)value); - } - - public void WriteSByte(sbyte value) { - stream.WriteByte((byte)value); - } - - public void WriteShort(short value) { - WriteUShort((ushort)value); - } - - public void WriteInt(int value) { - WriteUInt((uint)value); - } - - public void WriteFloat(float value) { - unsafe { - WriteInt(*((int*)&value)); - } - } - - public void WriteLong(long value) { - WriteULong((ulong)value); - } - - public void WriteDouble(double value) { - WriteLong(BitConverter.DoubleToInt64Bits(value)); - } - - public byte[] ReadBytes(int length) { - CheckRemaining(length); - byte[] result = new byte[length]; - stream.Read(result, 0, length); - return result; - } - - public byte ReadByte() { - CheckRemaining(1); - return Convert.ToByte(stream.ReadByte()); - } - - public ushort ReadUShort() { - CheckRemaining(2); - return (ushort)(stream.ReadByte() << 8 | stream.ReadByte()); - } - - public uint ReadUInt() { - CheckRemaining(4); - return (uint)(stream.ReadByte() << 24 - | stream.ReadByte() << 16 - | stream.ReadByte() << 8 - | stream.ReadByte()); - } - - public ulong ReadULong() { - return (ulong)ReadUInt() << 32 | (ulong)ReadUInt(); - } - - public sbyte ReadSByte() { - return (sbyte)ReadByte(); - } - - public short ReadShort() { - return (short)ReadUShort(); - } - - public int ReadInt() { - return (int)ReadUInt(); - } - - public float ReadFloat() { - unsafe { - int value = ReadInt(); - return *((float*)&value); - } - } - - public long ReadLong() { - return (long)ReadULong(); - } - - public double ReadDouble() { - return BitConverter.Int64BitsToDouble(ReadLong()); - } - - private void CheckRemaining(int length) { - if (stream.Length - stream.Position < length) { - throw new StreamUnderflowException(); - } - } -} - -// Contains loading, initialization code, -// and the FFI Function declarations in a com.sun.jna.Library. - - -// This is an implementation detail which will be called internally by the public API. -static class _UniFFILib { - static _UniFFILib() { - _UniFFILib.uniffiCheckContractApiVersion(); - _UniFFILib.uniffiCheckApiChecksums(); - - } - - [DllImport("servicepoint_binding_uniffi")] - public static extern void uniffi_servicepoint_binding_uniffi_fn_free_bitvec( - IntPtr ptr,ref RustCallStatus _uniffi_out_err - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern BitVecSafeHandle uniffi_servicepoint_binding_uniffi_fn_constructor_bitvec_clone(BitVecSafeHandle @other,ref RustCallStatus _uniffi_out_err - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern BitVecSafeHandle uniffi_servicepoint_binding_uniffi_fn_constructor_bitvec_load(RustBuffer @data,ref RustCallStatus _uniffi_out_err - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern BitVecSafeHandle uniffi_servicepoint_binding_uniffi_fn_constructor_bitvec_new(ulong @size,ref RustCallStatus _uniffi_out_err - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern RustBuffer uniffi_servicepoint_binding_uniffi_fn_method_bitvec_copy_raw(BitVecSafeHandle @ptr,ref RustCallStatus _uniffi_out_err - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern sbyte uniffi_servicepoint_binding_uniffi_fn_method_bitvec_equals(BitVecSafeHandle @ptr,BitVecSafeHandle @other,ref RustCallStatus _uniffi_out_err - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern void uniffi_servicepoint_binding_uniffi_fn_method_bitvec_fill(BitVecSafeHandle @ptr,sbyte @value,ref RustCallStatus _uniffi_out_err - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern sbyte uniffi_servicepoint_binding_uniffi_fn_method_bitvec_get(BitVecSafeHandle @ptr,ulong @index,ref RustCallStatus _uniffi_out_err - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern ulong uniffi_servicepoint_binding_uniffi_fn_method_bitvec_len(BitVecSafeHandle @ptr,ref RustCallStatus _uniffi_out_err - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern void uniffi_servicepoint_binding_uniffi_fn_method_bitvec_set(BitVecSafeHandle @ptr,ulong @index,sbyte @value,ref RustCallStatus _uniffi_out_err - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern void uniffi_servicepoint_binding_uniffi_fn_free_bitmap( - IntPtr ptr,ref RustCallStatus _uniffi_out_err - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern BitmapSafeHandle uniffi_servicepoint_binding_uniffi_fn_constructor_bitmap_clone(BitmapSafeHandle @other,ref RustCallStatus _uniffi_out_err - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern BitmapSafeHandle uniffi_servicepoint_binding_uniffi_fn_constructor_bitmap_load(ulong @width,ulong @height,RustBuffer @data,ref RustCallStatus _uniffi_out_err - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern BitmapSafeHandle uniffi_servicepoint_binding_uniffi_fn_constructor_bitmap_new(ulong @width,ulong @height,ref RustCallStatus _uniffi_out_err - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern BitmapSafeHandle uniffi_servicepoint_binding_uniffi_fn_constructor_bitmap_new_max_sized(ref RustCallStatus _uniffi_out_err - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern RustBuffer uniffi_servicepoint_binding_uniffi_fn_method_bitmap_copy_raw(BitmapSafeHandle @ptr,ref RustCallStatus _uniffi_out_err - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern sbyte uniffi_servicepoint_binding_uniffi_fn_method_bitmap_equals(BitmapSafeHandle @ptr,BitmapSafeHandle @other,ref RustCallStatus _uniffi_out_err - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern void uniffi_servicepoint_binding_uniffi_fn_method_bitmap_fill(BitmapSafeHandle @ptr,sbyte @value,ref RustCallStatus _uniffi_out_err - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern sbyte uniffi_servicepoint_binding_uniffi_fn_method_bitmap_get(BitmapSafeHandle @ptr,ulong @x,ulong @y,ref RustCallStatus _uniffi_out_err - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern ulong uniffi_servicepoint_binding_uniffi_fn_method_bitmap_height(BitmapSafeHandle @ptr,ref RustCallStatus _uniffi_out_err - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern void uniffi_servicepoint_binding_uniffi_fn_method_bitmap_set(BitmapSafeHandle @ptr,ulong @x,ulong @y,sbyte @value,ref RustCallStatus _uniffi_out_err - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern ulong uniffi_servicepoint_binding_uniffi_fn_method_bitmap_width(BitmapSafeHandle @ptr,ref RustCallStatus _uniffi_out_err - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern void uniffi_servicepoint_binding_uniffi_fn_free_brightnessgrid( - IntPtr ptr,ref RustCallStatus _uniffi_out_err - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern BrightnessGridSafeHandle uniffi_servicepoint_binding_uniffi_fn_constructor_brightnessgrid_clone(BrightnessGridSafeHandle @other,ref RustCallStatus _uniffi_out_err - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern BrightnessGridSafeHandle uniffi_servicepoint_binding_uniffi_fn_constructor_brightnessgrid_load(ulong @width,ulong @height,RustBuffer @data,ref RustCallStatus _uniffi_out_err - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern BrightnessGridSafeHandle uniffi_servicepoint_binding_uniffi_fn_constructor_brightnessgrid_new(ulong @width,ulong @height,ref RustCallStatus _uniffi_out_err - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern RustBuffer uniffi_servicepoint_binding_uniffi_fn_method_brightnessgrid_copy_raw(BrightnessGridSafeHandle @ptr,ref RustCallStatus _uniffi_out_err - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern sbyte uniffi_servicepoint_binding_uniffi_fn_method_brightnessgrid_equals(BrightnessGridSafeHandle @ptr,BrightnessGridSafeHandle @other,ref RustCallStatus _uniffi_out_err - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern void uniffi_servicepoint_binding_uniffi_fn_method_brightnessgrid_fill(BrightnessGridSafeHandle @ptr,byte @value,ref RustCallStatus _uniffi_out_err - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern byte uniffi_servicepoint_binding_uniffi_fn_method_brightnessgrid_get(BrightnessGridSafeHandle @ptr,ulong @x,ulong @y,ref RustCallStatus _uniffi_out_err - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern ulong uniffi_servicepoint_binding_uniffi_fn_method_brightnessgrid_height(BrightnessGridSafeHandle @ptr,ref RustCallStatus _uniffi_out_err - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern void uniffi_servicepoint_binding_uniffi_fn_method_brightnessgrid_set(BrightnessGridSafeHandle @ptr,ulong @x,ulong @y,byte @value,ref RustCallStatus _uniffi_out_err - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern ulong uniffi_servicepoint_binding_uniffi_fn_method_brightnessgrid_width(BrightnessGridSafeHandle @ptr,ref RustCallStatus _uniffi_out_err - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern void uniffi_servicepoint_binding_uniffi_fn_free_chargrid( - IntPtr ptr,ref RustCallStatus _uniffi_out_err - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern CharGridSafeHandle uniffi_servicepoint_binding_uniffi_fn_constructor_chargrid_clone(CharGridSafeHandle @other,ref RustCallStatus _uniffi_out_err - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern CharGridSafeHandle uniffi_servicepoint_binding_uniffi_fn_constructor_chargrid_load(RustBuffer @data,ref RustCallStatus _uniffi_out_err - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern CharGridSafeHandle uniffi_servicepoint_binding_uniffi_fn_constructor_chargrid_new(ulong @width,ulong @height,ref RustCallStatus _uniffi_out_err - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern RustBuffer uniffi_servicepoint_binding_uniffi_fn_method_chargrid_as_string(CharGridSafeHandle @ptr,ref RustCallStatus _uniffi_out_err - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern sbyte uniffi_servicepoint_binding_uniffi_fn_method_chargrid_equals(CharGridSafeHandle @ptr,CharGridSafeHandle @other,ref RustCallStatus _uniffi_out_err - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern void uniffi_servicepoint_binding_uniffi_fn_method_chargrid_fill(CharGridSafeHandle @ptr,RustBuffer @value,ref RustCallStatus _uniffi_out_err - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern RustBuffer uniffi_servicepoint_binding_uniffi_fn_method_chargrid_get(CharGridSafeHandle @ptr,ulong @x,ulong @y,ref RustCallStatus _uniffi_out_err - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern RustBuffer uniffi_servicepoint_binding_uniffi_fn_method_chargrid_get_col(CharGridSafeHandle @ptr,ulong @x,ref RustCallStatus _uniffi_out_err - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern RustBuffer uniffi_servicepoint_binding_uniffi_fn_method_chargrid_get_row(CharGridSafeHandle @ptr,ulong @y,ref RustCallStatus _uniffi_out_err - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern ulong uniffi_servicepoint_binding_uniffi_fn_method_chargrid_height(CharGridSafeHandle @ptr,ref RustCallStatus _uniffi_out_err - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern void uniffi_servicepoint_binding_uniffi_fn_method_chargrid_set(CharGridSafeHandle @ptr,ulong @x,ulong @y,RustBuffer @value,ref RustCallStatus _uniffi_out_err - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern void uniffi_servicepoint_binding_uniffi_fn_method_chargrid_set_col(CharGridSafeHandle @ptr,ulong @x,RustBuffer @col,ref RustCallStatus _uniffi_out_err - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern void uniffi_servicepoint_binding_uniffi_fn_method_chargrid_set_row(CharGridSafeHandle @ptr,ulong @y,RustBuffer @row,ref RustCallStatus _uniffi_out_err - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern Cp437GridSafeHandle uniffi_servicepoint_binding_uniffi_fn_method_chargrid_to_cp437(CharGridSafeHandle @ptr,ref RustCallStatus _uniffi_out_err - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern ulong uniffi_servicepoint_binding_uniffi_fn_method_chargrid_width(CharGridSafeHandle @ptr,ref RustCallStatus _uniffi_out_err - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern void uniffi_servicepoint_binding_uniffi_fn_free_command( - IntPtr ptr,ref RustCallStatus _uniffi_out_err - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern CommandSafeHandle uniffi_servicepoint_binding_uniffi_fn_constructor_command_bitmap_linear(ulong @offset,BitVecSafeHandle @bitmap,RustBuffer @compression,ref RustCallStatus _uniffi_out_err - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern CommandSafeHandle uniffi_servicepoint_binding_uniffi_fn_constructor_command_bitmap_linear_and(ulong @offset,BitVecSafeHandle @bitmap,RustBuffer @compression,ref RustCallStatus _uniffi_out_err - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern CommandSafeHandle uniffi_servicepoint_binding_uniffi_fn_constructor_command_bitmap_linear_or(ulong @offset,BitVecSafeHandle @bitmap,RustBuffer @compression,ref RustCallStatus _uniffi_out_err - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern CommandSafeHandle uniffi_servicepoint_binding_uniffi_fn_constructor_command_bitmap_linear_win(ulong @offsetX,ulong @offsetY,BitmapSafeHandle @bitmap,RustBuffer @compression,ref RustCallStatus _uniffi_out_err - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern CommandSafeHandle uniffi_servicepoint_binding_uniffi_fn_constructor_command_bitmap_linear_xor(ulong @offset,BitVecSafeHandle @bitmap,RustBuffer @compression,ref RustCallStatus _uniffi_out_err - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern CommandSafeHandle uniffi_servicepoint_binding_uniffi_fn_constructor_command_brightness(byte @brightness,ref RustCallStatus _uniffi_out_err - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern CommandSafeHandle uniffi_servicepoint_binding_uniffi_fn_constructor_command_char_brightness(ulong @offsetX,ulong @offsetY,BrightnessGridSafeHandle @grid,ref RustCallStatus _uniffi_out_err - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern CommandSafeHandle uniffi_servicepoint_binding_uniffi_fn_constructor_command_clear(ref RustCallStatus _uniffi_out_err - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern CommandSafeHandle uniffi_servicepoint_binding_uniffi_fn_constructor_command_clone(CommandSafeHandle @other,ref RustCallStatus _uniffi_out_err - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern CommandSafeHandle uniffi_servicepoint_binding_uniffi_fn_constructor_command_cp437_data(ulong @offsetX,ulong @offsetY,Cp437GridSafeHandle @grid,ref RustCallStatus _uniffi_out_err - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern CommandSafeHandle uniffi_servicepoint_binding_uniffi_fn_constructor_command_fade_out(ref RustCallStatus _uniffi_out_err - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern CommandSafeHandle uniffi_servicepoint_binding_uniffi_fn_constructor_command_hard_reset(ref RustCallStatus _uniffi_out_err - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern CommandSafeHandle uniffi_servicepoint_binding_uniffi_fn_constructor_command_utf8_data(ulong @offsetX,ulong @offsetY,CharGridSafeHandle @grid,ref RustCallStatus _uniffi_out_err - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern sbyte uniffi_servicepoint_binding_uniffi_fn_method_command_equals(CommandSafeHandle @ptr,CommandSafeHandle @other,ref RustCallStatus _uniffi_out_err - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern void uniffi_servicepoint_binding_uniffi_fn_free_connection( - IntPtr ptr,ref RustCallStatus _uniffi_out_err - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern ConnectionSafeHandle uniffi_servicepoint_binding_uniffi_fn_constructor_connection_new(RustBuffer @host,ref RustCallStatus _uniffi_out_err - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern ConnectionSafeHandle uniffi_servicepoint_binding_uniffi_fn_constructor_connection_new_fake(ref RustCallStatus _uniffi_out_err - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern void uniffi_servicepoint_binding_uniffi_fn_method_connection_send(ConnectionSafeHandle @ptr,CommandSafeHandle @command,ref RustCallStatus _uniffi_out_err - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern void uniffi_servicepoint_binding_uniffi_fn_free_cp437grid( - IntPtr ptr,ref RustCallStatus _uniffi_out_err - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern Cp437GridSafeHandle uniffi_servicepoint_binding_uniffi_fn_constructor_cp437grid_clone(Cp437GridSafeHandle @other,ref RustCallStatus _uniffi_out_err - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern Cp437GridSafeHandle uniffi_servicepoint_binding_uniffi_fn_constructor_cp437grid_load(ulong @width,ulong @height,RustBuffer @data,ref RustCallStatus _uniffi_out_err - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern Cp437GridSafeHandle uniffi_servicepoint_binding_uniffi_fn_constructor_cp437grid_new(ulong @width,ulong @height,ref RustCallStatus _uniffi_out_err - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern RustBuffer uniffi_servicepoint_binding_uniffi_fn_method_cp437grid_copy_raw(Cp437GridSafeHandle @ptr,ref RustCallStatus _uniffi_out_err - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern sbyte uniffi_servicepoint_binding_uniffi_fn_method_cp437grid_equals(Cp437GridSafeHandle @ptr,Cp437GridSafeHandle @other,ref RustCallStatus _uniffi_out_err - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern void uniffi_servicepoint_binding_uniffi_fn_method_cp437grid_fill(Cp437GridSafeHandle @ptr,byte @value,ref RustCallStatus _uniffi_out_err - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern byte uniffi_servicepoint_binding_uniffi_fn_method_cp437grid_get(Cp437GridSafeHandle @ptr,ulong @x,ulong @y,ref RustCallStatus _uniffi_out_err - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern ulong uniffi_servicepoint_binding_uniffi_fn_method_cp437grid_height(Cp437GridSafeHandle @ptr,ref RustCallStatus _uniffi_out_err - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern void uniffi_servicepoint_binding_uniffi_fn_method_cp437grid_set(Cp437GridSafeHandle @ptr,ulong @x,ulong @y,byte @value,ref RustCallStatus _uniffi_out_err - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern CharGridSafeHandle uniffi_servicepoint_binding_uniffi_fn_method_cp437grid_to_utf8(Cp437GridSafeHandle @ptr,ref RustCallStatus _uniffi_out_err - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern ulong uniffi_servicepoint_binding_uniffi_fn_method_cp437grid_width(Cp437GridSafeHandle @ptr,ref RustCallStatus _uniffi_out_err - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern RustBuffer uniffi_servicepoint_binding_uniffi_fn_func_get_constants(ref RustCallStatus _uniffi_out_err - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern RustBuffer ffi_servicepoint_binding_uniffi_rustbuffer_alloc(int @size,ref RustCallStatus _uniffi_out_err - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern RustBuffer ffi_servicepoint_binding_uniffi_rustbuffer_from_bytes(ForeignBytes @bytes,ref RustCallStatus _uniffi_out_err - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern void ffi_servicepoint_binding_uniffi_rustbuffer_free(RustBuffer @buf,ref RustCallStatus _uniffi_out_err - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern RustBuffer ffi_servicepoint_binding_uniffi_rustbuffer_reserve(RustBuffer @buf,int @additional,ref RustCallStatus _uniffi_out_err - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern void ffi_servicepoint_binding_uniffi_rust_future_continuation_callback_set(IntPtr @callback - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern void ffi_servicepoint_binding_uniffi_rust_future_poll_u8(IntPtr @handle,IntPtr @uniffiCallback - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern void ffi_servicepoint_binding_uniffi_rust_future_cancel_u8(IntPtr @handle - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern void ffi_servicepoint_binding_uniffi_rust_future_free_u8(IntPtr @handle - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern byte ffi_servicepoint_binding_uniffi_rust_future_complete_u8(IntPtr @handle,ref RustCallStatus _uniffi_out_err - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern void ffi_servicepoint_binding_uniffi_rust_future_poll_i8(IntPtr @handle,IntPtr @uniffiCallback - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern void ffi_servicepoint_binding_uniffi_rust_future_cancel_i8(IntPtr @handle - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern void ffi_servicepoint_binding_uniffi_rust_future_free_i8(IntPtr @handle - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern sbyte ffi_servicepoint_binding_uniffi_rust_future_complete_i8(IntPtr @handle,ref RustCallStatus _uniffi_out_err - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern void ffi_servicepoint_binding_uniffi_rust_future_poll_u16(IntPtr @handle,IntPtr @uniffiCallback - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern void ffi_servicepoint_binding_uniffi_rust_future_cancel_u16(IntPtr @handle - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern void ffi_servicepoint_binding_uniffi_rust_future_free_u16(IntPtr @handle - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern ushort ffi_servicepoint_binding_uniffi_rust_future_complete_u16(IntPtr @handle,ref RustCallStatus _uniffi_out_err - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern void ffi_servicepoint_binding_uniffi_rust_future_poll_i16(IntPtr @handle,IntPtr @uniffiCallback - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern void ffi_servicepoint_binding_uniffi_rust_future_cancel_i16(IntPtr @handle - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern void ffi_servicepoint_binding_uniffi_rust_future_free_i16(IntPtr @handle - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern short ffi_servicepoint_binding_uniffi_rust_future_complete_i16(IntPtr @handle,ref RustCallStatus _uniffi_out_err - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern void ffi_servicepoint_binding_uniffi_rust_future_poll_u32(IntPtr @handle,IntPtr @uniffiCallback - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern void ffi_servicepoint_binding_uniffi_rust_future_cancel_u32(IntPtr @handle - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern void ffi_servicepoint_binding_uniffi_rust_future_free_u32(IntPtr @handle - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern uint ffi_servicepoint_binding_uniffi_rust_future_complete_u32(IntPtr @handle,ref RustCallStatus _uniffi_out_err - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern void ffi_servicepoint_binding_uniffi_rust_future_poll_i32(IntPtr @handle,IntPtr @uniffiCallback - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern void ffi_servicepoint_binding_uniffi_rust_future_cancel_i32(IntPtr @handle - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern void ffi_servicepoint_binding_uniffi_rust_future_free_i32(IntPtr @handle - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern int ffi_servicepoint_binding_uniffi_rust_future_complete_i32(IntPtr @handle,ref RustCallStatus _uniffi_out_err - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern void ffi_servicepoint_binding_uniffi_rust_future_poll_u64(IntPtr @handle,IntPtr @uniffiCallback - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern void ffi_servicepoint_binding_uniffi_rust_future_cancel_u64(IntPtr @handle - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern void ffi_servicepoint_binding_uniffi_rust_future_free_u64(IntPtr @handle - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern ulong ffi_servicepoint_binding_uniffi_rust_future_complete_u64(IntPtr @handle,ref RustCallStatus _uniffi_out_err - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern void ffi_servicepoint_binding_uniffi_rust_future_poll_i64(IntPtr @handle,IntPtr @uniffiCallback - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern void ffi_servicepoint_binding_uniffi_rust_future_cancel_i64(IntPtr @handle - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern void ffi_servicepoint_binding_uniffi_rust_future_free_i64(IntPtr @handle - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern long ffi_servicepoint_binding_uniffi_rust_future_complete_i64(IntPtr @handle,ref RustCallStatus _uniffi_out_err - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern void ffi_servicepoint_binding_uniffi_rust_future_poll_f32(IntPtr @handle,IntPtr @uniffiCallback - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern void ffi_servicepoint_binding_uniffi_rust_future_cancel_f32(IntPtr @handle - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern void ffi_servicepoint_binding_uniffi_rust_future_free_f32(IntPtr @handle - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern float ffi_servicepoint_binding_uniffi_rust_future_complete_f32(IntPtr @handle,ref RustCallStatus _uniffi_out_err - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern void ffi_servicepoint_binding_uniffi_rust_future_poll_f64(IntPtr @handle,IntPtr @uniffiCallback - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern void ffi_servicepoint_binding_uniffi_rust_future_cancel_f64(IntPtr @handle - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern void ffi_servicepoint_binding_uniffi_rust_future_free_f64(IntPtr @handle - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern double ffi_servicepoint_binding_uniffi_rust_future_complete_f64(IntPtr @handle,ref RustCallStatus _uniffi_out_err - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern void ffi_servicepoint_binding_uniffi_rust_future_poll_pointer(IntPtr @handle,IntPtr @uniffiCallback - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern void ffi_servicepoint_binding_uniffi_rust_future_cancel_pointer(IntPtr @handle - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern void ffi_servicepoint_binding_uniffi_rust_future_free_pointer(IntPtr @handle - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern SafeHandle ffi_servicepoint_binding_uniffi_rust_future_complete_pointer(IntPtr @handle,ref RustCallStatus _uniffi_out_err - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern void ffi_servicepoint_binding_uniffi_rust_future_poll_rust_buffer(IntPtr @handle,IntPtr @uniffiCallback - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern void ffi_servicepoint_binding_uniffi_rust_future_cancel_rust_buffer(IntPtr @handle - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern void ffi_servicepoint_binding_uniffi_rust_future_free_rust_buffer(IntPtr @handle - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern RustBuffer ffi_servicepoint_binding_uniffi_rust_future_complete_rust_buffer(IntPtr @handle,ref RustCallStatus _uniffi_out_err - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern void ffi_servicepoint_binding_uniffi_rust_future_poll_void(IntPtr @handle,IntPtr @uniffiCallback - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern void ffi_servicepoint_binding_uniffi_rust_future_cancel_void(IntPtr @handle - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern void ffi_servicepoint_binding_uniffi_rust_future_free_void(IntPtr @handle - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern void ffi_servicepoint_binding_uniffi_rust_future_complete_void(IntPtr @handle,ref RustCallStatus _uniffi_out_err - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern ushort uniffi_servicepoint_binding_uniffi_checksum_func_get_constants( - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern ushort uniffi_servicepoint_binding_uniffi_checksum_method_bitvec_copy_raw( - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern ushort uniffi_servicepoint_binding_uniffi_checksum_method_bitvec_equals( - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern ushort uniffi_servicepoint_binding_uniffi_checksum_method_bitvec_fill( - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern ushort uniffi_servicepoint_binding_uniffi_checksum_method_bitvec_get( - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern ushort uniffi_servicepoint_binding_uniffi_checksum_method_bitvec_len( - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern ushort uniffi_servicepoint_binding_uniffi_checksum_method_bitvec_set( - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern ushort uniffi_servicepoint_binding_uniffi_checksum_method_bitmap_copy_raw( - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern ushort uniffi_servicepoint_binding_uniffi_checksum_method_bitmap_equals( - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern ushort uniffi_servicepoint_binding_uniffi_checksum_method_bitmap_fill( - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern ushort uniffi_servicepoint_binding_uniffi_checksum_method_bitmap_get( - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern ushort uniffi_servicepoint_binding_uniffi_checksum_method_bitmap_height( - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern ushort uniffi_servicepoint_binding_uniffi_checksum_method_bitmap_set( - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern ushort uniffi_servicepoint_binding_uniffi_checksum_method_bitmap_width( - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern ushort uniffi_servicepoint_binding_uniffi_checksum_method_brightnessgrid_copy_raw( - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern ushort uniffi_servicepoint_binding_uniffi_checksum_method_brightnessgrid_equals( - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern ushort uniffi_servicepoint_binding_uniffi_checksum_method_brightnessgrid_fill( - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern ushort uniffi_servicepoint_binding_uniffi_checksum_method_brightnessgrid_get( - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern ushort uniffi_servicepoint_binding_uniffi_checksum_method_brightnessgrid_height( - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern ushort uniffi_servicepoint_binding_uniffi_checksum_method_brightnessgrid_set( - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern ushort uniffi_servicepoint_binding_uniffi_checksum_method_brightnessgrid_width( - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern ushort uniffi_servicepoint_binding_uniffi_checksum_method_chargrid_as_string( - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern ushort uniffi_servicepoint_binding_uniffi_checksum_method_chargrid_equals( - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern ushort uniffi_servicepoint_binding_uniffi_checksum_method_chargrid_fill( - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern ushort uniffi_servicepoint_binding_uniffi_checksum_method_chargrid_get( - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern ushort uniffi_servicepoint_binding_uniffi_checksum_method_chargrid_get_col( - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern ushort uniffi_servicepoint_binding_uniffi_checksum_method_chargrid_get_row( - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern ushort uniffi_servicepoint_binding_uniffi_checksum_method_chargrid_height( - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern ushort uniffi_servicepoint_binding_uniffi_checksum_method_chargrid_set( - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern ushort uniffi_servicepoint_binding_uniffi_checksum_method_chargrid_set_col( - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern ushort uniffi_servicepoint_binding_uniffi_checksum_method_chargrid_set_row( - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern ushort uniffi_servicepoint_binding_uniffi_checksum_method_chargrid_to_cp437( - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern ushort uniffi_servicepoint_binding_uniffi_checksum_method_chargrid_width( - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern ushort uniffi_servicepoint_binding_uniffi_checksum_method_command_equals( - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern ushort uniffi_servicepoint_binding_uniffi_checksum_method_connection_send( - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern ushort uniffi_servicepoint_binding_uniffi_checksum_method_cp437grid_copy_raw( - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern ushort uniffi_servicepoint_binding_uniffi_checksum_method_cp437grid_equals( - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern ushort uniffi_servicepoint_binding_uniffi_checksum_method_cp437grid_fill( - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern ushort uniffi_servicepoint_binding_uniffi_checksum_method_cp437grid_get( - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern ushort uniffi_servicepoint_binding_uniffi_checksum_method_cp437grid_height( - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern ushort uniffi_servicepoint_binding_uniffi_checksum_method_cp437grid_set( - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern ushort uniffi_servicepoint_binding_uniffi_checksum_method_cp437grid_to_utf8( - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern ushort uniffi_servicepoint_binding_uniffi_checksum_method_cp437grid_width( - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern ushort uniffi_servicepoint_binding_uniffi_checksum_constructor_bitvec_clone( - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern ushort uniffi_servicepoint_binding_uniffi_checksum_constructor_bitvec_load( - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern ushort uniffi_servicepoint_binding_uniffi_checksum_constructor_bitvec_new( - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern ushort uniffi_servicepoint_binding_uniffi_checksum_constructor_bitmap_clone( - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern ushort uniffi_servicepoint_binding_uniffi_checksum_constructor_bitmap_load( - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern ushort uniffi_servicepoint_binding_uniffi_checksum_constructor_bitmap_new( - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern ushort uniffi_servicepoint_binding_uniffi_checksum_constructor_bitmap_new_max_sized( - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern ushort uniffi_servicepoint_binding_uniffi_checksum_constructor_brightnessgrid_clone( - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern ushort uniffi_servicepoint_binding_uniffi_checksum_constructor_brightnessgrid_load( - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern ushort uniffi_servicepoint_binding_uniffi_checksum_constructor_brightnessgrid_new( - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern ushort uniffi_servicepoint_binding_uniffi_checksum_constructor_chargrid_clone( - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern ushort uniffi_servicepoint_binding_uniffi_checksum_constructor_chargrid_load( - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern ushort uniffi_servicepoint_binding_uniffi_checksum_constructor_chargrid_new( - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern ushort uniffi_servicepoint_binding_uniffi_checksum_constructor_command_bitmap_linear( - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern ushort uniffi_servicepoint_binding_uniffi_checksum_constructor_command_bitmap_linear_and( - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern ushort uniffi_servicepoint_binding_uniffi_checksum_constructor_command_bitmap_linear_or( - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern ushort uniffi_servicepoint_binding_uniffi_checksum_constructor_command_bitmap_linear_win( - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern ushort uniffi_servicepoint_binding_uniffi_checksum_constructor_command_bitmap_linear_xor( - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern ushort uniffi_servicepoint_binding_uniffi_checksum_constructor_command_brightness( - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern ushort uniffi_servicepoint_binding_uniffi_checksum_constructor_command_char_brightness( - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern ushort uniffi_servicepoint_binding_uniffi_checksum_constructor_command_clear( - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern ushort uniffi_servicepoint_binding_uniffi_checksum_constructor_command_clone( - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern ushort uniffi_servicepoint_binding_uniffi_checksum_constructor_command_cp437_data( - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern ushort uniffi_servicepoint_binding_uniffi_checksum_constructor_command_fade_out( - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern ushort uniffi_servicepoint_binding_uniffi_checksum_constructor_command_hard_reset( - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern ushort uniffi_servicepoint_binding_uniffi_checksum_constructor_command_utf8_data( - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern ushort uniffi_servicepoint_binding_uniffi_checksum_constructor_connection_new( - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern ushort uniffi_servicepoint_binding_uniffi_checksum_constructor_connection_new_fake( - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern ushort uniffi_servicepoint_binding_uniffi_checksum_constructor_cp437grid_clone( - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern ushort uniffi_servicepoint_binding_uniffi_checksum_constructor_cp437grid_load( - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern ushort uniffi_servicepoint_binding_uniffi_checksum_constructor_cp437grid_new( - ); - - [DllImport("servicepoint_binding_uniffi")] - public static extern uint ffi_servicepoint_binding_uniffi_uniffi_contract_version( - ); - - - - static void uniffiCheckContractApiVersion() { - var scaffolding_contract_version = _UniFFILib.ffi_servicepoint_binding_uniffi_uniffi_contract_version(); - if (24 != scaffolding_contract_version) { - throw new UniffiContractVersionException($"ServicePoint: uniffi bindings expected version `24`, library returned `{scaffolding_contract_version}`"); - } - } - - static void uniffiCheckApiChecksums() { - { - var checksum = _UniFFILib.uniffi_servicepoint_binding_uniffi_checksum_func_get_constants(); - if (checksum != 41584) { - throw new UniffiContractChecksumException($"ServicePoint: uniffi bindings expected function `uniffi_servicepoint_binding_uniffi_checksum_func_get_constants` checksum `41584`, library returned `{checksum}`"); - } - } - { - var checksum = _UniFFILib.uniffi_servicepoint_binding_uniffi_checksum_method_bitvec_copy_raw(); - if (checksum != 12617) { - throw new UniffiContractChecksumException($"ServicePoint: uniffi bindings expected function `uniffi_servicepoint_binding_uniffi_checksum_method_bitvec_copy_raw` checksum `12617`, library returned `{checksum}`"); - } - } - { - var checksum = _UniFFILib.uniffi_servicepoint_binding_uniffi_checksum_method_bitvec_equals(); - if (checksum != 1191) { - throw new UniffiContractChecksumException($"ServicePoint: uniffi bindings expected function `uniffi_servicepoint_binding_uniffi_checksum_method_bitvec_equals` checksum `1191`, library returned `{checksum}`"); - } - } - { - var checksum = _UniFFILib.uniffi_servicepoint_binding_uniffi_checksum_method_bitvec_fill(); - if (checksum != 12255) { - throw new UniffiContractChecksumException($"ServicePoint: uniffi bindings expected function `uniffi_servicepoint_binding_uniffi_checksum_method_bitvec_fill` checksum `12255`, library returned `{checksum}`"); - } - } - { - var checksum = _UniFFILib.uniffi_servicepoint_binding_uniffi_checksum_method_bitvec_get(); - if (checksum != 43835) { - throw new UniffiContractChecksumException($"ServicePoint: uniffi bindings expected function `uniffi_servicepoint_binding_uniffi_checksum_method_bitvec_get` checksum `43835`, library returned `{checksum}`"); - } - } - { - var checksum = _UniFFILib.uniffi_servicepoint_binding_uniffi_checksum_method_bitvec_len(); - if (checksum != 22196) { - throw new UniffiContractChecksumException($"ServicePoint: uniffi bindings expected function `uniffi_servicepoint_binding_uniffi_checksum_method_bitvec_len` checksum `22196`, library returned `{checksum}`"); - } - } - { - var checksum = _UniFFILib.uniffi_servicepoint_binding_uniffi_checksum_method_bitvec_set(); - if (checksum != 16307) { - throw new UniffiContractChecksumException($"ServicePoint: uniffi bindings expected function `uniffi_servicepoint_binding_uniffi_checksum_method_bitvec_set` checksum `16307`, library returned `{checksum}`"); - } - } - { - var checksum = _UniFFILib.uniffi_servicepoint_binding_uniffi_checksum_method_bitmap_copy_raw(); - if (checksum != 3467) { - throw new UniffiContractChecksumException($"ServicePoint: uniffi bindings expected function `uniffi_servicepoint_binding_uniffi_checksum_method_bitmap_copy_raw` checksum `3467`, library returned `{checksum}`"); - } - } - { - var checksum = _UniFFILib.uniffi_servicepoint_binding_uniffi_checksum_method_bitmap_equals(); - if (checksum != 420) { - throw new UniffiContractChecksumException($"ServicePoint: uniffi bindings expected function `uniffi_servicepoint_binding_uniffi_checksum_method_bitmap_equals` checksum `420`, library returned `{checksum}`"); - } - } - { - var checksum = _UniFFILib.uniffi_servicepoint_binding_uniffi_checksum_method_bitmap_fill(); - if (checksum != 43887) { - throw new UniffiContractChecksumException($"ServicePoint: uniffi bindings expected function `uniffi_servicepoint_binding_uniffi_checksum_method_bitmap_fill` checksum `43887`, library returned `{checksum}`"); - } - } - { - var checksum = _UniFFILib.uniffi_servicepoint_binding_uniffi_checksum_method_bitmap_get(); - if (checksum != 61136) { - throw new UniffiContractChecksumException($"ServicePoint: uniffi bindings expected function `uniffi_servicepoint_binding_uniffi_checksum_method_bitmap_get` checksum `61136`, library returned `{checksum}`"); - } - } - { - var checksum = _UniFFILib.uniffi_servicepoint_binding_uniffi_checksum_method_bitmap_height(); - if (checksum != 44991) { - throw new UniffiContractChecksumException($"ServicePoint: uniffi bindings expected function `uniffi_servicepoint_binding_uniffi_checksum_method_bitmap_height` checksum `44991`, library returned `{checksum}`"); - } - } - { - var checksum = _UniFFILib.uniffi_servicepoint_binding_uniffi_checksum_method_bitmap_set(); - if (checksum != 25290) { - throw new UniffiContractChecksumException($"ServicePoint: uniffi bindings expected function `uniffi_servicepoint_binding_uniffi_checksum_method_bitmap_set` checksum `25290`, library returned `{checksum}`"); - } - } - { - var checksum = _UniFFILib.uniffi_servicepoint_binding_uniffi_checksum_method_bitmap_width(); - if (checksum != 30837) { - throw new UniffiContractChecksumException($"ServicePoint: uniffi bindings expected function `uniffi_servicepoint_binding_uniffi_checksum_method_bitmap_width` checksum `30837`, library returned `{checksum}`"); - } - } - { - var checksum = _UniFFILib.uniffi_servicepoint_binding_uniffi_checksum_method_brightnessgrid_copy_raw(); - if (checksum != 28155) { - throw new UniffiContractChecksumException($"ServicePoint: uniffi bindings expected function `uniffi_servicepoint_binding_uniffi_checksum_method_brightnessgrid_copy_raw` checksum `28155`, library returned `{checksum}`"); - } - } - { - var checksum = _UniFFILib.uniffi_servicepoint_binding_uniffi_checksum_method_brightnessgrid_equals(); - if (checksum != 13314) { - throw new UniffiContractChecksumException($"ServicePoint: uniffi bindings expected function `uniffi_servicepoint_binding_uniffi_checksum_method_brightnessgrid_equals` checksum `13314`, library returned `{checksum}`"); - } - } - { - var checksum = _UniFFILib.uniffi_servicepoint_binding_uniffi_checksum_method_brightnessgrid_fill(); - if (checksum != 63376) { - throw new UniffiContractChecksumException($"ServicePoint: uniffi bindings expected function `uniffi_servicepoint_binding_uniffi_checksum_method_brightnessgrid_fill` checksum `63376`, library returned `{checksum}`"); - } - } - { - var checksum = _UniFFILib.uniffi_servicepoint_binding_uniffi_checksum_method_brightnessgrid_get(); - if (checksum != 28736) { - throw new UniffiContractChecksumException($"ServicePoint: uniffi bindings expected function `uniffi_servicepoint_binding_uniffi_checksum_method_brightnessgrid_get` checksum `28736`, library returned `{checksum}`"); - } - } - { - var checksum = _UniFFILib.uniffi_servicepoint_binding_uniffi_checksum_method_brightnessgrid_height(); - if (checksum != 39528) { - throw new UniffiContractChecksumException($"ServicePoint: uniffi bindings expected function `uniffi_servicepoint_binding_uniffi_checksum_method_brightnessgrid_height` checksum `39528`, library returned `{checksum}`"); - } - } - { - var checksum = _UniFFILib.uniffi_servicepoint_binding_uniffi_checksum_method_brightnessgrid_set(); - if (checksum != 6330) { - throw new UniffiContractChecksumException($"ServicePoint: uniffi bindings expected function `uniffi_servicepoint_binding_uniffi_checksum_method_brightnessgrid_set` checksum `6330`, library returned `{checksum}`"); - } - } - { - var checksum = _UniFFILib.uniffi_servicepoint_binding_uniffi_checksum_method_brightnessgrid_width(); - if (checksum != 26384) { - throw new UniffiContractChecksumException($"ServicePoint: uniffi bindings expected function `uniffi_servicepoint_binding_uniffi_checksum_method_brightnessgrid_width` checksum `26384`, library returned `{checksum}`"); - } - } - { - var checksum = _UniFFILib.uniffi_servicepoint_binding_uniffi_checksum_method_chargrid_as_string(); - if (checksum != 46581) { - throw new UniffiContractChecksumException($"ServicePoint: uniffi bindings expected function `uniffi_servicepoint_binding_uniffi_checksum_method_chargrid_as_string` checksum `46581`, library returned `{checksum}`"); - } - } - { - var checksum = _UniFFILib.uniffi_servicepoint_binding_uniffi_checksum_method_chargrid_equals(); - if (checksum != 17533) { - throw new UniffiContractChecksumException($"ServicePoint: uniffi bindings expected function `uniffi_servicepoint_binding_uniffi_checksum_method_chargrid_equals` checksum `17533`, library returned `{checksum}`"); - } - } - { - var checksum = _UniFFILib.uniffi_servicepoint_binding_uniffi_checksum_method_chargrid_fill(); - if (checksum != 56996) { - throw new UniffiContractChecksumException($"ServicePoint: uniffi bindings expected function `uniffi_servicepoint_binding_uniffi_checksum_method_chargrid_fill` checksum `56996`, library returned `{checksum}`"); - } - } - { - var checksum = _UniFFILib.uniffi_servicepoint_binding_uniffi_checksum_method_chargrid_get(); - if (checksum != 1334) { - throw new UniffiContractChecksumException($"ServicePoint: uniffi bindings expected function `uniffi_servicepoint_binding_uniffi_checksum_method_chargrid_get` checksum `1334`, library returned `{checksum}`"); - } - } - { - var checksum = _UniFFILib.uniffi_servicepoint_binding_uniffi_checksum_method_chargrid_get_col(); - if (checksum != 64158) { - throw new UniffiContractChecksumException($"ServicePoint: uniffi bindings expected function `uniffi_servicepoint_binding_uniffi_checksum_method_chargrid_get_col` checksum `64158`, library returned `{checksum}`"); - } - } - { - var checksum = _UniFFILib.uniffi_servicepoint_binding_uniffi_checksum_method_chargrid_get_row(); - if (checksum != 39411) { - throw new UniffiContractChecksumException($"ServicePoint: uniffi bindings expected function `uniffi_servicepoint_binding_uniffi_checksum_method_chargrid_get_row` checksum `39411`, library returned `{checksum}`"); - } - } - { - var checksum = _UniFFILib.uniffi_servicepoint_binding_uniffi_checksum_method_chargrid_height(); - if (checksum != 13068) { - throw new UniffiContractChecksumException($"ServicePoint: uniffi bindings expected function `uniffi_servicepoint_binding_uniffi_checksum_method_chargrid_height` checksum `13068`, library returned `{checksum}`"); - } - } - { - var checksum = _UniFFILib.uniffi_servicepoint_binding_uniffi_checksum_method_chargrid_set(); - if (checksum != 64815) { - throw new UniffiContractChecksumException($"ServicePoint: uniffi bindings expected function `uniffi_servicepoint_binding_uniffi_checksum_method_chargrid_set` checksum `64815`, library returned `{checksum}`"); - } - } - { - var checksum = _UniFFILib.uniffi_servicepoint_binding_uniffi_checksum_method_chargrid_set_col(); - if (checksum != 43727) { - throw new UniffiContractChecksumException($"ServicePoint: uniffi bindings expected function `uniffi_servicepoint_binding_uniffi_checksum_method_chargrid_set_col` checksum `43727`, library returned `{checksum}`"); - } - } - { - var checksum = _UniFFILib.uniffi_servicepoint_binding_uniffi_checksum_method_chargrid_set_row(); - if (checksum != 19756) { - throw new UniffiContractChecksumException($"ServicePoint: uniffi bindings expected function `uniffi_servicepoint_binding_uniffi_checksum_method_chargrid_set_row` checksum `19756`, library returned `{checksum}`"); - } - } - { - var checksum = _UniFFILib.uniffi_servicepoint_binding_uniffi_checksum_method_chargrid_to_cp437(); - if (checksum != 19261) { - throw new UniffiContractChecksumException($"ServicePoint: uniffi bindings expected function `uniffi_servicepoint_binding_uniffi_checksum_method_chargrid_to_cp437` checksum `19261`, library returned `{checksum}`"); - } - } - { - var checksum = _UniFFILib.uniffi_servicepoint_binding_uniffi_checksum_method_chargrid_width(); - if (checksum != 48963) { - throw new UniffiContractChecksumException($"ServicePoint: uniffi bindings expected function `uniffi_servicepoint_binding_uniffi_checksum_method_chargrid_width` checksum `48963`, library returned `{checksum}`"); - } - } - { - var checksum = _UniFFILib.uniffi_servicepoint_binding_uniffi_checksum_method_command_equals(); - if (checksum != 20763) { - throw new UniffiContractChecksumException($"ServicePoint: uniffi bindings expected function `uniffi_servicepoint_binding_uniffi_checksum_method_command_equals` checksum `20763`, library returned `{checksum}`"); - } - } - { - var checksum = _UniFFILib.uniffi_servicepoint_binding_uniffi_checksum_method_connection_send(); - if (checksum != 23796) { - throw new UniffiContractChecksumException($"ServicePoint: uniffi bindings expected function `uniffi_servicepoint_binding_uniffi_checksum_method_connection_send` checksum `23796`, library returned `{checksum}`"); - } - } - { - var checksum = _UniFFILib.uniffi_servicepoint_binding_uniffi_checksum_method_cp437grid_copy_raw(); - if (checksum != 50937) { - throw new UniffiContractChecksumException($"ServicePoint: uniffi bindings expected function `uniffi_servicepoint_binding_uniffi_checksum_method_cp437grid_copy_raw` checksum `50937`, library returned `{checksum}`"); - } - } - { - var checksum = _UniFFILib.uniffi_servicepoint_binding_uniffi_checksum_method_cp437grid_equals(); - if (checksum != 21544) { - throw new UniffiContractChecksumException($"ServicePoint: uniffi bindings expected function `uniffi_servicepoint_binding_uniffi_checksum_method_cp437grid_equals` checksum `21544`, library returned `{checksum}`"); - } - } - { - var checksum = _UniFFILib.uniffi_servicepoint_binding_uniffi_checksum_method_cp437grid_fill(); - if (checksum != 46422) { - throw new UniffiContractChecksumException($"ServicePoint: uniffi bindings expected function `uniffi_servicepoint_binding_uniffi_checksum_method_cp437grid_fill` checksum `46422`, library returned `{checksum}`"); - } - } - { - var checksum = _UniFFILib.uniffi_servicepoint_binding_uniffi_checksum_method_cp437grid_get(); - if (checksum != 1945) { - throw new UniffiContractChecksumException($"ServicePoint: uniffi bindings expected function `uniffi_servicepoint_binding_uniffi_checksum_method_cp437grid_get` checksum `1945`, library returned `{checksum}`"); - } - } - { - var checksum = _UniFFILib.uniffi_servicepoint_binding_uniffi_checksum_method_cp437grid_height(); - if (checksum != 45951) { - throw new UniffiContractChecksumException($"ServicePoint: uniffi bindings expected function `uniffi_servicepoint_binding_uniffi_checksum_method_cp437grid_height` checksum `45951`, library returned `{checksum}`"); - } - } - { - var checksum = _UniFFILib.uniffi_servicepoint_binding_uniffi_checksum_method_cp437grid_set(); - if (checksum != 8371) { - throw new UniffiContractChecksumException($"ServicePoint: uniffi bindings expected function `uniffi_servicepoint_binding_uniffi_checksum_method_cp437grid_set` checksum `8371`, library returned `{checksum}`"); - } - } - { - var checksum = _UniFFILib.uniffi_servicepoint_binding_uniffi_checksum_method_cp437grid_to_utf8(); - if (checksum != 21516) { - throw new UniffiContractChecksumException($"ServicePoint: uniffi bindings expected function `uniffi_servicepoint_binding_uniffi_checksum_method_cp437grid_to_utf8` checksum `21516`, library returned `{checksum}`"); - } - } - { - var checksum = _UniFFILib.uniffi_servicepoint_binding_uniffi_checksum_method_cp437grid_width(); - if (checksum != 36872) { - throw new UniffiContractChecksumException($"ServicePoint: uniffi bindings expected function `uniffi_servicepoint_binding_uniffi_checksum_method_cp437grid_width` checksum `36872`, library returned `{checksum}`"); - } - } - { - var checksum = _UniFFILib.uniffi_servicepoint_binding_uniffi_checksum_constructor_bitvec_clone(); - if (checksum != 123) { - throw new UniffiContractChecksumException($"ServicePoint: uniffi bindings expected function `uniffi_servicepoint_binding_uniffi_checksum_constructor_bitvec_clone` checksum `123`, library returned `{checksum}`"); - } - } - { - var checksum = _UniFFILib.uniffi_servicepoint_binding_uniffi_checksum_constructor_bitvec_load(); - if (checksum != 48913) { - throw new UniffiContractChecksumException($"ServicePoint: uniffi bindings expected function `uniffi_servicepoint_binding_uniffi_checksum_constructor_bitvec_load` checksum `48913`, library returned `{checksum}`"); - } - } - { - var checksum = _UniFFILib.uniffi_servicepoint_binding_uniffi_checksum_constructor_bitvec_new(); - if (checksum != 11865) { - throw new UniffiContractChecksumException($"ServicePoint: uniffi bindings expected function `uniffi_servicepoint_binding_uniffi_checksum_constructor_bitvec_new` checksum `11865`, library returned `{checksum}`"); - } - } - { - var checksum = _UniFFILib.uniffi_servicepoint_binding_uniffi_checksum_constructor_bitmap_clone(); - if (checksum != 57298) { - throw new UniffiContractChecksumException($"ServicePoint: uniffi bindings expected function `uniffi_servicepoint_binding_uniffi_checksum_constructor_bitmap_clone` checksum `57298`, library returned `{checksum}`"); - } - } - { - var checksum = _UniFFILib.uniffi_servicepoint_binding_uniffi_checksum_constructor_bitmap_load(); - if (checksum != 24109) { - throw new UniffiContractChecksumException($"ServicePoint: uniffi bindings expected function `uniffi_servicepoint_binding_uniffi_checksum_constructor_bitmap_load` checksum `24109`, library returned `{checksum}`"); - } - } - { - var checksum = _UniFFILib.uniffi_servicepoint_binding_uniffi_checksum_constructor_bitmap_new(); - if (checksum != 49832) { - throw new UniffiContractChecksumException($"ServicePoint: uniffi bindings expected function `uniffi_servicepoint_binding_uniffi_checksum_constructor_bitmap_new` checksum `49832`, library returned `{checksum}`"); - } - } - { - var checksum = _UniFFILib.uniffi_servicepoint_binding_uniffi_checksum_constructor_bitmap_new_max_sized(); - if (checksum != 63762) { - throw new UniffiContractChecksumException($"ServicePoint: uniffi bindings expected function `uniffi_servicepoint_binding_uniffi_checksum_constructor_bitmap_new_max_sized` checksum `63762`, library returned `{checksum}`"); - } - } - { - var checksum = _UniFFILib.uniffi_servicepoint_binding_uniffi_checksum_constructor_brightnessgrid_clone(); - if (checksum != 33422) { - throw new UniffiContractChecksumException($"ServicePoint: uniffi bindings expected function `uniffi_servicepoint_binding_uniffi_checksum_constructor_brightnessgrid_clone` checksum `33422`, library returned `{checksum}`"); - } - } - { - var checksum = _UniFFILib.uniffi_servicepoint_binding_uniffi_checksum_constructor_brightnessgrid_load(); - if (checksum != 24788) { - throw new UniffiContractChecksumException($"ServicePoint: uniffi bindings expected function `uniffi_servicepoint_binding_uniffi_checksum_constructor_brightnessgrid_load` checksum `24788`, library returned `{checksum}`"); - } - } - { - var checksum = _UniFFILib.uniffi_servicepoint_binding_uniffi_checksum_constructor_brightnessgrid_new(); - if (checksum != 4979) { - throw new UniffiContractChecksumException($"ServicePoint: uniffi bindings expected function `uniffi_servicepoint_binding_uniffi_checksum_constructor_brightnessgrid_new` checksum `4979`, library returned `{checksum}`"); - } - } - { - var checksum = _UniFFILib.uniffi_servicepoint_binding_uniffi_checksum_constructor_chargrid_clone(); - if (checksum != 61241) { - throw new UniffiContractChecksumException($"ServicePoint: uniffi bindings expected function `uniffi_servicepoint_binding_uniffi_checksum_constructor_chargrid_clone` checksum `61241`, library returned `{checksum}`"); - } - } - { - var checksum = _UniFFILib.uniffi_servicepoint_binding_uniffi_checksum_constructor_chargrid_load(); - if (checksum != 47815) { - throw new UniffiContractChecksumException($"ServicePoint: uniffi bindings expected function `uniffi_servicepoint_binding_uniffi_checksum_constructor_chargrid_load` checksum `47815`, library returned `{checksum}`"); - } - } - { - var checksum = _UniFFILib.uniffi_servicepoint_binding_uniffi_checksum_constructor_chargrid_new(); - if (checksum != 13303) { - throw new UniffiContractChecksumException($"ServicePoint: uniffi bindings expected function `uniffi_servicepoint_binding_uniffi_checksum_constructor_chargrid_new` checksum `13303`, library returned `{checksum}`"); - } - } - { - var checksum = _UniFFILib.uniffi_servicepoint_binding_uniffi_checksum_constructor_command_bitmap_linear(); - if (checksum != 18079) { - throw new UniffiContractChecksumException($"ServicePoint: uniffi bindings expected function `uniffi_servicepoint_binding_uniffi_checksum_constructor_command_bitmap_linear` checksum `18079`, library returned `{checksum}`"); - } - } - { - var checksum = _UniFFILib.uniffi_servicepoint_binding_uniffi_checksum_constructor_command_bitmap_linear_and(); - if (checksum != 18147) { - throw new UniffiContractChecksumException($"ServicePoint: uniffi bindings expected function `uniffi_servicepoint_binding_uniffi_checksum_constructor_command_bitmap_linear_and` checksum `18147`, library returned `{checksum}`"); - } - } - { - var checksum = _UniFFILib.uniffi_servicepoint_binding_uniffi_checksum_constructor_command_bitmap_linear_or(); - if (checksum != 44912) { - throw new UniffiContractChecksumException($"ServicePoint: uniffi bindings expected function `uniffi_servicepoint_binding_uniffi_checksum_constructor_command_bitmap_linear_or` checksum `44912`, library returned `{checksum}`"); - } - } - { - var checksum = _UniFFILib.uniffi_servicepoint_binding_uniffi_checksum_constructor_command_bitmap_linear_win(); - if (checksum != 24563) { - throw new UniffiContractChecksumException($"ServicePoint: uniffi bindings expected function `uniffi_servicepoint_binding_uniffi_checksum_constructor_command_bitmap_linear_win` checksum `24563`, library returned `{checksum}`"); - } - } - { - var checksum = _UniFFILib.uniffi_servicepoint_binding_uniffi_checksum_constructor_command_bitmap_linear_xor(); - if (checksum != 54278) { - throw new UniffiContractChecksumException($"ServicePoint: uniffi bindings expected function `uniffi_servicepoint_binding_uniffi_checksum_constructor_command_bitmap_linear_xor` checksum `54278`, library returned `{checksum}`"); - } - } - { - var checksum = _UniFFILib.uniffi_servicepoint_binding_uniffi_checksum_constructor_command_brightness(); - if (checksum != 11291) { - throw new UniffiContractChecksumException($"ServicePoint: uniffi bindings expected function `uniffi_servicepoint_binding_uniffi_checksum_constructor_command_brightness` checksum `11291`, library returned `{checksum}`"); - } - } - { - var checksum = _UniFFILib.uniffi_servicepoint_binding_uniffi_checksum_constructor_command_char_brightness(); - if (checksum != 29467) { - throw new UniffiContractChecksumException($"ServicePoint: uniffi bindings expected function `uniffi_servicepoint_binding_uniffi_checksum_constructor_command_char_brightness` checksum `29467`, library returned `{checksum}`"); - } - } - { - var checksum = _UniFFILib.uniffi_servicepoint_binding_uniffi_checksum_constructor_command_clear(); - if (checksum != 11035) { - throw new UniffiContractChecksumException($"ServicePoint: uniffi bindings expected function `uniffi_servicepoint_binding_uniffi_checksum_constructor_command_clear` checksum `11035`, library returned `{checksum}`"); - } - } - { - var checksum = _UniFFILib.uniffi_servicepoint_binding_uniffi_checksum_constructor_command_clone(); - if (checksum != 42249) { - throw new UniffiContractChecksumException($"ServicePoint: uniffi bindings expected function `uniffi_servicepoint_binding_uniffi_checksum_constructor_command_clone` checksum `42249`, library returned `{checksum}`"); - } - } - { - var checksum = _UniFFILib.uniffi_servicepoint_binding_uniffi_checksum_constructor_command_cp437_data(); - if (checksum != 33157) { - throw new UniffiContractChecksumException($"ServicePoint: uniffi bindings expected function `uniffi_servicepoint_binding_uniffi_checksum_constructor_command_cp437_data` checksum `33157`, library returned `{checksum}`"); - } - } - { - var checksum = _UniFFILib.uniffi_servicepoint_binding_uniffi_checksum_constructor_command_fade_out(); - if (checksum != 49231) { - throw new UniffiContractChecksumException($"ServicePoint: uniffi bindings expected function `uniffi_servicepoint_binding_uniffi_checksum_constructor_command_fade_out` checksum `49231`, library returned `{checksum}`"); - } - } - { - var checksum = _UniFFILib.uniffi_servicepoint_binding_uniffi_checksum_constructor_command_hard_reset(); - if (checksum != 62130) { - throw new UniffiContractChecksumException($"ServicePoint: uniffi bindings expected function `uniffi_servicepoint_binding_uniffi_checksum_constructor_command_hard_reset` checksum `62130`, library returned `{checksum}`"); - } - } - { - var checksum = _UniFFILib.uniffi_servicepoint_binding_uniffi_checksum_constructor_command_utf8_data(); - if (checksum != 2263) { - throw new UniffiContractChecksumException($"ServicePoint: uniffi bindings expected function `uniffi_servicepoint_binding_uniffi_checksum_constructor_command_utf8_data` checksum `2263`, library returned `{checksum}`"); - } - } - { - var checksum = _UniFFILib.uniffi_servicepoint_binding_uniffi_checksum_constructor_connection_new(); - if (checksum != 30445) { - throw new UniffiContractChecksumException($"ServicePoint: uniffi bindings expected function `uniffi_servicepoint_binding_uniffi_checksum_constructor_connection_new` checksum `30445`, library returned `{checksum}`"); - } - } - { - var checksum = _UniFFILib.uniffi_servicepoint_binding_uniffi_checksum_constructor_connection_new_fake(); - if (checksum != 54331) { - throw new UniffiContractChecksumException($"ServicePoint: uniffi bindings expected function `uniffi_servicepoint_binding_uniffi_checksum_constructor_connection_new_fake` checksum `54331`, library returned `{checksum}`"); - } - } - { - var checksum = _UniFFILib.uniffi_servicepoint_binding_uniffi_checksum_constructor_cp437grid_clone(); - if (checksum != 28173) { - throw new UniffiContractChecksumException($"ServicePoint: uniffi bindings expected function `uniffi_servicepoint_binding_uniffi_checksum_constructor_cp437grid_clone` checksum `28173`, library returned `{checksum}`"); - } - } - { - var checksum = _UniFFILib.uniffi_servicepoint_binding_uniffi_checksum_constructor_cp437grid_load(); - if (checksum != 62136) { - throw new UniffiContractChecksumException($"ServicePoint: uniffi bindings expected function `uniffi_servicepoint_binding_uniffi_checksum_constructor_cp437grid_load` checksum `62136`, library returned `{checksum}`"); - } - } - { - var checksum = _UniFFILib.uniffi_servicepoint_binding_uniffi_checksum_constructor_cp437grid_new(); - if (checksum != 17350) { - throw new UniffiContractChecksumException($"ServicePoint: uniffi bindings expected function `uniffi_servicepoint_binding_uniffi_checksum_constructor_cp437grid_new` checksum `17350`, library returned `{checksum}`"); - } - } - } -} - -// Public interface members begin here. - -#pragma warning disable 8625 - - - - -class FfiConverterUInt8: FfiConverter { - public static FfiConverterUInt8 INSTANCE = new FfiConverterUInt8(); - - public override byte Lift(byte value) { - return value; - } - - public override byte Read(BigEndianStream stream) { - return stream.ReadByte(); - } - - public override byte Lower(byte value) { - return value; - } - - public override int AllocationSize(byte value) { - return 1; - } - - public override void Write(byte value, BigEndianStream stream) { - stream.WriteByte(value); - } -} - - - -class FfiConverterUInt64: FfiConverter { - public static FfiConverterUInt64 INSTANCE = new FfiConverterUInt64(); - - public override ulong Lift(ulong value) { - return value; - } - - public override ulong Read(BigEndianStream stream) { - return stream.ReadULong(); - } - - public override ulong Lower(ulong value) { - return value; - } - - public override int AllocationSize(ulong value) { - return 8; - } - - public override void Write(ulong value, BigEndianStream stream) { - stream.WriteULong(value); - } -} - - - -class FfiConverterBoolean: FfiConverter { - public static FfiConverterBoolean INSTANCE = new FfiConverterBoolean(); - - public override bool Lift(sbyte value) { - return value != 0; - } - - public override bool Read(BigEndianStream stream) { - return Lift(stream.ReadSByte()); - } - - public override sbyte Lower(bool value) { - return value ? (sbyte)1 : (sbyte)0; - } - - public override int AllocationSize(bool value) { - return (sbyte)1; - } - - public override void Write(bool value, BigEndianStream stream) { - stream.WriteSByte(Lower(value)); - } -} - - - -class FfiConverterString: FfiConverter { - public static FfiConverterString INSTANCE = new FfiConverterString(); - - // Note: we don't inherit from FfiConverterRustBuffer, because we use a - // special encoding when lowering/lifting. We can use `RustBuffer.len` to - // store our length and avoid writing it out to the buffer. - public override string Lift(RustBuffer value) { - try { - var bytes = value.AsStream().ReadBytes(value.len); - return System.Text.Encoding.UTF8.GetString(bytes); - } finally { - RustBuffer.Free(value); - } - } - - public override string Read(BigEndianStream stream) { - var length = stream.ReadInt(); - var bytes = stream.ReadBytes(length); - return System.Text.Encoding.UTF8.GetString(bytes); - } - - public override RustBuffer Lower(string value) { - var bytes = System.Text.Encoding.UTF8.GetBytes(value); - var rbuf = RustBuffer.Alloc(bytes.Length); - rbuf.AsWriteableStream().WriteBytes(bytes); - return rbuf; - } - - // TODO(CS) - // We aren't sure exactly how many bytes our string will be once it's UTF-8 - // encoded. Allocate 3 bytes per unicode codepoint which will always be - // enough. - public override int AllocationSize(string value) { - const int sizeForLength = 4; - var sizeForString = value.Length * 3; - return sizeForLength + sizeForString; - } - - public override void Write(string value, BigEndianStream stream) { - var bytes = System.Text.Encoding.UTF8.GetBytes(value); - stream.WriteInt(bytes.Length); - stream.WriteBytes(bytes); - } -} - - - - -class FfiConverterByteArray: FfiConverterRustBuffer { - public static FfiConverterByteArray INSTANCE = new FfiConverterByteArray(); - - public override byte[] Read(BigEndianStream stream) { - var length = stream.ReadInt(); - return stream.ReadBytes(length); - } - - public override int AllocationSize(byte[] value) { - return 4 + value.Length; - } - - public override void Write(byte[] value, BigEndianStream stream) { - stream.WriteInt(value.Length); - stream.WriteBytes(value); - } -} - - - - -// `SafeHandle` implements the semantics outlined below, i.e. its thread safe, and the dispose -// method will only be called once, once all outstanding native calls have completed. -// https://github.com/mozilla/uniffi-rs/blob/0dc031132d9493ca812c3af6e7dd60ad2ea95bf0/uniffi_bindgen/src/bindings/kotlin/templates/ObjectRuntime.kt#L31 -// https://learn.microsoft.com/en-us/dotnet/api/system.runtime.interopservices.criticalhandle - -public abstract class FFIObject: IDisposable where THandle : FFISafeHandle { - private THandle handle; - - public FFIObject(THandle handle) { - this.handle = handle; - } - - public THandle GetHandle() { - return handle; - } - - public void Dispose() { - handle.Dispose(); - } -} - -public abstract class FFISafeHandle: SafeHandle { - public FFISafeHandle(): base(new IntPtr(0), true) { - } - - public FFISafeHandle(IntPtr pointer): this() { - this.SetHandle(pointer); - } - - public override bool IsInvalid { - get { - return handle.ToInt64() == 0; - } - } - - // TODO(CS) this completely breaks any guarantees offered by SafeHandle.. Extracting - // raw value from SafeHandle puts responsiblity on the consumer of this function to - // ensure that SafeHandle outlives the stream, and anyone who might have read the raw - // value from the stream and are holding onto it. Otherwise, the result might be a use - // after free, or free while method calls are still in flight. - // - // This is also relevant for Kotlin. - // - public IntPtr DangerousGetRawFfiValue() { - return handle; - } -} - -static class FFIObjectUtil { - public static void DisposeAll(params Object?[] list) { - foreach (var obj in list) { - Dispose(obj); - } - } - - // Dispose is implemented by recursive type inspection at runtime. This is because - // generating correct Dispose calls for recursive complex types, e.g. List> - // is quite cumbersome. - private static void Dispose(dynamic? obj) { - if (obj == null) { - return; - } - - if (obj is IDisposable disposable) { - disposable.Dispose(); - return; - } - - var type = obj.GetType(); - if (type != null) { - if (type.IsGenericType) { - if (type.GetGenericTypeDefinition().IsAssignableFrom(typeof(List<>))) { - foreach (var value in obj) { - Dispose(value); - } - } else if (type.GetGenericTypeDefinition().IsAssignableFrom(typeof(Dictionary<,>))) { - foreach (var value in obj.Values) { - Dispose(value); - } - } - } - } - } -} -public interface IBitVec { - - byte[] CopyRaw(); - - bool Equals(BitVec @other); - - void Fill(bool @value); - - bool Get(ulong @index); - - ulong Len(); - - void Set(ulong @index, bool @value); - -} - -public class BitVecSafeHandle: FFISafeHandle { - public BitVecSafeHandle(): base() { - } - public BitVecSafeHandle(IntPtr pointer): base(pointer) { - } - override protected bool ReleaseHandle() { - _UniffiHelpers.RustCall((ref RustCallStatus status) => { - _UniFFILib.uniffi_servicepoint_binding_uniffi_fn_free_bitvec(this.handle, ref status); - }); - return true; - } -} -public class BitVec: FFIObject, IBitVec { - public BitVec(BitVecSafeHandle pointer): base(pointer) {} - public BitVec(ulong @size) : - this( - _UniffiHelpers.RustCall( (ref RustCallStatus _status) => - _UniFFILib.uniffi_servicepoint_binding_uniffi_fn_constructor_bitvec_new(FfiConverterUInt64.INSTANCE.Lower(@size), ref _status) -)) {} - - - public byte[] CopyRaw() { - return FfiConverterByteArray.INSTANCE.Lift( - _UniffiHelpers.RustCall( (ref RustCallStatus _status) => - _UniFFILib.uniffi_servicepoint_binding_uniffi_fn_method_bitvec_copy_raw(this.GetHandle(), ref _status) -)); - } - - public bool Equals(BitVec @other) { - return FfiConverterBoolean.INSTANCE.Lift( - _UniffiHelpers.RustCall( (ref RustCallStatus _status) => - _UniFFILib.uniffi_servicepoint_binding_uniffi_fn_method_bitvec_equals(this.GetHandle(), FfiConverterTypeBitVec.INSTANCE.Lower(@other), ref _status) -)); - } - - public void Fill(bool @value) { - _UniffiHelpers.RustCall( (ref RustCallStatus _status) => - _UniFFILib.uniffi_servicepoint_binding_uniffi_fn_method_bitvec_fill(this.GetHandle(), FfiConverterBoolean.INSTANCE.Lower(@value), ref _status) -); - } - - - public bool Get(ulong @index) { - return FfiConverterBoolean.INSTANCE.Lift( - _UniffiHelpers.RustCall( (ref RustCallStatus _status) => - _UniFFILib.uniffi_servicepoint_binding_uniffi_fn_method_bitvec_get(this.GetHandle(), FfiConverterUInt64.INSTANCE.Lower(@index), ref _status) -)); - } - - public ulong Len() { - return FfiConverterUInt64.INSTANCE.Lift( - _UniffiHelpers.RustCall( (ref RustCallStatus _status) => - _UniFFILib.uniffi_servicepoint_binding_uniffi_fn_method_bitvec_len(this.GetHandle(), ref _status) -)); - } - - public void Set(ulong @index, bool @value) { - _UniffiHelpers.RustCall( (ref RustCallStatus _status) => - _UniFFILib.uniffi_servicepoint_binding_uniffi_fn_method_bitvec_set(this.GetHandle(), FfiConverterUInt64.INSTANCE.Lower(@index), FfiConverterBoolean.INSTANCE.Lower(@value), ref _status) -); - } - - - - - public static BitVec Clone(BitVec @other) { - return new BitVec( - _UniffiHelpers.RustCall( (ref RustCallStatus _status) => - _UniFFILib.uniffi_servicepoint_binding_uniffi_fn_constructor_bitvec_clone(FfiConverterTypeBitVec.INSTANCE.Lower(@other), ref _status) -)); - } - - public static BitVec Load(byte[] @data) { - return new BitVec( - _UniffiHelpers.RustCall( (ref RustCallStatus _status) => - _UniFFILib.uniffi_servicepoint_binding_uniffi_fn_constructor_bitvec_load(FfiConverterByteArray.INSTANCE.Lower(@data), ref _status) -)); - } - - -} - -class FfiConverterTypeBitVec: FfiConverter { - public static FfiConverterTypeBitVec INSTANCE = new FfiConverterTypeBitVec(); - - public override BitVecSafeHandle Lower(BitVec value) { - return value.GetHandle(); - } - - public override BitVec Lift(BitVecSafeHandle value) { - return new BitVec(value); - } - - public override BitVec Read(BigEndianStream stream) { - return Lift(new BitVecSafeHandle(new IntPtr(stream.ReadLong()))); - } - - public override int AllocationSize(BitVec value) { - return 8; - } - - public override void Write(BitVec value, BigEndianStream stream) { - stream.WriteLong(Lower(value).DangerousGetRawFfiValue().ToInt64()); - } -} - - - -public interface IBitmap { - - byte[] CopyRaw(); - - bool Equals(Bitmap @other); - - void Fill(bool @value); - - bool Get(ulong @x, ulong @y); - - ulong Height(); - - void Set(ulong @x, ulong @y, bool @value); - - ulong Width(); - -} - -public class BitmapSafeHandle: FFISafeHandle { - public BitmapSafeHandle(): base() { - } - public BitmapSafeHandle(IntPtr pointer): base(pointer) { - } - override protected bool ReleaseHandle() { - _UniffiHelpers.RustCall((ref RustCallStatus status) => { - _UniFFILib.uniffi_servicepoint_binding_uniffi_fn_free_bitmap(this.handle, ref status); - }); - return true; - } -} -public class Bitmap: FFIObject, IBitmap { - public Bitmap(BitmapSafeHandle pointer): base(pointer) {} - public Bitmap(ulong @width, ulong @height) : - this( - _UniffiHelpers.RustCall( (ref RustCallStatus _status) => - _UniFFILib.uniffi_servicepoint_binding_uniffi_fn_constructor_bitmap_new(FfiConverterUInt64.INSTANCE.Lower(@width), FfiConverterUInt64.INSTANCE.Lower(@height), ref _status) -)) {} - - - public byte[] CopyRaw() { - return FfiConverterByteArray.INSTANCE.Lift( - _UniffiHelpers.RustCall( (ref RustCallStatus _status) => - _UniFFILib.uniffi_servicepoint_binding_uniffi_fn_method_bitmap_copy_raw(this.GetHandle(), ref _status) -)); - } - - public bool Equals(Bitmap @other) { - return FfiConverterBoolean.INSTANCE.Lift( - _UniffiHelpers.RustCall( (ref RustCallStatus _status) => - _UniFFILib.uniffi_servicepoint_binding_uniffi_fn_method_bitmap_equals(this.GetHandle(), FfiConverterTypeBitmap.INSTANCE.Lower(@other), ref _status) -)); - } - - public void Fill(bool @value) { - _UniffiHelpers.RustCall( (ref RustCallStatus _status) => - _UniFFILib.uniffi_servicepoint_binding_uniffi_fn_method_bitmap_fill(this.GetHandle(), FfiConverterBoolean.INSTANCE.Lower(@value), ref _status) -); - } - - - public bool Get(ulong @x, ulong @y) { - return FfiConverterBoolean.INSTANCE.Lift( - _UniffiHelpers.RustCall( (ref RustCallStatus _status) => - _UniFFILib.uniffi_servicepoint_binding_uniffi_fn_method_bitmap_get(this.GetHandle(), FfiConverterUInt64.INSTANCE.Lower(@x), FfiConverterUInt64.INSTANCE.Lower(@y), ref _status) -)); - } - - public ulong Height() { - return FfiConverterUInt64.INSTANCE.Lift( - _UniffiHelpers.RustCall( (ref RustCallStatus _status) => - _UniFFILib.uniffi_servicepoint_binding_uniffi_fn_method_bitmap_height(this.GetHandle(), ref _status) -)); - } - - public void Set(ulong @x, ulong @y, bool @value) { - _UniffiHelpers.RustCall( (ref RustCallStatus _status) => - _UniFFILib.uniffi_servicepoint_binding_uniffi_fn_method_bitmap_set(this.GetHandle(), FfiConverterUInt64.INSTANCE.Lower(@x), FfiConverterUInt64.INSTANCE.Lower(@y), FfiConverterBoolean.INSTANCE.Lower(@value), ref _status) -); - } - - - public ulong Width() { - return FfiConverterUInt64.INSTANCE.Lift( - _UniffiHelpers.RustCall( (ref RustCallStatus _status) => - _UniFFILib.uniffi_servicepoint_binding_uniffi_fn_method_bitmap_width(this.GetHandle(), ref _status) -)); - } - - - - public static Bitmap Clone(Bitmap @other) { - return new Bitmap( - _UniffiHelpers.RustCall( (ref RustCallStatus _status) => - _UniFFILib.uniffi_servicepoint_binding_uniffi_fn_constructor_bitmap_clone(FfiConverterTypeBitmap.INSTANCE.Lower(@other), ref _status) -)); - } - - public static Bitmap Load(ulong @width, ulong @height, byte[] @data) { - return new Bitmap( - _UniffiHelpers.RustCall( (ref RustCallStatus _status) => - _UniFFILib.uniffi_servicepoint_binding_uniffi_fn_constructor_bitmap_load(FfiConverterUInt64.INSTANCE.Lower(@width), FfiConverterUInt64.INSTANCE.Lower(@height), FfiConverterByteArray.INSTANCE.Lower(@data), ref _status) -)); - } - - public static Bitmap NewMaxSized() { - return new Bitmap( - _UniffiHelpers.RustCall( (ref RustCallStatus _status) => - _UniFFILib.uniffi_servicepoint_binding_uniffi_fn_constructor_bitmap_new_max_sized( ref _status) -)); - } - - -} - -class FfiConverterTypeBitmap: FfiConverter { - public static FfiConverterTypeBitmap INSTANCE = new FfiConverterTypeBitmap(); - - public override BitmapSafeHandle Lower(Bitmap value) { - return value.GetHandle(); - } - - public override Bitmap Lift(BitmapSafeHandle value) { - return new Bitmap(value); - } - - public override Bitmap Read(BigEndianStream stream) { - return Lift(new BitmapSafeHandle(new IntPtr(stream.ReadLong()))); - } - - public override int AllocationSize(Bitmap value) { - return 8; - } - - public override void Write(Bitmap value, BigEndianStream stream) { - stream.WriteLong(Lower(value).DangerousGetRawFfiValue().ToInt64()); - } -} - - - -public interface IBrightnessGrid { - - byte[] CopyRaw(); - - bool Equals(BrightnessGrid @other); - - void Fill(byte @value); - - byte Get(ulong @x, ulong @y); - - ulong Height(); - - void Set(ulong @x, ulong @y, byte @value); - - ulong Width(); - -} - -public class BrightnessGridSafeHandle: FFISafeHandle { - public BrightnessGridSafeHandle(): base() { - } - public BrightnessGridSafeHandle(IntPtr pointer): base(pointer) { - } - override protected bool ReleaseHandle() { - _UniffiHelpers.RustCall((ref RustCallStatus status) => { - _UniFFILib.uniffi_servicepoint_binding_uniffi_fn_free_brightnessgrid(this.handle, ref status); - }); - return true; - } -} -public class BrightnessGrid: FFIObject, IBrightnessGrid { - public BrightnessGrid(BrightnessGridSafeHandle pointer): base(pointer) {} - public BrightnessGrid(ulong @width, ulong @height) : - this( - _UniffiHelpers.RustCall( (ref RustCallStatus _status) => - _UniFFILib.uniffi_servicepoint_binding_uniffi_fn_constructor_brightnessgrid_new(FfiConverterUInt64.INSTANCE.Lower(@width), FfiConverterUInt64.INSTANCE.Lower(@height), ref _status) -)) {} - - - public byte[] CopyRaw() { - return FfiConverterByteArray.INSTANCE.Lift( - _UniffiHelpers.RustCall( (ref RustCallStatus _status) => - _UniFFILib.uniffi_servicepoint_binding_uniffi_fn_method_brightnessgrid_copy_raw(this.GetHandle(), ref _status) -)); - } - - public bool Equals(BrightnessGrid @other) { - return FfiConverterBoolean.INSTANCE.Lift( - _UniffiHelpers.RustCall( (ref RustCallStatus _status) => - _UniFFILib.uniffi_servicepoint_binding_uniffi_fn_method_brightnessgrid_equals(this.GetHandle(), FfiConverterTypeBrightnessGrid.INSTANCE.Lower(@other), ref _status) -)); - } - - public void Fill(byte @value) { - _UniffiHelpers.RustCall( (ref RustCallStatus _status) => - _UniFFILib.uniffi_servicepoint_binding_uniffi_fn_method_brightnessgrid_fill(this.GetHandle(), FfiConverterUInt8.INSTANCE.Lower(@value), ref _status) -); - } - - - public byte Get(ulong @x, ulong @y) { - return FfiConverterUInt8.INSTANCE.Lift( - _UniffiHelpers.RustCall( (ref RustCallStatus _status) => - _UniFFILib.uniffi_servicepoint_binding_uniffi_fn_method_brightnessgrid_get(this.GetHandle(), FfiConverterUInt64.INSTANCE.Lower(@x), FfiConverterUInt64.INSTANCE.Lower(@y), ref _status) -)); - } - - public ulong Height() { - return FfiConverterUInt64.INSTANCE.Lift( - _UniffiHelpers.RustCall( (ref RustCallStatus _status) => - _UniFFILib.uniffi_servicepoint_binding_uniffi_fn_method_brightnessgrid_height(this.GetHandle(), ref _status) -)); - } - - public void Set(ulong @x, ulong @y, byte @value) { - _UniffiHelpers.RustCall( (ref RustCallStatus _status) => - _UniFFILib.uniffi_servicepoint_binding_uniffi_fn_method_brightnessgrid_set(this.GetHandle(), FfiConverterUInt64.INSTANCE.Lower(@x), FfiConverterUInt64.INSTANCE.Lower(@y), FfiConverterUInt8.INSTANCE.Lower(@value), ref _status) -); - } - - - public ulong Width() { - return FfiConverterUInt64.INSTANCE.Lift( - _UniffiHelpers.RustCall( (ref RustCallStatus _status) => - _UniFFILib.uniffi_servicepoint_binding_uniffi_fn_method_brightnessgrid_width(this.GetHandle(), ref _status) -)); - } - - - - public static BrightnessGrid Clone(BrightnessGrid @other) { - return new BrightnessGrid( - _UniffiHelpers.RustCall( (ref RustCallStatus _status) => - _UniFFILib.uniffi_servicepoint_binding_uniffi_fn_constructor_brightnessgrid_clone(FfiConverterTypeBrightnessGrid.INSTANCE.Lower(@other), ref _status) -)); - } - - public static BrightnessGrid Load(ulong @width, ulong @height, byte[] @data) { - return new BrightnessGrid( - _UniffiHelpers.RustCall( (ref RustCallStatus _status) => - _UniFFILib.uniffi_servicepoint_binding_uniffi_fn_constructor_brightnessgrid_load(FfiConverterUInt64.INSTANCE.Lower(@width), FfiConverterUInt64.INSTANCE.Lower(@height), FfiConverterByteArray.INSTANCE.Lower(@data), ref _status) -)); - } - - -} - -class FfiConverterTypeBrightnessGrid: FfiConverter { - public static FfiConverterTypeBrightnessGrid INSTANCE = new FfiConverterTypeBrightnessGrid(); - - public override BrightnessGridSafeHandle Lower(BrightnessGrid value) { - return value.GetHandle(); - } - - public override BrightnessGrid Lift(BrightnessGridSafeHandle value) { - return new BrightnessGrid(value); - } - - public override BrightnessGrid Read(BigEndianStream stream) { - return Lift(new BrightnessGridSafeHandle(new IntPtr(stream.ReadLong()))); - } - - public override int AllocationSize(BrightnessGrid value) { - return 8; - } - - public override void Write(BrightnessGrid value, BigEndianStream stream) { - stream.WriteLong(Lower(value).DangerousGetRawFfiValue().ToInt64()); - } -} - - - -public interface ICharGrid { - - String AsString(); - - bool Equals(CharGrid @other); - - /// - void Fill(String @value); - - String Get(ulong @x, ulong @y); - - /// - String GetCol(ulong @x); - - /// - String GetRow(ulong @y); - - ulong Height(); - - /// - void Set(ulong @x, ulong @y, String @value); - - /// - void SetCol(ulong @x, String @col); - - /// - void SetRow(ulong @y, String @row); - - Cp437Grid ToCp437(); - - ulong Width(); - -} - -public class CharGridSafeHandle: FFISafeHandle { - public CharGridSafeHandle(): base() { - } - public CharGridSafeHandle(IntPtr pointer): base(pointer) { - } - override protected bool ReleaseHandle() { - _UniffiHelpers.RustCall((ref RustCallStatus status) => { - _UniFFILib.uniffi_servicepoint_binding_uniffi_fn_free_chargrid(this.handle, ref status); - }); - return true; - } -} -public class CharGrid: FFIObject, ICharGrid { - public CharGrid(CharGridSafeHandle pointer): base(pointer) {} - public CharGrid(ulong @width, ulong @height) : - this( - _UniffiHelpers.RustCall( (ref RustCallStatus _status) => - _UniFFILib.uniffi_servicepoint_binding_uniffi_fn_constructor_chargrid_new(FfiConverterUInt64.INSTANCE.Lower(@width), FfiConverterUInt64.INSTANCE.Lower(@height), ref _status) -)) {} - - - public String AsString() { - return FfiConverterString.INSTANCE.Lift( - _UniffiHelpers.RustCall( (ref RustCallStatus _status) => - _UniFFILib.uniffi_servicepoint_binding_uniffi_fn_method_chargrid_as_string(this.GetHandle(), ref _status) -)); - } - - public bool Equals(CharGrid @other) { - return FfiConverterBoolean.INSTANCE.Lift( - _UniffiHelpers.RustCall( (ref RustCallStatus _status) => - _UniFFILib.uniffi_servicepoint_binding_uniffi_fn_method_chargrid_equals(this.GetHandle(), FfiConverterTypeCharGrid.INSTANCE.Lower(@other), ref _status) -)); - } - - /// - public void Fill(String @value) { - _UniffiHelpers.RustCallWithError(FfiConverterTypeCharGridException.INSTANCE, (ref RustCallStatus _status) => - _UniFFILib.uniffi_servicepoint_binding_uniffi_fn_method_chargrid_fill(this.GetHandle(), FfiConverterString.INSTANCE.Lower(@value), ref _status) -); - } - - - public String Get(ulong @x, ulong @y) { - return FfiConverterString.INSTANCE.Lift( - _UniffiHelpers.RustCall( (ref RustCallStatus _status) => - _UniFFILib.uniffi_servicepoint_binding_uniffi_fn_method_chargrid_get(this.GetHandle(), FfiConverterUInt64.INSTANCE.Lower(@x), FfiConverterUInt64.INSTANCE.Lower(@y), ref _status) -)); - } - - /// - public String GetCol(ulong @x) { - return FfiConverterString.INSTANCE.Lift( - _UniffiHelpers.RustCallWithError(FfiConverterTypeCharGridException.INSTANCE, (ref RustCallStatus _status) => - _UniFFILib.uniffi_servicepoint_binding_uniffi_fn_method_chargrid_get_col(this.GetHandle(), FfiConverterUInt64.INSTANCE.Lower(@x), ref _status) -)); - } - - /// - public String GetRow(ulong @y) { - return FfiConverterString.INSTANCE.Lift( - _UniffiHelpers.RustCallWithError(FfiConverterTypeCharGridException.INSTANCE, (ref RustCallStatus _status) => - _UniFFILib.uniffi_servicepoint_binding_uniffi_fn_method_chargrid_get_row(this.GetHandle(), FfiConverterUInt64.INSTANCE.Lower(@y), ref _status) -)); - } - - public ulong Height() { - return FfiConverterUInt64.INSTANCE.Lift( - _UniffiHelpers.RustCall( (ref RustCallStatus _status) => - _UniFFILib.uniffi_servicepoint_binding_uniffi_fn_method_chargrid_height(this.GetHandle(), ref _status) -)); - } - - /// - public void Set(ulong @x, ulong @y, String @value) { - _UniffiHelpers.RustCallWithError(FfiConverterTypeCharGridException.INSTANCE, (ref RustCallStatus _status) => - _UniFFILib.uniffi_servicepoint_binding_uniffi_fn_method_chargrid_set(this.GetHandle(), FfiConverterUInt64.INSTANCE.Lower(@x), FfiConverterUInt64.INSTANCE.Lower(@y), FfiConverterString.INSTANCE.Lower(@value), ref _status) -); - } - - - /// - public void SetCol(ulong @x, String @col) { - _UniffiHelpers.RustCallWithError(FfiConverterTypeCharGridException.INSTANCE, (ref RustCallStatus _status) => - _UniFFILib.uniffi_servicepoint_binding_uniffi_fn_method_chargrid_set_col(this.GetHandle(), FfiConverterUInt64.INSTANCE.Lower(@x), FfiConverterString.INSTANCE.Lower(@col), ref _status) -); - } - - - /// - public void SetRow(ulong @y, String @row) { - _UniffiHelpers.RustCallWithError(FfiConverterTypeCharGridException.INSTANCE, (ref RustCallStatus _status) => - _UniFFILib.uniffi_servicepoint_binding_uniffi_fn_method_chargrid_set_row(this.GetHandle(), FfiConverterUInt64.INSTANCE.Lower(@y), FfiConverterString.INSTANCE.Lower(@row), ref _status) -); - } - - - public Cp437Grid ToCp437() { - return FfiConverterTypeCp437Grid.INSTANCE.Lift( - _UniffiHelpers.RustCall( (ref RustCallStatus _status) => - _UniFFILib.uniffi_servicepoint_binding_uniffi_fn_method_chargrid_to_cp437(this.GetHandle(), ref _status) -)); - } - - public ulong Width() { - return FfiConverterUInt64.INSTANCE.Lift( - _UniffiHelpers.RustCall( (ref RustCallStatus _status) => - _UniFFILib.uniffi_servicepoint_binding_uniffi_fn_method_chargrid_width(this.GetHandle(), ref _status) -)); - } - - - - public static CharGrid Clone(CharGrid @other) { - return new CharGrid( - _UniffiHelpers.RustCall( (ref RustCallStatus _status) => - _UniFFILib.uniffi_servicepoint_binding_uniffi_fn_constructor_chargrid_clone(FfiConverterTypeCharGrid.INSTANCE.Lower(@other), ref _status) -)); - } - - public static CharGrid Load(String @data) { - return new CharGrid( - _UniffiHelpers.RustCall( (ref RustCallStatus _status) => - _UniFFILib.uniffi_servicepoint_binding_uniffi_fn_constructor_chargrid_load(FfiConverterString.INSTANCE.Lower(@data), ref _status) -)); - } - - -} - -class FfiConverterTypeCharGrid: FfiConverter { - public static FfiConverterTypeCharGrid INSTANCE = new FfiConverterTypeCharGrid(); - - public override CharGridSafeHandle Lower(CharGrid value) { - return value.GetHandle(); - } - - public override CharGrid Lift(CharGridSafeHandle value) { - return new CharGrid(value); - } - - public override CharGrid Read(BigEndianStream stream) { - return Lift(new CharGridSafeHandle(new IntPtr(stream.ReadLong()))); - } - - public override int AllocationSize(CharGrid value) { - return 8; - } - - public override void Write(CharGrid value, BigEndianStream stream) { - stream.WriteLong(Lower(value).DangerousGetRawFfiValue().ToInt64()); - } -} - - - -public interface ICommand { - - bool Equals(Command @other); - -} - -public class CommandSafeHandle: FFISafeHandle { - public CommandSafeHandle(): base() { - } - public CommandSafeHandle(IntPtr pointer): base(pointer) { - } - override protected bool ReleaseHandle() { - _UniffiHelpers.RustCall((ref RustCallStatus status) => { - _UniFFILib.uniffi_servicepoint_binding_uniffi_fn_free_command(this.handle, ref status); - }); - return true; - } -} -public class Command: FFIObject, ICommand { - public Command(CommandSafeHandle pointer): base(pointer) {} - - - public bool Equals(Command @other) { - return FfiConverterBoolean.INSTANCE.Lift( - _UniffiHelpers.RustCall( (ref RustCallStatus _status) => - _UniFFILib.uniffi_servicepoint_binding_uniffi_fn_method_command_equals(this.GetHandle(), FfiConverterTypeCommand.INSTANCE.Lower(@other), ref _status) -)); - } - - - - public static Command BitmapLinear(ulong @offset, BitVec @bitmap, CompressionCode @compression) { - return new Command( - _UniffiHelpers.RustCall( (ref RustCallStatus _status) => - _UniFFILib.uniffi_servicepoint_binding_uniffi_fn_constructor_command_bitmap_linear(FfiConverterUInt64.INSTANCE.Lower(@offset), FfiConverterTypeBitVec.INSTANCE.Lower(@bitmap), FfiConverterTypeCompressionCode.INSTANCE.Lower(@compression), ref _status) -)); - } - - public static Command BitmapLinearAnd(ulong @offset, BitVec @bitmap, CompressionCode @compression) { - return new Command( - _UniffiHelpers.RustCall( (ref RustCallStatus _status) => - _UniFFILib.uniffi_servicepoint_binding_uniffi_fn_constructor_command_bitmap_linear_and(FfiConverterUInt64.INSTANCE.Lower(@offset), FfiConverterTypeBitVec.INSTANCE.Lower(@bitmap), FfiConverterTypeCompressionCode.INSTANCE.Lower(@compression), ref _status) -)); - } - - public static Command BitmapLinearOr(ulong @offset, BitVec @bitmap, CompressionCode @compression) { - return new Command( - _UniffiHelpers.RustCall( (ref RustCallStatus _status) => - _UniFFILib.uniffi_servicepoint_binding_uniffi_fn_constructor_command_bitmap_linear_or(FfiConverterUInt64.INSTANCE.Lower(@offset), FfiConverterTypeBitVec.INSTANCE.Lower(@bitmap), FfiConverterTypeCompressionCode.INSTANCE.Lower(@compression), ref _status) -)); - } - - public static Command BitmapLinearWin(ulong @offsetX, ulong @offsetY, Bitmap @bitmap, CompressionCode @compression) { - return new Command( - _UniffiHelpers.RustCall( (ref RustCallStatus _status) => - _UniFFILib.uniffi_servicepoint_binding_uniffi_fn_constructor_command_bitmap_linear_win(FfiConverterUInt64.INSTANCE.Lower(@offsetX), FfiConverterUInt64.INSTANCE.Lower(@offsetY), FfiConverterTypeBitmap.INSTANCE.Lower(@bitmap), FfiConverterTypeCompressionCode.INSTANCE.Lower(@compression), ref _status) -)); - } - - public static Command BitmapLinearXor(ulong @offset, BitVec @bitmap, CompressionCode @compression) { - return new Command( - _UniffiHelpers.RustCall( (ref RustCallStatus _status) => - _UniFFILib.uniffi_servicepoint_binding_uniffi_fn_constructor_command_bitmap_linear_xor(FfiConverterUInt64.INSTANCE.Lower(@offset), FfiConverterTypeBitVec.INSTANCE.Lower(@bitmap), FfiConverterTypeCompressionCode.INSTANCE.Lower(@compression), ref _status) -)); - } - - /// - public static Command Brightness(byte @brightness) { - return new Command( - _UniffiHelpers.RustCallWithError(FfiConverterTypeServicePointException.INSTANCE, (ref RustCallStatus _status) => - _UniFFILib.uniffi_servicepoint_binding_uniffi_fn_constructor_command_brightness(FfiConverterUInt8.INSTANCE.Lower(@brightness), ref _status) -)); - } - - public static Command CharBrightness(ulong @offsetX, ulong @offsetY, BrightnessGrid @grid) { - return new Command( - _UniffiHelpers.RustCall( (ref RustCallStatus _status) => - _UniFFILib.uniffi_servicepoint_binding_uniffi_fn_constructor_command_char_brightness(FfiConverterUInt64.INSTANCE.Lower(@offsetX), FfiConverterUInt64.INSTANCE.Lower(@offsetY), FfiConverterTypeBrightnessGrid.INSTANCE.Lower(@grid), ref _status) -)); - } - - public static Command Clear() { - return new Command( - _UniffiHelpers.RustCall( (ref RustCallStatus _status) => - _UniFFILib.uniffi_servicepoint_binding_uniffi_fn_constructor_command_clear( ref _status) -)); - } - - public static Command Clone(Command @other) { - return new Command( - _UniffiHelpers.RustCall( (ref RustCallStatus _status) => - _UniFFILib.uniffi_servicepoint_binding_uniffi_fn_constructor_command_clone(FfiConverterTypeCommand.INSTANCE.Lower(@other), ref _status) -)); - } - - public static Command Cp437Data(ulong @offsetX, ulong @offsetY, Cp437Grid @grid) { - return new Command( - _UniffiHelpers.RustCall( (ref RustCallStatus _status) => - _UniFFILib.uniffi_servicepoint_binding_uniffi_fn_constructor_command_cp437_data(FfiConverterUInt64.INSTANCE.Lower(@offsetX), FfiConverterUInt64.INSTANCE.Lower(@offsetY), FfiConverterTypeCp437Grid.INSTANCE.Lower(@grid), ref _status) -)); - } - - public static Command FadeOut() { - return new Command( - _UniffiHelpers.RustCall( (ref RustCallStatus _status) => - _UniFFILib.uniffi_servicepoint_binding_uniffi_fn_constructor_command_fade_out( ref _status) -)); - } - - public static Command HardReset() { - return new Command( - _UniffiHelpers.RustCall( (ref RustCallStatus _status) => - _UniFFILib.uniffi_servicepoint_binding_uniffi_fn_constructor_command_hard_reset( ref _status) -)); - } - - public static Command Utf8Data(ulong @offsetX, ulong @offsetY, CharGrid @grid) { - return new Command( - _UniffiHelpers.RustCall( (ref RustCallStatus _status) => - _UniFFILib.uniffi_servicepoint_binding_uniffi_fn_constructor_command_utf8_data(FfiConverterUInt64.INSTANCE.Lower(@offsetX), FfiConverterUInt64.INSTANCE.Lower(@offsetY), FfiConverterTypeCharGrid.INSTANCE.Lower(@grid), ref _status) -)); - } - - -} - -class FfiConverterTypeCommand: FfiConverter { - public static FfiConverterTypeCommand INSTANCE = new FfiConverterTypeCommand(); - - public override CommandSafeHandle Lower(Command value) { - return value.GetHandle(); - } - - public override Command Lift(CommandSafeHandle value) { - return new Command(value); - } - - public override Command Read(BigEndianStream stream) { - return Lift(new CommandSafeHandle(new IntPtr(stream.ReadLong()))); - } - - public override int AllocationSize(Command value) { - return 8; - } - - public override void Write(Command value, BigEndianStream stream) { - stream.WriteLong(Lower(value).DangerousGetRawFfiValue().ToInt64()); - } -} - - - -public interface IConnection { - - /// - void Send(Command @command); - -} - -public class ConnectionSafeHandle: FFISafeHandle { - public ConnectionSafeHandle(): base() { - } - public ConnectionSafeHandle(IntPtr pointer): base(pointer) { - } - override protected bool ReleaseHandle() { - _UniffiHelpers.RustCall((ref RustCallStatus status) => { - _UniFFILib.uniffi_servicepoint_binding_uniffi_fn_free_connection(this.handle, ref status); - }); - return true; - } -} -public class Connection: FFIObject, IConnection { - public Connection(ConnectionSafeHandle pointer): base(pointer) {} - public Connection(String @host) : - this( - _UniffiHelpers.RustCallWithError(FfiConverterTypeServicePointException.INSTANCE, (ref RustCallStatus _status) => - _UniFFILib.uniffi_servicepoint_binding_uniffi_fn_constructor_connection_new(FfiConverterString.INSTANCE.Lower(@host), ref _status) -)) {} - - - /// - public void Send(Command @command) { - _UniffiHelpers.RustCallWithError(FfiConverterTypeServicePointException.INSTANCE, (ref RustCallStatus _status) => - _UniFFILib.uniffi_servicepoint_binding_uniffi_fn_method_connection_send(this.GetHandle(), FfiConverterTypeCommand.INSTANCE.Lower(@command), ref _status) -); - } - - - - - public static Connection NewFake() { - return new Connection( - _UniffiHelpers.RustCall( (ref RustCallStatus _status) => - _UniFFILib.uniffi_servicepoint_binding_uniffi_fn_constructor_connection_new_fake( ref _status) -)); - } - - -} - -class FfiConverterTypeConnection: FfiConverter { - public static FfiConverterTypeConnection INSTANCE = new FfiConverterTypeConnection(); - - public override ConnectionSafeHandle Lower(Connection value) { - return value.GetHandle(); - } - - public override Connection Lift(ConnectionSafeHandle value) { - return new Connection(value); - } - - public override Connection Read(BigEndianStream stream) { - return Lift(new ConnectionSafeHandle(new IntPtr(stream.ReadLong()))); - } - - public override int AllocationSize(Connection value) { - return 8; - } - - public override void Write(Connection value, BigEndianStream stream) { - stream.WriteLong(Lower(value).DangerousGetRawFfiValue().ToInt64()); - } -} - - - -public interface ICp437Grid { - - byte[] CopyRaw(); - - bool Equals(Cp437Grid @other); - - void Fill(byte @value); - - byte Get(ulong @x, ulong @y); - - ulong Height(); - - void Set(ulong @x, ulong @y, byte @value); - - CharGrid ToUtf8(); - - ulong Width(); - -} - -public class Cp437GridSafeHandle: FFISafeHandle { - public Cp437GridSafeHandle(): base() { - } - public Cp437GridSafeHandle(IntPtr pointer): base(pointer) { - } - override protected bool ReleaseHandle() { - _UniffiHelpers.RustCall((ref RustCallStatus status) => { - _UniFFILib.uniffi_servicepoint_binding_uniffi_fn_free_cp437grid(this.handle, ref status); - }); - return true; - } -} -public class Cp437Grid: FFIObject, ICp437Grid { - public Cp437Grid(Cp437GridSafeHandle pointer): base(pointer) {} - public Cp437Grid(ulong @width, ulong @height) : - this( - _UniffiHelpers.RustCall( (ref RustCallStatus _status) => - _UniFFILib.uniffi_servicepoint_binding_uniffi_fn_constructor_cp437grid_new(FfiConverterUInt64.INSTANCE.Lower(@width), FfiConverterUInt64.INSTANCE.Lower(@height), ref _status) -)) {} - - - public byte[] CopyRaw() { - return FfiConverterByteArray.INSTANCE.Lift( - _UniffiHelpers.RustCall( (ref RustCallStatus _status) => - _UniFFILib.uniffi_servicepoint_binding_uniffi_fn_method_cp437grid_copy_raw(this.GetHandle(), ref _status) -)); - } - - public bool Equals(Cp437Grid @other) { - return FfiConverterBoolean.INSTANCE.Lift( - _UniffiHelpers.RustCall( (ref RustCallStatus _status) => - _UniFFILib.uniffi_servicepoint_binding_uniffi_fn_method_cp437grid_equals(this.GetHandle(), FfiConverterTypeCp437Grid.INSTANCE.Lower(@other), ref _status) -)); - } - - public void Fill(byte @value) { - _UniffiHelpers.RustCall( (ref RustCallStatus _status) => - _UniFFILib.uniffi_servicepoint_binding_uniffi_fn_method_cp437grid_fill(this.GetHandle(), FfiConverterUInt8.INSTANCE.Lower(@value), ref _status) -); - } - - - public byte Get(ulong @x, ulong @y) { - return FfiConverterUInt8.INSTANCE.Lift( - _UniffiHelpers.RustCall( (ref RustCallStatus _status) => - _UniFFILib.uniffi_servicepoint_binding_uniffi_fn_method_cp437grid_get(this.GetHandle(), FfiConverterUInt64.INSTANCE.Lower(@x), FfiConverterUInt64.INSTANCE.Lower(@y), ref _status) -)); - } - - public ulong Height() { - return FfiConverterUInt64.INSTANCE.Lift( - _UniffiHelpers.RustCall( (ref RustCallStatus _status) => - _UniFFILib.uniffi_servicepoint_binding_uniffi_fn_method_cp437grid_height(this.GetHandle(), ref _status) -)); - } - - public void Set(ulong @x, ulong @y, byte @value) { - _UniffiHelpers.RustCall( (ref RustCallStatus _status) => - _UniFFILib.uniffi_servicepoint_binding_uniffi_fn_method_cp437grid_set(this.GetHandle(), FfiConverterUInt64.INSTANCE.Lower(@x), FfiConverterUInt64.INSTANCE.Lower(@y), FfiConverterUInt8.INSTANCE.Lower(@value), ref _status) -); - } - - - public CharGrid ToUtf8() { - return FfiConverterTypeCharGrid.INSTANCE.Lift( - _UniffiHelpers.RustCall( (ref RustCallStatus _status) => - _UniFFILib.uniffi_servicepoint_binding_uniffi_fn_method_cp437grid_to_utf8(this.GetHandle(), ref _status) -)); - } - - public ulong Width() { - return FfiConverterUInt64.INSTANCE.Lift( - _UniffiHelpers.RustCall( (ref RustCallStatus _status) => - _UniFFILib.uniffi_servicepoint_binding_uniffi_fn_method_cp437grid_width(this.GetHandle(), ref _status) -)); - } - - - - public static Cp437Grid Clone(Cp437Grid @other) { - return new Cp437Grid( - _UniffiHelpers.RustCall( (ref RustCallStatus _status) => - _UniFFILib.uniffi_servicepoint_binding_uniffi_fn_constructor_cp437grid_clone(FfiConverterTypeCp437Grid.INSTANCE.Lower(@other), ref _status) -)); - } - - public static Cp437Grid Load(ulong @width, ulong @height, byte[] @data) { - return new Cp437Grid( - _UniffiHelpers.RustCall( (ref RustCallStatus _status) => - _UniFFILib.uniffi_servicepoint_binding_uniffi_fn_constructor_cp437grid_load(FfiConverterUInt64.INSTANCE.Lower(@width), FfiConverterUInt64.INSTANCE.Lower(@height), FfiConverterByteArray.INSTANCE.Lower(@data), ref _status) -)); - } - - -} - -class FfiConverterTypeCp437Grid: FfiConverter { - public static FfiConverterTypeCp437Grid INSTANCE = new FfiConverterTypeCp437Grid(); - - public override Cp437GridSafeHandle Lower(Cp437Grid value) { - return value.GetHandle(); - } - - public override Cp437Grid Lift(Cp437GridSafeHandle value) { - return new Cp437Grid(value); - } - - public override Cp437Grid Read(BigEndianStream stream) { - return Lift(new Cp437GridSafeHandle(new IntPtr(stream.ReadLong()))); - } - - public override int AllocationSize(Cp437Grid value) { - return 8; - } - - public override void Write(Cp437Grid value, BigEndianStream stream) { - stream.WriteLong(Lower(value).DangerousGetRawFfiValue().ToInt64()); - } -} - - - -public record Constants ( - ulong @tileSize, - ulong @tileWidth, - ulong @tileHeight, - ulong @pixelWidth, - ulong @pixelHeight, - ulong @pixelCount -) { -} - -class FfiConverterTypeConstants: FfiConverterRustBuffer { - public static FfiConverterTypeConstants INSTANCE = new FfiConverterTypeConstants(); - - public override Constants Read(BigEndianStream stream) { - return new Constants( - @tileSize: FfiConverterUInt64.INSTANCE.Read(stream), - @tileWidth: FfiConverterUInt64.INSTANCE.Read(stream), - @tileHeight: FfiConverterUInt64.INSTANCE.Read(stream), - @pixelWidth: FfiConverterUInt64.INSTANCE.Read(stream), - @pixelHeight: FfiConverterUInt64.INSTANCE.Read(stream), - @pixelCount: FfiConverterUInt64.INSTANCE.Read(stream) - ); - } - - public override int AllocationSize(Constants value) { - return - FfiConverterUInt64.INSTANCE.AllocationSize(value.@tileSize) + - FfiConverterUInt64.INSTANCE.AllocationSize(value.@tileWidth) + - FfiConverterUInt64.INSTANCE.AllocationSize(value.@tileHeight) + - FfiConverterUInt64.INSTANCE.AllocationSize(value.@pixelWidth) + - FfiConverterUInt64.INSTANCE.AllocationSize(value.@pixelHeight) + - FfiConverterUInt64.INSTANCE.AllocationSize(value.@pixelCount); - } - - public override void Write(Constants value, BigEndianStream stream) { - FfiConverterUInt64.INSTANCE.Write(value.@tileSize, stream); - FfiConverterUInt64.INSTANCE.Write(value.@tileWidth, stream); - FfiConverterUInt64.INSTANCE.Write(value.@tileHeight, stream); - FfiConverterUInt64.INSTANCE.Write(value.@pixelWidth, stream); - FfiConverterUInt64.INSTANCE.Write(value.@pixelHeight, stream); - FfiConverterUInt64.INSTANCE.Write(value.@pixelCount, stream); - } -} - - - - - -public class CharGridException: UniffiException { - // Each variant is a nested class - - - public class StringNotOneChar : CharGridException { - // Members - public String @value; - - // Constructor - public StringNotOneChar( - String @value) { - this.@value = @value; - } - } - - - public class InvalidSeriesLength : CharGridException { - // Members - public ulong @actual; - public ulong @expected; - - // Constructor - public InvalidSeriesLength( - ulong @actual, - ulong @expected) { - this.@actual = @actual; - this.@expected = @expected; - } - } - - - public class OutOfBounds : CharGridException { - // Members - public ulong @index; - public ulong @size; - - // Constructor - public OutOfBounds( - ulong @index, - ulong @size) { - this.@index = @index; - this.@size = @size; - } - } - - - -} - -class FfiConverterTypeCharGridException : FfiConverterRustBuffer, CallStatusErrorHandler { - public static FfiConverterTypeCharGridException INSTANCE = new FfiConverterTypeCharGridException(); - - public override CharGridException Read(BigEndianStream stream) { - var value = stream.ReadInt(); - switch (value) { - case 1: - return new CharGridException.StringNotOneChar( - FfiConverterString.INSTANCE.Read(stream)); - case 2: - return new CharGridException.InvalidSeriesLength( - FfiConverterUInt64.INSTANCE.Read(stream), - FfiConverterUInt64.INSTANCE.Read(stream)); - case 3: - return new CharGridException.OutOfBounds( - FfiConverterUInt64.INSTANCE.Read(stream), - FfiConverterUInt64.INSTANCE.Read(stream)); - default: - throw new InternalException(String.Format("invalid error value '{0}' in FfiConverterTypeCharGridException.Read()", value)); - } - } - - public override int AllocationSize(CharGridException value) { - switch (value) { - case CharGridException.StringNotOneChar variant_value: - return 4 - + FfiConverterString.INSTANCE.AllocationSize(variant_value.@value); - case CharGridException.InvalidSeriesLength variant_value: - return 4 - + FfiConverterUInt64.INSTANCE.AllocationSize(variant_value.@actual) - + FfiConverterUInt64.INSTANCE.AllocationSize(variant_value.@expected); - case CharGridException.OutOfBounds variant_value: - return 4 - + FfiConverterUInt64.INSTANCE.AllocationSize(variant_value.@index) - + FfiConverterUInt64.INSTANCE.AllocationSize(variant_value.@size); - default: - throw new InternalException(String.Format("invalid error value '{0}' in FfiConverterTypeCharGridException.AllocationSize()", value)); - } - } - - public override void Write(CharGridException value, BigEndianStream stream) { - switch (value) { - case CharGridException.StringNotOneChar variant_value: - stream.WriteInt(1); - FfiConverterString.INSTANCE.Write(variant_value.@value, stream); - break; - case CharGridException.InvalidSeriesLength variant_value: - stream.WriteInt(2); - FfiConverterUInt64.INSTANCE.Write(variant_value.@actual, stream); - FfiConverterUInt64.INSTANCE.Write(variant_value.@expected, stream); - break; - case CharGridException.OutOfBounds variant_value: - stream.WriteInt(3); - FfiConverterUInt64.INSTANCE.Write(variant_value.@index, stream); - FfiConverterUInt64.INSTANCE.Write(variant_value.@size, stream); - break; - default: - throw new InternalException(String.Format("invalid error value '{0}' in FfiConverterTypeCharGridException.Write()", value)); - } - } -} - - - - - -public enum CompressionCode: int { - - Uncompressed, - Zlib, - Bzip2, - Lzma, - Zstd -} - -class FfiConverterTypeCompressionCode: FfiConverterRustBuffer { - public static FfiConverterTypeCompressionCode INSTANCE = new FfiConverterTypeCompressionCode(); - - public override CompressionCode Read(BigEndianStream stream) { - var value = stream.ReadInt() - 1; - if (Enum.IsDefined(typeof(CompressionCode), value)) { - return (CompressionCode)value; - } else { - throw new InternalException(String.Format("invalid enum value '{0}' in FfiConverterTypeCompressionCode.Read()", value)); - } - } - - public override int AllocationSize(CompressionCode value) { - return 4; - } - - public override void Write(CompressionCode value, BigEndianStream stream) { - stream.WriteInt((int)value + 1); - } -} - - - - - - - -public class ServicePointException: UniffiException { - // Each variant is a nested class - - - public class IoException : ServicePointException { - // Members - public String @error; - - // Constructor - public IoException( - String @error) { - this.@error = @error; - } - } - - - public class InvalidBrightness : ServicePointException { - // Members - public byte @value; - - // Constructor - public InvalidBrightness( - byte @value) { - this.@value = @value; - } - } - - - -} - -class FfiConverterTypeServicePointException : FfiConverterRustBuffer, CallStatusErrorHandler { - public static FfiConverterTypeServicePointException INSTANCE = new FfiConverterTypeServicePointException(); - - public override ServicePointException Read(BigEndianStream stream) { - var value = stream.ReadInt(); - switch (value) { - case 1: - return new ServicePointException.IoException( - FfiConverterString.INSTANCE.Read(stream)); - case 2: - return new ServicePointException.InvalidBrightness( - FfiConverterUInt8.INSTANCE.Read(stream)); - default: - throw new InternalException(String.Format("invalid error value '{0}' in FfiConverterTypeServicePointException.Read()", value)); - } - } - - public override int AllocationSize(ServicePointException value) { - switch (value) { - case ServicePointException.IoException variant_value: - return 4 - + FfiConverterString.INSTANCE.AllocationSize(variant_value.@error); - case ServicePointException.InvalidBrightness variant_value: - return 4 - + FfiConverterUInt8.INSTANCE.AllocationSize(variant_value.@value); - default: - throw new InternalException(String.Format("invalid error value '{0}' in FfiConverterTypeServicePointException.AllocationSize()", value)); - } - } - - public override void Write(ServicePointException value, BigEndianStream stream) { - switch (value) { - case ServicePointException.IoException variant_value: - stream.WriteInt(1); - FfiConverterString.INSTANCE.Write(variant_value.@error, stream); - break; - case ServicePointException.InvalidBrightness variant_value: - stream.WriteInt(2); - FfiConverterUInt8.INSTANCE.Write(variant_value.@value, stream); - break; - default: - throw new InternalException(String.Format("invalid error value '{0}' in FfiConverterTypeServicePointException.Write()", value)); - } - } -} -#pragma warning restore 8625 -public static class ServicepointBindingUniffiMethods { - public static Constants GetConstants() { - return FfiConverterTypeConstants.INSTANCE.Lift( - _UniffiHelpers.RustCall( (ref RustCallStatus _status) => - _UniFFILib.uniffi_servicepoint_binding_uniffi_fn_func_get_constants( ref _status) -)); - } - -} - diff --git a/crates/servicepoint_binding_uniffi/libraries/csharp/csharp.sln b/crates/servicepoint_binding_uniffi/libraries/csharp/csharp.sln deleted file mode 100644 index 2fbf818..0000000 --- a/crates/servicepoint_binding_uniffi/libraries/csharp/csharp.sln +++ /dev/null @@ -1,34 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 17 -VisualStudioVersion = 17.0.31903.59 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ServicePoint", "ServicePoint\ServicePoint.csproj", "{53576D3C-E32E-49BF-BF10-2DB504E50CE1}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ServicePoint.Example", "ServicePoint.Example\ServicePoint.Example.csproj", "{FEF24227-090E-46C2-B8F6-ACB5AA1A4309}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ServicePoint.Tests", "ServicePoint.Tests\ServicePoint.Tests.csproj", "{9DC15508-A980-4135-9FC6-659FF54B4E5C}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {53576D3C-E32E-49BF-BF10-2DB504E50CE1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {53576D3C-E32E-49BF-BF10-2DB504E50CE1}.Debug|Any CPU.Build.0 = Debug|Any CPU - {53576D3C-E32E-49BF-BF10-2DB504E50CE1}.Release|Any CPU.ActiveCfg = Release|Any CPU - {53576D3C-E32E-49BF-BF10-2DB504E50CE1}.Release|Any CPU.Build.0 = Release|Any CPU - {FEF24227-090E-46C2-B8F6-ACB5AA1A4309}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {FEF24227-090E-46C2-B8F6-ACB5AA1A4309}.Debug|Any CPU.Build.0 = Debug|Any CPU - {FEF24227-090E-46C2-B8F6-ACB5AA1A4309}.Release|Any CPU.ActiveCfg = Release|Any CPU - {FEF24227-090E-46C2-B8F6-ACB5AA1A4309}.Release|Any CPU.Build.0 = Release|Any CPU - {9DC15508-A980-4135-9FC6-659FF54B4E5C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {9DC15508-A980-4135-9FC6-659FF54B4E5C}.Debug|Any CPU.Build.0 = Debug|Any CPU - {9DC15508-A980-4135-9FC6-659FF54B4E5C}.Release|Any CPU.ActiveCfg = Release|Any CPU - {9DC15508-A980-4135-9FC6-659FF54B4E5C}.Release|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection -EndGlobal diff --git a/crates/servicepoint_binding_uniffi/libraries/ruby/example/example.sh b/crates/servicepoint_binding_uniffi/libraries/ruby/example/example.sh deleted file mode 100755 index 25ed29e..0000000 --- a/crates/servicepoint_binding_uniffi/libraries/ruby/example/example.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/usr/bin/env bash - -LD_LIBRARY_PATH="../../../../../target/release:$LD_LIBRARY_PATH" ruby example.rb diff --git a/crates/servicepoint_binding_uniffi/src/bin/uniffi-bindgen-cs.rs b/crates/servicepoint_binding_uniffi/src/bin/uniffi-bindgen-cs.rs deleted file mode 100644 index ef11e75..0000000 --- a/crates/servicepoint_binding_uniffi/src/bin/uniffi-bindgen-cs.rs +++ /dev/null @@ -1,3 +0,0 @@ -fn main() { - uniffi_bindgen_cs::main().unwrap(); -} diff --git a/crates/servicepoint_binding_uniffi/src/bin/uniffi-bindgen-go.rs b/crates/servicepoint_binding_uniffi/src/bin/uniffi-bindgen-go.rs deleted file mode 100644 index 5f01856..0000000 --- a/crates/servicepoint_binding_uniffi/src/bin/uniffi-bindgen-go.rs +++ /dev/null @@ -1,3 +0,0 @@ -fn main() { - uniffi_bindgen_go::main().unwrap(); -} diff --git a/crates/servicepoint_binding_uniffi/src/bitmap.rs b/crates/servicepoint_binding_uniffi/src/bitmap.rs deleted file mode 100644 index 1291f7b..0000000 --- a/crates/servicepoint_binding_uniffi/src/bitmap.rs +++ /dev/null @@ -1,77 +0,0 @@ -use servicepoint::{DataRef, Grid}; -use std::sync::{Arc, RwLock}; - -#[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), - }) - } -} - -#[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, - )) - } - - #[uniffi::constructor] - pub fn new_max_sized() -> Arc { - Self::internal_new(servicepoint::Bitmap::max_sized()) - } - - #[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, - )) - } - - #[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() - .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 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(); - *a == *b - } - - pub fn copy_raw(&self) -> Vec { - self.actual.read().unwrap().data_ref().to_vec() - } -} diff --git a/crates/servicepoint_binding_uniffi/src/bitvec.rs b/crates/servicepoint_binding_uniffi/src/bitvec.rs deleted file mode 100644 index 1ad7751..0000000 --- a/crates/servicepoint_binding_uniffi/src/bitvec.rs +++ /dev/null @@ -1,61 +0,0 @@ -use std::sync::{Arc, RwLock}; - -#[derive(uniffi::Object)] -pub struct BitVec { - pub(crate) actual: RwLock, -} - -impl BitVec { - fn internal_new(actual: servicepoint::BitVec) -> Arc { - Arc::new(Self { - actual: RwLock::new(actual), - }) - } -} - -#[uniffi::export] -impl BitVec { - #[uniffi::constructor] - pub fn new(size: u64) -> Arc { - Self::internal_new(servicepoint::BitVec::repeat(false, size as usize)) - } - #[uniffi::constructor] - pub fn load(data: Vec) -> Arc { - Self::internal_new(servicepoint::BitVec::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) - } - - pub fn get(&self, index: u64) -> bool { - self.actual - .read() - .unwrap() - .get(index as usize) - .is_some_and(move |bit| *bit) - } - - pub fn fill(&self, value: bool) { - self.actual.write().unwrap().fill(value) - } - - pub fn len(&self) -> u64 { - self.actual.read().unwrap().len() as u64 - } - - pub fn equals(&self, other: &BitVec) -> bool { - let a = self.actual.read().unwrap(); - let b = other.actual.read().unwrap(); - *a == *b - } - - pub fn copy_raw(&self) -> Vec { - self.actual.read().unwrap().clone().into_vec() - } -} diff --git a/crates/servicepoint_binding_uniffi/src/brightness_grid.rs b/crates/servicepoint_binding_uniffi/src/brightness_grid.rs deleted file mode 100644 index afa0e3f..0000000 --- a/crates/servicepoint_binding_uniffi/src/brightness_grid.rs +++ /dev/null @@ -1,86 +0,0 @@ -use servicepoint::{Brightness, DataRef, Grid}; -use std::sync::{Arc, RwLock}; - -#[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), - }) - } -} - -#[uniffi::export] -impl BrightnessGrid { - #[uniffi::constructor] - pub fn new(width: u64, height: u64) -> Arc { - Self::internal_new(servicepoint::BrightnessGrid::new( - width as usize, - height as usize, - )) - } - - #[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, - )) - } - - #[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, - y as usize, - Brightness::saturating_from(value), - ) - } - - 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 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(); - let b = other.actual.read().unwrap(); - *a == *b - } - - pub fn copy_raw(&self) -> Vec { - self.actual - .read() - .unwrap() - .data_ref() - .iter() - .map(u8::from) - .collect() - } -} diff --git a/crates/servicepoint_binding_uniffi/src/char_grid.rs b/crates/servicepoint_binding_uniffi/src/char_grid.rs deleted file mode 100644 index e5d59a8..0000000 --- a/crates/servicepoint_binding_uniffi/src/char_grid.rs +++ /dev/null @@ -1,169 +0,0 @@ -use crate::cp437_grid::Cp437Grid; -use servicepoint::{Grid, SetValueSeriesError}; -use std::convert::Into; -use std::sync::{Arc, RwLock}; - -#[derive(uniffi::Object)] -pub struct CharGrid { - pub(crate) actual: RwLock, -} - -#[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] - pub fn new(width: u64, height: u64) -> Arc { - Self::internal_new(servicepoint::CharGrid::new( - width as usize, - height as usize, - )) - } - - #[uniffi::constructor] - pub fn load(data: String) -> Arc { - 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, - y: u64, - value: String, - ) -> Result<(), CharGridError> { - let value = Self::str_to_char(value)?; - self.actual - .write() - .unwrap() - .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() - } - - pub fn fill(&self, value: String) -> Result<(), CharGridError> { - let value = Self::str_to_char(value)?; - self.actual.write().unwrap().fill(value); - 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(); - *a == *b - } - - pub fn as_string(&self) -> String { - let grid = self.actual.read().unwrap(); - String::from(&*grid) - } - - pub fn set_row(&self, y: u64, row: String) -> Result<(), CharGridError> { - self.actual - .write() - .unwrap() - .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() - .set_row(x as usize, &col.chars().collect::>()) - .map_err(CharGridError::from) - } - - pub fn get_row(&self, y: u64) -> Result { - self.actual - .read() - .unwrap() - .get_row(y as usize) - .map(String::from_iter) - .ok_or(CharGridError::OutOfBounds { - index: y, - size: self.height(), - }) - } - - pub fn get_col(&self, x: u64) -> Result { - self.actual - .read() - .unwrap() - .get_col(x as usize) - .map(String::from_iter) - .ok_or(CharGridError::OutOfBounds { - index: x, - size: self.width(), - }) - } - - pub fn to_cp437(&self) -> Arc { - Cp437Grid::internal_new(servicepoint::Cp437Grid::from( - &*self.actual.read().unwrap(), - )) - } -} - -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 }); - } - - let value = value.chars().nth(0).unwrap(); - Ok(value) - } -} - -impl From for CharGridError { - fn from(e: SetValueSeriesError) -> Self { - match e { - SetValueSeriesError::OutOfBounds { index, size } => { - CharGridError::OutOfBounds { - index: index as u64, - size: size as u64, - } - } - SetValueSeriesError::InvalidLength { actual, expected } => { - CharGridError::InvalidSeriesLength { - actual: actual as u64, - expected: expected as u64, - } - } - } - } -} diff --git a/crates/servicepoint_binding_uniffi/src/command.rs b/crates/servicepoint_binding_uniffi/src/command.rs deleted file mode 100644 index bb479ae..0000000 --- a/crates/servicepoint_binding_uniffi/src/command.rs +++ /dev/null @@ -1,175 +0,0 @@ -use crate::bitmap::Bitmap; -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::Origin; -use std::sync::Arc; - -#[derive(uniffi::Object)] -pub struct Command { - pub(crate) actual: servicepoint::Command, -} - -impl Command { - fn internal_new(actual: servicepoint::Command) -> Arc { - Arc::new(Command { actual }) - } -} - -#[uniffi::export] -impl Command { - #[uniffi::constructor] - pub fn clear() -> Arc { - Self::internal_new(servicepoint::Command::Clear) - } - - #[uniffi::constructor] - pub fn brightness(brightness: u8) -> Result, ServicePointError> { - servicepoint::Brightness::try_from(brightness) - .map_err(move |value| ServicePointError::InvalidBrightness { - value, - }) - .map(servicepoint::Command::Brightness) - .map(Self::internal_new) - } - - #[uniffi::constructor] - pub fn fade_out() -> Arc { - Self::internal_new(servicepoint::Command::FadeOut) - } - - #[uniffi::constructor] - pub fn hard_reset() -> Arc { - Self::internal_new(servicepoint::Command::HardReset) - } - - #[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::Command::BitmapLinearWin( - origin, - bitmap, - servicepoint::CompressionCode::try_from(compression as u16) - .unwrap(), - ); - Self::internal_new(actual) - } - - #[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 = servicepoint::Command::CharBrightness(origin, grid); - Self::internal_new(actual) - } - - #[uniffi::constructor] - pub fn bitmap_linear( - offset: u64, - bitmap: &Arc, - compression: CompressionCode, - ) -> 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) - } - - #[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 = servicepoint::Command::Cp437Data(origin, grid); - Self::internal_new(actual) - } - - #[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 = servicepoint::Command::Utf8Data(origin, grid); - Self::internal_new(actual) - } - - #[uniffi::constructor] - pub fn clone(other: &Arc) -> Arc { - Self::internal_new(other.actual.clone()) - } - - pub fn equals(&self, other: &Command) -> bool { - self.actual == other.actual - } -} diff --git a/crates/servicepoint_binding_uniffi/src/compression_code.rs b/crates/servicepoint_binding_uniffi/src/compression_code.rs deleted file mode 100644 index 078230a..0000000 --- a/crates/servicepoint_binding_uniffi/src/compression_code.rs +++ /dev/null @@ -1,14 +0,0 @@ -#[repr(u16)] -#[derive(Debug, Clone, Copy, PartialEq, uniffi::Enum)] -pub enum CompressionCode { - /// no compression - Uncompressed = 0x0, - /// compress using flate2 with zlib header - Zlib = 0x677a, - /// compress using bzip2 - Bzip2 = 0x627a, - /// compress using lzma - Lzma = 0x6c7a, - /// compress using Zstandard - Zstd = 0x7a73, -} diff --git a/crates/servicepoint_binding_uniffi/src/connection.rs b/crates/servicepoint_binding_uniffi/src/connection.rs deleted file mode 100644 index 6ba4e07..0000000 --- a/crates/servicepoint_binding_uniffi/src/connection.rs +++ /dev/null @@ -1,36 +0,0 @@ -use std::sync::Arc; - -use crate::command::Command; -use crate::errors::ServicePointError; - -#[derive(uniffi::Object)] -pub struct Connection { - actual: servicepoint::Connection, -} - -#[uniffi::export] -impl Connection { - #[uniffi::constructor] - pub fn new(host: String) -> Result, ServicePointError> { - servicepoint::Connection::open(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| { - ServicePointError::IoError { - error: format!("{err:?}"), - } - }) - } -} diff --git a/crates/servicepoint_binding_uniffi/src/constants.rs b/crates/servicepoint_binding_uniffi/src/constants.rs deleted file mode 100644 index 3d0cfcb..0000000 --- a/crates/servicepoint_binding_uniffi/src/constants.rs +++ /dev/null @@ -1,23 +0,0 @@ -#[derive( - Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, uniffi::Record, -)] -pub struct Constants { - pub tile_size: u64, - pub tile_width: u64, - pub tile_height: u64, - pub pixel_width: u64, - pub pixel_height: u64, - pub pixel_count: u64, -} - -#[uniffi::export] -fn get_constants() -> Constants { - Constants { - tile_size: servicepoint::TILE_SIZE as u64, - tile_width: servicepoint::TILE_WIDTH as u64, - tile_height: servicepoint::TILE_HEIGHT as u64, - pixel_width: servicepoint::PIXEL_WIDTH as u64, - pixel_height: servicepoint::PIXEL_HEIGHT as u64, - pixel_count: servicepoint::PIXEL_COUNT as u64, - } -} diff --git a/crates/servicepoint_binding_uniffi/src/cp437_grid.rs b/crates/servicepoint_binding_uniffi/src/cp437_grid.rs deleted file mode 100644 index b201238..0000000 --- a/crates/servicepoint_binding_uniffi/src/cp437_grid.rs +++ /dev/null @@ -1,79 +0,0 @@ -use crate::char_grid::CharGrid; -use servicepoint::{DataRef, Grid}; -use std::sync::{Arc, RwLock}; - -#[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), - }) - } -} - -#[uniffi::export] -impl Cp437Grid { - #[uniffi::constructor] - pub fn new(width: u64, height: u64) -> Arc { - Self::internal_new(servicepoint::Cp437Grid::new( - width as usize, - height as usize, - )) - } - - #[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, - )) - } - - #[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, 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) - } - 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(); - let b = other.actual.read().unwrap(); - *a == *b - } - - pub fn copy_raw(&self) -> Vec { - self.actual.read().unwrap().data_ref().to_vec() - } - - pub fn to_utf8(&self) -> Arc { - CharGrid::internal_new(servicepoint::CharGrid::from( - &*self.actual.read().unwrap(), - )) - } -} diff --git a/crates/servicepoint_binding_uniffi/src/errors.rs b/crates/servicepoint_binding_uniffi/src/errors.rs deleted file mode 100644 index 9c28f5f..0000000 --- a/crates/servicepoint_binding_uniffi/src/errors.rs +++ /dev/null @@ -1,7 +0,0 @@ -#[derive(uniffi::Error, thiserror::Error, Debug)] -pub enum ServicePointError { - #[error("An IO error occurred: {error}")] - IoError { error: String }, - #[error("The specified brightness value {value} is out of range")] - InvalidBrightness { value: u8 }, -} diff --git a/crates/servicepoint_binding_uniffi/src/lib.rs b/crates/servicepoint_binding_uniffi/src/lib.rs deleted file mode 100644 index 2ecad45..0000000 --- a/crates/servicepoint_binding_uniffi/src/lib.rs +++ /dev/null @@ -1,12 +0,0 @@ -uniffi::setup_scaffolding!(); - -mod bitmap; -mod bitvec; -mod brightness_grid; -mod char_grid; -mod command; -mod compression_code; -mod connection; -mod constants; -mod cp437_grid; -mod errors; diff --git a/crates/servicepoint_binding_uniffi/uniffi.toml b/crates/servicepoint_binding_uniffi/uniffi.toml deleted file mode 100644 index 249e237..0000000 --- a/crates/servicepoint_binding_uniffi/uniffi.toml +++ /dev/null @@ -1,3 +0,0 @@ -[bindings.csharp] -namespace = "ServicePoint" -access_modifier = "public" diff --git a/crates/servicepoint_binding_uniffi/libraries/ruby/example/Gemfile b/example/Gemfile similarity index 100% rename from crates/servicepoint_binding_uniffi/libraries/ruby/example/Gemfile rename to example/Gemfile diff --git a/crates/servicepoint_binding_uniffi/libraries/ruby/example/Gemfile.lock b/example/Gemfile.lock similarity index 100% rename from crates/servicepoint_binding_uniffi/libraries/ruby/example/Gemfile.lock rename to example/Gemfile.lock diff --git a/crates/servicepoint_binding_uniffi/libraries/ruby/example/example.rb b/example/example.rb similarity index 100% rename from crates/servicepoint_binding_uniffi/libraries/ruby/example/example.rb rename to example/example.rb diff --git a/example/example.sh b/example/example.sh new file mode 100755 index 0000000..fae0755 --- /dev/null +++ b/example/example.sh @@ -0,0 +1,6 @@ +#!/usr/bin/env bash +set -e + +SCRIPT_PATH="$( cd -- "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P )" + +LD_LIBRARY_PATH="$SCRIPT_PATH/../target/release:$LD_LIBRARY_PATH" ruby "$SCRIPT_PATH/example.rb" diff --git a/flake.lock b/flake.lock index b07ad46..9e70e85 100644 --- a/flake.lock +++ b/flake.lock @@ -1,25 +1,5 @@ { "nodes": { - "naersk": { - "inputs": { - "nixpkgs": [ - "nixpkgs" - ] - }, - "locked": { - "lastModified": 1736429655, - "narHash": "sha256-BwMekRuVlSB9C0QgwKMICiJ5EVbLGjfe4qyueyNQyGI=", - "owner": "nix-community", - "repo": "naersk", - "rev": "0621e47bd95542b8e1ce2ee2d65d6a1f887a13ce", - "type": "github" - }, - "original": { - "owner": "nix-community", - "repo": "naersk", - "type": "github" - } - }, "nixpkgs": { "locked": { "lastModified": 1739357830, @@ -38,7 +18,6 @@ }, "root": { "inputs": { - "naersk": "naersk", "nixpkgs": "nixpkgs" } } diff --git a/flake.nix b/flake.nix index d903f36..fdd32de 100644 --- a/flake.nix +++ b/flake.nix @@ -3,17 +3,12 @@ inputs = { nixpkgs.url = "github:nixos/nixpkgs/nixos-24.11"; - naersk = { - url = "github:nix-community/naersk"; - inputs.nixpkgs.follows = "nixpkgs"; - }; }; outputs = inputs@{ self, nixpkgs, - naersk, }: let lib = nixpkgs.lib; @@ -33,101 +28,13 @@ } ); in - rec { - packages = forAllSystems ( - { pkgs, ... }: - let - naersk' = pkgs.callPackage naersk { }; - nativeBuildInputs = with pkgs; [ - pkg-config - makeWrapper - ]; - buildInputs = with pkgs; [ - xe - xz - ]; - makeExample = - { - package, - example, - features ? "", - }: - naersk'.buildPackage { - pname = example; - cargoBuildOptions = - x: - x - ++ [ - "--package" - package - ]; - src = ./.; - inherit nativeBuildInputs buildInputs; - strictDeps = true; - gitSubmodules = true; - overrideMain = old: { - preConfigure = '' - cargo_build_options="$cargo_build_options --example ${example} ${ - if features == "" then "" else "--features " + features - }" - ''; - }; - }; - makePackage = - package: - let - package-param = [ - "--package" - package - ]; - in - naersk'.buildPackage { - pname = package; - cargoBuildOptions = x: x ++ package-param; - cargoTestOptions = x: x ++ package-param; - src = ./.; - doCheck = true; - strictDeps = true; - inherit nativeBuildInputs buildInputs; - }; - in - rec { - servicepoint = makePackage "servicepoint"; - announce = makeExample { - package = "servicepoint"; - example = "announce"; - }; - game-of-life = makeExample { - package = "servicepoint"; - example = "game_of_life"; - features = "rand"; - }; - moving-line = makeExample { - package = "servicepoint"; - example = "moving_line"; - }; - random-brightness = makeExample { - package = "servicepoint"; - example = "random_brightness"; - features = "rand"; - }; - wiping-clear = makeExample { - package = "servicepoint"; - example = "wiping_clear"; - }; - } - ); - - legacyPackages = packages; - + { devShells = forAllSystems ( { pkgs, system }: { - default = pkgs.mkShell rec { - inputsFrom = [ self.packages.${system}.servicepoint ]; + default = pkgs.mkShell { packages = with pkgs; [ - (pkgs.symlinkJoin - { + (pkgs.symlinkJoin { name = "rust-toolchain"; paths = with pkgs; [ rustc @@ -140,11 +47,10 @@ ]; }) ruby - dotnet-sdk_8 - gcc - gnumake + xe + xz + pkg-config ]; - LD_LIBRARY_PATH = "${pkgs.lib.makeLibraryPath (builtins.concatMap (d: d.buildInputs) inputsFrom)}"; RUST_SRC_PATH = "${pkgs.rust.packages.stable.rustPlatform.rustLibSrc}"; }; } diff --git a/generate-binding.sh b/generate-binding.sh new file mode 100755 index 0000000..1d8b2fb --- /dev/null +++ b/generate-binding.sh @@ -0,0 +1,14 @@ +#!/usr/bin/env bash +set -e + +SCRIPT_PATH="$( cd -- "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P )" + +cd "$SCRIPT_PATH" +cargo build --release + +TARGET_PATH="$(realpath "$SCRIPT_PATH"/target/release)" +SERVICEPOINT_SO="$TARGET_PATH/libservicepoint_binding_uniffi.so" + +echo "Source: $SERVICEPOINT_SO" + +"$TARGET_PATH/uniffi-bindgen" generate --library "$SERVICEPOINT_SO" --language ruby --out-dir "$SCRIPT_PATH/lib" diff --git a/crates/servicepoint_binding_uniffi/libraries/ruby/lib/servicepoint_binding_uniffi.rb b/lib/servicepoint_binding_uniffi.rb similarity index 100% rename from crates/servicepoint_binding_uniffi/libraries/ruby/lib/servicepoint_binding_uniffi.rb rename to lib/servicepoint_binding_uniffi.rb diff --git a/servicepoint-binding-uniffi b/servicepoint-binding-uniffi new file mode 160000 index 0000000..1169d9f --- /dev/null +++ b/servicepoint-binding-uniffi @@ -0,0 +1 @@ +Subproject commit 1169d9f1d294268f699e9c4e088cb1d97d6c36ce diff --git a/crates/servicepoint_binding_uniffi/libraries/ruby/servicepoint.gemspec b/servicepoint.gemspec similarity index 100% rename from crates/servicepoint_binding_uniffi/libraries/ruby/servicepoint.gemspec rename to servicepoint.gemspec diff --git a/uniffi-bindgen/Cargo.toml b/uniffi-bindgen/Cargo.toml new file mode 100644 index 0000000..94f495b --- /dev/null +++ b/uniffi-bindgen/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "uniffi-bindgen" +publish = false +edition = "2021" +license = "GPL-3.0-or-later" +description = "C bindings for the servicepoint crate." +homepage = "https://git.berlin.ccc.de/servicepoint/servicepoint-binding-ruby" +repository = "https://git.berlin.ccc.de/servicepoint/servicepoint-binding-ruby.git" +#readme = "README.md" +keywords = ["cccb", "cccb-servicepoint", "uniffi"] + +[build-dependencies] +uniffi = { version = "0.25.3", features = ["build"] } + +[dependencies] +uniffi = { version = "0.25.3", features = ["cli"] } +thiserror = "2.0" diff --git a/crates/servicepoint_binding_uniffi/src/bin/uniffi-bindgen.rs b/uniffi-bindgen/src/main.rs similarity index 100% rename from crates/servicepoint_binding_uniffi/src/bin/uniffi-bindgen.rs rename to uniffi-bindgen/src/main.rs