Compare commits

..

No commits in common. "bcb734846d77b388c1a26d97b6c349a0d032f114" and "85a0110e1aa11bc958179d366645ca2f9165eb08" have entirely different histories.

14 changed files with 67 additions and 236 deletions

1
Cargo.lock generated
View File

@ -1031,7 +1031,6 @@ dependencies = [
"luaify", "luaify",
"luajit", "luajit",
"sysexits", "sysexits",
"thiserror",
"tokio", "tokio",
"tracing", "tracing",
] ]

View File

@ -13,7 +13,6 @@ derive_more = { version = "2.0.1", features = ["full"] }
luaffi = { path = "../luaffi" } luaffi = { path = "../luaffi" }
luajit = { path = "../luajit" } luajit = { path = "../luajit" }
sysexits = "0.9.0" sysexits = "0.9.0"
thiserror = "2.0.12"
tokio = { version = "1.45.1", features = ["rt", "time", "fs", "net", "process", "signal", "tracing"] } tokio = { version = "1.45.1", features = ["rt", "time", "fs", "net", "process", "signal", "tracing"] }
tracing = "0.1.41" tracing = "0.1.41"

View File

@ -2,10 +2,10 @@
use luaffi::{cdef, metatype}; use luaffi::{cdef, metatype};
#[cdef] #[cdef]
pub struct lb_chanlib; pub struct lb_libchannel;
#[metatype] #[metatype]
impl lb_chanlib { impl lb_libchannel {
#[new] #[new]
extern "Lua-C" fn new() -> Self { extern "Lua-C" fn new() -> Self {
Self Self

View File

@ -1,9 +1,8 @@
//! The `lb:fs` library provides synchronous and asynchronous utilities for interacting with the //! The `lb:fs` library provides utilities for interacting with the file system asynchronously.
//! file system.
//! //!
//! # Exports //! # Exports
//! //!
//! See [`lb_fslib`] for items exported by this library. //! See [`lb_libfs`] for items exported by this library.
use luaffi::{cdef, metatype}; use luaffi::{cdef, metatype};
use std::io; use std::io;
use tokio::fs; use tokio::fs;
@ -16,10 +15,10 @@ use tokio::fs;
/// local fs = require("lb:fs"); /// local fs = require("lb:fs");
/// ``` /// ```
#[cdef] #[cdef]
pub struct lb_fslib; pub struct lb_libfs;
#[metatype] #[metatype]
impl lb_fslib { impl lb_libfs {
#[new] #[new]
extern "Lua-C" fn new() -> Self { extern "Lua-C" fn new() -> Self {
Self Self
@ -32,12 +31,4 @@ impl lb_fslib {
pub extern "Lua-C" fn read_sync(&self, path: &str) -> io::Result<Vec<u8>> { pub extern "Lua-C" fn read_sync(&self, path: &str) -> io::Result<Vec<u8>> {
std::fs::read(path) std::fs::read(path)
} }
pub async extern "Lua-C" fn write(&self, path: &str, contents: &[u8]) -> io::Result<()> {
fs::write(path, contents).await
}
pub extern "Lua-C" fn write_sync(&self, path: &str, contents: &[u8]) -> io::Result<()> {
std::fs::write(path, contents)
}
} }

View File

@ -1,4 +1,4 @@
pub mod chan; pub mod channel;
pub mod fs; pub mod fs;
pub mod net; pub mod net;
pub mod runtime; pub mod runtime;

View File

@ -3,45 +3,27 @@
//! //!
//! # Exports //! # Exports
//! //!
//! See [`lb_netlib`] for items exported by this library. //! See [`lb_libnet`] for items exported by this library.
use derive_more::{From, FromStr}; use derive_more::{From, FromStr};
use luaffi::{cdef, metatype}; use luaffi::{cdef, metatype};
use std::{ use std::{
io,
net::{AddrParseError, IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr}, net::{AddrParseError, IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr},
time::Duration,
}; };
use thiserror::Error;
use tokio::net::{TcpListener, TcpSocket, TcpStream}; use tokio::net::{TcpListener, TcpSocket, TcpStream};
/// Errors that can be thrown by this library.
///
/// Functions which return this error will **throw** in Lua. The error message can be caught by
/// using [`pcall(f, ...)`](https://www.lua.org/manual/5.1/manual.html#pdf-pcall).
#[derive(Debug, Error)]
pub enum Error {
#[error("{0}")]
Io(#[from] std::io::Error),
#[error("{0}")]
InvalidAddr(#[from] AddrParseError),
#[error("socket was already converted")]
SocketConsumed,
}
type Result<T> = std::result::Result<T, Error>;
/// Items exported by the `lb:net` library. /// Items exported by the `lb:net` library.
/// ///
/// This library can be obtained by calling /// This library can be obtained by calling `require` in Lua.
/// [`require("lb:net")`](https://www.lua.org/manual/5.1/manual.html#pdf-require) in Lua.
/// ///
/// ```lua /// ```lua
/// local net = require("lb:net"); /// local net = require("lb:net");
/// ``` /// ```
#[cdef] #[cdef]
pub struct lb_netlib; pub struct lb_libnet;
#[metatype] #[metatype]
impl lb_netlib { impl lb_libnet {
#[new] #[new]
extern "Lua-C" fn new() -> Self { extern "Lua-C" fn new() -> Self {
Self Self
@ -77,7 +59,11 @@ impl lb_netlib {
/// If `s` is an [`lb_ipaddr`], a copy of that value is returned. If `s` is an /// If `s` is an [`lb_ipaddr`], a copy of that value is returned. If `s` is an
/// [`lb_socketaddr`], the IP address part of the socket address is returned. Otherwise, parses /// [`lb_socketaddr`], the IP address part of the socket address is returned. Otherwise, parses
/// `s` as an IP address string. Both IPv4 or IPv6 addresses are supported. /// `s` as an IP address string. Both IPv4 or IPv6 addresses are supported.
pub extern "Lua" fn ipaddr(&self, s: any) -> Result<lb_ipaddr> { ///
/// # Errors
///
/// Throws if `s` cannot be parsed as an IP address.
pub extern "Lua" fn ipaddr(&self, s: any) -> lb_ipaddr {
if __istype(__ct.lb_ipaddr, s) { if __istype(__ct.lb_ipaddr, s) {
__new(__ct.lb_ipaddr, s) // copy constructor __new(__ct.lb_ipaddr, s) // copy constructor
} else if __istype(__ct.lb_socketaddr, s) { } else if __istype(__ct.lb_socketaddr, s) {
@ -87,8 +73,8 @@ impl lb_netlib {
} }
} }
extern "Lua-C" fn __parse_ipaddr(&self, s: &str) -> Result<lb_ipaddr> { extern "Lua-C" fn __parse_ipaddr(&self, s: &str) -> Result<lb_ipaddr, AddrParseError> {
Ok(s.parse()?) s.parse()
} }
/// Creates an [`lb_socketaddr`] from the given input. /// Creates an [`lb_socketaddr`] from the given input.
@ -100,67 +86,52 @@ impl lb_netlib {
/// socket address string. Both IPv4 and IPv6 addresses are supported. /// socket address string. Both IPv4 and IPv6 addresses are supported.
/// ///
/// If `port` is not specified, `0` is used as the default. /// If `port` is not specified, `0` is used as the default.
pub extern "Lua" fn socketaddr(&self, s: any, port: any) -> Result<lb_socketaddr> { ///
/// # Errors
///
/// Throws if `s` cannot be parsed as an IP or socket address.
pub extern "Lua" fn socketaddr(&self, s: any, port: any) -> lb_socketaddr {
if port != () { if port != () {
self.__new_skaddr(self.ipaddr(s), port) self.__new_socketaddr(self.ipaddr(s), port)
} else { } else {
if __istype(__ct.lb_socketaddr, s) { if __istype(__ct.lb_socketaddr, s) {
__new(__ct.lb_socketaddr, s) // copy constructor __new(__ct.lb_socketaddr, s) // copy constructor
} else if __istype(__ct.lb_ipaddr, s) { } else if __istype(__ct.lb_ipaddr, s) {
self.__new_skaddr(s, 0) // default port 0 self.__new_socketaddr(s, 0) // default port 0
} else { } else {
self.__parse_skaddr(s) self.__parse_socketaddr(s)
} }
} }
} }
extern "Lua-C" fn __new_skaddr(&self, ip: &lb_ipaddr, port: u16) -> lb_socketaddr { extern "Lua-C" fn __new_socketaddr(&self, ip: &lb_ipaddr, port: u16) -> lb_socketaddr {
SocketAddr::new(ip.0, port).into() SocketAddr::new(ip.0, port).into()
} }
extern "Lua-C" fn __parse_skaddr(&self, s: &str) -> Result<lb_socketaddr> { extern "Lua-C" fn __parse_socketaddr(&self, s: &str) -> Result<lb_socketaddr, AddrParseError> {
Ok(s.parse()?) s.parse()
} }
/// Creates a new TCP socket configured for IPv4. /// Creates a new TCP socket configured for IPv4.
/// ///
/// See [`TcpSocket::new_v4`]. /// See [`TcpSocket::new_v4`].
pub extern "Lua-C" fn tcp(&self) -> Result<lb_tcpsocket> { ///
Ok(Some(TcpSocket::new_v4()?).into()) /// # Errors
///
/// Throws if an error was encountered during the socket creation.
pub extern "Lua-C" fn tcp_v4(&self) -> io::Result<lb_tcpsocket> {
TcpSocket::new_v4().map(lb_tcpsocket)
} }
/// Creates a new TCP socket configured for IPv6. /// Creates a new TCP socket configured for IPv6.
/// ///
/// See [`TcpSocket::new_v6`]. /// See [`TcpSocket::new_v6`].
pub extern "Lua-C" fn tcp6(&self) -> Result<lb_tcpsocket> { ///
Ok(Some(TcpSocket::new_v6()?).into()) /// # Errors
} ///
/// Throws if an error was encountered during the socket creation.
pub extern "Lua" fn bind_tcp(&self, addr: any, port: any) -> Result<lb_tcpsocket> { pub extern "Lua-C" fn tcp_v6(&self) -> io::Result<lb_tcpsocket> {
let addr = self.socketaddr(addr, port); TcpSocket::new_v6().map(lb_tcpsocket)
let socket;
if addr.ip().is_v6() {
socket = self.tcp6();
} else {
socket = self.tcp();
}
socket.bind(addr);
socket
}
pub extern "Lua" fn connect_tcp(&self, addr: any, port: any) -> Result<lb_tcpstream> {
let addr = self.socketaddr(addr, port);
let socket;
if addr.ip().is_v6() {
socket = self.tcp6();
} else {
socket = self.tcp();
}
socket.connect(addr)
}
pub extern "Lua" fn listen_tcp(&self, addr: any, port: any) -> Result<lb_tcplistener> {
self.bind_tcp(addr, port).listen(1024)
} }
} }
@ -303,7 +274,7 @@ impl lb_socketaddr {
/// Sets the IP part of this address. /// Sets the IP part of this address.
/// ///
/// This function accepts the same arguments as [`ipaddr`](lb_netlib::ipaddr). /// This function accepts the same arguments as [`ipaddr`](lb_libnet::ipaddr).
pub extern "Lua" fn set_ip(&mut self, s: any) -> &mut Self { pub extern "Lua" fn set_ip(&mut self, s: any) -> &mut Self {
if __istype(__ct.lb_ipaddr, s) { if __istype(__ct.lb_ipaddr, s) {
self.__set_ip(s); self.__set_ip(s);
@ -319,8 +290,8 @@ impl lb_socketaddr {
self.0.set_ip(ip.0); self.0.set_ip(ip.0);
} }
extern "Lua-C" fn __set_ip_parse(&mut self, s: &str) -> Result<()> { extern "Lua-C" fn __set_ip_parse(&mut self, s: &str) -> Result<(), AddrParseError> {
Ok(self.0.set_ip(s.parse()?)) s.parse().map(|ip| self.0.set_ip(ip))
} }
/// Returns the port part of this address. /// Returns the port part of this address.
@ -329,7 +300,7 @@ impl lb_socketaddr {
} }
/// Sets the port part of this address. /// Sets the port part of this address.
pub extern "Lua" fn set_port(&mut self, port: integer) -> &mut Self { pub extern "Lua" fn set_port(&mut self, port: number) -> &mut Self {
self.__set_port(port); self.__set_port(port);
self self
} }
@ -345,125 +316,13 @@ impl lb_socketaddr {
} }
} }
/// A TCP socket which has not yet been converted to an [`lb_tcpstream`] or [`lb_tcplistener`]. /// A TCP socket which has not yet been converted to a [`lb_tcpstream`] or [`lb_tcplistener`].
#[derive(Debug, From)] #[derive(Debug, From)]
#[cdef] #[cdef]
pub struct lb_tcpsocket(#[opaque] Option<TcpSocket>); pub struct lb_tcpsocket(#[opaque] TcpSocket);
#[metatype] #[metatype]
impl lb_tcpsocket { impl lb_tcpsocket {}
fn socket(&self) -> Result<&TcpSocket> {
self.0.as_ref().ok_or(Error::SocketConsumed)
}
/// See [`TcpSocket::keepalive`].
pub extern "Lua-C" fn keepalive(&self) -> Result<bool> {
Ok(self.socket()?.keepalive()?)
}
/// See [`TcpSocket::set_keepalive`].
pub extern "Lua-C" fn set_keepalive(&self, enabled: bool) -> Result<()> {
Ok(self.socket()?.set_keepalive(enabled)?)
}
/// See [`TcpSocket::reuseaddr`].
pub extern "Lua-C" fn reuseaddr(&self) -> Result<bool> {
Ok(self.socket()?.reuseaddr()?)
}
/// See [`TcpSocket::set_reuseaddr`].
pub extern "Lua-C" fn set_reuseaddr(&self, enabled: bool) -> Result<()> {
Ok(self.socket()?.set_reuseaddr(enabled)?)
}
/// See [`TcpSocket::reuseport`].
pub extern "Lua-C" fn reuseport(&self) -> Result<bool> {
Ok(self.socket()?.reuseport()?)
}
/// See [`TcpSocket::set_reuseport`].
pub extern "Lua-C" fn set_reuseport(&self, enabled: bool) -> Result<()> {
Ok(self.socket()?.set_reuseport(enabled)?)
}
/// See [`TcpSocket::send_buffer_size`].
pub extern "Lua-C" fn sendbuf(&self) -> Result<u32> {
Ok(self.socket()?.send_buffer_size()?)
}
/// See [`TcpSocket::set_send_buffer_size`].
pub extern "Lua-C" fn set_sendbuf(&self, size: u32) -> Result<()> {
Ok(self.socket()?.set_send_buffer_size(size)?)
}
/// See [`TcpSocket::recv_buffer_size`].
pub extern "Lua-C" fn recvbuf(&self) -> Result<u32> {
Ok(self.socket()?.recv_buffer_size()?)
}
/// See [`TcpSocket::set_recv_buffer_size`].
pub extern "Lua-C" fn set_recvbuf(&self, size: u32) -> Result<()> {
Ok(self.socket()?.set_recv_buffer_size(size)?)
}
/// See [`TcpSocket::linger`].
pub extern "Lua-C" fn linger(&self) -> Result<f64> {
Ok(self
.socket()?
.linger()?
.map(|n| n.as_secs_f64())
.unwrap_or(0.))
}
/// See [`TcpSocket::set_linger`].
pub extern "Lua-C" fn set_linger(&self, secs: f64) -> Result<()> {
Ok(self
.socket()?
.set_linger((secs != 0.).then_some(Duration::from_secs_f64(secs)))?)
}
/// See [`TcpSocket::nodelay`].
pub extern "Lua-C" fn nodelay(&self) -> Result<bool> {
Ok(self.socket()?.nodelay()?)
}
/// See [`TcpSocket::set_nodelay`].
pub extern "Lua-C" fn set_nodelay(&self, enabled: bool) -> Result<()> {
Ok(self.socket()?.set_nodelay(enabled)?)
}
/// See [`TcpSocket::tos`].
pub extern "Lua-C" fn tos(&self) -> Result<u32> {
Ok(self.socket()?.tos()?)
}
/// See [`TcpSocket::set_tos`].
pub extern "Lua-C" fn set_tos(&self, tos: u32) -> Result<()> {
Ok(self.socket()?.set_tos(tos)?)
}
/// See [`TcpSocket::local_addr`].
pub extern "Lua-C" fn local_addr(&self) -> Result<lb_socketaddr> {
Ok(self.socket()?.local_addr()?.into())
}
/// See [`TcpSocket::bind`].
pub extern "Lua-C" fn bind(&self, addr: &lb_socketaddr) -> Result<()> {
Ok(self.socket()?.bind(addr.0)?)
}
/// See [`TcpSocket::connect`].
pub async extern "Lua-C" fn connect(&mut self, addr: &lb_socketaddr) -> Result<lb_tcpstream> {
let socket = self.0.take().ok_or(Error::SocketConsumed)?;
Ok(socket.connect(addr.0).await?.into())
}
/// See [`TcpSocket::listen`].
pub extern "Lua-C" fn listen(&mut self, backlog: u32) -> Result<lb_tcplistener> {
let socket = self.0.take().ok_or(Error::SocketConsumed)?;
Ok(socket.listen(backlog)?.into())
}
}
#[derive(Debug, From)] #[derive(Debug, From)]
#[cdef] #[cdef]

View File

@ -1,4 +1,4 @@
use crate::{chan::lb_chanlib, fs::lb_fslib, net::lb_netlib, task::lb_tasklib}; use crate::{channel::lb_libchannel, fs::lb_libfs, net::lb_libnet, task::lb_libtask};
use derive_more::{Deref, DerefMut}; use derive_more::{Deref, DerefMut};
use luaffi::{Registry, Type}; use luaffi::{Registry, Type};
use luajit::{Chunk, State}; use luajit::{Chunk, State};
@ -18,10 +18,10 @@ impl Builder {
let mut registry = Registry::new(); let mut registry = Registry::new();
registry registry
.preload::<lb_tasklib>("lb:task") .preload::<lb_libtask>("lb:task")
.preload::<lb_chanlib>("lb:channel") .preload::<lb_libchannel>("lb:channel")
.preload::<lb_fslib>("lb:fs") .preload::<lb_libfs>("lb:fs")
.preload::<lb_netlib>("lb:net"); .preload::<lb_libnet>("lb:net");
Self { registry } Self { registry }
} }

View File

@ -4,10 +4,10 @@ use std::{ffi::c_int, process};
use tokio::task::JoinHandle; use tokio::task::JoinHandle;
#[cdef] #[cdef]
pub struct lb_tasklib; pub struct lb_libtask;
#[metatype] #[metatype]
impl lb_tasklib { impl lb_libtask {
#[new] #[new]
extern "Lua-C" fn new() -> Self { extern "Lua-C" fn new() -> Self {
Self Self

View File

@ -10,11 +10,11 @@ use std::{
pub mod stub_types { pub mod stub_types {
pub struct any; pub struct any;
pub struct nil; pub struct nil;
pub type boolean = bool; pub struct boolean;
pub struct lightuserdata; pub struct lightuserdata;
pub struct number; pub struct number;
pub struct integer; pub struct integer;
pub type string = String; pub struct string;
pub struct table; pub struct table;
pub struct function; pub struct function;
pub struct userdata; pub struct userdata;

View File

@ -1,4 +1,4 @@
---@diagnostic disable ---@diagnostic disable: unused-local, unused-function, undefined-global
local LUA_REFNIL = -1 -- lib_aux.c local LUA_REFNIL = -1 -- lib_aux.c
local FREELIST_REF = 0 local FREELIST_REF = 0

View File

@ -345,12 +345,12 @@ impl<'r> MetatypeBuilder<'r> {
) -> &mut Self { ) -> &mut Self {
write!(self.lua, "__idx.{name} = ").unwrap(); write!(self.lua, "__idx.{name} = ").unwrap();
f(&mut MetatypeMethodBuilder::new(self)); f(&mut MetatypeMethodBuilder::new(self));
writeln!(self.lua, ";").unwrap(); write!(self.lua, "; ").unwrap();
self self
} }
pub fn index_raw(&mut self, name: impl Display, value: impl Display) -> &mut Self { pub fn index_raw(&mut self, name: impl Display, value: impl Display) -> &mut Self {
writeln!(self.lua, "__idx.{name} = {value};").unwrap(); write!(self.lua, "__idx.{name} = {value}; ").unwrap();
self self
} }
@ -361,12 +361,12 @@ impl<'r> MetatypeBuilder<'r> {
) -> &mut Self { ) -> &mut Self {
write!(self.lua, "__mt.__{name} = ").unwrap(); write!(self.lua, "__mt.__{name} = ").unwrap();
f(&mut MetatypeMethodBuilder::new(self)); f(&mut MetatypeMethodBuilder::new(self));
writeln!(self.lua, ";").unwrap(); write!(self.lua, "; ").unwrap();
self self
} }
pub fn metatable_raw(&mut self, name: impl Display, value: impl Display) -> &mut Self { pub fn metatable_raw(&mut self, name: impl Display, value: impl Display) -> &mut Self {
writeln!(self.lua, "__mt.__{name} = {value};").unwrap(); write!(self.lua, "__mt.__{name} = {value}; ").unwrap();
self self
} }
} }

View File

@ -763,13 +763,13 @@ fn inject_merged_drop(registry: &mut Registry, lua: Option<&LuaFunction>) -> Res
fn document_ffi_function(func: &mut ImplItemFn) { fn document_ffi_function(func: &mut ImplItemFn) {
func.attrs.insert(0, parse_quote!(#[doc = func.attrs.insert(0, parse_quote!(#[doc =
r#"<span class="stab" title="This function is implemented in Rust and called via FFI." style="float: right; background: #fff5d6; font-weight: 500; margin-left: 3px; padding-left: 5px; padding-right: 5px;">FFI</span>"# r#"<span class="stab" title="This is a C/FFI function." style="float: right; font-weight: 500; margin-left: 3px; padding-left: 5px; padding-right: 5px;">FFI</span>"#
])); ]));
} }
fn document_lua_function(func: &mut ImplItemFn) { fn document_lua_function(func: &mut ImplItemFn) {
func.attrs.insert(0, parse_quote!(#[doc = func.attrs.insert(0, parse_quote!(#[doc =
r#"<span class="stab" title="This function is implemented in Lua." style="float: right; background: #ebf5ff; font-weight: 500; margin-left: 3px; padding-left: 5px; padding-right: 5px;">Lua</span>"# r#"<span class="stab" title="This is a Lua function." style="float: right; font-weight: 500; margin-left: 3px; padding-left: 5px; padding-right: 5px;">Lua</span>"#
])); ]));
} }
@ -799,10 +799,6 @@ fn document_metamethod(func: &mut ImplItemFn, method: Metamethod) {
_ => format!("This is a metamethod and cannot be called directly."), _ => format!("This is a metamethod and cannot be called directly."),
}; };
func.attrs.insert(0, parse_quote!(#[doc =
r#"<span class="stab" title="This function is a metamethod." style="float: right; background: #ebf5ff; margin-left: 3px; padding-left: 5px; padding-right: 5px;">Metamethod</span>"#
]));
func.attrs.push(parse_quote!(#[doc = ""])); func.attrs.push(parse_quote!(#[doc = ""]));
func.attrs.push(parse_quote!(#[doc = #s])); func.attrs.push(parse_quote!(#[doc = #s]));
} }

View File

@ -1 +1,2 @@
pub use lb::*; pub use lb::fs;
pub use lb::net;

View File

@ -97,15 +97,6 @@ struct Args {
)] )]
console_addr: SocketAddr, console_addr: SocketAddr,
/// Dump internal data.
#[clap(
long,
help_heading = "Debugging",
value_name = "DATA",
value_parser = ["cdef"]
)]
dump: Vec<String>,
/// Print version. /// Print version.
#[clap(long, short = 'V')] #[clap(long, short = 'V')]
version: bool, version: bool,
@ -207,11 +198,6 @@ fn init_tokio(args: &Args) -> tokio::runtime::Runtime {
fn init_lua(args: &Args) -> lb::runtime::Runtime { fn init_lua(args: &Args) -> lb::runtime::Runtime {
let rt = lb::runtime::Builder::new(); let rt = lb::runtime::Builder::new();
if args.dump.iter().find(|s| *s == "cdef").is_some() {
print!("{}", rt.registry());
}
let mut rt = rt.build().unwrap_or_else(exit_err(ExitCode::Software)); let mut rt = rt.build().unwrap_or_else(exit_err(ExitCode::Software));
for arg in args.jit.iter() { for arg in args.jit.iter() {