<commit_before>use ::opcodes::OpCode;

use cpu::cpu_error::CpuError;
use cpu::memory_bus::MemoryBus;
use cpu::registers::Registers;

const DEFAULT_CODE_SEGMENT_START_ADDRESS: u16 = 0xC000;  // Default to a 16KB ROM, leaving 32KB of main memory

/// A representation of a 6502 microprocessor
pub struct Cpu {
    memory: MemoryBus,
    pub registers: Registers,
}

pub type CpuLoadResult = Result<(), CpuError>;
pub type CpuStepResult = Result<(), CpuError>;

impl Cpu {
    /// Returns a default instance of a Cpu
    pub fn new() -> Cpu {
        Cpu {
            memory: MemoryBus::new(),
            registers: Registers::new(),
        }
    }

    /// Loads code into the Cpu main memory at an optional offset. If no
    /// offset is provided, the Cpu will, by default, load the code into
    /// main memory at 0xC000
    pub fn load<T>(&mut self, code: &[u8], addr: T) -> CpuLoadResult
        where T: Into<Option<u16>>
    {
        let addr = addr.into();
        let addr: u16 = if addr.is_some() {
            let addr = addr.unwrap();
            if addr as u32 + code.len() as u32 > u16::max_value() as u32 {
                return Err(CpuError::code_segment_out_of_range(addr));
            } else {
                addr
            }
        } else {
            DEFAULT_CODE_SEGMENT_START_ADDRESS
        };

        for x in 0..code.len() {
            self.memory.write_byte(addr + x as u16, code[x]);
        }

        Ok(())
    }

    /// Runs a single instruction of code through the Cpu
    pub fn step<T>(&mut self) -> CpuStepResult {
        let byte = self.memory.read_byte(self.registers.PC);

        if let Some(opcode) = OpCode::from_raw_byte(byte) {
            Ok(())
        } else {
            Err(CpuError::unknown_opcode(self.registers.PC, byte))
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use cpu::cpu_error::CpuError;

    #[test]
    fn can_instantiate_cpu() {
        let cpu = Cpu::new();

        assert!(0 == 0);
    }

    #[test]
    fn can_load_code_segment_into_memory() {
        let fake_code = vec![0x0A, 0x0B, 0x0C, 0x0D];
        let mut cpu = Cpu::new();
        cpu.load(&fake_code[..], None);

        let memory_sum: u32 = cpu.memory.iter().map(|n| *n as u32).sum();
        assert_eq!(46, memory_sum);
    }

    #[test]
    fn can_load_code_segment_at_default_address() {
        let fake_code = vec![0x0A, 0x0B, 0x0C, 0x0D];
        let mut cpu = Cpu::new();
        cpu.load(&fake_code[..], None);

        assert_eq!(0x0D, cpu.memory.read_byte(0xC003));
        assert_eq!(0x0C, cpu.memory.read_byte(0xC002));
        assert_eq!(0x0B, cpu.memory.read_byte(0xC001));
        assert_eq!(0x0A, cpu.memory.read_byte(0xC000));
    }

    #[test]
    fn can_load_code_segment_at_specific_address() {
        let fake_code = vec![0x0A, 0x0B, 0x0C, 0x0D];
        let mut cpu = Cpu::new();
        cpu.load(&fake_code[..], 0xF000);

        assert_eq!(0x0D, cpu.memory.read_byte(0xF003));
        assert_eq!(0x0C, cpu.memory.read_byte(0xF002));
        assert_eq!(0x0B, cpu.memory.read_byte(0xF001));
        assert_eq!(0x0A, cpu.memory.read_byte(0xF000));
    }

    #[test]
    fn errors_when_code_segment_extends_past_memory_bounds() {
        let fake_code = vec![0x0A, 0x0B, 0x0C, 0x0D];
        let mut cpu = Cpu::new();
        let load_result = cpu.load(&fake_code[..], 0xFFFD);

        assert_eq!(Err(CpuError::code_segment_out_of_range(0xFFFD)),
                   load_result);
    }
}
<commit_msg>Add test for stepping into invalid opcode<commit_after>use ::opcodes::OpCode;

use cpu::cpu_error::CpuError;
use cpu::memory_bus::MemoryBus;
use cpu::registers::Registers;

const DEFAULT_CODE_SEGMENT_START_ADDRESS: u16 = 0xC000;  // Default to a 16KB ROM, leaving 32KB of main memory

/// A representation of a 6502 microprocessor
pub struct Cpu {
    memory: MemoryBus,
    pub registers: Registers,
}

pub type CpuLoadResult = Result<(), CpuError>;
pub type CpuStepResult = Result<(), CpuError>;

impl Cpu {
    /// Returns a default instance of a Cpu
    pub fn new() -> Cpu {
        Cpu {
            memory: MemoryBus::new(),
            registers: Registers::new(),
        }
    }

    /// Loads code into the Cpu main memory at an optional offset. If no
    /// offset is provided, the Cpu will, by default, load the code into
    /// main memory at 0xC000
    pub fn load<T>(&mut self, code: &[u8], addr: T) -> CpuLoadResult
        where T: Into<Option<u16>>
    {
        let addr = addr.into();
        let addr: u16 = if addr.is_some() {
            let addr = addr.unwrap();
            if addr as u32 + code.len() as u32 > u16::max_value() as u32 {
                return Err(CpuError::code_segment_out_of_range(addr));
            } else {
                addr
            }
        } else {
            DEFAULT_CODE_SEGMENT_START_ADDRESS
        };

        for x in 0..code.len() {
            self.memory.write_byte(addr + x as u16, code[x]);
        }

        // Set the Program Counter to point at the
        // start address of the code segment
        self.registers.PC = addr;

        Ok(())
    }

    /// Runs a single instruction of code through the Cpu
    pub fn step(&mut self) -> CpuStepResult {
        let byte = self.memory.read_byte(self.registers.PC);

        if let Some(opcode) = OpCode::from_raw_byte(byte) {
            println!("Found: {}", opcode.mnemonic);
            Ok(())
        } else {
            Err(CpuError::unknown_opcode(self.registers.PC, byte))
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use cpu::cpu_error::CpuError;

    #[test]
    fn can_instantiate_cpu() {
        let cpu = Cpu::new();

        assert!(0 == 0);
    }

    #[test]
    fn can_load_code_segment_into_memory() {
        let fake_code = vec![0x0A, 0x0B, 0x0C, 0x0D];
        let mut cpu = Cpu::new();
        cpu.load(&fake_code[..], None);

        let memory_sum: u32 = cpu.memory.iter().map(|n| *n as u32).sum();
        assert_eq!(46, memory_sum);
    }

    #[test]
    fn can_load_code_segment_at_default_address() {
        let fake_code = vec![0x0A, 0x0B, 0x0C, 0x0D];
        let mut cpu = Cpu::new();
        cpu.load(&fake_code[..], None);

        assert_eq!(0x0D, cpu.memory.read_byte(0xC003));
        assert_eq!(0x0C, cpu.memory.read_byte(0xC002));
        assert_eq!(0x0B, cpu.memory.read_byte(0xC001));
        assert_eq!(0x0A, cpu.memory.read_byte(0xC000));
    }

    #[test]
    fn can_load_code_segment_at_specific_address() {
        let fake_code = vec![0x0A, 0x0B, 0x0C, 0x0D];
        let mut cpu = Cpu::new();
        cpu.load(&fake_code[..], 0xF000);

        assert_eq!(0x0D, cpu.memory.read_byte(0xF003));
        assert_eq!(0x0C, cpu.memory.read_byte(0xF002));
        assert_eq!(0x0B, cpu.memory.read_byte(0xF001));
        assert_eq!(0x0A, cpu.memory.read_byte(0xF000));
    }

    #[test]
    fn errors_when_code_segment_extends_past_memory_bounds() {
        let fake_code = vec![0x0A, 0x0B, 0x0C, 0x0D];
        let mut cpu = Cpu::new();
        let load_result = cpu.load(&fake_code[..], 0xFFFD);

        assert_eq!(Err(CpuError::code_segment_out_of_range(0xFFFD)),
                   load_result);
    }

    #[test]
    fn errors_on_unknown_opcode() {
        let fake_code = vec![0xC3];
        let mut cpu = Cpu::new();
        cpu.load(&fake_code[..], None);
        let step_result: CpuStepResult = cpu.step();

        assert_eq!(Err(CpuError::unknown_opcode(0xC000, 0xC3)), step_result);// This is the unofficial DCP (d,X) opcode
    }
}
<|endoftext|>


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

pub fn new(name: &str) {
  let path = format!("~/.muxed/{}", name);
  println!("{}", path);
  let mut file = File::create(&Path::new(path));
  file.write(b"This is a sample file");
}
<commit_msg>Don't use relative user paths. Use appropriate postfix path for homedir.<commit_after>use std::io::File;
use std::os::{homedir};

pub fn new(name: &str) {
  let home = homedir().unwrap().display();
  let path = format!("{}/.muxed/{}", home, name);
  println!("{}", path);
  let mut file = File::create(&Path::new(path));
  file.write(b"This is a sample file");
}
<|endoftext|>


<commit_before>//! The initializer module parses arguments and verfies commands are valid
//! The creator module handles creating the muxed directory and project files.
#![allow(experimental)]

use std::io::File;
use std::path::posix::Path;
use editor;
use root;

#[cfg(test)] use std::finally::Finally;
#[cfg(test)] use test_helper::{random_name,cleanup_file};

static TEMPLATE: &'static str = include_str!("creator/template.toml");
static DEFAULT_MUXED_DIR: &'static str = "muxed";

pub fn new(name: &str) {
    let muxed_dir = match root::muxed_dir_exists(&DEFAULT_MUXED_DIR.to_string()) {
        true  => Path::new(format!("{}/.{}/", root::homedir_string(), &DEFAULT_MUXED_DIR.to_string())),
        false => root::create_muxed_dir(&DEFAULT_MUXED_DIR.to_string())
    };

    let path = &Path::new(format!("{}/{}.toml", muxed_dir.display(), name));
    if !path.exists() {
        create_project_file(path);

        match editor::default_editor_set() {
            true  => editor::open_project_file(path),
            false => println!("Default editor is not set. Please define $EDITOR in your ~/.bashrc or similar file.")
        }
    } else {
        println!("Project already exists.");
    }
}

/// Copy and create the new project file from a template.
fn create_project_file(path: &Path) {
    match File::create(path).write(TEMPLATE.as_bytes()) {
        Ok(())  => (),
        Err(_e) => println!("Failed to create project {}", path.filename()),
    }
}

#[test]
fn creates_project_file() {
    let name = random_name();
    let path = &Path::new(format!("{}/.muxed/{}.toml", root::homedir_string(), name));
    create_project_file(path);
    assert!(path.exists());

    cleanup_file(path);
}

#[test]
fn new_writes_file_to_muxed_dir() {
    let name = random_name();
    let path = &Path::new(format!("{}/.muxed/{}.toml", root::homedir_string(), name));
    new(name.as_slice());
    assert!(path.exists());
    match fs::unlink(path) {
        Ok(()) => (), // succeeded
        Err(e) => println!("Failed to unlink the path {} with error {}", path.display(), e),
    }

    cleanup_file(path);
}

#[test]
fn new_writes_file_to_muxed_dir() {
    let name = random_name();
    let path = &Path::new(format!("{}/.muxed/{}.toml", root::homedir_string(), name));
    new(name.as_slice());
    assert!(path.exists());

    cleanup_file(path);
}
<commit_msg>Add method to check for errors when creating new files.<commit_after>//! The initializer module parses arguments and verfies commands are valid
//! The creator module handles creating the muxed directory and project files.
#![allow(experimental)]

use std::io::File;
use std::path::posix::Path;
use editor;
use root;

#[cfg(test)] use std::finally::Finally;
#[cfg(test)] use test_helper::{random_name,cleanup_file};

static TEMPLATE: &'static str = include_str!("creator/template.toml");
static DEFAULT_MUXED_DIR: &'static str = "muxed";

pub fn new(name: &str) {
    let muxed_dir = match root::muxed_dir_exists(&DEFAULT_MUXED_DIR.to_string()) {
        true  => Path::new(format!("{}/.{}/", root::homedir_string(), &DEFAULT_MUXED_DIR.to_string())),
        false => root::create_muxed_dir(&DEFAULT_MUXED_DIR.to_string())
    };

    let path = &Path::new(format!("{}/{}.toml", muxed_dir.display(), name));
    if !path.exists() {
        create_project_file(path);

        match editor::default_editor_set() {
            true  => editor::open_project_file(path),
            false => println!("Default editor is not set. Please define $EDITOR in your ~/.bashrc or similar file.")
        }
    } else {
        println!("Project already exists.");
    }
}

/// Copy and create the new project file from a template.
fn create_project_file(path: &Path) {
    match File::create(path).write(TEMPLATE.as_bytes()) {
        Ok(())  => (),
        Err(_e) => println!("Failed to create project {}", path.filename()),
    }
}

#[test]
fn creates_project_file() {
    let name = random_name();
    let path = &Path::new(format!("{}/.muxed/{}.toml", root::homedir_string(), name));
    create_project_file(path);
    assert!(path.exists());

    cleanup_file(path);
}

#[test]
fn errors_when_creating_project_file() {
    let name = random_name();
    let path = &Path::new(format!("{}/.muxed/{}.toml", root::homedir_string(), name));
    create_project_file(path);
    assert!(path.exists());

    cleanup_file(path);
}

#[test]
fn new_writes_file_to_muxed_dir() {
    let name = random_name();
    let path = &Path::new(format!("{}/.muxed/{}.toml", root::homedir_string(), name));
    new(name.as_slice());
    assert!(path.exists());

    cleanup_file(path);
}
<|endoftext|>


<commit_before>use crate::decor::{Formatted, Repr};
use crate::document::Document;
use crate::table::{Item, Table};
use crate::value::{Array, DateTime, InlineTable, Value};
use std::cell::{Cell, RefCell};
use std::fmt::{Display, Formatter, Result};

impl Display for Repr {
    fn fmt(&self, f: &mut Formatter) -> Result {
        write!(
            f,
            "{}{}{}",
            self.decor.prefix, self.raw_value, self.decor.suffix
        )
    }
}

impl<T> Display for Formatted<T> {
    fn fmt(&self, f: &mut Formatter) -> Result {
        write!(f, "{}", self.repr)
    }
}

impl Display for DateTime {
    fn fmt(&self, f: &mut Formatter) -> Result {
        match *self {
            DateTime::OffsetDateTime(d) => write!(f, "{}", d),
            DateTime::LocalDateTime(d) => write!(f, "{}", d),
            DateTime::LocalDate(d) => write!(f, "{}", d),
            DateTime::LocalTime(d) => write!(f, "{}", d),
        }
    }
}

impl Display for Value {
    fn fmt(&self, f: &mut Formatter) -> Result {
        match *self {
            Value::Integer(ref repr) => write!(f, "{}", repr),
            Value::String(ref repr) => write!(f, "{}", repr),
            Value::Float(ref repr) => write!(f, "{}", repr),
            Value::Boolean(ref repr) => write!(f, "{}", repr),
            Value::DateTime(ref repr) => write!(f, "{}", repr),
            Value::Array(ref array) => write!(f, "{}", array),
            Value::InlineTable(ref table) => write!(f, "{}", table),
        }
    }
}

impl Display for Array {
    fn fmt(&self, f: &mut Formatter) -> Result {
        write!(f, "{}[", self.decor.prefix)?;
        join(f, self.iter(), ",")?;
        if self.trailing_comma {
            write!(f, ",")?;
        }
        write!(f, "{}", self.trailing)?;
        write!(f, "]{}", self.decor.suffix)
    }
}

impl Display for InlineTable {
    fn fmt(&self, f: &mut Formatter) -> Result {
        write!(f, "{}{{", self.decor.prefix)?;
        write!(f, "{}", self.preamble)?;
        for (i, (key, value)) in self
            .items
            .iter()
            .filter(|&(_, kv)| kv.value.is_value())
            .map(|(_, kv)| (&kv.key, kv.value.as_value().unwrap()))
            .enumerate()
        {
            if i > 0 {
                write!(f, ",")?;
            }
            write!(f, "{}={}", key, value)?;
        }
        write!(f, "}}{}", self.decor.suffix)
    }
}

impl Table {
    fn visit_nested_tables<'t, F>(
        &'t self,
        path: &mut Vec<&'t str>,
        is_array_of_tables: bool,
        callback: &mut F,
    ) -> Result
    where
        F: FnMut(&Table, &Vec<&'t str>, bool) -> Result,
    {
        callback(self, path, is_array_of_tables)?;

        for kv in self.items.values() {
            match kv.value {
                Item::Table(ref t) => {
                    path.push(&kv.key.raw_value);
                    t.visit_nested_tables(path, false, callback)?;
                    path.pop();
                }
                Item::ArrayOfTables(ref a) => {
                    for t in a.iter() {
                        path.push(&kv.key.raw_value);
                        t.visit_nested_tables(path, true, callback)?;
                        path.pop();
                    }
                }
                _ => {}
            }
        }
        Ok(())
    }
}

fn visit_table(
    f: &mut Formatter,
    table: &Table,
    path: &Vec<&str>,
    is_array_of_tables: bool,
) -> Result {
    if path.len() == 0 {
        // don't print header for the root node
    } else if is_array_of_tables {
        write!(f, "{}[[", table.decor.prefix)?;
        write!(f, "{}", path.join("."))?;
        writeln!(f, "]]{}", table.decor.suffix)?;
    } else if !(table.implicit && table.values_len() == 0) {
        write!(f, "{}[", table.decor.prefix)?;
        write!(f, "{}", path.join("."))?;
        writeln!(f, "]{}", table.decor.suffix)?;
    }
    // print table body
    for kv in table.items.values() {
        if let Item::Value(ref value) = kv.value {
            writeln!(f, "{}={}", kv.key, value)?;
        }
    }
    Ok(())
}

impl Display for Table {
    fn fmt(&self, f: &mut Formatter) -> Result {
        let mut path = Vec::new();

        self.visit_nested_tables(&mut path, false, &mut |t, path, is_array| {
            visit_table(f, t, path, is_array)
        })?;
        Ok(())
    }
}

impl Display for Document {
    fn fmt(&self, f: &mut Formatter) -> Result {
        write!(f, "{}", self.as_table())?;
        write!(f, "{}", self.trailing)
    }
}

fn join<D, I>(f: &mut Formatter, iter: I, sep: &str) -> Result
where
    D: Display,
    I: Iterator<Item = D>,
{
    for (i, v) in iter.enumerate() {
        if i > 0 {
            write!(f, "{}", sep)?;
        }
        write!(f, "{}", v)?;
    }
    Ok(())
}
<commit_msg>clippy fixes<commit_after>use crate::decor::{Formatted, Repr};
use crate::document::Document;
use crate::table::{Item, Table};
use crate::value::{Array, DateTime, InlineTable, Value};
use std::fmt::{Display, Formatter, Result};

impl Display for Repr {
    fn fmt(&self, f: &mut Formatter) -> Result {
        write!(
            f,
            "{}{}{}",
            self.decor.prefix, self.raw_value, self.decor.suffix
        )
    }
}

impl<T> Display for Formatted<T> {
    fn fmt(&self, f: &mut Formatter) -> Result {
        write!(f, "{}", self.repr)
    }
}

impl Display for DateTime {
    fn fmt(&self, f: &mut Formatter) -> Result {
        match *self {
            DateTime::OffsetDateTime(d) => write!(f, "{}", d),
            DateTime::LocalDateTime(d) => write!(f, "{}", d),
            DateTime::LocalDate(d) => write!(f, "{}", d),
            DateTime::LocalTime(d) => write!(f, "{}", d),
        }
    }
}

impl Display for Value {
    fn fmt(&self, f: &mut Formatter) -> Result {
        match *self {
            Value::Integer(ref repr) => write!(f, "{}", repr),
            Value::String(ref repr) => write!(f, "{}", repr),
            Value::Float(ref repr) => write!(f, "{}", repr),
            Value::Boolean(ref repr) => write!(f, "{}", repr),
            Value::DateTime(ref repr) => write!(f, "{}", repr),
            Value::Array(ref array) => write!(f, "{}", array),
            Value::InlineTable(ref table) => write!(f, "{}", table),
        }
    }
}

impl Display for Array {
    fn fmt(&self, f: &mut Formatter) -> Result {
        write!(f, "{}[", self.decor.prefix)?;
        join(f, self.iter(), ",")?;
        if self.trailing_comma {
            write!(f, ",")?;
        }
        write!(f, "{}", self.trailing)?;
        write!(f, "]{}", self.decor.suffix)
    }
}

impl Display for InlineTable {
    fn fmt(&self, f: &mut Formatter) -> Result {
        write!(f, "{}{{", self.decor.prefix)?;
        write!(f, "{}", self.preamble)?;
        for (i, (key, value)) in self
            .items
            .iter()
            .filter(|&(_, kv)| kv.value.is_value())
            .map(|(_, kv)| (&kv.key, kv.value.as_value().unwrap()))
            .enumerate()
        {
            if i > 0 {
                write!(f, ",")?;
            }
            write!(f, "{}={}", key, value)?;
        }
        write!(f, "}}{}", self.decor.suffix)
    }
}

impl Table {
    fn visit_nested_tables<'t, F>(
        &'t self,
        path: &mut Vec<&'t str>,
        is_array_of_tables: bool,
        callback: &mut F,
    ) -> Result
    where
        F: FnMut(&Table, &Vec<&'t str>, bool) -> Result,
    {
        callback(self, path, is_array_of_tables)?;

        for kv in self.items.values() {
            match kv.value {
                Item::Table(ref t) => {
                    path.push(&kv.key.raw_value);
                    t.visit_nested_tables(path, false, callback)?;
                    path.pop();
                }
                Item::ArrayOfTables(ref a) => {
                    for t in a.iter() {
                        path.push(&kv.key.raw_value);
                        t.visit_nested_tables(path, true, callback)?;
                        path.pop();
                    }
                }
                _ => {}
            }
        }
        Ok(())
    }
}

fn visit_table(
    f: &mut Formatter,
    table: &Table,
    path: &[&str],
    is_array_of_tables: bool,
) -> Result {
    if path.is_empty() {
        // don't print header for the root node
    } else if is_array_of_tables {
        write!(f, "{}[[", table.decor.prefix)?;
        write!(f, "{}", path.join("."))?;
        writeln!(f, "]]{}", table.decor.suffix)?;
    } else if !(table.implicit && table.values_len() == 0) {
        write!(f, "{}[", table.decor.prefix)?;
        write!(f, "{}", path.join("."))?;
        writeln!(f, "]{}", table.decor.suffix)?;
    }
    // print table body
    for kv in table.items.values() {
        if let Item::Value(ref value) = kv.value {
            writeln!(f, "{}={}", kv.key, value)?;
        }
    }
    Ok(())
}

impl Display for Table {
    fn fmt(&self, f: &mut Formatter) -> Result {
        let mut path = Vec::new();

        self.visit_nested_tables(&mut path, false, &mut |t, path, is_array| {
            visit_table(f, t, path, is_array)
        })?;
        Ok(())
    }
}

impl Display for Document {
    fn fmt(&self, f: &mut Formatter) -> Result {
        write!(f, "{}", self.as_table())?;
        write!(f, "{}", self.trailing)
    }
}

fn join<D, I>(f: &mut Formatter, iter: I, sep: &str) -> Result
where
    D: Display,
    I: Iterator<Item = D>,
{
    for (i, v) in iter.enumerate() {
        if i > 0 {
            write!(f, "{}", sep)?;
        }
        write!(f, "{}", v)?;
    }
    Ok(())
}
<|endoftext|>


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

//! The display subsystem including window management, font rasterization, and
//! GPU drawing.
use std::sync::mpsc;

use parking_lot::{MutexGuard};

use Rgb;
use cli;
use config::Config;
use font::{self, Rasterize};
use meter::Meter;
use renderer::{self, GlyphCache, QuadRenderer};
use selection::Selection;
use term::{Term, SizeInfo};

use window::{self, Size, Pixels, Window, SetInnerSize};

#[derive(Debug)]
pub enum Error {
    /// Error with window management
    Window(window::Error),

    /// Error dealing with fonts
    Font(font::Error),

    /// Error in renderer
    Render(renderer::Error),
}

impl ::std::error::Error for Error {
    fn cause(&self) -> Option<&::std::error::Error> {
        match *self {
            Error::Window(ref err) => Some(err),
            Error::Font(ref err) => Some(err),
            Error::Render(ref err) => Some(err),
        }
    }

    fn description(&self) -> &str {
        match *self {
            Error::Window(ref err) => err.description(),
            Error::Font(ref err) => err.description(),
            Error::Render(ref err) => err.description(),
        }
    }
}

impl ::std::fmt::Display for Error {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        match *self {
            Error::Window(ref err) => err.fmt(f),
            Error::Font(ref err) => err.fmt(f),
            Error::Render(ref err) => err.fmt(f),
        }
    }
}

impl From<window::Error> for Error {
    fn from(val: window::Error) -> Error {
        Error::Window(val)
    }
}

impl From<font::Error> for Error {
    fn from(val: font::Error) -> Error {
        Error::Font(val)
    }
}

impl From<renderer::Error> for Error {
    fn from(val: renderer::Error) -> Error {
        Error::Render(val)
    }
}

/// The display wraps a window, font rasterizer, and GPU renderer
pub struct Display {
    window: Window,
    renderer: QuadRenderer,
    glyph_cache: GlyphCache,
    render_timer: bool,
    rx: mpsc::Receiver<(u32, u32)>,
    tx: mpsc::Sender<(u32, u32)>,
    meter: Meter,
    size_info: SizeInfo,
}

/// Can wakeup the render loop from other threads
pub struct Notifier(window::Proxy);

/// Types that are interested in when the display is resized
pub trait OnResize {
    fn on_resize(&mut self, size: &SizeInfo);
}

impl Notifier {
    pub fn notify(&self) {
        self.0.wakeup_event_loop();
    }
}

impl Display {
    pub fn notifier(&self) -> Notifier {
        Notifier(self.window.create_window_proxy())
    }

    pub fn update_config(&mut self, config: &Config) {
        self.render_timer = config.render_timer();
    }

    /// Get size info about the display
    pub fn size(&self) -> &SizeInfo {
        &self.size_info
    }

    pub fn new(
        config: &Config,
        options: &cli::Options,
    ) -> Result<Display, Error> {
        // Extract some properties from config
        let font = config.font();
        let dpi = config.dpi();
        let render_timer = config.render_timer();

        // Create the window where Alacritty will be displayed
        let mut window = Window::new(&options.title)?;

        // get window properties for initializing the other subsytems
        let size = window.inner_size_pixels()
            .expect("glutin returns window size");
        let dpr = window.hidpi_factor();

        info!("device_pixel_ratio: {}", dpr);

        let rasterizer = font::Rasterizer::new(dpi.x(), dpi.y(), dpr, config.use_thin_strokes())?;

        // Create renderer
        let mut renderer = QuadRenderer::new(&config, size)?;

        // Initialize glyph cache
        let glyph_cache = {
            info!("Initializing glyph cache");
            let init_start = ::std::time::Instant::now();

            let cache = renderer.with_loader(|mut api| {
                GlyphCache::new(rasterizer, config, &mut api)
            })?;

            let stop = init_start.elapsed();
            let stop_f = stop.as_secs() as f64 + stop.subsec_nanos() as f64 / 1_000_000_000f64;
            info!("Finished initializing glyph cache in {}", stop_f);

            cache
        };

        // Need font metrics to resize the window properly. This suggests to me the
        // font metrics should be computed before creating the window in the first
        // place so that a resize is not needed.
        let metrics = glyph_cache.font_metrics();
        let cell_width = (metrics.average_advance + font.offset().x as f64) as u32;
        let cell_height = (metrics.line_height + font.offset().y as f64) as u32;

        // Resize window to specified dimensions
        let dimensions = options.dimensions()
            .unwrap_or_else(|| config.dimensions());
        let width = cell_width * dimensions.columns_u32();
        let height = cell_height * dimensions.lines_u32();
        let size = Size { width: Pixels(width), height: Pixels(height) };
        info!("set_inner_size: {}", size);

        let viewport_size = Size {
            width: Pixels(width + 2 * config.padding().x as u32),
            height: Pixels(width + 2 * config.padding().y as u32),
        };
        window.set_inner_size(&viewport_size);
        renderer.resize(viewport_size.width.0 as _, viewport_size.height.0 as _);
        info!("Cell Size: ({} x {})", cell_width, cell_height);

        let size_info = SizeInfo {
            width: viewport_size.width.0 as f32,
            height: viewport_size.height.0 as f32,
            cell_width: cell_width as f32,
            cell_height: cell_height as f32,
            padding_x: config.padding().x.floor(),
            padding_y: config.padding().y.floor(),
        };

        // Channel for resize events
        //
        // macOS has a callback for getting resize events, the channel is used
        // to queue resize events until the next draw call. Unfortunately, it
        // seems that the event loop is blocked until the window is done
        // resizing. If any drawing were to happen during a resize, it would
        // need to be in the callback.
        let (tx, rx) = mpsc::channel();

        // Clear screen
        renderer.with_api(config, &size_info, 0. /* visual bell intensity */, |api| api.clear());

        let mut display = Display {
            window: window,
            renderer: renderer,
            glyph_cache: glyph_cache,
            render_timer: render_timer,
            tx: tx,
            rx: rx,
            meter: Meter::new(),
            size_info: size_info,
        };

        let resize_tx = display.resize_channel();
        let proxy = display.window.create_window_proxy();
        display.window.set_resize_callback(move |width, height| {
            let _ = resize_tx.send((width, height));
            proxy.wakeup_event_loop();
        });

        Ok(display)
    }

    #[inline]
    pub fn resize_channel(&self) -> mpsc::Sender<(u32, u32)> {
        self.tx.clone()
    }

    pub fn window(&mut self) -> &mut Window {
        &mut self.window
    }

    /// Process pending resize events
    pub fn handle_resize(
        &mut self,
        terminal: &mut MutexGuard<Term>,
        items: &mut [&mut OnResize]
    ) {
        // Resize events new_size and are handled outside the poll_events
        // iterator. This has the effect of coalescing multiple resize
        // events into one.
        let mut new_size = None;

        // Take most recent resize event, if any
        while let Ok(sz) = self.rx.try_recv() {
            new_size = Some(sz);
        }

        // Receive any resize events; only call gl::Viewport on last
        // available
        if let Some((w, h)) = new_size.take() {
            terminal.resize(w as f32, h as f32);
            let size = terminal.size_info();

            for mut item in items {
                item.on_resize(size)
            }

            self.renderer.resize(w as i32, h as i32);
        }

    }

    /// Draw the screen
    ///
    /// A reference to Term whose state is being drawn must be provided.
    ///
    /// This call may block if vsync is enabled
    pub fn draw(&mut self, mut terminal: MutexGuard<Term>, config: &Config, selection: &Selection) {
        // Clear dirty flag
        terminal.dirty = !terminal.visual_bell.completed();

        if let Some(title) = terminal.get_next_title() {
            self.window.set_title(&title);
        }

        let size_info = *terminal.size_info();
        let visual_bell_intensity = terminal.visual_bell.intensity();

        {
            let glyph_cache = &mut self.glyph_cache;

            // Draw grid
            {
                let _sampler = self.meter.sampler();

                // Make a copy of size_info since the closure passed here
                // borrows terminal mutably
                //
                // TODO I wonder if the renderable cells iter could avoid the
                // mutable borrow
                self.renderer.with_api(config, &size_info, visual_bell_intensity, |mut api| {
                    // Draw the grid
                    api.render_cells(terminal.renderable_cells(config, selection), glyph_cache);
                });
            }

            // Draw render timer
            if self.render_timer {
                let timing = format!("{:.3} usec", self.meter.average());
                let color = Rgb { r: 0xd5, g: 0x4e, b: 0x53 };
                self.renderer.with_api(config, &size_info, visual_bell_intensity, |mut api| {
                    api.render_string(&timing[..], glyph_cache, color);
                });
            }
        }

        // Unlock the terminal mutex; following call to swap_buffers() may block
        drop(terminal);
        self.window
            .swap_buffers()
            .expect("swap buffers");

        // Clear after swap_buffers when terminal mutex isn't held. Mesa for
        // some reason takes a long time to call glClear(). The driver descends
        // into xcb_connect_to_fd() which ends up calling __poll_nocancel()
        // which blocks for a while.
        //
        // By keeping this outside of the critical region, the Mesa bug is
        // worked around to some extent. Since this doesn't actually address the
        // issue of glClear being slow, less time is available for input
        // handling and rendering.
        self.renderer.with_api(config, &size_info, visual_bell_intensity, |api| {
            api.clear();
        });
    }
}
<commit_msg>Fix viewport_size.height calculation<commit_after>// Copyright 2016 Joe Wilm, The Alacritty Project Contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! The display subsystem including window management, font rasterization, and
//! GPU drawing.
use std::sync::mpsc;

use parking_lot::{MutexGuard};

use Rgb;
use cli;
use config::Config;
use font::{self, Rasterize};
use meter::Meter;
use renderer::{self, GlyphCache, QuadRenderer};
use selection::Selection;
use term::{Term, SizeInfo};

use window::{self, Size, Pixels, Window, SetInnerSize};

#[derive(Debug)]
pub enum Error {
    /// Error with window management
    Window(window::Error),

    /// Error dealing with fonts
    Font(font::Error),

    /// Error in renderer
    Render(renderer::Error),
}

impl ::std::error::Error for Error {
    fn cause(&self) -> Option<&::std::error::Error> {
        match *self {
            Error::Window(ref err) => Some(err),
            Error::Font(ref err) => Some(err),
            Error::Render(ref err) => Some(err),
        }
    }

    fn description(&self) -> &str {
        match *self {
            Error::Window(ref err) => err.description(),
            Error::Font(ref err) => err.description(),
            Error::Render(ref err) => err.description(),
        }
    }
}

impl ::std::fmt::Display for Error {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        match *self {
            Error::Window(ref err) => err.fmt(f),
            Error::Font(ref err) => err.fmt(f),
            Error::Render(ref err) => err.fmt(f),
        }
    }
}

impl From<window::Error> for Error {
    fn from(val: window::Error) -> Error {
        Error::Window(val)
    }
}

impl From<font::Error> for Error {
    fn from(val: font::Error) -> Error {
        Error::Font(val)
    }
}

impl From<renderer::Error> for Error {
    fn from(val: renderer::Error) -> Error {
        Error::Render(val)
    }
}

/// The display wraps a window, font rasterizer, and GPU renderer
pub struct Display {
    window: Window,
    renderer: QuadRenderer,
    glyph_cache: GlyphCache,
    render_timer: bool,
    rx: mpsc::Receiver<(u32, u32)>,
    tx: mpsc::Sender<(u32, u32)>,
    meter: Meter,
    size_info: SizeInfo,
}

/// Can wakeup the render loop from other threads
pub struct Notifier(window::Proxy);

/// Types that are interested in when the display is resized
pub trait OnResize {
    fn on_resize(&mut self, size: &SizeInfo);
}

impl Notifier {
    pub fn notify(&self) {
        self.0.wakeup_event_loop();
    }
}

impl Display {
    pub fn notifier(&self) -> Notifier {
        Notifier(self.window.create_window_proxy())
    }

    pub fn update_config(&mut self, config: &Config) {
        self.render_timer = config.render_timer();
    }

    /// Get size info about the display
    pub fn size(&self) -> &SizeInfo {
        &self.size_info
    }

    pub fn new(
        config: &Config,
        options: &cli::Options,
    ) -> Result<Display, Error> {
        // Extract some properties from config
        let font = config.font();
        let dpi = config.dpi();
        let render_timer = config.render_timer();

        // Create the window where Alacritty will be displayed
        let mut window = Window::new(&options.title)?;

        // get window properties for initializing the other subsytems
        let size = window.inner_size_pixels()
            .expect("glutin returns window size");
        let dpr = window.hidpi_factor();

        info!("device_pixel_ratio: {}", dpr);

        let rasterizer = font::Rasterizer::new(dpi.x(), dpi.y(), dpr, config.use_thin_strokes())?;

        // Create renderer
        let mut renderer = QuadRenderer::new(&config, size)?;

        // Initialize glyph cache
        let glyph_cache = {
            info!("Initializing glyph cache");
            let init_start = ::std::time::Instant::now();

            let cache = renderer.with_loader(|mut api| {
                GlyphCache::new(rasterizer, config, &mut api)
            })?;

            let stop = init_start.elapsed();
            let stop_f = stop.as_secs() as f64 + stop.subsec_nanos() as f64 / 1_000_000_000f64;
            info!("Finished initializing glyph cache in {}", stop_f);

            cache
        };

        // Need font metrics to resize the window properly. This suggests to me the
        // font metrics should be computed before creating the window in the first
        // place so that a resize is not needed.
        let metrics = glyph_cache.font_metrics();
        let cell_width = (metrics.average_advance + font.offset().x as f64) as u32;
        let cell_height = (metrics.line_height + font.offset().y as f64) as u32;

        // Resize window to specified dimensions
        let dimensions = options.dimensions()
            .unwrap_or_else(|| config.dimensions());
        let width = cell_width * dimensions.columns_u32();
        let height = cell_height * dimensions.lines_u32();
        let size = Size { width: Pixels(width), height: Pixels(height) };
        info!("set_inner_size: {}", size);

        let viewport_size = Size {
            width: Pixels(width + 2 * config.padding().x as u32),
            height: Pixels(height + 2 * config.padding().y as u32),
        };
        window.set_inner_size(&viewport_size);
        renderer.resize(viewport_size.width.0 as _, viewport_size.height.0 as _);
        info!("Cell Size: ({} x {})", cell_width, cell_height);

        let size_info = SizeInfo {
            width: viewport_size.width.0 as f32,
            height: viewport_size.height.0 as f32,
            cell_width: cell_width as f32,
            cell_height: cell_height as f32,
            padding_x: config.padding().x.floor(),
            padding_y: config.padding().y.floor(),
        };

        // Channel for resize events
        //
        // macOS has a callback for getting resize events, the channel is used
        // to queue resize events until the next draw call. Unfortunately, it
        // seems that the event loop is blocked until the window is done
        // resizing. If any drawing were to happen during a resize, it would
        // need to be in the callback.
        let (tx, rx) = mpsc::channel();

        // Clear screen
        renderer.with_api(config, &size_info, 0. /* visual bell intensity */, |api| api.clear());

        let mut display = Display {
            window: window,
            renderer: renderer,
            glyph_cache: glyph_cache,
            render_timer: render_timer,
            tx: tx,
            rx: rx,
            meter: Meter::new(),
            size_info: size_info,
        };

        let resize_tx = display.resize_channel();
        let proxy = display.window.create_window_proxy();
        display.window.set_resize_callback(move |width, height| {
            let _ = resize_tx.send((width, height));
            proxy.wakeup_event_loop();
        });

        Ok(display)
    }

    #[inline]
    pub fn resize_channel(&self) -> mpsc::Sender<(u32, u32)> {
        self.tx.clone()
    }

    pub fn window(&mut self) -> &mut Window {
        &mut self.window
    }

    /// Process pending resize events
    pub fn handle_resize(
        &mut self,
        terminal: &mut MutexGuard<Term>,
        items: &mut [&mut OnResize]
    ) {
        // Resize events new_size and are handled outside the poll_events
        // iterator. This has the effect of coalescing multiple resize
        // events into one.
        let mut new_size = None;

        // Take most recent resize event, if any
        while let Ok(sz) = self.rx.try_recv() {
            new_size = Some(sz);
        }

        // Receive any resize events; only call gl::Viewport on last
        // available
        if let Some((w, h)) = new_size.take() {
            terminal.resize(w as f32, h as f32);
            let size = terminal.size_info();

            for mut item in items {
                item.on_resize(size)
            }

            self.renderer.resize(w as i32, h as i32);
        }

    }

    /// Draw the screen
    ///
    /// A reference to Term whose state is being drawn must be provided.
    ///
    /// This call may block if vsync is enabled
    pub fn draw(&mut self, mut terminal: MutexGuard<Term>, config: &Config, selection: &Selection) {
        // Clear dirty flag
        terminal.dirty = !terminal.visual_bell.completed();

        if let Some(title) = terminal.get_next_title() {
            self.window.set_title(&title);
        }

        let size_info = *terminal.size_info();
        let visual_bell_intensity = terminal.visual_bell.intensity();

        {
            let glyph_cache = &mut self.glyph_cache;

            // Draw grid
            {
                let _sampler = self.meter.sampler();

                // Make a copy of size_info since the closure passed here
                // borrows terminal mutably
                //
                // TODO I wonder if the renderable cells iter could avoid the
                // mutable borrow
                self.renderer.with_api(config, &size_info, visual_bell_intensity, |mut api| {
                    // Draw the grid
                    api.render_cells(terminal.renderable_cells(config, selection), glyph_cache);
                });
            }

            // Draw render timer
            if self.render_timer {
                let timing = format!("{:.3} usec", self.meter.average());
                let color = Rgb { r: 0xd5, g: 0x4e, b: 0x53 };
                self.renderer.with_api(config, &size_info, visual_bell_intensity, |mut api| {
                    api.render_string(&timing[..], glyph_cache, color);
                });
            }
        }

        // Unlock the terminal mutex; following call to swap_buffers() may block
        drop(terminal);
        self.window
            .swap_buffers()
            .expect("swap buffers");

        // Clear after swap_buffers when terminal mutex isn't held. Mesa for
        // some reason takes a long time to call glClear(). The driver descends
        // into xcb_connect_to_fd() which ends up calling __poll_nocancel()
        // which blocks for a while.
        //
        // By keeping this outside of the critical region, the Mesa bug is
        // worked around to some extent. Since this doesn't actually address the
        // issue of glClear being slow, less time is available for input
        // handling and rendering.
        self.renderer.with_api(config, &size_info, visual_bell_intensity, |api| {
            api.clear();
        });
    }
}
<|endoftext|>


<commit_before>// Copyright 2014 Jonathan Eyolfson

use std::ptr;

use raw;

pub struct Display {
    ptr: *mut raw::wl_display
}

impl Display {
    pub fn connect_to_env_or_default() -> Display {
        unsafe {
            let ptr = raw::wl_display_connect(ptr::null());
            assert!(!ptr.is_null(), "wl_display_connect failed");
            Display { ptr: ptr }
        }
    }
    pub fn connect(name: &str) -> Display {
        unsafe {
            let ptr = raw::wl_display_connect(name.as_ptr() as *const i8);
            assert!(!ptr.is_null(), "wl_display_connect failed");
            Display { ptr: ptr }
        }
    }
    pub fn roundtrip(&mut self) -> i32 {
        unsafe {
            let r = raw::wl_display_roundtrip(self.ptr);
            assert!(r != -1, "wl_display_roundtrip failed");
            r
        }
    }
    pub fn read_events(&mut self) {
        unsafe {
            let r = raw::wl_display_read_events(self.ptr);
            assert!(r != -1, "wl_display_read_events failed");
        }
    }
    pub fn prepare_read(&mut self) {
        unsafe {
            let r = raw::wl_display_prepare_read(self.ptr);
            assert!(r != -1, "wl_display_prepare_read failed");
        }
    }
    pub fn cancel_read(&mut self) {
        unsafe {
            raw::wl_display_cancel_read(self.ptr);
        }
    }
    pub fn dispatch(&mut self) -> i32 {
        unsafe {
            let r = raw::wl_display_dispatch(self.ptr);
            assert!(r != -1, "wl_display_dispatch failed");
            r
        }
    }
    pub fn flush(&mut self) -> i32 {
        unsafe {
            let r = raw::wl_display_flush(self.ptr);
            assert!(r != -1, "wl_display_flush failed");
            r
        }
    }
    pub unsafe fn to_ptr(&mut self) -> *mut raw::wl_display { self.ptr }
}

impl Drop for Display {
    fn drop(&mut self) {
        unsafe {
            raw::wl_display_disconnect(self.ptr);
        }
    }
}
<commit_msg>Ensure that name is null terminated for FFI call in Display connect<commit_after>// Copyright 2014 Jonathan Eyolfson

use std::ptr;

use raw;

pub struct Display {
    ptr: *mut raw::wl_display
}

impl Display {
    pub fn connect_to_env_or_default() -> Display {
        unsafe {
            let ptr = raw::wl_display_connect(ptr::null());
            assert!(!ptr.is_null(), "wl_display_connect failed");
            Display { ptr: ptr }
        }
    }
    pub fn connect(name: &str) -> Display {
        let c_str = name.to_c_str();
        unsafe {
            let ptr = raw::wl_display_connect(c_str.as_ptr());
            assert!(!ptr.is_null(), "wl_display_connect failed");
            Display { ptr: ptr }
        }
    }
    pub fn roundtrip(&mut self) -> i32 {
        unsafe {
            let r = raw::wl_display_roundtrip(self.ptr);
            assert!(r != -1, "wl_display_roundtrip failed");
            r
        }
    }
    pub fn read_events(&mut self) {
        unsafe {
            let r = raw::wl_display_read_events(self.ptr);
            assert!(r != -1, "wl_display_read_events failed");
        }
    }
    pub fn prepare_read(&mut self) {
        unsafe {
            let r = raw::wl_display_prepare_read(self.ptr);
            assert!(r != -1, "wl_display_prepare_read failed");
        }
    }
    pub fn cancel_read(&mut self) {
        unsafe {
            raw::wl_display_cancel_read(self.ptr);
        }
    }
    pub fn dispatch(&mut self) -> i32 {
        unsafe {
            let r = raw::wl_display_dispatch(self.ptr);
            assert!(r != -1, "wl_display_dispatch failed");
            r
        }
    }
    pub fn flush(&mut self) -> i32 {
        unsafe {
            let r = raw::wl_display_flush(self.ptr);
            assert!(r != -1, "wl_display_flush failed");
            r
        }
    }
    pub unsafe fn to_ptr(&mut self) -> *mut raw::wl_display { self.ptr }
}

impl Drop for Display {
    fn drop(&mut self) {
        unsafe {
            raw::wl_display_disconnect(self.ptr);
        }
    }
}
<|endoftext|>


<commit_before>// I thought I need to memoize this but it is plenty fast already
fn collatz_length(a: u32) -> u32 {
    let mut length = 1;
    let mut n: u64 = a as u64;
    while n != 1 {
        if n % 2 == 0 {
            n  /= 2;
        } else {
            n = 3 * n + 1;
        }
        length += 1;
    }
    length
}

pub fn main() {
    let mut max = 0;
    let mut maxi = 0;
    for i in 2..1_000_000 {
        let cl = collatz_length(i);
        if cl > max {
            max = cl;
            maxi = i;
        }
    }
    println!("{}", maxi);
}
<commit_msg>a litte more rusty code<commit_after>// I thought I need to memoize this but it is plenty fast already
fn collatz_length(a: u32) -> u32 {
    let mut length = 1;
    let mut n: u64 = a as u64;
    while n != 1 {
        n = if n % 2 == 0 {
            n  / 2
        } else {
            3 * n + 1
        };
        length += 1;
    }
    length
}

pub fn main() {
    let mut max = 0;
    let mut maxi = 0;
    for i in 2..1_000_000 {
        let cl = collatz_length(i);
        if cl > max {
            max = cl;
            maxi = i;
        }
    }
    println!("{}", maxi);
}
<|endoftext|>


<commit_before>use rustc_middle::mir::mono::{Linkage as RLinkage, MonoItem, Visibility};

use crate::prelude::*;

pub(crate) fn get_clif_linkage(mono_item: MonoItem<'_>, linkage: RLinkage, visibility: Visibility) -> Linkage {
    match (linkage, visibility) {
        (RLinkage::External, Visibility::Default) => Linkage::Export,
        (RLinkage::Internal, Visibility::Default) => Linkage::Local,
        (RLinkage::External, Visibility::Hidden) => Linkage::Hidden,
        _ => panic!("{:?} = {:?} {:?}", mono_item, linkage, visibility),
    }
}

pub(crate) fn get_static_linkage(tcx: TyCtxt<'_>, def_id: DefId) -> Linkage {
    let fn_attrs = tcx.codegen_fn_attrs(def_id);

    if let Some(linkage) = fn_attrs.linkage {
        match linkage {
            RLinkage::External => Linkage::Export,
            RLinkage::Internal => Linkage::Local,
            RLinkage::ExternalWeak | RLinkage::WeakAny => Linkage::Preemptible,
            _ => panic!("{:?}", linkage),
        }
    } else {
        if tcx.is_reachable_non_generic(def_id) {
            Linkage::Export
        } else {
            Linkage::Export // FIXME use Linkage::Hidden
        }
    }
}
<commit_msg>linkage: Change linkage to hidden on non-exported symbols<commit_after>use rustc_middle::mir::mono::{Linkage as RLinkage, MonoItem, Visibility};

use crate::prelude::*;

pub(crate) fn get_clif_linkage(mono_item: MonoItem<'_>, linkage: RLinkage, visibility: Visibility) -> Linkage {
    match (linkage, visibility) {
        (RLinkage::External, Visibility::Default) => Linkage::Export,
        (RLinkage::Internal, Visibility::Default) => Linkage::Local,
        (RLinkage::External, Visibility::Hidden) => Linkage::Hidden,
        _ => panic!("{:?} = {:?} {:?}", mono_item, linkage, visibility),
    }
}

pub(crate) fn get_static_linkage(tcx: TyCtxt<'_>, def_id: DefId) -> Linkage {
    let fn_attrs = tcx.codegen_fn_attrs(def_id);

    if let Some(linkage) = fn_attrs.linkage {
        match linkage {
            RLinkage::External => Linkage::Export,
            RLinkage::Internal => Linkage::Local,
            RLinkage::ExternalWeak | RLinkage::WeakAny => Linkage::Preemptible,
            _ => panic!("{:?}", linkage),
        }
    } else {
        if tcx.is_reachable_non_generic(def_id) {
            Linkage::Export
        } else {
            Linkage::Hidden
        }
    }
}
<|endoftext|>


<commit_before>//! Log all requests in a format similar to Heroku's router, but with additional
//! information that we care about like User-Agent and Referer

use super::prelude::*;
use crate::util::request_header;
use conduit::Request;
use std::fmt;
use std::time::Instant;

#[allow(missing_debug_implementations)] // We can't
#[derive(Default)]
pub struct LogRequests {
    handler: Option<Box<dyn Handler>>,
}

impl AroundMiddleware for LogRequests {
    fn with_handler(&mut self, handler: Box<dyn Handler>) {
        self.handler = Some(handler);
    }
}

impl Handler for LogRequests {
    fn call(&self, req: &mut dyn Request) -> Result<Response, Box<dyn Error + Send>> {
        let request_start = Instant::now();
        let res = self.handler.as_ref().unwrap().call(req);
        let (level, response_code) = match res {
            Ok(ref r) => ("info", r.status.0),
            Err(_) => ("error", 500),
        };
        let response_time = request_start.elapsed();
        let response_time =
            response_time.as_secs() * 1000 + u64::from(response_time.subsec_nanos()) / 1_000_000;

        print!(
            "at={level} method={method} path=\"{path}\" \
             request_id={request_id} fwd=\"{ip}\" service={time_ms}ms \
             status={status} user_agent=\"{user_agent}\" referer=\"{referer}\"",
            level = level,
            method = req.method(),
            path = FullPath(req),
            ip = request_header(req, "X-Real-Ip"),
            time_ms = response_time,
            user_agent = request_header(req, "User-Agent"),
            referer = request_header(req, "Referer"), // sic
            request_id = request_header(req, "X-Request-Id"),
            status = response_code,
        );

        if let Err(ref e) = res {
            print!(" error=\"{}\"", e.description());
        }

        if response_time > 1000 {
            print!(" SLOW REQUEST");
        }

        println!();

        res
    }
}

struct FullPath<'a>(&'a dyn Request);

impl<'a> fmt::Display for FullPath<'a> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{}", self.0.path())?;
        if let Some(q_string) = self.0.query_string() {
            write!(f, "?{}", q_string)?;
        }
        Ok(())
    }
}
<commit_msg>Stop logging the referer header<commit_after>//! Log all requests in a format similar to Heroku's router, but with additional
//! information that we care about like User-Agent

use super::prelude::*;
use crate::util::request_header;
use conduit::Request;
use std::fmt;
use std::time::Instant;

#[allow(missing_debug_implementations)] // We can't
#[derive(Default)]
pub struct LogRequests {
    handler: Option<Box<dyn Handler>>,
}

impl AroundMiddleware for LogRequests {
    fn with_handler(&mut self, handler: Box<dyn Handler>) {
        self.handler = Some(handler);
    }
}

impl Handler for LogRequests {
    fn call(&self, req: &mut dyn Request) -> Result<Response, Box<dyn Error + Send>> {
        let request_start = Instant::now();
        let res = self.handler.as_ref().unwrap().call(req);
        let (level, response_code) = match res {
            Ok(ref r) => ("info", r.status.0),
            Err(_) => ("error", 500),
        };
        let response_time = request_start.elapsed();
        let response_time =
            response_time.as_secs() * 1000 + u64::from(response_time.subsec_nanos()) / 1_000_000;

        print!(
            "at={level} method={method} path=\"{path}\" \
             request_id={request_id} fwd=\"{ip}\" service={time_ms}ms \
             status={status} user_agent=\"{user_agent}\"",
            level = level,
            method = req.method(),
            path = FullPath(req),
            ip = request_header(req, "X-Real-Ip"),
            time_ms = response_time,
            user_agent = request_header(req, "User-Agent"),
            request_id = request_header(req, "X-Request-Id"),
            status = response_code,
        );

        if let Err(ref e) = res {
            print!(" error=\"{}\"", e.description());
        }

        if response_time > 1000 {
            print!(" SLOW REQUEST");
        }

        println!();

        res
    }
}

struct FullPath<'a>(&'a dyn Request);

impl<'a> fmt::Display for FullPath<'a> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{}", self.0.path())?;
        if let Some(q_string) = self.0.query_string() {
            write!(f, "?{}", q_string)?;
        }
        Ok(())
    }
}
<|endoftext|>


<commit_before>use serde_json;
use chrono::NaiveDateTime;

use error::Result;
use error::Error;
use user::User;
use chat::Chat;
use ::ValueExtension;

pub struct Message {
    pub message_id: i64,
    pub from_user: Option<User>,  // TODO: Change to User struct
    pub date: NaiveDateTime,
    pub chat: String,  // TODO: Change to Chat struct
    pub forward_from: Option<String>,  // TODO: Change to User struct
    pub forward_from_chat: Option<String>,  // TODO: Change to Chat struct
    pub forward_from_message_id: Option<i32>,
    pub forward_date: Option<i32>,
    pub reply_to_message: Option<Box<Message>>,
    pub edit_date: Option<i32>,
    pub text: Option<String>,
    pub entities: Option<String>,  // TODO: Change to MessageEntity struct
    pub audio: Option<String>,  // TODO: Change to audio struct
    pub document: Option<String>,  // TODO: Change to Document struct
    pub game: Option<String>,  // TODO: Change to Game struct
    pub photo: Option<String>,  // TODO: Change to Photo struct
    pub sticker: Option<String>,  // TODO: Change to Sticker struct
    pub video: Option<String>,  // TODO: Change to Video struct
    pub voice: Option<String>,  // TODO: Change to Voice struct
    pub caption: Option<String>,
    pub contact: Option<String>,  // TODO: Change to Contact struct
    pub location: Option<String>,  // TODO: Change to Location struct
    pub venue: Option<String>,  // TODO: Change to Venue struct
    pub new_chat_member: Option<String>,  // TODO: Change to User struct
    pub left_chat_member: Option<String>,  // TODO: Change to User struct
    pub new_chat_title: Option<String>,
    pub new_chat_photo: Option<String>,  // TODO: Change to array of Photo structs
    pub delete_chat_photo: Option<bool>,
    pub group_chat_created: Option<bool>,
    pub supergroup_chat_created: Option<bool>,
    pub channel_chat_created: Option<bool>,
    pub migrate_to_chat_id: Option<i32>,
    pub migrate_from_chat_id: Option<i32>,
    pub pinned_message: Option<String>,  // TODO: Change to Message struct
}

impl Message {
    pub fn new(message: &serde_json::Value) -> Result<i32> {
        let message_id = message.as_required_i64("message_id")?;
        let from_user = User::new(message.find("from").ok_or(Error::JsonNotFound)?)?;
        let date = message.as_required_date("date")?;
        let chat = Chat::new(message.find("chat").ok_or(Error::JsonNotFound)?)?;

        Ok(0)
    }
}
<commit_msg>Adding more fields from json<commit_after>use serde_json;
use chrono::NaiveDateTime;

use error::Result;
use error::Error;
use user::User;
use chat::Chat;
use ::ValueExtension;

pub struct Message {
    pub message_id: i64,
    pub from_user: Option<User>,
    pub date: NaiveDateTime,
    pub chat: Chat,
    pub forward_from: Option<User>,
    pub forward_from_chat: Option<Chat>,
    pub forward_from_message_id: Option<i64>,
    pub forward_date: Option<NaiveDateTime>,
    pub reply_to_message: Option<Box<Message>>,
    pub edit_date: Option<i64>,
    pub text: Option<String>,
    pub entities: Option<String>,  // TODO: Change to MessageEntity struct
    pub audio: Option<String>,  // TODO: Change to audio struct
    pub document: Option<String>,  // TODO: Change to Document struct
    pub game: Option<String>,  // TODO: Change to Game struct
    pub photo: Option<String>,  // TODO: Change to Photo struct
    pub sticker: Option<String>,  // TODO: Change to Sticker struct
    pub video: Option<String>,  // TODO: Change to Video struct
    pub voice: Option<String>,  // TODO: Change to Voice struct
    pub caption: Option<String>,
    pub contact: Option<String>,  // TODO: Change to Contact struct
    pub location: Option<String>,  // TODO: Change to Location struct
    pub venue: Option<String>,  // TODO: Change to Venue struct
    pub new_chat_member: Option<String>,  // TODO: Change to User struct
    pub left_chat_member: Option<String>,  // TODO: Change to User struct
    pub new_chat_title: Option<String>,
    pub new_chat_photo: Option<String>,  // TODO: Change to array of Photo structs
    pub delete_chat_photo: Option<bool>,
    pub group_chat_created: Option<bool>,
    pub supergroup_chat_created: Option<bool>,
    pub channel_chat_created: Option<bool>,
    pub migrate_to_chat_id: Option<i32>,
    pub migrate_from_chat_id: Option<i32>,
    pub pinned_message: Option<String>,  // TODO: Change to Message struct
}

impl Message {
    pub fn new(message: &serde_json::Value) -> Result<i32> {
        let message_id = message.as_required_i64("message_id")?;
        let from_user = message.find("from").map(User::new);
        let date = message.as_required_date("date")?;
        let chat = Chat::new(message.find("chat").ok_or(Error::JsonNotFound)?)?;
        let forward_from = message.find("forward_from").map(User::new);
        let forward_from_chat = message.find("forward_from_chat").map(Chat::new);
        let forward_from_message_id = message.as_required_i64("forward_from_message_id");
        let forward_date = message.as_optional_date("forward_date");

        Ok(0)
    }
}
<|endoftext|>


<commit_before>use sync::{Arc, Weak};

use vec::Vec;
use vec_deque::VecDeque;

use sync::spin::{InterruptSpinLock, RwLock, RwLockReadGuard};

use thread::WaitQueue;

use net::Interface;

use hal::net::discover;

use net::Packet;
use net::defs::Device;

const MAX_QUEUE_SIZE: usize = 512;

#[derive(Clone)]
/// A network stack
///
/// This object represent a shareable network stack. This object stack
/// internally uses an Arc so it can be safely shared.
pub struct Instance(Arc<InstanceRaw>);

/// A weak reference over a network stack
pub struct InstanceWeak(Weak<InstanceRaw>);

struct InstanceRaw {
    /// Interfaces registered
    interfaces: RwLock<Vec<Interface>>,
    /// Contains packets to be processed
    rx_queue: InterruptSpinLock<VecDeque<Packet>>,
    /// Used to wait for packet to arrive in the rx_queue
    rx_wait: WaitQueue,
}

// rx_queue is protected by a spin lock
// rx_wait is Sync
unsafe impl Sync for InstanceRaw {}

impl Instance {
    /// Network thread linked to an instance
    ///
    /// This function is used to process packet that are received within a
    /// network stack instance
    pub fn network_thread(instance: Instance) {
        loop {
            let pkt_opt = instance.0.rx_queue.lock().pop_front();

            match pkt_opt {
                None => {
                    instance.refresh_interfaces();
                    // No packet to process => wait for one to come
                    wait_event!(instance.0.rx_wait,
                                !instance.0.rx_queue.lock().is_empty());
                    instance.refresh_interfaces();
                }
                Some(pkt) => {
                    // Treat the packet
                    println!("New incoming packet!");
                }
            }
        }
    }

    /// Create a new network stack
    ///
    /// TODO: This cannot really be used more than once for now.
    pub fn new() -> Self {
        let inner = Arc::new(InstanceRaw {
            interfaces: RwLock::new(Vec::new()),
            rx_queue: InterruptSpinLock::new(VecDeque::with_capacity(MAX_QUEUE_SIZE)),
            rx_wait: WaitQueue::new(),
        });

        let instance = Instance(inner);

        let intfs = discover();

        if intfs.is_empty() {
            println!("Warning: Uni.rs is built with network capabilities but no interface found");
        } else {
            println!("{} interface(s) discovered:", intfs.len());

            for i in &intfs {
                println!("  - {} ({})", i.read().name_ref(),
                         i.read().hw_addr_ref());
            }
        }

        *(instance.0.interfaces.write()) = intfs;

        instance
    }

    /// Get a weak reference over the network stack
    pub fn downgrade(&self) -> InstanceWeak {
        InstanceWeak(Arc::downgrade(&self.0))
    }

    /// Get the list of registered interfaces within network stack
    pub fn interfaces<'a>(&'a self) -> RwLockReadGuard<'a, Vec<Interface>> {
        self.0.interfaces.read()
    }

    /// Call refresh on every registered interface
    fn refresh_interfaces(&self) {
        for intf in self.interfaces().iter() {
            intf.write().refresh();
        }
    }

    /// Enqueue a packet to be received on the network stack
    ///
    /// Returns false if the receive queue is full and therefore the packet was
    /// not enqueued.
    ///
    /// Note: This is safe to be called from interrupt context. Indeed the
    /// receive queue is not resizable so no allocation will be performed by
    /// this function
    pub fn enqueue_rx_packet(&self, packet: Packet) -> bool {
        let mut locked_rx_queue = self.0.rx_queue.lock();

        if locked_rx_queue.len() == MAX_QUEUE_SIZE {
            // Queue is full, we don't want to cause a reallocation in
            // interruption context. So we don't enqueue the packet
            return false;
        }

        // Enqueue the packet
        locked_rx_queue.push_back(packet);

        // Wake up network thread
        self.0.rx_wait.unblock();

        true
    }
}

impl InstanceWeak {
    /// Upgrade the weak reference to a strong one
    pub fn upgrade(&self) -> Option<Instance> {
        self.0.upgrade().map(|strong| Instance(strong))
    }
}
<commit_msg>net/imp: Fix some issues detected by clippy<commit_after>use sync::{Arc, Weak};

use vec::Vec;
use vec_deque::VecDeque;

use sync::spin::{InterruptSpinLock, RwLock, RwLockReadGuard};

use thread::WaitQueue;

use net::Interface;

use hal::net::discover;

use net::Packet;
use net::defs::Device;

const MAX_QUEUE_SIZE: usize = 512;

#[derive(Clone)]
/// A network stack
///
/// This object represent a shareable network stack. This object stack
/// internally uses an Arc so it can be safely shared.
pub struct Instance(Arc<InstanceRaw>);

/// A weak reference over a network stack
pub struct InstanceWeak(Weak<InstanceRaw>);

struct InstanceRaw {
    /// Interfaces registered
    interfaces: RwLock<Vec<Interface>>,
    /// Contains packets to be processed
    rx_queue: InterruptSpinLock<VecDeque<Packet>>,
    /// Used to wait for packet to arrive in the rx_queue
    rx_wait: WaitQueue,
}

// rx_queue is protected by a spin lock
// rx_wait is Sync
unsafe impl Sync for InstanceRaw {}

impl Instance {
    /// Network thread linked to an instance
    ///
    /// This function is used to process packet that are received within a
    /// network stack instance
    pub fn network_thread(instance: Instance) {
        loop {
            let pkt_opt = instance.0.rx_queue.lock().pop_front();

            match pkt_opt {
                None => {
                    instance.refresh_interfaces();
                    // No packet to process => wait for one to come
                    wait_event!(instance.0.rx_wait,
                                !instance.0.rx_queue.lock().is_empty());
                    instance.refresh_interfaces();
                }
                Some(pkt) => {
                    // Treat the packet
                    println!("New incoming packet!");
                }
            }
        }
    }

    /// Create a new network stack
    ///
    /// TODO: This cannot really be used more than once for now.
    pub fn new() -> Self {
        let inner = Arc::new(InstanceRaw {
            interfaces: RwLock::new(Vec::new()),
            rx_queue: InterruptSpinLock::new(VecDeque::with_capacity(MAX_QUEUE_SIZE)),
            rx_wait: WaitQueue::new(),
        });

        let instance = Instance(inner);

        let intfs = discover();

        if intfs.is_empty() {
            println!("Warning: Uni.rs is built with network capabilities but no interface found");
        } else {
            println!("{} interface(s) discovered:", intfs.len());

            for i in &intfs {
                println!("  - {} ({})", i.read().name_ref(),
                         i.read().hw_addr_ref());
            }
        }

        *(instance.0.interfaces.write()) = intfs;

        instance
    }

    /// Get a weak reference over the network stack
    pub fn downgrade(&self) -> InstanceWeak {
        InstanceWeak(Arc::downgrade(&self.0))
    }

    /// Get the list of registered interfaces within network stack
    pub fn interfaces(&self) -> RwLockReadGuard<Vec<Interface>> {
        self.0.interfaces.read()
    }

    /// Call refresh on every registered interface
    fn refresh_interfaces(&self) {
        for intf in self.interfaces().iter() {
            intf.write().refresh();
        }
    }

    /// Enqueue a packet to be received on the network stack
    ///
    /// Returns false if the receive queue is full and therefore the packet was
    /// not enqueued.
    ///
    /// Note: This is safe to be called from interrupt context. Indeed the
    /// receive queue is not resizable so no allocation will be performed by
    /// this function
    pub fn enqueue_rx_packet(&self, packet: Packet) -> bool {
        let mut locked_rx_queue = self.0.rx_queue.lock();

        if locked_rx_queue.len() == MAX_QUEUE_SIZE {
            // Queue is full, we don't want to cause a reallocation in
            // interruption context. So we don't enqueue the packet
            return false;
        }

        // Enqueue the packet
        locked_rx_queue.push_back(packet);

        // Wake up network thread
        self.0.rx_wait.unblock();

        true
    }
}

impl InstanceWeak {
    /// Upgrade the weak reference to a strong one
    pub fn upgrade(&self) -> Option<Instance> {
        self.0.upgrade().map(Instance)
    }
}
<|endoftext|>


<commit_before>// Copyright 2015 The Servo Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution.
//
// 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 bincode;
use std::sync::mpsc;
use std::sync::{Arc, Mutex};
use std::collections::hash_map::HashMap;
use std::cell::{RefCell};
use std::io::{Error, ErrorKind};
use std::slice;
use std::fmt::{self, Debug, Formatter};
use std::cmp::{PartialEq};
use std::ops::Deref;
use std::mem;
use std::usize;
use uuid::Uuid;

use super::incrementor::Incrementor;

#[derive(Clone)]
struct ServerRecord {
    sender: OsIpcSender,
    conn_sender: mpsc::Sender<bool>,
    conn_receiver: Arc<Mutex<mpsc::Receiver<bool>>>,
}

impl ServerRecord {
    fn new(sender: OsIpcSender) -> ServerRecord {
        let (tx, rx) = mpsc::channel::<bool>();
        ServerRecord {
            sender: sender,
            conn_sender: tx,
            conn_receiver: Arc::new(Mutex::new(rx)),
        }
    }

    fn accept(&self) {
        self.conn_receiver.lock().unwrap().recv().unwrap();
    }

    fn connect(&self) {
        self.conn_sender.send(true).unwrap();
    }
}

lazy_static! {
    static ref ONE_SHOT_SERVERS: Mutex<HashMap<String,ServerRecord>> = Mutex::new(HashMap::new());
}

struct MpscChannelMessage(Vec<u8>, Vec<OsIpcChannel>, Vec<OsIpcSharedMemory>);

pub fn channel() -> Result<(OsIpcSender, OsIpcReceiver),MpscError> {
    let (base_sender, base_receiver) = mpsc::channel::<MpscChannelMessage>();
    Ok((OsIpcSender::new(base_sender), OsIpcReceiver::new(base_receiver)))
}

#[derive(Debug)]
pub struct OsIpcReceiver {
    receiver: RefCell<Option<mpsc::Receiver<MpscChannelMessage>>>,
}

impl PartialEq for OsIpcReceiver {
    fn eq(&self, other: &OsIpcReceiver) -> bool {
        self.receiver.borrow().as_ref().map(|rx| rx as *const _) ==
            other.receiver.borrow().as_ref().map(|rx| rx as *const _)
    }
}

impl OsIpcReceiver {
    fn new(receiver: mpsc::Receiver<MpscChannelMessage>) -> OsIpcReceiver {
        OsIpcReceiver {
            receiver: RefCell::new(Some(receiver)),
        }
    }

    pub fn consume(&self) -> OsIpcReceiver {
        let receiver = self.receiver.borrow_mut().take();
        OsIpcReceiver::new(receiver.unwrap())
    }

    pub fn recv(&self) -> Result<(Vec<u8>, Vec<OsOpaqueIpcChannel>, Vec<OsIpcSharedMemory>),MpscError> {
        let r = self.receiver.borrow();
        match r.as_ref().unwrap().recv() {
            Ok(MpscChannelMessage(d,c,s)) => Ok((d,
                                                 c.into_iter().map(OsOpaqueIpcChannel::new).collect(),
                                                 s)),
            Err(_) => Err(MpscError::ChannelClosedError),
        }
    }

    pub fn try_recv(&self) -> Result<(Vec<u8>, Vec<OsOpaqueIpcChannel>, Vec<OsIpcSharedMemory>),MpscError> {
        let r = self.receiver.borrow();
        match r.as_ref().unwrap().try_recv() {
            Ok(MpscChannelMessage(d,c,s)) => Ok((d,
                                                 c.into_iter().map(OsOpaqueIpcChannel::new).collect(),
                                                 s)),
            Err(_) => Err(MpscError::ChannelClosedError),
        }
    }
}

#[derive(Clone, Debug)]
pub struct OsIpcSender {
    sender: RefCell<mpsc::Sender<MpscChannelMessage>>,
}

impl PartialEq for OsIpcSender {
    fn eq(&self, other: &OsIpcSender) -> bool {
        &*self.sender.borrow() as *const _ ==
            &*other.sender.borrow() as *const _
    }
}

impl OsIpcSender {
    fn new(sender: mpsc::Sender<MpscChannelMessage>) -> OsIpcSender {
        OsIpcSender {
            sender: RefCell::new(sender),
        }
    }

    pub fn connect(name: String) -> Result<OsIpcSender,MpscError> {
        let record = ONE_SHOT_SERVERS.lock().unwrap().get(&name).unwrap().clone();
        record.connect();
        Ok(record.sender)
    }

    pub fn get_max_fragment_size() -> usize {
        usize::MAX
    }

    pub fn send(&self,
                data: &[u8],
                ports: Vec<OsIpcChannel>,
                shared_memory_regions: Vec<OsIpcSharedMemory>)
                -> Result<(),MpscError>
    {
        match self.sender.borrow().send(MpscChannelMessage(data.to_vec(), ports, shared_memory_regions)) {
            Err(_) => Err(MpscError::BrokenPipeError),
            Ok(_) => Ok(()),
        }
    }
}

pub struct OsIpcReceiverSet {
    incrementor: Incrementor,
    receiver_ids: Vec<u64>,
    receivers: Vec<OsIpcReceiver>,
}

impl OsIpcReceiverSet {
    pub fn new() -> Result<OsIpcReceiverSet,MpscError> {
        Ok(OsIpcReceiverSet {
            incrementor: Incrementor::new(),
            receiver_ids: vec![],
            receivers: vec![],
        })
    }

    pub fn add(&mut self, receiver: OsIpcReceiver) -> Result<u64,MpscError> {
        let last_index = self.incrementor.increment();
        self.receiver_ids.push(last_index);
        self.receivers.push(receiver.consume());
        Ok(last_index)
    }

    pub fn select(&mut self) -> Result<Vec<OsIpcSelectionResult>,MpscError> {
        let mut receivers: Vec<Option<mpsc::Receiver<MpscChannelMessage>>> = Vec::with_capacity(self.receivers.len());
        let mut r_id: Option<u64> = None;
        let mut r_index: usize = 0;

        {
            let select = mpsc::Select::new();
            // we *must* allocate exact capacity for this, because the Handles *can't move*
            let mut handles: Vec<mpsc::Handle<MpscChannelMessage>> = Vec::with_capacity(self.receivers.len());

            for r in &self.receivers {
                let inner_r = mem::replace(&mut *r.receiver.borrow_mut(), None);
                receivers.push(inner_r);
            }

            for r in &receivers {
                unsafe {
                    handles.push(select.handle(r.as_ref().unwrap()));
                    handles.last_mut().unwrap().add();
                }
            }

            let id = select.wait();

            for (index,h) in handles.iter().enumerate() {
                if h.id() == id {
                    r_index = index;
                    r_id = Some(self.receiver_ids[index]);
                    break;
                }
            }
        }

        // put the receivers back
        for (index,r) in self.receivers.iter().enumerate() {
            mem::replace(&mut *r.receiver.borrow_mut(), mem::replace(&mut receivers[index], None));
        }

        match r_id {
            None => Err(MpscError::UnknownError),
            Some(r_id) => {
                let receivers = &mut self.receivers;
                match receivers[r_index].recv() {
                    Ok((data, channels, shmems)) =>
                        Ok(vec![OsIpcSelectionResult::DataReceived(r_id, data, channels, shmems)]),
                    Err(MpscError::ChannelClosedError) => {
                        receivers.remove(r_index);
                        self.receiver_ids.remove(r_index);
                        Ok(vec![OsIpcSelectionResult::ChannelClosed(r_id)])
                    },
                    Err(err) => Err(err),
                }
            }
        }
    }
}

pub enum OsIpcSelectionResult {
    DataReceived(u64, Vec<u8>, Vec<OsOpaqueIpcChannel>, Vec<OsIpcSharedMemory>),
    ChannelClosed(u64),
}

impl OsIpcSelectionResult {
    pub fn unwrap(self) -> (u64, Vec<u8>, Vec<OsOpaqueIpcChannel>, Vec<OsIpcSharedMemory>) {
        match self {
            OsIpcSelectionResult::DataReceived(id, data, channels, shared_memory_regions) => {
                (id, data, channels, shared_memory_regions)
            }
            OsIpcSelectionResult::ChannelClosed(id) => {
                panic!("OsIpcSelectionResult::unwrap(): receiver ID {} was closed!", id)
            }
        }
    }
}

pub struct OsIpcOneShotServer {
    receiver: OsIpcReceiver,
    name: String,
}

impl OsIpcOneShotServer {
    pub fn new() -> Result<(OsIpcOneShotServer, String),MpscError> {
        let (sender, receiver) = try!(channel());

        let name = Uuid::new_v4().to_string();
        let record = ServerRecord::new(sender);
        ONE_SHOT_SERVERS.lock().unwrap().insert(name.clone(), record);
        Ok((OsIpcOneShotServer {
            receiver: receiver,
            name: name.clone(),
        },name.clone()))
    }

    pub fn accept(self) -> Result<(OsIpcReceiver,
                                    Vec<u8>,
                                    Vec<OsOpaqueIpcChannel>,
                                    Vec<OsIpcSharedMemory>),MpscError>
    {
        let record = ONE_SHOT_SERVERS.lock().unwrap().get(&self.name).unwrap().clone();
        record.accept();
        ONE_SHOT_SERVERS.lock().unwrap().remove(&self.name).unwrap();
        let (data, channels, shmems) = try!(self.receiver.recv());
        Ok((self.receiver, data, channels, shmems))
    }
}

#[derive(PartialEq, Debug)]
pub enum OsIpcChannel {
    Sender(OsIpcSender),
    Receiver(OsIpcReceiver),
}

#[derive(PartialEq, Debug)]
pub struct OsOpaqueIpcChannel {
    channel: RefCell<Option<OsIpcChannel>>,
}

impl OsOpaqueIpcChannel {
    fn new(channel: OsIpcChannel) -> OsOpaqueIpcChannel {
        OsOpaqueIpcChannel {
            channel: RefCell::new(Some(channel))
        }
    }

    pub fn to_receiver(&self) -> OsIpcReceiver {
        match self.channel.borrow_mut().take().unwrap() {
            OsIpcChannel::Sender(_) => panic!("Opaque channel is not a receiver!"),
            OsIpcChannel::Receiver(r) => r
        }
    }

    pub fn to_sender(&mut self) -> OsIpcSender {
        match self.channel.borrow_mut().take().unwrap() {
            OsIpcChannel::Sender(s) => s,
            OsIpcChannel::Receiver(_) => panic!("Opaque channel is not a sender!"),
        }
    }
}

pub struct OsIpcSharedMemory {
    ptr: *mut u8,
    length: usize,
    data: Arc<Vec<u8>>,
}

unsafe impl Send for OsIpcSharedMemory {}
unsafe impl Sync for OsIpcSharedMemory {}

impl Clone for OsIpcSharedMemory {
    fn clone(&self) -> OsIpcSharedMemory {
        OsIpcSharedMemory {
            ptr: self.ptr,
            length: self.length,
            data: self.data.clone(),
        }
    }
}

impl PartialEq for OsIpcSharedMemory {
    fn eq(&self, other: &OsIpcSharedMemory) -> bool {
        **self == **other
    }
}

impl Debug for OsIpcSharedMemory {
    fn fmt(&self, formatter: &mut Formatter) -> Result<(), fmt::Error> {
        (**self).fmt(formatter)
    }
}

impl Deref for OsIpcSharedMemory {
    type Target = [u8];

    #[inline]
    fn deref(&self) -> &[u8] {
        if self.ptr.is_null() {
            panic!("attempted to access a consumed `OsIpcSharedMemory`")
        }
        unsafe {
            slice::from_raw_parts(self.ptr, self.length)
        }
    }
}

impl OsIpcSharedMemory {
    pub fn from_byte(byte: u8, length: usize) -> OsIpcSharedMemory {
        let mut v = Arc::new(vec![byte; length]);
        OsIpcSharedMemory {
            ptr: Arc::get_mut(&mut v).unwrap().as_mut_ptr(),
            length: length,
            data: v
        }
    }

    pub fn from_bytes(bytes: &[u8]) -> OsIpcSharedMemory {
        let mut v = Arc::new(bytes.to_vec());
        OsIpcSharedMemory {
            ptr: Arc::get_mut(&mut v).unwrap().as_mut_ptr(),
            length: v.len(),
            data: v
        }
    }
}

#[derive(Debug, PartialEq)]
pub enum MpscError {
    ChannelClosedError,
    BrokenPipeError,
    UnknownError,
}

impl MpscError {
    #[allow(dead_code)]
    pub fn channel_is_closed(&self) -> bool {
        *self == MpscError::ChannelClosedError
    }
}

impl From<MpscError> for bincode::Error {
    fn from(mpsc_error: MpscError) -> Self {
        Error::from(mpsc_error).into()
    }
}

impl From<MpscError> for Error {
    fn from(mpsc_error: MpscError) -> Error {
        match mpsc_error {
            MpscError::ChannelClosedError => {
                Error::new(ErrorKind::ConnectionReset, "MPSC channel sender closed")
            }
            MpscError::BrokenPipeError => {
                Error::new(ErrorKind::BrokenPipe, "MPSC channel receiver closed")
            }
            MpscError::UnknownError => Error::new(ErrorKind::Other, "Other MPSC channel error"),
        }
    }
}

<commit_msg>inprocess: `try_recv()`: Don't report `ChannelClosedError` for "no data" condition<commit_after>// Copyright 2015 The Servo Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution.
//
// 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 bincode;
use std::sync::mpsc;
use std::sync::{Arc, Mutex};
use std::collections::hash_map::HashMap;
use std::cell::{RefCell};
use std::io::{Error, ErrorKind};
use std::slice;
use std::fmt::{self, Debug, Formatter};
use std::cmp::{PartialEq};
use std::ops::Deref;
use std::mem;
use std::usize;
use uuid::Uuid;

use super::incrementor::Incrementor;

#[derive(Clone)]
struct ServerRecord {
    sender: OsIpcSender,
    conn_sender: mpsc::Sender<bool>,
    conn_receiver: Arc<Mutex<mpsc::Receiver<bool>>>,
}

impl ServerRecord {
    fn new(sender: OsIpcSender) -> ServerRecord {
        let (tx, rx) = mpsc::channel::<bool>();
        ServerRecord {
            sender: sender,
            conn_sender: tx,
            conn_receiver: Arc::new(Mutex::new(rx)),
        }
    }

    fn accept(&self) {
        self.conn_receiver.lock().unwrap().recv().unwrap();
    }

    fn connect(&self) {
        self.conn_sender.send(true).unwrap();
    }
}

lazy_static! {
    static ref ONE_SHOT_SERVERS: Mutex<HashMap<String,ServerRecord>> = Mutex::new(HashMap::new());
}

struct MpscChannelMessage(Vec<u8>, Vec<OsIpcChannel>, Vec<OsIpcSharedMemory>);

pub fn channel() -> Result<(OsIpcSender, OsIpcReceiver),MpscError> {
    let (base_sender, base_receiver) = mpsc::channel::<MpscChannelMessage>();
    Ok((OsIpcSender::new(base_sender), OsIpcReceiver::new(base_receiver)))
}

#[derive(Debug)]
pub struct OsIpcReceiver {
    receiver: RefCell<Option<mpsc::Receiver<MpscChannelMessage>>>,
}

impl PartialEq for OsIpcReceiver {
    fn eq(&self, other: &OsIpcReceiver) -> bool {
        self.receiver.borrow().as_ref().map(|rx| rx as *const _) ==
            other.receiver.borrow().as_ref().map(|rx| rx as *const _)
    }
}

impl OsIpcReceiver {
    fn new(receiver: mpsc::Receiver<MpscChannelMessage>) -> OsIpcReceiver {
        OsIpcReceiver {
            receiver: RefCell::new(Some(receiver)),
        }
    }

    pub fn consume(&self) -> OsIpcReceiver {
        let receiver = self.receiver.borrow_mut().take();
        OsIpcReceiver::new(receiver.unwrap())
    }

    pub fn recv(&self) -> Result<(Vec<u8>, Vec<OsOpaqueIpcChannel>, Vec<OsIpcSharedMemory>),MpscError> {
        let r = self.receiver.borrow();
        match r.as_ref().unwrap().recv() {
            Ok(MpscChannelMessage(d,c,s)) => Ok((d,
                                                 c.into_iter().map(OsOpaqueIpcChannel::new).collect(),
                                                 s)),
            Err(_) => Err(MpscError::ChannelClosedError),
        }
    }

    pub fn try_recv(&self) -> Result<(Vec<u8>, Vec<OsOpaqueIpcChannel>, Vec<OsIpcSharedMemory>),MpscError> {
        let r = self.receiver.borrow();
        match r.as_ref().unwrap().try_recv() {
            Ok(MpscChannelMessage(d,c,s)) => Ok((d,
                                                 c.into_iter().map(OsOpaqueIpcChannel::new).collect(),
                                                 s)),
            Err(mpsc::TryRecvError::Disconnected) => Err(MpscError::ChannelClosedError),
            Err(_) => Err(MpscError::UnknownError),
        }
    }
}

#[derive(Clone, Debug)]
pub struct OsIpcSender {
    sender: RefCell<mpsc::Sender<MpscChannelMessage>>,
}

impl PartialEq for OsIpcSender {
    fn eq(&self, other: &OsIpcSender) -> bool {
        &*self.sender.borrow() as *const _ ==
            &*other.sender.borrow() as *const _
    }
}

impl OsIpcSender {
    fn new(sender: mpsc::Sender<MpscChannelMessage>) -> OsIpcSender {
        OsIpcSender {
            sender: RefCell::new(sender),
        }
    }

    pub fn connect(name: String) -> Result<OsIpcSender,MpscError> {
        let record = ONE_SHOT_SERVERS.lock().unwrap().get(&name).unwrap().clone();
        record.connect();
        Ok(record.sender)
    }

    pub fn get_max_fragment_size() -> usize {
        usize::MAX
    }

    pub fn send(&self,
                data: &[u8],
                ports: Vec<OsIpcChannel>,
                shared_memory_regions: Vec<OsIpcSharedMemory>)
                -> Result<(),MpscError>
    {
        match self.sender.borrow().send(MpscChannelMessage(data.to_vec(), ports, shared_memory_regions)) {
            Err(_) => Err(MpscError::BrokenPipeError),
            Ok(_) => Ok(()),
        }
    }
}

pub struct OsIpcReceiverSet {
    incrementor: Incrementor,
    receiver_ids: Vec<u64>,
    receivers: Vec<OsIpcReceiver>,
}

impl OsIpcReceiverSet {
    pub fn new() -> Result<OsIpcReceiverSet,MpscError> {
        Ok(OsIpcReceiverSet {
            incrementor: Incrementor::new(),
            receiver_ids: vec![],
            receivers: vec![],
        })
    }

    pub fn add(&mut self, receiver: OsIpcReceiver) -> Result<u64,MpscError> {
        let last_index = self.incrementor.increment();
        self.receiver_ids.push(last_index);
        self.receivers.push(receiver.consume());
        Ok(last_index)
    }

    pub fn select(&mut self) -> Result<Vec<OsIpcSelectionResult>,MpscError> {
        let mut receivers: Vec<Option<mpsc::Receiver<MpscChannelMessage>>> = Vec::with_capacity(self.receivers.len());
        let mut r_id: Option<u64> = None;
        let mut r_index: usize = 0;

        {
            let select = mpsc::Select::new();
            // we *must* allocate exact capacity for this, because the Handles *can't move*
            let mut handles: Vec<mpsc::Handle<MpscChannelMessage>> = Vec::with_capacity(self.receivers.len());

            for r in &self.receivers {
                let inner_r = mem::replace(&mut *r.receiver.borrow_mut(), None);
                receivers.push(inner_r);
            }

            for r in &receivers {
                unsafe {
                    handles.push(select.handle(r.as_ref().unwrap()));
                    handles.last_mut().unwrap().add();
                }
            }

            let id = select.wait();

            for (index,h) in handles.iter().enumerate() {
                if h.id() == id {
                    r_index = index;
                    r_id = Some(self.receiver_ids[index]);
                    break;
                }
            }
        }

        // put the receivers back
        for (index,r) in self.receivers.iter().enumerate() {
            mem::replace(&mut *r.receiver.borrow_mut(), mem::replace(&mut receivers[index], None));
        }

        match r_id {
            None => Err(MpscError::UnknownError),
            Some(r_id) => {
                let receivers = &mut self.receivers;
                match receivers[r_index].recv() {
                    Ok((data, channels, shmems)) =>
                        Ok(vec![OsIpcSelectionResult::DataReceived(r_id, data, channels, shmems)]),
                    Err(MpscError::ChannelClosedError) => {
                        receivers.remove(r_index);
                        self.receiver_ids.remove(r_index);
                        Ok(vec![OsIpcSelectionResult::ChannelClosed(r_id)])
                    },
                    Err(err) => Err(err),
                }
            }
        }
    }
}

pub enum OsIpcSelectionResult {
    DataReceived(u64, Vec<u8>, Vec<OsOpaqueIpcChannel>, Vec<OsIpcSharedMemory>),
    ChannelClosed(u64),
}

impl OsIpcSelectionResult {
    pub fn unwrap(self) -> (u64, Vec<u8>, Vec<OsOpaqueIpcChannel>, Vec<OsIpcSharedMemory>) {
        match self {
            OsIpcSelectionResult::DataReceived(id, data, channels, shared_memory_regions) => {
                (id, data, channels, shared_memory_regions)
            }
            OsIpcSelectionResult::ChannelClosed(id) => {
                panic!("OsIpcSelectionResult::unwrap(): receiver ID {} was closed!", id)
            }
        }
    }
}

pub struct OsIpcOneShotServer {
    receiver: OsIpcReceiver,
    name: String,
}

impl OsIpcOneShotServer {
    pub fn new() -> Result<(OsIpcOneShotServer, String),MpscError> {
        let (sender, receiver) = try!(channel());

        let name = Uuid::new_v4().to_string();
        let record = ServerRecord::new(sender);
        ONE_SHOT_SERVERS.lock().unwrap().insert(name.clone(), record);
        Ok((OsIpcOneShotServer {
            receiver: receiver,
            name: name.clone(),
        },name.clone()))
    }

    pub fn accept(self) -> Result<(OsIpcReceiver,
                                    Vec<u8>,
                                    Vec<OsOpaqueIpcChannel>,
                                    Vec<OsIpcSharedMemory>),MpscError>
    {
        let record = ONE_SHOT_SERVERS.lock().unwrap().get(&self.name).unwrap().clone();
        record.accept();
        ONE_SHOT_SERVERS.lock().unwrap().remove(&self.name).unwrap();
        let (data, channels, shmems) = try!(self.receiver.recv());
        Ok((self.receiver, data, channels, shmems))
    }
}

#[derive(PartialEq, Debug)]
pub enum OsIpcChannel {
    Sender(OsIpcSender),
    Receiver(OsIpcReceiver),
}

#[derive(PartialEq, Debug)]
pub struct OsOpaqueIpcChannel {
    channel: RefCell<Option<OsIpcChannel>>,
}

impl OsOpaqueIpcChannel {
    fn new(channel: OsIpcChannel) -> OsOpaqueIpcChannel {
        OsOpaqueIpcChannel {
            channel: RefCell::new(Some(channel))
        }
    }

    pub fn to_receiver(&self) -> OsIpcReceiver {
        match self.channel.borrow_mut().take().unwrap() {
            OsIpcChannel::Sender(_) => panic!("Opaque channel is not a receiver!"),
            OsIpcChannel::Receiver(r) => r
        }
    }

    pub fn to_sender(&mut self) -> OsIpcSender {
        match self.channel.borrow_mut().take().unwrap() {
            OsIpcChannel::Sender(s) => s,
            OsIpcChannel::Receiver(_) => panic!("Opaque channel is not a sender!"),
        }
    }
}

pub struct OsIpcSharedMemory {
    ptr: *mut u8,
    length: usize,
    data: Arc<Vec<u8>>,
}

unsafe impl Send for OsIpcSharedMemory {}
unsafe impl Sync for OsIpcSharedMemory {}

impl Clone for OsIpcSharedMemory {
    fn clone(&self) -> OsIpcSharedMemory {
        OsIpcSharedMemory {
            ptr: self.ptr,
            length: self.length,
            data: self.data.clone(),
        }
    }
}

impl PartialEq for OsIpcSharedMemory {
    fn eq(&self, other: &OsIpcSharedMemory) -> bool {
        **self == **other
    }
}

impl Debug for OsIpcSharedMemory {
    fn fmt(&self, formatter: &mut Formatter) -> Result<(), fmt::Error> {
        (**self).fmt(formatter)
    }
}

impl Deref for OsIpcSharedMemory {
    type Target = [u8];

    #[inline]
    fn deref(&self) -> &[u8] {
        if self.ptr.is_null() {
            panic!("attempted to access a consumed `OsIpcSharedMemory`")
        }
        unsafe {
            slice::from_raw_parts(self.ptr, self.length)
        }
    }
}

impl OsIpcSharedMemory {
    pub fn from_byte(byte: u8, length: usize) -> OsIpcSharedMemory {
        let mut v = Arc::new(vec![byte; length]);
        OsIpcSharedMemory {
            ptr: Arc::get_mut(&mut v).unwrap().as_mut_ptr(),
            length: length,
            data: v
        }
    }

    pub fn from_bytes(bytes: &[u8]) -> OsIpcSharedMemory {
        let mut v = Arc::new(bytes.to_vec());
        OsIpcSharedMemory {
            ptr: Arc::get_mut(&mut v).unwrap().as_mut_ptr(),
            length: v.len(),
            data: v
        }
    }
}

#[derive(Debug, PartialEq)]
pub enum MpscError {
    ChannelClosedError,
    BrokenPipeError,
    UnknownError,
}

impl MpscError {
    #[allow(dead_code)]
    pub fn channel_is_closed(&self) -> bool {
        *self == MpscError::ChannelClosedError
    }
}

impl From<MpscError> for bincode::Error {
    fn from(mpsc_error: MpscError) -> Self {
        Error::from(mpsc_error).into()
    }
}

impl From<MpscError> for Error {
    fn from(mpsc_error: MpscError) -> Error {
        match mpsc_error {
            MpscError::ChannelClosedError => {
                Error::new(ErrorKind::ConnectionReset, "MPSC channel sender closed")
            }
            MpscError::BrokenPipeError => {
                Error::new(ErrorKind::BrokenPipe, "MPSC channel receiver closed")
            }
            MpscError::UnknownError => Error::new(ErrorKind::Other, "Other MPSC channel error"),
        }
    }
}

<|endoftext|>