use avril_core::serde_v8::JsBuffer; use std::io; pub const CHUNK: usize = 64 * 1024; /// Portable per-operation segment limit: the POSIX minimum vector count. pub const MAX_SLICES: usize = 16; pub type Response = (Option, Option<(&'static str, String)>); pub fn response(result: io::Result) -> Response { match result { Ok(value) => (Some(value), None), Err(error) => { let kind = match error.kind() { io::ErrorKind::NotFound => "NotFound", io::ErrorKind::PermissionDenied => "PermissionDenied", io::ErrorKind::AlreadyExists => "AlreadyExists", io::ErrorKind::DirectoryNotEmpty => "NotEmpty", io::ErrorKind::CrossesDevices => "CrossDevice", io::ErrorKind::NotADirectory => "NotADirectory", io::ErrorKind::IsADirectory => "IsADirectory", io::ErrorKind::InvalidInput => "InvalidInput", io::ErrorKind::NotConnected => "BadResource", io::ErrorKind::WouldBlock => "Busy", io::ErrorKind::BrokenPipe => "BrokenPipe", io::ErrorKind::Unsupported => "NotSupported", _ => "IoError", }; (None, Some((kind, error.to_string()))) } } } /// Keeps a vector's leading bounded prefix; the rest reports as a partial /// write. Nonempty data is never skipped or reordered. pub fn bound_vectored(buffers: Vec) -> Vec { let mut kept = Vec::new(); let mut total = 0; for mut segment in buffers { if kept.len() >= MAX_SLICES || total >= CHUNK { break; } if segment.is_empty() { continue; } let room = CHUNK - total; if segment.len() > room { let mut slice = segment.into_parts(); slice.truncate(room); segment = JsBuffer::from_parts(slice); } total += segment.len(); kept.push(segment); } kept }