Skip to content

Commit 0a5fff5

Browse files
committed
Implements stdout:read() for process object
1 parent b658f06 commit 0a5fff5

7 files changed

Lines changed: 45 additions & 14 deletions

File tree

.github/workflows/build-project.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,5 +16,7 @@ jobs:
1616
steps:
1717
- name: Check out repository
1818
uses: actions/checkout@v4
19+
- name: Lint
20+
run: cargo clippy -- -D warnings
1921
- name: Install Project
2022
run: cargo install --path .

Cargo.lock

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

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ rustc-hash = "2.1.1"
1212
serde = { version = "1.0.219", features = ["derive"] }
1313
serde_yaml = "0.9.34"
1414
thiserror = "2.0.12"
15-
tokio = { version = "1.44.1", features = ["process", "rt"] }
15+
tokio = { version = "1.44.1", features = ["io-util", "process", "rt"] }
1616
url = "2.5.4"
1717
zl = { git = "https://github.com/ultimaweapon/zero-lua.git" }
1818

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -157,9 +157,9 @@ Working directory for the process. If this key does not present it will default
157157

158158
Can be either `null`, `inherit` or `pipe`. If this key does not present it will default to `inherit`. For `pipe` the process object will have `stdout` property, which have [read](https://www.lua.org/manual/5.4/manual.html#pdf-file:read) method.
159159

160-
### Url
160+
### Url:new(url)
161161

162-
`Url` is a class to parse and manipulate a URL.
162+
Create an instance of `Url` class from `url`.
163163

164164
## Exit code
165165

src/api/os/capture.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,10 @@ pub fn entry(cx: &mut Context) -> Result<(), Error> {
6565
.map_err(|e| Error::with_source(format!("failed to run '{}'", opts.prog), e))?;
6666

6767
if !r.status.success() {
68-
return Err(format!("'{}' exited with an error ({})", opts.prog, r.status).into());
68+
return Err(Error::other(format!(
69+
"'{}' exited with an error ({})",
70+
opts.prog, r.status
71+
)));
6972
}
7073

7174
// Set result.

src/api/os/run.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,10 @@ pub fn entry(cx: &mut Context<NonYieldable>) -> Result<(), Error> {
4040
.map_err(|e| Error::with_source(format!("failed to run '{}'", opts.prog), e))?;
4141

4242
if !status.success() {
43-
return Err(format!("'{}' exited with an error ({})", opts.prog, status).into());
43+
return Err(Error::other(format!(
44+
"'{}' exited with an error ({})",
45+
opts.prog, status
46+
)));
4447
}
4548

4649
Ok(())

src/api/os/spawn.rs

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@ use std::borrow::Cow;
22
use std::cell::RefCell;
33
use std::panic::AssertUnwindSafe;
44
use std::process::{Child, Command, Stdio};
5-
use tokio::io::AsyncRead;
5+
use tokio::io::{AsyncBufReadExt, AsyncRead, BufReader};
66
use tokio::process::ChildStdout;
7-
use zl::{Context, Error, Frame, FromOption, PositiveInt, Value, class};
7+
use zl::{Context, Error, Frame, FromOption, PositiveInt, Value, Yieldable, class};
88

99
/// Implementation of `os.spawn`.
1010
pub fn entry(cx: &mut Context) -> Result<(), Error> {
@@ -86,7 +86,7 @@ pub fn entry(cx: &mut Context) -> Result<(), Error> {
8686
// Set stdout.
8787
if let Some(v) = stdout {
8888
let v = match ChildStdout::from_std(v) {
89-
Ok(v) => OutputStream(AssertUnwindSafe(RefCell::new(Box::new(v)))),
89+
Ok(v) => OutputStream(AssertUnwindSafe(RefCell::new(BufReader::new(Box::new(v))))),
9090
Err(e) => {
9191
return Err(Error::with_source(
9292
"failed to convert stdout to asynchronous",
@@ -142,12 +142,35 @@ impl Drop for Process {
142142
}
143143

144144
/// Class of `stdout` property of the value returned from `os.spawn`.
145-
pub struct OutputStream(AssertUnwindSafe<RefCell<Box<dyn AsyncRead + Unpin>>>);
145+
pub struct OutputStream(AssertUnwindSafe<RefCell<BufReader<Box<dyn AsyncRead + Unpin>>>>);
146146

147147
#[class]
148148
impl OutputStream {
149-
fn read(_: &mut Context) -> Result<(), Error> {
150-
todo!()
149+
async fn read(cx: &mut Context<'_, Yieldable>) -> Result<(), Error> {
150+
// Lock stream.
151+
let stream = cx.to_ud::<Self>(PositiveInt::ONE).into_ud();
152+
let mut stream = stream
153+
.0
154+
.try_borrow_mut()
155+
.map_err(|_| Error::other(c"concurrent read is not supported"))?;
156+
157+
// Read.
158+
if cx.args() == 1 {
159+
let mut line = String::new();
160+
let len = stream.read_line(&mut line).await?;
161+
162+
if len != 0 {
163+
if line.ends_with('\n') {
164+
line.pop();
165+
}
166+
167+
cx.push_str(line);
168+
}
169+
} else {
170+
todo!()
171+
}
172+
173+
Ok(())
151174
}
152175
}
153176

0 commit comments

Comments
 (0)