Skip to content

Commit

Permalink
add uniffi CharGrid
Browse files Browse the repository at this point in the history
  • Loading branch information
kaesaecracker committed Nov 13, 2024
1 parent 9553d9f commit d0d70c0
Show file tree
Hide file tree
Showing 9 changed files with 755 additions and 10 deletions.
2 changes: 1 addition & 1 deletion crates/servicepoint_binding_uniffi/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ uniffi = { version = "0.25.0", features = ["build"] }

[dependencies]
uniffi = { version = "0.25.0" }
thiserror = "1.0.66"
thiserror.workspace = true

[dependencies.servicepoint]
version = "0.11.0"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
namespace ServicePoint.Tests;

public class CharGridTests
{
[Fact]
public void BasicFunctions()
{
var grid = new CharGrid(8, 2);
Assert.Equal("\0", grid.Get(0, 0));
Assert.Equal("\0", grid.Get(grid.Width() - 1, grid.Height() - 1));
grid.Fill(" ");
Assert.Equal(" ", grid.Get(1, 1));
grid.Set(1, 1, "-");
Assert.Equal("-", grid.Get(1, 1));
Assert.Throws<PanicException>(() => grid.Get(8, 2));
}

[Fact]
public void RowAndCol()
{
var grid = new CharGrid(3, 2);
Assert.Equal("\0\0\0", grid.GetRow(0));
grid.Fill(" ");
Assert.Equal(" ", grid.GetCol(1));
Assert.Throws<CharGridException.OutOfBounds>(() => grid.GetCol(3));
Assert.Throws<CharGridException.InvalidSeriesLength>(() => grid.SetRow(1, "Text"));
grid.SetRow(1, "Foo");
Assert.Equal("Foo", grid.GetRow(1));
Assert.Equal(" o", grid.GetCol(2));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,6 @@ public void HardResetSendable()
[Fact]
public void BitmapLinearWinSendable()
{
_connection.Send(Command.BitmapLinearWin(0, 0, Bitmap.NewMaxSized()));
_connection.Send(Command.BitmapLinearWin(0, 0, Bitmap.NewMaxSized(), CompressionCode.Uncompressed));
}
}

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion crates/servicepoint_binding_uniffi/src/bitmap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ impl Bitmap {
let b = other.actual.read().unwrap();
*a == *b
}

pub fn copy_raw(&self) -> Vec<u8> {
self.actual.read().unwrap().data_ref().to_vec()
}
Expand Down
8 changes: 7 additions & 1 deletion crates/servicepoint_binding_uniffi/src/brightness_grid.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,12 @@ impl BrightnessGrid {
}

pub fn copy_raw(&self) -> Vec<u8> {
self.actual.read().unwrap().data_ref().iter().map(u8::from).collect()
self.actual
.read()
.unwrap()
.data_ref()
.iter()
.map(u8::from)
.collect()
}
}
163 changes: 163 additions & 0 deletions crates/servicepoint_binding_uniffi/src/char_grid.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
use servicepoint::{Grid, SeriesError};
use std::convert::Into;
use std::sync::{Arc, RwLock};
use crate::cp437_grid::Cp437Grid;

#[derive(uniffi::Object)]
pub struct CharGrid {
pub(crate) actual: RwLock<servicepoint::CharGrid>,
}

#[derive(uniffi::Error, thiserror::Error, Debug)]
pub enum CharGridError {
#[error("Exactly one character was expected, but {value:?} was provided")]
StringNotOneChar { value: String },
#[error("The provided series was expected to have a length of {expected}, but was {actual}")]
InvalidSeriesLength { actual: u64, expected: u64 },
#[error("The index {index} was out of bounds for size {size}")]
OutOfBounds { index: u64, size: u64 },
}

#[uniffi::export]
impl CharGrid {
#[uniffi::constructor]
pub fn new(width: u64, height: u64) -> Arc<Self> {
Self::internal_new(servicepoint::CharGrid::new(
width as usize,
height as usize,
))
}

#[uniffi::constructor]
pub fn load(data: String) -> Arc<Self> {
Self::internal_new(servicepoint::CharGrid::from(&*data))
}

#[uniffi::constructor]
pub fn clone(other: &Arc<Self>) -> Arc<Self> {
Self::internal_new(other.actual.read().unwrap().clone())
}

pub fn set(
&self,
x: u64,
y: u64,
value: String,
) -> Result<(), CharGridError> {
let value = Self::str_to_char(value)?;
self.actual
.write()
.unwrap()
.set(x as usize, y as usize, value);
Ok(())
}

pub fn get(&self, x: u64, y: u64) -> String {
self.actual
.read()
.unwrap()
.get(x as usize, y as usize)
.into()
}

pub fn fill(&self, value: String) -> Result<(), CharGridError> {
let value = Self::str_to_char(value)?;
self.actual.write().unwrap().fill(value);
Ok(())
}

pub fn width(&self) -> u64 {
self.actual.read().unwrap().width() as u64
}

pub fn height(&self) -> u64 {
self.actual.read().unwrap().height() as u64
}

pub fn equals(&self, other: &CharGrid) -> bool {
let a = self.actual.read().unwrap();
let b = other.actual.read().unwrap();
*a == *b
}

pub fn as_string(&self) -> String {
let grid = self.actual.read().unwrap();
String::from(&*grid)
}

pub fn set_row(&self, y: u64, row: String) -> Result<(), CharGridError> {
self.actual
.write()
.unwrap()
.set_row(y as usize, &*row.chars().collect::<Vec<_>>())
.map_err(CharGridError::from)
}

pub fn set_col(&self, x: u64, col: String) -> Result<(), CharGridError> {
self.actual
.write()
.unwrap()
.set_row(x as usize, &*col.chars().collect::<Vec<_>>())
.map_err(CharGridError::from)
}

pub fn get_row(&self, y: u64) -> Result<String, CharGridError> {
self.actual
.read()
.unwrap()
.get_row(y as usize)
.map(move |vec| String::from_iter(vec))
.ok_or(CharGridError::OutOfBounds {index: y, size: self.height()})
}

pub fn get_col(&self, x: u64) -> Result<String, CharGridError> {
self.actual
.read()
.unwrap()
.get_col(x as usize)
.map(move |vec| String::from_iter(vec))
.ok_or(CharGridError::OutOfBounds {index: x, size: self.width()})
}

pub fn to_cp437(&self) -> Arc<Cp437Grid> {
Cp437Grid::internal_new(servicepoint::Cp437Grid::from(&*self.actual.read().unwrap()))
}
}

impl CharGrid {
pub(crate) fn internal_new(actual: servicepoint::CharGrid) -> Arc<Self> {
Arc::new(Self {
actual: RwLock::new(actual),
})
}

fn str_to_char(value: String) -> Result<char, CharGridError> {
if value.len() != 1 {
return Err(CharGridError::StringNotOneChar {
value,
});
}

let value = value.chars().nth(0).unwrap();
Ok(value)
}
}

impl From<SeriesError> for CharGridError {
fn from(e: SeriesError) -> Self {
match e {
SeriesError::OutOfBounds { index, size } => {
CharGridError::OutOfBounds {
index: index as u64,
size: size as u64,
}
}
SeriesError::InvalidLength { actual, expected } => {
CharGridError::InvalidSeriesLength {
actual: actual as u64,
expected: expected as u64,
}
}
}
}
}
13 changes: 7 additions & 6 deletions crates/servicepoint_binding_uniffi/src/cp437_grid.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
use servicepoint::{DataRef, Grid};
use std::sync::{Arc, RwLock};
use crate::char_grid::CharGrid;

#[derive(uniffi::Object)]
pub struct Cp437Grid {
pub(crate) actual: RwLock<servicepoint::Cp437Grid>,
}

impl Cp437Grid {
fn internal_new(actual: servicepoint::Cp437Grid) -> Arc<Self> {
pub(crate) fn internal_new(actual: servicepoint::Cp437Grid) -> Arc<Self> {
Arc::new(Self {
actual: RwLock::new(actual),
})
Expand Down Expand Up @@ -46,11 +47,7 @@ impl Cp437Grid {
}

pub fn get(&self, x: u64, y: u64) -> u8 {
self.actual
.read()
.unwrap()
.get(x as usize, y as usize)
.into()
self.actual.read().unwrap().get(x as usize, y as usize)
}

pub fn fill(&self, value: u8) {
Expand All @@ -73,4 +70,8 @@ impl Cp437Grid {
pub fn copy_raw(&self) -> Vec<u8> {
self.actual.read().unwrap().data_ref().to_vec()
}

pub fn to_utf8(&self) -> Arc<CharGrid> {
CharGrid::internal_new(servicepoint::CharGrid::from(&*self.actual.read().unwrap()))
}
}
1 change: 1 addition & 0 deletions crates/servicepoint_binding_uniffi/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ uniffi::setup_scaffolding!();
mod bitmap;
mod bitvec;
mod brightness_grid;
mod char_grid;
mod command;
mod compression_code;
mod connection;
Expand Down

0 comments on commit d0d70c0

Please sign in to comment.