Skip to content

Commit

Permalink
Making some progress integrating Remglk-rs into Emglken. DispatchRock…
Browse files Browse the repository at this point in the history
… has to be a union, and because of the WASM ABI, it can't be returned from functions
  • Loading branch information
curiousdannii committed Feb 21, 2024
1 parent 7a1b3a6 commit 33318d9
Show file tree
Hide file tree
Showing 10 changed files with 90 additions and 58 deletions.
10 changes: 9 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,12 @@ members = [
resolver = "2"

[profile.release]
lto = true
lto = true

[profile.dev-wasm]
inherits = "dev"
panic = "abort"

[profile.release-wasm]
inherits = "release"
panic = "abort"
46 changes: 31 additions & 15 deletions remglk/src/glkapi/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -213,13 +213,18 @@ where S: Default + GlkSystem {
let update = self.update();
self.system.send_glkote_update(update);
let event = self.system.get_glkote_event();
let res = self.handle_event(event)?;
if let Some(fref) = res.fref {
let (filename, fref) = match fref {
FileRefResponse::String(filename) => (filename, None),
FileRefResponse::Fref(fref) => (fref.filename.clone(), Some(fref)),
};
return Ok(Some(self.create_fileref(filename, rock, usage, fref)));
if let Some(event) = event {
let res = self.handle_event(event)?;
if let Some(fref) = res.fref {
let (filename, fref) = match fref {
FileRefResponse::String(filename) => (filename, None),
FileRefResponse::Fref(fref) => (fref.filename.clone(), Some(fref)),
};
return Ok(Some(self.create_fileref(filename, rock, usage, fref)));
}
}
else {
self.glk_exit();
}
Ok(None)
}
Expand Down Expand Up @@ -455,7 +460,13 @@ where S: Default + GlkSystem {
let update = self.update();
self.system.send_glkote_update(update);
let event = self.system.get_glkote_event();
self.handle_event(event)
if let Some(event) = event {
self.handle_event(event)
}
else {
self.glk_exit();
Ok(GlkEvent::default())
}
}

pub fn glk_select_poll(&mut self) -> GlkEvent {
Expand Down Expand Up @@ -1019,7 +1030,12 @@ where S: Default + GlkSystem {

pub fn get_glkote_init(&mut self) {
let event = self.system.get_glkote_event();
self.handle_event(event).unwrap();
if let Some(event) = event {
self.handle_event(event).unwrap();
}
else {
self.glk_exit();
}
}

pub fn handle_event(&mut self, mut event: Event) -> GlkResult<GlkEvent> {
Expand Down Expand Up @@ -1257,7 +1273,7 @@ where S: Default + GlkSystem {
Ok(Some(str))
}

fn create_memory_stream<T>(&mut self, buf: Box<[T]>, fmode: FileMode, rock: u32, disprock: Option<DispatchRockPtr>) -> GlkResult<GlkStream>
fn create_memory_stream<T>(&mut self, buf: Box<[T]>, fmode: FileMode, rock: u32, disprock: Option<DispatchRock>) -> GlkResult<GlkStream>
where Stream: From<ArrayBackedStream<T>> {
if fmode == FileMode::WriteAppend {
return Err(IllegalFilemode);
Expand Down Expand Up @@ -1545,14 +1561,14 @@ where S: Default + GlkSystem {
Ok(())
}

pub fn retain_array(&self, buf: &GlkBuffer) -> DispatchRockPtr {
pub fn retain_array(&self, buf: &GlkBuffer) -> DispatchRock {
match buf {
GlkBuffer::U8(buf) => (self.retain_array_callbacks_u8.as_ref().unwrap().retain)(buf.as_ptr(), buf.len() as u32, "&+#!Cn".as_ptr()),
GlkBuffer::U32(buf) => (self.retain_array_callbacks_u32.as_ref().unwrap().retain)(buf.as_ptr(), buf.len() as u32, "&+#!Iu".as_ptr()),
}
}

pub fn unretain_array(&self, buf: GlkOwnedBuffer, disprock: DispatchRockPtr) {
pub fn unretain_array(&self, buf: GlkOwnedBuffer, disprock: DispatchRock) {
let len = buf.len() as u32;
match buf {
GlkOwnedBuffer::U8(buf) => (self.retain_array_callbacks_u8.as_ref().unwrap().unretain)(Box::leak(buf).as_ptr(), len, "&+#!Cn".as_ptr(), disprock),
Expand Down Expand Up @@ -1593,8 +1609,8 @@ pub struct GlkDate {
}

// Retained array callbacks
pub type RetainArrayCallback<T> = extern fn(*const T, u32, *const u8) -> DispatchRockPtr;
pub type UnretainArrayCallback<T> = extern fn(*const T, u32, *const u8, DispatchRockPtr);
pub type RetainArrayCallback<T> = extern fn(*const T, u32, *const u8) -> DispatchRock;
pub type UnretainArrayCallback<T> = extern fn(*const T, u32, *const u8, DispatchRock);

pub struct RetainArrayCallbacks<T> {
pub retain: RetainArrayCallback<T>,
Expand Down Expand Up @@ -1708,7 +1724,7 @@ fn glkdate_to_datetime<T: TimeZone>(timezone: T, date: &GlkDate) -> DateTime<T>
normalised_date = normalised_date.checked_add_months(chrono::Months::new(months as u32)).unwrap();
}
if months < 0 {
normalised_date = normalised_date.checked_sub_months(chrono::Months::new(months as u32)).unwrap();
normalised_date = normalised_date.checked_sub_months(chrono::Months::new((-months) as u32)).unwrap();
}
let mut normalised_date = NaiveDateTime::from(normalised_date).and_utc();
let duration = Duration::days(date.day as i64 - 1)
Expand Down
18 changes: 12 additions & 6 deletions remglk/src/glkapi/objects.rs
Original file line number Diff line number Diff line change
Expand Up @@ -196,8 +196,8 @@ where T: Default + GlkObjectClass, GlkObject<T>: Default + Eq {
/** Contains the private metadata we keep in each object store */
#[derive(Default)]
pub struct GlkObjectMetadata<T> {
pub array_disprock: Option<DispatchRockPtr>,
pub disprock: Option<DispatchRockPtr>,
pub array_disprock: Option<DispatchRock>,
pub disprock: Option<DispatchRock>,
/** The ID, used in the GlkOte protocol */
pub id: u32,
obj: T,
Expand Down Expand Up @@ -241,14 +241,20 @@ impl<T> DerefMut for GlkObjectMetadata<T> {
/** A dispatch rock, which could be anything (*not* the same as a normal Glk rock) */
// See for explanation https://stackoverflow.com/a/38315613/2854284
#[repr(C)]
pub struct DispatchRock {
pub struct DispatchRockPtr {
_data: [u8; 0],
_marker: core::marker::PhantomData<(*mut u8, core::marker::PhantomPinned)>,
}
pub type DispatchRockPtr = *const DispatchRock;

pub type DispatchRegisterCallback<T> = fn(*const Mutex<GlkObjectMetadata<T>>, u32) -> DispatchRockPtr;
pub type DispatchUnregisterCallback<T> = fn(*const Mutex<GlkObjectMetadata<T>>, u32, DispatchRockPtr);
#[derive(Clone, Copy)]
#[repr(C)]
pub union DispatchRock {
num: u32,
ptr: *const DispatchRockPtr,
}

pub type DispatchRegisterCallback<T> = fn(*const Mutex<GlkObjectMetadata<T>>, u32) -> DispatchRock;
pub type DispatchUnregisterCallback<T> = fn(*const Mutex<GlkObjectMetadata<T>>, u32, DispatchRock);

pub trait GlkObjectClass {
fn get_object_class_id() -> u32;
Expand Down
2 changes: 1 addition & 1 deletion remglk/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,5 +29,5 @@ pub trait GlkSystem {
/** Send an update to GlkOte */
fn send_glkote_update(&mut self, update: Update);
/** Get an event from GlkOte */
fn get_glkote_event(&mut self) -> Event;
fn get_glkote_event(&mut self) -> Option<Event>;
}
4 changes: 2 additions & 2 deletions remglk_capi/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,12 @@ crate-type=["staticlib"]

[dependencies]
remglk = {path = "../remglk", version = "0.1.0"}
serde = {version = "1.0"}
serde = "1.0"
serde_json = "1.0"
thiserror = "1.0.40"
widestring = "1.0.2"

[target.'cfg(emscripten)'.dependencies]
[target.'cfg(target_os = "emscripten")'.dependencies]
emscripten_em_js = {path = "../emscripten_em_js", version = "0.1.0"}

[build-dependencies]
Expand Down
21 changes: 11 additions & 10 deletions remglk_capi/src/dispatch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ use super::*;
use common::*;
use glkapi::*;

type RegisterCallbackGeneric = extern fn(*const c_void, u32) -> DispatchRockPtr;
type UnregisterCallbackGeneric = extern fn(*const c_void, u32, DispatchRockPtr);
type RegisterCallbackGeneric = extern fn(*const c_void, u32) -> DispatchRock;
type UnregisterCallbackGeneric = extern fn(*const c_void, u32, DispatchRock);

#[no_mangle]
pub unsafe extern "C" fn gidispatch_set_object_registry(register_cb: RegisterCallbackGeneric, unregister_cb: UnregisterCallbackGeneric) {
Expand All @@ -37,29 +37,30 @@ pub unsafe extern "C" fn gidispatch_set_object_registry(register_cb: RegisterCal
}

// The C function `gidispatch_get_objrock` takes a generic pointer, which we can't really deal with here in Rust, so support.c will handle calling the appropriate function
// The WASM ABI means that we can't return a DispatchRock, so it must be set through an out parameter
#[no_mangle]
pub extern "C" fn gidispatch_get_objrock_fileref(ptr: FileRefPtr) -> DispatchRockPtr {
pub extern "C" fn gidispatch_get_objrock_fileref(ptr: FileRefPtr, dispatchrock_ptr: *mut DispatchRock) {
let obj = from_ptr(ptr);
let obj = obj.lock().unwrap();
obj.disprock.unwrap()
write_ptr(dispatchrock_ptr, obj.disprock.unwrap());
}

#[no_mangle]
pub extern "C" fn gidispatch_get_objrock_stream(ptr: StreamPtr) -> DispatchRockPtr {
pub extern "C" fn gidispatch_get_objrock_stream(ptr: StreamPtr, dispatchrock_ptr: *mut DispatchRock) {
let obj = from_ptr(ptr);
let obj = obj.lock().unwrap();
obj.disprock.unwrap()
write_ptr(dispatchrock_ptr, obj.disprock.unwrap());
}

#[no_mangle]
pub extern "C" fn gidispatch_get_objrock_window(ptr: WindowPtr) -> DispatchRockPtr {
pub extern "C" fn gidispatch_get_objrock_window(ptr: WindowPtr, dispatchrock_ptr: *mut DispatchRock) {
let obj = from_ptr(ptr);
let obj = obj.lock().unwrap();
obj.disprock.unwrap()
write_ptr(dispatchrock_ptr, obj.disprock.unwrap());
}

type RetainArrayCallbackGeneric = extern fn(*const c_void, u32, *const c_char) -> DispatchRockPtr;
type UnretainArrayCallbackGeneric = extern fn(*const c_void, u32, *const c_char, DispatchRockPtr);
type RetainArrayCallbackGeneric = extern fn(*const c_void, u32, *const c_char) -> DispatchRock;
type UnretainArrayCallbackGeneric = extern fn(*const c_void, u32, *const c_char, DispatchRock);

#[no_mangle]
pub unsafe extern "C" fn gidispatch_set_retained_registry(register_cb: RetainArrayCallbackGeneric, unregister_cb: UnretainArrayCallbackGeneric) {
Expand Down
12 changes: 9 additions & 3 deletions remglk_capi/src/glk/support.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,19 @@ MIT licenced
#include "support.h"

gidispatch_rock_t gidispatch_get_objrock(void *obj, glui32 objclass) {
gidispatch_rock_t rock;
switch (objclass) {
case gidisp_Class_Fileref:
return gidispatch_get_objrock_fileref(obj);
gidispatch_get_objrock_fileref(obj, &rock);
return rock;
case gidisp_Class_Stream:
return gidispatch_get_objrock_stream(obj);
gidispatch_get_objrock_stream(obj, &rock);
return rock;
case gidisp_Class_Window:
return gidispatch_get_objrock_window(obj);
gidispatch_get_objrock_window(obj, &rock);
return rock;
default:
__builtin_unreachable();
}
}

Expand Down
6 changes: 3 additions & 3 deletions remglk_capi/src/glk/support.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@
#include "gi_dispa.h"
#include "glkstart.h"

extern gidispatch_rock_t gidispatch_get_objrock_fileref(void *obj);
extern gidispatch_rock_t gidispatch_get_objrock_stream(void *obj);
extern gidispatch_rock_t gidispatch_get_objrock_window(void *obj);
extern void gidispatch_get_objrock_fileref(void *obj, gidispatch_rock_t *rock_ptr);
extern void gidispatch_get_objrock_stream(void *obj, gidispatch_rock_t *rock_ptr);
extern void gidispatch_get_objrock_window(void *obj, gidispatch_rock_t *rock_ptr);

glkunix_argumentlist_t *glkunix_arguments_addr(void);

Expand Down
23 changes: 9 additions & 14 deletions remglk_capi/src/systems/emglken.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,8 @@ https://github.com/curiousdannii/remglk-rs
*/

use std::collections::HashMap;
use std::env::temp_dir;
use std::fs;
use std::io::{self, BufRead};
use std::path::Path;

use emscripten_em_js::em_js;
//use emscripten_em_js::em_js;

use super::*;
use remglk::GlkSystem;
Expand All @@ -32,8 +28,7 @@ pub fn glkapi() -> &'static Mutex<GlkApi> {

#[derive(Default)]
pub struct EmglkenSystem {
cache: HashMap<String, Box<[u8]>>,
tempfile_counter: u32,
_cache: HashMap<String, Box<[u8]>>,
}

impl GlkSystem for EmglkenSystem {
Expand All @@ -46,35 +41,35 @@ impl GlkSystem for EmglkenSystem {
}
}

fn fileref_delete(&mut self, fileref: &SystemFileRef) {
fn fileref_delete(&mut self, _fileref: &SystemFileRef) {
unimplemented!()
}

fn fileref_exists(&mut self, fileref: &SystemFileRef) -> bool {
fn fileref_exists(&mut self, _fileref: &SystemFileRef) -> bool {
unimplemented!()
}

fn fileref_read(&mut self, fileref: &SystemFileRef) -> Option<Box<[u8]>> {
fn fileref_read(&mut self, _fileref: &SystemFileRef) -> Option<Box<[u8]>> {
unimplemented!()
}

fn fileref_temporary(&mut self, filetype: FileType) -> SystemFileRef {
fn fileref_temporary(&mut self, _filetype: FileType) -> SystemFileRef {
unimplemented!()
}

fn fileref_write_buffer(&mut self, fileref: &SystemFileRef, buf: Box<[u8]>) {
fn fileref_write_buffer(&mut self, _fileref: &SystemFileRef, _buf: Box<[u8]>) {
unimplemented!()
}

fn flush_writeable_files(&mut self) {
unimplemented!()
}

fn get_glkote_event(&mut self) -> Event {
fn get_glkote_event(&mut self) -> Option<Event> {
unimplemented!()
}

fn send_glkote_update(&mut self, update: Update) {
fn send_glkote_update(&mut self, _update: Update) {
unimplemented!()
}
}
6 changes: 3 additions & 3 deletions remglk_capi/src/systems/standard.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ impl GlkSystem for StandardSystem {
self.cache.shrink_to(4);
}

fn get_glkote_event(&mut self) -> Event {
fn get_glkote_event(&mut self) -> Option<Event> {
// Read a line from stdin
let stdin = io::stdin();
for line in stdin.lock().lines() {
Expand All @@ -94,9 +94,9 @@ impl GlkSystem for StandardSystem {
continue;
}
let event: Event = serde_json::from_str(&data).unwrap();
return event;
return Some(event);
}
unreachable!()
None
}

fn send_glkote_update(&mut self, update: Update) {
Expand Down

0 comments on commit 33318d9

Please sign in to comment.