diff --git a/fix_journal.py b/fix_journal.py deleted file mode 100644 index acc1d4d3..00000000 --- a/fix_journal.py +++ /dev/null @@ -1,4 +0,0 @@ -with open('.jules/bolt.md', 'r') as f: - content = f.read() - -# I will append the learning at the end if it doesn't exist, but since it currently only contains my previous write, I need to look at git history to restore it. diff --git a/stdlib/src/lib.rs b/stdlib/src/lib.rs index b1629bdb..ab1acd3e 100644 --- a/stdlib/src/lib.rs +++ b/stdlib/src/lib.rs @@ -54,6 +54,7 @@ pub mod mock; pub mod mongodb; pub mod mysql; pub mod net; +pub mod net_handler; pub mod notification; pub mod oauth; pub mod os; diff --git a/stdlib/src/net.rs b/stdlib/src/net.rs index 4982d05f..4da84d7e 100644 --- a/stdlib/src/net.rs +++ b/stdlib/src/net.rs @@ -1,13 +1,7 @@ use crate::{StdFunction, StdlibModule, StdlibRegistry}; -use indexmap::IndexMap; -use std::cell::RefCell; use std::collections::HashMap; use std::rc::Rc; -use techscript_runtime::{ - context::Capability, - error::{RuntimeError, RuntimeErrorKind}, - value::RuntimeValue, -}; +use techscript_runtime::context::Capability; impl StdlibRegistry { pub fn register_net(&mut self) { @@ -19,28 +13,7 @@ impl StdlibRegistry { Rc::new(StdFunction { name: "tcp_listen".to_string(), arity: 1, - callback: |ctx, args| { - let port = args[0].try_into_int()?; - let listener = std::net::TcpListener::bind(format!("127.0.0.1:{}", port)) - .map_err(|e| { - RuntimeError::new( - RuntimeErrorKind::InvalidOperation(format!( - "TCP bind error: {}", - e - )), - None, - None, - ) - })?; - let handle_id = ctx.resources.borrow_mut().insert(listener); - let mut listener_map = IndexMap::new(); - listener_map.insert("port".to_string(), RuntimeValue::Int(port)); - listener_map.insert("_handle".to_string(), RuntimeValue::Int(handle_id as i64)); - Ok(RuntimeValue::Map { - entries: Rc::new(RefCell::new(listener_map)), - is_const: false, - }) - }, + callback: crate::net_handler::tcp_listen, }), ); @@ -49,30 +22,7 @@ impl StdlibRegistry { Rc::new(StdFunction { name: "tcp_connect".to_string(), arity: 2, - callback: |ctx, args| { - let ip = args[0].try_into_string()?; - let port = args[1].try_into_int()?; - let stream = - std::net::TcpStream::connect(format!("{}:{}", ip, port)).map_err(|e| { - RuntimeError::new( - RuntimeErrorKind::InvalidOperation(format!( - "TCP connect error: {}", - e - )), - None, - None, - ) - })?; - let handle_id = ctx.resources.borrow_mut().insert(stream); - let mut stream_map = IndexMap::new(); - stream_map.insert("ip".to_string(), RuntimeValue::Str(ip)); - stream_map.insert("port".to_string(), RuntimeValue::Int(port)); - stream_map.insert("_handle".to_string(), RuntimeValue::Int(handle_id as i64)); - Ok(RuntimeValue::Map { - entries: Rc::new(RefCell::new(stream_map)), - is_const: false, - }) - }, + callback: crate::net_handler::tcp_connect, }), ); @@ -81,23 +31,7 @@ impl StdlibRegistry { Rc::new(StdFunction { name: "tcp_send".to_string(), arity: 2, - callback: |ctx, args| { - if let RuntimeValue::Map { entries, .. } = &args[0] { - let handle_id = entries - .borrow() - .get("_handle") - .cloned() - .unwrap_or(RuntimeValue::Null) - .try_into_int()? as u32; - let mut resources = ctx.resources.borrow_mut(); - if let Some(stream) = resources.get_mut::(handle_id) { - use std::io::Write; - let msg = args[1].try_into_string()?; - stream.write_all(msg.as_bytes()).ok(); - } - } - Ok(RuntimeValue::Null) - }, + callback: crate::net_handler::tcp_send, }), ); @@ -106,27 +40,7 @@ impl StdlibRegistry { Rc::new(StdFunction { name: "tcp_recv".to_string(), arity: 1, - callback: |ctx, args| { - if let RuntimeValue::Map { entries, .. } = &args[0] { - let handle_id = entries - .borrow() - .get("_handle") - .cloned() - .unwrap_or(RuntimeValue::Null) - .try_into_int()? as u32; - let mut resources = ctx.resources.borrow_mut(); - if let Some(stream) = resources.get_mut::(handle_id) { - use std::io::Read; - let mut buf = [0; 512]; - if let Ok(n) = stream.read(&mut buf) { - return Ok(RuntimeValue::Str( - String::from_utf8_lossy(&buf[..n]).to_string(), - )); - } - } - } - Ok(RuntimeValue::Str(String::new())) - }, + callback: crate::net_handler::tcp_recv, }), ); diff --git a/stdlib/src/net_handler.rs b/stdlib/src/net_handler.rs new file mode 100644 index 00000000..df76f51f --- /dev/null +++ b/stdlib/src/net_handler.rs @@ -0,0 +1,100 @@ +use indexmap::IndexMap; +use std::cell::RefCell; +use std::rc::Rc; +use techscript_runtime::{ + error::{RuntimeError, RuntimeErrorKind}, + value::RuntimeValue, + RuntimeContext, +}; + +pub fn tcp_listen( + ctx: &mut RuntimeContext, + args: Vec, +) -> Result { + let port = args[0].try_into_int()?; + let listener = std::net::TcpListener::bind(format!("127.0.0.1:{}", port)).map_err(|e| { + RuntimeError::new( + RuntimeErrorKind::InvalidOperation(format!("TCP bind error: {}", e)), + None, + None, + ) + })?; + let handle_id = ctx.resources.borrow_mut().insert(listener); + let mut listener_map = IndexMap::new(); + listener_map.insert("port".to_string(), RuntimeValue::Int(port)); + listener_map.insert("_handle".to_string(), RuntimeValue::Int(handle_id as i64)); + Ok(RuntimeValue::Map { + entries: Rc::new(RefCell::new(listener_map)), + is_const: false, + }) +} + +pub fn tcp_connect( + ctx: &mut RuntimeContext, + args: Vec, +) -> Result { + let ip = args[0].try_into_string()?; + let port = args[1].try_into_int()?; + let stream = std::net::TcpStream::connect(format!("{}:{}", ip, port)).map_err(|e| { + RuntimeError::new( + RuntimeErrorKind::InvalidOperation(format!("TCP connect error: {}", e)), + None, + None, + ) + })?; + let handle_id = ctx.resources.borrow_mut().insert(stream); + let mut stream_map = IndexMap::new(); + stream_map.insert("ip".to_string(), RuntimeValue::Str(ip)); + stream_map.insert("port".to_string(), RuntimeValue::Int(port)); + stream_map.insert("_handle".to_string(), RuntimeValue::Int(handle_id as i64)); + Ok(RuntimeValue::Map { + entries: Rc::new(RefCell::new(stream_map)), + is_const: false, + }) +} + +pub fn tcp_send( + ctx: &mut RuntimeContext, + args: Vec, +) -> Result { + if let RuntimeValue::Map { entries, .. } = &args[0] { + let handle_id = entries + .borrow() + .get("_handle") + .cloned() + .unwrap_or(RuntimeValue::Null) + .try_into_int()? as u32; + let mut resources = ctx.resources.borrow_mut(); + if let Some(stream) = resources.get_mut::(handle_id) { + use std::io::Write; + let msg = args[1].try_into_string()?; + stream.write_all(msg.as_bytes()).ok(); + } + } + Ok(RuntimeValue::Null) +} + +pub fn tcp_recv( + ctx: &mut RuntimeContext, + args: Vec, +) -> Result { + if let RuntimeValue::Map { entries, .. } = &args[0] { + let handle_id = entries + .borrow() + .get("_handle") + .cloned() + .unwrap_or(RuntimeValue::Null) + .try_into_int()? as u32; + let mut resources = ctx.resources.borrow_mut(); + if let Some(stream) = resources.get_mut::(handle_id) { + use std::io::Read; + let mut buf = [0; 512]; + if let Ok(n) = stream.read(&mut buf) { + return Ok(RuntimeValue::Str( + String::from_utf8_lossy(&buf[..n]).to_string(), + )); + } + } + } + Ok(RuntimeValue::Str(String::new())) +} diff --git a/stdlib/tests/stdlib_tests.rs b/stdlib/tests/stdlib_tests.rs index ce296064..50a54c49 100644 --- a/stdlib/tests/stdlib_tests.rs +++ b/stdlib/tests/stdlib_tests.rs @@ -540,7 +540,9 @@ fn test_http_module() { &mut ctx_unprivileged, vec![RuntimeValue::Str(format!("http://127.0.0.1:{}", port))], ); - assert!(matches!(res_get, Err(techscript_runtime::RuntimeError { kind: techscript_runtime::RuntimeErrorKind::InvalidOperation(msg), .. }) if msg.contains("Security policy violation"))); + assert!( + matches!(res_get, Err(techscript_runtime::RuntimeError { kind: techscript_runtime::RuntimeErrorKind::InvalidOperation(msg), .. }) if msg.contains("Security policy violation")) + ); let post = http.exports.get("post").unwrap(); let res_post = post.call( @@ -550,7 +552,9 @@ fn test_http_module() { RuntimeValue::Str("body".to_string()), ], ); - assert!(matches!(res_post, Err(techscript_runtime::RuntimeError { kind: techscript_runtime::RuntimeErrorKind::InvalidOperation(msg), .. }) if msg.contains("Security policy violation"))); + assert!( + matches!(res_post, Err(techscript_runtime::RuntimeError { kind: techscript_runtime::RuntimeErrorKind::InvalidOperation(msg), .. }) if msg.contains("Security policy violation")) + ); // Test with Network capability let mut caps = HashSet::new();