<commit_before>use std::fs::read_to_string;
use std::fs::File;
use std::io::Read;
use std::path::Path;

use anyhow::{bail, Context, Result};
use pueue_lib::network::message::*;
use snap::read::FrameDecoder;
use tempfile::TempDir;

use crate::fixtures::*;
use crate::helper::*;

/// This function creates files `[1-20]` in the specified directory.
/// The return value is the expected output.
///
/// If `partial == true`, the expected output are only the last 5 lines.
fn create_test_files(path: &Path, partial: bool) -> Result<String> {
    // Convert numbers from 1 to 01, so they're correctly ordered when using `ls`.
    let names: Vec<String> = (0..20)
        .map(|number| {
            if number < 10 {
                let mut name = "0".to_string();
                name.push_str(&number.to_string());
                name
            } else {
                number.to_string()
            }
        })
        .collect();

    for name in &names {
        File::create(path.join(name.to_string()))?;
    }

    // Only return the last 5 lines if partial output is requested.
    if partial {
        return Ok((15..20).fold(String::new(), |mut full, name| {
            full.push_str(&name.to_string());
            full.push('\n');
            full
        }));
    }

    // Create the full expected output.
    let mut expected_output = names.join("\n");
    expected_output.push('\n');
    Ok(expected_output)
}

// Log output is send in a compressed form from the daemon.
// We have to unpack it first.
fn decompress_log(bytes: Vec<u8>) -> Result<String> {
    let mut decoder = FrameDecoder::new(&bytes[..]);
    let mut output = String::new();
    decoder
        .read_to_string(&mut output)
        .context("Failed to decompress remote log output")?;

    Ok(output)
}

#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
/// Make sure that receiving partial output from the daemon works.
async fn test_full_log() -> Result<()> {
    let daemon = daemon().await?;
    let shared = &daemon.settings.shared;

    // Create a temporary directory and put some files into it.
    let tempdir = TempDir::new().unwrap();
    let tempdir_path = tempdir.path();
    let expected_output =
        create_test_files(tempdir_path, false).context("Failed to create test files.")?;

    // Add a task that lists those files and wait for it to finish.
    let command = format!("ls {:?}", tempdir_path);
    assert_success(add_task(shared, &command, false).await?);
    wait_for_task_condition(shared, 0, |task| task.is_done()).await?;

    // Request all log lines
    let log_message = LogRequestMessage {
        task_ids: vec![0],
        send_logs: true,
        lines: None,
    };
    let response = send_message(shared, Message::Log(log_message)).await?;
    let logs = match response {
        Message::LogResponse(logs) => logs,
        _ => bail!("Received non LogResponse: {:#?}", response),
    };

    // Get the received output
    let logs = logs.get(&0).unwrap();
    let output = logs
        .output
        .clone()
        .context("Didn't find output on TaskLogMessage")?;
    let output = decompress_log(output)?;

    // Make sure it's the same
    assert_eq!(output, expected_output);

    Ok(())
}

#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
/// Make sure that receiving partial output from the daemon works.
async fn test_partial_log() -> Result<()> {
    let daemon = daemon().await?;
    let shared = &daemon.settings.shared;

    // Create a temporary directory and put some files into it.
    let tempdir = TempDir::new().unwrap();
    let tempdir_path = tempdir.path();
    let expected_output =
        create_test_files(tempdir_path, true).context("Failed to create test files.")?;

    // Add a task that lists those files and wait for it to finish.
    let command = format!("ls {:?}", tempdir_path);
    assert_success(add_task(shared, &command, false).await?);
    wait_for_task_condition(shared, 0, |task| task.is_done()).await?;

    // Debug output to see what the file actually looks like:
    let real_log_path = shared.pueue_directory().join("task_logs").join("0.log");
    let content = read_to_string(real_log_path).context("Failed to read actual file")?;
    println!("Actual log file contents: \n{}", content);

    // Request a partial log for task 0
    let log_message = LogRequestMessage {
        task_ids: vec![0],
        send_logs: true,
        lines: Some(5),
    };
    let response = send_message(shared, Message::Log(log_message)).await?;
    let logs = match response {
        Message::LogResponse(logs) => logs,
        _ => bail!("Received non LogResponse: {:#?}", response),
    };

    // Get the received output
    let logs = logs.get(&0).unwrap();
    let output = logs
        .output
        .clone()
        .context("Didn't find output on TaskLogMessage")?;
    let output = decompress_log(output)?;

    // Make sure it's the same
    assert_eq!(output, expected_output);

    Ok(())
}
<commit_msg>tests: Add test for log order in file<commit_after>use std::fs::read_to_string;
use std::fs::File;
use std::io::Read;
use std::path::Path;

use anyhow::{bail, Context, Result};
use pueue_lib::network::message::*;
use snap::read::FrameDecoder;
use tempfile::TempDir;

use crate::fixtures::*;
use crate::helper::*;

/// This function creates files `[1-20]` in the specified directory.
/// The return value is the expected output.
///
/// If `partial == true`, the expected output are only the last 5 lines.
fn create_test_files(path: &Path, partial: bool) -> Result<String> {
    // Convert numbers from 1 to 01, so they're correctly ordered when using `ls`.
    let names: Vec<String> = (0..20)
        .map(|number| {
            if number < 10 {
                let mut name = "0".to_string();
                name.push_str(&number.to_string());
                name
            } else {
                number.to_string()
            }
        })
        .collect();

    for name in &names {
        File::create(path.join(name.to_string()))?;
    }

    // Only return the last 5 lines if partial output is requested.
    if partial {
        return Ok((15..20).fold(String::new(), |mut full, name| {
            full.push_str(&name.to_string());
            full.push('\n');
            full
        }));
    }

    // Create the full expected output.
    let mut expected_output = names.join("\n");
    expected_output.push('\n');
    Ok(expected_output)
}

// Log output is send in a compressed form from the daemon.
// We have to unpack it first.
fn decompress_log(bytes: Vec<u8>) -> Result<String> {
    let mut decoder = FrameDecoder::new(&bytes[..]);
    let mut output = String::new();
    decoder
        .read_to_string(&mut output)
        .context("Failed to decompress remote log output")?;

    Ok(output)
}

#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
/// Make sure that receiving partial output from the daemon works.
async fn test_full_log() -> Result<()> {
    let daemon = daemon().await?;
    let shared = &daemon.settings.shared;

    // Create a temporary directory and put some files into it.
    let tempdir = TempDir::new().unwrap();
    let tempdir_path = tempdir.path();
    let expected_output =
        create_test_files(tempdir_path, false).context("Failed to create test files.")?;

    // Add a task that lists those files and wait for it to finish.
    let command = format!("ls {:?}", tempdir_path);
    assert_success(add_task(shared, &command, false).await?);
    wait_for_task_condition(shared, 0, |task| task.is_done()).await?;

    // Request all log lines
    let log_message = LogRequestMessage {
        task_ids: vec![0],
        send_logs: true,
        lines: None,
    };
    let response = send_message(shared, Message::Log(log_message)).await?;
    let logs = match response {
        Message::LogResponse(logs) => logs,
        _ => bail!("Received non LogResponse: {:#?}", response),
    };

    // Get the received output
    let logs = logs.get(&0).unwrap();
    let output = logs
        .output
        .clone()
        .context("Didn't find output on TaskLogMessage")?;
    let output = decompress_log(output)?;

    // Make sure it's the same
    assert_eq!(output, expected_output);

    Ok(())
}

#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
/// Make sure that receiving partial output from the daemon works.
async fn test_partial_log() -> Result<()> {
    let daemon = daemon().await?;
    let shared = &daemon.settings.shared;

    // Create a temporary directory and put some files into it.
    let tempdir = TempDir::new().unwrap();
    let tempdir_path = tempdir.path();
    let expected_output =
        create_test_files(tempdir_path, true).context("Failed to create test files.")?;

    // Add a task that lists those files and wait for it to finish.
    let command = format!("ls {:?}", tempdir_path);
    assert_success(add_task(shared, &command, false).await?);
    wait_for_task_condition(shared, 0, |task| task.is_done()).await?;

    // Debug output to see what the file actually looks like:
    let real_log_path = shared.pueue_directory().join("task_logs").join("0.log");
    let content = read_to_string(real_log_path).context("Failed to read actual file")?;
    println!("Actual log file contents: \n{}", content);

    // Request a partial log for task 0
    let log_message = LogRequestMessage {
        task_ids: vec![0],
        send_logs: true,
        lines: Some(5),
    };
    let response = send_message(shared, Message::Log(log_message)).await?;
    let logs = match response {
        Message::LogResponse(logs) => logs,
        _ => bail!("Received non LogResponse: {:#?}", response),
    };

    // Get the received output
    let logs = logs.get(&0).unwrap();
    let output = logs
        .output
        .clone()
        .context("Didn't find output on TaskLogMessage")?;
    let output = decompress_log(output)?;

    // Make sure it's the same
    assert_eq!(output, expected_output);

    Ok(())
}

#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
/// Ensure that stdout and stderr are properly ordered in log output.
async fn test_correct_log_order() -> Result<()> {
    let daemon = daemon().await?;
    let shared = &daemon.settings.shared;

    // Add a task that lists those files and wait for it to finish.
    let command = "echo 'test' && echo 'error' && echo 'test'";
    assert_success(add_task(shared, &command, false).await?);
    wait_for_task_condition(shared, 0, |task| task.is_done()).await?;

    // Request all log lines
    let log_message = LogRequestMessage {
        task_ids: vec![0],
        send_logs: true,
        lines: None,
    };
    let response = send_message(shared, Message::Log(log_message)).await?;
    let logs = match response {
        Message::LogResponse(logs) => logs,
        _ => bail!("Received non LogResponse: {:#?}", response),
    };

    // Get the received output
    let logs = logs.get(&0).unwrap();
    let output = logs
        .output
        .clone()
        .context("Didn't find output on TaskLogMessage")?;
    let output = decompress_log(output)?;

    // Make sure it's the same
    assert_eq!(output, "test\nerror\ntest\n");

    Ok(())
}
<|endoftext|>


<commit_before>// Copyright (c) The Libra Core Contributors
// SPDX-License-Identifier: Apache-2.0

use crate::{FuzzTarget, FuzzTargetImpl};
use anyhow::{format_err, Result};
use once_cell::sync::Lazy;
use std::{collections::BTreeMap, env};

// List fuzz target modules here.
mod consensus;
mod executor;
mod json_rpc_service;
mod mempool;
mod move_vm;
mod network;
mod proof;
mod safety_rules;
mod secure_json_rpc_client;
mod secure_storage_vault;
mod state_sync;
mod storage;
mod transaction;
mod vm;

static ALL_TARGETS: Lazy<BTreeMap<&'static str, Box<dyn FuzzTargetImpl>>> = Lazy::new(|| {
    // List fuzz targets here in this format:
    let targets: Vec<Box<dyn FuzzTargetImpl>> = vec![
        // Consensus
        Box::new(consensus::ConsensusProposal::default()),
        // Executor
        Box::new(executor::ExecuteAndCommitBlocks::default()),
        Box::new(executor::ExecuteAndCommitChunk::default()),
        // JSON RPC Service
        Box::new(json_rpc_service::JsonRpcSubmitTransactionRequest::default()),
        // Mempool
        Box::new(mempool::MempoolIncomingTransactions::default()),
        // Move VM
        Box::new(move_vm::ValueTarget::default()),
        // Proof
        Box::new(proof::TestAccumulatorProofFuzzer::default()),
        Box::new(proof::SparseMerkleProofFuzzer::default()),
        Box::new(proof::TestAccumulatorRangeProofFuzzer::default()),
        Box::new(proof::TransactionInfoWithProofFuzzer::default()),
        Box::new(proof::AccountStateProofFuzzer::default()),
        Box::new(proof::EventProofFuzzer::default()),
        Box::new(proof::TransactionListProofFuzzer::default()),
        // Network
        Box::new(network::RpcInboundRequest::default()),
        Box::new(network::NetworkNoiseInitiator::default()),
        Box::new(network::NetworkNoiseResponder::default()),
        Box::new(network::NetworkNoiseStream::default()),
        Box::new(network::NetworkHandshakeExchange::default()),
        Box::new(network::NetworkHandshakeNegotiation::default()),
        // Safety Rules Server (LSR)
        Box::new(safety_rules::SafetyRulesConstructAndSignVote::default()),
        Box::new(safety_rules::SafetyRulesInitialize::default()),
        Box::new(safety_rules::SafetyRulesHandleMessage::default()),
        Box::new(safety_rules::SafetyRulesSignProposal::default()),
        Box::new(safety_rules::SafetyRulesSignTimeout::default()),
        // Secure JSON RPC Client
        Box::new(secure_json_rpc_client::SecureJsonRpcSubmitTransaction::default()),
        Box::new(secure_json_rpc_client::SecureJsonRpcGetAccountState::default()),
        Box::new(secure_json_rpc_client::SecureJsonRpcGetAccountTransaction::default()),
        // Secure Storage Vault
        Box::new(secure_storage_vault::VaultGenericResponse::default()),
        Box::new(secure_storage_vault::VaultPolicyReadResponse::default()),
        Box::new(secure_storage_vault::VaultPolicyListResponse::default()),
        Box::new(secure_storage_vault::VaultSecretListResponse::default()),
        Box::new(secure_storage_vault::VaultSecretReadResponse::default()),
        Box::new(secure_storage_vault::VaultTokenCreateResponse::default()),
        Box::new(secure_storage_vault::VaultTokenRenewResponse::default()),
        Box::new(secure_storage_vault::VaultTransitCreateResponse::default()),
        Box::new(secure_storage_vault::VaultTransitExportResponse::default()),
        Box::new(secure_storage_vault::VaultTransitListResponse::default()),
        Box::new(secure_storage_vault::VaultTransitReadResponse::default()),
        Box::new(secure_storage_vault::VaultTransitRestoreResponse::default()),
        Box::new(secure_storage_vault::VaultTransitSignResponse::default()),
        Box::new(secure_storage_vault::VaultUnsealedResponse::default()),
        // State Sync
        Box::new(state_sync::StateSyncMsg::default()),
        // Storage
        // Box::new(storage::StorageSaveBlocks::default()),
        Box::new(storage::StorageSchemaDecode::default()),
        Box::new(storage::JellyfishGetWithProof::default()),
        Box::new(storage::JellyfishGetWithProofWithDistinctLastNibble::default()),
        Box::new(storage::JellyfishGetRangeProof::default()),
        Box::new(storage::AccumulatorFrozenSubtreeHashes::default()),
        Box::new(storage::AccumulatorProof::default()),
        Box::new(storage::AccumulatorConsistencyProof::default()),
        Box::new(storage::AccumulatorRangeProof::default()),
        Box::new(storage::AccumulatorAppendMany::default()),
        Box::new(storage::AccumulatorAppendEmpty::default()),
        // Transaction
        Box::new(transaction::LanguageTransactionExecution::default()),
        Box::new(transaction::SignedTransactionTarget::default()),
        // VM
        Box::new(vm::CompiledModuleTarget::default()),
    ];
    targets
        .into_iter()
        .map(|target| (target.name(), target))
        .collect()
});

impl FuzzTarget {
    /// The environment variable used for passing fuzz targets to child processes.
    pub(crate) const ENV_VAR: &'static str = "FUZZ_TARGET";

    /// Get the current fuzz target from the environment.
    pub fn from_env() -> Result<Self> {
        let name = env::var(Self::ENV_VAR)?;
        Self::by_name(&name).ok_or_else(|| format_err!("Unknown fuzz target '{}'", name))
    }

    /// Get a fuzz target by name.
    pub fn by_name(name: &str) -> Option<Self> {
        ALL_TARGETS.get(name).map(|target| FuzzTarget(&**target))
    }

    /// A list of all fuzz targets.
    pub fn all_targets() -> impl Iterator<Item = Self> {
        ALL_TARGETS.values().map(|target| FuzzTarget(&**target))
    }
}
<commit_msg>[fuzz] disable JellyfishGetWithProof harness<commit_after>// Copyright (c) The Libra Core Contributors
// SPDX-License-Identifier: Apache-2.0

use crate::{FuzzTarget, FuzzTargetImpl};
use anyhow::{format_err, Result};
use once_cell::sync::Lazy;
use std::{collections::BTreeMap, env};

// List fuzz target modules here.
mod consensus;
mod executor;
mod json_rpc_service;
mod mempool;
mod move_vm;
mod network;
mod proof;
mod safety_rules;
mod secure_json_rpc_client;
mod secure_storage_vault;
mod state_sync;
mod storage;
mod transaction;
mod vm;

static ALL_TARGETS: Lazy<BTreeMap<&'static str, Box<dyn FuzzTargetImpl>>> = Lazy::new(|| {
    // List fuzz targets here in this format:
    let targets: Vec<Box<dyn FuzzTargetImpl>> = vec![
        // Consensus
        Box::new(consensus::ConsensusProposal::default()),
        // Executor
        Box::new(executor::ExecuteAndCommitBlocks::default()),
        Box::new(executor::ExecuteAndCommitChunk::default()),
        // JSON RPC Service
        Box::new(json_rpc_service::JsonRpcSubmitTransactionRequest::default()),
        // Mempool
        Box::new(mempool::MempoolIncomingTransactions::default()),
        // Move VM
        Box::new(move_vm::ValueTarget::default()),
        // Proof
        Box::new(proof::TestAccumulatorProofFuzzer::default()),
        Box::new(proof::SparseMerkleProofFuzzer::default()),
        Box::new(proof::TestAccumulatorRangeProofFuzzer::default()),
        Box::new(proof::TransactionInfoWithProofFuzzer::default()),
        Box::new(proof::AccountStateProofFuzzer::default()),
        Box::new(proof::EventProofFuzzer::default()),
        Box::new(proof::TransactionListProofFuzzer::default()),
        // Network
        Box::new(network::RpcInboundRequest::default()),
        Box::new(network::NetworkNoiseInitiator::default()),
        Box::new(network::NetworkNoiseResponder::default()),
        Box::new(network::NetworkNoiseStream::default()),
        Box::new(network::NetworkHandshakeExchange::default()),
        Box::new(network::NetworkHandshakeNegotiation::default()),
        // Safety Rules Server (LSR)
        Box::new(safety_rules::SafetyRulesConstructAndSignVote::default()),
        Box::new(safety_rules::SafetyRulesInitialize::default()),
        Box::new(safety_rules::SafetyRulesHandleMessage::default()),
        Box::new(safety_rules::SafetyRulesSignProposal::default()),
        Box::new(safety_rules::SafetyRulesSignTimeout::default()),
        // Secure JSON RPC Client
        Box::new(secure_json_rpc_client::SecureJsonRpcSubmitTransaction::default()),
        Box::new(secure_json_rpc_client::SecureJsonRpcGetAccountState::default()),
        Box::new(secure_json_rpc_client::SecureJsonRpcGetAccountTransaction::default()),
        // Secure Storage Vault
        Box::new(secure_storage_vault::VaultGenericResponse::default()),
        Box::new(secure_storage_vault::VaultPolicyReadResponse::default()),
        Box::new(secure_storage_vault::VaultPolicyListResponse::default()),
        Box::new(secure_storage_vault::VaultSecretListResponse::default()),
        Box::new(secure_storage_vault::VaultSecretReadResponse::default()),
        Box::new(secure_storage_vault::VaultTokenCreateResponse::default()),
        Box::new(secure_storage_vault::VaultTokenRenewResponse::default()),
        Box::new(secure_storage_vault::VaultTransitCreateResponse::default()),
        Box::new(secure_storage_vault::VaultTransitExportResponse::default()),
        Box::new(secure_storage_vault::VaultTransitListResponse::default()),
        Box::new(secure_storage_vault::VaultTransitReadResponse::default()),
        Box::new(secure_storage_vault::VaultTransitRestoreResponse::default()),
        Box::new(secure_storage_vault::VaultTransitSignResponse::default()),
        Box::new(secure_storage_vault::VaultUnsealedResponse::default()),
        // State Sync
        Box::new(state_sync::StateSyncMsg::default()),
        // Storage
        // Box::new(storage::StorageSaveBlocks::default()),
        Box::new(storage::StorageSchemaDecode::default()),
        //Box::new(storage::JellyfishGetWithProof::default()),
        Box::new(storage::JellyfishGetWithProofWithDistinctLastNibble::default()),
        Box::new(storage::JellyfishGetRangeProof::default()),
        Box::new(storage::AccumulatorFrozenSubtreeHashes::default()),
        Box::new(storage::AccumulatorProof::default()),
        Box::new(storage::AccumulatorConsistencyProof::default()),
        Box::new(storage::AccumulatorRangeProof::default()),
        Box::new(storage::AccumulatorAppendMany::default()),
        Box::new(storage::AccumulatorAppendEmpty::default()),
        // Transaction
        Box::new(transaction::LanguageTransactionExecution::default()),
        Box::new(transaction::SignedTransactionTarget::default()),
        // VM
        Box::new(vm::CompiledModuleTarget::default()),
    ];
    targets
        .into_iter()
        .map(|target| (target.name(), target))
        .collect()
});

impl FuzzTarget {
    /// The environment variable used for passing fuzz targets to child processes.
    pub(crate) const ENV_VAR: &'static str = "FUZZ_TARGET";

    /// Get the current fuzz target from the environment.
    pub fn from_env() -> Result<Self> {
        let name = env::var(Self::ENV_VAR)?;
        Self::by_name(&name).ok_or_else(|| format_err!("Unknown fuzz target '{}'", name))
    }

    /// Get a fuzz target by name.
    pub fn by_name(name: &str) -> Option<Self> {
        ALL_TARGETS.get(name).map(|target| FuzzTarget(&**target))
    }

    /// A list of all fuzz targets.
    pub fn all_targets() -> impl Iterator<Item = Self> {
        ALL_TARGETS.values().map(|target| FuzzTarget(&**target))
    }
}
<|endoftext|>


<commit_before>use std::fmt;

pub trait XYPair {
    fn as_tuple(&self) -> (int, int);
}

#[deriving(Copy)]
pub struct Point {
    pub x: int,
    pub y: int
}

impl Point {

    pub fn new(x: int, y: int) -> Point {
        Point { x: x, y: y }
    }

    pub fn zero() -> Point {
        Point { x: 0, y: 0 }
    }

    pub fn move_dir(&self, dir: Direction) -> Point {
        *self + dir.as_tuple()
    }

}

impl Add<Point, Point> for Point {
    fn add(self, other: Point) -> Point {
        let (ox, oy) = other.as_tuple();
        Point { x: self.x + ox, y: self.y + oy }
    }
}

impl Add<(int, int), Point> for Point {
    fn add(self, other: (int, int)) -> Point {
        let (ox, oy) = other;
        Point { x: self.x + ox, y: self.y + oy }
    }
}

impl fmt::Show for Point {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "Point({}, {})", self.x, self.y)
    }
}

impl XYPair for Point {
    fn as_tuple(&self) -> (int, int) {
        (self.x, self.y)
    }
}

pub enum Direction {
    Up,
    Down,
    Left,
    Right,
}

impl XYPair for Direction {
    fn as_tuple(&self) -> (int, int) {
        match *self {
            Direction::Up      => (  0, -1),
            Direction::Down    => (  0,  1),
            Direction::Left    => ( -1,  0),
            Direction::Right   => (  1,  0),
        }
    }
}
<commit_msg>Remove redundant implementation of Show for Point<commit_after>pub trait XYPair {
    fn as_tuple(&self) -> (int, int);
}

#[deriving(Show, Copy)]
pub struct Point {
    pub x: int,
    pub y: int
}

impl Point {

    pub fn new(x: int, y: int) -> Point {
        Point { x: x, y: y }
    }

    pub fn zero() -> Point {
        Point { x: 0, y: 0 }
    }

    pub fn move_dir(&self, dir: Direction) -> Point {
        *self + dir.as_tuple()
    }

}

impl Add<Point, Point> for Point {
    fn add(self, other: Point) -> Point {
        let (ox, oy) = other.as_tuple();
        Point { x: self.x + ox, y: self.y + oy }
    }
}

impl Add<(int, int), Point> for Point {
    fn add(self, other: (int, int)) -> Point {
        let (ox, oy) = other;
        Point { x: self.x + ox, y: self.y + oy }
    }
}

impl XYPair for Point {
    fn as_tuple(&self) -> (int, int) {
        (self.x, self.y)
    }
}

pub enum Direction {
    Up,
    Down,
    Left,
    Right,
}

impl XYPair for Direction {
    fn as_tuple(&self) -> (int, int) {
        match *self {
            Direction::Up      => (  0, -1),
            Direction::Down    => (  0,  1),
            Direction::Left    => ( -1,  0),
            Direction::Right   => (  1,  0),
        }
    }
}
<|endoftext|>


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

use ansi_term;
use serde;
use serde_json;

use error;
use value;

pub struct JsonSource<R>(serde_json::StreamDeserializer<value::Value, io::Bytes<R>>)
    where R: io::Read;

pub struct JsonSink<W, F>(W, F)
    where W: io::Write,
          F: FormatterClone + serde_json::ser::Formatter;

// TODO: this is needed until https://github.com/serde-rs/json/pull/139 is merged
pub trait FormatterClone {
    fn clone_formatter(&self) -> Self;
}

#[derive(Clone, Debug)]
pub struct ReadableFormatter {
    current_indent: usize,

    bracket_style: ansi_term::Style,
    colon_style: ansi_term::Style,
    comma_style: ansi_term::Style,

    field_style: ansi_term::Style,
    value_style: ansi_term::Style,
}

#[inline]
pub fn source<R>(r: R) -> JsonSource<R>
    where R: io::Read
{
    JsonSource(serde_json::StreamDeserializer::new(r.bytes()))
}

#[inline]
pub fn sink_compact<W>(w: W) -> JsonSink<W, serde_json::ser::CompactFormatter>
    where W: io::Write
{
    JsonSink(w, serde_json::ser::CompactFormatter)
}

#[inline]
pub fn sink_readable<W>(w: W) -> JsonSink<W, ReadableFormatter>
    where W: io::Write
{
    JsonSink(w, ReadableFormatter::new())
}

impl<R> value::Source for JsonSource<R>
    where R: io::Read
{
    #[inline]
    fn read(&mut self) -> error::Result<Option<value::Value>> {
        match self.0.next() {
            Some(Ok(v)) => Ok(Some(v)),
            Some(Err(e)) => Err(error::Error::from(e)),
            None => Ok(None),
        }
    }
}

impl<W, F> value::Sink for JsonSink<W, F>
    where W: io::Write,
          F: FormatterClone + serde_json::ser::Formatter
{
    #[inline]
    fn write(&mut self, v: value::Value) -> error::Result<()> {
        {
            let mut serializer =
                serde_json::ser::Serializer::with_formatter(&mut self.0, self.1.clone_formatter());
            try!(serde::Serialize::serialize(&v, &mut serializer));
        }
        try!(self.0.write_all(b"\n"));
        Ok(())
    }
}

impl FormatterClone for serde_json::ser::CompactFormatter {
    fn clone_formatter(&self) -> Self {
        serde_json::ser::CompactFormatter
    }
}

impl ReadableFormatter {
    fn new() -> ReadableFormatter {
        ReadableFormatter {
            current_indent: 0,

            bracket_style: ansi_term::Colour::White.bold(),
            colon_style: ansi_term::Colour::White.bold(),
            comma_style: ansi_term::Colour::White.bold(),

            field_style: ansi_term::Colour::Blue.bold(),
            value_style: ansi_term::Colour::Green.normal(),
        }
    }
}

impl serde_json::ser::Formatter for ReadableFormatter {
    fn open<W>(&mut self, writer: &mut W, ch: u8) -> serde_json::error::Result<()>
        where W: io::Write
    {
        self.current_indent += 1;
        // TODO: optimize this maybe?
        let char_str = format!("{}", char::from_u32(ch as u32).unwrap());
        try!(write!(writer, "{}", self.bracket_style.paint(char_str)));

        if ch as char == '{' {
            try!(write!(writer, "{}", self.field_style.prefix()));
        }
        Ok(())
    }

    fn comma<W>(&mut self, writer: &mut W, first: bool) -> serde_json::error::Result<()>
        where W: io::Write
    {
        if !first {
            try!(write!(writer, "{}", self.comma_style.paint(",")));
        }
        try!(writer.write_all(b"\n"));

        try!(write!(writer, "{}", self.field_style.prefix()));

        indent(writer, self.current_indent)
    }

    fn colon<W>(&mut self, writer: &mut W) -> serde_json::error::Result<()>
        where W: io::Write
    {
        try!(write!(writer, "{}", self.colon_style.paint(":")));
        try!(write!(writer, " "));

        try!(write!(writer, "{}", self.value_style.prefix()));

        Ok(())
    }

    fn close<W>(&mut self, writer: &mut W, ch: u8) -> serde_json::error::Result<()>
        where W: io::Write
    {
        self.current_indent -= 1;
        try!(writer.write(b"\n"));
        try!(indent(writer, self.current_indent));

        // TODO: optimize this maybe?
        let char_str = format!("{}", char::from_u32(ch as u32).unwrap());
        try!(write!(writer, "{}", self.bracket_style.paint(char_str)));

        Ok(())
    }
}

impl FormatterClone for ReadableFormatter {
    fn clone_formatter(&self) -> Self {
        self.clone()
    }
}

fn indent<W>(wr: &mut W, n: usize) -> serde_json::error::Result<()>
    where W: io::Write
{
    for _ in 0..n {
        try!(wr.write_all(b"  "));
    }

    Ok(())
}
<commit_msg>Make color generation more defensive<commit_after>use std::char;
use std::io;

use ansi_term;
use serde;
use serde_json;

use error;
use value;

pub struct JsonSource<R>(serde_json::StreamDeserializer<value::Value, io::Bytes<R>>)
    where R: io::Read;

pub struct JsonSink<W, F>(W, F)
    where W: io::Write,
          F: FormatterClone + serde_json::ser::Formatter;

// TODO: this is needed until https://github.com/serde-rs/json/pull/139 is merged
pub trait FormatterClone {
    fn clone_formatter(&self) -> Self;
}

#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
enum Context {
  Object,
  Array,
}

#[derive(Clone, Debug)]
pub struct ReadableFormatter {
    current_indent: usize,
    context: Context,

    bracket_style: ansi_term::Style,
    colon_style: ansi_term::Style,
    comma_style: ansi_term::Style,

    field_style: ansi_term::Style,
    value_style: ansi_term::Style,
}

#[inline]
pub fn source<R>(r: R) -> JsonSource<R>
    where R: io::Read
{
    JsonSource(serde_json::StreamDeserializer::new(r.bytes()))
}

#[inline]
pub fn sink_compact<W>(w: W) -> JsonSink<W, serde_json::ser::CompactFormatter>
    where W: io::Write
{
    JsonSink(w, serde_json::ser::CompactFormatter)
}

#[inline]
pub fn sink_readable<W>(w: W) -> JsonSink<W, ReadableFormatter>
    where W: io::Write
{
    JsonSink(w, ReadableFormatter::new())
}

impl<R> value::Source for JsonSource<R>
    where R: io::Read
{
    #[inline]
    fn read(&mut self) -> error::Result<Option<value::Value>> {
        match self.0.next() {
            Some(Ok(v)) => Ok(Some(v)),
            Some(Err(e)) => Err(error::Error::from(e)),
            None => Ok(None),
        }
    }
}

impl<W, F> value::Sink for JsonSink<W, F>
    where W: io::Write,
          F: FormatterClone + serde_json::ser::Formatter
{
    #[inline]
    fn write(&mut self, v: value::Value) -> error::Result<()> {
        {
            let mut serializer =
                serde_json::ser::Serializer::with_formatter(&mut self.0, self.1.clone_formatter());
            try!(serde::Serialize::serialize(&v, &mut serializer));
        }
        try!(self.0.write_all(b"\n"));
        Ok(())
    }
}

impl FormatterClone for serde_json::ser::CompactFormatter {
    fn clone_formatter(&self) -> Self {
        serde_json::ser::CompactFormatter
    }
}

impl ReadableFormatter {
    fn new() -> ReadableFormatter {
        ReadableFormatter {
            current_indent: 0,
            context: Context::Array,

            bracket_style: ansi_term::Colour::White.bold(),
            colon_style: ansi_term::Colour::White.bold(),
            comma_style: ansi_term::Colour::White.bold(),

            field_style: ansi_term::Colour::Blue.bold(),
            value_style: ansi_term::Colour::Green.normal(),
        }
    }
}

impl serde_json::ser::Formatter for ReadableFormatter {
    fn open<W>(&mut self, writer: &mut W, ch: u8) -> serde_json::error::Result<()>
        where W: io::Write
    {
        self.current_indent += 1;
        // TODO: optimize this maybe?
        let char_str = format!("{}", ch as char);
        try!(write!(writer, "{}", self.bracket_style.paint(char_str)));

        self.context = match ch as char {
            '{' =>  Context::Object,
            '[' => Context::Array,
            _ => Context::Array,
        };

        Ok(())
    }

    fn comma<W>(&mut self, writer: &mut W, first: bool) -> serde_json::error::Result<()>
        where W: io::Write
    {
        if !first {
            try!(write!(writer, "{}", self.comma_style.paint(",")));
        }
        try!(writer.write_all(b"\n"));

        try!(indent(writer, self.current_indent));

        match self.context {
            Context::Object => try!(write!(writer, "{}", self.field_style.prefix())),
            Context::Array => try!(write!(writer, "{}", self.value_style.prefix())),
        }

        Ok(())
    }

    fn colon<W>(&mut self, writer: &mut W) -> serde_json::error::Result<()>
        where W: io::Write
    {
        try!(write!(writer, "{}", self.field_style.suffix()));
        try!(write!(writer, "{}", self.colon_style.paint(":")));
        try!(write!(writer, " "));

        try!(write!(writer, "{}", self.value_style.prefix()));

        Ok(())
    }

    fn close<W>(&mut self, writer: &mut W, ch: u8) -> serde_json::error::Result<()>
        where W: io::Write
    {
        self.current_indent -= 1;

        match self.context {
            Context::Object => try!(write!(writer, "{}", self.field_style.suffix())),
            Context::Array => try!(write!(writer, "{}", self.value_style.suffix())),
        }

        try!(writer.write(b"\n"));
        try!(indent(writer, self.current_indent));

        // TODO: optimize this maybe?
        let char_str = format!("{}", ch as char);
        try!(write!(writer, "{}", self.bracket_style.paint(char_str)));

        Ok(())
    }
}

impl FormatterClone for ReadableFormatter {
    fn clone_formatter(&self) -> Self {
        self.clone()
    }
}

fn indent<W>(wr: &mut W, n: usize) -> serde_json::error::Result<()>
    where W: io::Write
{
    for _ in 0..n {
        try!(wr.write_all(b"  "));
    }

    Ok(())
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

extern crate mozangle;
extern crate webrender;

use mozangle::shaders::{BuiltInResources, Output, ShaderSpec, ShaderValidator};

// from glslang
const FRAGMENT_SHADER: u32 = 0x8B30;
const VERTEX_SHADER: u32 = 0x8B31;

struct Shader {
    name: &'static str,
    features: &'static [&'static str],
}

const SHADER_PREFIX: &str = "#define WR_MAX_VERTEX_TEXTURE_WIDTH 1024U\n";

const BRUSH_FEATURES: &[&str] = &["", "ALPHA_PASS"];
const CLIP_FEATURES: &[&str] = &["TRANSFORM"];
const CACHE_FEATURES: &[&str] = &[""];
const GRADIENT_FEATURES: &[&str] = &[ "", "DITHERING", "ALPHA_PASS", "DITHERING,ALPHA_PASS" ];
const PRIM_FEATURES: &[&str] = &[""];

const SHADERS: &[Shader] = &[
    // Clip mask shaders
    Shader {
        name: "cs_clip_rectangle",
        features: CLIP_FEATURES,
    },
    Shader {
        name: "cs_clip_image",
        features: CLIP_FEATURES,
    },
    Shader {
        name: "cs_clip_box_shadow",
        features: CLIP_FEATURES,
    },
    Shader {
        name: "cs_clip_line",
        features: CLIP_FEATURES,
    },
    // Cache shaders
    Shader {
        name: "cs_blur",
        features: &[ "ALPHA_TARGET", "COLOR_TARGET" ],
    },
    Shader {
        name: "cs_border_segment",
        features: CACHE_FEATURES,
    },
    Shader {
        name: "cs_border_solid",
        features: CACHE_FEATURES,
    },
    // Prim shaders
    Shader {
        name: "ps_split_composite",
        features: PRIM_FEATURES,
    },
    Shader {
        name: "ps_text_run",
        features: &[ "", "GLYPH_TRANSFORM" ],
    },
    // Brush shaders
    Shader {
        name: "brush_yuv_image",
        features: &[
            "",
            "YUV_NV12",
            "YUV_PLANAR",
            "YUV_INTERLEAVED",
            "TEXTURE_2D,YUV_NV12",
            "YUV_NV12,ALPHA_PASS",
        ],
    },
    Shader {
        name: "brush_solid",
        features: BRUSH_FEATURES,
    },
    Shader {
        name: "brush_image",
        features: BRUSH_FEATURES,
    },
    Shader {
        name: "brush_blend",
        features: BRUSH_FEATURES,
    },
    Shader {
        name: "brush_mix_blend",
        features: BRUSH_FEATURES,
    },
    Shader {
        name: "brush_radial_gradient",
        features: GRADIENT_FEATURES,
    },
    Shader {
        name: "brush_linear_gradient",
        features: GRADIENT_FEATURES,
    },
];

const VERSION_STRING: &str = "#version 300 es\n";

#[test]
fn validate_shaders() {
    mozangle::shaders::initialize().unwrap();

    let resources = BuiltInResources::default();
    let vs_validator =
        ShaderValidator::new(VERTEX_SHADER, ShaderSpec::Gles3, Output::Essl, &resources).unwrap();

    let fs_validator =
        ShaderValidator::new(FRAGMENT_SHADER, ShaderSpec::Gles3, Output::Essl, &resources).unwrap();

    for shader in SHADERS {
        for config in shader.features {
            let mut features = String::new();
            features.push_str(SHADER_PREFIX);

            for feature in config.split(",") {
                features.push_str(&format!("#define WR_FEATURE_{}\n", feature));
            }

            let (vs, fs) =
                webrender::build_shader_strings(VERSION_STRING, &features, shader.name, &None);

            validate(&vs_validator, shader.name, vs);
            validate(&fs_validator, shader.name, fs);
        }
    }
}

fn validate(validator: &ShaderValidator, name: &str, source: String) {
    // Check for each `switch` to have a `default`, see
    // https://github.com/servo/webrender/wiki/Driver-issues#lack-of-default-case-in-a-switch
    assert_eq!(source.matches("switch").count(), source.matches("default:").count(),
        "Shader '{}' doesn't have all `switch` covered with `default` cases", name);
    // Run Angle validator
    match validator.compile_and_translate(&[&source]) {
        Ok(_) => {
            println!("Shader translated succesfully: {}", name);
        }
        Err(_) => {
            panic!(
                "Shader compilation failed: {}\n{}",
                name,
                validator.info_log()
            );
        }
    }
}
<commit_msg>Remove transform feature from angle validation<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

extern crate mozangle;
extern crate webrender;

use mozangle::shaders::{BuiltInResources, Output, ShaderSpec, ShaderValidator};

// from glslang
const FRAGMENT_SHADER: u32 = 0x8B30;
const VERTEX_SHADER: u32 = 0x8B31;

struct Shader {
    name: &'static str,
    features: &'static [&'static str],
}

const SHADER_PREFIX: &str = "#define WR_MAX_VERTEX_TEXTURE_WIDTH 1024U\n";

const BRUSH_FEATURES: &[&str] = &["", "ALPHA_PASS"];
const CLIP_FEATURES: &[&str] = &[""];
const CACHE_FEATURES: &[&str] = &[""];
const GRADIENT_FEATURES: &[&str] = &[ "", "DITHERING", "ALPHA_PASS", "DITHERING,ALPHA_PASS" ];
const PRIM_FEATURES: &[&str] = &[""];

const SHADERS: &[Shader] = &[
    // Clip mask shaders
    Shader {
        name: "cs_clip_rectangle",
        features: CLIP_FEATURES,
    },
    Shader {
        name: "cs_clip_image",
        features: CLIP_FEATURES,
    },
    Shader {
        name: "cs_clip_box_shadow",
        features: CLIP_FEATURES,
    },
    Shader {
        name: "cs_clip_line",
        features: CLIP_FEATURES,
    },
    // Cache shaders
    Shader {
        name: "cs_blur",
        features: &[ "ALPHA_TARGET", "COLOR_TARGET" ],
    },
    Shader {
        name: "cs_border_segment",
        features: CACHE_FEATURES,
    },
    Shader {
        name: "cs_border_solid",
        features: CACHE_FEATURES,
    },
    // Prim shaders
    Shader {
        name: "ps_split_composite",
        features: PRIM_FEATURES,
    },
    Shader {
        name: "ps_text_run",
        features: &[ "", "GLYPH_TRANSFORM" ],
    },
    // Brush shaders
    Shader {
        name: "brush_yuv_image",
        features: &[
            "",
            "YUV_NV12",
            "YUV_PLANAR",
            "YUV_INTERLEAVED",
            "TEXTURE_2D,YUV_NV12",
            "YUV_NV12,ALPHA_PASS",
        ],
    },
    Shader {
        name: "brush_solid",
        features: BRUSH_FEATURES,
    },
    Shader {
        name: "brush_image",
        features: BRUSH_FEATURES,
    },
    Shader {
        name: "brush_blend",
        features: BRUSH_FEATURES,
    },
    Shader {
        name: "brush_mix_blend",
        features: BRUSH_FEATURES,
    },
    Shader {
        name: "brush_radial_gradient",
        features: GRADIENT_FEATURES,
    },
    Shader {
        name: "brush_linear_gradient",
        features: GRADIENT_FEATURES,
    },
];

const VERSION_STRING: &str = "#version 300 es\n";

#[test]
fn validate_shaders() {
    mozangle::shaders::initialize().unwrap();

    let resources = BuiltInResources::default();
    let vs_validator =
        ShaderValidator::new(VERTEX_SHADER, ShaderSpec::Gles3, Output::Essl, &resources).unwrap();

    let fs_validator =
        ShaderValidator::new(FRAGMENT_SHADER, ShaderSpec::Gles3, Output::Essl, &resources).unwrap();

    for shader in SHADERS {
        for config in shader.features {
            let mut features = String::new();
            features.push_str(SHADER_PREFIX);

            for feature in config.split(",") {
                features.push_str(&format!("#define WR_FEATURE_{}\n", feature));
            }

            let (vs, fs) =
                webrender::build_shader_strings(VERSION_STRING, &features, shader.name, &None);

            validate(&vs_validator, shader.name, vs);
            validate(&fs_validator, shader.name, fs);
        }
    }
}

fn validate(validator: &ShaderValidator, name: &str, source: String) {
    // Check for each `switch` to have a `default`, see
    // https://github.com/servo/webrender/wiki/Driver-issues#lack-of-default-case-in-a-switch
    assert_eq!(source.matches("switch").count(), source.matches("default:").count(),
        "Shader '{}' doesn't have all `switch` covered with `default` cases", name);
    // Run Angle validator
    match validator.compile_and_translate(&[&source]) {
        Ok(_) => {
            println!("Shader translated succesfully: {}", name);
        }
        Err(_) => {
            panic!(
                "Shader compilation failed: {}\n{}",
                name,
                validator.info_log()
            );
        }
    }
}
<|endoftext|>


<commit_before>mod immediate;
mod multithreaded;
#[cfg(feature = "rayon")]
mod rayon;

use alloc::sync::Arc;
use alloc::vec::Vec;
use crate::error::Result;
use crate::parser::Component;

pub struct RowData {
    pub index: usize,
    pub component: Component,
    pub quantization_table: Arc<[u16; 64]>,
}

pub trait Worker {
    fn start(&mut self, row_data: RowData) -> Result<()>;
    fn append_row(&mut self, row: (usize, Vec<i16>)) -> Result<()>;
    fn get_result(&mut self, index: usize) -> Result<Vec<u8>>;
    /// Default implementation for spawning multiple tasks.
    fn append_rows(&mut self, row: &mut dyn Iterator<Item=(usize, Vec<i16>)>)
        -> Result<()>
    {
        for item in row {
            self.append_row(item)?;
        }
        Ok(())
    }
}

pub enum PreferWorkerKind {
    Immediate,
    Multithreaded,
}

/// Execute something with a worker system.
pub fn with_worker<T>(prefer: PreferWorkerKind, f: impl FnOnce(&mut dyn Worker) -> T) -> T {
    #[cfg(any(target_arch = "asmjs", target_arch = "wasm32"))]
    {
        return self::immediate::with_immediate(f);
    }
    match prefer {
        #[cfg(feature = "rayon")]
        PreferWorkerKind::Multithreaded => self::rayon::with_rayon(f),
        PreferWorkerKind::Multithreaded => self::multithreaded::with_multithreading(f),
        _ => self::immediate::with_immediate(f),
    }
}

<commit_msg>Merging cfg checks<commit_after>mod immediate;
mod multithreaded;
#[cfg(feature = "rayon")]
mod rayon;

use alloc::sync::Arc;
use alloc::vec::Vec;
use crate::error::Result;
use crate::parser::Component;

pub struct RowData {
    pub index: usize,
    pub component: Component,
    pub quantization_table: Arc<[u16; 64]>,
}

pub trait Worker {
    fn start(&mut self, row_data: RowData) -> Result<()>;
    fn append_row(&mut self, row: (usize, Vec<i16>)) -> Result<()>;
    fn get_result(&mut self, index: usize) -> Result<Vec<u8>>;
    /// Default implementation for spawning multiple tasks.
    fn append_rows(&mut self, row: &mut dyn Iterator<Item=(usize, Vec<i16>)>)
        -> Result<()>
    {
        for item in row {
            self.append_row(item)?;
        }
        Ok(())
    }
}

pub enum PreferWorkerKind {
    Immediate,
    Multithreaded,
}

/// Execute something with a worker system.
pub fn with_worker<T>(prefer: PreferWorkerKind, f: impl FnOnce(&mut dyn Worker) -> T) -> T {
    match prefer {
        #[cfg(all(not(any(target_arch = "asmjs", target_arch = "wasm32")), feature = "rayon"))]
        PreferWorkerKind::Multithreaded => self::rayon::with_rayon(f),
        #[cfg(not(any(target_arch = "asmjs", target_arch = "wasm32")))]
        PreferWorkerKind::Multithreaded => self::multithreaded::with_multithreading(f),
        _ => self::immediate::with_immediate(f),
    }
}

<|endoftext|>


<commit_before>use std::io::File;
use std::io::{Reader, Writer, Seek, SeekSet, SeekEnd};
use std::io::{IoResult, IoError, InvalidInput};
use std::iter;
use std::iter::range_inclusive;
use std::path::BytesContainer;
use error;
use error::ZipError;
use maybe_utf8::MaybeUTF8;
use flate;
use crc32;
use format;
use fileinfo;
use fileinfo::{CompressionMethod, FileInfo};

pub struct ZipReader<R> {
    reader: R,
    end_record: format::EndOfCentralDirectoryRecord,
}

pub struct Files<'a, R> {
    zip_reader: &'a mut ZipReader<R>,
    current_entry: u16,
    current_offset: u64,
}

impl<'a, R:Reader+Seek> Iterator<Result<FileInfo, ZipError>> for Files<'a, R> {
    fn next(&mut self) -> Option<Result<FileInfo, ZipError>> {
        if self.current_entry < self.zip_reader.end_record.total_entry_count {
            match self.zip_reader.reader.seek(self.current_offset as i64, SeekSet) {
                Ok(()) => {}
                Err(err) => { return Some(Err(error::IoError(err))); }
            }
            let h = match format::CentralDirectoryHeader::read(&mut self.zip_reader.reader) {
                Ok(h) => h,
                Err(err) => { return Some(Err(err)); }
            };
            let info = FileInfo::from_cdh(&h);
            self.current_entry += 1;
            self.current_offset += h.total_size() as u64;
            Some(Ok(info))
        } else {
            None
        }
    }
}

impl ZipReader<File> {
    pub fn open(path: &Path) -> Result<ZipReader<File>, ZipError> {
        ZipReader::new(try_io!(File::open(path)))
    }
}

impl<R:Reader+Seek> ZipReader<R> {
    pub fn new(reader: R) -> Result<ZipReader<R>, ZipError> {
        // find the End of Central Directory record, looking backwards from the end of the file
        let mut r = reader;
        try_io!(r.seek(0, SeekEnd));
        let file_size = try_io!(r.tell());
        let mut end_record_offset : Option<u64> = None;
        for i in range_inclusive(4, file_size) {
            let offset = file_size - i;
            try_io!(r.seek(offset as i64, SeekSet));

            let sig = try_io!(r.read_le_u32());

            // TODO: check for false positives here
            if sig == format::EOCDR_SIGNATURE {
                end_record_offset = Some(offset);
                break;
            }

        }

        match end_record_offset {
            Some(offset) => {
                try_io!(r.seek(offset as i64, SeekSet));
                let e = try!(format::EndOfCentralDirectoryRecord::read(&mut r));
                Ok(ZipReader {reader: r, end_record: e})
            },
            None => Err(error::NotAZipFile)
        }
    }

    pub fn files_raw<'a>(&'a mut self) -> Files<'a, R> {
        let cdr_offset = self.end_record.central_directory_offset;
        Files {
            zip_reader: self,
            current_entry: 0,
            current_offset: cdr_offset as u64
        }
    }

    pub fn files<'a>(&'a mut self) -> iter::Map<Result<FileInfo, ZipError>, FileInfo,
                                                Files<'a, R>> {
        self.files_raw().map(|fileinfo_or_err| fileinfo_or_err.unwrap())
    }

    pub fn file_names<'a>(&'a mut self) -> iter::Map<Result<FileInfo, ZipError>, MaybeUTF8,
                                                     Files<'a, R>> {
        self.files_raw().map(|fileinfo_or_err| fileinfo_or_err.unwrap().name)
    }

    pub fn info<T:BytesContainer>(&mut self, name: T) -> Result<FileInfo, ZipError> {
        for i in self.files() {
            if i.name.equiv(&name) {
                return Ok(i);
            }
        }
        Err(error::FileNotFoundInArchive)
    }

    // TODO: Create a Reader for the cases when you don't want to decompress the whole file
    pub fn read(&mut self, f: &FileInfo) -> Result<Vec<u8>, ZipError> {
        try_io!(self.reader.seek(f.local_file_header_offset as i64, SeekSet));
        let h = try!(format::LocalFileHeader::read(&mut self.reader));
        let file_offset = f.local_file_header_offset as i64 + h.total_size() as i64;

        let result =
            match CompressionMethod::from_u16(h.compression_method) {
                fileinfo::Store => self.read_stored_file(file_offset, h.uncompressed_size),
                fileinfo::Deflate => self.read_deflated_file(file_offset, h.compressed_size, h.uncompressed_size),
                _ => fail!()
            };
        let result = try_io!(result);

        // Check the CRC32 of the result against the one stored in the header
        let crc = crc32::crc32(result.as_slice());

        if crc == h.crc32 { Ok(result) }
        else { Err(error::CrcError) }
    }

    fn read_stored_file(&mut self, pos: i64, uncompressed_size: u32) -> IoResult<Vec<u8>> {
        try!(self.reader.seek(pos, SeekSet));
        self.reader.read_exact(uncompressed_size as uint)
    }

    fn read_deflated_file(&mut self, pos: i64, compressed_size: u32, uncompressed_size: u32) -> IoResult<Vec<u8>> {
        try!(self.reader.seek(pos, SeekSet));
        let compressed_bytes = try!(self.reader.read_exact(compressed_size as uint));
        let uncompressed_bytes = match flate::inflate_bytes(compressed_bytes.as_slice()) {
            Some(bytes) => bytes,
            None => return Err(IoError { kind: InvalidInput, desc: "decompression failure", detail: None })
        };
        assert!(uncompressed_bytes.len() as u32 == uncompressed_size);
        // FIXME try not to copy the buffer, or switch to the incremental fashion
        Ok(Vec::from_slice(uncompressed_bytes.as_slice()))
    }

    // when we make read return a Reader, we will be able to loop here and copy
    // blocks of a fixed size from Reader to Writer
    pub fn extract<T:Writer>(&mut self, f: &FileInfo, writer: &mut T) -> Result<(), ZipError> {
        match self.read(f) {
            Ok(bytes) => { try_io!(writer.write(bytes.as_slice())); Ok(()) },
            Err(x) => Err(x)
        }
    }

}

<commit_msg>language changes: lifetime bounds on types.<commit_after>use std::io::File;
use std::io::{Reader, Writer, Seek, SeekSet, SeekEnd};
use std::io::{IoResult, IoError, InvalidInput};
use std::iter;
use std::iter::range_inclusive;
use std::path::BytesContainer;
use error;
use error::ZipError;
use maybe_utf8::MaybeUTF8;
use flate;
use crc32;
use format;
use fileinfo;
use fileinfo::{CompressionMethod, FileInfo};

pub struct ZipReader<R> {
    reader: R,
    end_record: format::EndOfCentralDirectoryRecord,
}

pub struct Files<'a, R:'a> {
    zip_reader: &'a mut ZipReader<R>,
    current_entry: u16,
    current_offset: u64,
}

impl<'a, R:Reader+Seek> Iterator<Result<FileInfo, ZipError>> for Files<'a, R> {
    fn next(&mut self) -> Option<Result<FileInfo, ZipError>> {
        if self.current_entry < self.zip_reader.end_record.total_entry_count {
            match self.zip_reader.reader.seek(self.current_offset as i64, SeekSet) {
                Ok(()) => {}
                Err(err) => { return Some(Err(error::IoError(err))); }
            }
            let h = match format::CentralDirectoryHeader::read(&mut self.zip_reader.reader) {
                Ok(h) => h,
                Err(err) => { return Some(Err(err)); }
            };
            let info = FileInfo::from_cdh(&h);
            self.current_entry += 1;
            self.current_offset += h.total_size() as u64;
            Some(Ok(info))
        } else {
            None
        }
    }
}

impl ZipReader<File> {
    pub fn open(path: &Path) -> Result<ZipReader<File>, ZipError> {
        ZipReader::new(try_io!(File::open(path)))
    }
}

impl<R:Reader+Seek> ZipReader<R> {
    pub fn new(reader: R) -> Result<ZipReader<R>, ZipError> {
        // find the End of Central Directory record, looking backwards from the end of the file
        let mut r = reader;
        try_io!(r.seek(0, SeekEnd));
        let file_size = try_io!(r.tell());
        let mut end_record_offset : Option<u64> = None;
        for i in range_inclusive(4, file_size) {
            let offset = file_size - i;
            try_io!(r.seek(offset as i64, SeekSet));

            let sig = try_io!(r.read_le_u32());

            // TODO: check for false positives here
            if sig == format::EOCDR_SIGNATURE {
                end_record_offset = Some(offset);
                break;
            }

        }

        match end_record_offset {
            Some(offset) => {
                try_io!(r.seek(offset as i64, SeekSet));
                let e = try!(format::EndOfCentralDirectoryRecord::read(&mut r));
                Ok(ZipReader {reader: r, end_record: e})
            },
            None => Err(error::NotAZipFile)
        }
    }

    pub fn files_raw<'a>(&'a mut self) -> Files<'a, R> {
        let cdr_offset = self.end_record.central_directory_offset;
        Files {
            zip_reader: self,
            current_entry: 0,
            current_offset: cdr_offset as u64
        }
    }

    pub fn files<'a>(&'a mut self) -> iter::Map<Result<FileInfo, ZipError>, FileInfo,
                                                Files<'a, R>> {
        self.files_raw().map(|fileinfo_or_err| fileinfo_or_err.unwrap())
    }

    pub fn file_names<'a>(&'a mut self) -> iter::Map<Result<FileInfo, ZipError>, MaybeUTF8,
                                                     Files<'a, R>> {
        self.files_raw().map(|fileinfo_or_err| fileinfo_or_err.unwrap().name)
    }

    pub fn info<T:BytesContainer>(&mut self, name: T) -> Result<FileInfo, ZipError> {
        for i in self.files() {
            if i.name.equiv(&name) {
                return Ok(i);
            }
        }
        Err(error::FileNotFoundInArchive)
    }

    // TODO: Create a Reader for the cases when you don't want to decompress the whole file
    pub fn read(&mut self, f: &FileInfo) -> Result<Vec<u8>, ZipError> {
        try_io!(self.reader.seek(f.local_file_header_offset as i64, SeekSet));
        let h = try!(format::LocalFileHeader::read(&mut self.reader));
        let file_offset = f.local_file_header_offset as i64 + h.total_size() as i64;

        let result =
            match CompressionMethod::from_u16(h.compression_method) {
                fileinfo::Store => self.read_stored_file(file_offset, h.uncompressed_size),
                fileinfo::Deflate => self.read_deflated_file(file_offset, h.compressed_size, h.uncompressed_size),
                _ => fail!()
            };
        let result = try_io!(result);

        // Check the CRC32 of the result against the one stored in the header
        let crc = crc32::crc32(result.as_slice());

        if crc == h.crc32 { Ok(result) }
        else { Err(error::CrcError) }
    }

    fn read_stored_file(&mut self, pos: i64, uncompressed_size: u32) -> IoResult<Vec<u8>> {
        try!(self.reader.seek(pos, SeekSet));
        self.reader.read_exact(uncompressed_size as uint)
    }

    fn read_deflated_file(&mut self, pos: i64, compressed_size: u32, uncompressed_size: u32) -> IoResult<Vec<u8>> {
        try!(self.reader.seek(pos, SeekSet));
        let compressed_bytes = try!(self.reader.read_exact(compressed_size as uint));
        let uncompressed_bytes = match flate::inflate_bytes(compressed_bytes.as_slice()) {
            Some(bytes) => bytes,
            None => return Err(IoError { kind: InvalidInput, desc: "decompression failure", detail: None })
        };
        assert!(uncompressed_bytes.len() as u32 == uncompressed_size);
        // FIXME try not to copy the buffer, or switch to the incremental fashion
        Ok(Vec::from_slice(uncompressed_bytes.as_slice()))
    }

    // when we make read return a Reader, we will be able to loop here and copy
    // blocks of a fixed size from Reader to Writer
    pub fn extract<T:Writer>(&mut self, f: &FileInfo, writer: &mut T) -> Result<(), ZipError> {
        match self.read(f) {
            Ok(bytes) => { try_io!(writer.write(bytes.as_slice())); Ok(()) },
            Err(x) => Err(x)
        }
    }

}

<|endoftext|>


<commit_before>// Test that an impl trait type that expands to itself is an error.

fn test() -> impl Sized {       //~ ERROR E0720
    test()
}

fn main() {}
<commit_msg>Apply suggestions from code review<commit_after>// Test that an `impl Trait` type that expands to itself is an error.

fn test() -> impl Sized { //~ ERROR E0720
    test()
}

fn main() {}
<|endoftext|>


<commit_before>// Copyright 2020 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.

//! Data structures for commands of virtio video devices.

use std::convert::{TryFrom, TryInto};
use std::fmt;
use std::io;

use base::error;
use data_model::Le32;
use enumn::N;

use crate::virtio::video::control::*;
use crate::virtio::video::format::*;
use crate::virtio::video::params::Params;
use crate::virtio::video::protocol::*;
use crate::virtio::Reader;

/// An error indicating a failure while reading a request from the guest.
#[derive(Debug)]
pub enum ReadCmdError {
    /// Failure while reading an object.
    IoError(io::Error),
    /// Invalid arguement is passed,
    InvalidArgument,
    /// The type of the command was invalid.
    InvalidCmdType(u32),
    /// The type of the requested control was unsupported.
    UnsupportedCtrlType(u32),
}

impl fmt::Display for ReadCmdError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use self::ReadCmdError::*;
        match self {
            IoError(e) => write!(f, "failed to read an object: {}", e),
            InvalidArgument => write!(f, "invalid arguement is passed in command"),
            InvalidCmdType(t) => write!(f, "invalid command type: {}", t),
            UnsupportedCtrlType(t) => write!(f, "unsupported control type: {}", t),
        }
    }
}

impl std::error::Error for ReadCmdError {}

impl From<io::Error> for ReadCmdError {
    fn from(e: io::Error) -> ReadCmdError {
        ReadCmdError::IoError(e)
    }
}

#[derive(PartialEq, Eq, PartialOrd, Ord, N, Clone, Copy, Debug)]
#[repr(u32)]
pub enum QueueType {
    Input = VIRTIO_VIDEO_QUEUE_TYPE_INPUT,
    Output = VIRTIO_VIDEO_QUEUE_TYPE_OUTPUT,
}
impl_try_from_le32_for_enumn!(QueueType, "queue_type");

#[derive(Debug)]
pub enum VideoCmd {
    QueryCapability {
        queue_type: QueueType,
    },
    StreamCreate {
        stream_id: u32,
        coded_format: Format,
    },
    StreamDestroy {
        stream_id: u32,
    },
    StreamDrain {
        stream_id: u32,
    },
    ResourceCreate {
        stream_id: u32,
        queue_type: QueueType,
        resource_id: u32,
        plane_offsets: Vec<u32>,
        uuid: u128,
    },
    ResourceQueue {
        stream_id: u32,
        queue_type: QueueType,
        resource_id: u32,
        timestamp: u64,
        data_sizes: Vec<u32>,
    },
    ResourceDestroyAll {
        stream_id: u32,
        queue_type: QueueType,
    },
    QueueClear {
        stream_id: u32,
        queue_type: QueueType,
    },
    GetParams {
        stream_id: u32,
        queue_type: QueueType,
    },
    SetParams {
        stream_id: u32,
        queue_type: QueueType,
        params: Params,
    },
    QueryControl {
        query_ctrl_type: QueryCtrlType,
    },
    GetControl {
        stream_id: u32,
        ctrl_type: CtrlType,
    },
    SetControl {
        stream_id: u32,
        ctrl_val: CtrlVal,
    },
}

impl<'a> VideoCmd {
    /// Reads a request on virtqueue and construct a VideoCmd value.
    pub fn from_reader(r: &'a mut Reader) -> Result<Self, ReadCmdError> {
        use self::ReadCmdError::*;
        use self::VideoCmd::*;

        // Unlike structs in virtio_video.h in the kernel, our command structs in protocol.rs don't
        // have a field of `struct virtio_video_cmd_hdr`. So, we first read the header here and
        // a body below.
        let hdr = r.read_obj::<virtio_video_cmd_hdr>()?;

        Ok(match hdr.type_.into() {
            VIRTIO_VIDEO_CMD_QUERY_CAPABILITY => {
                let virtio_video_query_capability { queue_type, .. } = r.read_obj()?;
                QueryCapability {
                    queue_type: queue_type.try_into()?,
                }
            }
            VIRTIO_VIDEO_CMD_STREAM_CREATE => {
                let virtio_video_stream_create {
                    in_mem_type,
                    out_mem_type,
                    coded_format,
                    ..
                } = r.read_obj()?;

                if in_mem_type != VIRTIO_VIDEO_MEM_TYPE_VIRTIO_OBJECT
                    || out_mem_type != VIRTIO_VIDEO_MEM_TYPE_VIRTIO_OBJECT
                {
                    error!("mem_type must be VIRTIO_OBJECT");
                    return Err(InvalidArgument);
                }
                StreamCreate {
                    stream_id: hdr.stream_id.into(),
                    coded_format: coded_format.try_into()?,
                }
            }
            VIRTIO_VIDEO_CMD_STREAM_DESTROY => {
                let virtio_video_stream_destroy { .. } = r.read_obj()?;
                StreamDestroy {
                    stream_id: hdr.stream_id.into(),
                }
            }
            VIRTIO_VIDEO_CMD_STREAM_DRAIN => {
                let virtio_video_stream_drain { .. } = r.read_obj()?;
                StreamDrain {
                    stream_id: hdr.stream_id.into(),
                }
            }
            VIRTIO_VIDEO_CMD_RESOURCE_CREATE => {
                let virtio_video_resource_create {
                    queue_type,
                    resource_id,
                    planes_layout,
                    num_planes,
                    plane_offsets,
                    ..
                } = r.read_obj()?;

                // Assume ChromeOS-specific requirements.
                if Into::<u32>::into(planes_layout) != VIRTIO_VIDEO_PLANES_LAYOUT_SINGLE_BUFFER {
                    error!(
                        "each buffer must be a single DMAbuf: {}",
                        Into::<u32>::into(planes_layout),
                    );
                    return Err(InvalidArgument);
                }

                let num_planes: u32 = num_planes.into();
                if num_planes as usize > plane_offsets.len() {
                    error!(
                        "num_planes must not exceed {} but {}",
                        plane_offsets.len(),
                        num_planes
                    );
                    return Err(InvalidArgument);
                }
                let plane_offsets = plane_offsets[0..num_planes as usize]
                    .iter()
                    .map(|x| Into::<u32>::into(*x))
                    .collect::<Vec<u32>>();

                let virtio_video_object_entry { uuid } = r.read_obj()?;

                ResourceCreate {
                    stream_id: hdr.stream_id.into(),
                    queue_type: queue_type.try_into()?,
                    resource_id: resource_id.into(),
                    plane_offsets,
                    uuid: u128::from_be_bytes(uuid),
                }
            }
            VIRTIO_VIDEO_CMD_RESOURCE_QUEUE => {
                let virtio_video_resource_queue {
                    queue_type,
                    resource_id,
                    timestamp,
                    num_data_sizes,
                    data_sizes,
                    ..
                } = r.read_obj()?;

                let num_data_sizes: u32 = num_data_sizes.into();
                if num_data_sizes as usize > data_sizes.len() {
                    return Err(InvalidArgument);
                }
                let data_sizes = data_sizes[0..num_data_sizes as usize]
                    .iter()
                    .map(|x| Into::<u32>::into(*x))
                    .collect::<Vec<u32>>();
                ResourceQueue {
                    stream_id: hdr.stream_id.into(),
                    queue_type: queue_type.try_into()?,
                    resource_id: resource_id.into(),
                    timestamp: timestamp.into(),
                    data_sizes,
                }
            }
            VIRTIO_VIDEO_CMD_RESOURCE_DESTROY_ALL => {
                let virtio_video_resource_destroy_all { queue_type, .. } = r.read_obj()?;
                ResourceDestroyAll {
                    stream_id: hdr.stream_id.into(),
                    queue_type: queue_type.try_into()?,
                }
            }
            VIRTIO_VIDEO_CMD_QUEUE_CLEAR => {
                let virtio_video_queue_clear { queue_type, .. } = r.read_obj()?;
                QueueClear {
                    stream_id: hdr.stream_id.into(),
                    queue_type: queue_type.try_into()?,
                }
            }
            VIRTIO_VIDEO_CMD_GET_PARAMS => {
                let virtio_video_get_params { queue_type, .. } = r.read_obj()?;
                GetParams {
                    stream_id: hdr.stream_id.into(),
                    queue_type: queue_type.try_into()?,
                }
            }
            VIRTIO_VIDEO_CMD_SET_PARAMS => {
                let virtio_video_set_params { params } = r.read_obj()?;
                SetParams {
                    stream_id: hdr.stream_id.into(),
                    queue_type: params.queue_type.try_into()?,
                    params: params.try_into()?,
                }
            }
            VIRTIO_VIDEO_CMD_QUERY_CONTROL => {
                let body = r.read_obj::<virtio_video_query_control>()?;
                let query_ctrl_type = match body.control.into() {
                    VIRTIO_VIDEO_CONTROL_PROFILE => QueryCtrlType::Profile(
                        r.read_obj::<virtio_video_query_control_profile>()?
                            .format
                            .try_into()?,
                    ),
                    VIRTIO_VIDEO_CONTROL_LEVEL => QueryCtrlType::Level(
                        r.read_obj::<virtio_video_query_control_level>()?
                            .format
                            .try_into()?,
                    ),
                    t => {
                        return Err(ReadCmdError::UnsupportedCtrlType(t));
                    }
                };
                QueryControl { query_ctrl_type }
            }
            VIRTIO_VIDEO_CMD_GET_CONTROL => {
                let virtio_video_get_control { control, .. } = r.read_obj()?;
                let ctrl_type = match control.into() {
                    VIRTIO_VIDEO_CONTROL_BITRATE => CtrlType::Bitrate,
                    VIRTIO_VIDEO_CONTROL_PROFILE => CtrlType::Profile,
                    VIRTIO_VIDEO_CONTROL_LEVEL => CtrlType::Level,
                    VIRTIO_VIDEO_CONTROL_FORCE_KEYFRAME => CtrlType::ForceKeyframe,
                    t => {
                        return Err(ReadCmdError::UnsupportedCtrlType(t));
                    }
                };
                GetControl {
                    stream_id: hdr.stream_id.into(),
                    ctrl_type,
                }
            }
            VIRTIO_VIDEO_CMD_SET_CONTROL => {
                let virtio_video_set_control { control, .. } = r.read_obj()?;
                let ctrl_val = match control.into() {
                    VIRTIO_VIDEO_CONTROL_BITRATE => CtrlVal::Bitrate(
                        r.read_obj::<virtio_video_control_val_bitrate>()?
                            .bitrate
                            .into(),
                    ),
                    VIRTIO_VIDEO_CONTROL_PROFILE => CtrlVal::Profile(
                        r.read_obj::<virtio_video_control_val_profile>()?
                            .profile
                            .try_into()?,
                    ),
                    VIRTIO_VIDEO_CONTROL_LEVEL => CtrlVal::Level(
                        r.read_obj::<virtio_video_control_val_level>()?
                            .level
                            .try_into()?,
                    ),
                    VIRTIO_VIDEO_CONTROL_FORCE_KEYFRAME => CtrlVal::ForceKeyframe(),
                    t => {
                        return Err(ReadCmdError::UnsupportedCtrlType(t));
                    }
                };
                SetControl {
                    stream_id: hdr.stream_id.into(),
                    ctrl_val,
                }
            }
            _ => return Err(ReadCmdError::InvalidCmdType(hdr.type_.into())),
        })
    }
}
<commit_msg>virtio: video: use thiserror in the command module<commit_after>// Copyright 2020 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.

//! Data structures for commands of virtio video devices.

use std::convert::{TryFrom, TryInto};
use std::io;
use thiserror::Error as ThisError;

use base::error;
use data_model::Le32;
use enumn::N;

use crate::virtio::video::control::*;
use crate::virtio::video::format::*;
use crate::virtio::video::params::Params;
use crate::virtio::video::protocol::*;
use crate::virtio::Reader;

/// An error indicating a failure while reading a request from the guest.
#[derive(Debug, ThisError)]
pub enum ReadCmdError {
    /// Failed to read an object.
    #[error("failed to read object: {0}")]
    IoError(#[from] io::Error),
    /// Invalid argument is passed.
    #[error("invalid argument passed to command")]
    InvalidArgument,
    /// The type of the command was invalid.
    #[error("invalid command type: {0}")]
    InvalidCmdType(u32),
    /// The type of the requested control was unsupported.
    #[error("unsupported control type: {0}")]
    UnsupportedCtrlType(u32),
}

#[derive(PartialEq, Eq, PartialOrd, Ord, N, Clone, Copy, Debug)]
#[repr(u32)]
pub enum QueueType {
    Input = VIRTIO_VIDEO_QUEUE_TYPE_INPUT,
    Output = VIRTIO_VIDEO_QUEUE_TYPE_OUTPUT,
}
impl_try_from_le32_for_enumn!(QueueType, "queue_type");

#[derive(Debug)]
pub enum VideoCmd {
    QueryCapability {
        queue_type: QueueType,
    },
    StreamCreate {
        stream_id: u32,
        coded_format: Format,
    },
    StreamDestroy {
        stream_id: u32,
    },
    StreamDrain {
        stream_id: u32,
    },
    ResourceCreate {
        stream_id: u32,
        queue_type: QueueType,
        resource_id: u32,
        plane_offsets: Vec<u32>,
        uuid: u128,
    },
    ResourceQueue {
        stream_id: u32,
        queue_type: QueueType,
        resource_id: u32,
        timestamp: u64,
        data_sizes: Vec<u32>,
    },
    ResourceDestroyAll {
        stream_id: u32,
        queue_type: QueueType,
    },
    QueueClear {
        stream_id: u32,
        queue_type: QueueType,
    },
    GetParams {
        stream_id: u32,
        queue_type: QueueType,
    },
    SetParams {
        stream_id: u32,
        queue_type: QueueType,
        params: Params,
    },
    QueryControl {
        query_ctrl_type: QueryCtrlType,
    },
    GetControl {
        stream_id: u32,
        ctrl_type: CtrlType,
    },
    SetControl {
        stream_id: u32,
        ctrl_val: CtrlVal,
    },
}

impl<'a> VideoCmd {
    /// Reads a request on virtqueue and construct a VideoCmd value.
    pub fn from_reader(r: &'a mut Reader) -> Result<Self, ReadCmdError> {
        use self::ReadCmdError::*;
        use self::VideoCmd::*;

        // Unlike structs in virtio_video.h in the kernel, our command structs in protocol.rs don't
        // have a field of `struct virtio_video_cmd_hdr`. So, we first read the header here and
        // a body below.
        let hdr = r.read_obj::<virtio_video_cmd_hdr>()?;

        Ok(match hdr.type_.into() {
            VIRTIO_VIDEO_CMD_QUERY_CAPABILITY => {
                let virtio_video_query_capability { queue_type, .. } = r.read_obj()?;
                QueryCapability {
                    queue_type: queue_type.try_into()?,
                }
            }
            VIRTIO_VIDEO_CMD_STREAM_CREATE => {
                let virtio_video_stream_create {
                    in_mem_type,
                    out_mem_type,
                    coded_format,
                    ..
                } = r.read_obj()?;

                if in_mem_type != VIRTIO_VIDEO_MEM_TYPE_VIRTIO_OBJECT
                    || out_mem_type != VIRTIO_VIDEO_MEM_TYPE_VIRTIO_OBJECT
                {
                    error!("mem_type must be VIRTIO_OBJECT");
                    return Err(InvalidArgument);
                }
                StreamCreate {
                    stream_id: hdr.stream_id.into(),
                    coded_format: coded_format.try_into()?,
                }
            }
            VIRTIO_VIDEO_CMD_STREAM_DESTROY => {
                let virtio_video_stream_destroy { .. } = r.read_obj()?;
                StreamDestroy {
                    stream_id: hdr.stream_id.into(),
                }
            }
            VIRTIO_VIDEO_CMD_STREAM_DRAIN => {
                let virtio_video_stream_drain { .. } = r.read_obj()?;
                StreamDrain {
                    stream_id: hdr.stream_id.into(),
                }
            }
            VIRTIO_VIDEO_CMD_RESOURCE_CREATE => {
                let virtio_video_resource_create {
                    queue_type,
                    resource_id,
                    planes_layout,
                    num_planes,
                    plane_offsets,
                    ..
                } = r.read_obj()?;

                // Assume ChromeOS-specific requirements.
                if Into::<u32>::into(planes_layout) != VIRTIO_VIDEO_PLANES_LAYOUT_SINGLE_BUFFER {
                    error!(
                        "each buffer must be a single DMAbuf: {}",
                        Into::<u32>::into(planes_layout),
                    );
                    return Err(InvalidArgument);
                }

                let num_planes: u32 = num_planes.into();
                if num_planes as usize > plane_offsets.len() {
                    error!(
                        "num_planes must not exceed {} but {}",
                        plane_offsets.len(),
                        num_planes
                    );
                    return Err(InvalidArgument);
                }
                let plane_offsets = plane_offsets[0..num_planes as usize]
                    .iter()
                    .map(|x| Into::<u32>::into(*x))
                    .collect::<Vec<u32>>();

                let virtio_video_object_entry { uuid } = r.read_obj()?;

                ResourceCreate {
                    stream_id: hdr.stream_id.into(),
                    queue_type: queue_type.try_into()?,
                    resource_id: resource_id.into(),
                    plane_offsets,
                    uuid: u128::from_be_bytes(uuid),
                }
            }
            VIRTIO_VIDEO_CMD_RESOURCE_QUEUE => {
                let virtio_video_resource_queue {
                    queue_type,
                    resource_id,
                    timestamp,
                    num_data_sizes,
                    data_sizes,
                    ..
                } = r.read_obj()?;

                let num_data_sizes: u32 = num_data_sizes.into();
                if num_data_sizes as usize > data_sizes.len() {
                    return Err(InvalidArgument);
                }
                let data_sizes = data_sizes[0..num_data_sizes as usize]
                    .iter()
                    .map(|x| Into::<u32>::into(*x))
                    .collect::<Vec<u32>>();
                ResourceQueue {
                    stream_id: hdr.stream_id.into(),
                    queue_type: queue_type.try_into()?,
                    resource_id: resource_id.into(),
                    timestamp: timestamp.into(),
                    data_sizes,
                }
            }
            VIRTIO_VIDEO_CMD_RESOURCE_DESTROY_ALL => {
                let virtio_video_resource_destroy_all { queue_type, .. } = r.read_obj()?;
                ResourceDestroyAll {
                    stream_id: hdr.stream_id.into(),
                    queue_type: queue_type.try_into()?,
                }
            }
            VIRTIO_VIDEO_CMD_QUEUE_CLEAR => {
                let virtio_video_queue_clear { queue_type, .. } = r.read_obj()?;
                QueueClear {
                    stream_id: hdr.stream_id.into(),
                    queue_type: queue_type.try_into()?,
                }
            }
            VIRTIO_VIDEO_CMD_GET_PARAMS => {
                let virtio_video_get_params { queue_type, .. } = r.read_obj()?;
                GetParams {
                    stream_id: hdr.stream_id.into(),
                    queue_type: queue_type.try_into()?,
                }
            }
            VIRTIO_VIDEO_CMD_SET_PARAMS => {
                let virtio_video_set_params { params } = r.read_obj()?;
                SetParams {
                    stream_id: hdr.stream_id.into(),
                    queue_type: params.queue_type.try_into()?,
                    params: params.try_into()?,
                }
            }
            VIRTIO_VIDEO_CMD_QUERY_CONTROL => {
                let body = r.read_obj::<virtio_video_query_control>()?;
                let query_ctrl_type = match body.control.into() {
                    VIRTIO_VIDEO_CONTROL_PROFILE => QueryCtrlType::Profile(
                        r.read_obj::<virtio_video_query_control_profile>()?
                            .format
                            .try_into()?,
                    ),
                    VIRTIO_VIDEO_CONTROL_LEVEL => QueryCtrlType::Level(
                        r.read_obj::<virtio_video_query_control_level>()?
                            .format
                            .try_into()?,
                    ),
                    t => {
                        return Err(ReadCmdError::UnsupportedCtrlType(t));
                    }
                };
                QueryControl { query_ctrl_type }
            }
            VIRTIO_VIDEO_CMD_GET_CONTROL => {
                let virtio_video_get_control { control, .. } = r.read_obj()?;
                let ctrl_type = match control.into() {
                    VIRTIO_VIDEO_CONTROL_BITRATE => CtrlType::Bitrate,
                    VIRTIO_VIDEO_CONTROL_PROFILE => CtrlType::Profile,
                    VIRTIO_VIDEO_CONTROL_LEVEL => CtrlType::Level,
                    VIRTIO_VIDEO_CONTROL_FORCE_KEYFRAME => CtrlType::ForceKeyframe,
                    t => {
                        return Err(ReadCmdError::UnsupportedCtrlType(t));
                    }
                };
                GetControl {
                    stream_id: hdr.stream_id.into(),
                    ctrl_type,
                }
            }
            VIRTIO_VIDEO_CMD_SET_CONTROL => {
                let virtio_video_set_control { control, .. } = r.read_obj()?;
                let ctrl_val = match control.into() {
                    VIRTIO_VIDEO_CONTROL_BITRATE => CtrlVal::Bitrate(
                        r.read_obj::<virtio_video_control_val_bitrate>()?
                            .bitrate
                            .into(),
                    ),
                    VIRTIO_VIDEO_CONTROL_PROFILE => CtrlVal::Profile(
                        r.read_obj::<virtio_video_control_val_profile>()?
                            .profile
                            .try_into()?,
                    ),
                    VIRTIO_VIDEO_CONTROL_LEVEL => CtrlVal::Level(
                        r.read_obj::<virtio_video_control_val_level>()?
                            .level
                            .try_into()?,
                    ),
                    VIRTIO_VIDEO_CONTROL_FORCE_KEYFRAME => CtrlVal::ForceKeyframe(),
                    t => {
                        return Err(ReadCmdError::UnsupportedCtrlType(t));
                    }
                };
                SetControl {
                    stream_id: hdr.stream_id.into(),
                    ctrl_val,
                }
            }
            _ => return Err(ReadCmdError::InvalidCmdType(hdr.type_.into())),
        })
    }
}
<|endoftext|>


<commit_before>//! This module contains all render objects used in OrbTk. Render
//! objects are used to define how to draw parts of a widget.

use std::{any::Any, collections::BTreeMap};

use dces::prelude::*;

use crate::{application::ContextProvider, prelude::*, render::RenderContext2D, utils::*};

pub use self::cursor::*;
pub use self::default::*;
pub use self::font_icon::*;
pub use self::image::*;
pub use self::pipeline::*;
pub use self::rectangle::*;
pub use self::text::*;

mod cursor;
mod default;
mod font_icon;
mod image;
mod pipeline;
mod rectangle;
mod text;

pub trait RenderObject: Any {
    fn render(
        &self,
        render_context: &mut RenderContext2D,
        entity: Entity,
        ecm: &mut EntityComponentManager<Tree>,
        context_provider: &ContextProvider,
        theme: &Rc<Theme>,
        offsets: &mut BTreeMap<Entity, (f64, f64)>,
        debug: bool,
    ) {
        let mut global_position = Point::default();

        if let Some(parent) = ecm.entity_store().parent[&entity] {
            if let Some(offset) = offsets.get(&parent) {
                global_position = Point::new(offset.0, offset.1);
            }
        }

        if let Ok(visibility) = ecm
            .component_store()
            .get::<Visibility>("visibility", entity)
        {
            if *visibility != Visibility::Visible {
                return;
            }
        } else {
            return;
        }

        render_context.begin_path();
        render_context.set_alpha(
            *ecm.component_store()
                .get::<f32>("opacity", entity)
                .unwrap_or(&1.0),
        );

        // Could be unwrap because every widget has the clip property
        let clip = *ecm.component_store().get::<bool>("clip", entity).unwrap();
        if clip {
            if let Ok(bounds) = ecm.component_store().get::<Rectangle>("bounds", entity) {
                render_context.save();
                render_context.rect(
                    global_position.x() + bounds.x(),
                    global_position.y() + bounds.y(),
                    bounds.width(),
                    bounds.height(),
                );
                render_context.clip();
            }
        }

        self.render_self(
            &mut Context::new((entity, ecm), &theme, context_provider, render_context),
            &global_position,
        );

        let mut global_pos = (0.0, 0.0);

        if let Ok(bounds) = ecm.component_store().get::<Rectangle>("bounds", entity) {
            global_pos = (
                global_position.x() + bounds.x(),
                global_position.y() + bounds.y(),
            );
            offsets.insert(entity, global_pos);
        }

        if let Ok(g_pos) = ecm
            .component_store_mut()
            .get_mut::<Point>("position", entity)
        {
            g_pos.set_x(global_pos.0);
            g_pos.set_y(global_pos.1);
        }

        self.render_children(
            render_context,
            entity,
            ecm,
            context_provider,
            &theme,
            offsets,
            debug,
        );

        render_context.close_path();

        if clip {
            render_context.restore();
        }

        // render debug border for each widget
        if debug {
            if let Ok(bounds) = ecm.component_store().get::<Rectangle>("bounds", entity) {
                render_context.begin_path();
                render_context.set_stroke_style(Brush::from("#0033cc"));
                render_context.stroke_rect(
                    global_position.x() + bounds.x(),
                    global_position.y() + bounds.y(),
                    bounds.width(),
                    bounds.height(),
                );
                render_context.close_path();
            }
        }
    }

    fn render_self(&self, _: &mut Context, _: &Point) {}

    fn render_children(
        &self,
        render_context: &mut RenderContext2D,
        entity: Entity,
        ecm: &mut EntityComponentManager<Tree>,
        context_provider: &ContextProvider,
        theme: &Rc<Theme>,
        offsets: &mut BTreeMap<Entity, (f64, f64)>,
        debug: bool,
    ) {
        for index in 0..ecm.entity_store().children[&entity].len() {
            let child = ecm.entity_store().children[&entity][index];

            if let Some(render_object) = context_provider.render_objects.borrow().get(&child) {
                render_object.render(
                    render_context,
                    child,
                    ecm,
                    context_provider,
                    &theme,
                    offsets,
                    debug,
                );
            }
        }
    }
}
<commit_msg>orbtk_core: update render_object documentation<commit_after>//! This module contains all render objects used in OrbTk. Render
//! objects are used to define how to draw parts of a widget.

use std::{any::Any, collections::BTreeMap};

use dces::prelude::*;

use crate::{application::ContextProvider, prelude::*, render::RenderContext2D, utils::*};

pub use self::cursor::*;
pub use self::default::*;
pub use self::font_icon::*;
pub use self::image::*;
pub use self::pipeline::*;
pub use self::rectangle::*;
pub use self::text::*;

mod cursor;
mod default;
mod font_icon;
mod image;
mod pipeline;
mod rectangle;
mod text;

/// The `RenderObject` trait defines rendering of 2D objects.
///
/// The trait is acting as a wrapper to the render subcrate. Calls to
/// render objects (self, or its children) will consume the `renderer`
/// methods. The acutual subcrate path is brought into scape with the
/// identifier `render` which resolves to `orbtk_tinyskia` by now.
pub trait RenderObject: Any {
    fn render(
        &self,
        render_context: &mut RenderContext2D,
        entity: Entity,
        ecm: &mut EntityComponentManager<Tree>,
        context_provider: &ContextProvider,
        theme: &Rc<Theme>,
        offsets: &mut BTreeMap<Entity, (f64, f64)>,
        debug: bool,
    ) {
        let mut global_position = Point::default();

        if let Some(parent) = ecm.entity_store().parent[&entity] {
            if let Some(offset) = offsets.get(&parent) {
                global_position = Point::new(offset.0, offset.1);
            }
        }

        if let Ok(visibility) = ecm
            .component_store()
            .get::<Visibility>("visibility", entity)
        {
            if *visibility != Visibility::Visible {
                return;
            }
        } else {
            return;
        }

        render_context.begin_path();
        render_context.set_alpha(
            *ecm.component_store()
                .get::<f32>("opacity", entity)
                .unwrap_or(&1.0),
        );

        // We can safely use unwrap(), because every widget implements the clip property
        let clip = *ecm.component_store().get::<bool>("clip", entity).unwrap();
        if clip {
            if let Ok(bounds) = ecm.component_store().get::<Rectangle>("bounds", entity) {
                render_context.save();
                render_context.rect(
                    global_position.x() + bounds.x(),
                    global_position.y() + bounds.y(),
                    bounds.width(),
                    bounds.height(),
                );
                render_context.clip();
            }
        }

        self.render_self(
            &mut Context::new((entity, ecm), &theme, context_provider, render_context),
            &global_position,
        );

        let mut global_pos = (0.0, 0.0);

        if let Ok(bounds) = ecm.component_store().get::<Rectangle>("bounds", entity) {
            global_pos = (
                global_position.x() + bounds.x(),
                global_position.y() + bounds.y(),
            );
            offsets.insert(entity, global_pos);
        }

        if let Ok(g_pos) = ecm
            .component_store_mut()
            .get_mut::<Point>("position", entity)
        {
            g_pos.set_x(global_pos.0);
            g_pos.set_y(global_pos.1);
        }

        self.render_children(
            render_context,
            entity,
            ecm,
            context_provider,
            &theme,
            offsets,
            debug,
        );

        render_context.close_path();

        if clip {
            render_context.restore();
        }

        // debug mode: render each widget with a border
        if debug {
            if let Ok(bounds) = ecm.component_store().get::<Rectangle>("bounds", entity) {
                render_context.begin_path();
                render_context.set_stroke_style(Brush::from("#0033cc"));
                render_context.stroke_rect(
                    global_position.x() + bounds.x(),
                    global_position.y() + bounds.y(),
                    bounds.width(),
                    bounds.height(),
                );
                render_context.close_path();
            }
        }
    }

    fn render_self(&self, _: &mut Context, _: &Point) {}

    fn render_children(
        &self,
        render_context: &mut RenderContext2D,
        entity: Entity,
        ecm: &mut EntityComponentManager<Tree>,
        context_provider: &ContextProvider,
        theme: &Rc<Theme>,
        offsets: &mut BTreeMap<Entity, (f64, f64)>,
        debug: bool,
    ) {
        for index in 0..ecm.entity_store().children[&entity].len() {
            let child = ecm.entity_store().children[&entity][index];

            if let Some(render_object) = context_provider.render_objects.borrow().get(&child) {
                render_object.render(
                    render_context,
                    child,
                    ecm,
                    context_provider,
                    &theme,
                    offsets,
                    debug,
                );
            }
        }
    }
}
<|endoftext|>


<commit_before>// Copyright (C) 2017, 2018 O.S. Systems Sofware LTDA
//
// SPDX-License-Identifier: Apache-2.0
use slog_scope::info;

use structopt::StructOpt;
use updatehub;

#[derive(StructOpt, Debug)]
#[structopt(
    no_version,
    name = "updatehub",
    author = "O.S. Systems Software LTDA. <contact@ossystems.com.br>",
    about = "A generic and safe Firmware Over-The-Air agent.",
    version = updatehub::version()
)]
struct Opt {
    /// Increase the verboseness level
    #[structopt(short = "v", long = "verbose", parse(from_occurrences))]
    verbose: usize,
}

fn run() -> Result<(), failure::Error> {
    let opt = Opt::from_args();

    updatehub::logger::init(opt.verbose);
    info!("Starting UpdateHub Agent {}", updatehub::version());

    let settings = updatehub::Settings::load()?;
    updatehub::run(settings)?;

    Ok(())
}

fn main() {
    if let Err(ref e) = run() {
        eprintln!("{}", e);
        e.iter_causes().skip(1).for_each(|e| eprintln!(" caused by: {}\n", e));

        std::process::exit(1);
    }
}
<commit_msg>clippy: Remove unecessary `use`<commit_after>// Copyright (C) 2017, 2018 O.S. Systems Sofware LTDA
//
// SPDX-License-Identifier: Apache-2.0
use slog_scope::info;

use structopt::StructOpt;

#[derive(StructOpt, Debug)]
#[structopt(
    no_version,
    name = "updatehub",
    author = "O.S. Systems Software LTDA. <contact@ossystems.com.br>",
    about = "A generic and safe Firmware Over-The-Air agent.",
    version = updatehub::version()
)]
struct Opt {
    /// Increase the verboseness level
    #[structopt(short = "v", long = "verbose", parse(from_occurrences))]
    verbose: usize,
}

fn run() -> Result<(), failure::Error> {
    let opt = Opt::from_args();

    updatehub::logger::init(opt.verbose);
    info!("Starting UpdateHub Agent {}", updatehub::version());

    let settings = updatehub::Settings::load()?;
    updatehub::run(settings)?;

    Ok(())
}

fn main() {
    if let Err(ref e) = run() {
        eprintln!("{}", e);
        e.iter_causes().skip(1).for_each(|e| eprintln!(" caused by: {}\n", e));

        std::process::exit(1);
    }
}
<|endoftext|>


<commit_before>// See LICENSE file for copyright and license details.

use cgmath::vector::Vec2;

#[deriving(Decodable)]
pub struct Size2<T> {
    x: T,
    y: T,
}

pub type Bool = bool;
pub type Int = i32; // TODO: rename, collision with trait

pub type PlayerId = Int;
pub type UnitId = Int;
pub type MapPos = Vec2<Int>;

// vim: set tabstop=4 shiftwidth=4 softtabstop=4 expandtab:
<commit_msg>core_types.rs: Dir<commit_after>// See LICENSE file for copyright and license details.

use cgmath::vector::Vec2;

#[deriving(Decodable)]
pub struct Size2<T> {
    x: T,
    y: T,
}

pub type Bool = bool;
pub type Int = i32; // TODO: rename, collision with trait

pub type PlayerId = Int;
pub type UnitId = Int;
pub type MapPos = Vec2<Int>;

pub enum Dir {
  NorthEast,
  East,
  SouthEast,
  SouthWest,
  West,
  NorthWest,
}

// vim: set tabstop=4 shiftwidth=4 softtabstop=4 expandtab:
<|endoftext|>