Skip to content

Instantly share code, notes, and snippets.

@jberkenbilt
jberkenbilt / 0-controller.rs
Created December 2, 2024 00:50
Go to Rust: final code
//! This is an internal implementation of sample API. The
//! implementation pretends to make network calls and accesses locked
//! data. It is wrapped by a function-based API that operates a
//! singleton.
use base::{AsyncRwLock, LockBox, Runtime};
use implbox::ImplBox;
use std::error::Error;
use std::marker::PhantomData;
use std::ops::DerefMut;
@jberkenbilt
jberkenbilt / controller.diff
Last active December 2, 2024 00:30
Go to Rust 05: controller diff
diff -ur --ex 04-generic-async-rwlock-first-try/controller/src/lib.rs 05-final/controller/src/lib.rs
--- 04-generic-async-rwlock-first-try/controller/src/lib.rs 2024-12-01 16:36:03
+++ 05-final/controller/src/lib.rs 2024-12-01 19:26:01
@@ -2,8 +2,11 @@
//! implementation pretends to make network calls and accesses locked
//! data. It is wrapped by a function-based API that operates a
//! singleton.
-use base::AsyncRwLock;
+use base::{AsyncRwLock, LockBox, Runtime};
+use implbox::ImplBox;
@jberkenbilt
jberkenbilt / implbox.rs
Last active December 1, 2024 23:27
Go to Rust: just implbox
use std::any::TypeId;
use std::marker::PhantomData;
unsafe impl<T: Send> Send for ImplBox<T> {}
unsafe impl<T: Sync> Sync for ImplBox<T> {}
pub struct ImplBox<T> {
id: TypeId,
ptr: *const (),
destroy: fn(*const ()),
_t: PhantomData<T>,
@jberkenbilt
jberkenbilt / tests.rs
Created December 1, 2024 19:15
Go to Rust: 04 tokio runtime tests
use super::*;
use crate::{Locker, TokioRuntime};
use std::sync::Arc;
use std::time::Duration;
use tokio::sync::oneshot;
use tokio::task;
async fn generic_thing<M>(m: &M)
where
M: AsyncRwLock<i32>,
@jberkenbilt
jberkenbilt / runtime.rs
Last active December 1, 2024 19:13
Go to Rust: 04 tokio runtime
use crate::rwlock::TokioLockWrapper;
use base::{AsyncRwLock, Locker, Runtime};
pub mod rwlock;
#[derive(Default, Clone)]
pub struct TokioRuntime;
impl Locker for TokioRuntime {
fn new_lock<T: Sync + Send>(item: T) -> impl AsyncRwLock<T> {
@jberkenbilt
jberkenbilt / runtime.rs
Last active December 1, 2024 16:28
Go to Rust: 04 initial RwLock trait
use std::ops::{Deref, DerefMut};
pub trait Runtime: Locker {}
/// The [AsyncRwLock::read] and [AsyncRwLock::write] functions must return
/// actual async-aware lock guards that maintain the lock until they are out of
/// scope. They must not block the thread while holding the lock.
pub trait AsyncRwLock<T> {
fn new(item: T) -> Self;
fn read(
@jberkenbilt
jberkenbilt / controller.rs
Created December 1, 2024 15:46
Go to Rust: controller with tokio
use std::error::Error;
use tokio::sync::RwLock;
#[derive(Default)]
struct ReqData {
seq: i32,
last_path: String,
}
#[derive(Default)]
@jberkenbilt
jberkenbilt / method_caller.rs
Created December 1, 2024 00:51
Go to Rust: 03 MethodCaller trait
trait MethodCaller<'a, ArgT, ResultT>: FnOnce(&'a Controller, ArgT) -> Self::Fut {
type Fut: Future<Output = Result<ResultT, Box<dyn Error + Sync + Send>>>;
}
impl<
'a,
ArgT,
ResultT,
FnT: FnOnce(&'a Controller, ArgT) -> Fut,
Fut: Future<Output = Result<ResultT, Box<dyn Error + Sync + Send>>>,
> MethodCaller<'a, ArgT, ResultT> for FnT
@jberkenbilt
jberkenbilt / 02-error.txt
Created November 30, 2024 13:51
Go to Rust: 02 compiler error
error[E0308]: mismatched types
--> device/src/lib.rs:51:5
|
51 | run_method(Controller::one, val)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other
|
= note: expected opaque type `impl for<'a> Future<Output = Result<i32, Box<(dyn std::error::Error + Send + Sync + 'static)>>>`
found opaque type `impl Future<Output = Result<i32, Box<(dyn std::error::Error + Send + Sync + 'static)>>>`
= help: consider `await`ing on both `Future`s
= note: distinct uses of `impl Trait` result in different opaque types
@jberkenbilt
jberkenbilt / 02-01.diff
Created November 30, 2024 13:43
Go to Rust: 02 diff 01
@@ -25,17 +24,15 @@
/// call methods on the singleton. It takes a closure that takes a
/// &[Controller] and an arg, calls the closure using the singleton,
/// and returns the result.
-fn run_method<ArgT, ResultT, FnT>(
+fn run_method<ArgT, ResultT, FnT, Fut>(
f: FnT,
arg: ArgT,
) -> Result<ResultT, Box<dyn Error + Sync + Send>>
where