replace bit_vec module with bitvec library

This commit is contained in:
Vinzenz Schroeter 2024-06-03 21:08:26 +02:00
parent c600761f29
commit 947a3fe60e
16 changed files with 187 additions and 369 deletions

40
Cargo.lock generated
View file

@ -95,6 +95,18 @@ version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1"
[[package]]
name = "bitvec"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c"
dependencies = [
"funty",
"radium",
"tap",
"wyz",
]
[[package]] [[package]]
name = "bzip2" name = "bzip2"
version = "0.4.4" version = "0.4.4"
@ -267,6 +279,12 @@ dependencies = [
"miniz_oxide", "miniz_oxide",
] ]
[[package]]
name = "funty"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c"
[[package]] [[package]]
name = "getrandom" name = "getrandom"
version = "0.2.15" version = "0.2.15"
@ -419,6 +437,12 @@ dependencies = [
"proc-macro2", "proc-macro2",
] ]
[[package]]
name = "radium"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09"
[[package]] [[package]]
name = "rand" name = "rand"
version = "0.8.5" version = "0.8.5"
@ -542,6 +566,7 @@ dependencies = [
name = "servicepoint" name = "servicepoint"
version = "0.5.1" version = "0.5.1"
dependencies = [ dependencies = [
"bitvec",
"bzip2", "bzip2",
"clap 4.5.4", "clap 4.5.4",
"flate2", "flate2",
@ -602,6 +627,12 @@ dependencies = [
"unicode-ident", "unicode-ident",
] ]
[[package]]
name = "tap"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369"
[[package]] [[package]]
name = "tempfile" name = "tempfile"
version = "3.10.1" version = "3.10.1"
@ -766,6 +797,15 @@ version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0"
[[package]]
name = "wyz"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed"
dependencies = [
"tap",
]
[[package]] [[package]]
name = "zstd" name = "zstd"
version = "0.13.1" version = "0.13.1"

View file

@ -14,6 +14,7 @@ crate-type = ["rlib"]
[dependencies] [dependencies]
log = "0.4" log = "0.4"
bitvec = "1.0"
flate2 = { version = "1.0", optional = true } flate2 = { version = "1.0", optional = true }
bzip2 = { version = "0.4", optional = true } bzip2 = { version = "0.4", optional = true }
zstd = { version = "0.13", optional = true } zstd = { version = "0.13", optional = true }

View file

@ -4,7 +4,7 @@ use std::time::Duration;
use clap::Parser; use clap::Parser;
use servicepoint::*; use servicepoint::{bitvec::prelude::BitVec, *};
#[derive(Parser, Debug)] #[derive(Parser, Debug)]
struct Cli { struct Cli {
@ -34,7 +34,7 @@ fn main() {
// this works because the pixel grid has max size // this works because the pixel grid has max size
let pixel_data: Vec<u8> = enabled_pixels.clone().into(); let pixel_data: Vec<u8> = enabled_pixels.clone().into();
let bit_vec = BitVec::from(&*pixel_data); let bit_vec = BitVec::from_vec(pixel_data);
connection connection
.send(Command::BitmapLinearAnd(0, bit_vec, CompressionCode::Lzma)) .send(Command::BitmapLinearAnd(0, bit_vec, CompressionCode::Lzma))

View file

@ -1,257 +0,0 @@
use crate::DataRef;
/// A fixed-size vector of bits
#[derive(Debug, Clone, PartialEq)]
pub struct BitVec {
size: usize,
data: Vec<u8>,
}
impl BitVec {
/// Create a new `BitVec`.
///
/// # Arguments
///
/// * `size`: size in bits.
///
/// returns: `BitVec` with all bits set to false.
///
/// # Panics
///
/// When `size` is not divisible by 8.
#[must_use]
pub fn new(size: usize) -> BitVec {
assert_eq!(size % 8, 0);
Self {
size,
data: vec![0; size / 8],
}
}
/// Sets the value of a bit.
///
/// # Arguments
///
/// * `index`: the bit index to edit
/// * `value`: the value to set the bit to
///
/// returns: old value of the bit
///
/// # Panics
///
/// When accessing `index` out of bounds.
pub fn set(&mut self, index: usize, value: bool) -> bool {
let (byte_index, bit_mask) = self.get_indexes(index);
let byte = self.data[byte_index];
let old_value = byte & bit_mask != 0;
self.data[byte_index] = if value {
byte | bit_mask
} else {
byte & (u8::MAX ^ bit_mask)
};
old_value
}
/// Gets the value of a bit.
///
/// # Arguments
///
/// * `index`: the bit index to read
///
/// returns: value of the bit
///
/// # Panics
///
/// When accessing `index` out of bounds.
#[must_use]
pub fn get(&self, index: usize) -> bool {
let (byte_index, bit_mask) = self.get_indexes(index);
self.data[byte_index] & bit_mask != 0
}
/// Sets all bits to the specified value
///
/// # Arguments
///
/// * `value`: the value to set all bits to
///
/// # Examples
/// ```
/// use servicepoint::BitVec;
/// let mut vec = BitVec::new(8);
/// vec.fill(true);
/// ```
pub fn fill(&mut self, value: bool) {
let byte: u8 = if value { 0xFF } else { 0x00 };
self.data.fill(byte);
}
/// Gets the length in bits
#[must_use]
pub fn len(&self) -> usize {
self.size
}
/// returns true if length is 0.
#[must_use]
pub fn is_empty(&self) -> bool {
self.data.is_empty()
}
/// Get an iterator over every bit in the vector
pub fn iter(&self) -> Iter {
Iter {
bit_vec: self,
index: 0,
end: self.size,
}
}
/// Calculates the byte index and bitmask for a specific bit in the vector
fn get_indexes(&self, bit_index: usize) -> (usize, u8) {
assert!(
bit_index < self.size,
"bit index {bit_index} is outside of range 0..<{}",
self.size
);
let byte_index = bit_index / 8;
let bit_in_byte_index = 7 - bit_index % 8;
let bit_mask: u8 = 1 << bit_in_byte_index;
(byte_index, bit_mask)
}
}
impl DataRef for BitVec {
fn data_ref_mut(&mut self) -> &mut [u8] {
self.data.as_mut_slice()
}
fn data_ref(&self) -> &[u8] {
self.data.as_slice()
}
}
impl From<BitVec> for Vec<u8> {
/// Turns the `BitVec` into the underlying `Vec<u8>`
fn from(value: BitVec) -> Self {
value.data
}
}
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 {
Self {
size: value.len() * 8,
data: Vec::from(value),
}
}
}
pub struct Iter<'t> {
pub(crate) bit_vec: &'t BitVec,
pub(crate) index: usize,
pub(crate) end: usize,
}
impl<'t> Iterator for Iter<'t> {
type Item = bool;
fn next(&mut self) -> Option<Self::Item> {
if self.index >= self.end {
return None;
}
let result = Some(self.bit_vec.get(self.index));
self.index += 1;
result
}
}
#[cfg(test)]
mod tests {
use crate::{BitVec, DataRef};
#[test]
fn fill() {
let mut vec = BitVec::new(8 * 3);
assert_eq!(vec.data, [0x00, 0x00, 0x00]);
vec.fill(true);
assert_eq!(vec.data, [0xFF, 0xFF, 0xFF]);
vec.fill(false);
assert_eq!(vec.data, [0x00, 0x00, 0x00]);
}
#[test]
fn get_set() {
let mut vec = BitVec::new(8 * 3);
assert!(!vec.get(1));
assert!(!vec.get(11));
vec.set(1, true);
vec.set(11, true);
assert_eq!(vec.data, [0x40, 0x10, 0x00]);
assert!(!vec.get(0));
assert!(vec.get(1));
assert!(vec.get(11));
}
#[test]
fn load() {
let mut vec = BitVec::new(8 * 3);
vec.set(6, true);
vec.set(7, true);
vec.set(8, true);
vec.set(9, true);
vec.set(10, true);
vec.set(vec.len() - 1, true);
assert_eq!(vec.data, [0x03, 0xE0, 0x01]);
let data: Vec<u8> = vec.into();
let vec = BitVec::from(&*data);
assert_eq!(vec.data, [0x03, 0xE0, 0x01]);
}
#[test]
fn mut_data_ref() {
let mut vec = BitVec::new(8 * 3);
let data_ref = vec.data_ref_mut();
data_ref.copy_from_slice(&[0x40, 0x10, 0x00]);
assert_eq!(vec.data, [0x40, 0x10, 0x00]);
assert!(vec.get(1));
}
#[test]
fn is_empty() {
let vec = BitVec::new(8 * 3);
assert!(!vec.is_empty());
let vec = BitVec::new(0);
assert!(vec.is_empty());
}
#[test]
fn get_returns_old() {
let mut vec = BitVec::new(8);
assert!(!vec.set(1, true));
assert!(vec.set(1, true));
assert!(vec.set(1, false));
assert!(!vec.set(1, false));
}
#[test]
fn debug_print() {
let vec = BitVec::new(8 * 3);
format!("{vec:?}");
}
}

View file

@ -85,17 +85,12 @@ impl Grid<u8> for ByteGrid {
/// * `x` and `y`: position of the cell /// * `x` and `y`: position of the cell
/// * `value`: the value to write to the cell /// * `value`: the value to write to the cell
/// ///
/// returns: old value of the cell.
///
/// # Panics /// # Panics
/// ///
/// When accessing `x` or `y` out of bounds. /// When accessing `x` or `y` out of bounds.
fn set(&mut self, x: usize, y: usize, value: u8) -> u8 { fn set(&mut self, x: usize, y: usize, value: u8) {
self.check_indexes(x, y); self.check_indexes(x, y);
let pos = &mut self.data[x + y * self.width]; self.data[x + y * self.width] = value;
let old_val = *pos;
*pos = value;
old_val
} }
/// Gets the current value at the specified position. /// Gets the current value at the specified position.

View file

@ -1,7 +1,9 @@
use bitvec::prelude::{BitVec, Msb0};
use crate::command_code::CommandCode; use crate::command_code::CommandCode;
use crate::compression::{into_compressed, into_decompressed}; use crate::compression::{into_compressed, into_decompressed};
use crate::{ use crate::{
BitVec, ByteGrid, CompressionCode, Grid, Header, Packet, PixelGrid, ByteGrid, CompressionCode, Grid, Header, Packet, PixelGrid, SpBitVec,
TILE_SIZE, TILE_SIZE,
}; };
@ -25,6 +27,7 @@ pub type Offset = usize;
/// Type alias for documenting the meaning of the u16 in enum values /// Type alias for documenting the meaning of the u16 in enum values
pub type Brightness = u8; pub type Brightness = u8;
// TODO: check order
/// A command to send to the display. /// A command to send to the display.
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]
pub enum Command { pub enum Command {
@ -43,16 +46,16 @@ pub enum Command {
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.
BitmapLinear(Offset, BitVec, CompressionCode), BitmapLinear(Offset, SpBitVec, CompressionCode),
/// Set pixel data according to an and-mask starting at the offset. /// Set pixel data according to an and-mask starting at the offset.
/// The contained `BitVec` is always uncompressed. /// The contained `BitVec` is always uncompressed.
BitmapLinearAnd(Offset, BitVec, CompressionCode), BitmapLinearAnd(Offset, SpBitVec, CompressionCode),
/// Set pixel data according to an or-mask starting at the offset. /// Set pixel data according to an or-mask starting at the offset.
/// The contained `BitVec` is always uncompressed. /// The contained `BitVec` is always uncompressed.
BitmapLinearOr(Offset, BitVec, CompressionCode), BitmapLinearOr(Offset, SpBitVec, CompressionCode),
/// Set pixel data according to a xor-mask starting at the offset. /// Set pixel data according to a xor-mask starting at the offset.
/// The contained `BitVec` is always uncompressed. /// The contained `BitVec` is always uncompressed.
BitmapLinearXor(Offset, BitVec, CompressionCode), BitmapLinearXor(Offset, SpBitVec, CompressionCode),
/// Show text on the screen. Note that the byte data has to be CP437 encoded. /// Show text on the screen. Note that the byte data has to be CP437 encoded.
Cp437Data(Origin, ByteGrid), Cp437Data(Origin, ByteGrid),
/// Sets a window of pixels to the specified values /// Sets a window of pixels to the specified values
@ -366,7 +369,7 @@ impl Command {
/// Helper method for Packets into `BitMapLinear*`-Commands /// 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<u8, Msb0>, CompressionCode), TryFromPacketError> {
let Packet(Header(_, _, length, sub, reserved), payload) = packet; let Packet(Header(_, _, length, sub, reserved), payload) = packet;
if reserved != 0 { if reserved != 0 {
return Err(TryFromPacketError::ExtraneousHeaderValues); return Err(TryFromPacketError::ExtraneousHeaderValues);
@ -387,17 +390,18 @@ impl Command {
payload.len(), payload.len(),
)); ));
} }
Ok((BitVec::from(&*payload), sub)) Ok((BitVec::from_vec(payload), sub))
} }
} }
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use bitvec::prelude::BitVec;
use crate::command::TryFromPacketError; use crate::command::TryFromPacketError;
use crate::command_code::CommandCode; use crate::command_code::CommandCode;
use crate::{ use crate::{
BitVec, ByteGrid, Command, CompressionCode, Grid, Header, Origin, ByteGrid, Command, CompressionCode, Header, Origin, Packet, PixelGrid,
Packet, PixelGrid,
}; };
fn round_trip(original: Command) { fn round_trip(original: Command) {
@ -462,20 +466,24 @@ mod tests {
#[test] #[test]
fn round_trip_bitmap_linear() { fn round_trip_bitmap_linear() {
for compression in all_compressions().to_owned() { for compression in all_compressions().to_owned() {
round_trip(Command::BitmapLinear(23, BitVec::new(40), compression)); round_trip(Command::BitmapLinear(
23,
BitVec::repeat(false, 40),
compression,
));
round_trip(Command::BitmapLinearAnd( round_trip(Command::BitmapLinearAnd(
23, 23,
BitVec::new(40), BitVec::repeat(false, 40),
compression, compression,
)); ));
round_trip(Command::BitmapLinearOr( round_trip(Command::BitmapLinearOr(
23, 23,
BitVec::new(40), BitVec::repeat(false, 40),
compression, compression,
)); ));
round_trip(Command::BitmapLinearXor( round_trip(Command::BitmapLinearXor(
23, 23,
BitVec::new(40), BitVec::repeat(false, 40),
compression, compression,
)); ));
round_trip(Command::BitmapLinearWin( round_trip(Command::BitmapLinearWin(
@ -590,8 +598,12 @@ mod tests {
#[test] #[test]
fn error_decompression_failed_and() { fn error_decompression_failed_and() {
for compression in all_compressions().to_owned() { for compression in all_compressions().to_owned() {
let p: Packet = let p: Packet = Command::BitmapLinearAnd(
Command::BitmapLinearAnd(0, BitVec::new(8), compression).into(); 0,
BitVec::repeat(false, 8),
compression,
)
.into();
let Packet(header, mut payload) = p; let Packet(header, mut payload) = p;
// mangle it // mangle it
@ -633,7 +645,7 @@ mod tests {
fn error_reserved_used() { fn error_reserved_used() {
let Packet(header, payload) = Command::BitmapLinear( let Packet(header, payload) = Command::BitmapLinear(
0, 0,
BitVec::new(8), BitVec::repeat(false, 8),
CompressionCode::Uncompressed, CompressionCode::Uncompressed,
) )
.into(); .into();
@ -649,7 +661,7 @@ mod tests {
fn error_invalid_compression() { fn error_invalid_compression() {
let Packet(header, payload) = Command::BitmapLinear( let Packet(header, payload) = Command::BitmapLinear(
0, 0,
BitVec::new(8), BitVec::repeat(false, 8),
CompressionCode::Uncompressed, CompressionCode::Uncompressed,
) )
.into(); .into();
@ -665,7 +677,7 @@ mod tests {
fn error_unexpected_size() { fn error_unexpected_size() {
let Packet(header, payload) = Command::BitmapLinear( let Packet(header, payload) = Command::BitmapLinear(
0, 0,
BitVec::new(8), BitVec::repeat(false, 8),
CompressionCode::Uncompressed, CompressionCode::Uncompressed,
) )
.into(); .into();

View file

@ -6,12 +6,10 @@ pub trait Grid<T> {
/// ///
/// * `x` and `y`: position of the cell to read /// * `x` and `y`: position of the cell to read
/// ///
/// returns: the old value
///
/// # Panics /// # Panics
/// ///
/// When accessing `x` or `y` out of bounds. /// When accessing `x` or `y` out of bounds.
fn set(&mut self, x: usize, y: usize, value: T) -> T; fn set(&mut self, x: usize, y: usize, value: T);
/// Get the current value at the specified position /// Get the current value at the specified position
/// ///
@ -46,11 +44,12 @@ pub trait Grid<T> {
/// * `x` and `y`: position of the cell to read /// * `x` and `y`: position of the cell to read
/// ///
/// returns: the old value or None /// returns: the old value or None
fn set_optional(&mut self, x: isize, y: isize, value: T) -> Option<T> { fn set_optional(&mut self, x: isize, y: isize, value: T) -> bool {
if self.is_in_bounds(x, y) { if self.is_in_bounds(x, y) {
Some(self.set(x as usize, y as usize, value)) self.set(x as usize, y as usize, value);
true
} else { } else {
None false
} }
} }

View file

@ -2,7 +2,6 @@
use std::time::Duration; use std::time::Duration;
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}; pub use crate::command::{Brightness, Command, Offset, Origin};
pub use crate::compression_code::CompressionCode; pub use crate::compression_code::CompressionCode;
@ -11,8 +10,11 @@ pub use crate::data_ref::DataRef;
pub use crate::grid::{Grid, RefGrid}; pub use crate::grid::{Grid, RefGrid};
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;
pub use bitvec;
use bitvec::prelude::{BitVec, Msb0};
type SpBitVec = BitVec<u8, Msb0>;
mod bit_vec;
mod byte_grid; mod byte_grid;
mod command; mod command;
mod command_code; mod command_code;

View file

@ -1,11 +1,14 @@
use crate::{BitVec, DataRef, Grid, PIXEL_HEIGHT, PIXEL_WIDTH}; use crate::{BitVec, DataRef, Grid, SpBitVec, PIXEL_HEIGHT, PIXEL_WIDTH};
use bitvec::order::Msb0;
use bitvec::prelude::BitSlice;
use bitvec::slice::Iter;
/// A grid of pixels stored in packed bytes. /// A grid of pixels stored in packed bytes.
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]
pub struct PixelGrid { pub struct PixelGrid {
width: usize, width: usize,
height: usize, height: usize,
bit_vec: BitVec, bit_vec: SpBitVec,
} }
impl PixelGrid { impl PixelGrid {
@ -26,7 +29,7 @@ impl PixelGrid {
Self { Self {
width, width,
height, height,
bit_vec: BitVec::new(width * height), bit_vec: BitVec::repeat(false, width * height),
} }
} }
@ -56,11 +59,11 @@ impl PixelGrid {
Self { Self {
width, width,
height, height,
bit_vec: BitVec::from(data), bit_vec: BitVec::from_slice(data),
} }
} }
pub fn iter(&self) -> crate::bit_vec::Iter { pub fn iter(&self) -> Iter<'_, u8, Msb0> {
self.bit_vec.iter() self.bit_vec.iter()
} }
@ -98,13 +101,13 @@ impl Grid<bool> for PixelGrid {
/// # Panics /// # Panics
/// ///
/// When accessing `x` or `y` out of bounds. /// When accessing `x` or `y` out of bounds.
fn set(&mut self, x: usize, y: usize, value: bool) -> bool { fn set(&mut self, x: usize, y: usize, value: bool) {
self.check_indexes(x, y); self.check_indexes(x, y);
self.bit_vec.set(x + y * self.width, value) self.bit_vec.set(x + y * self.width, value)
} }
fn get(&self, x: usize, y: usize) -> bool { fn get(&self, x: usize, y: usize) -> bool {
self.bit_vec.get(x + y * self.width) self.bit_vec[x + y * self.width]
} }
/// Sets the state of all pixels in the `PixelGrid`. /// Sets the state of all pixels in the `PixelGrid`.
@ -128,11 +131,11 @@ impl Grid<bool> for PixelGrid {
impl DataRef for PixelGrid { impl DataRef for PixelGrid {
fn data_ref_mut(&mut self) -> &mut [u8] { fn data_ref_mut(&mut self) -> &mut [u8] {
self.bit_vec.data_ref_mut() self.bit_vec.as_raw_mut_slice()
} }
fn data_ref(&self) -> &[u8] { fn data_ref(&self) -> &[u8] {
self.bit_vec.data_ref() self.bit_vec.as_raw_slice()
} }
} }
@ -149,19 +152,17 @@ pub struct IterRows<'t> {
} }
impl<'t> Iterator for IterRows<'t> { impl<'t> Iterator for IterRows<'t> {
type Item = crate::bit_vec::Iter<'t>; type Item = &'t BitSlice<u8, Msb0>;
fn next(&mut self) -> Option<Self::Item> { fn next(&mut self) -> Option<Self::Item> {
if self.row >= self.pixel_grid.height { if self.row >= self.pixel_grid.height {
return None; return None;
} }
let result = Some(crate::bit_vec::Iter {
bit_vec: &self.pixel_grid.bit_vec, let start = self.row * self.pixel_grid.width;
index: self.row * self.pixel_grid.width, let end = start + self.pixel_grid.width;
end: (self.row + 1) * self.pixel_grid.width,
});
self.row += 1; self.row += 1;
result Some(&self.pixel_grid.bit_vec[start..end])
} }
} }

View file

@ -2,9 +2,28 @@
//! //!
//! prefix `sp_bit_vec_` //! prefix `sp_bit_vec_`
use servicepoint::{BitVec, DataRef};
use crate::c_slice::CByteSlice; use crate::c_slice::CByteSlice;
use servicepoint::bitvec::prelude::{BitVec, Msb0};
/// cbindgen:no-export
type SpBitVec = BitVec<u8, Msb0>;
#[derive(Clone)]
pub struct CBitVec {
actual: SpBitVec,
}
impl From<SpBitVec> for CBitVec {
fn from(actual: SpBitVec) -> Self {
Self { actual }
}
}
impl From<CBitVec> for SpBitVec {
fn from(value: CBitVec) -> Self {
value.actual
}
}
/// Creates a new `BitVec` instance. /// Creates a new `BitVec` instance.
/// ///
@ -25,8 +44,10 @@ use crate::c_slice::CByteSlice;
/// - the returned instance is freed in some way, either by using a consuming function or /// - the returned instance is freed in some way, either by using a consuming function or
/// by explicitly calling `sp_bit_vec_dealloc`. /// by explicitly calling `sp_bit_vec_dealloc`.
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn sp_bit_vec_new(size: usize) -> *mut BitVec { pub unsafe extern "C" fn sp_bit_vec_new(size: usize) -> *mut CBitVec {
Box::into_raw(Box::new(BitVec::new(size))) Box::into_raw(Box::new(CBitVec {
actual: SpBitVec::repeat(false, size),
}))
} }
/// Interpret the data as a series of bits and load then into a new `BitVec` instance. /// Interpret the data as a series of bits and load then into a new `BitVec` instance.
@ -43,9 +64,11 @@ pub unsafe extern "C" fn sp_bit_vec_new(size: usize) -> *mut BitVec {
pub unsafe extern "C" fn sp_bit_vec_load( pub unsafe extern "C" fn sp_bit_vec_load(
data: *const u8, data: *const u8,
data_length: usize, data_length: usize,
) -> *mut BitVec { ) -> *mut CBitVec {
let data = std::slice::from_raw_parts(data, data_length); let data = std::slice::from_raw_parts(data, data_length);
Box::into_raw(Box::new(BitVec::from(data))) Box::into_raw(Box::new(CBitVec {
actual: SpBitVec::from_slice(data),
}))
} }
/// Clones a `BitVec`. /// Clones a `BitVec`.
@ -59,7 +82,9 @@ pub unsafe extern "C" fn sp_bit_vec_load(
/// - the returned instance is freed in some way, either by using a consuming function or /// - the returned instance is freed in some way, either by using a consuming function or
/// by explicitly calling `sp_bit_vec_dealloc`. /// by explicitly calling `sp_bit_vec_dealloc`.
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn sp_bit_vec_clone(this: *const BitVec) -> *mut BitVec { pub unsafe extern "C" fn sp_bit_vec_clone(
this: *const CBitVec,
) -> *mut CBitVec {
Box::into_raw(Box::new((*this).clone())) Box::into_raw(Box::new((*this).clone()))
} }
@ -73,7 +98,7 @@ pub unsafe extern "C" fn sp_bit_vec_clone(this: *const BitVec) -> *mut BitVec {
/// - `this` is not used concurrently or after this call /// - `this` is not used concurrently or after this call
/// - `this` was not passed to another consuming function, e.g. to create a `Command` /// - `this` was not passed to another consuming function, e.g. to create a `Command`
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn sp_bit_vec_dealloc(this: *mut BitVec) { pub unsafe extern "C" fn sp_bit_vec_dealloc(this: *mut CBitVec) {
_ = Box::from_raw(this); _ = Box::from_raw(this);
} }
@ -98,10 +123,10 @@ pub unsafe extern "C" fn sp_bit_vec_dealloc(this: *mut BitVec) {
/// - `this` is not written to concurrently /// - `this` is not written to concurrently
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn sp_bit_vec_get( pub unsafe extern "C" fn sp_bit_vec_get(
this: *const BitVec, this: *const CBitVec,
index: usize, index: usize,
) -> bool { ) -> bool {
(*this).get(index) *(*this).actual.get(index).unwrap()
} }
/// Sets the value of a bit in the `BitVec`. /// Sets the value of a bit in the `BitVec`.
@ -126,11 +151,11 @@ pub unsafe extern "C" fn sp_bit_vec_get(
/// - `this` is not written to or read from concurrently /// - `this` is not written to or read from concurrently
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn sp_bit_vec_set( pub unsafe extern "C" fn sp_bit_vec_set(
this: *mut BitVec, this: *mut CBitVec,
index: usize, index: usize,
value: bool, value: bool,
) -> bool { ) {
(*this).set(index, value) (*this).actual.set(index, value)
} }
/// Sets the value of all bits in the `BitVec`. /// Sets the value of all bits in the `BitVec`.
@ -146,8 +171,8 @@ pub unsafe extern "C" fn sp_bit_vec_set(
/// - `this` points to a valid `BitVec` /// - `this` points to a valid `BitVec`
/// - `this` is not written to or read from concurrently /// - `this` is not written to or read from concurrently
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn sp_bit_vec_fill(this: *mut BitVec, value: bool) { pub unsafe extern "C" fn sp_bit_vec_fill(this: *mut CBitVec, value: bool) {
(*this).fill(value) (*this).actual.fill(value)
} }
/// Gets the length of the `BitVec` in bits. /// Gets the length of the `BitVec` in bits.
@ -158,8 +183,8 @@ pub unsafe extern "C" fn sp_bit_vec_fill(this: *mut BitVec, value: bool) {
/// ///
/// - `this` points to a valid `BitVec` /// - `this` points to a valid `BitVec`
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn sp_bit_vec_len(this: *const BitVec) -> usize { pub unsafe extern "C" fn sp_bit_vec_len(this: *const CBitVec) -> usize {
(*this).len() (*this).actual.len()
} }
/// Returns true if length is 0. /// Returns true if length is 0.
@ -170,8 +195,8 @@ pub unsafe extern "C" fn sp_bit_vec_len(this: *const BitVec) -> usize {
/// ///
/// - `this` points to a valid `BitVec` /// - `this` points to a valid `BitVec`
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn sp_bit_vec_is_empty(this: *const BitVec) -> bool { pub unsafe extern "C" fn sp_bit_vec_is_empty(this: *const CBitVec) -> bool {
(*this).is_empty() (*this).actual.is_empty()
} }
/// Gets an unsafe reference to the data of the `BitVec` instance. /// Gets an unsafe reference to the data of the `BitVec` instance.
@ -185,9 +210,9 @@ pub unsafe extern "C" fn sp_bit_vec_is_empty(this: *const BitVec) -> bool {
/// - the returned memory range is never accessed concurrently, either via the `BitVec` or directly /// - the returned memory range is never accessed concurrently, either via the `BitVec` or directly
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn sp_bit_vec_unsafe_data_ref( pub unsafe extern "C" fn sp_bit_vec_unsafe_data_ref(
this: *mut BitVec, this: *mut CBitVec,
) -> CByteSlice { ) -> CByteSlice {
let data = (*this).data_ref_mut(); let data = (*this).actual.as_raw_mut_slice();
CByteSlice { CByteSlice {
start: data.as_mut_ptr_range().start, start: data.as_mut_ptr_range().start,
length: data.len(), length: data.len(),

View file

@ -5,10 +5,12 @@
use std::ptr::null_mut; use std::ptr::null_mut;
use servicepoint::{ use servicepoint::{
BitVec, Brightness, ByteGrid, Command, CompressionCode, Offset, Origin, Brightness, ByteGrid, Command, CompressionCode, Offset, Origin, Packet,
Packet, PixelGrid, PixelGrid,
}; };
use crate::bit_vec::CBitVec;
/// Tries to turn a `Packet` into a `Command`. The packet is deallocated in the process. /// Tries to turn a `Packet` into a `Command`. The packet is deallocated in the process.
/// ///
/// Returns: pointer to new `Command` instance or NULL /// Returns: pointer to new `Command` instance or NULL
@ -140,13 +142,13 @@ pub unsafe extern "C" fn sp_command_char_brightness(
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn sp_command_bitmap_linear( pub unsafe extern "C" fn sp_command_bitmap_linear(
offset: Offset, offset: Offset,
bit_vec: *mut BitVec, bit_vec: *mut CBitVec,
compression: CompressionCode, compression: CompressionCode,
) -> *mut Command { ) -> *mut Command {
let bit_vec = *Box::from_raw(bit_vec); let bit_vec = *Box::from_raw(bit_vec);
Box::into_raw(Box::new(Command::BitmapLinear( Box::into_raw(Box::new(Command::BitmapLinear(
offset, offset,
bit_vec, bit_vec.into(),
compression, compression,
))) )))
} }
@ -166,13 +168,13 @@ pub unsafe extern "C" fn sp_command_bitmap_linear(
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn sp_command_bitmap_linear_and( pub unsafe extern "C" fn sp_command_bitmap_linear_and(
offset: Offset, offset: Offset,
bit_vec: *mut BitVec, bit_vec: *mut CBitVec,
compression: CompressionCode, compression: CompressionCode,
) -> *mut Command { ) -> *mut Command {
let bit_vec = *Box::from_raw(bit_vec); let bit_vec = *Box::from_raw(bit_vec);
Box::into_raw(Box::new(Command::BitmapLinearAnd( Box::into_raw(Box::new(Command::BitmapLinearAnd(
offset, offset,
bit_vec, bit_vec.into(),
compression, compression,
))) )))
} }
@ -192,13 +194,13 @@ pub unsafe extern "C" fn sp_command_bitmap_linear_and(
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn sp_command_bitmap_linear_or( pub unsafe extern "C" fn sp_command_bitmap_linear_or(
offset: Offset, offset: Offset,
bit_vec: *mut BitVec, bit_vec: *mut CBitVec,
compression: CompressionCode, compression: CompressionCode,
) -> *mut Command { ) -> *mut Command {
let bit_vec = *Box::from_raw(bit_vec); let bit_vec = *Box::from_raw(bit_vec);
Box::into_raw(Box::new(Command::BitmapLinearOr( Box::into_raw(Box::new(Command::BitmapLinearOr(
offset, offset,
bit_vec, bit_vec.into(),
compression, compression,
))) )))
} }
@ -218,13 +220,13 @@ pub unsafe extern "C" fn sp_command_bitmap_linear_or(
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn sp_command_bitmap_linear_xor( pub unsafe extern "C" fn sp_command_bitmap_linear_xor(
offset: Offset, offset: Offset,
bit_vec: *mut BitVec, bit_vec: *mut CBitVec,
compression: CompressionCode, compression: CompressionCode,
) -> *mut Command { ) -> *mut Command {
let bit_vec = *Box::from_raw(bit_vec); let bit_vec = *Box::from_raw(bit_vec);
Box::into_raw(Box::new(Command::BitmapLinearXor( Box::into_raw(Box::new(Command::BitmapLinearXor(
offset, offset,
bit_vec, bit_vec.into(),
compression, compression,
))) )))
} }

View file

@ -22,4 +22,4 @@ pub mod pixel_grid;
/// The minimum time needed for the display to refresh the screen in ms. /// The minimum time needed for the display to refresh the screen in ms.
pub const FRAME_PACING_MS: u32 = servicepoint::FRAME_PACING.as_millis() as u32; pub const FRAME_PACING_MS: u32 = servicepoint::FRAME_PACING.as_millis() as u32;
mod c_slice; pub mod c_slice;

View file

@ -21,46 +21,45 @@ namespace ServicePoint.BindGen
/// <summary>Creates a new `BitVec` instance. # Arguments * `size`: size in bits. returns: `BitVec` with all bits set to false. # Panics When `size` is not divisible by 8. # Safety The caller has to make sure that: - the returned instance is freed in some way, either by using a consuming function or by explicitly calling `sp_bit_vec_dealloc`.</summary> /// <summary>Creates a new `BitVec` instance. # Arguments * `size`: size in bits. returns: `BitVec` with all bits set to false. # Panics When `size` is not divisible by 8. # Safety The caller has to make sure that: - the returned instance is freed in some way, either by using a consuming function or by explicitly calling `sp_bit_vec_dealloc`.</summary>
[DllImport(__DllName, EntryPoint = "sp_bit_vec_new", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] [DllImport(__DllName, EntryPoint = "sp_bit_vec_new", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern BitVec* sp_bit_vec_new(nuint size); public static extern CBitVec* sp_bit_vec_new(nuint size);
/// <summary>Interpret the data as a series of bits and load then into a new `BitVec` instance. # Safety The caller has to make sure that: - `data` points to a valid memory location of at least `data_length` bytes in size. - the returned instance is freed in some way, either by using a consuming function or by explicitly calling `sp_bit_vec_dealloc`.</summary> /// <summary>Interpret the data as a series of bits and load then into a new `BitVec` instance. # Safety The caller has to make sure that: - `data` points to a valid memory location of at least `data_length` bytes in size. - the returned instance is freed in some way, either by using a consuming function or by explicitly calling `sp_bit_vec_dealloc`.</summary>
[DllImport(__DllName, EntryPoint = "sp_bit_vec_load", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] [DllImport(__DllName, EntryPoint = "sp_bit_vec_load", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern BitVec* sp_bit_vec_load(byte* data, nuint data_length); public static extern CBitVec* sp_bit_vec_load(byte* data, nuint data_length);
/// <summary>Clones a `BitVec`. # Safety The caller has to make sure that: - `this` points to a valid `BitVec` - `this` is not written to concurrently - the returned instance is freed in some way, either by using a consuming function or by explicitly calling `sp_bit_vec_dealloc`.</summary> /// <summary>Clones a `BitVec`. # Safety The caller has to make sure that: - `this` points to a valid `BitVec` - `this` is not written to concurrently - the returned instance is freed in some way, either by using a consuming function or by explicitly calling `sp_bit_vec_dealloc`.</summary>
[DllImport(__DllName, EntryPoint = "sp_bit_vec_clone", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] [DllImport(__DllName, EntryPoint = "sp_bit_vec_clone", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern BitVec* sp_bit_vec_clone(BitVec* @this); public static extern CBitVec* sp_bit_vec_clone(CBitVec* @this);
/// <summary>Deallocates a `BitVec`. # Safety The caller has to make sure that: - `this` points to a valid `BitVec` - `this` is not used concurrently or after this call - `this` was not passed to another consuming function, e.g. to create a `Command`</summary> /// <summary>Deallocates a `BitVec`. # Safety The caller has to make sure that: - `this` points to a valid `BitVec` - `this` is not used concurrently or after this call - `this` was not passed to another consuming function, e.g. to create a `Command`</summary>
[DllImport(__DllName, EntryPoint = "sp_bit_vec_dealloc", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] [DllImport(__DllName, EntryPoint = "sp_bit_vec_dealloc", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern void sp_bit_vec_dealloc(BitVec* @this); public static extern void sp_bit_vec_dealloc(CBitVec* @this);
/// <summary>Gets the value of a bit from the `BitVec`. # Arguments * `this`: instance to read from * `index`: the bit index to read returns: value of the bit # Panics When accessing `index` out of bounds. # Safety The caller has to make sure that: - `this` points to a valid `BitVec` - `this` is not written to concurrently</summary> /// <summary>Gets the value of a bit from the `BitVec`. # Arguments * `this`: instance to read from * `index`: the bit index to read returns: value of the bit # Panics When accessing `index` out of bounds. # Safety The caller has to make sure that: - `this` points to a valid `BitVec` - `this` is not written to concurrently</summary>
[DllImport(__DllName, EntryPoint = "sp_bit_vec_get", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] [DllImport(__DllName, EntryPoint = "sp_bit_vec_get", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
[return: MarshalAs(UnmanagedType.U1)] [return: MarshalAs(UnmanagedType.U1)]
public static extern bool sp_bit_vec_get(BitVec* @this, nuint index); public static extern bool sp_bit_vec_get(CBitVec* @this, nuint index);
/// <summary>Sets the value of a bit in the `BitVec`. # Arguments * `this`: instance to write to * `index`: the bit index to edit * `value`: the value to set the bit to returns: old value of the bit # Panics When accessing `index` out of bounds. # Safety The caller has to make sure that: - `this` points to a valid `BitVec` - `this` is not written to or read from concurrently</summary> /// <summary>Sets the value of a bit in the `BitVec`. # Arguments * `this`: instance to write to * `index`: the bit index to edit * `value`: the value to set the bit to returns: old value of the bit # Panics When accessing `index` out of bounds. # Safety The caller has to make sure that: - `this` points to a valid `BitVec` - `this` is not written to or read from concurrently</summary>
[DllImport(__DllName, EntryPoint = "sp_bit_vec_set", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] [DllImport(__DllName, EntryPoint = "sp_bit_vec_set", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
[return: MarshalAs(UnmanagedType.U1)] public static extern void sp_bit_vec_set(CBitVec* @this, nuint index, [MarshalAs(UnmanagedType.U1)] bool value);
public static extern bool sp_bit_vec_set(BitVec* @this, nuint index, [MarshalAs(UnmanagedType.U1)] bool value);
/// <summary>Sets the value of all bits in the `BitVec`. # Arguments * `value`: the value to set all bits to # Safety The caller has to make sure that: - `this` points to a valid `BitVec` - `this` is not written to or read from concurrently</summary> /// <summary>Sets the value of all bits in the `BitVec`. # Arguments * `value`: the value to set all bits to # Safety The caller has to make sure that: - `this` points to a valid `BitVec` - `this` is not written to or read from concurrently</summary>
[DllImport(__DllName, EntryPoint = "sp_bit_vec_fill", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] [DllImport(__DllName, EntryPoint = "sp_bit_vec_fill", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern void sp_bit_vec_fill(BitVec* @this, [MarshalAs(UnmanagedType.U1)] bool value); public static extern void sp_bit_vec_fill(CBitVec* @this, [MarshalAs(UnmanagedType.U1)] bool value);
/// <summary>Gets the length of the `BitVec` in bits. # Safety The caller has to make sure that: - `this` points to a valid `BitVec`</summary> /// <summary>Gets the length of the `BitVec` in bits. # Safety The caller has to make sure that: - `this` points to a valid `BitVec`</summary>
[DllImport(__DllName, EntryPoint = "sp_bit_vec_len", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] [DllImport(__DllName, EntryPoint = "sp_bit_vec_len", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern nuint sp_bit_vec_len(BitVec* @this); public static extern nuint sp_bit_vec_len(CBitVec* @this);
/// <summary>Returns true if length is 0. # Safety The caller has to make sure that: - `this` points to a valid `BitVec`</summary> /// <summary>Returns true if length is 0. # Safety The caller has to make sure that: - `this` points to a valid `BitVec`</summary>
[DllImport(__DllName, EntryPoint = "sp_bit_vec_is_empty", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] [DllImport(__DllName, EntryPoint = "sp_bit_vec_is_empty", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
[return: MarshalAs(UnmanagedType.U1)] [return: MarshalAs(UnmanagedType.U1)]
public static extern bool sp_bit_vec_is_empty(BitVec* @this); public static extern bool sp_bit_vec_is_empty(CBitVec* @this);
/// <summary>Gets an unsafe reference to the data of the `BitVec` instance. ## Safety The caller has to make sure that: - `this` points to a valid `BitVec` - the returned memory range is never accessed after the passed `BitVec` has been freed - the returned memory range is never accessed concurrently, either via the `BitVec` or directly</summary> /// <summary>Gets an unsafe reference to the data of the `BitVec` instance. ## Safety The caller has to make sure that: - `this` points to a valid `BitVec` - the returned memory range is never accessed after the passed `BitVec` has been freed - the returned memory range is never accessed concurrently, either via the `BitVec` or directly</summary>
[DllImport(__DllName, EntryPoint = "sp_bit_vec_unsafe_data_ref", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] [DllImport(__DllName, EntryPoint = "sp_bit_vec_unsafe_data_ref", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern CByteSlice sp_bit_vec_unsafe_data_ref(BitVec* @this); public static extern CByteSlice sp_bit_vec_unsafe_data_ref(CBitVec* @this);
/// <summary>Creates a new `ByteGrid` with the specified dimensions. returns: `ByteGrid` initialized to 0. # Safety The caller has to make sure that: - the returned instance is freed in some way, either by using a consuming function or by explicitly calling `sp_byte_grid_dealloc`.</summary> /// <summary>Creates a new `ByteGrid` with the specified dimensions. returns: `ByteGrid` initialized to 0. # Safety The caller has to make sure that: - the returned instance is freed in some way, either by using a consuming function or by explicitly calling `sp_byte_grid_dealloc`.</summary>
[DllImport(__DllName, EntryPoint = "sp_byte_grid_new", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] [DllImport(__DllName, EntryPoint = "sp_byte_grid_new", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
@ -132,19 +131,19 @@ namespace ServicePoint.BindGen
/// <summary>Allocates a new `Command::BitmapLinear` instance. The passed `BitVec` gets consumed. # Safety The caller has to make sure that: - `bit_vec` points to a valid instance of `BitVec` - `bit_vec` is not used concurrently or after this call - `compression` matches one of the allowed enum values - the returned `Command` instance is freed in some way, either by using a consuming function or by explicitly calling `sp_command_dealloc`.</summary> /// <summary>Allocates a new `Command::BitmapLinear` instance. The passed `BitVec` gets consumed. # Safety The caller has to make sure that: - `bit_vec` points to a valid instance of `BitVec` - `bit_vec` is not used concurrently or after this call - `compression` matches one of the allowed enum values - the returned `Command` instance is freed in some way, either by using a consuming function or by explicitly calling `sp_command_dealloc`.</summary>
[DllImport(__DllName, EntryPoint = "sp_command_bitmap_linear", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] [DllImport(__DllName, EntryPoint = "sp_command_bitmap_linear", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern Command* sp_command_bitmap_linear(nuint offset, BitVec* bit_vec, CompressionCode compression); public static extern Command* sp_command_bitmap_linear(nuint offset, CBitVec* bit_vec, CompressionCode compression);
/// <summary>Allocates a new `Command::BitmapLinearAnd` instance. The passed `BitVec` gets consumed. # Safety The caller has to make sure that: - `bit_vec` points to a valid instance of `BitVec` - `bit_vec` is not used concurrently or after this call - `compression` matches one of the allowed enum values - the returned `Command` instance is freed in some way, either by using a consuming function or by explicitly calling `sp_command_dealloc`.</summary> /// <summary>Allocates a new `Command::BitmapLinearAnd` instance. The passed `BitVec` gets consumed. # Safety The caller has to make sure that: - `bit_vec` points to a valid instance of `BitVec` - `bit_vec` is not used concurrently or after this call - `compression` matches one of the allowed enum values - the returned `Command` instance is freed in some way, either by using a consuming function or by explicitly calling `sp_command_dealloc`.</summary>
[DllImport(__DllName, EntryPoint = "sp_command_bitmap_linear_and", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] [DllImport(__DllName, EntryPoint = "sp_command_bitmap_linear_and", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern Command* sp_command_bitmap_linear_and(nuint offset, BitVec* bit_vec, CompressionCode compression); public static extern Command* sp_command_bitmap_linear_and(nuint offset, CBitVec* bit_vec, CompressionCode compression);
/// <summary>Allocates a new `Command::BitmapLinearOr` instance. The passed `BitVec` gets consumed. # Safety The caller has to make sure that: - `bit_vec` points to a valid instance of `BitVec` - `bit_vec` is not used concurrently or after this call - `compression` matches one of the allowed enum values - the returned `Command` instance is freed in some way, either by using a consuming function or by explicitly calling `sp_command_dealloc`.</summary> /// <summary>Allocates a new `Command::BitmapLinearOr` instance. The passed `BitVec` gets consumed. # Safety The caller has to make sure that: - `bit_vec` points to a valid instance of `BitVec` - `bit_vec` is not used concurrently or after this call - `compression` matches one of the allowed enum values - the returned `Command` instance is freed in some way, either by using a consuming function or by explicitly calling `sp_command_dealloc`.</summary>
[DllImport(__DllName, EntryPoint = "sp_command_bitmap_linear_or", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] [DllImport(__DllName, EntryPoint = "sp_command_bitmap_linear_or", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern Command* sp_command_bitmap_linear_or(nuint offset, BitVec* bit_vec, CompressionCode compression); public static extern Command* sp_command_bitmap_linear_or(nuint offset, CBitVec* bit_vec, CompressionCode compression);
/// <summary>Allocates a new `Command::BitmapLinearXor` instance. The passed `BitVec` gets consumed. # Safety The caller has to make sure that: - `bit_vec` points to a valid instance of `BitVec` - `bit_vec` is not used concurrently or after this call - `compression` matches one of the allowed enum values - the returned `Command` instance is freed in some way, either by using a consuming function or by explicitly calling `sp_command_dealloc`.</summary> /// <summary>Allocates a new `Command::BitmapLinearXor` instance. The passed `BitVec` gets consumed. # Safety The caller has to make sure that: - `bit_vec` points to a valid instance of `BitVec` - `bit_vec` is not used concurrently or after this call - `compression` matches one of the allowed enum values - the returned `Command` instance is freed in some way, either by using a consuming function or by explicitly calling `sp_command_dealloc`.</summary>
[DllImport(__DllName, EntryPoint = "sp_command_bitmap_linear_xor", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] [DllImport(__DllName, EntryPoint = "sp_command_bitmap_linear_xor", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern Command* sp_command_bitmap_linear_xor(nuint offset, BitVec* bit_vec, CompressionCode compression); public static extern Command* sp_command_bitmap_linear_xor(nuint offset, CBitVec* bit_vec, CompressionCode compression);
/// <summary>Allocates a new `Command::Cp437Data` instance. The passed `ByteGrid` gets consumed. # Safety The caller has to make sure that: - `byte_grid` points to a valid instance of `ByteGrid` - `byte_grid` is not used concurrently or after this call - the returned `Command` instance is freed in some way, either by using a consuming function or by explicitly calling `sp_command_dealloc`.</summary> /// <summary>Allocates a new `Command::Cp437Data` instance. The passed `ByteGrid` gets consumed. # Safety The caller has to make sure that: - `byte_grid` points to a valid instance of `ByteGrid` - `byte_grid` is not used concurrently or after this call - the returned `Command` instance is freed in some way, either by using a consuming function or by explicitly calling `sp_command_dealloc`.</summary>
[DllImport(__DllName, EntryPoint = "sp_command_cp437_data", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] [DllImport(__DllName, EntryPoint = "sp_command_cp437_data", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
@ -227,6 +226,11 @@ namespace ServicePoint.BindGen
} }
[StructLayout(LayoutKind.Sequential)]
public unsafe partial struct CBitVec
{
}
[StructLayout(LayoutKind.Sequential)] [StructLayout(LayoutKind.Sequential)]
public unsafe partial struct CByteSlice public unsafe partial struct CByteSlice
{ {
@ -234,11 +238,6 @@ namespace ServicePoint.BindGen
public nuint length; public nuint length;
} }
[StructLayout(LayoutKind.Sequential)]
public unsafe partial struct BitVec
{
}
[StructLayout(LayoutKind.Sequential)] [StructLayout(LayoutKind.Sequential)]
public unsafe partial struct ByteGrid public unsafe partial struct ByteGrid
{ {

View file

@ -2,7 +2,7 @@ using ServicePoint.BindGen;
namespace ServicePoint; namespace ServicePoint;
public sealed class BitVec : SpNativeInstance<BindGen.BitVec> public sealed class BitVec : SpNativeInstance<BindGen.CBitVec>
{ {
public static BitVec New(int size) public static BitVec New(int size)
{ {
@ -80,7 +80,7 @@ public sealed class BitVec : SpNativeInstance<BindGen.BitVec>
} }
} }
private unsafe BitVec(BindGen.BitVec* instance) : base(instance) private unsafe BitVec(BindGen.CBitVec* instance) : base(instance)
{ {
} }

View file

@ -27,19 +27,19 @@
</PropertyGroup> </PropertyGroup>
<!-- generate C# bindings --> <!-- generate C# bindings -->
<Target Name="BuildBindings" Condition="'$(Configuration)'=='Release'" BeforeTargets="Build"> <Target Name="BuildBindings" Condition="'$(Configuration)'=='Release'" BeforeTargets="PrepareForBuild">
<Exec Command="cargo build --release"/> <Exec Command="cargo build --release"/>
<Exec Command="cargo build --manifest-path ../../../crates/servicepoint_binding_c/Cargo.toml --release"/>
</Target> </Target>
<Target Name="BuildBindings" Condition="'$(Configuration)'=='Debug'" BeforeTargets="Build"> <Target Name="BuildBindings" Condition="'$(Configuration)'=='Debug'" BeforeTargets="PrepareForBuild">
<Exec Command="cargo build"/> <Exec Command="cargo build"/>
<Exec Command="cargo build --manifest-path ../../../crates/servicepoint_binding_c/Cargo.toml"/>
</Target> </Target>
<!-- build native library to include in output --> <!-- build native library to include in output -->
<Target Name="BuildLibrary" Condition="'$(Configuration)'=='Release'" BeforeTargets="Build"> <Target Name="BuildLibrary" Condition="'$(Configuration)'=='Release'" BeforeTargets="PrepareForBuild">
<Exec Command="cargo build --manifest-path ../../../crates/servicepoint/Cargo.toml --release"/>
</Target> </Target>
<Target Name="BuildLibrary" Condition="'$(Configuration)'=='Debug'" BeforeTargets="Build"> <Target Name="BuildLibrary" Condition="'$(Configuration)'=='Debug'" BeforeTargets="PrepareForBuild">
<Exec Command="cargo build --manifest-path ../../../crates/servicepoint/Cargo.toml"/>
</Target> </Target>
<!-- include native binary in output --> <!-- include native binary in output -->

View file

@ -12,7 +12,6 @@ fn main() {
.input_extern_file("../servicepoint_binding_c/src/lib.rs") .input_extern_file("../servicepoint_binding_c/src/lib.rs")
.input_extern_file("../servicepoint_binding_c/src/c_slice.rs") .input_extern_file("../servicepoint_binding_c/src/c_slice.rs")
.input_extern_file("../servicepoint_binding_c/src/packet.rs") .input_extern_file("../servicepoint_binding_c/src/packet.rs")
.input_extern_file("../servicepoint/src/bit_vec.rs")
.input_extern_file("../servicepoint/src/byte_grid.rs") .input_extern_file("../servicepoint/src/byte_grid.rs")
.input_extern_file("../servicepoint/src/command.rs") .input_extern_file("../servicepoint/src/command.rs")
.input_extern_file("../servicepoint/src/connection.rs") .input_extern_file("../servicepoint/src/connection.rs")