Vendor dependencies

This commit is contained in:
2026-08-01 16:11:49 +03:00
parent 7f139a0241
commit 6b5e7f0f8b
29706 changed files with 9575646 additions and 0 deletions
@@ -0,0 +1,153 @@
use std::cmp::min;
use std::collections::VecDeque;
use std::pin::Pin;
use std::task::{Context, Poll, Waker};
use futures_util::{AsyncRead, AsyncWrite};
#[derive(Debug, Default)]
pub struct ByteChannel {
queue: VecDeque<u8>,
waker: Option<Waker>,
closed: bool,
}
impl ByteChannel {
pub fn new() -> Self {
Self::default()
}
}
impl AsyncRead for ByteChannel {
fn poll_read(
mut self: Pin<&mut Self>,
cx: &mut Context<'_>,
buf: &mut [u8],
) -> Poll<std::io::Result<usize>> {
if buf.is_empty() || (self.queue.is_empty() && self.closed) {
return Poll::Ready(Ok(0));
}
let num_read = min(self.queue.len(), buf.len());
if num_read == 0 {
self.waker = Some(cx.waker().clone());
return Poll::Pending;
}
buf.iter_mut()
.zip(self.queue.drain(0..num_read))
.for_each(|(dst, src)| *dst = src);
Poll::Ready(Ok(num_read))
}
}
impl AsyncWrite for ByteChannel {
fn poll_write(
mut self: Pin<&mut Self>,
_cx: &mut Context<'_>,
buf: &[u8],
) -> Poll<std::io::Result<usize>> {
self.queue.extend(buf.iter());
if let Some(waker) = self.waker.take() {
waker.wake();
}
Poll::Ready(Ok(buf.len()))
}
fn poll_flush(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<std::io::Result<()>> {
Poll::Ready(Ok(()))
}
fn poll_close(mut self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<std::io::Result<()>> {
self.closed = true;
if let Some(waker) = self.waker.take() {
waker.wake();
}
Poll::Ready(Ok(()))
}
}
#[cfg(test)]
mod tests {
use futures_util::future::join;
use futures_util::{AsyncReadExt, AsyncWriteExt};
use super::*;
#[tokio::test]
async fn test_write_then_read() {
let channel = ByteChannel::new();
let (mut reader, mut writer) = channel.split();
let mut buf = [0u8; 3];
writer.write_all(&[1, 2, 3, 4]).await.unwrap();
assert_eq!(reader.read(&mut buf).await.unwrap(), 3);
assert_eq!(&buf, &[1, 2, 3]);
writer.write_all(&[5, 6]).await.unwrap();
assert_eq!(reader.read(&mut buf).await.unwrap(), 3);
assert_eq!(&buf, &[4, 5, 6]);
writer.close().await.unwrap();
assert_eq!(reader.read(&mut buf).await.unwrap(), 0);
}
#[tokio::test]
async fn test_read_then_write() {
let channel = ByteChannel::new();
let (mut reader, mut writer) = channel.split();
join(
async {
let mut buf = [0u8; 3];
assert_eq!(reader.read(&mut buf).await.unwrap(), 3);
assert_eq!(&buf, &[1, 2, 3]);
},
async {
writer.write_all(&[1, 2, 3, 4]).await.unwrap();
},
)
.await;
}
#[tokio::test]
async fn test_read_then_close() {
let channel = ByteChannel::new();
let (mut reader, mut writer) = channel.split();
join(
async {
let mut buf = [0u8; 3];
assert_eq!(reader.read(&mut buf).await.unwrap(), 0);
assert_eq!(&buf, &[0, 0, 0]);
},
async {
writer.close().await.unwrap();
},
)
.await;
}
#[tokio::test]
async fn test_close_then_read() {
let channel = ByteChannel::new();
let (mut reader, mut writer) = channel.split();
writer.write_all(&[1, 2, 3]).await.unwrap();
writer.close().await.unwrap();
// should still read bytes from queue
let mut buf = [0u8; 3];
assert_eq!(reader.read(&mut buf).await.unwrap(), 3);
assert_eq!(&buf, &[1, 2, 3]);
// should read EOF
assert_eq!(reader.read(&mut buf).await.unwrap(), 0);
}
#[tokio::test]
async fn test_read_into_empty_buffer() {
let channel = ByteChannel::new();
let (mut reader, _writer) = channel.split();
let mut buf = [0u8; 0];
assert_eq!(reader.read(&mut buf).await.unwrap(), 0);
}
}
@@ -0,0 +1,77 @@
use std::cell::RefCell;
use std::pin::Pin;
use std::rc::Rc;
use std::task::{Context, Poll};
use futures_util::{Sink, Stream};
use pin_project::{pin_project, pinned_drop};
#[pin_project(PinnedDrop)]
pub struct DropObservable<S> {
#[pin]
inner: S,
handle: Rc<RefCell<bool>>,
}
#[pinned_drop]
impl<T> PinnedDrop for DropObservable<T> {
fn drop(self: Pin<&mut Self>) {
*self.project().handle.borrow_mut() = true
}
}
pub struct DropObserver {
handle: Rc<RefCell<bool>>,
}
impl DropObserver {
pub fn is_dropped(&self) -> bool {
*self.handle.borrow()
}
}
pub fn observe_drop<T>(inner: T) -> (DropObservable<T>, DropObserver) {
let handle = Rc::new(RefCell::new(false));
(
DropObservable {
inner,
handle: handle.clone(),
},
DropObserver { handle },
)
}
impl<S: Stream> Stream for DropObservable<S> {
type Item = S::Item;
fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
self.project().inner.poll_next(cx)
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.inner.size_hint()
}
}
impl<S, Item> Sink<Item> for DropObservable<S>
where
S: Sink<Item>,
{
type Error = S::Error;
fn poll_ready(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
self.project().inner.poll_ready(cx)
}
fn start_send(self: Pin<&mut Self>, item: Item) -> Result<(), Self::Error> {
self.project().inner.start_send(item)
}
fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
self.project().inner.poll_flush(cx)
}
fn poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
self.project().inner.poll_close(cx)
}
}
@@ -0,0 +1,52 @@
use std::pin::Pin;
use std::task::{Context, Poll};
use futures_util::sink::Sink;
use wasm_bindgen::prelude::*;
/// A Sink that always errors on the first write.
pub struct FailingSink {
failed: bool,
}
impl FailingSink {
pub fn new() -> Self {
Self { failed: false }
}
}
impl Default for FailingSink {
fn default() -> Self {
Self::new()
}
}
impl Sink<JsValue> for FailingSink {
type Error = JsValue;
fn poll_ready(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
Poll::Ready(Ok(()))
}
fn start_send(mut self: Pin<&mut Self>, _item: JsValue) -> Result<(), Self::Error> {
if !self.failed {
self.failed = true;
// Return an error on first write
Err(JsValue::from_str("intentional error"))
} else {
Ok(())
}
}
fn poll_flush(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
if self.failed {
Poll::Ready(Err(JsValue::from_str("sink has failed")))
} else {
Poll::Ready(Ok(()))
}
}
fn poll_close(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
Poll::Ready(Ok(()))
}
}
+11
View File
@@ -0,0 +1,11 @@
pub use byte_channel::ByteChannel;
pub use drop_observer::observe_drop;
pub use failing_sink::FailingSink;
pub use simple_channel::SimpleChannel;
pub use unhandled_error_guard::UnhandledErrorGuard;
pub mod byte_channel;
pub mod drop_observer;
pub mod failing_sink;
pub mod simple_channel;
pub mod unhandled_error_guard;
@@ -0,0 +1,163 @@
use std::collections::VecDeque;
use std::pin::Pin;
use std::task::{Context, Poll, Waker};
use futures_util::{Sink, Stream};
use pin_project::pin_project;
#[pin_project]
#[derive(Debug)]
pub struct SimpleChannel<T> {
queue: VecDeque<T>,
waker: Option<Waker>,
closed: bool,
}
impl<T> SimpleChannel<T> {
pub fn new() -> Self {
SimpleChannel {
queue: VecDeque::new(),
waker: None,
closed: false,
}
}
}
impl<T> Default for SimpleChannel<T> {
fn default() -> Self {
Self::new()
}
}
impl<T> Stream for SimpleChannel<T> {
type Item = T;
fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
let this = self.project();
match this.queue.pop_front() {
Some(item) => Poll::Ready(Some(item)),
None if *this.closed => Poll::Ready(None),
None => {
*this.waker = Some(cx.waker().clone());
Poll::Pending
}
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
(self.queue.len(), None)
}
}
impl<T> Sink<T> for SimpleChannel<T> {
type Error = ();
fn poll_ready(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
Poll::Ready(Ok(()))
}
fn start_send(self: Pin<&mut Self>, item: T) -> Result<(), Self::Error> {
let this = self.project();
this.queue.push_back(item);
if let Some(waker) = this.waker.take() {
waker.wake();
}
Ok(())
}
fn poll_flush(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
Poll::Ready(Ok(()))
}
fn poll_close(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
let this = self.project();
*this.closed = true;
if let Some(waker) = this.waker.take() {
waker.wake();
}
Poll::Ready(Ok(()))
}
}
#[cfg(test)]
mod tests {
use futures_util::future::join;
use futures_util::stream::iter;
use futures_util::{SinkExt, StreamExt};
use super::*;
#[tokio::test]
async fn test_write_then_read() {
let channel = SimpleChannel::<u32>::new();
let (mut sink, mut stream) = channel.split();
send_many(&mut sink, vec![1, 2, 3]).await.unwrap();
assert_eq!(stream.next().await.unwrap(), 1);
assert_eq!(stream.next().await.unwrap(), 2);
send_many(&mut sink, vec![4, 5]).await.unwrap();
assert_eq!(stream.next().await.unwrap(), 3);
assert_eq!(stream.next().await.unwrap(), 4);
assert_eq!(stream.next().await.unwrap(), 5);
sink.close().await.unwrap();
assert_eq!(stream.next().await, None);
}
#[tokio::test]
async fn test_read_then_write() {
let channel = SimpleChannel::<u32>::new();
let (mut sink, mut stream) = channel.split();
join(
async {
assert_eq!(stream.next().await.unwrap(), 1);
assert_eq!(stream.next().await.unwrap(), 2);
assert_eq!(stream.next().await.unwrap(), 3);
},
async {
send_many(&mut sink, vec![1, 2, 3, 4]).await.unwrap();
},
)
.await;
}
#[tokio::test]
async fn test_read_then_close() {
let channel = SimpleChannel::<u32>::new();
let (mut sink, mut stream) = channel.split();
join(
async {
assert_eq!(stream.next().await, None);
},
async {
sink.close().await.unwrap();
},
)
.await;
}
#[tokio::test]
async fn test_close_then_read() {
let channel = SimpleChannel::<u32>::new();
let (mut sink, stream) = channel.split();
send_many(&mut sink, vec![1, 2, 3]).await.unwrap();
sink.close().await.unwrap();
// should still read items from queue
assert_eq!(stream.collect::<Vec<_>>().await, vec![1, 2, 3]);
}
async fn send_many<T, Si>(
sink: &mut Si,
values: impl IntoIterator<Item = T>,
) -> Result<(), Si::Error>
where
Si: Sink<T> + Unpin,
{
sink.send_all(&mut iter(values).map(Ok)).await
}
}
@@ -0,0 +1,69 @@
use std::cell::RefCell;
use std::rc::Rc;
use wasm_bindgen::closure::Closure;
use wasm_bindgen::{JsCast, JsValue};
use web_sys::{window, ErrorEvent, PromiseRejectionEvent};
pub struct UnhandledErrorGuard {
errors: Rc<RefCell<Vec<JsValue>>>,
listener: JsValue,
}
const ERROR_TYPES: [&str; 2] = ["error", "unhandledrejection"];
impl UnhandledErrorGuard {
pub fn new() -> Self {
// Add a listener that collects any errors
let errors = Rc::new(RefCell::new(vec![]));
let listener = {
let errors = errors.clone();
Closure::<dyn FnMut(_)>::new(move |event: JsValue| {
if let Some(event) = event.dyn_ref::<ErrorEvent>() {
errors.borrow_mut().push(event.error());
} else if let Some(event) = event.dyn_ref::<PromiseRejectionEvent>() {
errors.borrow_mut().push(event.reason());
}
})
};
if let Some(window) = window() {
for event_type in ERROR_TYPES {
window
.add_event_listener_with_callback(event_type, listener.as_ref().unchecked_ref())
.unwrap();
}
}
Self {
errors,
listener: listener.into_js_value(),
}
}
}
impl Default for UnhandledErrorGuard {
fn default() -> Self {
Self::new()
}
}
impl Drop for UnhandledErrorGuard {
fn drop(&mut self) {
// Remove listeners
if let Some(window) = window() {
for event_type in ERROR_TYPES {
window
.add_event_listener_with_callback(
event_type,
self.listener.as_ref().unchecked_ref(),
)
.unwrap();
}
}
// Panic if there are any errors
let errors = self.errors.take();
assert!(
errors.is_empty(),
"There were {} unexpected errors",
errors.len()
);
}
}