<commit_before>#![allow(dead_code)]

use core::fmt;
use core::cell::UnsafeCell;
use core::sync::atomic::AtomicUsize;
use core::sync::atomic::Ordering::{Acquire, Release, AcqRel};

use task::Waker;

/// A synchronization primitive for task wakeup.
///
/// Sometimes the task interested in a given event will change over time.
/// An `AtomicWaker` can coordinate concurrent notifications with the consumer
/// potentially "updating" the underlying task to wake up. This is useful in
/// scenarios where a computation completes in another thread and wants to
/// notify the consumer, but the consumer is in the process of being migrated to
/// a new logical task.
///
/// Consumers should call `register` before checking the result of a computation
/// and producers should call `wake` after producing the computation (this
/// differs from the usual `thread::park` pattern). It is also permitted for
/// `wake` to be called **before** `register`. This results in a no-op.
///
/// A single `AtomicWaker` may be reused for any number of calls to `register` or
/// `wake`.
///
/// `AtomicWaker` does not provide any memory ordering guarantees, as such the
/// user should use caution and use other synchronization primitives to guard
/// the result of the underlying computation.
pub struct AtomicWaker {
    state: AtomicUsize,
    waker: UnsafeCell<Option<Waker>>,
}

/// Initial state, the `AtomicWaker` is currently not being used.
///
/// The value `2` is picked specifically because it between the write lock &
/// read lock values. Since the read lock is represented by an incrementing
/// counter, this enables an atomic fetch_sub operation to be used for releasing
/// a lock.
const WAITING: usize = 2;

/// The `register` function has determined that the task is no longer current.
/// This implies that `AtomicWaker::register` is being called from a different
/// task than is represented by the currently stored task. The write lock is
/// obtained to update the task cell.
const LOCKED_WRITE: usize = 0;

/// At least one call to `wake` happened concurrently to `register` updating
/// the task cell. This state is detected when `register` exits the mutation
/// code and signals to `register` that it is responsible for notifying its own
/// task.
const LOCKED_WRITE_NOTIFIED: usize = 1;

/// The `wake` function has locked access to the task cell for notification.
///
/// The constant is left here mostly for documentation reasons.
#[allow(dead_code)]
const LOCKED_READ: usize = 3;

impl AtomicWaker {
    /// Create an `AtomicWaker` with no initial `Waker`
    pub fn new() -> AtomicWaker {
        // Make sure that task is Sync
        trait AssertSync: Sync {}
        impl AssertSync for Waker {}

        AtomicWaker {
            state: AtomicUsize::new(WAITING),
            waker: UnsafeCell::new(None),
        }
    }

    /// Registers the waker to be notified on calls to `wake`.
    ///
    /// The new task will take place of any previous tasks that were registered
    /// by previous calls to `register`. Any calls to `wake` that happen after
    /// a call to `register` (as defined by the memory ordering rules), will
    /// notify the `register` caller's task and deregister the waker from future
    /// notifications. Because of this, callers should ensure `register` gets
    /// invoked with a new `Waker` **each** time they require a wakeup.
    ///
    /// It is safe to call `register` with multiple other threads concurrently
    /// calling `wake`. This will result in the `register` caller's current
    /// task being notified once.
    ///
    /// This function is safe to call concurrently, but this is generally a bad
    /// idea. Concurrent calls to `register` will attempt to register different
    /// tasks to be notified. One of the callers will win and have its task set,
    /// but there is no guarantee as to which caller will succeed.
    ///
    /// # Examples
    ///
    /// Here is how `register` is used when implementing a flag.
    ///
    /// ```
    /// # use futures_core::{Future, Poll, Never};
    /// # use futures_core::Async::*;
    /// # use futures_core::task::{self, AtomicWaker};
    /// # use std::sync::atomic::AtomicBool;
    /// # use std::sync::atomic::Ordering::SeqCst;
    /// struct Flag {
    ///     waker: AtomicWaker,
    ///     set: AtomicBool,
    /// }
    ///
    /// impl Future for Flag {
    ///     type Item = ();
    ///     type Error = Never;
    ///
    ///     fn poll(&mut self, cx: &mut task::Context) -> Poll<(), Never> {
    ///         self.waker.register(cx.waker());
    ///
    ///         if self.set.load(SeqCst) {
    ///             Ok(Ready(()))
    ///         } else {
    ///             Ok(Pending)
    ///         }
    ///     }
    /// }
    /// ```
    pub fn register(&self, waker: &Waker) {
        match self.state.compare_and_swap(WAITING, LOCKED_WRITE, Acquire) {
            WAITING => {
                unsafe {
                    // Locked acquired, update the waker cell
                    *self.waker.get() = Some(waker.clone());

                    // Release the lock. If the state transitioned to
                    // `LOCKED_NOTIFIED`, this means that an notify has been
                    // signaled, so notify the task.
                    //
                    // Start by assuming that the state is LOCKED_WRITE as this
                    // is what we jut set it to.
                    let mut curr = LOCKED_WRITE;

                    loop {
                        let res = self.state.compare_exchange(
                            curr, WAITING, AcqRel, Acquire);

                        match res {
                            Ok(_) => return,
                            Err(actual) => {
                                // Update `curr` for the next iteration of the
                                // loop
                                curr = actual;
                            }
                        }

                        // Since we aren't using the weak variant of the atomic
                        // operation, the only possible option for `curr` is
                        // `LOCKED_WRITE_NOTIFIED`.
                        assert_eq!(curr, LOCKED_WRITE_NOTIFIED);

                        if let Some(waker) = (*self.waker.get()).take() {
                            waker.wake();
                        }
                    }
                }
            }
            LOCKED_WRITE | LOCKED_WRITE_NOTIFIED => {
                // A thread is concurrently calling `register`. This shouldn't
                // happen as it doesn't really make much sense, but it isn't
                // unsafe per se. Since two threads are concurrently trying to
                // update the task, it's undefined which one "wins" (no ordering
                // guarantees), so we can just do nothing.
            }
            state => {
                debug_assert!(state != LOCKED_WRITE, "unexpected state LOCKED_WRITE");
                debug_assert!(state != LOCKED_WRITE_NOTIFIED, "unexpected state LOCKED_WRITE_NOTIFIED");

                // Currently in a read locked state, this implies that `wake`
                // is currently being called on the old task handle. So, we call
                // `wake` on the new task handle
                waker.wake();
            }
        }
    }

    /// Calls `wake` on the last `Waker` passed to `register`.
    ///
    /// If `register` has not been called yet, then this does nothing.
    pub fn wake(&self) {
        let mut curr = WAITING;

        loop {
            if curr == LOCKED_WRITE {
                // Transition the state to LOCKED_NOTIFIED
                let actual = self.state.compare_and_swap(LOCKED_WRITE, LOCKED_WRITE_NOTIFIED, Release);

                if curr == actual {
                    // Success, return
                    return;
                }

                // update current state variable and try again
                curr = actual;

            } else if curr == LOCKED_WRITE_NOTIFIED {
                // Currently in `LOCKED_WRITE_NOTIFIED` state, nothing else to do.
                return;

            } else {
                // Currently in a LOCKED_READ state, so attempt to increment the
                // lock count.
                let actual = self.state.compare_and_swap(curr, curr + 1, Acquire);

                // Locked acquired
                if actual == curr {
                    // Notify the task
                    unsafe {
                        if let Some(waker) = (*self.waker.get()).take() {
                            waker.wake();
                        }
                    }

                    // Release the lock
                    self.state.fetch_sub(1, Release);

                    // Done
                    return;
                }

                // update current state variable and try again
                curr = actual;

            }
        }
    }
}

impl Default for AtomicWaker {
    fn default() -> Self {
        AtomicWaker::new()
    }
}

impl fmt::Debug for AtomicWaker {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        write!(fmt, "AtomicWaker")
    }
}

unsafe impl Send for AtomicWaker {}
unsafe impl Sync for AtomicWaker {}
<commit_msg>Add comment<commit_after>#![allow(dead_code)]

use core::fmt;
use core::cell::UnsafeCell;
use core::sync::atomic::AtomicUsize;
use core::sync::atomic::Ordering::{Acquire, Release, AcqRel};

use task::Waker;

/// A synchronization primitive for task wakeup.
///
/// Sometimes the task interested in a given event will change over time.
/// An `AtomicWaker` can coordinate concurrent notifications with the consumer
/// potentially "updating" the underlying task to wake up. This is useful in
/// scenarios where a computation completes in another thread and wants to
/// notify the consumer, but the consumer is in the process of being migrated to
/// a new logical task.
///
/// Consumers should call `register` before checking the result of a computation
/// and producers should call `wake` after producing the computation (this
/// differs from the usual `thread::park` pattern). It is also permitted for
/// `wake` to be called **before** `register`. This results in a no-op.
///
/// A single `AtomicWaker` may be reused for any number of calls to `register` or
/// `wake`.
///
/// `AtomicWaker` does not provide any memory ordering guarantees, as such the
/// user should use caution and use other synchronization primitives to guard
/// the result of the underlying computation.
pub struct AtomicWaker {
    state: AtomicUsize,
    waker: UnsafeCell<Option<Waker>>,
}

/// Initial state, the `AtomicWaker` is currently not being used.
///
/// The value `2` is picked specifically because it between the write lock &
/// read lock values. Since the read lock is represented by an incrementing
/// counter, this enables an atomic fetch_sub operation to be used for releasing
/// a lock.
const WAITING: usize = 2;

/// The `register` function has determined that the task is no longer current.
/// This implies that `AtomicWaker::register` is being called from a different
/// task than is represented by the currently stored task. The write lock is
/// obtained to update the task cell.
const LOCKED_WRITE: usize = 0;

/// At least one call to `wake` happened concurrently to `register` updating
/// the task cell. This state is detected when `register` exits the mutation
/// code and signals to `register` that it is responsible for notifying its own
/// task.
const LOCKED_WRITE_NOTIFIED: usize = 1;

/// The `wake` function has locked access to the task cell for notification.
///
/// The constant is left here mostly for documentation reasons.
#[allow(dead_code)]
const LOCKED_READ: usize = 3;

impl AtomicWaker {
    /// Create an `AtomicWaker` with no initial `Waker`
    pub fn new() -> AtomicWaker {
        // Make sure that task is Sync
        trait AssertSync: Sync {}
        impl AssertSync for Waker {}

        AtomicWaker {
            state: AtomicUsize::new(WAITING),
            waker: UnsafeCell::new(None),
        }
    }

    /// Registers the waker to be notified on calls to `wake`.
    ///
    /// The new task will take place of any previous tasks that were registered
    /// by previous calls to `register`. Any calls to `wake` that happen after
    /// a call to `register` (as defined by the memory ordering rules), will
    /// notify the `register` caller's task and deregister the waker from future
    /// notifications. Because of this, callers should ensure `register` gets
    /// invoked with a new `Waker` **each** time they require a wakeup.
    ///
    /// It is safe to call `register` with multiple other threads concurrently
    /// calling `wake`. This will result in the `register` caller's current
    /// task being notified once.
    ///
    /// This function is safe to call concurrently, but this is generally a bad
    /// idea. Concurrent calls to `register` will attempt to register different
    /// tasks to be notified. One of the callers will win and have its task set,
    /// but there is no guarantee as to which caller will succeed.
    ///
    /// # Examples
    ///
    /// Here is how `register` is used when implementing a flag.
    ///
    /// ```
    /// # use futures_core::{Future, Poll, Never};
    /// # use futures_core::Async::*;
    /// # use futures_core::task::{self, AtomicWaker};
    /// # use std::sync::atomic::AtomicBool;
    /// # use std::sync::atomic::Ordering::SeqCst;
    /// struct Flag {
    ///     waker: AtomicWaker,
    ///     set: AtomicBool,
    /// }
    ///
    /// impl Future for Flag {
    ///     type Item = ();
    ///     type Error = Never;
    ///
    ///     fn poll(&mut self, cx: &mut task::Context) -> Poll<(), Never> {
    ///         // Register **before** checkin `set` to avoid a race condition
    ///         // that would result in lost notifications.
    ///         self.waker.register(cx.waker());
    ///
    ///         if self.set.load(SeqCst) {
    ///             Ok(Ready(()))
    ///         } else {
    ///             Ok(Pending)
    ///         }
    ///     }
    /// }
    /// ```
    pub fn register(&self, waker: &Waker) {
        match self.state.compare_and_swap(WAITING, LOCKED_WRITE, Acquire) {
            WAITING => {
                unsafe {
                    // Locked acquired, update the waker cell
                    *self.waker.get() = Some(waker.clone());

                    // Release the lock. If the state transitioned to
                    // `LOCKED_NOTIFIED`, this means that an notify has been
                    // signaled, so notify the task.
                    //
                    // Start by assuming that the state is LOCKED_WRITE as this
                    // is what we jut set it to.
                    let mut curr = LOCKED_WRITE;

                    loop {
                        let res = self.state.compare_exchange(
                            curr, WAITING, AcqRel, Acquire);

                        match res {
                            Ok(_) => return,
                            Err(actual) => {
                                // Update `curr` for the next iteration of the
                                // loop
                                curr = actual;
                            }
                        }

                        // Since we aren't using the weak variant of the atomic
                        // operation, the only possible option for `curr` is
                        // `LOCKED_WRITE_NOTIFIED`.
                        assert_eq!(curr, LOCKED_WRITE_NOTIFIED);

                        if let Some(waker) = (*self.waker.get()).take() {
                            waker.wake();
                        }
                    }
                }
            }
            LOCKED_WRITE | LOCKED_WRITE_NOTIFIED => {
                // A thread is concurrently calling `register`. This shouldn't
                // happen as it doesn't really make much sense, but it isn't
                // unsafe per se. Since two threads are concurrently trying to
                // update the task, it's undefined which one "wins" (no ordering
                // guarantees), so we can just do nothing.
            }
            state => {
                debug_assert!(state != LOCKED_WRITE, "unexpected state LOCKED_WRITE");
                debug_assert!(state != LOCKED_WRITE_NOTIFIED, "unexpected state LOCKED_WRITE_NOTIFIED");

                // Currently in a read locked state, this implies that `wake`
                // is currently being called on the old task handle. So, we call
                // `wake` on the new task handle
                waker.wake();
            }
        }
    }

    /// Calls `wake` on the last `Waker` passed to `register`.
    ///
    /// If `register` has not been called yet, then this does nothing.
    pub fn wake(&self) {
        let mut curr = WAITING;

        loop {
            if curr == LOCKED_WRITE {
                // Transition the state to LOCKED_NOTIFIED
                let actual = self.state.compare_and_swap(LOCKED_WRITE, LOCKED_WRITE_NOTIFIED, Release);

                if curr == actual {
                    // Success, return
                    return;
                }

                // update current state variable and try again
                curr = actual;

            } else if curr == LOCKED_WRITE_NOTIFIED {
                // Currently in `LOCKED_WRITE_NOTIFIED` state, nothing else to do.
                return;

            } else {
                // Currently in a LOCKED_READ state, so attempt to increment the
                // lock count.
                let actual = self.state.compare_and_swap(curr, curr + 1, Acquire);

                // Locked acquired
                if actual == curr {
                    // Notify the task
                    unsafe {
                        if let Some(waker) = (*self.waker.get()).take() {
                            waker.wake();
                        }
                    }

                    // Release the lock
                    self.state.fetch_sub(1, Release);

                    // Done
                    return;
                }

                // update current state variable and try again
                curr = actual;

            }
        }
    }
}

impl Default for AtomicWaker {
    fn default() -> Self {
        AtomicWaker::new()
    }
}

impl fmt::Debug for AtomicWaker {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        write!(fmt, "AtomicWaker")
    }
}

unsafe impl Send for AtomicWaker {}
unsafe impl Sync for AtomicWaker {}
<|endoftext|>


<commit_before>// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! A wrapper around any Reader to treat it as an RNG.

use collections::Collection;
use io::Reader;
use rand::Rng;
use result::{Ok, Err};

/// An RNG that reads random bytes straight from a `Reader`. This will
/// work best with an infinite reader, but this is not required.
///
/// It will fail if it there is insufficient data to fulfill a request.
///
/// # Example
///
/// ```rust
/// use std::rand::{reader, Rng};
/// use std::io::MemReader;
///
/// let mut rng = reader::ReaderRng::new(MemReader::new(vec!(1,2,3,4,5,6,7,8)));
/// println!("{:x}", rng.gen::<uint>());
/// ```
pub struct ReaderRng<R> {
    reader: R
}

impl<R: Reader> ReaderRng<R> {
    /// Create a new `ReaderRng` from a `Reader`.
    pub fn new(r: R) -> ReaderRng<R> {
        ReaderRng {
            reader: r
        }
    }
}

impl<R: Reader> Rng for ReaderRng<R> {
    fn next_u32(&mut self) -> u32 {
        // This is designed for speed: reading a LE integer on a LE
        // platform just involves blitting the bytes into the memory
        // of the u32, similarly for BE on BE; avoiding byteswapping.
        if cfg!(target_endian="little") {
            self.reader.read_le_u32().unwrap()
        } else {
            self.reader.read_be_u32().unwrap()
        }
    }
    fn next_u64(&mut self) -> u64 {
        // see above for explanation.
        if cfg!(target_endian="little") {
            self.reader.read_le_u64().unwrap()
        } else {
            self.reader.read_be_u64().unwrap()
        }
    }
    fn fill_bytes(&mut self, v: &mut [u8]) {
        if v.len() == 0 { return }
        match self.reader.read_at_least(v.len(), v) {
            Ok(_) => {}
            Err(e) => fail!("ReaderRng.fill_bytes error: {}", e)
        }
    }
}

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

    use super::ReaderRng;
    use io::MemReader;
    use mem;
    use rand::Rng;

    #[test]
    fn test_reader_rng_u64() {
        // transmute from the target to avoid endianness concerns.
        let v = vec![0u8, 0, 0, 0, 0, 0, 0, 1,
                     0  , 0, 0, 0, 0, 0, 0, 2,
                     0,   0, 0, 0, 0, 0, 0, 3];
        let mut rng = ReaderRng::new(MemReader::new(v));

        assert_eq!(rng.next_u64(), mem::to_be64(1));
        assert_eq!(rng.next_u64(), mem::to_be64(2));
        assert_eq!(rng.next_u64(), mem::to_be64(3));
    }
    #[test]
    fn test_reader_rng_u32() {
        let v = vec![0u8, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 3];
        let mut rng = ReaderRng::new(MemReader::new(v));

        assert_eq!(rng.next_u32(), mem::to_be32(1));
        assert_eq!(rng.next_u32(), mem::to_be32(2));
        assert_eq!(rng.next_u32(), mem::to_be32(3));
    }
    #[test]
    fn test_reader_rng_fill_bytes() {
        let v = [1u8, 2, 3, 4, 5, 6, 7, 8];
        let mut w = [0u8, .. 8];

        let mut rng = ReaderRng::new(MemReader::new(Vec::from_slice(v)));
        rng.fill_bytes(w);

        assert!(v == w);
    }

    #[test]
    #[should_fail]
    fn test_reader_rng_insufficient_bytes() {
        let mut rng = ReaderRng::new(MemReader::new(vec!()));
        let mut v = [0u8, .. 3];
        rng.fill_bytes(v);
    }
}
<commit_msg>Clean up rustc warnings.<commit_after>// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! A wrapper around any Reader to treat it as an RNG.

use collections::Collection;
use io::Reader;
use rand::Rng;
use result::{Ok, Err};

/// An RNG that reads random bytes straight from a `Reader`. This will
/// work best with an infinite reader, but this is not required.
///
/// It will fail if it there is insufficient data to fulfill a request.
///
/// # Example
///
/// ```rust
/// use std::rand::{reader, Rng};
/// use std::io::MemReader;
///
/// let mut rng = reader::ReaderRng::new(MemReader::new(vec!(1,2,3,4,5,6,7,8)));
/// println!("{:x}", rng.gen::<uint>());
/// ```
pub struct ReaderRng<R> {
    reader: R
}

impl<R: Reader> ReaderRng<R> {
    /// Create a new `ReaderRng` from a `Reader`.
    pub fn new(r: R) -> ReaderRng<R> {
        ReaderRng {
            reader: r
        }
    }
}

impl<R: Reader> Rng for ReaderRng<R> {
    fn next_u32(&mut self) -> u32 {
        // This is designed for speed: reading a LE integer on a LE
        // platform just involves blitting the bytes into the memory
        // of the u32, similarly for BE on BE; avoiding byteswapping.
        if cfg!(target_endian="little") {
            self.reader.read_le_u32().unwrap()
        } else {
            self.reader.read_be_u32().unwrap()
        }
    }
    fn next_u64(&mut self) -> u64 {
        // see above for explanation.
        if cfg!(target_endian="little") {
            self.reader.read_le_u64().unwrap()
        } else {
            self.reader.read_be_u64().unwrap()
        }
    }
    fn fill_bytes(&mut self, v: &mut [u8]) {
        if v.len() == 0 { return }
        match self.reader.read_at_least(v.len(), v) {
            Ok(_) => {}
            Err(e) => fail!("ReaderRng.fill_bytes error: {}", e)
        }
    }
}

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

    use super::ReaderRng;
    use io::MemReader;
    use rand::Rng;

    #[test]
    fn test_reader_rng_u64() {
        // transmute from the target to avoid endianness concerns.
        let v = vec![0u8, 0, 0, 0, 0, 0, 0, 1,
                     0  , 0, 0, 0, 0, 0, 0, 2,
                     0,   0, 0, 0, 0, 0, 0, 3];
        let mut rng = ReaderRng::new(MemReader::new(v));

        assert_eq!(rng.next_u64(), 1_u64.to_be());
        assert_eq!(rng.next_u64(), 2_u64.to_be());
        assert_eq!(rng.next_u64(), 3_u64.to_be());
    }
    #[test]
    fn test_reader_rng_u32() {
        let v = vec![0u8, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 3];
        let mut rng = ReaderRng::new(MemReader::new(v));

        assert_eq!(rng.next_u32(), 1_u32.to_be());
        assert_eq!(rng.next_u32(), 2_u32.to_be());
        assert_eq!(rng.next_u32(), 3_u32.to_be());
    }
    #[test]
    fn test_reader_rng_fill_bytes() {
        let v = [1u8, 2, 3, 4, 5, 6, 7, 8];
        let mut w = [0u8, .. 8];

        let mut rng = ReaderRng::new(MemReader::new(v.as_slice().to_vec()));
        rng.fill_bytes(w);

        assert!(v == w);
    }

    #[test]
    #[should_fail]
    fn test_reader_rng_insufficient_bytes() {
        let mut rng = ReaderRng::new(MemReader::new(vec!()));
        let mut v = [0u8, .. 3];
        rng.fill_bytes(v);
    }
}
<|endoftext|>


<commit_before>
use chrono::{DateTime, UTC, TimeZone};

/// Represents provisioning profile data.
#[derive(Debug)]
pub struct Profile {
    pub uuid: String,
    pub name: String,
    pub app_identifier: String,
    pub creation_date: DateTime<UTC>,
    pub expiration_date: DateTime<UTC>,
}

impl Profile {
    pub fn empty() -> Self {
        Profile {
            uuid: "".into(),
            name: "".into(),
            app_identifier: "".into(),
            creation_date: UTC.timestamp(0, 0),
            expiration_date: UTC.timestamp(0, 0),
        }
    }

    /// Returns `true` if one or more fields of the profile contain `string`.
    pub fn contains(&self, string: &str) -> bool {
        let s = string.to_lowercase();
        let items = &[&self.name, &self.app_identifier, &self.uuid];
        for item in items {
            if item.to_lowercase().contains(&s) {
                return true;
            }
        }
        false
    }

    /// Returns profile in a text form.
    pub fn description(&self) -> String {
        let mut desc = String::new();
        desc.push_str(&self.uuid);
        desc.push_str("\n");
        desc.push_str(&self.app_identifier);
        desc.push_str("\n");
        desc.push_str(&self.name);
        desc.push_str("\n");
        desc.push_str(&format!("{} - {}", self.creation_date, self.expiration_date));
        desc
    }
}

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

    #[test]
    fn contains() {
        let profile = Profile {
            uuid: "123".into(),
            name: "name".into(),
            app_identifier: "id".into(),
        };
        expect!(profile.contains("12")).to(be_true());
        expect!(profile.contains("me")).to(be_true());
        expect!(profile.contains("id")).to(be_true());
    }
}
<commit_msg>Update tests.<commit_after>
use chrono::{DateTime, UTC, TimeZone};

/// Represents provisioning profile data.
#[derive(Debug)]
pub struct Profile {
    pub uuid: String,
    pub name: String,
    pub app_identifier: String,
    pub creation_date: DateTime<UTC>,
    pub expiration_date: DateTime<UTC>,
}

impl Profile {
    pub fn empty() -> Self {
        Profile {
            uuid: "".into(),
            name: "".into(),
            app_identifier: "".into(),
            creation_date: UTC.timestamp(0, 0),
            expiration_date: UTC.timestamp(0, 0),
        }
    }

    /// Returns `true` if one or more fields of the profile contain `string`.
    pub fn contains(&self, string: &str) -> bool {
        let s = string.to_lowercase();
        let items = &[&self.name, &self.app_identifier, &self.uuid];
        for item in items {
            if item.to_lowercase().contains(&s) {
                return true;
            }
        }
        false
    }

    /// Returns profile in a text form.
    pub fn description(&self) -> String {
        let mut desc = String::new();
        desc.push_str(&self.uuid);
        desc.push_str("\n");
        desc.push_str(&self.app_identifier);
        desc.push_str("\n");
        desc.push_str(&self.name);
        desc.push_str("\n");
        desc.push_str(&format!("{} - {}", self.creation_date, self.expiration_date));
        desc
    }
}

#[cfg(test)]
mod tests {
    use expectest::prelude::*;
    use chrono::{UTC, TimeZone};
    use super::*;

    #[test]
    fn contains() {
        let profile = Profile {
            uuid: "123".into(),
            name: "name".into(),
            app_identifier: "id".into(),
            creation_date: UTC.timestamp(0, 0),
            expiration_date: UTC.timestamp(0, 0),
        };
        expect!(profile.contains("12")).to(be_true());
        expect!(profile.contains("me")).to(be_true());
        expect!(profile.contains("id")).to(be_true());
    }
}
<|endoftext|>


<commit_before>use codespan::{ByteIndex, Files, LineIndex, Location, Span};
use std::io;
use termcolor::{Color, ColorSpec, WriteColor};

use crate::{Diagnostic, Label, Severity};

/// Configures how a diagnostic is rendered.
#[derive(Clone, Debug)]
pub struct Config {
    /// The color to use when rendering bugs. Defaults to `Color::Red`.
    pub bug_color: Color,
    /// The color to use when rendering errors. Defaults to `Color::Red`.
    pub error_color: Color,
    /// The color to use when rendering warnings. Defaults to `Color::Yellow`.
    pub warning_color: Color,
    /// The color to use when rendering notes. Defaults to `Color::Green`.
    pub note_color: Color,
    /// The color to use when rendering helps. Defaults to `Color::Cyan`.
    pub help_color: Color,
    /// The color to use when rendering secondary labels. Defaults to
    /// `Color::Blue` (or `Color::Cyan` on windows).
    pub secondary_color: Color,
    /// The color to use when rendering gutters. Defaults to `Color::Blue`
    /// (or `Color::Cyan` on windows).
    pub gutter_color: Color,
    /// The character to use when underlining a primary label. Defaults to: `^`.
    pub primary_mark: char,
    /// The character to use when underlining a secondary label. Defaults to: `-`.
    pub secondary_mark: char,
}

impl Default for Config {
    fn default() -> Config {
        // Blue is really difficult to see on the standard windows command line
        #[cfg(windows)]
        const BLUE: Color = Color::Cyan;
        #[cfg(not(windows))]
        const BLUE: Color = Color::Blue;

        Config {
            bug_color: Color::Red,
            error_color: Color::Red,
            warning_color: Color::Yellow,
            note_color: Color::Green,
            help_color: Color::Cyan,
            secondary_color: BLUE,
            gutter_color: BLUE,
            primary_mark: '^',
            secondary_mark: '-',
        }
    }
}

impl Config {
    /// The color used to mark a given severity.
    pub fn severity_color(&self, severity: Severity) -> Color {
        match severity {
            Severity::Bug => self.bug_color,
            Severity::Error => self.error_color,
            Severity::Warning => self.warning_color,
            Severity::Note => self.note_color,
            Severity::Help => self.help_color,
        }
    }
}

pub fn emit(
    mut writer: impl WriteColor,
    config: &Config,
    files: &Files,
    diagnostic: &Diagnostic,
) -> io::Result<()> {
    Header::new(diagnostic).emit(&mut writer, config)?;

    MarkedSource::new_primary(files, &diagnostic).emit(&mut writer, config)?;

    for label in &diagnostic.secondary_labels {
        MarkedSource::new_secondary(files, &label).emit(&mut writer, config)?;
    }

    Ok(())
}

/// Diagnostic header
///
/// ```text
/// error[E0001]: Unexpected type in `+` application
/// ```
#[derive(Copy, Clone, Debug)]
struct Header<'a> {
    severity: Severity,
    code: Option<&'a str>,
    message: &'a str,
}

impl<'a> Header<'a> {
    fn new(diagnostic: &'a Diagnostic) -> Header<'a> {
        Header {
            severity: diagnostic.severity,
            code: diagnostic.code.as_ref().map(String::as_str),
            message: &diagnostic.message,
        }
    }

    fn severity_name(&self) -> &'static str {
        match self.severity {
            Severity::Bug => "bug",
            Severity::Error => "error",
            Severity::Warning => "warning",
            Severity::Help => "help",
            Severity::Note => "note",
        }
    }

    fn emit(&self, writer: &mut impl WriteColor, config: &Config) -> io::Result<()> {
        let message_spec = ColorSpec::new().set_bold(true).set_intense(true).clone();
        let primary_spec = ColorSpec::new()
            .set_bold(true)
            .set_intense(true)
            .set_fg(Some(config.severity_color(self.severity)))
            .clone();

        // Write severity name
        //
        // ```
        // error
        // ```
        writer.set_color(&primary_spec)?;
        write!(writer, "{}", self.severity_name())?;
        if let Some(code) = &self.code {
            // Write error code
            //
            // ```
            // [E0001]
            // ```
            write!(writer, "[{}]", code)?;
        }

        // Write diagnostic message
        //
        // ```
        // : Unexpected type in `+` application
        // ```
        writer.set_color(&message_spec)?;
        write!(writer, ": {}", self.message)?;
        write!(writer, "\n")?;
        writer.reset()?;

        Ok(())
    }
}

enum MarkStyle {
    Primary(Severity),
    Secondary,
}

/// A marked section of source code
///
/// ```text
///   ┌╴ test:2:9
///   │
/// 2 │ (+ test "")
///   │         ^^ expected `Int` but found `String`
///   ╵
/// ```
struct MarkedSource<'a> {
    files: &'a Files,
    label: &'a Label,
    mark_style: MarkStyle,
}

impl<'a> MarkedSource<'a> {
    fn new_primary(files: &'a Files, diagnostic: &'a Diagnostic) -> MarkedSource<'a> {
        MarkedSource {
            files,
            label: &diagnostic.primary_label,
            mark_style: MarkStyle::Primary(diagnostic.severity),
        }
    }

    fn new_secondary(files: &'a Files, label: &'a Label) -> MarkedSource<'a> {
        MarkedSource {
            files,
            label,
            mark_style: MarkStyle::Secondary,
        }
    }

    fn span(&self) -> Span {
        self.label.span
    }

    fn start(&self) -> ByteIndex {
        self.span().start()
    }

    fn end(&self) -> ByteIndex {
        self.span().end()
    }

    fn file_name(&self) -> &'a str {
        self.files.name(self.label.file_id)
    }

    fn location(&self, byte_index: ByteIndex) -> Result<Location, impl std::error::Error> {
        self.files.location(self.label.file_id, byte_index)
    }

    fn source_slice(&self, span: Span) -> Result<&'a str, impl std::error::Error> {
        self.files.source_slice(self.label.file_id, span)
    }

    fn line_span(&self, line_index: LineIndex) -> Result<Span, impl std::error::Error> {
        self.files.line_span(self.label.file_id, line_index)
    }

    fn label_color(&self, config: &Config) -> Color {
        match self.mark_style {
            MarkStyle::Primary(severity) => config.severity_color(severity),
            MarkStyle::Secondary => config.secondary_color,
        }
    }

    fn underline_char(&self, config: &Config) -> char {
        match self.mark_style {
            MarkStyle::Primary(_) => config.primary_mark,
            MarkStyle::Secondary => config.secondary_mark,
        }
    }

    fn emit(&self, writer: &mut impl WriteColor, config: &Config) -> io::Result<()> {
        let gutter_spec = ColorSpec::new().set_fg(Some(config.gutter_color)).clone();
        let label_spec = ColorSpec::new()
            .set_fg(Some(self.label_color(config)))
            .clone();

        let start = self.location(self.start()).expect("location_start");
        let end = self.location(self.end()).expect("location_end");
        let start_line_span = self.line_span(start.line).expect("line_span");
        let end_line_span = self.line_span(end.line).expect("line_span");

        // Use the length of the last line number as the gutter padding
        let gutter_padding = format!("{}", end.line.number()).len();

        // File name
        //
        // ```
        // ┌╴ test:2:9
        // ```

        // Write gutter
        writer.set_color(&gutter_spec)?;
        write!(writer, "{: >width$} ┌╴ ", "", width = gutter_padding)?;
        writer.reset()?;

        // Write file name
        write!(
            writer,
            "{file}:{line}:{column}",
            file = self.file_name(),
            line = start.line.number(),
            column = start.column.number(),
        )?;
        write!(writer, "\n")?;

        // Source code snippet
        //
        // ```
        //   │
        // 2 │ (+ test "")
        //   │         ^^ expected `Int` but found `String`
        //   ╵
        // ```

        // Write line number and gutter
        writer.set_color(&gutter_spec)?;
        write!(writer, "{: >width$} │ ", "", width = gutter_padding)?;
        write!(writer, "\n")?;
        write!(
            writer,
            "{: >width$} │ ",
            start.line.number(),
            width = gutter_padding,
        )?;
        writer.reset()?;

        let line_trimmer = |ch: char| ch == '\r' || ch == '\n';

        // Write source prefix before marked section
        let prefix_span = start_line_span.with_end(self.start());
        let source_prefix = self.source_slice(prefix_span).expect("prefix");
        write!(writer, "{}", source_prefix)?;

        // Write marked section
        let mark_len = if start.line == end.line {
            // Single line

            // Write marked source section
            let marked_source = self.source_slice(self.span()).expect("marked_source");
            writer.set_color(&label_spec)?;
            write!(writer, "{}", marked_source)?;
            writer.reset()?;
            marked_source.len()
        } else {
            // Multiple lines

            // Write marked source section
            let marked_span = start_line_span.with_start(self.start());
            let marked_source = self.source_slice(marked_span).expect("start_of_marked");
            writer.set_color(&label_spec)?;
            write!(writer, "{}", marked_source)?;

            for line_index in ((start.line.to_usize() + 1)..end.line.to_usize())
                .map(|i| LineIndex::from(i as u32))
            {
                // Write line number and gutter
                writer.set_color(&gutter_spec)?;
                write!(
                    writer,
                    "{: >width$} │ ",
                    line_index.number(),
                    width = gutter_padding,
                )?;

                // Write marked source section
                let mark_span = self.line_span(line_index).expect("marked_line_span");
                let marked_source = self.source_slice(mark_span).expect("marked_source");
                writer.set_color(&label_spec)?;
                write!(writer, "{}", marked_source.trim_end_matches(line_trimmer))?;
                write!(writer, "\n")?;
            }

            // Write line number and gutter
            writer.set_color(&gutter_spec)?;
            write!(
                writer,
                "{: >width$} │ ",
                end.line.number(),
                width = gutter_padding,
            )?;

            // Write marked source section
            let mark_span = end_line_span.with_end(self.end());
            let marked_source = self.source_slice(mark_span).expect("marked_source");
            writer.set_color(&label_spec)?;
            write!(writer, "{}", marked_source)?;
            writer.reset()?;
            marked_source.len()
        };

        // Write source suffix after marked section
        let suffix_span = end_line_span.with_start(self.end());
        let source_suffix = self.source_slice(suffix_span).expect("suffix");
        write!(writer, "{}", source_suffix.trim_end_matches(line_trimmer))?;
        write!(writer, "\n")?;

        // Write underline gutter
        writer.set_color(&gutter_spec)?;
        write!(writer, "{: >width$} │ ", "", width = gutter_padding)?;
        writer.reset()?;

        // Write underline and label
        writer.set_color(&label_spec)?;
        write!(writer, "{: >width$}", "", width = source_prefix.len())?;
        for _ in 0..mark_len {
            write!(writer, "{}", self.underline_char(config))?;
        }
        if !self.label.message.is_empty() {
            write!(writer, " {}", self.label.message)?;
            write!(writer, "\n")?;
        }
        writer.reset()?;

        // Write final gutter
        writer.set_color(&gutter_spec)?;
        write!(writer, "{: >width$} ╵", "", width = gutter_padding)?;
        write!(writer, "\n")?;
        writer.reset()?;

        Ok(())
    }
}
<commit_msg>Add source locus component<commit_after>use codespan::{ByteIndex, Files, LineIndex, Location, Span};
use std::io;
use termcolor::{Color, ColorSpec, WriteColor};

use crate::{Diagnostic, Label, Severity};

/// Configures how a diagnostic is rendered.
#[derive(Clone, Debug)]
pub struct Config {
    /// The color to use when rendering bugs. Defaults to `Color::Red`.
    pub bug_color: Color,
    /// The color to use when rendering errors. Defaults to `Color::Red`.
    pub error_color: Color,
    /// The color to use when rendering warnings. Defaults to `Color::Yellow`.
    pub warning_color: Color,
    /// The color to use when rendering notes. Defaults to `Color::Green`.
    pub note_color: Color,
    /// The color to use when rendering helps. Defaults to `Color::Cyan`.
    pub help_color: Color,
    /// The color to use when rendering secondary labels. Defaults to
    /// `Color::Blue` (or `Color::Cyan` on windows).
    pub secondary_color: Color,
    /// The color to use when rendering gutters. Defaults to `Color::Blue`
    /// (or `Color::Cyan` on windows).
    pub gutter_color: Color,
    /// The character to use when underlining a primary label. Defaults to: `^`.
    pub primary_mark: char,
    /// The character to use when underlining a secondary label. Defaults to: `-`.
    pub secondary_mark: char,
}

impl Default for Config {
    fn default() -> Config {
        // Blue is really difficult to see on the standard windows command line
        #[cfg(windows)]
        const BLUE: Color = Color::Cyan;
        #[cfg(not(windows))]
        const BLUE: Color = Color::Blue;

        Config {
            bug_color: Color::Red,
            error_color: Color::Red,
            warning_color: Color::Yellow,
            note_color: Color::Green,
            help_color: Color::Cyan,
            secondary_color: BLUE,
            gutter_color: BLUE,
            primary_mark: '^',
            secondary_mark: '-',
        }
    }
}

impl Config {
    /// The color used to mark a given severity.
    pub fn severity_color(&self, severity: Severity) -> Color {
        match severity {
            Severity::Bug => self.bug_color,
            Severity::Error => self.error_color,
            Severity::Warning => self.warning_color,
            Severity::Note => self.note_color,
            Severity::Help => self.help_color,
        }
    }
}

pub fn emit(
    mut writer: impl WriteColor,
    config: &Config,
    files: &Files,
    diagnostic: &Diagnostic,
) -> io::Result<()> {
    Header::new(diagnostic).emit(&mut writer, config)?;

    MarkedSource::new_primary(files, &diagnostic).emit(&mut writer, config)?;

    for label in &diagnostic.secondary_labels {
        MarkedSource::new_secondary(files, &label).emit(&mut writer, config)?;
    }

    Ok(())
}

/// Diagnostic header
///
/// ```text
/// error[E0001]: Unexpected type in `+` application
/// ```
#[derive(Copy, Clone, Debug)]
struct Header<'a> {
    severity: Severity,
    code: Option<&'a str>,
    message: &'a str,
}

impl<'a> Header<'a> {
    fn new(diagnostic: &'a Diagnostic) -> Header<'a> {
        Header {
            severity: diagnostic.severity,
            code: diagnostic.code.as_ref().map(String::as_str),
            message: &diagnostic.message,
        }
    }

    fn severity_name(&self) -> &'static str {
        match self.severity {
            Severity::Bug => "bug",
            Severity::Error => "error",
            Severity::Warning => "warning",
            Severity::Help => "help",
            Severity::Note => "note",
        }
    }

    fn emit(&self, writer: &mut impl WriteColor, config: &Config) -> io::Result<()> {
        let message_spec = ColorSpec::new().set_bold(true).set_intense(true).clone();
        let primary_spec = ColorSpec::new()
            .set_bold(true)
            .set_intense(true)
            .set_fg(Some(config.severity_color(self.severity)))
            .clone();

        // Write severity name
        //
        // ```
        // error
        // ```
        writer.set_color(&primary_spec)?;
        write!(writer, "{}", self.severity_name())?;
        if let Some(code) = &self.code {
            // Write error code
            //
            // ```
            // [E0001]
            // ```
            write!(writer, "[{}]", code)?;
        }

        // Write diagnostic message
        //
        // ```
        // : Unexpected type in `+` application
        // ```
        writer.set_color(&message_spec)?;
        write!(writer, ": {}", self.message)?;
        write!(writer, "\n")?;
        writer.reset()?;

        Ok(())
    }
}

enum MarkStyle {
    Primary(Severity),
    Secondary,
}

/// A marked section of source code
///
/// ```text
///   ┌╴ test:2:9
///   │
/// 2 │ (+ test "")
///   │         ^^ expected `Int` but found `String`
///   ╵
/// ```
struct MarkedSource<'a> {
    files: &'a Files,
    label: &'a Label,
    mark_style: MarkStyle,
}

impl<'a> MarkedSource<'a> {
    fn new_primary(files: &'a Files, diagnostic: &'a Diagnostic) -> MarkedSource<'a> {
        MarkedSource {
            files,
            label: &diagnostic.primary_label,
            mark_style: MarkStyle::Primary(diagnostic.severity),
        }
    }

    fn new_secondary(files: &'a Files, label: &'a Label) -> MarkedSource<'a> {
        MarkedSource {
            files,
            label,
            mark_style: MarkStyle::Secondary,
        }
    }

    fn span(&self) -> Span {
        self.label.span
    }

    fn start(&self) -> ByteIndex {
        self.span().start()
    }

    fn end(&self) -> ByteIndex {
        self.span().end()
    }

    fn file_name(&self) -> &'a str {
        self.files.name(self.label.file_id)
    }

    fn location(&self, byte_index: ByteIndex) -> Result<Location, impl std::error::Error> {
        self.files.location(self.label.file_id, byte_index)
    }

    fn source_slice(&self, span: Span) -> Result<&'a str, impl std::error::Error> {
        self.files.source_slice(self.label.file_id, span)
    }

    fn line_span(&self, line_index: LineIndex) -> Result<Span, impl std::error::Error> {
        self.files.line_span(self.label.file_id, line_index)
    }

    fn label_color(&self, config: &Config) -> Color {
        match self.mark_style {
            MarkStyle::Primary(severity) => config.severity_color(severity),
            MarkStyle::Secondary => config.secondary_color,
        }
    }

    fn underline_char(&self, config: &Config) -> char {
        match self.mark_style {
            MarkStyle::Primary(_) => config.primary_mark,
            MarkStyle::Secondary => config.secondary_mark,
        }
    }

    fn emit(&self, writer: &mut impl WriteColor, config: &Config) -> io::Result<()> {
        let gutter_spec = ColorSpec::new().set_fg(Some(config.gutter_color)).clone();
        let label_spec = ColorSpec::new()
            .set_fg(Some(self.label_color(config)))
            .clone();

        let start = self.location(self.start()).expect("location_start");
        let end = self.location(self.end()).expect("location_end");
        let start_line_span = self.line_span(start.line).expect("line_span");
        let end_line_span = self.line_span(end.line).expect("line_span");

        // Use the length of the last line number as the gutter padding
        let gutter_padding = format!("{}", end.line.number()).len();

        // Label locus
        //
        // ```
        // ┌╴ test:2:9
        // ```

        // Write gutter
        writer.set_color(&gutter_spec)?;
        write!(writer, "{: >width$} ┌╴ ", "", width = gutter_padding)?;
        writer.reset()?;

        // Write locus
        SourceLocus::new(self.file_name(), start).emit(writer, config)?;
        write!(writer, "\n")?;

        // Source code snippet
        //
        // ```
        //   │
        // 2 │ (+ test "")
        //   │         ^^ expected `Int` but found `String`
        //   ╵
        // ```

        // Write line number and gutter
        writer.set_color(&gutter_spec)?;
        write!(writer, "{: >width$} │ ", "", width = gutter_padding)?;
        write!(writer, "\n")?;
        write!(
            writer,
            "{: >width$} │ ",
            start.line.number(),
            width = gutter_padding,
        )?;
        writer.reset()?;

        let line_trimmer = |ch: char| ch == '\r' || ch == '\n';

        // Write source prefix before marked section
        let prefix_span = start_line_span.with_end(self.start());
        let source_prefix = self.source_slice(prefix_span).expect("prefix");
        write!(writer, "{}", source_prefix)?;

        // Write marked section
        let mark_len = if start.line == end.line {
            // Single line

            // Write marked source section
            let marked_source = self.source_slice(self.span()).expect("marked_source");
            writer.set_color(&label_spec)?;
            write!(writer, "{}", marked_source)?;
            writer.reset()?;
            marked_source.len()
        } else {
            // Multiple lines

            // Write marked source section
            let marked_span = start_line_span.with_start(self.start());
            let marked_source = self.source_slice(marked_span).expect("start_of_marked");
            writer.set_color(&label_spec)?;
            write!(writer, "{}", marked_source)?;

            for line_index in ((start.line.to_usize() + 1)..end.line.to_usize())
                .map(|i| LineIndex::from(i as u32))
            {
                // Write line number and gutter
                writer.set_color(&gutter_spec)?;
                write!(
                    writer,
                    "{: >width$} │ ",
                    line_index.number(),
                    width = gutter_padding,
                )?;

                // Write marked source section
                let mark_span = self.line_span(line_index).expect("marked_line_span");
                let marked_source = self.source_slice(mark_span).expect("marked_source");
                writer.set_color(&label_spec)?;
                write!(writer, "{}", marked_source.trim_end_matches(line_trimmer))?;
                write!(writer, "\n")?;
            }

            // Write line number and gutter
            writer.set_color(&gutter_spec)?;
            write!(
                writer,
                "{: >width$} │ ",
                end.line.number(),
                width = gutter_padding,
            )?;

            // Write marked source section
            let mark_span = end_line_span.with_end(self.end());
            let marked_source = self.source_slice(mark_span).expect("marked_source");
            writer.set_color(&label_spec)?;
            write!(writer, "{}", marked_source)?;
            writer.reset()?;
            marked_source.len()
        };

        // Write source suffix after marked section
        let suffix_span = end_line_span.with_start(self.end());
        let source_suffix = self.source_slice(suffix_span).expect("suffix");
        write!(writer, "{}", source_suffix.trim_end_matches(line_trimmer))?;
        write!(writer, "\n")?;

        // Write underline gutter
        writer.set_color(&gutter_spec)?;
        write!(writer, "{: >width$} │ ", "", width = gutter_padding)?;
        writer.reset()?;

        // Write underline and label
        writer.set_color(&label_spec)?;
        write!(writer, "{: >width$}", "", width = source_prefix.len())?;
        for _ in 0..mark_len {
            write!(writer, "{}", self.underline_char(config))?;
        }
        if !self.label.message.is_empty() {
            write!(writer, " {}", self.label.message)?;
            write!(writer, "\n")?;
        }
        writer.reset()?;

        // Write final gutter
        writer.set_color(&gutter_spec)?;
        write!(writer, "{: >width$} ╵", "", width = gutter_padding)?;
        write!(writer, "\n")?;
        writer.reset()?;

        Ok(())
    }
}

/// The 'location focus' of a source code snippet.
///
/// This is displayed in a way that other tools can understand, for
/// example when command+clicking in iTerm.
///
/// ```text
/// test:2:9
/// ```
struct SourceLocus<'a> {
    file_name: &'a str,
    location: Location,
}

impl<'a> SourceLocus<'a> {
    fn new(file_name: &'a str, location: Location) -> SourceLocus<'a> {
        SourceLocus {
            file_name,
            location,
        }
    }

    fn emit(&self, writer: &mut impl WriteColor, _config: &Config) -> io::Result<()> {
        write!(
            writer,
            "{file}:{line}:{column}",
            file = self.file_name,
            line = self.location.line.number(),
            column = self.location.column.number(),
        )
    }
}
<|endoftext|>


<commit_before>extern crate websocket;
extern crate futures;
extern crate tokio_core;
extern crate serde;
extern crate serde_json;
#[macro_use]
extern crate serde_derive;

use std::fmt::Debug;

use websocket::message::OwnedMessage;
use websocket::server::InvalidConnection;
use websocket::client::async::Framed;
use websocket::async::{Server, MessageCodec};

use tokio_core::net::TcpStream;
use tokio_core::reactor::{Handle, Core};

use futures::{Future, Sink, Stream};
use futures::future::{self, Loop};

fn main() {
    let mut core = Core::new().unwrap();
    let handle = core.handle();
    let server = Server::bind("localhost:8081", &handle).unwrap();

    let f = server.incoming()
        // we don't wanna save the stream if it drops
        .map_err(|InvalidConnection { error, .. }| error)
        .for_each(|(upgrade, addr)| {
            println!("Got a connection from: {}", addr);
            if !upgrade.protocols().iter().any(|s| s == "rust-websocket") {
                spawn_future(upgrade.reject(), "Upgrade Rejection", &handle);
                return Ok(());
            }

            let client = upgrade
                .use_protocol("rust-websocket")
                .accept();
            let f = client
                .and_then(|(framed, _)| {
                    let (sink, stream) = framed.split();

                    let input = stream
                            .for_each(|msg|{
                                println!("0");
                                let mut state = State::new();
                                handle_incoming(&mut state, &msg);
                                Ok(())
                            });
                    let output = sink
                            .send({
                                println!("1");
                                OwnedMessage::Text("hi!".to_owned())
                            });
                    Ok(input.map(|_| ()).map_err(|_| ()).join(output.map(|_| ()).map_err(|_| ())))
                });
            spawn_future(f, "Client Status", &handle);
            Ok(())
        });

    core.run(f).unwrap();
}

fn spawn_future<F, I, E>(f: F, desc: &'static str, handle: &Handle)
    where F: Future<Item = I, Error = E> + 'static,
          E: Debug
{
    handle.spawn(f.map_err(move |e| println!("Error in {}: '{:?}'", desc, e))
                     .map(move |_| println!("{}: Finished.", desc)));
}

fn handle_incoming(state: &mut State, msg: &OwnedMessage) {
    println!("handle_incoming");
    match msg {
        &OwnedMessage::Text(ref txt) => {
            println!("Received message: {}", txt);
            state.msg = txt.clone();
        }
        _ => {}
    }
}

type FramedStream = Framed<TcpStream, MessageCodec<OwnedMessage>>;

fn send(state: &State, stream: FramedStream) -> futures::sink::Send<FramedStream> {
    let msg = serde_json::to_string(&state).unwrap();
    println!("Sending message: {}", msg);
    stream.send(OwnedMessage::Text(msg))
}

#[derive(Serialize)]
struct State {
    msg: String,
}

impl State {
    fn new() -> State {
        State { msg: "git gud".to_string() }
    }
}

<commit_msg>Make IO actually non blocking<commit_after>extern crate websocket;
extern crate futures;
extern crate tokio_core;
extern crate serde;
extern crate serde_json;
#[macro_use]
extern crate serde_derive;

use std::fmt::Debug;

use websocket::message::OwnedMessage;
use websocket::server::InvalidConnection;
use websocket::client::async::Framed;
use websocket::async::{Server, MessageCodec};
use websocket::WebSocketError;

use tokio_core::net::TcpStream;
use tokio_core::reactor::{Handle, Core};

use futures::{Future, Sink, Stream};
use futures::future::{self, Loop};

fn main() {
    let mut core = Core::new().unwrap();
    let handle = core.handle();
    let server = Server::bind("localhost:8081", &handle).unwrap();

    let f = server.incoming()
        // we don't wanna save the stream if it drops
        .map_err(|InvalidConnection { error, .. }| error)
        .for_each(|(upgrade, addr)| {
            println!("Got a connection from: {}", addr);
            if !upgrade.protocols().iter().any(|s| s == "rust-websocket") {
                spawn_future(upgrade.reject(), "Upgrade Rejection", &handle);
                return Ok(());
            }

            let client = upgrade
                .use_protocol("rust-websocket")
                .accept();
            let f = client
                .and_then(|(framed, _)| {
                    let (sink, stream) = framed.split();

                    let input = stream
                            .for_each(|msg|{
                                println!("0");
                                let mut state = State::new();
                                handle_incoming(&mut state, &msg);
                                Ok(())
                            })
                            .map_err(|e| WebSocketError::NoDataAvailable);

                    let output = sink
                            .send({
                                println!("1");
                                OwnedMessage::Text("hi!".to_owned())
                            })
                            .map_err(|e| WebSocketError::NoDataAvailable);
                    input.join(output)
                });
            spawn_future(f, "Client Status", &handle);
            Ok(())
        });

    core.run(f).unwrap();
}

fn spawn_future<F, I, E>(f: F, desc: &'static str, handle: &Handle)
    where F: Future<Item = I, Error = E> + 'static,
          E: Debug
{
    handle.spawn(f.map_err(move |e| println!("Error in {}: '{:?}'", desc, e))
                     .map(move |_| println!("{}: Finished.", desc)));
}

fn handle_incoming(state: &mut State, msg: &OwnedMessage) {
    println!("handle_incoming");
    match msg {
        &OwnedMessage::Text(ref txt) => {
            println!("Received message: {}", txt);
            state.msg = txt.clone();
        }
        _ => {}
    }
}

type FramedStream = Framed<TcpStream, MessageCodec<OwnedMessage>>;

fn send(state: &State, stream: FramedStream) -> futures::sink::Send<FramedStream> {
    let msg = serde_json::to_string(&state).unwrap();
    println!("Sending message: {}", msg);
    stream.send(OwnedMessage::Text(msg))
}

#[derive(Serialize)]
struct State {
    msg: String,
}

impl State {
    fn new() -> State {
        State { msg: "git gud".to_string() }
    }
}

<|endoftext|>


<commit_before>/*
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

//! This crate contains a GraphQL schema representation.

#![deny(warnings)]
#![deny(rust_2018_idioms)]
#![deny(clippy::all)]

pub mod definitions;
mod errors;
mod fb_schema;
mod graphqlschema_generated;

use common::{DiagnosticsResult, SourceLocationKey};
pub use definitions::{
    Argument, ArgumentDefinitions, ArgumentValue, Directive, DirectiveValue, Enum, EnumID,
    EnumValue, Field, FieldID, InputObject, InputObjectID, Interface, InterfaceID, Object,
    ObjectID, Scalar, ScalarID, Schema, Type, TypeReference, TypeWithFields, Union, UnionID,
};
pub use errors::{Result, SchemaError};
use fb_schema::FlatBufferSchema;
pub use graphql_syntax::DirectiveLocation;
pub use graphqlschema_generated::graphqlschema::*;

const BUILTINS: &str = include_str!("./builtins.graphql");

pub fn build_schema(sdl: &str) -> DiagnosticsResult<Schema> {
    build_schema_with_extensions::<_, &str>(&[sdl], &[])
}

pub fn build_schema_with_extensions<T: AsRef<str>, U: AsRef<str>>(
    server_sdls: &[T],
    extension_sdls: &[U],
) -> DiagnosticsResult<Schema> {
    let mut server_definitions = {
        let schema_doc =
            graphql_syntax::parse_schema_document(BUILTINS, SourceLocationKey::generated())?;
        schema_doc.definitions
    };

    let mut combined_sdl: String = String::new();
    for server_sdl in server_sdls {
        combined_sdl.push_str(server_sdl.as_ref());
        combined_sdl.push_str("\n");
    }
    server_definitions.extend(
        graphql_syntax::parse_schema_document(&combined_sdl, SourceLocationKey::generated())?
            .definitions,
    );

    let mut extension_definitions = Vec::new();
    for extension_sdl in extension_sdls {
        extension_definitions.extend(
            graphql_syntax::parse_schema_document(
                extension_sdl.as_ref(),
                SourceLocationKey::generated(),
            )?
            .definitions,
        );
    }

    Schema::build(&server_definitions, &extension_definitions)
}

pub fn build_schema_from_flat_buffer(bytes: &[u8]) -> DiagnosticsResult<FlatBufferSchema<'_>> {
    Ok(FlatBufferSchema::build(bytes))
}
<commit_msg>Implement intersection schema<commit_after>/*
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

//! This crate contains a GraphQL schema representation.

#![deny(warnings)]
#![deny(rust_2018_idioms)]
#![deny(clippy::all)]

pub mod definitions;
mod errors;
mod fb_schema;
mod graphqlschema_generated;

use common::{DiagnosticsResult, SourceLocationKey};
pub use definitions::{
    Argument, ArgumentDefinitions, ArgumentValue, Directive, DirectiveValue, Enum, EnumID,
    EnumValue, Field, FieldID, InputObject, InputObjectID, Interface, InterfaceID, Object,
    ObjectID, Scalar, ScalarID, Schema, Type, TypeReference, TypeWithFields, Union, UnionID,
};
pub use errors::{Result, SchemaError};
use fb_schema::FlatBufferSchema;
pub use graphql_syntax::{DirectiveLocation, TypeSystemDefinition};
pub use graphqlschema_generated::graphqlschema::*;

const BUILTINS: &str = include_str!("./builtins.graphql");

pub fn build_schema(sdl: &str) -> DiagnosticsResult<Schema> {
    build_schema_with_extensions::<_, &str>(&[sdl], &[])
}

pub fn build_schema_with_extensions<T: AsRef<str>, U: AsRef<str>>(
    server_sdls: &[T],
    extension_sdls: &[U],
) -> DiagnosticsResult<Schema> {
    let mut server_definitions = builtins()?;
    let mut combined_sdl: String = String::new();
    for server_sdl in server_sdls {
        combined_sdl.push_str(server_sdl.as_ref());
        combined_sdl.push_str("\n");
    }
    server_definitions.extend(
        graphql_syntax::parse_schema_document(&combined_sdl, SourceLocationKey::generated())?
            .definitions,
    );

    let mut extension_definitions = Vec::new();
    for extension_sdl in extension_sdls {
        extension_definitions.extend(
            graphql_syntax::parse_schema_document(
                extension_sdl.as_ref(),
                SourceLocationKey::generated(),
            )?
            .definitions,
        );
    }

    Schema::build(&server_definitions, &extension_definitions)
}

pub fn build_schema_from_flat_buffer(bytes: &[u8]) -> DiagnosticsResult<FlatBufferSchema<'_>> {
    Ok(FlatBufferSchema::build(bytes))
}

pub fn builtins() -> DiagnosticsResult<Vec<TypeSystemDefinition>> {
    Ok(
        graphql_syntax::parse_schema_document(BUILTINS, SourceLocationKey::generated())?
            .definitions,
    )
}
<|endoftext|>


<commit_before>use std::ffi::CString;
use std::os::raw::{c_void, c_long};
use std::ptr;
use std::rc::Rc;
use winapi;
use winapi::um::d3d11::ID3D11Device;
use winapi::um::d3d11::ID3D11Texture2D;

pub fn get_proc_address(name: &str) -> *const c_void {
    let name = CString::new(name.as_bytes()).unwrap();
    unsafe {
        GetProcAddress(name.as_ptr()) as *const _ as _
    }
}

pub struct SharedEglThings {
    device: EGLDeviceEXT,
    display: types::EGLDisplay,
    config: types::EGLConfig,
}

fn cast_attributes(slice: &[types::EGLenum]) -> &EGLint {
    unsafe {
        &*(slice.as_ptr() as *const EGLint)
    }
}

macro_rules! attributes {
    ($( $key: expr => $value: expr, )*) => {
        cast_attributes(&[
            $( $key, $value, )*
            NONE,
        ])
    }
}

impl SharedEglThings {
    pub unsafe fn new(d3d_device: *mut ID3D11Device) -> Rc<Self> {
        let device = eglCreateDeviceANGLE(
            D3D11_DEVICE_ANGLE,
            d3d_device,
            ptr::null(),
        ).check();
        let display = GetPlatformDisplayEXT(
            PLATFORM_DEVICE_EXT,
            device,
            attributes! [
                EXPERIMENTAL_PRESENT_PATH_ANGLE => EXPERIMENTAL_PRESENT_PATH_FAST_ANGLE,
            ],
        ).check();
        Initialize(display, ptr::null_mut(), ptr::null_mut()).check();

        // Adapted from
        // https://searchfox.org/mozilla-central/rev/056a4057/gfx/gl/GLContextProviderEGL.cpp#635
        let mut configs = [ptr::null(); 64];
        let mut num_configs = 0;
        ChooseConfig(
            display,
            attributes! [
                SURFACE_TYPE => WINDOW_BIT,
                RENDERABLE_TYPE => OPENGL_ES2_BIT,
                RED_SIZE => 8,
                GREEN_SIZE => 8,
                BLUE_SIZE => 8,
                ALPHA_SIZE => 8,
            ],
            configs.as_mut_ptr(),
            configs.len() as i32,
            &mut num_configs,
        ).check();
        assert!(num_configs >= 0);
        // FIXME: pick a preferable config?
        let config = configs[0];

        Rc::new(SharedEglThings { device, display, config })
    }
}

impl Drop for SharedEglThings {
    fn drop(&mut self) {
        unsafe {
            // FIXME does EGLDisplay or EGLConfig need clean up? How?
            eglReleaseDeviceANGLE(self.device).check();
        }
    }
}

pub struct PerVisualEglThings {
    shared: Rc<SharedEglThings>,
    context: types::EGLContext,
    surface: types::EGLSurface,
}

impl PerVisualEglThings {
    pub unsafe fn new(shared: Rc<SharedEglThings>, buffer: *const ID3D11Texture2D,
           width: u32, height: u32)
           -> Self {
        let context = CreateContext(
            shared.display,
            shared.config,
            NO_CONTEXT,
            attributes![],
        ).check();

        let surface = CreatePbufferFromClientBuffer(
            shared.display,
            D3D_TEXTURE_ANGLE,
            buffer as types::EGLClientBuffer,
            shared.config,
            attributes! [
                WIDTH => width,
                HEIGHT => height,
                FLEXIBLE_SURFACE_COMPATIBILITY_SUPPORTED_ANGLE => TRUE,
            ],
        ).check();

        PerVisualEglThings { shared, context, surface }
    }

    pub fn make_current(&self) {
        unsafe {
            MakeCurrent(self.shared.display, self.surface, self.surface, self.context).check();
        }
    }
}

impl Drop for PerVisualEglThings {
    fn drop(&mut self) {
        unsafe {
            if GetCurrentContext() == self.context {
                // release the current context without assigning a new one
                MakeCurrent(self.shared.display, NO_SURFACE, NO_SURFACE, NO_CONTEXT).check();
            }
            DestroyContext(self.shared.display, self.context).check();
            DestroySurface(self.shared.display, self.surface).check();
        }
    }
}

fn check_error() {
    unsafe {
        let error = GetError() as types::EGLenum;
        assert_eq!(error, SUCCESS, "0x{:x} != 0x{:x}", error, SUCCESS);
    }
}

trait Check {
    fn check(self) -> Self;
}

impl Check for *const c_void {
    fn check(self) -> Self {
        check_error();
        assert!(!self.is_null());
        self
    }
}

impl Check for *mut c_void {
    fn check(self) -> Self {
        check_error();
        assert!(!self.is_null());
        self
    }
}

impl Check for types::EGLBoolean {
    fn check(self) -> Self {
        check_error();
        assert_eq!(self, TRUE);
        self
    }
}

// Adapted from https://github.com/tomaka/glutin/blob/1f3b8360cb/src/api/egl/ffi.rs
#[allow(non_camel_case_types)] pub type khronos_utime_nanoseconds_t = khronos_uint64_t;
#[allow(non_camel_case_types)] pub type khronos_uint64_t = u64;
#[allow(non_camel_case_types)] pub type khronos_ssize_t = c_long;
pub type EGLint = i32;
pub type EGLNativeDisplayType = *const c_void;
pub type EGLNativePixmapType = *const c_void;
pub type EGLNativeWindowType = winapi::shared::windef::HWND;
pub type NativeDisplayType = EGLNativeDisplayType;
pub type NativePixmapType = EGLNativePixmapType;
pub type NativeWindowType = EGLNativeWindowType;

include!(concat!(env!("OUT_DIR"), "/egl_bindings.rs"));

// Adapted from https://chromium.googlesource.com/angle/angle/+/master/include/EGL/eglext_angle.h
type EGLDeviceEXT = *mut c_void;
const EXPERIMENTAL_PRESENT_PATH_ANGLE: types::EGLenum = 0x33A4;
const EXPERIMENTAL_PRESENT_PATH_FAST_ANGLE: types::EGLenum = 0x33A9;
const D3D_TEXTURE_ANGLE: types::EGLenum = 0x33A3;
const FLEXIBLE_SURFACE_COMPATIBILITY_SUPPORTED_ANGLE: types::EGLenum = 0x33A6;

extern "C" {
    fn eglCreateDeviceANGLE(
        device_type: types::EGLenum,
        device: *mut ID3D11Device,
        attrib_list: *const types::EGLAttrib,
    ) -> EGLDeviceEXT;

    fn eglReleaseDeviceANGLE(device: EGLDeviceEXT) -> types::EGLBoolean;
}
<commit_msg>Move to-be-implemented EGL config choice to a function<commit_after>use std::ffi::CString;
use std::os::raw::{c_void, c_long};
use std::ptr;
use std::rc::Rc;
use winapi;
use winapi::um::d3d11::ID3D11Device;
use winapi::um::d3d11::ID3D11Texture2D;

pub fn get_proc_address(name: &str) -> *const c_void {
    let name = CString::new(name.as_bytes()).unwrap();
    unsafe {
        GetProcAddress(name.as_ptr()) as *const _ as _
    }
}

pub struct SharedEglThings {
    device: EGLDeviceEXT,
    display: types::EGLDisplay,
    config: types::EGLConfig,
}

fn cast_attributes(slice: &[types::EGLenum]) -> &EGLint {
    unsafe {
        &*(slice.as_ptr() as *const EGLint)
    }
}

macro_rules! attributes {
    ($( $key: expr => $value: expr, )*) => {
        cast_attributes(&[
            $( $key, $value, )*
            NONE,
        ])
    }
}

impl SharedEglThings {
    pub unsafe fn new(d3d_device: *mut ID3D11Device) -> Rc<Self> {
        let device = eglCreateDeviceANGLE(
            D3D11_DEVICE_ANGLE,
            d3d_device,
            ptr::null(),
        ).check();
        let display = GetPlatformDisplayEXT(
            PLATFORM_DEVICE_EXT,
            device,
            attributes! [
                EXPERIMENTAL_PRESENT_PATH_ANGLE => EXPERIMENTAL_PRESENT_PATH_FAST_ANGLE,
            ],
        ).check();
        Initialize(display, ptr::null_mut(), ptr::null_mut()).check();

        // Adapted from
        // https://searchfox.org/mozilla-central/rev/056a4057/gfx/gl/GLContextProviderEGL.cpp#635
        let mut configs = [ptr::null(); 64];
        let mut num_configs = 0;
        ChooseConfig(
            display,
            attributes! [
                SURFACE_TYPE => WINDOW_BIT,
                RENDERABLE_TYPE => OPENGL_ES2_BIT,
                RED_SIZE => 8,
                GREEN_SIZE => 8,
                BLUE_SIZE => 8,
                ALPHA_SIZE => 8,
            ],
            configs.as_mut_ptr(),
            configs.len() as i32,
            &mut num_configs,
        ).check();
        let config = pick_config(&configs[..num_configs as usize]);

        Rc::new(SharedEglThings { device, display, config })
    }
}

fn pick_config(configs: &[types::EGLConfig]) -> types::EGLConfig {
    // FIXME: better criteria to make this choice?
    // Firefox uses GetConfigAttrib to find a config that has the requested r/g/b/a sizes
    // https://searchfox.org/mozilla-central/rev/056a4057/gfx/gl/GLContextProviderEGL.cpp#662-685

    configs[0]
}

impl Drop for SharedEglThings {
    fn drop(&mut self) {
        unsafe {
            // FIXME does EGLDisplay or EGLConfig need clean up? How?
            eglReleaseDeviceANGLE(self.device).check();
        }
    }
}

pub struct PerVisualEglThings {
    shared: Rc<SharedEglThings>,
    context: types::EGLContext,
    surface: types::EGLSurface,
}

impl PerVisualEglThings {
    pub unsafe fn new(shared: Rc<SharedEglThings>, buffer: *const ID3D11Texture2D,
           width: u32, height: u32)
           -> Self {
        let context = CreateContext(
            shared.display,
            shared.config,
            NO_CONTEXT,
            attributes![],
        ).check();

        let surface = CreatePbufferFromClientBuffer(
            shared.display,
            D3D_TEXTURE_ANGLE,
            buffer as types::EGLClientBuffer,
            shared.config,
            attributes! [
                WIDTH => width,
                HEIGHT => height,
                FLEXIBLE_SURFACE_COMPATIBILITY_SUPPORTED_ANGLE => TRUE,
            ],
        ).check();

        PerVisualEglThings { shared, context, surface }
    }

    pub fn make_current(&self) {
        unsafe {
            MakeCurrent(self.shared.display, self.surface, self.surface, self.context).check();
        }
    }
}

impl Drop for PerVisualEglThings {
    fn drop(&mut self) {
        unsafe {
            if GetCurrentContext() == self.context {
                // release the current context without assigning a new one
                MakeCurrent(self.shared.display, NO_SURFACE, NO_SURFACE, NO_CONTEXT).check();
            }
            DestroyContext(self.shared.display, self.context).check();
            DestroySurface(self.shared.display, self.surface).check();
        }
    }
}

fn check_error() {
    unsafe {
        let error = GetError() as types::EGLenum;
        assert_eq!(error, SUCCESS, "0x{:x} != 0x{:x}", error, SUCCESS);
    }
}

trait Check {
    fn check(self) -> Self;
}

impl Check for *const c_void {
    fn check(self) -> Self {
        check_error();
        assert!(!self.is_null());
        self
    }
}

impl Check for *mut c_void {
    fn check(self) -> Self {
        check_error();
        assert!(!self.is_null());
        self
    }
}

impl Check for types::EGLBoolean {
    fn check(self) -> Self {
        check_error();
        assert_eq!(self, TRUE);
        self
    }
}

// Adapted from https://github.com/tomaka/glutin/blob/1f3b8360cb/src/api/egl/ffi.rs
#[allow(non_camel_case_types)] pub type khronos_utime_nanoseconds_t = khronos_uint64_t;
#[allow(non_camel_case_types)] pub type khronos_uint64_t = u64;
#[allow(non_camel_case_types)] pub type khronos_ssize_t = c_long;
pub type EGLint = i32;
pub type EGLNativeDisplayType = *const c_void;
pub type EGLNativePixmapType = *const c_void;
pub type EGLNativeWindowType = winapi::shared::windef::HWND;
pub type NativeDisplayType = EGLNativeDisplayType;
pub type NativePixmapType = EGLNativePixmapType;
pub type NativeWindowType = EGLNativeWindowType;

include!(concat!(env!("OUT_DIR"), "/egl_bindings.rs"));

// Adapted from https://chromium.googlesource.com/angle/angle/+/master/include/EGL/eglext_angle.h
type EGLDeviceEXT = *mut c_void;
const EXPERIMENTAL_PRESENT_PATH_ANGLE: types::EGLenum = 0x33A4;
const EXPERIMENTAL_PRESENT_PATH_FAST_ANGLE: types::EGLenum = 0x33A9;
const D3D_TEXTURE_ANGLE: types::EGLenum = 0x33A3;
const FLEXIBLE_SURFACE_COMPATIBILITY_SUPPORTED_ANGLE: types::EGLenum = 0x33A6;

extern "C" {
    fn eglCreateDeviceANGLE(
        device_type: types::EGLenum,
        device: *mut ID3D11Device,
        attrib_list: *const types::EGLAttrib,
    ) -> EGLDeviceEXT;

    fn eglReleaseDeviceANGLE(device: EGLDeviceEXT) -> types::EGLBoolean;
}
<|endoftext|>


<commit_before>use hyper::{Client, Uri, Method, Chunk, Error, StatusCode};
use hyper::header::{Authorization, Accept, UserAgent, qitem};
use hyper::client::{Request, Response, FutureResponse};
use hyper_tls::HttpsConnector;
use futures::{Future, Stream};
use futures::future;
use serde_json;
use slog::*;
use serde::Deserialize;

use models::*;
use endpoint::HnNewsEndpoint;
use app::Main;
use utils::*;

pub fn get_top_story_ids(main: &mut Main) -> Result<HnTopStories, Error> {
    let logger = &main.logger; // These need to be here as otherwise it'll cause mutable<>immutable borrow error
    let endpoint = &main.endpoint;
    let client = &main.client;
    let work = request_top_story_ids(&client, &endpoint)
        .and_then(|res| {
            log_response_status(&logger, &endpoint.get_top_stories_path(), &res.status());
            res.body()
                .fold(Vec::new(), |mut v, chunk| {
                    v.extend(&chunk[..]);
                    future::ok::<_, Error>(v)
                })
        })
        .map(|chunks|
            deserialize::<HnTopStories>(chunks)
        );
    let result = main.core.run(work);
    result
}

fn deserialize<T:Deserialize>(chunks:Vec<u8>) -> T {
    let s = String::from_utf8(chunks).unwrap();
    let deserialized: T = serde_json::from_str(&s).unwrap();
    deserialized
}

///
/// Gets HnItem wrapped in Result
///
pub fn get_item_by_id(item: &str, main: &mut Main) -> Result<HnItem, Error> {
    let logger = &main.logger; // These need to be here as otherwise it'll cause mutable<>immutable borrow error
    let endpoint = &main.endpoint;
    let client = &main.client;
    let work = request_item(&item, &client, &endpoint)
        .and_then(|res| {
            log_response_status(&logger, &endpoint.get_item_path(&item), &res.status());
            res.body()
                .fold(Vec::new(), |mut v, chunk| {
                    v.extend(&chunk[..]);
                    future::ok::<_, Error>(v)
                })
        })
        .map(|chunks| {
            deserialize::<HnItem>(chunks)
        });
    let result = main.core.run(work);
    result
}

fn get_comments_for_a_story(main: &mut Main, story_id: i32) {}

fn log_response_status(logger: &Logger, url: &str, status: &StatusCode) {
    info!(logger,
          format!("Request to {} finished with status {}", url, status));
}

fn request_top_story_ids(client: &Client<HttpsConnector>,
                         endpoints: &HnNewsEndpoint)
                         -> FutureResponse {
    let url = parse_url_from_str(&endpoints.get_top_stories_path());
    let mut request = Request::new(Method::Get, url);
    common_headers(&mut request);
    client.request(request)
}
fn request_item(item: &str,
                client: &Client<HttpsConnector>,
                endpoints: &HnNewsEndpoint)
                -> FutureResponse {
    let url = parse_url_from_str(&endpoints.get_item_path(item));
    let mut request = Request::new(Method::Get, url);
    common_headers(&mut request);
    client.request(request)
}

fn common_headers(req: &mut Request) {
    req.headers_mut().set(UserAgent::new("hyper"));
}

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

    #[test]
    fn request_item_test() {
        let mut main = create_main();
        let s = String::from("8000");
        let response = main.core.run(request_item(&s, &main.client, &main.endpoint)).unwrap();
        assert_eq!(StatusCode::Ok, response.status());
    }
    #[test]
    fn request_top_stories_test() {
        let mut main = create_main();
        let response = main.core.run(request_top_story_ids(&main.client, &main.endpoint)).unwrap();
        assert_eq!(StatusCode::Ok, response.status());
    }

    #[test]
    fn get_item_by_id_test() {
        let mut main = create_main();
        let s = String::from("126809");
        let hnitem: HnItem = get_item_by_id(&s, &mut main).unwrap();
        assert!(hnitem.score != 0);
        assert!(hnitem.id != 0);
        assert!(!hnitem.type_str.is_empty());
        assert!(!hnitem.title.is_empty());
        assert_eq!(126809, hnitem.id);
    }
    #[test]
    fn get_top_stories_test() {
        let mut main = create_main();
        let top_stories: HnTopStories = get_top_story_ids(&mut main).unwrap();
        assert!(top_stories.values.len() != 0);
    }
}
<commit_msg>changes user agent<commit_after>use hyper::{Client, Uri, Method, Chunk, Error, StatusCode};
use hyper::header::{Authorization, Accept, UserAgent, qitem};
use hyper::client::{Request, Response, FutureResponse};
use hyper_tls::HttpsConnector;
use futures::{Future, Stream};
use futures::future;
use serde_json;
use slog::*;
use serde::Deserialize;

use models::*;
use endpoint::HnNewsEndpoint;
use app::Main;
use utils::*;

pub fn get_top_story_ids(main: &mut Main) -> Result<HnTopStories, Error> {
    let logger = &main.logger; // These need to be here as otherwise it'll cause mutable<>immutable borrow error
    let endpoint = &main.endpoint;
    let client = &main.client;
    let work = request_top_story_ids(&client, &endpoint)
        .and_then(|res| {
            log_response_status(&logger, &endpoint.get_top_stories_path(), &res.status());
            res.body()
                .fold(Vec::new(), |mut v, chunk| {
                    v.extend(&chunk[..]);
                    future::ok::<_, Error>(v)
                })
        })
        .map(|chunks|
            deserialize::<HnTopStories>(chunks)
        );
    let result = main.core.run(work);
    result
}

fn deserialize<T:Deserialize>(chunks:Vec<u8>) -> T {
    let s = String::from_utf8(chunks).unwrap();
    let deserialized: T = serde_json::from_str(&s).unwrap();
    deserialized
}

///
/// Gets HnItem wrapped in Result
///
pub fn get_item_by_id(item: &str, main: &mut Main) -> Result<HnItem, Error> {
    let logger = &main.logger; // These need to be here as otherwise it'll cause mutable<>immutable borrow error
    let endpoint = &main.endpoint;
    let client = &main.client;
    let work = request_item(&item, &client, &endpoint)
        .and_then(|res| {
            log_response_status(&logger, &endpoint.get_item_path(&item), &res.status());
            res.body()
                .fold(Vec::new(), |mut v, chunk| {
                    v.extend(&chunk[..]);
                    future::ok::<_, Error>(v)
                })
        })
        .map(|chunks| {
            deserialize::<HnItem>(chunks)
        });
    let result = main.core.run(work);
    result
}

fn get_comments_for_a_story(main: &mut Main, story_id: i32) {}

fn log_response_status(logger: &Logger, url: &str, status: &StatusCode) {
    info!(logger,
          format!("Request to {} finished with status {}", url, status));
}

fn request_top_story_ids(client: &Client<HttpsConnector>,
                         endpoints: &HnNewsEndpoint)
                         -> FutureResponse {
    let url = parse_url_from_str(&endpoints.get_top_stories_path());
    let mut request = Request::new(Method::Get, url);
    common_headers(&mut request);
    client.request(request)
}
fn request_item(item: &str,
                client: &Client<HttpsConnector>,
                endpoints: &HnNewsEndpoint)
                -> FutureResponse {
    let url = parse_url_from_str(&endpoints.get_item_path(item));
    let mut request = Request::new(Method::Get, url);
    common_headers(&mut request);
    client.request(request)
}

fn common_headers(req: &mut Request) {
    req.headers_mut().set(UserAgent::new("rs-hackernews-cli"));
}

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

    #[test]
    fn request_item_test() {
        let mut main = create_main();
        let s = String::from("8000");
        let response = main.core.run(request_item(&s, &main.client, &main.endpoint)).unwrap();
        assert_eq!(StatusCode::Ok, response.status());
    }
    #[test]
    fn request_top_stories_test() {
        let mut main = create_main();
        let response = main.core.run(request_top_story_ids(&main.client, &main.endpoint)).unwrap();
        assert_eq!(StatusCode::Ok, response.status());
    }

    #[test]
    fn get_item_by_id_test() {
        let mut main = create_main();
        let s = String::from("126809");
        let hnitem: HnItem = get_item_by_id(&s, &mut main).unwrap();
        assert!(hnitem.score != 0);
        assert!(hnitem.id != 0);
        assert!(!hnitem.type_str.is_empty());
        assert!(!hnitem.title.is_empty());
        assert_eq!(126809, hnitem.id);
    }
    #[test]
    fn get_top_stories_test() {
        let mut main = create_main();
        let top_stories: HnTopStories = get_top_story_ids(&mut main).unwrap();
        assert!(top_stories.values.len() != 0);
    }
}
<|endoftext|>