1 stable release
1.0.0 | Apr 11, 2020 |
---|
#2018 in Asynchronous
9KB
103 lines
A simple !Unpin
I/O backend for async-std
This is a wrapper around async-std
's Cursor, but this one is !Unpin
.
I wanted it for tests for async I/O code that was supposed to be able to support both Unpin
and !Unpin
backends.
See the crate-level documentation for usage info and examples.
lib.rs
:
A simple !Unpin
I/O backend for async-std, designed for use in tests.
This crate provides the PinCursor
struct which wraps around async_std::io::Cursor
but is explicitly not Unpin
. It is a little building block to help write tests
where you want to ensure that your own asynchronous IO code behaves correctly when reading from
or writing to something that is definitely !Unpin
.
- It can be backed by any
Unpin
data buffer that can be slotted intoasync_std::io::Cursor
. UsuallyVec<u8>
or&mut [u8]
(e. g. from an array) are used. - It implements
async_std::io::{Read, Write, Seek}
, so you can poll these traits' methods in your own futures. - At the same time, it provides several high-level methods through which you can manipulate
the PinCursor in a simple
async {}
block.
Examples
use pin_cursor::PinCursor;
use async_std::io::{prelude::*, Cursor};
use std::io::SeekFrom;
use std::pin::Pin;
// Construct a async_std::io::Cursor however you like...
let mut data: Vec<u8> = Vec::new();
let cursor = Cursor::new(&mut data);
// ... then wrap it in PinCursor and a pinned pointer, thus losing the Unpin privileges.
let mut cursor: Pin<Box<PinCursor<_>>> = Box::pin(PinCursor::wrap(cursor));
// Note that we have to make an owning pointer first -
// making a Pin<&mut PinCursor<_>> directly is impossible!
// (There is a more complex way to allocate on stack - see the features section.)
// Methods of PinCursor mostly return futures and are designed for use in async contexts.
async {
// You can write!
assert_eq!(cursor.as_mut().write(&[1u8, 2u8, 3u8]).await.unwrap(), 3);
// You can seek!
assert_eq!(cursor.position(), 3);
assert_eq!(cursor.as_mut().seek(SeekFrom::Start(1)).await.unwrap(), 1);
assert_eq!(cursor.position(), 1);
// You can read!
let mut buf = [0u8; 1];
assert_eq!(cursor.as_mut().read(buf.as_mut()).await.unwrap(), 1);
assert_eq!(buf[0], 2);
// There's also this way of seeking that doesn't involve futures.
cursor.as_mut().set_position(0);
assert_eq!(cursor.as_mut().read(buf.as_mut()).await.unwrap(), 1);
assert_eq!(buf[0], 1);
}
Features
The optional feature stackpin
enables integration with stackpin, a crate that provides
a way to allocate !Unpin
structures on stack.
# use pin_cursor::PinCursor;
# use async_std::io::Cursor;
# use std::pin::Pin;
use stackpin::stack_let;
let mut data: Vec<u8> = vec![1, 2];
stack_let!(mut cursor : PinCursor<_> = Cursor::new(&mut data));
let cursor_ptr: Pin<&mut PinCursor<_>> = Pin::as_mut(&mut cursor);
Now you have a correctly pinned PinCursor
that's allocated on stack instead of in a box.
Dependencies
~4–13MB
~167K SLoC