<commit_before>#![no_std]
#![allow(unused_imports)]

extern crate alloc;
extern crate lang_items;
extern crate libtock_drivers;

use core::fmt::Write;
use libtock_core::result::CommandError;
use libtock_drivers::console::Console;
#[cfg(feature = "with_nfc")]
use libtock_drivers::nfc::NfcTag;
#[cfg(feature = "with_nfc")]
use libtock_drivers::nfc::RecvOp;
use libtock_drivers::result::TockError;

#[allow(dead_code)]
/// Helper function to write a slice into a transmission buffer.
fn write_tx_buffer(buf: &mut [u8], slice: &[u8]) {
    for (i, &byte) in slice.iter().enumerate() {
        buf[i] = byte;
    }
}

#[allow(dead_code)]
/// Helper function to write on console the received packet.
fn print_rx_buffer(buf: &mut [u8], amount: usize) {
    if amount < 1 || amount > buf.len() {
        return;
    }
    let mut console = Console::new();
    write!(console, " -- RX Packet:").unwrap();
    for byte in buf.iter().take(amount - 1) {
        write!(console, " {:02x?}", byte).unwrap();
    }
    writeln!(console, " {:02x?}", buf[amount - 1]).unwrap();
}

#[cfg(feature = "with_nfc")]
#[derive(PartialEq, Eq)]
/// enum for reserving the NFC tag state.
enum State {
    Enabled,
    Disabled,
}

fn main() {
    let mut console = Console::new();

    writeln!(console, "****************************************").unwrap();
    writeln!(console, "nfct_test application is installed").unwrap();

    #[cfg(feature = "with_nfc")]
    let mut state = State::Disabled;
    #[cfg(feature = "with_nfc")]
    let mut state_change_cntr = 0;
    #[cfg(feature = "with_nfc")]
    loop {
        match state {
            State::Enabled => {
                let mut rx_buf = [0; 256];
                loop {
                    match NfcTag::receive(&mut rx_buf) {
                        Ok(RecvOp {
                            recv_amount: amount,
                            ..
                        }) => print_rx_buffer(&mut rx_buf, amount),
                        Err(TockError::Command(CommandError {
                            return_code: -4, /* EOFF: Not Ready */
                            ..
                        })) => (),
                        Err(TockError::Command(CommandError {
                            return_code: value, ..
                        })) => writeln!(console, " -- Err({})!", value).unwrap(),
                        Err(_) => writeln!(console, " -- RX ERROR").unwrap(),
                    }

                    match rx_buf[0] {
                        0xe0 /* RATS */=> {
                            let mut answer_to_select = [0x05, 0x78, 0x80, 0xB1, 0x00];
                            let amount = answer_to_select.len();
                            match NfcTag::transmit(&mut answer_to_select, amount) {
                                Ok(_) => (),
                                Err(_) => writeln!(console, " -- tx error!").unwrap(),
                            }
                        }
                        0xc2 /* DESELECT */ => {
                            // Ignore the request
                            let mut command_error = [0x6A, 0x81];
                            let amount = command_error.len();
                            match NfcTag::transmit(&mut command_error, amount) {
                                Ok(_) => (),
                                Err(_) => writeln!(console, " -- tx error!").unwrap(),
                            }
                        }
                        0x02 | 0x03 /* APDU Prefix */ => {
                            // If the received packet is applet selection command (FIDO 2)
                            if rx_buf[1] == 0x00 && rx_buf[2] == 0xa4 && rx_buf[3] == 0x04 {
                                // Vesion: "U2F_V2"
                                // let mut reply = [rx_buf[0], 0x55, 0x32, 0x46, 0x5f, 0x56, 0x32, 0x90, 0x00,];
                                // Vesion: "FIDO_2_0"
                                let mut reply = [rx_buf[0], 0x46, 0x49, 0x44, 0x4f, 0x5f, 0x32, 0x5f, 0x30, 0x90, 0x00,];
                                let amount = reply.len();
                                match NfcTag::transmit(&mut reply, amount) {
                                    Ok(_) => (),
                                    Err(_) => writeln!(console, " -- tx error!").unwrap(),
                                }
                            } else {
                                let mut reply = [rx_buf[0], 0x90, 0x00];
                                let amount = reply.len();
                                match NfcTag::transmit(&mut reply, amount) {
                                    Ok(_) => (),
                                    Err(_) => writeln!(console, " -- tx error!").unwrap(),
                                }
                            }
                        }
                        0x52 | 0x50 /* WUPA | Halt */ => {
                            if NfcTag::disable_emulation() {
                                writeln!(console, " -- TAG DISABLED").unwrap();
                            }
                            state = State::Disabled;
                            break;
                        }
                        _ => (),
                    }
                }
            }
            State::Disabled => {
                NfcTag::enable_emulation();
                // Configure Type 4 tag
                if NfcTag::configure(4) {
                    state = State::Enabled;
                }
            }
        }
        state_change_cntr += 1;
        if state_change_cntr > 100 && state == State::Disabled {
            break;
        }
    }
    writeln!(console, "****************************************").unwrap();
}
<commit_msg>Remove duplicate code<commit_after>#![no_std]
#![allow(unused_imports)]

extern crate alloc;
extern crate lang_items;
extern crate libtock_drivers;

use core::fmt::Write;
use libtock_core::result::CommandError;
use libtock_drivers::console::Console;
#[cfg(feature = "with_nfc")]
use libtock_drivers::nfc::NfcTag;
#[cfg(feature = "with_nfc")]
use libtock_drivers::nfc::RecvOp;
use libtock_drivers::result::TockError;

#[allow(dead_code)]
/// Helper function to write a slice into a transmission buffer.
fn write_tx_buffer(buf: &mut [u8], slice: &[u8]) {
    for (i, &byte) in slice.iter().enumerate() {
        buf[i] = byte;
    }
}

#[allow(dead_code)]
/// Helper function to write on console the received packet.
fn print_rx_buffer(buf: &mut [u8], amount: usize) {
    if amount < 1 || amount > buf.len() {
        return;
    }
    let mut console = Console::new();
    write!(console, " -- RX Packet:").unwrap();
    for byte in buf.iter().take(amount - 1) {
        write!(console, " {:02x?}", byte).unwrap();
    }
    writeln!(console, " {:02x?}", buf[amount - 1]).unwrap();
}

#[allow(dead_code)]
/// Helper function to write on console the received packet.
fn transmit_slice(buf: &mut [u8] {
    let amount = buf.len();
    match NfcTag::transmit(&mut buf, amount) {
        Ok(_) => (),
        Err(_) => writeln!(console, " -- tx error!").unwrap(),
    }
}

#[cfg(feature = "with_nfc")]
#[derive(PartialEq, Eq)]
/// enum for reserving the NFC tag state.
enum State {
    Enabled,
    Disabled,
}

fn main() {
    let mut console = Console::new();

    writeln!(console, "****************************************").unwrap();
    writeln!(console, "nfct_test application is installed").unwrap();

    #[cfg(feature = "with_nfc")]
    let mut state = State::Disabled;
    #[cfg(feature = "with_nfc")]
    let mut state_change_cntr = 0;
    #[cfg(feature = "with_nfc")]
    loop {
        match state {
            State::Enabled => {
                let mut rx_buf = [0; 256];
                loop {
                    match NfcTag::receive(&mut rx_buf) {
                        Ok(RecvOp {
                            recv_amount: amount,
                            ..
                        }) => print_rx_buffer(&mut rx_buf, amount),
                        Err(TockError::Command(CommandError {
                            return_code: -4, /* EOFF: Not Ready */
                            ..
                        })) => (),
                        Err(TockError::Command(CommandError {
                            return_code: value, ..
                        })) => writeln!(console, " -- Err({})!", value).unwrap(),
                        Err(_) => writeln!(console, " -- RX Err").unwrap(),
                    }

                    match rx_buf[0] {
                        0xe0 /* RATS */=> {
                            let mut answer_to_select = [0x05, 0x78, 0x80, 0xB1, 0x00];
                            transmit_slice(&mut answer_to_select);
                        }
                        0xc2 /* DESELECT */ => {
                            // Ignore the request
                            let mut command_error = [0x6A, 0x81];
                            transmit_slice(&mut command_error);
                        }
                        0x02 | 0x03 /* APDU Prefix */ => {
                            // If the received packet is applet selection command (FIDO 2)
                            if rx_buf[1] == 0x00 && rx_buf[2] == 0xa4 && rx_buf[3] == 0x04 {
                                /// Vesion: "U2F_V2"
                                // let mut reply = [rx_buf[0], 0x55, 0x32, 0x46, 0x5f, 0x56, 0x32, 0x90, 0x00,];
                                /// Vesion: "FIDO_2_0"
                                let mut reply = [rx_buf[0], 0x46, 0x49, 0x44, 0x4f, 0x5f, 0x32, 0x5f, 0x30, 0x90, 0x00,];
                                transmit_slice(&mut reply);
                            } else {
                                let mut reply = [rx_buf[0], 0x90, 0x00];
                                transmit_slice(&mut reply);
                            }
                        }
                        0x52 | 0x50 /* WUPA | Halt */ => {
                            if NfcTag::disable_emulation() {
                                writeln!(console, " -- TAG DISABLED").unwrap();
                            }
                            state = State::Disabled;
                            break;
                        }
                        _ => (),
                    }
                }
            }
            State::Disabled => {
                NfcTag::enable_emulation();
                // Configure Type 4 tag
                if NfcTag::configure(4) {
                    state = State::Enabled;
                }
            }
        }
        state_change_cntr += 1;
        if state_change_cntr > 100 && state == State::Disabled {
            break;
        }
    }
    writeln!(console, "****************************************").unwrap();
}
<|endoftext|>


<commit_before>use core::intrinsics;

// NOTE This function and the ones below are implemented using assembly because they using a custom
// calling convention which can't be implemented using a normal Rust function.
// NOTE The only difference between the iOS and non-iOS versions of those functions is that the iOS
// versions use 3 leading underscores in the names of called functions instead of 2.
#[cfg(not(any(target_os = "ios", target_env = "msvc")))]
#[naked]
#[cfg_attr(not(feature = "mangled-names"), no_mangle)]
pub unsafe fn __aeabi_uidivmod() {
    asm!("push {lr}
          sub sp, sp, #4
          mov r2, sp
          bl __udivmodsi4
          ldr r1, [sp]
          add sp, sp, #4
          pop {pc}" ::: "memory" : "volatile");
    intrinsics::unreachable();
}

#[cfg(target_os = "ios")]
#[naked]
#[cfg_attr(not(feature = "mangled-names"), no_mangle)]
pub unsafe fn __aeabi_uidivmod() {
    asm!("push {lr}
          sub sp, sp, #4
          mov r2, sp
          bl ___udivmodsi4
          ldr r1, [sp]
          add sp, sp, #4
          pop {pc}" ::: "memory" : "volatile");
    intrinsics::unreachable();
}

#[cfg(not(target_os = "ios"))]
#[naked]
#[cfg_attr(not(feature = "mangled-names"), no_mangle)]
pub unsafe fn __aeabi_uldivmod() {
    asm!("push {r4, lr}
          sub sp, sp, #16
          add r4, sp, #8
          str r4, [sp]
          bl __udivmoddi4
          ldr r2, [sp, #8]
          ldr r3, [sp, #12]
          add sp, sp, #16
          pop {r4, pc}" ::: "memory" : "volatile");
    intrinsics::unreachable();
}

#[cfg(target_os = "ios")]
#[naked]
#[cfg_attr(not(feature = "mangled-names"), no_mangle)]
pub unsafe fn __aeabi_uldivmod() {
    asm!("push {r4, lr}
          sub sp, sp, #16
          add r4, sp, #8
          str r4, [sp]
          bl ___udivmoddi4
          ldr r2, [sp, #8]
          ldr r3, [sp, #12]
          add sp, sp, #16
          pop {r4, pc}" ::: "memory" : "volatile");
    intrinsics::unreachable();
}

#[cfg(not(target_os = "ios"))]
#[naked]
#[cfg_attr(not(feature = "mangled-names"), no_mangle)]
pub unsafe fn __aeabi_idivmod() {
    asm!("push {r0, r1, r4, lr}
          bl __aeabi_idiv
          pop {r1, r2}
          muls r2, r2, r0
          subs r1, r1, r2
          pop {r4, pc}" ::: "memory" : "volatile");
    intrinsics::unreachable();
}

#[cfg(target_os = "ios")]
#[naked]
#[cfg_attr(not(feature = "mangled-names"), no_mangle)]
pub unsafe fn __aeabi_idivmod() {
    asm!("push {r0, r1, r4, lr}
          bl ___aeabi_idiv
          pop {r1, r2}
          muls r2, r2, r0
          subs r1, r1, r2
          pop {r4, pc}" ::: "memory" : "volatile");
    intrinsics::unreachable();
}

#[cfg(not(target_os = "ios"))]
#[naked]
#[cfg_attr(not(feature = "mangled-names"), no_mangle)]
pub unsafe fn __aeabi_ldivmod() {
    asm!("push {r4, lr}
          sub sp, sp, #16
          add r4, sp, #8
          str r4, [sp]
          bl __divmoddi4
          ldr r2, [sp, #8]
          ldr r3, [sp, #12]
          add sp, sp, #16
          pop {r4, pc}" ::: "memory" : "volatile");
    intrinsics::unreachable();
}

#[cfg(target_os = "ios")]
#[naked]
#[cfg_attr(not(feature = "mangled-names"), no_mangle)]
pub unsafe fn __aeabi_ldivmod() {
    asm!("push {r4, lr}
          sub sp, sp, #16
          add r4, sp, #8
          str r4, [sp]
          bl ___divmoddi4
          ldr r2, [sp, #8]
          ldr r3, [sp, #12]
          add sp, sp, #16
          pop {r4, pc}" ::: "memory" : "volatile");
    intrinsics::unreachable();
}

// FIXME: The `*4` and `*8` variants should be defined as aliases.

#[cfg(not(target_os = "ios"))]
#[cfg_attr(not(feature = "mangled-names"), no_mangle)]
#[cfg_attr(thumb, linkage = "weak")]
pub unsafe extern "aapcs" fn __aeabi_memcpy(dest: *mut u8, src: *const u8, n: usize) {
    ::mem::memcpy(dest, src, n);
}

#[cfg(not(target_os = "ios"))]
#[cfg_attr(not(feature = "mangled-names"), no_mangle)]
#[cfg_attr(thumb, linkage = "weak")]
pub unsafe extern "aapcs" fn __aeabi_memcpy4(dest: *mut u8, src: *const u8, mut n: usize) {
    use core::ptr;

    let mut dest = dest as *mut u32;
    let mut src = src as *mut u32;

    while n >= 4 {
        ptr::write(dest, ptr::read(src));
        dest = dest.offset(1);
        src = src.offset(1);
        n -= 4;
    }

    __aeabi_memcpy(dest as *mut u8, src as *const u8, n);
}

#[cfg(not(target_os = "ios"))]
#[cfg_attr(not(feature = "mangled-names"), no_mangle)]
#[cfg_attr(thumb, linkage = "weak")]
pub unsafe extern "aapcs" fn __aeabi_memcpy8(dest: *mut u8, src: *const u8, n: usize) {
    __aeabi_memcpy4(dest, src, n);
}

#[cfg(not(target_os = "ios"))]
#[cfg_attr(not(feature = "mangled-names"), no_mangle)]
#[cfg_attr(thumb, linkage = "weak")]
pub unsafe extern "aapcs" fn __aeabi_memmove(dest: *mut u8, src: *const u8, n: usize) {
    ::mem::memmove(dest, src, n);
}

#[cfg(not(target_os = "ios"))]
#[cfg_attr(not(feature = "mangled-names"), no_mangle)]
#[cfg_attr(thumb, linkage = "weak")]
pub unsafe extern "aapcs" fn __aeabi_memmove4(dest: *mut u8, src: *const u8, n: usize) {
    __aeabi_memmove(dest, src, n);
}

#[cfg(not(target_os = "ios"))]
#[cfg_attr(not(feature = "mangled-names"), no_mangle)]
#[cfg_attr(thumb, linkage = "weak")]
pub unsafe extern "aapcs" fn __aeabi_memmove8(dest: *mut u8, src: *const u8, n: usize) {
    __aeabi_memmove(dest, src, n);
}

#[cfg(not(target_os = "ios"))]
#[cfg_attr(not(feature = "mangled-names"), no_mangle)]
#[cfg_attr(thumb, linkage = "weak")]
pub unsafe extern "aapcs" fn __aeabi_memset(dest: *mut u8, n: usize, c: i32) {
    // Note the different argument order
    ::mem::memset(dest, c, n);
}

#[cfg(not(target_os = "ios"))]
#[cfg_attr(not(feature = "mangled-names"), no_mangle)]
#[cfg_attr(thumb, linkage = "weak")]
pub unsafe extern "aapcs" fn __aeabi_memset4(dest: *mut u8, mut n: usize, c: i32) {
    use core::ptr;

    let mut dest = dest as *mut u32;

    let byte = (c as u32) & 0xff;
    let c = (byte << 24) | (byte << 16) | (byte << 8) | byte;

    while n >= 4 {
        ptr::write(dest, c);
        dest = dest.offset(1);
        n -= 4;
    }

    __aeabi_memset(dest as *mut u8, n, byte as i32);
}

#[cfg(not(target_os = "ios"))]
#[cfg_attr(not(feature = "mangled-names"), no_mangle)]
#[cfg_attr(thumb, linkage = "weak")]
pub unsafe extern "aapcs" fn __aeabi_memset8(dest: *mut u8, n: usize, c: i32) {
    __aeabi_memset4(dest, n, c);
}

#[cfg(not(target_os = "ios"))]
#[cfg_attr(not(feature = "mangled-names"), no_mangle)]
#[cfg_attr(thumb, linkage = "weak")]
pub unsafe extern "aapcs" fn __aeabi_memclr(dest: *mut u8, n: usize) {
    __aeabi_memset(dest, n, 0);
}

#[cfg(not(target_os = "ios"))]
#[cfg_attr(not(feature = "mangled-names"), no_mangle)]
#[cfg_attr(thumb, linkage = "weak")]
pub unsafe extern "aapcs" fn __aeabi_memclr4(dest: *mut u8, n: usize) {
    __aeabi_memset4(dest, n, 0);
}

#[cfg(not(target_os = "ios"))]
#[cfg_attr(not(feature = "mangled-names"), no_mangle)]
#[cfg_attr(thumb, linkage = "weak")]
pub unsafe extern "aapcs" fn __aeabi_memclr8(dest: *mut u8, n: usize) {
    __aeabi_memset4(dest, n, 0);
}
<commit_msg>Fix undefined symbol errors on windows/arm<commit_after>use core::intrinsics;

// NOTE This function and the ones below are implemented using assembly because they using a custom
// calling convention which can't be implemented using a normal Rust function.
// NOTE The only difference between the iOS and non-iOS versions of those functions is that the iOS
// versions use 3 leading underscores in the names of called functions instead of 2.
#[cfg(not(any(target_os = "ios", target_env = "msvc")))]
#[naked]
#[cfg_attr(not(feature = "mangled-names"), no_mangle)]
pub unsafe fn __aeabi_uidivmod() {
    asm!("push {lr}
          sub sp, sp, #4
          mov r2, sp
          bl __udivmodsi4
          ldr r1, [sp]
          add sp, sp, #4
          pop {pc}" ::: "memory" : "volatile");
    intrinsics::unreachable();
}

#[cfg(target_os = "ios")]
#[naked]
#[cfg_attr(not(feature = "mangled-names"), no_mangle)]
pub unsafe fn __aeabi_uidivmod() {
    asm!("push {lr}
          sub sp, sp, #4
          mov r2, sp
          bl ___udivmodsi4
          ldr r1, [sp]
          add sp, sp, #4
          pop {pc}" ::: "memory" : "volatile");
    intrinsics::unreachable();
}

#[cfg(not(target_os = "ios"))]
#[naked]
#[cfg_attr(not(feature = "mangled-names"), no_mangle)]
pub unsafe fn __aeabi_uldivmod() {
    asm!("push {r4, lr}
          sub sp, sp, #16
          add r4, sp, #8
          str r4, [sp]
          bl __udivmoddi4
          ldr r2, [sp, #8]
          ldr r3, [sp, #12]
          add sp, sp, #16
          pop {r4, pc}" ::: "memory" : "volatile");
    intrinsics::unreachable();
}

#[cfg(target_os = "ios")]
#[naked]
#[cfg_attr(not(feature = "mangled-names"), no_mangle)]
pub unsafe fn __aeabi_uldivmod() {
    asm!("push {r4, lr}
          sub sp, sp, #16
          add r4, sp, #8
          str r4, [sp]
          bl ___udivmoddi4
          ldr r2, [sp, #8]
          ldr r3, [sp, #12]
          add sp, sp, #16
          pop {r4, pc}" ::: "memory" : "volatile");
    intrinsics::unreachable();
}

#[cfg(not(target_os = "ios"))]
#[naked]
#[cfg_attr(not(feature = "mangled-names"), no_mangle)]
pub unsafe fn __aeabi_idivmod() {
    asm!("push {r0, r1, r4, lr}
          bl __aeabi_idiv
          pop {r1, r2}
          muls r2, r2, r0
          subs r1, r1, r2
          pop {r4, pc}" ::: "memory" : "volatile");
    intrinsics::unreachable();
}

#[cfg(target_os = "ios")]
#[naked]
#[cfg_attr(not(feature = "mangled-names"), no_mangle)]
pub unsafe fn __aeabi_idivmod() {
    asm!("push {r0, r1, r4, lr}
          bl ___aeabi_idiv
          pop {r1, r2}
          muls r2, r2, r0
          subs r1, r1, r2
          pop {r4, pc}" ::: "memory" : "volatile");
    intrinsics::unreachable();
}

#[cfg(not(target_os = "ios"))]
#[naked]
#[cfg_attr(not(feature = "mangled-names"), no_mangle)]
pub unsafe fn __aeabi_ldivmod() {
    asm!("push {r4, lr}
          sub sp, sp, #16
          add r4, sp, #8
          str r4, [sp]
          bl __divmoddi4
          ldr r2, [sp, #8]
          ldr r3, [sp, #12]
          add sp, sp, #16
          pop {r4, pc}" ::: "memory" : "volatile");
    intrinsics::unreachable();
}

#[cfg(target_os = "ios")]
#[naked]
#[cfg_attr(not(feature = "mangled-names"), no_mangle)]
pub unsafe fn __aeabi_ldivmod() {
    asm!("push {r4, lr}
          sub sp, sp, #16
          add r4, sp, #8
          str r4, [sp]
          bl ___divmoddi4
          ldr r2, [sp, #8]
          ldr r3, [sp, #12]
          add sp, sp, #16
          pop {r4, pc}" ::: "memory" : "volatile");
    intrinsics::unreachable();
}

// FIXME: The `*4` and `*8` variants should be defined as aliases.

#[cfg(not(target_os = "ios"))]
#[cfg_attr(not(feature = "mangled-names"), no_mangle)]
#[cfg_attr(thumb, linkage = "weak")]
pub unsafe extern "aapcs" fn __aeabi_memcpy(dest: *mut u8, src: *const u8, n: usize) {
    ::mem::memcpy(dest, src, n);
}

#[cfg(not(target_os = "ios"))]
#[cfg_attr(not(feature = "mangled-names"), no_mangle)]
#[cfg_attr(thumb, linkage = "weak")]
pub unsafe extern "aapcs" fn __aeabi_memcpy4(dest: *mut u8, src: *const u8, mut n: usize) {
    use core::ptr;

    let mut dest = dest as *mut u32;
    let mut src = src as *mut u32;

    while n >= 4 {
        ptr::write(dest, ptr::read(src));
        dest = dest.offset(1);
        src = src.offset(1);
        n -= 4;
    }

    __aeabi_memcpy(dest as *mut u8, src as *const u8, n);
}

#[cfg(not(target_os = "ios"))]
#[cfg_attr(not(feature = "mangled-names"), no_mangle)]
#[cfg_attr(thumb, linkage = "weak")]
pub unsafe extern "aapcs" fn __aeabi_memcpy8(dest: *mut u8, src: *const u8, n: usize) {
    __aeabi_memcpy4(dest, src, n);
}

#[cfg(not(target_os = "ios"))]
#[cfg_attr(not(feature = "mangled-names"), no_mangle)]
#[cfg_attr(thumb, linkage = "weak")]
pub unsafe extern "aapcs" fn __aeabi_memmove(dest: *mut u8, src: *const u8, n: usize) {
    ::mem::memmove(dest, src, n);
}

#[cfg(not(any(target_os = "ios", target_env = "msvc")))]
#[cfg_attr(not(feature = "mangled-names"), no_mangle)]
#[cfg_attr(thumb, linkage = "weak")]
pub unsafe extern "aapcs" fn __aeabi_memmove4(dest: *mut u8, src: *const u8, n: usize) {
    __aeabi_memmove(dest, src, n);
}

#[cfg(not(any(target_os = "ios", target_env = "msvc")))]
#[cfg_attr(not(feature = "mangled-names"), no_mangle)]
#[cfg_attr(thumb, linkage = "weak")]
pub unsafe extern "aapcs" fn __aeabi_memmove8(dest: *mut u8, src: *const u8, n: usize) {
    __aeabi_memmove(dest, src, n);
}

#[cfg(not(target_os = "ios"))]
#[cfg_attr(not(feature = "mangled-names"), no_mangle)]
#[cfg_attr(thumb, linkage = "weak")]
pub unsafe extern "aapcs" fn __aeabi_memset(dest: *mut u8, n: usize, c: i32) {
    // Note the different argument order
    ::mem::memset(dest, c, n);
}

#[cfg(not(target_os = "ios"))]
#[cfg_attr(not(feature = "mangled-names"), no_mangle)]
#[cfg_attr(thumb, linkage = "weak")]
pub unsafe extern "aapcs" fn __aeabi_memset4(dest: *mut u8, mut n: usize, c: i32) {
    use core::ptr;

    let mut dest = dest as *mut u32;

    let byte = (c as u32) & 0xff;
    let c = (byte << 24) | (byte << 16) | (byte << 8) | byte;

    while n >= 4 {
        ptr::write(dest, c);
        dest = dest.offset(1);
        n -= 4;
    }

    __aeabi_memset(dest as *mut u8, n, byte as i32);
}

#[cfg(not(target_os = "ios"))]
#[cfg_attr(not(feature = "mangled-names"), no_mangle)]
#[cfg_attr(thumb, linkage = "weak")]
pub unsafe extern "aapcs" fn __aeabi_memset8(dest: *mut u8, n: usize, c: i32) {
    __aeabi_memset4(dest, n, c);
}

#[cfg(not(target_os = "ios"))]
#[cfg_attr(not(feature = "mangled-names"), no_mangle)]
#[cfg_attr(thumb, linkage = "weak")]
pub unsafe extern "aapcs" fn __aeabi_memclr(dest: *mut u8, n: usize) {
    __aeabi_memset(dest, n, 0);
}

#[cfg(not(any(target_os = "ios", target_env = "msvc")))]
#[cfg_attr(not(feature = "mangled-names"), no_mangle)]
#[cfg_attr(thumb, linkage = "weak")]
pub unsafe extern "aapcs" fn __aeabi_memclr4(dest: *mut u8, n: usize) {
    __aeabi_memset4(dest, n, 0);
}

#[cfg(not(any(target_os = "ios", target_env = "msvc")))]
#[cfg_attr(not(feature = "mangled-names"), no_mangle)]
#[cfg_attr(thumb, linkage = "weak")]
pub unsafe extern "aapcs" fn __aeabi_memclr8(dest: *mut u8, n: usize) {
    __aeabi_memset4(dest, n, 0);
}
<|endoftext|>


<commit_before>use std::ops::Index;

use cgmath::Point3;

use crate::aabb::AABB;
use crate::pt_renderer::{Intersect, Ray};
use crate::stats;
use crate::triangle::RTTriangle;

const MAX_LEAF_SIZE: usize = 8;

#[allow(dead_code)]
#[derive(Clone, Copy)]
pub enum SplitMode {
    Object,
    Spatial,
    SAH,
}

pub struct BVHNode {
    aabb: AABB,
    pub start_i: usize,
    pub end_i: usize,
    left_child_i: Option<usize>,
    right_child_i: Option<usize>,
}

impl BVHNode {
    fn new(triangles: &Triangles) -> BVHNode {
        let start_i = triangles.start_i;
        let end_i = start_i + triangles.len();
        BVHNode {
            aabb: triangles.aabb.clone(),
            start_i,
            end_i,
            left_child_i: None,
            right_child_i: None,
        }
    }

    fn n_tris(&self) -> usize {
        self.end_i - self.start_i
    }

    pub fn is_leaf(&self) -> bool {
        self.left_child_i.is_none()
    }
}

impl Intersect<'_, f32> for BVHNode {
    fn intersect(&self, ray: &Ray) -> Option<f32> {
        self.aabb.intersect(ray)
    }
}

struct Triangles<'a> {
    triangles: &'a [RTTriangle],
    centers: &'a [Point3<f32>],
    indices: &'a mut [usize],
    aabb: AABB,
    /// Node contains indices [start_i, start_i + len) from the main indices array
    start_i: usize,
    /// Axis along which the indices have been sorted
    sorted_axis: usize,
}

impl<'a> Triangles<'a> {
    fn new(
        triangles: &'a [RTTriangle],
        centers: &'a [Point3<f32>],
        indices: &'a mut [usize],
        start_i: usize,
    ) -> Triangles<'a> {
        let mut aabb = AABB::empty();
        for &i in indices.iter() {
            let tri = &triangles[i];
            aabb.add_aabb(&tri.aabb());
        }
        Triangles {
            triangles,
            centers,
            indices,
            aabb,
            start_i,
            // Use bogus value since nothing has been sorted
            sorted_axis: 42,
        }
    }

    fn sort_longest_axis(&mut self) {
        let axis_i = self.aabb.longest_edge_i();
        self.sort(axis_i);
    }

    fn sort(&mut self, axis_i: usize) {
        // The indices are already sorted along the requested axis
        if axis_i == self.sorted_axis {
            return;
        }
        let centers = self.centers;
        self.indices.sort_unstable_by(|&i1, &i2| {
            let c1 = centers[i1][axis_i];
            let c2 = centers[i2][axis_i];
            c1.partial_cmp(&c2).unwrap()
        });
        self.sorted_axis = axis_i;
    }

    fn split(self, i: usize) -> (Triangles<'a>, Triangles<'a>) {
        let (i1, i2) = self.indices.split_at_mut(i);
        let mut node1 = Triangles::new(self.triangles, self.centers, i1, self.start_i);
        let mut node2 = Triangles::new(self.triangles, self.centers, i2, self.start_i + i);
        node1.sorted_axis = self.sorted_axis;
        node2.sorted_axis = self.sorted_axis;
        (node1, node2)
    }

    fn len(&self) -> usize {
        self.indices.len()
    }

    fn last(&self) -> &RTTriangle {
        let &i = self.indices.last().unwrap();
        &self.triangles[i]
    }
}

impl Index<usize> for Triangles<'_> {
    type Output = RTTriangle;

    fn index(&self, i: usize) -> &RTTriangle {
        let i = self.indices[i];
        &self.triangles[i]
    }
}

pub struct BVH {
    nodes: Vec<BVHNode>,
}

impl BVH {
    pub fn empty() -> BVH {
        BVH { nodes: Vec::new() }
    }

    pub fn build(triangles: &[RTTriangle], split_mode: SplitMode) -> (BVH, Vec<usize>) {
        stats::start_bvh();
        let centers: Vec<Point3<f32>> = triangles.iter().map(|ref tri| tri.center()).collect();
        let mut permutation: Vec<usize> = (0..triangles.len()).collect();
        let tris = Triangles::new(triangles, &centers, &mut permutation, 0);
        let mut nodes = Vec::with_capacity(f32::log2(triangles.len() as f32) as usize);
        nodes.push(BVHNode::new(&tris));
        let mut split_stack = vec![(0usize, tris)];

        while let Some((node_i, mut tris)) = split_stack.pop() {
            let mid_offset = match split_mode {
                SplitMode::Object => object_split(&mut tris),
                SplitMode::Spatial => spatial_split(&mut tris),
                SplitMode::SAH => sah_split(&mut tris),
            };
            let (t1, t2) = if let Some(offset) = mid_offset {
                tris.split(offset)
            } else {
                continue;
            };

            let left_child = BVHNode::new(&t1);
            nodes[node_i].left_child_i = Some(nodes.len());
            if left_child.n_tris() > MAX_LEAF_SIZE {
                split_stack.push((nodes.len(), t1));
            }
            nodes.push(left_child);

            let right_child = BVHNode::new(&t2);
            nodes[node_i].right_child_i = Some(nodes.len());
            if right_child.n_tris() > MAX_LEAF_SIZE {
                split_stack.push((nodes.len(), t2));
            }
            nodes.push(right_child);
        }
        nodes.shrink_to_fit();
        let bvh = BVH { nodes };
        stats::stop_bvh(&bvh);
        (bvh, permutation)
    }

    pub fn get_children(&self, node: &BVHNode) -> Option<(&BVHNode, &BVHNode)> {
        if let Some(left_i) = node.left_child_i {
            Some((
                &self.nodes[left_i],
                &self.nodes[node.right_child_i.unwrap()],
            ))
        } else {
            None
        }
    }

    pub fn root(&self) -> &BVHNode {
        &self.nodes[0]
    }

    pub fn size(&self) -> usize {
        self.nodes.len()
    }

    pub fn n_tris(&self) -> usize {
        self.root().n_tris()
    }
}

fn object_split(triangles: &mut Triangles) -> Option<usize> {
    triangles.sort_longest_axis();
    Some(triangles.len() / 2)
}

fn spatial_split(triangles: &mut Triangles) -> Option<usize> {
    let aabb = &triangles.aabb;
    let axis_i = aabb.longest_edge_i();
    let mid_val = aabb.center()[axis_i];
    triangles.sort(axis_i);
    let centers = triangles.centers;
    let i = triangles
        .indices
        .binary_search_by(|&i| {
            let c = centers[i][axis_i];
            c.partial_cmp(&mid_val).unwrap()
        })
        .unwrap_or_else(|e| e);
    // Use object median if all centers are on one side of the median
    if i == 0 || i == triangles.len() {
        object_split(triangles)
    } else {
        Some(i)
    }
}

fn sah_split(triangles: &mut Triangles) -> Option<usize> {
    let mut min_score = std::f32::MAX;
    let mut min_axis = 0;
    let mut min_i = 0;
    let sorted_axis = triangles.sorted_axis;
    for offset in 0..3 {
        // Check the sorted axis first
        let axis = (sorted_axis + offset) % 3;
        triangles.sort(axis);
        // Precompute all right side bbs
        let mut right_bbs = Vec::with_capacity(triangles.len());
        right_bbs.push(triangles.last().aabb());
        for i in 1..triangles.len() {
            let mut new_bb = right_bbs[i - 1].clone();
            new_bb.add_aabb(&triangles[triangles.len() - 1 - i].aabb());
            right_bbs.push(new_bb);
        }
        let mut left_bb = AABB::empty();
        // Go through the possible splits
        for i in 0..triangles.len() {
            left_bb.add_aabb(&triangles[i].aabb());
            let right_bb = &right_bbs[right_bbs.len() - 1 - i];
            let score = i as f32 * left_bb.area() + (triangles.len() - i) as f32 * right_bb.area();
            if score < min_score {
                min_score = score;
                min_axis = axis;
                min_i = i;
            }
        }
    }
    if min_i == 0 {
        None
    } else {
        triangles.sort(min_axis);
        Some(min_i)
    }
}
<commit_msg>Remove unused function<commit_after>use std::ops::Index;

use cgmath::Point3;

use crate::aabb::AABB;
use crate::pt_renderer::{Intersect, Ray};
use crate::stats;
use crate::triangle::RTTriangle;

const MAX_LEAF_SIZE: usize = 8;

#[allow(dead_code)]
#[derive(Clone, Copy)]
pub enum SplitMode {
    Object,
    Spatial,
    SAH,
}

pub struct BVHNode {
    aabb: AABB,
    pub start_i: usize,
    pub end_i: usize,
    left_child_i: Option<usize>,
    right_child_i: Option<usize>,
}

impl BVHNode {
    fn new(triangles: &Triangles) -> BVHNode {
        let start_i = triangles.start_i;
        let end_i = start_i + triangles.len();
        BVHNode {
            aabb: triangles.aabb.clone(),
            start_i,
            end_i,
            left_child_i: None,
            right_child_i: None,
        }
    }

    fn n_tris(&self) -> usize {
        self.end_i - self.start_i
    }

    pub fn is_leaf(&self) -> bool {
        self.left_child_i.is_none()
    }
}

impl Intersect<'_, f32> for BVHNode {
    fn intersect(&self, ray: &Ray) -> Option<f32> {
        self.aabb.intersect(ray)
    }
}

struct Triangles<'a> {
    triangles: &'a [RTTriangle],
    centers: &'a [Point3<f32>],
    indices: &'a mut [usize],
    aabb: AABB,
    /// Node contains indices [start_i, start_i + len) from the main indices array
    start_i: usize,
    /// Axis along which the indices have been sorted
    sorted_axis: usize,
}

impl<'a> Triangles<'a> {
    fn new(
        triangles: &'a [RTTriangle],
        centers: &'a [Point3<f32>],
        indices: &'a mut [usize],
        start_i: usize,
    ) -> Triangles<'a> {
        let mut aabb = AABB::empty();
        for &i in indices.iter() {
            let tri = &triangles[i];
            aabb.add_aabb(&tri.aabb());
        }
        Triangles {
            triangles,
            centers,
            indices,
            aabb,
            start_i,
            // Use bogus value since nothing has been sorted
            sorted_axis: 42,
        }
    }

    fn sort_longest_axis(&mut self) {
        let axis_i = self.aabb.longest_edge_i();
        self.sort(axis_i);
    }

    fn sort(&mut self, axis_i: usize) {
        // The indices are already sorted along the requested axis
        if axis_i == self.sorted_axis {
            return;
        }
        let centers = self.centers;
        self.indices.sort_unstable_by(|&i1, &i2| {
            let c1 = centers[i1][axis_i];
            let c2 = centers[i2][axis_i];
            c1.partial_cmp(&c2).unwrap()
        });
        self.sorted_axis = axis_i;
    }

    fn split(self, i: usize) -> (Triangles<'a>, Triangles<'a>) {
        let (i1, i2) = self.indices.split_at_mut(i);
        let mut node1 = Triangles::new(self.triangles, self.centers, i1, self.start_i);
        let mut node2 = Triangles::new(self.triangles, self.centers, i2, self.start_i + i);
        node1.sorted_axis = self.sorted_axis;
        node2.sorted_axis = self.sorted_axis;
        (node1, node2)
    }

    fn len(&self) -> usize {
        self.indices.len()
    }

    fn last(&self) -> &RTTriangle {
        let &i = self.indices.last().unwrap();
        &self.triangles[i]
    }
}

impl Index<usize> for Triangles<'_> {
    type Output = RTTriangle;

    fn index(&self, i: usize) -> &RTTriangle {
        let i = self.indices[i];
        &self.triangles[i]
    }
}

pub struct BVH {
    nodes: Vec<BVHNode>,
}

impl BVH {
    pub fn build(triangles: &[RTTriangle], split_mode: SplitMode) -> (BVH, Vec<usize>) {
        stats::start_bvh();
        let centers: Vec<Point3<f32>> = triangles.iter().map(|ref tri| tri.center()).collect();
        let mut permutation: Vec<usize> = (0..triangles.len()).collect();
        let tris = Triangles::new(triangles, &centers, &mut permutation, 0);
        let mut nodes = Vec::with_capacity(f32::log2(triangles.len() as f32) as usize);
        nodes.push(BVHNode::new(&tris));
        let mut split_stack = vec![(0usize, tris)];

        while let Some((node_i, mut tris)) = split_stack.pop() {
            let mid_offset = match split_mode {
                SplitMode::Object => object_split(&mut tris),
                SplitMode::Spatial => spatial_split(&mut tris),
                SplitMode::SAH => sah_split(&mut tris),
            };
            let (t1, t2) = if let Some(offset) = mid_offset {
                tris.split(offset)
            } else {
                continue;
            };

            let left_child = BVHNode::new(&t1);
            nodes[node_i].left_child_i = Some(nodes.len());
            if left_child.n_tris() > MAX_LEAF_SIZE {
                split_stack.push((nodes.len(), t1));
            }
            nodes.push(left_child);

            let right_child = BVHNode::new(&t2);
            nodes[node_i].right_child_i = Some(nodes.len());
            if right_child.n_tris() > MAX_LEAF_SIZE {
                split_stack.push((nodes.len(), t2));
            }
            nodes.push(right_child);
        }
        nodes.shrink_to_fit();
        let bvh = BVH { nodes };
        stats::stop_bvh(&bvh);
        (bvh, permutation)
    }

    pub fn get_children(&self, node: &BVHNode) -> Option<(&BVHNode, &BVHNode)> {
        if let Some(left_i) = node.left_child_i {
            Some((
                &self.nodes[left_i],
                &self.nodes[node.right_child_i.unwrap()],
            ))
        } else {
            None
        }
    }

    pub fn root(&self) -> &BVHNode {
        &self.nodes[0]
    }

    pub fn size(&self) -> usize {
        self.nodes.len()
    }

    pub fn n_tris(&self) -> usize {
        self.root().n_tris()
    }
}

fn object_split(triangles: &mut Triangles) -> Option<usize> {
    triangles.sort_longest_axis();
    Some(triangles.len() / 2)
}

fn spatial_split(triangles: &mut Triangles) -> Option<usize> {
    let aabb = &triangles.aabb;
    let axis_i = aabb.longest_edge_i();
    let mid_val = aabb.center()[axis_i];
    triangles.sort(axis_i);
    let centers = triangles.centers;
    let i = triangles
        .indices
        .binary_search_by(|&i| {
            let c = centers[i][axis_i];
            c.partial_cmp(&mid_val).unwrap()
        })
        .unwrap_or_else(|e| e);
    // Use object median if all centers are on one side of the median
    if i == 0 || i == triangles.len() {
        object_split(triangles)
    } else {
        Some(i)
    }
}

fn sah_split(triangles: &mut Triangles) -> Option<usize> {
    let mut min_score = std::f32::MAX;
    let mut min_axis = 0;
    let mut min_i = 0;
    let sorted_axis = triangles.sorted_axis;
    for offset in 0..3 {
        // Check the sorted axis first
        let axis = (sorted_axis + offset) % 3;
        triangles.sort(axis);
        // Precompute all right side bbs
        let mut right_bbs = Vec::with_capacity(triangles.len());
        right_bbs.push(triangles.last().aabb());
        for i in 1..triangles.len() {
            let mut new_bb = right_bbs[i - 1].clone();
            new_bb.add_aabb(&triangles[triangles.len() - 1 - i].aabb());
            right_bbs.push(new_bb);
        }
        let mut left_bb = AABB::empty();
        // Go through the possible splits
        for i in 0..triangles.len() {
            left_bb.add_aabb(&triangles[i].aabb());
            let right_bb = &right_bbs[right_bbs.len() - 1 - i];
            let score = i as f32 * left_bb.area() + (triangles.len() - i) as f32 * right_bb.area();
            if score < min_score {
                min_score = score;
                min_axis = axis;
                min_i = i;
            }
        }
    }
    if min_i == 0 {
        None
    } else {
        triangles.sort(min_axis);
        Some(min_i)
    }
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate cfg_if;
extern crate gcc;

use std::cmp::Ordering;
use std::env;
use std::ffi::{OsStr, OsString};
use std::fs;
use std::iter;
use std::path::{Path, PathBuf};
use std::process::{self, Child, Command, Stdio};
use std::str;

cfg_if! {
    if #[cfg(feature = "v1_8_0")] {
        const TARGET_VERSION: &'static str = "1.8.0";
    } else if #[cfg(feature = "v1_7_1")] {
        const TARGET_VERSION: &'static str = "1.7.1";
    } else if #[cfg(feature = "v1_7_0")] {
        const TARGET_VERSION: &'static str = "1.7.0";
    } else if #[cfg(feature = "v1_6_0")] {
        const TARGET_VERSION: &'static str = "1.6.0";
    } else if #[cfg(feature = "v1_5_1")] {
        const TARGET_VERSION: &'static str = "1.5.1";
    } else if #[cfg(feature = "v1_5_0")] {
        const TARGET_VERSION: &'static str = "1.5.0";
    } else if #[cfg(feature = "v1_4_3")] {
        const TARGET_VERSION: &'static str = "1.4.3";
    } else if #[cfg(feature = "v1_4_2")] {
        const TARGET_VERSION: &'static str = "1.4.2";
    } else if #[cfg(feature = "v1_4_0")] {
        const TARGET_VERSION: &'static str = "1.4.0";
    } else if #[cfg(feature = "v1_3_1")] {
        const TARGET_VERSION: &'static str = "1.3.1";
    } else if #[cfg(feature = "v1_3_0")] {
        const TARGET_VERSION: &'static str = "1.3.0";
    } else {
        const TARGET_VERSION: &'static str = "1.2.0";
    }
}

fn main() {
    if let Ok(lib) = env::var("GPGME_LIB") {
        let mode = match env::var_os("GPGME_STATIC") {
            Some(_) => "static",
            _ => "dylib",
        };
        println!("cargo:rustc-link-lib={0}={1}", mode, lib);
        return;
    } else if let Some(path) = env::var_os("GPGME_CONFIG") {
        if !try_config(path) {
            process::exit(1);
        }
        return;
    }

    if !Path::new("libassuan/.git").exists() || !Path::new("gpgme/.git").exists() {
        run(Command::new("git").args(&["submodule", "update", "--init"]));
    }

    if try_build() || try_config("gpgme-config") {
        return;
    }
    process::exit(1);
}

fn try_config<S: AsRef<OsStr>>(path: S) -> bool {
    let path = path.as_ref();

    if let Some(output) = output(Command::new(&path).arg("--version")) {
        test_version(&output);
    } else {
        return false;
    }

    if let Some(output) = output(Command::new(&path).arg("--prefix")) {
        println!("cargo:root={}", output);
    }

    let mut command = Command::new(&path);
    if cfg!(unix) {
        command.arg("--thread=pthread");
    }
    command.arg("--libs");
    if let Some(output) = output(&mut command) {
        parse_config_output(&output);
        return true;
    }
    false
}

fn parse_config_output(output: &str) {
    let parts = output.split(|c: char| c.is_whitespace()).filter_map(|p| if p.len() > 2 {
        Some(p.split_at(2))
    } else {
        None
    });

    for (flag, val) in parts {
        match flag {
            "-L" => {
                println!("cargo:rustc-link-search=native={}", val);
            }
            "-F" => {
                println!("cargo:rustc-link-search=framework={}", val);
            }
            "-l" => {
                println!("cargo:rustc-link-lib={}", val);
            }
            _ => {}
        }
    }
}

fn try_build() -> bool {
    let src = PathBuf::from(env::current_dir().unwrap()).join("libassuan");
    let dst = env::var("OUT_DIR").unwrap();
    let build = PathBuf::from(&dst).join("build/assuan");
    let target = env::var("TARGET").unwrap();
    let host = env::var("HOST").unwrap();
    let gpgerror_root = env::var("DEP_GPG_ERROR_ROOT").unwrap();
    let compiler = gcc::Config::new().get_compiler();
    let cflags = compiler.args().iter().fold(OsString::new(), |mut c, a| {
        c.push(a);
        c.push(" ");
        c
    });

    let _ = fs::create_dir_all(&build);

    if !run(Command::new("sh").current_dir(&src).arg("autogen.sh")) {
        return false;
    }
    if !run(Command::new("sh")
        .current_dir(&build)
        .env("CC", compiler.path())
        .env("CFLAGS", &cflags)
        .arg(src.join("configure"))
        .args(&["--enable-maintainer-mode",
                "--build",
                &host, "--host", &target,
                "--enable-static",
                "--disable-shared",
                &format!("--with-libgpg-error-prefix={}", &gpgerror_root),
                &format!("--prefix={}", &dst)])) {
        return false;
    }
    if !run(Command::new("make")
        .current_dir(&build)
        .arg("-j").arg(env::var("NUM_JOBS").unwrap())) {
        return false;
    }
    if !run(Command::new("make")
        .current_dir(&build)
        .arg("install")) {
        return false;
    }

    let src = PathBuf::from(env::current_dir().unwrap()).join("gpgme");
    let build = PathBuf::from(&dst).join("build/gpgme");
    let _ = fs::create_dir_all(&build);

    if !run(Command::new("sh").current_dir(&src).arg("autogen.sh")) {
        return false;
    }
    if !run(Command::new("sh")
        .current_dir(&build)
        .env("CC", compiler.path())
        .env("CFLAGS", &cflags)
        .arg(src.join("configure"))
        .args(&["--enable-maintainer-mode",
                "--build", &host,
                "--host", &target,
                "--enable-static",
                "--disable-shared",
                "--disable-languages",
                &format!("--with-libgpg-error-prefix={}", &gpgerror_root),
                &format!("--with-libassuan-prefix={}", &dst),
                &format!("--prefix={}", &dst)])) {
        return false;
    }
    if !run(Command::new("make")
        .current_dir(&build)
        .arg("-j").arg(env::var("NUM_JOBS").unwrap())) {
        return false;
    }
    if !run(Command::new("make").current_dir(&build).arg("install")) {
        return false;
    }

    println!("cargo:rustc-link-search=native={}",
             PathBuf::from(dst.clone()).join("lib").display());
    println!("cargo:rustc-link-lib=static=assuan");
    println!("cargo:rustc-link-lib=static=gpgme");
    println!("cargo:root={}", &dst);
    true
}

fn test_version(version: &str) {
    let version = version.trim();
    for (x, y) in TARGET_VERSION.split('.').zip(version.split('.').chain(iter::repeat("0"))) {
        let (x, y): (u8, u8) = (x.parse().unwrap(), y.parse().unwrap());
        match x.cmp(&y) {
            Ordering::Less => break,
            Ordering::Greater => {
                panic!("GPGME version `{}` is less than requested `{}`",
                       version,
                       TARGET_VERSION)
            }
            _ => (),
        }
    }
}

fn spawn(cmd: &mut Command) -> Option<Child> {
    println!("running: {:?}", cmd);
    match cmd.stdin(Stdio::null()).spawn() {
        Ok(child) => Some(child),
        Err(e) => {
            println!("failed to execute command: {:?}\nerror: {}", cmd, e);
            None
        }
    }
}

fn run(cmd: &mut Command) -> bool {
    if let Some(mut child) = spawn(cmd) {
        match child.wait() {
            Ok(status) => {
                if !status.success() {
                    println!("command did not execute successfully: {:?}\n\
                       expected success, got: {}", cmd, status);
                } else {
                    return true;
                }
            }
            Err(e) => {
                println!("failed to execute command: {:?}\nerror: {}", cmd, e);
            }
        }
    }
    false
}

fn output(cmd: &mut Command) -> Option<String> {
    if let Some(child) = spawn(cmd.stdout(Stdio::piped())) {
        match child.wait_with_output() {
            Ok(output) => {
                if !output.status.success() {
                    println!("command did not execute successfully: {:?}\n\
                       expected success, got: {}", cmd, output.status);
                } else {
                    return String::from_utf8(output.stdout).ok();
                }
            }
            Err(e) => {
                println!("failed to execute command: {:?}\nerror: {}", cmd, e);
            }
        }
    }
    None
}
<commit_msg>Disable maintainer-mode and documentation<commit_after>#[macro_use]
extern crate cfg_if;
extern crate gcc;

use std::cmp::Ordering;
use std::env;
use std::ffi::{OsStr, OsString};
use std::fs;
use std::iter;
use std::path::{Path, PathBuf};
use std::process::{self, Child, Command, Stdio};
use std::str;

cfg_if! {
    if #[cfg(feature = "v1_8_0")] {
        const TARGET_VERSION: &'static str = "1.8.0";
    } else if #[cfg(feature = "v1_7_1")] {
        const TARGET_VERSION: &'static str = "1.7.1";
    } else if #[cfg(feature = "v1_7_0")] {
        const TARGET_VERSION: &'static str = "1.7.0";
    } else if #[cfg(feature = "v1_6_0")] {
        const TARGET_VERSION: &'static str = "1.6.0";
    } else if #[cfg(feature = "v1_5_1")] {
        const TARGET_VERSION: &'static str = "1.5.1";
    } else if #[cfg(feature = "v1_5_0")] {
        const TARGET_VERSION: &'static str = "1.5.0";
    } else if #[cfg(feature = "v1_4_3")] {
        const TARGET_VERSION: &'static str = "1.4.3";
    } else if #[cfg(feature = "v1_4_2")] {
        const TARGET_VERSION: &'static str = "1.4.2";
    } else if #[cfg(feature = "v1_4_0")] {
        const TARGET_VERSION: &'static str = "1.4.0";
    } else if #[cfg(feature = "v1_3_1")] {
        const TARGET_VERSION: &'static str = "1.3.1";
    } else if #[cfg(feature = "v1_3_0")] {
        const TARGET_VERSION: &'static str = "1.3.0";
    } else {
        const TARGET_VERSION: &'static str = "1.2.0";
    }
}

fn main() {
    if let Ok(lib) = env::var("GPGME_LIB") {
        let mode = match env::var_os("GPGME_STATIC") {
            Some(_) => "static",
            _ => "dylib",
        };
        println!("cargo:rustc-link-lib={0}={1}", mode, lib);
        return;
    } else if let Some(path) = env::var_os("GPGME_CONFIG") {
        if !try_config(path) {
            process::exit(1);
        }
        return;
    }

    if !Path::new("libassuan/.git").exists() || !Path::new("gpgme/.git").exists() {
        run(Command::new("git").args(&["submodule", "update", "--init"]));
    }

    if try_build() || try_config("gpgme-config") {
        return;
    }
    process::exit(1);
}

fn try_config<S: AsRef<OsStr>>(path: S) -> bool {
    let path = path.as_ref();

    if let Some(output) = output(Command::new(&path).arg("--version")) {
        test_version(&output);
    } else {
        return false;
    }

    if let Some(output) = output(Command::new(&path).arg("--prefix")) {
        println!("cargo:root={}", output);
    }

    let mut command = Command::new(&path);
    if cfg!(unix) {
        command.arg("--thread=pthread");
    }
    command.arg("--libs");
    if let Some(output) = output(&mut command) {
        parse_config_output(&output);
        return true;
    }
    false
}

fn parse_config_output(output: &str) {
    let parts = output.split(|c: char| c.is_whitespace()).filter_map(|p| if p.len() > 2 {
        Some(p.split_at(2))
    } else {
        None
    });

    for (flag, val) in parts {
        match flag {
            "-L" => {
                println!("cargo:rustc-link-search=native={}", val);
            }
            "-F" => {
                println!("cargo:rustc-link-search=framework={}", val);
            }
            "-l" => {
                println!("cargo:rustc-link-lib={}", val);
            }
            _ => {}
        }
    }
}

fn try_build() -> bool {
    let src = PathBuf::from(env::current_dir().unwrap()).join("libassuan");
    let dst = env::var("OUT_DIR").unwrap();
    let build = PathBuf::from(&dst).join("build/assuan");
    let target = env::var("TARGET").unwrap();
    let host = env::var("HOST").unwrap();
    let gpgerror_root = env::var("DEP_GPG_ERROR_ROOT").unwrap();
    let compiler = gcc::Config::new().get_compiler();
    let cflags = compiler.args().iter().fold(OsString::new(), |mut c, a| {
        c.push(a);
        c.push(" ");
        c
    });

    let _ = fs::create_dir_all(&build);

    if !run(Command::new("sh").current_dir(&src).arg("autogen.sh")) {
        return false;
    }
    if !run(Command::new("sh")
        .current_dir(&build)
        .env("CC", compiler.path())
        .env("CFLAGS", &cflags)
        .arg(src.join("configure"))
        .args(&["--build", &host,
                "--host", &target,
                "--enable-static",
                "--disable-shared",
                "--disable-doc",
                &format!("--with-libgpg-error-prefix={}", &gpgerror_root),
                &format!("--prefix={}", &dst)])) {
        return false;
    }
    if !run(Command::new("make")
        .current_dir(&build)
        .arg("-j").arg(env::var("NUM_JOBS").unwrap())) {
        return false;
    }
    if !run(Command::new("make")
        .current_dir(&build)
        .arg("install")) {
        return false;
    }

    let src = PathBuf::from(env::current_dir().unwrap()).join("gpgme");
    let build = PathBuf::from(&dst).join("build/gpgme");
    let _ = fs::create_dir_all(&build);

    if !run(Command::new("sh").current_dir(&src).arg("autogen.sh")) {
        return false;
    }
    if !run(Command::new("sh")
        .current_dir(&build)
        .env("CC", compiler.path())
        .env("CFLAGS", &cflags)
        .arg(src.join("configure"))
        .args(&["--build", &host,
                "--host", &target,
                "--enable-static",
                "--disable-shared",
                "--disable-languages",
                "--disable-doc",
                &format!("--with-libgpg-error-prefix={}", &gpgerror_root),
                &format!("--with-libassuan-prefix={}", &dst),
                &format!("--prefix={}", &dst)])) {
        return false;
    }
    if !run(Command::new("make")
        .current_dir(&build)
        .arg("-j").arg(env::var("NUM_JOBS").unwrap())) {
        return false;
    }
    if !run(Command::new("make").current_dir(&build).arg("install")) {
        return false;
    }

    println!("cargo:rustc-link-search=native={}",
             PathBuf::from(dst.clone()).join("lib").display());
    println!("cargo:rustc-link-lib=static=assuan");
    println!("cargo:rustc-link-lib=static=gpgme");
    println!("cargo:root={}", &dst);
    true
}

fn test_version(version: &str) {
    let version = version.trim();
    for (x, y) in TARGET_VERSION.split('.').zip(version.split('.').chain(iter::repeat("0"))) {
        let (x, y): (u8, u8) = (x.parse().unwrap(), y.parse().unwrap());
        match x.cmp(&y) {
            Ordering::Less => break,
            Ordering::Greater => {
                panic!("GPGME version `{}` is less than requested `{}`",
                       version,
                       TARGET_VERSION)
            }
            _ => (),
        }
    }
}

fn spawn(cmd: &mut Command) -> Option<Child> {
    println!("running: {:?}", cmd);
    match cmd.stdin(Stdio::null()).spawn() {
        Ok(child) => Some(child),
        Err(e) => {
            println!("failed to execute command: {:?}\nerror: {}", cmd, e);
            None
        }
    }
}

fn run(cmd: &mut Command) -> bool {
    if let Some(mut child) = spawn(cmd) {
        match child.wait() {
            Ok(status) => {
                if !status.success() {
                    println!("command did not execute successfully: {:?}\n\
                       expected success, got: {}", cmd, status);
                } else {
                    return true;
                }
            }
            Err(e) => {
                println!("failed to execute command: {:?}\nerror: {}", cmd, e);
            }
        }
    }
    false
}

fn output(cmd: &mut Command) -> Option<String> {
    if let Some(child) = spawn(cmd.stdout(Stdio::piped())) {
        match child.wait_with_output() {
            Ok(output) => {
                if !output.status.success() {
                    println!("command did not execute successfully: {:?}\n\
                       expected success, got: {}", cmd, output.status);
                } else {
                    return String::from_utf8(output.stdout).ok();
                }
            }
            Err(e) => {
                println!("failed to execute command: {:?}\nerror: {}", cmd, e);
            }
        }
    }
    None
}
<|endoftext|>


<commit_before>use snafu::{Backtrace, ErrorCompat, Snafu};
use std::io;
use std::path;
use std::result;
use std::string;

pub type Result<T> = result::Result<T, Error>;

#[derive(Debug, Snafu)]
#[snafu(visibility(pub(crate)))]
pub enum Error {
    #[snafu(display("io error: {}", source))]
    IO {
        source: io::Error,
        backtrace: Backtrace,
    },

    #[snafu(display("file io error [{:?}]: {}", path, source))]
    FileIO {
        path: path::PathBuf,
        source: io::Error,
        backtrace: Backtrace,
    },

    #[snafu(display("dir entry error [{:?}]: {}", dir, source))]
    EntryIO {
        dir: path::PathBuf,
        source: io::Error,
        backtrace: Backtrace,
    },

    #[snafu(display("toml decode error [{:?}]: {}", path, source))]
    TomlDecode {
        path: path::PathBuf,
        source: toml::de::Error,
        backtrace: Backtrace,
    },

    #[snafu(display("toml encode error [{:?}]: {}", path, source))]
    TomlEncode {
        path: path::PathBuf,
        source: toml::ser::Error,
        backtrace: Backtrace,
    },

    #[snafu(display("message pack encode error [{:?}]: {}", path, source))]
    RMPEncode {
        path: path::PathBuf,
        source: rmp_serde::encode::Error,
        backtrace: Backtrace,
    },

    #[snafu(display("message pack decode error [{:?}]: {}", path, source))]
    RMPDecode {
        path: path::PathBuf,
        source: rmp_serde::decode::Error,
        backtrace: Backtrace,
    },

    #[snafu(display("base64 decode error: {}", source))]
    Base64Decode {
        source: base64::DecodeError,
        backtrace: Backtrace,
    },

    #[snafu(display("utf8 decode error: {}", source))]
    UTF8Decode {
        source: string::FromUtf8Error,
        backtrace: Backtrace,
    },

    #[snafu(display("json decode error: {}", source))]
    JsonDecode {
        source: serde_json::Error,
        backtrace: Backtrace,
    },

    #[snafu(display("failed to create regex matcher \"{}\": {}", matcher, source))]
    Regex {
        matcher: String,
        source: regex::Error,
        backtrace: Backtrace,
    },

    #[snafu(display("reqwest error: {}", source))]
    Reqwest {
        source: reqwest::Error,
        backtrace: Backtrace,
    },

    #[snafu(display("failed to parse episode title: {}", name))]
    NoEpisodeTitle { name: String },

    #[snafu(display("series should only have one episode, but found multiple\n\tshould only be: {}\n\tfound: {}", original, conflict))]
    MultipleEpsInSingleEpSeries { original: String, conflict: String },

    #[snafu(display("expected episode number for file: {}", name))]
    ExpectedEpNumber { name: String },

    #[snafu(display("failed to parse episode: {}", name))]
    NoEpMatches { name: String },

    #[snafu(display(
        "found different episode titles:\n\texpecting: {}\n\tfound: {}",
        expecting,
        found
    ))]
    MultipleTitles { expecting: String, found: String },

    #[snafu(display("no episodes found at path: {:?}", path))]
    NoEpisodes { path: path::PathBuf },

    #[snafu(display("episode {} not found for {}", episode, series))]
    EpisodeNotFound { episode: u32, series: String },

    #[snafu(display("failed to play episode {} of {}: {}", episode, series, source))]
    FailedToPlayEpisode {
        episode: u32,
        series: String,
        source: io::Error,
    },

    #[snafu(display("video player didn't exit normally while playing: {:?}", path))]
    AbnormalPlayerExit { path: path::PathBuf },

    #[snafu(display("no series with id {} found", id))]
    NoSeriesWithID { id: u32 },

    #[snafu(display("no series found with name similar to {}", name))]
    NoMatchingSeries { name: String },

    #[snafu(display("need series data to run in offline mode\nrun the program with --prefetch first when an internet connection is available"))]
    RunWithPrefetch {},

    #[snafu(display("received bad response from AniList (code {}): {}", code, message))]
    BadAniListResponse { code: u16, message: String },

    #[snafu(display("no data found for season {}", season))]
    NoSeason { season: usize },
}

impl Error {
    pub fn is_file_nonexistant(&self) -> bool {
        match self {
            Error::FileIO { source, .. } => source.kind() == io::ErrorKind::NotFound,
            _ => false,
        }
    }

    pub fn is_http_code(&self, http_code: u16) -> bool {
        match self {
            Error::BadAniListResponse { code, .. } if http_code == *code => true,
            Error::Reqwest { source, .. } => {
                let status = match source.status() {
                    Some(status) => status,
                    None => return false,
                };

                status.as_u16() == http_code
            }
            _ => false,
        }
    }
}

pub fn display_error(err: Error) {
    eprintln!("{}", err);

    if let Some(backtrace) = err.backtrace() {
        eprintln!("backtrace:\n{}", backtrace);
    }
}
<commit_msg>[err] Improve RunWithPrefetch error message<commit_after>use snafu::{Backtrace, ErrorCompat, Snafu};
use std::io;
use std::path;
use std::result;
use std::string;

pub type Result<T> = result::Result<T, Error>;

#[derive(Debug, Snafu)]
#[snafu(visibility(pub(crate)))]
pub enum Error {
    #[snafu(display("io error: {}", source))]
    IO {
        source: io::Error,
        backtrace: Backtrace,
    },

    #[snafu(display("file io error [{:?}]: {}", path, source))]
    FileIO {
        path: path::PathBuf,
        source: io::Error,
        backtrace: Backtrace,
    },

    #[snafu(display("dir entry error [{:?}]: {}", dir, source))]
    EntryIO {
        dir: path::PathBuf,
        source: io::Error,
        backtrace: Backtrace,
    },

    #[snafu(display("toml decode error [{:?}]: {}", path, source))]
    TomlDecode {
        path: path::PathBuf,
        source: toml::de::Error,
        backtrace: Backtrace,
    },

    #[snafu(display("toml encode error [{:?}]: {}", path, source))]
    TomlEncode {
        path: path::PathBuf,
        source: toml::ser::Error,
        backtrace: Backtrace,
    },

    #[snafu(display("message pack encode error [{:?}]: {}", path, source))]
    RMPEncode {
        path: path::PathBuf,
        source: rmp_serde::encode::Error,
        backtrace: Backtrace,
    },

    #[snafu(display("message pack decode error [{:?}]: {}", path, source))]
    RMPDecode {
        path: path::PathBuf,
        source: rmp_serde::decode::Error,
        backtrace: Backtrace,
    },

    #[snafu(display("base64 decode error: {}", source))]
    Base64Decode {
        source: base64::DecodeError,
        backtrace: Backtrace,
    },

    #[snafu(display("utf8 decode error: {}", source))]
    UTF8Decode {
        source: string::FromUtf8Error,
        backtrace: Backtrace,
    },

    #[snafu(display("json decode error: {}", source))]
    JsonDecode {
        source: serde_json::Error,
        backtrace: Backtrace,
    },

    #[snafu(display("failed to create regex matcher \"{}\": {}", matcher, source))]
    Regex {
        matcher: String,
        source: regex::Error,
        backtrace: Backtrace,
    },

    #[snafu(display("reqwest error: {}", source))]
    Reqwest {
        source: reqwest::Error,
        backtrace: Backtrace,
    },

    #[snafu(display("failed to parse episode title: {}", name))]
    NoEpisodeTitle { name: String },

    #[snafu(display("series should only have one episode, but found multiple\n\tshould only be: {}\n\tfound: {}", original, conflict))]
    MultipleEpsInSingleEpSeries { original: String, conflict: String },

    #[snafu(display("expected episode number for file: {}", name))]
    ExpectedEpNumber { name: String },

    #[snafu(display("failed to parse episode: {}", name))]
    NoEpMatches { name: String },

    #[snafu(display(
        "found different episode titles:\n\texpecting: {}\n\tfound: {}",
        expecting,
        found
    ))]
    MultipleTitles { expecting: String, found: String },

    #[snafu(display("no episodes found at path: {:?}", path))]
    NoEpisodes { path: path::PathBuf },

    #[snafu(display("episode {} not found for {}", episode, series))]
    EpisodeNotFound { episode: u32, series: String },

    #[snafu(display("failed to play episode {} of {}: {}", episode, series, source))]
    FailedToPlayEpisode {
        episode: u32,
        series: String,
        source: io::Error,
    },

    #[snafu(display("video player didn't exit normally while playing: {:?}", path))]
    AbnormalPlayerExit { path: path::PathBuf },

    #[snafu(display("no series with id {} found", id))]
    NoSeriesWithID { id: u32 },

    #[snafu(display("no series found with name similar to {}", name))]
    NoMatchingSeries { name: String },

    #[snafu(display("need existing series info to run in offline mode\nrun the program with --prefetch first when an internet connection is available"))]
    RunWithPrefetch {},

    #[snafu(display("received bad response from AniList (code {}): {}", code, message))]
    BadAniListResponse { code: u16, message: String },

    #[snafu(display("no data found for season {}", season))]
    NoSeason { season: usize },
}

impl Error {
    pub fn is_file_nonexistant(&self) -> bool {
        match self {
            Error::FileIO { source, .. } => source.kind() == io::ErrorKind::NotFound,
            _ => false,
        }
    }

    pub fn is_http_code(&self, http_code: u16) -> bool {
        match self {
            Error::BadAniListResponse { code, .. } if http_code == *code => true,
            Error::Reqwest { source, .. } => {
                let status = match source.status() {
                    Some(status) => status,
                    None => return false,
                };

                status.as_u16() == http_code
            }
            _ => false,
        }
    }
}

pub fn display_error(err: Error) {
    eprintln!("{}", err);

    if let Some(backtrace) = err.backtrace() {
        eprintln!("backtrace:\n{}", backtrace);
    }
}
<|endoftext|>


<commit_before>#![allow(dead_code)]
extern crate polydraw;

use polydraw::{Application, Renderer, Frame};
use polydraw::geom::point::Point;
use polydraw::geom::ring::Ring;
use polydraw::draw::RGB;

#[derive(Debug, PartialEq, Eq, Clone, Copy)]
struct Poly {
   color: RGB,
   start: usize,
   end: usize,
}

impl Poly {
   #[inline]
   pub fn new(color: RGB, start: usize, end: usize) -> Self {
      Poly {
         color: color,
         start: start,
         end: end,
      }
   }
}

#[derive(Debug, PartialEq, Eq, Clone, Copy)]
enum Edge {
   Inclined(usize),
   InclinedRev(usize),
   Horizontal(i64),
   HorizontalRev(i64),
   Vertical(i64),
   VerticalRev(i64),
}

impl Default for Edge {
   #[inline]
   fn default() -> Edge {
      Edge::Inclined(0)
   }
}

#[derive(Debug, PartialEq, Eq, Clone, Copy)]
struct InclinedEdge {
   p1: usize,
   p2: usize,
}

impl InclinedEdge {
   #[inline]
   pub fn new(p1: usize, p2: usize) -> Self {
      InclinedEdge {
         p1: p1,
         p2: p2,
      }
   }
}

impl Default for InclinedEdge {
   #[inline]
   fn default() -> InclinedEdge {
      InclinedEdge::new(0, 0)
   }
}

#[derive(Debug, PartialEq, Eq, Clone, Copy)]
struct PolyRef {
   src: usize,
   start: usize,
   end: usize,
}

impl PolyRef {
   #[inline]
   pub fn new(src: usize, start: usize, end: usize) -> Self {
      PolyRef {
         src: src,
         start: start,
         end: end,
      }
   }
}

impl Default for PolyRef {
   #[inline]
   fn default() -> PolyRef {
      PolyRef::new(0, 0, 0)
   }
}

struct PolySource {
   polys: Vec<Poly>,
   edges: Vec<Edge>,
   inclined: Vec<InclinedEdge>,
   points: Vec<Point>,
}

impl PolySource {
   fn new() -> Self {
      let polys = vec![
         // A
         Poly::new(RGB::new(18, 78, 230), 0, 3),
         // B
         Poly::new(RGB::new(47, 11, 206), 3, 6),
         // C
         Poly::new(RGB::new(170, 44, 206), 6, 9),
         // D
         Poly::new(RGB::new(243, 0, 149), 9, 12),
         // E
         Poly::new(RGB::new(170, 36, 14), 12, 15),
         // F
         Poly::new(RGB::new(219, 65, 18), 15, 18),
         // G
         Poly::new(RGB::new(254, 185, 21), 18, 21),
         // H
         Poly::new(RGB::new(244, 239, 114), 21, 24),
         // I
         Poly::new(RGB::new(109, 233, 158), 24, 27),
         // J
         Poly::new(RGB::new(66, 222, 241), 27, 30),
      ];

      let edges = vec![
         // 0: A
         Edge::Vertical(0),
         Edge::InclinedRev(0),
         Edge::InclinedRev(1),

         // 1: B
         Edge::Inclined(1),
         Edge::InclinedRev(2),
         Edge::InclinedRev(3),

         // 2: C
         Edge::Inclined(3),
         Edge::InclinedRev(4),
         Edge::HorizontalRev(0),

         // 3: D
         Edge::Inclined(4),
         Edge::Inclined(5),
         Edge::InclinedRev(6),

         // 4: E
         Edge::Inclined(6),
         Edge::Inclined(7),
         Edge::VerticalRev(10),

         // 5: F
         Edge::Inclined(2),
         Edge::Inclined(8),
         Edge::InclinedRev(9),

         // 6: G
         Edge::Inclined(9),
         Edge::InclinedRev(10),
         Edge::InclinedRev(5),

         // 7: H
         Edge::Inclined(0),
         Edge::InclinedRev(11),
         Edge::InclinedRev(8),

         // 8: I
         Edge::Inclined(10),
         Edge::Inclined(12),
         Edge::InclinedRev(7),

         // 9: J
         Edge::Inclined(11),
         Edge::Horizontal(10),
         Edge::InclinedRev(12),
      ];

      let inclined = vec![
         InclinedEdge::new(2, 1),  // 0
         InclinedEdge::new(0, 2),  // 1
         InclinedEdge::new(3, 2),  // 2
         InclinedEdge::new(0, 3),  // 3
         InclinedEdge::new(4, 3),  // 4
         InclinedEdge::new(3, 5),  // 5
         InclinedEdge::new(4, 5),  // 6
         InclinedEdge::new(5, 6),  // 7
         InclinedEdge::new(2, 7),  // 8
         InclinedEdge::new(3, 7),  // 9
         InclinedEdge::new(5, 7),  // 10
         InclinedEdge::new(7, 1),  // 11
         InclinedEdge::new(7, 6),  // 12
      ];

      let points = vec![
         Point::new(0, 0),   // 0
         Point::new(0, 10),  // 1
         Point::new(2, 5),   // 2
         Point::new(3, 1),   // 3
         Point::new(10, 0),  // 4
         Point::new(8, 5),   // 5
         Point::new(10, 10), // 6
         Point::new(7, 9),   // 7
      ];

      PolySource {
         polys: polys,
         edges: edges,
         inclined: inclined,
         points: points,
      }
   }
}

struct TriangleRenderer {
   src: PolySource,

   upper: Ring<Edge>,
   upper_ref: Ring<PolyRef>,

   lower: Ring<Edge>,
   lower_ref: Ring<PolyRef>,

   points: Ring<Point>,
}

impl TriangleRenderer {
   fn new() -> Self {
      TriangleRenderer {
         src: PolySource::new(),

         upper: Ring::new(262144),
         upper_ref: Ring::new(65536),

         lower: Ring::new(262144),
         lower_ref: Ring::new(65536),

         points: Ring::new(262144),
      }
   }
}

impl Renderer for TriangleRenderer {
   fn render(&mut self, frame: &mut Frame) {
      frame.clear();
   }
}

fn main() {
   let mut renderer = TriangleRenderer::new();

   Application::new()
      .renderer(&mut renderer)
      .title("Triangle3")
      .run();
}
<commit_msg>Min Y calculation for the source polys<commit_after>#![allow(dead_code)]
extern crate polydraw;

use std::i64;
use std::cmp::min;

use polydraw::{Application, Renderer, Frame};
use polydraw::geom::point::Point;
use polydraw::geom::ring::Ring;
use polydraw::draw::RGB;

#[derive(Debug, PartialEq, Eq, Clone, Copy)]
struct Poly {
   color: RGB,
   start: usize,
   end: usize,
}

impl Poly {
   #[inline]
   pub fn new(color: RGB, start: usize, end: usize) -> Self {
      Poly {
         color: color,
         start: start,
         end: end,
      }
   }
}

#[derive(Debug, PartialEq, Eq, Clone, Copy)]
enum Edge {
   Inclined(usize),
   InclinedRev(usize),
   Horizontal(i64),
   HorizontalRev(i64),
   Vertical(i64),
   VerticalRev(i64),
}

impl Default for Edge {
   #[inline]
   fn default() -> Edge {
      Edge::Inclined(0)
   }
}

#[derive(Debug, PartialEq, Eq, Clone, Copy)]
struct InclinedEdge {
   p1: usize,
   p2: usize,
}

impl InclinedEdge {
   #[inline]
   pub fn new(p1: usize, p2: usize) -> Self {
      InclinedEdge {
         p1: p1,
         p2: p2,
      }
   }
}

impl Default for InclinedEdge {
   #[inline]
   fn default() -> InclinedEdge {
      InclinedEdge::new(0, 0)
   }
}

#[derive(Debug, PartialEq, Eq, Clone, Copy)]
struct PolyRef {
   src: usize,
   start: usize,
   end: usize,
}

impl PolyRef {
   #[inline]
   pub fn new(src: usize, start: usize, end: usize) -> Self {
      PolyRef {
         src: src,
         start: start,
         end: end,
      }
   }
}

impl Default for PolyRef {
   #[inline]
   fn default() -> PolyRef {
      PolyRef::new(0, 0, 0)
   }
}

#[derive(Debug, PartialEq, Eq, Clone, Copy)]
struct InclinedEdgeRef {
   p1: usize,
   p2: usize,
   src_p1: usize,
   src_p2: usize,
}

impl InclinedEdgeRef {
   #[inline]
   pub fn new(p1: usize, p2: usize, src_p1: usize, src_p2: usize) -> Self {
      InclinedEdgeRef {
         p1: p1,
         p2: p2,
         src_p1: src_p1,
         src_p2: src_p2,
      }
   }
}

impl Default for InclinedEdgeRef {
   #[inline]
   fn default() -> InclinedEdgeRef {
      InclinedEdgeRef::new(0, 0, 0, 0)
   }
}

#[derive(Debug, PartialEq, Eq, Clone, Copy)]
struct PolyMinYRef {
   poly: usize,
   min_y: i64,
}

struct PolySource {
   polys: Vec<Poly>,
   edges: Vec<Edge>,
   inclined: Vec<InclinedEdge>,
   points: Vec<Point>,
}

impl PolySource {
   fn new() -> Self {
      let polys = vec![
         // A
         Poly::new(RGB::new(18, 78, 230), 0, 3),
         // B
         Poly::new(RGB::new(47, 11, 206), 3, 6),
         // C
         Poly::new(RGB::new(170, 44, 206), 6, 9),
         // D
         Poly::new(RGB::new(243, 0, 149), 9, 12),
         // E
         Poly::new(RGB::new(170, 36, 14), 12, 15),
         // F
         Poly::new(RGB::new(219, 65, 18), 15, 18),
         // G
         Poly::new(RGB::new(254, 185, 21), 18, 21),
         // H
         Poly::new(RGB::new(244, 239, 114), 21, 24),
         // I
         Poly::new(RGB::new(109, 233, 158), 24, 27),
         // J
         Poly::new(RGB::new(66, 222, 241), 27, 30),
      ];

      let edges = vec![
         // 0: A
         Edge::Vertical(0),
         Edge::InclinedRev(0),
         Edge::InclinedRev(1),

         // 1: B
         Edge::Inclined(1),
         Edge::InclinedRev(2),
         Edge::InclinedRev(3),

         // 2: C
         Edge::Inclined(3),
         Edge::InclinedRev(4),
         Edge::HorizontalRev(0),

         // 3: D
         Edge::Inclined(4),
         Edge::Inclined(5),
         Edge::InclinedRev(6),

         // 4: E
         Edge::Inclined(6),
         Edge::Inclined(7),
         Edge::VerticalRev(10),

         // 5: F
         Edge::Inclined(2),
         Edge::Inclined(8),
         Edge::InclinedRev(9),

         // 6: G
         Edge::Inclined(9),
         Edge::InclinedRev(10),
         Edge::InclinedRev(5),

         // 7: H
         Edge::Inclined(0),
         Edge::InclinedRev(11),
         Edge::InclinedRev(8),

         // 8: I
         Edge::Inclined(10),
         Edge::Inclined(12),
         Edge::InclinedRev(7),

         // 9: J
         Edge::Inclined(11),
         Edge::Horizontal(10),
         Edge::InclinedRev(12),
      ];

      let inclined = vec![
         InclinedEdge::new(2, 1),  // 0
         InclinedEdge::new(0, 2),  // 1
         InclinedEdge::new(3, 2),  // 2
         InclinedEdge::new(0, 3),  // 3
         InclinedEdge::new(4, 3),  // 4
         InclinedEdge::new(3, 5),  // 5
         InclinedEdge::new(4, 5),  // 6
         InclinedEdge::new(5, 6),  // 7
         InclinedEdge::new(2, 7),  // 8
         InclinedEdge::new(3, 7),  // 9
         InclinedEdge::new(5, 7),  // 10
         InclinedEdge::new(7, 1),  // 11
         InclinedEdge::new(7, 6),  // 12
      ];

      let points = vec![
         Point::new(0, 0),   // 0
         Point::new(0, 10),  // 1
         Point::new(2, 5),   // 2
         Point::new(3, 1),   // 3
         Point::new(10, 0),  // 4
         Point::new(8, 5),   // 5
         Point::new(10, 10), // 6
         Point::new(7, 9),   // 7
      ];

      PolySource {
         polys: polys,
         edges: edges,
         inclined: inclined,
         points: points,
      }
   }

   pub fn polys_min_y(&self) -> Vec<PolyMinYRef> {
      let mut v = Vec::new();

      for (poly_index, poly) in self.polys.iter().enumerate() {
         let mut min_y = i64::MAX;

         for edge_index in poly.start..poly.end {
            let y = match self.edges[edge_index] {
               Edge::Inclined(i) => {
                  self.inclined_min_y(i)
               },
               Edge::InclinedRev(i) => {
                  self.inclined_min_y(i)
               },
               Edge::Horizontal(y) => {
                  y
               },
               Edge::HorizontalRev(y) => {
                  y
               },
               _ => {
                  continue;
               }
            };

            if y < min_y {
               min_y = y;
            }
         }

         v.push(PolyMinYRef {
            poly: poly_index,
            min_y: min_y,
         });
      }

      v
   }

   #[inline]
   fn inclined_min_y(&self, i: usize) -> i64 {
      let inclined = self.inclined[i];
      min(
         self.points[inclined.p1].y,
         self.points[inclined.p2].y
      )
   }
}

struct TriangleRenderer {
   src: PolySource,
   src_min_y: Vec<PolyMinYRef>,

   upper_polys: Ring<PolyRef>,
   upper_edges: Ring<Edge>,

   lower_polys: Ring<PolyRef>,
   lower_edges: Ring<Edge>,

   points: Ring<Point>,
   inclined: Ring<InclinedEdgeRef>,
}

impl TriangleRenderer {
   fn new() -> Self {
      let src = PolySource::new();
      let src_min_y = src.polys_min_y();

      TriangleRenderer {
         src: src,
         src_min_y: src_min_y,

         upper_polys: Ring::new(65536),
         upper_edges: Ring::new(262144),

         lower_polys: Ring::new(65536),
         lower_edges: Ring::new(262144),

         points: Ring::new(262144),
         inclined: Ring::new(262144),
      }
   }

   pub fn clear(&mut self) {
      self.upper_polys.clear();
      self.upper_edges.clear();

      self.lower_polys.clear();
      self.lower_edges.clear();

      self.points.clear();
      self.inclined.clear();
   }
}

impl Renderer for TriangleRenderer {
   fn render(&mut self, frame: &mut Frame) {
      frame.clear();

      self.clear();
   }
}

fn main() {
   let mut renderer = TriangleRenderer::new();

   Application::new()
      .renderer(&mut renderer)
      .title("Triangle3")
      .run();
}
<|endoftext|>


<commit_before>use std::env;
use std::process::{Command, Output};
use git2::Repository;
use errors::*;

pub trait Config {
  fn get(&self, name: &str) -> Result<String>;
  fn set(&self, name: &str, value: &str) -> Result<()>;
}

pub struct GitConfig {
  namespace: String,
  repo: Repository,
}

impl GitConfig {
  pub fn new(namespace: &str) -> Result<GitConfig> {
    let path = try!(env::current_dir().chain_err(|| ""));
    let repo = try!(Repository::discover(path).chain_err(|| ""));

    Ok(GitConfig {
      namespace: namespace.into(),
      repo: repo,
    })
  }

  pub fn auto_include(&self) {
    let filename = format!(".{}", self.namespace);
    let include_path = format!("../{}", filename);

    // Make sure .git-together exists
    if let Some(path) = self.repo.workdir() {
      let mut path_buf = path.to_path_buf();
      path_buf.push(&filename);
      if !path_buf.exists() {
        return;
      }
    } else {
      return;
    }

    // Make sure we're not already including .git-together
    if let Ok(output) = self.output(&["--local", "--get-all", "include.path"]) {
      let stdout = String::from_utf8_lossy(&output.stdout);
      if stdout.split('\n').any(|x| x == include_path) {
        return;
      }
    }

    let _ = self.output(&["--add", "include.path", &include_path]);
  }

  fn output(&self, args: &[&str]) -> Result<Output> {
    let output = try!(Command::new("git")
      .arg("config")
      .args(args)
      .output());

    if output.status.success() {
      Ok(output)
    } else {
      Err(ErrorKind::GitConfig(output).into())
    }
  }
}

impl Config for GitConfig {
  fn get(&self, name: &str) -> Result<String> {
    let name = format!("{}.{}", self.namespace, name);
    let output = try!(self.output(&[&name]));
    let stdout = String::from_utf8_lossy(&output.stdout);

    Ok(stdout.trim_right().into())
  }

  fn set(&self, name: &str, value: &str) -> Result<()> {
    let name = format!("{}.{}", self.namespace, name);

    self.output(&[&name, value]).and(Ok(()))
  }
}
<commit_msg>use git2 in Config::get<commit_after>use std::env;
use std::process::{Command, Output};
use git2;
use errors::*;

pub trait Config {
  fn get(&self, name: &str) -> Result<String>;
  fn set(&self, name: &str, value: &str) -> Result<()>;
}

pub struct GitConfig {
  namespace: String,
  repo: git2::Repository,
  config: git2::Config,
}

impl GitConfig {
  pub fn new(namespace: &str) -> Result<GitConfig> {
    let path = try!(env::current_dir().chain_err(|| ""));
    let repo = try!(git2::Repository::discover(path).chain_err(|| ""));
    let config = try!(repo.config().chain_err(|| ""));

    Ok(GitConfig {
      namespace: namespace.into(),
      repo: repo,
      config: config,
    })
  }

  pub fn auto_include(&self) {
    let filename = format!(".{}", self.namespace);
    let include_path = format!("../{}", filename);

    // Make sure .git-together exists
    if let Some(path) = self.repo.workdir() {
      let mut path_buf = path.to_path_buf();
      path_buf.push(&filename);
      if !path_buf.exists() {
        return;
      }
    } else {
      return;
    }

    // Make sure we're not already including .git-together
    if let Ok(output) = self.output(&["--local", "--get-all", "include.path"]) {
      let stdout = String::from_utf8_lossy(&output.stdout);
      if stdout.split('\n').any(|x| x == include_path) {
        return;
      }
    }

    let _ = self.output(&["--add", "include.path", &include_path]);
  }

  fn output(&self, args: &[&str]) -> Result<Output> {
    let output = try!(Command::new("git")
      .arg("config")
      .args(args)
      .output());

    if output.status.success() {
      Ok(output)
    } else {
      Err(ErrorKind::GitConfig(output).into())
    }
  }
}

impl Config for GitConfig {
  fn get(&self, name: &str) -> Result<String> {
    let name = format!("{}.{}", self.namespace, name);
    self.config.get_string(&name).chain_err(|| "")
  }

  fn set(&self, name: &str, value: &str) -> Result<()> {
    let name = format!("{}.{}", self.namespace, name);

    self.output(&[&name, value]).and(Ok(()))
  }
}
<|endoftext|>