<commit_before>// Copyright 2021 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

use std::collections::VecDeque;
use std::io::{self, stdin};
use std::ops::DerefMut;
use std::path::PathBuf;
use std::sync::Arc;

use anyhow::{anyhow, bail, Context};
use base::{error, warn, Event, RawDescriptor, Terminal};
use cros_async::{EventAsync, Executor};
use data_model::DataInit;

use argh::FromArgs;
use futures::future::{AbortHandle, Abortable};
use hypervisor::ProtectionType;
use once_cell::sync::OnceCell;
use sync::Mutex;
use vm_memory::GuestMemory;
use vmm_vhost::message::{VhostUserProtocolFeatures, VhostUserVirtioFeatures};

use crate::serial_device::{SerialDevice, SerialHardware, SerialParameters, SerialType};
use crate::virtio::console::{
    handle_input, process_transmit_queue, spawn_input_thread, virtio_console_config, ConsoleError,
};
use crate::virtio::vhost::user::device::handler::{
    CallEvent, DeviceRequestHandler, VhostUserBackend,
};
use crate::virtio::{self, copy_config};

static CONSOLE_EXECUTOR: OnceCell<Executor> = OnceCell::new();

async fn run_tx_queue(
    mut queue: virtio::Queue,
    mem: GuestMemory,
    call_evt: Arc<Mutex<CallEvent>>,
    kick_evt: EventAsync,
    mut output: Box<dyn io::Write>,
) {
    loop {
        if let Err(e) = kick_evt.next_val().await {
            error!("Failed to read kick event for tx queue: {}", e);
            break;
        }
        process_transmit_queue(&mem, &call_evt, &mut queue, &mut output);
    }
}

async fn run_rx_queue(
    mut queue: virtio::Queue,
    mem: GuestMemory,
    call_evt: Arc<Mutex<CallEvent>>,
    kick_evt: EventAsync,
    in_buffer: Arc<Mutex<VecDeque<u8>>>,
    in_avail_evt: EventAsync,
) {
    loop {
        if let Err(e) = in_avail_evt.next_val().await {
            error!("Failed reading in_avail_evt: {}", e);
            break;
        }
        match handle_input(&mem, &call_evt, in_buffer.lock().deref_mut(), &mut queue) {
            Ok(()) => {}
            Err(ConsoleError::RxDescriptorsExhausted) => {
                if let Err(e) = kick_evt.next_val().await {
                    error!("Failed to read kick event for rx queue: {}", e);
                    break;
                }
            }
        }
    }
}

struct ConsoleBackend {
    input: Option<Box<dyn io::Read + Send>>,
    output: Option<Box<dyn io::Write + Send>>,
    avail_features: u64,
    acked_features: u64,
    acked_protocol_features: VhostUserProtocolFeatures,
    workers: [Option<AbortHandle>; Self::MAX_QUEUE_NUM],
}

impl SerialDevice for ConsoleBackend {
    fn new(
        protected_vm: ProtectionType,
        _evt: Event,
        input: Option<Box<dyn io::Read + Send>>,
        output: Option<Box<dyn io::Write + Send>>,
        _keep_rds: Vec<RawDescriptor>,
    ) -> ConsoleBackend {
        let avail_features = 1u64 << crate::virtio::VIRTIO_F_VERSION_1
            | virtio::base_features(protected_vm)
            | VhostUserVirtioFeatures::PROTOCOL_FEATURES.bits();
        ConsoleBackend {
            input,
            output,
            avail_features,
            acked_features: 0,
            acked_protocol_features: VhostUserProtocolFeatures::empty(),
            workers: Default::default(),
        }
    }
}

impl VhostUserBackend for ConsoleBackend {
    const MAX_QUEUE_NUM: usize = 2; /* transmit and receive queues */
    const MAX_VRING_LEN: u16 = 256;

    type Doorbell = CallEvent;
    type Error = anyhow::Error;

    fn features(&self) -> u64 {
        self.avail_features
    }

    fn ack_features(&mut self, value: u64) -> anyhow::Result<()> {
        let unrequested_features = value & !self.avail_features;
        if unrequested_features != 0 {
            bail!("invalid features are given: {:#x}", unrequested_features);
        }

        self.acked_features |= value;

        Ok(())
    }

    fn acked_features(&self) -> u64 {
        self.acked_features
    }

    fn protocol_features(&self) -> VhostUserProtocolFeatures {
        VhostUserProtocolFeatures::CONFIG
    }

    fn ack_protocol_features(&mut self, features: u64) -> anyhow::Result<()> {
        let features = VhostUserProtocolFeatures::from_bits(features)
            .ok_or_else(|| anyhow!("invalid protocol features are given: {:#x}", features))?;
        let supported = self.protocol_features();
        self.acked_protocol_features = features & supported;
        Ok(())
    }

    fn acked_protocol_features(&self) -> u64 {
        self.acked_protocol_features.bits()
    }

    fn read_config(&self, offset: u64, data: &mut [u8]) {
        let config = virtio_console_config {
            max_nr_ports: 1.into(),
            ..Default::default()
        };
        copy_config(data, 0, config.as_slice(), offset);
    }

    fn reset(&mut self) {
        for handle in self.workers.iter_mut().filter_map(Option::take) {
            handle.abort();
        }
    }

    fn start_queue(
        &mut self,
        idx: usize,
        mut queue: virtio::Queue,
        mem: GuestMemory,
        call_evt: Arc<Mutex<CallEvent>>,
        kick_evt: Event,
    ) -> anyhow::Result<()> {
        if let Some(handle) = self.workers.get_mut(idx).and_then(Option::take) {
            warn!("Starting new queue handler without stopping old handler");
            handle.abort();
        }

        // Enable any virtqueue features that were negotiated (like VIRTIO_RING_F_EVENT_IDX).
        queue.ack_features(self.acked_features);

        // Safe because the executor is initialized in main() below.
        let ex = CONSOLE_EXECUTOR.get().expect("Executor not initialized.");

        let kick_evt =
            EventAsync::new(kick_evt.0, ex).context("Failed to create EventAsync for kick_evt")?;
        let (handle, registration) = AbortHandle::new_pair();
        match idx {
            // ReceiveQueue
            0 => {
                // See explanation in devices/src/virtio/console.rs
                // We need a multithreaded input polling because io::Read only provides
                // a blocking interface which we cannot use in an async function.
                let in_avail_evt = match Event::new() {
                    Ok(evt) => evt,
                    Err(e) => {
                        bail!("Failed creating Event: {}", e);
                    }
                };

                let input_unpacked = self
                    .input
                    .take()
                    .ok_or_else(|| anyhow!("input source unavailable"))?;
                let in_buffer = spawn_input_thread(input_unpacked, &in_avail_evt)
                    .take()
                    .ok_or_else(|| anyhow!("input channel unavailable"))?;

                // Create the async 'in' event so we can await on it.
                let in_avail_async_evt = EventAsync::new(in_avail_evt.0, ex)
                    .context("Failed to create EventAsync for in_avail_evt")?;

                ex.spawn_local(Abortable::new(
                    run_rx_queue(
                        queue,
                        mem,
                        call_evt,
                        kick_evt,
                        in_buffer,
                        in_avail_async_evt,
                    ),
                    registration,
                ))
                .detach();
            }
            // TransmitQueue
            1 => {
                // Take ownership of output writer.
                // Safe because output should always be initialized to something
                let output_unwrapped: Box<dyn io::Write + Send> = self
                    .output
                    .take()
                    .ok_or_else(|| anyhow!("no output available"))?;
                ex.spawn_local(Abortable::new(
                    run_tx_queue(queue, mem, call_evt, kick_evt, output_unwrapped),
                    registration,
                ))
                .detach();
            }
            _ => bail!("attempted to start unknown queue: {}", idx),
        }

        self.workers[idx] = Some(handle);
        Ok(())
    }

    fn stop_queue(&mut self, idx: usize) {
        if let Some(handle) = self.workers.get_mut(idx).and_then(Option::take) {
            handle.abort();
        }
    }
}

fn run_console(params: &SerialParameters, socket: &str) -> anyhow::Result<()> {
    // We need to pass an event as per Serial Device API but we don't really use it anyway.
    let evt = Event::new()?;
    // Same for keep_rds, we don't really use this.
    let mut keep_rds = Vec::new();
    let console = match params.create_serial_device::<ConsoleBackend>(
        ProtectionType::Unprotected,
        &evt,
        &mut keep_rds,
    ) {
        Ok(c) => c,
        Err(e) => bail!(e),
    };

    let handler = DeviceRequestHandler::new(console);
    let ex = Executor::new().context("Failed to create executor")?;

    let _ = CONSOLE_EXECUTOR.set(ex.clone());

    if let Err(e) = ex.run_until(handler.run(socket, &ex)) {
        bail!(e);
    }
    Ok(())
}

#[derive(FromArgs)]
#[argh(description = "")]
struct Options {
    #[argh(option, description = "path to a socket", arg_name = "PATH")]
    socket: String,
    #[argh(option, description = "path to a file", arg_name = "OUTFILE")]
    output_file: Option<PathBuf>,
    #[argh(option, description = "path to a file", arg_name = "INFILE")]
    input_file: Option<PathBuf>,
}

/// Starts a vhost-user console device.
/// Returns an error if the given `args` is invalid or the device fails to run.
pub fn run_console_device(program_name: &str, args: &[&str]) -> anyhow::Result<()> {
    let Options {
        input_file,
        output_file,
        socket,
    } = match Options::from_args(&[program_name], args) {
        Ok(opts) => opts,
        Err(e) => {
            if e.status.is_err() {
                bail!(e.output);
            } else {
                println!("{}", e.output);
            }
            return Ok(());
        }
    };

    // Set stdin() in raw mode so we can send over individual keystrokes unbuffered
    stdin()
        .set_raw_mode()
        .context("Failed to set terminal raw mode")?;

    let type_ = match output_file {
        Some(_) => SerialType::File,
        None => SerialType::Stdout,
    };

    let params = SerialParameters {
        type_,
        hardware: SerialHardware::VirtioConsole,
        // Required only if type_ is SerialType::File or SerialType::UnixSocket
        path: output_file,
        input: input_file,
        num: 1,
        console: true,
        earlycon: false,
        // We do not support stdin-less mode
        stdin: true,
    };

    if let Err(e) = run_console(&params, &socket) {
        bail!("error occurred: {:#}", e);
    }

    // Restore terminal capabilities back to what they were before
    stdin()
        .set_canon_mode()
        .context("Failed to restore canonical mode for terminal")?;

    Ok(())
}
<commit_msg>devices: vhost-user: console: always restore terminal capabilities<commit_after>// Copyright 2021 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

use std::collections::VecDeque;
use std::io::{self, stdin};
use std::ops::DerefMut;
use std::path::PathBuf;
use std::sync::Arc;

use anyhow::{anyhow, bail, Context};
use base::{error, warn, Event, RawDescriptor, Terminal};
use cros_async::{EventAsync, Executor};
use data_model::DataInit;

use argh::FromArgs;
use futures::future::{AbortHandle, Abortable};
use hypervisor::ProtectionType;
use once_cell::sync::OnceCell;
use sync::Mutex;
use vm_memory::GuestMemory;
use vmm_vhost::message::{VhostUserProtocolFeatures, VhostUserVirtioFeatures};

use crate::serial_device::{SerialDevice, SerialHardware, SerialParameters, SerialType};
use crate::virtio::console::{
    handle_input, process_transmit_queue, spawn_input_thread, virtio_console_config, ConsoleError,
};
use crate::virtio::vhost::user::device::handler::{
    CallEvent, DeviceRequestHandler, VhostUserBackend,
};
use crate::virtio::{self, copy_config};

static CONSOLE_EXECUTOR: OnceCell<Executor> = OnceCell::new();

async fn run_tx_queue(
    mut queue: virtio::Queue,
    mem: GuestMemory,
    call_evt: Arc<Mutex<CallEvent>>,
    kick_evt: EventAsync,
    mut output: Box<dyn io::Write>,
) {
    loop {
        if let Err(e) = kick_evt.next_val().await {
            error!("Failed to read kick event for tx queue: {}", e);
            break;
        }
        process_transmit_queue(&mem, &call_evt, &mut queue, &mut output);
    }
}

async fn run_rx_queue(
    mut queue: virtio::Queue,
    mem: GuestMemory,
    call_evt: Arc<Mutex<CallEvent>>,
    kick_evt: EventAsync,
    in_buffer: Arc<Mutex<VecDeque<u8>>>,
    in_avail_evt: EventAsync,
) {
    loop {
        if let Err(e) = in_avail_evt.next_val().await {
            error!("Failed reading in_avail_evt: {}", e);
            break;
        }
        match handle_input(&mem, &call_evt, in_buffer.lock().deref_mut(), &mut queue) {
            Ok(()) => {}
            Err(ConsoleError::RxDescriptorsExhausted) => {
                if let Err(e) = kick_evt.next_val().await {
                    error!("Failed to read kick event for rx queue: {}", e);
                    break;
                }
            }
        }
    }
}

struct ConsoleBackend {
    input: Option<Box<dyn io::Read + Send>>,
    output: Option<Box<dyn io::Write + Send>>,
    avail_features: u64,
    acked_features: u64,
    acked_protocol_features: VhostUserProtocolFeatures,
    workers: [Option<AbortHandle>; Self::MAX_QUEUE_NUM],
}

impl SerialDevice for ConsoleBackend {
    fn new(
        protected_vm: ProtectionType,
        _evt: Event,
        input: Option<Box<dyn io::Read + Send>>,
        output: Option<Box<dyn io::Write + Send>>,
        _keep_rds: Vec<RawDescriptor>,
    ) -> ConsoleBackend {
        let avail_features = 1u64 << crate::virtio::VIRTIO_F_VERSION_1
            | virtio::base_features(protected_vm)
            | VhostUserVirtioFeatures::PROTOCOL_FEATURES.bits();
        ConsoleBackend {
            input,
            output,
            avail_features,
            acked_features: 0,
            acked_protocol_features: VhostUserProtocolFeatures::empty(),
            workers: Default::default(),
        }
    }
}

impl VhostUserBackend for ConsoleBackend {
    const MAX_QUEUE_NUM: usize = 2; /* transmit and receive queues */
    const MAX_VRING_LEN: u16 = 256;

    type Doorbell = CallEvent;
    type Error = anyhow::Error;

    fn features(&self) -> u64 {
        self.avail_features
    }

    fn ack_features(&mut self, value: u64) -> anyhow::Result<()> {
        let unrequested_features = value & !self.avail_features;
        if unrequested_features != 0 {
            bail!("invalid features are given: {:#x}", unrequested_features);
        }

        self.acked_features |= value;

        Ok(())
    }

    fn acked_features(&self) -> u64 {
        self.acked_features
    }

    fn protocol_features(&self) -> VhostUserProtocolFeatures {
        VhostUserProtocolFeatures::CONFIG
    }

    fn ack_protocol_features(&mut self, features: u64) -> anyhow::Result<()> {
        let features = VhostUserProtocolFeatures::from_bits(features)
            .ok_or_else(|| anyhow!("invalid protocol features are given: {:#x}", features))?;
        let supported = self.protocol_features();
        self.acked_protocol_features = features & supported;
        Ok(())
    }

    fn acked_protocol_features(&self) -> u64 {
        self.acked_protocol_features.bits()
    }

    fn read_config(&self, offset: u64, data: &mut [u8]) {
        let config = virtio_console_config {
            max_nr_ports: 1.into(),
            ..Default::default()
        };
        copy_config(data, 0, config.as_slice(), offset);
    }

    fn reset(&mut self) {
        for handle in self.workers.iter_mut().filter_map(Option::take) {
            handle.abort();
        }
    }

    fn start_queue(
        &mut self,
        idx: usize,
        mut queue: virtio::Queue,
        mem: GuestMemory,
        call_evt: Arc<Mutex<CallEvent>>,
        kick_evt: Event,
    ) -> anyhow::Result<()> {
        if let Some(handle) = self.workers.get_mut(idx).and_then(Option::take) {
            warn!("Starting new queue handler without stopping old handler");
            handle.abort();
        }

        // Enable any virtqueue features that were negotiated (like VIRTIO_RING_F_EVENT_IDX).
        queue.ack_features(self.acked_features);

        // Safe because the executor is initialized in main() below.
        let ex = CONSOLE_EXECUTOR.get().expect("Executor not initialized.");

        let kick_evt =
            EventAsync::new(kick_evt.0, ex).context("Failed to create EventAsync for kick_evt")?;
        let (handle, registration) = AbortHandle::new_pair();
        match idx {
            // ReceiveQueue
            0 => {
                // See explanation in devices/src/virtio/console.rs
                // We need a multithreaded input polling because io::Read only provides
                // a blocking interface which we cannot use in an async function.
                let in_avail_evt = match Event::new() {
                    Ok(evt) => evt,
                    Err(e) => {
                        bail!("Failed creating Event: {}", e);
                    }
                };

                let input_unpacked = self
                    .input
                    .take()
                    .ok_or_else(|| anyhow!("input source unavailable"))?;
                let in_buffer = spawn_input_thread(input_unpacked, &in_avail_evt)
                    .take()
                    .ok_or_else(|| anyhow!("input channel unavailable"))?;

                // Create the async 'in' event so we can await on it.
                let in_avail_async_evt = EventAsync::new(in_avail_evt.0, ex)
                    .context("Failed to create EventAsync for in_avail_evt")?;

                ex.spawn_local(Abortable::new(
                    run_rx_queue(
                        queue,
                        mem,
                        call_evt,
                        kick_evt,
                        in_buffer,
                        in_avail_async_evt,
                    ),
                    registration,
                ))
                .detach();
            }
            // TransmitQueue
            1 => {
                // Take ownership of output writer.
                // Safe because output should always be initialized to something
                let output_unwrapped: Box<dyn io::Write + Send> = self
                    .output
                    .take()
                    .ok_or_else(|| anyhow!("no output available"))?;
                ex.spawn_local(Abortable::new(
                    run_tx_queue(queue, mem, call_evt, kick_evt, output_unwrapped),
                    registration,
                ))
                .detach();
            }
            _ => bail!("attempted to start unknown queue: {}", idx),
        }

        self.workers[idx] = Some(handle);
        Ok(())
    }

    fn stop_queue(&mut self, idx: usize) {
        if let Some(handle) = self.workers.get_mut(idx).and_then(Option::take) {
            handle.abort();
        }
    }
}

fn run_console(params: &SerialParameters, socket: &str) -> anyhow::Result<()> {
    // We need to pass an event as per Serial Device API but we don't really use it anyway.
    let evt = Event::new()?;
    // Same for keep_rds, we don't really use this.
    let mut keep_rds = Vec::new();
    let console = match params.create_serial_device::<ConsoleBackend>(
        ProtectionType::Unprotected,
        &evt,
        &mut keep_rds,
    ) {
        Ok(c) => c,
        Err(e) => bail!(e),
    };

    let handler = DeviceRequestHandler::new(console);
    let ex = Executor::new().context("Failed to create executor")?;

    let _ = CONSOLE_EXECUTOR.set(ex.clone());

    if let Err(e) = ex.run_until(handler.run(socket, &ex)) {
        bail!(e);
    }
    Ok(())
}

#[derive(FromArgs)]
#[argh(description = "")]
struct Options {
    #[argh(option, description = "path to a socket", arg_name = "PATH")]
    socket: String,
    #[argh(option, description = "path to a file", arg_name = "OUTFILE")]
    output_file: Option<PathBuf>,
    #[argh(option, description = "path to a file", arg_name = "INFILE")]
    input_file: Option<PathBuf>,
}

/// Starts a vhost-user console device.
/// Returns an error if the given `args` is invalid or the device fails to run.
pub fn run_console_device(program_name: &str, args: &[&str]) -> anyhow::Result<()> {
    let Options {
        input_file,
        output_file,
        socket,
    } = match Options::from_args(&[program_name], args) {
        Ok(opts) => opts,
        Err(e) => {
            if e.status.is_err() {
                bail!(e.output);
            } else {
                println!("{}", e.output);
            }
            return Ok(());
        }
    };

    // Set stdin() in raw mode so we can send over individual keystrokes unbuffered
    stdin()
        .set_raw_mode()
        .context("Failed to set terminal raw mode")?;

    let type_ = match output_file {
        Some(_) => SerialType::File,
        None => SerialType::Stdout,
    };

    let params = SerialParameters {
        type_,
        hardware: SerialHardware::VirtioConsole,
        // Required only if type_ is SerialType::File or SerialType::UnixSocket
        path: output_file,
        input: input_file,
        num: 1,
        console: true,
        earlycon: false,
        // We do not support stdin-less mode
        stdin: true,
    };

    let res = run_console(&params, &socket);

    // Restore terminal capabilities back to what they were before
    stdin()
        .set_canon_mode()
        .context("Failed to restore canonical mode for terminal")?;

    if let Err(e) = res {
        bail!("error occurred: {:#}", e);
    }

    Ok(())
}
<|endoftext|>


<commit_before>use std::io::stdin;

enum Operator {
	Add,
	Subtract,
	Push,
	Pop,
	None,
}

fn parse(s: String) -> Operator {
	let c = s.chars().next();
	match c {
		Some(i) => match i {
		'+' => Operator::Add,
		'-' => Operator::Subtract,
		_ => Operator::Push,
		},
		None => Operator::None,
	}

}

fn main() {

	let mut x = stdin();

	loop{
		let mut y: String = "".to_string();
		let _ = x.read_line(&mut y);

		let z = parse(y);
	    println!("{}", match z{
	    	Operator::Add => "Addition!",
	    	Operator::Subtract => "Subtraction!",
	    	_ => "other!",
	    });
	}
}
<commit_msg>input parsing split by whitespace<commit_after>use std::io;

enum Operator {
	Add,
	Subtract,
	Push,
	Pop,
	None,
}

fn parse(s: &str) -> Operator {
	match s {
		"+" => Operator::Add,
		"-" => Operator::Subtract,
		"pop" => Operator::Pop,
		_ => Operator::None,
	}
}

fn process(s: String) {
	for o in s.split(" "){
		let b = parse(o.trim());
		println!("{}",match b {
			Operator::Add => "addition!",
			Operator::Subtract => "subtraction!",
			Operator::Pop => "popped!",
			_ => "other!",
		});
	}
}

fn main() {

	let mut x = io::stdin();

	loop{
		let mut y: String = "".to_string();
		let _ = x.read_line(&mut y);

	    process(y);
	}
}
<|endoftext|>


<commit_before>use nom_lua53;
use nom_lua53::Statement;
use nom_lua53::stat_expr_types::Block;
use types::LuaState;
use expression;
use std;
use super::{Result, var_to_string};
use super::types::LuaValue;

pub enum FlowControl {
    None,
    Return(Vec<LuaValue>),
    Break,
}

pub fn exec_statement(stmt: &Statement, ctx: &mut LuaState) -> Result<FlowControl> {
    match stmt {
        &Statement::LVarAssign(ref ass) => {
            let values = ass.vals
                .as_ref()
                .expect("There should be some values. Why isn't there any value?!");
            for (var, val) in ass.vars.iter().zip(values.iter()) {
                let computed_value = expression::eval_expr(val, &ctx);
                let local_scope = ctx.get_mutable_local_scope().unwrap();
                local_scope.set_string(var_to_string(var), &computed_value.unwrap());
            };
            Ok(FlowControl::None)
        }
        &Statement::Assignment(ref ass) => {
            let mut values = Vec::with_capacity(ass.vals.len());
            for exp in ass.vals.iter() {
                values.push(expression::eval_expr(&exp, &ctx)?);
            }

            for (prefexp, val) in ass.vars.iter().zip(values.drain(..)) {
                let assignment = expression::prefixexp::resolve_prefix_expr(
                    &prefexp.prefix,
                    &prefexp.suffix_chain,
                    ctx,
                )?;
                assignment.environment.set(&assignment.index, &val)?;
            }
            println!("Assigning {:?} to {:?}", ass.vals, ass.vars);
            Ok(FlowControl::None)
        }
        &Statement::Semicolon => {
            Ok(FlowControl::None)
        }
        &Statement::Ite(ref ite) => {
            exec_if_then_else(ite, ctx)
        }
        &Statement::While(ref blk) => {
            exec_while(blk, ctx)
        }
        &Statement::Break => Ok(FlowControl::Break),
        _ => {Ok(FlowControl::None)}
    }
}

pub fn exec_block(block: &Block, ctx: &mut LuaState) -> Result<FlowControl> {
    ctx.push_scope();
    for stmt in block.stmts.iter() {
        match exec_statement(&stmt, ctx)? {
            FlowControl::Break => return Ok(FlowControl::Break),
            FlowControl::Return(val) => return Ok(FlowControl::Return(val)),
            FlowControl::None => {}
        }
    };
    let ret = if let Some(ref expressions) = block.ret_stmt {
        let mut results = std::vec::Vec::with_capacity(expressions.len());
        for exp in expressions {
            results.push(expression::eval_expr(exp, ctx)?)
        }
        Ok(FlowControl::Return(results))
    } else {
        Ok(FlowControl::None)
    };

    ctx.pop_scope();
    return ret
}

pub fn exec_if_then_else(ite: &nom_lua53::IfThenElse, ctx: &mut LuaState) -> Result<FlowControl> {
    if expression::boolean_coercion(&expression::eval_expr(&ite.cond, ctx)?) {
        exec_block(&ite.then_blk, ctx)
    } else {
        match ite.elseifs.iter().fold(None,
         |current, &(ref exp, ref block)|
          if current.is_none() {
              match expression::eval_expr(&exp, ctx) {
                  Ok(_) => Some(exec_block(&block, ctx)),
                  Err(err) => Some(Err(err))
              }
          } else { current }) {
              Some(val) => val,
              None => match &ite.else_blk {
                  &Some(ref blk) => exec_block(blk, ctx),
                  &None => Ok(FlowControl::None)
              }
          }
    }
}

pub fn exec_while(blk: &nom_lua53::WhileBlock, ctx: &mut LuaState) -> Result<FlowControl> {
    while expression::boolean_coercion(&expression::eval_expr(&blk.cond, ctx)?) {
        let disrupt = exec_block(&blk.block, ctx)?;
        match disrupt {
            FlowControl::Return(val) => {
                return Ok(FlowControl::Return(val))
            }
            FlowControl::Break => {
                return Ok(FlowControl::None)
            }
            FlowControl::None => {}
        }
    }
    return Ok(FlowControl::None)
}<commit_msg>Cleanup the block scope on flow disruption<commit_after>use nom_lua53;
use nom_lua53::Statement;
use nom_lua53::stat_expr_types::Block;
use types::LuaState;
use expression;
use std;
use super::{Result, var_to_string};
use super::types::LuaValue;

#[derive(PartialEq)]
pub enum FlowControl {
    None,
    Return(Vec<LuaValue>),
    Break,
}

pub fn exec_statement(stmt: &Statement, ctx: &mut LuaState) -> Result<FlowControl> {
    match stmt {
        &Statement::LVarAssign(ref ass) => {
            let values = ass.vals
                .as_ref()
                .expect("There should be some values. Why isn't there any value?!");
            for (var, val) in ass.vars.iter().zip(values.iter()) {
                let computed_value = expression::eval_expr(val, &ctx);
                let local_scope = ctx.get_mutable_local_scope().unwrap();
                local_scope.set_string(var_to_string(var), &computed_value.unwrap());
            };
            Ok(FlowControl::None)
        }
        &Statement::Assignment(ref ass) => {
            let mut values = Vec::with_capacity(ass.vals.len());
            for exp in ass.vals.iter() {
                values.push(expression::eval_expr(&exp, &ctx)?);
            }

            for (prefexp, val) in ass.vars.iter().zip(values.drain(..)) {
                let assignment = expression::prefixexp::resolve_prefix_expr(
                    &prefexp.prefix,
                    &prefexp.suffix_chain,
                    ctx,
                )?;
                assignment.environment.set(&assignment.index, &val)?;
            }
            println!("Assigning {:?} to {:?}", ass.vals, ass.vars);
            Ok(FlowControl::None)
        }
        &Statement::Semicolon => {
            Ok(FlowControl::None)
        }
        &Statement::Ite(ref ite) => {
            exec_if_then_else(ite, ctx)
        }
        &Statement::While(ref blk) => {
            exec_while(blk, ctx)
        }
        &Statement::Break => Ok(FlowControl::Break),
        _ => {Ok(FlowControl::None)}
    }
}

pub fn exec_block(block: &Block, ctx: &mut LuaState) -> Result<FlowControl> {
    ctx.push_scope();
    let mut ret = FlowControl::None;
    for stmt in block.stmts.iter() {
        match exec_statement(&stmt, ctx)? {
            FlowControl::Break => { ret =  FlowControl::Break; break },
            FlowControl::Return(val) => { ret = FlowControl::Return(val); break },
            FlowControl::None => {}
        }
    };

    if ret != FlowControl::None {
        if let Some(ref expressions) = block.ret_stmt {
            let mut results = std::vec::Vec::with_capacity(expressions.len());
            for exp in expressions {
                results.push(expression::eval_expr(exp, ctx)?)
            }
            ret = FlowControl::Return(results)
        }
    }

    ctx.pop_scope();
    Ok(ret)
}

pub fn exec_if_then_else(ite: &nom_lua53::IfThenElse, ctx: &mut LuaState) -> Result<FlowControl> {
    if expression::boolean_coercion(&expression::eval_expr(&ite.cond, ctx)?) {
        exec_block(&ite.then_blk, ctx)
    } else {
        match ite.elseifs.iter().fold(None,
         |current, &(ref exp, ref block)|
          if current.is_none() {
              match expression::eval_expr(&exp, ctx) {
                  Ok(_) => Some(exec_block(&block, ctx)),
                  Err(err) => Some(Err(err))
              }
          } else { current }) {
              Some(val) => val,
              None => match &ite.else_blk {
                  &Some(ref blk) => exec_block(blk, ctx),
                  &None => Ok(FlowControl::None)
              }
          }
    }
}

pub fn exec_while(blk: &nom_lua53::WhileBlock, ctx: &mut LuaState) -> Result<FlowControl> {
    while expression::boolean_coercion(&expression::eval_expr(&blk.cond, ctx)?) {
        let disrupt = exec_block(&blk.block, ctx)?;
        match disrupt {
            FlowControl::Return(val) => {
                return Ok(FlowControl::Return(val))
            }
            FlowControl::Break => {
                return Ok(FlowControl::None)
            }
            FlowControl::None => {}
        }
    }
    return Ok(FlowControl::None)
}<|endoftext|>


<commit_before>use std;
use std::error::Error;
use std::io::Write;
use std::rc::Rc;
use std::result::Result;

use serde_yaml;

use super::traits::{ConvertResult, Converter, ImportResult, Importer};
use crate::build::Val;

pub struct YamlConverter {}

impl YamlConverter {
    pub fn new() -> Self {
        YamlConverter {}
    }

    fn convert_list(&self, items: &Vec<Rc<Val>>) -> std::io::Result<serde_yaml::Value> {
        let mut v = Vec::new();
        for val in items.iter() {
            v.push(self.convert_value(val)?);
        }
        Ok(serde_yaml::Value::Sequence(v))
    }

    fn convert_env(&self, items: &Vec<(String, String)>) -> std::io::Result<serde_yaml::Value> {
        let mut mp = serde_yaml::Mapping::new();
        for &(ref k, ref v) in items.iter() {
            mp.insert(
                serde_yaml::Value::String(k.clone()),
                serde_yaml::Value::String(v.clone()),
            );
        }
        Ok(serde_yaml::Value::Mapping(mp))
    }

    fn convert_tuple(&self, items: &Vec<(String, Rc<Val>)>) -> std::io::Result<serde_yaml::Value> {
        let mut mapping = serde_yaml::Mapping::new();
        for &(ref k, ref v) in items.iter() {
            mapping.insert(serde_yaml::Value::String(k.clone()), self.convert_value(v)?);
        }
        Ok(serde_yaml::Value::Mapping(mapping))
    }

    fn convert_value(&self, v: &Val) -> std::io::Result<serde_yaml::Value> {
        let yaml_val = match v {
            &Val::Boolean(b) => serde_yaml::Value::Bool(b),
            &Val::Empty => serde_yaml::Value::Null,
            &Val::Float(f) => match serde_yaml::to_value(f) {
                Ok(v) => v,
                _ => panic!("Float is too large or not a Number {}", f),
            },
            &Val::Int(i) => match serde_yaml::to_value(i) {
                Ok(v) => v,
                _ => panic!("Int is too large or not a Number {}", i),
            },
            &Val::Str(ref s) => serde_yaml::Value::String(s.clone()),
            &Val::Func(_) => {
                eprintln!("Skipping func encoding as null...");
                serde_yaml::Value::Null
            }
            &Val::Module(_) => {
                eprintln!("Skipping module encoding as null...");
                serde_yaml::Value::Null
            }
            &Val::Env(ref fs) => self.convert_env(fs)?,
            &Val::List(ref l) => self.convert_list(l)?,
            &Val::Tuple(ref t) => self.convert_tuple(t)?,
        };
        Ok(yaml_val)
    }

    fn merge_mapping_keys(
        &self,
        mut fs: &mut Vec<(String, Rc<Val>)>,
        m: &serde_yaml::Mapping,
    ) -> Result<(), Box<dyn Error>> {
        for (key, value) in m {
            // This is a little gross but since yaml allows maps to be keyed
            // by more than just a string it's necessary.
            let key = match key {
                serde_yaml::Value::Bool(b) => b.to_string(),
                serde_yaml::Value::Null => "null".to_string(),
                serde_yaml::Value::Number(n) => n.to_string(),
                serde_yaml::Value::String(s) => s.clone(),
                serde_yaml::Value::Sequence(_) | serde_yaml::Value::Mapping(_) => {
                    eprintln!("Unsupported key type in yaml import skipping");
                    continue;
                }
            };
            if key == "<<" {
                // TODO(jwall): Handle merge keys
                if let serde_yaml::Value::Mapping(merge_map) = value {
                    self.merge_mapping_keys(&mut fs, merge_map)?;
                }
            } else {
                fs.push((key, Rc::new(self.convert_yaml_val(&value)?)));
            }
        }
        Ok(())
    }

    fn convert_yaml_val(&self, v: &serde_yaml::Value) -> Result<Val, Box<dyn Error>> {
        Ok(match v {
            serde_yaml::Value::String(s) => Val::Str(s.clone()),
            serde_yaml::Value::Number(n) => {
                if let Some(i) = n.as_i64() {
                    Val::Int(i)
                } else {
                    Val::Float(n.as_f64().expect("Number was not an int or a float!!"))
                }
            }
            serde_yaml::Value::Bool(b) => Val::Boolean(*b),
            serde_yaml::Value::Null => Val::Empty,
            serde_yaml::Value::Sequence(l) => {
                let mut vs = Vec::with_capacity(l.len());
                for aval in l {
                    vs.push(Rc::new(self.convert_yaml_val(aval)?));
                }
                Val::List(vs)
            }
            serde_yaml::Value::Mapping(m) => {
                let mut fs = Vec::with_capacity(m.len());
                self.merge_mapping_keys(&mut fs, m)?;
                Val::Tuple(fs)
            }
        })
    }

    fn write(&self, v: &Val, w: &mut Write) -> ConvertResult {
        let jsn_val = self.convert_value(v)?;
        serde_yaml::to_writer(w, &jsn_val)?;
        Ok(())
    }
}

impl Converter for YamlConverter {
    fn convert(&self, v: Rc<Val>, mut w: &mut Write) -> ConvertResult {
        self.write(&v, &mut w)
    }

    fn file_ext(&self) -> String {
        String::from("yaml")
    }

    fn description(&self) -> String {
        "Convert ucg Vals into valid yaml.".to_string()
    }

    #[allow(unused_must_use)]
    fn help(&self) -> String {
        include_str!("yaml_help.txt").to_string()
    }
}

impl Importer for YamlConverter {
    fn import(&self, bytes: &[u8]) -> ImportResult {
        let json_val = serde_yaml::from_slice(bytes)?;
        Ok(Rc::new(self.convert_yaml_val(&json_val)?))
    }
}
<commit_msg>DEV: Collapse fields when merging yaml maps<commit_after>use std;
use std::collections::BTreeSet;
use std::error::Error;
use std::io::Write;
use std::rc::Rc;
use std::result::Result;

use serde_yaml;

use super::traits::{ConvertResult, Converter, ImportResult, Importer};
use crate::build::Val;

pub struct YamlConverter {}

impl YamlConverter {
    pub fn new() -> Self {
        YamlConverter {}
    }

    fn convert_list(&self, items: &Vec<Rc<Val>>) -> std::io::Result<serde_yaml::Value> {
        let mut v = Vec::new();
        for val in items.iter() {
            v.push(self.convert_value(val)?);
        }
        Ok(serde_yaml::Value::Sequence(v))
    }

    fn convert_env(&self, items: &Vec<(String, String)>) -> std::io::Result<serde_yaml::Value> {
        let mut mp = serde_yaml::Mapping::new();
        for &(ref k, ref v) in items.iter() {
            mp.insert(
                serde_yaml::Value::String(k.clone()),
                serde_yaml::Value::String(v.clone()),
            );
        }
        Ok(serde_yaml::Value::Mapping(mp))
    }

    fn convert_tuple(&self, items: &Vec<(String, Rc<Val>)>) -> std::io::Result<serde_yaml::Value> {
        let mut mapping = serde_yaml::Mapping::new();
        for &(ref k, ref v) in items.iter() {
            mapping.insert(serde_yaml::Value::String(k.clone()), self.convert_value(v)?);
        }
        Ok(serde_yaml::Value::Mapping(mapping))
    }

    fn convert_value(&self, v: &Val) -> std::io::Result<serde_yaml::Value> {
        let yaml_val = match v {
            &Val::Boolean(b) => serde_yaml::Value::Bool(b),
            &Val::Empty => serde_yaml::Value::Null,
            &Val::Float(f) => match serde_yaml::to_value(f) {
                Ok(v) => v,
                _ => panic!("Float is too large or not a Number {}", f),
            },
            &Val::Int(i) => match serde_yaml::to_value(i) {
                Ok(v) => v,
                _ => panic!("Int is too large or not a Number {}", i),
            },
            &Val::Str(ref s) => serde_yaml::Value::String(s.clone()),
            &Val::Func(_) => {
                eprintln!("Skipping func encoding as null...");
                serde_yaml::Value::Null
            }
            &Val::Module(_) => {
                eprintln!("Skipping module encoding as null...");
                serde_yaml::Value::Null
            }
            &Val::Env(ref fs) => self.convert_env(fs)?,
            &Val::List(ref l) => self.convert_list(l)?,
            &Val::Tuple(ref t) => self.convert_tuple(t)?,
        };
        Ok(yaml_val)
    }

    fn merge_mapping_keys(
        &self,
        mut fs: &mut Vec<(String, Rc<Val>)>,
        m: &serde_yaml::Mapping,
    ) -> Result<(), Box<dyn Error>> {
        for (key, value) in m {
            // This is a little gross but since yaml allows maps to be keyed
            // by more than just a string it's necessary.
            let key = match key {
                serde_yaml::Value::Bool(b) => b.to_string(),
                serde_yaml::Value::Null => "null".to_string(),
                serde_yaml::Value::Number(n) => n.to_string(),
                serde_yaml::Value::String(s) => s.clone(),
                serde_yaml::Value::Sequence(_) | serde_yaml::Value::Mapping(_) => {
                    eprintln!("Unsupported key type in yaml import skipping");
                    continue;
                }
            };
            if key == "<<" {
                // TODO(jwall): Handle merge keys
                if let serde_yaml::Value::Mapping(merge_map) = value {
                    self.merge_mapping_keys(&mut fs, merge_map)?;
                }
            } else {
                fs.push((key, Rc::new(self.convert_yaml_val(&value)?)));
            }
        }
        Ok(())
    }

    fn convert_yaml_val(&self, v: &serde_yaml::Value) -> Result<Val, Box<dyn Error>> {
        Ok(match v {
            serde_yaml::Value::String(s) => Val::Str(s.clone()),
            serde_yaml::Value::Number(n) => {
                if let Some(i) = n.as_i64() {
                    Val::Int(i)
                } else {
                    Val::Float(n.as_f64().expect("Number was not an int or a float!!"))
                }
            }
            serde_yaml::Value::Bool(b) => Val::Boolean(*b),
            serde_yaml::Value::Null => Val::Empty,
            serde_yaml::Value::Sequence(l) => {
                let mut vs = Vec::with_capacity(l.len());
                for aval in l {
                    vs.push(Rc::new(self.convert_yaml_val(aval)?));
                }
                Val::List(vs)
            }
            serde_yaml::Value::Mapping(m) => {
                let mut fs = Vec::with_capacity(m.len());
                self.merge_mapping_keys(&mut fs, m)?;
				fs.reverse();
				let mut seen_keys = BTreeSet::new();
				let mut collapsed = Vec::with_capacity(fs.len());
				for (k, val) in fs {
					if !seen_keys.contains(&k) {
						collapsed.push((k.clone(), val));
						seen_keys.insert(k);
					}
				}
				collapsed.reverse();
                Val::Tuple(collapsed)
            }
        })
    }

    fn write(&self, v: &Val, w: &mut Write) -> ConvertResult {
        let jsn_val = self.convert_value(v)?;
        serde_yaml::to_writer(w, &jsn_val)?;
        Ok(())
    }
}

impl Converter for YamlConverter {
    fn convert(&self, v: Rc<Val>, mut w: &mut Write) -> ConvertResult {
        self.write(&v, &mut w)
    }

    fn file_ext(&self) -> String {
        String::from("yaml")
    }

    fn description(&self) -> String {
        "Convert ucg Vals into valid yaml.".to_string()
    }

    #[allow(unused_must_use)]
    fn help(&self) -> String {
        include_str!("yaml_help.txt").to_string()
    }
}

impl Importer for YamlConverter {
    fn import(&self, bytes: &[u8]) -> ImportResult {
        let json_val = serde_yaml::from_slice(bytes)?;
        Ok(Rc::new(self.convert_yaml_val(&json_val)?))
    }
}
<|endoftext|>


<commit_before>use cfg_if::cfg_if;
use std::time::Instant;

/// Trait for the platform thread parker implementation.
///
/// All unsafe methods are unsafe because the Unix thread parker is based on
/// pthread mutexes and condvars. Those primitives must not be moved and used
/// from any other memory address than the one they were located at when they
/// were initialized. As such, it's UB to call any unsafe method on
/// `ThreadParkerT` if the implementing instance has moved since the last
/// call to any of the unsafe methods.
pub trait ThreadParkerT {
    type UnparkHandle: UnparkHandleT;

    const IS_CHEAP_TO_CONSTRUCT: bool;

    fn new() -> Self;

    /// Prepares the parker. This should be called before adding it to the queue.
    unsafe fn prepare_park(&self);

    /// Checks if the park timed out. This should be called while holding the
    /// queue lock after park_until has returned false.
    unsafe fn timed_out(&self) -> bool;

    /// Parks the thread until it is unparked. This should be called after it has
    /// been added to the queue, after unlocking the queue.
    unsafe fn park(&self);

    /// Parks the thread until it is unparked or the timeout is reached. This
    /// should be called after it has been added to the queue, after unlocking
    /// the queue. Returns true if we were unparked and false if we timed out.
    unsafe fn park_until(&self, timeout: Instant) -> bool;

    /// Locks the parker to prevent the target thread from exiting. This is
    /// necessary to ensure that thread-local ThreadData objects remain valid.
    /// This should be called while holding the queue lock.
    unsafe fn unpark_lock(&self) -> Self::UnparkHandle;
}

/// Handle for a thread that is about to be unparked. We need to mark the thread
/// as unparked while holding the queue lock, but we delay the actual unparking
/// until after the queue lock is released.
pub trait UnparkHandleT {
    /// Wakes up the parked thread. This should be called after the queue lock is
    /// released to avoid blocking the queue for too long.
    ///
    /// This method is unsafe for the same reason as the unsafe methods in
    /// `ThreadParkerT`.
    #[inline]
    unsafe fn unpark(self);
}

cfg_if! {
    if #[cfg(all(has_sized_atomics, target_os = "linux"))] {
        #[path = "linux.rs"]
        mod imp;
    } else if #[cfg(unix)] {
        #[path = "unix.rs"]
        mod imp;
    } else if #[cfg(windows)] {
        #[path = "windows/mod.rs"]
        mod imp;
    } else if #[cfg(all(has_sized_atomics, target_os = "redox"))] {
        #[path = "redox.rs"]
        mod imp;
    } else if #[cfg(all(target_env = "sgx", target_vendor = "fortanix"))] {
        #[path = "sgx.rs"]
        mod imp;
    } else if #[cfg(all(
        feature = "nightly",
        target_arch = "wasm32",
        target_feature = "atomics"
    ))] {
        #[path = "wasm.rs"]
        mod imp;
    } else if #[cfg(all(feature = "nightly", target_os = "cloudabi"))] {
        #[path = "cloudabi.rs"]
        mod imp;
    } else {
        #[path = "generic.rs"]
        mod imp;
    }
}

pub use self::imp::{thread_yield, ThreadParker, UnparkHandle};
<commit_msg>Make Android use futex based parker<commit_after>use cfg_if::cfg_if;
use std::time::Instant;

/// Trait for the platform thread parker implementation.
///
/// All unsafe methods are unsafe because the Unix thread parker is based on
/// pthread mutexes and condvars. Those primitives must not be moved and used
/// from any other memory address than the one they were located at when they
/// were initialized. As such, it's UB to call any unsafe method on
/// `ThreadParkerT` if the implementing instance has moved since the last
/// call to any of the unsafe methods.
pub trait ThreadParkerT {
    type UnparkHandle: UnparkHandleT;

    const IS_CHEAP_TO_CONSTRUCT: bool;

    fn new() -> Self;

    /// Prepares the parker. This should be called before adding it to the queue.
    unsafe fn prepare_park(&self);

    /// Checks if the park timed out. This should be called while holding the
    /// queue lock after park_until has returned false.
    unsafe fn timed_out(&self) -> bool;

    /// Parks the thread until it is unparked. This should be called after it has
    /// been added to the queue, after unlocking the queue.
    unsafe fn park(&self);

    /// Parks the thread until it is unparked or the timeout is reached. This
    /// should be called after it has been added to the queue, after unlocking
    /// the queue. Returns true if we were unparked and false if we timed out.
    unsafe fn park_until(&self, timeout: Instant) -> bool;

    /// Locks the parker to prevent the target thread from exiting. This is
    /// necessary to ensure that thread-local ThreadData objects remain valid.
    /// This should be called while holding the queue lock.
    unsafe fn unpark_lock(&self) -> Self::UnparkHandle;
}

/// Handle for a thread that is about to be unparked. We need to mark the thread
/// as unparked while holding the queue lock, but we delay the actual unparking
/// until after the queue lock is released.
pub trait UnparkHandleT {
    /// Wakes up the parked thread. This should be called after the queue lock is
    /// released to avoid blocking the queue for too long.
    ///
    /// This method is unsafe for the same reason as the unsafe methods in
    /// `ThreadParkerT`.
    #[inline]
    unsafe fn unpark(self);
}

cfg_if! {
    if #[cfg(all(has_sized_atomics, any(target_os = "linux", target_os = "android")))] {
        #[path = "linux.rs"]
        mod imp;
    } else if #[cfg(unix)] {
        #[path = "unix.rs"]
        mod imp;
    } else if #[cfg(windows)] {
        #[path = "windows/mod.rs"]
        mod imp;
    } else if #[cfg(all(has_sized_atomics, target_os = "redox"))] {
        #[path = "redox.rs"]
        mod imp;
    } else if #[cfg(all(target_env = "sgx", target_vendor = "fortanix"))] {
        #[path = "sgx.rs"]
        mod imp;
    } else if #[cfg(all(
        feature = "nightly",
        target_arch = "wasm32",
        target_feature = "atomics"
    ))] {
        #[path = "wasm.rs"]
        mod imp;
    } else if #[cfg(all(feature = "nightly", target_os = "cloudabi"))] {
        #[path = "cloudabi.rs"]
        mod imp;
    } else {
        #[path = "generic.rs"]
        mod imp;
    }
}

pub use self::imp::{thread_yield, ThreadParker, UnparkHandle};
<|endoftext|>


<commit_before>#![no_main]

use gimli::{
    read::{BaseAddresses, CieOrFde, EhFrame, UninitializedUnwindContext, UnwindSection},
    LittleEndian,
};
use libfuzzer_sys::fuzz_target;

fuzz_target!(|eh_frame: &[u8]| {
    let eh_frame = EhFrame::new(&eh_frame, LittleEndian);

    let mut ctx = UninitializedUnwindContext::new();
    let bases = BaseAddresses::default()
        .set_eh_frame(0)
        .set_eh_frame_hdr(0)
        .set_text(0)
        .set_got(0);

    let mut entries = eh_frame.entries(&bases);
    while let Ok(Some(entry)) = entries.next() {
        match entry {
            CieOrFde::Cie(_) => continue,
            CieOrFde::Fde(partial) => {
                if let Ok(fde) = partial.parse(EhFrame::cie_from_offset) {
                    if let Ok(mut table) = fde.rows(&eh_frame, &bases, &mut ctx) {
                        while let Ok(Some(_row)) = table.next_row() {
                            continue;
                        }
                    }
                }
            }
        };
    }
});
<commit_msg>Fix fuzz<commit_after>#![no_main]

use gimli::{
    read::{BaseAddresses, CieOrFde, EhFrame, UnwindContext, UnwindSection},
    LittleEndian,
};
use libfuzzer_sys::fuzz_target;

fuzz_target!(|eh_frame: &[u8]| {
    let eh_frame = EhFrame::new(&eh_frame, LittleEndian);

    let mut ctx = Box::new(UnwindContext::new());
    let bases = BaseAddresses::default()
        .set_eh_frame(0)
        .set_eh_frame_hdr(0)
        .set_text(0)
        .set_got(0);

    let mut entries = eh_frame.entries(&bases);
    while let Ok(Some(entry)) = entries.next() {
        match entry {
            CieOrFde::Cie(_) => continue,
            CieOrFde::Fde(partial) => {
                if let Ok(fde) = partial.parse(EhFrame::cie_from_offset) {
                    if let Ok(mut table) = fde.rows(&eh_frame, &bases, &mut ctx) {
                        while let Ok(Some(_row)) = table.next_row() {
                            continue;
                        }
                    }
                }
            }
        };
    }
});
<|endoftext|>


<commit_before>//  Copyright 2019 Twitter, Inc
//
//  Licensed under the Apache License, Version 2.0 (the "License");
//  you may not use this file except in compliance with the License.
//  You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
//  Unless required by applicable law or agreed to in writing, software
//  distributed under the License is distributed on an "AS IS" BASIS,
//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//  See the License for the specific language governing permissions and
//  limitations under the License.

use hsl::HSL;
use png::HasParameters;
use rusttype::{point, FontCollection, PositionedGlyph, Scale};

use datastructures::histogram::{Histogram, Latched};
use datastructures::Heatmap;
use logger::*;

use std::collections::HashMap;
use std::fs::File;
use std::io::BufWriter;
use std::path::Path;

pub fn save_waterfall<S: ::std::hash::BuildHasher>(
    heatmap: &Heatmap,
    file: &str,
    labels: HashMap<usize, String, S>,
    interval: usize,
) {
    debug!("saving waterfall");
    let height = heatmap.slices();
    let width = heatmap.buckets();

    // create image buffer
    let mut buffer = ImageBuffer::<ColorRgb>::new(width, height);

    let mut y = 0;
    let histogram = Latched::new(0, heatmap.highest_count(), 3);
    for slice in heatmap {
        for b in slice.histogram() {
            let magnitude = (b.count() as f64 / b.width() as f64).ceil() as usize;
            if magnitude > 0 {
                histogram.incr(magnitude, 1);
            }
        }
    }

    if let Some(min) = histogram.percentile(0.0) {
        // let min = histogram.percentile(0.0).unwrap();
        let low = histogram.percentile(0.01).unwrap();
        let mid = histogram.percentile(0.50).unwrap();
        let high = histogram.percentile(0.99).unwrap();
        let max = histogram.percentile(1.0).unwrap();

        debug!(
            "min: {} low: {} mid: {} high: {} max: {}",
            min, low, mid, high, max
        );

        let mut values: Vec<usize> = labels.keys().cloned().collect();
        values.sort();
        let mut l = 0;
        for (y, slice) in heatmap.into_iter().enumerate() {
            for (x, bucket) in slice.histogram().into_iter().enumerate() {
                let value = color_from_value(bucket.count() / bucket.width(), low, mid, high);
                buffer.set_pixel(x, y, value);
            }
        }

        if !values.is_empty() {
            let mut x = 0;
            let y = 0;
            let slice = heatmap.into_iter().next().unwrap();
            for bucket in slice.histogram() {
                let value = bucket.max();
                if value >= values[l] {
                    if let Some(label) = labels.get(&values[l]) {
                        let overlay = string_buffer(label, 25.0);
                        buffer.overlay(&overlay, x, y);
                        buffer.vertical_line(
                            x,
                            ColorRgb {
                                r: 255,
                                g: 255,
                                b: 255,
                            },
                        );
                    }
                    l += 1;
                    if l >= values.len() {
                        break;
                    }
                }
                x += 1;
            }
        }
    }

    let mut begin = heatmap.begin_utc();
    for (y, slice) in heatmap.into_iter().enumerate() {
        let slice_begin = slice.begin_utc();
        if slice_begin - begin >= time::Duration::nanoseconds(interval as i64) {
            let label = format!("{}", slice_begin.rfc3339());
            let overlay = string_buffer(&label, 25.0);
            buffer.overlay(&overlay, 0, y + 2);
            buffer.horizontal_line(
                y,
                ColorRgb {
                    r: 255,
                    g: 255,
                    b: 255,
                },
            );
            begin = slice_begin;
        }
    }

    let _ = buffer.write_png(file);
}

#[derive(Clone, Copy, Debug, PartialEq)]
struct ColorRgb {
    pub r: u8,
    pub g: u8,
    pub b: u8,
}

struct ImageBuffer<T> {
    buffer: Vec<Vec<T>>,
    height: usize,
    width: usize,
}

fn string_buffer(string: &str, size: f32) -> ImageBuffer<ColorRgb> {
    // load font
    let font_data = dejavu::sans_mono::regular();
    let collection = FontCollection::from_bytes(font_data as &[u8]).unwrap();
    let font = collection.into_font().unwrap();

    // size and scaling
    let height: f32 = size;
    let pixel_height = height.ceil() as usize;
    let scale = Scale {
        x: height * 1.0,
        y: height,
    };

    let v_metrics = font.v_metrics(scale);
    let offset = point(0.0, v_metrics.ascent);

    let glyphs: Vec<PositionedGlyph> = font.layout(string, scale, offset).collect();

    let width = glyphs
        .iter()
        .map(|g| g.unpositioned().h_metrics().advance_width)
        .fold(0.0, |x, y| x + y)
        .ceil() as usize;

    let mut overlay = ImageBuffer::<ColorRgb>::new(width, pixel_height);

    for g in glyphs {
        if let Some(bb) = g.pixel_bounding_box() {
            g.draw(|x, y, v| {
                let x = (x as i32 + bb.min.x) as usize;
                let y = (y as i32 + bb.min.y) as usize;
                if v > 0.25 {
                    overlay.set_pixel(
                        x,
                        y,
                        ColorRgb {
                            r: 255,
                            g: 255,
                            b: 255,
                        },
                    );
                }
            })
        }
    }

    overlay
}

/// maps a value to a color based on a low point, mid point, and high point
/// values below low will clip to black
/// mid point is the transition between luminosity (black-blue) and hue (blue->red) ramps
/// values above high will clip to red
fn color_from_value(value: usize, low: usize, mid: usize, high: usize) -> ColorRgb {
    let hsl = if value < low {
        HSL {
            h: 250.0,
            s: 1.0,
            l: 0.0,
        }
    } else if value < mid {
        HSL {
            h: 250.0,
            s: 1.0,
            l: (value as f64 / mid as f64) * 0.5,
        }
    } else if value < high {
        HSL {
            h: 250.0 - (250.0 * (value - mid) as f64 / high as f64),
            s: 1.0,
            l: 0.5,
        }
    } else {
        HSL {
            h: 0.0,
            s: 1.0,
            l: 0.5,
        }
    };

    let (r, g, b) = hsl.to_rgb();

    ColorRgb { r, g, b }
}

impl ImageBuffer<ColorRgb> {
    pub fn new(width: usize, height: usize) -> ImageBuffer<ColorRgb> {
        let background = ColorRgb { r: 0, g: 0, b: 0 };
        let mut row = Vec::<ColorRgb>::with_capacity(width);
        for _ in 0..width {
            row.push(background);
        }
        let mut buffer = Vec::<Vec<ColorRgb>>::with_capacity(height);
        for _ in 0..height {
            buffer.push(row.clone());
        }
        ImageBuffer {
            buffer,
            height,
            width,
        }
    }

    pub fn write_png(self, file: &str) -> Result<(), &'static str> {
        let mut buffer = Vec::<u8>::with_capacity(self.height * self.width);
        for row in 0..self.height {
            for col in 0..self.width {
                let pixel = self.buffer[row][col];
                buffer.push(pixel.r);
                buffer.push(pixel.g);
                buffer.push(pixel.b);
            }
        }
        let path = &Path::new(&file);
        if let Ok(file) = File::create(path) {
            let w = BufWriter::new(file);
            let mut encoder = png::Encoder::new(w, self.width as u32, self.height as u32);
            encoder.set(png::ColorType::RGB).set(png::BitDepth::Eight);
            if let Ok(mut writer) = encoder.write_header() {
                if writer.write_image_data(&buffer).is_ok() {
                    Ok(())
                } else {
                    Err("Error writing PNG data")
                }
            } else {
                Err("Error writing PNG header")
            }
        } else {
            Err("Error creating file")
        }
    }

    pub fn set_pixel(&mut self, x: usize, y: usize, value: ColorRgb) {
        if x < self.width && y < self.height {
            self.buffer[y][x] = value;
        }
    }

    pub fn overlay(&mut self, other: &ImageBuffer<ColorRgb>, x: usize, y: usize) {
        let ignore = ColorRgb { r: 0, g: 0, b: 0 };
        for sx in 0..other.width {
            for sy in 0..other.height {
                if (other.buffer[sy][sx] != ignore)
                    && (((sy + y) < self.height) && ((sx + x) < self.width))
                {
                    self.buffer[(sy + y)][(sx + x)] = other.buffer[sy][sx];
                }
            }
        }
    }

    pub fn horizontal_line(&mut self, y: usize, color: ColorRgb) {
        for x in 0..self.width {
            self.buffer[y][x] = color;
        }
    }

    pub fn vertical_line(&mut self, x: usize, color: ColorRgb) {
        for y in 0..self.height {
            self.buffer[y][x] = color;
        }
    }
}
<commit_msg>remove unused variable (#196)<commit_after>//  Copyright 2019 Twitter, Inc
//
//  Licensed under the Apache License, Version 2.0 (the "License");
//  you may not use this file except in compliance with the License.
//  You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
//  Unless required by applicable law or agreed to in writing, software
//  distributed under the License is distributed on an "AS IS" BASIS,
//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//  See the License for the specific language governing permissions and
//  limitations under the License.

use hsl::HSL;
use png::HasParameters;
use rusttype::{point, FontCollection, PositionedGlyph, Scale};

use datastructures::histogram::{Histogram, Latched};
use datastructures::Heatmap;
use logger::*;

use std::collections::HashMap;
use std::fs::File;
use std::io::BufWriter;
use std::path::Path;

pub fn save_waterfall<S: ::std::hash::BuildHasher>(
    heatmap: &Heatmap,
    file: &str,
    labels: HashMap<usize, String, S>,
    interval: usize,
) {
    debug!("saving waterfall");
    let height = heatmap.slices();
    let width = heatmap.buckets();

    // create image buffer
    let mut buffer = ImageBuffer::<ColorRgb>::new(width, height);

    let histogram = Latched::new(0, heatmap.highest_count(), 3);
    for slice in heatmap {
        for b in slice.histogram() {
            let magnitude = (b.count() as f64 / b.width() as f64).ceil() as usize;
            if magnitude > 0 {
                histogram.incr(magnitude, 1);
            }
        }
    }

    if let Some(min) = histogram.percentile(0.0) {
        // let min = histogram.percentile(0.0).unwrap();
        let low = histogram.percentile(0.01).unwrap();
        let mid = histogram.percentile(0.50).unwrap();
        let high = histogram.percentile(0.99).unwrap();
        let max = histogram.percentile(1.0).unwrap();

        debug!(
            "min: {} low: {} mid: {} high: {} max: {}",
            min, low, mid, high, max
        );

        let mut values: Vec<usize> = labels.keys().cloned().collect();
        values.sort();
        let mut l = 0;
        for (y, slice) in heatmap.into_iter().enumerate() {
            for (x, bucket) in slice.histogram().into_iter().enumerate() {
                let value = color_from_value(bucket.count() / bucket.width(), low, mid, high);
                buffer.set_pixel(x, y, value);
            }
        }

        if !values.is_empty() {
            let mut x = 0;
            let y = 0;
            let slice = heatmap.into_iter().next().unwrap();
            for bucket in slice.histogram() {
                let value = bucket.max();
                if value >= values[l] {
                    if let Some(label) = labels.get(&values[l]) {
                        let overlay = string_buffer(label, 25.0);
                        buffer.overlay(&overlay, x, y);
                        buffer.vertical_line(
                            x,
                            ColorRgb {
                                r: 255,
                                g: 255,
                                b: 255,
                            },
                        );
                    }
                    l += 1;
                    if l >= values.len() {
                        break;
                    }
                }
                x += 1;
            }
        }
    }

    let mut begin = heatmap.begin_utc();
    for (y, slice) in heatmap.into_iter().enumerate() {
        let slice_begin = slice.begin_utc();
        if slice_begin - begin >= time::Duration::nanoseconds(interval as i64) {
            let label = format!("{}", slice_begin.rfc3339());
            let overlay = string_buffer(&label, 25.0);
            buffer.overlay(&overlay, 0, y + 2);
            buffer.horizontal_line(
                y,
                ColorRgb {
                    r: 255,
                    g: 255,
                    b: 255,
                },
            );
            begin = slice_begin;
        }
    }

    let _ = buffer.write_png(file);
}

#[derive(Clone, Copy, Debug, PartialEq)]
struct ColorRgb {
    pub r: u8,
    pub g: u8,
    pub b: u8,
}

struct ImageBuffer<T> {
    buffer: Vec<Vec<T>>,
    height: usize,
    width: usize,
}

fn string_buffer(string: &str, size: f32) -> ImageBuffer<ColorRgb> {
    // load font
    let font_data = dejavu::sans_mono::regular();
    let collection = FontCollection::from_bytes(font_data as &[u8]).unwrap();
    let font = collection.into_font().unwrap();

    // size and scaling
    let height: f32 = size;
    let pixel_height = height.ceil() as usize;
    let scale = Scale {
        x: height * 1.0,
        y: height,
    };

    let v_metrics = font.v_metrics(scale);
    let offset = point(0.0, v_metrics.ascent);

    let glyphs: Vec<PositionedGlyph> = font.layout(string, scale, offset).collect();

    let width = glyphs
        .iter()
        .map(|g| g.unpositioned().h_metrics().advance_width)
        .fold(0.0, |x, y| x + y)
        .ceil() as usize;

    let mut overlay = ImageBuffer::<ColorRgb>::new(width, pixel_height);

    for g in glyphs {
        if let Some(bb) = g.pixel_bounding_box() {
            g.draw(|x, y, v| {
                let x = (x as i32 + bb.min.x) as usize;
                let y = (y as i32 + bb.min.y) as usize;
                if v > 0.25 {
                    overlay.set_pixel(
                        x,
                        y,
                        ColorRgb {
                            r: 255,
                            g: 255,
                            b: 255,
                        },
                    );
                }
            })
        }
    }

    overlay
}

/// maps a value to a color based on a low point, mid point, and high point
/// values below low will clip to black
/// mid point is the transition between luminosity (black-blue) and hue (blue->red) ramps
/// values above high will clip to red
fn color_from_value(value: usize, low: usize, mid: usize, high: usize) -> ColorRgb {
    let hsl = if value < low {
        HSL {
            h: 250.0,
            s: 1.0,
            l: 0.0,
        }
    } else if value < mid {
        HSL {
            h: 250.0,
            s: 1.0,
            l: (value as f64 / mid as f64) * 0.5,
        }
    } else if value < high {
        HSL {
            h: 250.0 - (250.0 * (value - mid) as f64 / high as f64),
            s: 1.0,
            l: 0.5,
        }
    } else {
        HSL {
            h: 0.0,
            s: 1.0,
            l: 0.5,
        }
    };

    let (r, g, b) = hsl.to_rgb();

    ColorRgb { r, g, b }
}

impl ImageBuffer<ColorRgb> {
    pub fn new(width: usize, height: usize) -> ImageBuffer<ColorRgb> {
        let background = ColorRgb { r: 0, g: 0, b: 0 };
        let mut row = Vec::<ColorRgb>::with_capacity(width);
        for _ in 0..width {
            row.push(background);
        }
        let mut buffer = Vec::<Vec<ColorRgb>>::with_capacity(height);
        for _ in 0..height {
            buffer.push(row.clone());
        }
        ImageBuffer {
            buffer,
            height,
            width,
        }
    }

    pub fn write_png(self, file: &str) -> Result<(), &'static str> {
        let mut buffer = Vec::<u8>::with_capacity(self.height * self.width);
        for row in 0..self.height {
            for col in 0..self.width {
                let pixel = self.buffer[row][col];
                buffer.push(pixel.r);
                buffer.push(pixel.g);
                buffer.push(pixel.b);
            }
        }
        let path = &Path::new(&file);
        if let Ok(file) = File::create(path) {
            let w = BufWriter::new(file);
            let mut encoder = png::Encoder::new(w, self.width as u32, self.height as u32);
            encoder.set(png::ColorType::RGB).set(png::BitDepth::Eight);
            if let Ok(mut writer) = encoder.write_header() {
                if writer.write_image_data(&buffer).is_ok() {
                    Ok(())
                } else {
                    Err("Error writing PNG data")
                }
            } else {
                Err("Error writing PNG header")
            }
        } else {
            Err("Error creating file")
        }
    }

    pub fn set_pixel(&mut self, x: usize, y: usize, value: ColorRgb) {
        if x < self.width && y < self.height {
            self.buffer[y][x] = value;
        }
    }

    pub fn overlay(&mut self, other: &ImageBuffer<ColorRgb>, x: usize, y: usize) {
        let ignore = ColorRgb { r: 0, g: 0, b: 0 };
        for sx in 0..other.width {
            for sy in 0..other.height {
                if (other.buffer[sy][sx] != ignore)
                    && (((sy + y) < self.height) && ((sx + x) < self.width))
                {
                    self.buffer[(sy + y)][(sx + x)] = other.buffer[sy][sx];
                }
            }
        }
    }

    pub fn horizontal_line(&mut self, y: usize, color: ColorRgb) {
        for x in 0..self.width {
            self.buffer[y][x] = color;
        }
    }

    pub fn vertical_line(&mut self, x: usize, color: ColorRgb) {
        for y in 0..self.height {
            self.buffer[y][x] = color;
        }
    }
}
<|endoftext|>


<commit_before>/// Used to align a widget vertical or horizontal.
#[derive(Copy, Clone, PartialEq, Debug)]
pub enum Alignment {
    Start,
    Center,
    End,
    Stretch,
}

impl Default for Alignment {
    fn default() -> Self {
        Alignment::Stretch
    }
}

impl Alignment {
    /// Calculates the position (x or y) of the widget depending on the available measure, the goal measure
    /// margin and alignment.
    pub fn align_position(
        &self,
        available_measure: f64,
        measure: f64,
        margin_start: f64,
        margin_end: f64,
    ) -> f64 {
        match self {
            Alignment::End => available_measure - measure - margin_end,
            Alignment::Center => (available_measure - measure) / 2.0,
            _ => margin_start,
        }
    }

    /// Calculates the measure (measure or height) of the widget depending on the available measure, the goal measure
    /// margin and horizontal alignment.
    pub fn align_measure(
        &self,
        available_measure: f64,
        measure: f64,
        margin_start: f64,
        margin_end: f64,
    ) -> f64 {
        match self {
            Alignment::Stretch => available_measure - margin_start - margin_end,
            _ => measure,
        }
    }
}

impl From<&str> for Alignment {
    fn from(t: &str) -> Self {
        match t {
            "End" | "end" => Alignment::End,
            "Center" | "center" => Alignment::Center,
            "Start" | "start" => Alignment::Start,
            _ => Alignment::Stretch,
        }
    }
}

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

    #[test]
    fn test_align_position() {
        let available_measure = 100.0;
        let measure = 50.0;

        let alignment = Alignment::Stretch;
        assert_eq!(
            alignment.align_position(available_measure, measure, 0.0, 0.0),
            0.0
        );

        let alignment = Alignment::Center;
        assert_eq!(
            alignment.align_position(available_measure, measure, 0.0, 0.0),
            25.0
        );

        let alignment = Alignment::Start;
        assert_eq!(
            alignment.align_position(available_measure, measure, 0.0, 0.0),
            0.0
        );

        let alignment = Alignment::End;
        assert_eq!(
            alignment.align_position(available_measure, measure, 0.0, 0.0),
            50.0
        );
    }

    #[test]
    fn test_align_measure() {
        let available_measure = 100.0;
        let measure = 50.0;

        let alignment = Alignment::Stretch;
        assert_eq!(
            alignment.align_measure(available_measure, measure, 0.0, 0.0),
            available_measure
        );

        let alignment = Alignment::Center;
        assert_eq!(
            alignment.align_measure(available_measure, measure, 0.0, 0.0),
            measure
        );

        let alignment = Alignment::Start;
        assert_eq!(
            alignment.align_measure(available_measure, measure, 0.0, 0.0),
            measure
        );

        let alignment = Alignment::End;
        assert_eq!(
            alignment.align_measure(available_measure, measure, 0.0, 0.0),
            measure
        );
    }

    #[test]
    fn test_into() {
        let alignment: Alignment = "start".into();
        assert_eq!(alignment, Alignment::Start);

        let alignment: Alignment = "start".into();
        assert_eq!(alignment, Alignment::Start);

        let alignment: Alignment = "Center".into();
        assert_eq!(alignment, Alignment::Center);

        let alignment: Alignment = "center".into();
        assert_eq!(alignment, Alignment::Center);

        let alignment: Alignment = "end".into();
        assert_eq!(alignment, Alignment::End);

        let alignment: Alignment = "end".into();
        assert_eq!(alignment, Alignment::End);

        let alignment: Alignment = "Stretch".into();
        assert_eq!(alignment, Alignment::Stretch);

        let alignment: Alignment = "stretch".into();
        assert_eq!(alignment, Alignment::Stretch);

        let alignment: Alignment = "other".into();
        assert_eq!(alignment, Alignment::Stretch);
    }
}
<commit_msg>Pass by values for copy types<commit_after>/// Used to align a widget vertical or horizontal.
#[derive(Copy, Clone, PartialEq, Debug)]
pub enum Alignment {
    Start,
    Center,
    End,
    Stretch,
}

impl Default for Alignment {
    fn default() -> Self {
        Alignment::Stretch
    }
}

impl Alignment {
    /// Calculates the position (x or y) of the widget depending on the available measure, the goal measure
    /// margin and alignment.
    pub fn align_position(
        self,
        available_measure: f64,
        measure: f64,
        margin_start: f64,
        margin_end: f64,
    ) -> f64 {
        match self {
            Alignment::End => available_measure - measure - margin_end,
            Alignment::Center => (available_measure - measure) / 2.0,
            _ => margin_start,
        }
    }

    /// Calculates the measure (measure or height) of the widget depending on the available measure, the goal measure
    /// margin and horizontal alignment.
    pub fn align_measure(
        self,
        available_measure: f64,
        measure: f64,
        margin_start: f64,
        margin_end: f64,
    ) -> f64 {
        match self {
            Alignment::Stretch => available_measure - margin_start - margin_end,
            _ => measure,
        }
    }
}

impl From<&str> for Alignment {
    fn from(t: &str) -> Self {
        match t {
            "End" | "end" => Alignment::End,
            "Center" | "center" => Alignment::Center,
            "Start" | "start" => Alignment::Start,
            _ => Alignment::Stretch,
        }
    }
}

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

    #[test]
    fn test_align_position() {
        let available_measure = 100.0;
        let measure = 50.0;

        let alignment = Alignment::Stretch;
        assert_eq!(
            alignment.align_position(available_measure, measure, 0.0, 0.0),
            0.0
        );

        let alignment = Alignment::Center;
        assert_eq!(
            alignment.align_position(available_measure, measure, 0.0, 0.0),
            25.0
        );

        let alignment = Alignment::Start;
        assert_eq!(
            alignment.align_position(available_measure, measure, 0.0, 0.0),
            0.0
        );

        let alignment = Alignment::End;
        assert_eq!(
            alignment.align_position(available_measure, measure, 0.0, 0.0),
            50.0
        );
    }

    #[test]
    fn test_align_measure() {
        let available_measure = 100.0;
        let measure = 50.0;

        let alignment = Alignment::Stretch;
        assert_eq!(
            alignment.align_measure(available_measure, measure, 0.0, 0.0),
            available_measure
        );

        let alignment = Alignment::Center;
        assert_eq!(
            alignment.align_measure(available_measure, measure, 0.0, 0.0),
            measure
        );

        let alignment = Alignment::Start;
        assert_eq!(
            alignment.align_measure(available_measure, measure, 0.0, 0.0),
            measure
        );

        let alignment = Alignment::End;
        assert_eq!(
            alignment.align_measure(available_measure, measure, 0.0, 0.0),
            measure
        );
    }

    #[test]
    fn test_into() {
        let alignment: Alignment = "start".into();
        assert_eq!(alignment, Alignment::Start);

        let alignment: Alignment = "start".into();
        assert_eq!(alignment, Alignment::Start);

        let alignment: Alignment = "Center".into();
        assert_eq!(alignment, Alignment::Center);

        let alignment: Alignment = "center".into();
        assert_eq!(alignment, Alignment::Center);

        let alignment: Alignment = "end".into();
        assert_eq!(alignment, Alignment::End);

        let alignment: Alignment = "end".into();
        assert_eq!(alignment, Alignment::End);

        let alignment: Alignment = "Stretch".into();
        assert_eq!(alignment, Alignment::Stretch);

        let alignment: Alignment = "stretch".into();
        assert_eq!(alignment, Alignment::Stretch);

        let alignment: Alignment = "other".into();
        assert_eq!(alignment, Alignment::Stretch);
    }
}
<|endoftext|>


<commit_before>extern crate cbindgen;

use cbindgen::*;
use std::path::Path;
use std::process::Command;
use std::{env, fs, str};

fn style_str(style: Style) -> &'static str {
    match style {
        Style::Both => "both",
        Style::Tag => "tag",
        Style::Type => "type",
    }
}

fn run_cbindgen(
    cbindgen_path: &'static str,
    path: &Path,
    output: &Path,
    language: Language,
    cpp_compat: bool,
    style: Option<Style>,
) {
    let program = Path::new(cbindgen_path);
    let mut command = Command::new(&program);
    match language {
        Language::Cxx => {}
        Language::C => {
            command.arg("--lang").arg("c");

            if cpp_compat {
                command.arg("--cpp-compat");
            }
        }
    }

    if let Some(style) = style {
        command.arg("--style").arg(style_str(style));
    }

    command.arg("-o").arg(output);

    if env::var("CBINDGEN_TEST_VERIFY").is_ok() {
        command.arg("--verify");
    }

    let mut config = path.clone().to_path_buf();
    config.set_extension("toml");
    if config.exists() {
        command.arg("--config").arg(config);
    }

    command.arg(path);

    println!("Running: {:?}", command);
    let cbindgen_output = command.output().expect("failed to execute process");
    assert!(
        cbindgen_output.status.success(),
        "cbindgen failed: {:?} with error: {}",
        output,
        str::from_utf8(&cbindgen_output.stderr).unwrap_or_default()
    );
}

fn compile(cbindgen_output: &Path, tests_path: &Path, language: Language, style: Option<Style>) {
    let cc = match language {
        Language::Cxx => env::var("CXX").unwrap_or_else(|_| "g++".to_owned()),
        Language::C => env::var("CC").unwrap_or_else(|_| "gcc".to_owned()),
    };

    let mut object = cbindgen_output.to_path_buf();
    object.set_extension("o");

    let mut command = Command::new(cc);
    command.arg("-D").arg("DEFINED");
    command.arg("-c").arg(cbindgen_output);
    command.arg("-o").arg(&object);
    command.arg("-I").arg(tests_path);
    command.arg("-Wall");
    command.arg("-Werror");
    // `swift_name` is not recognzied by gcc.
    command.arg("-Wno-attributes");
    if let Language::Cxx = language {
        // enum class is a c++11 extension which makes g++ on macos 10.14 error out
        // inline variables are are a c++17 extension
        command.arg("-std=c++17");
        if let Ok(extra_flags) = env::var("CXXFLAGS") {
            command.args(extra_flags.split_whitespace());
        }
    } else {
        if let Ok(extra_flags) = env::var("CFLAGS") {
            command.args(extra_flags.split_whitespace());
        }
    }

    if let Some(style) = style {
        command.arg("-D");
        command.arg(format!(
            "CBINDGEN_STYLE_{}",
            style_str(style).to_uppercase()
        ));
    }

    println!("Running: {:?}", command);
    let out = command.output().expect("failed to compile");
    assert!(out.status.success(), "Output failed to compile: {:?}", out);

    if object.exists() {
        fs::remove_file(object).unwrap();
    }
}

fn run_compile_test(
    cbindgen_path: &'static str,
    name: &'static str,
    path: &Path,
    language: Language,
    cpp_compat: bool,
    style: Option<Style>,
) {
    let crate_dir = env::var("CARGO_MANIFEST_DIR").unwrap();
    let tests_path = Path::new(&crate_dir).join("tests");
    let mut output = tests_path.join("expectations");
    if let Some(style) = style {
        match style {
            Style::Both => {
                output.push("both");
            }
            Style::Tag => {
                output.push("tag");
            }
            Style::Type => {}
        }
    }

    let ext = match language {
        Language::Cxx => "cpp",
        Language::C => {
            if cpp_compat {
                "compat.c"
            } else {
                "c"
            }
        }
    };

    output.push(format!("{}.{}", name, ext));

    run_cbindgen(cbindgen_path, path, &output, language, cpp_compat, style);
    compile(&output, &tests_path, language, style);

    if language == Language::C && cpp_compat {
        compile(&output, &tests_path, Language::Cxx, style)
    }
}

fn test_file(cbindgen_path: &'static str, name: &'static str, filename: &'static str) {
    let test = Path::new(filename);
    for style in &[Style::Type, Style::Tag, Style::Both] {
        for cpp_compat in &[true, false] {
            run_compile_test(
                cbindgen_path,
                name,
                &test,
                Language::C,
                *cpp_compat,
                Some(*style),
            );
        }
    }
    run_compile_test(
        cbindgen_path,
        name,
        &test,
        Language::Cxx,
        /* cpp_compat = */ false,
        None,
    );
}

macro_rules! test_file {
    ($cbindgen_path:expr, $test_function_name:ident, $name:expr, $file:tt) => {
        #[test]
        fn $test_function_name() {
            test_file($cbindgen_path, $name, $file);
        }
    };
}

// This file is generated by build.rs
include!(concat!(env!("OUT_DIR"), "/tests.rs"));
<commit_msg>Generate test object files in a temporary directory instead of in-tree<commit_after>extern crate cbindgen;

use cbindgen::*;
use std::path::Path;
use std::process::Command;
use std::{env, fs, str};

fn style_str(style: Style) -> &'static str {
    match style {
        Style::Both => "both",
        Style::Tag => "tag",
        Style::Type => "type",
    }
}

fn run_cbindgen(
    cbindgen_path: &'static str,
    path: &Path,
    output: &Path,
    language: Language,
    cpp_compat: bool,
    style: Option<Style>,
) {
    let program = Path::new(cbindgen_path);
    let mut command = Command::new(&program);
    match language {
        Language::Cxx => {}
        Language::C => {
            command.arg("--lang").arg("c");

            if cpp_compat {
                command.arg("--cpp-compat");
            }
        }
    }

    if let Some(style) = style {
        command.arg("--style").arg(style_str(style));
    }

    command.arg("-o").arg(output);

    if env::var("CBINDGEN_TEST_VERIFY").is_ok() {
        command.arg("--verify");
    }

    let mut config = path.clone().to_path_buf();
    config.set_extension("toml");
    if config.exists() {
        command.arg("--config").arg(config);
    }

    command.arg(path);

    println!("Running: {:?}", command);
    let cbindgen_output = command.output().expect("failed to execute process");
    assert!(
        cbindgen_output.status.success(),
        "cbindgen failed: {:?} with error: {}",
        output,
        str::from_utf8(&cbindgen_output.stderr).unwrap_or_default()
    );
}

fn compile(
    cbindgen_output: &Path,
    tests_path: &Path,
    tmp_dir: &Path,
    language: Language,
    style: Option<Style>,
) {
    let cc = match language {
        Language::Cxx => env::var("CXX").unwrap_or_else(|_| "g++".to_owned()),
        Language::C => env::var("CC").unwrap_or_else(|_| "gcc".to_owned()),
    };

    let mut object = tmp_dir.join(cbindgen_output);
    object.set_extension("o");

    let mut command = Command::new(cc);
    command.arg("-D").arg("DEFINED");
    command.arg("-c").arg(cbindgen_output);
    command.arg("-o").arg(&object);
    command.arg("-I").arg(tests_path);
    command.arg("-Wall");
    command.arg("-Werror");
    // `swift_name` is not recognzied by gcc.
    command.arg("-Wno-attributes");
    if let Language::Cxx = language {
        // enum class is a c++11 extension which makes g++ on macos 10.14 error out
        // inline variables are are a c++17 extension
        command.arg("-std=c++17");
        if let Ok(extra_flags) = env::var("CXXFLAGS") {
            command.args(extra_flags.split_whitespace());
        }
    } else {
        if let Ok(extra_flags) = env::var("CFLAGS") {
            command.args(extra_flags.split_whitespace());
        }
    }

    if let Some(style) = style {
        command.arg("-D");
        command.arg(format!(
            "CBINDGEN_STYLE_{}",
            style_str(style).to_uppercase()
        ));
    }

    println!("Running: {:?}", command);
    let out = command.output().expect("failed to compile");
    assert!(out.status.success(), "Output failed to compile: {:?}", out);

    if object.exists() {
        fs::remove_file(object).unwrap();
    }
}

fn run_compile_test(
    cbindgen_path: &'static str,
    name: &'static str,
    path: &Path,
    tmp_dir: &Path,
    language: Language,
    cpp_compat: bool,
    style: Option<Style>,
) {
    let crate_dir = env::var("CARGO_MANIFEST_DIR").unwrap();
    let tests_path = Path::new(&crate_dir).join("tests");
    let mut output = tests_path.join("expectations");
    if let Some(style) = style {
        match style {
            Style::Both => {
                output.push("both");
            }
            Style::Tag => {
                output.push("tag");
            }
            Style::Type => {}
        }
    }

    let ext = match language {
        Language::Cxx => "cpp",
        Language::C => {
            if cpp_compat {
                "compat.c"
            } else {
                "c"
            }
        }
    };

    output.push(format!("{}.{}", name, ext));

    run_cbindgen(cbindgen_path, path, &output, language, cpp_compat, style);
    compile(&output, &tests_path, tmp_dir, language, style);

    if language == Language::C && cpp_compat {
        compile(&output, &tests_path, tmp_dir, Language::Cxx, style)
    }
}

fn test_file(cbindgen_path: &'static str, name: &'static str, filename: &'static str) {
    let test = Path::new(filename);
    let tmp_dir = tempfile::Builder::new()
        .prefix("cbindgen-test-output")
        .tempdir()
        .expect("Creating tmp dir failed");
    let tmp_dir = tmp_dir.path();
    for style in &[Style::Type, Style::Tag, Style::Both] {
        for cpp_compat in &[true, false] {
            run_compile_test(
                cbindgen_path,
                name,
                &test,
                tmp_dir,
                Language::C,
                *cpp_compat,
                Some(*style),
            );
        }
    }
    run_compile_test(
        cbindgen_path,
        name,
        &test,
        tmp_dir,
        Language::Cxx,
        /* cpp_compat = */ false,
        None,
    );
}

macro_rules! test_file {
    ($cbindgen_path:expr, $test_function_name:ident, $name:expr, $file:tt) => {
        #[test]
        fn $test_function_name() {
            test_file($cbindgen_path, $name, $file);
        }
    };
}

// This file is generated by build.rs
include!(concat!(env!("OUT_DIR"), "/tests.rs"));
<|endoftext|>


<commit_before>#[crate_type = "bin"];
#[feature(globs)];
#[feature(managed_boxes)];

extern mod protobuf;

use std::rt::io;
use std::rt::io::Reader;
use std::rt::io::Writer;
use std::str;
use plugin::*;
use protobuf::*;
use protobuf::codegen::*;

mod descriptor {
    pub use protobuf::descriptor::*;
}

mod plugin;

fn main() {
    let req = parse_from_reader::<CodeGeneratorRequest>(@io::stdin() as @Reader);
    let gen_options = GenOptions {
        dummy: false,
    };
    let result = gen(req.proto_file, &gen_options);
    let mut resp = CodeGeneratorResponse::new();
    resp.file = do result.map |file| {
        let mut r = CodeGeneratorResponse_File::new();
        r.name = Some(file.name.to_owned());
        r.content = Some(str::from_utf8(file.content));
        r
    };
    resp.write_to_writer(@io::stdout() as @Writer);
}
<commit_msg>Workaround of hangup of stdin() on Linux<commit_after>#[crate_type = "bin"];
#[feature(globs)];
#[feature(managed_boxes)];

extern mod protobuf;

use std::rt::io;
use std::rt::io::Reader;
use std::rt::io::Writer;
use std::str;
use plugin::*;
use protobuf::*;
use protobuf::codegen::*;

mod descriptor {
    pub use protobuf::descriptor::*;
}

mod plugin;

fn main() {
    // io::stdin() hangs on EOF on Linux
    // https://github.com/mozilla/rust/issues/10237
    let req = parse_from_reader::<CodeGeneratorRequest>(@io::native::stdio::stdin() as @Reader);
    let gen_options = GenOptions {
        dummy: false,
    };
    let result = gen(req.proto_file, &gen_options);
    let mut resp = CodeGeneratorResponse::new();
    resp.file = do result.map |file| {
        let mut r = CodeGeneratorResponse_File::new();
        r.name = Some(file.name.to_owned());
        r.content = Some(str::from_utf8(file.content));
        r
    };
    resp.write_to_writer(@io::stdout() as @Writer);
}
<|endoftext|>