Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions chd-rs-capi/chd.h
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,31 @@ chd_error chd_codec_config(const struct chd_file *_chd, int32_t _param, void *_c
chd_error chd_read_header(const char *filename,
struct chd_header *header);

/**
* Read CHD header data from the file into the pointed struct.
*
* Ownership of the core_file is retained by the caller when calling this function.
*
* # Safety
* * `filename` is a valid, null-terminated **UTF-8** string.
* * `header` is either `NULL`, or an aligned pointer to a possibly uninitialized `chd_header` struct.
* * If `header` is `NULL`, returns `CHDERR_INVALID_PARAMETER`
*/
chd_error chd_read_header_file(core_file *file,
struct chd_header *header);

/**
* Read CHD header data from the file into the pointed struct.
*
* Ownership is retained by the caller when calling this function.
*
* # Safety
* * `file` is a valid pointer to a `core_file` with respect to the implementation of libchdcorefile that was linked.
* * `header` is either `NULL`, or an aligned pointer to a possibly uninitialized `chd_header` struct.
*/
chd_error chd_read_header_core_file(core_file *file,
struct chd_header *header);

/**
* Returns the associated `core_file*`.
*
Expand Down
31 changes: 24 additions & 7 deletions chd-rs-capi/src/chdcorefile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,7 @@ impl SeekRead for CoreFile {

impl Read for CoreFile {
fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
let res = unsafe {
core_fread(
self.file,
buf.as_mut_ptr() as *mut c_void,
buf.len(),
)
};
let res = unsafe { core_fread(self.file, buf.as_mut_ptr() as *mut c_void, buf.len()) };
Ok(res)
}
}
Expand All @@ -45,6 +39,8 @@ mod tests {
use crate::chdcorefile_sys::core_fopen;
use std::fs::File;
use std::io::{Read, Write};
use std::mem::MaybeUninit;
use crate::chd_read_header_core_file;

#[test]
fn chdcorefile_read() {
Expand All @@ -59,6 +55,27 @@ mod tests {
file.read_exact(&mut buf).unwrap();
assert_eq!(&[0, 1, 2, 3, 4, 5, 6, 7, 8, 9], &buf);
}

#[test]
fn chdcorefile_read_header() {
let file = unsafe {
core_fopen(
b"../chd-rs/.testimages/cliffhgr.chd\0".as_ptr() as *const std::os::raw::c_char
)
};

unsafe {
let mut header = MaybeUninit::zeroed();
chd_read_header_core_file(file, &mut header);
let header = header.assume_init();
eprintln!("{:?}", header);

}

// let mut buf = [0u8; 10];
// file.read_exact(&mut buf).unwrap();
// assert_eq!(&[0, 1, 2, 3, 4, 5, 6, 7, 8, 9], &buf);
}
}

impl Drop for CoreFile {
Expand Down
1 change: 1 addition & 0 deletions chd-rs-capi/src/header.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ pub const CHD_SHA1_BYTES: usize = 20;
#[allow(non_camel_case_types)]
/// libchdr-compatible CHD header struct.
/// This struct is ABI-compatible with [chd.h](https://github.com/rtissera/libchdr/blob/cdcb714235b9ff7d207b703260706a364282b063/include/libchdr/chd.h#L302)
#[derive(Debug)]
pub struct chd_header {
length: u32,
version: u32,
Expand Down
62 changes: 61 additions & 1 deletion chd-rs-capi/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -358,6 +358,65 @@ pub unsafe extern "C" fn chd_read_header(
}
}

#[no_mangle]
#[cfg(feature = "chd_core_file")]
#[cfg_attr(docsrs, doc(cfg(chd_core_file)))]
/// Read CHD header data from the file into the pointed struct.
///
/// Ownership of the core_file is retained by the caller when calling this function.
///
/// # Safety
/// * `filename` is a valid, null-terminated **UTF-8** string.
/// * `header` is either `NULL`, or an aligned pointer to a possibly uninitialized `chd_header` struct.
/// * If `header` is `NULL`, returns `CHDERR_INVALID_PARAMETER`
pub unsafe extern "C" fn chd_read_header_file(
file: *mut chdcorefile_sys::core_file,
header: *mut MaybeUninit<chd_header>,
) -> chd_error {
let core_file = Box::new(crate::chdcorefile::CoreFile { file }) as Box<dyn SeekRead>;
let chd = match Chd::open(core_file, None) {
Ok(chd) => chd,
Err(e) => return e,
};

let chd_header = ffi_chd_get_header(&chd);
let result = match unsafe { header.as_mut() } {
None => Error::InvalidParameter,
Some(header) => {
header.write(chd_header);
Error::None
}
};

let (file, _) = chd.into_inner();
let file = file as Box<dyn Any>;
let Ok(file) = file.downcast::<CoreFile>() else {
return Error::Unknown;
};

let file = *file;
std::mem::forget(file);

result
}

#[no_mangle]
#[cfg(feature = "chd_virtio")]
#[cfg_attr(docsrs, doc(cfg(chd_virtio)))]
/// Read CHD header data from the file into the pointed struct.
///
/// Ownership is retained by the caller when calling this function.
///
/// # Safety
/// * `file` is a valid pointer to a `core_file` with respect to the implementation of libchdcorefile that was linked.
/// * `header` is either `NULL`, or an aligned pointer to a possibly uninitialized `chd_header` struct.
pub unsafe extern "C" fn chd_read_header_core_file(
file: *mut chdcorefile_sys::core_file,
header: *mut MaybeUninit<chd_header>,
) -> chd_error {
unsafe { chd_read_header_file(file, header) }
}

#[no_mangle]
#[cfg(feature = "chd_core_file")]
#[cfg_attr(docsrs, doc(cfg(chd_core_file)))]
Expand Down Expand Up @@ -431,7 +490,7 @@ pub unsafe extern "C" fn chd_open_file(
Some(ffi_takeown_chd(parent))
};

let core_file = Box::new(crate::chdcorefile::CoreFile { file: file }) as Box<dyn SeekRead>;
let core_file = Box::new(crate::chdcorefile::CoreFile { file }) as Box<dyn SeekRead>;
let chd = match Chd::open(core_file, parent) {
Ok(chd) => chd,
Err(e) => return e,
Expand Down Expand Up @@ -472,6 +531,7 @@ pub extern "C" fn chd_get_codec_name(_codec: u32) -> *const c_char {
b"Unknown\0".as_ptr() as *const c_char
}

use crate::chdcorefile::CoreFile;
#[cfg(feature = "chd_precache")]
use std::io::SeekFrom;

Expand Down
1 change: 0 additions & 1 deletion chd-rs/src/chdfile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -381,7 +381,6 @@ impl<'a, F: Read + Seek> Hunk<'a, F> {
/// [`Error::RequiresParent`](crate::Error::RequiresParent).
///
/// If the provided output buffer is the wrong length, this will return
/// If the hunk refers to a parent CHD that was not provided, this will return
/// [`Error::OutOfMemory`](crate::Error::OutOfMemory).
pub fn read_hunk_in(
&mut self,
Expand Down