<commit_before>use libc;

use std::ptr::null_mut;

/// 16k is enough for anybody.
const STACK_SIZE: u64 = 16384;

/// Get the offset in bytes of some particular struct member.
///
/// Idea is simply to see what the address of that member would be if the
/// struct was created at address 0x0 (which gives its offset in bytes).
macro_rules! offset_of {
    ( $($kind:ty, $member:ident),*) => {{
        $(
            unsafe {
                let ptr: *mut $kind = std::mem::transmute(0x0usize);
                let member_addr: usize = std::mem::transmute(&(*ptr).$member);

                member_addr
            }
         )*
    }};
}

/// Return a pointer to the TLS value at the given offset.
macro_rules! get_thread_mem {
    ( $($offset:expr, $kind:ty),* ) => {{
        $(
            let dest_ptr: *mut $kind;

            // We can't use constant segment offsets here due to some odd
            // asm! behavior, so just use indirect (it's slower, oh well).
            asm!("mov %fs:($1), $0"
                 : "=r"(dest_ptr)
                 : "r" ($offset)
                 :: "volatile");

            dest_ptr
          )*
        }
    };
}

macro_rules! set_thread_mem {
    ( $($offset:expr, $expression:expr),* ) => {{
        $(
            asm!("movl $1, %fs:($0)" :
                 : "r"($offset), "i"($expression)
                 :: "volatile");
          )*
        }
    };
}

#[repr(C, packed)]
#[derive(Debug)]
pub struct ControlBlockHead {
    tcb: *mut libc::c_void,
    dtv: *mut libc::c_void,
    thread_self: *mut Thread,

    /// We don't actually care about the rest.
    padding: [*mut libc::c_void; 21],
}

#[repr(C, packed)]
#[derive(Debug)]
pub struct Thread {
    header: ControlBlockHead,

    /// This thread's id
    pub tid: libc::pid_t,

    /// This thread's parent pid
    pub pid: libc::pid_t,

    pub magic: usize
}

unsafe fn get_thread_tcb() {
}

pub unsafe fn get_current_thread() -> () {
    let thd_ptr: *mut Thread = get_thread_mem!(0, Thread);
    if thd_ptr.is_null() { panic!("TLS thread return NULL"); }

    let thd = &*thd_ptr;

    println!("magic = {}", thd.magic);
}

pub unsafe fn allocate_stack() -> *mut libc::c_void {
    let prot = libc::PROT_EXEC | libc::PROT_READ | libc::PROT_WRITE;
    let flags = libc::MAP_PRIVATE | libc::MAP_ANONYMOUS | libc::MAP_STACK;

    let stack = libc::mmap(null_mut(), STACK_SIZE, prot, flags, -1, 0);

    if stack == libc::MAP_FAILED || stack.is_null() {
        panic!("couldn't mmap space for stack");
    }

    stack
}
<commit_msg>Macros don't need to be variadic<commit_after>use libc;

use std::ptr::null_mut;

/// 16k is enough for anybody.
const STACK_SIZE: u64 = 16384;

/// Get the offset in bytes of some particular struct member.
///
/// Idea is simply to see what the address of that member would be if the
/// struct was created at address 0x0 (which gives its offset in bytes).
macro_rules! offset_of {
    ($kind:ty, $member:ident) => {
        unsafe {
            let ptr: *mut $kind = std::mem::transmute(0x0usize);
            let member_addr: usize = std::mem::transmute(&(*ptr).$member);

            member_addr
        }
    };
}

/// Return a pointer to the TLS value at the given offset.
macro_rules! get_thread_mem {
    ($offset:expr, $kind:ty) => {{
        let dest_ptr: *mut $kind;

        // We can't use constant segment offsets here due to some odd
        // asm! behavior, so just use indirect (it's slower, oh well).
        asm!("mov %fs:($1), $0"
             : "=r"(dest_ptr)
             : "r" ($offset)
             :: "volatile");

        dest_ptr
    }};
}

macro_rules! set_thread_mem {
    ($offset:expr, $expression:expr) => {
        asm!("movl $1, %fs:($0)" :
             : "r"($offset), "i"($expression)
             :: "volatile");
    };
}

#[repr(C, packed)]
#[derive(Debug)]
pub struct ControlBlockHead {
    tcb: *mut libc::c_void,
    dtv: *mut libc::c_void,
    thread_self: *mut Thread,

    /// We don't actually care about the rest.
    padding: [*mut libc::c_void; 21],
}

#[repr(C, packed)]
#[derive(Debug)]
pub struct Thread {
    header: ControlBlockHead,

    /// This thread's id
    pub tid: libc::pid_t,

    /// This thread's parent pid
    pub pid: libc::pid_t,

    pub magic: usize
}

unsafe fn get_thread_tcb() {
}

pub unsafe fn get_current_thread() -> () {
    let thd_ptr: *mut Thread = get_thread_mem!(0, Thread);
    if thd_ptr.is_null() { panic!("TLS thread return NULL"); }

    let thd = &*thd_ptr;

    println!("magic = {}", thd.magic);
}

pub unsafe fn allocate_stack() -> *mut libc::c_void {
    let prot = libc::PROT_EXEC | libc::PROT_READ | libc::PROT_WRITE;
    let flags = libc::MAP_PRIVATE | libc::MAP_ANONYMOUS | libc::MAP_STACK;

    let stack = libc::mmap(null_mut(), STACK_SIZE, prot, flags, -1, 0);

    if stack == libc::MAP_FAILED || stack.is_null() {
        panic!("couldn't mmap space for stack");
    }

    stack
}
<|endoftext|>


<commit_before>use std::io;
use std::path::{PathBuf, Path};
use std::fs::File;
use std::cmp::{Ordering, PartialEq, Ord};
use std::collections::HashMap;
use object::File as OFile;
use memmap::{Mmap, Protection};
use gimli::*;
use rustc_demangle::demangle;
use cargo::core::Workspace;

use config::Config;
use source_analysis::*;

/// Describes a function as `low_pc`, `high_pc` and bool representing `is_test`.
type FuncDesc = (u64, u64, FunctionType);

#[derive(Clone, Copy, PartialEq)]
enum FunctionType {
    Generated,
    Test,
    Standard
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd)]
pub enum LineType {
    /// Generated test main. Shouldn't be traced.
    TestMain,
    /// Entry of function known to be a test
    TestEntry(u64),
    /// Entry of function. May or may not be test
    FunctionEntry(u64),
    /// Standard statement
    Statement,
    /// Condition
    Condition,
    /// Unknown type
    Unknown,
    /// Unused meta-code
    UnusedGeneric,
}

#[derive(Debug, Clone, Eq, PartialOrd)]
pub struct TracerData {
    pub path: PathBuf,
    pub line: u64,
    pub address: Option<u64>,
    pub trace_type: LineType,
    pub hits: u64,
}

impl PartialEq for TracerData {
    fn eq(&self, other: &TracerData) -> bool {
        (self.path == other.path) && (self.line == other.line)
    }
}

impl Ord for TracerData {

    fn cmp(&self, other: &TracerData) -> Ordering {
        if self == other {
            Ordering::Equal
        } else if self.path == other.path {
            if self.line > other.line {
                Ordering::Greater
            } else {
                Ordering::Less
            }
        } else if self.path > other.path {
            Ordering::Greater
        } else {
            Ordering::Less
        }
    }
}

fn generate_func_desc<R, Offset>(die: &DebuggingInformationEntry<R, Offset>,
                                 debug_str: &DebugStr<R>) -> Result<FuncDesc>
    where R: Reader<Offset = Offset>,
          Offset: ReaderOffset
{
    let mut func_type = FunctionType::Standard;
    let low = die.attr_value(DW_AT_low_pc)?;
    let high = die.attr_value(DW_AT_high_pc)?;
    let linkage = die.attr_value(DW_AT_linkage_name)?;

    // Low is a program counter address so stored in an Addr
    let low = match low {
        Some(AttributeValue::Addr(x)) => x,
        _ => 0u64,
    };
    // High is an offset from the base pc, therefore is u64 data.
    let high = match high {
        Some(AttributeValue::Udata(x)) => x,
        _ => 0u64,
    };
    if let Some(AttributeValue::DebugStrRef(offset)) = linkage {
        let name = debug_str.get_str(offset)
            .and_then(|r| r.to_string().map(|s| s.to_string()))
            .unwrap_or("".into());
        let name = demangle(name.as_ref()).to_string();
        // Simplest test is whether it's in tests namespace.
        // Rust guidelines recommend all tests are in a tests module.
        func_type = if name.contains("tests::") {
            FunctionType::Test
        } else if name.contains("__test::main") {
            FunctionType::Generated
        } else {
            FunctionType::Standard
        };
    }
    Ok((low, high, func_type))
}

/// Finds all function entry points and returns a vector
/// This will identify definite tests, but may be prone to false negatives.
/// TODO Potential to trace all function calls from `__test::main` and find addresses of interest
fn get_entry_points<R, Offset>(debug_info: &CompilationUnitHeader<R, Offset>,
                               debug_abbrev: &Abbreviations,
                               debug_str: &DebugStr<R>) -> Vec<FuncDesc>
    where R: Reader<Offset = Offset>,
          Offset: ReaderOffset
{
    let mut result:Vec<FuncDesc> = Vec::new();
    let mut cursor = debug_info.entries(debug_abbrev);
    // skip compilation unit root.
    let _ = cursor.next_entry();
    while let Ok(Some((_, node))) = cursor.next_dfs() {
        // Function DIE
        if node.tag() == DW_TAG_subprogram {

            if let Ok(fd) = generate_func_desc(node, debug_str) {
                result.push(fd);
            }
        }
    }
    result
}

fn get_addresses_from_program<R, Offset>(prog: IncompleteLineNumberProgram<R>,
                                         entries: &[(u64, LineType)],
                                         project: &Path) -> Result<Vec<TracerData>>
    where R: Reader<Offset = Offset>,
          Offset: ReaderOffset
{
    let mut result: Vec<TracerData> = Vec::new();
    let ( cprog, seq) = prog.sequences()?;
    for s in seq {
        let mut temp_store : Vec<TracerData> = Vec::new();
        let mut sm = cprog.resume_from(&s);
         while let Ok(Some((header, &ln_row))) = sm.next_row() {
            if let Some(file) = ln_row.file(header) {
                let mut path = PathBuf::new();

                if let Some(dir) = file.directory(header) {
                    if let Ok(temp) = dir.to_string() {
                        path.push(temp.as_ref());
                    }
                }
                // Fix relative paths and determine if in target directory
                // Source in target directory shouldn't be covered as it's either
                // autogenerated or resulting from the projects Cargo.lock
                let is_target = if path.is_relative() {
                    let res = path.starts_with("target");
                    if !res {
                        if let Ok(p) = path.canonicalize() {
                            path = p;
                        }
                    }
                    res
                } else {
                    path.starts_with(project.join("target"))
                };
                // Source is part of project so we cover it.
                if !is_target && path.starts_with(project) {
                    let force_test = path.starts_with(project.join("tests"));
                    if let Some(file) = ln_row.file(header) {
                        // If we can't map to line, we can't trace it.
                        let line = match ln_row.line() {
                            Some(l) => l,
                            None => continue,
                        };

                        let file = file.path_name();

                        if let Ok(file) = file.to_string() {
                            path.push(file.as_ref());
                            if !path.is_file() {
                                // Not really a source file!
                                continue;
                            }
                            let address = ln_row.address();

                            let desc = entries.iter()
                                              .filter(|&&(addr, _)| addr == address )
                                              .map(|&(_, t)| t)
                                              .nth(0)
                                              .unwrap_or(LineType::Unknown);
                            // TODO HACK: If in tests/ directory force it to a TestEntry
                            let desc = match desc {
                                LineType::FunctionEntry(e) if force_test => LineType::TestEntry(e),
                                x => x
                            };
                            temp_store.push( TracerData {
                                path: path,
                                line: line,
                                address: Some(address),
                                trace_type: desc,
                                hits: 0u64
                            });
                        }
                    }
                }
            }
        }
        if !temp_store.is_empty() {
            temp_store.sort();
            temp_store.dedup();
            result.append(&mut temp_store);
        }
    }
    Ok(result)
}

fn get_line_addresses<Endian: Endianity>(endian: Endian,
                                         project: &Path,
                                         obj: &OFile,
                                         analysis: &HashMap<PathBuf, LineAnalysis>,
                                         ignore_tests: bool) -> Result<Vec<TracerData>>  {
    let mut result: Vec<TracerData> = Vec::new();
    let debug_info = obj.get_section(".debug_info").unwrap_or(&[]);
    let debug_info = DebugInfo::new(debug_info, endian);
    let debug_abbrev = obj.get_section(".debug_abbrev").unwrap_or(&[]);
    let debug_abbrev = DebugAbbrev::new(debug_abbrev, endian);
    let debug_strings = obj.get_section(".debug_str").unwrap_or(&[]);
    let debug_strings = DebugStr::new(debug_strings, endian);

    let mut iter = debug_info.units();
    while let Ok(Some(cu)) = iter.next() {
        let addr_size = cu.address_size();
        let abbr = match cu.abbreviations(&debug_abbrev) {
            Ok(a) => a,
            _ => continue,
        };
        let entries = get_entry_points(&cu, &abbr, &debug_strings)
            .iter()
            .map(|&(a, b, c)| {
                match c {
                    FunctionType::Test => (a, LineType::TestEntry(b)),
                    FunctionType::Standard => (a, LineType::FunctionEntry(b)),
                    FunctionType::Generated => (a, LineType::TestMain),
                }
            }).collect::<Vec<_>>();
        if let Ok(Some((_, root))) = cu.entries(&abbr).next_dfs() {
            let offset = match root.attr_value(DW_AT_stmt_list) {
                Ok(Some(AttributeValue::DebugLineRef(o))) => o,
                _ => continue,
            };
            let debug_line = obj.get_section(".debug_line").unwrap_or(&[]);
            let debug_line = DebugLine::new(debug_line, endian);

            let prog = debug_line.program(offset, addr_size, None, None)?;
            if let Ok(mut addresses) = get_addresses_from_program(prog, &entries, project) {
                result.append(&mut addresses);
            }
        }
    }
    // Due to rust being a higher level language multiple instructions may map
    // to the same line. This prunes these to just the first instruction address
    let mut result = result.iter()
                           .filter(|x| !(ignore_tests && x.path.starts_with(project.join("tests"))))
                           .filter(|x| !analysis.should_ignore(x.path.as_ref(), &(x.line as usize)))
                           .filter(|x| x.trace_type != LineType::TestMain)
                           .cloned()
                           .collect::<Vec<TracerData>>();

    let addresses = result.iter()
                          .map(|x| x.address.unwrap())
                          .collect::<Vec<_>>();
    // TODO Probably a more idiomatic way to do this.
    {
        let test_entries = result.iter_mut()
                                 .filter(|x| match x.trace_type {
                                     LineType::TestEntry(_) => true,
                                     _ => false,
                                 });

        for test_entry in test_entries {
            let endpoint = match test_entry.trace_type {
                LineType::TestEntry(x) => x,
                _ => continue,
            };
            let addr = test_entry.address.unwrap();
            let max_address = addresses.iter()
                                       .fold(0, |acc, x| {
                                           if x > &(addr + acc) && (x-addr) <= endpoint {
                                               *x - addr
                                           } else {
                                               acc
                                           }
                                       });
            test_entry.trace_type = LineType::TestEntry(max_address);
        }
    }
    for (file, ref line_analysis) in analysis.iter() {
        for line in &line_analysis.cover {
            let line64 = *line as u64;
            let contain = result.iter().any(|ref x| &x.path == file && line64 == x.line);
            if !contain && !line_analysis.should_ignore(line) {
                result.push(TracerData {
                    line: line64,
                    path: file.to_path_buf(),
                    address: None,
                    hits: 0,
                    trace_type: LineType::UnusedGeneric,
                });
            }
        }
    }
    Ok(result)
}

/// Generates a list of lines we want to trace the coverage of. Used to instrument the
/// traces into the test executable
pub fn generate_tracer_data(project: &Workspace, test: &Path, config: &Config) -> io::Result<Vec<TracerData>> {
    let manifest = project.root();
    let file = File::open(test)?;
    let file = Mmap::open(&file, Protection::Read)?;
    if let Ok(obj) = OFile::parse(unsafe {file.as_slice() }) {
        let analysis = get_line_analysis(project, config);
        let data = if obj.is_little_endian() {
            get_line_addresses(LittleEndian,
                               manifest,
                               &obj,
                               &analysis,
                               config.ignore_tests)
        } else {
            get_line_addresses(BigEndian,
                               manifest,
                               &obj,
                               &analysis,
                               config.ignore_tests)
        };
        data.map_err(|_| io::Error::new(io::ErrorKind::InvalidData, "Error while parsing"))
    } else {
        Err(io::Error::new(io::ErrorKind::InvalidData, "Unable to parse binary."))
    }
}

<commit_msg>use RunTimeEndian to simplify code<commit_after>use std::io;
use std::path::{PathBuf, Path};
use std::fs::File;
use std::cmp::{Ordering, PartialEq, Ord};
use std::collections::HashMap;
use object::File as OFile;
use memmap::{Mmap, Protection};
use gimli::*;
use rustc_demangle::demangle;
use cargo::core::Workspace;

use config::Config;
use source_analysis::*;

/// Describes a function as `low_pc`, `high_pc` and bool representing `is_test`.
type FuncDesc = (u64, u64, FunctionType);

#[derive(Clone, Copy, PartialEq)]
enum FunctionType {
    Generated,
    Test,
    Standard
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd)]
pub enum LineType {
    /// Generated test main. Shouldn't be traced.
    TestMain,
    /// Entry of function known to be a test
    TestEntry(u64),
    /// Entry of function. May or may not be test
    FunctionEntry(u64),
    /// Standard statement
    Statement,
    /// Condition
    Condition,
    /// Unknown type
    Unknown,
    /// Unused meta-code
    UnusedGeneric,
}

#[derive(Debug, Clone, Eq, PartialOrd)]
pub struct TracerData {
    pub path: PathBuf,
    pub line: u64,
    pub address: Option<u64>,
    pub trace_type: LineType,
    pub hits: u64,
}

impl PartialEq for TracerData {
    fn eq(&self, other: &TracerData) -> bool {
        (self.path == other.path) && (self.line == other.line)
    }
}

impl Ord for TracerData {

    fn cmp(&self, other: &TracerData) -> Ordering {
        if self == other {
            Ordering::Equal
        } else if self.path == other.path {
            if self.line > other.line {
                Ordering::Greater
            } else {
                Ordering::Less
            }
        } else if self.path > other.path {
            Ordering::Greater
        } else {
            Ordering::Less
        }
    }
}

fn generate_func_desc<R, Offset>(die: &DebuggingInformationEntry<R, Offset>,
                                 debug_str: &DebugStr<R>) -> Result<FuncDesc>
    where R: Reader<Offset = Offset>,
          Offset: ReaderOffset
{
    let mut func_type = FunctionType::Standard;
    let low = die.attr_value(DW_AT_low_pc)?;
    let high = die.attr_value(DW_AT_high_pc)?;
    let linkage = die.attr_value(DW_AT_linkage_name)?;

    // Low is a program counter address so stored in an Addr
    let low = match low {
        Some(AttributeValue::Addr(x)) => x,
        _ => 0u64,
    };
    // High is an offset from the base pc, therefore is u64 data.
    let high = match high {
        Some(AttributeValue::Udata(x)) => x,
        _ => 0u64,
    };
    if let Some(AttributeValue::DebugStrRef(offset)) = linkage {
        let name = debug_str.get_str(offset)
            .and_then(|r| r.to_string().map(|s| s.to_string()))
            .unwrap_or("".into());
        let name = demangle(name.as_ref()).to_string();
        // Simplest test is whether it's in tests namespace.
        // Rust guidelines recommend all tests are in a tests module.
        func_type = if name.contains("tests::") {
            FunctionType::Test
        } else if name.contains("__test::main") {
            FunctionType::Generated
        } else {
            FunctionType::Standard
        };
    }
    Ok((low, high, func_type))
}

/// Finds all function entry points and returns a vector
/// This will identify definite tests, but may be prone to false negatives.
/// TODO Potential to trace all function calls from `__test::main` and find addresses of interest
fn get_entry_points<R, Offset>(debug_info: &CompilationUnitHeader<R, Offset>,
                               debug_abbrev: &Abbreviations,
                               debug_str: &DebugStr<R>) -> Vec<FuncDesc>
    where R: Reader<Offset = Offset>,
          Offset: ReaderOffset
{
    let mut result:Vec<FuncDesc> = Vec::new();
    let mut cursor = debug_info.entries(debug_abbrev);
    // skip compilation unit root.
    let _ = cursor.next_entry();
    while let Ok(Some((_, node))) = cursor.next_dfs() {
        // Function DIE
        if node.tag() == DW_TAG_subprogram {

            if let Ok(fd) = generate_func_desc(node, debug_str) {
                result.push(fd);
            }
        }
    }
    result
}

fn get_addresses_from_program<R, Offset>(prog: IncompleteLineNumberProgram<R>,
                                         entries: &[(u64, LineType)],
                                         project: &Path) -> Result<Vec<TracerData>>
    where R: Reader<Offset = Offset>,
          Offset: ReaderOffset
{
    let mut result: Vec<TracerData> = Vec::new();
    let ( cprog, seq) = prog.sequences()?;
    for s in seq {
        let mut temp_store : Vec<TracerData> = Vec::new();
        let mut sm = cprog.resume_from(&s);
         while let Ok(Some((header, &ln_row))) = sm.next_row() {
            if let Some(file) = ln_row.file(header) {
                let mut path = PathBuf::new();

                if let Some(dir) = file.directory(header) {
                    if let Ok(temp) = dir.to_string() {
                        path.push(temp.as_ref());
                    }
                }
                // Fix relative paths and determine if in target directory
                // Source in target directory shouldn't be covered as it's either
                // autogenerated or resulting from the projects Cargo.lock
                let is_target = if path.is_relative() {
                    let res = path.starts_with("target");
                    if !res {
                        if let Ok(p) = path.canonicalize() {
                            path = p;
                        }
                    }
                    res
                } else {
                    path.starts_with(project.join("target"))
                };
                // Source is part of project so we cover it.
                if !is_target && path.starts_with(project) {
                    let force_test = path.starts_with(project.join("tests"));
                    if let Some(file) = ln_row.file(header) {
                        // If we can't map to line, we can't trace it.
                        let line = match ln_row.line() {
                            Some(l) => l,
                            None => continue,
                        };

                        let file = file.path_name();

                        if let Ok(file) = file.to_string() {
                            path.push(file.as_ref());
                            if !path.is_file() {
                                // Not really a source file!
                                continue;
                            }
                            let address = ln_row.address();

                            let desc = entries.iter()
                                              .filter(|&&(addr, _)| addr == address )
                                              .map(|&(_, t)| t)
                                              .nth(0)
                                              .unwrap_or(LineType::Unknown);
                            // TODO HACK: If in tests/ directory force it to a TestEntry
                            let desc = match desc {
                                LineType::FunctionEntry(e) if force_test => LineType::TestEntry(e),
                                x => x
                            };
                            temp_store.push( TracerData {
                                path: path,
                                line: line,
                                address: Some(address),
                                trace_type: desc,
                                hits: 0u64
                            });
                        }
                    }
                }
            }
        }
        if !temp_store.is_empty() {
            temp_store.sort();
            temp_store.dedup();
            result.append(&mut temp_store);
        }
    }
    Ok(result)
}

fn get_line_addresses(endian: RunTimeEndian,
                      project: &Path,
                      obj: &OFile,
                      analysis: &HashMap<PathBuf, LineAnalysis>,
                      ignore_tests: bool) -> Result<Vec<TracerData>>  {
    let mut result: Vec<TracerData> = Vec::new();
    let debug_info = obj.get_section(".debug_info").unwrap_or(&[]);
    let debug_info = DebugInfo::new(debug_info, endian);
    let debug_abbrev = obj.get_section(".debug_abbrev").unwrap_or(&[]);
    let debug_abbrev = DebugAbbrev::new(debug_abbrev, endian);
    let debug_strings = obj.get_section(".debug_str").unwrap_or(&[]);
    let debug_strings = DebugStr::new(debug_strings, endian);

    let mut iter = debug_info.units();
    while let Ok(Some(cu)) = iter.next() {
        let addr_size = cu.address_size();
        let abbr = match cu.abbreviations(&debug_abbrev) {
            Ok(a) => a,
            _ => continue,
        };
        let entries = get_entry_points(&cu, &abbr, &debug_strings)
            .iter()
            .map(|&(a, b, c)| {
                match c {
                    FunctionType::Test => (a, LineType::TestEntry(b)),
                    FunctionType::Standard => (a, LineType::FunctionEntry(b)),
                    FunctionType::Generated => (a, LineType::TestMain),
                }
            }).collect::<Vec<_>>();
        if let Ok(Some((_, root))) = cu.entries(&abbr).next_dfs() {
            let offset = match root.attr_value(DW_AT_stmt_list) {
                Ok(Some(AttributeValue::DebugLineRef(o))) => o,
                _ => continue,
            };
            let debug_line = obj.get_section(".debug_line").unwrap_or(&[]);
            let debug_line = DebugLine::new(debug_line, endian);

            let prog = debug_line.program(offset, addr_size, None, None)?;
            if let Ok(mut addresses) = get_addresses_from_program(prog, &entries, project) {
                result.append(&mut addresses);
            }
        }
    }
    // Due to rust being a higher level language multiple instructions may map
    // to the same line. This prunes these to just the first instruction address
    let mut result = result.iter()
                           .filter(|x| !(ignore_tests && x.path.starts_with(project.join("tests"))))
                           .filter(|x| !analysis.should_ignore(x.path.as_ref(), &(x.line as usize)))
                           .filter(|x| x.trace_type != LineType::TestMain)
                           .cloned()
                           .collect::<Vec<TracerData>>();

    let addresses = result.iter()
                          .map(|x| x.address.unwrap())
                          .collect::<Vec<_>>();
    // TODO Probably a more idiomatic way to do this.
    {
        let test_entries = result.iter_mut()
                                 .filter(|x| match x.trace_type {
                                     LineType::TestEntry(_) => true,
                                     _ => false,
                                 });

        for test_entry in test_entries {
            let endpoint = match test_entry.trace_type {
                LineType::TestEntry(x) => x,
                _ => continue,
            };
            let addr = test_entry.address.unwrap();
            let max_address = addresses.iter()
                                       .fold(0, |acc, x| {
                                           if x > &(addr + acc) && (x-addr) <= endpoint {
                                               *x - addr
                                           } else {
                                               acc
                                           }
                                       });
            test_entry.trace_type = LineType::TestEntry(max_address);
        }
    }
    for (file, ref line_analysis) in analysis.iter() {
        for line in &line_analysis.cover {
            let line64 = *line as u64;
            let contain = result.iter().any(|ref x| &x.path == file && line64 == x.line);
            if !contain && !line_analysis.should_ignore(line) {
                result.push(TracerData {
                    line: line64,
                    path: file.to_path_buf(),
                    address: None,
                    hits: 0,
                    trace_type: LineType::UnusedGeneric,
                });
            }
        }
    }
    Ok(result)
}

/// Generates a list of lines we want to trace the coverage of. Used to instrument the
/// traces into the test executable
pub fn generate_tracer_data(project: &Workspace, test: &Path, config: &Config) -> io::Result<Vec<TracerData>> {
    let manifest = project.root();
    let file = File::open(test)?;
    let file = Mmap::open(&file, Protection::Read)?;
    if let Ok(obj) = OFile::parse(unsafe {file.as_slice() }) {
        let analysis = get_line_analysis(project, config);
        let endian = if obj.is_little_endian() {
            RunTimeEndian::Little
        } else {
            RunTimeEndian::Big
        };
        get_line_addresses(endian,
                           manifest,
                           &obj,
                           &analysis,
                           config.ignore_tests)
            .map_err(|_| io::Error::new(io::ErrorKind::InvalidData, "Error while parsing"))
    } else {
        Err(io::Error::new(io::ErrorKind::InvalidData, "Unable to parse binary."))
    }
}

<|endoftext|>


<commit_before>extern crate sdl2;

use sdl2::video::{Window, WindowPos, OPENGL};
use sdl2::render::{RenderDriverIndex, ACCELERATED, Renderer};
use sdl2::pixels::Color;
use sdl2::event::poll_event;
use sdl2::event::Event::{Quit, KeyDown};
use sdl2::keycode::KeyCode;

fn main()
{
    sdl2::init(sdl2::INIT_VIDEO);
    let window = match Window::new("rust-sdl2 demo: Video", WindowPos::PosCentered,
                                   WindowPos::PosCentered, 800, 600, OPENGL)
    {
        Ok(window) => window,
        Err(err) => panic!("failed to create window: {}", err)
    };
    let renderer = match Renderer::from_window(window, RenderDriverIndex::Auto, ACCELERATED)
    {
        Ok(renderer) => renderer,
        Err(err) => panic!("failed to create renderer: {}", err)
    };
    let _ = renderer.set_draw_color(Color::RGB(255, 0, 0));
    let _ = renderer.clear();
    renderer.present();
    loop
    {
        match poll_event()
        {
            Quit(_) => break,
            KeyDown(_, _, key, _, _, _) =>
            {
                if key == KeyCode::Escape {break;}
            }
            _ => {}
        }
    }
    sdl2::quit();
}
<commit_msg>title<commit_after>extern crate sdl2;

use sdl2::video::{Window, WindowPos, OPENGL};
use sdl2::render::{RenderDriverIndex, ACCELERATED, Renderer};
use sdl2::pixels::Color;
use sdl2::event::poll_event;
use sdl2::event::Event::{Quit, KeyDown};
use sdl2::keycode::KeyCode;

fn main()
{
    sdl2::init(sdl2::INIT_VIDEO);
    let window = match Window::new("Wolf3D", WindowPos::PosCentered,
                                   WindowPos::PosCentered, 800, 600, OPENGL)
    {
        Ok(window) => window,
        Err(err) => panic!("failed to create window: {}", err)
    };
    let renderer = match Renderer::from_window(window, RenderDriverIndex::Auto, ACCELERATED)
    {
        Ok(renderer) => renderer,
        Err(err) => panic!("failed to create renderer: {}", err)
    };
    let _ = renderer.set_draw_color(Color::RGB(255, 0, 0));
    let _ = renderer.clear();
    renderer.present();
    loop
    {
        match poll_event()
        {
            Quit(_) => break,
            KeyDown(_, _, key, _, _, _) =>
            {
                if key == KeyCode::Escape {break;}
            }
            _ => {}
        }
    }
    sdl2::quit();
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate pretty_assertions;

extern crate rexpect;

use rexpect::spawn;

use std::env;
use std::fs::File;
use std::io::Read;
use std::path::Path;
use std::process::{Command, Stdio};

#[test]
fn fmt_repl() {
    let source = "src/repl.glu";

    let mut before = String::new();
    File::open(source)
        .unwrap()
        .read_to_string(&mut before)
        .unwrap();

    let status = Command::new("../target/debug/gluon")
        .args(&["fmt", source])
        .spawn()
        .expect("Could not find gluon executable")
        .wait()
        .unwrap();
    assert!(status.success());

    let mut after = String::new();
    File::open(source)
        .unwrap()
        .read_to_string(&mut after)
        .unwrap();

    assert_eq!(before, after);
}

#[test]
fn issue_365_run_io_from_command_line() {
    if ::std::env::var("GLUON_PATH").is_err() {
        ::std::env::set_var("GLUON_PATH", "..");
    }

    let path = env::args().next().unwrap();
    let gluon_path = Path::new(&path[..])
        .parent()
        .and_then(|p| p.parent())
        .expect("folder")
        .join("gluon");
    let output = Command::new(&*gluon_path)
        .stdin(Stdio::piped())
        .stdout(Stdio::piped())
        .stderr(Stdio::piped())
        .arg("tests/print.glu")
        .output()
        .unwrap_or_else(|err| panic!("{}\nWhen opening `{}`", err, gluon_path.display()));

    let stderr = String::from_utf8_lossy(&output.stderr);
    if stderr != "" {
        panic!("{}", stderr);
    }
    assert_eq!(String::from_utf8_lossy(&output.stdout), "123\n");
}

static COMMAND: &str = "../target/debug/gluon -i";
static TIMEOUT: u64 = 10_000;
static PROMPT: &str = "> ";

macro_rules! test {
    ($e: expr) => { $e.unwrap_or_else(|err| panic!("{}", err)) }
}

#[test]
fn prompt() {
    let mut repl = test!(spawn(COMMAND, Some(TIMEOUT)));
    test!(repl.exp_string(PROMPT));
}

#[test]
fn exit() {
    let mut repl = test!(spawn(COMMAND, Some(TIMEOUT)));
    test!(repl.exp_string(PROMPT));

    test!(repl.send_line(":q"));
    test!(repl.exp_eof());
}

#[test]
#[ignore] // TODO fix intermittent test failure
fn hello_world() {
    let mut repl = test!(spawn(COMMAND, Some(TIMEOUT)));
    test!(repl.exp_string(PROMPT));

    test!(repl.send_line("let io = import! std.io"));

    test!(repl.send_line("io.println \"Hello world\""));
    test!(repl.exp_string("Hello world"));
}

#[test]
fn expression_types() {
    let mut repl = test!(spawn(COMMAND, Some(TIMEOUT)));
    test!(repl.exp_string(PROMPT));

    test!(repl.send_line(":t 5"));
    test!(repl.exp_string("Int"));

    test!(repl.send_line(":t 5 + 5"));
    test!(repl.exp_string("Int -> Int"));

    test!(repl.send_line(":t \"gluon\""));
    test!(repl.exp_string("String"));
}

#[test]
fn names() {
    let mut repl = test!(spawn(COMMAND, Some(TIMEOUT)));
    test!(repl.exp_string(PROMPT));

    test!(repl.send_line(":i std.prelude.show"));
    test!(repl.exp_string("std.prelude.show: forall a . [std.prelude.Show a] -> a -> String"));
}

#[test]
fn comments() {
    let mut repl = test!(spawn(COMMAND, Some(TIMEOUT)));
    test!(repl.exp_string(PROMPT));

    test!(repl.send_line("1 + 2 // Calls the + function on 1 and 2"));
    test!(repl.exp_string("3"));

    test!(repl.send_line("1 + 2 /* Calls the + function on 1 and 2 */"));
    test!(repl.exp_string("3"));
}

#[test]
fn if_expressions() {
    let mut repl = test!(spawn(COMMAND, Some(TIMEOUT)));
    test!(repl.exp_string(PROMPT));

    test!(repl.send_line("if True then 1 else 0"));
    test!(repl.exp_string("1"));

    test!(repl.send_line("if False then 1 else 0"));
    test!(repl.exp_string("0"));
}

#[test]
fn records() {
    let mut repl = test!(spawn(COMMAND, Some(TIMEOUT)));
    test!(repl.exp_string(PROMPT));

    test!(repl.send_line("let record = { pi = 3.14, add1 = (+) 1.0 }"));

    test!(repl.send_line("record.pi"));
    test!(repl.exp_string("3.14"));

    test!(repl.send_line("let record_2 = {x = 1 .. record }"));

    test!(repl.send_line("record_2.x"));
    test!(repl.exp_string("1"));

    test!(repl.send_line("record_2.pi"));
    test!(repl.exp_string("3.14"));
}

#[test]
fn arrays() {
    let mut repl = test!(spawn(COMMAND, Some(TIMEOUT)));
    test!(repl.exp_string(PROMPT));

    test!(repl.send_line("let array = import! std.array"));

    test!(repl.send_line("array.len [1, 2, 3]"));
    test!(repl.exp_string("3"));
}

<commit_msg>Update test macro for use of Result.<commit_after>#[macro_use]
extern crate pretty_assertions;

extern crate rexpect;

use rexpect::spawn;
use rexpect::errors::*;

use std::env;
use std::fs::File;
use std::io::Read;
use std::path::Path;
use std::process::{Command, Stdio};

#[test]
fn fmt_repl() {
    let source = "src/repl.glu";

    let mut before = String::new();
    File::open(source)
        .unwrap()
        .read_to_string(&mut before)
        .unwrap();

    let status = Command::new("../target/debug/gluon")
        .args(&["fmt", source])
        .spawn()
        .expect("Could not find gluon executable")
        .wait()
        .unwrap();
    assert!(status.success());

    let mut after = String::new();
    File::open(source)
        .unwrap()
        .read_to_string(&mut after)
        .unwrap();

    assert_eq!(before, after);
}

#[test]
fn issue_365_run_io_from_command_line() {
    if ::std::env::var("GLUON_PATH").is_err() {
        ::std::env::set_var("GLUON_PATH", "..");
    }

    let path = env::args().next().unwrap();
    let gluon_path = Path::new(&path[..])
        .parent()
        .and_then(|p| p.parent())
        .expect("folder")
        .join("gluon");
    let output = Command::new(&*gluon_path)
        .stdin(Stdio::piped())
        .stdout(Stdio::piped())
        .stderr(Stdio::piped())
        .arg("tests/print.glu")
        .output()
        .unwrap_or_else(|err| panic!("{}\nWhen opening `{}`", err, gluon_path.display()));

    let stderr = String::from_utf8_lossy(&output.stderr);
    if stderr != "" {
        panic!("{}", stderr);
    }
    assert_eq!(String::from_utf8_lossy(&output.stdout), "123\n");
}

static COMMAND: &str = "../target/debug/gluon -i";
static TIMEOUT: u64 = 10_000;
static PROMPT: &str = "> ";

macro_rules! test {
    ($b: block) => {
        || -> Result<()> {
            $b
        }().unwrap_or_else(|err| panic!("{}", err));
    };
}

#[test]
fn prompt() {
    test!({
        let mut repl = spawn(COMMAND, Some(TIMEOUT))?;
        repl.exp_string(PROMPT)?;

        Ok(())
    });
}

#[test]
fn exit() {
    test!({
        let mut repl = spawn(COMMAND, Some(TIMEOUT))?;
        repl.exp_string(PROMPT)?;

        repl.send_line(":q")?;
        repl.exp_eof()?;

        Ok(())
    });
}

#[test]
#[ignore] // TODO fix intermittent test failure
fn hello_world() {
    test!({
    let mut repl = spawn(COMMAND, Some(TIMEOUT))?;
        repl.exp_string(PROMPT)?;

        repl.send_line("let io = import! std.io")?;

        repl.send_line("io.println \"Hello world\"")?;
        repl.exp_string("Hello world")?;

        Ok(())
    });
}

#[test]
fn expression_types() {
    test!({
        let mut repl = spawn(COMMAND, Some(TIMEOUT))?;
        repl.exp_string(PROMPT)?;

        repl.send_line(":t 5")?;
        repl.exp_string("Int")?;

        repl.send_line(":t 5 + 5")?;
        repl.exp_string("Int -> Int")?;

        repl.send_line(":t \"gluon\"")?;
        repl.exp_string("String")?;

        Ok(())
    });
}

#[test]
fn names() {
    test!({
        let mut repl = spawn(COMMAND, Some(TIMEOUT))?;
        repl.exp_string(PROMPT)?;

        repl.send_line(":i std.prelude.show")?;
        repl.exp_string("std.prelude.show: forall a . [std.prelude.Show a] -> a -> String")?;

        Ok(())
    });
}

#[test]
fn comments() {
    test!({
        let mut repl = spawn(COMMAND, Some(TIMEOUT))?;
        repl.exp_string(PROMPT)?;

        repl.send_line("1 + 2 // Calls the + function on 1 and 2")?;
        repl.exp_string("3")?;

        repl.send_line("1 + 2 /* Calls the + function on 1 and 2 */")?;
        repl.exp_string("3")?;

        Ok(())
    });
}

#[test]
fn if_expressions() {
    test!({
        let mut repl = spawn(COMMAND, Some(TIMEOUT))?;
        repl.exp_string(PROMPT)?;

        repl.send_line("if True then 1 else 0")?;
        repl.exp_string("1")?;

        repl.send_line("if False then 1 else 0")?;
        repl.exp_string("0")?;

        Ok(())
    });
}

#[test]
fn records() {
    test!({
        let mut repl = spawn(COMMAND, Some(TIMEOUT))?;
        repl.exp_string(PROMPT)?;

        repl.send_line("let record = { pi = 3.14, add1 = (+) 1.0 }")?;

        repl.send_line("record.pi")?;
        repl.exp_string("3.14")?;

        repl.send_line("let record_2 = {x = 1 .. record }")?;

        repl.send_line("record_2.x")?;
        repl.exp_string("1")?;

        repl.send_line("record_2.pi")?;
        repl.exp_string("3.14")?;

        Ok(())
    });
}

#[test]
fn arrays() {
    test!({
        let mut repl = spawn(COMMAND, Some(TIMEOUT))?;
        repl.exp_string(PROMPT)?;

        repl.send_line("let array = import! std.array")?;

        repl.send_line("array.len [1, 2, 3]")?;
        repl.exp_string("3")?;

        Ok(())
    });
}

<|endoftext|>


<commit_before>//! The unimpl! macro is defined here. It is used to generate
//! a non-fatal error on not yet implemented things.

use std::cell::RefCell;
use std::fs::File;
use std::io::Write;

use syntax::source_map::Span;

use rustc::ty::TyCtxt;

thread_local! {
    static SPAN_STACK: RefCell<Vec<Span>> = RefCell::new(vec![]);
}

// Just public, because of the unimpl macro
pub struct NonFatal(pub String);

pub macro unimpl($($tt:tt)*) {
    panic!(NonFatal(format!($($tt)*)));
}

pub fn try_unimpl(tcx: TyCtxt, log: &mut Option<File>, f: impl FnOnce()) {
    let res = ::std::panic::catch_unwind(::std::panic::AssertUnwindSafe(|| f()));

    if let Err(err) = res {
        SPAN_STACK.with(|span_stack| {
            match err.downcast::<NonFatal>() {
                Ok(non_fatal) => {
                    if cfg!(debug_assertions) {
                        writeln!(
                            log.as_mut().unwrap(),
                            "{} at {:?}",
                            &non_fatal.0,
                            span_stack.borrow()
                        )
                        .unwrap();
                    }
                    tcx.sess.err(&non_fatal.0)
                }
                Err(err) => ::std::panic::resume_unwind(err),
            }
            span_stack.borrow_mut().clear();
        });
    }
}

pub fn with_unimpl_span(span: Span, f: impl FnOnce()) {
    SPAN_STACK.with(|span_stack| {
        span_stack.borrow_mut().push(span);
        f();
        span_stack.borrow_mut().pop();
    });
}
<commit_msg>Improve unimpl! docs<commit_after>//! The unimpl! macro is defined here. It is used to generate
//! a non-fatal error on not yet implemented things.

use std::cell::RefCell;
use std::fs::File;
use std::io::Write;

use syntax::source_map::Span;

use rustc::ty::TyCtxt;

thread_local! {
    static SPAN_STACK: RefCell<Vec<Span>> = RefCell::new(vec![]);
}

// Just public, because of the unimpl macro
#[doc(hidden)]
pub struct NonFatal(pub String);

/// Use when something in the current function is unimplemented.
///
/// This will emit an error and continue codegen at a different function.
pub macro unimpl($($tt:tt)*) {
    panic!(NonFatal(format!($($tt)*)));
}

pub fn try_unimpl(tcx: TyCtxt, log: &mut Option<File>, f: impl FnOnce()) {
    let res = ::std::panic::catch_unwind(::std::panic::AssertUnwindSafe(|| f()));

    if let Err(err) = res {
        SPAN_STACK.with(|span_stack| {
            match err.downcast::<NonFatal>() {
                Ok(non_fatal) => {
                    if cfg!(debug_assertions) {
                        writeln!(
                            log.as_mut().unwrap(),
                            "{} at {:?}",
                            &non_fatal.0,
                            span_stack.borrow()
                        )
                        .unwrap();
                    }
                    tcx.sess.err(&non_fatal.0)
                }
                Err(err) => ::std::panic::resume_unwind(err),
            }
            span_stack.borrow_mut().clear();
        });
    }
}

pub fn with_unimpl_span(span: Span, f: impl FnOnce()) {
    SPAN_STACK.with(|span_stack| {
        span_stack.borrow_mut().push(span);
        f();
        span_stack.borrow_mut().pop();
    });
}
<|endoftext|>


<commit_before>// Copyright 2013-2015, The Gtk-rs Project Developers.
// See the COPYRIGHT file at the top-level directory of this distribution.
// Licensed under the MIT license, see the LICENSE file or <http://opensource.org/licenses/MIT>

use glib::translate::*;
use gdk;
use ffi;

use glib::object::{Downcast, Upcast};
use {
    Widget,
    WindowPosition,
    WindowType,
};

glib_wrapper! {
    pub struct Window(Object<ffi::GtkWindow>): ::Widget, ::Container, ::Bin, ::Buildable;

    match fn {
        get_type => || ffi::gtk_window_get_type(),
    }
}

impl Window {
    pub fn new(window_type: WindowType) -> Window {
        assert_initialized_main_thread!();
        unsafe { Widget::from_glib_none(ffi::gtk_window_new(window_type)).downcast_unchecked() }
    }
}

pub trait WindowExt {
    fn move_(&self, x: i32, y: i32);
    fn set_type_hint(&self, hint: gdk::WindowTypeHint);
    fn set_title(&self, title: &str);
    fn set_decorated(&self, setting: bool);
    fn get_title(&self) -> Option<String>;
    fn set_default_size(&self, width: i32, height: i32);
    fn set_window_position(&self, window_position: WindowPosition);
    #[cfg(gtk_3_10)]
    fn set_titlebar<T: Upcast<Widget>>(&self, titlebar: &T);
}

impl<O: Upcast<Window>> WindowExt for O {
    fn move_(&self, x: i32, y: i32) {
        unsafe {
            ffi::gtk_window_move(self.to_glib_none().0, x, y);
        }
    }

    fn set_type_hint(&self, hint: gdk::WindowTypeHint) {
        unsafe {
            ffi::gtk_window_set_type_hint(self.to_glib_none().0, hint);
        }
    }

    fn set_title(&self, title: &str) {
        unsafe {
            ffi::gtk_window_set_title(self.to_glib_none().0, title.to_glib_none().0);
        }
    }

    fn set_decorated(&self, setting: bool) {
        unsafe {
            ffi::gtk_window_set_decorated(self.to_glib_none().0, setting.to_glib());
        }
    }

    fn get_title(&self) -> Option<String> {
        unsafe {
            from_glib_none(ffi::gtk_window_get_title(self.to_glib_none().0))
        }
    }

    fn set_default_size(&self, width: i32, height: i32) {
        unsafe {
            ffi::gtk_window_set_default_size(self.to_glib_none().0, width, height)
        }
    }

    fn set_window_position(&self, window_position: WindowPosition) {
        unsafe {
            ffi::gtk_window_set_position(self.to_glib_none().0, window_position);
        }
    }

    #[cfg(gtk_3_10)]
    fn set_titlebar<T: Upcast<Widget>>(&self, titlebar: &T) {
        unsafe {
            ffi::gtk_window_set_titlebar(self.to_glib_none().0,
                titlebar.to_glib_none().0);
        }
    }
}
<commit_msg>Implement `Window::set_transient_for`, which is used to make dialogs modal<commit_after>// Copyright 2013-2015, The Gtk-rs Project Developers.
// See the COPYRIGHT file at the top-level directory of this distribution.
// Licensed under the MIT license, see the LICENSE file or <http://opensource.org/licenses/MIT>

use glib::translate::*;
use gdk;
use ffi;

use glib::object::{Downcast, Upcast};
use {
    Widget,
    WindowPosition,
    WindowType,
};

glib_wrapper! {
    pub struct Window(Object<ffi::GtkWindow>): ::Widget, ::Container, ::Bin, ::Buildable;

    match fn {
        get_type => || ffi::gtk_window_get_type(),
    }
}

impl Window {
    pub fn new(window_type: WindowType) -> Window {
        assert_initialized_main_thread!();
        unsafe { Widget::from_glib_none(ffi::gtk_window_new(window_type)).downcast_unchecked() }
    }
}

pub trait WindowExt {
    fn move_(&self, x: i32, y: i32);
    fn set_type_hint(&self, hint: gdk::WindowTypeHint);
    fn set_title(&self, title: &str);
    fn set_decorated(&self, setting: bool);
    fn get_title(&self) -> Option<String>;
    fn set_default_size(&self, width: i32, height: i32);
    fn set_window_position(&self, window_position: WindowPosition);
    #[cfg(gtk_3_10)]
    fn set_titlebar<T: Upcast<Widget>>(&self, titlebar: &T);
    fn set_transient_for<T: Upcast<Window> = Window>(&self, parent: Option<&T>);
}

impl<O: Upcast<Window>> WindowExt for O {
    fn move_(&self, x: i32, y: i32) {
        unsafe {
            ffi::gtk_window_move(self.to_glib_none().0, x, y);
        }
    }

    fn set_type_hint(&self, hint: gdk::WindowTypeHint) {
        unsafe {
            ffi::gtk_window_set_type_hint(self.to_glib_none().0, hint);
        }
    }

    fn set_title(&self, title: &str) {
        unsafe {
            ffi::gtk_window_set_title(self.to_glib_none().0, title.to_glib_none().0);
        }
    }

    fn set_decorated(&self, setting: bool) {
        unsafe {
            ffi::gtk_window_set_decorated(self.to_glib_none().0, setting.to_glib());
        }
    }

    fn get_title(&self) -> Option<String> {
        unsafe {
            from_glib_none(ffi::gtk_window_get_title(self.to_glib_none().0))
        }
    }

    fn set_default_size(&self, width: i32, height: i32) {
        unsafe {
            ffi::gtk_window_set_default_size(self.to_glib_none().0, width, height)
        }
    }

    fn set_window_position(&self, window_position: WindowPosition) {
        unsafe {
            ffi::gtk_window_set_position(self.to_glib_none().0, window_position);
        }
    }

    #[cfg(gtk_3_10)]
    fn set_titlebar<T: Upcast<Widget>>(&self, titlebar: &T) {
        unsafe {
            ffi::gtk_window_set_titlebar(self.to_glib_none().0,
                titlebar.to_glib_none().0);
        }
    }

    fn set_transient_for<T: Upcast<Window> = Window>(&self, parent: Option<&T>) {
        unsafe {
            ffi::gtk_window_set_transient_for(self.to_glib_none().0, parent.to_glib_none().0);
        }
    }
}
<|endoftext|>


<commit_before>use serde;
use serde_json;
use time;
use std::collections::HashMap;

use std::sync::atomic::{AtomicUsize, Ordering};

pub const DEFAULT_LIBIDY_DID: &str = "LibindyDid111111111111";

pub struct ProtocolVersion {}

lazy_static! {
    pub static ref PROTOCOL_VERSION: AtomicUsize = AtomicUsize::new(1);
}

impl ProtocolVersion {
    pub fn set(version: usize) {
        PROTOCOL_VERSION.store(version, Ordering::Relaxed);
    }

    pub fn get() -> usize {
        PROTOCOL_VERSION.load(Ordering::Relaxed)
    }

    pub fn is_node_1_3() -> bool {
        ProtocolVersion::get() == 1
    }
}

#[derive(Serialize, Deserialize, PartialEq, Debug)]
#[serde(rename_all = "camelCase")]
pub struct TxnAuthrAgrmtAcceptanceData {
    pub mechanism: String,
    pub taa_digest: String,
    pub time: u64
}

#[derive(Serialize, Deserialize, PartialEq, Debug)]
#[serde(rename_all = "camelCase")]
pub struct Request<T: serde::Serialize> {
    pub req_id: u64,
    pub identifier: String,
    pub operation: T,
    pub protocol_version: Option<usize>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub signature: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub signatures: Option<HashMap<String, String>>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub taa_acceptance: Option<TxnAuthrAgrmtAcceptanceData>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub endorser: Option<String>
}

impl<T: serde::Serialize> Request<T> {
    pub fn new(req_id: u64, identifier: &str, operation: T, protocol_version: usize) -> Request<T> {
        Request {
            req_id,
            identifier: identifier.to_string(),
            operation,
            protocol_version: Some(protocol_version),
            signature: None,
            signatures: None,
            taa_acceptance: None,
            endorser: None,
        }
    }

    pub fn build_request(identifier: Option<&str>, operation: T) -> Result<String, serde_json::Error> {
        let req_id = time::get_time().sec as u64 * (1e9 as u64) + time::get_time().nsec as u64;
        let identifier = identifier.unwrap_or(DEFAULT_LIBIDY_DID);
        serde_json::to_string(&Request::new(req_id, identifier, operation, ProtocolVersion::get()))
    }
}<commit_msg>Request identifier can be optional<commit_after>use serde;
use serde_json;
use time;
use std::collections::HashMap;

use std::sync::atomic::{AtomicUsize, Ordering};

pub const DEFAULT_LIBIDY_DID: &str = "LibindyDid111111111111";

pub struct ProtocolVersion {}

lazy_static! {
    pub static ref PROTOCOL_VERSION: AtomicUsize = AtomicUsize::new(1);
}

impl ProtocolVersion {
    pub fn set(version: usize) {
        PROTOCOL_VERSION.store(version, Ordering::Relaxed);
    }

    pub fn get() -> usize {
        PROTOCOL_VERSION.load(Ordering::Relaxed)
    }

    pub fn is_node_1_3() -> bool {
        ProtocolVersion::get() == 1
    }
}

#[derive(Serialize, Deserialize, PartialEq, Debug)]
#[serde(rename_all = "camelCase")]
pub struct TxnAuthrAgrmtAcceptanceData {
    pub mechanism: String,
    pub taa_digest: String,
    pub time: u64
}

#[derive(Serialize, Deserialize, PartialEq, Debug)]
#[serde(rename_all = "camelCase")]
pub struct Request<T: serde::Serialize> {
    pub req_id: u64,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub identifier: Option<String>,
    pub operation: T,
    pub protocol_version: Option<usize>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub signature: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub signatures: Option<HashMap<String, String>>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub taa_acceptance: Option<TxnAuthrAgrmtAcceptanceData>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub endorser: Option<String>
}

impl<T: serde::Serialize> Request<T> {
    pub fn new(req_id: u64, identifier: &str, operation: T, protocol_version: usize) -> Request<T> {
        Request {
            req_id,
            identifier: Some(identifier.to_string()),
            operation,
            protocol_version: Some(protocol_version),
            signature: None,
            signatures: None,
            taa_acceptance: None,
            endorser: None,
        }
    }

    pub fn build_request(identifier: Option<&str>, operation: T) -> Result<String, serde_json::Error> {
        let req_id = time::get_time().sec as u64 * (1e9 as u64) + time::get_time().nsec as u64;
        let identifier = identifier.unwrap_or(DEFAULT_LIBIDY_DID);
        serde_json::to_string(&Request::new(req_id, identifier, operation, ProtocolVersion::get()))
    }
}<|endoftext|>


<commit_before>
pub( crate ) mod private
{
  use std::collections::HashMap;
  use std::rc::Rc;
  use core::fmt;
  use crate::*;
  use wtools::error::BasicError;

  // qqq : for Dima : adjust formatting

  ///
  /// Handle for command routine.
  ///

  // qqq : for Dima : make alias for Result with BasicError
  pub struct OnCommand( Option< Rc< dyn Fn( &instruction::Instruction ) -> Result< (), BasicError > > > );

  impl OnCommand
  {
    /// Checks that OnCommand has callback to call.
    pub fn callable( &self ) -> bool
    {
      if self.0.is_some()
      {
        true
      }
      else
      {
        false
      }
    }
    /// Perform callback.
    pub fn perform( &self, instruction : &instruction::Instruction ) -> Result< (), BasicError >
    {
      if self.0.is_some()
      {
        let r = self.0.as_ref().unwrap();
        return r( instruction );
      }

      Ok( () )
    }
  }

  impl Default for OnCommand
  {
    fn default() -> Self
    {
      Self ( Option::None )
    }
  }

  impl From<&'static dyn Fn( &instruction::Instruction ) -> Result< (), BasicError >> for OnCommand
  {
    fn from( src : &'static dyn Fn( &instruction::Instruction ) -> Result< (), BasicError > ) -> Self
    {
      OnCommand( Some( Rc::new( src ) ) )
    }
  }

  impl Clone for OnCommand
  {
    fn clone( &self ) -> Self
    {
      match self
      {
        OnCommand ( Option::None ) => Self ( None ),
        OnCommand ( Option::Some( boxed ) ) => Self ( Some( boxed.clone() ) ),
      }
    }
  }

  impl fmt::Debug for OnCommand
  {
    fn fmt( &self, f: &mut fmt::Formatter<'_> ) -> fmt::Result
    {
      match self
      {
        OnCommand ( Option::None ) => f.write_str( "None" ),
        OnCommand ( Option::Some( _rc ) ) => f.write_str( "OnCommand" ),
      }
    }
  }

  ///
  /// Command descriptor.
  ///

  #[derive( Default, Debug, Clone )]
  pub struct Command
  {
    /// Command common hint.
    pub hint : String,
    /// Command full hint.
    pub long_hint : String,
    /// Phrase descriptor for command.
    pub phrase : String,
    /// Command subject hint.
    pub subject_hint : String,
    /// Hints for command options.
    pub properties_hints : HashMap< String, String >,
    /// Map of aliases.
    pub properties_aliases : HashMap< String, Vec< String > >,
    /// Command routine.
    pub routine : OnCommand,
  }

  impl PartialEq for Command
  {
    /* qqq : for Dmytro : extend */
    fn eq( &self, other: &Self ) -> bool
    {
      self.hint == other.hint
      && self.long_hint == other.long_hint
      && self.subject_hint == other.subject_hint
    }
  }

  impl Command
  {
    /// Generate short help for command.
    pub fn help_short( &self ) -> String
    {
      format!( "{} - {}", self.phrase, self.hint )
    }

    /// Generate short help for command.
    pub fn help_long( &self ) -> String
    {
      let properties_hints = self.properties_hints.iter().map( | ( key, value ) | format!( "  {} - {}", key, value ) ).collect::< Vec< _ > >();
      let properties_hints = properties_hints.join( "\n" );
      format!( "{} - {}\n{}", self.phrase, self.long_hint, properties_hints )
    }

    /// Execute callback.
    pub fn perform( &self, instruction : &instruction::Instruction ) -> Result< (), BasicError >
    {
      if self.subject_hint.len() == 0 && instruction.subject.len() != 0
      {
        return Err( BasicError::new( "Unexpected subject." ) );
      }

      for ( key, _value ) in &instruction.properties_map
      {
        if self.properties_hints.get( key.as_str() ).is_none()
        {
          return Err( BasicError::new( "Unknown option." ) );
        }
      }
      if self.routine.callable()
      {
        return self.routine.perform( instruction );
      }

      Ok( () )
    }
  }

  ///
  /// Options for command.
  ///

  #[derive( Debug, Clone, Default )]
  pub struct CommandOptions
  {
    ins : Command,
  }

  //

  // ro : null,
  // h : null,
  // lh : null,

  impl CommandOptions
  {
    field_str!{ hint }
    field_str!{ hint, h }
    field_str!{ long_hint }
    field_str!{ long_hint, lh }
    field_str!{ phrase }
    field_str!{ subject_hint }
    field_str!{ subject_hint, sh }
    field_map_str_str!{ properties_hints, property_hint }
    field_map_str_vec_str!{ properties_aliases, property_alias }
    field_routine!{ routine }
    field_routine!{ routine, ro }

    /// Command former.
    pub fn form( &self ) -> Command
    {
      self.ins.clone()
    }

  }
}

/// Protected namespace of the module.
pub mod protected
{
  pub use super::private::OnCommand;
  pub use super::private::Command;
  pub use super::private::CommandOptions;
}

pub use protected::*;

/// Exposed namespace of the module.
pub mod exposed
{
  pub use super::private::OnCommand;
  pub use super::private::Command;
  pub use super::private::CommandOptions;
}

/// Namespace of the module to include with `use module::*`.
pub mod prelude
{
  pub use super::private::OnCommand;
  pub use super::private::Command;
  pub use super::private::CommandOptions;
}

<commit_msg>Fix routines `help_short`, `help_long`, print phrase with dots<commit_after>
pub( crate ) mod private
{
  use std::collections::HashMap;
  use std::rc::Rc;
  use core::fmt;
  use crate::*;
  use wtools::error::BasicError;

  // qqq : for Dima : adjust formatting

  ///
  /// Handle for command routine.
  ///

  // qqq : for Dima : make alias for Result with BasicError
  pub struct OnCommand( Option< Rc< dyn Fn( &instruction::Instruction ) -> Result< (), BasicError > > > );

  impl OnCommand
  {
    /// Checks that OnCommand has callback to call.
    pub fn callable( &self ) -> bool
    {
      if self.0.is_some()
      {
        true
      }
      else
      {
        false
      }
    }
    /// Perform callback.
    pub fn perform( &self, instruction : &instruction::Instruction ) -> Result< (), BasicError >
    {
      if self.0.is_some()
      {
        let r = self.0.as_ref().unwrap();
        return r( instruction );
      }

      Ok( () )
    }
  }

  impl Default for OnCommand
  {
    fn default() -> Self
    {
      Self ( Option::None )
    }
  }

  impl From<&'static dyn Fn( &instruction::Instruction ) -> Result< (), BasicError >> for OnCommand
  {
    fn from( src : &'static dyn Fn( &instruction::Instruction ) -> Result< (), BasicError > ) -> Self
    {
      OnCommand( Some( Rc::new( src ) ) )
    }
  }

  impl Clone for OnCommand
  {
    fn clone( &self ) -> Self
    {
      match self
      {
        OnCommand ( Option::None ) => Self ( None ),
        OnCommand ( Option::Some( boxed ) ) => Self ( Some( boxed.clone() ) ),
      }
    }
  }

  impl fmt::Debug for OnCommand
  {
    fn fmt( &self, f: &mut fmt::Formatter<'_> ) -> fmt::Result
    {
      match self
      {
        OnCommand ( Option::None ) => f.write_str( "None" ),
        OnCommand ( Option::Some( _rc ) ) => f.write_str( "OnCommand" ),
      }
    }
  }

  ///
  /// Command descriptor.
  ///

  #[derive( Default, Debug, Clone )]
  pub struct Command
  {
    /// Command common hint.
    pub hint : String,
    /// Command full hint.
    pub long_hint : String,
    /// Phrase descriptor for command.
    pub phrase : String,
    /// Command subject hint.
    pub subject_hint : String,
    /// Hints for command options.
    pub properties_hints : HashMap< String, String >,
    /// Map of aliases.
    pub properties_aliases : HashMap< String, Vec< String > >,
    /// Command routine.
    pub routine : OnCommand,
  }

  impl PartialEq for Command
  {
    /* qqq : for Dmytro : extend */
    fn eq( &self, other: &Self ) -> bool
    {
      self.hint == other.hint
      && self.long_hint == other.long_hint
      && self.subject_hint == other.subject_hint
    }
  }

  impl Command
  {
    /// Generate short help for command.
    pub fn help_short( &self ) -> String
    {
      format!( ".{} - {}", self.phrase.split( " " ).collect::< Vec< _ > >().join( "." ), self.hint )
    }

    /// Generate short help for command.
    pub fn help_long( &self ) -> String
    {
      let properties_hints = self.properties_hints.iter().map( | ( key, value ) | format!( "  {} - {}", key, value ) ).collect::< Vec< _ > >();
      let properties_hints = properties_hints.join( "\n" );
      format!( ".{} - {}\n{}", self.phrase.split( " " ).collect::< Vec< _ > >().join( "." ), self.long_hint, properties_hints )
    }

    /// Execute callback.
    pub fn perform( &self, instruction : &instruction::Instruction ) -> Result< (), BasicError >
    {
      if self.subject_hint.len() == 0 && instruction.subject.len() != 0
      {
        return Err( BasicError::new( "Unexpected subject." ) );
      }

      for ( key, _value ) in &instruction.properties_map
      {
        if self.properties_hints.get( key.as_str() ).is_none()
        {
          return Err( BasicError::new( "Unknown option." ) );
        }
      }
      if self.routine.callable()
      {
        return self.routine.perform( instruction );
      }

      Ok( () )
    }
  }

  ///
  /// Options for command.
  ///

  #[derive( Debug, Clone, Default )]
  pub struct CommandOptions
  {
    ins : Command,
  }

  //

  // ro : null,
  // h : null,
  // lh : null,

  impl CommandOptions
  {
    field_str!{ hint }
    field_str!{ hint, h }
    field_str!{ long_hint }
    field_str!{ long_hint, lh }
    field_str!{ phrase }
    field_str!{ subject_hint }
    field_str!{ subject_hint, sh }
    field_map_str_str!{ properties_hints, property_hint }
    field_map_str_vec_str!{ properties_aliases, property_alias }
    field_routine!{ routine }
    field_routine!{ routine, ro }

    /// Command former.
    pub fn form( &self ) -> Command
    {
      self.ins.clone()
    }

  }
}

/// Protected namespace of the module.
pub mod protected
{
  pub use super::private::OnCommand;
  pub use super::private::Command;
  pub use super::private::CommandOptions;
}

pub use protected::*;

/// Exposed namespace of the module.
pub mod exposed
{
  pub use super::private::OnCommand;
  pub use super::private::Command;
  pub use super::private::CommandOptions;
}

/// Namespace of the module to include with `use module::*`.
pub mod prelude
{
  pub use super::private::OnCommand;
  pub use super::private::Command;
  pub use super::private::CommandOptions;
}

<|endoftext|>


<commit_before>#![unstable(issue = "none", feature = "windows_stdio")]

use crate::char::decode_utf16;
use crate::cmp;
use crate::io;
use crate::ptr;
use crate::str;
use crate::sys::c;
use crate::sys::cvt;
use crate::sys::handle::Handle;
use core::str::utf8_char_width;

// Don't cache handles but get them fresh for every read/write. This allows us to track changes to
// the value over time (such as if a process calls `SetStdHandle` while it's running). See #40490.
pub struct Stdin {
    surrogate: u16,
}
pub struct Stdout {
    incomplete_utf8: IncompleteUtf8,
}

pub struct Stderr {
    incomplete_utf8: IncompleteUtf8,
}

struct IncompleteUtf8 {
    bytes: [u8; 4],
    len: u8,
}

// Apparently Windows doesn't handle large reads on stdin or writes to stdout/stderr well (see
// #13304 for details).
//
// From MSDN (2011): "The storage for this buffer is allocated from a shared heap for the
// process that is 64 KB in size. The maximum size of the buffer will depend on heap usage."
//
// We choose the cap at 8 KiB because libuv does the same, and it seems to be acceptable so far.
const MAX_BUFFER_SIZE: usize = 8192;

// The standard buffer size of BufReader for Stdin should be able to hold 3x more bytes than there
// are `u16`'s in MAX_BUFFER_SIZE. This ensures the read data can always be completely decoded from
// UTF-16 to UTF-8.
pub const STDIN_BUF_SIZE: usize = MAX_BUFFER_SIZE / 2 * 3;

pub fn get_handle(handle_id: c::DWORD) -> io::Result<c::HANDLE> {
    let handle = unsafe { c::GetStdHandle(handle_id) };
    if handle == c::INVALID_HANDLE_VALUE {
        Err(io::Error::last_os_error())
    } else if handle.is_null() {
        Err(io::Error::from_raw_os_error(c::ERROR_INVALID_HANDLE as i32))
    } else {
        Ok(handle)
    }
}

fn is_console(handle: c::HANDLE) -> bool {
    // `GetConsoleMode` will return false (0) if this is a pipe (we don't care about the reported
    // mode). This will only detect Windows Console, not other terminals connected to a pipe like
    // MSYS. Which is exactly what we need, as only Windows Console needs a conversion to UTF-16.
    let mut mode = 0;
    unsafe { c::GetConsoleMode(handle, &mut mode) != 0 }
}

fn write(
    handle_id: c::DWORD,
    data: &[u8],
    incomplete_utf8: &mut IncompleteUtf8,
) -> io::Result<usize> {
    if data.is_empty() {
        return Ok(0);
    }

    let handle = get_handle(handle_id)?;
    if !is_console(handle) {
        let handle = Handle::new(handle);
        let ret = handle.write(data);
        handle.into_raw(); // Don't close the handle
        return ret;
    }

    match incomplete_utf8.len {
        0 => {}
        1..=3 => {
            if data[0] >> 6 != 0b10 {
                incomplete_utf8.len = 0;
                // not a continuation byte - reject
                return Err(io::Error::new_const(
                    io::ErrorKind::InvalidData,
                    &"Windows stdio in console mode does not support writing non-UTF-8 byte sequences",
                ));
            }
            incomplete_utf8.bytes[incomplete_utf8.len as usize] = data[0];
            incomplete_utf8.len += 1;
            let char_width = utf8_char_width(incomplete_utf8.bytes[0]);
            if (incomplete_utf8.len as usize) < char_width {
                // more bytes needed
                return Ok(1);
            }
            let s = str::from_utf8(&incomplete_utf8.bytes[0..incomplete_utf8.len as usize]);
            incomplete_utf8.len = 0;
            match s {
                Ok(s) => {
                    assert_eq!(char_width, s.len());
                    let written = write_valid_utf8_to_console(handle, s)?;
                    assert_eq!(written, s.len()); // guaranteed by write_valid_utf8_to_console() for single codepoint writes
                    return Ok(1);
                }
                Err(_) => {
                    return Err(io::Error::new_const(
                        io::ErrorKind::InvalidData,
                        &"Windows stdio in console mode does not support writing non-UTF-8 byte sequences",
                    ));
                }
            }
        }
        _ => {
            panic!("Unexpected number of incomplete UTF-8 chars.");
        }
    }

    // As the console is meant for presenting text, we assume bytes of `data` are encoded as UTF-8,
    // which needs to be encoded as UTF-16.
    //
    // If the data is not valid UTF-8 we write out as many bytes as are valid.
    // If the first byte is invalid it is either first byte of a multi-byte sequence but the
    // provided byte slice is too short or it is the first byte of an invalide multi-byte sequence.
    let len = cmp::min(data.len(), MAX_BUFFER_SIZE / 2);
    let utf8 = match str::from_utf8(&data[..len]) {
        Ok(s) => s,
        Err(ref e) if e.valid_up_to() == 0 => {
            let first_byte_char_width = utf8_char_width(data[0]);
            if first_byte_char_width > 1 && data.len() < first_byte_char_width {
                incomplete_utf8.bytes[0] = data[0];
                incomplete_utf8.len = 1;
                return Ok(1);
            } else {
                return Err(io::Error::new_const(
                    io::ErrorKind::InvalidData,
                    &"Windows stdio in console mode does not support writing non-UTF-8 byte sequences",
                ));
            }
        }
        Err(e) => str::from_utf8(&data[..e.valid_up_to()]).unwrap(),
    };

    write_valid_utf8_to_console(handle, utf8)
}

fn write_valid_utf8_to_console(handle: c::HANDLE, utf8: &str) -> io::Result<usize> {
    let mut utf16 = [0u16; MAX_BUFFER_SIZE / 2];
    let mut len_utf16 = 0;
    for (chr, dest) in utf8.encode_utf16().zip(utf16.iter_mut()) {
        *dest = chr;
        len_utf16 += 1;
    }
    let utf16 = &utf16[..len_utf16];

    let mut written = write_u16s(handle, &utf16)?;

    // Figure out how many bytes of as UTF-8 were written away as UTF-16.
    if written == utf16.len() {
        Ok(utf8.len())
    } else {
        // Make sure we didn't end up writing only half of a surrogate pair (even though the chance
        // is tiny). Because it is not possible for user code to re-slice `data` in such a way that
        // a missing surrogate can be produced (and also because of the UTF-8 validation above),
        // write the missing surrogate out now.
        // Buffering it would mean we have to lie about the number of bytes written.
        let first_char_remaining = utf16[written];
        if first_char_remaining >= 0xDCEE && first_char_remaining <= 0xDFFF {
            // low surrogate
            // We just hope this works, and give up otherwise
            let _ = write_u16s(handle, &utf16[written..written + 1]);
            written += 1;
        }
        // Calculate the number of bytes of `utf8` that were actually written.
        let mut count = 0;
        for ch in utf16[..written].iter() {
            count += match ch {
                0x0000..=0x007F => 1,
                0x0080..=0x07FF => 2,
                0xDCEE..=0xDFFF => 1, // Low surrogate. We already counted 3 bytes for the other.
                _ => 3,
            };
        }
        debug_assert!(String::from_utf16(&utf16[..written]).unwrap() == utf8[..count]);
        Ok(count)
    }
}

fn write_u16s(handle: c::HANDLE, data: &[u16]) -> io::Result<usize> {
    let mut written = 0;
    cvt(unsafe {
        c::WriteConsoleW(
            handle,
            data.as_ptr() as c::LPCVOID,
            data.len() as u32,
            &mut written,
            ptr::null_mut(),
        )
    })?;
    Ok(written as usize)
}

impl Stdin {
    pub const fn new() -> Stdin {
        Stdin { surrogate: 0 }
    }
}

impl io::Read for Stdin {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        let handle = get_handle(c::STD_INPUT_HANDLE)?;
        if !is_console(handle) {
            let handle = Handle::new(handle);
            let ret = handle.read(buf);
            handle.into_raw(); // Don't close the handle
            return ret;
        }

        if buf.len() == 0 {
            return Ok(0);
        } else if buf.len() < 4 {
            return Err(io::Error::new_const(
                io::ErrorKind::InvalidInput,
                &"Windows stdin in console mode does not support a buffer too small to \
                 guarantee holding one arbitrary UTF-8 character (4 bytes)",
            ));
        }

        let mut utf16_buf = [0u16; MAX_BUFFER_SIZE / 2];
        // In the worst case, an UTF-8 string can take 3 bytes for every `u16` of an UTF-16. So
        // we can read at most a third of `buf.len()` chars and uphold the guarantee no data gets
        // lost.
        let amount = cmp::min(buf.len() / 3, utf16_buf.len());
        let read = read_u16s_fixup_surrogates(handle, &mut utf16_buf, amount, &mut self.surrogate)?;

        utf16_to_utf8(&utf16_buf[..read], buf)
    }
}

// We assume that if the last `u16` is an unpaired surrogate they got sliced apart by our
// buffer size, and keep it around for the next read hoping to put them together.
// This is a best effort, and may not work if we are not the only reader on Stdin.
fn read_u16s_fixup_surrogates(
    handle: c::HANDLE,
    buf: &mut [u16],
    mut amount: usize,
    surrogate: &mut u16,
) -> io::Result<usize> {
    // Insert possibly remaining unpaired surrogate from last read.
    let mut start = 0;
    if *surrogate != 0 {
        buf[0] = *surrogate;
        *surrogate = 0;
        start = 1;
        if amount == 1 {
            // Special case: `Stdin::read` guarantees we can always read at least one new `u16`
            // and combine it with an unpaired surrogate, because the UTF-8 buffer is at least
            // 4 bytes.
            amount = 2;
        }
    }
    let mut amount = read_u16s(handle, &mut buf[start..amount])? + start;

    if amount > 0 {
        let last_char = buf[amount - 1];
        if last_char >= 0xD800 && last_char <= 0xDBFF {
            // high surrogate
            *surrogate = last_char;
            amount -= 1;
        }
    }
    Ok(amount)
}

fn read_u16s(handle: c::HANDLE, buf: &mut [u16]) -> io::Result<usize> {
    // Configure the `pInputControl` parameter to not only return on `\r\n` but also Ctrl-Z, the
    // traditional DOS method to indicate end of character stream / user input (SUB).
    // See #38274 and https://stackoverflow.com/questions/43836040/win-api-readconsole.
    const CTRL_Z: u16 = 0x1A;
    const CTRL_Z_MASK: c::ULONG = 1 << CTRL_Z;
    let mut input_control = c::CONSOLE_READCONSOLE_CONTROL {
        nLength: crate::mem::size_of::<c::CONSOLE_READCONSOLE_CONTROL>() as c::ULONG,
        nInitialChars: 0,
        dwCtrlWakeupMask: CTRL_Z_MASK,
        dwControlKeyState: 0,
    };

    let mut amount = 0;
    cvt(unsafe {
        c::ReadConsoleW(
            handle,
            buf.as_mut_ptr() as c::LPVOID,
            buf.len() as u32,
            &mut amount,
            &mut input_control as c::PCONSOLE_READCONSOLE_CONTROL,
        )
    })?;

    if amount > 0 && buf[amount as usize - 1] == CTRL_Z {
        amount -= 1;
    }
    Ok(amount as usize)
}

#[allow(unused)]
fn utf16_to_utf8(utf16: &[u16], utf8: &mut [u8]) -> io::Result<usize> {
    let mut written = 0;
    for chr in decode_utf16(utf16.iter().cloned()) {
        match chr {
            Ok(chr) => {
                chr.encode_utf8(&mut utf8[written..]);
                written += chr.len_utf8();
            }
            Err(_) => {
                // We can't really do any better than forget all data and return an error.
                return Err(io::Error::new_const(
                    io::ErrorKind::InvalidData,
                    &"Windows stdin in console mode does not support non-UTF-16 input; \
                     encountered unpaired surrogate",
                ));
            }
        }
    }
    Ok(written)
}

impl IncompleteUtf8 {
    pub const fn new() -> IncompleteUtf8 {
        IncompleteUtf8 { bytes: [0; 4], len: 0 }
    }
}

impl Stdout {
    pub const fn new() -> Stdout {
        Stdout { incomplete_utf8: IncompleteUtf8::new() }
    }
}

impl io::Write for Stdout {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        write(c::STD_OUTPUT_HANDLE, buf, &mut self.incomplete_utf8)
    }

    fn flush(&mut self) -> io::Result<()> {
        Ok(())
    }
}

impl Stderr {
    pub const fn new() -> Stderr {
        Stderr { incomplete_utf8: IncompleteUtf8::new() }
    }
}

impl io::Write for Stderr {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        write(c::STD_ERROR_HANDLE, buf, &mut self.incomplete_utf8)
    }

    fn flush(&mut self) -> io::Result<()> {
        Ok(())
    }
}

pub fn is_ebadf(err: &io::Error) -> bool {
    err.raw_os_error() == Some(c::ERROR_INVALID_HANDLE as i32)
}

pub fn panic_output() -> Option<impl io::Write> {
    Some(Stderr::new())
}
<commit_msg>assert!() instead of panic!() for expected invariant<commit_after>#![unstable(issue = "none", feature = "windows_stdio")]

use crate::char::decode_utf16;
use crate::cmp;
use crate::io;
use crate::ptr;
use crate::str;
use crate::sys::c;
use crate::sys::cvt;
use crate::sys::handle::Handle;
use core::str::utf8_char_width;

// Don't cache handles but get them fresh for every read/write. This allows us to track changes to
// the value over time (such as if a process calls `SetStdHandle` while it's running). See #40490.
pub struct Stdin {
    surrogate: u16,
}
pub struct Stdout {
    incomplete_utf8: IncompleteUtf8,
}

pub struct Stderr {
    incomplete_utf8: IncompleteUtf8,
}

struct IncompleteUtf8 {
    bytes: [u8; 4],
    len: u8,
}

// Apparently Windows doesn't handle large reads on stdin or writes to stdout/stderr well (see
// #13304 for details).
//
// From MSDN (2011): "The storage for this buffer is allocated from a shared heap for the
// process that is 64 KB in size. The maximum size of the buffer will depend on heap usage."
//
// We choose the cap at 8 KiB because libuv does the same, and it seems to be acceptable so far.
const MAX_BUFFER_SIZE: usize = 8192;

// The standard buffer size of BufReader for Stdin should be able to hold 3x more bytes than there
// are `u16`'s in MAX_BUFFER_SIZE. This ensures the read data can always be completely decoded from
// UTF-16 to UTF-8.
pub const STDIN_BUF_SIZE: usize = MAX_BUFFER_SIZE / 2 * 3;

pub fn get_handle(handle_id: c::DWORD) -> io::Result<c::HANDLE> {
    let handle = unsafe { c::GetStdHandle(handle_id) };
    if handle == c::INVALID_HANDLE_VALUE {
        Err(io::Error::last_os_error())
    } else if handle.is_null() {
        Err(io::Error::from_raw_os_error(c::ERROR_INVALID_HANDLE as i32))
    } else {
        Ok(handle)
    }
}

fn is_console(handle: c::HANDLE) -> bool {
    // `GetConsoleMode` will return false (0) if this is a pipe (we don't care about the reported
    // mode). This will only detect Windows Console, not other terminals connected to a pipe like
    // MSYS. Which is exactly what we need, as only Windows Console needs a conversion to UTF-16.
    let mut mode = 0;
    unsafe { c::GetConsoleMode(handle, &mut mode) != 0 }
}

fn write(
    handle_id: c::DWORD,
    data: &[u8],
    incomplete_utf8: &mut IncompleteUtf8,
) -> io::Result<usize> {
    if data.is_empty() {
        return Ok(0);
    }

    let handle = get_handle(handle_id)?;
    if !is_console(handle) {
        let handle = Handle::new(handle);
        let ret = handle.write(data);
        handle.into_raw(); // Don't close the handle
        return ret;
    }

    if incomplete_utf8.len > 0 {
        assert!(
            incomplete_utf8.len < 4,
            "Unexpected number of bytes for incomplete UTF-8 codepoint."
        );
        if data[0] >> 6 != 0b10 {
            incomplete_utf8.len = 0;
            // not a continuation byte - reject
            return Err(io::Error::new_const(
                io::ErrorKind::InvalidData,
                &"Windows stdio in console mode does not support writing non-UTF-8 byte sequences",
            ));
        }
        incomplete_utf8.bytes[incomplete_utf8.len as usize] = data[0];
        incomplete_utf8.len += 1;
        let char_width = utf8_char_width(incomplete_utf8.bytes[0]);
        if (incomplete_utf8.len as usize) < char_width {
            // more bytes needed
            return Ok(1);
        }
        let s = str::from_utf8(&incomplete_utf8.bytes[0..incomplete_utf8.len as usize]);
        incomplete_utf8.len = 0;
        match s {
            Ok(s) => {
                assert_eq!(char_width, s.len());
                let written = write_valid_utf8_to_console(handle, s)?;
                assert_eq!(written, s.len()); // guaranteed by write_valid_utf8_to_console() for single codepoint writes
                return Ok(1);
            }
            Err(_) => {
                return Err(io::Error::new_const(
                    io::ErrorKind::InvalidData,
                    &"Windows stdio in console mode does not support writing non-UTF-8 byte sequences",
                ));
            }
        }
    }

    // As the console is meant for presenting text, we assume bytes of `data` are encoded as UTF-8,
    // which needs to be encoded as UTF-16.
    //
    // If the data is not valid UTF-8 we write out as many bytes as are valid.
    // If the first byte is invalid it is either first byte of a multi-byte sequence but the
    // provided byte slice is too short or it is the first byte of an invalide multi-byte sequence.
    let len = cmp::min(data.len(), MAX_BUFFER_SIZE / 2);
    let utf8 = match str::from_utf8(&data[..len]) {
        Ok(s) => s,
        Err(ref e) if e.valid_up_to() == 0 => {
            let first_byte_char_width = utf8_char_width(data[0]);
            if first_byte_char_width > 1 && data.len() < first_byte_char_width {
                incomplete_utf8.bytes[0] = data[0];
                incomplete_utf8.len = 1;
                return Ok(1);
            } else {
                return Err(io::Error::new_const(
                    io::ErrorKind::InvalidData,
                    &"Windows stdio in console mode does not support writing non-UTF-8 byte sequences",
                ));
            }
        }
        Err(e) => str::from_utf8(&data[..e.valid_up_to()]).unwrap(),
    };

    write_valid_utf8_to_console(handle, utf8)
}

fn write_valid_utf8_to_console(handle: c::HANDLE, utf8: &str) -> io::Result<usize> {
    let mut utf16 = [0u16; MAX_BUFFER_SIZE / 2];
    let mut len_utf16 = 0;
    for (chr, dest) in utf8.encode_utf16().zip(utf16.iter_mut()) {
        *dest = chr;
        len_utf16 += 1;
    }
    let utf16 = &utf16[..len_utf16];

    let mut written = write_u16s(handle, &utf16)?;

    // Figure out how many bytes of as UTF-8 were written away as UTF-16.
    if written == utf16.len() {
        Ok(utf8.len())
    } else {
        // Make sure we didn't end up writing only half of a surrogate pair (even though the chance
        // is tiny). Because it is not possible for user code to re-slice `data` in such a way that
        // a missing surrogate can be produced (and also because of the UTF-8 validation above),
        // write the missing surrogate out now.
        // Buffering it would mean we have to lie about the number of bytes written.
        let first_char_remaining = utf16[written];
        if first_char_remaining >= 0xDCEE && first_char_remaining <= 0xDFFF {
            // low surrogate
            // We just hope this works, and give up otherwise
            let _ = write_u16s(handle, &utf16[written..written + 1]);
            written += 1;
        }
        // Calculate the number of bytes of `utf8` that were actually written.
        let mut count = 0;
        for ch in utf16[..written].iter() {
            count += match ch {
                0x0000..=0x007F => 1,
                0x0080..=0x07FF => 2,
                0xDCEE..=0xDFFF => 1, // Low surrogate. We already counted 3 bytes for the other.
                _ => 3,
            };
        }
        debug_assert!(String::from_utf16(&utf16[..written]).unwrap() == utf8[..count]);
        Ok(count)
    }
}

fn write_u16s(handle: c::HANDLE, data: &[u16]) -> io::Result<usize> {
    let mut written = 0;
    cvt(unsafe {
        c::WriteConsoleW(
            handle,
            data.as_ptr() as c::LPCVOID,
            data.len() as u32,
            &mut written,
            ptr::null_mut(),
        )
    })?;
    Ok(written as usize)
}

impl Stdin {
    pub const fn new() -> Stdin {
        Stdin { surrogate: 0 }
    }
}

impl io::Read for Stdin {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        let handle = get_handle(c::STD_INPUT_HANDLE)?;
        if !is_console(handle) {
            let handle = Handle::new(handle);
            let ret = handle.read(buf);
            handle.into_raw(); // Don't close the handle
            return ret;
        }

        if buf.len() == 0 {
            return Ok(0);
        } else if buf.len() < 4 {
            return Err(io::Error::new_const(
                io::ErrorKind::InvalidInput,
                &"Windows stdin in console mode does not support a buffer too small to \
                 guarantee holding one arbitrary UTF-8 character (4 bytes)",
            ));
        }

        let mut utf16_buf = [0u16; MAX_BUFFER_SIZE / 2];
        // In the worst case, an UTF-8 string can take 3 bytes for every `u16` of an UTF-16. So
        // we can read at most a third of `buf.len()` chars and uphold the guarantee no data gets
        // lost.
        let amount = cmp::min(buf.len() / 3, utf16_buf.len());
        let read = read_u16s_fixup_surrogates(handle, &mut utf16_buf, amount, &mut self.surrogate)?;

        utf16_to_utf8(&utf16_buf[..read], buf)
    }
}

// We assume that if the last `u16` is an unpaired surrogate they got sliced apart by our
// buffer size, and keep it around for the next read hoping to put them together.
// This is a best effort, and may not work if we are not the only reader on Stdin.
fn read_u16s_fixup_surrogates(
    handle: c::HANDLE,
    buf: &mut [u16],
    mut amount: usize,
    surrogate: &mut u16,
) -> io::Result<usize> {
    // Insert possibly remaining unpaired surrogate from last read.
    let mut start = 0;
    if *surrogate != 0 {
        buf[0] = *surrogate;
        *surrogate = 0;
        start = 1;
        if amount == 1 {
            // Special case: `Stdin::read` guarantees we can always read at least one new `u16`
            // and combine it with an unpaired surrogate, because the UTF-8 buffer is at least
            // 4 bytes.
            amount = 2;
        }
    }
    let mut amount = read_u16s(handle, &mut buf[start..amount])? + start;

    if amount > 0 {
        let last_char = buf[amount - 1];
        if last_char >= 0xD800 && last_char <= 0xDBFF {
            // high surrogate
            *surrogate = last_char;
            amount -= 1;
        }
    }
    Ok(amount)
}

fn read_u16s(handle: c::HANDLE, buf: &mut [u16]) -> io::Result<usize> {
    // Configure the `pInputControl` parameter to not only return on `\r\n` but also Ctrl-Z, the
    // traditional DOS method to indicate end of character stream / user input (SUB).
    // See #38274 and https://stackoverflow.com/questions/43836040/win-api-readconsole.
    const CTRL_Z: u16 = 0x1A;
    const CTRL_Z_MASK: c::ULONG = 1 << CTRL_Z;
    let mut input_control = c::CONSOLE_READCONSOLE_CONTROL {
        nLength: crate::mem::size_of::<c::CONSOLE_READCONSOLE_CONTROL>() as c::ULONG,
        nInitialChars: 0,
        dwCtrlWakeupMask: CTRL_Z_MASK,
        dwControlKeyState: 0,
    };

    let mut amount = 0;
    cvt(unsafe {
        c::ReadConsoleW(
            handle,
            buf.as_mut_ptr() as c::LPVOID,
            buf.len() as u32,
            &mut amount,
            &mut input_control as c::PCONSOLE_READCONSOLE_CONTROL,
        )
    })?;

    if amount > 0 && buf[amount as usize - 1] == CTRL_Z {
        amount -= 1;
    }
    Ok(amount as usize)
}

#[allow(unused)]
fn utf16_to_utf8(utf16: &[u16], utf8: &mut [u8]) -> io::Result<usize> {
    let mut written = 0;
    for chr in decode_utf16(utf16.iter().cloned()) {
        match chr {
            Ok(chr) => {
                chr.encode_utf8(&mut utf8[written..]);
                written += chr.len_utf8();
            }
            Err(_) => {
                // We can't really do any better than forget all data and return an error.
                return Err(io::Error::new_const(
                    io::ErrorKind::InvalidData,
                    &"Windows stdin in console mode does not support non-UTF-16 input; \
                     encountered unpaired surrogate",
                ));
            }
        }
    }
    Ok(written)
}

impl IncompleteUtf8 {
    pub const fn new() -> IncompleteUtf8 {
        IncompleteUtf8 { bytes: [0; 4], len: 0 }
    }
}

impl Stdout {
    pub const fn new() -> Stdout {
        Stdout { incomplete_utf8: IncompleteUtf8::new() }
    }
}

impl io::Write for Stdout {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        write(c::STD_OUTPUT_HANDLE, buf, &mut self.incomplete_utf8)
    }

    fn flush(&mut self) -> io::Result<()> {
        Ok(())
    }
}

impl Stderr {
    pub const fn new() -> Stderr {
        Stderr { incomplete_utf8: IncompleteUtf8::new() }
    }
}

impl io::Write for Stderr {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        write(c::STD_ERROR_HANDLE, buf, &mut self.incomplete_utf8)
    }

    fn flush(&mut self) -> io::Result<()> {
        Ok(())
    }
}

pub fn is_ebadf(err: &io::Error) -> bool {
    err.raw_os_error() == Some(c::ERROR_INVALID_HANDLE as i32)
}

pub fn panic_output() -> Option<impl io::Write> {
    Some(Stderr::new())
}
<|endoftext|>


<commit_before>extern mod extra;
use std::vec::from_elem;
use grid::{Row, Column, alive, dead, Cell, Grid};
mod grid;

/****************************************************************************
 * Something to say Ben??
 ****************************************************************************/

/*
 * Constructs an immutable grid from the contents of an array of strings.
 * The grid is declared mutable, and mutated only inside this fn.
*/
pub fn build_from_file_contents(file_contents: ~[~str]) -> Grid
{
  let height = file_contents.len();
  assert!(height > 0u);
  let width = file_contents[0].len();
  let cells = from_elem(width, Cell { value: alive } );

  let mut result = Grid {
      inner: from_elem(height, cells.clone())
  };
  for row in range(0, height) {
    for column in range(0, width) {
      let file_value: char = file_contents[row][column] as char;
      let cell_value = match file_value {
        'o' => alive,
        '.' => dead,
         _  => fail!("Unexpected cell value found in file.")
      };
      result.inner[row][column] = Cell { value: cell_value };
   }
  }
  return result;
} // fn build_from_file_contents

/*
 Returns a count for how many neighbors of a cell in the grid
 are alive.
 Starts to the cell to the left of the cell/row and sums up cell_alive
 working in clockwise order.
*/
fn count_neighbors(Row(row): Row, Column(col): Column, grid: &Grid) -> uint {
  let left_column  = Column(col - 1);
  let right_column = Column(col + 1);
  let above_row    = Row(row - 1);
  let below_row    = Row(row + 1);

  return grid.cell_alive(Row(row), left_column) + // left
      grid.cell_alive(above_row, left_column)   + // left-above
      grid.cell_alive(above_row, Column(col))   + // above
      grid.cell_alive(above_row, right_column)  + // above-right
      grid.cell_alive(Row(row), right_column)   + // right
      grid.cell_alive(below_row, right_column)  + // below-right
      grid.cell_alive(below_row, Column(col))   + // below
      grid.cell_alive(below_row, left_column);    // below-left
}  // fn count_neighbors

/*pub fn print_neighbor_count(grid: &Grid) {
  let x = grid.inner.len();
  for row in range(0, x) {
    for column in range(0, x) {
      let r = Row(row);
      let c = Column(column);
      let n = count_neighbors(r, c, grid);
      print!("{:u}", n);
    }
    println!("");
  }
}  // fn print_neighbor_count
*/

// 1)Any live cell with fewer than two live neighbours dies, as if caused by
// under-population.
// 2) Any live cell with two or three live neighbours lives on to the next
// generation.
// 3) Any live cell with more than three live neighbours dies, as if by
// overcrowding.
// 4) Any dead cell with exactly three live neighbours becomes a live cell, as
// if by reproduction.
pub fn build_from_grid(prevg: &Grid) -> Grid
{
  let cell_value = |row: uint, column: uint| {
    let ncount = count_neighbors(Row(row), Column(column), prevg);
    let cv = match (prevg.inner[row][column].value, ncount) {
      (dead, 3)       => alive,
      (alive, 2..3)   => alive,
      _               => dead
    };
    return Cell { value: cv };
  };
  let mut result = prevg.clone();
  for row in range(0, prevg.height()) {
    for column in range(0, prevg.width()) {
      result.inner[row][column] = cell_value(row, column);
    }
  }
  return result;
}  // fn build_from_grid
<commit_msg>Refactored { braces.<commit_after>extern mod extra;
use std::vec::from_elem;
use grid::{Row, Column, alive, dead, Cell, Grid};
mod grid;

/****************************************************************************
 * Something to say Ben??
 ****************************************************************************/

/*
 * Constructs an immutable grid from the contents of an array of strings.
 * The grid is declared mutable, and mutated only inside this fn.
*/
pub fn build_from_file_contents(file_contents: ~[~str]) -> Grid {
  let height = file_contents.len();
  assert!(height > 0u);
  let width = file_contents[0].len();
  let cells = from_elem(width, Cell { value: alive } );

  let mut result = Grid {
      inner: from_elem(height, cells.clone())
  };
  for row in range(0, height) {
    for column in range(0, width) {
      let file_value: char = file_contents[row][column] as char;
      let cell_value = match file_value {
        'o' => alive,
        '.' => dead,
         _  => fail!("Unexpected cell value found in file.")
      };
      result.inner[row][column] = Cell { value: cell_value };
   }
  }
  return result;
} // fn build_from_file_contents

/*
 Returns a count for how many neighbors of a cell in the grid
 are alive.
 Starts to the cell to the left of the cell/row and sums up cell_alive
 working in clockwise order.
*/
fn count_neighbors(Row(row): Row, Column(col): Column, grid: &Grid) -> uint {
  let left_column  = Column(col - 1);
  let right_column = Column(col + 1);
  let above_row    = Row(row - 1);
  let below_row    = Row(row + 1);

  return grid.cell_alive(Row(row), left_column) + // left
      grid.cell_alive(above_row, left_column)   + // left-above
      grid.cell_alive(above_row, Column(col))   + // above
      grid.cell_alive(above_row, right_column)  + // above-right
      grid.cell_alive(Row(row), right_column)   + // right
      grid.cell_alive(below_row, right_column)  + // below-right
      grid.cell_alive(below_row, Column(col))   + // below
      grid.cell_alive(below_row, left_column);    // below-left
}  // fn count_neighbors

/*pub fn print_neighbor_count(grid: &Grid) {
  let x = grid.inner.len();
  for row in range(0, x) {
    for column in range(0, x) {
      let r = Row(row);
      let c = Column(column);
      let n = count_neighbors(r, c, grid);
      print!("{:u}", n);
    }
    println!("");
  }
}  // fn print_neighbor_count
*/

// 1)Any live cell with fewer than two live neighbours dies, as if caused by
// under-population.
// 2) Any live cell with two or three live neighbours lives on to the next
// generation.
// 3) Any live cell with more than three live neighbours dies, as if by
// overcrowding.
// 4) Any dead cell with exactly three live neighbours becomes a live cell, as
// if by reproduction.
pub fn build_from_grid(prevg: &Grid) -> Grid {
  let cell_value = |row: uint, column: uint| {
    let ncount = count_neighbors(Row(row), Column(column), prevg);
    let cv = match (prevg.inner[row][column].value, ncount) {
      (dead, 3)       => alive,
      (alive, 2..3)   => alive,
      _               => dead
    };
    return Cell { value: cv };
  };
  let mut result = prevg.clone();
  for row in range(0, prevg.height()) {
    for column in range(0, prevg.width()) {
      result.inner[row][column] = cell_value(row, column);
    }
  }
  return result;
}  // fn build_from_grid
<|endoftext|>