1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110
use super::super::handle::BodyHandle; use crate::abi; use std::io::Write; /// A low-level interface to a streaming HTTP body. /// /// The interface to this type is very similar to [`BodyHandle`], however it is write-only, and can /// only be created as a result of calling /// [`ResponseHandle::send_to_client()`][`crate::handle::ResponseHandle::send_to_client()`] or /// [`RequestHandle::send_async_streaming()`][`crate::handle::RequestHandle::send_async_streaming()`]. /// /// This type implements [`Write`] to write to the end of a body. Note that these operations are /// unbuffered, unlike the same operations on the higher-level [`Body`][`crate::Body`] type. /// /// A streaming body will be automatically closed when it goes out of scope, or when it is passed to /// [`drop()`]. #[derive(Debug, Eq, Hash, PartialEq)] #[repr(transparent)] pub struct StreamingBodyHandle { handle: u32, } impl StreamingBodyHandle { /// Make a streaming body handle from a non-streaming handle. /// /// This should only be used when calling the raw ABI directly, and care should be taken not to /// reuse or alias handle values. pub(crate) fn from_body_handle(body_handle: &BodyHandle) -> Self { Self { handle: body_handle.handle, } } /// Get a non-streaming body handle from a streaming handle. /// /// This should only be used when calling the raw ABI directly, and care should be taken not to /// reuse or alias handle values, or to use the returned value in contexts where a streaming /// handle is not valid. fn as_body_handle(&self) -> BodyHandle { BodyHandle { handle: self.handle, } } /// Append another body onto the end of this body. /// /// This operation is performed in amortized constant time, and so should always be preferred to /// reading an entire body and then writing the same contents to another body. /// /// The other body will no longer be valid after this call. /// /// # Examples /// /// ```no_run /// # use fastly::handle::{BodyHandle, ResponseHandle}; /// # let response_handle = ResponseHandle::new(); /// # let other_body = BodyHandle::new(); /// let mut streaming_body = response_handle.stream_to_client(BodyHandle::new()); /// streaming_body.append(other_body); /// ``` pub fn append(&mut self, other: BodyHandle) { self.as_body_handle().append(other) } /// Write a slice of bytes to the end of this streaming body, and return the number of bytes written. /// /// # Examples /// /// ```no_run /// # use fastly::handle::{BodyHandle, ResponseHandle}; /// # let response_handle = ResponseHandle::new(); /// let mut streaming_body = response_handle.stream_to_client(BodyHandle::new()); /// streaming_body.write_bytes(&[0, 1, 2, 3]); /// ``` pub fn write_bytes(&mut self, bytes: &[u8]) -> usize { self.as_body_handle().write_bytes(bytes) } /// Write a string slice to the end of this streaming body, and return the number of bytes written. /// /// # Examples /// /// ```no_run /// # use fastly::handle::{BodyHandle, ResponseHandle}; /// # let response_handle = ResponseHandle::new(); /// let mut streaming_body = response_handle.stream_to_client(BodyHandle::new()); /// streaming_body.write_str("woof woof"); /// ``` pub fn write_str(&mut self, string: &str) -> usize { self.write_bytes(string.as_bytes()) } } impl Drop for StreamingBodyHandle { fn drop(&mut self) { unsafe { abi::fastly_http_body::close(self.as_body_handle().as_u32()) } .result() .expect("fastly_http_body::close failed"); } } impl Write for StreamingBodyHandle { fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> { Ok(self.write_bytes(buf)) } fn flush(&mut self) -> std::io::Result<()> { Ok(()) } }