Skip to content

Commit 149c5cf

Browse files
authored
Add host functions that have to run on the tick and futures (#8)
* Add rust crate * Add futures * Add redstone functions * Update rust crate
1 parent 4f3aae6 commit 149c5cf

File tree

23 files changed

+574
-26
lines changed

23 files changed

+574
-26
lines changed

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,4 +25,4 @@ run-data
2525

2626
repo
2727

28-
.DS_Store
28+
.DS_Store

rustedcomputer-rs/.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
.DS_Store
2+
target/

rustedcomputer-rs/Cargo.lock

Lines changed: 65 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

rustedcomputer-rs/Cargo.toml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
[package]
2+
name = "rustedcomputer"
3+
version = "0.1.0"
4+
edition = "2024"
5+
license = "MPL-2.0"
6+
description = "Programmable Computers in Minecraft with WebAssembly"
7+
homepage = "https://github.com/TheBlckbird/rustedcomputer"
8+
repository = "https://github.com/TheBlckbird/rustedcomputer"
9+
readme = "Readme.md"
10+
11+
[dependencies]
12+
thiserror = "2.0.16"

rustedcomputer-rs/Readme.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# Rusted Computer
2+
3+
This is a reserved crate. It will later be the wrapper crate for [github.com/TheBlckbird/rustedcomputer](https://github.com/TheBlckbird/rustedcomputer).
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
use std::ops::{Deref, DerefMut};
2+
3+
pub struct FutureId(i32);
4+
5+
impl From<i32> for FutureId {
6+
fn from(value: i32) -> Self {
7+
Self(value)
8+
}
9+
}
10+
11+
impl Deref for FutureId {
12+
type Target = i32;
13+
14+
fn deref(&self) -> &Self::Target {
15+
&self.0
16+
}
17+
}
18+
19+
impl DerefMut for FutureId {
20+
fn deref_mut(&mut self) -> &mut Self::Target {
21+
&mut self.0
22+
}
23+
}
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
use std::pin::Pin;
2+
use std::{ptr, slice, thread};
3+
use std::task::{Context, Poll, RawWaker, RawWakerVTable, Waker};
4+
use std::time::Duration;
5+
use crate::async_runtime::future_id::FutureId;
6+
use crate::error::{Result, RustedComputerError};
7+
8+
pub mod future_id;
9+
10+
pub struct RustedComputerFuture<T, F>
11+
where
12+
F: Fn(String) -> T,
13+
{
14+
pub id: FutureId,
15+
pub converter: F,
16+
}
17+
18+
impl<T, F> RustedComputerFuture<T, F>
19+
where
20+
F: Fn(String) -> T,
21+
{
22+
pub fn new<G>(caller: G, converter: F) -> Self
23+
where
24+
G: Fn() -> FutureId,
25+
{
26+
let id = caller();
27+
Self { id, converter }
28+
}
29+
}
30+
31+
impl<T, F> Future for RustedComputerFuture<T, F>
32+
where
33+
F: Fn(String) -> T,
34+
{
35+
type Output = Result<T>;
36+
37+
fn poll(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<Self::Output> {
38+
let poll_result = unsafe { poll(*self.id) };
39+
40+
let length = (poll_result & 0xFFFFFFFF) as usize;
41+
let pointer = (poll_result >> 32) as *mut u8;
42+
43+
let slice = unsafe { slice::from_raw_parts_mut(pointer, length) };
44+
let boxed_slice = unsafe { Box::from_raw(slice) };
45+
let future = str::from_utf8(&boxed_slice).unwrap();
46+
47+
if future == "P" {
48+
Poll::Pending
49+
} else if future == "F" {
50+
Poll::Ready(Err(RustedComputerError::FutureFailed))
51+
} else if future.starts_with("S") {
52+
let future_result = future[1..].to_owned();
53+
let converted_result = (self.converter)(future_result);
54+
55+
Poll::Ready(Ok(converted_result))
56+
} else {
57+
unreachable!()
58+
}
59+
}
60+
}
61+
62+
fn noop_raw_waker() -> RawWaker {
63+
fn clone(_: *const ()) -> RawWaker {
64+
noop_raw_waker()
65+
}
66+
fn no_op(_: *const ()) {}
67+
68+
static VTABLE: RawWakerVTable = RawWakerVTable::new(clone, no_op, no_op, no_op);
69+
RawWaker::new(ptr::null(), &VTABLE)
70+
}
71+
72+
fn noop_waker() -> Waker {
73+
unsafe { Waker::from_raw(noop_raw_waker()) }
74+
}
75+
76+
pub fn block_on<F: Future>(mut future: F) -> F::Output {
77+
let mut future = unsafe { Pin::new_unchecked(&mut future) };
78+
let waker = noop_waker();
79+
let mut cx = Context::from_waker(&waker);
80+
81+
loop {
82+
match future.as_mut().poll(&mut cx) {
83+
Poll::Ready(val) => return val,
84+
Poll::Pending => {
85+
thread::sleep(Duration::from_millis(100));
86+
}
87+
}
88+
}
89+
}
90+
91+
#[link(wasm_import_module = "future")]
92+
unsafe extern "C" {
93+
#[link_name = "poll"]
94+
pub fn poll(future_id: i32) -> i64;
95+
}

rustedcomputer-rs/src/error.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
use thiserror::Error;
2+
3+
#[derive(Error, Debug)]
4+
pub enum RustedComputerError {
5+
#[error("Future failed to resolve")]
6+
FutureFailed,
7+
#[error("Future had a timeout")]
8+
FutureTimeout,
9+
}
10+
11+
pub type Result<T, E = RustedComputerError> = std::result::Result<T, E>;
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
pub mod redstone;
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
use crate::async_runtime::RustedComputerFuture;
2+
use crate::error::Result;
3+
use crate::side::Side;
4+
5+
pub async fn set_output(side: Side, power: u8) -> Result<()> {
6+
let side = side.to_string();
7+
let side_length = side.len() as i32;
8+
let side_offset = side.as_ptr() as i32;
9+
10+
let caller = || unsafe { ext_set_output(side_length, side_offset, power as i32) }.into();
11+
let converter = |_| ();
12+
13+
RustedComputerFuture::new(caller, converter).await
14+
}
15+
16+
pub async fn get_input(side: Side) -> Result<u8> {
17+
let side = side.to_string();
18+
let side_length = side.len() as i32;
19+
let side_offset = side.as_ptr() as i32;
20+
21+
let caller = || unsafe { ext_get_input(side_length, side_offset) }.into();
22+
let converter = |value: String| value.parse().unwrap();
23+
24+
RustedComputerFuture::new(caller, converter).await
25+
}
26+
27+
#[link(wasm_import_module = "redstone")]
28+
unsafe extern "C" {
29+
#[link_name = "set_output"]
30+
fn ext_set_output(side_length: i32, side_offset: i32, power: i32) -> i32;
31+
32+
#[link_name = "get_input"]
33+
fn ext_get_input(side_length: i32, side_offset: i32) -> i32;
34+
}

0 commit comments

Comments
 (0)