Created
August 20, 2019 23:45
-
-
Save rust-play/8ec4f34492e292ca50595ecc7ea02983 to your computer and use it in GitHub Desktop.
Code shared from the Rust Playground
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use std::collections::HashMap; | |
pub type DidWork = bool; | |
pub type RequestId = String; | |
pub struct PsCore<'pscore, MOD, OUT, OUTR, INR, E> { | |
pending_outs: HashMap<RequestId, Box<dyn Fn(&mut MOD, OUTR) + 'pscore>>, | |
out_outbox: Vec<(Option<RequestId>, OUT)>, | |
in_outbox: Vec<(RequestId, INR)>, | |
phantom_error: std::marker::PhantomData<E>, | |
} | |
impl<'pscore, MOD, OUT, OUTR, INR, E> PsCore<'pscore, MOD, OUT, OUTR, INR, E> { | |
pub fn new() -> Self { | |
Self { | |
pending_outs: HashMap::new(), | |
out_outbox: Vec::new(), | |
in_outbox: Vec::new(), | |
phantom_error: std::marker::PhantomData, | |
} | |
} | |
pub fn process(&mut self) -> Result<DidWork, E> { | |
Ok(true) | |
} | |
pub fn send_out_request(&mut self, request: OUT, cb: Box<dyn Fn(&mut MOD, OUTR) + 'pscore>) { | |
let request_id = "".to_string(); | |
self.pending_outs.insert(request_id.clone(), cb); | |
self.out_outbox.push((Some(request_id), request)); | |
} | |
pub fn handle_out_response(&mut self, m: &mut MOD, request_id: RequestId, response: OUTR) { | |
match self.pending_outs.remove(&request_id) { | |
None => println!("no pending for request_id {}", request_id), | |
Some(cb) => { | |
cb(m, response) | |
} | |
} | |
} | |
pub fn post_in_response(&mut self, request_id: RequestId, response: INR) { | |
self.in_outbox.push((request_id, response)); | |
} | |
pub fn drain_requests(&mut self) -> Vec<(Option<RequestId>, OUT)> { | |
self.out_outbox.drain(..).collect() | |
} | |
pub fn drain_responses(&mut self) -> Vec<(RequestId, INR)> { | |
self.in_outbox.drain(..).collect() | |
} | |
} | |
pub trait PsModule<'pmod, MOD, OUT, OUTR, IN, INR, E> { | |
fn as_mut(&mut self) -> &mut MOD; | |
fn get_core(&mut self) -> &mut PsCore<'pmod, MOD, OUT, OUTR, INR, E>; | |
fn take_core(&mut self) -> PsCore<'pmod, MOD, OUT, OUTR, INR, E>; | |
fn put_core(&mut self, core: PsCore<'pmod, MOD, OUT, OUTR, INR, E>); | |
fn process(&mut self) -> Result<DidWork, E> { | |
self.get_core().process() | |
} | |
fn request(&mut self, request_id: Option<RequestId>, request: IN); | |
fn respond(&mut self, request_id: RequestId, response: OUTR) { | |
let mut core = self.take_core(); | |
core.handle_out_response(self.as_mut(), request_id, response); | |
self.put_core(core); | |
} | |
fn drain_requests(&mut self) -> Vec<(Option<RequestId>, OUT)> { | |
self.get_core().drain_requests() | |
} | |
fn drain_responses(&mut self) -> Vec<(RequestId, INR)> { | |
self.get_core().drain_responses() | |
} | |
} | |
#[derive(Debug)] | |
pub struct CError(pub String); | |
#[derive(Debug)] | |
pub struct COut(pub String); | |
#[derive(Debug)] | |
pub struct COutR(pub String); | |
#[derive(Debug)] | |
pub struct CIn(pub String); | |
#[derive(Debug)] | |
pub struct CInR(pub String); | |
pub struct CryptoTransport<'ct> { | |
core: Option<PsCore<'ct, CryptoTransport<'ct>, COut, COutR, CInR, CError>>, | |
inner: Vec<String>, | |
} | |
impl<'ct> CryptoTransport<'ct> { | |
pub fn new() -> Self { | |
Self { | |
core: Some(PsCore::new()), | |
inner: Vec::new(), | |
} | |
} | |
pub fn print_inner(&self) { | |
println!("ct inner: {:?}", self.inner); | |
} | |
} | |
impl<'ct> PsModule<'ct, CryptoTransport<'ct>, COut, COutR, CIn, CInR, CError> for CryptoTransport<'ct> { | |
fn as_mut(&mut self) -> &mut CryptoTransport<'ct> { | |
&mut *self | |
} | |
fn get_core(&mut self) -> &mut PsCore<'ct, CryptoTransport<'ct>, COut, COutR, CInR, CError> { | |
self.core.as_mut().unwrap() | |
} | |
fn take_core(&mut self) -> PsCore<'ct, CryptoTransport<'ct>, COut, COutR, CInR, CError> { | |
std::mem::replace(&mut self.core, None).unwrap() | |
} | |
fn put_core(&mut self, core: PsCore<'ct, CryptoTransport<'ct>, COut, COutR, CInR, CError>) { | |
std::mem::replace(&mut self.core, Some(core)); | |
} | |
fn process(&mut self) -> Result<DidWork, CError> { | |
self.get_core().send_out_request(COut("test_out_request".to_string()), Box::new(|m, r| { | |
m.inner.push(r.0); | |
})); | |
self.get_core().process() | |
} | |
fn request(&mut self, request_id: Option<RequestId>, request: CIn) { | |
self.inner.push(request.0); | |
if let Some(request_id) = request_id { | |
self.get_core().post_in_response(request_id, CInR("responding".to_string())); | |
} | |
} | |
} | |
pub fn main() { | |
let mut ct = CryptoTransport::new(); | |
// process will generate an outgoing request of us | |
ct.process().unwrap(); | |
println!("req: {:?}", ct.drain_requests()); | |
// that request has a request_id of "", let's respond to it: | |
ct.respond("".to_string(), COutR("test-resp".to_string())); | |
// make sure the ct inner state was updated | |
ct.print_inner(); | |
// now, let's make a request of ct | |
ct.request(Some("zz".to_string()), CIn("test-req".to_string())); | |
// was it posted? | |
ct.print_inner(); | |
// see if we get a response | |
println!("resp: {:?}", ct.drain_responses()); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment