diff --git a/Cargo.toml b/Cargo.toml index ab751aa..8c530db 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -42,7 +42,6 @@ smallvec = {version = "1.6", features=["union"], optional = true} tokio = {version = "0.2", optional = true} [build-dependencies] -cc = "1.0.68" rustc_version = "0.2" [dev-dependencies] diff --git a/build.rs b/build.rs index e2cea4e..6cb813f 100644 --- a/build.rs +++ b/build.rs @@ -1,37 +1,8 @@ extern crate rustc_version; -extern crate cc; - -use std::path::Path; use rustc_version::{version, version_meta, Channel}; -const FFI_SRC_DIR: &str = "src/ffi"; - -//TODO: Replace the wrapper C file with a pure Rust impl in `ffi::cookie::` -fn build_cookie_wrapper(floc: impl AsRef) -{ - let mut builder = cc::Build::new(); - // --std=c99 -W -Wall -Werror -pedantic -O3 -flto - builder.flag("--std=c99") - .flag("-W") - .flag("-Wall") - .flag_if_supported("-Wextra") - .flag("-Werror") - .flag("-pedantic") - .flag("-fno-strict-aliasing") - .include("include/") - .opt_level(3) - // .flag_if_supported("-flto") //XXX: For some reason, this makes static linking the library fail. - - // Not sure if we want these two. We can check the codegen later. - //.pic(false) - //.use_plt(false) - - .file(Path::new(FFI_SRC_DIR).join(floc)) - .compile("wrapper"); -} - fn main() { // Assert we haven't travelled back in time assert!(version().unwrap().major >= 1); @@ -51,8 +22,4 @@ fn main() { println!("cargo:rustc-cfg=dev"); } } - - build_cookie_wrapper("wrapper.c"); - -//println!("cargo:rustc-link-lib={}", link); } diff --git a/src/ffi.rs b/src/ffi.rs index 05c6513..02f821f 100644 --- a/src/ffi.rs +++ b/src/ffi.rs @@ -31,6 +31,8 @@ pub struct CPassthrough pub struct CSink { sink: Sink, + + //last_err: () //TODO: how to implement this? } #[derive(Debug, Clone, PartialEq, Eq, Hash, Copy)] diff --git a/src/ffi/cookie.rs b/src/ffi/cookie.rs index d289e77..d5c8c7a 100644 --- a/src/ffi/cookie.rs +++ b/src/ffi/cookie.rs @@ -1,14 +1,114 @@ +#![allow(non_camel_case_types)] + use super::*; -use libc::{c_void, FILE}; +use std::{ + slice, +}; +use libc::{ + c_void, + c_char, + c_int, + off64_t, + ssize_t, + size_t, + + FILE, +}; //TODO: Remove `wrapper.c`, implement it in Rust here -//FILE* _cc20c_create(cc20_sink_t* restrict sink) +type cookie_read_function_t = Option ssize_t>; +type cookie_write_function_t = Option ssize_t>; +type cookie_seek_function_t = Option c_int>; +type cookie_close_function_t = Option c_int>; + +const _: [u8; 8] = [0u8; std::mem::size_of::()]; + +// `fopencookie` API +#[derive(Debug, Clone, Copy, Default)] +#[repr(C)] +struct cookie_io_functions_t +{ + read: cookie_read_function_t, + write: cookie_write_function_t, + seek: cookie_seek_function_t, + close: cookie_close_function_t, +} + extern "C" { - fn _cc20c_create(sink: *mut c_void) -> *mut FILE; + fn fopencookie(cookie: *mut c_void, mode: *const c_char, funcs: cookie_io_functions_t) -> *mut FILE; +} + +#[inline(always)] unsafe fn ref_cookie<'a>(cookie: *mut c_void) -> Option<&'a mut CSink> +{ + if cookie.is_null() { + None + } else { + Some(&mut *(cookie as *mut CSink)) + } +} + +macro_rules! unwrap { + (? $expr:expr, $or:expr) => { + if let Some(val) = $expr { + val + } else { + return $or; + } + }; +} + +extern "C" fn read(_cookie: *mut c_void, _buf: *mut c_char, _size: size_t) -> ssize_t +{ + -1 +} +extern "C" fn write(cookie: *mut c_void, buf: *const c_char, size: size_t) -> ssize_t +{ + //Remember: Cannot return -1 here + no_unwind!({ + if buf.is_null() { + return 0; + } + let sink = unwrap!(? unsafe { ref_cookie(cookie) }, 0); + let buf = unsafe { slice::from_raw_parts(buf as *const u8, size) }; + + match sink.sink.write(buf) { + Ok(n) if n < ssize_t::MAX as usize => n as ssize_t, + Err(_er) => { + //sink.last_err_code = + //sink.last_err = Some( + 0 + }, + _ => { + // TODO + // Write succeeded, but wrote more than `isize::MAX`. + 0 + }, + } + }).unwrap_or(0) +} +extern "C" fn seek(_cookie: *mut c_void, _offset: *mut off64_t, _whence: c_int) -> c_int +{ + -1 +} +extern "C" fn close(cookie: *mut c_void) -> c_int +{ + let sink = if cookie.is_null() { + return -1; + } else { + cookie as *mut CSink + }; + let sink = unsafe { interop::take(sink) }; + drop(sink); + 0 } #[inline(always)] pub unsafe fn create(raw_sink: *mut CSink) -> *mut FILE { - _cc20c_create(raw_sink as *mut c_void) + fopencookie(raw_sink as *mut c_void, b"wb\0" as *const u8 as *const c_char, cookie_io_functions_t { + read: Some(read), + write: Some(write), + seek: Some(seek), + close: Some(close), + }) } diff --git a/src/ffi/wrapper.c b/src/ffi/wrapper.c deleted file mode 100644 index 64e87a9..0000000 --- a/src/ffi/wrapper.c +++ /dev/null @@ -1,52 +0,0 @@ -#define _GNU_SOURCE -#include -#include -#include - -#include - -#define IGNORE(v) ((void)(v)) - -static ssize_t cc20c_read(void* cookie, char* buffer, size_t size) -{ - IGNORE(cookie); - IGNORE(buffer); - IGNORE(size); - - return -1; -} - -static ssize_t cc20c_write(void* cookie, const char* buffer, size_t size) -{ - cc20_result_t res = cc20_write(buffer, &size, cookie); - IGNORE(res); // TODO: set an error flag `res` in `cookie` (i.e. `CSink`) - return (ssize_t) size; -} - -static int cc20c_seek(void* cookie, off64_t* pos, int w) -{ - IGNORE(cookie); - IGNORE(pos); - IGNORE(w); - - return -1; -} - -static int cc20c_close(void* cookie) -{ - struct cc20_metadata meta ={0}; - cc20_close_sink(cookie, &meta); - if(meta.backing) fclose(meta.backing); - else return -1; - return 0; -} - -FILE* _cc20c_create(cc20_sink_t* restrict sink) -{ - return fopencookie(sink, "wb", (cookie_io_functions_t){ - .read = &cc20c_read, - .write = &cc20c_write, - .seek = &cc20c_seek, - .close = &cc20c_close, - }); -}