rloop 0.3.0__tar.gz → 0.3.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {rloop-0.3.0 → rloop-0.3.1}/Cargo.lock +1 -1
- {rloop-0.3.0 → rloop-0.3.1}/Cargo.toml +1 -1
- {rloop-0.3.0 → rloop-0.3.1}/PKG-INFO +1 -1
- {rloop-0.3.0 → rloop-0.3.1}/src/tcp.rs +34 -13
- {rloop-0.3.0 → rloop-0.3.1}/LICENSE +0 -0
- {rloop-0.3.0 → rloop-0.3.1}/README.md +0 -0
- {rloop-0.3.0 → rloop-0.3.1}/pyproject.toml +0 -0
- {rloop-0.3.0 → rloop-0.3.1}/rloop/__init__.py +0 -0
- {rloop-0.3.0 → rloop-0.3.1}/rloop/_compat.py +0 -0
- {rloop-0.3.0 → rloop-0.3.1}/rloop/_rloop.pyi +0 -0
- {rloop-0.3.0 → rloop-0.3.1}/rloop/exc.py +0 -0
- {rloop-0.3.0 → rloop-0.3.1}/rloop/futures.py +0 -0
- {rloop-0.3.0 → rloop-0.3.1}/rloop/loop.py +0 -0
- {rloop-0.3.0 → rloop-0.3.1}/rloop/server.py +0 -0
- {rloop-0.3.0 → rloop-0.3.1}/rloop/subprocess.py +0 -0
- {rloop-0.3.0 → rloop-0.3.1}/rloop/transports.py +0 -0
- {rloop-0.3.0 → rloop-0.3.1}/rloop/utils.py +0 -0
- {rloop-0.3.0 → rloop-0.3.1}/src/event_loop.rs +0 -0
- {rloop-0.3.0 → rloop-0.3.1}/src/handles.rs +0 -0
- {rloop-0.3.0 → rloop-0.3.1}/src/io.rs +0 -0
- {rloop-0.3.0 → rloop-0.3.1}/src/lib.rs +0 -0
- {rloop-0.3.0 → rloop-0.3.1}/src/log.rs +0 -0
- {rloop-0.3.0 → rloop-0.3.1}/src/py.rs +0 -0
- {rloop-0.3.0 → rloop-0.3.1}/src/server.rs +0 -0
- {rloop-0.3.0 → rloop-0.3.1}/src/sock.rs +0 -0
- {rloop-0.3.0 → rloop-0.3.1}/src/time.rs +0 -0
- {rloop-0.3.0 → rloop-0.3.1}/src/udp.rs +0 -0
- {rloop-0.3.0 → rloop-0.3.1}/src/utils.rs +0 -0
- {rloop-0.3.0 → rloop-0.3.1}/tests/conftest.py +0 -0
- {rloop-0.3.0 → rloop-0.3.1}/tests/tcp/__init__.py +0 -0
- {rloop-0.3.0 → rloop-0.3.1}/tests/tcp/test_tcp_conn.py +0 -0
- {rloop-0.3.0 → rloop-0.3.1}/tests/tcp/test_tcp_server.py +0 -0
- {rloop-0.3.0 → rloop-0.3.1}/tests/test_handles.py +0 -0
- {rloop-0.3.0 → rloop-0.3.1}/tests/test_sockets.py +0 -0
- {rloop-0.3.0 → rloop-0.3.1}/tests/udp/test_udp.py +0 -0
|
@@ -24,6 +24,11 @@ use crate::{
|
|
|
24
24
|
utils::syscall,
|
|
25
25
|
};
|
|
26
26
|
|
|
27
|
+
// PyO3 removed private CPython's APIs
|
|
28
|
+
unsafe extern "C" {
|
|
29
|
+
fn _PyBytes_Resize(bytes: *mut *mut pyo3::ffi::PyObject, newsize: pyo3::ffi::Py_ssize_t) -> std::os::raw::c_int;
|
|
30
|
+
}
|
|
31
|
+
|
|
27
32
|
pub(crate) struct TCPServer {
|
|
28
33
|
pub fd: i32,
|
|
29
34
|
sfamily: i32,
|
|
@@ -557,25 +562,41 @@ pub(crate) struct TCPReadHandle {
|
|
|
557
562
|
|
|
558
563
|
impl TCPReadHandle {
|
|
559
564
|
#[inline]
|
|
560
|
-
fn recv_direct(&self, py: Python, transport: &TCPTransport
|
|
565
|
+
fn recv_direct(&self, py: Python, transport: &TCPTransport) -> (Option<Py<PyAny>>, bool, bool) {
|
|
566
|
+
const BUF_MAXSIZE: usize = 262_144;
|
|
567
|
+
//: alloc an uninitialized `PyBytes` and read into it: single copy (kernel -> bytes), matching asyncio/CPython's `sock.recv`
|
|
568
|
+
let mut obj =
|
|
569
|
+
unsafe { pyo3::ffi::PyBytes_FromStringAndSize(std::ptr::null(), BUF_MAXSIZE as pyo3::ffi::Py_ssize_t) };
|
|
570
|
+
if obj.is_null() {
|
|
571
|
+
unsafe { pyo3::ffi::PyErr_Clear() };
|
|
572
|
+
return (None, false, false);
|
|
573
|
+
}
|
|
574
|
+
let buf = unsafe { std::slice::from_raw_parts_mut(pyo3::ffi::PyBytes_AsString(obj).cast::<u8>(), BUF_MAXSIZE) };
|
|
575
|
+
|
|
561
576
|
let (read, closed) = self.read_into(&mut transport.state.borrow_mut().stream, buf);
|
|
562
577
|
if read > 0 {
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
578
|
+
if read < BUF_MAXSIZE && unsafe { _PyBytes_Resize(&mut obj, read as pyo3::ffi::Py_ssize_t) } != 0 {
|
|
579
|
+
unsafe { pyo3::ffi::PyErr_Clear() };
|
|
580
|
+
return (None, closed, false);
|
|
581
|
+
}
|
|
582
|
+
let pydata = unsafe { Bound::from_owned_ptr(py, obj).unbind() };
|
|
583
|
+
// `read == BUF_MAXSIZE` means the buffer filled, so more data may be waiting.
|
|
584
|
+
return (Some(pydata), closed, read == BUF_MAXSIZE);
|
|
566
585
|
}
|
|
567
|
-
(
|
|
586
|
+
unsafe { pyo3::ffi::Py_DECREF(obj) };
|
|
587
|
+
(None, closed, false)
|
|
568
588
|
}
|
|
569
589
|
|
|
570
590
|
#[inline]
|
|
571
|
-
fn recv_buffered(&self, py: Python, transport: &TCPTransport) -> (Option<Py<PyAny>>, bool) {
|
|
591
|
+
fn recv_buffered(&self, py: Python, transport: &TCPTransport) -> (Option<Py<PyAny>>, bool, bool) {
|
|
572
592
|
let pybuf: PyBuffer<u8> = PyBuffer::get(&transport.protom_buf_get.bind(py).call1((-1,)).unwrap()).unwrap();
|
|
593
|
+
let max_len = pybuf.len_bytes();
|
|
573
594
|
|
|
574
595
|
let (read, closed) = if pybuf.is_c_contiguous() && !pybuf.readonly() {
|
|
575
596
|
// Read straight into the protocol's buffer, no intermediate allocation or
|
|
576
597
|
// copy. The GIL is held for the whole call, so nothing else can touch the
|
|
577
598
|
// buffer concurrently, and we only access it through this slice.
|
|
578
|
-
let buf = unsafe { std::slice::from_raw_parts_mut(pybuf.buf_ptr().cast::<u8>(),
|
|
599
|
+
let buf = unsafe { std::slice::from_raw_parts_mut(pybuf.buf_ptr().cast::<u8>(), max_len) };
|
|
579
600
|
self.read_into(&mut transport.state.borrow_mut().stream, buf)
|
|
580
601
|
} else {
|
|
581
602
|
// Fallback for non-contiguous/read-only buffers: copy through a temp Vec.
|
|
@@ -588,9 +609,9 @@ impl TCPReadHandle {
|
|
|
588
609
|
};
|
|
589
610
|
|
|
590
611
|
if read > 0 {
|
|
591
|
-
return (Some(read.into_py_any(py).unwrap()), closed);
|
|
612
|
+
return (Some(read.into_py_any(py).unwrap()), closed, read == max_len);
|
|
592
613
|
}
|
|
593
|
-
(None, closed)
|
|
614
|
+
(None, closed, false)
|
|
594
615
|
}
|
|
595
616
|
|
|
596
617
|
#[inline(always)]
|
|
@@ -628,7 +649,7 @@ impl TCPReadHandle {
|
|
|
628
649
|
}
|
|
629
650
|
|
|
630
651
|
impl Handle for TCPReadHandle {
|
|
631
|
-
fn run(&self, py: Python, event_loop: &EventLoop,
|
|
652
|
+
fn run(&self, py: Python, event_loop: &EventLoop, _state: &mut EventLoopRunState) {
|
|
632
653
|
let pytransport = event_loop.get_tcp_transport(self.fd, py);
|
|
633
654
|
let transport = pytransport.borrow(py);
|
|
634
655
|
|
|
@@ -636,14 +657,14 @@ impl Handle for TCPReadHandle {
|
|
|
636
657
|
// otherwise we won't get another readable event from the poller
|
|
637
658
|
let mut close = false;
|
|
638
659
|
loop {
|
|
639
|
-
let (data, eof) = match transport.proto_buffered {
|
|
660
|
+
let (data, eof, full) = match transport.proto_buffered {
|
|
640
661
|
true => self.recv_buffered(py, &transport),
|
|
641
|
-
false => self.recv_direct(py, &transport
|
|
662
|
+
false => self.recv_direct(py, &transport),
|
|
642
663
|
};
|
|
643
664
|
|
|
644
665
|
if let Some(data) = data {
|
|
645
666
|
_ = transport.protom_recv_data.call1(py, (data,));
|
|
646
|
-
if !eof {
|
|
667
|
+
if !eof && full {
|
|
647
668
|
continue;
|
|
648
669
|
}
|
|
649
670
|
}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|