libmirage 0.1.0

Rust bindings for libMirage
Documentation
use crate::translate::StringVariantHashMap;
use crate::{SectorType, ffi};
use glib::translate::*;
use std::collections::HashMap;

#[doc(alias = "mirage_helper_ascii2isrc")]
pub fn ascii2isrc(c: glib::Char) -> u8 {
    assert_initialized_main_thread!();
    unsafe { ffi::mirage_helper_ascii2isrc(c.into_glib()) }
}

#[doc(alias = "mirage_helper_bcd2hex")]
pub fn bcd2hex(bcd: i32) -> i32 {
    assert_initialized_main_thread!();
    unsafe { ffi::mirage_helper_bcd2hex(bcd) }
}

#[doc(alias = "mirage_helper_calculate_crc16")]
pub fn calculate_crc16(data: &[u8], crctab: &[u16; 256], reflected: bool, invert: bool) -> u16 {
    unsafe {
        ffi::mirage_helper_calculate_crc16(
            data.as_ptr(),
            data.len() as glib::ffi::guint,
            &raw const *crctab,
            reflected.into_glib(),
            invert.into_glib(),
        )
    }
}

#[doc(alias = "mirage_helper_calculate_crc32_fast")]
pub fn calculate_crc32_fast(
    data: &[u8],
    crctab: &[u32; 2048],
    reflected: bool,
    invert: bool,
) -> u32 {
    unsafe {
        ffi::mirage_helper_calculate_crc32_fast(
            data.as_ptr(),
            data.len() as glib::ffi::guint,
            &raw const *crctab,
            reflected.into_glib(),
            invert.into_glib(),
        )
    }
}

#[doc(alias = "mirage_helper_calculate_crc32_standard")]
pub fn calculate_crc32_standard(
    data: &[u8],
    crctab: &[u32; 256],
    reflected: bool,
    invert: bool,
) -> u32 {
    unsafe {
        ffi::mirage_helper_calculate_crc32_standard(
            data.as_ptr(),
            data.len() as glib::ffi::guint,
            &raw const *crctab,
            reflected.into_glib(),
            invert.into_glib(),
        )
    }
}

#[doc(alias = "mirage_helper_determine_sector_type")]
pub fn determine_sector_type(buf: &[u8]) -> SectorType {
    assert_initialized_main_thread!();
    unsafe { from_glib(ffi::mirage_helper_determine_sector_type(buf.as_ptr())) }
}

#[cfg(feature = "v3_3_2")]
#[cfg_attr(docsrs, doc(cfg(feature = "v3_3_2")))]
#[doc(alias = "mirage_helper_dump_buffer_to_hex")]
pub fn dump_buffer_to_hex(data: &[u8], add_spaces: bool, wrap: i32) -> Option<glib::GString> {
    assert_initialized_main_thread!();
    let data_size = data.len() as _;
    unsafe {
        from_glib_full(ffi::mirage_helper_dump_buffer_to_hex(
            data.to_glib_none().0,
            data_size,
            add_spaces.into_glib(),
            wrap,
        ))
    }
}

#[doc(alias = "mirage_helper_encoding_from_bom")]
pub fn encoding_from_bom(buffer: &[u8; 4]) -> Option<glib::GString> {
    unsafe { from_glib_none(ffi::mirage_helper_encoding_from_bom(&raw const *buffer)) }
}

#[doc(alias = "mirage_helper_find_data_file")]
pub fn find_data_file(filename: &str, path: Option<&str>) -> Option<glib::GString> {
    assert_initialized_main_thread!();
    unsafe {
        from_glib_full(ffi::mirage_helper_find_data_file(
            filename.to_glib_none().0,
            path.to_glib_none().0,
        ))
    }
}

/// # Example
/// ```
/// # use libmirage::helper::format_string;
/// let result = format_string!(
///     "%b-%02s-track%t.%e",
///     "b" => "some_image",
///     "s" => 1i16,
///     "t" => 3i16,
///     "e" => "iso",
/// );
/// assert_eq!("some_image-01-track3.iso", result.unwrap());
/// ```
#[macro_export]
#[doc(hidden)]
#[doc(alias = "mirage_helper_format_string")]
macro_rules! helper_format_string {
    ($format:expr $(, $($token:expr => $value:expr),* $(,)?)?) => {{
        #[allow(unused_mut)]
        let mut map = ::std::collections::HashMap::<::std::string::String, $crate::glib::Variant>::default();
        $(
            $(
                map.insert($token.into(), $value.into());
            )*
        )?
        $crate::helper::format_stringd($format, &map)
    }};
}

#[doc(inline)]
pub use helper_format_string as format_string;
use std::ffi::c_char;
use std::os::raw::c_void;
use std::{ops, slice};

#[doc(alias = "mirage_helper_format_stringd")]
pub fn format_stringd(
    format: &str,
    dictionary: &HashMap<String, glib::Variant>,
) -> Option<glib::GString> {
    unsafe {
        from_glib_full(ffi::mirage_helper_format_stringd(
            format.to_glib_none().0,
            StringVariantHashMap(dictionary).to_glib_none().0,
        ))
    }
}

#[doc(alias = "mirage_helper_get_suffix")]
pub fn get_suffix(filename: &str) -> Option<glib::GString> {
    assert_initialized_main_thread!();
    unsafe { from_glib_none(ffi::mirage_helper_get_suffix(filename.to_glib_none().0)) }
}

#[doc(alias = "mirage_helper_has_suffix")]
pub fn has_suffix(filename: &str, suffix: &str) -> bool {
    assert_initialized_main_thread!();
    unsafe {
        from_glib(ffi::mirage_helper_has_suffix(
            filename.to_glib_none().0,
            suffix.to_glib_none().0,
        ))
    }
}

#[doc(alias = "mirage_helper_hex2bcd")]
pub fn hex2bcd(hex: i32) -> i32 {
    assert_initialized_main_thread!();
    unsafe { ffi::mirage_helper_hex2bcd(hex) }
}

#[doc(alias = "mirage_helper_init_crc16_lut")]
pub fn init_crc16_lut(genpoly: u16) -> Option<LookupTable<u16>> {
    assert_initialized_main_thread!();
    unsafe {
        let ret = ffi::mirage_helper_init_crc16_lut(genpoly);
        if ret.is_null() {
            None
        } else {
            Some(LookupTable(ret, 256))
        }
    }
}

#[doc(alias = "mirage_helper_init_crc32_lut")]
pub fn init_crc32_lut(genpoly: u32, slices: u32) -> Option<LookupTable<u32>> {
    assert_initialized_main_thread!();
    unsafe {
        let ret = ffi::mirage_helper_init_crc32_lut(genpoly, slices);
        if ret.is_null() {
            None
        } else {
            Some(LookupTable(ret, slices as usize * 256))
        }
    }
}

#[doc(alias = "mirage_helper_init_ecma_130b_scrambler_lut")]
pub fn init_ecma_130b_scrambler_lut() -> Option<LookupTable<u8>> {
    assert_initialized_main_thread!();
    unsafe {
        let ret = ffi::mirage_helper_init_ecma_130b_scrambler_lut();
        if ret.is_null() {
            None
        } else {
            Some(LookupTable(ret, 2340))
        }
    }
}

#[derive(Debug)]
pub struct LookupTable<T>(*mut T, usize);

impl<T> Drop for LookupTable<T> {
    fn drop(&mut self) {
        unsafe { glib::ffi::g_free(self.0 as *mut c_void) };
    }
}

impl<T> ops::Deref for LookupTable<T> {
    type Target = [T];

    fn deref(&self) -> &Self::Target {
        unsafe { slice::from_raw_parts(self.0, self.1) }
    }
}

impl<T> ops::DerefMut for LookupTable<T> {
    fn deref_mut(&mut self) -> &mut Self::Target {
        unsafe { slice::from_raw_parts_mut(self.0, self.1) }
    }
}

#[doc(alias = "mirage_helper_isrc2ascii")]
pub fn isrc2ascii(c: u8) -> glib::Char {
    assert_initialized_main_thread!();
    unsafe { from_glib(ffi::mirage_helper_isrc2ascii(c)) }
}

#[doc(alias = "mirage_helper_lba2msf")]
pub fn lba2msf(lba: i32, diff: bool) -> (u8, u8, u8) {
    assert_initialized_main_thread!();
    unsafe {
        let mut m = std::mem::MaybeUninit::uninit();
        let mut s = std::mem::MaybeUninit::uninit();
        let mut f = std::mem::MaybeUninit::uninit();
        ffi::mirage_helper_lba2msf(
            lba,
            diff.into_glib(),
            m.as_mut_ptr(),
            s.as_mut_ptr(),
            f.as_mut_ptr(),
        );
        (m.assume_init(), s.assume_init(), f.assume_init())
    }
}

#[doc(alias = "mirage_helper_lba2msf_str")]
pub fn lba2msf_str(lba: i32, diff: bool) -> Option<glib::GString> {
    assert_initialized_main_thread!();
    unsafe { from_glib_full(ffi::mirage_helper_lba2msf_str(lba, diff.into_glib())) }
}

#[doc(alias = "mirage_helper_msf2lba")]
pub fn msf2lba(m: u8, s: u8, f: u8, diff: bool) -> i32 {
    assert_initialized_main_thread!();
    unsafe { ffi::mirage_helper_msf2lba(m, s, f, diff.into_glib()) }
}

#[doc(alias = "mirage_helper_msf2lba_str")]
pub fn msf2lba_str(msf: &str, diff: bool) -> i32 {
    assert_initialized_main_thread!();
    unsafe { ffi::mirage_helper_msf2lba_str(msf.to_glib_none().0, diff.into_glib()) }
}

#[doc(alias = "mirage_helper_sector_edc_ecc_compute_edc_block")]
pub fn sector_edc_ecc_compute_edc_block(src: &[u8], dest: &mut [u8; 4]) {
    let size = u16::try_from(src.len()).expect("size should fit into a u16");
    unsafe { ffi::mirage_helper_sector_edc_ecc_compute_edc_block(src.as_ptr(), size, dest) }
}

#[doc(alias = "mirage_helper_strcasecmp")]
pub fn strcasecmp(str1: &str, str2: &str) -> i32 {
    assert_initialized_main_thread!();
    unsafe { ffi::mirage_helper_strcasecmp(str1.to_glib_none().0, str2.to_glib_none().0) }
}

#[doc(alias = "mirage_helper_strncasecmp")]
pub fn strncasecmp(str1: &str, str2: &str) -> i32 {
    assert_initialized_main_thread!();
    let len = str2.len() as _;
    unsafe { ffi::mirage_helper_strncasecmp(str1.to_glib_none().0, str2.to_glib_none().0, len) }
}

#[doc(alias = "mirage_helper_subchannel_deinterleave")]
pub fn subchannel_deinterleave(subchan: i32, channel96: &[u8; 96], channel12: &mut [u8; 12]) {
    unsafe { ffi::mirage_helper_subchannel_deinterleave(subchan, channel96, channel12) }
}

#[doc(alias = "mirage_helper_subchannel_interleave")]
pub fn subchannel_interleave(subchan: i32, channel12: &[u8; 12], channel96: &mut [u8; 96]) {
    unsafe { ffi::mirage_helper_subchannel_interleave(subchan, channel12, channel96) }
}

#[doc(alias = "mirage_helper_subchannel_q_calculate_crc")]
pub fn subchannel_q_calculate_crc(data: &[u8; 10]) -> u16 {
    unsafe { ffi::mirage_helper_subchannel_q_calculate_crc(data) }
}

#[doc(alias = "mirage_helper_subchannel_q_decode_isrc")]
pub fn subchannel_q_decode_isrc(buf: &[u8; 8], isrc: &mut [c_char; 12]) {
    unsafe { ffi::mirage_helper_subchannel_q_decode_isrc(buf, isrc) }
}

#[doc(alias = "mirage_helper_subchannel_q_decode_mcn")]
pub fn subchannel_q_decode_mcn(buf: &[u8; 7], mcn: &mut [c_char; 13]) {
    unsafe { ffi::mirage_helper_subchannel_q_decode_mcn(buf, mcn) }
}

#[doc(alias = "mirage_helper_subchannel_q_encode_isrc")]
pub fn subchannel_q_encode_isrc(buf: &mut [u8; 8], isrc: &[c_char; 12]) {
    unsafe { ffi::mirage_helper_subchannel_q_encode_isrc(buf, isrc) }
}

#[doc(alias = "mirage_helper_subchannel_q_encode_mcn")]
pub fn subchannel_q_encode_mcn(buf: &mut [u8; 7], mcn: &[c_char; 13]) {
    unsafe { ffi::mirage_helper_subchannel_q_encode_mcn(buf, mcn) }
}

#[doc(alias = "mirage_helper_validate_isrc")]
pub fn validate_isrc(isrc: &[c_char; 12]) -> bool {
    unsafe { from_glib(ffi::mirage_helper_validate_isrc(isrc)) }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn format_string_works() {
        let result = format_string!(
            "%b-%02s-track%t.%e",
            "b" => "some_image",
            "s" => 1i16,
            "t" => 3i16,
            "e" => "iso",
        );
        assert_eq!("some_image-01-track3.iso", result.unwrap());
    }
}