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

use crate::*;
use atomics::AtomicCounter;
use datastructures::UnsignedCounterPrimitive;
use evmap::{ReadHandle, WriteHandle};
use std::sync::Mutex;

use std::collections::{HashMap, HashSet};
use std::sync::Arc;

#[derive(Clone)]
pub struct Recorder<T: 'static>
where
    Box<AtomicCounter<Primitive = T>>: From<T>,
    T: UnsignedCounterPrimitive + From<u8>,
    u64: From<T>,
{
    data_read: ReadHandle<String, Arc<Channel<T>>>,
    data_write: Arc<Mutex<WriteHandle<String, Arc<Channel<T>>>>>,
    labels: Arc<Mutex<HashSet<String>>>,
}

impl<T> Recorder<T>
where
    Box<AtomicCounter<Primitive = T>>: From<T>,
    T: UnsignedCounterPrimitive + From<u8>,
    u64: From<T>,
{
    pub fn new() -> Self {
        let (read, write) = evmap::new();
        Self {
            data_read: read,
            data_write: Arc::new(Mutex::new(write)),
            labels: Arc::new(Mutex::new(HashSet::new())),
        }
    }

    pub fn record(&self, channel: String, measurement: Measurement<T>) {
        self.data_read
            .get_and(&channel, |channel| (*channel)[0].record(measurement));
    }

    pub fn counter(&self, channel: String) -> u64 {
        self.data_read
            .get_and(&channel, |channel| (*channel)[0].counter())
            .unwrap_or(0)
    }

    pub fn percentile(&self, channel: String, percentile: f64) -> Option<u64> {
        self.data_read
            .get_and(&channel, |channel| (*channel)[0].percentile(percentile))
            .unwrap_or(None)
    }

    pub fn add_channel(&self, name: String, source: Source, histogram: Option<Histogram<T>>) {
        debug!("add channel: {} source: {:?}", name, source);
        let channel = Channel::new(name.clone(), source, histogram);
        if self
            .data_read
            .get_and(&name, |channel| channel.len())
            .unwrap_or(0)
            == 0
        {
            let mut write = self.data_write.lock().unwrap();
            write.insert(name.clone(), Arc::new(channel));
            write.refresh();
            let mut labels = self.labels.lock().unwrap();
            labels.insert(name);
        }
    }

    pub fn delete_channel(&self, name: String) {
        debug!("delete channel: {}", name);
        let mut write = self.data_write.lock().unwrap();
        write.empty(name.clone());
        write.refresh();
        let mut labels = self.labels.lock().unwrap();
        labels.remove(&name);
    }

    pub fn readings(&self) -> Vec<Reading> {
        let mut result = Vec::new();
        let labels = self.labels.lock().unwrap();
        for label in &*labels {
            let readings = self
                .data_read
                .get_and(label, |channel| (*channel)[0].readings());
            if let Some(readings) = readings {
                result.extend(readings);
            }
        }
        result
    }

    pub fn hash_map(&self) -> HashMap<String, HashMap<Output, u64>> {
        let mut result = HashMap::new();
        let labels = self.labels.lock().unwrap();
        for label in &*labels {
            let readings = self
                .data_read
                .get_and(label, |channel| (*channel)[0].hash_map());
            if let Some(readings) = readings {
                result.insert(label.to_owned(), readings);
            }
        }
        result
    }

    #[cfg(feature = "waterfall")]
    pub fn save_files(&self) {
        unsafe {
            for label in &*self.labels.get() {
                let readings = self
                    .data_read
                    .get_and(label, |channel| (*channel)[0].save_files());
            }
        }
    }

    pub fn add_output(&self, name: String, output: Output) {
        self.data_read
            .get_and(&name, |channel| (*channel)[0].add_output(output));
    }

    pub fn delete_output(&self, name: String, output: Output) {
        self.data_read
            .get_and(&name, |channel| (*channel)[0].delete_output(output));
    }

    pub fn latch(&self) {
        let labels = self.labels.lock().unwrap();
        for label in &*labels {
            self.data_read
                .get_and(label, |channel| (*channel)[0].latch());
        }
    }

    pub fn zero(&self) {
        let labels = self.labels.lock().unwrap();
        for label in &*labels {
            self.data_read
                .get_and(label, |channel| (*channel)[0].zero());
        }
    }

    pub fn clear(&self) {
        let labels = self.labels.lock().unwrap();
        for label in &*labels {
            self.delete_channel(label.to_string());
        }
    }
}

impl<T> Default for Recorder<T>
where
    Box<AtomicCounter<Primitive = T>>: From<T>,
    T: UnsignedCounterPrimitive + From<u8>,
    u64: From<T>,
{
    fn default() -> Self {
        Self::new()
    }
}
<commit_msg>metrics: expose a shrink_to_fit() (#211)<commit_after>//  Copyright 2019 Twitter, Inc
//
//  Licensed under the Apache License, Version 2.0 (the "License");
//  you may not use this file except in compliance with the License.
//  You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
//  Unless required by applicable law or agreed to in writing, software
//  distributed under the License is distributed on an "AS IS" BASIS,
//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//  See the License for the specific language governing permissions and
//  limitations under the License.

use crate::*;
use atomics::AtomicCounter;
use datastructures::UnsignedCounterPrimitive;
use evmap::{ReadHandle, WriteHandle};
use std::sync::Mutex;

use std::collections::{HashMap, HashSet};
use std::sync::Arc;

#[derive(Clone)]
pub struct Recorder<T: 'static>
where
    Box<AtomicCounter<Primitive = T>>: From<T>,
    T: UnsignedCounterPrimitive + From<u8>,
    u64: From<T>,
{
    data_read: ReadHandle<String, Arc<Channel<T>>>,
    data_write: Arc<Mutex<WriteHandle<String, Arc<Channel<T>>>>>,
    labels: Arc<Mutex<HashSet<String>>>,
}

impl<T> Recorder<T>
where
    Box<AtomicCounter<Primitive = T>>: From<T>,
    T: UnsignedCounterPrimitive + From<u8>,
    u64: From<T>,
{
    pub fn new() -> Self {
        let (read, write) = evmap::new();
        Self {
            data_read: read,
            data_write: Arc::new(Mutex::new(write)),
            labels: Arc::new(Mutex::new(HashSet::new())),
        }
    }

    pub fn record(&self, channel: String, measurement: Measurement<T>) {
        self.data_read
            .get_and(&channel, |channel| (*channel)[0].record(measurement));
    }

    pub fn counter(&self, channel: String) -> u64 {
        self.data_read
            .get_and(&channel, |channel| (*channel)[0].counter())
            .unwrap_or(0)
    }

    pub fn percentile(&self, channel: String, percentile: f64) -> Option<u64> {
        self.data_read
            .get_and(&channel, |channel| (*channel)[0].percentile(percentile))
            .unwrap_or(None)
    }

    pub fn add_channel(&self, name: String, source: Source, histogram: Option<Histogram<T>>) {
        debug!("add channel: {} source: {:?}", name, source);
        let channel = Channel::new(name.clone(), source, histogram);
        if self
            .data_read
            .get_and(&name, |channel| channel.len())
            .unwrap_or(0)
            == 0
        {
            let mut write = self.data_write.lock().unwrap();
            write.insert(name.clone(), Arc::new(channel));
            write.refresh();
            let mut labels = self.labels.lock().unwrap();
            labels.insert(name);
        }
    }

    pub fn delete_channel(&self, name: String) {
        debug!("delete channel: {}", name);
        let mut write = self.data_write.lock().unwrap();
        write.empty(name.clone());
        write.refresh();
        let mut labels = self.labels.lock().unwrap();
        labels.remove(&name);
    }

    pub fn readings(&self) -> Vec<Reading> {
        let mut result = Vec::new();
        let labels = self.labels.lock().unwrap();
        for label in &*labels {
            let readings = self
                .data_read
                .get_and(label, |channel| (*channel)[0].readings());
            if let Some(readings) = readings {
                result.extend(readings);
            }
        }
        result
    }

    pub fn hash_map(&self) -> HashMap<String, HashMap<Output, u64>> {
        let mut result = HashMap::new();
        let labels = self.labels.lock().unwrap();
        for label in &*labels {
            let readings = self
                .data_read
                .get_and(label, |channel| (*channel)[0].hash_map());
            if let Some(readings) = readings {
                result.insert(label.to_owned(), readings);
            }
        }
        result
    }

    #[cfg(feature = "waterfall")]
    pub fn save_files(&self) {
        unsafe {
            for label in &*self.labels.get() {
                let readings = self
                    .data_read
                    .get_and(label, |channel| (*channel)[0].save_files());
            }
        }
    }

    pub fn add_output(&self, name: String, output: Output) {
        self.data_read
            .get_and(&name, |channel| (*channel)[0].add_output(output));
    }

    pub fn delete_output(&self, name: String, output: Output) {
        self.data_read
            .get_and(&name, |channel| (*channel)[0].delete_output(output));
    }

    pub fn latch(&self) {
        let labels = self.labels.lock().unwrap();
        for label in &*labels {
            self.data_read
                .get_and(label, |channel| (*channel)[0].latch());
        }
    }

    pub fn zero(&self) {
        let labels = self.labels.lock().unwrap();
        for label in &*labels {
            self.data_read
                .get_and(label, |channel| (*channel)[0].zero());
        }
    }

    pub fn clear(&self) {
        let mut labels = self.labels.lock().unwrap();
        let mut write = self.data_write.lock().unwrap();
        labels.clear();
        write.purge();
        write.refresh();
    }

    pub fn shrink_to_fit(&self) {
        let mut write = self.data_write.lock().unwrap();
        write.fit_all();
        write.refresh();
    }
}

impl<T> Default for Recorder<T>
where
    Box<AtomicCounter<Primitive = T>>: From<T>,
    T: UnsignedCounterPrimitive + From<u8>,
    u64: From<T>,
{
    fn default() -> Self {
        Self::new()
    }
}
<|endoftext|>


<commit_before>use crate::arena::Arena;

use rustc_serialize::{Encodable, Encoder};

use std::alloc::Layout;
use std::cmp::Ordering;
use std::fmt;
use std::hash::{Hash, Hasher};
use std::iter;
use std::mem;
use std::ops::Deref;
use std::ptr;
use std::slice;

extern "C" {
    /// A dummy type used to force `List` to be unsized while not requiring references to it be wide
    /// pointers.
    type OpaqueListContents;
}

/// A wrapper for slices with the additional invariant
/// that the slice is interned and no other slice with
/// the same contents can exist in the same context.
/// This means we can use pointer for both
/// equality comparisons and hashing.
///
/// Unlike slices, The types contained in `List` are expected to be `Copy`
/// and iterating over a `List` returns `T` instead of a reference.
///
/// Note: `Slice` was already taken by the `Ty`.
#[repr(C)]
pub struct List<T> {
    len: usize,
    data: [T; 0],
    opaque: OpaqueListContents,
}

unsafe impl<'a, T: 'a> rustc_data_structures::tagged_ptr::Pointer for &'a List<T> {
    const BITS: usize = std::mem::align_of::<usize>().trailing_zeros() as usize;
    fn into_usize(self) -> usize {
        self as *const List<T> as usize
    }
    unsafe fn from_usize(ptr: usize) -> Self {
        &*(ptr as *const List<T>)
    }
    unsafe fn with_ref<R, F: FnOnce(&Self) -> R>(ptr: usize, f: F) -> R {
        // Self: Copy so this is fine
        let ptr = Self::from_usize(ptr);
        f(&ptr)
    }
}

unsafe impl<T: Sync> Sync for List<T> {}

impl<T: Copy> List<T> {
    #[inline]
    pub(super) fn from_arena<'tcx>(arena: &'tcx Arena<'tcx>, slice: &[T]) -> &'tcx List<T> {
        assert!(!mem::needs_drop::<T>());
        assert!(mem::size_of::<T>() != 0);
        assert!(!slice.is_empty());

        let (layout, _offset) =
            Layout::new::<usize>().extend(Layout::for_value::<[T]>(slice)).unwrap();
        let mem = arena.dropless.alloc_raw(layout);
        unsafe {
            let result = &mut *(mem as *mut List<T>);
            // Write the length
            result.len = slice.len();

            // Write the elements
            let arena_slice = slice::from_raw_parts_mut(result.data.as_mut_ptr(), result.len);
            arena_slice.copy_from_slice(slice);

            result
        }
    }

    // If this method didn't exist, we would use `slice.iter` due to
    // deref coercion.
    //
    // This would be weird, as `self.into_iter` iterates over `T` directly.
    #[inline(always)]
    pub fn iter(&self) -> <&'_ List<T> as IntoIterator>::IntoIter {
        self.into_iter()
    }
}

impl<T: fmt::Debug> fmt::Debug for List<T> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        (**self).fmt(f)
    }
}

impl<S: Encoder, T: Encodable<S>> Encodable<S> for List<T> {
    #[inline]
    fn encode(&self, s: &mut S) -> Result<(), S::Error> {
        (**self).encode(s)
    }
}

impl<S: Encoder, T: Encodable<S>> Encodable<S> for &List<T> {
    #[inline]
    fn encode(&self, s: &mut S) -> Result<(), S::Error> {
        (**self).encode(s)
    }
}

impl<T> Ord for List<T>
where
    T: Ord,
{
    fn cmp(&self, other: &List<T>) -> Ordering {
        if self == other { Ordering::Equal } else { <[T] as Ord>::cmp(&**self, &**other) }
    }
}

impl<T> PartialOrd for List<T>
where
    T: PartialOrd,
{
    fn partial_cmp(&self, other: &List<T>) -> Option<Ordering> {
        if self == other {
            Some(Ordering::Equal)
        } else {
            <[T] as PartialOrd>::partial_cmp(&**self, &**other)
        }
    }
}

impl<T: PartialEq> PartialEq for List<T> {
    #[inline]
    fn eq(&self, other: &List<T>) -> bool {
        ptr::eq(self, other)
    }
}
impl<T: Eq> Eq for List<T> {}

impl<T> Hash for List<T> {
    #[inline]
    fn hash<H: Hasher>(&self, s: &mut H) {
        (self as *const List<T>).hash(s)
    }
}

impl<T> Deref for List<T> {
    type Target = [T];
    #[inline(always)]
    fn deref(&self) -> &[T] {
        self.as_ref()
    }
}

impl<T> AsRef<[T]> for List<T> {
    #[inline(always)]
    fn as_ref(&self) -> &[T] {
        unsafe { slice::from_raw_parts(self.data.as_ptr(), self.len) }
    }
}

impl<'a, T: Copy> IntoIterator for &'a List<T> {
    type Item = T;
    type IntoIter = iter::Copied<<&'a [T] as IntoIterator>::IntoIter>;
    #[inline(always)]
    fn into_iter(self) -> Self::IntoIter {
        self[..].iter().copied()
    }
}

impl<T> List<T> {
    #[inline(always)]
    pub fn empty<'a>() -> &'a List<T> {
        #[repr(align(64), C)]
        struct EmptySlice([u8; 64]);
        static EMPTY_SLICE: EmptySlice = EmptySlice([0; 64]);
        assert!(mem::align_of::<T>() <= 64);
        unsafe { &*(&EMPTY_SLICE as *const _ as *const List<T>) }
    }
}
<commit_msg>Rollup merge of #80342 - pierwill:patch-1, r=lcnr<commit_after>use crate::arena::Arena;

use rustc_serialize::{Encodable, Encoder};

use std::alloc::Layout;
use std::cmp::Ordering;
use std::fmt;
use std::hash::{Hash, Hasher};
use std::iter;
use std::mem;
use std::ops::Deref;
use std::ptr;
use std::slice;

extern "C" {
    /// A dummy type used to force `List` to be unsized while not requiring references to it be wide
    /// pointers.
    type OpaqueListContents;
}

/// A wrapper for slices with the additional invariant
/// that the slice is interned and no other slice with
/// the same contents can exist in the same context.
/// This means we can use pointer for both
/// equality comparisons and hashing.
///
/// Unlike slices, the types contained in `List` are expected to be `Copy`
/// and iterating over a `List` returns `T` instead of a reference.
///
/// Note: `Slice` was already taken by the `Ty`.
#[repr(C)]
pub struct List<T> {
    len: usize,
    data: [T; 0],
    opaque: OpaqueListContents,
}

unsafe impl<'a, T: 'a> rustc_data_structures::tagged_ptr::Pointer for &'a List<T> {
    const BITS: usize = std::mem::align_of::<usize>().trailing_zeros() as usize;
    fn into_usize(self) -> usize {
        self as *const List<T> as usize
    }
    unsafe fn from_usize(ptr: usize) -> Self {
        &*(ptr as *const List<T>)
    }
    unsafe fn with_ref<R, F: FnOnce(&Self) -> R>(ptr: usize, f: F) -> R {
        // Self: Copy so this is fine
        let ptr = Self::from_usize(ptr);
        f(&ptr)
    }
}

unsafe impl<T: Sync> Sync for List<T> {}

impl<T: Copy> List<T> {
    #[inline]
    pub(super) fn from_arena<'tcx>(arena: &'tcx Arena<'tcx>, slice: &[T]) -> &'tcx List<T> {
        assert!(!mem::needs_drop::<T>());
        assert!(mem::size_of::<T>() != 0);
        assert!(!slice.is_empty());

        let (layout, _offset) =
            Layout::new::<usize>().extend(Layout::for_value::<[T]>(slice)).unwrap();
        let mem = arena.dropless.alloc_raw(layout);
        unsafe {
            let result = &mut *(mem as *mut List<T>);
            // Write the length
            result.len = slice.len();

            // Write the elements
            let arena_slice = slice::from_raw_parts_mut(result.data.as_mut_ptr(), result.len);
            arena_slice.copy_from_slice(slice);

            result
        }
    }

    // If this method didn't exist, we would use `slice.iter` due to
    // deref coercion.
    //
    // This would be weird, as `self.into_iter` iterates over `T` directly.
    #[inline(always)]
    pub fn iter(&self) -> <&'_ List<T> as IntoIterator>::IntoIter {
        self.into_iter()
    }
}

impl<T: fmt::Debug> fmt::Debug for List<T> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        (**self).fmt(f)
    }
}

impl<S: Encoder, T: Encodable<S>> Encodable<S> for List<T> {
    #[inline]
    fn encode(&self, s: &mut S) -> Result<(), S::Error> {
        (**self).encode(s)
    }
}

impl<S: Encoder, T: Encodable<S>> Encodable<S> for &List<T> {
    #[inline]
    fn encode(&self, s: &mut S) -> Result<(), S::Error> {
        (**self).encode(s)
    }
}

impl<T> Ord for List<T>
where
    T: Ord,
{
    fn cmp(&self, other: &List<T>) -> Ordering {
        if self == other { Ordering::Equal } else { <[T] as Ord>::cmp(&**self, &**other) }
    }
}

impl<T> PartialOrd for List<T>
where
    T: PartialOrd,
{
    fn partial_cmp(&self, other: &List<T>) -> Option<Ordering> {
        if self == other {
            Some(Ordering::Equal)
        } else {
            <[T] as PartialOrd>::partial_cmp(&**self, &**other)
        }
    }
}

impl<T: PartialEq> PartialEq for List<T> {
    #[inline]
    fn eq(&self, other: &List<T>) -> bool {
        ptr::eq(self, other)
    }
}
impl<T: Eq> Eq for List<T> {}

impl<T> Hash for List<T> {
    #[inline]
    fn hash<H: Hasher>(&self, s: &mut H) {
        (self as *const List<T>).hash(s)
    }
}

impl<T> Deref for List<T> {
    type Target = [T];
    #[inline(always)]
    fn deref(&self) -> &[T] {
        self.as_ref()
    }
}

impl<T> AsRef<[T]> for List<T> {
    #[inline(always)]
    fn as_ref(&self) -> &[T] {
        unsafe { slice::from_raw_parts(self.data.as_ptr(), self.len) }
    }
}

impl<'a, T: Copy> IntoIterator for &'a List<T> {
    type Item = T;
    type IntoIter = iter::Copied<<&'a [T] as IntoIterator>::IntoIter>;
    #[inline(always)]
    fn into_iter(self) -> Self::IntoIter {
        self[..].iter().copied()
    }
}

impl<T> List<T> {
    #[inline(always)]
    pub fn empty<'a>() -> &'a List<T> {
        #[repr(align(64), C)]
        struct EmptySlice([u8; 64]);
        static EMPTY_SLICE: EmptySlice = EmptySlice([0; 64]);
        assert!(mem::align_of::<T>() <= 64);
        unsafe { &*(&EMPTY_SLICE as *const _ as *const List<T>) }
    }
}
<|endoftext|>


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

use std::io::Read;
use std::str::FromStr;

use bodyparser;
use bldr_core::build_config::{BLDR_CFG, BuildCfg};
use constant_time_eq::constant_time_eq;
use github_api_client::GitHubClient;
use hab_core::package::Plan;
use hex::ToHex;
use http_gateway::http::controller::*;
use iron::status;
use openssl::hash::MessageDigest;
use openssl::pkey::PKey;
use openssl::sign::Signer;
use persistent;
use protocol::originsrv::{OriginProject, OriginProjectGet};
use protocol::scheduler::{Group, GroupCreate};
use router::Router;

use error::Error;
use headers::*;
use types::*;

pub enum GitHubEvent {
    Push,
    Ping,
}

impl FromStr for GitHubEvent {
    type Err = Error;

    fn from_str(event: &str) -> Result<Self, Self::Err> {
        match event {
            "ping" => Ok(GitHubEvent::Ping),
            "push" => Ok(GitHubEvent::Push),
            _ => Err(Error::UnknownGitHubEvent(event.to_string())),
        }
    }
}

enum HandleResult<T> {
    Ok(T),
    Err(Response),
}

pub fn handle_event(req: &mut Request) -> IronResult<Response> {
    let event = match req.headers.get::<XGitHubEvent>() {
        Some(&XGitHubEvent(ref event)) => {
            match GitHubEvent::from_str(event) {
                Ok(event) => event,
                Err(err) => return Ok(Response::with((status::BadRequest, err.to_string()))),
            }
        }
        _ => return Ok(Response::with(status::BadRequest)),
    };

    // Authenticate the hook
    let github = req.get::<persistent::Read<GitHubCli>>().unwrap();
    let gh_signature = match req.headers.get::<XHubSignature>() {
        Some(&XHubSignature(ref sig)) => sig.clone(),
        None => {
            error!("Received a GitHub hook with no signature!");
            return Ok(Response::with(status::BadRequest));
        }
    };

    let mut payload = String::new();
    if let Err(err) = req.body.read_to_string(&mut payload) {
        error!(
            "Can not read request body. SEEMS LIKE A BAD THING. err = {:?}",
            err
        );
        return Ok(Response::with(status::BadRequest));
    }

    let key = PKey::hmac(github.webhook_secret.as_bytes()).unwrap();
    let mut signer = Signer::new(MessageDigest::sha1(), &key).unwrap();
    signer.update(payload.as_bytes()).unwrap();
    let hmac = signer.finish().unwrap();
    let computed_signature = format!("sha1={}", &hmac.to_hex());

    if !constant_time_eq(gh_signature.as_bytes(), computed_signature.as_bytes()) {
        error!(
            "Web hook signatuers don't match. GH = {:?}, Our = {:?}",
            gh_signature,
            computed_signature
        );
        return Ok(Response::with(status::BadRequest));
    }

    match event {
        GitHubEvent::Ping => Ok(Response::with(status::Ok)),
        GitHubEvent::Push => handle_push(req),
    }
}

pub fn repo_file_content(req: &mut Request) -> IronResult<Response> {
    let github = req.get::<persistent::Read<GitHubCli>>().unwrap();
    let session = req.extensions.get::<Authenticated>().unwrap();
    let params = req.extensions.get::<Router>().unwrap();
    let path = match params.find("path") {
        Some(path) => path,
        None => return Ok(Response::with(status::BadRequest)),
    };
    let install_id = match params.find("install_id") {
        Some(install_id) => {
            match install_id.parse::<u32>() {
                Ok(install_id) => install_id,
                Err(_) => return Ok(Response::with(status::BadRequest)),
            }
        }
        None => return Ok(Response::with(status::BadRequest)),
    };
    let token = {
        match github.app_installation_token(install_id) {
            Ok(token) => token,
            Err(err) => {
                return Ok(Response::with((status::BadGateway, err.to_string())));
            }
        }
    };
    let repo = {
        let repo = match params.find("repo") {
            Some(repo) => repo,
            None => return Ok(Response::with(status::BadRequest)),
        };
        let repos = match github.repositories(session.get_oauth_token(), install_id) {
            Ok(repos) => repos,
            Err(err) => return Ok(Response::with((status::BadGateway, err.to_string()))),
        };
        match repos.into_iter().find(|r| r.name == repo) {
            Some(repo) => repo,
            None => return Ok(Response::with(status::NotFound)),
        }
    };
    match github.contents(&token, repo.id, path) {
        Ok(search) => Ok(render_json(status::Ok, &search)),
        Err(err) => Ok(Response::with((status::BadGateway, err.to_string()))),
    }
}

pub fn search_code(req: &mut Request) -> IronResult<Response> {
    let github = req.get::<persistent::Read<GitHubCli>>().unwrap();
    let params = req.extensions.get::<Router>().unwrap();
    let query = match req.url.query() {
        Some(query) => query,
        None => return Ok(Response::with(status::BadRequest)),
    };
    let install_id = match params.find("install_id") {
        Some(install_id) => {
            match install_id.parse::<u32>() {
                Ok(install_id) => install_id,
                Err(_) => return Ok(Response::with(status::BadRequest)),
            }
        }
        None => return Ok(Response::with(status::BadRequest)),
    };
    let token = {
        match github.app_installation_token(install_id) {
            Ok(token) => token,
            Err(err) => {
                return Ok(Response::with((status::BadGateway, err.to_string())));
            }
        }
    };
    match github.search_code(&token, query) {
        Ok(search) => Ok(render_json(status::Ok, &search)),
        Err(err) => Ok(Response::with((status::BadGateway, err.to_string()))),
    }
}

fn handle_push(req: &mut Request) -> IronResult<Response> {
    let hook = match req.get::<bodyparser::Struct<GitHubWebhookPush>>() {
        Ok(Some(hook)) => hook,
        Ok(None) => return Ok(Response::with(status::UnprocessableEntity)),
        Err(err) => {
            return Ok(Response::with(
                (status::UnprocessableEntity, err.to_string()),
            ));
        }
    };

    if hook.commits.is_empty() {
        return Ok(Response::with(status::Ok));
    }

    let github = req.get::<persistent::Read<GitHubCli>>().unwrap();
    let token = match github.app_installation_token(hook.installation.id) {
        Ok(token) => token,
        Err(err) => {
            return Ok(Response::with((status::BadGateway, err.to_string())));
        }
    };

    let mut query = format!("q={}+in:path+repo:{}", "plan.sh", hook.repository.full_name);
    let plans = match github.search_code(&token, &query) {
        Ok(search) => search.items,
        Err(err) => return Ok(Response::with((status::BadGateway, err.to_string()))),
    };

    if plans.is_empty() {
        return Ok(Response::with(status::Ok));
    }

    query = format!("q={}+in:path+repo:{}", BLDR_CFG, hook.repository.full_name);

    let config = match github.search_code(&token, &query) {
        Ok(search) => {
            match search
                .items
                .into_iter()
                .filter(|i| i.path == BLDR_CFG)
                .collect::<Vec<SearchItem>>()
                .pop() {
                Some(item) => {
                    match read_bldr_config(&*github, &token, &hook, &item.path) {
                        HandleResult::Ok(cfg) => Some(cfg),
                        HandleResult::Err(response) => return Ok(response),
                    }
                }
                None => None,
            }
        }
        Err(err) => return Ok(Response::with((status::BadGateway, err.to_string()))),
    };

    debug!("Config, {:?}", config);

    let mut plans = match read_plans(&github, &token, &hook, plans) {
        HandleResult::Ok(plans) => plans,
        HandleResult::Err(err) => return Ok(err),
    };

    debug!("Plans, {:?}", plans);

    if let Some(cfg) = config {
        plans.retain(|plan| match cfg.get(&plan.name) {
            Some(project) => hook.changed().iter().any(|f| project.triggered_by(f)),
            None => false,
        })
    }

    build_plans(req, &hook.repository.clone_url, plans)
}

fn build_plans(req: &mut Request, repo_url: &str, plans: Vec<Plan>) -> IronResult<Response> {
    let mut request = GroupCreate::new();

    for plan in plans.into_iter() {
        let mut project_get = OriginProjectGet::new();
        project_get.set_name(format!("{}/{}", &plan.origin, &plan.name));

        match route_message::<OriginProjectGet, OriginProject>(req, &project_get) {
            Ok(project) => {
                if repo_url != project.get_vcs_data() {
                    error!(
                        "Incoming repository URL ({}) doesn't match what's in the project vcs data ({}). Aborting.",
                        repo_url,
                        project.get_vcs_data()
                    );
                    continue;
                }
            }
            Err(err) => {
                error!("Failed to fetch project. err = {:?}", &err);
                continue;
            }
        }

        debug!("Scheduling, {:?}", plan);
        request.set_origin(plan.origin);
        request.set_package(plan.name);
        // JW TODO: We need to be able to determine which platform this build is for based on
        // the directory structure the plan is found in or metadata inside the plan. We will need
        // to have this done before we support building additional targets with Builder.
        request.set_target("x86_64-linux".to_string());
        match route_message::<GroupCreate, Group>(req, &request) {
            Ok(group) => debug!("Group created, {:?}", group),
            Err(err) => debug!("Failed to create group, {:?}", err),
        }
    }

    Ok(Response::with(status::Ok))
}

fn read_bldr_config(
    github: &GitHubClient,
    token: &str,
    hook: &GitHubWebhookPush,
    path: &str,
) -> HandleResult<BuildCfg> {
    match github.contents(token, hook.repository.id, path) {
        Ok(contents) => {
            match contents.decode() {
                Ok(ref bytes) => {
                    match BuildCfg::from_slice(bytes) {
                        Ok(cfg) => HandleResult::Ok(cfg),
                        Err(err) => HandleResult::Err(Response::with(
                            (status::UnprocessableEntity, err.to_string()),
                        )),
                    }
                }
                Err(err) => {
                    HandleResult::Err(Response::with(
                        (status::UnprocessableEntity, err.to_string()),
                    ))
                }
            }
        }
        Err(err) => HandleResult::Err(Response::with((status::BadGateway, err.to_string()))),
    }
}

fn read_plans(
    github: &GitHubClient,
    token: &str,
    hook: &GitHubWebhookPush,
    plans: Vec<SearchItem>,
) -> HandleResult<Vec<Plan>> {
    let mut parsed = Vec::with_capacity(plans.len());
    for plan in plans {
        match github.contents(token, hook.repository.id, &plan.path) {
            Ok(contents) => {
                match contents.decode() {
                    Ok(bytes) => {
                        match Plan::from_bytes(bytes.as_slice()) {
                            Ok(plan) => parsed.push(plan),
                            Err(err) => debug!("{}, {}", plan.path, err),
                        }
                    }
                    Err(err) => {
                        return HandleResult::Err(Response::with((
                            status::UnprocessableEntity,
                            format!("{}, {}", plan.path, err),
                        )))
                    }
                }
            }
            Err(err) => {
                return HandleResult::Err(Response::with(
                    (status::BadGateway, format!("{}, {}", plan.path, err)),
                ))
            }
        }
    }
    HandleResult::Ok(parsed)
}
<commit_msg>Fix deserialization error on GitHub notify<commit_after>// Copyright (c) 2017 Chef Software Inc. and/or applicable contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::io::Read;
use std::str::FromStr;

use bldr_core::build_config::{BLDR_CFG, BuildCfg};
use constant_time_eq::constant_time_eq;
use github_api_client::GitHubClient;
use hab_core::package::Plan;
use hex::ToHex;
use http_gateway::http::controller::*;
use iron::status;
use openssl::hash::MessageDigest;
use openssl::pkey::PKey;
use openssl::sign::Signer;
use persistent;
use protocol::originsrv::{OriginProject, OriginProjectGet};
use protocol::scheduler::{Group, GroupCreate};
use router::Router;
use serde_json;

use error::Error;
use headers::*;
use types::*;

pub enum GitHubEvent {
    Push,
    Ping,
}

impl FromStr for GitHubEvent {
    type Err = Error;

    fn from_str(event: &str) -> Result<Self, Self::Err> {
        match event {
            "ping" => Ok(GitHubEvent::Ping),
            "push" => Ok(GitHubEvent::Push),
            _ => Err(Error::UnknownGitHubEvent(event.to_string())),
        }
    }
}

enum HandleResult<T> {
    Ok(T),
    Err(Response),
}

pub fn handle_event(req: &mut Request) -> IronResult<Response> {
    let event = match req.headers.get::<XGitHubEvent>() {
        Some(&XGitHubEvent(ref event)) => {
            match GitHubEvent::from_str(event) {
                Ok(event) => event,
                Err(err) => return Ok(Response::with((status::BadRequest, err.to_string()))),
            }
        }
        _ => return Ok(Response::with(status::BadRequest)),
    };

    // Authenticate the hook
    let github = req.get::<persistent::Read<GitHubCli>>().unwrap();
    let gh_signature = match req.headers.get::<XHubSignature>() {
        Some(&XHubSignature(ref sig)) => sig.clone(),
        None => {
            warn!("Received a GitHub hook with no signature");
            return Ok(Response::with(status::BadRequest));
        }
    };

    let mut payload = String::new();
    if let Err(err) = req.body.read_to_string(&mut payload) {
        warn!("Unable to read GitHub Hook request body, {}", err);
        return Ok(Response::with(status::BadRequest));
    }
    trace!("handle-notify, {}", payload);

    let key = PKey::hmac(github.webhook_secret.as_bytes()).unwrap();
    let mut signer = Signer::new(MessageDigest::sha1(), &key).unwrap();
    signer.update(payload.as_bytes()).unwrap();
    let hmac = signer.finish().unwrap();
    let computed_signature = format!("sha1={}", &hmac.to_hex());

    if !constant_time_eq(gh_signature.as_bytes(), computed_signature.as_bytes()) {
        warn!(
            "Web hook signatures don't match. GH = {}, Our = {}",
            gh_signature,
            computed_signature
        );
        return Ok(Response::with(status::BadRequest));
    }

    match event {
        GitHubEvent::Ping => Ok(Response::with(status::Ok)),
        GitHubEvent::Push => handle_push(req, &payload),
    }
}

pub fn repo_file_content(req: &mut Request) -> IronResult<Response> {
    let github = req.get::<persistent::Read<GitHubCli>>().unwrap();
    let session = req.extensions.get::<Authenticated>().unwrap();
    let params = req.extensions.get::<Router>().unwrap();
    let path = match params.find("path") {
        Some(path) => path,
        None => return Ok(Response::with(status::BadRequest)),
    };
    let install_id = match params.find("install_id") {
        Some(install_id) => {
            match install_id.parse::<u32>() {
                Ok(install_id) => install_id,
                Err(_) => return Ok(Response::with(status::BadRequest)),
            }
        }
        None => return Ok(Response::with(status::BadRequest)),
    };
    let token = {
        match github.app_installation_token(install_id) {
            Ok(token) => token,
            Err(err) => {
                return Ok(Response::with((status::BadGateway, err.to_string())));
            }
        }
    };
    let repo = {
        let repo = match params.find("repo") {
            Some(repo) => repo,
            None => return Ok(Response::with(status::BadRequest)),
        };
        let repos = match github.repositories(session.get_oauth_token(), install_id) {
            Ok(repos) => repos,
            Err(err) => return Ok(Response::with((status::BadGateway, err.to_string()))),
        };
        match repos.into_iter().find(|r| r.name == repo) {
            Some(repo) => repo,
            None => return Ok(Response::with(status::NotFound)),
        }
    };
    match github.contents(&token, repo.id, path) {
        Ok(search) => Ok(render_json(status::Ok, &search)),
        Err(err) => Ok(Response::with((status::BadGateway, err.to_string()))),
    }
}

pub fn search_code(req: &mut Request) -> IronResult<Response> {
    let github = req.get::<persistent::Read<GitHubCli>>().unwrap();
    let params = req.extensions.get::<Router>().unwrap();
    let query = match req.url.query() {
        Some(query) => query,
        None => return Ok(Response::with(status::BadRequest)),
    };
    let install_id = match params.find("install_id") {
        Some(install_id) => {
            match install_id.parse::<u32>() {
                Ok(install_id) => install_id,
                Err(_) => return Ok(Response::with(status::BadRequest)),
            }
        }
        None => return Ok(Response::with(status::BadRequest)),
    };
    let token = {
        match github.app_installation_token(install_id) {
            Ok(token) => token,
            Err(err) => {
                return Ok(Response::with((status::BadGateway, err.to_string())));
            }
        }
    };
    match github.search_code(&token, query) {
        Ok(search) => Ok(render_json(status::Ok, &search)),
        Err(err) => Ok(Response::with((status::BadGateway, err.to_string()))),
    }
}

fn handle_push(req: &mut Request, body: &str) -> IronResult<Response> {
    let hook = match serde_json::from_str::<GitHubWebhookPush>(&body) {
        Ok(hook) => hook,
        Err(err) => {
            return Ok(Response::with(
                (status::UnprocessableEntity, err.to_string()),
            ));
        }
    };

    if hook.commits.is_empty() {
        return Ok(Response::with(status::Ok));
    }

    let github = req.get::<persistent::Read<GitHubCli>>().unwrap();
    let token = match github.app_installation_token(hook.installation.id) {
        Ok(token) => token,
        Err(err) => {
            return Ok(Response::with((status::BadGateway, err.to_string())));
        }
    };

    let mut query = format!("q={}+in:path+repo:{}", "plan.sh", hook.repository.full_name);
    let plans = match github.search_code(&token, &query) {
        Ok(search) => search.items,
        Err(err) => return Ok(Response::with((status::BadGateway, err.to_string()))),
    };

    if plans.is_empty() {
        return Ok(Response::with(status::Ok));
    }

    query = format!("q={}+in:path+repo:{}", BLDR_CFG, hook.repository.full_name);

    let config = match github.search_code(&token, &query) {
        Ok(search) => {
            match search
                .items
                .into_iter()
                .filter(|i| i.path == BLDR_CFG)
                .collect::<Vec<SearchItem>>()
                .pop() {
                Some(item) => {
                    match read_bldr_config(&*github, &token, &hook, &item.path) {
                        HandleResult::Ok(cfg) => Some(cfg),
                        HandleResult::Err(response) => return Ok(response),
                    }
                }
                None => None,
            }
        }
        Err(err) => return Ok(Response::with((status::BadGateway, err.to_string()))),
    };

    debug!("Config, {:?}", config);

    let mut plans = match read_plans(&github, &token, &hook, plans) {
        HandleResult::Ok(plans) => plans,
        HandleResult::Err(err) => return Ok(err),
    };

    debug!("Plans, {:?}", plans);

    if let Some(cfg) = config {
        plans.retain(|plan| match cfg.get(&plan.name) {
            Some(project) => hook.changed().iter().any(|f| project.triggered_by(f)),
            None => false,
        })
    }

    build_plans(req, &hook.repository.clone_url, plans)
}

fn build_plans(req: &mut Request, repo_url: &str, plans: Vec<Plan>) -> IronResult<Response> {
    let mut request = GroupCreate::new();

    for plan in plans.into_iter() {
        let mut project_get = OriginProjectGet::new();
        project_get.set_name(format!("{}/{}", &plan.origin, &plan.name));

        match route_message::<OriginProjectGet, OriginProject>(req, &project_get) {
            Ok(project) => {
                if repo_url != project.get_vcs_data() {
                    warn!(
                        "Repo URL ({}) doesn't match project vcs data ({}). Aborting.",
                        repo_url,
                        project.get_vcs_data()
                    );
                    continue;
                }
            }
            Err(err) => {
                warn!("Failed to fetch project, {}", err);
                continue;
            }
        }

        debug!("Scheduling, {:?}", plan);
        request.set_origin(plan.origin);
        request.set_package(plan.name);
        // JW TODO: We need to be able to determine which platform this build is for based on
        // the directory structure the plan is found in or metadata inside the plan. We will need
        // to have this done before we support building additional targets with Builder.
        request.set_target("x86_64-linux".to_string());
        match route_message::<GroupCreate, Group>(req, &request) {
            Ok(group) => debug!("Group created, {:?}", group),
            Err(err) => debug!("Failed to create group, {:?}", err),
        }
    }

    Ok(Response::with(status::Ok))
}

fn read_bldr_config(
    github: &GitHubClient,
    token: &str,
    hook: &GitHubWebhookPush,
    path: &str,
) -> HandleResult<BuildCfg> {
    match github.contents(token, hook.repository.id, path) {
        Ok(contents) => {
            match contents.decode() {
                Ok(ref bytes) => {
                    match BuildCfg::from_slice(bytes) {
                        Ok(cfg) => HandleResult::Ok(cfg),
                        Err(err) => HandleResult::Err(Response::with(
                            (status::UnprocessableEntity, err.to_string()),
                        )),
                    }
                }
                Err(err) => {
                    HandleResult::Err(Response::with(
                        (status::UnprocessableEntity, err.to_string()),
                    ))
                }
            }
        }
        Err(err) => HandleResult::Err(Response::with((status::BadGateway, err.to_string()))),
    }
}

fn read_plans(
    github: &GitHubClient,
    token: &str,
    hook: &GitHubWebhookPush,
    plans: Vec<SearchItem>,
) -> HandleResult<Vec<Plan>> {
    let mut parsed = Vec::with_capacity(plans.len());
    for plan in plans {
        match github.contents(token, hook.repository.id, &plan.path) {
            Ok(contents) => {
                match contents.decode() {
                    Ok(bytes) => {
                        match Plan::from_bytes(bytes.as_slice()) {
                            Ok(plan) => parsed.push(plan),
                            Err(err) => debug!("{}, {}", plan.path, err),
                        }
                    }
                    Err(err) => {
                        return HandleResult::Err(Response::with((
                            status::UnprocessableEntity,
                            format!("{}, {}", plan.path, err),
                        )))
                    }
                }
            }
            Err(err) => {
                return HandleResult::Err(Response::with(
                    (status::BadGateway, format!("{}, {}", plan.path, err)),
                ))
            }
        }
    }
    HandleResult::Ok(parsed)
}
<|endoftext|>


<commit_before>use spec::ChainSpec;
use types::{BeaconBlock, BeaconBlockBody, Eth1Data, Hash256};

/// Generate a genesis BeaconBlock.
pub fn genesis_beacon_block(state_root: Hash256, spec: &ChainSpec) -> BeaconBlock {
    BeaconBlock {
        slot: spec.genesis_slot,
        parent_root: spec.zero_hash,
        state_root,
        randao_reveal: spec.empty_signature.clone(),
        eth1_data: Eth1Data {
            deposit_root: spec.zero_hash,
            block_hash: spec.zero_hash,
        },
        signature: spec.empty_signature.clone(),
        body: BeaconBlockBody {
            proposer_slashings: vec![],
            casper_slashings: vec![],
            attestations: vec![],
            custody_reseeds: vec![],
            custody_challenges: vec![],
            custody_responses: vec![],
            deposits: vec![],
            exits: vec![],
        },
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use bls::Signature;

    #[test]
    fn test_genesis() {
        let spec = ChainSpec::foundation();
        let state_root = Hash256::from("cats".as_bytes());

        // This only checks that the function runs without panic.
        genesis_beacon_block(state_root, &spec);
    }

    #[test]
    fn test_zero_items() {
        let spec = ChainSpec::foundation();

        let state_root = Hash256::zero();

        let genesis_block = genesis_beacon_block(state_root, &spec);

        assert!(genesis_block.slot == 0);
        assert!(genesis_block.parent_root.is_zero());
        assert_eq!(genesis_block.randao_reveal, Signature::empty_signature());
        assert!(genesis_block.eth1_data.deposit_root.is_zero());
        assert!(genesis_block.eth1_data.block_hash.is_zero());
    }

    #[test]
    fn test_beacon_body() {
        let spec = ChainSpec::foundation();

        let state_root = Hash256::zero();

        let genesis_block = genesis_beacon_block(state_root, &spec);

        // Custody items are not being implemented until phase 1 so tests to be added later

        assert!(genesis_block.body.proposer_slashings.is_empty());
        assert!(genesis_block.body.casper_slashings.is_empty());
        assert!(genesis_block.body.attestations.is_empty());
        assert!(genesis_block.body.deposits.is_empty());
        assert!(genesis_block.body.exits.is_empty());
    }

    #[test]
    fn test_signature() {
        let spec = ChainSpec::foundation();

        let state_root = Hash256::zero();

        let genesis_block = genesis_beacon_block(state_root, &spec);

        // Signature should consist of [bytes48(0), bytes48(0)]
        // Note this is implemented using Apache Milagro BLS which requires one extra byte -> 97bytes
        let raw_sig = genesis_block.signature.as_raw();
        let raw_sig_bytes = raw_sig.as_bytes();

        for item in raw_sig_bytes.iter() {
            assert!(*item == 0);
        }
        assert_eq!(genesis_block.signature, Signature::empty_signature());
    }
}
<commit_msg>Add test for `state_root` to genesis<commit_after>use spec::ChainSpec;
use types::{BeaconBlock, BeaconBlockBody, Eth1Data, Hash256};

/// Generate a genesis BeaconBlock.
pub fn genesis_beacon_block(state_root: Hash256, spec: &ChainSpec) -> BeaconBlock {
    BeaconBlock {
        slot: spec.genesis_slot,
        parent_root: spec.zero_hash,
        state_root,
        randao_reveal: spec.empty_signature.clone(),
        eth1_data: Eth1Data {
            deposit_root: spec.zero_hash,
            block_hash: spec.zero_hash,
        },
        signature: spec.empty_signature.clone(),
        body: BeaconBlockBody {
            proposer_slashings: vec![],
            casper_slashings: vec![],
            attestations: vec![],
            custody_reseeds: vec![],
            custody_challenges: vec![],
            custody_responses: vec![],
            deposits: vec![],
            exits: vec![],
        },
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use bls::Signature;

    #[test]
    fn test_state_root() {
        let spec = ChainSpec::foundation();
        let state_root = Hash256::from("cats".as_bytes());

        let block = genesis_beacon_block(state_root, &spec);

        assert_eq!(block.state_root, state_root);
    }

    #[test]
    fn test_zero_items() {
        let spec = ChainSpec::foundation();

        let state_root = Hash256::zero();

        let genesis_block = genesis_beacon_block(state_root, &spec);

        assert!(genesis_block.slot == 0);
        assert!(genesis_block.parent_root.is_zero());
        assert_eq!(genesis_block.randao_reveal, Signature::empty_signature());
        assert!(genesis_block.eth1_data.deposit_root.is_zero());
        assert!(genesis_block.eth1_data.block_hash.is_zero());
    }

    #[test]
    fn test_beacon_body() {
        let spec = ChainSpec::foundation();

        let state_root = Hash256::zero();

        let genesis_block = genesis_beacon_block(state_root, &spec);

        // Custody items are not being implemented until phase 1 so tests to be added later

        assert!(genesis_block.body.proposer_slashings.is_empty());
        assert!(genesis_block.body.casper_slashings.is_empty());
        assert!(genesis_block.body.attestations.is_empty());
        assert!(genesis_block.body.deposits.is_empty());
        assert!(genesis_block.body.exits.is_empty());
    }

    #[test]
    fn test_signature() {
        let spec = ChainSpec::foundation();

        let state_root = Hash256::zero();

        let genesis_block = genesis_beacon_block(state_root, &spec);

        // Signature should consist of [bytes48(0), bytes48(0)]
        // Note this is implemented using Apache Milagro BLS which requires one extra byte -> 97bytes
        let raw_sig = genesis_block.signature.as_raw();
        let raw_sig_bytes = raw_sig.as_bytes();

        for item in raw_sig_bytes.iter() {
            assert!(*item == 0);
        }
        assert_eq!(genesis_block.signature, Signature::empty_signature());
    }
}
<|endoftext|>


<commit_before>//! Library used by tidy and other tools.
//!
//! This library contains the tidy lints and exposes it
//! to be used by tools.

use walkdir::{DirEntry, WalkDir};
use std::fs::File;
use std::io::Read;

use std::path::Path;

macro_rules! t {
    ($e:expr, $p:expr) => (match $e {
        Ok(e) => e,
        Err(e) => panic!("{} failed on {} with {}", stringify!($e), ($p).display(), e),
    });

    ($e:expr) => (match $e {
        Ok(e) => e,
        Err(e) => panic!("{} failed with {}", stringify!($e), e),
    })
}

macro_rules! tidy_error {
    ($bad:expr, $fmt:expr, $($arg:tt)*) => ({
        *$bad = true;
        eprint!("tidy error: ");
        eprintln!($fmt, $($arg)*);
    });
}

pub mod bins;
pub mod style;
pub mod errors;
pub mod features;
pub mod cargo;
pub mod edition;
pub mod pal;
pub mod deps;
pub mod extdeps;
pub mod ui_tests;
pub mod unit_tests;
pub mod unstable_book;

fn filter_dirs(path: &Path) -> bool {
    let skip = [
        "src/llvm-emscripten",
        "src/llvm-project",
        "src/stdarch",
        "src/tools/cargo",
        "src/tools/clippy",
        "src/tools/miri",
        "src/tools/rls",
        "src/tools/rust-installer",
        "src/tools/rustfmt",
    ];
    skip.iter().any(|p| path.ends_with(p))
}

fn walk_many(
    paths: &[&Path], skip: &mut dyn FnMut(&Path) -> bool, f: &mut dyn FnMut(&DirEntry, &str)
) {
    for path in paths {
        walk(path, skip, f);
    }
}

fn walk(path: &Path, skip: &mut dyn FnMut(&Path) -> bool, f: &mut dyn FnMut(&DirEntry, &str)) {
    let mut contents = String::new();
    walk_no_read(path, skip, &mut |entry| {
        contents.clear();
        if t!(File::open(entry.path()), entry.path()).read_to_string(&mut contents).is_err() {
            contents.clear();
        }
        f(&entry, &contents);
    });
}

fn walk_no_read(path: &Path, skip: &mut dyn FnMut(&Path) -> bool, f: &mut dyn FnMut(&DirEntry)) {
    let walker = WalkDir::new(path).into_iter()
        .filter_entry(|e| !skip(e.path()));
    for entry in walker {
        if let Ok(entry) = entry {
            if entry.file_type().is_dir() {
                continue;
            }
            f(&entry);
        }
    }
}
<commit_msg>Rollup merge of #64998 - spastorino:filter-rls-on-tidy, r=petrochenkov<commit_after>//! Library used by tidy and other tools.
//!
//! This library contains the tidy lints and exposes it
//! to be used by tools.

use walkdir::{DirEntry, WalkDir};
use std::fs::File;
use std::io::Read;

use std::path::Path;

macro_rules! t {
    ($e:expr, $p:expr) => (match $e {
        Ok(e) => e,
        Err(e) => panic!("{} failed on {} with {}", stringify!($e), ($p).display(), e),
    });

    ($e:expr) => (match $e {
        Ok(e) => e,
        Err(e) => panic!("{} failed with {}", stringify!($e), e),
    })
}

macro_rules! tidy_error {
    ($bad:expr, $fmt:expr, $($arg:tt)*) => ({
        *$bad = true;
        eprint!("tidy error: ");
        eprintln!($fmt, $($arg)*);
    });
}

pub mod bins;
pub mod style;
pub mod errors;
pub mod features;
pub mod cargo;
pub mod edition;
pub mod pal;
pub mod deps;
pub mod extdeps;
pub mod ui_tests;
pub mod unit_tests;
pub mod unstable_book;

fn filter_dirs(path: &Path) -> bool {
    let skip = [
        "src/llvm-emscripten",
        "src/llvm-project",
        "src/stdarch",
        "src/tools/cargo",
        "src/tools/clippy",
        "src/tools/miri",
        "src/tools/rls",
        "src/tools/rust-installer",
        "src/tools/rustfmt",

        // Filter RLS output directories
        "target/rls",
    ];
    skip.iter().any(|p| path.ends_with(p))
}

fn walk_many(
    paths: &[&Path], skip: &mut dyn FnMut(&Path) -> bool, f: &mut dyn FnMut(&DirEntry, &str)
) {
    for path in paths {
        walk(path, skip, f);
    }
}

fn walk(path: &Path, skip: &mut dyn FnMut(&Path) -> bool, f: &mut dyn FnMut(&DirEntry, &str)) {
    let mut contents = String::new();
    walk_no_read(path, skip, &mut |entry| {
        contents.clear();
        if t!(File::open(entry.path()), entry.path()).read_to_string(&mut contents).is_err() {
            contents.clear();
        }
        f(&entry, &contents);
    });
}

fn walk_no_read(path: &Path, skip: &mut dyn FnMut(&Path) -> bool, f: &mut dyn FnMut(&DirEntry)) {
    let walker = WalkDir::new(path).into_iter()
        .filter_entry(|e| !skip(e.path()));
    for entry in walker {
        if let Ok(entry) = entry {
            if entry.file_type().is_dir() {
                continue;
            }
            f(&entry);
        }
    }
}
<|endoftext|>


<commit_before>use std::env;
use std::borrow::Cow;
use std::path::Path;
use std::fs::File;
use std::process::Command;
use std::error::Error;
use super::Worker;

/// A TeX to HTML conversion worker -- this is a demonstration only
/// it lacks robustness guards
/// see the Perl worker used in production for a full overviewthread::spawn(move || {
///  https://github.com/dginev/latexml-plugin-cortex
#[derive(Clone, Debug)]
pub struct TexToHtmlWorker {
  /// the usual
  pub service: String,
  /// the usual
  pub version: f32,
  /// the usual
  pub message_size: usize,
  /// the usual
  pub source: String,
  /// the usual
  pub sink: String,
}
impl Default for TexToHtmlWorker {
  fn default() -> TexToHtmlWorker {
    TexToHtmlWorker {
      service: "tex_to_html".to_string(),
      version: 0.1,
      message_size: 100_000,
      source: "tcp://127.0.0.1:51695".to_string(),
      sink: "tcp://127.0.0.1:51696".to_string(),
    }
  }
}
impl Worker for TexToHtmlWorker {
  fn get_service(&self) -> &str {
    &self.service
  }
  fn get_source_address(&self) -> Cow<str> {
    Cow::Borrowed(&self.source)
  }
  fn get_sink_address(&self) -> Cow<str> {
    Cow::Borrowed(&self.sink)
  }
  fn message_size(&self) -> usize {
    self.message_size
  }

  fn convert(&self, path: &Path) -> Result<File, Box<Error>> {
    let name = path.file_stem().unwrap().to_str().unwrap();
    let destination_path = env::temp_dir().to_str().unwrap().to_string() + "/" + name + ".zip";
    // println!("Source {:?}", path);
    Command::new("latexmlc")
      .arg("--whatsin")
      .arg("archive")
      .arg("--whatsout")
      .arg("archive")
      .arg("--format")
      .arg("html5")
      .arg("--pmml")
      .arg("--cmml")
      .arg("--mathtex")
      .arg("--preload")
      .arg("[ids]latexml.sty")
      .arg("--nodefaultresources")
      .arg("--inputencoding")
      .arg("iso-8859-1")
      .arg("--timeout")
      .arg("300")
      .arg("--log")
      .arg("cortex.log")
      .arg("--destination")
      .arg(destination_path.clone())
      .arg(path.to_string_lossy().to_string())
      .output()
      .unwrap_or_else(|e| panic!("failed to execute process: {}", e));

    // println!("Dest: {:?}", destination_path);
    File::open(destination_path.clone()).map_err(Into::into)
  }
}
<commit_msg>identity for tex_to_html worker<commit_after>use super::Worker;
use std::borrow::Cow;
use std::env;
use std::error::Error;
use std::fs::File;
use std::path::Path;
use std::process::Command;

/// A TeX to HTML conversion worker -- this is a demonstration only
/// it lacks robustness guards
/// see the Perl worker used in production for a full overviewthread::spawn(move || {
///  https://github.com/dginev/latexml-plugin-cortex
#[derive(Clone, Debug)]
pub struct TexToHtmlWorker {
  /// the usual
  pub service: String,
  /// the usual
  pub version: f32,
  /// the usual
  pub message_size: usize,
  /// the usual
  pub source: String,
  /// the usual
  pub sink: String,
  ///  the usual
  pub identity: String,
}
impl Default for TexToHtmlWorker {
  fn default() -> TexToHtmlWorker {
    TexToHtmlWorker {
      service: "tex_to_html".to_string(),
      version: 0.1,
      message_size: 100_000,
      source: "tcp://127.0.0.1:51695".to_string(),
      sink: "tcp://127.0.0.1:51696".to_string(),
      identity: String::new()
    }
  }
}
impl Worker for TexToHtmlWorker {
  fn get_service(&self) -> &str {
    &self.service
  }
  fn get_source_address(&self) -> Cow<str> {
    Cow::Borrowed(&self.source)
  }
  fn get_sink_address(&self) -> Cow<str> {
    Cow::Borrowed(&self.sink)
  }
  fn message_size(&self) -> usize {
    self.message_size
  }
  fn get_identity(&self) -> &str { &self.identity }
  fn set_identity(&mut self, identity: String) { self.identity = identity; }

  fn convert(&self, path: &Path) -> Result<File, Box<Error>> {
    let name = path.file_stem().unwrap().to_str().unwrap();
    let destination_path = env::temp_dir().to_str().unwrap().to_string() + "/" + name + ".zip";
    // println!("Source {:?}", path);
    Command::new("latexmlc")
      .arg("--whatsin")
      .arg("archive")
      .arg("--whatsout")
      .arg("archive")
      .arg("--format")
      .arg("html5")
      .arg("--pmml")
      .arg("--cmml")
      .arg("--mathtex")
      .arg("--preload")
      .arg("[ids]latexml.sty")
      .arg("--nodefaultresources")
      .arg("--inputencoding")
      .arg("iso-8859-1")
      .arg("--timeout")
      .arg("300")
      .arg("--log")
      .arg("cortex.log")
      .arg("--destination")
      .arg(destination_path.clone())
      .arg(path.to_string_lossy().to_string())
      .output()
      .unwrap_or_else(|e| panic!("failed to execute process: {}", e));

    // println!("Dest: {:?}", destination_path);
    File::open(destination_path.clone()).map_err(Into::into)
  }
}
<|endoftext|>


<commit_before>#![allow(non_upper_case_globals)]
#![allow(dead_code)]
extern crate libc;
extern crate xlib;
extern crate xinerama;

use self::libc::{ c_char, c_int, c_uint, c_void };
use self::libc::funcs::c95::stdlib::malloc;
use self::xlib::{
    Display,
    Window,
    XConfigureRequestEvent,
    XButtonEvent,
    XSetWindowBorder,
    XSetWindowBorderWidth,
    XDefaultScreenOfDisplay,
    XDestroyWindowEvent,
    XDisplayWidth,
    XDisplayHeight,
    XEnterWindowEvent,
    XErrorEvent,
    XFetchName,
    XKeyEvent,
    XLeaveWindowEvent,
    XMapRequestEvent,
    XMapWindow,
    XMoveWindow,
    XNextEvent,
    XOpenDisplay,
    XPending,
    XQueryTree,
    XResizeWindow,
    XRootWindowOfScreen,
    XScreenCount,
    XSelectInput,
    XSetErrorHandler,
    XSync,
    XUnmapEvent,
    XUnmapWindow,
};
use self::xinerama::{
    XineramaQueryScreens,
};

use std::collections::TreeSet;
use std::os::env;
use std::ptr::null_mut;
use std::mem::transmute;
use std::mem::uninitialized;
use std::str::raw::c_str_to_static_slice;
use std::slice::raw::buf_as_slice;

use window_system::{ Rectangle, WindowSystem, WindowSystemEvent };
use window_system::{
    ConfigurationRequest,
    Enter,
    Leave,
    WindowCreated,
    WindowDestroyed,
    WindowUnmapped,
    ButtonPressed,
    KeyPressed,
    UnknownEvent
};

const KeyPress               : uint =  2;
const KeyRelease             : uint =  3;
const ButtonPress            : uint =  4;
const ButtonRelease          : uint =  5;
const MotionNotify           : uint =  6;
const EnterNotify            : uint =  7;
const LeaveNotify            : uint =  8;
const FocusIn                : uint =  9;
const FocusOut               : uint = 10;
const KeymapNotify           : uint = 11;
const Expose                 : uint = 12;
const GraphicsExpose         : uint = 13;
const NoExpose               : uint = 14;
const VisibilityNotify       : uint = 15;
const CreateNotify           : uint = 16;
const DestroyNotify          : uint = 17;
const UnmapNotify            : uint = 18;
const MapNotify              : uint = 19;
const MapRequest             : uint = 20;
const ReparentNotify         : uint = 21;
const ConfigureNotify        : uint = 22;
const ConfigureRequest       : uint = 23;
const GravityNotify          : uint = 24;
const ResizeRequest          : uint = 25;
const CirculateNotify        : uint = 26;
const CirculateRequest       : uint = 27;
const PropertyNotify         : uint = 28;
const SelectionClear         : uint = 29;
const SelectionRequest       : uint = 30;
const SelectionNotify        : uint = 31;
const ColormapNotify         : uint = 32;
const ClientMessage          : uint = 33;
const MappingNotify          : uint = 34;

extern fn error_handler(display: *mut Display, event: *mut XErrorEvent) -> c_int {
    return 0;
}

pub struct XlibWindowSystem {
    display: *mut Display,
    root:    Window,
    event:   *mut c_void,
    awaiting_unmap: TreeSet<Window>
}

impl XlibWindowSystem {
    pub fn new() -> XlibWindowSystem {
        unsafe {
            let display = XOpenDisplay(null_mut());

            if display == null_mut() {
                error!("No display found at {}",
                    env().iter()
                       .find(|&&(ref d, _)| *d == String::from_str("DISPLAY"))
                       .map(|&(_, ref v)| v.clone())
                       .unwrap());
                panic!("Exiting");
            }

            let screen  = XDefaultScreenOfDisplay(display);
            let root    = XRootWindowOfScreen(screen);

            XSetErrorHandler(error_handler as *mut u8);

            XSelectInput(display, root, 0x180034);
            XSync(display, 0);

            XlibWindowSystem {
                display: display,
                root:    root,
                event:   malloc(256),
                awaiting_unmap: TreeSet::new()
            }
        }
    }

    fn get_event_as<T>(&self) -> &T {
        unsafe {
            let event_ptr : *const T = transmute(self.event);
            let ref event : T = *event_ptr;
            event
        }
    }
}

impl WindowSystem for XlibWindowSystem {
    fn get_screen_infos(&self) -> Vec<Rectangle> {
        unsafe {
            let mut num : c_int = 0;
            let screen_ptr = XineramaQueryScreens(self.display, &mut num);

            // If xinerama is not active, just return the default display
            // dimensions and "emulate" xinerama.
            if num == 0 {
                return vec!(Rectangle(0, 0,
                                      self.get_display_width(0) as uint,
                                      self.get_display_height(0) as uint));
            }

            buf_as_slice(screen_ptr, num as uint, |x| {
                let mut result : Vec<Rectangle> = Vec::new();
                for &screen_info in x.iter() {
                    result.push(Rectangle(
                            screen_info.x_org as uint,
                            screen_info.y_org as uint,
                            screen_info.width as uint,
                            screen_info.height as uint));
                }
                result
            })
        }
    }

    fn get_number_of_screens(&self) -> uint {
        unsafe {
            XScreenCount(self.display) as uint
        }
    }

    fn get_display_width(&self, screen: uint) -> u32 {
        unsafe {
            XDisplayWidth(self.display, screen as i32) as u32
        }
    }

    fn get_display_height(&self, screen: uint) -> u32 {
        unsafe {
            XDisplayHeight(self.display, screen as i32) as u32
        }
    }

    fn get_window_name(&self, window: Window) -> String {
        if window == self.root { return String::from_str("root"); }
        unsafe {
            let mut name : *mut c_char = uninitialized();
            XFetchName(self.display, window, &mut name);
            String::from_str(c_str_to_static_slice(transmute(name)))
        }
    }

    fn get_windows(&self) -> Vec<Window> {
        unsafe {
            let mut unused = 0u64;
            let mut children : *mut u64 = uninitialized();
            let children_ptr : *mut *mut u64 = &mut children;
            let mut num_children : c_uint = 0;
            XQueryTree(self.display, self.root, &mut unused, &mut unused, children_ptr, &mut num_children);
            let const_children : *const u64 = children as *const u64;
            buf_as_slice(const_children, num_children as uint, |x|
                         x.to_vec().iter()
                            .filter(|&&c| c != self.root)
                            .map(|&c| c)
                            .collect())
        }
    }

    fn set_window_border_width(&mut self, window: Window, border_width: uint) {
        if window == self.root { return; }
        unsafe {
            XSetWindowBorderWidth(self.display, window, border_width as u32);
        }
    }

    fn set_window_border_color(&mut self, window: Window, border_color: uint) {
        if window == self.root { return; }
        unsafe {
            XSetWindowBorder(self.display, window, border_color as Window);
        }
    }

    fn resize_window(&mut self, window: Window, width: uint, height: uint) {
        unsafe {
            XResizeWindow(self.display, window, width as u32, height as u32);
        }
    }

    fn move_window(&mut self, window: Window, x: uint, y: uint) {
        unsafe {
            XMoveWindow(self.display, window, x as i32, y as i32);
        }
    }

    fn show_window(&mut self, window: Window) {
        unsafe {
            XMapWindow(self.display, window);
        }
    }

    fn hide_window(&mut self, window: Window) {
        self.awaiting_unmap.insert(window);
        unsafe {
            XUnmapWindow(self.display, window);
        }
    }

    fn event_pending(&self) -> bool {
        unsafe {
            XPending(self.display) != 0
        }
    }

    fn get_event(&mut self) -> WindowSystemEvent {
        unsafe {
            //XSync(self.display, 0);
            XNextEvent(self.display, self.event);
        }

        let event_type : c_int = *self.get_event_as();

        match event_type as uint {
            ConfigureRequest => {
                let event : &XConfigureRequestEvent = self.get_event_as();
                ConfigurationRequest(event.window)
            },
            MapRequest => {
                let event : &XMapRequestEvent = self.get_event_as();
                unsafe { XSelectInput(self.display, event.window, 0x180034); }
                WindowCreated(event.window)
            },
            UnmapNotify => {
                let event : &XUnmapEvent = self.get_event_as();
                WindowUnmapped(event.window, event.send_event > 0)
            },
            DestroyNotify => {
                let event : &XDestroyWindowEvent = self.get_event_as();
                WindowDestroyed(event.window)
            },
            EnterNotify => {
                let event : &XEnterWindowEvent = self.get_event_as();
                if event.detail != 2 {
                    Enter(event.window)
                } else {
                    UnknownEvent
                }
            },
            LeaveNotify => {
                let event : &XLeaveWindowEvent = self.get_event_as();
                if event.detail != 2 {
                    Leave(event.window)
                } else {
                    UnknownEvent
                }
            },
            ButtonPress => {
                let event : &XButtonEvent = self.get_event_as();
                ButtonPressed(event.window, event.state as uint, event.button as uint,
                              event.x_root as uint, event.y_root as uint)
            },
            KeyPress => {
                let event : &XKeyEvent = self.get_event_as();
                KeyPressed(event.window, event.keycode as uint, event.state as uint)
            },
            _  => {
                UnknownEvent
            }
        }
    }
}
<commit_msg>fixed input mask for windows<commit_after>#![allow(non_upper_case_globals)]
#![allow(dead_code)]
extern crate libc;
extern crate xlib;
extern crate xinerama;

use self::libc::{ c_char, c_int, c_uint, c_void };
use self::libc::funcs::c95::stdlib::malloc;
use self::xlib::{
    Display,
    Window,
    XConfigureRequestEvent,
    XButtonEvent,
    XSetWindowBorder,
    XSetWindowBorderWidth,
    XDefaultScreenOfDisplay,
    XDestroyWindowEvent,
    XDisplayWidth,
    XDisplayHeight,
    XEnterWindowEvent,
    XErrorEvent,
    XFetchName,
    XKeyEvent,
    XLeaveWindowEvent,
    XMapRequestEvent,
    XMapWindow,
    XMoveWindow,
    XNextEvent,
    XOpenDisplay,
    XPending,
    XQueryTree,
    XResizeWindow,
    XRootWindowOfScreen,
    XScreenCount,
    XSelectInput,
    XSetErrorHandler,
    XSync,
    XUnmapEvent,
    XUnmapWindow,
};
use self::xinerama::{
    XineramaQueryScreens,
};

use std::collections::TreeSet;
use std::os::env;
use std::ptr::null_mut;
use std::mem::transmute;
use std::mem::uninitialized;
use std::str::raw::c_str_to_static_slice;
use std::slice::raw::buf_as_slice;

use window_system::{ Rectangle, WindowSystem, WindowSystemEvent };
use window_system::{
    ConfigurationRequest,
    Enter,
    Leave,
    WindowCreated,
    WindowDestroyed,
    WindowUnmapped,
    ButtonPressed,
    KeyPressed,
    UnknownEvent
};

const KeyPress               : uint =  2;
const KeyRelease             : uint =  3;
const ButtonPress            : uint =  4;
const ButtonRelease          : uint =  5;
const MotionNotify           : uint =  6;
const EnterNotify            : uint =  7;
const LeaveNotify            : uint =  8;
const FocusIn                : uint =  9;
const FocusOut               : uint = 10;
const KeymapNotify           : uint = 11;
const Expose                 : uint = 12;
const GraphicsExpose         : uint = 13;
const NoExpose               : uint = 14;
const VisibilityNotify       : uint = 15;
const CreateNotify           : uint = 16;
const DestroyNotify          : uint = 17;
const UnmapNotify            : uint = 18;
const MapNotify              : uint = 19;
const MapRequest             : uint = 20;
const ReparentNotify         : uint = 21;
const ConfigureNotify        : uint = 22;
const ConfigureRequest       : uint = 23;
const GravityNotify          : uint = 24;
const ResizeRequest          : uint = 25;
const CirculateNotify        : uint = 26;
const CirculateRequest       : uint = 27;
const PropertyNotify         : uint = 28;
const SelectionClear         : uint = 29;
const SelectionRequest       : uint = 30;
const SelectionNotify        : uint = 31;
const ColormapNotify         : uint = 32;
const ClientMessage          : uint = 33;
const MappingNotify          : uint = 34;

extern fn error_handler(display: *mut Display, event: *mut XErrorEvent) -> c_int {
    return 0;
}

pub struct XlibWindowSystem {
    display: *mut Display,
    root:    Window,
    event:   *mut c_void,
    awaiting_unmap: TreeSet<Window>
}

impl XlibWindowSystem {
    pub fn new() -> XlibWindowSystem {
        unsafe {
            let display = XOpenDisplay(null_mut());

            if display == null_mut() {
                error!("No display found at {}",
                    env().iter()
                       .find(|&&(ref d, _)| *d == String::from_str("DISPLAY"))
                       .map(|&(_, ref v)| v.clone())
                       .unwrap());
                panic!("Exiting");
            }

            let screen  = XDefaultScreenOfDisplay(display);
            let root    = XRootWindowOfScreen(screen);

            XSetErrorHandler(error_handler as *mut u8);

            XSelectInput(display, root, 0x180034);
            XSync(display, 0);

            XlibWindowSystem {
                display: display,
                root:    root,
                event:   malloc(256),
                awaiting_unmap: TreeSet::new()
            }
        }
    }

    fn get_event_as<T>(&self) -> &T {
        unsafe {
            let event_ptr : *const T = transmute(self.event);
            let ref event : T = *event_ptr;
            event
        }
    }
}

impl WindowSystem for XlibWindowSystem {
    fn get_screen_infos(&self) -> Vec<Rectangle> {
        unsafe {
            let mut num : c_int = 0;
            let screen_ptr = XineramaQueryScreens(self.display, &mut num);

            // If xinerama is not active, just return the default display
            // dimensions and "emulate" xinerama.
            if num == 0 {
                return vec!(Rectangle(0, 0,
                                      self.get_display_width(0) as uint,
                                      self.get_display_height(0) as uint));
            }

            buf_as_slice(screen_ptr, num as uint, |x| {
                let mut result : Vec<Rectangle> = Vec::new();
                for &screen_info in x.iter() {
                    result.push(Rectangle(
                            screen_info.x_org as uint,
                            screen_info.y_org as uint,
                            screen_info.width as uint,
                            screen_info.height as uint));
                }
                result
            })
        }
    }

    fn get_number_of_screens(&self) -> uint {
        unsafe {
            XScreenCount(self.display) as uint
        }
    }

    fn get_display_width(&self, screen: uint) -> u32 {
        unsafe {
            XDisplayWidth(self.display, screen as i32) as u32
        }
    }

    fn get_display_height(&self, screen: uint) -> u32 {
        unsafe {
            XDisplayHeight(self.display, screen as i32) as u32
        }
    }

    fn get_window_name(&self, window: Window) -> String {
        if window == self.root { return String::from_str("root"); }
        unsafe {
            let mut name : *mut c_char = uninitialized();
            XFetchName(self.display, window, &mut name);
            String::from_str(c_str_to_static_slice(transmute(name)))
        }
    }

    fn get_windows(&self) -> Vec<Window> {
        unsafe {
            let mut unused = 0u64;
            let mut children : *mut u64 = uninitialized();
            let children_ptr : *mut *mut u64 = &mut children;
            let mut num_children : c_uint = 0;
            XQueryTree(self.display, self.root, &mut unused, &mut unused, children_ptr, &mut num_children);
            let const_children : *const u64 = children as *const u64;
            buf_as_slice(const_children, num_children as uint, |x|
                         x.to_vec().iter()
                            .filter(|&&c| c != self.root)
                            .map(|&c| c)
                            .collect())
        }
    }

    fn set_window_border_width(&mut self, window: Window, border_width: uint) {
        if window == self.root { return; }
        unsafe {
            XSetWindowBorderWidth(self.display, window, border_width as u32);
        }
    }

    fn set_window_border_color(&mut self, window: Window, border_color: uint) {
        if window == self.root { return; }
        unsafe {
            XSetWindowBorder(self.display, window, border_color as Window);
        }
    }

    fn resize_window(&mut self, window: Window, width: uint, height: uint) {
        unsafe {
            XResizeWindow(self.display, window, width as u32, height as u32);
        }
    }

    fn move_window(&mut self, window: Window, x: uint, y: uint) {
        unsafe {
            XMoveWindow(self.display, window, x as i32, y as i32);
        }
    }

    fn show_window(&mut self, window: Window) {
        unsafe {
            XMapWindow(self.display, window);
        }
    }

    fn hide_window(&mut self, window: Window) {
        self.awaiting_unmap.insert(window);
        unsafe {
            XUnmapWindow(self.display, window);
        }
    }

    fn event_pending(&self) -> bool {
        unsafe {
            XPending(self.display) != 0
        }
    }

    fn get_event(&mut self) -> WindowSystemEvent {
        unsafe {
            //XSync(self.display, 0);
            XNextEvent(self.display, self.event);
        }

        let event_type : c_int = *self.get_event_as();

        match event_type as uint {
            ConfigureRequest => {
                let event : &XConfigureRequestEvent = self.get_event_as();
                ConfigurationRequest(event.window)
            },
            MapRequest => {
                let event : &XMapRequestEvent = self.get_event_as();
                unsafe { XSelectInput(self.display, event.window, 0x180030); }
                WindowCreated(event.window)
            },
            UnmapNotify => {
                let event : &XUnmapEvent = self.get_event_as();
                WindowUnmapped(event.window, event.send_event > 0)
            },
            DestroyNotify => {
                let event : &XDestroyWindowEvent = self.get_event_as();
                WindowDestroyed(event.window)
            },
            EnterNotify => {
                let event : &XEnterWindowEvent = self.get_event_as();
                if event.detail != 2 {
                    Enter(event.window)
                } else {
                    UnknownEvent
                }
            },
            LeaveNotify => {
                let event : &XLeaveWindowEvent = self.get_event_as();
                if event.detail != 2 {
                    Leave(event.window)
                } else {
                    UnknownEvent
                }
            },
            ButtonPress => {
                let event : &XButtonEvent = self.get_event_as();
                ButtonPressed(event.window, event.state as uint, event.button as uint,
                              event.x_root as uint, event.y_root as uint)
            },
            KeyPress => {
                let event : &XKeyEvent = self.get_event_as();
                KeyPressed(event.window, event.keycode as uint, event.state as uint)
            },
            _  => {
                UnknownEvent
            }
        }
    }
}
<|endoftext|>


<commit_before>// Copyright (c) 2021 The Vulkano developers
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or
// https://www.apache.org/licenses/LICENSE-2.0> or the MIT
// license <LICENSE-MIT or https://opensource.org/licenses/MIT>,
// at your option. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.

use super::{write_file, VkRegistryData};
use heck::{ToSnakeCase, ToUpperCamelCase};
use indexmap::IndexMap;
use proc_macro2::{Ident, TokenStream};
use quote::{format_ident, quote};
use vk_parse::{Extension, ExtensionChild, InterfaceItem};

pub fn write(vk_data: &VkRegistryData) {
    let entry_fns_output = fns_output(
        &[],
        "Entry",
        "Raw Vulkan global entry point-level functions.\n\nTo use these, you need to include the Ash crate, using the same version Vulkano uses.",
    );
    let instance_fns_output = fns_output(
        &extension_fns_members("instance", &vk_data.extensions),
        "Instance",
        "Raw Vulkan instance-level functions.\n\nTo use these, you need to include the Ash crate, using the same version Vulkano uses.",
    );
    let device_fns_output = fns_output(
        &extension_fns_members("device", &vk_data.extensions),
        "Device",
        "Raw Vulkan device-level functions.\n\nTo use these, you need to include the Ash crate, using the same version Vulkano uses.",
    );
    write_file(
        "fns.rs",
        format!(
            "vk.xml header version {}.{}.{}",
            vk_data.header_version.0, vk_data.header_version.1, vk_data.header_version.2
        ),
        quote! {
            #entry_fns_output
            #instance_fns_output
            #device_fns_output
        },
    );
}

#[derive(Clone, Debug)]
struct FnsMember {
    name: Ident,
    fn_struct: Ident,
}

fn fns_output(extension_members: &[FnsMember], fns_level: &str, doc: &str) -> TokenStream {
    let struct_name = format_ident!("{}Functions", fns_level);
    let members = ["1_0", "1_1", "1_2", "1_3"]
        .into_iter()
        .map(|version| FnsMember {
            name: format_ident!("v{}", version),
            fn_struct: format_ident!("{}FnV{}", fns_level, version),
        })
        .chain(extension_members.iter().cloned())
        .collect::<Vec<_>>();

    let struct_items = members.iter().map(|FnsMember { name, fn_struct }| {
        quote! { pub #name: ash::vk::#fn_struct, }
    });

    let load_items = members.iter().map(|FnsMember { name, fn_struct }| {
        quote! { #name: ash::vk::#fn_struct::load(&mut load_fn), }
    });

    quote! {
        #[doc = #doc]
        #[allow(missing_docs)]
        pub struct #struct_name {
            #(#struct_items)*
            pub _ne: crate::NonExhaustive,
        }

        impl #struct_name {
            pub(crate) fn load<F>(mut load_fn: F) -> #struct_name
                where F: FnMut(&CStr) -> *const c_void
            {
                #struct_name {
                    #(#load_items)*
                    _ne: crate::NonExhaustive(()),
                }
            }
        }

        impl std::fmt::Debug for #struct_name {
            #[inline]
            fn fmt(&self, _f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
                Ok(())
            }
        }
    }
}

fn extension_fns_members(ty: &str, extensions: &IndexMap<&str, &Extension>) -> Vec<FnsMember> {
    extensions
        .values()
        .filter(|ext| ext.ext_type.as_ref().unwrap() == ty)
        // Filter only extensions that have functions
        .filter(|ext| {
            ext.children.iter().any(|ch| {
                if let ExtensionChild::Require { items, .. } = ch {
                    items
                        .iter()
                        .any(|i| matches!(i, InterfaceItem::Command { .. }))
                } else {
                    false
                }
            })
        })
        .map(|ext| {
            let base = ext.name.strip_prefix("VK_").unwrap().to_snake_case();
            let name = format_ident!("{}", base);
            let fn_struct = format_ident!("{}Fn", base.to_upper_camel_case());
            FnsMember { name, fn_struct }
        })
        .collect()
}
<commit_msg>Include device extension functions under instance functions if they use a physical device (#1974)<commit_after>// Copyright (c) 2021 The Vulkano developers
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or
// https://www.apache.org/licenses/LICENSE-2.0> or the MIT
// license <LICENSE-MIT or https://opensource.org/licenses/MIT>,
// at your option. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.

use super::{write_file, VkRegistryData};
use heck::{ToSnakeCase, ToUpperCamelCase};
use indexmap::IndexMap;
use proc_macro2::{Ident, TokenStream};
use quote::{format_ident, quote};
use vk_parse::{Extension, ExtensionChild, InterfaceItem};

pub fn write(vk_data: &VkRegistryData) {
    let entry_fns_output = fns_output(
        &[],
        "Entry",
        "Raw Vulkan global entry point-level functions.\n\nTo use these, you need to include the Ash crate, using the same version Vulkano uses.",
    );
    let instance_fns_output = fns_output(
        &instance_extension_fns_members(&vk_data.extensions),
        "Instance",
        "Raw Vulkan instance-level functions.\n\nTo use these, you need to include the Ash crate, using the same version Vulkano uses.",
    );
    let device_fns_output = fns_output(
        &device_extension_fns_members(&vk_data.extensions),
        "Device",
        "Raw Vulkan device-level functions.\n\nTo use these, you need to include the Ash crate, using the same version Vulkano uses.",
    );
    write_file(
        "fns.rs",
        format!(
            "vk.xml header version {}.{}.{}",
            vk_data.header_version.0, vk_data.header_version.1, vk_data.header_version.2
        ),
        quote! {
            #entry_fns_output
            #instance_fns_output
            #device_fns_output
        },
    );
}

#[derive(Clone, Debug)]
struct FnsMember {
    name: Ident,
    fn_struct: Ident,
}

fn fns_output(extension_members: &[FnsMember], fns_level: &str, doc: &str) -> TokenStream {
    let struct_name = format_ident!("{}Functions", fns_level);
    let members = ["1_0", "1_1", "1_2", "1_3"]
        .into_iter()
        .map(|version| FnsMember {
            name: format_ident!("v{}", version),
            fn_struct: format_ident!("{}FnV{}", fns_level, version),
        })
        .chain(extension_members.iter().cloned())
        .collect::<Vec<_>>();

    let struct_items = members.iter().map(|FnsMember { name, fn_struct }| {
        quote! { pub #name: ash::vk::#fn_struct, }
    });

    let load_items = members.iter().map(|FnsMember { name, fn_struct }| {
        quote! { #name: ash::vk::#fn_struct::load(&mut load_fn), }
    });

    quote! {
        #[doc = #doc]
        #[allow(missing_docs)]
        pub struct #struct_name {
            #(#struct_items)*
            pub _ne: crate::NonExhaustive,
        }

        impl #struct_name {
            pub(crate) fn load<F>(mut load_fn: F) -> #struct_name
                where F: FnMut(&CStr) -> *const c_void
            {
                #struct_name {
                    #(#load_items)*
                    _ne: crate::NonExhaustive(()),
                }
            }
        }

        impl std::fmt::Debug for #struct_name {
            #[inline]
            fn fmt(&self, _f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
                Ok(())
            }
        }
    }
}

fn device_extension_fns_members(extensions: &IndexMap<&str, &Extension>) -> Vec<FnsMember> {
    extensions
        .values()
        // Include any device extensions that have functions.
        .filter(|ext| ext.ext_type.as_ref().unwrap() == "device")
        .filter(|ext| {
            ext.children.iter().any(|ch| {
                if let ExtensionChild::Require { items, .. } = ch {
                    items
                        .iter()
                        .any(|i| matches!(i, InterfaceItem::Command { .. }))
                } else {
                    false
                }
            })
        })
        .map(|ext| {
            let base = ext.name.strip_prefix("VK_").unwrap().to_snake_case();
            let name = format_ident!("{}", base);
            let fn_struct = format_ident!("{}Fn", base.to_upper_camel_case());
            FnsMember { name, fn_struct }
        })
        .collect()
}

fn instance_extension_fns_members(extensions: &IndexMap<&str, &Extension>) -> Vec<FnsMember> {
    extensions
        .values()
        .filter(|ext| {
            match ext.ext_type.as_deref().unwrap() {
                // Include any instance extensions that have functions.
                "instance" => ext.children.iter().any(|ch| {
                    if let ExtensionChild::Require { items, .. } = ch {
                        items
                            .iter()
                            .any(|i| matches!(i, InterfaceItem::Command { .. }))
                    } else {
                        false
                    }
                }),
                // Include device extensions that have functions containing "PhysicalDevice".
                // Note: this test might not be sufficient in the long run...
                "device" => ext.children.iter().any(|ch| {
                    if let ExtensionChild::Require { items, .. } = ch {
                        items
                            .iter()
                            .any(|i| matches!(i, InterfaceItem::Command { name, .. } if name.contains("PhysicalDevice")))
                    } else {
                        false
                    }
                }),
                _ => unreachable!(),
            }
        })
        .map(|ext| {
            let base = ext.name.strip_prefix("VK_").unwrap().to_snake_case();
            let name = format_ident!("{}", base);
            let fn_struct = format_ident!("{}Fn", base.to_upper_camel_case());
            FnsMember { name, fn_struct }
        })
        .collect()
}
<|endoftext|>