mirror of
https://github.com/denoland/deno.git
synced 2024-11-01 09:24:20 -04:00
d5634164cb
Closes https://github.com/denoland/deno/issues/2699 Closes https://github.com/denoland/deno/issues/2347 Uses unstable rustfmt features. Since dprint invokes `rustfmt` we do not need to switch the cargo toolchain to nightly. Do we care about formatting stability of our codebase across Rust versions? (I don't)
82 lines
2.2 KiB
Rust
82 lines
2.2 KiB
Rust
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
|
|
// Forked from https://github.com/Thomasdezeeuw/sendfile/blob/024f82cd4dede9048392a5bd6d8afcd4d5aa83d5/src/lib.rs
|
|
|
|
use std::future::Future;
|
|
use std::io;
|
|
use std::os::unix::io::RawFd;
|
|
use std::pin::Pin;
|
|
use std::task::Poll;
|
|
use std::task::{self};
|
|
|
|
pub struct SendFile {
|
|
pub io: (RawFd, RawFd),
|
|
pub written: usize,
|
|
}
|
|
|
|
impl SendFile {
|
|
#[inline]
|
|
pub fn try_send(&mut self) -> Result<usize, std::io::Error> {
|
|
#[cfg(target_os = "linux")]
|
|
{
|
|
// This is the maximum the Linux kernel will write in a single call.
|
|
let count = 0x7ffff000;
|
|
let mut offset = self.written as libc::off_t;
|
|
|
|
let res =
|
|
// SAFETY: call to libc::sendfile()
|
|
unsafe { libc::sendfile(self.io.1, self.io.0, &mut offset, count) };
|
|
if res == -1 {
|
|
Err(io::Error::last_os_error())
|
|
} else {
|
|
self.written = offset as usize;
|
|
Ok(res as usize)
|
|
}
|
|
}
|
|
#[cfg(target_os = "macos")]
|
|
{
|
|
// Send all bytes.
|
|
let mut length = 0;
|
|
// On macOS `length` is value-result parameter. It determines the number
|
|
// of bytes to write and returns the number of bytes written also in
|
|
// case of `EAGAIN` errors.
|
|
// SAFETY: call to libc::sendfile()
|
|
let res = unsafe {
|
|
libc::sendfile(
|
|
self.io.0,
|
|
self.io.1,
|
|
self.written as libc::off_t,
|
|
&mut length,
|
|
std::ptr::null_mut(),
|
|
0,
|
|
)
|
|
};
|
|
self.written += length as usize;
|
|
if res == -1 {
|
|
Err(io::Error::last_os_error())
|
|
} else {
|
|
Ok(length as usize)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Future for SendFile {
|
|
type Output = Result<(), std::io::Error>;
|
|
|
|
fn poll(
|
|
mut self: Pin<&mut Self>,
|
|
_: &mut task::Context<'_>,
|
|
) -> Poll<Self::Output> {
|
|
loop {
|
|
match self.try_send() {
|
|
Ok(0) => break Poll::Ready(Ok(())),
|
|
Ok(_) => continue,
|
|
Err(ref err) if err.kind() == io::ErrorKind::WouldBlock => {
|
|
break Poll::Pending
|
|
}
|
|
Err(ref err) if err.kind() == io::ErrorKind::Interrupted => continue, // Try again.
|
|
Err(err) => break Poll::Ready(Err(err)),
|
|
}
|
|
}
|
|
}
|
|
}
|