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

use super::xhci_abi::{Error as TrbError, NormalTrb, TransferDescriptor, TrbCast, TrbType};
use bit_field::Error as BitFieldError;
use std::fmt::{self, Display};
use sys_util::{GuestAddress, GuestMemory, GuestMemoryError};

#[derive(Debug)]
pub enum Error {
    ReadGuestMemory(GuestMemoryError),
    WriteGuestMemory(GuestMemoryError),
    UnknownTrbType(BitFieldError),
    CastTrb(TrbError),
    BadTrbType(TrbType),
}

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

impl Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use self::Error::*;

        match self {
            ReadGuestMemory(e) => write!(f, "cannot read guest memory: {}", e),
            WriteGuestMemory(e) => write!(f, "cannot write guest memory: {}", e),
            UnknownTrbType(e) => write!(f, "unknown trb type: {}", e),
            CastTrb(e) => write!(f, "cannot cast trb: {}", e),
            BadTrbType(t) => write!(f, "should not build buffer from trb type: {:?}", t),
        }
    }
}

/// See xHCI spec 3.2.8 for scatter/gather transfer. It's used in bulk/interrupt transfers. See
/// 3.2.10 for details.
pub struct ScatterGatherBuffer {
    mem: GuestMemory,
    td: TransferDescriptor,
}

impl ScatterGatherBuffer {
    /// Create a new buffer from transfer descriptor.
    pub fn new(mem: GuestMemory, td: TransferDescriptor) -> Result<ScatterGatherBuffer> {
        for atrb in &td {
            let trb_type = atrb.trb.get_trb_type().map_err(Error::UnknownTrbType)?;
            if trb_type != TrbType::Normal
                && trb_type != TrbType::DataStage
                && trb_type != TrbType::Isoch
            {
                return Err(Error::BadTrbType(trb_type));
            }
        }
        Ok(ScatterGatherBuffer { mem, td })
    }

    /// Total len of this buffer.
    pub fn len(&self) -> Result<usize> {
        let mut total_len = 0usize;
        for atrb in &self.td {
            total_len += atrb
                .trb
                .cast::<NormalTrb>()
                .map_err(Error::CastTrb)?
                .get_trb_transfer_length() as usize;
        }
        Ok(total_len)
    }

    /// Read content to buffer, return number of bytes read.
    pub fn read(&self, buffer: &mut [u8]) -> Result<usize> {
        let mut total_size = 0usize;
        let mut offset = 0;
        for atrb in &self.td {
            let normal_trb = atrb.trb.cast::<NormalTrb>().map_err(Error::CastTrb)?;
            let len = normal_trb.get_trb_transfer_length() as usize;
            let buffer_len = {
                if offset == buffer.len() {
                    return Ok(total_size);
                }
                if buffer.len() > offset + len {
                    len
                } else {
                    buffer.len() - offset
                }
            };
            let buffer_end = offset + buffer_len;
            let cur_buffer = &mut buffer[offset..buffer_end];
            offset = buffer_end;
            total_size += self
                .mem
                .read_at_addr(cur_buffer, GuestAddress(normal_trb.get_data_buffer()))
                .map_err(Error::ReadGuestMemory)?;
        }
        Ok(total_size)
    }

    /// Write content from buffer, return number of bytes written.
    pub fn write(&self, buffer: &[u8]) -> Result<usize> {
        let mut total_size = 0usize;
        let mut offset = 0;
        for atrb in &self.td {
            let normal_trb = atrb.trb.cast::<NormalTrb>().map_err(Error::CastTrb)?;
            let len = normal_trb.get_trb_transfer_length() as usize;
            let buffer_len = {
                if offset == buffer.len() {
                    return Ok(total_size);
                }
                if buffer.len() > offset + len {
                    len
                } else {
                    buffer.len() - offset
                }
            };
            let buffer_end = offset + buffer_len;
            let cur_buffer = &buffer[offset..buffer_end];
            offset = buffer_end;
            total_size += self
                .mem
                .write_at_addr(cur_buffer, GuestAddress(normal_trb.get_data_buffer()))
                .map_err(Error::WriteGuestMemory)?;
        }
        Ok(total_size)
    }
}

#[cfg(test)]
mod test {
    use super::*;
    use crate::usb::xhci::xhci_abi::{AddressedTrb, Trb};

    #[test]
    fn scatter_gather_buffer_test() {
        let gm = GuestMemory::new(&vec![(GuestAddress(0), 0x1000)]).unwrap();
        let mut td = TransferDescriptor::new();

        // In this td, we are going to have scatter buffer at 0x100, length 4, 0x200 length 2 and
        // 0x300 length 1.

        let mut trb = Trb::new();
        let ntrb = trb.cast_mut::<NormalTrb>().unwrap();
        ntrb.set_trb_type(TrbType::Normal);
        ntrb.set_data_buffer(0x100);
        ntrb.set_trb_transfer_length(4);
        td.push(AddressedTrb { trb, gpa: 0 });

        let mut trb = Trb::new();
        let ntrb = trb.cast_mut::<NormalTrb>().unwrap();
        ntrb.set_trb_type(TrbType::Normal);
        ntrb.set_data_buffer(0x200);
        ntrb.set_trb_transfer_length(2);
        td.push(AddressedTrb { trb, gpa: 0 });

        let mut trb = Trb::new();
        let ntrb = trb.cast_mut::<NormalTrb>().unwrap();
        ntrb.set_trb_type(TrbType::Normal);
        ntrb.set_data_buffer(0x300);
        ntrb.set_trb_transfer_length(1);
        td.push(AddressedTrb { trb, gpa: 0 });

        let buffer = ScatterGatherBuffer::new(gm.clone(), td).unwrap();

        assert_eq!(buffer.len().unwrap(), 7);
        let data_to_write: [u8; 7] = [7, 6, 5, 4, 3, 2, 1];
        buffer.write(&data_to_write).unwrap();

        let mut d = [0; 4];
        gm.read_exact_at_addr(&mut d, GuestAddress(0x100)).unwrap();
        assert_eq!(d, [7, 6, 5, 4]);
        gm.read_exact_at_addr(&mut d, GuestAddress(0x200)).unwrap();
        assert_eq!(d, [3, 2, 0, 0]);
        gm.read_exact_at_addr(&mut d, GuestAddress(0x300)).unwrap();
        assert_eq!(d, [1, 0, 0, 0]);

        let mut data_read = [0; 7];
        buffer.read(&mut data_read).unwrap();
        assert_eq!(data_to_write, data_read);
    }
}
<commit_msg>devices: xhci: support TRB Immediate Data bit<commit_after>// Copyright 2019 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

use super::xhci_abi::{
    AddressedTrb, Error as TrbError, NormalTrb, TransferDescriptor, TrbCast, TrbType,
};
use bit_field::Error as BitFieldError;
use std::fmt::{self, Display};
use sys_util::{GuestAddress, GuestMemory, GuestMemoryError};

#[derive(Debug)]
pub enum Error {
    ReadGuestMemory(GuestMemoryError),
    WriteGuestMemory(GuestMemoryError),
    UnknownTrbType(BitFieldError),
    CastTrb(TrbError),
    BadTrbType(TrbType),
    ImmediateDataTooLong(usize),
}

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

impl Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use self::Error::*;

        match self {
            ReadGuestMemory(e) => write!(f, "cannot read guest memory: {}", e),
            WriteGuestMemory(e) => write!(f, "cannot write guest memory: {}", e),
            UnknownTrbType(e) => write!(f, "unknown trb type: {}", e),
            CastTrb(e) => write!(f, "cannot cast trb: {}", e),
            BadTrbType(t) => write!(f, "should not build buffer from trb type: {:?}", t),
            ImmediateDataTooLong(l) => write!(f, "immediate data longer than allowed: {}", l),
        }
    }
}

/// See xHCI spec 3.2.8 for scatter/gather transfer. It's used in bulk/interrupt transfers. See
/// 3.2.10 for details.
pub struct ScatterGatherBuffer {
    mem: GuestMemory,
    td: TransferDescriptor,
}

impl ScatterGatherBuffer {
    /// Create a new buffer from transfer descriptor.
    pub fn new(mem: GuestMemory, td: TransferDescriptor) -> Result<ScatterGatherBuffer> {
        for atrb in &td {
            let trb_type = atrb.trb.get_trb_type().map_err(Error::UnknownTrbType)?;
            if trb_type != TrbType::Normal
                && trb_type != TrbType::DataStage
                && trb_type != TrbType::Isoch
            {
                return Err(Error::BadTrbType(trb_type));
            }
        }
        Ok(ScatterGatherBuffer { mem, td })
    }

    /// Total len of this buffer.
    pub fn len(&self) -> Result<usize> {
        let mut total_len = 0usize;
        for atrb in &self.td {
            total_len += atrb
                .trb
                .cast::<NormalTrb>()
                .map_err(Error::CastTrb)?
                .get_trb_transfer_length() as usize;
        }
        Ok(total_len)
    }

    /// Get the guest address and length of the TRB's data buffer.
    /// This is usually a separate buffer pointed to by the TRB,
    /// but it can also be within the TRB itself in the case of immediate data.
    fn get_trb_data(&self, atrb: &AddressedTrb) -> Result<(GuestAddress, usize)> {
        let normal_trb = atrb.trb.cast::<NormalTrb>().map_err(Error::CastTrb)?;
        let len = normal_trb.get_trb_transfer_length() as usize;
        let addr = if normal_trb.get_immediate_data() == 1 {
            // If the Immediate Data flag is set, the first <= 8 bytes of the TRB hold the data.
            if len > 8 {
                return Err(Error::ImmediateDataTooLong(len));
            }
            atrb.gpa
        } else {
            normal_trb.get_data_buffer()
        };
        Ok((GuestAddress(addr), len))
    }

    /// Read content to buffer, return number of bytes read.
    pub fn read(&self, buffer: &mut [u8]) -> Result<usize> {
        let mut total_size = 0usize;
        let mut offset = 0;
        for atrb in &self.td {
            let (guest_address, len) = self.get_trb_data(&atrb)?;
            let buffer_len = {
                if offset == buffer.len() {
                    return Ok(total_size);
                }
                if buffer.len() > offset + len {
                    len
                } else {
                    buffer.len() - offset
                }
            };
            let buffer_end = offset + buffer_len;
            let cur_buffer = &mut buffer[offset..buffer_end];
            offset = buffer_end;
            total_size += self
                .mem
                .read_at_addr(cur_buffer, guest_address)
                .map_err(Error::ReadGuestMemory)?;
        }
        Ok(total_size)
    }

    /// Write content from buffer, return number of bytes written.
    pub fn write(&self, buffer: &[u8]) -> Result<usize> {
        let mut total_size = 0usize;
        let mut offset = 0;
        for atrb in &self.td {
            let (guest_address, len) = self.get_trb_data(&atrb)?;
            let buffer_len = {
                if offset == buffer.len() {
                    return Ok(total_size);
                }
                if buffer.len() > offset + len {
                    len
                } else {
                    buffer.len() - offset
                }
            };
            let buffer_end = offset + buffer_len;
            let cur_buffer = &buffer[offset..buffer_end];
            offset = buffer_end;
            total_size += self
                .mem
                .write_at_addr(cur_buffer, guest_address)
                .map_err(Error::WriteGuestMemory)?;
        }
        Ok(total_size)
    }
}

#[cfg(test)]
mod test {
    use super::*;
    use crate::usb::xhci::xhci_abi::{AddressedTrb, Trb};

    #[test]
    fn scatter_gather_buffer_test() {
        let gm = GuestMemory::new(&vec![(GuestAddress(0), 0x1000)]).unwrap();
        let mut td = TransferDescriptor::new();

        // In this td, we are going to have scatter buffer at 0x100, length 4, 0x200 length 2 and
        // 0x300 length 1.

        let mut trb = Trb::new();
        let ntrb = trb.cast_mut::<NormalTrb>().unwrap();
        ntrb.set_trb_type(TrbType::Normal);
        ntrb.set_data_buffer(0x100);
        ntrb.set_trb_transfer_length(4);
        td.push(AddressedTrb { trb, gpa: 0 });

        let mut trb = Trb::new();
        let ntrb = trb.cast_mut::<NormalTrb>().unwrap();
        ntrb.set_trb_type(TrbType::Normal);
        ntrb.set_data_buffer(0x200);
        ntrb.set_trb_transfer_length(2);
        td.push(AddressedTrb { trb, gpa: 0 });

        let mut trb = Trb::new();
        let ntrb = trb.cast_mut::<NormalTrb>().unwrap();
        ntrb.set_trb_type(TrbType::Normal);
        ntrb.set_data_buffer(0x300);
        ntrb.set_trb_transfer_length(1);
        td.push(AddressedTrb { trb, gpa: 0 });

        let buffer = ScatterGatherBuffer::new(gm.clone(), td).unwrap();

        assert_eq!(buffer.len().unwrap(), 7);
        let data_to_write: [u8; 7] = [7, 6, 5, 4, 3, 2, 1];
        buffer.write(&data_to_write).unwrap();

        let mut d = [0; 4];
        gm.read_exact_at_addr(&mut d, GuestAddress(0x100)).unwrap();
        assert_eq!(d, [7, 6, 5, 4]);
        gm.read_exact_at_addr(&mut d, GuestAddress(0x200)).unwrap();
        assert_eq!(d, [3, 2, 0, 0]);
        gm.read_exact_at_addr(&mut d, GuestAddress(0x300)).unwrap();
        assert_eq!(d, [1, 0, 0, 0]);

        let mut data_read = [0; 7];
        buffer.read(&mut data_read).unwrap();
        assert_eq!(data_to_write, data_read);
    }

    #[test]
    fn immediate_data_test() {
        let gm = GuestMemory::new(&vec![(GuestAddress(0), 0x1000)]).unwrap();
        let mut td = TransferDescriptor::new();

        let expected_immediate_data: [u8; 8] = [0xDE, 0xAD, 0xBE, 0xEF, 0xF0, 0x0D, 0xCA, 0xFE];

        let mut trb = Trb::new();
        let ntrb = trb.cast_mut::<NormalTrb>().unwrap();
        ntrb.set_trb_type(TrbType::Normal);
        ntrb.set_data_buffer(u64::from_le_bytes(expected_immediate_data));
        ntrb.set_trb_transfer_length(8);
        ntrb.set_immediate_data(1);
        td.push(AddressedTrb { trb, gpa: 0xC00 });

        gm.write_obj_at_addr(trb, GuestAddress(0xc00)).unwrap();

        let buffer = ScatterGatherBuffer::new(gm.clone(), td).unwrap();

        let mut data_read = [0; 8];
        buffer.read(&mut data_read).unwrap();
        assert_eq!(data_read, expected_immediate_data);
    }
}
<|endoftext|>


<commit_before>use std::fs;
use std::path::{Path, PathBuf};
use std::ffi::OsStr;
use toml;
use semver::Version;
use rr_result::RrResult;
use utils::{modify_file, map_file};

#[derive(Debug)]
pub struct CargoProj {
    /// the name of the cargo project
    name: String,

    /// the version of the cargo project
    version: Version,

    /// the path to the `Cargo.toml`
    cargo_toml: PathBuf,

    /// the path to an optinal changelog file
    changelog: Option<PathBuf>
}

impl CargoProj {
    /// Searches for the root directory (containing a `Cargo.toml`) of the cargo project starting
    /// at `start_dir` and continuing the search upwards the directory tree until it's found.
    pub fn find(start_dir: &Path) -> RrResult<CargoProj> {
        let cargo_dir = find_cargo_toml_dir(start_dir)?;

        let cargo_toml = cargo_dir.join("Cargo.toml");
        let toml = parse_toml(&cargo_toml)?;

        let package = toml.as_table()
            .and_then(|t| t.get("package"))
            .ok_or(format!("Couldn't get 'package' table from: {:?}", toml))?;

        let name = package.get("name")
            .and_then(toml::Value::as_str)
            .ok_or(format!("Couldn't get 'name' string from: {:?}", package))?;

        let version = {
            let version_str = package.get("version")
                .and_then(toml::Value::as_str)
                .ok_or(format!("Couldn't get 'version' string from: {:?}", package))?;

            Version::parse(version_str)?
        };

        let changelog = find_changelog(&cargo_dir)?;

        Ok(CargoProj {
            name: name.to_string(),
            version: version,
            cargo_toml: cargo_toml,
            changelog: changelog
        })
    }

    /// The name of the cargo project.
    pub fn name(&self) -> &str {
        &self.name
    }

    /// The version of the cargo project.
    pub fn version(&self) -> &Version {
        &self.version
    }

    /// Write the new `version` into the `Cargo.toml`.
    pub fn write_version(&mut self, version: &Version) -> RrResult<()> {
        if *version != self.version {
            modify_file(&self.cargo_toml, |contents| {
                contents.replace(&format!("version = \"{}\"", self.version),
                                 &format!("version = \"{}\"", version))
            })?;

            self.version = version.clone();
        }

        Ok(())
    }

    /// The root directory of the cargo project.
    pub fn root_dir(&self) -> RrResult<&Path> {
        self.cargo_toml.parent()
            .ok_or(format!("Couldn't get directory of path: {:?}", self.cargo_toml).into())
    }

    pub fn changelog(&self) -> Option<&Path> {
        self.changelog.as_ref().map(|p| p.as_path())
    }
}

/// Convenience macro to read all files from a directory.
///
/// Should be possible to be written as a function, but for
/// now I didn't want to wrangle with rustc to find the
/// correct return type for ther FilterMap iterator adpater.
macro_rules! read_files {
    ($dir:expr) => (
        {
            let dir_entries = fs::read_dir($dir)?;

            let files = dir_entries.filter_map(|f| {
                match f {
                    Ok(f) => { let p = f.path(); if p.is_file() { Some(p) } else { None } },
                    _ => None
                }
            });

            files
        }
    )
}

/// Searches for a directory containing a `Cargo.toml` file starting at
/// `start_dir` and continuing the search upwards the directory tree
/// until a directory is found.
fn find_cargo_toml_dir(start_dir: &Path) -> RrResult<PathBuf> {
    let mut dir = start_dir.to_path_buf();
    loop {
        for file in read_files!(&dir) {
            if let Some("Cargo.toml") = file.file_name().and_then(OsStr::to_str) {
                return Ok(dir);
            }
        }

        if ! dir.pop() {
            return Err(format!("Couldn't find 'Cargo.toml' starting at directory '{}'!", start_dir.display()).into());
        }
    }
}

/// Searches for an optional changelog file in `dir`.
fn find_changelog(dir: &Path) -> RrResult<Option<PathBuf>> {
    for file in read_files!(dir) {
        if let Some(base_name) = file.file_stem().and_then(OsStr::to_str).map(str::to_lowercase) {
            if base_name == "changelog" {
                return Ok(Some(file));
            }
        }
    }

    Ok(None)
}

fn parse_toml(path: &Path) -> RrResult<toml::Value> {
    map_file(path, |contents| {
        let val = contents.parse::<toml::Value>()?;
        Ok(val)
    })
}
<commit_msg>Only replace first `version = ` line in Cargo.toml<commit_after>use std::fs;
use std::path::{Path, PathBuf};
use std::ffi::OsStr;
use toml;
use semver::Version;
use rr_result::RrResult;
use utils::{modify_file, map_file};

#[derive(Debug)]
pub struct CargoProj {
    /// the name of the cargo project
    name: String,

    /// the version of the cargo project
    version: Version,

    /// the path to the `Cargo.toml`
    cargo_toml: PathBuf,

    /// the path to an optinal changelog file
    changelog: Option<PathBuf>
}

impl CargoProj {
    /// Searches for the root directory (containing a `Cargo.toml`) of the cargo project starting
    /// at `start_dir` and continuing the search upwards the directory tree until it's found.
    pub fn find(start_dir: &Path) -> RrResult<CargoProj> {
        let cargo_dir = find_cargo_toml_dir(start_dir)?;

        let cargo_toml = cargo_dir.join("Cargo.toml");
        let toml = parse_toml(&cargo_toml)?;

        let package = toml.as_table()
            .and_then(|t| t.get("package"))
            .ok_or(format!("Couldn't get 'package' table from: {:?}", toml))?;

        let name = package.get("name")
            .and_then(toml::Value::as_str)
            .ok_or(format!("Couldn't get 'name' string from: {:?}", package))?;

        let version = {
            let version_str = package.get("version")
                .and_then(toml::Value::as_str)
                .ok_or(format!("Couldn't get 'version' string from: {:?}", package))?;

            Version::parse(version_str)?
        };

        let changelog = find_changelog(&cargo_dir)?;

        Ok(CargoProj {
            name: name.to_string(),
            version: version,
            cargo_toml: cargo_toml,
            changelog: changelog
        })
    }

    /// The name of the cargo project.
    pub fn name(&self) -> &str {
        &self.name
    }

    /// The version of the cargo project.
    pub fn version(&self) -> &Version {
        &self.version
    }

    /// Write the new `version` into the `Cargo.toml`.
    pub fn write_version(&mut self, version: &Version) -> RrResult<()> {
        if *version != self.version {
            modify_file(&self.cargo_toml, |contents| {
                contents.replacen(&format!("version = \"{}\"", self.version),
                                  &format!("version = \"{}\"", version), 1)
            })?;

            self.version = version.clone();
        }

        Ok(())
    }

    /// The root directory of the cargo project.
    pub fn root_dir(&self) -> RrResult<&Path> {
        self.cargo_toml.parent()
            .ok_or(format!("Couldn't get directory of path: {:?}", self.cargo_toml).into())
    }

    pub fn changelog(&self) -> Option<&Path> {
        self.changelog.as_ref().map(|p| p.as_path())
    }
}

/// Convenience macro to read all files from a directory.
///
/// Should be possible to be written as a function, but for
/// now I didn't want to wrangle with rustc to find the
/// correct return type for ther FilterMap iterator adpater.
macro_rules! read_files {
    ($dir:expr) => (
        {
            let dir_entries = fs::read_dir($dir)?;

            let files = dir_entries.filter_map(|f| {
                match f {
                    Ok(f) => { let p = f.path(); if p.is_file() { Some(p) } else { None } },
                    _ => None
                }
            });

            files
        }
    )
}

/// Searches for a directory containing a `Cargo.toml` file starting at
/// `start_dir` and continuing the search upwards the directory tree
/// until a directory is found.
fn find_cargo_toml_dir(start_dir: &Path) -> RrResult<PathBuf> {
    let mut dir = start_dir.to_path_buf();
    loop {
        for file in read_files!(&dir) {
            if let Some("Cargo.toml") = file.file_name().and_then(OsStr::to_str) {
                return Ok(dir);
            }
        }

        if ! dir.pop() {
            return Err(format!("Couldn't find 'Cargo.toml' starting at directory '{}'!", start_dir.display()).into());
        }
    }
}

/// Searches for an optional changelog file in `dir`.
fn find_changelog(dir: &Path) -> RrResult<Option<PathBuf>> {
    for file in read_files!(dir) {
        if let Some(base_name) = file.file_stem().and_then(OsStr::to_str).map(str::to_lowercase) {
            if base_name == "changelog" {
                return Ok(Some(file));
            }
        }
    }

    Ok(None)
}

fn parse_toml(path: &Path) -> RrResult<toml::Value> {
    map_file(path, |contents| {
        let val = contents.parse::<toml::Value>()?;
        Ok(val)
    })
}
<|endoftext|>


<commit_before> #![feature(augmented_assignments)]

extern crate cgmath;
extern crate docopt;
#[macro_use]
extern crate glium;
extern crate pbr;
extern crate rand;
extern crate rayon;
extern crate rustc_serialize;
extern crate time;

use docopt::Docopt;
use pbr::ProgressBar;
use rand::{SeedableRng, XorShiftRng};
use std::fmt;

mod nbody;
mod visualize;
use self::visualize::visualize_benchmarks;
use self::nbody::NBodyBenchmark;

const USAGE: &'static str = "
Usage: nbody bench [--no-par | --no-seq] [--visualize --bodies N --ticks N]
       nbody visualize [--bodies N]
       nbody (--help | --version)

Commands:
    bench              Run the benchmark and print the timings.
    visualize          Show the graphical visualizer.

Options:
    -h, --help         Show this message.
    --no-par           Skip parallel execution.
    --no-seq           Skip sequential execution.
    --bodies N         Use N bodies [default: 4000].
    --ticks N          Simulate for N ticks [default: 100].
";

#[derive(RustcDecodable)]
struct Args {
    cmd_benchmark: bool,
    cmd_visualize: bool,
    flag_no_par: bool,
    flag_no_seq: bool,
    flag_bodies: usize,
    flag_ticks: usize,
}

impl fmt::Display for Args {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        try!(writeln!(f, "Configuration:"));

        if self.cmd_benchmark   { try!(writeln!(f, "  bench")); }
        if self.cmd_visualize   { try!(writeln!(f, "  visualize")); }
        if self.flag_no_par     { try!(writeln!(f, "  --no-par")); }
        if self.flag_no_seq     { try!(writeln!(f, "  --no-seq")); }

        try!(writeln!(f, "  --bodies {}", self.flag_bodies));
        try!(writeln!(f, "  --ticks {}", self.flag_ticks));

        Ok(())
    }
}

fn main() {
    let args: Args =
        Docopt::new(USAGE)
            .and_then(|d| d.decode())
            .unwrap_or_else(|e| e.exit());

    if args.cmd_benchmark {
        run_benchmarks(!args.flag_no_par, !args.flag_no_seq,
                       args.flag_bodies, args.flag_ticks);
    }

    if args.cmd_visualize {
        visualize_benchmarks(args.flag_bodies);
    }
}

fn run_benchmarks(run_par: bool, run_seq: bool, bodies: usize, ticks: usize) {
    let par_time = if run_par {
        let mut rng = XorShiftRng::from_seed([0, 1, 2, 3]);
        let mut benchmark = NBodyBenchmark::new(bodies, &mut rng);
        let par_start = time::precise_time_ns();

        let mut progress = ProgressBar::new(ticks);
        for _ in 0..ticks {
            progress.inc();
            benchmark.tick_par();
        }
        progress.finish();

        Some(time::precise_time_ns() - par_start)
    } else {
        None
    };

    let seq_time = if run_seq {
        let mut rng = XorShiftRng::from_seed([0, 1, 2, 3]);
        let mut benchmark = NBodyBenchmark::new(bodies, &mut rng);
        let seq_start = time::precise_time_ns();

        let mut progress = ProgressBar::new(ticks);
        for _ in 0..ticks {
            progress.inc();
            benchmark.tick_seq();
        }
        progress.finish();

        Some(time::precise_time_ns() - seq_start)
    } else {
        None
    };

    if let Some(t) = par_time { println!("Parallel time   : {}", t); }
    if let Some(t) = seq_time { println!("Sequential time : {}", t); }

    if let (Some(pt), Some(st)) = (par_time, seq_time) {
        println!("Parallel speedup: {}", (st as f32) / (pt as f32));
    }
}
<commit_msg>Fix argument field name<commit_after> #![feature(augmented_assignments)]

extern crate cgmath;
extern crate docopt;
#[macro_use]
extern crate glium;
extern crate pbr;
extern crate rand;
extern crate rayon;
extern crate rustc_serialize;
extern crate time;

use docopt::Docopt;
use pbr::ProgressBar;
use rand::{SeedableRng, XorShiftRng};
use std::fmt;

mod nbody;
mod visualize;
use self::visualize::visualize_benchmarks;
use self::nbody::NBodyBenchmark;

const USAGE: &'static str = "
Usage: nbody bench [--no-par | --no-seq] [--visualize --bodies N --ticks N]
       nbody visualize [--bodies N]
       nbody (--help | --version)

Commands:
    bench              Run the benchmark and print the timings.
    visualize          Show the graphical visualizer.

Options:
    -h, --help         Show this message.
    --no-par           Skip parallel execution.
    --no-seq           Skip sequential execution.
    --bodies N         Use N bodies [default: 4000].
    --ticks N          Simulate for N ticks [default: 100].
";

#[derive(RustcDecodable)]
struct Args {
    cmd_bench: bool,
    cmd_visualize: bool,
    flag_no_par: bool,
    flag_no_seq: bool,
    flag_bodies: usize,
    flag_ticks: usize,
}

impl fmt::Display for Args {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        try!(writeln!(f, "Configuration:"));

        if self.cmd_bench       { try!(writeln!(f, "  bench")); }
        if self.cmd_visualize   { try!(writeln!(f, "  visualize")); }
        if self.flag_no_par     { try!(writeln!(f, "  --no-par")); }
        if self.flag_no_seq     { try!(writeln!(f, "  --no-seq")); }

        try!(writeln!(f, "  --bodies {}", self.flag_bodies));
        try!(writeln!(f, "  --ticks {}", self.flag_ticks));

        Ok(())
    }
}

fn main() {
    let args: Args =
        Docopt::new(USAGE)
            .and_then(|d| d.decode())
            .unwrap_or_else(|e| e.exit());

    if args.cmd_benchmark {
        run_benchmarks(!args.flag_no_par, !args.flag_no_seq,
                       args.flag_bodies, args.flag_ticks);
    }

    if args.cmd_visualize {
        visualize_benchmarks(args.flag_bodies);
    }
}

fn run_benchmarks(run_par: bool, run_seq: bool, bodies: usize, ticks: usize) {
    let par_time = if run_par {
        let mut rng = XorShiftRng::from_seed([0, 1, 2, 3]);
        let mut benchmark = NBodyBenchmark::new(bodies, &mut rng);
        let par_start = time::precise_time_ns();

        let mut progress = ProgressBar::new(ticks);
        for _ in 0..ticks {
            progress.inc();
            benchmark.tick_par();
        }
        progress.finish();

        Some(time::precise_time_ns() - par_start)
    } else {
        None
    };

    let seq_time = if run_seq {
        let mut rng = XorShiftRng::from_seed([0, 1, 2, 3]);
        let mut benchmark = NBodyBenchmark::new(bodies, &mut rng);
        let seq_start = time::precise_time_ns();

        let mut progress = ProgressBar::new(ticks);
        for _ in 0..ticks {
            progress.inc();
            benchmark.tick_seq();
        }
        progress.finish();

        Some(time::precise_time_ns() - seq_start)
    } else {
        None
    };

    if let Some(t) = par_time { println!("Parallel time   : {}", t); }
    if let Some(t) = seq_time { println!("Sequential time : {}", t); }

    if let (Some(pt), Some(st)) = (par_time, seq_time) {
        println!("Parallel speedup: {}", (st as f32) / (pt as f32));
    }
}
<|endoftext|>


<commit_before>use std::vec::Vec;
use regex::Regex;
use matching::*;
use files::*;
use tokens::*;
use support::*;

pub fn get_token_types<'a>() -> Vec<(&'a str, &'a str)>
{
    // TODO: Read types from rules file
    let mut token_types: Vec<(&str, &str)> = Vec::new();

    token_types.push(("comment.line",       	r"//[^\n|$]*"));
    token_types.push(("comment.block",      	r"/\*([^\*]|(\*[^/]))*\*/"));
    token_types.push(("control",            	r"\.|\(|\)|\{|}|\[|]|;|,"));
    token_types.push(("literal.int",        	r"(0(x|b|o|d))?[:digit:]+"));
    token_types.push(("literal.long",       	r"(0(x|b|o|d))?[:digit:]+[lL]"));
    token_types.push(("literal.float",      	r"(\.(\d+)(f|F)?)|((\d+)\.(\d+)(f|F)?)|((\d+)(f|F))"));
    token_types.push(("literal.double",     	r"[:digit:]*\.[:digit:]+"));
    token_types.push(("literal.char",       	r"'[a-z A-Z]?'"));
    token_types.push(("literal.string",     	"\"([^\"\n\r]|\\.)*\""));
    token_types.push(("literal.boolean",    	r"true|false"));
    token_types.push(("literal.null",       	r"null"));
    token_types.push(("block.generics.args",	r"<( )*([a-zA-Z],?( )*)+( )*>"));
    token_types.push(("operator.unary",     	r"(\+\+)|(--)"));
    token_types.push(("operator.binary",    	r"((\+|<<|>>|-|/|\*|\||&)=?)|="));
    token_types.push(("operator.comparator",	r">|>=|<|<=|&&|\|\||==|instanceof"));
    token_types.push(("type",               	r"boolean|long|int|byte|short|char|double|float|void"));
    token_types.push(("mod.permission",     	r"public|private|protected"));
    token_types.push(("mod.access",    			r"static"));
    token_types.push(("mod.behaviour", 			r"final|volitile|transient|synchronized|native|abstract|throws"));
    token_types.push(("mod.inheritance",		r"extends|implements"));
    token_types.push(("action",             	r"return|continue|break|throw|new|assert|strictfp"));
    token_types.push(("construct.conditional", 	r"if|else"));
    token_types.push(("construct.handles",		r"try|catch|finally"));
    token_types.push(("construct.switch", 		r"switch|case:|default:"));
    token_types.push(("construct.loop",		 	r"do|while|for"));
    token_types.push(("construct.type", 		r"class|interface|enum"));
    token_types.push(("special.package",      	r"package"));
    token_types.push(("special.reserved",   	r"goto|const"));
    token_types.push(("special.import",     	r"import( +static)?( )+([a-zA-Z\._])+\*?"));
    token_types.push(("identifier",				r"([:alpha:]|[\$_])+([:alnum:]|[\$_])*"));

    token_types
}

pub fn get_invalid_token_values<'a>() -> Vec<&'a str>
{
    // TODO: Read invalid types from rules file
    let mut invalid_tokens: Vec<&str> = Vec::new();

    invalid_tokens.push("enum");
    invalid_tokens.push("interface");

    invalid_tokens
}

pub fn get_invalid_token_types<'a>() -> Vec<&'a str>
{
    // TODO: Read invalid types from rules file
    let mut invalid_types: Vec<&str> = Vec::new();

    invalid_types.push("literal.null");
    invalid_types.push("block.generics.args");
    invalid_types.push("literal.string");
    invalid_types.push("literal.char");
    invalid_types.push("literal.float");
    invalid_types.push("literal.double");
    invalid_types.push("special.reserved");
    invalid_types.push("construct.conditional");
    invalid_types.push("construct.handles");
    invalid_types.push("construct.switch");
    invalid_types.push("construct.loop");

    invalid_types
}

pub fn lex_file<'a>(file_path: &str) -> Vec<Token<'a>>
{
    let input = read_in(file_path);
    lex_string(input)
}

pub fn lex_string<'a>(input: String) -> Vec<Token<'a>>
{
    // List the first match from each matcher; the index of the match will correspond to an index in matchers
    let mut matches: Vec<MatchResult> = Vec::new();
    let mut tokens: Vec<Token> = Vec::new();

    let token_types: Vec<(&str, &str)> = get_token_types();
    let matchers: Vec<Regex> = assemble_matchers(&token_types);

    let mut string_index = 0;
    while string_index < input.len()
    {
        let string = &input[string_index..];
        for (index, matcher) in matchers.iter().enumerate()
        {
            let token_name = token_types[index].0;
            let result = matcher.find(string);
            let match_result = MatchResult::parse(token_name, result, index);
            matches.push(match_result);
        }

        // print matches
        println!("\nMatches on {}:", string);
        for result in matches.iter()
        {
            println!("\t{}\t({}, {})\t{}", result.token_name, result.start, result.end, result.valid);
        }

        // Find the first match and add it as a token; stop when there are no tokens to be found
        let (valid, index) = find_first_match(&matches);
        if valid
        {
            {
                let match_result = &matches[index];
                let start = match_result.start + string_index;
                let end = match_result.end + string_index;
                let value = slice_of(&input, (start, end));
                let token = Token{name: match_result.token_name, range: (start, end), value: value};
                string_index = end;
                println!("\tThe dominant token is: {} at index: {} = {} with value: {}", matches[index].token_name, index, matches[index].index, token.value);
                println!("\tRange: ({}, {})", start, end);
                tokens.push(token);
            }
            matches.clear();
        }
        else
        {
            println!("no matches found");
            break;
        }
    }

    tokens
}
<commit_msg>Fix comment lexing<commit_after>use std::vec::Vec;
use regex::Regex;
use matching::*;
use files::*;
use tokens::*;
use support::*;

pub fn get_token_types<'a>() -> Vec<(&'a str, &'a str)>
{
    // TODO: Read types from rules file
    let mut token_types: Vec<(&str, &str)> = Vec::new();

    token_types.push(("comment.line",       	r"//[^\n]*"));
    token_types.push(("comment.block",      	r"/\*([^\*]|(\*[^/]))*\*/"));
    token_types.push(("control",            	r"\.|\(|\)|\{|}|\[|]|;|,"));
    token_types.push(("literal.int",        	r"(0(x|b|o|d))?[:digit:]+"));
    token_types.push(("literal.long",       	r"(0(x|b|o|d))?[:digit:]+[lL]"));
    token_types.push(("literal.float",      	r"(\.(\d+)(f|F)?)|((\d+)\.(\d+)(f|F)?)|((\d+)(f|F))"));
    token_types.push(("literal.double",     	r"[:digit:]*\.[:digit:]+"));
    token_types.push(("literal.char",       	r"'[a-z A-Z]?'"));
    token_types.push(("literal.string",     	"\"([^\"\n\r]|\\.)*\""));
    token_types.push(("literal.boolean",    	r"true|false"));
    token_types.push(("literal.null",       	r"null"));
    token_types.push(("block.generics.args",	r"<( )*([a-zA-Z],?( )*)+( )*>"));
    token_types.push(("operator.unary",     	r"(\+\+)|(--)"));
    token_types.push(("operator.binary",    	r"((\+|<<|>>|-|/|\*|\||&)=?)|="));
    token_types.push(("operator.comparator",	r">|>=|<|<=|&&|\|\||==|instanceof"));
    token_types.push(("type",               	r"boolean|long|int|byte|short|char|double|float|void"));
    token_types.push(("mod.permission",     	r"public|private|protected"));
    token_types.push(("mod.access",    			r"static"));
    token_types.push(("mod.behaviour", 			r"final|volitile|transient|synchronized|native|abstract|throws"));
    token_types.push(("mod.inheritance",		r"extends|implements"));
    token_types.push(("action",             	r"return|continue|break|throw|new|assert|strictfp"));
    token_types.push(("construct.conditional", 	r"if|else"));
    token_types.push(("construct.handles",		r"try|catch|finally"));
    token_types.push(("construct.switch", 		r"switch|case:|default:"));
    token_types.push(("construct.loop",		 	r"do|while|for"));
    token_types.push(("construct.type", 		r"class|interface|enum"));
    token_types.push(("special.package",      	r"package"));
    token_types.push(("special.reserved",   	r"goto|const"));
    token_types.push(("special.import",     	r"import( +static)?( )+([a-zA-Z\._])+\*?"));
    token_types.push(("identifier",				r"([:alpha:]|[\$_])+([:alnum:]|[\$_])*"));

    token_types
}

pub fn get_invalid_token_values<'a>() -> Vec<&'a str>
{
    // TODO: Read invalid types from rules file
    let mut invalid_tokens: Vec<&str> = Vec::new();

    invalid_tokens.push("enum");
    invalid_tokens.push("interface");

    invalid_tokens
}

pub fn get_invalid_token_types<'a>() -> Vec<&'a str>
{
    // TODO: Read invalid types from rules file
    let mut invalid_types: Vec<&str> = Vec::new();

    invalid_types.push("literal.null");
    invalid_types.push("block.generics.args");
    invalid_types.push("literal.string");
    invalid_types.push("literal.char");
    invalid_types.push("literal.float");
    invalid_types.push("literal.double");
    invalid_types.push("special.reserved");
    invalid_types.push("construct.conditional");
    invalid_types.push("construct.handles");
    invalid_types.push("construct.switch");
    invalid_types.push("construct.loop");

    invalid_types
}

pub fn lex_file<'a>(file_path: &str) -> Vec<Token<'a>>
{
    let input = read_in(file_path);
    lex_string(input)
}

pub fn lex_string<'a>(input: String) -> Vec<Token<'a>>
{
    // List the first match from each matcher; the index of the match will correspond to an index in matchers
    let mut matches: Vec<MatchResult> = Vec::new();
    let mut tokens: Vec<Token> = Vec::new();

    let token_types: Vec<(&str, &str)> = get_token_types();
    let matchers: Vec<Regex> = assemble_matchers(&token_types);

    let mut string_index = 0;
    while string_index < input.len()
    {
        let string = &input[string_index..];
        for (index, matcher) in matchers.iter().enumerate()
        {
            let token_name = token_types[index].0;
            let result = matcher.find(string);
            let match_result = MatchResult::parse(token_name, result, index);
            matches.push(match_result);
        }

        // print matches
        println!("\nMatches on {}:", string);
        for result in matches.iter()
        {
            println!("\t{}\t({}, {})\t{}", result.token_name, result.start, result.end, result.valid);
        }

        // Find the first match and add it as a token; stop when there are no tokens to be found
        let (valid, index) = find_first_match(&matches);
        if valid
        {
            {
                let match_result = &matches[index];
                let start = match_result.start + string_index;
                let end = match_result.end + string_index;
                let value = slice_of(&input, (start, end));
                let token = Token{name: match_result.token_name, range: (start, end), value: value};
                string_index = end;
                println!("\tThe dominant token is: {} at index: {} = {} with value: {}", matches[index].token_name, index, matches[index].index, token.value);
                println!("\tRange: ({}, {})", start, end);
                tokens.push(token);
            }
            matches.clear();
        }
        else
        {
            println!("no matches found");
            break;
        }
    }

    tokens
}
<|endoftext|>


<commit_before>//! # Functions and types used by generated protobuf code
//!
//! These are not considered to be public API of rust-protobuf,
//! so they can be changed any time (provided compatibility with
//! previously generated code is preserved).

pub use crate::cached_size::CachedSize;
use crate::coded_input_stream::CodedInputStream;
use crate::coded_output_stream::CodedOutputStream;
use crate::enums::Enum;
use crate::error::Result;
pub use crate::lazy::Lazy;
pub use crate::wire_format::WireType;
use crate::zigzag::*;
use crate::EnumOrUnknown;
use crate::Message;
use crate::MessageField;

pub(crate) mod map;
pub(crate) mod repeated;
pub(crate) mod unsorted;
pub use map::compute_map_size;
pub use map::read_map_into;
pub use map::write_map_with_cached_sizes;
pub use repeated::read_repeated_packed_enum_or_unknown_into;
pub use unsorted::read_unknown_or_skip_group;
pub use unsorted::unknown_fields_size;

use crate::varint::encode::encoded_varint64_len;

/// Given `u64` value compute varint encoded length.
pub fn compute_raw_varint64_size(value: u64) -> u64 {
    encoded_varint64_len(value) as u64
}

/// Given `u32` value compute varint encoded length.
pub(crate) fn compute_raw_varint32_size(value: u32) -> u64 {
    compute_raw_varint64_size(value as u64)
}

/// Fixed size integers.
pub trait ProtobufFixed {
    /// Size of this fixed type in bytes.
    const LEN: u32;
}

/// Helper trait implemented by integer types which could be encoded as varint.
pub trait ProtobufVarint {
    /// Size of self when encoded as varint.
    fn len_varint(&self) -> u64;
}

/// Helper trait implemented by integer types which could be encoded as zigzag varint.
pub trait ProtobufVarintZigzag {
    /// Size of self when encoded as zigzag varint.
    fn len_varint_zigzag(&self) -> u64;
}

impl ProtobufVarint for u64 {
    fn len_varint(&self) -> u64 {
        compute_raw_varint64_size(*self)
    }
}

impl ProtobufVarint for u32 {
    fn len_varint(&self) -> u64 {
        (*self as u64).len_varint()
    }
}

impl ProtobufVarint for i64 {
    fn len_varint(&self) -> u64 {
        // same as length of u64
        (*self as u64).len_varint()
    }
}

impl ProtobufVarintZigzag for i64 {
    fn len_varint_zigzag(&self) -> u64 {
        compute_raw_varint64_size(encode_zig_zag_64(*self))
    }
}

impl ProtobufVarint for i32 {
    fn len_varint(&self) -> u64 {
        // sign-extend and then compute
        (*self as i64).len_varint()
    }
}

impl ProtobufVarintZigzag for i32 {
    fn len_varint_zigzag(&self) -> u64 {
        compute_raw_varint32_size(encode_zig_zag_32(*self))
    }
}

impl ProtobufVarint for bool {
    fn len_varint(&self) -> u64 {
        1
    }
}

impl ProtobufFixed for u32 {
    const LEN: u32 = 4;
}

impl ProtobufFixed for i32 {
    const LEN: u32 = 4;
}

impl ProtobufFixed for u64 {
    const LEN: u32 = 8;
}

impl ProtobufFixed for i64 {
    const LEN: u32 = 8;
}

impl ProtobufFixed for f32 {
    const LEN: u32 = 4;
}

impl ProtobufFixed for f64 {
    const LEN: u32 = 8;
}

/// Technically `bool` is not fixed, but it can be considered as fixed
/// for the purpose of encoding.
impl ProtobufFixed for bool {
    const LEN: u32 = 1;
}

/// Size of serialized repeated packed field, excluding length and tag.
pub fn vec_packed_varint_data_size<T: ProtobufVarint>(vec: &[T]) -> u64 {
    vec.iter()
        .map(|v| v.len_varint() as u64)
        .fold(0, |a, i| a + i)
}

/// Size of serialized repeated packed field, excluding length and tag.
pub fn vec_packed_varint_zigzag_data_size<T: ProtobufVarintZigzag>(vec: &[T]) -> u64 {
    vec.iter()
        .map(|v| v.len_varint_zigzag())
        .fold(0, |a, i| a + i)
}

/// Size of serialized repeated packed enum field, excluding length and tag.
pub fn vec_packed_enum_or_unknown_data_size<E: Enum>(vec: &[EnumOrUnknown<E>]) -> u64 {
    vec.iter()
        .map(|e| compute_raw_varint32_size(e.value() as u32))
        .fold(0, |a, i| a + i)
}

/// Size of serialized data with length prefix and tag
pub fn vec_packed_varint_size<T: ProtobufVarint>(field_number: u32, vec: &[T]) -> u64 {
    if vec.is_empty() {
        0
    } else {
        let data_size = vec_packed_varint_data_size(vec);
        tag_size(field_number) + data_size.len_varint() + data_size
    }
}

/// Size of serialized data with length prefix and tag
pub fn vec_packed_varint_zigzag_size<T: ProtobufVarintZigzag>(field_number: u32, vec: &[T]) -> u64 {
    if vec.is_empty() {
        0
    } else {
        let data_size = vec_packed_varint_zigzag_data_size(vec);
        tag_size(field_number) + data_size.len_varint() + data_size
    }
}

/// Size of serialized data with length prefix and tag
pub fn vec_packed_enum_or_unknown_size<E: Enum>(
    field_number: u32,
    vec: &[EnumOrUnknown<E>],
) -> u64 {
    if vec.is_empty() {
        0
    } else {
        let data_size = vec_packed_enum_or_unknown_data_size(vec);
        tag_size(field_number) + data_size.len_varint() + data_size
    }
}

/// Compute data size of fixed encoding of repeated field data.
pub(crate) fn vec_packed_fixed_data_size<V: ProtobufFixed>(vec: &[V]) -> u64 {
    (vec.len() as u64) * (V::LEN as u64)
}

/// Compute field size (data plus header) of fixed encoding of repeated field.
pub fn vec_packed_fixed_size<V: ProtobufFixed>(field_number: u32, vec: &[V]) -> u64 {
    if vec.is_empty() {
        0
    } else {
        let data_size = vec_packed_fixed_data_size::<V>(vec);
        tag_size(field_number) + data_size.len_varint() + data_size
    }
}

/// Compute tag size. Size of tag does not depend on wire type.
pub fn tag_size(field_number: u32) -> u64 {
    encoded_varint64_len((field_number as u64) << 3) as u64
}

/// Size of encoded `sint32` value.
pub fn sint32_size_no_tag(value: i32) -> u64 {
    compute_raw_varint32_size(encode_zig_zag_32(value))
}

/// Size of encoded `sint64` value.
pub fn sint64_size_no_tag(value: i64) -> u64 {
    compute_raw_varint64_size(encode_zig_zag_64(value))
}

/// Size of encoded `int32` value.
pub fn int32_size_no_tag(value: i32) -> u64 {
    value.len_varint()
}

/// Size of encoded `int64` value.
pub fn int64_size_no_tag(value: i64) -> u64 {
    value.len_varint()
}

/// Size of encoded `uint32` value.
pub fn uint32_size_no_tag(value: u32) -> u64 {
    value.len_varint()
}

/// Size of encoded `uint64` value.
pub fn uint64_size_no_tag(value: u64) -> u64 {
    value.len_varint()
}

/// Size of encoded bytes field.
pub fn bytes_size_no_tag(bytes: &[u8]) -> u64 {
    compute_raw_varint64_size(bytes.len() as u64) + bytes.len() as u64
}

/// Size of encoded string field.
pub fn string_size_no_tag(s: &str) -> u64 {
    bytes_size_no_tag(s.as_bytes())
}

/// Read singular `message` field.
pub fn read_singular_message_into_field<M>(
    is: &mut CodedInputStream,
    target: &mut MessageField<M>,
) -> Result<()>
where
    M: Message,
{
    let mut m = M::new();
    is.merge_message(&mut m)?;
    *target = MessageField::some(m);
    Ok(())
}

/// Write message with field number and length to the stream.
pub fn write_message_field_with_cached_size<M>(
    field_number: u32,
    message: &M,
    os: &mut CodedOutputStream,
) -> Result<()>
where
    M: Message,
{
    os.write_tag(field_number, WireType::LengthDelimited)?;
    os.write_raw_varint32(message.cached_size())?;
    message.write_to_with_cached_sizes(os)
}
<commit_msg>Code cleanup<commit_after>//! # Functions and types used by generated protobuf code
//!
//! These are not considered to be public API of rust-protobuf,
//! so they can be changed any time (provided compatibility with
//! previously generated code is preserved).

pub use crate::cached_size::CachedSize;
use crate::coded_input_stream::CodedInputStream;
use crate::coded_output_stream::CodedOutputStream;
use crate::enums::Enum;
use crate::error::Result;
pub use crate::lazy::Lazy;
pub use crate::wire_format::WireType;
use crate::zigzag::*;
use crate::EnumOrUnknown;
use crate::Message;
use crate::MessageField;

pub(crate) mod map;
pub(crate) mod repeated;
pub(crate) mod unsorted;
pub use map::compute_map_size;
pub use map::read_map_into;
pub use map::write_map_with_cached_sizes;
pub use repeated::read_repeated_packed_enum_or_unknown_into;
pub use unsorted::read_unknown_or_skip_group;
pub use unsorted::unknown_fields_size;

use crate::varint::encode::encoded_varint64_len;

/// Given `u64` value compute varint encoded length.
pub fn compute_raw_varint64_size(value: u64) -> u64 {
    encoded_varint64_len(value) as u64
}

/// Given `u32` value compute varint encoded length.
pub(crate) fn compute_raw_varint32_size(value: u32) -> u64 {
    compute_raw_varint64_size(value as u64)
}

/// Fixed size integers.
pub trait ProtobufFixed {
    /// Size of this fixed type in bytes.
    const LEN: u32;
}

/// Helper trait implemented by integer types which could be encoded as varint.
pub trait ProtobufVarint {
    /// Size of self when encoded as varint.
    fn len_varint(&self) -> u64;
}

/// Helper trait implemented by integer types which could be encoded as zigzag varint.
pub trait ProtobufVarintZigzag {
    /// Size of self when encoded as zigzag varint.
    fn len_varint_zigzag(&self) -> u64;
}

impl ProtobufVarint for u64 {
    fn len_varint(&self) -> u64 {
        compute_raw_varint64_size(*self)
    }
}

impl ProtobufVarint for u32 {
    fn len_varint(&self) -> u64 {
        (*self as u64).len_varint()
    }
}

impl ProtobufVarint for i64 {
    fn len_varint(&self) -> u64 {
        // same as length of u64
        (*self as u64).len_varint()
    }
}

impl ProtobufVarintZigzag for i64 {
    fn len_varint_zigzag(&self) -> u64 {
        compute_raw_varint64_size(encode_zig_zag_64(*self))
    }
}

impl ProtobufVarint for i32 {
    fn len_varint(&self) -> u64 {
        // sign-extend and then compute
        (*self as i64).len_varint()
    }
}

impl ProtobufVarintZigzag for i32 {
    fn len_varint_zigzag(&self) -> u64 {
        compute_raw_varint32_size(encode_zig_zag_32(*self))
    }
}

impl ProtobufVarint for bool {
    fn len_varint(&self) -> u64 {
        1
    }
}

impl ProtobufFixed for u32 {
    const LEN: u32 = 4;
}

impl ProtobufFixed for i32 {
    const LEN: u32 = 4;
}

impl ProtobufFixed for u64 {
    const LEN: u32 = 8;
}

impl ProtobufFixed for i64 {
    const LEN: u32 = 8;
}

impl ProtobufFixed for f32 {
    const LEN: u32 = 4;
}

impl ProtobufFixed for f64 {
    const LEN: u32 = 8;
}

/// Technically `bool` is not fixed, but it can be considered as fixed
/// for the purpose of encoding.
impl ProtobufFixed for bool {
    const LEN: u32 = 1;
}

/// Size of serialized repeated packed field, excluding length and tag.
pub fn vec_packed_varint_data_size<T: ProtobufVarint>(vec: &[T]) -> u64 {
    vec.iter().map(|v| v.len_varint() as u64).sum()
}

/// Size of serialized repeated packed field, excluding length and tag.
pub fn vec_packed_varint_zigzag_data_size<T: ProtobufVarintZigzag>(vec: &[T]) -> u64 {
    vec.iter().map(|v| v.len_varint_zigzag()).sum()
}

/// Size of serialized repeated packed enum field, excluding length and tag.
pub fn vec_packed_enum_or_unknown_data_size<E: Enum>(vec: &[EnumOrUnknown<E>]) -> u64 {
    vec.iter()
        .map(|e| compute_raw_varint32_size(e.value() as u32))
        .sum()
}

/// Size of serialized data with length prefix and tag
pub fn vec_packed_varint_size<T: ProtobufVarint>(field_number: u32, vec: &[T]) -> u64 {
    if vec.is_empty() {
        0
    } else {
        let data_size = vec_packed_varint_data_size(vec);
        tag_size(field_number) + data_size.len_varint() + data_size
    }
}

/// Size of serialized data with length prefix and tag
pub fn vec_packed_varint_zigzag_size<T: ProtobufVarintZigzag>(field_number: u32, vec: &[T]) -> u64 {
    if vec.is_empty() {
        0
    } else {
        let data_size = vec_packed_varint_zigzag_data_size(vec);
        tag_size(field_number) + data_size.len_varint() + data_size
    }
}

/// Size of serialized data with length prefix and tag
pub fn vec_packed_enum_or_unknown_size<E: Enum>(
    field_number: u32,
    vec: &[EnumOrUnknown<E>],
) -> u64 {
    if vec.is_empty() {
        0
    } else {
        let data_size = vec_packed_enum_or_unknown_data_size(vec);
        tag_size(field_number) + data_size.len_varint() + data_size
    }
}

/// Compute data size of fixed encoding of repeated field data.
pub(crate) fn vec_packed_fixed_data_size<V: ProtobufFixed>(vec: &[V]) -> u64 {
    (vec.len() as u64) * (V::LEN as u64)
}

/// Compute field size (data plus header) of fixed encoding of repeated field.
pub fn vec_packed_fixed_size<V: ProtobufFixed>(field_number: u32, vec: &[V]) -> u64 {
    if vec.is_empty() {
        0
    } else {
        let data_size = vec_packed_fixed_data_size::<V>(vec);
        tag_size(field_number) + data_size.len_varint() + data_size
    }
}

/// Compute tag size. Size of tag does not depend on wire type.
pub fn tag_size(field_number: u32) -> u64 {
    encoded_varint64_len((field_number as u64) << 3) as u64
}

/// Size of encoded `sint32` value.
pub fn sint32_size_no_tag(value: i32) -> u64 {
    compute_raw_varint32_size(encode_zig_zag_32(value))
}

/// Size of encoded `sint64` value.
pub fn sint64_size_no_tag(value: i64) -> u64 {
    compute_raw_varint64_size(encode_zig_zag_64(value))
}

/// Size of encoded `int32` value.
pub fn int32_size_no_tag(value: i32) -> u64 {
    value.len_varint()
}

/// Size of encoded `int64` value.
pub fn int64_size_no_tag(value: i64) -> u64 {
    value.len_varint()
}

/// Size of encoded `uint32` value.
pub fn uint32_size_no_tag(value: u32) -> u64 {
    value.len_varint()
}

/// Size of encoded `uint64` value.
pub fn uint64_size_no_tag(value: u64) -> u64 {
    value.len_varint()
}

/// Size of encoded bytes field.
pub fn bytes_size_no_tag(bytes: &[u8]) -> u64 {
    compute_raw_varint64_size(bytes.len() as u64) + bytes.len() as u64
}

/// Size of encoded string field.
pub fn string_size_no_tag(s: &str) -> u64 {
    bytes_size_no_tag(s.as_bytes())
}

/// Read singular `message` field.
pub fn read_singular_message_into_field<M>(
    is: &mut CodedInputStream,
    target: &mut MessageField<M>,
) -> Result<()>
where
    M: Message,
{
    let mut m = M::new();
    is.merge_message(&mut m)?;
    *target = MessageField::some(m);
    Ok(())
}

/// Write message with field number and length to the stream.
pub fn write_message_field_with_cached_size<M>(
    field_number: u32,
    message: &M,
    os: &mut CodedOutputStream,
) -> Result<()>
where
    M: Message,
{
    os.write_tag(field_number, WireType::LengthDelimited)?;
    os.write_raw_varint32(message.cached_size())?;
    message.write_to_with_cached_sizes(os)
}
<|endoftext|>


<commit_before>// This whole file is strongly inspired by: https://github.com/jeaye/q3/blob/master/src/client/ui/ttf/glyph.rs
// available under the BSD-3 licence.
// It has been modified to work with gl-rs, nalgebra, and rust-freetype

use na::Vec2;

#[packed]
/// A ttf glyph.
pub struct Glyph {
    #[doc(hidden)]
    pub tex:        Vec2<f32>,
    #[doc(hidden)]
    pub advance:    Vec2<f32>,
    #[doc(hidden)]
    pub dimensions: Vec2<f32>,
    #[doc(hidden)]
    pub offset:     Vec2<f32>,
    #[doc(hidden)]
    pub buffer:     Vec<u8>
}

impl Glyph {
    /// Creates a new empty glyph.
    pub fn new(tex:        Vec2<f32>,
               advance:    Vec2<f32>,
               dimensions: Vec2<f32>,
               offset:     Vec2<f32>,
               buffer:     Vec<u8>)
               -> Glyph {
        Glyph {
            tex:        tex,
            advance:    advance,
            dimensions: dimensions,
            offset:     offset,
            buffer:     buffer
        }
    }
}
<commit_msg>Fix for 1.2.0-nightly (613e57b44 2015-06-01)<commit_after>// This whole file is strongly inspired by: https://github.com/jeaye/q3/blob/master/src/client/ui/ttf/glyph.rs
// available under the BSD-3 licence.
// It has been modified to work with gl-rs, nalgebra, and rust-freetype

use na::Vec2;

#[repr(packed)]
/// A ttf glyph.
pub struct Glyph {
    #[doc(hidden)]
    pub tex:        Vec2<f32>,
    #[doc(hidden)]
    pub advance:    Vec2<f32>,
    #[doc(hidden)]
    pub dimensions: Vec2<f32>,
    #[doc(hidden)]
    pub offset:     Vec2<f32>,
    #[doc(hidden)]
    pub buffer:     Vec<u8>
}

impl Glyph {
    /// Creates a new empty glyph.
    pub fn new(tex:        Vec2<f32>,
               advance:    Vec2<f32>,
               dimensions: Vec2<f32>,
               offset:     Vec2<f32>,
               buffer:     Vec<u8>)
               -> Glyph {
        Glyph {
            tex:        tex,
            advance:    advance,
            dimensions: dimensions,
            offset:     offset,
            buffer:     buffer
        }
    }
}
<|endoftext|>


<commit_before>use crate::ast::Field;
use crate::attr::Display;
use proc_macro2::TokenTree;
use quote::{format_ident, quote_spanned};
use std::collections::HashSet as Set;
use syn::ext::IdentExt;
use syn::parse::{ParseStream, Parser};
use syn::{Ident, Index, LitStr, Member, Result, Token};

impl Display<'_> {
    // Transform `"error {var}"` to `"error {}", var`.
    pub fn expand_shorthand(&mut self, fields: &[Field]) {
        let raw_args = self.args.clone();
        let mut named_args = explicit_named_args.parse2(raw_args).unwrap();
        let fields: Set<Member> = fields.iter().map(|f| f.member.clone()).collect();

        let span = self.fmt.span();
        let fmt = self.fmt.value();
        let mut read = fmt.as_str();
        let mut out = String::new();
        let mut args = self.args.clone();
        let mut has_bonus_display = false;

        let mut has_trailing_comma = false;
        if let Some(TokenTree::Punct(punct)) = args.clone().into_iter().last() {
            if punct.as_char() == ',' {
                has_trailing_comma = true;
            }
        }

        while let Some(brace) = read.find('{') {
            out += &read[..brace + 1];
            read = &read[brace + 1..];
            if read.starts_with('{') {
                out.push('{');
                read = &read[1..];
                continue;
            }
            let next = match read.chars().next() {
                Some(next) => next,
                None => return,
            };
            let member = match next {
                '0'..='9' => {
                    let int = take_int(&mut read);
                    let member = match int.parse::<u32>() {
                        Ok(index) => Member::Unnamed(Index { index, span }),
                        Err(_) => return,
                    };
                    if !fields.contains(&member) {
                        out += ∫
                        continue;
                    }
                    member
                }
                'a'..='z' | 'A'..='Z' | '_' => {
                    let mut ident = take_ident(&mut read);
                    ident.set_span(span);
                    Member::Named(ident)
                }
                _ => continue,
            };
            let local = match &member {
                Member::Unnamed(index) => format_ident!("_{}", index),
                Member::Named(ident) => ident.clone(),
            };
            let mut formatvar = local.clone();
            if formatvar.to_string().starts_with("r#") {
                formatvar = format_ident!("r_{}", formatvar);
            }
            if formatvar.to_string().starts_with('_') {
                // Work around leading underscore being rejected by 1.40 and
                // older compilers. https://github.com/rust-lang/rust/pull/66847
                formatvar = format_ident!("field_{}", formatvar);
            }
            out += &formatvar.to_string();
            if !named_args.insert(formatvar.clone()) {
                // Already specified in the format argument list.
                continue;
            }
            if !has_trailing_comma {
                args.extend(quote_spanned!(span=> ,));
            }
            args.extend(quote_spanned!(span=> #formatvar = #local));
            if read.starts_with('}') && fields.contains(&member) {
                has_bonus_display = true;
                args.extend(quote_spanned!(span=> .as_display()));
            }
            has_trailing_comma = false;
        }

        out += read;
        self.fmt = LitStr::new(&out, self.fmt.span());
        self.args = args;
        self.has_bonus_display = has_bonus_display;
    }
}

fn explicit_named_args(input: ParseStream) -> Result<Set<Ident>> {
    let mut named_args = Set::new();

    while !input.is_empty() {
        if input.peek(Token![,]) && input.peek2(Ident::peek_any) && input.peek3(Token![=]) {
            input.parse::<Token![,]>()?;
            let ident = input.call(Ident::parse_any)?;
            input.parse::<Token![=]>()?;
            named_args.insert(ident);
        } else {
            input.parse::<TokenTree>()?;
        }
    }

    Ok(named_args)
}

fn take_int(read: &mut &str) -> String {
    let mut int = String::new();
    for (i, ch) in read.char_indices() {
        match ch {
            '0'..='9' => int.push(ch),
            _ => {
                *read = &read[i..];
                break;
            }
        }
    }
    int
}

fn take_ident(read: &mut &str) -> Ident {
    let mut ident = String::new();
    let raw = read.starts_with("r#");
    if raw {
        ident.push_str("r#");
        *read = &read[2..];
    }
    for (i, ch) in read.char_indices() {
        match ch {
            'a'..='z' | 'A'..='Z' | '0'..='9' | '_' => ident.push(ch),
            _ => {
                *read = &read[i..];
                break;
            }
        }
    }
    syn::parse_str(&ident).unwrap()
}
<commit_msg>Fix second place that keyword fmt argument is failing<commit_after>use crate::ast::Field;
use crate::attr::Display;
use proc_macro2::TokenTree;
use quote::{format_ident, quote_spanned};
use std::collections::HashSet as Set;
use syn::ext::IdentExt;
use syn::parse::{ParseStream, Parser};
use syn::{Ident, Index, LitStr, Member, Result, Token};

impl Display<'_> {
    // Transform `"error {var}"` to `"error {}", var`.
    pub fn expand_shorthand(&mut self, fields: &[Field]) {
        let raw_args = self.args.clone();
        let mut named_args = explicit_named_args.parse2(raw_args).unwrap();
        let fields: Set<Member> = fields.iter().map(|f| f.member.clone()).collect();

        let span = self.fmt.span();
        let fmt = self.fmt.value();
        let mut read = fmt.as_str();
        let mut out = String::new();
        let mut args = self.args.clone();
        let mut has_bonus_display = false;

        let mut has_trailing_comma = false;
        if let Some(TokenTree::Punct(punct)) = args.clone().into_iter().last() {
            if punct.as_char() == ',' {
                has_trailing_comma = true;
            }
        }

        while let Some(brace) = read.find('{') {
            out += &read[..brace + 1];
            read = &read[brace + 1..];
            if read.starts_with('{') {
                out.push('{');
                read = &read[1..];
                continue;
            }
            let next = match read.chars().next() {
                Some(next) => next,
                None => return,
            };
            let member = match next {
                '0'..='9' => {
                    let int = take_int(&mut read);
                    let member = match int.parse::<u32>() {
                        Ok(index) => Member::Unnamed(Index { index, span }),
                        Err(_) => return,
                    };
                    if !fields.contains(&member) {
                        out += ∫
                        continue;
                    }
                    member
                }
                'a'..='z' | 'A'..='Z' | '_' => {
                    let mut ident = take_ident(&mut read);
                    ident.set_span(span);
                    Member::Named(ident)
                }
                _ => continue,
            };
            let local = match &member {
                Member::Unnamed(index) => format_ident!("_{}", index),
                Member::Named(ident) => ident.clone(),
            };
            let mut formatvar = local.clone();
            if formatvar.to_string().starts_with("r#") {
                formatvar = format_ident!("r_{}", formatvar);
            }
            if formatvar.to_string().starts_with('_') {
                // Work around leading underscore being rejected by 1.40 and
                // older compilers. https://github.com/rust-lang/rust/pull/66847
                formatvar = format_ident!("field_{}", formatvar);
            }
            out += &formatvar.to_string();
            if !named_args.insert(formatvar.clone()) {
                // Already specified in the format argument list.
                continue;
            }
            if !has_trailing_comma {
                args.extend(quote_spanned!(span=> ,));
            }
            args.extend(quote_spanned!(span=> #formatvar = #local));
            if read.starts_with('}') && fields.contains(&member) {
                has_bonus_display = true;
                args.extend(quote_spanned!(span=> .as_display()));
            }
            has_trailing_comma = false;
        }

        out += read;
        self.fmt = LitStr::new(&out, self.fmt.span());
        self.args = args;
        self.has_bonus_display = has_bonus_display;
    }
}

fn explicit_named_args(input: ParseStream) -> Result<Set<Ident>> {
    let mut named_args = Set::new();

    while !input.is_empty() {
        if input.peek(Token![,]) && input.peek2(Ident::peek_any) && input.peek3(Token![=]) {
            input.parse::<Token![,]>()?;
            let ident = input.call(Ident::parse_any)?;
            input.parse::<Token![=]>()?;
            named_args.insert(ident);
        } else {
            input.parse::<TokenTree>()?;
        }
    }

    Ok(named_args)
}

fn take_int(read: &mut &str) -> String {
    let mut int = String::new();
    for (i, ch) in read.char_indices() {
        match ch {
            '0'..='9' => int.push(ch),
            _ => {
                *read = &read[i..];
                break;
            }
        }
    }
    int
}

fn take_ident(read: &mut &str) -> Ident {
    let mut ident = String::new();
    let raw = read.starts_with("r#");
    if raw {
        ident.push_str("r#");
        *read = &read[2..];
    }
    for (i, ch) in read.char_indices() {
        match ch {
            'a'..='z' | 'A'..='Z' | '0'..='9' | '_' => ident.push(ch),
            _ => {
                *read = &read[i..];
                break;
            }
        }
    }
    Ident::parse_any.parse_str(&ident).unwrap()
}
<|endoftext|>


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

// gpio_blinkled_signals.rs - Blinks an LED connected to a GPIO pin in a loop,
// while handling any incoming SIGINT (Ctrl-C) and SIGTERM signals so the
// pin's state can be reset before the application exits.
//
// Remember to add a resistor of an appropriate value in series, to prevent
// exceeding the maximum current rating of the GPIO pin and the LED.

use std::error::Error;
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Arc;
use std::thread;
use std::time::Duration;

// The simple-signal crate is used to handle incoming signals.
use simple_signal::{set_handler, Signal};

use rppal::gpio::Gpio;

// Gpio uses BCM pin numbering. BCM GPIO 23 is tied to physical pin 16.
const GPIO_LED: u8 = 23;

fn main() -> Result<(), Box<dyn Error>> {
    // Retrieve the GPIO pin and configure it as an output.
    let mut pin = Gpio::new()?.get(GPIO_LED)?.into_output();

    // Clone running, so we can safely access it from within the signal handler.
    let running = Arc::new(AtomicBool::new(true));
    let r = running.clone();

    // When a SIGINT (Ctrl-C) or SIGTERM signal is caught, atomically set running to false.
    set_handler(&[Signal::Int, Signal::Term], move |_| {
        r.store(false, Ordering::SeqCst);
    });

    // Blink the LED until running is set to false.
    while running.load(Ordering::SeqCst) {
        pin.toggle();
        thread::sleep(Duration::from_millis(500));
    }

    // After we're done blinking, turn the LED off.
    pin.set_low();

    Ok(())

    // When the pin variable goes out of scope, the GPIO pin mode is automatically reset
    // to its original value, provided reset_on_drop is set to true (default).
}
<commit_msg>Include parent module when calling functions<commit_after>// Copyright (c) 2017-2019 Rene van der Meer
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.

// gpio_blinkled_signals.rs - Blinks an LED connected to a GPIO pin in a loop,
// while handling any incoming SIGINT (Ctrl-C) and SIGTERM signals so the
// pin's state can be reset before the application exits.
//
// Remember to add a resistor of an appropriate value in series, to prevent
// exceeding the maximum current rating of the GPIO pin and the LED.

use std::error::Error;
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Arc;
use std::thread;
use std::time::Duration;

// The simple-signal crate is used to handle incoming signals.
use simple_signal::{self, Signal};

use rppal::gpio::Gpio;

// Gpio uses BCM pin numbering. BCM GPIO 23 is tied to physical pin 16.
const GPIO_LED: u8 = 23;

fn main() -> Result<(), Box<dyn Error>> {
    // Retrieve the GPIO pin and configure it as an output.
    let mut pin = Gpio::new()?.get(GPIO_LED)?.into_output();

    // Clone running, so we can safely access it from within the signal handler.
    let running = Arc::new(AtomicBool::new(true));
    let r = running.clone();

    // When a SIGINT (Ctrl-C) or SIGTERM signal is caught, atomically set running to false.
    simple_signal::set_handler(&[Signal::Int, Signal::Term], move |_| {
        r.store(false, Ordering::SeqCst);
    });

    // Blink the LED until running is set to false.
    while running.load(Ordering::SeqCst) {
        pin.toggle();
        thread::sleep(Duration::from_millis(500));
    }

    // After we're done blinking, turn the LED off.
    pin.set_low();

    Ok(())

    // When the pin variable goes out of scope, the GPIO pin mode is automatically reset
    // to its original value, provided reset_on_drop is set to true (default).
}
<|endoftext|>


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

//! General AEAD implementation combining an `IndCpaCipher` with a `tink_core::Mac`

use super::IndCpaCipher;
use tink_core::{utils::wrap_err, TinkError};

/// `EncryptThenAuthenticate` performs an encrypt-then-MAC operation on plaintext
/// and additional authenticated data (aad). The MAC is computed over (aad ||
/// ciphertext || size of aad). This implementation is based on
/// http://tools.ietf.org/html/draft-mcgrew-aead-aes-cbc-hmac-sha2-05.
pub struct EncryptThenAuthenticate {
    ind_cpa_cipher: Box<dyn IndCpaCipher>,
    mac: Box<dyn tink_core::Mac>,
    tag_size: usize,
}

/// Manual implementation of [`Clone`] relying on the trait bounds for
/// primitives to provide `.box_clone()` methods.
impl Clone for EncryptThenAuthenticate {
    fn clone(&self) -> Self {
        Self {
            ind_cpa_cipher: self.ind_cpa_cipher.box_clone(),
            mac: self.mac.box_clone(),
            tag_size: self.tag_size,
        }
    }
}

const MIN_TAG_SIZE_IN_BYTES: usize = 10;

impl EncryptThenAuthenticate {
    /// Return a new instance of EncryptThenAuthenticate.
    pub fn new(
        ind_cpa_cipher: Box<dyn IndCpaCipher>,
        mac: Box<dyn tink_core::Mac>,
        tag_size: usize,
    ) -> Result<EncryptThenAuthenticate, TinkError> {
        if tag_size < MIN_TAG_SIZE_IN_BYTES {
            return Err("EncryptThenAuthenticate: tag size too small".into());
        }
        Ok(EncryptThenAuthenticate {
            ind_cpa_cipher,
            mac,
            tag_size,
        })
    }
}

impl tink_core::Aead for EncryptThenAuthenticate {
    /// Encrypt `plaintext` with `additional_data` as additional authenticated
    /// data. The resulting ciphertext allows for checking authenticity and
    /// integrity of additional data, but does not guarantee its secrecy.
    ///
    /// The plaintext is encrypted with an [`IndCpaCipher`], then MAC is computed over
    /// (additional_data || ciphertext || n) where n is additional_data's length
    /// in bits represented as a 64-bit bigendian unsigned integer. The final
    /// ciphertext format is (IND-CPA ciphertext || mac).
    fn encrypt(&self, plaintext: &[u8], additional_data: &[u8]) -> Result<Vec<u8>, TinkError> {
        let mut ciphertext = self
            .ind_cpa_cipher
            .encrypt(plaintext)
            .map_err(|e| wrap_err("EncryptThenAuthenticate", e))?;

        // Authenticate the following data:
        // additional_data || payload || aad_size_in_bits
        let mut to_auth_data = Vec::with_capacity(additional_data.len() + ciphertext.len() + 8);
        to_auth_data.extend_from_slice(additional_data);
        to_auth_data.extend_from_slice(&ciphertext);
        let aad_size_in_bits = (additional_data.len() * 8) as u64;
        to_auth_data.extend_from_slice(&aad_size_in_bits.to_be_bytes());

        let tag = self
            .mac
            .compute_mac(&to_auth_data)
            .map_err(|e| wrap_err("EncryptThenAuthenticate", e))?;
        if tag.len() != self.tag_size {
            return Err("EncryptThenAuthenticate: invalid tag size".into());
        }

        // Put the tag at the end of the ciphertext.
        ciphertext.extend_from_slice(&tag);
        Ok(ciphertext)
    }

    /// Decrypt `ciphertext` with `additional_data` as additional authenticated
    /// data.
    fn decrypt(&self, ciphertext: &[u8], additional_data: &[u8]) -> Result<Vec<u8>, TinkError> {
        if ciphertext.len() < self.tag_size {
            return Err("EncryptThenAuthenticate: ciphertext too short".into());
        }

        // payload contains everything except the tag at the end.
        let payload = &ciphertext[..(ciphertext.len() - self.tag_size)];

        // Authenticate the following data:
        // additional_data || payload || aad_size_in_bits
        let mut to_auth_data = Vec::with_capacity(additional_data.len() + payload.len() + 8);
        to_auth_data.extend_from_slice(additional_data);
        to_auth_data.extend_from_slice(payload);
        let aad_size_in_bits = (additional_data.len() * 8) as u64;
        to_auth_data.extend_from_slice(&aad_size_in_bits.to_be_bytes());

        // Verify against the tag at the end of the ciphertext.
        self.mac
            .verify_mac(
                &ciphertext[(ciphertext.len() - self.tag_size)..],
                &to_auth_data,
            )
            .map_err(|e| wrap_err("EncryptThenAuthenticate", e))?;

        let plaintext = self
            .ind_cpa_cipher
            .decrypt(payload)
            .map_err(|e| wrap_err("EncryptThenAuthenticate", e))?;

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

//! General AEAD implementation combining an `IndCpaCipher` with a `tink_core::Mac`

use super::IndCpaCipher;
use tink_core::{utils::wrap_err, TinkError};

/// `EncryptThenAuthenticate` performs an encrypt-then-MAC operation on plaintext
/// and additional authenticated data (aad). The MAC is computed over (aad ||
/// ciphertext || size of aad). This implementation is based on
/// <http://tools.ietf.org/html/draft-mcgrew-aead-aes-cbc-hmac-sha2-05>.
pub struct EncryptThenAuthenticate {
    ind_cpa_cipher: Box<dyn IndCpaCipher>,
    mac: Box<dyn tink_core::Mac>,
    tag_size: usize,
}

/// Manual implementation of [`Clone`] relying on the trait bounds for
/// primitives to provide `.box_clone()` methods.
impl Clone for EncryptThenAuthenticate {
    fn clone(&self) -> Self {
        Self {
            ind_cpa_cipher: self.ind_cpa_cipher.box_clone(),
            mac: self.mac.box_clone(),
            tag_size: self.tag_size,
        }
    }
}

const MIN_TAG_SIZE_IN_BYTES: usize = 10;

impl EncryptThenAuthenticate {
    /// Return a new instance of EncryptThenAuthenticate.
    pub fn new(
        ind_cpa_cipher: Box<dyn IndCpaCipher>,
        mac: Box<dyn tink_core::Mac>,
        tag_size: usize,
    ) -> Result<EncryptThenAuthenticate, TinkError> {
        if tag_size < MIN_TAG_SIZE_IN_BYTES {
            return Err("EncryptThenAuthenticate: tag size too small".into());
        }
        Ok(EncryptThenAuthenticate {
            ind_cpa_cipher,
            mac,
            tag_size,
        })
    }
}

impl tink_core::Aead for EncryptThenAuthenticate {
    /// Encrypt `plaintext` with `additional_data` as additional authenticated
    /// data. The resulting ciphertext allows for checking authenticity and
    /// integrity of additional data, but does not guarantee its secrecy.
    ///
    /// The plaintext is encrypted with an [`IndCpaCipher`], then MAC is computed over
    /// (additional_data || ciphertext || n) where n is additional_data's length
    /// in bits represented as a 64-bit bigendian unsigned integer. The final
    /// ciphertext format is (IND-CPA ciphertext || mac).
    fn encrypt(&self, plaintext: &[u8], additional_data: &[u8]) -> Result<Vec<u8>, TinkError> {
        let mut ciphertext = self
            .ind_cpa_cipher
            .encrypt(plaintext)
            .map_err(|e| wrap_err("EncryptThenAuthenticate", e))?;

        // Authenticate the following data:
        // additional_data || payload || aad_size_in_bits
        let mut to_auth_data = Vec::with_capacity(additional_data.len() + ciphertext.len() + 8);
        to_auth_data.extend_from_slice(additional_data);
        to_auth_data.extend_from_slice(&ciphertext);
        let aad_size_in_bits = (additional_data.len() * 8) as u64;
        to_auth_data.extend_from_slice(&aad_size_in_bits.to_be_bytes());

        let tag = self
            .mac
            .compute_mac(&to_auth_data)
            .map_err(|e| wrap_err("EncryptThenAuthenticate", e))?;
        if tag.len() != self.tag_size {
            return Err("EncryptThenAuthenticate: invalid tag size".into());
        }

        // Put the tag at the end of the ciphertext.
        ciphertext.extend_from_slice(&tag);
        Ok(ciphertext)
    }

    /// Decrypt `ciphertext` with `additional_data` as additional authenticated
    /// data.
    fn decrypt(&self, ciphertext: &[u8], additional_data: &[u8]) -> Result<Vec<u8>, TinkError> {
        if ciphertext.len() < self.tag_size {
            return Err("EncryptThenAuthenticate: ciphertext too short".into());
        }

        // payload contains everything except the tag at the end.
        let payload = &ciphertext[..(ciphertext.len() - self.tag_size)];

        // Authenticate the following data:
        // additional_data || payload || aad_size_in_bits
        let mut to_auth_data = Vec::with_capacity(additional_data.len() + payload.len() + 8);
        to_auth_data.extend_from_slice(additional_data);
        to_auth_data.extend_from_slice(payload);
        let aad_size_in_bits = (additional_data.len() * 8) as u64;
        to_auth_data.extend_from_slice(&aad_size_in_bits.to_be_bytes());

        // Verify against the tag at the end of the ciphertext.
        self.mac
            .verify_mac(
                &ciphertext[(ciphertext.len() - self.tag_size)..],
                &to_auth_data,
            )
            .map_err(|e| wrap_err("EncryptThenAuthenticate", e))?;

        let plaintext = self
            .ind_cpa_cipher
            .decrypt(payload)
            .map_err(|e| wrap_err("EncryptThenAuthenticate", e))?;

        Ok(plaintext)
    }
}
<|endoftext|>