ledger_sim/drivers/
local.rs1use std::{
5 net::{IpAddr, Ipv4Addr, SocketAddr},
6 process::Stdio,
7};
8
9use async_trait::async_trait;
10use tokio::process::{Child, Command};
11use tracing::debug;
12
13use super::Driver;
14use crate::{Handle, Options};
15
16pub struct LocalDriver;
18
19#[derive(Debug)]
21pub struct LocalHandle {
22 addr: SocketAddr,
24 child: Child,
26}
27
28impl LocalDriver {
29 pub fn new() -> Self {
31 Self
32 }
33}
34
35impl Default for LocalDriver {
36 fn default() -> Self {
38 Self
39 }
40}
41
42#[async_trait]
44impl Driver for LocalDriver {
45 type Handle = LocalHandle;
46
47 async fn run(&self, app: &str, opts: Options) -> anyhow::Result<Self::Handle> {
48 let mut cmd = Command::new("speculos.py");
50
51 let mut cmd = cmd.kill_on_drop(true);
53
54 cmd = cmd.stdout(Stdio::inherit()).stderr(Stdio::inherit());
58
59 for a in opts.args() {
61 cmd = cmd.arg(a);
62 }
63
64 if let Some(root) = opts.root {
65 let (_, path) = std::env::vars()
67 .find(|(k, _v)| k == "PATH")
68 .unwrap_or(("PATH".to_string(), "".to_string()));
69
70 cmd = cmd.env("PATH", format!("{path}:{root}"));
71 }
72
73 cmd = cmd.arg(app);
75
76 debug!("Command: {:?}", cmd);
77
78 let child = cmd.spawn()?;
80
81 let addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), opts.http_port);
82 Ok(LocalHandle { child, addr })
83 }
84
85 async fn wait(&self, handle: &mut Self::Handle) -> anyhow::Result<()> {
86 let _status = handle.child.wait().await?;
87
88 Ok(())
91 }
92
93 async fn exit(&self, mut handle: Self::Handle) -> anyhow::Result<()> {
94 handle.child.kill().await?;
95 Ok(())
96 }
97}
98
99#[async_trait]
100impl Handle for LocalHandle {
101 fn addr(&self) -> SocketAddr {
102 self.addr
103 }
104}