a bunch of minor changes combined:
- From instead of Into - unsafe_data_ref for other payloads - CByteSlice for returning memory spans - send Packet instead of Into<Packet> - expose packet layer to C/C#
This commit is contained in:
		
							parent
							
								
									5803b71f3a
								
							
						
					
					
						commit
						1dad113ca1
					
				
					 33 changed files with 462 additions and 733 deletions
				
			
		
							
								
								
									
										11
									
								
								Cargo.toml
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								Cargo.toml
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,11 @@
 | 
				
			||||||
 | 
					[workspace]
 | 
				
			||||||
 | 
					resolver = "2"
 | 
				
			||||||
 | 
					members = [
 | 
				
			||||||
 | 
					    "servicepoint2",
 | 
				
			||||||
 | 
					    "servicepoint2-binding-cs",
 | 
				
			||||||
 | 
					    "examples/announce",
 | 
				
			||||||
 | 
					    "examples/game_of_life",
 | 
				
			||||||
 | 
					    "examples/moving_line",
 | 
				
			||||||
 | 
					    "examples/wiping_clear",
 | 
				
			||||||
 | 
					    "examples/random_brightness"
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
| 
						 | 
					@ -49,6 +49,7 @@ Uses C bindings internally to provide a similar API to rust. Things to keep in m
 | 
				
			||||||
- C# specifics are documented in the library. Use the rust documentation for everything else. Naming and semantics are the same apart from CamelCase instead of kebap_case.
 | 
					- C# specifics are documented in the library. Use the rust documentation for everything else. Naming and semantics are the same apart from CamelCase instead of kebap_case.
 | 
				
			||||||
- You will only get rust backtraces in debug builds of the native code.
 | 
					- You will only get rust backtraces in debug builds of the native code.
 | 
				
			||||||
- F# is not explicitly tested. If there are usability or functionality problems, please open an issue.
 | 
					- F# is not explicitly tested. If there are usability or functionality problems, please open an issue.
 | 
				
			||||||
 | 
					- Reading and writing to instances concurrently is not safe. Only reading concurrently is safe.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
```csharp
 | 
					```csharp
 | 
				
			||||||
using ServicePoint2;
 | 
					using ServicePoint2;
 | 
				
			||||||
| 
						 | 
					@ -79,6 +80,7 @@ The lowest common denominator. Things to keep in mind:
 | 
				
			||||||
- Instances get consumed in the same way they do when writing rust / C# code. Do not use an instance after an (implicit!) free.
 | 
					- Instances get consumed in the same way they do when writing rust / C# code. Do not use an instance after an (implicit!) free.
 | 
				
			||||||
- Option<T> or Result<T, E> turn into nullable return values - check for NULL!
 | 
					- Option<T> or Result<T, E> 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.
 | 
					- 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.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
```c++
 | 
					```c++
 | 
				
			||||||
#include <stdio.h>
 | 
					#include <stdio.h>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										567
									
								
								examples/Cargo.lock
									
										
									
										generated
									
									
									
								
							
							
						
						
									
										567
									
								
								examples/Cargo.lock
									
										
									
										generated
									
									
									
								
							| 
						 | 
					@ -1,567 +0,0 @@
 | 
				
			||||||
# This file is automatically @generated by Cargo.
 | 
					 | 
				
			||||||
# It is not intended for manual editing.
 | 
					 | 
				
			||||||
version = 3
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
[[package]]
 | 
					 | 
				
			||||||
name = "adler"
 | 
					 | 
				
			||||||
version = "1.0.2"
 | 
					 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					 | 
				
			||||||
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
[[package]]
 | 
					 | 
				
			||||||
name = "aho-corasick"
 | 
					 | 
				
			||||||
version = "1.1.3"
 | 
					 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					 | 
				
			||||||
checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916"
 | 
					 | 
				
			||||||
dependencies = [
 | 
					 | 
				
			||||||
 "memchr",
 | 
					 | 
				
			||||||
]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
[[package]]
 | 
					 | 
				
			||||||
name = "announce"
 | 
					 | 
				
			||||||
version = "0.1.0"
 | 
					 | 
				
			||||||
dependencies = [
 | 
					 | 
				
			||||||
 "clap",
 | 
					 | 
				
			||||||
 "env_logger",
 | 
					 | 
				
			||||||
 "servicepoint2",
 | 
					 | 
				
			||||||
]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
[[package]]
 | 
					 | 
				
			||||||
name = "anstream"
 | 
					 | 
				
			||||||
version = "0.6.14"
 | 
					 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					 | 
				
			||||||
checksum = "418c75fa768af9c03be99d17643f93f79bbba589895012a80e3452a19ddda15b"
 | 
					 | 
				
			||||||
dependencies = [
 | 
					 | 
				
			||||||
 "anstyle",
 | 
					 | 
				
			||||||
 "anstyle-parse",
 | 
					 | 
				
			||||||
 "anstyle-query",
 | 
					 | 
				
			||||||
 "anstyle-wincon",
 | 
					 | 
				
			||||||
 "colorchoice",
 | 
					 | 
				
			||||||
 "is_terminal_polyfill",
 | 
					 | 
				
			||||||
 "utf8parse",
 | 
					 | 
				
			||||||
]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
[[package]]
 | 
					 | 
				
			||||||
name = "anstyle"
 | 
					 | 
				
			||||||
version = "1.0.7"
 | 
					 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					 | 
				
			||||||
checksum = "038dfcf04a5feb68e9c60b21c9625a54c2c0616e79b72b0fd87075a056ae1d1b"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
[[package]]
 | 
					 | 
				
			||||||
name = "anstyle-parse"
 | 
					 | 
				
			||||||
version = "0.2.4"
 | 
					 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					 | 
				
			||||||
checksum = "c03a11a9034d92058ceb6ee011ce58af4a9bf61491aa7e1e59ecd24bd40d22d4"
 | 
					 | 
				
			||||||
dependencies = [
 | 
					 | 
				
			||||||
 "utf8parse",
 | 
					 | 
				
			||||||
]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
[[package]]
 | 
					 | 
				
			||||||
name = "anstyle-query"
 | 
					 | 
				
			||||||
version = "1.0.3"
 | 
					 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					 | 
				
			||||||
checksum = "a64c907d4e79225ac72e2a354c9ce84d50ebb4586dee56c82b3ee73004f537f5"
 | 
					 | 
				
			||||||
dependencies = [
 | 
					 | 
				
			||||||
 "windows-sys",
 | 
					 | 
				
			||||||
]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
[[package]]
 | 
					 | 
				
			||||||
name = "anstyle-wincon"
 | 
					 | 
				
			||||||
version = "3.0.3"
 | 
					 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					 | 
				
			||||||
checksum = "61a38449feb7068f52bb06c12759005cf459ee52bb4adc1d5a7c4322d716fb19"
 | 
					 | 
				
			||||||
dependencies = [
 | 
					 | 
				
			||||||
 "anstyle",
 | 
					 | 
				
			||||||
 "windows-sys",
 | 
					 | 
				
			||||||
]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
[[package]]
 | 
					 | 
				
			||||||
name = "bzip2"
 | 
					 | 
				
			||||||
version = "0.4.4"
 | 
					 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					 | 
				
			||||||
checksum = "bdb116a6ef3f6c3698828873ad02c3014b3c85cadb88496095628e3ef1e347f8"
 | 
					 | 
				
			||||||
dependencies = [
 | 
					 | 
				
			||||||
 "bzip2-sys",
 | 
					 | 
				
			||||||
 "libc",
 | 
					 | 
				
			||||||
]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
[[package]]
 | 
					 | 
				
			||||||
name = "bzip2-sys"
 | 
					 | 
				
			||||||
version = "0.1.11+1.0.8"
 | 
					 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					 | 
				
			||||||
checksum = "736a955f3fa7875102d57c82b8cac37ec45224a07fd32d58f9f7a186b6cd4cdc"
 | 
					 | 
				
			||||||
dependencies = [
 | 
					 | 
				
			||||||
 "cc",
 | 
					 | 
				
			||||||
 "libc",
 | 
					 | 
				
			||||||
 "pkg-config",
 | 
					 | 
				
			||||||
]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
[[package]]
 | 
					 | 
				
			||||||
name = "cc"
 | 
					 | 
				
			||||||
version = "1.0.97"
 | 
					 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					 | 
				
			||||||
checksum = "099a5357d84c4c61eb35fc8eafa9a79a902c2f76911e5747ced4e032edd8d9b4"
 | 
					 | 
				
			||||||
dependencies = [
 | 
					 | 
				
			||||||
 "jobserver",
 | 
					 | 
				
			||||||
 "libc",
 | 
					 | 
				
			||||||
 "once_cell",
 | 
					 | 
				
			||||||
]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
[[package]]
 | 
					 | 
				
			||||||
name = "cfg-if"
 | 
					 | 
				
			||||||
version = "1.0.0"
 | 
					 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					 | 
				
			||||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
[[package]]
 | 
					 | 
				
			||||||
name = "clap"
 | 
					 | 
				
			||||||
version = "4.5.4"
 | 
					 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					 | 
				
			||||||
checksum = "90bc066a67923782aa8515dbaea16946c5bcc5addbd668bb80af688e53e548a0"
 | 
					 | 
				
			||||||
dependencies = [
 | 
					 | 
				
			||||||
 "clap_builder",
 | 
					 | 
				
			||||||
 "clap_derive",
 | 
					 | 
				
			||||||
]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
[[package]]
 | 
					 | 
				
			||||||
name = "clap_builder"
 | 
					 | 
				
			||||||
version = "4.5.2"
 | 
					 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					 | 
				
			||||||
checksum = "ae129e2e766ae0ec03484e609954119f123cc1fe650337e155d03b022f24f7b4"
 | 
					 | 
				
			||||||
dependencies = [
 | 
					 | 
				
			||||||
 "anstream",
 | 
					 | 
				
			||||||
 "anstyle",
 | 
					 | 
				
			||||||
 "clap_lex",
 | 
					 | 
				
			||||||
 "strsim",
 | 
					 | 
				
			||||||
]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
[[package]]
 | 
					 | 
				
			||||||
name = "clap_derive"
 | 
					 | 
				
			||||||
version = "4.5.4"
 | 
					 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					 | 
				
			||||||
checksum = "528131438037fd55894f62d6e9f068b8f45ac57ffa77517819645d10aed04f64"
 | 
					 | 
				
			||||||
dependencies = [
 | 
					 | 
				
			||||||
 "heck",
 | 
					 | 
				
			||||||
 "proc-macro2",
 | 
					 | 
				
			||||||
 "quote",
 | 
					 | 
				
			||||||
 "syn",
 | 
					 | 
				
			||||||
]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
[[package]]
 | 
					 | 
				
			||||||
name = "clap_lex"
 | 
					 | 
				
			||||||
version = "0.7.0"
 | 
					 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					 | 
				
			||||||
checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
[[package]]
 | 
					 | 
				
			||||||
name = "colorchoice"
 | 
					 | 
				
			||||||
version = "1.0.1"
 | 
					 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					 | 
				
			||||||
checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
[[package]]
 | 
					 | 
				
			||||||
name = "crc32fast"
 | 
					 | 
				
			||||||
version = "1.4.0"
 | 
					 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					 | 
				
			||||||
checksum = "b3855a8a784b474f333699ef2bbca9db2c4a1f6d9088a90a2d25b1eb53111eaa"
 | 
					 | 
				
			||||||
dependencies = [
 | 
					 | 
				
			||||||
 "cfg-if",
 | 
					 | 
				
			||||||
]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
[[package]]
 | 
					 | 
				
			||||||
name = "env_filter"
 | 
					 | 
				
			||||||
version = "0.1.0"
 | 
					 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					 | 
				
			||||||
checksum = "a009aa4810eb158359dda09d0c87378e4bbb89b5a801f016885a4707ba24f7ea"
 | 
					 | 
				
			||||||
dependencies = [
 | 
					 | 
				
			||||||
 "log",
 | 
					 | 
				
			||||||
 "regex",
 | 
					 | 
				
			||||||
]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
[[package]]
 | 
					 | 
				
			||||||
name = "env_logger"
 | 
					 | 
				
			||||||
version = "0.11.3"
 | 
					 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					 | 
				
			||||||
checksum = "38b35839ba51819680ba087cd351788c9a3c476841207e0b8cee0b04722343b9"
 | 
					 | 
				
			||||||
dependencies = [
 | 
					 | 
				
			||||||
 "anstream",
 | 
					 | 
				
			||||||
 "anstyle",
 | 
					 | 
				
			||||||
 "env_filter",
 | 
					 | 
				
			||||||
 "humantime",
 | 
					 | 
				
			||||||
 "log",
 | 
					 | 
				
			||||||
]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
[[package]]
 | 
					 | 
				
			||||||
name = "flate2"
 | 
					 | 
				
			||||||
version = "1.0.30"
 | 
					 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					 | 
				
			||||||
checksum = "5f54427cfd1c7829e2a139fcefea601bf088ebca651d2bf53ebc600eac295dae"
 | 
					 | 
				
			||||||
dependencies = [
 | 
					 | 
				
			||||||
 "crc32fast",
 | 
					 | 
				
			||||||
 "miniz_oxide",
 | 
					 | 
				
			||||||
]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
[[package]]
 | 
					 | 
				
			||||||
name = "game_of_life"
 | 
					 | 
				
			||||||
version = "0.1.0"
 | 
					 | 
				
			||||||
dependencies = [
 | 
					 | 
				
			||||||
 "clap",
 | 
					 | 
				
			||||||
 "env_logger",
 | 
					 | 
				
			||||||
 "rand",
 | 
					 | 
				
			||||||
 "servicepoint2",
 | 
					 | 
				
			||||||
]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
[[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 = "heck"
 | 
					 | 
				
			||||||
version = "0.5.0"
 | 
					 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					 | 
				
			||||||
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
[[package]]
 | 
					 | 
				
			||||||
name = "humantime"
 | 
					 | 
				
			||||||
version = "2.1.0"
 | 
					 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					 | 
				
			||||||
checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
[[package]]
 | 
					 | 
				
			||||||
name = "is_terminal_polyfill"
 | 
					 | 
				
			||||||
version = "1.70.0"
 | 
					 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					 | 
				
			||||||
checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
[[package]]
 | 
					 | 
				
			||||||
name = "jobserver"
 | 
					 | 
				
			||||||
version = "0.1.31"
 | 
					 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					 | 
				
			||||||
checksum = "d2b099aaa34a9751c5bf0878add70444e1ed2dd73f347be99003d4577277de6e"
 | 
					 | 
				
			||||||
dependencies = [
 | 
					 | 
				
			||||||
 "libc",
 | 
					 | 
				
			||||||
]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
[[package]]
 | 
					 | 
				
			||||||
name = "libc"
 | 
					 | 
				
			||||||
version = "0.2.154"
 | 
					 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					 | 
				
			||||||
checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
[[package]]
 | 
					 | 
				
			||||||
name = "log"
 | 
					 | 
				
			||||||
version = "0.4.21"
 | 
					 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					 | 
				
			||||||
checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
[[package]]
 | 
					 | 
				
			||||||
name = "lz4"
 | 
					 | 
				
			||||||
version = "1.24.0"
 | 
					 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					 | 
				
			||||||
checksum = "7e9e2dd86df36ce760a60f6ff6ad526f7ba1f14ba0356f8254fb6905e6494df1"
 | 
					 | 
				
			||||||
dependencies = [
 | 
					 | 
				
			||||||
 "libc",
 | 
					 | 
				
			||||||
 "lz4-sys",
 | 
					 | 
				
			||||||
]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
[[package]]
 | 
					 | 
				
			||||||
name = "lz4-sys"
 | 
					 | 
				
			||||||
version = "1.9.4"
 | 
					 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					 | 
				
			||||||
checksum = "57d27b317e207b10f69f5e75494119e391a96f48861ae870d1da6edac98ca900"
 | 
					 | 
				
			||||||
dependencies = [
 | 
					 | 
				
			||||||
 "cc",
 | 
					 | 
				
			||||||
 "libc",
 | 
					 | 
				
			||||||
]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
[[package]]
 | 
					 | 
				
			||||||
name = "memchr"
 | 
					 | 
				
			||||||
version = "2.7.2"
 | 
					 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					 | 
				
			||||||
checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
[[package]]
 | 
					 | 
				
			||||||
name = "miniz_oxide"
 | 
					 | 
				
			||||||
version = "0.7.2"
 | 
					 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					 | 
				
			||||||
checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7"
 | 
					 | 
				
			||||||
dependencies = [
 | 
					 | 
				
			||||||
 "adler",
 | 
					 | 
				
			||||||
]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
[[package]]
 | 
					 | 
				
			||||||
name = "moving_line"
 | 
					 | 
				
			||||||
version = "0.1.0"
 | 
					 | 
				
			||||||
dependencies = [
 | 
					 | 
				
			||||||
 "clap",
 | 
					 | 
				
			||||||
 "env_logger",
 | 
					 | 
				
			||||||
 "servicepoint2",
 | 
					 | 
				
			||||||
]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
[[package]]
 | 
					 | 
				
			||||||
name = "once_cell"
 | 
					 | 
				
			||||||
version = "1.19.0"
 | 
					 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					 | 
				
			||||||
checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
[[package]]
 | 
					 | 
				
			||||||
name = "pkg-config"
 | 
					 | 
				
			||||||
version = "0.3.30"
 | 
					 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					 | 
				
			||||||
checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
[[package]]
 | 
					 | 
				
			||||||
name = "ppv-lite86"
 | 
					 | 
				
			||||||
version = "0.2.17"
 | 
					 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					 | 
				
			||||||
checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
[[package]]
 | 
					 | 
				
			||||||
name = "proc-macro2"
 | 
					 | 
				
			||||||
version = "1.0.82"
 | 
					 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					 | 
				
			||||||
checksum = "8ad3d49ab951a01fbaafe34f2ec74122942fe18a3f9814c3268f1bb72042131b"
 | 
					 | 
				
			||||||
dependencies = [
 | 
					 | 
				
			||||||
 "unicode-ident",
 | 
					 | 
				
			||||||
]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
[[package]]
 | 
					 | 
				
			||||||
name = "quote"
 | 
					 | 
				
			||||||
version = "1.0.36"
 | 
					 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					 | 
				
			||||||
checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7"
 | 
					 | 
				
			||||||
dependencies = [
 | 
					 | 
				
			||||||
 "proc-macro2",
 | 
					 | 
				
			||||||
]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
[[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 = "random_brightness"
 | 
					 | 
				
			||||||
version = "0.1.0"
 | 
					 | 
				
			||||||
dependencies = [
 | 
					 | 
				
			||||||
 "clap",
 | 
					 | 
				
			||||||
 "env_logger",
 | 
					 | 
				
			||||||
 "rand",
 | 
					 | 
				
			||||||
 "servicepoint2",
 | 
					 | 
				
			||||||
]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
[[package]]
 | 
					 | 
				
			||||||
name = "regex"
 | 
					 | 
				
			||||||
version = "1.10.4"
 | 
					 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					 | 
				
			||||||
checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c"
 | 
					 | 
				
			||||||
dependencies = [
 | 
					 | 
				
			||||||
 "aho-corasick",
 | 
					 | 
				
			||||||
 "memchr",
 | 
					 | 
				
			||||||
 "regex-automata",
 | 
					 | 
				
			||||||
 "regex-syntax",
 | 
					 | 
				
			||||||
]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
[[package]]
 | 
					 | 
				
			||||||
name = "regex-automata"
 | 
					 | 
				
			||||||
version = "0.4.6"
 | 
					 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					 | 
				
			||||||
checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea"
 | 
					 | 
				
			||||||
dependencies = [
 | 
					 | 
				
			||||||
 "aho-corasick",
 | 
					 | 
				
			||||||
 "memchr",
 | 
					 | 
				
			||||||
 "regex-syntax",
 | 
					 | 
				
			||||||
]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
[[package]]
 | 
					 | 
				
			||||||
name = "regex-syntax"
 | 
					 | 
				
			||||||
version = "0.8.3"
 | 
					 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					 | 
				
			||||||
checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
[[package]]
 | 
					 | 
				
			||||||
name = "servicepoint2"
 | 
					 | 
				
			||||||
version = "0.2.0"
 | 
					 | 
				
			||||||
dependencies = [
 | 
					 | 
				
			||||||
 "bzip2",
 | 
					 | 
				
			||||||
 "flate2",
 | 
					 | 
				
			||||||
 "log",
 | 
					 | 
				
			||||||
 "lz4",
 | 
					 | 
				
			||||||
 "zstd",
 | 
					 | 
				
			||||||
]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
[[package]]
 | 
					 | 
				
			||||||
name = "strsim"
 | 
					 | 
				
			||||||
version = "0.11.1"
 | 
					 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					 | 
				
			||||||
checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
[[package]]
 | 
					 | 
				
			||||||
name = "syn"
 | 
					 | 
				
			||||||
version = "2.0.63"
 | 
					 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					 | 
				
			||||||
checksum = "bf5be731623ca1a1fb7d8be6f261a3be6d3e2337b8a1f97be944d020c8fcb704"
 | 
					 | 
				
			||||||
dependencies = [
 | 
					 | 
				
			||||||
 "proc-macro2",
 | 
					 | 
				
			||||||
 "quote",
 | 
					 | 
				
			||||||
 "unicode-ident",
 | 
					 | 
				
			||||||
]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
[[package]]
 | 
					 | 
				
			||||||
name = "unicode-ident"
 | 
					 | 
				
			||||||
version = "1.0.12"
 | 
					 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					 | 
				
			||||||
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
[[package]]
 | 
					 | 
				
			||||||
name = "utf8parse"
 | 
					 | 
				
			||||||
version = "0.2.1"
 | 
					 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					 | 
				
			||||||
checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
[[package]]
 | 
					 | 
				
			||||||
name = "wasi"
 | 
					 | 
				
			||||||
version = "0.11.0+wasi-snapshot-preview1"
 | 
					 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					 | 
				
			||||||
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
[[package]]
 | 
					 | 
				
			||||||
name = "windows-sys"
 | 
					 | 
				
			||||||
version = "0.52.0"
 | 
					 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					 | 
				
			||||||
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
 | 
					 | 
				
			||||||
dependencies = [
 | 
					 | 
				
			||||||
 "windows-targets",
 | 
					 | 
				
			||||||
]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
[[package]]
 | 
					 | 
				
			||||||
name = "windows-targets"
 | 
					 | 
				
			||||||
version = "0.52.5"
 | 
					 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					 | 
				
			||||||
checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb"
 | 
					 | 
				
			||||||
dependencies = [
 | 
					 | 
				
			||||||
 "windows_aarch64_gnullvm",
 | 
					 | 
				
			||||||
 "windows_aarch64_msvc",
 | 
					 | 
				
			||||||
 "windows_i686_gnu",
 | 
					 | 
				
			||||||
 "windows_i686_gnullvm",
 | 
					 | 
				
			||||||
 "windows_i686_msvc",
 | 
					 | 
				
			||||||
 "windows_x86_64_gnu",
 | 
					 | 
				
			||||||
 "windows_x86_64_gnullvm",
 | 
					 | 
				
			||||||
 "windows_x86_64_msvc",
 | 
					 | 
				
			||||||
]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
[[package]]
 | 
					 | 
				
			||||||
name = "windows_aarch64_gnullvm"
 | 
					 | 
				
			||||||
version = "0.52.5"
 | 
					 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					 | 
				
			||||||
checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
[[package]]
 | 
					 | 
				
			||||||
name = "windows_aarch64_msvc"
 | 
					 | 
				
			||||||
version = "0.52.5"
 | 
					 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					 | 
				
			||||||
checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
[[package]]
 | 
					 | 
				
			||||||
name = "windows_i686_gnu"
 | 
					 | 
				
			||||||
version = "0.52.5"
 | 
					 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					 | 
				
			||||||
checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
[[package]]
 | 
					 | 
				
			||||||
name = "windows_i686_gnullvm"
 | 
					 | 
				
			||||||
version = "0.52.5"
 | 
					 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					 | 
				
			||||||
checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
[[package]]
 | 
					 | 
				
			||||||
name = "windows_i686_msvc"
 | 
					 | 
				
			||||||
version = "0.52.5"
 | 
					 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					 | 
				
			||||||
checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
[[package]]
 | 
					 | 
				
			||||||
name = "windows_x86_64_gnu"
 | 
					 | 
				
			||||||
version = "0.52.5"
 | 
					 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					 | 
				
			||||||
checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
[[package]]
 | 
					 | 
				
			||||||
name = "windows_x86_64_gnullvm"
 | 
					 | 
				
			||||||
version = "0.52.5"
 | 
					 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					 | 
				
			||||||
checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
[[package]]
 | 
					 | 
				
			||||||
name = "windows_x86_64_msvc"
 | 
					 | 
				
			||||||
version = "0.52.5"
 | 
					 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					 | 
				
			||||||
checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
[[package]]
 | 
					 | 
				
			||||||
name = "wiping_clear"
 | 
					 | 
				
			||||||
version = "0.1.0"
 | 
					 | 
				
			||||||
dependencies = [
 | 
					 | 
				
			||||||
 "clap",
 | 
					 | 
				
			||||||
 "env_logger",
 | 
					 | 
				
			||||||
 "servicepoint2",
 | 
					 | 
				
			||||||
]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
[[package]]
 | 
					 | 
				
			||||||
name = "zstd"
 | 
					 | 
				
			||||||
version = "0.13.1"
 | 
					 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					 | 
				
			||||||
checksum = "2d789b1514203a1120ad2429eae43a7bd32b90976a7bb8a05f7ec02fa88cc23a"
 | 
					 | 
				
			||||||
dependencies = [
 | 
					 | 
				
			||||||
 "zstd-safe",
 | 
					 | 
				
			||||||
]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
[[package]]
 | 
					 | 
				
			||||||
name = "zstd-safe"
 | 
					 | 
				
			||||||
version = "7.1.0"
 | 
					 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					 | 
				
			||||||
checksum = "1cd99b45c6bc03a018c8b8a86025678c87e55526064e38f9df301989dce7ec0a"
 | 
					 | 
				
			||||||
dependencies = [
 | 
					 | 
				
			||||||
 "zstd-sys",
 | 
					 | 
				
			||||||
]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
[[package]]
 | 
					 | 
				
			||||||
name = "zstd-sys"
 | 
					 | 
				
			||||||
version = "2.0.10+zstd.1.5.6"
 | 
					 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					 | 
				
			||||||
checksum = "c253a4914af5bafc8fa8c86ee400827e83cf6ec01195ec1f1ed8441bf00d65aa"
 | 
					 | 
				
			||||||
dependencies = [
 | 
					 | 
				
			||||||
 "cc",
 | 
					 | 
				
			||||||
 "pkg-config",
 | 
					 | 
				
			||||||
]
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,9 +0,0 @@
 | 
				
			||||||
[workspace]
 | 
					 | 
				
			||||||
resolver = "2"
 | 
					 | 
				
			||||||
members = [
 | 
					 | 
				
			||||||
    "announce",
 | 
					 | 
				
			||||||
    "game_of_life",
 | 
					 | 
				
			||||||
    "moving_line",
 | 
					 | 
				
			||||||
    "wiping_clear",
 | 
					 | 
				
			||||||
    "random_brightness"
 | 
					 | 
				
			||||||
]
 | 
					 | 
				
			||||||
| 
						 | 
					@ -20,7 +20,7 @@ fn main() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let connection = Connection::open(&cli.destination).unwrap();
 | 
					    let connection = Connection::open(&cli.destination).unwrap();
 | 
				
			||||||
    if cli.clear {
 | 
					    if cli.clear {
 | 
				
			||||||
        connection.send(Command::Clear).unwrap();
 | 
					        connection.send(Command::Clear.into()).unwrap();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let mut max_width = 0;
 | 
					    let mut max_width = 0;
 | 
				
			||||||
| 
						 | 
					@ -43,6 +43,6 @@ fn main() {
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    connection
 | 
					    connection
 | 
				
			||||||
        .send(Command::Cp437Data(Origin::top_left(), chars))
 | 
					        .send(Command::Cp437Data(Origin::top_left(), chars).into())
 | 
				
			||||||
        .unwrap();
 | 
					        .unwrap();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -23,7 +23,7 @@ fn main() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    loop {
 | 
					    loop {
 | 
				
			||||||
        connection
 | 
					        connection
 | 
				
			||||||
            .send(Command::BitmapLinearWin(Origin::top_left(), field.clone()))
 | 
					            .send(Command::BitmapLinearWin(Origin::top_left(), field.clone()).into())
 | 
				
			||||||
            .expect("could not send");
 | 
					            .expect("could not send");
 | 
				
			||||||
        thread::sleep(Duration::from_millis(14));
 | 
					        thread::sleep(Duration::from_millis(14));
 | 
				
			||||||
        field = iteration(field);
 | 
					        field = iteration(field);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3,11 +3,11 @@ OUT_DIR := ${ROOT_DIR}/out
 | 
				
			||||||
 | 
					
 | 
				
			||||||
SP2_DIR := ${ROOT_DIR}/../../servicepoint2
 | 
					SP2_DIR := ${ROOT_DIR}/../../servicepoint2
 | 
				
			||||||
SP2_INCLUDE := ${ROOT_DIR}/../../servicepoint2-binding-c
 | 
					SP2_INCLUDE := ${ROOT_DIR}/../../servicepoint2-binding-c
 | 
				
			||||||
SP2_TARGET_RELEASE := ${ROOT_DIR}/../../target/release
 | 
					SP2_TARGET_RELEASE := ${SP2_DIR}/target/release
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.PHONY: build run clean
 | 
					.PHONY: build run clean
 | 
				
			||||||
 | 
					
 | 
				
			||||||
build: ${OUT_DIR}/lang_c
 | 
					all: ${OUT_DIR}/lang_c
 | 
				
			||||||
 | 
					
 | 
				
			||||||
run: ${OUT_DIR}/lang_c
 | 
					run: ${OUT_DIR}/lang_c
 | 
				
			||||||
	out/lang_c
 | 
						out/lang_c
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -8,11 +8,11 @@ int main(void) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    sp2_PixelGrid *pixels = sp2_pixel_grid_new(sp2_PIXEL_WIDTH, sp2_PIXEL_HEIGHT);
 | 
					    sp2_PixelGrid *pixels = sp2_pixel_grid_new(sp2_PIXEL_WIDTH, sp2_PIXEL_HEIGHT);
 | 
				
			||||||
    sp2_pixel_grid_fill(pixels, true);
 | 
					    sp2_pixel_grid_fill(pixels, true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    sp2_Command *command = sp2_command_bitmap_linear_win(0, 0, pixels);
 | 
					    sp2_Command *command = sp2_command_bitmap_linear_win(0, 0, pixels);
 | 
				
			||||||
    if (command == NULL)
 | 
					    sp2_Packet *packet = sp2_packet_from_command(command);
 | 
				
			||||||
        return 4;
 | 
					    if (!sp2_connection_send(connection, packet))
 | 
				
			||||||
    if (!sp2_connection_send(connection, command))
 | 
					        return 1;
 | 
				
			||||||
        return 5;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    sp2_connection_dealloc(connection);
 | 
					    sp2_connection_dealloc(connection);
 | 
				
			||||||
    return 0;
 | 
					    return 0;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2,8 +2,8 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
using var connection = Connection.Open("127.0.0.1:2342");
 | 
					using var connection = Connection.Open("127.0.0.1:2342");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
connection.Send(Command.Clear());
 | 
					connection.Send(Command.Clear().IntoPacket());
 | 
				
			||||||
connection.Send(Command.Brightness(128));
 | 
					connection.Send(Command.Brightness(128).IntoPacket());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
using var pixels = PixelGrid.New(Constants.PixelWidth, Constants.PixelHeight);
 | 
					using var pixels = PixelGrid.New(Constants.PixelWidth, Constants.PixelHeight);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -14,6 +14,6 @@ for (var offset = 0; offset < int.MaxValue; offset++)
 | 
				
			||||||
    for (var y = 0; y < pixels.Height; y++)
 | 
					    for (var y = 0; y < pixels.Height; y++)
 | 
				
			||||||
        pixels[(y + offset) % Constants.PixelWidth, y] = true;
 | 
					        pixels[(y + offset) % Constants.PixelWidth, y] = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    connection.Send(Command.BitmapLinearWin(0, 0, pixels.Clone()));
 | 
					    connection.Send(Command.BitmapLinearWin(0, 0, pixels.Clone()).IntoPacket());
 | 
				
			||||||
    Thread.Sleep(14);
 | 
					    Thread.Sleep(14);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -24,7 +24,7 @@ fn main() {
 | 
				
			||||||
            pixels.set((y + x_offset) % PIXEL_WIDTH as usize, y, true);
 | 
					            pixels.set((y + x_offset) % PIXEL_WIDTH as usize, y, true);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        connection
 | 
					        connection
 | 
				
			||||||
            .send(Command::BitmapLinearWin(Origin::top_left(), pixels.clone()))
 | 
					            .send(Command::BitmapLinearWin(Origin::top_left(), pixels.clone()).into())
 | 
				
			||||||
            .unwrap();
 | 
					            .unwrap();
 | 
				
			||||||
        thread::sleep(Duration::from_millis(14));
 | 
					        thread::sleep(Duration::from_millis(14));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -30,13 +30,13 @@ fn main() {
 | 
				
			||||||
        let mut filled_grid = PixelGrid::max_sized();
 | 
					        let mut filled_grid = PixelGrid::max_sized();
 | 
				
			||||||
        filled_grid.fill(true);
 | 
					        filled_grid.fill(true);
 | 
				
			||||||
        connection
 | 
					        connection
 | 
				
			||||||
            .send(BitmapLinearWin(Origin::top_left(), filled_grid))
 | 
					            .send(BitmapLinearWin(Origin::top_left(), filled_grid).into())
 | 
				
			||||||
            .unwrap();
 | 
					            .unwrap();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // set all pixels to the same random brightness
 | 
					    // set all pixels to the same random brightness
 | 
				
			||||||
    let mut rng = rand::thread_rng();
 | 
					    let mut rng = rand::thread_rng();
 | 
				
			||||||
    connection.send(Brightness(rng.gen())).unwrap();
 | 
					    connection.send(Brightness(rng.gen()).into()).unwrap();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // continuously update random windows to new random brightness
 | 
					    // continuously update random windows to new random brightness
 | 
				
			||||||
    loop {
 | 
					    loop {
 | 
				
			||||||
| 
						 | 
					@ -56,7 +56,7 @@ fn main() {
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        connection.send(CharBrightness(origin, luma)).unwrap();
 | 
					        connection.send(CharBrightness(origin, luma).into()).unwrap();
 | 
				
			||||||
        std::thread::sleep(wait_duration);
 | 
					        std::thread::sleep(wait_duration);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -36,7 +36,7 @@ fn main() {
 | 
				
			||||||
        let bit_vec = BitVec::from(&*pixel_data);
 | 
					        let bit_vec = BitVec::from(&*pixel_data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        connection
 | 
					        connection
 | 
				
			||||||
            .send(Command::BitmapLinearAnd(0, bit_vec, CompressionCode::Gz))
 | 
					            .send(Command::BitmapLinearAnd(0, bit_vec, CompressionCode::Gz).into())
 | 
				
			||||||
            .unwrap();
 | 
					            .unwrap();
 | 
				
			||||||
        thread::sleep(sleep_duration);
 | 
					        thread::sleep(sleep_duration);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -68,7 +68,7 @@ typedef uint16_t sp2_CompressionCode;
 | 
				
			||||||
typedef struct sp2_BitVec sp2_BitVec;
 | 
					typedef struct sp2_BitVec sp2_BitVec;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * A grid of bytes
 | 
					 * A 2D grid of bytes
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
typedef struct sp2_ByteGrid sp2_ByteGrid;
 | 
					typedef struct sp2_ByteGrid sp2_ByteGrid;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -82,13 +82,40 @@ typedef struct sp2_Command sp2_Command;
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
typedef struct sp2_Connection sp2_Connection;
 | 
					typedef struct sp2_Connection sp2_Connection;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * The raw packet. Should probably not be used directly.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					typedef struct sp2_Packet sp2_Packet;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * A grid of pixels stored in packed bytes.
 | 
					 * A grid of pixels stored in packed bytes.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
typedef struct sp2_PixelGrid sp2_PixelGrid;
 | 
					typedef struct sp2_PixelGrid sp2_PixelGrid;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Represents a `&mut [u8]` as a struct usable by C code.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Usage of this type is inherently unsafe.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					typedef struct sp2_CByteSlice {
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * The start address of the memory
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    uint8_t *start;
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * The amount of memory in bytes
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    size_t length;
 | 
				
			||||||
 | 
					} sp2_CByteSlice;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Type alias for documenting the meaning of the u16 in enum values
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
typedef uint16_t sp2_Offset;
 | 
					typedef uint16_t sp2_Offset;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Type alias for documenting the meaning of the u16 in enum values
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
typedef uint8_t sp2_Brightness;
 | 
					typedef uint8_t sp2_Brightness;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef __cplusplus
 | 
					#ifdef __cplusplus
 | 
				
			||||||
| 
						 | 
					@ -140,6 +167,19 @@ struct sp2_BitVec *sp2_bit_vec_new(size_t size);
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
bool sp2_bit_vec_set(struct sp2_BitVec *this_, size_t index, bool value);
 | 
					bool sp2_bit_vec_set(struct sp2_BitVec *this_, size_t index, bool value);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Gets an unsafe reference to the data of the `BitVec` instance.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * ## Safety
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * The caller has to make sure to never access the returned memory after the `BitVec`
 | 
				
			||||||
 | 
					 * instance has been consumed or manually deallocated.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Reading and writing concurrently to either the original instance or the returned data will
 | 
				
			||||||
 | 
					 * result in undefined behavior.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					struct sp2_CByteSlice sp2_bit_vec_unsafe_data_ref(struct sp2_BitVec *this_);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Clones a `ByteGrid`.
 | 
					 * Clones a `ByteGrid`.
 | 
				
			||||||
 * The returned instance has to be freed with `byte_grid_dealloc`.
 | 
					 * The returned instance has to be freed with `byte_grid_dealloc`.
 | 
				
			||||||
| 
						 | 
					@ -166,7 +206,7 @@ uint8_t sp2_byte_grid_get(const struct sp2_ByteGrid *this_, size_t x, size_t y);
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Gets the height in pixels of the `ByteGrid` instance.
 | 
					 * Gets the height in pixels of the `ByteGrid` instance.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
size_t sp2_byte_grid_height(const struct sp2_PixelGrid *this_);
 | 
					size_t sp2_byte_grid_height(const struct sp2_ByteGrid *this_);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Loads a `ByteGrid` with the specified dimensions from the provided data.
 | 
					 * Loads a `ByteGrid` with the specified dimensions from the provided data.
 | 
				
			||||||
| 
						 | 
					@ -191,10 +231,23 @@ void sp2_byte_grid_set(struct sp2_ByteGrid *this_,
 | 
				
			||||||
                       size_t y,
 | 
					                       size_t y,
 | 
				
			||||||
                       uint8_t value);
 | 
					                       uint8_t value);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Gets an unsafe reference to the data of the `ByteGrid` instance.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * ## Safety
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * The caller has to make sure to never access the returned memory after the `ByteGrid`
 | 
				
			||||||
 | 
					 * instance has been consumed or manually deallocated.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Reading and writing concurrently to either the original instance or the returned data will
 | 
				
			||||||
 | 
					 * result in undefined behavior.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					struct sp2_CByteSlice sp2_byte_grid_unsafe_data_ref(struct sp2_ByteGrid *this_);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Gets the width in pixels of the `ByteGrid` instance.
 | 
					 * Gets the width in pixels of the `ByteGrid` instance.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
size_t sp2_byte_grid_width(const struct sp2_PixelGrid *this_);
 | 
					size_t sp2_byte_grid_width(const struct sp2_ByteGrid *this_);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Allocates a new `Command::BitmapLinear` instance.
 | 
					 * Allocates a new `Command::BitmapLinear` instance.
 | 
				
			||||||
| 
						 | 
					@ -283,6 +336,13 @@ struct sp2_Command *sp2_command_fade_out(void);
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
struct sp2_Command *sp2_command_hard_reset(void);
 | 
					struct sp2_Command *sp2_command_hard_reset(void);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Tries to turn a `Packet` into a `Command`. The packet is gets deallocated in the process.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Returns: pointer to command or NULL
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					struct sp2_Command *sp2_command_try_from_packet(struct sp2_Packet *packet);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Tries to load a `Command` from the passed array with the specified length.
 | 
					 * Tries to load a `Command` from the passed array with the specified length.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
| 
						 | 
					@ -309,7 +369,12 @@ struct sp2_Connection *sp2_connection_open(const char *host);
 | 
				
			||||||
 * Sends the command instance. The instance is consumed / destroyed and cannot be used after this call.
 | 
					 * Sends the command instance. The instance is consumed / destroyed and cannot be used after this call.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
bool sp2_connection_send(const struct sp2_Connection *connection,
 | 
					bool sp2_connection_send(const struct sp2_Connection *connection,
 | 
				
			||||||
                         struct sp2_Command *command_ptr);
 | 
					                         struct sp2_Packet *command_ptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Turns a `Command` into a `Packet`. The command gets deallocated in the process.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					struct sp2_Packet *sp2_packet_from_command(struct sp2_Command *command);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Clones a `PixelGrid`.
 | 
					 * Clones a `PixelGrid`.
 | 
				
			||||||
| 
						 | 
					@ -362,6 +427,19 @@ void sp2_pixel_grid_set(struct sp2_PixelGrid *this_,
 | 
				
			||||||
                        size_t y,
 | 
					                        size_t y,
 | 
				
			||||||
                        bool value);
 | 
					                        bool value);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Gets an unsafe reference to the data of the `PixelGrid` instance.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * ## Safety
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * The caller has to make sure to never access the returned memory after the `PixelGrid`
 | 
				
			||||||
 | 
					 * instance has been consumed or manually deallocated.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Reading and writing concurrently to either the original instance or the returned data will
 | 
				
			||||||
 | 
					 * result in undefined behavior.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					struct sp2_CByteSlice sp2_pixel_grid_unsafe_data_ref(struct sp2_PixelGrid *this_);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Gets the width in pixels of the `PixelGrid` instance.
 | 
					 * Gets the width in pixels of the `PixelGrid` instance.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -8,6 +8,8 @@ fn main() {
 | 
				
			||||||
        .input_extern_file("../servicepoint2/src/connection.rs")
 | 
					        .input_extern_file("../servicepoint2/src/connection.rs")
 | 
				
			||||||
        .input_extern_file("../servicepoint2/src/pixel_grid.rs")
 | 
					        .input_extern_file("../servicepoint2/src/pixel_grid.rs")
 | 
				
			||||||
        .input_extern_file("../servicepoint2/src/lib.rs")
 | 
					        .input_extern_file("../servicepoint2/src/lib.rs")
 | 
				
			||||||
 | 
					        .input_extern_file("../servicepoint2/src/c_slice.rs")
 | 
				
			||||||
 | 
					        .input_extern_file("../servicepoint2/src/packet.rs")
 | 
				
			||||||
        .csharp_dll_name("servicepoint2")
 | 
					        .csharp_dll_name("servicepoint2")
 | 
				
			||||||
        .csharp_namespace("ServicePoint2.BindGen")
 | 
					        .csharp_namespace("ServicePoint2.BindGen")
 | 
				
			||||||
        .csharp_use_nint_types(true)
 | 
					        .csharp_use_nint_types(true)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -50,6 +50,10 @@ namespace ServicePoint2.BindGen
 | 
				
			||||||
        [DllImport(__DllName, EntryPoint = "sp2_bit_vec_len", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
 | 
					        [DllImport(__DllName, EntryPoint = "sp2_bit_vec_len", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
 | 
				
			||||||
        public static extern nuint sp2_bit_vec_len(BitVec* @this);
 | 
					        public static extern nuint sp2_bit_vec_len(BitVec* @this);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <summary>Gets an unsafe reference to the data of the `BitVec` instance.  ## Safety  The caller has to make sure to never access the returned memory after the `BitVec` instance has been consumed or manually deallocated.  Reading and writing concurrently to either the original instance or the returned data will result in undefined behavior.</summary>
 | 
				
			||||||
 | 
					        [DllImport(__DllName, EntryPoint = "sp2_bit_vec_unsafe_data_ref", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
 | 
				
			||||||
 | 
					        public static extern CByteSlice sp2_bit_vec_unsafe_data_ref(BitVec* @this);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /// <summary>Creates a new `ByteGrid` instance. The returned instance has to be freed with `byte_grid_dealloc`.</summary>
 | 
					        /// <summary>Creates a new `ByteGrid` instance. The returned instance has to be freed with `byte_grid_dealloc`.</summary>
 | 
				
			||||||
        [DllImport(__DllName, EntryPoint = "sp2_byte_grid_new", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
 | 
					        [DllImport(__DllName, EntryPoint = "sp2_byte_grid_new", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
 | 
				
			||||||
        public static extern ByteGrid* sp2_byte_grid_new(nuint width, nuint height);
 | 
					        public static extern ByteGrid* sp2_byte_grid_new(nuint width, nuint height);
 | 
				
			||||||
| 
						 | 
					@ -86,9 +90,13 @@ namespace ServicePoint2.BindGen
 | 
				
			||||||
        [DllImport(__DllName, EntryPoint = "sp2_byte_grid_height", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
 | 
					        [DllImport(__DllName, EntryPoint = "sp2_byte_grid_height", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
 | 
				
			||||||
        public static extern nuint sp2_byte_grid_height(ByteGrid* @this);
 | 
					        public static extern nuint sp2_byte_grid_height(ByteGrid* @this);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /// <summary>Tries to load a `Command` from the passed array with the specified length.  returns: NULL in case of an error, pointer to the allocated command otherwise</summary>
 | 
					        /// <summary>Gets an unsafe reference to the data of the `ByteGrid` instance.  ## Safety  The caller has to make sure to never access the returned memory after the `ByteGrid` instance has been consumed or manually deallocated.  Reading and writing concurrently to either the original instance or the returned data will result in undefined behavior.</summary>
 | 
				
			||||||
        [DllImport(__DllName, EntryPoint = "sp2_command_try_load", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
 | 
					        [DllImport(__DllName, EntryPoint = "sp2_byte_grid_unsafe_data_ref", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
 | 
				
			||||||
        public static extern Command* sp2_command_try_load(byte* data, nuint length);
 | 
					        public static extern CByteSlice sp2_byte_grid_unsafe_data_ref(ByteGrid* @this);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <summary>Tries to turn a `Packet` into a `Command`. The packet is gets deallocated in the process.  Returns: pointer to command or NULL</summary>
 | 
				
			||||||
 | 
					        [DllImport(__DllName, EntryPoint = "sp2_command_try_from_packet", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
 | 
				
			||||||
 | 
					        public static extern Command* sp2_command_try_from_packet(Packet* packet);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /// <summary>Clones a `Command` instance</summary>
 | 
					        /// <summary>Clones a `Command` instance</summary>
 | 
				
			||||||
        [DllImport(__DllName, EntryPoint = "sp2_command_clone", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
 | 
					        [DllImport(__DllName, EntryPoint = "sp2_command_clone", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
 | 
				
			||||||
| 
						 | 
					@ -149,7 +157,7 @@ namespace ServicePoint2.BindGen
 | 
				
			||||||
        /// <summary>Sends the command instance. The instance is consumed / destroyed and cannot be used after this call.</summary>
 | 
					        /// <summary>Sends the command instance. The instance is consumed / destroyed and cannot be used after this call.</summary>
 | 
				
			||||||
        [DllImport(__DllName, EntryPoint = "sp2_connection_send", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
 | 
					        [DllImport(__DllName, EntryPoint = "sp2_connection_send", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
 | 
				
			||||||
        [return: MarshalAs(UnmanagedType.U1)]
 | 
					        [return: MarshalAs(UnmanagedType.U1)]
 | 
				
			||||||
        public static extern bool sp2_connection_send(Connection* connection, Command* command_ptr);
 | 
					        public static extern bool sp2_connection_send(Connection* connection, Packet* command_ptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /// <summary>Closes and deallocates a connection instance</summary>
 | 
					        /// <summary>Closes and deallocates a connection instance</summary>
 | 
				
			||||||
        [DllImport(__DllName, EntryPoint = "sp2_connection_dealloc", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
 | 
					        [DllImport(__DllName, EntryPoint = "sp2_connection_dealloc", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
 | 
				
			||||||
| 
						 | 
					@ -192,9 +200,21 @@ namespace ServicePoint2.BindGen
 | 
				
			||||||
        [DllImport(__DllName, EntryPoint = "sp2_pixel_grid_height", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
 | 
					        [DllImport(__DllName, EntryPoint = "sp2_pixel_grid_height", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
 | 
				
			||||||
        public static extern nuint sp2_pixel_grid_height(PixelGrid* @this);
 | 
					        public static extern nuint sp2_pixel_grid_height(PixelGrid* @this);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /// <summary>Gets a reference to the data of the `PixelGrid` instance.</summary>
 | 
					        /// <summary>Gets an unsafe reference to the data of the `PixelGrid` instance.  ## Safety  The caller has to make sure to never access the returned memory after the `PixelGrid` instance has been consumed or manually deallocated.  Reading and writing concurrently to either the original instance or the returned data will result in undefined behavior.</summary>
 | 
				
			||||||
        [DllImport(__DllName, EntryPoint = "sp2_pixel_grid_data_ref", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
 | 
					        [DllImport(__DllName, EntryPoint = "sp2_pixel_grid_unsafe_data_ref", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
 | 
				
			||||||
        public static extern byte* sp2_pixel_grid_data_ref(PixelGrid* @this);
 | 
					        public static extern CByteSlice sp2_pixel_grid_unsafe_data_ref(PixelGrid* @this);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <summary>Turns a `Command` into a `Packet`. The command gets deallocated in the process.</summary>
 | 
				
			||||||
 | 
					        [DllImport(__DllName, EntryPoint = "sp2_packet_from_command", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
 | 
				
			||||||
 | 
					        public static extern Packet* sp2_packet_from_command(Command* command);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <summary>Tries to load a `Packet` from the passed array with the specified length.  returns: NULL in case of an error, pointer to the allocated packet otherwise</summary>
 | 
				
			||||||
 | 
					        [DllImport(__DllName, EntryPoint = "sp2_packet_try_load", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
 | 
				
			||||||
 | 
					        public static extern Packet* sp2_packet_try_load(byte* data, nuint length);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <summary>Deallocates a `Packet`.  Note: do not call this if the instance has been consumed in another way, e.g. by sending it.</summary>
 | 
				
			||||||
 | 
					        [DllImport(__DllName, EntryPoint = "sp2_packet_dealloc", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
 | 
				
			||||||
 | 
					        public static extern void sp2_packet_dealloc(Packet* @this);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					@ -219,6 +239,18 @@ namespace ServicePoint2.BindGen
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    [StructLayout(LayoutKind.Sequential)]
 | 
				
			||||||
 | 
					    public unsafe partial struct CByteSlice
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        public byte* start;
 | 
				
			||||||
 | 
					        public nuint length;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    [StructLayout(LayoutKind.Sequential)]
 | 
				
			||||||
 | 
					    public unsafe partial struct Packet
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public enum Command
 | 
					    public enum Command
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -68,11 +68,23 @@ public sealed class BitVec : Sp2NativeInstance<BindGen.BitVec>
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public Span<byte> Data
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        get
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            unsafe
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                var slice = NativeMethods.sp2_bit_vec_unsafe_data_ref(Instance);
 | 
				
			||||||
 | 
					                return new Span<byte>(slice.start, (int)slice.length);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private unsafe BitVec(BindGen.BitVec* instance) : base(instance)
 | 
					    private unsafe BitVec(BindGen.BitVec* instance) : base(instance)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    protected override unsafe void Dealloc()
 | 
					    private protected override unsafe void Dealloc()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        NativeMethods.sp2_bit_vec_dealloc(Instance);
 | 
					        NativeMethods.sp2_bit_vec_dealloc(Instance);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -111,11 +111,23 @@ public sealed class ByteGrid : Sp2NativeInstance<BindGen.ByteGrid>
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public Span<byte> Data
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        get
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            unsafe
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                var slice = NativeMethods.sp2_byte_grid_unsafe_data_ref(Instance);
 | 
				
			||||||
 | 
					                return new Span<byte>(slice.start, (int)slice.length);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private unsafe ByteGrid(BindGen.ByteGrid* instance) : base(instance)
 | 
					    private unsafe ByteGrid(BindGen.ByteGrid* instance) : base(instance)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    protected override unsafe void Dealloc()
 | 
					    private protected override unsafe void Dealloc()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        NativeMethods.sp2_byte_grid_dealloc(Instance);
 | 
					        NativeMethods.sp2_byte_grid_dealloc(Instance);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -5,6 +5,22 @@ namespace ServicePoint2;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
public sealed class Command : Sp2NativeInstance<BindGen.Command>
 | 
					public sealed class Command : Sp2NativeInstance<BindGen.Command>
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					    public static bool TryFromPacket(Packet packet, [MaybeNullWhen(false)] out Command command)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        unsafe
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            var result = NativeMethods.sp2_command_try_from_packet(packet.Into());
 | 
				
			||||||
 | 
					            if (result == null)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                command = null;
 | 
				
			||||||
 | 
					                return false;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            command = new Command(result);
 | 
				
			||||||
 | 
					            return true;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public Command Clone()
 | 
					    public Command Clone()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        unsafe
 | 
					        unsafe
 | 
				
			||||||
| 
						 | 
					@ -13,21 +29,6 @@ public sealed class Command : Sp2NativeInstance<BindGen.Command>
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public static bool TryLoad(Span<byte> bytes, [MaybeNullWhen(false)] out Command command)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        unsafe
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            fixed (byte* bytesPtr = bytes)
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                var instance = NativeMethods.sp2_command_try_load(bytesPtr, (nuint)bytes.Length);
 | 
					 | 
				
			||||||
                command = instance == null
 | 
					 | 
				
			||||||
                    ? null
 | 
					 | 
				
			||||||
                    : new Command(instance);
 | 
					 | 
				
			||||||
                return command != null;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public static Command Clear()
 | 
					    public static Command Clear()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        unsafe
 | 
					        unsafe
 | 
				
			||||||
| 
						 | 
					@ -124,7 +125,7 @@ public sealed class Command : Sp2NativeInstance<BindGen.Command>
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    protected override unsafe void Dealloc()
 | 
					    private protected override unsafe void Dealloc()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        NativeMethods.sp2_command_dealloc(Instance);
 | 
					        NativeMethods.sp2_command_dealloc(Instance);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -16,15 +16,15 @@ public sealed class Connection : Sp2NativeInstance<BindGen.Connection>
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public bool Send(Command command)
 | 
					    public bool Send(Packet packet)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        unsafe
 | 
					        unsafe
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            return NativeMethods.sp2_connection_send(Instance, command.Into());
 | 
					            return NativeMethods.sp2_connection_send(Instance, packet.Into());
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    protected override unsafe void Dealloc()
 | 
					    private protected override unsafe void Dealloc()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        NativeMethods.sp2_connection_dealloc(Instance);
 | 
					        NativeMethods.sp2_connection_dealloc(Instance);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										39
									
								
								servicepoint2-binding-cs/src/Packet.cs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								servicepoint2-binding-cs/src/Packet.cs
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,39 @@
 | 
				
			||||||
 | 
					using System.Diagnostics.CodeAnalysis;
 | 
				
			||||||
 | 
					using ServicePoint2.BindGen;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace ServicePoint2;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public sealed class Packet : Sp2NativeInstance<BindGen.Packet>
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    public static Packet FromCommand(Command command)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        unsafe
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            return new Packet(NativeMethods.sp2_packet_from_command(command.Into()));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public static bool TryFromBytes(Span<byte> bytes, [MaybeNullWhen(false)] out Packet packet)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        unsafe
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            fixed (byte* bytesPtr = bytes)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                var instance = NativeMethods.sp2_packet_try_load(bytesPtr, (nuint)bytes.Length);
 | 
				
			||||||
 | 
					                packet = instance == null
 | 
				
			||||||
 | 
					                    ? null
 | 
				
			||||||
 | 
					                    : new Packet(instance);
 | 
				
			||||||
 | 
					                return packet != null;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private unsafe Packet(BindGen.Packet* instance) : base(instance)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private protected override unsafe void Dealloc()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        NativeMethods.sp2_packet_dealloc(Instance);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -86,8 +86,8 @@ public sealed class PixelGrid : Sp2NativeInstance<BindGen.PixelGrid>
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            unsafe
 | 
					            unsafe
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                var ptr = NativeMethods.sp2_pixel_grid_data_ref(Instance);
 | 
					                var slice = NativeMethods.sp2_pixel_grid_unsafe_data_ref(Instance);
 | 
				
			||||||
                return new Span<byte>(ptr, Width * Height / 8);
 | 
					                return new Span<byte>(slice.start, (int)slice.length);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					@ -96,7 +96,7 @@ public sealed class PixelGrid : Sp2NativeInstance<BindGen.PixelGrid>
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    protected override unsafe void Dealloc()
 | 
					    private protected override unsafe void Dealloc()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        NativeMethods.sp2_pixel_grid_dealloc(Instance);
 | 
					        NativeMethods.sp2_pixel_grid_dealloc(Instance);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										16
									
								
								servicepoint2-binding-cs/src/ServicePoint2Extensions.cs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								servicepoint2-binding-cs/src/ServicePoint2Extensions.cs
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,16 @@
 | 
				
			||||||
 | 
					using System.Diagnostics.CodeAnalysis;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace ServicePoint2;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public static class ServicePoint2Extensions
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    public static Packet IntoPacket(this Command command)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return Packet.FromCommand(command);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public static bool TryIntoCommand(this Packet packet, [MaybeNullWhen(false)] out Command command)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return Command.TryFromPacket(packet, out command);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -22,7 +22,7 @@ public abstract class Sp2NativeInstance<T>
 | 
				
			||||||
        _instance = instance;
 | 
					        _instance = instance;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    protected abstract void Dealloc();
 | 
					    private protected abstract void Dealloc();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    internal unsafe T* Into()
 | 
					    internal unsafe T* Into()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -71,14 +71,17 @@ impl BitVec {
 | 
				
			||||||
        self.data.fill(byte);
 | 
					        self.data.fill(byte);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Gets the length in bits
 | 
				
			||||||
    pub fn len(&self) -> usize {
 | 
					    pub fn len(&self) -> usize {
 | 
				
			||||||
        self.data.len() * 8
 | 
					        self.data.len() * 8
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pub fn data_ref(&self) -> &[u8] {
 | 
					    /// Get the underlying bits in their raw packed bytes form
 | 
				
			||||||
        &*self.data
 | 
					    pub fn mut_data_ref(&mut self) -> &mut [u8] {
 | 
				
			||||||
 | 
					        self.data.as_mut_slice()
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Calculates the byte index and bitmask for a specific bit in the vector
 | 
				
			||||||
    fn get_indexes(&self, index: usize) -> (usize, u8) {
 | 
					    fn get_indexes(&self, index: usize) -> (usize, u8) {
 | 
				
			||||||
        let byte_index = index / 8;
 | 
					        let byte_index = index / 8;
 | 
				
			||||||
        let bit_in_byte_index = 7 - index % 8;
 | 
					        let bit_in_byte_index = 7 - index % 8;
 | 
				
			||||||
| 
						 | 
					@ -87,13 +90,15 @@ impl BitVec {
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl Into<Vec<u8>> for BitVec {
 | 
					impl From<BitVec> for Vec<u8> {
 | 
				
			||||||
    fn into(self) -> Vec<u8> {
 | 
					    /// Turns the `BitVec` into the underlying `Vec<u8>`
 | 
				
			||||||
        self.data
 | 
					    fn from(value: BitVec) -> Self {
 | 
				
			||||||
 | 
					        value.data
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl From<&[u8]> for BitVec {
 | 
					impl From<&[u8]> for BitVec {
 | 
				
			||||||
 | 
					    /// Interpret the data as a series of bits and load then into a new `BitVec` instance.
 | 
				
			||||||
    fn from(value: &[u8]) -> Self {
 | 
					    fn from(value: &[u8]) -> Self {
 | 
				
			||||||
        Self {
 | 
					        Self {
 | 
				
			||||||
            data: Vec::from(value),
 | 
					            data: Vec::from(value),
 | 
				
			||||||
| 
						 | 
					@ -102,6 +107,7 @@ impl From<&[u8]> for BitVec {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl std::fmt::Debug for BitVec {
 | 
					impl std::fmt::Debug for BitVec {
 | 
				
			||||||
 | 
					    /// Formats a `BitVec` for debug. The manual implementation includes the length of the instance.
 | 
				
			||||||
    fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 | 
					    fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 | 
				
			||||||
        fmt.debug_struct("BitVec")
 | 
					        fmt.debug_struct("BitVec")
 | 
				
			||||||
            .field("len", &self.len())
 | 
					            .field("len", &self.len())
 | 
				
			||||||
| 
						 | 
					@ -112,7 +118,7 @@ impl std::fmt::Debug for BitVec {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[cfg(feature = "c-api")]
 | 
					#[cfg(feature = "c-api")]
 | 
				
			||||||
pub mod c_api {
 | 
					pub mod c_api {
 | 
				
			||||||
    use crate::BitVec;
 | 
					    use crate::{BitVec, CByteSlice};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// Creates a new `BitVec` instance.
 | 
					    /// Creates a new `BitVec` instance.
 | 
				
			||||||
    /// The returned instance has to be freed with `bit_vec_dealloc`.
 | 
					    /// The returned instance has to be freed with `bit_vec_dealloc`.
 | 
				
			||||||
| 
						 | 
					@ -167,4 +173,22 @@ pub mod c_api {
 | 
				
			||||||
    pub unsafe extern "C" fn sp2_bit_vec_len(this: *const BitVec) -> usize {
 | 
					    pub unsafe extern "C" fn sp2_bit_vec_len(this: *const BitVec) -> usize {
 | 
				
			||||||
        (*this).len()
 | 
					        (*this).len()
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Gets an unsafe reference to the data of the `BitVec` instance.
 | 
				
			||||||
 | 
					    ///
 | 
				
			||||||
 | 
					    /// ## Safety
 | 
				
			||||||
 | 
					    ///
 | 
				
			||||||
 | 
					    /// The caller has to make sure to never access the returned memory after the `BitVec`
 | 
				
			||||||
 | 
					    /// instance has been consumed or manually deallocated.
 | 
				
			||||||
 | 
					    ///
 | 
				
			||||||
 | 
					    /// Reading and writing concurrently to either the original instance or the returned data will
 | 
				
			||||||
 | 
					    /// result in undefined behavior.
 | 
				
			||||||
 | 
					    #[no_mangle]
 | 
				
			||||||
 | 
					    pub unsafe extern "C" fn sp2_bit_vec_unsafe_data_ref(this: *mut BitVec) -> CByteSlice {
 | 
				
			||||||
 | 
					        let data = (*this).mut_data_ref();
 | 
				
			||||||
 | 
					        CByteSlice {
 | 
				
			||||||
 | 
					            start: data.as_mut_ptr_range().start,
 | 
				
			||||||
 | 
					            length: data.len(),
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,7 +1,9 @@
 | 
				
			||||||
/// A grid of bytes
 | 
					/// A 2D grid of bytes
 | 
				
			||||||
#[derive(Debug, Clone)]
 | 
					#[derive(Debug, Clone)]
 | 
				
			||||||
pub struct ByteGrid {
 | 
					pub struct ByteGrid {
 | 
				
			||||||
 | 
					    /// Size in the x-axis
 | 
				
			||||||
    pub width: usize,
 | 
					    pub width: usize,
 | 
				
			||||||
 | 
					    /// Size in the y-axis
 | 
				
			||||||
    pub height: usize,
 | 
					    pub height: usize,
 | 
				
			||||||
    data: Vec<u8>,
 | 
					    data: Vec<u8>,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -50,18 +52,24 @@ impl ByteGrid {
 | 
				
			||||||
    pub fn fill(&mut self, value: u8) {
 | 
					    pub fn fill(&mut self, value: u8) {
 | 
				
			||||||
        self.data.fill(value)
 | 
					        self.data.fill(value)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Get the underlying byte rows
 | 
				
			||||||
 | 
					    pub fn mut_data_ref(&mut self) -> &mut [u8] {
 | 
				
			||||||
 | 
					        self.data.as_mut_slice()
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl Into<Vec<u8>> for ByteGrid {
 | 
					impl From<ByteGrid> for Vec<u8> {
 | 
				
			||||||
    fn into(self) -> Vec<u8> {
 | 
					    /// Turn into the underlying `Vec<u8>` containing the rows of bytes.
 | 
				
			||||||
        self.data
 | 
					    fn from(value: ByteGrid) -> Self {
 | 
				
			||||||
 | 
					        value.data
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[cfg(feature = "c-api")]
 | 
					#[cfg(feature = "c-api")]
 | 
				
			||||||
pub mod c_api
 | 
					pub mod c_api
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    use crate::ByteGrid;
 | 
					    use crate::{ByteGrid, CByteSlice};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// Creates a new `ByteGrid` instance.
 | 
					    /// Creates a new `ByteGrid` instance.
 | 
				
			||||||
    /// The returned instance has to be freed with `byte_grid_dealloc`.
 | 
					    /// The returned instance has to be freed with `byte_grid_dealloc`.
 | 
				
			||||||
| 
						 | 
					@ -122,4 +130,22 @@ pub mod c_api
 | 
				
			||||||
    pub unsafe extern "C" fn sp2_byte_grid_height(this: *const ByteGrid) -> usize {
 | 
					    pub unsafe extern "C" fn sp2_byte_grid_height(this: *const ByteGrid) -> usize {
 | 
				
			||||||
        (*this).height
 | 
					        (*this).height
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Gets an unsafe reference to the data of the `ByteGrid` instance.
 | 
				
			||||||
 | 
					    ///
 | 
				
			||||||
 | 
					    /// ## Safety
 | 
				
			||||||
 | 
					    ///
 | 
				
			||||||
 | 
					    /// The caller has to make sure to never access the returned memory after the `ByteGrid`
 | 
				
			||||||
 | 
					    /// instance has been consumed or manually deallocated.
 | 
				
			||||||
 | 
					    ///
 | 
				
			||||||
 | 
					    /// Reading and writing concurrently to either the original instance or the returned data will
 | 
				
			||||||
 | 
					    /// result in undefined behavior.
 | 
				
			||||||
 | 
					    #[no_mangle]
 | 
				
			||||||
 | 
					    pub unsafe extern "C" fn sp2_byte_grid_unsafe_data_ref(this: *mut ByteGrid) -> CByteSlice {
 | 
				
			||||||
 | 
					        let data = (*this).mut_data_ref();
 | 
				
			||||||
 | 
					        CByteSlice {
 | 
				
			||||||
 | 
					            start: data.as_mut_ptr_range().start,
 | 
				
			||||||
 | 
					            length: data.len(),
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
							
								
								
									
										11
									
								
								servicepoint2/src/c_slice.rs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								servicepoint2/src/c_slice.rs
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,11 @@
 | 
				
			||||||
 | 
					#[cfg(feature = "c-api")]
 | 
				
			||||||
 | 
					#[repr(C)]
 | 
				
			||||||
 | 
					/// Represents a span of memory (`&mut [u8]` ) as a struct usable by C code.
 | 
				
			||||||
 | 
					///
 | 
				
			||||||
 | 
					/// Usage of this type is inherently unsafe.
 | 
				
			||||||
 | 
					pub struct CByteSlice {
 | 
				
			||||||
 | 
					    /// The start address of the memory
 | 
				
			||||||
 | 
					    pub start: *mut u8,
 | 
				
			||||||
 | 
					    /// The amount of memory in bytes
 | 
				
			||||||
 | 
					    pub length: usize,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -1,7 +1,8 @@
 | 
				
			||||||
use crate::{
 | 
					use crate::{
 | 
				
			||||||
    BitVec, ByteGrid, CommandCode, CompressionCode, Header, Packet, PixelGrid,
 | 
					    BitVec, ByteGrid, CompressionCode, Header, Packet, PixelGrid,
 | 
				
			||||||
    TILE_SIZE,
 | 
					    TILE_SIZE,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					use crate::command_code::CommandCode;
 | 
				
			||||||
use crate::compression::{into_compressed, into_decompressed};
 | 
					use crate::compression::{into_compressed, into_decompressed};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// An origin marks the top left position of a window sent to the display.
 | 
					/// An origin marks the top left position of a window sent to the display.
 | 
				
			||||||
| 
						 | 
					@ -18,8 +19,10 @@ impl Origin {
 | 
				
			||||||
#[derive(Debug, Clone, Copy)]
 | 
					#[derive(Debug, Clone, Copy)]
 | 
				
			||||||
pub struct Size(pub u16, pub u16);
 | 
					pub struct Size(pub u16, pub u16);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// Type alias for documenting the meaning of the u16 in enum values
 | 
				
			||||||
pub type Offset = u16;
 | 
					pub type Offset = u16;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// Type alias for documenting the meaning of the u16 in enum values
 | 
				
			||||||
pub type Brightness = u8;
 | 
					pub type Brightness = u8;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// A command to send to the display.
 | 
					/// A command to send to the display.
 | 
				
			||||||
| 
						 | 
					@ -29,12 +32,14 @@ pub enum Command {
 | 
				
			||||||
    Clear,
 | 
					    Clear,
 | 
				
			||||||
    /// Kills the udp daemon, usually results in a reboot of the display.
 | 
					    /// Kills the udp daemon, usually results in a reboot of the display.
 | 
				
			||||||
    HardReset,
 | 
					    HardReset,
 | 
				
			||||||
 | 
					    /// Slowly decrease brightness until off? Untested.
 | 
				
			||||||
    FadeOut,
 | 
					    FadeOut,
 | 
				
			||||||
    /// Set the brightness of tiles
 | 
					    /// Set the brightness of tiles
 | 
				
			||||||
    CharBrightness(Origin, ByteGrid),
 | 
					    CharBrightness(Origin, ByteGrid),
 | 
				
			||||||
    /// Set the brightness of all tiles
 | 
					    /// Set the brightness of all tiles
 | 
				
			||||||
    Brightness(Brightness),
 | 
					    Brightness(Brightness),
 | 
				
			||||||
    #[deprecated]
 | 
					    #[deprecated]
 | 
				
			||||||
 | 
					    /// Legacy command code, gets ignored by the real display.
 | 
				
			||||||
    BitmapLegacy,
 | 
					    BitmapLegacy,
 | 
				
			||||||
    /// Set pixel data starting at the offset.
 | 
					    /// Set pixel data starting at the offset.
 | 
				
			||||||
    /// The contained BitVec is always uncompressed.
 | 
					    /// The contained BitVec is always uncompressed.
 | 
				
			||||||
| 
						 | 
					@ -54,9 +59,10 @@ pub enum Command {
 | 
				
			||||||
    BitmapLinearWin(Origin, PixelGrid),
 | 
					    BitmapLinearWin(Origin, PixelGrid),
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl Into<Packet> for Command {
 | 
					impl From<Command> for Packet {
 | 
				
			||||||
    fn into(self) -> Packet {
 | 
					    /// Move the `Command` into a `Packet` instance for sending.
 | 
				
			||||||
        match self {
 | 
					    fn from(value: Command) -> Self {
 | 
				
			||||||
 | 
					        match value {
 | 
				
			||||||
            Command::Clear => command_code_only(CommandCode::Clear),
 | 
					            Command::Clear => command_code_only(CommandCode::Clear),
 | 
				
			||||||
            Command::FadeOut => command_code_only(CommandCode::FadeOut),
 | 
					            Command::FadeOut => command_code_only(CommandCode::FadeOut),
 | 
				
			||||||
            Command::HardReset => command_code_only(CommandCode::HardReset),
 | 
					            Command::HardReset => command_code_only(CommandCode::HardReset),
 | 
				
			||||||
| 
						 | 
					@ -64,10 +70,9 @@ impl Into<Packet> for Command {
 | 
				
			||||||
            Command::BitmapLegacy => {
 | 
					            Command::BitmapLegacy => {
 | 
				
			||||||
                command_code_only(CommandCode::BitmapLegacy)
 | 
					                command_code_only(CommandCode::BitmapLegacy)
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            Command::CharBrightness(origin, grid) => origin_size_payload(
 | 
					            Command::CharBrightness(Origin(x, y), grid) => Packet(
 | 
				
			||||||
                CommandCode::CharBrightness,
 | 
					                Header(CommandCode::CharBrightness.into(),
 | 
				
			||||||
                origin,
 | 
					                       x, y, grid.width as u16, grid.height as u16),
 | 
				
			||||||
                Size(grid.width as u16, grid.height as u16),
 | 
					 | 
				
			||||||
                grid.into(),
 | 
					                grid.into(),
 | 
				
			||||||
            ),
 | 
					            ),
 | 
				
			||||||
            Command::Brightness(brightness) => Packet(
 | 
					            Command::Brightness(brightness) => Packet(
 | 
				
			||||||
| 
						 | 
					@ -126,10 +131,8 @@ impl Into<Packet> for Command {
 | 
				
			||||||
                    bits.into(),
 | 
					                    bits.into(),
 | 
				
			||||||
                )
 | 
					                )
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            Command::Cp437Data(origin, grid) => origin_size_payload(
 | 
					            Command::Cp437Data(Origin(x, y), grid) => Packet(
 | 
				
			||||||
                CommandCode::Cp437Data,
 | 
					                Header(CommandCode::Cp437Data.into(), x, y, grid.width as u16, grid.height as u16),
 | 
				
			||||||
                origin,
 | 
					 | 
				
			||||||
                Size(grid.width as u16, grid.height as u16),
 | 
					 | 
				
			||||||
                grid.into(),
 | 
					                grid.into(),
 | 
				
			||||||
            ),
 | 
					            ),
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
| 
						 | 
					@ -137,6 +140,7 @@ impl Into<Packet> for Command {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive(Debug)]
 | 
					#[derive(Debug)]
 | 
				
			||||||
 | 
					/// Err values for `Command::try_from`.
 | 
				
			||||||
pub enum TryFromPacketError {
 | 
					pub enum TryFromPacketError {
 | 
				
			||||||
    /// the contained command code does not correspond to a known command
 | 
					    /// the contained command code does not correspond to a known command
 | 
				
			||||||
    InvalidCommand(u16),
 | 
					    InvalidCommand(u16),
 | 
				
			||||||
| 
						 | 
					@ -155,6 +159,7 @@ pub enum TryFromPacketError {
 | 
				
			||||||
impl TryFrom<Packet> for Command {
 | 
					impl TryFrom<Packet> for Command {
 | 
				
			||||||
    type Error = TryFromPacketError;
 | 
					    type Error = TryFromPacketError;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Try to interpret the `Packet` as one containing a `Command`
 | 
				
			||||||
    fn try_from(value: Packet) -> Result<Self, Self::Error> {
 | 
					    fn try_from(value: Packet) -> Result<Self, Self::Error> {
 | 
				
			||||||
        let Packet(Header(command_u16, a, b, c, d), _) = value;
 | 
					        let Packet(Header(command_u16, a, b, c, d), _) = value;
 | 
				
			||||||
        let command_code = match CommandCode::try_from(command_u16) {
 | 
					        let command_code = match CommandCode::try_from(command_u16) {
 | 
				
			||||||
| 
						 | 
					@ -178,9 +183,11 @@ impl TryFrom<Packet> for Command {
 | 
				
			||||||
                    ));
 | 
					                    ));
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                match check_empty_header(header) {
 | 
					                let Header(_, a, b, c, d) = header;
 | 
				
			||||||
                    Some(err) => Err(err),
 | 
					                if a != 0 || b != 0 || c != 0 || d != 0 {
 | 
				
			||||||
                    None => Ok(Command::Brightness(payload[0])),
 | 
					                    Err(TryFromPacketError::ExtraneousHeaderValues)
 | 
				
			||||||
 | 
					                } else {
 | 
				
			||||||
 | 
					                    Ok(Command::Brightness(payload[0]))
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            CommandCode::HardReset => match check_command_only(value) {
 | 
					            CommandCode::HardReset => match check_command_only(value) {
 | 
				
			||||||
| 
						 | 
					@ -238,6 +245,7 @@ impl TryFrom<Packet> for Command {
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// Helper method for BitMapLinear*-Commands into Packet
 | 
				
			||||||
fn bitmap_linear_into_packet(
 | 
					fn bitmap_linear_into_packet(
 | 
				
			||||||
    command: CommandCode,
 | 
					    command: CommandCode,
 | 
				
			||||||
    offset: Offset,
 | 
					    offset: Offset,
 | 
				
			||||||
| 
						 | 
					@ -257,30 +265,12 @@ fn bitmap_linear_into_packet(
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
fn origin_size_payload(
 | 
					/// Helper method for creating empty packets only containing the command code
 | 
				
			||||||
    command: CommandCode,
 | 
					 | 
				
			||||||
    origin: Origin,
 | 
					 | 
				
			||||||
    size: Size,
 | 
					 | 
				
			||||||
    payload: Vec<u8>,
 | 
					 | 
				
			||||||
) -> Packet {
 | 
					 | 
				
			||||||
    let Origin(x, y) = origin;
 | 
					 | 
				
			||||||
    let Size(w, h) = size;
 | 
					 | 
				
			||||||
    Packet(Header(command.into(), x, y, w, h), payload.into())
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
fn command_code_only(code: CommandCode) -> Packet {
 | 
					fn command_code_only(code: CommandCode) -> Packet {
 | 
				
			||||||
    Packet(Header(code.into(), 0x0000, 0x0000, 0x0000, 0x0000), vec![])
 | 
					    Packet(Header(code.into(), 0x0000, 0x0000, 0x0000, 0x0000), vec![])
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
fn check_empty_header(header: Header) -> Option<TryFromPacketError> {
 | 
					/// Helper method for checking that a packet is empty and only contains a command code
 | 
				
			||||||
    let Header(_, a, b, c, d) = header;
 | 
					 | 
				
			||||||
    if a != 0 || b != 0 || c != 0 || d != 0 {
 | 
					 | 
				
			||||||
        Some(TryFromPacketError::ExtraneousHeaderValues)
 | 
					 | 
				
			||||||
    } else {
 | 
					 | 
				
			||||||
        None
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
fn check_command_only(packet: Packet) -> Option<TryFromPacketError> {
 | 
					fn check_command_only(packet: Packet) -> Option<TryFromPacketError> {
 | 
				
			||||||
    let Packet(Header(_, a, b, c, d), payload) = packet;
 | 
					    let Packet(Header(_, a, b, c, d), payload) = packet;
 | 
				
			||||||
    if payload.len() != 0 {
 | 
					    if payload.len() != 0 {
 | 
				
			||||||
| 
						 | 
					@ -292,6 +282,7 @@ fn check_command_only(packet: Packet) -> Option<TryFromPacketError> {
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// Helper method for Packets into BitMapLinear*-Commands
 | 
				
			||||||
fn packet_into_linear_bitmap(
 | 
					fn packet_into_linear_bitmap(
 | 
				
			||||||
    packet: Packet,
 | 
					    packet: Packet,
 | 
				
			||||||
) -> Result<(BitVec, CompressionCode), TryFromPacketError> {
 | 
					) -> Result<(BitVec, CompressionCode), TryFromPacketError> {
 | 
				
			||||||
| 
						 | 
					@ -323,21 +314,17 @@ pub mod c_api
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    use crate::{BitVec, Brightness, ByteGrid, Command, CompressionCode, Offset, Origin, Packet, PixelGrid};
 | 
					    use crate::{BitVec, Brightness, ByteGrid, Command, CompressionCode, Offset, Origin, Packet, PixelGrid};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// Tries to load a `Command` from the passed array with the specified length.
 | 
					
 | 
				
			||||||
 | 
					    /// Tries to turn a `Packet` into a `Command`. The packet is gets deallocated in the process.
 | 
				
			||||||
    ///
 | 
					    ///
 | 
				
			||||||
    /// returns: NULL in case of an error, pointer to the allocated command otherwise
 | 
					    /// Returns: pointer to command or NULL
 | 
				
			||||||
    #[no_mangle]
 | 
					    #[no_mangle]
 | 
				
			||||||
    pub unsafe extern "C" fn sp2_command_try_load(data: *const u8, length: usize) -> *mut Command {
 | 
					    pub unsafe extern "C" fn sp2_command_try_from_packet(packet: *mut Packet) -> *mut Command {
 | 
				
			||||||
        let data = std::slice::from_raw_parts(data, length);
 | 
					        let packet = *Box::from_raw(packet);
 | 
				
			||||||
        let packet = match Packet::try_from(data) {
 | 
					        match Command::try_from(packet) {
 | 
				
			||||||
            Err(_) => return null_mut(),
 | 
					            Err(_) => return null_mut(),
 | 
				
			||||||
            Ok(packet) => packet
 | 
					            Ok(command) => Box::into_raw(Box::new(command)),
 | 
				
			||||||
        };
 | 
					        }
 | 
				
			||||||
        let command = match Command::try_from(packet) {
 | 
					 | 
				
			||||||
            Err(_) => return null_mut(),
 | 
					 | 
				
			||||||
            Ok(command) => command,
 | 
					 | 
				
			||||||
        };
 | 
					 | 
				
			||||||
        Box::into_raw(Box::new(command))
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// Clones a `Command` instance
 | 
					    /// Clones a `Command` instance
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,9 +1,7 @@
 | 
				
			||||||
use CommandCode::*;
 | 
					/// The u16 command codes used for the `Commands`.
 | 
				
			||||||
 | 
					 | 
				
			||||||
/// The codes used for the commands. See the documentation on the corresponding commands.
 | 
					 | 
				
			||||||
#[repr(u16)]
 | 
					#[repr(u16)]
 | 
				
			||||||
#[derive(Debug, Copy, Clone)]
 | 
					#[derive(Debug, Copy, Clone)]
 | 
				
			||||||
pub enum CommandCode {
 | 
					pub(crate) enum CommandCode {
 | 
				
			||||||
    Clear = 0x0002,
 | 
					    Clear = 0x0002,
 | 
				
			||||||
    Cp437Data = 0x0003,
 | 
					    Cp437Data = 0x0003,
 | 
				
			||||||
    CharBrightness = 0x0005,
 | 
					    CharBrightness = 0x0005,
 | 
				
			||||||
| 
						 | 
					@ -19,16 +17,20 @@ pub enum CommandCode {
 | 
				
			||||||
    BitmapLinearXor = 0x0016,
 | 
					    BitmapLinearXor = 0x0016,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl Into<u16> for CommandCode {
 | 
					impl From<CommandCode> for u16 {
 | 
				
			||||||
    fn into(self) -> u16 {
 | 
					    /// returns the u16 command code corresponding to the enum value
 | 
				
			||||||
        self as u16
 | 
					    fn from(value: CommandCode) -> Self {
 | 
				
			||||||
 | 
					        value as u16
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl TryFrom<u16> for CommandCode {
 | 
					impl TryFrom<u16> for CommandCode {
 | 
				
			||||||
    type Error = ();
 | 
					    type Error = ();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Returns the enum value for the specified `u16` or `Error` if the code is unknown.
 | 
				
			||||||
    fn try_from(value: u16) -> Result<Self, Self::Error> {
 | 
					    fn try_from(value: u16) -> Result<Self, Self::Error> {
 | 
				
			||||||
 | 
					        use CommandCode::*;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        match value {
 | 
					        match value {
 | 
				
			||||||
            value if value == Clear as u16 => Ok(Clear),
 | 
					            value if value == Clear as u16 => Ok(Clear),
 | 
				
			||||||
            value if value == Cp437Data as u16 => Ok(Cp437Data),
 | 
					            value if value == Cp437Data as u16 => Ok(Cp437Data),
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -15,9 +15,9 @@ pub enum CompressionCode {
 | 
				
			||||||
    Zs = 0x7a73,
 | 
					    Zs = 0x7a73,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl Into<u16> for CompressionCode {
 | 
					impl From<CompressionCode> for u16 {
 | 
				
			||||||
    fn into(self) -> u16 {
 | 
					    fn from(value: CompressionCode) -> Self {
 | 
				
			||||||
        self as u16
 | 
					        value as u16
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -42,7 +42,7 @@ impl Connection {
 | 
				
			||||||
    ///     .expect("connection failed");
 | 
					    ///     .expect("connection failed");
 | 
				
			||||||
    ///
 | 
					    ///
 | 
				
			||||||
    ///  // turn off all pixels
 | 
					    ///  // turn off all pixels
 | 
				
			||||||
    ///  connection.send(servicepoint2::Command::Clear)
 | 
					    ///  connection.send(servicepoint2::Command::Clear.into())
 | 
				
			||||||
    ///     .expect("send failed");
 | 
					    ///     .expect("send failed");
 | 
				
			||||||
    ///
 | 
					    ///
 | 
				
			||||||
    ///  // turn on all pixels
 | 
					    ///  // turn on all pixels
 | 
				
			||||||
| 
						 | 
					@ -50,12 +50,12 @@ impl Connection {
 | 
				
			||||||
    ///  pixels.fill(true);
 | 
					    ///  pixels.fill(true);
 | 
				
			||||||
    ///
 | 
					    ///
 | 
				
			||||||
    ///  // send pixels to display
 | 
					    ///  // send pixels to display
 | 
				
			||||||
    ///  connection.send(servicepoint2::Command::BitmapLinearWin(servicepoint2::Origin::top_left(), pixels))
 | 
					    ///  connection.send(servicepoint2::Command::BitmapLinearWin(servicepoint2::Origin::top_left(), pixels).into())
 | 
				
			||||||
    ///     .expect("send failed");
 | 
					    ///     .expect("send failed");
 | 
				
			||||||
    /// ```
 | 
					    /// ```
 | 
				
			||||||
    pub fn send(
 | 
					    pub fn send(
 | 
				
			||||||
        &self,
 | 
					        &self,
 | 
				
			||||||
        packet: impl Into<Packet> + Debug,
 | 
					        packet: Packet,
 | 
				
			||||||
    ) -> Result<(), std::io::Error> {
 | 
					    ) -> Result<(), std::io::Error> {
 | 
				
			||||||
        debug!("sending {packet:?}");
 | 
					        debug!("sending {packet:?}");
 | 
				
			||||||
        let packet: Packet = packet.into();
 | 
					        let packet: Packet = packet.into();
 | 
				
			||||||
| 
						 | 
					@ -71,7 +71,7 @@ pub mod c_api
 | 
				
			||||||
    use std::ffi::{c_char, CStr};
 | 
					    use std::ffi::{c_char, CStr};
 | 
				
			||||||
    use std::ptr::null_mut;
 | 
					    use std::ptr::null_mut;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    use crate::{Command, Connection};
 | 
					    use crate::{Connection, Packet};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// Creates a new instance of Connection.
 | 
					    /// Creates a new instance of Connection.
 | 
				
			||||||
    /// The returned instance has to be deallocated with `connection_dealloc`.
 | 
					    /// The returned instance has to be deallocated with `connection_dealloc`.
 | 
				
			||||||
| 
						 | 
					@ -87,15 +87,14 @@ pub mod c_api
 | 
				
			||||||
            Ok(value) => value
 | 
					            Ok(value) => value
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let boxed = Box::new(connection);
 | 
					        Box::into_raw(Box::new(connection))
 | 
				
			||||||
        Box::into_raw(boxed)
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// Sends the command instance. The instance is consumed / destroyed and cannot be used after this call.
 | 
					    /// Sends the command instance. The instance is consumed / destroyed and cannot be used after this call.
 | 
				
			||||||
    #[no_mangle]
 | 
					    #[no_mangle]
 | 
				
			||||||
    pub unsafe extern "C" fn sp2_connection_send(connection: *const Connection, command_ptr: *mut Command) -> bool{
 | 
					    pub unsafe extern "C" fn sp2_connection_send(connection: *const Connection, command_ptr: *mut Packet) -> bool{
 | 
				
			||||||
        let command = Box::from_raw(command_ptr);
 | 
					        let packet = Box::from_raw(command_ptr);
 | 
				
			||||||
        (*connection).send(*command).is_ok()
 | 
					        (*connection).send(*packet).is_ok()
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// Closes and deallocates a connection instance
 | 
					    /// Closes and deallocates a connection instance
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,12 +1,14 @@
 | 
				
			||||||
pub use crate::bit_vec::BitVec;
 | 
					pub use crate::bit_vec::BitVec;
 | 
				
			||||||
pub use crate::byte_grid::ByteGrid;
 | 
					pub use crate::byte_grid::ByteGrid;
 | 
				
			||||||
pub use crate::command::{Brightness, Command, Offset, Origin, Size};
 | 
					pub use crate::command::{Brightness, Command, Offset, Origin, Size};
 | 
				
			||||||
pub use crate::command_code::CommandCode;
 | 
					 | 
				
			||||||
pub use crate::compression_code::CompressionCode;
 | 
					pub use crate::compression_code::CompressionCode;
 | 
				
			||||||
pub use crate::connection::Connection;
 | 
					pub use crate::connection::Connection;
 | 
				
			||||||
pub use crate::packet::{Header, Packet, Payload};
 | 
					pub use crate::packet::{Header, Packet, Payload};
 | 
				
			||||||
pub use crate::pixel_grid::PixelGrid;
 | 
					pub use crate::pixel_grid::PixelGrid;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[cfg(feature = "c-api")]
 | 
				
			||||||
 | 
					pub use crate::c_slice::CByteSlice;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
mod bit_vec;
 | 
					mod bit_vec;
 | 
				
			||||||
mod byte_grid;
 | 
					mod byte_grid;
 | 
				
			||||||
mod command;
 | 
					mod command;
 | 
				
			||||||
| 
						 | 
					@ -16,6 +18,7 @@ mod compression_code;
 | 
				
			||||||
mod connection;
 | 
					mod connection;
 | 
				
			||||||
mod packet;
 | 
					mod packet;
 | 
				
			||||||
mod pixel_grid;
 | 
					mod pixel_grid;
 | 
				
			||||||
 | 
					mod c_slice;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// size of a single tile in one dimension
 | 
					/// size of a single tile in one dimension
 | 
				
			||||||
pub const TILE_SIZE: u16 = 8;
 | 
					pub const TILE_SIZE: u16 = 8;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,3 +1,5 @@
 | 
				
			||||||
 | 
					use std::mem::size_of;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// A raw header. Should probably not be used directly.
 | 
					/// A raw header. Should probably not be used directly.
 | 
				
			||||||
#[derive(Debug)]
 | 
					#[derive(Debug)]
 | 
				
			||||||
pub struct Header(pub u16, pub u16, pub u16, pub u16, pub u16);
 | 
					pub struct Header(pub u16, pub u16, pub u16, pub u16, pub u16);
 | 
				
			||||||
| 
						 | 
					@ -9,12 +11,13 @@ pub type Payload = Vec<u8>;
 | 
				
			||||||
#[derive(Debug)]
 | 
					#[derive(Debug)]
 | 
				
			||||||
pub struct Packet(pub Header, pub Payload);
 | 
					pub struct Packet(pub Header, pub Payload);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl Into<Payload> for Packet {
 | 
					impl From<Packet> for Vec<u8> {
 | 
				
			||||||
    fn into(self) -> Vec<u8> {
 | 
					    /// Turn the packet into raw bytes ready to send
 | 
				
			||||||
        let Packet(Header(mode, a, b, c, d), payload) = self;
 | 
					    fn from(value: Packet) -> Self {
 | 
				
			||||||
 | 
					        let Packet(Header(mode, a, b, c, d), payload) = value;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let mut packet = vec![0u8; 10 + payload.len()];
 | 
					        let mut packet = vec![0u8; 10 + payload.len()];
 | 
				
			||||||
        packet[0..=1].copy_from_slice(&u16::to_be_bytes(mode));
 | 
					        packet[0..=1].copy_from_slice(&u16::to_be_bytes(mode.into()));
 | 
				
			||||||
        packet[2..=3].copy_from_slice(&u16::to_be_bytes(a));
 | 
					        packet[2..=3].copy_from_slice(&u16::to_be_bytes(a));
 | 
				
			||||||
        packet[4..=5].copy_from_slice(&u16::to_be_bytes(b));
 | 
					        packet[4..=5].copy_from_slice(&u16::to_be_bytes(b));
 | 
				
			||||||
        packet[6..=7].copy_from_slice(&u16::to_be_bytes(c));
 | 
					        packet[6..=7].copy_from_slice(&u16::to_be_bytes(c));
 | 
				
			||||||
| 
						 | 
					@ -33,8 +36,17 @@ fn u16_from_be_slice(slice: &[u8]) -> u16 {
 | 
				
			||||||
    u16::from_be_bytes(bytes)
 | 
					    u16::from_be_bytes(bytes)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl From<Payload> for Packet {
 | 
					impl TryFrom<&[u8]> for Packet {
 | 
				
			||||||
    fn from(value: Vec<u8>) -> Self {
 | 
					    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<Self, Self::Error> {
 | 
				
			||||||
 | 
					        if value.len() < size_of::<Header>() {
 | 
				
			||||||
 | 
					            return Err(());
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let mode = u16_from_be_slice(&value[0..=1]);
 | 
					        let mode = u16_from_be_slice(&value[0..=1]);
 | 
				
			||||||
        let a = u16_from_be_slice(&value[2..=3]);
 | 
					        let a = u16_from_be_slice(&value[2..=3]);
 | 
				
			||||||
        let b = u16_from_be_slice(&value[4..=5]);
 | 
					        let b = u16_from_be_slice(&value[4..=5]);
 | 
				
			||||||
| 
						 | 
					@ -42,19 +54,42 @@ impl From<Payload> for Packet {
 | 
				
			||||||
        let d = u16_from_be_slice(&value[8..=9]);
 | 
					        let d = u16_from_be_slice(&value[8..=9]);
 | 
				
			||||||
        let payload = value[10..].to_vec();
 | 
					        let payload = value[10..].to_vec();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        Packet(Header(mode, a, b, c, d), payload)
 | 
					        Ok(Packet(Header(mode, a, b, c, d), payload))
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl From<&[u8]> for Packet {
 | 
					#[cfg(feature = "c-api")]
 | 
				
			||||||
    fn from(value: &[u8]) -> Self {
 | 
					mod c_api {
 | 
				
			||||||
        let mode = u16_from_be_slice(&value[0..=1]);
 | 
					    use std::ptr::null_mut;
 | 
				
			||||||
        let a = u16_from_be_slice(&value[2..=3]);
 | 
					 | 
				
			||||||
        let b = u16_from_be_slice(&value[4..=5]);
 | 
					 | 
				
			||||||
        let c = u16_from_be_slice(&value[6..=7]);
 | 
					 | 
				
			||||||
        let d = u16_from_be_slice(&value[8..=9]);
 | 
					 | 
				
			||||||
        let payload = value[10..].to_vec();
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        Packet(Header(mode, a, b, c, d), payload)
 | 
					    use crate::{Command, Packet};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Turns a `Command` into a `Packet`. The command gets deallocated in the process.
 | 
				
			||||||
 | 
					    #[no_mangle]
 | 
				
			||||||
 | 
					    pub unsafe extern "C" fn sp2_packet_from_command(command: *mut Command) -> *mut Packet {
 | 
				
			||||||
 | 
					        let command = *Box::from_raw(command);
 | 
				
			||||||
 | 
					        let packet = command.into();
 | 
				
			||||||
 | 
					        Box::into_raw(Box::new(packet))
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Tries to load a `Packet` from the passed array with the specified length.
 | 
				
			||||||
 | 
					    ///
 | 
				
			||||||
 | 
					    /// returns: NULL in case of an error, pointer to the allocated packet otherwise
 | 
				
			||||||
 | 
					    #[no_mangle]
 | 
				
			||||||
 | 
					    pub unsafe extern "C" fn sp2_packet_try_load(data: *const u8, length: usize) -> *mut Packet {
 | 
				
			||||||
 | 
					        let data = std::slice::from_raw_parts(data, length);
 | 
				
			||||||
 | 
					        match Packet::try_from(data) {
 | 
				
			||||||
 | 
					            Err(_) => null_mut(),
 | 
				
			||||||
 | 
					            Ok(packet) => Box::into_raw(Box::new(packet))
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Deallocates a `Packet`.
 | 
				
			||||||
 | 
					    ///
 | 
				
			||||||
 | 
					    /// Note: do not call this if the instance has been consumed in another way, e.g. by sending it.
 | 
				
			||||||
 | 
					    #[no_mangle]
 | 
				
			||||||
 | 
					    pub unsafe extern "C" fn sp2_packet_dealloc(this: *mut Packet) {
 | 
				
			||||||
 | 
					        _ = Box::from_raw(this)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -77,20 +77,22 @@ impl PixelGrid {
 | 
				
			||||||
        self.bit_vec.fill(value);
 | 
					        self.bit_vec.fill(value);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pub fn data_ref(&self) -> &[u8] {
 | 
					    pub fn mut_data_ref(&mut self) -> &mut [u8] {
 | 
				
			||||||
        self.bit_vec.data_ref()
 | 
					        self.bit_vec.mut_data_ref()
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl Into<Vec<u8>> for PixelGrid {
 | 
					impl From<PixelGrid> for Vec<u8> {
 | 
				
			||||||
    fn into(self) -> Vec<u8> {
 | 
					    /// Turns a `PixelGrid` into the underlying `Vec<u8>`.
 | 
				
			||||||
        self.bit_vec.into()
 | 
					    fn from(value: PixelGrid) -> Self {
 | 
				
			||||||
 | 
					        value.bit_vec.into()
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[cfg(feature = "c-api")]
 | 
					#[cfg(feature = "c-api")]
 | 
				
			||||||
pub mod c_api
 | 
					pub mod c_api
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					    use crate::c_slice::CByteSlice;
 | 
				
			||||||
    use crate::PixelGrid;
 | 
					    use crate::PixelGrid;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// Creates a new `PixelGrid` instance.
 | 
					    /// Creates a new `PixelGrid` instance.
 | 
				
			||||||
| 
						 | 
					@ -153,10 +155,21 @@ pub mod c_api
 | 
				
			||||||
        (*this).height
 | 
					        (*this).height
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// Gets a reference to the data of the `PixelGrid` instance.
 | 
					    /// Gets an unsafe reference to the data of the `PixelGrid` instance.
 | 
				
			||||||
 | 
					    ///
 | 
				
			||||||
 | 
					    /// ## Safety
 | 
				
			||||||
 | 
					    ///
 | 
				
			||||||
 | 
					    /// The caller has to make sure to never access the returned memory after the `PixelGrid`
 | 
				
			||||||
 | 
					    /// instance has been consumed or manually deallocated.
 | 
				
			||||||
 | 
					    ///
 | 
				
			||||||
 | 
					    /// Reading and writing concurrently to either the original instance or the returned data will
 | 
				
			||||||
 | 
					    /// result in undefined behavior.
 | 
				
			||||||
    #[no_mangle]
 | 
					    #[no_mangle]
 | 
				
			||||||
    pub unsafe extern "C" fn sp2_pixel_grid_data_ref(this: *const PixelGrid) -> *const u8 {
 | 
					    pub unsafe extern "C" fn sp2_pixel_grid_unsafe_data_ref(this: *mut PixelGrid) -> CByteSlice {
 | 
				
			||||||
        // TODO: also return length
 | 
					        let data = (*this).mut_data_ref();
 | 
				
			||||||
        (*this).data_ref().as_ptr_range().start
 | 
					        CByteSlice {
 | 
				
			||||||
 | 
					            start: data.as_mut_ptr_range().start,
 | 
				
			||||||
 | 
					            length: data.len(),
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue