<commit_before>use std::mem;
use std::slice;
use std::str;

use objc::{Id, ShareId};

use INSObject;

pub trait INSCopying : INSObject {
    type Output: INSObject;

    fn copy(&self) -> ShareId<Self::Output> {
        unsafe {
            let obj: *mut Self::Output = msg_send![self, copy];
            Id::from_retained_ptr(obj)
        }
    }
}

pub trait INSMutableCopying : INSObject {
    type Output: INSObject;

    fn mutable_copy(&self) -> Id<Self::Output> {
        unsafe {
            let obj: *mut Self::Output = msg_send![self, mutableCopy];
            Id::from_retained_ptr(obj)
        }
    }
}

static UTF8_ENCODING: usize = 4;

pub trait INSString : INSObject {
    fn len(&self) -> usize {
        unsafe {
            msg_send![self, lengthOfBytesUsingEncoding:UTF8_ENCODING]
        }
    }

    fn as_str(&self) -> &str {
        let bytes = unsafe {
            let bytes: *const i8 = msg_send![self, UTF8String];
            bytes as *const u8
        };
        let len = self.len();
        unsafe {
            let bytes = slice::from_raw_buf(&bytes, len);
            let s = str::from_utf8(bytes).unwrap();
            mem::transmute(s)
        }
    }

    fn from_str(string: &str) -> Id<Self> {
        let cls = <Self as INSObject>::class();
        unsafe {
            let obj: *mut Self = msg_send![cls, alloc];
            let obj: *mut Self = msg_send![obj, initWithBytes:string.as_ptr()
                                                       length:string.len()
                                                     encoding:UTF8_ENCODING];
            Id::from_retained_ptr(obj)
        }
    }
}

object_struct!(NSString);

impl INSString for NSString { }

impl INSCopying for NSString {
    type Output = NSString;
}

impl Str for NSString {
    fn as_slice(&self) -> &str {
        self.as_str()
    }
}

#[cfg(test)]
mod tests {
    use objc::Id;
    use super::{INSCopying, INSString, NSString};

    #[test]
    fn test_utf8() {
        let expected = "ประเทศไทย中华Việt Nam";
        let s: Id<NSString> = INSString::from_str(expected);
        assert!(s.len() == expected.len());
        assert!(s.as_str() == expected);
    }

    #[test]
    fn test_interior_nul() {
        let expected = "Hello\0World";
        let s: Id<NSString> = INSString::from_str(expected);
        assert!(s.len() == expected.len());
        assert!(s.as_str() == expected);
    }

    #[test]
    fn test_copy() {
        let s: Id<NSString> = INSString::from_str("Hello!");
        let copied = s.copy();
        assert!(copied.as_str() == s.as_str());
    }
}
<commit_msg>Replaced deprecated from_raw_buf method.<commit_after>use std::slice;
use std::str;

use objc::{Id, ShareId};

use INSObject;

pub trait INSCopying : INSObject {
    type Output: INSObject;

    fn copy(&self) -> ShareId<Self::Output> {
        unsafe {
            let obj: *mut Self::Output = msg_send![self, copy];
            Id::from_retained_ptr(obj)
        }
    }
}

pub trait INSMutableCopying : INSObject {
    type Output: INSObject;

    fn mutable_copy(&self) -> Id<Self::Output> {
        unsafe {
            let obj: *mut Self::Output = msg_send![self, mutableCopy];
            Id::from_retained_ptr(obj)
        }
    }
}

static UTF8_ENCODING: usize = 4;

pub trait INSString : INSObject {
    fn len(&self) -> usize {
        unsafe {
            msg_send![self, lengthOfBytesUsingEncoding:UTF8_ENCODING]
        }
    }

    fn as_str(&self) -> &str {
        let bytes = unsafe {
            let bytes: *const i8 = msg_send![self, UTF8String];
            bytes as *const u8
        };
        let len = self.len();
        unsafe {
            let bytes = slice::from_raw_parts(bytes, len);
            str::from_utf8(bytes).unwrap()
        }
    }

    fn from_str(string: &str) -> Id<Self> {
        let cls = <Self as INSObject>::class();
        unsafe {
            let obj: *mut Self = msg_send![cls, alloc];
            let obj: *mut Self = msg_send![obj, initWithBytes:string.as_ptr()
                                                       length:string.len()
                                                     encoding:UTF8_ENCODING];
            Id::from_retained_ptr(obj)
        }
    }
}

object_struct!(NSString);

impl INSString for NSString { }

impl INSCopying for NSString {
    type Output = NSString;
}

impl Str for NSString {
    fn as_slice(&self) -> &str {
        self.as_str()
    }
}

#[cfg(test)]
mod tests {
    use objc::Id;
    use super::{INSCopying, INSString, NSString};

    #[test]
    fn test_utf8() {
        let expected = "ประเทศไทย中华Việt Nam";
        let s: Id<NSString> = INSString::from_str(expected);
        assert!(s.len() == expected.len());
        assert!(s.as_str() == expected);
    }

    #[test]
    fn test_interior_nul() {
        let expected = "Hello\0World";
        let s: Id<NSString> = INSString::from_str(expected);
        assert!(s.len() == expected.len());
        assert!(s.as_str() == expected);
    }

    #[test]
    fn test_copy() {
        let s: Id<NSString> = INSString::from_str("Hello!");
        let copied = s.copy();
        assert!(copied.as_str() == s.as_str());
    }
}
<|endoftext|>


<commit_before>use std::io;

use bytes::BytesMut;
use tokio_io::codec::{Decoder, Encoder};

use cmd::Command;
use error::Error;
use ftp::Answer;

pub struct BytesCodec;
pub struct FtpCodec;

impl Decoder for FtpCodec {
    type Item = Command;
    type Error = io::Error;

    fn decode(&mut self, buf: &mut BytesMut) -> io::Result<Option<Command>> {
        if let Some(index) = find_crlf(buf) {
            let line = buf.split_to(index);
            buf.split_to(2); // Remove \r\n.
            Command::new(line.to_vec())
                .map(|command| Some(command))
                .map_err(Error::to_io_error)
        } else {
            Ok(None)
        }
    }
}

impl Encoder for FtpCodec {
    type Item = Answer;
    type Error = io::Error;

    fn encode(&mut self, answer: Answer, buf: &mut BytesMut) -> io::Result<()> {
        // TODO: avoid using String?
        let answer =
            if answer.message.is_empty() {
                format!("{}\r\n", answer.code as u32)
            } else {
                format!("{} {}\r\n", answer.code as u32, answer.message)
            };
        buf.extend(answer.as_bytes());
        Ok(())
    }
}

impl Decoder for BytesCodec {
    type Item = Vec<u8>;
    type Error = io::Error;

    fn decode(&mut self, buf: &mut BytesMut) -> io::Result<Option<Vec<u8>>> {
        if buf.len() == 0 {
            return Ok(None);
        }
        let data = buf.to_vec();
        buf.clear();
        Ok(Some(data))
    }
}

impl Encoder for BytesCodec {
    type Item = Vec<u8>;
    type Error = io::Error;

    fn encode(&mut self, data: Vec<u8>, buf: &mut BytesMut) -> io::Result<()> {
        buf.extend(data);
        Ok(())
    }
}

fn find_crlf(buf: &mut BytesMut) -> Option<usize> {
    buf.windows(2)
        .position(|bytes| bytes == b"\r\n")
}
<commit_msg>Switch to Vec<u8> for FtpCodec encoder<commit_after>use std::io::{self, Write};

use bytes::BytesMut;
use tokio_io::codec::{Decoder, Encoder};

use cmd::Command;
use error::Error;
use ftp::Answer;

pub struct BytesCodec;
pub struct FtpCodec;

impl Decoder for FtpCodec {
    type Item = Command;
    type Error = io::Error;

    fn decode(&mut self, buf: &mut BytesMut) -> io::Result<Option<Command>> {
        if let Some(index) = find_crlf(buf) {
            let line = buf.split_to(index);
            buf.split_to(2); // Remove \r\n.
            Command::new(line.to_vec())
                .map(|command| Some(command))
                .map_err(Error::to_io_error)
        } else {
            Ok(None)
        }
    }
}

impl Encoder for FtpCodec {
    type Item = Answer;
    type Error = io::Error;

    fn encode(&mut self, answer: Answer, buf: &mut BytesMut) -> io::Result<()> {
        let mut buffer = vec![];
        if answer.message.is_empty() {
            write!(buffer, "{}\r\n", answer.code as u32)?;
        } else {
            write!(buffer, "{} {}\r\n", answer.code as u32, answer.message)?;
        }
        buf.extend(&buffer);
        Ok(())
    }
}

impl Decoder for BytesCodec {
    type Item = Vec<u8>;
    type Error = io::Error;

    fn decode(&mut self, buf: &mut BytesMut) -> io::Result<Option<Vec<u8>>> {
        if buf.len() == 0 {
            return Ok(None);
        }
        let data = buf.to_vec();
        buf.clear();
        Ok(Some(data))
    }
}

impl Encoder for BytesCodec {
    type Item = Vec<u8>;
    type Error = io::Error;

    fn encode(&mut self, data: Vec<u8>, buf: &mut BytesMut) -> io::Result<()> {
        buf.extend(data);
        Ok(())
    }
}

fn find_crlf(buf: &mut BytesMut) -> Option<usize> {
    buf.windows(2)
        .position(|bytes| bytes == b"\r\n")
}
<|endoftext|>


<commit_before>use std::fmt;
use std::ops::{Add, Sub, Mul};
use std::iter::{Iterator,IntoIterator};

#[derive(Debug, Copy, Clone)]
pub struct Color {
    r: u8,
    g: u8,
    b: u8,
    next: NextColor,
}

#[derive(Debug, Copy, Clone)]
pub enum NextColor {
    Red, Green, Blue, Done
}

impl Iterator for Color{
    type Item = u8;

    fn next(&mut self) -> Option<Self::Item> {
        match self.next {
            NextColor::Red => {
                self.next = NextColor::Green;
                Some(self.r)
            }
            NextColor::Green => {
                self.next = NextColor::Blue;
                Some(self.g)
            }
            NextColor::Blue => {
                self.next = NextColor::Done;
                Some(self.b)
            }
            NextColor::Done => None
        }
    }
}

impl Color {
    pub fn new(r: u8, g: u8, b: u8) -> Color {
        Color { r: r, g: g, b: b, next: NextColor::Red }
    }

    pub fn new_f64(r: f64, g: f64, b: f64) -> Color {
        Color::new(Color::clamp((r * 255.0) as i16),
                   Color::clamp((g * 255.0) as i16),
                   Color::clamp((b * 255.0) as i16))
    }

    #[inline(always)]
    pub fn r(&self) -> u8 {
        self.r
    }

    #[inline(always)]
    pub fn r_f64(&self) -> f64 {
        self.r() as f64 / 255.0
    }

    #[inline(always)]
    pub fn g(&self) -> u8 {
        self.g
    }

    #[inline(always)]
    pub fn g_f64(&self) -> f64 {
        self.g() as f64 / 255.0
    }

    #[inline(always)]
    pub fn b(&self) -> u8 {
        self.b
    }

    #[inline(always)]
    pub fn b_f64(&self) -> f64 {
        self.b() as f64 / 255.0
    }

    #[inline(always)]
    pub fn as_u32(&self) -> u32 {
        0xFF000000
            & (self.r as u32)
            & (self.g as u32) << 8
            & (self.b as u32) << 16
    }

    fn clamp(value: i16) -> u8 {
        if value < 0 {
            return 0;
        }

        if value > (u8::max_value() as i16) {
            return u8::max_value();
        }

        value as u8
    }
}

impl fmt::Display for Color {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "(r: {}, g: {}, b: {})", self.r(), self.g(), self.b())
    }
}

// Math

impl Add for Color {
    type Output = Color;

    fn add(self, other: Color) -> Color {
        let r = Color::clamp((self.r() as i16) + (other.r() as i16));
        let g = Color::clamp((self.g() as i16) + (other.g() as i16));
        let b = Color::clamp((self.b() as i16) + (other.b() as i16));

        Color::new(r, g, b)
    }
}

impl Sub for Color {
    type Output = Color;

    fn sub(self, other: Color) -> Color {
        let r = Color::clamp((self.r() as i16) - (other.r() as i16));
        let g = Color::clamp((self.g() as i16) - (other.g() as i16));
        let b = Color::clamp((self.b() as i16) - (other.b() as i16));

        Color::new(r, g, b)
    }
}

impl Mul for Color {
    type Output = Color;

    fn mul(self, other: Color) -> Color {
        let r = self.r_f64() * other.r_f64();
        let g = self.g_f64() * other.g_f64();
        let b = self.b_f64() * other.b_f64();

        Color::new_f64(r, g, b)
    }
}

impl Mul<f64> for Color {
    type Output = Color;

    fn mul(self, other: f64) -> Color {
        let r = self.r_f64() * other;
        let g = self.g_f64() * other;
        let b = self.b_f64() * other;

        Color::new_f64(r, g, b)
    }
}

// Factor methods for common colors
macro_rules! define_color {
    ($name: ident, $r: expr, $g: expr, $b: expr) => (
        #[inline(always)]
        pub fn $name() -> Color {
            Color::new($r, $g, $b)
        }
    )
}

impl Color {
    define_color!(black, 0, 0, 0);
    define_color!(white, 0xFF, 0xFF, 0xFF);
    define_color!(red, 0xFF, 0, 0);
    define_color!(green, 0, 0xFF, 0);
    define_color!(blue, 0, 0, 0xFF);
}
<commit_msg>i32 is faster than i16<commit_after>use std::fmt;
use std::ops::{Add, Sub, Mul};
use std::iter::Iterator;

#[derive(Debug, Copy, Clone)]
pub struct Color {
    r: u8,
    g: u8,
    b: u8,
    next: NextColor,
}

#[derive(Debug, Copy, Clone)]
pub enum NextColor {
    Red, Green, Blue, Done
}

impl Iterator for Color{
    type Item = u8;

    fn next(&mut self) -> Option<Self::Item> {
        match self.next {
            NextColor::Red => {
                self.next = NextColor::Green;
                Some(self.r)
            }
            NextColor::Green => {
                self.next = NextColor::Blue;
                Some(self.g)
            }
            NextColor::Blue => {
                self.next = NextColor::Done;
                Some(self.b)
            }
            NextColor::Done => None
        }
    }
}

impl Color {
    pub fn new(r: u8, g: u8, b: u8) -> Color {
        Color { r: r, g: g, b: b, next: NextColor::Red }
    }

    pub fn new_f64(r: f64, g: f64, b: f64) -> Color {
        Color::new(Color::clamp((r * 255.0) as i32),
                   Color::clamp((g * 255.0) as i32),
                   Color::clamp((b * 255.0) as i32))
    }

    #[inline(always)]
    pub fn r(&self) -> u8 {
        self.r
    }

    #[inline(always)]
    pub fn r_f64(&self) -> f64 {
        self.r() as f64 / 255.0
    }

    #[inline(always)]
    pub fn g(&self) -> u8 {
        self.g
    }

    #[inline(always)]
    pub fn g_f64(&self) -> f64 {
        self.g() as f64 / 255.0
    }

    #[inline(always)]
    pub fn b(&self) -> u8 {
        self.b
    }

    #[inline(always)]
    pub fn b_f64(&self) -> f64 {
        self.b() as f64 / 255.0
    }

    #[inline(always)]
    pub fn as_u32(&self) -> u32 {
        0xFF000000
            & (self.r as u32)
            & (self.g as u32) << 8
            & (self.b as u32) << 16
    }

    fn clamp(value: i32) -> u8 {
        match value {
            v if v < 0 => 0,
            v if v > (u8::max_value() as i32) => u8::max_value(),
            v => v as u8
        }
    }
}

impl fmt::Display for Color {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "(r: {}, g: {}, b: {})", self.r(), self.g(), self.b())
    }
}

// Math

impl Add for Color {
    type Output = Color;

    fn add(self, other: Color) -> Color {
        let f = |f: fn(&Color)->u8| Color::clamp((f(&self) as i32) + (f(&other) as i32));

        Color::new(f(Color::r), f(Color::g), f(Color::b))
    }
}

impl Sub for Color {
    type Output = Color;

    fn sub(self, other: Color) -> Color {
        let r = Color::clamp((self.r() as i32) - (other.r() as i32));
        let g = Color::clamp((self.g() as i32) - (other.g() as i32));
        let b = Color::clamp((self.b() as i32) - (other.b() as i32));

        Color::new(r, g, b)
    }
}

impl Mul for Color {
    type Output = Color;

    fn mul(self, other: Color) -> Color {
        let r = self.r_f64() * other.r_f64();
        let g = self.g_f64() * other.g_f64();
        let b = self.b_f64() * other.b_f64();

        Color::new_f64(r, g, b)
    }
}

impl Mul<f64> for Color {
    type Output = Color;

    fn mul(self, other: f64) -> Color {
        let r = self.r_f64() * other;
        let g = self.g_f64() * other;
        let b = self.b_f64() * other;

        Color::new_f64(r, g, b)
    }
}

// Factor methods for common colors
macro_rules! define_color {
    ($name: ident, $r: expr, $g: expr, $b: expr) => (
        #[inline(always)]
        pub fn $name() -> Color {
            Color::new($r, $g, $b)
        }
    )
}

impl Color {
    define_color!(black, 0, 0, 0);
    define_color!(white, 0xFF, 0xFF, 0xFF);
    define_color!(red, 0xFF, 0, 0);
    define_color!(green, 0, 0xFF, 0);
    define_color!(blue, 0, 0, 0xFF);
}
<|endoftext|>


<commit_before>//! Graphics draw state.

/// Graphics draw state used for blending, clipping and stencil rendering.
#[derive(Copy, Clone, PartialEq, Debug, PartialOrd)]
pub struct DrawState {
    /// Scissor mask to use. If set, no pixel outside of this
    /// rectangle (in screen space) will be written to as a result of rendering.
    pub scissor: Option<[u32; 4]>,
    /// Stencil test to use. If None, no stencil testing is done.
    pub stencil: Option<Stencil>,
    /// Blend function to use. If None, blending is disabled.
    pub blend: Option<Blend>,
}

impl Default for DrawState {
    fn default() -> Self {
        DrawState::new_alpha()
    }
}

impl DrawState {
    /// Uses alpha blending.
    pub fn new_alpha() -> DrawState {
        DrawState {
            blend: Some(Blend::Alpha),
            stencil: None,
            scissor: None,
        }
    }

    /// Draws to stencil buffer with value 255.
    /// This can be used for clipping.
    pub fn new_clip() -> DrawState {
        DrawState {
            blend: Some(Blend::Alpha),
            stencil: Some(Stencil::Clip(255)),
            scissor: None,
        }
    }

    /// Tests against stencil buffer with value 255.
    /// Draws inside the shape defined by stencil buffer.
    pub fn new_inside() -> DrawState {
        DrawState {
            blend: Some(Blend::Alpha),
            stencil: Some(Stencil::Inside(255)),
            scissor: None,
        }
    }

    /// Tests against stencil buffer with value 255.
    /// Draws outside the shape defined by stencil buffer.
    pub fn new_outside() -> DrawState {
        DrawState {
            blend: Some(Blend::Alpha),
            stencil: Some(Stencil::Outside(255)),
            scissor: None,
        }
    }

    /// Sets blending.
    pub fn blend(mut self, blend: Blend) -> DrawState {
        self.blend = Some(blend);
        self
    }

    /// Sets scissor `[x, y, w, h]`.
    pub fn scissor(mut self, scissor: [u32; 4]) -> DrawState {
        self.scissor = Some(scissor);
        self
    }
}

/// The blend setting to use when drawing.
///
/// Using presets since some backends need one pipeline state object instance
/// per blending technique.
#[derive(Copy, Clone, Debug, PartialEq, PartialOrd)]
pub enum Blend {
    /// Alpha blending (allows semi-transparent pixels).
    ///
    /// ```ignore
    /// new_dest_color = src_color * src_alpha + dest_color * (1 - src_alpha)
    /// new_dest_alpha = src_alpha + dest_alpha
    /// ```
    Alpha,
    /// Additive blending.
    ///
    /// ```ignore
    /// new_dest_color = src_color + dest_color
    /// new_dest_alpha = src_alpha + dest_alpha
    /// ```
    Add,
    /// Multiply color components.
    ///
    /// ```ignore
    /// new_dest_color = src_color * dest_color
    /// new_dest_alpha = src_alpha * dest_alpha
    /// ```
    Multiply,
    /// Invert colors when rendering a white shape.
    ///
    /// ```ignore
    /// new_dest_color = ref_color - src_color
    /// new_dest_alpha = dest_alpha
    /// ```
    ///
    /// When combining two fragments, subtract the destination color from a constant color
    /// using the source color as weight. Has an invert effect with the constant color
    /// as base and source color controlling displacement from the base color.
    /// A white source color and a white value results in plain invert.
    /// The output alpha is same as destination alpha.
    Invert,
}

/// Stencil buffer settings.
#[derive(Copy, Clone, Debug, PartialEq, PartialOrd)]
pub enum Stencil {
    /// Draw to stencil buffer.
    Clip(u8),
    /// Draw pixels that have stencil value.
    Inside(u8),
    /// Draw pixels that does not have stencil value.
    Outside(u8),
}
<commit_msg>Ignore non-rust doctests<commit_after>//! Graphics draw state.

/// Graphics draw state used for blending, clipping and stencil rendering.
#[derive(Copy, Clone, PartialEq, Debug, PartialOrd)]
pub struct DrawState {
    /// Scissor mask to use. If set, no pixel outside of this
    /// rectangle (in screen space) will be written to as a result of rendering.
    pub scissor: Option<[u32; 4]>,
    /// Stencil test to use. If None, no stencil testing is done.
    pub stencil: Option<Stencil>,
    /// Blend function to use. If None, blending is disabled.
    pub blend: Option<Blend>,
}

impl Default for DrawState {
    fn default() -> Self {
        DrawState::new_alpha()
    }
}

impl DrawState {
    /// Uses alpha blending.
    pub fn new_alpha() -> DrawState {
        DrawState {
            blend: Some(Blend::Alpha),
            stencil: None,
            scissor: None,
        }
    }

    /// Draws to stencil buffer with value 255.
    /// This can be used for clipping.
    pub fn new_clip() -> DrawState {
        DrawState {
            blend: Some(Blend::Alpha),
            stencil: Some(Stencil::Clip(255)),
            scissor: None,
        }
    }

    /// Tests against stencil buffer with value 255.
    /// Draws inside the shape defined by stencil buffer.
    pub fn new_inside() -> DrawState {
        DrawState {
            blend: Some(Blend::Alpha),
            stencil: Some(Stencil::Inside(255)),
            scissor: None,
        }
    }

    /// Tests against stencil buffer with value 255.
    /// Draws outside the shape defined by stencil buffer.
    pub fn new_outside() -> DrawState {
        DrawState {
            blend: Some(Blend::Alpha),
            stencil: Some(Stencil::Outside(255)),
            scissor: None,
        }
    }

    /// Sets blending.
    pub fn blend(mut self, blend: Blend) -> DrawState {
        self.blend = Some(blend);
        self
    }

    /// Sets scissor `[x, y, w, h]`.
    pub fn scissor(mut self, scissor: [u32; 4]) -> DrawState {
        self.scissor = Some(scissor);
        self
    }
}

/// The blend setting to use when drawing.
///
/// Using presets since some backends need one pipeline state object instance
/// per blending technique.
#[derive(Copy, Clone, Debug, PartialEq, PartialOrd)]
pub enum Blend {
    /// Alpha blending (allows semi-transparent pixels).
    ///
    /// ```not_rust
    /// new_dest_color = src_color * src_alpha + dest_color * (1 - src_alpha)
    /// new_dest_alpha = src_alpha + dest_alpha
    /// ```
    Alpha,
    /// Additive blending.
    ///
    /// ```not_rust
    /// new_dest_color = src_color + dest_color
    /// new_dest_alpha = src_alpha + dest_alpha
    /// ```
    Add,
    /// Multiply color components.
    ///
    /// ```not_rust
    /// new_dest_color = src_color * dest_color
    /// new_dest_alpha = src_alpha * dest_alpha
    /// ```
    Multiply,
    /// Invert colors when rendering a white shape.
    ///
    /// ```not_rust
    /// new_dest_color = ref_color - src_color
    /// new_dest_alpha = dest_alpha
    /// ```
    ///
    /// When combining two fragments, subtract the destination color from a constant color
    /// using the source color as weight. Has an invert effect with the constant color
    /// as base and source color controlling displacement from the base color.
    /// A white source color and a white value results in plain invert.
    /// The output alpha is same as destination alpha.
    Invert,
}

/// Stencil buffer settings.
#[derive(Copy, Clone, Debug, PartialEq, PartialOrd)]
pub enum Stencil {
    /// Draw to stencil buffer.
    Clip(u8),
    /// Draw pixels that have stencil value.
    Inside(u8),
    /// Draw pixels that does not have stencil value.
    Outside(u8),
}
<|endoftext|>


<commit_before>use std::default::Default;
use std::ops::Deref;

use docopt::Docopt;
use rustc_serialize;

pub fn parse() -> Args {
    Docopt::new(USAGE).and_then(|d| d.decode()).unwrap_or_else(
        |e| e.exit(),
    )
}

// Write the Docopt usage string.
static USAGE: &'static str = "
Usage: dora test [options] <file>
       dora [options] <file> [--] [<argument>...]
       dora (--version | --help)

Options:
    -h, --help              Shows this text
    --version               Shows version
    --emit-ast              Emits AST to stdout
    --emit-llvm             Emits initial LLVM IR to stdout
    --emit-asm=<fct>        Emits assembly code to stdout
    --emit-asm-file         Emits assembly code into file dora-<pid>.asm
    --emit-stubs            Emits generated stubs
    --emit-debug=<fct>      Emits debug instruction at beginning of functions
    --omit-bounds-check     Omit array index out of bounds checks
    --check                 Only type check given program
    --asm-syntax TYPE       Emits assembly with Intel or AT&T syntax
                            Allowed values: intel, att
    --enable-perf           Enable dump for perf
    --gc-events             Dump GC events
    --gc-stress             Collect garbage at every allocation
    --gc-stats              Print GC statistics
    --gc=<name>             Switch GC. Possible values: zero, copy (default), swiper

    --heap-size=<SIZE>       Set heap size
";

#[derive(Debug, RustcDecodable)]
pub struct Args {
    pub arg_argument: Option<Vec<String>>,
    pub arg_file: String,

    pub flag_emit_ast: bool,
    pub flag_emit_asm: Option<String>,
    pub flag_emit_asm_file: bool,
    pub flag_emit_llvm: bool,
    pub flag_emit_stubs: bool,
    pub flag_enable_perf: bool,
    pub flag_omit_bounds_check: bool,
    pub flag_version: bool,
    pub flag_emit_debug: Option<String>,
    pub flag_asm_syntax: Option<AsmSyntax>,
    pub flag_gc_events: bool,
    pub flag_gc_stress: bool,
    pub flag_gc_stats: bool,
    pub flag_gc: Option<CollectorName>,
    pub flag_heap_size: Option<MemSize>,
    pub flag_check: bool,

    pub cmd_test: bool,
}

impl Default for Args {
    fn default() -> Args {
        Args {
            arg_argument: None,
            arg_file: "".into(),

            flag_emit_ast: false,
            flag_emit_asm: None,
            flag_emit_asm_file: false,
            flag_emit_llvm: false,
            flag_emit_stubs: false,
            flag_emit_debug: None,
            flag_enable_perf: false,
            flag_omit_bounds_check: false,
            flag_version: false,
            flag_asm_syntax: None,
            flag_gc_events: false,
            flag_gc_stress: false,
            flag_gc_stats: false,
            flag_gc: None,
            flag_heap_size: None,
            flag_check: false,

            cmd_test: false,
        }
    }
}

#[derive(Copy, Clone, Debug, RustcDecodable)]
pub enum CollectorName {
    Zero,
    Copy,
    Swiper,
}

#[derive(Copy, Clone, Debug, RustcDecodable)]
pub enum AsmSyntax {
    Intel,
    Att,
}

#[derive(Copy, Clone, Debug)]
pub struct MemSize(usize);

impl Deref for MemSize {
    type Target = usize;

    fn deref(&self) -> &usize {
        &self.0
    }
}

impl rustc_serialize::Decodable for MemSize {
    fn decode<D: rustc_serialize::Decoder>(d: &mut D) -> Result<MemSize, D::Error> {
        let mut size = d.read_str()?;
        let suffix = if let Some(ch) = size.chars().last() {
            match ch {
                'k' | 'K' => 1024,
                'm' | 'M' => 1024 * 1024,
                'g' | 'G' => 1024 * 1024 * 1024,
                _ => 1,
            }
        } else {
            1
        };

        if suffix != 1 {
            size.pop();
        }

        match size.parse::<usize>() {
            Ok(size) => Ok(MemSize(size * suffix)),
            Err(_) => Err(d.error("cannot parse mem size")),
        }
    }
}
<commit_msg>introduce --opt for using optimizing compiler<commit_after>use std::default::Default;
use std::ops::Deref;

use docopt::Docopt;
use rustc_serialize;

pub fn parse() -> Args {
    Docopt::new(USAGE).and_then(|d| d.decode()).unwrap_or_else(
        |e| e.exit(),
    )
}

// Write the Docopt usage string.
static USAGE: &'static str = "
Usage: dora test [options] <file>
       dora [options] <file> [--] [<argument>...]
       dora (--version | --help)

Options:
    -h, --help              Shows this text
    --version               Shows version
    --emit-ast              Emits AST to stdout
    --emit-llvm             Emits initial LLVM IR to stdout
    --emit-asm=<fct>        Emits assembly code to stdout
    --emit-asm-file         Emits assembly code into file dora-<pid>.asm
    --emit-stubs            Emits generated stubs
    --emit-debug=<fct>      Emits debug instruction at beginning of functions
    --opt=<fct>             Use optimizing compiler for given functions
    --omit-bounds-check     Omit array index out of bounds checks
    --check                 Only type check given program
    --asm-syntax TYPE       Emits assembly with Intel or AT&T syntax
                            Allowed values: intel, att
    --enable-perf           Enable dump for perf
    --gc-events             Dump GC events
    --gc-stress             Collect garbage at every allocation
    --gc-stats              Print GC statistics
    --gc=<name>             Switch GC. Possible values: zero, copy (default), swiper

    --heap-size=<SIZE>       Set heap size
";

#[derive(Debug, RustcDecodable)]
pub struct Args {
    pub arg_argument: Option<Vec<String>>,
    pub arg_file: String,

    pub flag_emit_ast: bool,
    pub flag_emit_asm: Option<String>,
    pub flag_emit_asm_file: bool,
    pub flag_emit_llvm: bool,
    pub flag_emit_stubs: bool,
    pub flag_enable_perf: bool,
    pub flag_opt: Option<String>,
    pub flag_omit_bounds_check: bool,
    pub flag_version: bool,
    pub flag_emit_debug: Option<String>,
    pub flag_asm_syntax: Option<AsmSyntax>,
    pub flag_gc_events: bool,
    pub flag_gc_stress: bool,
    pub flag_gc_stats: bool,
    pub flag_gc: Option<CollectorName>,
    pub flag_heap_size: Option<MemSize>,
    pub flag_check: bool,

    pub cmd_test: bool,
}

impl Default for Args {
    fn default() -> Args {
        Args {
            arg_argument: None,
            arg_file: "".into(),

            flag_emit_ast: false,
            flag_emit_asm: None,
            flag_emit_asm_file: false,
            flag_emit_llvm: false,
            flag_emit_stubs: false,
            flag_emit_debug: None,
            flag_enable_perf: false,
            flag_opt: None,
            flag_omit_bounds_check: false,
            flag_version: false,
            flag_asm_syntax: None,
            flag_gc_events: false,
            flag_gc_stress: false,
            flag_gc_stats: false,
            flag_gc: None,
            flag_heap_size: None,
            flag_check: false,

            cmd_test: false,
        }
    }
}

#[derive(Copy, Clone, Debug, RustcDecodable)]
pub enum CollectorName {
    Zero,
    Copy,
    Swiper,
}

#[derive(Copy, Clone, Debug, RustcDecodable)]
pub enum AsmSyntax {
    Intel,
    Att,
}

#[derive(Copy, Clone, Debug)]
pub struct MemSize(usize);

impl Deref for MemSize {
    type Target = usize;

    fn deref(&self) -> &usize {
        &self.0
    }
}

impl rustc_serialize::Decodable for MemSize {
    fn decode<D: rustc_serialize::Decoder>(d: &mut D) -> Result<MemSize, D::Error> {
        let mut size = d.read_str()?;
        let suffix = if let Some(ch) = size.chars().last() {
            match ch {
                'k' | 'K' => 1024,
                'm' | 'M' => 1024 * 1024,
                'g' | 'G' => 1024 * 1024 * 1024,
                _ => 1,
            }
        } else {
            1
        };

        if suffix != 1 {
            size.pop();
        }

        match size.parse::<usize>() {
            Ok(size) => Ok(MemSize(size * suffix)),
            Err(_) => Err(d.error("cannot parse mem size")),
        }
    }
}
<|endoftext|>


<commit_before><commit_msg>revert<commit_after><|endoftext|>


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

use middle::def::*;
use middle::ty;
use util::ppaux;

use syntax::ast;
use syntax::visit::{self, Visitor};

struct CheckCrateVisitor<'a, 'tcx: 'a> {
    tcx: &'a ty::ctxt<'tcx>,
    in_const: bool
}

impl<'a, 'tcx> CheckCrateVisitor<'a, 'tcx> {
    fn with_const<F>(&mut self, in_const: bool, f: F) where
        F: FnOnce(&mut CheckCrateVisitor<'a, 'tcx>),
    {
        let was_const = self.in_const;
        self.in_const = in_const;
        f(self);
        self.in_const = was_const;
    }
    fn inside_const<F>(&mut self, f: F) where
        F: FnOnce(&mut CheckCrateVisitor<'a, 'tcx>),
    {
        self.with_const(true, f);
    }
}

impl<'a, 'tcx, 'v> Visitor<'v> for CheckCrateVisitor<'a, 'tcx> {
    fn visit_item(&mut self, i: &ast::Item) {
        match i.node {
            ast::ItemStatic(_, _, ref ex) |
            ast::ItemConst(_, ref ex) => {
                self.inside_const(|v| v.visit_expr(&**ex));
            }
            ast::ItemEnum(ref enum_definition, _) => {
                self.inside_const(|v| {
                    for var in enum_definition.variants.iter() {
                        if let Some(ref ex) = var.node.disr_expr {
                            v.visit_expr(&**ex);
                        }
                    }
                });
            }
            _ => self.with_const(false, |v| visit::walk_item(v, i))
        }
    }
    fn visit_pat(&mut self, p: &ast::Pat) {
        let is_const = match p.node {
            ast::PatLit(_) | ast::PatRange(..) => true,
            _ => false
        };
        self.with_const(is_const, |v| visit::walk_pat(v, p))
    }
    fn visit_expr(&mut self, ex: &ast::Expr) {
        if self.in_const {
            check_expr(self, ex);
        }
        visit::walk_expr(self, ex);
    }
}

pub fn check_crate(tcx: &ty::ctxt) {
    visit::walk_crate(&mut CheckCrateVisitor { tcx: tcx, in_const: false },
                      tcx.map.krate());
    tcx.sess.abort_if_errors();
}

fn check_expr(v: &mut CheckCrateVisitor, e: &ast::Expr) {
    match e.node {
        ast::ExprUnary(ast::UnDeref, _) => {}
        ast::ExprUnary(ast::UnUniq, _) => {
            span_err!(v.tcx.sess, e.span, E0010,
                      "cannot do allocations in constant expressions");
        }
        ast::ExprBinary(..) | ast::ExprUnary(..) => {
            let method_call = ty::MethodCall::expr(e.id);
            if v.tcx.method_map.borrow().contains_key(&method_call) {
                span_err!(v.tcx.sess, e.span, E0011,
                          "user-defined operators are not allowed in constant \
                           expressions");
            }
        }
        ast::ExprLit(_) => {}
        ast::ExprCast(ref from, _) => {
            let toty = ty::expr_ty(v.tcx, e);
            let fromty = ty::expr_ty(v.tcx, &**from);
            let is_legal_cast =
                ty::type_is_numeric(toty) ||
                ty::type_is_unsafe_ptr(toty) ||
                (ty::type_is_bare_fn(toty) && ty::type_is_bare_fn_item(fromty));
            if !is_legal_cast {
                span_err!(v.tcx.sess, e.span, E0012,
                          "can not cast to `{}` in a constant expression",
                          ppaux::ty_to_string(v.tcx, toty));
            }
            if ty::type_is_unsafe_ptr(fromty) && ty::type_is_numeric(toty) {
                span_err!(v.tcx.sess, e.span, E0018,
                          "can not cast a pointer to an integer in a constant \
                           expression");
            }
        }
        ast::ExprPath(ref pth) => {
            // NB: In the future you might wish to relax this slightly
            // to handle on-demand instantiation of functions via
            // foo::<bar> in a const. Currently that is only done on
            // a path in trans::callee that only works in block contexts.
            if !pth.segments.iter().all(|segment| segment.parameters.is_empty()) {
                span_err!(v.tcx.sess, e.span, E0013,
                          "paths in constants may only refer to items without \
                           type parameters");
            }
            match v.tcx.def_map.borrow()[e.id] {
                DefStatic(..) | DefConst(..) |
                DefFn(..) | DefStruct(_) |
                DefVariant(_, _, _) => {}

                def => {
                    debug!("(checking const) found bad def: {}", def);
                    span_err!(v.tcx.sess, e.span, E0014,
                              "paths in constants may only refer to constants \
                               or functions");
                }
            }
        }
        ast::ExprCall(ref callee, _) => {
            match v.tcx.def_map.borrow()[callee.id] {
                DefStruct(..) | DefVariant(..) => {}    // OK.
                _ => {
                    span_err!(v.tcx.sess, e.span, E0015,
                              "function calls in constants are limited to \
                               struct and enum constructors");
                }
            }
        }
        ast::ExprBlock(ref block) => {
            // Check all statements in the block
            for stmt in block.stmts.iter() {
                let block_span_err = |&: span|
                    span_err!(v.tcx.sess, span, E0016,
                              "blocks in constants are limited to items and \
                               tail expressions");
                match stmt.node {
                    ast::StmtDecl(ref decl, _) => {
                        match decl.node {
                            ast::DeclLocal(_) => block_span_err(decl.span),

                            // Item statements are allowed
                            ast::DeclItem(_) => {}
                        }
                    }
                    ast::StmtExpr(ref expr, _) => block_span_err(expr.span),
                    ast::StmtSemi(ref semi, _) => block_span_err(semi.span),
                    ast::StmtMac(..) => {
                        v.tcx.sess.span_bug(e.span, "unexpanded statement \
                                                     macro in const?!")
                    }
                }
            }
            if let Some(ref expr) = block.expr {
                check_expr(v, &**expr);
            }
        }
        ast::ExprVec(_) |
        ast::ExprAddrOf(ast::MutImmutable, _) |
        ast::ExprParen(..) |
        ast::ExprField(..) |
        ast::ExprTupField(..) |
        ast::ExprIndex(..) |
        ast::ExprTup(..) |
        ast::ExprRepeat(..) |
        ast::ExprStruct(..) => {}

        ast::ExprAddrOf(_, ref inner) => {
            match inner.node {
                // Mutable slices are allowed.
                ast::ExprVec(_) => {}
                _ => span_err!(v.tcx.sess, e.span, E0017,
                               "references in constants may only refer \
                                to immutable values")

            }
        }

        _ => span_err!(v.tcx.sess, e.span, E0019,
                       "constant contains unimplemented expression type")
    }
}
<commit_msg>rustc: check_const: avoid recursing into a block's tail expression twice.<commit_after>// Copyright 2012-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.

use middle::def::*;
use middle::ty;
use util::ppaux;

use syntax::ast;
use syntax::visit::{self, Visitor};

struct CheckCrateVisitor<'a, 'tcx: 'a> {
    tcx: &'a ty::ctxt<'tcx>,
    in_const: bool
}

impl<'a, 'tcx> CheckCrateVisitor<'a, 'tcx> {
    fn with_const<F>(&mut self, in_const: bool, f: F) where
        F: FnOnce(&mut CheckCrateVisitor<'a, 'tcx>),
    {
        let was_const = self.in_const;
        self.in_const = in_const;
        f(self);
        self.in_const = was_const;
    }
    fn inside_const<F>(&mut self, f: F) where
        F: FnOnce(&mut CheckCrateVisitor<'a, 'tcx>),
    {
        self.with_const(true, f);
    }
}

impl<'a, 'tcx, 'v> Visitor<'v> for CheckCrateVisitor<'a, 'tcx> {
    fn visit_item(&mut self, i: &ast::Item) {
        match i.node {
            ast::ItemStatic(_, _, ref ex) |
            ast::ItemConst(_, ref ex) => {
                self.inside_const(|v| v.visit_expr(&**ex));
            }
            ast::ItemEnum(ref enum_definition, _) => {
                self.inside_const(|v| {
                    for var in enum_definition.variants.iter() {
                        if let Some(ref ex) = var.node.disr_expr {
                            v.visit_expr(&**ex);
                        }
                    }
                });
            }
            _ => self.with_const(false, |v| visit::walk_item(v, i))
        }
    }
    fn visit_pat(&mut self, p: &ast::Pat) {
        let is_const = match p.node {
            ast::PatLit(_) | ast::PatRange(..) => true,
            _ => false
        };
        self.with_const(is_const, |v| visit::walk_pat(v, p))
    }
    fn visit_expr(&mut self, ex: &ast::Expr) {
        if self.in_const {
            check_expr(self, ex);
        }
        visit::walk_expr(self, ex);
    }
}

pub fn check_crate(tcx: &ty::ctxt) {
    visit::walk_crate(&mut CheckCrateVisitor { tcx: tcx, in_const: false },
                      tcx.map.krate());
    tcx.sess.abort_if_errors();
}

fn check_expr(v: &mut CheckCrateVisitor, e: &ast::Expr) {
    match e.node {
        ast::ExprUnary(ast::UnDeref, _) => {}
        ast::ExprUnary(ast::UnUniq, _) => {
            span_err!(v.tcx.sess, e.span, E0010,
                      "cannot do allocations in constant expressions");
        }
        ast::ExprBinary(..) | ast::ExprUnary(..) => {
            let method_call = ty::MethodCall::expr(e.id);
            if v.tcx.method_map.borrow().contains_key(&method_call) {
                span_err!(v.tcx.sess, e.span, E0011,
                          "user-defined operators are not allowed in constant \
                           expressions");
            }
        }
        ast::ExprLit(_) => {}
        ast::ExprCast(ref from, _) => {
            let toty = ty::expr_ty(v.tcx, e);
            let fromty = ty::expr_ty(v.tcx, &**from);
            let is_legal_cast =
                ty::type_is_numeric(toty) ||
                ty::type_is_unsafe_ptr(toty) ||
                (ty::type_is_bare_fn(toty) && ty::type_is_bare_fn_item(fromty));
            if !is_legal_cast {
                span_err!(v.tcx.sess, e.span, E0012,
                          "can not cast to `{}` in a constant expression",
                          ppaux::ty_to_string(v.tcx, toty));
            }
            if ty::type_is_unsafe_ptr(fromty) && ty::type_is_numeric(toty) {
                span_err!(v.tcx.sess, e.span, E0018,
                          "can not cast a pointer to an integer in a constant \
                           expression");
            }
        }
        ast::ExprPath(ref pth) => {
            // NB: In the future you might wish to relax this slightly
            // to handle on-demand instantiation of functions via
            // foo::<bar> in a const. Currently that is only done on
            // a path in trans::callee that only works in block contexts.
            if !pth.segments.iter().all(|segment| segment.parameters.is_empty()) {
                span_err!(v.tcx.sess, e.span, E0013,
                          "paths in constants may only refer to items without \
                           type parameters");
            }
            match v.tcx.def_map.borrow()[e.id] {
                DefStatic(..) | DefConst(..) |
                DefFn(..) | DefStruct(_) |
                DefVariant(_, _, _) => {}

                def => {
                    debug!("(checking const) found bad def: {}", def);
                    span_err!(v.tcx.sess, e.span, E0014,
                              "paths in constants may only refer to constants \
                               or functions");
                }
            }
        }
        ast::ExprCall(ref callee, _) => {
            match v.tcx.def_map.borrow()[callee.id] {
                DefStruct(..) | DefVariant(..) => {}    // OK.
                _ => {
                    span_err!(v.tcx.sess, e.span, E0015,
                              "function calls in constants are limited to \
                               struct and enum constructors");
                }
            }
        }
        ast::ExprBlock(ref block) => {
            // Check all statements in the block
            for stmt in block.stmts.iter() {
                let block_span_err = |&: span|
                    span_err!(v.tcx.sess, span, E0016,
                              "blocks in constants are limited to items and \
                               tail expressions");
                match stmt.node {
                    ast::StmtDecl(ref decl, _) => {
                        match decl.node {
                            ast::DeclLocal(_) => block_span_err(decl.span),

                            // Item statements are allowed
                            ast::DeclItem(_) => {}
                        }
                    }
                    ast::StmtExpr(ref expr, _) => block_span_err(expr.span),
                    ast::StmtSemi(ref semi, _) => block_span_err(semi.span),
                    ast::StmtMac(..) => {
                        v.tcx.sess.span_bug(e.span, "unexpanded statement \
                                                     macro in const?!")
                    }
                }
            }
        }
        ast::ExprVec(_) |
        ast::ExprAddrOf(ast::MutImmutable, _) |
        ast::ExprParen(..) |
        ast::ExprField(..) |
        ast::ExprTupField(..) |
        ast::ExprIndex(..) |
        ast::ExprTup(..) |
        ast::ExprRepeat(..) |
        ast::ExprStruct(..) => {}

        ast::ExprAddrOf(_, ref inner) => {
            match inner.node {
                // Mutable slices are allowed.
                ast::ExprVec(_) => {}
                _ => span_err!(v.tcx.sess, e.span, E0017,
                               "references in constants may only refer \
                                to immutable values")

            }
        }

        _ => span_err!(v.tcx.sess, e.span, E0019,
                       "constant contains unimplemented expression type")
    }
}
<|endoftext|>


<commit_before>use rustc_hir::Mutability;
use rustc_index::bit_set::HybridBitSet;
use rustc_middle::mir::visit::{MutVisitor, PlaceContext, Visitor};
use rustc_middle::mir::{self, BasicBlock, Local, Location};
use rustc_middle::ty::TyCtxt;

use crate::transform::{MirPass, MirSource};

/// This pass looks for MIR that always copies the same local into the return place and eliminates
/// the copy by renaming all uses of that local to `_0`.
///
/// This allows LLVM to perform an optimization similar to the named return value optimization
/// (NRVO) that is guaranteed in C++. This avoids a stack allocation and `memcpy` for the
/// relatively common pattern of allocating a buffer on the stack, mutating it, and returning it by
/// value like so:
///
/// ```rust
/// fn foo(init: fn(&mut [u8; 1024])) -> [u8; 1024] {
///     let mut buf = [0; 1024];
///     init(&mut buf);
///     buf
/// }
/// ```
///
/// For now, this pass is very simple and only capable of eliminating a single copy. A more general
/// version of copy propagation, such as the one based on non-overlapping live ranges in [#47954] and
/// [#71003], could yield even more benefits.
///
/// [#47954]: https://github.com/rust-lang/rust/pull/47954
/// [#71003]: https://github.com/rust-lang/rust/pull/71003
pub struct RenameReturnPlace;

impl<'tcx> MirPass<'tcx> for RenameReturnPlace {
    fn run_pass(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body: &mut mir::Body<'tcx>) {
        if tcx.sess.opts.debugging_opts.mir_opt_level == 0 {
            return;
        }

        let returned_local = match local_eligible_for_nrvo(body) {
            Some(l) => l,
            None => {
                debug!("`{:?}` was ineligible for NRVO", src.def_id());
                return;
            }
        };

        // Sometimes, the return place is assigned a local of a different but coercable type, for
        // example `&T` instead of `&mut T`. Overwriting the `LocalInfo` for the return place would
        // result in it having an incorrect type. Although this doesn't seem to cause a problem in
        // codegen, bail out anyways since it happens so rarely.
        let ret_ty = body.local_decls[mir::RETURN_PLACE].ty;
        let assigned_ty = body.local_decls[returned_local].ty;
        if ret_ty != assigned_ty {
            debug!("`{:?}` was eligible for NRVO but for type mismatch", src.def_id());
            debug!("typeof(_0) != typeof({:?}); {:?} != {:?}", returned_local, ret_ty, assigned_ty);
            return;
        }

        debug!(
            "`{:?}` was eligible for NRVO, making {:?} the return place",
            src.def_id(),
            returned_local
        );

        RenameToReturnPlace { tcx, to_rename: returned_local }.visit_body(body);

        // Clean up the `NOP`s we inserted for statements made useless by our renaming.
        for block_data in body.basic_blocks_mut() {
            block_data.statements.retain(|stmt| stmt.kind != mir::StatementKind::Nop);
        }

        // Overwrite the debuginfo of `_0` with that of the renamed local.
        let (renamed_decl, ret_decl) =
            body.local_decls.pick2_mut(returned_local, mir::RETURN_PLACE);
        ret_decl.clone_from(renamed_decl);

        // The return place is always mutable.
        ret_decl.mutability = Mutability::Mut;
    }
}

/// MIR that is eligible for the NRVO must fulfill two conditions:
///   1. The return place must not be read prior to the `Return` terminator.
///   2. A simple assignment of a whole local to the return place (e.g., `_0 = _1`) must be the
///      only definition of the return place reaching the `Return` terminator.
///
/// If the MIR fulfills both these conditions, this function returns the `Local` that is assigned
/// to the return place along all possible paths through the control-flow graph.
fn local_eligible_for_nrvo(body: &mut mir::Body<'_>) -> Option<Local> {
    if IsReturnPlaceRead::run(body) {
        return None;
    }

    let mut copied_to_return_place = None;
    for block in body.basic_blocks().indices() {
        // Look for blocks with a `Return` terminator.
        if !matches!(body[block].terminator().kind, mir::TerminatorKind::Return) {
            continue;
        }

        // Look for an assignment of a single local to the return place prior to the `Return`.
        let returned_local = find_local_assigned_to_return_place(block, body)?;
        match body.local_kind(returned_local) {
            // FIXME: Can we do this for arguments as well?
            mir::LocalKind::Arg => return None,

            mir::LocalKind::ReturnPointer => bug!("Return place was assigned to itself?"),
            mir::LocalKind::Var | mir::LocalKind::Temp => {}
        }

        // If multiple different locals are copied to the return place. We can't pick a
        // single one to rename.
        if copied_to_return_place.map_or(false, |old| old != returned_local) {
            return None;
        }

        copied_to_return_place = Some(returned_local);
    }

    return copied_to_return_place;
}

fn find_local_assigned_to_return_place(
    start: BasicBlock,
    body: &mut mir::Body<'_>,
) -> Option<Local> {
    let mut block = start;
    let mut seen = HybridBitSet::new_empty(body.basic_blocks().len());

    // Iterate as long as `block` has exactly one predecessor that we have not yet visited.
    while seen.insert(block) {
        trace!("Looking for assignments to `_0` in {:?}", block);

        let local = body[block].statements.iter().rev().find_map(as_local_assigned_to_return_place);
        if local.is_some() {
            return local;
        }

        match body.predecessors()[block].as_slice() {
            &[pred] => block = pred,
            _ => return None,
        }
    }

    return None;
}

// If this statement is an assignment of an unprojected local to the return place,
// return that local.
fn as_local_assigned_to_return_place(stmt: &mir::Statement<'_>) -> Option<Local> {
    if let mir::StatementKind::Assign(box (lhs, rhs)) = &stmt.kind {
        if lhs.as_local() == Some(mir::RETURN_PLACE) {
            if let mir::Rvalue::Use(mir::Operand::Copy(rhs) | mir::Operand::Move(rhs)) = rhs {
                return rhs.as_local();
            }
        }
    }

    None
}

struct RenameToReturnPlace<'tcx> {
    to_rename: Local,
    tcx: TyCtxt<'tcx>,
}

/// Replaces all uses of `self.to_rename` with `_0`.
impl MutVisitor<'tcx> for RenameToReturnPlace<'tcx> {
    fn tcx(&self) -> TyCtxt<'tcx> {
        self.tcx
    }

    fn visit_statement(&mut self, stmt: &mut mir::Statement<'tcx>, loc: Location) {
        // Remove assignments of the local being replaced to the return place, since it is now the
        // return place:
        //     _0 = _1
        if as_local_assigned_to_return_place(stmt) == Some(self.to_rename) {
            stmt.kind = mir::StatementKind::Nop;
            return;
        }

        // Remove storage annotations for the local being replaced:
        //     StorageLive(_1)
        if let mir::StatementKind::StorageLive(local) | mir::StatementKind::StorageDead(local) =
            stmt.kind
        {
            if local == self.to_rename {
                stmt.kind = mir::StatementKind::Nop;
                return;
            }
        }

        self.super_statement(stmt, loc)
    }

    fn visit_terminator(&mut self, terminator: &mut mir::Terminator<'tcx>, loc: Location) {
        // Ignore the implicit "use" of the return place in a `Return` statement.
        if let mir::TerminatorKind::Return = terminator.kind {
            return;
        }

        self.super_terminator(terminator, loc);
    }

    fn visit_local(&mut self, l: &mut Local, _: PlaceContext, _: Location) {
        assert_ne!(*l, mir::RETURN_PLACE);
        if *l == self.to_rename {
            *l = mir::RETURN_PLACE;
        }
    }
}

struct IsReturnPlaceRead(bool);

impl IsReturnPlaceRead {
    fn run(body: &mir::Body<'_>) -> bool {
        let mut vis = IsReturnPlaceRead(false);
        vis.visit_body(body);
        vis.0
    }
}

impl Visitor<'tcx> for IsReturnPlaceRead {
    fn visit_local(&mut self, &l: &Local, ctxt: PlaceContext, _: Location) {
        if l == mir::RETURN_PLACE && ctxt.is_use() && !ctxt.is_place_assignment() {
            self.0 = true;
        }
    }

    fn visit_terminator(&mut self, terminator: &mir::Terminator<'tcx>, loc: Location) {
        // Ignore the implicit "use" of the return place in a `Return` statement.
        if let mir::TerminatorKind::Return = terminator.kind {
            return;
        }

        self.super_terminator(terminator, loc);
    }
}
<commit_msg>Perform MIR NRVO even if types don't match<commit_after>use rustc_hir::Mutability;
use rustc_index::bit_set::HybridBitSet;
use rustc_middle::mir::visit::{MutVisitor, PlaceContext, Visitor};
use rustc_middle::mir::{self, BasicBlock, Local, Location};
use rustc_middle::ty::TyCtxt;

use crate::transform::{MirPass, MirSource};

/// This pass looks for MIR that always copies the same local into the return place and eliminates
/// the copy by renaming all uses of that local to `_0`.
///
/// This allows LLVM to perform an optimization similar to the named return value optimization
/// (NRVO) that is guaranteed in C++. This avoids a stack allocation and `memcpy` for the
/// relatively common pattern of allocating a buffer on the stack, mutating it, and returning it by
/// value like so:
///
/// ```rust
/// fn foo(init: fn(&mut [u8; 1024])) -> [u8; 1024] {
///     let mut buf = [0; 1024];
///     init(&mut buf);
///     buf
/// }
/// ```
///
/// For now, this pass is very simple and only capable of eliminating a single copy. A more general
/// version of copy propagation, such as the one based on non-overlapping live ranges in [#47954] and
/// [#71003], could yield even more benefits.
///
/// [#47954]: https://github.com/rust-lang/rust/pull/47954
/// [#71003]: https://github.com/rust-lang/rust/pull/71003
pub struct RenameReturnPlace;

impl<'tcx> MirPass<'tcx> for RenameReturnPlace {
    fn run_pass(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body: &mut mir::Body<'tcx>) {
        if tcx.sess.opts.debugging_opts.mir_opt_level == 0 {
            return;
        }

        let returned_local = match local_eligible_for_nrvo(body) {
            Some(l) => l,
            None => {
                debug!("`{:?}` was ineligible for NRVO", src.def_id());
                return;
            }
        };

        debug!(
            "`{:?}` was eligible for NRVO, making {:?} the return place",
            src.def_id(),
            returned_local
        );

        RenameToReturnPlace { tcx, to_rename: returned_local }.visit_body(body);

        // Clean up the `NOP`s we inserted for statements made useless by our renaming.
        for block_data in body.basic_blocks_mut() {
            block_data.statements.retain(|stmt| stmt.kind != mir::StatementKind::Nop);
        }

        // Overwrite the debuginfo of `_0` with that of the renamed local.
        let (renamed_decl, ret_decl) =
            body.local_decls.pick2_mut(returned_local, mir::RETURN_PLACE);

        // Sometimes, the return place is assigned a local of a different but coercable type, for
        // example `&mut T` instead of `&T`. Overwriting the `LocalInfo` for the return place means
        // its type may no longer match the return type of its function. This doesn't cause a
        // problem in codegen because these two types are layout-compatible, but may be unexpected.
        debug!("_0: {:?} = {:?}: {:?}", ret_decl.ty, returned_local, renamed_decl.ty);
        ret_decl.clone_from(renamed_decl);

        // The return place is always mutable.
        ret_decl.mutability = Mutability::Mut;
    }
}

/// MIR that is eligible for the NRVO must fulfill two conditions:
///   1. The return place must not be read prior to the `Return` terminator.
///   2. A simple assignment of a whole local to the return place (e.g., `_0 = _1`) must be the
///      only definition of the return place reaching the `Return` terminator.
///
/// If the MIR fulfills both these conditions, this function returns the `Local` that is assigned
/// to the return place along all possible paths through the control-flow graph.
fn local_eligible_for_nrvo(body: &mut mir::Body<'_>) -> Option<Local> {
    if IsReturnPlaceRead::run(body) {
        return None;
    }

    let mut copied_to_return_place = None;
    for block in body.basic_blocks().indices() {
        // Look for blocks with a `Return` terminator.
        if !matches!(body[block].terminator().kind, mir::TerminatorKind::Return) {
            continue;
        }

        // Look for an assignment of a single local to the return place prior to the `Return`.
        let returned_local = find_local_assigned_to_return_place(block, body)?;
        match body.local_kind(returned_local) {
            // FIXME: Can we do this for arguments as well?
            mir::LocalKind::Arg => return None,

            mir::LocalKind::ReturnPointer => bug!("Return place was assigned to itself?"),
            mir::LocalKind::Var | mir::LocalKind::Temp => {}
        }

        // If multiple different locals are copied to the return place. We can't pick a
        // single one to rename.
        if copied_to_return_place.map_or(false, |old| old != returned_local) {
            return None;
        }

        copied_to_return_place = Some(returned_local);
    }

    return copied_to_return_place;
}

fn find_local_assigned_to_return_place(
    start: BasicBlock,
    body: &mut mir::Body<'_>,
) -> Option<Local> {
    let mut block = start;
    let mut seen = HybridBitSet::new_empty(body.basic_blocks().len());

    // Iterate as long as `block` has exactly one predecessor that we have not yet visited.
    while seen.insert(block) {
        trace!("Looking for assignments to `_0` in {:?}", block);

        let local = body[block].statements.iter().rev().find_map(as_local_assigned_to_return_place);
        if local.is_some() {
            return local;
        }

        match body.predecessors()[block].as_slice() {
            &[pred] => block = pred,
            _ => return None,
        }
    }

    return None;
}

// If this statement is an assignment of an unprojected local to the return place,
// return that local.
fn as_local_assigned_to_return_place(stmt: &mir::Statement<'_>) -> Option<Local> {
    if let mir::StatementKind::Assign(box (lhs, rhs)) = &stmt.kind {
        if lhs.as_local() == Some(mir::RETURN_PLACE) {
            if let mir::Rvalue::Use(mir::Operand::Copy(rhs) | mir::Operand::Move(rhs)) = rhs {
                return rhs.as_local();
            }
        }
    }

    None
}

struct RenameToReturnPlace<'tcx> {
    to_rename: Local,
    tcx: TyCtxt<'tcx>,
}

/// Replaces all uses of `self.to_rename` with `_0`.
impl MutVisitor<'tcx> for RenameToReturnPlace<'tcx> {
    fn tcx(&self) -> TyCtxt<'tcx> {
        self.tcx
    }

    fn visit_statement(&mut self, stmt: &mut mir::Statement<'tcx>, loc: Location) {
        // Remove assignments of the local being replaced to the return place, since it is now the
        // return place:
        //     _0 = _1
        if as_local_assigned_to_return_place(stmt) == Some(self.to_rename) {
            stmt.kind = mir::StatementKind::Nop;
            return;
        }

        // Remove storage annotations for the local being replaced:
        //     StorageLive(_1)
        if let mir::StatementKind::StorageLive(local) | mir::StatementKind::StorageDead(local) =
            stmt.kind
        {
            if local == self.to_rename {
                stmt.kind = mir::StatementKind::Nop;
                return;
            }
        }

        self.super_statement(stmt, loc)
    }

    fn visit_terminator(&mut self, terminator: &mut mir::Terminator<'tcx>, loc: Location) {
        // Ignore the implicit "use" of the return place in a `Return` statement.
        if let mir::TerminatorKind::Return = terminator.kind {
            return;
        }

        self.super_terminator(terminator, loc);
    }

    fn visit_local(&mut self, l: &mut Local, _: PlaceContext, _: Location) {
        assert_ne!(*l, mir::RETURN_PLACE);
        if *l == self.to_rename {
            *l = mir::RETURN_PLACE;
        }
    }
}

struct IsReturnPlaceRead(bool);

impl IsReturnPlaceRead {
    fn run(body: &mir::Body<'_>) -> bool {
        let mut vis = IsReturnPlaceRead(false);
        vis.visit_body(body);
        vis.0
    }
}

impl Visitor<'tcx> for IsReturnPlaceRead {
    fn visit_local(&mut self, &l: &Local, ctxt: PlaceContext, _: Location) {
        if l == mir::RETURN_PLACE && ctxt.is_use() && !ctxt.is_place_assignment() {
            self.0 = true;
        }
    }

    fn visit_terminator(&mut self, terminator: &mir::Terminator<'tcx>, loc: Location) {
        // Ignore the implicit "use" of the return place in a `Return` statement.
        if let mir::TerminatorKind::Return = terminator.kind {
            return;
        }

        self.super_terminator(terminator, loc);
    }
}
<|endoftext|>


<commit_before>use rusqlite::Connection;

#[derive(Debug)]
pub struct Job {
    pub id: i32,
    pub name: String,
}

trait JobModuleTrait {
    // Static method signature; `Self` refers to the implementor type.
    fn new(name: &'static str) -> Self;
    fn hashmap(conn: &Connection)-> Vec<Job>;
    // fn update_hashcache(&self, &hashcache) -> &'static str;
}

pub fn table_create_job(conn: &Connection) {
    let load_table = conn.execute("CREATE TABLE JOB (
                  id              INTEGER PRIMARY KEY ASC,
                  name            TEXT NOT NULL UNIQUE
                  )", &[]);
    if load_table.is_err() {
        println!("table_create_job Failed {:?}", load_table);
        return;
    }
    load_table.unwrap();
}

pub fn insert_job(conn: &Connection, name: String) {

    let me = Job {
        id: 0,
        name: name,
    };
    let load_instance = conn.execute("INSERT INTO JOB (name)
                  VALUES (?1)",
                 &[&me.name]);
    if load_instance.is_err() {
        return;
    }
    load_instance.unwrap();
}

pub fn list_job(conn: &Connection)-> Vec<Job> {
    let mut stmt = conn.prepare("SELECT id, name FROM JOB").unwrap();
    let wraped_job_iter = stmt.query_map(&[], |row| {
        Job {
            id: row.get(0),
            name: row.get(1)
        }
    });
    let mut items = Vec::<Job>::new();
    if wraped_job_iter.is_err() {
        return items;
    }
    let job_iter = wraped_job_iter.unwrap();
    for person in job_iter {
        items.push(person.unwrap());
    }
    return items;
}

pub fn pk_job_by_name(conn: &Connection, name: String, pk: &mut i32) {
    let mut stmt = conn.prepare("SELECT id, fk_fs_dir,name  FROM JOB WHERE name =?1").unwrap();
    let job_iter = stmt.query_map(&[&name], |row| {
        Job {
            id: row.get(0),
            name: row.get(2),
        }
    }).unwrap();
    let mut items = Vec::<Job>::new();
    for person in job_iter {
        let bill= person.unwrap();
        *pk = bill.id;
        return;
    }
}
<commit_msg>Add std::result to insert_job and pk_job_by_name<commit_after>use rusqlite::Connection;
use std::result;

#[derive(Debug)]
pub enum Version { Version1, Version2 }

#[derive(Debug)]
pub struct Job {
    pub id: i32,
    pub name: String,
}

trait JobModuleTrait {
    // Static method signature; `Self` refers to the implementor type.
    fn new(name: &'static str) -> Self;
    fn hashmap(conn: &Connection)-> Vec<Job>;
    // fn update_hashcache(&self, &hashcache) -> &'static str;
}

pub fn table_create_job(conn: &Connection) {
    let load_table = conn.execute("CREATE TABLE JOB (
                  id              INTEGER PRIMARY KEY ASC,
                  name            TEXT NOT NULL UNIQUE
                  )", &[]);
    if load_table.is_err() {
        println!("table_create_job Failed {:?}", load_table);
        return;
    }
    load_table.unwrap();
}

pub fn insert_job(conn: &Connection, name: &String) -> Result<Version, &'static str> {

    let me = Job {
        id: 0,
        name: name.clone(),
    };
    let load_instance = conn.execute("INSERT INTO JOB (name)
                  VALUES (?1)",
                 &[&me.name]);
    if load_instance.is_err() {
        return Err("Insert failed");
    }
    load_instance.unwrap();
    return Ok(Version::Version1);
}

pub fn list_job(conn: &Connection)-> Vec<Job> {
    let mut stmt = conn.prepare("SELECT id, name FROM JOB").unwrap();
    let wraped_job_iter = stmt.query_map(&[], |row| {
        Job {
            id: row.get(0),
            name: row.get(1)
        }
    });
    let mut items = Vec::<Job>::new();
    if wraped_job_iter.is_err() {
        return items;
    }
    let job_iter = wraped_job_iter.unwrap();
    for person in job_iter {
        items.push(person.unwrap());
    }
    return items;
}

pub fn pk_job_by_name(conn: &Connection, name: &String, pk: &mut i32) -> Result<Version, &'static str>{
    let bill = name.clone();
    let mut stmt = conn.prepare("SELECT id, name  FROM JOB WHERE name = ?1").unwrap();
    let job_iter = stmt.query_map(&[&bill], |row| {
        Job {
            id: row.get(0),
            name: row.get(1),
        }
    }).unwrap();
    let mut found = 0;
    let mut items = Vec::<Job>::new();
    for person in job_iter {
        let bill= person.unwrap();
        *pk = bill.id;
        found = 1;
    }
    if found == 1 {
        return Ok(Version::Version1);
    }
    return Err("None found");
}
<|endoftext|>


<commit_before>use std::fmt;
use std::error::Error;

pub enum SpawnError<S: Sized> {
    /// The State Machine Slab capacity is reached
    ///
    /// The capacity is configured in the `rotor::Config` and is used
    /// for creating `rotor::Loop`.
    ///
    /// The item in this struct is the Seed that send to create a machine
    NoSlabSpace(S),
    /// Error returned from `Machine::create` handler
    UserError(Box<Error>),
}

impl<S> fmt::Display for SpawnError<S> {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        use self::SpawnError::*;
        match *self {
            NoSlabSpace(_) => {
                write!(fmt, "state machine slab capacity limit is reached")
            }
            UserError(ref err) => {
                write!(fmt, "{}", err)
            }
        }
    }
}

impl<S> SpawnError<S> {
    pub fn description(&self) -> &str {
        use self::SpawnError::*;
        match self {
            &NoSlabSpace(_) => "state machine slab capacity limit is reached",
            &UserError(ref err) => err.description(),
        }
    }
    pub fn cause(&self) -> Option<&Error> {
        use self::SpawnError::*;
        match self {
            &NoSlabSpace(_) => None,
            &UserError(ref err) => Some(&**err),
        }
    }
    pub fn map<T:Sized, F: FnOnce(S) -> T>(self, fun:F) -> SpawnError<T> {
        use self::SpawnError::*;
        match self {
            NoSlabSpace(x) => NoSlabSpace(fun(x)),
            UserError(e) => UserError(e),
        }
    }
}
impl<S: Error> Error for SpawnError<S> {
    fn description(&self) -> &str {
        self.description()
    }
    fn cause(&self) -> Option<&Error> {
        self.cause()
    }
}

impl<S> From<Box<Error>> for SpawnError<S> {
    fn from(x: Box<Error>) -> SpawnError<S> {
        SpawnError::UserError(x)
    }
}

impl<S> fmt::Debug for SpawnError<S> {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        use self::SpawnError::*;
        match *self {
            NoSlabSpace(..) => {
                write!(fmt, "NoSlabSpace(<hidden seed>)")
            }
            UserError(ref err) => {
                write!(fmt, "UserError({:?})", err)
            }
        }
    }
}
<commit_msg>Add docstring for `SpawnError`<commit_after>use std::fmt;
use std::error::Error;

/// Error when spawning a new state machine
pub enum SpawnError<S: Sized> {
    /// The State Machine Slab capacity is reached
    ///
    /// The capacity is configured in the `rotor::Config` and is used
    /// for creating `rotor::Loop`.
    ///
    /// The item in this struct is the Seed that send to create a machine
    NoSlabSpace(S),
    /// Error returned from `Machine::create` handler
    UserError(Box<Error>),
}

impl<S> fmt::Display for SpawnError<S> {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        use self::SpawnError::*;
        match *self {
            NoSlabSpace(_) => {
                write!(fmt, "state machine slab capacity limit is reached")
            }
            UserError(ref err) => {
                write!(fmt, "{}", err)
            }
        }
    }
}

impl<S> SpawnError<S> {
    pub fn description(&self) -> &str {
        use self::SpawnError::*;
        match self {
            &NoSlabSpace(_) => "state machine slab capacity limit is reached",
            &UserError(ref err) => err.description(),
        }
    }
    pub fn cause(&self) -> Option<&Error> {
        use self::SpawnError::*;
        match self {
            &NoSlabSpace(_) => None,
            &UserError(ref err) => Some(&**err),
        }
    }
    pub fn map<T:Sized, F: FnOnce(S) -> T>(self, fun:F) -> SpawnError<T> {
        use self::SpawnError::*;
        match self {
            NoSlabSpace(x) => NoSlabSpace(fun(x)),
            UserError(e) => UserError(e),
        }
    }
}
impl<S: Error> Error for SpawnError<S> {
    fn description(&self) -> &str {
        self.description()
    }
    fn cause(&self) -> Option<&Error> {
        self.cause()
    }
}

impl<S> From<Box<Error>> for SpawnError<S> {
    fn from(x: Box<Error>) -> SpawnError<S> {
        SpawnError::UserError(x)
    }
}

impl<S> fmt::Debug for SpawnError<S> {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        use self::SpawnError::*;
        match *self {
            NoSlabSpace(..) => {
                write!(fmt, "NoSlabSpace(<hidden seed>)")
            }
            UserError(ref err) => {
                write!(fmt, "UserError({:?})", err)
            }
        }
    }
}
<|endoftext|>


<commit_before>use crypto::random_zbase32;
use hyper::{StatusCode};
use std::error::Error;
use std::fmt;

/// Union of all possible runtime error types.
#[derive(Debug)]
pub enum BrokerError {
    /// User input error, which results in 400
    Input(String),
    /// Identity provider error, which results in 503
    Provider(String),
    /// Identity provider request error, which results in 400
    ProviderInput(String),
    /// Internal errors, which result in 500
    Internal(String),
    /// User was rate limited, results in 413
    RateLimited,
    /// User session not found, results in 400
    SessionExpired,
    /// Result status used by bridges to cancel a request
    ProviderCancelled,
}

impl BrokerError {
    /// Log this error at the appropriate log level.
    /// Internal errors return a reference number for the error.
    pub fn log(&self) -> Option<String> {
        match *self {
            // User errors only at debug level.
            ref err @ BrokerError::Input(_)
                | ref err @ BrokerError::ProviderInput(_)
                | ref err @ BrokerError::RateLimited
                | ref err @ BrokerError::SessionExpired
                | ref err @ BrokerError::ProviderCancelled
                => {
                debug!("{}", err.description());
                None
            },
            // Provider errors can be noteworthy, especially when
            // the issue is network related.
            ref err @ BrokerError::Provider(_) => {
                info!("{}", err.description());
                None
            },
            // Internal errors should ring alarm bells.
            ref err @ BrokerError::Internal(_) => {
                let reference = random_zbase32(6);
                error!("[REF:{}] {}", err.description(), reference);
                Some(reference)
            },
        }
    }

    /// Get the HTTP status code for this error.
    pub fn http_status_code(&self) -> StatusCode {
        match *self {
            BrokerError::Input(_) => StatusCode::BadRequest,
            BrokerError::Provider(_) => StatusCode::ServiceUnavailable,
            BrokerError::ProviderInput(_) => StatusCode::BadRequest,
            BrokerError::Internal(_) => StatusCode::InternalServerError,
            BrokerError::RateLimited => StatusCode::TooManyRequests,
            BrokerError::SessionExpired => StatusCode::BadRequest,
            // Internal status that should never bubble this far
            BrokerError::ProviderCancelled => unreachable!(),
        }
    }

    /// Get the OAuth2 error code for this error
    pub fn oauth_error_code(&self) -> &str {
        match *self {
            BrokerError::Input(_) => "invalid_request",
            BrokerError::Provider(_) => "temporarily_unavailable",
            BrokerError::ProviderInput(_) => "temporarily_unavailable",
            BrokerError::Internal(_) => "server_error",
            // We will never redirect for these types of errors
            BrokerError::RateLimited => unreachable!(),
            BrokerError::SessionExpired => unreachable!(),
            // Internal status that should never bubble this far
            BrokerError::ProviderCancelled => unreachable!(),
        }
    }
}

impl Error for BrokerError {
    fn description(&self) -> &str {
        match *self {
            BrokerError::Input(ref description)
                | BrokerError::Provider(ref description)
                | BrokerError::ProviderInput(ref description)
                | BrokerError::Internal(ref description)
                => description,
            BrokerError::RateLimited => "too many requests",
            BrokerError::SessionExpired => "session has expired",
            BrokerError::ProviderCancelled => "bridge cancelled the request",
        }
    }
}

impl fmt::Display for BrokerError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.description())
    }
}

/// Result type with `BrokerError` for errors.
pub type BrokerResult<T> = Result<T, BrokerError>;
<commit_msg>Fix clippy warning about similar branches<commit_after>use crypto::random_zbase32;
use hyper::{StatusCode};
use std::error::Error;
use std::fmt;

/// Union of all possible runtime error types.
#[derive(Debug)]
pub enum BrokerError {
    /// User input error, which results in 400
    Input(String),
    /// Identity provider error, which results in 503
    Provider(String),
    /// Identity provider request error, which results in 400
    ProviderInput(String),
    /// Internal errors, which result in 500
    Internal(String),
    /// User was rate limited, results in 413
    RateLimited,
    /// User session not found, results in 400
    SessionExpired,
    /// Result status used by bridges to cancel a request
    ProviderCancelled,
}

impl BrokerError {
    /// Log this error at the appropriate log level.
    /// Internal errors return a reference number for the error.
    pub fn log(&self) -> Option<String> {
        match *self {
            // User errors only at debug level.
            ref err @ BrokerError::Input(_)
                | ref err @ BrokerError::ProviderInput(_)
                | ref err @ BrokerError::RateLimited
                | ref err @ BrokerError::SessionExpired
                | ref err @ BrokerError::ProviderCancelled
                => {
                debug!("{}", err.description());
                None
            },
            // Provider errors can be noteworthy, especially when
            // the issue is network related.
            ref err @ BrokerError::Provider(_) => {
                info!("{}", err.description());
                None
            },
            // Internal errors should ring alarm bells.
            ref err @ BrokerError::Internal(_) => {
                let reference = random_zbase32(6);
                error!("[REF:{}] {}", err.description(), reference);
                Some(reference)
            },
        }
    }

    /// Get the HTTP status code for this error.
    pub fn http_status_code(&self) -> StatusCode {
        match *self {
            BrokerError::Input(_)
                | BrokerError::ProviderInput(_)
                | BrokerError::SessionExpired
                => StatusCode::BadRequest,
            BrokerError::Provider(_) => StatusCode::ServiceUnavailable,
            BrokerError::Internal(_) => StatusCode::InternalServerError,
            BrokerError::RateLimited => StatusCode::TooManyRequests,
            // Internal status that should never bubble this far
            BrokerError::ProviderCancelled => unreachable!(),
        }
    }

    /// Get the OAuth2 error code for this error
    pub fn oauth_error_code(&self) -> &str {
        match *self {
            BrokerError::Input(_) => "invalid_request",
            BrokerError::Provider(_)
                | BrokerError::ProviderInput(_)
                => "temporarily_unavailable",
            BrokerError::Internal(_) => "server_error",
            // We will never redirect for these types of errors
            BrokerError::RateLimited
                | BrokerError::SessionExpired
                // Internal status that should never bubble this far
                | BrokerError::ProviderCancelled
                => unreachable!(),
        }
    }
}

impl Error for BrokerError {
    fn description(&self) -> &str {
        match *self {
            BrokerError::Input(ref description)
                | BrokerError::Provider(ref description)
                | BrokerError::ProviderInput(ref description)
                | BrokerError::Internal(ref description)
                => description,
            BrokerError::RateLimited => "too many requests",
            BrokerError::SessionExpired => "session has expired",
            BrokerError::ProviderCancelled => "bridge cancelled the request",
        }
    }
}

impl fmt::Display for BrokerError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.description())
    }
}

/// Result type with `BrokerError` for errors.
pub type BrokerResult<T> = Result<T, BrokerError>;
<|endoftext|>


<commit_before>use crate::syntax::Api;
use proc_macro2::Ident;
use std::collections::BTreeMap;
use std::iter::FromIterator;

pub struct NamespaceEntries<'a> {
    direct: Vec<&'a Api>,
    nested: BTreeMap<&'a Ident, NamespaceEntries<'a>>,
}

impl<'a> NamespaceEntries<'a> {
    pub fn new(apis: &'a [Api]) -> Self {
        let api_refs = Vec::from_iter(apis);
        sort_by_inner_namespace(api_refs, 0)
    }

    pub fn direct_content(&self) -> &[&'a Api] {
        &self.direct
    }

    pub fn nested_content(&self) -> impl Iterator<Item = (&Ident, &NamespaceEntries)> {
        self.nested.iter().map(|(k, entries)| (*k, entries))
    }
}

fn sort_by_inner_namespace(apis: Vec<&Api>, depth: usize) -> NamespaceEntries {
    let mut direct = Vec::new();
    let mut nested_namespaces = BTreeMap::new();
    for api in apis {
        if let Some(ns) = api.namespace() {
            let first_ns_elem = ns.iter().nth(depth);
            if let Some(first_ns_elem) = first_ns_elem {
                nested_namespaces
                    .entry(first_ns_elem)
                    .or_insert_with(Vec::new)
                    .push(api);
                continue;
            }
        }
        direct.push(api);
    }

    let nested = nested_namespaces
        .into_iter()
        .map(|(k, apis)| (k, sort_by_inner_namespace(apis, depth + 1)))
        .collect();

    NamespaceEntries { direct, nested }
}

#[cfg(test)]
mod tests {
    use super::NamespaceEntries;
    use crate::syntax::namespace::Namespace;
    use crate::syntax::{Api, Doc, ExternType, Pair};
    use proc_macro2::{Ident, Span};
    use syn::Token;

    #[test]
    fn test_ns_entries_sort() {
        let apis = &[
            make_api(None, "C"),
            make_api(None, "A"),
            make_api(Some("G"), "E"),
            make_api(Some("D"), "F"),
            make_api(Some("G"), "H"),
            make_api(Some("D::K"), "L"),
            make_api(Some("D::K"), "M"),
            make_api(None, "B"),
            make_api(Some("D"), "I"),
            make_api(Some("D"), "J"),
        ];

        let root = NamespaceEntries::new(apis);

        // ::
        let root_direct = root.direct_content();
        assert_eq!(root_direct.len(), 3);
        assert_ident(root_direct[0], "C");
        assert_ident(root_direct[1], "A");
        assert_ident(root_direct[2], "B");

        let mut root_nested = root.nested_content();
        let (id, d) = root_nested.next().unwrap();
        assert_eq!(id, "D");
        let (id, g) = root_nested.next().unwrap();
        assert_eq!(id, "G");
        assert!(root_nested.next().is_none());

        // ::D
        let d_direct = d.direct_content();
        assert_eq!(d_direct.len(), 3);
        assert_ident(d_direct[0], "F");
        assert_ident(d_direct[1], "I");
        assert_ident(d_direct[2], "J");

        let mut d_nested = d.nested_content();
        let (id, k) = d_nested.next().unwrap();
        assert_eq!(id, "K");

        // ::D::K
        let k_direct = k.direct_content();
        assert_eq!(k_direct.len(), 2);
        assert_ident(k_direct[0], "L");
        assert_ident(k_direct[1], "M");

        // ::G
        let g_direct = g.direct_content();
        assert_eq!(g_direct.len(), 2);
        assert_ident(g_direct[0], "E");
        assert_ident(g_direct[1], "H");

        let mut g_nested = g.nested_content();
        assert!(g_nested.next().is_none());
    }

    fn assert_ident(api: &Api, expected: &str) {
        if let Api::CxxType(cxx_type) = api {
            assert_eq!(cxx_type.ident.cxx.ident, expected);
        } else {
            unreachable!()
        }
    }

    fn make_api(ns: Option<&str>, ident: &str) -> Api {
        let ns = ns.map_or(Namespace::ROOT, |ns| syn::parse_str(ns).unwrap());
        Api::CxxType(ExternType {
            doc: Doc::new(),
            type_token: Token![type](Span::call_site()),
            ident: Pair::new(ns, Ident::new(ident, Span::call_site())),
            semi_token: Token![;](Span::call_site()),
            trusted: false,
        })
    }
}
<commit_msg>Keep apis usable later in sort_by_inner_namespace<commit_after>use crate::syntax::Api;
use proc_macro2::Ident;
use std::collections::BTreeMap;
use std::iter::FromIterator;

pub struct NamespaceEntries<'a> {
    direct: Vec<&'a Api>,
    nested: BTreeMap<&'a Ident, NamespaceEntries<'a>>,
}

impl<'a> NamespaceEntries<'a> {
    pub fn new(apis: &'a [Api]) -> Self {
        let api_refs = Vec::from_iter(apis);
        sort_by_inner_namespace(api_refs, 0)
    }

    pub fn direct_content(&self) -> &[&'a Api] {
        &self.direct
    }

    pub fn nested_content(&self) -> impl Iterator<Item = (&Ident, &NamespaceEntries)> {
        self.nested.iter().map(|(k, entries)| (*k, entries))
    }
}

fn sort_by_inner_namespace(apis: Vec<&Api>, depth: usize) -> NamespaceEntries {
    let mut direct = Vec::new();
    let mut nested_namespaces = BTreeMap::new();
    for api in &apis {
        if let Some(ns) = api.namespace() {
            let first_ns_elem = ns.iter().nth(depth);
            if let Some(first_ns_elem) = first_ns_elem {
                nested_namespaces
                    .entry(first_ns_elem)
                    .or_insert_with(Vec::new)
                    .push(*api);
                continue;
            }
        }
        direct.push(*api);
    }

    let nested = nested_namespaces
        .into_iter()
        .map(|(k, apis)| (k, sort_by_inner_namespace(apis, depth + 1)))
        .collect();

    NamespaceEntries { direct, nested }
}

#[cfg(test)]
mod tests {
    use super::NamespaceEntries;
    use crate::syntax::namespace::Namespace;
    use crate::syntax::{Api, Doc, ExternType, Pair};
    use proc_macro2::{Ident, Span};
    use syn::Token;

    #[test]
    fn test_ns_entries_sort() {
        let apis = &[
            make_api(None, "C"),
            make_api(None, "A"),
            make_api(Some("G"), "E"),
            make_api(Some("D"), "F"),
            make_api(Some("G"), "H"),
            make_api(Some("D::K"), "L"),
            make_api(Some("D::K"), "M"),
            make_api(None, "B"),
            make_api(Some("D"), "I"),
            make_api(Some("D"), "J"),
        ];

        let root = NamespaceEntries::new(apis);

        // ::
        let root_direct = root.direct_content();
        assert_eq!(root_direct.len(), 3);
        assert_ident(root_direct[0], "C");
        assert_ident(root_direct[1], "A");
        assert_ident(root_direct[2], "B");

        let mut root_nested = root.nested_content();
        let (id, d) = root_nested.next().unwrap();
        assert_eq!(id, "D");
        let (id, g) = root_nested.next().unwrap();
        assert_eq!(id, "G");
        assert!(root_nested.next().is_none());

        // ::D
        let d_direct = d.direct_content();
        assert_eq!(d_direct.len(), 3);
        assert_ident(d_direct[0], "F");
        assert_ident(d_direct[1], "I");
        assert_ident(d_direct[2], "J");

        let mut d_nested = d.nested_content();
        let (id, k) = d_nested.next().unwrap();
        assert_eq!(id, "K");

        // ::D::K
        let k_direct = k.direct_content();
        assert_eq!(k_direct.len(), 2);
        assert_ident(k_direct[0], "L");
        assert_ident(k_direct[1], "M");

        // ::G
        let g_direct = g.direct_content();
        assert_eq!(g_direct.len(), 2);
        assert_ident(g_direct[0], "E");
        assert_ident(g_direct[1], "H");

        let mut g_nested = g.nested_content();
        assert!(g_nested.next().is_none());
    }

    fn assert_ident(api: &Api, expected: &str) {
        if let Api::CxxType(cxx_type) = api {
            assert_eq!(cxx_type.ident.cxx.ident, expected);
        } else {
            unreachable!()
        }
    }

    fn make_api(ns: Option<&str>, ident: &str) -> Api {
        let ns = ns.map_or(Namespace::ROOT, |ns| syn::parse_str(ns).unwrap());
        Api::CxxType(ExternType {
            doc: Doc::new(),
            type_token: Token![type](Span::call_site()),
            ident: Pair::new(ns, Ident::new(ident, Span::call_site())),
            semi_token: Token![;](Span::call_site()),
            trusted: false,
        })
    }
}
<|endoftext|>