wasmtime/runtime/component/concurrent/futures_and_streams/
buffers.rs1use crate::prelude::*;
2#[cfg(feature = "component-model-bytes")]
3use bytes::{Bytes, BytesMut};
4use core::mem::{self, MaybeUninit};
5use core::slice;
6
7pub use untyped::*;
10mod untyped {
11 use super::WriteBuffer;
12 use crate::vm::SendSyncPtr;
13 use crate::{Result, bail};
14 use core::any::TypeId;
15 use core::marker;
16 use core::mem;
17 use core::ptr::NonNull;
18
19 pub struct UntypedWriteBuffer<'a> {
28 element_type_id: TypeId,
29 buf: SendSyncPtr<dyn WriteBuffer<()>>,
30 _marker: marker::PhantomData<&'a mut dyn WriteBuffer<()>>,
31 }
32
33 union ReinterpretWriteBuffer<T> {
36 typed: *mut dyn WriteBuffer<T>,
37 untyped: *mut dyn WriteBuffer<()>,
38 }
39
40 impl<'a> UntypedWriteBuffer<'a> {
41 pub fn new<T: 'static>(buf: &'a mut dyn WriteBuffer<T>) -> UntypedWriteBuffer<'a> {
46 UntypedWriteBuffer {
47 element_type_id: TypeId::of::<T>(),
48 buf: SendSyncPtr::new(
53 NonNull::new(unsafe {
54 let r = ReinterpretWriteBuffer { typed: buf };
55 assert_eq!(mem::size_of_val(&r.typed), mem::size_of_val(&r.untyped));
56 r.untyped
57 })
58 .unwrap(),
59 ),
60 _marker: marker::PhantomData,
61 }
62 }
63
64 pub fn get_mut<T: 'static>(&mut self) -> Result<&mut dyn WriteBuffer<T>> {
69 if self.element_type_id != TypeId::of::<T>() {
70 bail!("host stream item type mismatch")
71 }
72
73 Ok(unsafe {
78 &mut *ReinterpretWriteBuffer {
79 untyped: self.buf.as_ptr(),
80 }
81 .typed
82 })
83 }
84 }
85}
86
87pub unsafe trait WriteBuffer<T>: Send + Sync + 'static {
98 fn remaining(&self) -> &[T];
100
101 fn skip(&mut self, count: usize);
103
104 fn take(&mut self, count: usize, fun: &mut dyn FnMut(&[MaybeUninit<T>]));
117}
118
119pub trait ReadBuffer<T>: Send + Sync + 'static {
123 fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I);
125
126 fn remaining_capacity(&self) -> usize;
128
129 fn move_from(&mut self, input: &mut dyn WriteBuffer<T>, count: usize);
139}
140
141pub(super) struct Extender<'a, B>(pub(super) &'a mut B);
142
143impl<T, B: ReadBuffer<T>> Extend<T> for Extender<'_, B> {
144 fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
145 self.0.extend(iter)
146 }
147}
148
149unsafe impl<T: Send + Sync + 'static> WriteBuffer<T> for Option<T> {
152 fn remaining(&self) -> &[T] {
153 if let Some(me) = self {
154 slice::from_ref(me)
155 } else {
156 &[]
157 }
158 }
159
160 fn skip(&mut self, count: usize) {
161 match count {
162 0 => {}
163 1 => {
164 assert!(self.is_some());
165 *self = None;
166 }
167 _ => panic!("cannot skip more than {} item(s)", self.remaining().len()),
168 }
169 }
170
171 fn take(&mut self, count: usize, fun: &mut dyn FnMut(&[MaybeUninit<T>])) {
172 match count {
173 0 => fun(&mut []),
174 1 => {
175 let mut item = MaybeUninit::new(self.take().unwrap());
176 fun(slice::from_mut(&mut item));
177 }
178 _ => panic!("cannot forget more than {} item(s)", self.remaining().len()),
179 }
180 }
181}
182
183impl<T: Send + Sync + 'static> ReadBuffer<T> for Option<T> {
184 fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
185 let mut iter = iter.into_iter();
186 if self.is_none() {
187 *self = iter.next();
188 }
189 assert!(iter.next().is_none());
190 }
191
192 fn remaining_capacity(&self) -> usize {
193 if self.is_some() { 0 } else { 1 }
194 }
195
196 fn move_from(&mut self, input: &mut dyn WriteBuffer<T>, count: usize) {
197 match count {
198 0 => {}
199 1 => {
200 assert!(self.is_none());
201 input.take(1, &mut |slice| {
202 unsafe {
206 *self = Some(slice[0].assume_init_read());
207 }
208 });
209 }
210 _ => panic!(
211 "cannot take more than {} item(s)",
212 self.remaining_capacity()
213 ),
214 }
215 }
216}
217
218pub struct SliceBuffer {
220 buffer: Vec<u8>,
221 offset: usize,
222 limit: usize,
223}
224
225impl SliceBuffer {
226 pub fn new(buffer: Vec<u8>, offset: usize, limit: usize) -> Self {
227 assert!(offset <= limit);
228 assert!(limit <= buffer.len());
229 Self {
230 buffer,
231 offset,
232 limit,
233 }
234 }
235
236 pub fn into_parts(self) -> (Vec<u8>, usize, usize) {
237 (self.buffer, self.offset, self.limit)
238 }
239}
240
241unsafe impl WriteBuffer<u8> for SliceBuffer {
245 fn remaining(&self) -> &[u8] {
246 &self.buffer[self.offset..self.limit]
247 }
248
249 fn skip(&mut self, count: usize) {
250 assert!(self.offset + count <= self.limit);
251 self.offset += count;
252 }
253
254 fn take(&mut self, count: usize, fun: &mut dyn FnMut(&[MaybeUninit<u8>])) {
255 assert!(count <= self.remaining().len());
256 self.offset += count;
257 fun(unsafe {
260 mem::transmute::<&[u8], &[MaybeUninit<u8>]>(
261 &self.buffer[self.offset - count..self.offset],
262 )
263 });
264 }
265}
266
267pub struct VecBuffer<T> {
269 buffer: Vec<MaybeUninit<T>>,
270 offset: usize,
271}
272
273impl<T> Default for VecBuffer<T> {
274 fn default() -> Self {
275 Self::with_capacity(0)
276 }
277}
278
279impl<T> VecBuffer<T> {
280 pub fn with_capacity(capacity: usize) -> Self {
282 Self {
283 buffer: Vec::with_capacity(capacity),
284 offset: 0,
285 }
286 }
287
288 pub fn reset(&mut self) {
291 self.skip_(self.remaining_().len());
292 self.buffer.clear();
293 self.offset = 0;
294 }
295
296 fn remaining_(&self) -> &[T] {
297 unsafe { mem::transmute::<&[MaybeUninit<T>], &[T]>(&self.buffer[self.offset..]) }
301 }
302
303 fn skip_(&mut self, count: usize) {
304 assert!(count <= self.remaining_().len());
305 for item in &mut self.buffer[self.offset..][..count] {
306 self.offset += 1;
309 unsafe {
311 item.assume_init_drop();
312 }
313 }
314 }
315}
316
317unsafe impl<T: Send + Sync + 'static> WriteBuffer<T> for VecBuffer<T> {
321 fn remaining(&self) -> &[T] {
322 self.remaining_()
323 }
324
325 fn skip(&mut self, count: usize) {
326 self.skip_(count)
327 }
328
329 fn take(&mut self, count: usize, fun: &mut dyn FnMut(&[MaybeUninit<T>])) {
330 assert!(count <= self.remaining().len());
331 self.offset += count;
335 fun(&self.buffer[self.offset - count..self.offset]);
336 }
337}
338
339impl<T> From<Vec<T>> for VecBuffer<T> {
340 fn from(buffer: Vec<T>) -> Self {
341 Self {
342 buffer: unsafe { mem::transmute::<Vec<T>, Vec<MaybeUninit<T>>>(buffer) },
345 offset: 0,
346 }
347 }
348}
349
350impl<T> Drop for VecBuffer<T> {
351 fn drop(&mut self) {
352 self.reset();
353 }
354}
355
356impl<T: Send + Sync + 'static> ReadBuffer<T> for Vec<T> {
357 fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
358 Extend::extend(self, iter)
359 }
360
361 fn remaining_capacity(&self) -> usize {
362 self.capacity().checked_sub(self.len()).unwrap()
363 }
364
365 fn move_from(&mut self, input: &mut dyn WriteBuffer<T>, count: usize) {
366 assert!(count <= self.remaining_capacity());
367 input.take(count, &mut |slice| {
368 for item in slice {
369 self.push(unsafe { item.assume_init_read() });
373 }
374 });
375 }
376}
377
378#[cfg(feature = "component-model-bytes")]
381unsafe impl WriteBuffer<u8> for Bytes {
382 fn remaining(&self) -> &[u8] {
383 self
384 }
385
386 fn skip(&mut self, count: usize) {
387 let _prefix = self.split_to(count);
388 }
389
390 fn take(&mut self, count: usize, fun: &mut dyn FnMut(&[MaybeUninit<u8>])) {
391 let prefix = self.split_to(count);
392 fun(unsafe_byte_slice(&prefix));
393 }
394}
395
396#[cfg(feature = "component-model-bytes")]
399unsafe impl WriteBuffer<u8> for BytesMut {
400 fn remaining(&self) -> &[u8] {
401 self
402 }
403
404 fn skip(&mut self, count: usize) {
405 let _prefix = self.split_to(count);
406 }
407
408 fn take(&mut self, count: usize, fun: &mut dyn FnMut(&[MaybeUninit<u8>])) {
409 let prefix = self.split_to(count);
410 fun(unsafe_byte_slice(&prefix));
411 }
412}
413
414#[cfg(feature = "component-model-bytes")]
415impl ReadBuffer<u8> for BytesMut {
416 fn extend<I: IntoIterator<Item = u8>>(&mut self, iter: I) {
417 Extend::extend(self, iter)
418 }
419
420 fn remaining_capacity(&self) -> usize {
421 self.capacity().checked_sub(self.len()).unwrap()
422 }
423
424 fn move_from(&mut self, input: &mut dyn WriteBuffer<u8>, count: usize) {
425 assert!(count <= self.remaining_capacity());
426 input.take(count, &mut |slice| {
427 let slice = unsafe { mem::transmute::<&[MaybeUninit<u8>], &[u8]>(slice) };
431 self.extend_from_slice(slice);
432 });
433 }
434}
435
436#[cfg(feature = "component-model-bytes")]
437fn unsafe_byte_slice(slice: &[u8]) -> &[MaybeUninit<u8>] {
438 unsafe { mem::transmute::<&[u8], &[MaybeUninit<u8>]>(slice) }
441}
442
443#[cfg(test)]
444mod tests {
445 use super::*;
446
447 #[test]
448 fn test_vec_buffer_take() {
449 let mut buf = VecBuffer::from(vec!["a".to_string(), "b".to_string(), "c".to_string()]);
450 let mut dst = Vec::new();
451 dst.reserve(1);
452 dst.move_from(&mut buf, 1);
453 assert_eq!(buf.remaining().len(), 2);
454 assert_eq!(dst.len(), 1);
455 None.move_from(&mut buf, 1);
456 assert_eq!(buf.remaining().len(), 1);
457 assert_eq!(dst.len(), 1);
458 }
459
460 #[test]
461 fn test_slice_buffer_take() {
462 let mut buf = SliceBuffer::new(vec![1, 2, 3], 0, 3);
463 let mut dst = Vec::new();
464 dst.reserve(1);
465 dst.move_from(&mut buf, 1);
466 assert_eq!(buf.remaining().len(), 2);
467 assert_eq!(dst.len(), 1);
468 }
469
470 #[test]
471 #[cfg(feature = "component-model-bytes")]
472 fn test_cursor_bytes_take() {
473 let mut buf = Bytes::from(&b"123"[..]);
474 let mut dst = Vec::new();
475 dst.reserve(1);
476 dst.move_from(&mut buf, 1);
477 assert_eq!(buf.remaining().len(), 2);
478 assert_eq!(dst.len(), 1);
479
480 let mut dst = BytesMut::new();
481 dst.reserve(1);
482 dst.move_from(&mut buf, 1);
483 assert_eq!(buf.remaining().len(), 1);
484 assert_eq!(dst.len(), 1);
485 }
486
487 #[test]
488 #[cfg(feature = "component-model-bytes")]
489 fn test_cursor_bytes_mut_take() {
490 let mut buf = BytesMut::from(&b"123"[..]);
491 let mut dst = Vec::new();
492 dst.reserve(1);
493 dst.move_from(&mut buf, 1);
494 assert_eq!(buf.remaining().len(), 2);
495 assert_eq!(dst.len(), 1);
496
497 let mut dst = BytesMut::new();
498 dst.reserve(1);
499 dst.move_from(&mut buf, 1);
500 assert_eq!(buf.remaining().len(), 1);
501 assert_eq!(dst.len(), 1);
502 }
503}