<commit_before>//! Handles CPU startup (segment init, etc) that's common to all CPUs.
//! Chip specific init (like the interrupt table) should be in the relevant <chip> module.

// ****************************************************************************
//
// Imports
//
// ****************************************************************************

use r0;
use cortex_m;
use alloc_cortex_m;

use board;
// use cpu::{systick, uart};

extern "C" {
    // These symbols come from the linker script
    static mut _data_start_flash: usize;
    static mut _data_start: usize;
    static mut _data_end: usize;
    static mut _bss_start: usize;
    static mut _bss_end: usize;
    static mut _heap_start: usize;
    static mut _heap_end: usize;
    // This is defined by your application
    fn main();
    fn _stack_top();
}

// ****************************************************************************
//
// Public Types
//
// ****************************************************************************

// None

// ****************************************************************************
//
// Public Data
//
// ****************************************************************************

/// Contains exception handlers, interrupt service routine vectors and a magic value
/// that marks the start of the stack.
#[link_section=".nvic_table"]
#[no_mangle]
pub static ISR_VECTORS: [Option<cortex_m::Handler>; 48] = [// Stack pointer
                                                           Some(_stack_top),
                                                           // Reset
                                                           Some(reset_vector),
                                                           // NMI
                                                           Some(isr_nmi),
                                                           // Hard Fault
                                                           Some(isr_hardfault),
                                                           // Unused
                                                           None,
                                                           // CM0+ Bus Fault
                                                           Some(isr_busfault),
                                                           // CM0+ Usage Fault
                                                           Some(isr_usagefault),
                                                           // Unused
                                                           None,
                                                           // Unused
                                                           None,
                                                           // Unused
                                                           None,
                                                           // Unused
                                                           None,
                                                           // Supervisor call
                                                           Some(isr_svcall),
                                                           // Debug monitor
                                                           Some(isr_debugmon),
                                                           // Unused
                                                           None,
                                                           // Pendable service request
                                                           Some(isr_pendsv),
                                                           // SysTick
                                                           Some(isr_systick),
                                                           // DMA Channel 0 transfer complete
                                                           None,
                                                           // DMA Channel 0 transfer complete
                                                           None,
                                                           // DMA Channel 0 transfer complete
                                                           None,
                                                           // DMA Channel 0 transfer complete
                                                           None,
                                                           // MCM
                                                           None,
                                                           // Flash
                                                           None,
                                                           // PMC
                                                           None,
                                                           // LLWU
                                                           None,
                                                           // I2C0
                                                           None,
                                                           // Reserved
                                                           None,
                                                           // SPI0
                                                           None,
                                                           // SPI1
                                                           None,
                                                           // SCI0
                                                           None,
                                                           // SCI1
                                                           None,
                                                           // SCI2
                                                           None,
                                                           // ADC0
                                                           None,
                                                           // ACMP0
                                                           None,
                                                           // FTM0
                                                           None,
                                                           // FTM1
                                                           None,
                                                           // FTM2
                                                           None,
                                                           // RTC
                                                           None,
                                                           // ACMP1
                                                           None,
                                                           // PIT_CH0
                                                           None,
                                                           // PIT_CH1
                                                           None,
                                                           // KBI0
                                                           None,
                                                           // KBI1
                                                           None,
                                                           // Reserved
                                                           None,
                                                           // ICS
                                                           None,
                                                           // Watchdog
                                                           None,
                                                           // Reserved
                                                           None,
                                                           // Reserved
                                                           None,
                                                           // Reserved
                                                           None];

// ****************************************************************************
//
// Private Types
//
// ****************************************************************************

/// Kind of exception
#[derive(Debug)]
enum Exception {
    /// i.e. currently not servicing an exception
    ThreadMode,
    /// Non-maskable interrupt.
    Nmi,
    /// All class of fault.
    HardFault,
    /// Memory management.
    MemoryManagementFault,
    /// Pre-fetch fault, memory access fault.
    BusFault,
    /// Undefined instruction or illegal state.
    UsageFault,
    /// System service call via SWI instruction
    SVCall,
    /// Pendable request for system service
    PendSV,
    /// System tick timer
    Systick,
    /// An interrupt
    Interrupt(u8),
    // Unreachable variant
    #[doc(hidden)]
    Reserved,
}

// ****************************************************************************
//
// Private Data
//
// ****************************************************************************

// None

// ****************************************************************************
//
// Public Functions
//
// ****************************************************************************

/// Performs what you might otherwise call 'C Startup'.
/// This routine is specified at the reset vector in the ISR vector table.
///
/// Copies global .data init from flash to SRAM and then
/// zeros the bss segment.
#[no_mangle]
pub unsafe extern "C" fn reset_vector() {
    let data_start_flash: *mut usize = &mut _data_start_flash;
    let data_start: *mut usize = &mut _data_start;
    let data_end: *mut usize = &mut _data_end;
    let bss_start: *mut usize = &mut _bss_start;
    let bss_end: *mut usize = &mut _bss_end;
    let heap_start: *mut usize = &mut _heap_start;
    let heap_end: *mut usize = &mut _heap_end;

    r0::init_data(data_start, data_end, data_start_flash);
    r0::zero_bss(bss_start, bss_end);

    alloc_cortex_m::init(heap_start, heap_end);

    // Freescale app does
    // __init_registers
    // __init_hardware
    //   - Sets SCB->VTOR
    // __init_user
    //

    // Need to perform SIM init
    // Then ICS init

    board::init();
    main();
    loop {}
}

// ****************************************************************************
//
// Private Functions
//
// ****************************************************************************

impl Exception {
    /// Returns the exception that's currently being serviced
    pub fn current() -> Exception {
        match cortex_m::peripheral::scb().icsr.read() as u8 {
            0 => Exception::ThreadMode,
            2 => Exception::Nmi,
            3 => Exception::HardFault,
            4 => Exception::MemoryManagementFault,
            5 => Exception::BusFault,
            6 => Exception::UsageFault,
            11 => Exception::SVCall,
            14 => Exception::PendSV,
            15 => Exception::Systick,
            n if n >= 16 => Exception::Interrupt(n - 16),
            _ => Exception::Reserved,
        }
    }
}

/// A HardFault is an exception that occurs because of an error during
/// exception processing, or because an exception cannot be managed by any
/// other exception mechanism. HardFaults have a fixed priority of -1, meaning
/// they have higher priority than any exception with configurable priority.
///
/// This function came from japaric's excellent F3 crate.
#[naked]
pub unsafe extern "C" fn isr_hardfault() {
    use core::intrinsics;

    // NOTE need asm!, #[naked] and unreachable() to avoid modifying the stack
    // pointer (MSP)
    asm!("mrs r0, MSP
          ldr r1, [r0, #20]
          bl isr_hardfault_rs" :::: "volatile");

    intrinsics::unreachable();
}

/// Once the StacFrame has been gathered by `isr_hardfault`, we can process the
/// HardFault using a normal Rust function. It's `no_mangle` because we
/// refer to it from raw assembler in `isr_hardfault`.
#[no_mangle]
pub unsafe extern "C" fn isr_hardfault_rs(_sf: &cortex_m::StackFrame) -> ! {
    // Need ITM support for this to work
    // iprintln!("EXCEPTION {:?} @ PC=0x{:08x}", Exception::current(), sf.pc);

    // We can see this in the debugger
    let _exc = Exception::current();

    bkpt!();

    loop {}
}

/// A Non Maskable Interrupt (NMI) can be signalled by a peripheral or
/// triggered by software. This is the highest priority exception other than
/// reset. It is permanently enabled and has a fixed priority of -2. NMIs
/// cannot be:
/// * masked or prevented from activation by any other exception
/// * preempted by any exception other than Reset.
pub unsafe extern "C" fn isr_nmi() {
    // Do nothing
}

/// A MemManage fault is an exception that occurs because of a memory
/// protection related fault. The the fixed memory protection constraints
/// determines this fault, for both instruction and data memory transactions.
/// This fault is always used to abort instruction accesses to Execute Never
/// (XN) memory regions.
pub unsafe extern "C" fn isr_mmfault() {
    board::panic();
}

/// A BusFault is an exception that occurs because of a memory related fault
/// for an instruction or data memory transaction. This might be from an error
/// detected on a bus in the memory system.
pub unsafe extern "C" fn isr_busfault() {
    board::panic();
}

/// A UsageFault is an exception that occurs because of a fault related to instruction execution. This includes:
/// * an undefined instruction
/// * an illegal unaligned access
/// * invalid state on instruction execution
/// * an error on exception return.
/// The following can cause a UsageFault when the core is configured to report them:
/// * an unaligned address on word and halfword memory access
/// * division by zero.
pub unsafe extern "C" fn isr_usagefault() {
    board::panic();
}

/// A supervisor call (SVC) is an exception that is triggered by the SVC
/// instruction. In an OS environment, applications can use SVC instructions
/// to access OS kernel functions and device drivers.
pub unsafe extern "C" fn isr_svcall() {
    // Nothing
}

/// Debug monitor interrupt handler.
pub unsafe extern "C" fn isr_debugmon() {
    // Nothing
}

/// PendSV is an interrupt-driven request for system-level service. In an OS
/// environment, use PendSV for context switching when no other exception is
/// active.
pub unsafe extern "C" fn isr_pendsv() {
    // Nothing
}

/// A SysTick exception is an exception the system timer generates when it
/// reaches zero. Software can also generate a SysTick exception. In an OS
/// environment, the processor can use this exception as system tick.
pub unsafe extern "C" fn isr_systick() {
    // systick::isr();
}

/// A place-holder ISR used when we have nothing better to use.
pub unsafe extern "C" fn isr_empty_def() {
    board::panic();
}

// ****************************************************************************
//
// End Of File
//
// ****************************************************************************
<commit_msg>Blink on hardfault if no debugger.<commit_after>//! Handles CPU startup (segment init, etc) that's common to all CPUs.
//! Chip specific init (like the interrupt table) should be in the relevant <chip> module.

// ****************************************************************************
//
// Imports
//
// ****************************************************************************

use r0;
use cortex_m;
use alloc_cortex_m;

use board;
// use cpu::{systick, uart};

extern "C" {
    // These symbols come from the linker script
    static mut _data_start_flash: usize;
    static mut _data_start: usize;
    static mut _data_end: usize;
    static mut _bss_start: usize;
    static mut _bss_end: usize;
    static mut _heap_start: usize;
    static mut _heap_end: usize;
    // This is defined by your application
    fn main();
    fn _stack_top();
}

// ****************************************************************************
//
// Public Types
//
// ****************************************************************************

// None

// ****************************************************************************
//
// Public Data
//
// ****************************************************************************

/// Contains exception handlers, interrupt service routine vectors and a magic value
/// that marks the start of the stack.
#[link_section=".nvic_table"]
#[no_mangle]
pub static ISR_VECTORS: [Option<cortex_m::Handler>; 48] = [// Stack pointer
                                                           Some(_stack_top),
                                                           // Reset
                                                           Some(reset_vector),
                                                           // NMI
                                                           Some(isr_nmi),
                                                           // Hard Fault
                                                           Some(isr_hardfault),
                                                           // Unused
                                                           None,
                                                           // CM0+ Bus Fault
                                                           Some(isr_busfault),
                                                           // CM0+ Usage Fault
                                                           Some(isr_usagefault),
                                                           // Unused
                                                           None,
                                                           // Unused
                                                           None,
                                                           // Unused
                                                           None,
                                                           // Unused
                                                           None,
                                                           // Supervisor call
                                                           Some(isr_svcall),
                                                           // Debug monitor
                                                           Some(isr_debugmon),
                                                           // Unused
                                                           None,
                                                           // Pendable service request
                                                           Some(isr_pendsv),
                                                           // SysTick
                                                           Some(isr_systick),
                                                           // DMA Channel 0 transfer complete
                                                           None,
                                                           // DMA Channel 0 transfer complete
                                                           None,
                                                           // DMA Channel 0 transfer complete
                                                           None,
                                                           // DMA Channel 0 transfer complete
                                                           None,
                                                           // MCM
                                                           None,
                                                           // Flash
                                                           None,
                                                           // PMC
                                                           None,
                                                           // LLWU
                                                           None,
                                                           // I2C0
                                                           None,
                                                           // Reserved
                                                           None,
                                                           // SPI0
                                                           None,
                                                           // SPI1
                                                           None,
                                                           // SCI0
                                                           None,
                                                           // SCI1
                                                           None,
                                                           // SCI2
                                                           None,
                                                           // ADC0
                                                           None,
                                                           // ACMP0
                                                           None,
                                                           // FTM0
                                                           None,
                                                           // FTM1
                                                           None,
                                                           // FTM2
                                                           None,
                                                           // RTC
                                                           None,
                                                           // ACMP1
                                                           None,
                                                           // PIT_CH0
                                                           None,
                                                           // PIT_CH1
                                                           None,
                                                           // KBI0
                                                           None,
                                                           // KBI1
                                                           None,
                                                           // Reserved
                                                           None,
                                                           // ICS
                                                           None,
                                                           // Watchdog
                                                           None,
                                                           // Reserved
                                                           None,
                                                           // Reserved
                                                           None,
                                                           // Reserved
                                                           None];

// ****************************************************************************
//
// Private Types
//
// ****************************************************************************

/// Kind of exception
#[derive(Debug)]
enum Exception {
    /// i.e. currently not servicing an exception
    ThreadMode,
    /// Non-maskable interrupt.
    Nmi,
    /// All class of fault.
    HardFault,
    /// Memory management.
    MemoryManagementFault,
    /// Pre-fetch fault, memory access fault.
    BusFault,
    /// Undefined instruction or illegal state.
    UsageFault,
    /// System service call via SWI instruction
    SVCall,
    /// Pendable request for system service
    PendSV,
    /// System tick timer
    Systick,
    /// An interrupt
    Interrupt(u8),
    // Unreachable variant
    #[doc(hidden)]
    Reserved,
}

// ****************************************************************************
//
// Private Data
//
// ****************************************************************************

// None

// ****************************************************************************
//
// Public Functions
//
// ****************************************************************************

/// Performs what you might otherwise call 'C Startup'.
/// This routine is specified at the reset vector in the ISR vector table.
///
/// Copies global .data init from flash to SRAM and then
/// zeros the bss segment.
#[no_mangle]
pub unsafe extern "C" fn reset_vector() {
    let data_start_flash: *mut usize = &mut _data_start_flash;
    let data_start: *mut usize = &mut _data_start;
    let data_end: *mut usize = &mut _data_end;
    let bss_start: *mut usize = &mut _bss_start;
    let bss_end: *mut usize = &mut _bss_end;
    let heap_start: *mut usize = &mut _heap_start;
    let heap_end: *mut usize = &mut _heap_end;

    r0::init_data(data_start, data_end, data_start_flash);
    r0::zero_bss(bss_start, bss_end);

    alloc_cortex_m::init(heap_start, heap_end);

    // Freescale app does
    // __init_registers
    // __init_hardware
    //   - Sets SCB->VTOR
    // __init_user
    //

    // Need to perform SIM init
    // Then ICS init

    board::init();
    main();
    loop {}
}

// ****************************************************************************
//
// Private Functions
//
// ****************************************************************************

impl Exception {
    /// Returns the exception that's currently being serviced
    pub fn current() -> Exception {
        match cortex_m::peripheral::scb().icsr.read() as u8 {
            0 => Exception::ThreadMode,
            2 => Exception::Nmi,
            3 => Exception::HardFault,
            4 => Exception::MemoryManagementFault,
            5 => Exception::BusFault,
            6 => Exception::UsageFault,
            11 => Exception::SVCall,
            14 => Exception::PendSV,
            15 => Exception::Systick,
            n if n >= 16 => Exception::Interrupt(n - 16),
            _ => Exception::Reserved,
        }
    }
}

/// A HardFault is an exception that occurs because of an error during
/// exception processing, or because an exception cannot be managed by any
/// other exception mechanism. HardFaults have a fixed priority of -1, meaning
/// they have higher priority than any exception with configurable priority.
///
/// This function came from japaric's excellent F3 crate.
#[naked]
pub unsafe extern "C" fn isr_hardfault() {
    use core::intrinsics;

    // NOTE need asm!, #[naked] and unreachable() to avoid modifying the stack
    // pointer (MSP)
    asm!("mrs r0, MSP
          ldr r1, [r0, #20]
          bl isr_hardfault_rs" :::: "volatile");

    intrinsics::unreachable();
}

/// Once the StacFrame has been gathered by `isr_hardfault`, we can process the
/// HardFault using a normal Rust function. It's `no_mangle` because we
/// refer to it from raw assembler in `isr_hardfault`.
#[no_mangle]
pub unsafe extern "C" fn isr_hardfault_rs(_sf: &cortex_m::StackFrame) -> ! {
    // Need ITM support for this to work
    // iprintln!("EXCEPTION {:?} @ PC=0x{:08x}", Exception::current(), sf.pc);

    // We can see this in the debugger
    let _exc = Exception::current();

    bkpt!();

    board::panic();
}

/// A Non Maskable Interrupt (NMI) can be signalled by a peripheral or
/// triggered by software. This is the highest priority exception other than
/// reset. It is permanently enabled and has a fixed priority of -2. NMIs
/// cannot be:
/// * masked or prevented from activation by any other exception
/// * preempted by any exception other than Reset.
pub unsafe extern "C" fn isr_nmi() {
    // Do nothing
}

/// A MemManage fault is an exception that occurs because of a memory
/// protection related fault. The the fixed memory protection constraints
/// determines this fault, for both instruction and data memory transactions.
/// This fault is always used to abort instruction accesses to Execute Never
/// (XN) memory regions.
pub unsafe extern "C" fn isr_mmfault() {
    board::panic();
}

/// A BusFault is an exception that occurs because of a memory related fault
/// for an instruction or data memory transaction. This might be from an error
/// detected on a bus in the memory system.
pub unsafe extern "C" fn isr_busfault() {
    board::panic();
}

/// A UsageFault is an exception that occurs because of a fault related to instruction execution. This includes:
/// * an undefined instruction
/// * an illegal unaligned access
/// * invalid state on instruction execution
/// * an error on exception return.
/// The following can cause a UsageFault when the core is configured to report them:
/// * an unaligned address on word and halfword memory access
/// * division by zero.
pub unsafe extern "C" fn isr_usagefault() {
    board::panic();
}

/// A supervisor call (SVC) is an exception that is triggered by the SVC
/// instruction. In an OS environment, applications can use SVC instructions
/// to access OS kernel functions and device drivers.
pub unsafe extern "C" fn isr_svcall() {
    // Nothing
}

/// Debug monitor interrupt handler.
pub unsafe extern "C" fn isr_debugmon() {
    // Nothing
}

/// PendSV is an interrupt-driven request for system-level service. In an OS
/// environment, use PendSV for context switching when no other exception is
/// active.
pub unsafe extern "C" fn isr_pendsv() {
    // Nothing
}

/// A SysTick exception is an exception the system timer generates when it
/// reaches zero. Software can also generate a SysTick exception. In an OS
/// environment, the processor can use this exception as system tick.
pub unsafe extern "C" fn isr_systick() {
    // systick::isr();
}

/// A place-holder ISR used when we have nothing better to use.
pub unsafe extern "C" fn isr_empty_def() {
    board::panic();
}

// ****************************************************************************
//
// End Of File
//
// ****************************************************************************
<|endoftext|>


<commit_before>//! The following is an adaptation of the "pa_devs.c" official PortAudio C example.

extern crate portaudio;
use portaudio as pa;

const INTERLEAVED: bool = true;
const LATENCY: pa::Time = 0.0; // Ignored by PortAudio::is_*_format_supported.
const STANDARD_SAMPLE_RATES: [f64; 13] = [
    8000.0, 9600.0, 11025.0, 12000.0, 16000.0, 22050.0, 24000.0, 32000.0,
    44100.0, 48000.0, 88200.0, 96000.0, 192000.0,
];

fn main() {
    run().unwrap()
}

fn run() -> Result<(), pa::Error> {

    let pa = try!(pa::PortAudio::new());

    let num_devices = try!(pa.device_count());
    println!("Number of devices = {}", num_devices);

    for device in try!(pa.devices()) {
        let (idx, info) = try!(device);
        println!("--------------------------------------- {:?}", idx);
        println!("{:#?}", &info);

        let in_channels = info.max_input_channels;
        let input_params = pa::StreamParameters::<i16>::new(idx, in_channels, INTERLEAVED, LATENCY);
        let out_channels = info.max_output_channels;
        let output_params = pa::StreamParameters::<i16>::new(idx, out_channels, INTERLEAVED, LATENCY);

        println!("Supported standard sample rates for half-duplex 16-bit {} channel input:", in_channels);
        for &sample_rate in &STANDARD_SAMPLE_RATES {
            if pa.is_input_format_supported(input_params, sample_rate).is_ok() {
                println!("\t{}hz", sample_rate);
            }
        }

        println!("Supported standard sample rates for half-duplex 16-bit {} channel output:", out_channels);
        for &sample_rate in &STANDARD_SAMPLE_RATES {
            if pa.is_output_format_supported(output_params, sample_rate).is_ok() {
                println!("\t{}hz", sample_rate);
            }
        }

        println!("Supported standard sample rates for full-duplex 16-bit {} channel input, {} channel output:",
                 in_channels, out_channels);
        for &sample_rate in &STANDARD_SAMPLE_RATES {
            if pa.is_duplex_format_supported(input_params, output_params, sample_rate).is_ok() {
                println!("\t{}hz", sample_rate);
            }
        }
    }

    Ok(())
}
<commit_msg>Print default devices in dvices.rs example<commit_after>//! The following is an adaptation of the "pa_devs.c" official PortAudio C example.

extern crate portaudio;
use portaudio as pa;

const INTERLEAVED: bool = true;
const LATENCY: pa::Time = 0.0; // Ignored by PortAudio::is_*_format_supported.
const STANDARD_SAMPLE_RATES: [f64; 13] = [
    8000.0, 9600.0, 11025.0, 12000.0, 16000.0, 22050.0, 24000.0, 32000.0,
    44100.0, 48000.0, 88200.0, 96000.0, 192000.0,
];

fn main() {
    run().unwrap()
}

fn run() -> Result<(), pa::Error> {

    let pa = try!(pa::PortAudio::new());

    let num_devices = try!(pa.device_count());
    println!("Number of devices = {}", num_devices);

    println!("Defualt input device: {:?}", pa.default_input_device());
    println!("Defualt output device: {:?}", pa.default_output_device());

    println!("All devices:");
    for device in try!(pa.devices()) {
        let (idx, info) = try!(device);
        println!("--------------------------------------- {:?}", idx);
        println!("{:#?}", &info);

        let in_channels = info.max_input_channels;
        let input_params = pa::StreamParameters::<i16>::new(idx, in_channels, INTERLEAVED, LATENCY);
        let out_channels = info.max_output_channels;
        let output_params = pa::StreamParameters::<i16>::new(idx, out_channels, INTERLEAVED, LATENCY);

        println!("Supported standard sample rates for half-duplex 16-bit {} channel input:", in_channels);
        for &sample_rate in &STANDARD_SAMPLE_RATES {
            if pa.is_input_format_supported(input_params, sample_rate).is_ok() {
                println!("\t{}hz", sample_rate);
            }
        }

        println!("Supported standard sample rates for half-duplex 16-bit {} channel output:", out_channels);
        for &sample_rate in &STANDARD_SAMPLE_RATES {
            if pa.is_output_format_supported(output_params, sample_rate).is_ok() {
                println!("\t{}hz", sample_rate);
            }
        }

        println!("Supported standard sample rates for full-duplex 16-bit {} channel input, {} channel output:",
                 in_channels, out_channels);
        for &sample_rate in &STANDARD_SAMPLE_RATES {
            if pa.is_duplex_format_supported(input_params, output_params, sample_rate).is_ok() {
                println!("\t{}hz", sample_rate);
            }
        }
    }

    Ok(())
}
<|endoftext|>


<commit_before>use common::util::*;

#[test]
fn test_default() {
    //CmdResult.stdout_only(...) trims trailing newlines
    assert_eq!("hi\n", new_ucmd!().arg("hi").succeeds().no_stderr().stdout);
}

#[test]
fn test_no_trailing_newline() {
    //CmdResult.stdout_only(...) trims trailing newlines
    assert_eq!("hi", new_ucmd!().arg("-n").arg("hi").succeeds().no_stderr().stdout);
}

#[test]
fn test_escape_alert() {
    new_ucmd!().args(&["-e", "\\a"]).succeeds().stdout_only("\x07\n");
}

#[test]
fn test_escape_backslash() {
    new_ucmd!().args(&["-e", "\\\\"]).succeeds().stdout_only("\\\n");
}

#[test]
fn test_escape_backspace() {
    new_ucmd!().args(&["-e", "\\b"]).succeeds().stdout_only("\x08\n");
}

#[test]
fn test_escape_carriage_return() {
    new_ucmd!().args(&["-e", "\\r"]).succeeds().stdout_only("\r\n");
}

#[test]
fn test_escape_escape() {
    new_ucmd!().args(&["-e", "\\e"]).succeeds().stdout_only("\x1B\n");
}

#[test]
fn test_escape_form_feed() {
    new_ucmd!().args(&["-e", "\\f"]).succeeds().stdout_only("\x0C\n");
}

#[test]
fn test_escape_hex() {
    new_ucmd!().args(&["-e", "\\x41"]).succeeds().stdout_only("A\n");
}

#[test]
fn test_escape_short_hex() {
    new_ucmd!().args(&["-e", "foo\\xa bar"]).succeeds().stdout_only("foo\n bar");
}

#[test]
fn test_escape_no_hex() {
    new_ucmd!().args(&["-e", "foo\\x bar"]).succeeds().stdout_only("foo\\x bar");
}

#[test]
fn test_escape_one_slash() {
    new_ucmd!().args(&["-e", "foo\\ bar"]).succeeds().stdout_only("foo\\ bar");
}

#[test]
fn test_escape_one_slash_multi() {
    new_ucmd!().args(&["-e", "foo\\", "bar"]).succeeds().stdout_only("foo\\ bar");
}

#[test]
fn test_escape_newline() {
    new_ucmd!().args(&["-e", "\\na"]).succeeds().stdout_only("\na\n");
}

#[test]
fn test_escape_no_further_output() {
    new_ucmd!().args(&["-e", "a\\cb", "c"]).succeeds().stdout_only("a\n");
}

#[test]
fn test_escape_octal() {
    new_ucmd!().args(&["-e", "\\0100"]).succeeds().stdout_only("@\n");
}

#[test]
fn test_escape_short_octal() {
    new_ucmd!().args(&["-e", "foo\\040bar"]).succeeds().stdout_only("foo bar");
}

#[test]
fn test_escape_no_octal() {
    new_ucmd!().args(&["-e", "foo\\0 bar"]).succeeds().stdout_only("foo\\0 bar");
}

#[test]
fn test_escape_tab() {
    new_ucmd!().args(&["-e", "\\t"]).succeeds().stdout_only("\t\n");
}

#[test]
fn test_escape_vertical_tab() {
    new_ucmd!().args(&["-e", "\\v"]).succeeds().stdout_only("\x0B\n");
}

#[test]
fn test_disable_escapes() {
    let input_str = "\\a \\\\ \\b \\r \\e \\f \\x41 \\n a\\cb \\u0100 \\t \\v";
    new_ucmd!()
        .arg("-E")
        .arg(input_str)
        .succeeds()
        .stdout_only(format!("{}\n", input_str));
}
<commit_msg>echo: update tests to check for ending newlines<commit_after>use common::util::*;

#[test]
fn test_default() {
    //CmdResult.stdout_only(...) trims trailing newlines
    assert_eq!("hi\n", new_ucmd!().arg("hi").succeeds().no_stderr().stdout);
}

#[test]
fn test_no_trailing_newline() {
    //CmdResult.stdout_only(...) trims trailing newlines
    assert_eq!("hi", new_ucmd!().arg("-n").arg("hi").succeeds().no_stderr().stdout);
}

#[test]
fn test_escape_alert() {
    new_ucmd!().args(&["-e", "\\a"]).succeeds().stdout_only("\x07\n");
}

#[test]
fn test_escape_backslash() {
    new_ucmd!().args(&["-e", "\\\\"]).succeeds().stdout_only("\\\n");
}

#[test]
fn test_escape_backspace() {
    new_ucmd!().args(&["-e", "\\b"]).succeeds().stdout_only("\x08\n");
}

#[test]
fn test_escape_carriage_return() {
    new_ucmd!().args(&["-e", "\\r"]).succeeds().stdout_only("\r\n");
}

#[test]
fn test_escape_escape() {
    new_ucmd!().args(&["-e", "\\e"]).succeeds().stdout_only("\x1B\n");
}

#[test]
fn test_escape_form_feed() {
    new_ucmd!().args(&["-e", "\\f"]).succeeds().stdout_only("\x0C\n");
}

#[test]
fn test_escape_hex() {
    new_ucmd!().args(&["-e", "\\x41"]).succeeds().stdout_only("A\n");
}

#[test]
fn test_escape_short_hex() {
    new_ucmd!().args(&["-e", "foo\\xa bar"]).succeeds().stdout_only("foo\n bar\n");
}

#[test]
fn test_escape_no_hex() {
    new_ucmd!().args(&["-e", "foo\\x bar"]).succeeds().stdout_only("foo\\x bar\n");
}

#[test]
fn test_escape_one_slash() {
    new_ucmd!().args(&["-e", "foo\\ bar"]).succeeds().stdout_only("foo\\ bar\n");
}

#[test]
fn test_escape_one_slash_multi() {
    new_ucmd!().args(&["-e", "foo\\", "bar"]).succeeds().stdout_only("foo\\ bar\n");
}

#[test]
fn test_escape_newline() {
    new_ucmd!().args(&["-e", "\\na"]).succeeds().stdout_only("\na\n");
}

#[test]
fn test_escape_no_further_output() {
    new_ucmd!().args(&["-e", "a\\cb", "c"]).succeeds().stdout_only("a\n");
}

#[test]
fn test_escape_octal() {
    new_ucmd!().args(&["-e", "\\0100"]).succeeds().stdout_only("@\n");
}

#[test]
fn test_escape_short_octal() {
    new_ucmd!().args(&["-e", "foo\\040bar"]).succeeds().stdout_only("foo bar\n");
}

#[test]
fn test_escape_no_octal() {
    new_ucmd!().args(&["-e", "foo\\0 bar"]).succeeds().stdout_only("foo\\0 bar\n");
}

#[test]
fn test_escape_tab() {
    new_ucmd!().args(&["-e", "\\t"]).succeeds().stdout_only("\t\n");
}

#[test]
fn test_escape_vertical_tab() {
    new_ucmd!().args(&["-e", "\\v"]).succeeds().stdout_only("\x0B\n");
}

#[test]
fn test_disable_escapes() {
    let input_str = "\\a \\\\ \\b \\r \\e \\f \\x41 \\n a\\cb \\u0100 \\t \\v";
    new_ucmd!()
        .arg("-E")
        .arg(input_str)
        .succeeds()
        .stdout_only(format!("{}\n", input_str));
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate wlroots;

use std::time::Instant;

use wlroots::{Compositor, CompositorBuilder, InputManagerHandler, KeyEvent, KeyboardHandler,
              OutputBuilder, OutputBuilderResult, OutputHandler, OutputManagerHandler};
use wlroots::render::Texture;
use wlroots::types::{KeyboardHandle, OutputHandle};
use wlroots::wlroots_sys::wl_output_transform;
use wlroots::xkbcommon::xkb::keysyms;

const CAT_STRIDE: i32 = 128;
const CAT_WIDTH: i32 = 128;
const CAT_HEIGHT: i32 = 128;
const CAT_DATA: &'static [u8] = include_bytes!("cat.data");

/// Helper step by iterator, because `step_by` on `Range` is unstable.
struct StepRange(i32, i32, i32);
impl Iterator for StepRange {
    type Item = i32;
    fn next(&mut self) -> Option<i32> {
        if self.0 < self.1 {
            let v = self.0;
            self.0 = v + self.2;
            Some(v)
        } else {
            None
        }
    }
}

struct CompositorState {
    cat_texture: Option<Texture>,
    last_frame: Instant,
    x_offs: f32,
    y_offs: f32,
    x_vel: f32,
    y_vel: f32
}

compositor_data!(CompositorState);

impl CompositorState {
    fn new() -> Self {
        CompositorState {
            cat_texture: None,
            last_frame: Instant::now(),
            x_offs: 0.0,
            y_offs: 0.0,
            x_vel: 128.0,
            y_vel: 128.0
        }
    }
}

// TODO Basic rotation
// TODO Config reading
// TODO Arrow key velocity control

struct OutputManager;

struct Output;

struct InputManager;

struct KeyboardManager;

impl OutputManagerHandler for OutputManager {
    fn output_added<'output>(&mut self,
                             _: &mut Compositor,
                             builder: OutputBuilder<'output>)
                             -> Option<OutputBuilderResult<'output>> {
        let output = Output;
        let res = builder.build_best_mode(output);
        // TODO
        // for output in self.outputs() {
        //    if output.name() == "pre-configured-name-from-config" {
        // TODO Don't hard code, alias name, read from file
        res.output
            .transform(wl_output_transform::WL_OUTPUT_TRANSFORM_NORMAL);
        //    }
        // }
        Some(res)
    }
}

impl OutputHandler for Output {
    fn output_frame(&mut self, compositor: &mut Compositor, output: &mut OutputHandle) {
        let (width, height) = output.effective_resolution();
        let renderer = compositor
            .gles2_renderer
            .as_mut()
            .expect("Compositor was not loaded with gles2 renderer");
        let compositor_data: &mut CompositorState = (&mut compositor.data)
            .downcast_mut()
            .unwrap();
        let now = Instant::now();
        let delta = now.duration_since(compositor_data.last_frame);
        let seconds_delta = delta.as_secs() as f32;
        let nano_delta = delta.subsec_nanos() as u64;
        let ms = (seconds_delta * 1000.0) + nano_delta as f32 / 1000000.0;
        let seconds = ms / 1000.0;
        // TODO the method probably takes a different type, because you nede to call
        // start first. Will look into it.
        renderer.render(output, |renderer, output| {
            let cat_texture = compositor_data.cat_texture.as_ref().unwrap();
            for y in StepRange(-128 + compositor_data.y_offs as i32, height, 128) {
                for x in StepRange(-128 + compositor_data.x_offs as i32, width, 128) {
                    let matrix = cat_texture.get_matrix(&output.transform_matrix(), x, y);
                    // wlr_log!(L_ERROR, "x: {}, y: {}", x, y);
                    renderer.render_with_matrix(&cat_texture, &matrix);
                }
            }
        });
        compositor_data.x_offs += compositor_data.x_vel * seconds;
        compositor_data.y_offs += compositor_data.y_vel * seconds;
        if compositor_data.x_offs > 128.0 {
            compositor_data.x_offs = 0.0
        }
        if compositor_data.y_offs > 128.0 {
            compositor_data.y_offs = 0.0
        }
        compositor_data.last_frame = now;
    }
}

impl InputManagerHandler for InputManager {
    fn keyboard_added(&mut self,
                      _: &mut Compositor,
                      _: &mut KeyboardHandle)
                      -> Option<Box<KeyboardHandler>> {
        Some(Box::new(KeyboardManager))
    }
}

impl KeyboardHandler for KeyboardManager {
    fn on_key(&mut self,
              compositor: &mut Compositor,
              _: &mut KeyboardHandle,
              key_event: &mut KeyEvent) {
        let keys = key_event.input_keys();

        for key in keys {
            match key {
                keysyms::KEY_Escape => compositor.terminate(),
                keysyms::KEY_Left => update_velocities(compositor.into(), -16.0, 0.0),
                keysyms::KEY_Right => update_velocities(compositor.into(), 16.0, 0.0),
                keysyms::KEY_Up => update_velocities(compositor.into(), 0.0, -16.0),
                keysyms::KEY_Down => update_velocities(compositor.into(), 0.0, 16.0),
                _ => {}
            }
        }
    }
}

fn update_velocities(compositor: &mut CompositorState, x_diff: f32, y_diff: f32) {
    compositor.x_vel += x_diff;
    compositor.y_vel += y_diff;
}

fn main() {
    let compositor_state = CompositorState::new();
    let input_manager = Box::new(InputManager);
    let output_manager = Box::new(OutputManager);
    let mut compositor = CompositorBuilder::new()
        .gles2_renderer(true)
        .build_auto(compositor_state, input_manager, output_manager);
    {
        let gles2_renderer = &mut compositor.gles2_renderer.as_mut().unwrap();
        let compositor_data: &mut CompositorState = (&mut compositor.data).downcast_mut().unwrap();
        compositor_data.cat_texture = gles2_renderer
            .create_texture()
            .map(|mut cat_texture| {
                     cat_texture.upload_pixels(CAT_STRIDE, CAT_WIDTH, CAT_HEIGHT, CAT_DATA);
                     cat_texture
                 })
    };
    compositor.run();
}
<commit_msg>Get input from command line for rotation<commit_after>#[macro_use]
extern crate wlroots;

use std::env;
use std::time::Instant;

use wlroots::{Compositor, CompositorBuilder, InputManagerHandler, KeyEvent, KeyboardHandler,
              OutputBuilder, OutputBuilderResult, OutputHandler, OutputManagerHandler};
use wlroots::render::Texture;
use wlroots::types::{KeyboardHandle, OutputHandle};
use wlroots::wlroots_sys::wl_output_transform;
use wlroots::xkbcommon::xkb::keysyms;

const CAT_STRIDE: i32 = 128;
const CAT_WIDTH: i32 = 128;
const CAT_HEIGHT: i32 = 128;
const CAT_DATA: &'static [u8] = include_bytes!("cat.data");

/// Helper step by iterator, because `step_by` on `Range` is unstable.
struct StepRange(i32, i32, i32);
impl Iterator for StepRange {
    type Item = i32;
    fn next(&mut self) -> Option<i32> {
        if self.0 < self.1 {
            let v = self.0;
            self.0 = v + self.2;
            Some(v)
        } else {
            None
        }
    }
}

struct CompositorState {
    cat_texture: Option<Texture>,
    rotation: wl_output_transform,
    last_frame: Instant,
    x_offs: f32,
    y_offs: f32,
    x_vel: f32,
    y_vel: f32
}

compositor_data!(CompositorState);

impl CompositorState {
    fn new(rotation: wl_output_transform) -> Self {
        CompositorState {
            cat_texture: None,
            rotation,
            last_frame: Instant::now(),
            x_offs: 0.0,
            y_offs: 0.0,
            x_vel: 128.0,
            y_vel: 128.0
        }
    }
}

// TODO Basic rotation
// TODO Config reading
// TODO Arrow key velocity control

struct OutputManager;

struct Output;

struct InputManager;

struct KeyboardManager;

impl OutputManagerHandler for OutputManager {
    fn output_added<'output>(&mut self,
                             compositor: &mut Compositor,
                             builder: OutputBuilder<'output>)
                             -> Option<OutputBuilderResult<'output>> {
        let compositor_data: &mut CompositorState = compositor.into();
        let output = Output;
        let res = builder.build_best_mode(output);
        res.output.transform(compositor_data.rotation);
        Some(res)
    }
}

impl OutputHandler for Output {
    fn output_frame(&mut self, compositor: &mut Compositor, output: &mut OutputHandle) {
        let (width, height) = output.effective_resolution();
        let renderer = compositor
            .gles2_renderer
            .as_mut()
            .expect("Compositor was not loaded with gles2 renderer");
        let compositor_data: &mut CompositorState = (&mut compositor.data)
            .downcast_mut()
            .unwrap();
        let now = Instant::now();
        let delta = now.duration_since(compositor_data.last_frame);
        let seconds_delta = delta.as_secs() as f32;
        let nano_delta = delta.subsec_nanos() as u64;
        let ms = (seconds_delta * 1000.0) + nano_delta as f32 / 1000000.0;
        let seconds = ms / 1000.0;
        // TODO the method probably takes a different type, because you nede to call
        // start first. Will look into it.
        renderer.render(output, |renderer, output| {
            let cat_texture = compositor_data.cat_texture.as_ref().unwrap();
            for y in StepRange(-128 + compositor_data.y_offs as i32, height, 128) {
                for x in StepRange(-128 + compositor_data.x_offs as i32, width, 128) {
                    let matrix = cat_texture.get_matrix(&output.transform_matrix(), x, y);
                    // wlr_log!(L_ERROR, "x: {}, y: {}", x, y);
                    renderer.render_with_matrix(&cat_texture, &matrix);
                }
            }
        });
        compositor_data.x_offs += compositor_data.x_vel * seconds;
        compositor_data.y_offs += compositor_data.y_vel * seconds;
        if compositor_data.x_offs > 128.0 {
            compositor_data.x_offs = 0.0
        }
        if compositor_data.y_offs > 128.0 {
            compositor_data.y_offs = 0.0
        }
        compositor_data.last_frame = now;
    }
}

impl InputManagerHandler for InputManager {
    fn keyboard_added(&mut self,
                      _: &mut Compositor,
                      _: &mut KeyboardHandle)
                      -> Option<Box<KeyboardHandler>> {
        Some(Box::new(KeyboardManager))
    }
}

impl KeyboardHandler for KeyboardManager {
    fn on_key(&mut self,
              compositor: &mut Compositor,
              _: &mut KeyboardHandle,
              key_event: &mut KeyEvent) {
        let keys = key_event.input_keys();

        for key in keys {
            match key {
                keysyms::KEY_Escape => compositor.terminate(),
                keysyms::KEY_Left => update_velocities(compositor.into(), -16.0, 0.0),
                keysyms::KEY_Right => update_velocities(compositor.into(), 16.0, 0.0),
                keysyms::KEY_Up => update_velocities(compositor.into(), 0.0, -16.0),
                keysyms::KEY_Down => update_velocities(compositor.into(), 0.0, 16.0),
                _ => {}
            }
        }
    }
}

fn update_velocities(compositor: &mut CompositorState, x_diff: f32, y_diff: f32) {
    compositor.x_vel += x_diff;
    compositor.y_vel += y_diff;
}

fn main() {
    use wl_output_transform::*;
    let mut args = env::args();
    args.next();
    let rotation = if let Some(arg) = args.next() {
        match arg.as_str() {
            "90" => WL_OUTPUT_TRANSFORM_90,
            "180" => WL_OUTPUT_TRANSFORM_180,
            "270" => WL_OUTPUT_TRANSFORM_270,
            "flipped" => WL_OUTPUT_TRANSFORM_FLIPPED,
            "flipped_90" => WL_OUTPUT_TRANSFORM_FLIPPED_90,
            "flipped_180" => WL_OUTPUT_TRANSFORM_FLIPPED_180,
            "flipped_270" => WL_OUTPUT_TRANSFORM_FLIPPED_270,
            _ => WL_OUTPUT_TRANSFORM_NORMAL,
        }
    } else {
        WL_OUTPUT_TRANSFORM_NORMAL
    };
    let compositor_state = CompositorState::new(rotation);
    let input_manager = Box::new(InputManager);
    let output_manager = Box::new(OutputManager);
    let mut compositor = CompositorBuilder::new()
        .gles2_renderer(true)
        .build_auto(compositor_state, input_manager, output_manager);
    {
        let gles2_renderer = &mut compositor.gles2_renderer.as_mut().unwrap();
        let compositor_data: &mut CompositorState = (&mut compositor.data).downcast_mut().unwrap();
        compositor_data.cat_texture = gles2_renderer
            .create_texture()
            .map(|mut cat_texture| {
                     cat_texture.upload_pixels(CAT_STRIDE, CAT_WIDTH, CAT_HEIGHT, CAT_DATA);
                     cat_texture
                 })
    };
    compositor.run();
}
<|endoftext|>


<commit_before>//! An example of using syntect for testing syntax definitions.
//! Basically exactly the same as what Sublime Text can do,
//! but without needing ST installed
extern crate syntect;
extern crate walkdir;
#[macro_use]
extern crate lazy_static;
extern crate regex;
//extern crate onig;
use syntect::parsing::{SyntaxSet, ParseState, ScopeStack, Scope};
use syntect::highlighting::ScopeSelectors;
use syntect::easy::{ScopeRegionIterator};

use std::path::Path;
use std::io::{BufRead, BufReader};
use std::fs::File;
use std::cmp::{min, max};
use walkdir::{DirEntry, WalkDir, WalkDirIterator};
use std::str::FromStr;
use regex::Regex;

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum SyntaxTestHeaderError {
    MalformedHeader,
    SyntaxDefinitionNotFound,
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum SyntaxTestFileResult {
    FailedAssertions(usize, usize),
    Success(usize),
}

lazy_static! {
    pub static ref SYNTAX_TEST_HEADER_PATTERN: Regex = Regex::new(r#"(?xm)
            ^(?P<testtoken_start>\s*\S+)
            \s+SYNTAX\sTEST\s+
            "(?P<syntax_file>[^"]+)"
            \s*(?P<testtoken_end>\S+)?$
        "#).unwrap();
    pub static ref SYNTAX_TEST_ASSERTION_PATTERN: Regex = Regex::new(r#"(?xm)
        \s*(?:
            (?P<begin_of_token><-)|(?P<range>\^+)
        )(.+)$"#).unwrap();
}

#[derive(Debug)]
struct AssertionRange<'a> {
    begin_char: usize,
    end_char: usize,
    scope_selector_text: &'a str
}

#[derive(Debug)]
struct ScopedText {
    scope: Vec<Scope>,
    char_start: usize,
    text_len: usize,
}

#[derive(Debug)]
struct RangeTestResult {
    column_begin: usize,
    column_end: usize,
    success: bool,
}

fn get_line_assertion_details<'a>(testtoken_start: &str, testtoken_end: Option<&str>, line: &'a str) -> Option<AssertionRange<'a>> {
    // if the test start token specified in the test file's header is on the line
    if let Some(index) = line.find(testtoken_start) {
        let (before_token_start, token_and_rest_of_line) = line.split_at(index);
        if before_token_start.trim_left().is_empty() { // if only whitespace precedes the test token on the line
            if let Some(captures) = SYNTAX_TEST_ASSERTION_PATTERN.captures(&token_and_rest_of_line[testtoken_start.len()..]) {
                let mut sst = captures.get(3).unwrap().as_str().trim_right(); // get the scope selector text
                if let Some(token) = testtoken_end { // if there is an end token defined in the test file header
                    sst = sst.trim_right_matches(&token); // trim it from the scope selector text
                }
                return Some(AssertionRange {
                    begin_char: index + if captures.get(2).is_some() { testtoken_start.len() + captures.get(2).unwrap().start() } else { 0 },
                    end_char: index + if captures.get(2).is_some() { testtoken_start.len() + captures.get(2).unwrap().end() } else { 1 },
                    scope_selector_text: sst
                })
            }
        }
    }
    None
}

fn process_assertions(assertion: &AssertionRange, test_against_line_scopes: &Vec<ScopedText>) -> Vec<RangeTestResult> {
    // format the scope selector to include a space at the beginning, because, currently, ScopeSelector expects excludes to begin with " -"
    // and they are sometimes in the syntax test as ^^^-comment, for example
    let selector = ScopeSelectors::from_str(&format!(" {}", &assertion.scope_selector_text)).unwrap();
    // find the scope at the specified start column, and start matching the selector through the rest of the tokens on the line from there until the end column is reached
    let mut results = Vec::new();
    for scoped_text in test_against_line_scopes.iter().skip_while(|s|s.char_start + s.text_len <= assertion.begin_char).take_while(|s|s.char_start < assertion.end_char) {
        let match_value = selector.does_match(scoped_text.scope.as_slice());
        let result = RangeTestResult {
            column_begin: max(scoped_text.char_start, assertion.begin_char),
            column_end: min(scoped_text.char_start + scoped_text.text_len, assertion.end_char),
            success: match_value.is_some()
        };
        results.push(result);
    }
    // don't ignore assertions after the newline, they should be treated as though they are asserting against the newline
    let last = test_against_line_scopes.last().unwrap();
    if last.char_start + last.text_len < assertion.end_char {
        let match_value = selector.does_match(last.scope.as_slice());
        let result = RangeTestResult {
            column_begin: max(last.char_start + last.text_len, assertion.begin_char),
            column_end: assertion.end_char,
            success: match_value.is_some()
        };
        results.push(result);
    }
    results
}

fn test_file(ss: &SyntaxSet, path: &Path, parse_test_lines: bool) -> Result<SyntaxTestFileResult, SyntaxTestHeaderError> {
    let f = File::open(path).unwrap();
    let mut reader = BufReader::new(f);
    let mut line = String::new();

    // read the first line from the file - if we have reached EOF already, it's an invalid file
    if reader.read_line(&mut line).unwrap() == 0 {
        return Err(SyntaxTestHeaderError::MalformedHeader);
    }

    line = line.replace("\r", &"");

    // parse the syntax test header in the first line of the file
    match SYNTAX_TEST_HEADER_PATTERN.captures(&line.to_string()) {
        Some(captures) => {
            let testtoken_start = captures.name("testtoken_start").unwrap().as_str();
            let testtoken_end = captures.name("testtoken_end").map_or(None, |c|Some(c.as_str()));
            let syntax_file = captures.name("syntax_file").unwrap().as_str();

            // find the relevant syntax definition to parse the file with - case is important!
            println!("The test file references syntax definition file: {}", syntax_file);
            let syntax = match ss.find_syntax_by_path(syntax_file) {
                Some(syntax) => syntax,
                None => return Err(SyntaxTestHeaderError::SyntaxDefinitionNotFound)
            };

            let mut state = ParseState::new(syntax);
            let mut stack = ScopeStack::new();

            let mut current_line_number = 1;
            let mut test_against_line_number = 1;
            let mut scopes_on_line_being_tested = Vec::new();
            let mut previous_non_assertion_line = line.to_string();

            let mut assertion_failures: usize = 0;
            let mut total_assertions: usize = 0;

            loop {
                let mut line_has_assertion = false;
                if let Some(assertion) = get_line_assertion_details(testtoken_start, testtoken_end, &line) {
                    let result = process_assertions(&assertion, &scopes_on_line_being_tested);
                    total_assertions += &assertion.end_char - &assertion.begin_char;
                    for failure in result.iter().filter(|r|!r.success) {
                        let chars: Vec<char> = previous_non_assertion_line.chars().skip(failure.column_begin).take(failure.column_end - failure.column_begin).collect();
                        println!("  Assertion selector {:?} \
                            from line {:?} failed against line {:?}, column range {:?}-{:?} \
                            (with text {:?}) \
                            has scope {:?}",
                            assertion.scope_selector_text.trim(),
                            current_line_number, test_against_line_number, failure.column_begin, failure.column_end,
                            chars,
                            scopes_on_line_being_tested.iter().skip_while(|s|s.char_start + s.text_len <= failure.column_begin).next().unwrap_or(scopes_on_line_being_tested.last().unwrap()).scope
                        );
                        assertion_failures += failure.column_end - failure.column_begin;
                    }
                    line_has_assertion = true;
                }
                if !line_has_assertion || parse_test_lines {
                    if !line_has_assertion {
                        scopes_on_line_being_tested.clear();
                        test_against_line_number = current_line_number;
                        previous_non_assertion_line = line.to_string();
                    }
                    let ops = state.parse_line(&line);
                    let mut col: usize = 0;
                    for (s, op) in ScopeRegionIterator::new(&ops, &line) {
                        stack.apply(op);
                        if s.is_empty() { // in this case we don't care about blank tokens
                            continue;
                        } else if !line_has_assertion {
                            // if the line has no assertions on it, remember the scopes on the line so we can test against them later
                            let len = s.chars().count();
                            scopes_on_line_being_tested.push(
                                ScopedText {
                                    char_start: col,
                                    text_len: len,
                                    scope: stack.as_slice().to_vec()
                                }
                            );
                            // TODO: warn when there are duplicate adjacent (non-meta?) scopes, as it is almost always undesired
                            col += len;
                        }
                    }
                }

                line.clear();
                current_line_number += 1;
                if reader.read_line(&mut line).unwrap() == 0 {
                    break;
                }
                line = line.replace("\r", &"");
            }
            Ok(
                if assertion_failures > 0 {
                    SyntaxTestFileResult::FailedAssertions(assertion_failures, total_assertions)
                } else {
                    SyntaxTestFileResult::Success(total_assertions)
                }
            )
        },
        None => Err(SyntaxTestHeaderError::MalformedHeader)
    }
}

fn main() {
    let args: Vec<String> = std::env::args().collect();
    let tests_path = if args.len() < 2 {
        "."
    } else {
        &args[1]
    };
    let syntaxes_path = if args.len() == 3 {
        &args[2]
    } else {
        ""
    };

    // load the syntaxes from disk if told to
    // (as opposed to from the binary dumps)
    // this helps to ensure that a recompile isn't needed
    // when using this for syntax development
    let mut ss = if syntaxes_path.is_empty() {
        SyntaxSet::load_defaults_newlines() // note we load the version with newlines
    } else {
        SyntaxSet::new()
    };
    if !syntaxes_path.is_empty() {
        println!("loading syntax definitions from {}", syntaxes_path);
        ss.load_syntaxes(&syntaxes_path, true).unwrap(); // note that we load the version with newlines
        ss.link_syntaxes();
    }

    let exit_code = recursive_walk(&ss, &tests_path);
    println!("exiting with code {}", exit_code);
    std::process::exit(exit_code);

}

fn recursive_walk(ss: &SyntaxSet, path: &str) -> i32 {
    let mut exit_code: i32 = 0; // exit with code 0 by default, if all tests pass
    let walker = WalkDir::new(path).into_iter();
    for entry in walker.filter_entry(|e|e.file_type().is_dir() || is_a_syntax_test_file(e)) {
        let entry = entry.unwrap();
        if entry.file_type().is_file() {
            println!("Testing file {}", entry.path().display());
            let result = test_file(&ss, entry.path(), true);
            println!("{:?}", result);
            if exit_code != 2 { // leave exit code 2 if there was an error
                if let Err(_) = result { // set exit code 2 if there was an error
                    exit_code = 2;
                } else if let Ok(ok) = result {
                    if let SyntaxTestFileResult::FailedAssertions(_, _) = ok {
                        exit_code = 1; // otherwise, if there were failures, exit with code 1
                    }
                }
            }
        }
    }
    exit_code
}

fn is_a_syntax_test_file(entry: &DirEntry) -> bool {
    entry.file_name()
         .to_str()
         .map(|s| s.starts_with("syntax_test_"))
         .unwrap_or(false)
}
<commit_msg>make test behaviour more like ST's when not only tests are on the line<commit_after>//! An example of using syntect for testing syntax definitions.
//! Basically exactly the same as what Sublime Text can do,
//! but without needing ST installed
extern crate syntect;
extern crate walkdir;
#[macro_use]
extern crate lazy_static;
extern crate regex;
//extern crate onig;
use syntect::parsing::{SyntaxSet, ParseState, ScopeStack, Scope};
use syntect::highlighting::ScopeSelectors;
use syntect::easy::{ScopeRegionIterator};

use std::path::Path;
use std::io::{BufRead, BufReader};
use std::fs::File;
use std::cmp::{min, max};
use walkdir::{DirEntry, WalkDir, WalkDirIterator};
use std::str::FromStr;
use regex::Regex;

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum SyntaxTestHeaderError {
    MalformedHeader,
    SyntaxDefinitionNotFound,
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum SyntaxTestFileResult {
    FailedAssertions(usize, usize),
    Success(usize),
}

lazy_static! {
    pub static ref SYNTAX_TEST_HEADER_PATTERN: Regex = Regex::new(r#"(?xm)
            ^(?P<testtoken_start>\s*\S+)
            \s+SYNTAX\sTEST\s+
            "(?P<syntax_file>[^"]+)"
            \s*(?P<testtoken_end>\S+)?$
        "#).unwrap();
    pub static ref SYNTAX_TEST_ASSERTION_PATTERN: Regex = Regex::new(r#"(?xm)
        \s*(?:
            (?P<begin_of_token><-)|(?P<range>\^+)
        )(.+)$"#).unwrap();
}

#[derive(Debug)]
struct AssertionRange<'a> {
    begin_char: usize,
    end_char: usize,
    scope_selector_text: &'a str,
    is_pure_assertion_line: bool,
}

#[derive(Debug)]
struct ScopedText {
    scope: Vec<Scope>,
    char_start: usize,
    text_len: usize,
}

#[derive(Debug)]
struct RangeTestResult {
    column_begin: usize,
    column_end: usize,
    success: bool,
}

fn get_line_assertion_details<'a>(testtoken_start: &str, testtoken_end: Option<&str>, line: &'a str) -> Option<AssertionRange<'a>> {
    // if the test start token specified in the test file's header is on the line
    if let Some(index) = line.find(testtoken_start) {
        let (before_token_start, token_and_rest_of_line) = line.split_at(index);

        if let Some(captures) = SYNTAX_TEST_ASSERTION_PATTERN.captures(&token_and_rest_of_line[testtoken_start.len()..]) {
            let mut sst = captures.get(3).unwrap().as_str().trim_right(); // get the scope selector text
            if let Some(token) = testtoken_end { // if there is an end token defined in the test file header
                sst = sst.trim_right_matches(&token); // trim it from the scope selector text
            }
            return Some(AssertionRange {
                begin_char: index + if captures.get(2).is_some() { testtoken_start.len() + captures.get(2).unwrap().start() } else { 0 },
                end_char: index + if captures.get(2).is_some() { testtoken_start.len() + captures.get(2).unwrap().end() } else { 1 },
                scope_selector_text: sst,
                is_pure_assertion_line: before_token_start.trim_left().is_empty(), // if only whitespace precedes the test token on the line, then it is a pure assertion line
            })
        }
    }
    None
}

fn process_assertions(assertion: &AssertionRange, test_against_line_scopes: &Vec<ScopedText>) -> Vec<RangeTestResult> {
    // format the scope selector to include a space at the beginning, because, currently, ScopeSelector expects excludes to begin with " -"
    // and they are sometimes in the syntax test as ^^^-comment, for example
    let selector = ScopeSelectors::from_str(&format!(" {}", &assertion.scope_selector_text)).unwrap();
    // find the scope at the specified start column, and start matching the selector through the rest of the tokens on the line from there until the end column is reached
    let mut results = Vec::new();
    for scoped_text in test_against_line_scopes.iter().skip_while(|s|s.char_start + s.text_len <= assertion.begin_char).take_while(|s|s.char_start < assertion.end_char) {
        let match_value = selector.does_match(scoped_text.scope.as_slice());
        let result = RangeTestResult {
            column_begin: max(scoped_text.char_start, assertion.begin_char),
            column_end: min(scoped_text.char_start + scoped_text.text_len, assertion.end_char),
            success: match_value.is_some()
        };
        results.push(result);
    }
    // don't ignore assertions after the newline, they should be treated as though they are asserting against the newline
    let last = test_against_line_scopes.last().unwrap();
    if last.char_start + last.text_len < assertion.end_char {
        let match_value = selector.does_match(last.scope.as_slice());
        let result = RangeTestResult {
            column_begin: max(last.char_start + last.text_len, assertion.begin_char),
            column_end: assertion.end_char,
            success: match_value.is_some()
        };
        results.push(result);
    }
    results
}

fn test_file(ss: &SyntaxSet, path: &Path, parse_test_lines: bool) -> Result<SyntaxTestFileResult, SyntaxTestHeaderError> {
    let f = File::open(path).unwrap();
    let mut reader = BufReader::new(f);
    let mut line = String::new();

    // read the first line from the file - if we have reached EOF already, it's an invalid file
    if reader.read_line(&mut line).unwrap() == 0 {
        return Err(SyntaxTestHeaderError::MalformedHeader);
    }

    line = line.replace("\r", &"");

    // parse the syntax test header in the first line of the file
    match SYNTAX_TEST_HEADER_PATTERN.captures(&line.to_string()) {
        Some(captures) => {
            let testtoken_start = captures.name("testtoken_start").unwrap().as_str();
            let testtoken_end = captures.name("testtoken_end").map_or(None, |c|Some(c.as_str()));
            let syntax_file = captures.name("syntax_file").unwrap().as_str();

            // find the relevant syntax definition to parse the file with - case is important!
            println!("The test file references syntax definition file: {}", syntax_file);
            let syntax = match ss.find_syntax_by_path(syntax_file) {
                Some(syntax) => syntax,
                None => return Err(SyntaxTestHeaderError::SyntaxDefinitionNotFound)
            };

            let mut state = ParseState::new(syntax);
            let mut stack = ScopeStack::new();

            let mut current_line_number = 1;
            let mut test_against_line_number = 1;
            let mut scopes_on_line_being_tested = Vec::new();
            let mut previous_non_assertion_line = line.to_string();

            let mut assertion_failures: usize = 0;
            let mut total_assertions: usize = 0;

            loop {
                let mut line_only_has_assertion = false;
                let mut line_has_assertion = false;
                if let Some(assertion) = get_line_assertion_details(testtoken_start, testtoken_end, &line) {
                    let result = process_assertions(&assertion, &scopes_on_line_being_tested);
                    total_assertions += &assertion.end_char - &assertion.begin_char;
                    for failure in result.iter().filter(|r|!r.success) {
                        let chars: Vec<char> = previous_non_assertion_line.chars().skip(failure.column_begin).take(failure.column_end - failure.column_begin).collect();
                        println!("  Assertion selector {:?} \
                            from line {:?} failed against line {:?}, column range {:?}-{:?} \
                            (with text {:?}) \
                            has scope {:?}",
                            assertion.scope_selector_text.trim(),
                            current_line_number, test_against_line_number, failure.column_begin, failure.column_end,
                            chars,
                            scopes_on_line_being_tested.iter().skip_while(|s|s.char_start + s.text_len <= failure.column_begin).next().unwrap_or(scopes_on_line_being_tested.last().unwrap()).scope
                        );
                        assertion_failures += failure.column_end - failure.column_begin;
                    }
                    line_only_has_assertion = assertion.is_pure_assertion_line;
                    line_has_assertion = true;
                }
                if !line_only_has_assertion || parse_test_lines {
                    if !line_has_assertion { // ST seems to ignore lines that have assertions when calculating which line the assertion tests against
                        scopes_on_line_being_tested.clear();
                        test_against_line_number = current_line_number;
                        previous_non_assertion_line = line.to_string();
                    }
                    let ops = state.parse_line(&line);
                    let mut col: usize = 0;
                    for (s, op) in ScopeRegionIterator::new(&ops, &line) {
                        stack.apply(op);
                        if s.is_empty() { // in this case we don't care about blank tokens
                            continue;
                        } else if !line_has_assertion {
                            // if the line has no assertions on it, remember the scopes on the line so we can test against them later
                            let len = s.chars().count();
                            scopes_on_line_being_tested.push(
                                ScopedText {
                                    char_start: col,
                                    text_len: len,
                                    scope: stack.as_slice().to_vec()
                                }
                            );
                            // TODO: warn when there are duplicate adjacent (non-meta?) scopes, as it is almost always undesired
                            col += len;
                        }
                    }
                }

                line.clear();
                current_line_number += 1;
                if reader.read_line(&mut line).unwrap() == 0 {
                    break;
                }
                line = line.replace("\r", &"");
            }
            Ok(
                if assertion_failures > 0 {
                    SyntaxTestFileResult::FailedAssertions(assertion_failures, total_assertions)
                } else {
                    SyntaxTestFileResult::Success(total_assertions)
                }
            )
        },
        None => Err(SyntaxTestHeaderError::MalformedHeader)
    }
}

fn main() {
    let args: Vec<String> = std::env::args().collect();
    let tests_path = if args.len() < 2 {
        "."
    } else {
        &args[1]
    };
    let syntaxes_path = if args.len() == 3 {
        &args[2]
    } else {
        ""
    };

    // load the syntaxes from disk if told to
    // (as opposed to from the binary dumps)
    // this helps to ensure that a recompile isn't needed
    // when using this for syntax development
    let mut ss = if syntaxes_path.is_empty() {
        SyntaxSet::load_defaults_newlines() // note we load the version with newlines
    } else {
        SyntaxSet::new()
    };
    if !syntaxes_path.is_empty() {
        println!("loading syntax definitions from {}", syntaxes_path);
        ss.load_syntaxes(&syntaxes_path, true).unwrap(); // note that we load the version with newlines
        ss.link_syntaxes();
    }

    let exit_code = recursive_walk(&ss, &tests_path);
    println!("exiting with code {}", exit_code);
    std::process::exit(exit_code);

}

fn recursive_walk(ss: &SyntaxSet, path: &str) -> i32 {
    let mut exit_code: i32 = 0; // exit with code 0 by default, if all tests pass
    let walker = WalkDir::new(path).into_iter();
    for entry in walker.filter_entry(|e|e.file_type().is_dir() || is_a_syntax_test_file(e)) {
        let entry = entry.unwrap();
        if entry.file_type().is_file() {
            println!("Testing file {}", entry.path().display());
            let result = test_file(&ss, entry.path(), true);
            println!("{:?}", result);
            if exit_code != 2 { // leave exit code 2 if there was an error
                if let Err(_) = result { // set exit code 2 if there was an error
                    exit_code = 2;
                } else if let Ok(ok) = result {
                    if let SyntaxTestFileResult::FailedAssertions(_, _) = ok {
                        exit_code = 1; // otherwise, if there were failures, exit with code 1
                    }
                }
            }
        }
    }
    exit_code
}

fn is_a_syntax_test_file(entry: &DirEntry) -> bool {
    entry.file_name()
         .to_str()
         .map(|s| s.starts_with("syntax_test_"))
         .unwrap_or(false)
}
<|endoftext|>


<commit_before>// Copyright (c) 2013-2015 Sandstorm Development Group, Inc. and contributors
// Licensed under the MIT License:
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

extern crate gj;
use gj::io::{AsyncRead, AsyncWrite};

fn child_loop(delay: u32, stream: gj::io::SocketStream, buf: Vec<u8>) -> gj::Promise<()> {

    // This blocks the entire thread. This is okay because we are on a child thread
    // where nothing else needs to happen.
    ::std::thread::sleep_ms(delay);

    return stream.write(buf).then(move |(stream, buf)| {
        return Ok(child_loop(delay, stream, buf));
    });
}

fn child(delay: u32) -> gj::Result<gj::io::SocketStream> {
    let (_, stream) = try!(gj::io::spawn(move |parent_stream, wait_scope| {
        try!(child_loop(delay, parent_stream, vec![0u8]).wait(wait_scope));
        Ok(())
    }));
    return Ok(stream);
}

fn listen_to_child(id: String, stream: gj::io::SocketStream, buf: Vec<u8>) -> gj::Promise<()> {
    return stream.read(buf, 1).then(move |(stream, buf, _n)| {
        println!("heard back from {}", id);
        return Ok(listen_to_child(id, stream, buf));
    });
}

fn parent_wait_loop() -> gj::Promise<()> {
    println!("parent wait loop...");

    // If we used ::std::thread::sleep_ms() here, we would block the main event loop.
    return gj::io::Timer.after_delay_ms(3000).then(|()| {
        return Ok(parent_wait_loop());
    });
}

pub fn main() {
    gj::EventLoop::top_level(|wait_scope| {

        let children = vec![
            parent_wait_loop(),
            listen_to_child("CHILD 1".to_string(), try!(child(700)), vec![0]),
            listen_to_child("CHILD 2".to_string(), try!(child(1900)), vec![0]),
            listen_to_child("CHILD 3".to_string(), try!(child(2600)), vec![0])];

        try!(gj::join_promises(children).wait(wait_scope));

        Ok(())
    }).unwrap();
}
<commit_msg>Documentation in threads example.<commit_after>// Copyright (c) 2013-2015 Sandstorm Development Group, Inc. and contributors
// Licensed under the MIT License:
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

//! Tasks scheduled on a GJ event loop are not preemptive. For an event loop to make progress,
//! event callbacks must yield control by returning.
//!
//! GJ event loops are thread-local. To take advantage of multiprocessor hardware or to deal with
//! tasks that cannot easily yield, you can send tasks to separate threads where they will execute
//! on separate event loops. The example program illustrates how that might work, using
//! `std::thread::sleep_ms()` as a stand-in for a blocking computation.

extern crate gj;
use gj::io::{AsyncRead, AsyncWrite};

fn child_loop(delay: u32, stream: gj::io::SocketStream, buf: Vec<u8>) -> gj::Promise<()> {

    // This blocks the entire thread. This is okay because we are on a child thread
    // where nothing else needs to happen.
    ::std::thread::sleep_ms(delay);

    return stream.write(buf).then(move |(stream, buf)| {
        return Ok(child_loop(delay, stream, buf));
    });
}

fn child(delay: u32) -> gj::Result<gj::io::SocketStream> {
    let (_, stream) = try!(gj::io::spawn(move |parent_stream, wait_scope| {
        try!(child_loop(delay, parent_stream, vec![0u8]).wait(wait_scope));
        Ok(())
    }));
    return Ok(stream);
}

fn listen_to_child(id: String, stream: gj::io::SocketStream, buf: Vec<u8>) -> gj::Promise<()> {
    return stream.read(buf, 1).then(move |(stream, buf, _n)| {
        println!("heard back from {}", id);
        return Ok(listen_to_child(id, stream, buf));
    });
}

fn parent_wait_loop() -> gj::Promise<()> {
    println!("parent wait loop...");

    // If we used ::std::thread::sleep_ms() here, we would block the main event loop.
    return gj::io::Timer.after_delay_ms(3000).then(|()| {
        return Ok(parent_wait_loop());
    });
}

pub fn main() {
    gj::EventLoop::top_level(|wait_scope| {

        let children = vec![
            parent_wait_loop(),
            listen_to_child("CHILD 1".to_string(), try!(child(700)), vec![0]),
            listen_to_child("CHILD 2".to_string(), try!(child(1900)), vec![0]),
            listen_to_child("CHILD 3".to_string(), try!(child(2600)), vec![0])];

        try!(gj::join_promises(children).wait(wait_scope));

        Ok(())
    }).unwrap();
}
<|endoftext|>


<commit_before>// This is free and unencumbered software released into the public domain.
//
// Anyone is free to copy, modify, publish, use, compile, sell, or
// distribute this software, either in source code form or as a compiled
// binary, for any purpose, commercial or non-commercial, and by any
// means.
//
// In jurisdictions that recognize copyright laws, the author or authors
// of this software dedicate any and all copyright interest in the
// software to the public domain. We make this dedication for the benefit
// of the public at large and to the detriment of our heirs and
// successors. We intend this dedication to be an overt act of
// relinquishment in perpetuity of all present and future rights to this
// software under copyright law.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
//
// For more information, please refer to <http://unlicense.org/>

// This line shouldn't be necessary in a real project.
extern crate hyper_pkg as hyper;

use std::error::Error;
use std::io;
use std::time::Duration;

use futures::prelude::*;
use twitter_stream::Token;

const TIMEOUT: Duration = Duration::from_secs(90);

#[tokio::main]
async fn main() {
    let token = Token::from_parts(
        "consumer_key",
        "consumer_secret",
        "access_key",
        "access_secret",
    );

    let mut conn = hyper::client::HttpConnector::new();
    conn.set_connect_timeout(Some(TIMEOUT));
    let tls = native_tls::TlsConnector::new().unwrap();
    let conn = hyper_tls::HttpsConnector::from((conn, tls.into()));
    let mut conn = hyper_timeout::TimeoutConnector::new(conn);
    conn.set_read_timeout(Some(TIMEOUT));

    let client = hyper::Client::builder().build::<_, hyper::Body>(conn);

    let result = twitter_stream::Builder::new(token)
        .track("@Twitter")
        .listen_with_client(client)
        .try_flatten_stream()
        .try_for_each(|json| {
            println!("{}", json);
            future::ok(())
        })
        .await;

    match result {
        Ok(()) => {}
        Err(twitter_stream::Error::Service(e)) => {
            if let Some(e) = e.source() {
                if let Some(e) = e.downcast_ref::<io::Error>() {
                    if e.kind() == io::ErrorKind::TimedOut {
                        eprintln!("timed out");
                        return;
                    }
                }
            }
            eprintln!("error: {:?}", e);
        }
        Err(e) => {
            eprintln!("error: {:?}", e);
        }
    }
}
<commit_msg>example: Minor cleanup<commit_after>// This is free and unencumbered software released into the public domain.
//
// Anyone is free to copy, modify, publish, use, compile, sell, or
// distribute this software, either in source code form or as a compiled
// binary, for any purpose, commercial or non-commercial, and by any
// means.
//
// In jurisdictions that recognize copyright laws, the author or authors
// of this software dedicate any and all copyright interest in the
// software to the public domain. We make this dedication for the benefit
// of the public at large and to the detriment of our heirs and
// successors. We intend this dedication to be an overt act of
// relinquishment in perpetuity of all present and future rights to this
// software under copyright law.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
//
// For more information, please refer to <http://unlicense.org/>

// This line shouldn't be necessary in a real project.
extern crate hyper_pkg as hyper;

use std::error::Error;
use std::io;
use std::time::Duration;

use futures::prelude::*;
use twitter_stream::Token;

const TIMEOUT: Duration = Duration::from_secs(90);

#[tokio::main]
async fn main() {
    let token = Token::from_parts(
        "consumer_key",
        "consumer_secret",
        "access_key",
        "access_secret",
    );

    let mut conn = hyper::client::HttpConnector::new();
    conn.set_connect_timeout(Some(TIMEOUT));
    let mut conn = hyper_timeout::TimeoutConnector::new(conn);
    conn.set_read_timeout(Some(TIMEOUT));
    let tls = native_tls::TlsConnector::new().unwrap();
    let conn = hyper_tls::HttpsConnector::from((conn, tls.into()));

    let client = hyper::Client::builder().build::<_, hyper::Body>(conn);

    let result = twitter_stream::Builder::new(token)
        .track("@Twitter")
        .listen_with_client(client)
        .try_flatten_stream()
        .try_for_each(|json| {
            println!("{}", json);
            future::ok(())
        })
        .await;

    match result {
        Ok(()) => {}
        Err(twitter_stream::Error::Service(e)) => {
            if let Some(e) = e.source() {
                if let Some(e) = e.downcast_ref::<io::Error>() {
                    if e.kind() == io::ErrorKind::TimedOut {
                        eprintln!("timed out");
                        return;
                    }
                }
            }
            eprintln!("error: {:?}", e);
        }
        Err(e) => {
            eprintln!("error: {:?}", e);
        }
    }
}
<|endoftext|>


<commit_before>pub mod tcp_connection;
pub mod tcp_pump;

pub mod tcp {
	pub use super::tcp_pump;
	pub use super::tcp_connection;
}

use std::sync::Arc;
use std::sync::mpsc::{ Sender };

use ::protocol::{ ApiMessage, ApiRequestMessage, ApiResponseMessage };

pub enum ConnectionMessage<Req: ApiMessage, Res: ApiMessage> {
	Request(
		Sender<Arc<ApiResponseMessage<Res>>>,
		ApiRequestMessage<Req>
	),
	Response(Arc<ApiResponseMessage<Res>>)
}<commit_msg>Adding some comments to tcp messages<commit_after>pub mod tcp_connection;
pub mod tcp_pump;

pub mod tcp {
	pub use super::tcp_pump;
	pub use super::tcp_connection;
}

use std::sync::Arc;
use std::sync::mpsc::{ Sender };

use ::protocol::{ ApiMessage, ApiRequestMessage, ApiResponseMessage };

/// The low-level message that a connection will receive and process
pub enum ConnectionMessage<Req: ApiMessage, Res: ApiMessage> {
	/// An asynchronous Kafka request
	Request(
		/// Where to send the response asynchronously
		Sender<Arc<ApiResponseMessage<Res>>>,
		/// The request to send
		ApiRequestMessage<Req>
	),
	/// An asynchronous Kafka response
	Response(Arc<ApiResponseMessage<Res>>)
}<|endoftext|>