merge upstream

This commit is contained in:
Ricky Han
2019-02-25 14:54:10 -05:00
18 changed files with 919 additions and 279 deletions

View File

@@ -169,6 +169,7 @@ pub enum Instruction {
},
Unpack,
FormatValue {
conversion: Option<ast::ConversionFlag>,
spec: String,
},
}
@@ -361,7 +362,10 @@ impl Instruction {
UnpackSequence { size } => w!(UnpackSequence, size),
UnpackEx { before, after } => w!(UnpackEx, before, after),
Unpack => w!(Unpack),
FormatValue { spec } => w!(FormatValue, spec),
FormatValue {
conversion: _,
spec,
} => w!(FormatValue, spec), // TODO: write conversion
}
}
}

View File

@@ -1352,9 +1352,16 @@ impl Compiler {
},
});
}
ast::StringGroup::FormattedValue { value, spec } => {
ast::StringGroup::FormattedValue {
value,
conversion,
spec,
} => {
self.compile_expression(value)?;
self.emit(Instruction::FormatValue { spec: spec.clone() });
self.emit(Instruction::FormatValue {
conversion: *conversion,
spec: spec.clone(),
});
}
}
Ok(())

View File

@@ -654,8 +654,15 @@ impl Frame {
}
Ok(None)
}
bytecode::Instruction::FormatValue { spec } => {
let value = self.pop_value();
bytecode::Instruction::FormatValue { conversion, spec } => {
use ast::ConversionFlag::*;
let value = match conversion {
Some(Str) => vm.to_str(&self.pop_value())?,
Some(Repr) => vm.to_repr(&self.pop_value())?,
Some(Ascii) => self.pop_value(), // TODO
None => self.pop_value(),
};
let spec = vm.new_str(spec.clone());
let formatted = vm.call_method(&value, "__format__", vec![spec])?;
self.push_value(formatted);

View File

@@ -1,10 +1,16 @@
use super::objtype;
use crate::pyobject::{
PyContext, PyFuncArgs, PyObjectPayload, PyObjectRef, PyResult, TypeProtocol,
IntoPyObject, PyContext, PyFuncArgs, PyObjectPayload, PyObjectRef, PyResult, TypeProtocol,
};
use crate::vm::VirtualMachine;
use num_traits::Zero;
impl IntoPyObject for bool {
fn into_pyobject(self, ctx: &PyContext) -> PyResult {
Ok(ctx.new_bool(self))
}
}
pub fn boolval(vm: &mut VirtualMachine, obj: PyObjectRef) -> Result<bool, PyObjectRef> {
let result = match obj.borrow().payload {
PyObjectPayload::Integer { ref value } => !value.is_zero(),

View File

@@ -3,8 +3,8 @@ use super::objstr;
use super::objtype;
use crate::format::FormatSpec;
use crate::pyobject::{
FromPyObjectRef, PyContext, PyFuncArgs, PyObject, PyObjectPayload, PyObjectRef, PyResult,
TypeProtocol,
FromPyObjectRef, IntoPyObject, PyContext, PyFuncArgs, PyObject, PyObjectPayload, PyObjectRef,
PyResult, TypeProtocol,
};
use crate::vm::VirtualMachine;
use num_bigint::{BigInt, ToBigInt};
@@ -15,6 +15,22 @@ use std::hash::{Hash, Hasher};
// This proxy allows for easy switching between types.
type IntType = BigInt;
pub type PyInt = BigInt;
impl IntoPyObject for PyInt {
fn into_pyobject(self, ctx: &PyContext) -> PyResult {
Ok(ctx.new_int(self))
}
}
// TODO: macro to impl for all primitive ints
impl IntoPyObject for usize {
fn into_pyobject(self, ctx: &PyContext) -> PyResult {
Ok(ctx.new_int(self))
}
}
fn int_repr(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
arg_check!(vm, args, required = [(int, Some(vm.ctx.int_type()))]);
let v = get_value(int);

View File

@@ -1,7 +1,8 @@
use super::objint;
use super::objtype;
use crate::pyobject::{
PyContext, PyFuncArgs, PyObject, PyObjectPayload, PyObjectRef, PyResult, TypeProtocol,
FromPyObject, PyContext, PyFuncArgs, PyObject, PyObjectPayload, PyObjectRef, PyResult,
TypeProtocol,
};
use crate::vm::VirtualMachine;
use num_bigint::{BigInt, Sign};
@@ -18,6 +19,18 @@ pub struct RangeType {
pub step: BigInt,
}
type PyRange = RangeType;
impl FromPyObject for PyRange {
fn typ(ctx: &PyContext) -> Option<PyObjectRef> {
Some(ctx.range_type())
}
fn from_pyobject(obj: PyObjectRef) -> PyResult<Self> {
Ok(get_value(&obj))
}
}
impl RangeType {
#[inline]
pub fn try_len(&self) -> Option<usize> {
@@ -345,22 +358,12 @@ fn range_bool(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
Ok(vm.ctx.new_bool(len > 0))
}
fn range_contains(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
arg_check!(
vm,
args,
required = [(zelf, Some(vm.ctx.range_type())), (needle, None)]
);
let range = get_value(zelf);
let result = if objtype::isinstance(needle, &vm.ctx.int_type()) {
range.contains(&objint::get_value(needle))
fn range_contains(vm: &mut VirtualMachine, zelf: PyRange, needle: PyObjectRef) -> bool {
if objtype::isinstance(&needle, &vm.ctx.int_type()) {
zelf.contains(&objint::get_value(&needle))
} else {
false
};
Ok(vm.ctx.new_bool(result))
}
}
fn range_index(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {

View File

@@ -3,7 +3,8 @@ use super::objsequence::PySliceableSequence;
use super::objtype;
use crate::format::{FormatParseError, FormatPart, FormatString};
use crate::pyobject::{
PyContext, PyFuncArgs, PyObject, PyObjectPayload, PyObjectRef, PyResult, TypeProtocol,
FromPyObject, PyContext, PyFuncArgs, PyObject, PyObjectPayload, PyObjectRef, PyResult,
TypeProtocol,
};
use crate::vm::VirtualMachine;
use num_traits::ToPrimitive;
@@ -17,6 +18,16 @@ extern crate unicode_segmentation;
use self::unicode_segmentation::UnicodeSegmentation;
impl FromPyObject for String {
fn typ(ctx: &PyContext) -> Option<PyObjectRef> {
Some(ctx.str_type())
}
fn from_pyobject(obj: PyObjectRef) -> PyResult<Self> {
Ok(get_value(&obj))
}
}
pub fn init(context: &PyContext) {
let str_type = &context.str_type;
context.set_attr(&str_type, "__add__", context.new_rustfunc(str_add));
@@ -474,15 +485,8 @@ fn str_rstrip(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
Ok(vm.ctx.new_str(value))
}
fn str_endswith(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
arg_check!(
vm,
args,
required = [(s, Some(vm.ctx.str_type())), (pat, Some(vm.ctx.str_type()))]
);
let value = get_value(&s);
let pat = get_value(&pat);
Ok(vm.ctx.new_bool(value.ends_with(pat.as_str())))
fn str_endswith(_vm: &mut VirtualMachine, zelf: String, suffix: String) -> bool {
zelf.ends_with(&suffix)
}
fn str_isidentifier(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {

View File

@@ -29,6 +29,7 @@ use crate::obj::objsuper;
use crate::obj::objtuple;
use crate::obj::objtype;
use crate::obj::objzip;
use crate::stdlib::socket::Socket;
use crate::vm::VirtualMachine;
use num_bigint::BigInt;
use num_bigint::ToBigInt;
@@ -72,7 +73,7 @@ pub type PyObjectWeakRef = Weak<RefCell<PyObject>>;
/// Use this type for function which return a python object or and exception.
/// Both the python object and the python exception are `PyObjectRef` types
/// since exceptions are also python objects.
pub type PyResult = Result<PyObjectRef, PyObjectRef>; // A valid value, or an exception
pub type PyResult<T = PyObjectRef> = Result<T, PyObjectRef>; // A valid value, or an exception
/// For attributes we do not use a dict, but a hashmap. This is probably
/// faster, unordered, and only supports strings as keys.
@@ -553,13 +554,13 @@ impl PyContext {
)
}
pub fn new_rustfunc<F: 'static + Fn(&mut VirtualMachine, PyFuncArgs) -> PyResult>(
&self,
function: F,
) -> PyObjectRef {
pub fn new_rustfunc<F, T, R>(&self, factory: F) -> PyObjectRef
where
F: PyNativeFuncFactory<T, R>,
{
PyObject::new(
PyObjectPayload::RustFunction {
function: Box::new(function),
function: factory.create(self),
},
self.builtin_function_or_method_type(),
)
@@ -945,6 +946,203 @@ impl PyFuncArgs {
}
}
pub trait FromPyObject: Sized {
fn typ(ctx: &PyContext) -> Option<PyObjectRef>;
fn from_pyobject(obj: PyObjectRef) -> PyResult<Self>;
}
impl FromPyObject for PyObjectRef {
fn typ(_ctx: &PyContext) -> Option<PyObjectRef> {
None
}
fn from_pyobject(obj: PyObjectRef) -> PyResult<Self> {
Ok(obj)
}
}
pub trait IntoPyObject {
fn into_pyobject(self, ctx: &PyContext) -> PyResult;
}
impl IntoPyObject for PyObjectRef {
fn into_pyobject(self, _ctx: &PyContext) -> PyResult {
Ok(self)
}
}
impl IntoPyObject for PyResult {
fn into_pyobject(self, _ctx: &PyContext) -> PyResult {
self
}
}
pub trait FromPyFuncArgs: Sized {
fn required_params(ctx: &PyContext) -> Vec<Parameter>;
fn from_py_func_args(args: &mut PyFuncArgs) -> PyResult<Self>;
}
macro_rules! tuple_from_py_func_args {
($($T:ident),+) => {
impl<$($T),+> FromPyFuncArgs for ($($T,)+)
where
$($T: FromPyFuncArgs),+
{
fn required_params(ctx: &PyContext) -> Vec<Parameter> {
vec![$($T::required_params(ctx),)+].into_iter().flatten().collect()
}
fn from_py_func_args(args: &mut PyFuncArgs) -> PyResult<Self> {
Ok(($($T::from_py_func_args(args)?,)+))
}
}
};
}
tuple_from_py_func_args!(A);
tuple_from_py_func_args!(A, B);
tuple_from_py_func_args!(A, B, C);
tuple_from_py_func_args!(A, B, C, D);
tuple_from_py_func_args!(A, B, C, D, E);
impl<T> FromPyFuncArgs for T
where
T: FromPyObject,
{
fn required_params(ctx: &PyContext) -> Vec<Parameter> {
vec![Parameter {
kind: PositionalOnly,
typ: T::typ(ctx),
}]
}
fn from_py_func_args(args: &mut PyFuncArgs) -> PyResult<Self> {
Self::from_pyobject(args.shift())
}
}
pub type PyNativeFunc = Box<dyn Fn(&mut VirtualMachine, PyFuncArgs) -> PyResult>;
pub trait PyNativeFuncFactory<T, R> {
fn create(self, ctx: &PyContext) -> PyNativeFunc;
}
impl<F> PyNativeFuncFactory<PyFuncArgs, PyResult> for F
where
F: Fn(&mut VirtualMachine, PyFuncArgs) -> PyResult + 'static,
{
fn create(self, _ctx: &PyContext) -> PyNativeFunc {
Box::new(self)
}
}
macro_rules! tuple_py_native_func_factory {
($($T:ident),+) => {
impl<F, $($T,)+ R> PyNativeFuncFactory<($($T,)+), R> for F
where
F: Fn(&mut VirtualMachine, $($T),+) -> R + 'static,
$($T: FromPyFuncArgs,)+
R: IntoPyObject,
{
fn create(self, ctx: &PyContext) -> PyNativeFunc {
let parameters = vec![$($T::required_params(ctx)),+]
.into_iter()
.flatten()
.collect();
let signature = Signature::new(parameters);
Box::new(move |vm, mut args| {
signature.check(vm, &mut args)?;
(self)(vm, $($T::from_py_func_args(&mut args)?,)+)
.into_pyobject(&vm.ctx)
})
}
}
};
}
tuple_py_native_func_factory!(A);
tuple_py_native_func_factory!(A, B);
tuple_py_native_func_factory!(A, B, C);
tuple_py_native_func_factory!(A, B, C, D);
tuple_py_native_func_factory!(A, B, C, D, E);
#[derive(Debug)]
pub struct Signature {
positional_params: Vec<Parameter>,
keyword_params: HashMap<String, Parameter>,
}
impl Signature {
fn new(params: Vec<Parameter>) -> Self {
let mut positional_params = Vec::new();
let mut keyword_params = HashMap::new();
for param in params {
match param.kind {
PositionalOnly => {
positional_params.push(param);
}
KeywordOnly { ref name } => {
keyword_params.insert(name.clone(), param);
}
}
}
Self {
positional_params,
keyword_params,
}
}
fn arg_type(&self, pos: usize) -> Option<&PyObjectRef> {
self.positional_params[pos].typ.as_ref()
}
#[allow(unused)]
fn kwarg_type(&self, name: &str) -> Option<&PyObjectRef> {
self.keyword_params[name].typ.as_ref()
}
fn check(&self, vm: &mut VirtualMachine, args: &PyFuncArgs) -> PyResult<()> {
// TODO: check arity
for (pos, arg) in args.args.iter().enumerate() {
if let Some(expected_type) = self.arg_type(pos) {
if !objtype::isinstance(arg, expected_type) {
let arg_typ = arg.typ();
let expected_type_name = vm.to_pystr(&expected_type)?;
let actual_type = vm.to_pystr(&arg_typ)?;
return Err(vm.new_type_error(format!(
"argument of type {} is required for parameter {} (got: {})",
expected_type_name,
pos + 1,
actual_type
)));
}
}
}
Ok(())
}
}
#[derive(Debug)]
pub struct Parameter {
typ: Option<PyObjectRef>,
kind: ParameterKind,
}
#[derive(Debug)]
pub enum ParameterKind {
PositionalOnly,
KeywordOnly { name: String },
}
use self::ParameterKind::*;
/// Rather than determining the type of a python object, this enum is more
/// a holder for the rust payload of a python object. It is more a carrier
/// of rust data for a particular python object. Determine the python type
@@ -1045,6 +1243,9 @@ pub enum PyObjectPayload {
RustFunction {
function: Box<Fn(&mut VirtualMachine, PyFuncArgs) -> PyResult>,
},
Socket {
socket: Socket,
},
}
impl fmt::Debug for PyObjectPayload {
@@ -1082,6 +1283,7 @@ impl fmt::Debug for PyObjectPayload {
PyObjectPayload::Instance { .. } => write!(f, "instance"),
PyObjectPayload::RustFunction { .. } => write!(f, "rust function"),
PyObjectPayload::Frame { .. } => write!(f, "frame"),
PyObjectPayload::Socket { .. } => write!(f, "socket"),
}
}
}

View File

@@ -6,6 +6,7 @@ mod math;
mod pystruct;
mod random;
mod re;
pub mod socket;
mod string;
mod time_module;
mod tokenize;
@@ -25,24 +26,25 @@ pub type StdlibInitFunc = Box<dyn Fn(&PyContext) -> PyObjectRef>;
pub fn get_module_inits() -> HashMap<String, StdlibInitFunc> {
let mut modules = HashMap::new();
modules.insert("ast".to_string(), Box::new(ast::mk_module) as StdlibInitFunc);
modules.insert("dis".to_string(), Box::new(dis::mk_module) as StdlibInitFunc);
modules.insert("json".to_string(), Box::new(json::mk_module) as StdlibInitFunc);
modules.insert("keyword".to_string(), Box::new(keyword::mk_module) as StdlibInitFunc);
modules.insert("math".to_string(), Box::new(math::mk_module) as StdlibInitFunc);
modules.insert("re".to_string(), Box::new(re::mk_module) as StdlibInitFunc);
modules.insert("random".to_string(), Box::new(random::mk_module) as StdlibInitFunc);
modules.insert("string".to_string(), Box::new(string::mk_module) as StdlibInitFunc);
modules.insert("struct".to_string(), Box::new(pystruct::mk_module) as StdlibInitFunc);
modules.insert("time".to_string(), Box::new(time_module::mk_module) as StdlibInitFunc);
modules.insert( "tokenize".to_string(), Box::new(tokenize::mk_module) as StdlibInitFunc);
modules.insert("types".to_string(), Box::new(types::mk_module) as StdlibInitFunc);
modules.insert("_weakref".to_string(), Box::new(weakref::mk_module) as StdlibInitFunc);
modules.insert("dis".to_string(), Box::new(dis::mk_module));
modules.insert("json".to_string(), Box::new(json::mk_module));
modules.insert("keyword".to_string(), Box::new(keyword::mk_module));
modules.insert("math".to_string(), Box::new(math::mk_module));
modules.insert("re".to_string(), Box::new(re::mk_module));
modules.insert("random".to_string(), Box::new(random::mk_module));
modules.insert("string".to_string(), Box::new(string::mk_module));
modules.insert("struct".to_string(), Box::new(pystruct::mk_module));
modules.insert("time".to_string(), Box::new(time_module::mk_module));
modules.insert("tokenize".to_string(), Box::new(tokenize::mk_module));
modules.insert("types".to_string(), Box::new(types::mk_module));
modules.insert("_weakref".to_string(), Box::new(weakref::mk_module));
// disable some modules on WASM
#[cfg(not(target_arch = "wasm32"))]
{
modules.insert("io".to_string(), Box::new(io::mk_module) as StdlibInitFunc);
modules.insert("os".to_string(), Box::new(os::mk_module) as StdlibInitFunc);
modules.insert("io".to_string(), Box::new(io::mk_module));
modules.insert("os".to_string(), Box::new(os::mk_module));
modules.insert("socket".to_string(), Box::new(socket::mk_module));
}
modules

315
vm/src/stdlib/socket.rs Normal file
View File

@@ -0,0 +1,315 @@
use crate::obj::objbytes;
use crate::obj::objint;
use crate::obj::objsequence::get_elements;
use crate::obj::objstr;
use crate::pyobject::{
PyContext, PyFuncArgs, PyObject, PyObjectPayload, PyObjectRef, PyResult, TypeProtocol,
};
use crate::vm::VirtualMachine;
use num_traits::ToPrimitive;
use std::io;
use std::io::Read;
use std::io::Write;
use std::net::{SocketAddr, TcpListener, TcpStream, UdpSocket};
#[derive(Copy, Clone)]
enum AddressFamily {
AfUnix = 1,
AfInet = 2,
AfInet6 = 3,
}
impl AddressFamily {
fn from_i32(value: i32) -> AddressFamily {
match value {
1 => AddressFamily::AfUnix,
2 => AddressFamily::AfInet,
3 => AddressFamily::AfInet6,
_ => panic!("Unknown value: {}", value),
}
}
}
#[derive(Copy, Clone)]
enum SocketKind {
SockStream = 1,
SockDgram = 2,
}
impl SocketKind {
fn from_i32(value: i32) -> SocketKind {
match value {
1 => SocketKind::SockStream,
2 => SocketKind::SockDgram,
_ => panic!("Unknown value: {}", value),
}
}
}
enum Connection {
TcpListener(TcpListener),
TcpStream(TcpStream),
UdpSocket(UdpSocket),
}
impl Connection {
fn accept(&mut self) -> io::Result<(TcpStream, SocketAddr)> {
match self {
Connection::TcpListener(con) => con.accept(),
_ => Err(io::Error::new(io::ErrorKind::Other, "oh no!")),
}
}
}
impl Read for Connection {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
match self {
Connection::TcpStream(con) => con.read(buf),
_ => Err(io::Error::new(io::ErrorKind::Other, "oh no!")),
}
}
}
impl Write for Connection {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
match self {
Connection::TcpStream(con) => con.write(buf),
_ => Err(io::Error::new(io::ErrorKind::Other, "oh no!")),
}
}
fn flush(&mut self) -> io::Result<()> {
Ok(())
}
}
pub struct Socket {
address_family: AddressFamily,
sk: SocketKind,
con: Option<Connection>,
}
impl Socket {
fn new(address_family: AddressFamily, sk: SocketKind) -> Socket {
Socket {
address_family,
sk: sk,
con: None,
}
}
}
fn socket_new(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
arg_check!(
vm,
args,
required = [
(cls, None),
(family_int, Some(vm.ctx.int_type())),
(kind_int, Some(vm.ctx.int_type()))
]
);
let address_family = AddressFamily::from_i32(objint::get_value(family_int).to_i32().unwrap());
let kind = SocketKind::from_i32(objint::get_value(kind_int).to_i32().unwrap());
let socket = Socket::new(address_family, kind);
Ok(PyObject::new(
PyObjectPayload::Socket { socket },
cls.clone(),
))
}
fn socket_connect(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
arg_check!(
vm,
args,
required = [(zelf, None), (address, Some(vm.ctx.tuple_type()))]
);
let elements = get_elements(address);
let host = objstr::get_value(&elements[0]);
let port = objint::get_value(&elements[1]);
let address_string = format!("{}:{}", host, port.to_string());
let mut mut_obj = zelf.borrow_mut();
match mut_obj.payload {
PyObjectPayload::Socket { ref mut socket } => {
if let Ok(stream) = TcpStream::connect(address_string) {
socket.con = Some(Connection::TcpStream(stream));
Ok(vm.get_none())
} else {
// TODO: Socket error
Err(vm.new_type_error("socket failed".to_string()))
}
}
_ => Err(vm.new_type_error("".to_string())),
}
}
fn socket_bind(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
arg_check!(
vm,
args,
required = [(zelf, None), (address, Some(vm.ctx.tuple_type()))]
);
let elements = get_elements(address);
let host = objstr::get_value(&elements[0]);
let port = objint::get_value(&elements[1]);
let address_string = format!("{}:{}", host, port.to_string());
let mut mut_obj = zelf.borrow_mut();
match mut_obj.payload {
PyObjectPayload::Socket { ref mut socket } => {
if let Ok(stream) = TcpListener::bind(address_string) {
socket.con = Some(Connection::TcpListener(stream));
Ok(vm.get_none())
} else {
// TODO: Socket error
Err(vm.new_type_error("socket failed".to_string()))
}
}
_ => Err(vm.new_type_error("".to_string())),
}
}
fn socket_listen(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
Ok(vm.get_none())
}
fn socket_accept(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
arg_check!(vm, args, required = [(zelf, None)]);
let mut mut_obj = zelf.borrow_mut();
match mut_obj.payload {
PyObjectPayload::Socket { ref mut socket } => {
let ret = match socket.con {
Some(ref mut v) => v.accept(),
None => return Err(vm.new_type_error("".to_string())),
};
let tcp_stream = match ret {
Ok((socket, _addr)) => socket,
_ => return Err(vm.new_type_error("".to_string())),
};
let socket = Socket {
address_family: socket.address_family.clone(),
sk: socket.sk.clone(),
con: Some(Connection::TcpStream(tcp_stream)),
};
let sock_obj = PyObject::new(PyObjectPayload::Socket { socket }, mut_obj.typ());
let elements = vec![sock_obj, vm.get_none()];
Ok(PyObject::new(
PyObjectPayload::Sequence { elements },
vm.ctx.tuple_type(),
))
}
_ => Err(vm.new_type_error("".to_string())),
}
}
fn socket_recv(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
arg_check!(
vm,
args,
required = [(zelf, None), (bufsize, Some(vm.ctx.int_type()))]
);
let mut mut_obj = zelf.borrow_mut();
match mut_obj.payload {
PyObjectPayload::Socket { ref mut socket } => {
let mut buffer = Vec::new();
let _temp = match socket.con {
Some(ref mut v) => v.read_to_end(&mut buffer).unwrap(),
None => 0,
};
Ok(PyObject::new(
PyObjectPayload::Bytes { value: buffer },
vm.ctx.bytes_type(),
))
}
_ => Err(vm.new_type_error("".to_string())),
}
}
fn socket_send(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
arg_check!(
vm,
args,
required = [(zelf, None), (bytes, Some(vm.ctx.bytes_type()))]
);
let mut mut_obj = zelf.borrow_mut();
match mut_obj.payload {
PyObjectPayload::Socket { ref mut socket } => {
match socket.con {
Some(ref mut v) => v.write(&objbytes::get_value(&bytes)).unwrap(),
None => return Err(vm.new_type_error("".to_string())),
};
Ok(vm.get_none())
}
_ => Err(vm.new_type_error("".to_string())),
}
}
fn socket_close(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
arg_check!(vm, args, required = [(zelf, None)]);
let mut mut_obj = zelf.borrow_mut();
match mut_obj.payload {
PyObjectPayload::Socket { ref mut socket } => match socket.address_family {
AddressFamily::AfInet => match socket.sk {
SocketKind::SockStream => {
socket.con = None;
Ok(vm.get_none())
}
_ => Err(vm.new_type_error("".to_string())),
},
_ => Err(vm.new_type_error("".to_string())),
},
_ => Err(vm.new_type_error("".to_string())),
}
}
pub fn mk_module(ctx: &PyContext) -> PyObjectRef {
let py_mod = ctx.new_module(&"socket".to_string(), ctx.new_scope(None));
ctx.set_attr(
&py_mod,
"AF_INET",
ctx.new_int(AddressFamily::AfInet as i32),
);
ctx.set_attr(
&py_mod,
"SOCK_STREAM",
ctx.new_int(SocketKind::SockStream as i32),
);
let socket = {
let socket = ctx.new_class("socket", ctx.object());
ctx.set_attr(&socket, "__new__", ctx.new_rustfunc(socket_new));
ctx.set_attr(&socket, "connect", ctx.new_rustfunc(socket_connect));
ctx.set_attr(&socket, "recv", ctx.new_rustfunc(socket_recv));
ctx.set_attr(&socket, "send", ctx.new_rustfunc(socket_send));
ctx.set_attr(&socket, "bind", ctx.new_rustfunc(socket_bind));
ctx.set_attr(&socket, "accept", ctx.new_rustfunc(socket_accept));
ctx.set_attr(&socket, "listen", ctx.new_rustfunc(socket_listen));
ctx.set_attr(&socket, "close", ctx.new_rustfunc(socket_close));
socket
};
ctx.set_attr(&py_mod, "socket", socket.clone());
py_mod
}