78 lines
3.0 KiB
Rust
78 lines
3.0 KiB
Rust
use std::num::NonZero;
|
|
use std::rc::Rc;
|
|
|
|
use itertools::Itertools;
|
|
use orchid_base::{is, mk_errv};
|
|
use orchid_extension::gen_expr::{call, new_atom};
|
|
use orchid_extension::std_reqs::ReadLimit;
|
|
use orchid_extension::tree::{GenMember, comments, fun, prefix};
|
|
use orchid_extension::{Expr, ForeignAtom, TAtom, get_arg};
|
|
|
|
use crate::std::binary::binary_atom::BlobAtom;
|
|
use crate::std::stream::stream_cmds::{ReadStreamCmd, WriteAction, WriteStreamCmd};
|
|
use crate::{Int, OrcString};
|
|
|
|
pub fn gen_stream_lib() -> Vec<GenMember> {
|
|
prefix("std", [comments(
|
|
["Read from and write to byte streams"],
|
|
prefix("stream", [
|
|
fun(true, "read_bin", async |hand: ForeignAtom, succ: Expr, fail: Expr| {
|
|
new_atom(ReadStreamCmd { hand, succ, fail, as_str: false, limit: ReadLimit::End })
|
|
}),
|
|
fun(true, "read_str", async |hand: ForeignAtom, succ: Expr, fail: Expr| {
|
|
new_atom(ReadStreamCmd { hand, succ, fail, as_str: true, limit: ReadLimit::End })
|
|
}),
|
|
fun(true, "read_until", async |hand: ForeignAtom, delim: Int, succ: Expr, fail: Expr| {
|
|
let Ok(end) = delim.0.try_into() else {
|
|
return Err(mk_errv(
|
|
is("Byte out of range").await,
|
|
format!(
|
|
"{} doesn't fit into a byte and cannot be used as a delimiter for reading",
|
|
delim.0
|
|
),
|
|
[get_arg(1).pos().await],
|
|
));
|
|
};
|
|
let limit = ReadLimit::Delimiter(end);
|
|
Ok(new_atom(ReadStreamCmd { hand, succ, fail, as_str: false, limit }))
|
|
}),
|
|
fun(true, "read_bytes", async |hand: ForeignAtom, count: Int, succ: Expr, fail: Expr| {
|
|
match count.0.try_into().map(NonZero::new) {
|
|
Ok(Some(nzlen)) => {
|
|
let limit = ReadLimit::Length(nzlen);
|
|
Ok(new_atom(ReadStreamCmd { hand, succ, fail, as_str: false, limit }))
|
|
},
|
|
Ok(None) => Ok(call(succ, new_atom(BlobAtom(Rc::default()))).await),
|
|
Err(_) => Err(mk_errv(
|
|
is("Length cannot be negative").await,
|
|
format!("{} is negative and cannot be used as a length", count.0),
|
|
[get_arg(1).pos().await],
|
|
)),
|
|
}
|
|
}),
|
|
fun(true, "read_line", async |hand: ForeignAtom, succ: Expr, fail: Expr| {
|
|
const LIMIT_BR: ReadLimit = ReadLimit::Delimiter(b'\n');
|
|
new_atom(ReadStreamCmd { hand, succ, fail, as_str: true, limit: LIMIT_BR })
|
|
}),
|
|
fun(true, "write_str", async |hand: ForeignAtom, str: OrcString, succ: Expr, fail: Expr| {
|
|
let action = WriteAction::Write(Rc::new(str.get_string().await.bytes().collect_vec()));
|
|
new_atom(WriteStreamCmd { hand, action, succ, fail })
|
|
}),
|
|
fun(
|
|
true,
|
|
"write_bin",
|
|
async |hand: ForeignAtom, bin: TAtom<BlobAtom>, succ: Expr, fail: Expr| {
|
|
let action = WriteAction::Write(bin.own().await.0.clone());
|
|
new_atom(WriteStreamCmd { hand, action, succ, fail })
|
|
},
|
|
),
|
|
fun(true, "flush", async |hand: ForeignAtom, succ: Expr, fail: Expr| {
|
|
new_atom(WriteStreamCmd { hand, action: WriteAction::Flush, succ, fail })
|
|
}),
|
|
fun(true, "close", async |hand: ForeignAtom, succ: Expr, fail: Expr| {
|
|
new_atom(WriteStreamCmd { hand, action: WriteAction::Close, succ, fail })
|
|
}),
|
|
]),
|
|
)])
|
|
}
|