<commit_before>
use crate::parse::*;
use crate::util::*;
use std::collections::HashMap;
use std::mem;
use std::sync::Mutex;

lazy_static! {
    static ref STR_LABEL: Mutex<i32> = Mutex::new(0);
    static ref GLOBALS: Mutex<Vec<Var>> = Mutex::new(Vec::new());
    static ref STACKSIZE: Mutex<i32> = Mutex::new(0);
}

#[derive(Clone, Debug)]
struct Env<'a> {
    vars: HashMap<String, Var>,
    next: Option<Box<&'a Env<'a>>>,
}

fn new_env<'a>(next: Option<&'a Env>) -> Env<'a> {
    Env {
        vars: HashMap::new(),
        next: if let Some(e) = next {
            Some(Box::new(e))
        } else {
            None
        },
    }
}

impl<'a> Env<'a> {
    fn find(&self, name: & String) -> Option<&Var> {
        if let Some(v) = self.vars.get(name) {
            return Some(v);
        } else if let Some(ref next) = self.next {
            return next.find(name);
        } else {
            return None;
        }
    }
}

#[derive(Clone, Debug, PartialEq)]
pub struct Var {
    pub ty: Type,
    pub is_local: bool,

    // local
    pub offset: i32,

    // global
    pub name: String,
    pub data: String,
    pub len: usize,
}

fn alloc_var(ty: Type) -> Var {
    Var {
        ty: ty,
        is_local: true,
        offset: 0,
        name: String::new(),
        data: String::new(),
        len: 0,
    }
}

fn init_globals() {
    *GLOBALS.lock().unwrap() = Vec::new();
}

fn globals() -> Vec<Var> {
    GLOBALS.lock().unwrap().clone()
}

fn globals_push(var: Var) {
    let mut globals = GLOBALS.lock().unwrap();
    globals.push(var);
}

fn stacksize() -> i32 {
    *STACKSIZE.lock().unwrap()
}

fn init_stacksize() {
    let mut stacksize = STACKSIZE.lock().unwrap();
    *stacksize = 0;
}

fn add_stacksize(i: i32) {
    let mut stacksize = STACKSIZE.lock().unwrap();
    *stacksize += i;
}

fn bump_str_label() -> i32 {
    let mut str_label = STR_LABEL.lock().unwrap();
    let ret = *str_label;
    *str_label += 1;
    return ret;
}

fn swap(p: &mut Node, q: &mut Node) {
    mem::swap(p, q);
}

fn addr_of(base: Node, ty: Type) -> Node {
    let mut node = alloc_node();
    node.op = NodeType::ADDR;
    node.ty = ptr_of(ty);

    node.expr = Some(Box::new(base));
    return node;
}

fn walk<'a>(env: &'a mut Env, node: &'a mut Node, decay: bool) -> &'a Node {
    match node.op {
        NodeType::NUM => {
            return node;
        }
        NodeType::STR => {
            let name = format!(".L.str{}", bump_str_label());
            let tmp = node.clone();
            let node_ty = tmp.ty;
            let node_str = tmp.str_cnt;

            let mut var = alloc_var(node.clone().ty);
            var.is_local = false;
            var.name = String::from(name.clone());
            var.len = node_str.len() + 1;
            var.data = node_str;
            globals_push(var.clone());

            *node = alloc_node();
            node.op = NodeType::GVAR;
            node.ty = node_ty;
            node.name = name;
            return walk(env, node, decay);
        }
        NodeType::IDENT => {
            match env.find(&node.name) {
                None => {
                    panic!("undefined variable: {}", node.name);
                }
                Some(var) => {
                    node.op = NodeType::LVAR;
                    node.offset = var.offset;

                    if decay && var.ty.ty == CType::ARY {
                        *node = addr_of(node.clone(), *var.clone().ty.ary_of.unwrap());
                        return node;
                    }
                    node.ty = var.clone().ty;
                    return node;
                }
            }
        }
        NodeType::GVAR => {
            if decay && node.ty.ty == CType::ARY {
                *node = addr_of(node.clone(), *node.clone().ty.ary_of.unwrap());
            }
            return node;
        }
        NodeType::VARDEF => {
            add_stacksize(size_of(node.clone().ty));
            node.offset = stacksize();

            let var = Var {
                ty: node.ty.clone(),
                is_local: true,
                offset: stacksize(),
                name: String::new(),
                data: String::new(),
                len: 0,
            };
            env.vars.insert(node.name.clone(), var.clone());

            match node.init {
                Some(_) => {
                    node.init = Some(Box::new(walk(env, &mut *node.clone().init.unwrap(), true).clone()));
                }
                None => { }
            }
            return node;
        }
        NodeType::IF => {
            node.cond = Some(Box::new(walk(env, &mut *node.clone().cond.unwrap(), true).clone()));
            node.then = Some(Box::new(walk(env, &mut *node.clone().then.unwrap(), true).clone()));

            if node.els.is_some() {
                node.els = Some(Box::new(walk(env, &mut *node.clone().els.unwrap(), true).clone()));
            }
            return node;
        }
        NodeType::FOR => {
            node.init = Some(Box::new(walk(env, &mut *node.clone().init.unwrap(), true).clone()));
            node.cond = Some(Box::new(walk(env, &mut *node.clone().cond.unwrap(), true).clone()));
            node.inc = Some(Box::new(walk(env, &mut *node.clone().inc.unwrap(), true).clone()));
            node.body = Some(Box::new(walk(env, &mut *node.clone().body.unwrap(), true).clone()));
            return node;
        }
        NodeType::ADD | NodeType::SUB => {
            node.lhs = Some(Box::new(walk(env, &mut *node.clone().lhs.unwrap(), true).clone()));
            node.rhs = Some(Box::new(walk(env, &mut *node.clone().rhs.unwrap(), true).clone()));

            match (&mut node.lhs, &mut node.rhs) {
                (Some(ref mut lhs), Some(ref mut rhs)) => {
                    if rhs.ty.ty == CType::PTR {
                        swap(lhs, rhs);
                    }
                }
                _ => {}
            }
            match node.rhs {
                Some(ref rhs) => {
                    if rhs.ty.ty == CType::PTR {
                        panic!("'pointer {:?} pointer' is not defined", node.op);
                    }
                }
                None => {
                }
            }

            match node.lhs {
                Some(ref lhs) => {
                    node.ty = lhs.ty.clone();
                }
                None => { }
            }

            return node;
        }
        NodeType::EQ => {
            node.lhs = Some(Box::new(walk(env, &mut *node.clone().lhs.unwrap(), false).clone()));
            if node.clone().lhs.unwrap().op != NodeType::LVAR && node.clone().lhs.unwrap().op != NodeType::DEREF {
                panic!("not an lvalue: {:?} ({})", node.op, node.name);
            }

            node.rhs = Some(Box::new(walk(env, &mut *node.clone().rhs.unwrap(), true).clone()));
            node.ty = node.clone().lhs.unwrap().ty;
            return node;
        }
        NodeType::MUL |
            NodeType::DIV |
            NodeType::LT |
            NodeType::LOGAND |
            NodeType::LOGOR => {
                node.lhs = Some(Box::new(walk(env, &mut *node.clone().lhs.unwrap(), true).clone()));
                node.rhs = Some(Box::new(walk(env, &mut *node.clone().rhs.unwrap(), true).clone()));

                match node.lhs {
                    Some(ref lhs) => {
                        node.ty = lhs.ty.clone();
                    }
                    None => { }
                }
                return node;
            }
        NodeType::ADDR => {
            node.expr = Some(Box::new(walk(env, &mut *node.clone().expr.unwrap(), true).clone()));
            node.ty = ptr_of(node.clone().expr.unwrap().ty);
            return node;
        }
        NodeType::DEREF => {
            node.expr = Some(Box::new(walk(env, &mut *node.clone().expr.unwrap(), true).clone()));
            match &mut node.expr {
                Some(ref expr) => {
                    if expr.ty.ty != CType::PTR {
                        panic!("operand must be a pointer");
                    }
                }
                None => {}
            }

            node.ty = *node.clone().expr.unwrap().ty.ptr_of.unwrap();
            return node;
        }
        NodeType::RETURN => {
            node.expr = Some(Box::new(walk(env, &mut *node.clone().expr.unwrap(), true).clone()));
            return node;
        }
        NodeType::SIZEOF => {
            let mut nexpr = *node.clone().expr.unwrap();
            let expr = walk(env, &mut nexpr, false);
            let val = size_of(expr.clone().ty);

            *node = alloc_node();
            node.op = NodeType::NUM;
            node.ty = int_ty();
            node.val = val;
            return node;
        }
        NodeType::CALL => {
            for i in 0..node.args.len() {
                node.args[i] = walk(env, &mut node.args[i], true).clone();
            }
            node.ty = int_ty();
            return node;
        }
        NodeType::FUNC => {
            for i in 0..node.args.len() {
                node.args[i] = walk(env, &mut node.args[i], true).clone();
            }
            node.body = Some(Box::new(walk(env, &mut *node.clone().body.unwrap(), true).clone()));
            return node;
        }
        NodeType::COMP_STMT => {
            let mut newenv = new_env(Some(env));
            for i in 0..node.stmts.len() {
                node.stmts[i] = walk(&mut newenv, &mut node.stmts[i], true).clone();
            }
            return node;
        }
        NodeType::EXPR_STMT => {
            node.expr = Some(Box::new(walk(env, &mut *node.clone().expr.unwrap(), true).clone()));
            return node;
        }
        _ => {
            panic!("unknown node type");
        }
    }
}

pub fn sema(nodes: &mut Vec<Node>) {
    for node in nodes.iter_mut() {
        assert!(node.op == NodeType::FUNC);

        init_stacksize();
        init_globals();
        let mut env = new_env(None);
        walk(&mut env, node, true);
        node.stacksize = stacksize();
        node.globals = globals();
    }
}
<commit_msg>Simplify.<commit_after>
use crate::parse::*;
use crate::util::*;
use std::collections::HashMap;
use std::mem;
use std::sync::Mutex;

lazy_static! {
    static ref STR_LABEL: Mutex<i32> = Mutex::new(0);
    static ref GLOBALS: Mutex<Vec<Var>> = Mutex::new(Vec::new());
    static ref STACKSIZE: Mutex<i32> = Mutex::new(0);
}

#[derive(Clone, Debug)]
struct Env<'a> {
    vars: HashMap<String, Var>,
    next: Option<Box<&'a Env<'a>>>,
}

fn new_env<'a>(next: Option<&'a Env>) -> Env<'a> {
    Env {
        vars: HashMap::new(),
        next: if let Some(e) = next {
            Some(Box::new(e))
        } else {
            None
        },
    }
}

impl<'a> Env<'a> {
    fn find(&self, name: & String) -> Option<&Var> {
        if let Some(v) = self.vars.get(name) {
            return Some(v);
        } else if let Some(ref next) = self.next {
            return next.find(name);
        } else {
            return None;
        }
    }
}

#[derive(Clone, Debug, PartialEq)]
pub struct Var {
    pub ty: Type,
    pub is_local: bool,

    // local
    pub offset: i32,

    // global
    pub name: String,
    pub data: String,
    pub len: usize,
}

fn alloc_var(ty: Type) -> Var {
    Var {
        ty: ty,
        is_local: true,
        offset: 0,
        name: String::new(),
        data: String::new(),
        len: 0,
    }
}

fn init_globals() {
    *GLOBALS.lock().unwrap() = Vec::new();
}

fn globals() -> Vec<Var> {
    GLOBALS.lock().unwrap().clone()
}

fn globals_push(var: Var) {
    let mut globals = GLOBALS.lock().unwrap();
    globals.push(var);
}

fn stacksize() -> i32 {
    *STACKSIZE.lock().unwrap()
}

fn init_stacksize() {
    let mut stacksize = STACKSIZE.lock().unwrap();
    *stacksize = 0;
}

fn add_stacksize(i: i32) {
    let mut stacksize = STACKSIZE.lock().unwrap();
    *stacksize += i;
}

fn bump_str_label() -> i32 {
    let mut str_label = STR_LABEL.lock().unwrap();
    let ret = *str_label;
    *str_label += 1;
    return ret;
}

fn swap(p: &mut Node, q: &mut Node) {
    mem::swap(p, q);
}

fn maybe_decay(base: & mut Node, decay: bool) -> & mut Node {
    if !decay || base.ty.ty != CType::ARY {
        return base;
    }

    let tmp = base.clone();
    *base = alloc_node();
    base.op = NodeType::ADDR;
    base.ty = ptr_of(*tmp.clone().ty.ary_of.unwrap());

    base.expr = Some(Box::new(tmp));
    return base;
}

fn walk<'a>(env: &'a mut Env, node: &'a mut Node, decay: bool) -> &'a Node {
    match node.op {
        NodeType::NUM => {
            return node;
        }
        NodeType::STR => {
            let name = format!(".L.str{}", bump_str_label());
            let tmp = node.clone();
            let node_ty = tmp.ty;
            let node_str = tmp.str_cnt;

            let mut var = alloc_var(node.clone().ty);
            var.is_local = false;
            var.name = String::from(name.clone());
            var.len = node_str.len() + 1;
            var.data = node_str;
            globals_push(var.clone());

            *node = alloc_node();
            node.op = NodeType::GVAR;
            node.ty = node_ty;
            node.name = name;
            return maybe_decay(node, decay);
        }
        NodeType::IDENT => {
            let var = match env.find(&node.name) {
                None => panic!("undefined variable: {}", node.name),
                Some(var) => var,
            };

            *node = alloc_node();
            node.op = NodeType::LVAR;
            node.offset = var.offset;
            node.ty = var.ty.clone();
            return maybe_decay(node, decay);
        }
        NodeType::VARDEF => {
            add_stacksize(size_of(node.clone().ty));
            node.offset = stacksize();

            let var = Var {
                ty: node.ty.clone(),
                is_local: true,
                offset: stacksize(),
                name: String::new(),
                data: String::new(),
                len: 0,
            };
            env.vars.insert(node.name.clone(), var.clone());

            match node.init {
                Some(_) => {
                    node.init = Some(Box::new(walk(env, &mut *node.clone().init.unwrap(), true).clone()));
                }
                None => { }
            }
            return node;
        }
        NodeType::IF => {
            node.cond = Some(Box::new(walk(env, &mut *node.clone().cond.unwrap(), true).clone()));
            node.then = Some(Box::new(walk(env, &mut *node.clone().then.unwrap(), true).clone()));

            if node.els.is_some() {
                node.els = Some(Box::new(walk(env, &mut *node.clone().els.unwrap(), true).clone()));
            }
            return node;
        }
        NodeType::FOR => {
            node.init = Some(Box::new(walk(env, &mut *node.clone().init.unwrap(), true).clone()));
            node.cond = Some(Box::new(walk(env, &mut *node.clone().cond.unwrap(), true).clone()));
            node.inc = Some(Box::new(walk(env, &mut *node.clone().inc.unwrap(), true).clone()));
            node.body = Some(Box::new(walk(env, &mut *node.clone().body.unwrap(), true).clone()));
            return node;
        }
        NodeType::ADD | NodeType::SUB => {
            node.lhs = Some(Box::new(walk(env, &mut *node.clone().lhs.unwrap(), true).clone()));
            node.rhs = Some(Box::new(walk(env, &mut *node.clone().rhs.unwrap(), true).clone()));

            match (&mut node.lhs, &mut node.rhs) {
                (Some(ref mut lhs), Some(ref mut rhs)) => {
                    if rhs.ty.ty == CType::PTR {
                        swap(lhs, rhs);
                    }
                }
                _ => {}
            }
            match node.rhs {
                Some(ref rhs) => {
                    if rhs.ty.ty == CType::PTR {
                        panic!("'pointer {:?} pointer' is not defined", node.op);
                    }
                }
                None => {
                }
            }

            match node.lhs {
                Some(ref lhs) => {
                    node.ty = lhs.ty.clone();
                }
                None => { }
            }

            return node;
        }
        NodeType::EQ => {
            node.lhs = Some(Box::new(walk(env, &mut *node.clone().lhs.unwrap(), false).clone()));
            if node.clone().lhs.unwrap().op != NodeType::LVAR && node.clone().lhs.unwrap().op != NodeType::DEREF {
                panic!("not an lvalue: {:?} ({})", node.op, node.name);
            }

            node.rhs = Some(Box::new(walk(env, &mut *node.clone().rhs.unwrap(), true).clone()));
            node.ty = node.clone().lhs.unwrap().ty;
            return node;
        }
        NodeType::MUL |
            NodeType::DIV |
            NodeType::LT |
            NodeType::LOGAND |
            NodeType::LOGOR => {
                node.lhs = Some(Box::new(walk(env, &mut *node.clone().lhs.unwrap(), true).clone()));
                node.rhs = Some(Box::new(walk(env, &mut *node.clone().rhs.unwrap(), true).clone()));

                match node.lhs {
                    Some(ref lhs) => {
                        node.ty = lhs.ty.clone();
                    }
                    None => { }
                }
                return node;
            }
        NodeType::ADDR => {
            node.expr = Some(Box::new(walk(env, &mut *node.clone().expr.unwrap(), true).clone()));
            node.ty = ptr_of(node.clone().expr.unwrap().ty);
            return node;
        }
        NodeType::DEREF => {
            node.expr = Some(Box::new(walk(env, &mut *node.clone().expr.unwrap(), true).clone()));
            match &mut node.expr {
                Some(ref expr) => {
                    if expr.ty.ty != CType::PTR {
                        panic!("operand must be a pointer: {:?}", expr);
                    }
                }
                None => {}
            }

            node.ty = *node.clone().expr.unwrap().ty.ptr_of.unwrap();
            return node;
        }
        NodeType::RETURN => {
            node.expr = Some(Box::new(walk(env, &mut *node.clone().expr.unwrap(), true).clone()));
            return node;
        }
        NodeType::SIZEOF => {
            let mut nexpr = *node.clone().expr.unwrap();
            let expr = walk(env, &mut nexpr, false);
            let val = size_of(expr.clone().ty);

            *node = alloc_node();
            node.op = NodeType::NUM;
            node.ty = int_ty();
            node.val = val;
            return node;
        }
        NodeType::CALL => {
            for i in 0..node.args.len() {
                node.args[i] = walk(env, &mut node.args[i], true).clone();
            }
            node.ty = int_ty();
            return node;
        }
        NodeType::FUNC => {
            for i in 0..node.args.len() {
                node.args[i] = walk(env, &mut node.args[i], true).clone();
            }
            node.body = Some(Box::new(walk(env, &mut *node.clone().body.unwrap(), true).clone()));
            return node;
        }
        NodeType::COMP_STMT => {
            let mut newenv = new_env(Some(env));
            for i in 0..node.stmts.len() {
                node.stmts[i] = walk(&mut newenv, &mut node.stmts[i], true).clone();
            }
            return node;
        }
        NodeType::EXPR_STMT => {
            node.expr = Some(Box::new(walk(env, &mut *node.clone().expr.unwrap(), true).clone()));
            return node;
        }
        _ => {
            panic!("unknown node type");
        }
    }
}

pub fn sema(nodes: &mut Vec<Node>) {
    for node in nodes.iter_mut() {
        assert!(node.op == NodeType::FUNC);

        init_stacksize();
        init_globals();
        let mut env = new_env(None);
        walk(&mut env, node, true);
        node.stacksize = stacksize();
        node.globals = globals();
    }
}
<|endoftext|>


<commit_before>// Copyright 2015 Birunthan Mohanathas
//
// Licensed under the MIT license <http://opensource.org/licenses/MIT>. This
// file may not be copied, modified, or distributed except according to those
// terms.

use measure::Measureable;

pub struct Skin<'a> {
    name: String,
    measures: Vec<Box<Measureable<'a> + 'a>>,
}

impl<'a> Skin<'a> {
    pub fn new(name: &str) -> Skin {
        Skin {
            name: name.to_string(),
            measures: Vec::new(),
        }
    }

    pub fn name(&self) -> &str {
        self.name.as_slice()
    }
}

#[test]
fn test_name() {
    let skin = Skin::new("skin");
    assert_eq!("skin", skin.name());
}
<commit_msg>Allow measures to be added to a Skin<commit_after>// Copyright 2015 Birunthan Mohanathas
//
// Licensed under the MIT license <http://opensource.org/licenses/MIT>. This
// file may not be copied, modified, or distributed except according to those
// terms.

use measure::Measureable;

pub struct Skin<'a> {
    name: String,
    measures: Vec<Box<Measureable<'a> + 'a>>,
}

impl<'a> Skin<'a> {
    pub fn new(name: &str) -> Skin {
        Skin {
            name: name.to_string(),
            measures: Vec::new(),
        }
    }

    pub fn name(&self) -> &str {
        self.name.as_slice()
    }

    pub fn add_measure(&mut self, measure: Box<Measureable<'a> + 'a>) {
        self.measures.push(measure);
    }

    pub fn measures(&self) -> &Vec<Box<Measureable<'a> + 'a>> {
        &self.measures
    }
}

#[test]
fn test_name() {
    let skin = Skin::new("skin");
    assert_eq!("skin", skin.name());
}

#[test]
fn test_add_measure() {
    use time_measure::TimeMeasure;

    let mut skin = Skin::new("skin");
    skin.add_measure(box TimeMeasure::new("foo"));
    assert_eq!(1, skin.measures().len());
}
<|endoftext|>


<commit_before>//! The module defines song structs and methods.

use time::{strptime, Duration, Tm};
use rustc_serialize::{Encodable, Encoder, Decodable, Decoder};

use std::collections::BTreeMap;
use std::str::FromStr;
use std::fmt;

use error::{Error, ParseError};
use convert::FromIter;

/// Song ID
#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Default)]
pub struct Id(pub u32);

impl Encodable for Id {
    fn encode<S: Encoder>(&self, e: &mut S) -> Result<(), S::Error> {
        self.0.encode(e)
    }
}

impl Decodable for Id {
    fn decode<S: Decoder>(d: &mut S) -> Result<Id, S::Error> {
        d.read_u32().map(Id)
    }
}

impl fmt::Display for Id {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.0.fmt(f)
    }
}

/// Song place in the queue
#[derive(Debug, Copy, Clone, PartialEq, Default, RustcEncodable)]
pub struct QueuePlace {
    /// song ID
    pub id: Id,
    /// absolute zero-based song position
    pub pos: u32,
    /// song priority, if present, defaults to 0
    pub prio: u8
}

/// Song range
#[derive(Debug, Copy, Clone, PartialEq)]
pub struct Range(pub Duration, pub Option<Duration>);

impl Encodable for Range {
    fn encode<S: Encoder>(&self, e: &mut S) -> Result<(), S::Error> {
        e.emit_tuple(2, |e|
            e.emit_tuple_arg(0, |e| e.emit_i64(self.0.num_seconds())).and_then(|_|
            e.emit_tuple_arg(1, |e| e.emit_option(|e| self.1.map(|d| e.emit_option_some(|e| d.num_seconds().encode(e))).unwrap_or_else(|| e.emit_option_none())))))
    }
}

impl Default for Range {
    fn default() -> Range {
        Range(Duration::seconds(0), None)
    }
}

impl fmt::Display for Range {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.0.num_seconds().fmt(f)
            .and_then(|_| f.write_str(":"))
            .and_then(|_| self.1.map(|v| v.num_seconds().fmt(f)).unwrap_or(Ok(())))
    }
}

impl FromStr for Range {
    type Err = ParseError;
    fn from_str(s: &str) -> Result<Range, ParseError> {
        let mut splits = s.split('-').flat_map(|v| v.parse().into_iter());
        match (splits.next(), splits.next()) {
            (Some(s), Some(e)) => Ok(Range(Duration::seconds(s), Some(Duration::seconds(e)))),
            (None, Some(e)) => Ok(Range(Duration::zero(), Some(Duration::seconds(e)))),
            (Some(s), None) => Ok(Range(Duration::seconds(s), None)),
            (None, None) => Ok(Range(Duration::zero(), None)),
        }
    }
}

/// Song data
#[derive(Debug, Clone, PartialEq, Default)]
pub struct Song {
    /// filename
    pub file: String,
    /// name (for streams)
    pub name: Option<String>,
    /// last modification time
    pub last_mod: Option<Tm>,
    /// duration (in seconds resolution)
    pub duration: Option<Duration>,
    /// place in the queue (if queued for playback)
    pub place: Option<QueuePlace>,
    /// range to play (if queued for playback and range was set)
    pub range: Option<Range>,
    /// arbitrary tags, like album, artist etc
    pub tags: BTreeMap<String, String>,
}

impl Encodable for Song {
    fn encode<S: Encoder>(&self, e: &mut S) -> Result<(), S::Error> {
        e.emit_struct("Song", 7, |e|
            e.emit_struct_field("file", 0, |e| self.file.encode(e)).and_then(|_|
            e.emit_struct_field("name", 1, |e| self.name.encode(e))).and_then(|_|
            e.emit_struct_field("last_mod", 2, |e| e.emit_option(
                    |e| self.last_mod.as_ref().map(|m| e.emit_option_some(|e| m.to_timespec().sec.encode(e))).unwrap_or_else(|| e.emit_option_none())))).and_then(|_|
            e.emit_struct_field("duration", 3, |e| e.emit_option(
                    |e| self.duration.as_ref().map(|d| e.emit_option_some(|e| d.num_seconds().encode(e))).unwrap_or_else(|| e.emit_option_none())
                    ))).and_then(|_|
            e.emit_struct_field("place", 4, |e| self.place.encode(e))).and_then(|_|
            e.emit_struct_field("range", 5, |e| self.range.encode(e))).and_then(|_|
            e.emit_struct_field("tags", 6, |e| self.tags.encode(e))))
    }
}

impl FromIter for Song {
    /// build song from map
    fn from_iter<I: Iterator<Item=Result<(String, String), Error>>>(iter: I) -> Result<Song, Error> {
        let mut result = Song::default();

        for res in iter {
            let line = try!(res);
            match &*line.0 {
                "file" => result.file = line.1.to_owned(),
                "Last-Modified" => result.last_mod = try!(strptime(&*line.1, "%Y-%m-%dT%H:%M:%S%Z").map_err(ParseError::BadTime).map(Some)),
                "Name" => result.name = Some(line.1.to_owned()),
                "Time" => result.duration = Some(Duration::seconds(try!(line.1.parse()))),
                "Range" => result.range = Some(try!(line.1.parse())),
                "Id" => match result.place {
                    None => result.place = Some(QueuePlace { id: Id(try!(line.1.parse())), pos: 0, prio: 0 }),
                    Some(ref mut place) => place.id = Id(try!(line.1.parse())),
                },
                "Pos" => match result.place {
                    None => result.place = Some(QueuePlace { pos: try!(line.1.parse()), id: Id(0), prio: 0 }),
                    Some(ref mut place) => place.pos = try!(line.1.parse()),
                },
                "Prio" => match result.place {
                    None => result.place = Some(QueuePlace { prio: try!(line.1.parse()), id: Id(0), pos: 0 }),
                    Some(ref mut place) => place.prio = try!(line.1.parse()),
                },
                _ => { result.tags.insert(line.0, line.1); }
            }
        }

        Ok(result)
    }
}

<commit_msg>add title field to a song object<commit_after>//! The module defines song structs and methods.

use time::{strptime, Duration, Tm};
use rustc_serialize::{Encodable, Encoder, Decodable, Decoder};

use std::collections::BTreeMap;
use std::str::FromStr;
use std::fmt;

use error::{Error, ParseError};
use convert::FromIter;

/// Song ID
#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Default)]
pub struct Id(pub u32);

impl Encodable for Id {
    fn encode<S: Encoder>(&self, e: &mut S) -> Result<(), S::Error> {
        self.0.encode(e)
    }
}

impl Decodable for Id {
    fn decode<S: Decoder>(d: &mut S) -> Result<Id, S::Error> {
        d.read_u32().map(Id)
    }
}

impl fmt::Display for Id {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.0.fmt(f)
    }
}

/// Song place in the queue
#[derive(Debug, Copy, Clone, PartialEq, Default, RustcEncodable)]
pub struct QueuePlace {
    /// song ID
    pub id: Id,
    /// absolute zero-based song position
    pub pos: u32,
    /// song priority, if present, defaults to 0
    pub prio: u8
}

/// Song range
#[derive(Debug, Copy, Clone, PartialEq)]
pub struct Range(pub Duration, pub Option<Duration>);

impl Encodable for Range {
    fn encode<S: Encoder>(&self, e: &mut S) -> Result<(), S::Error> {
        e.emit_tuple(2, |e|
            e.emit_tuple_arg(0, |e| e.emit_i64(self.0.num_seconds())).and_then(|_|
            e.emit_tuple_arg(1, |e| e.emit_option(|e| self.1.map(|d| e.emit_option_some(|e| d.num_seconds().encode(e))).unwrap_or_else(|| e.emit_option_none())))))
    }
}

impl Default for Range {
    fn default() -> Range {
        Range(Duration::seconds(0), None)
    }
}

impl fmt::Display for Range {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.0.num_seconds().fmt(f)
            .and_then(|_| f.write_str(":"))
            .and_then(|_| self.1.map(|v| v.num_seconds().fmt(f)).unwrap_or(Ok(())))
    }
}

impl FromStr for Range {
    type Err = ParseError;
    fn from_str(s: &str) -> Result<Range, ParseError> {
        let mut splits = s.split('-').flat_map(|v| v.parse().into_iter());
        match (splits.next(), splits.next()) {
            (Some(s), Some(e)) => Ok(Range(Duration::seconds(s), Some(Duration::seconds(e)))),
            (None, Some(e)) => Ok(Range(Duration::zero(), Some(Duration::seconds(e)))),
            (Some(s), None) => Ok(Range(Duration::seconds(s), None)),
            (None, None) => Ok(Range(Duration::zero(), None)),
        }
    }
}

/// Song data
#[derive(Debug, Clone, PartialEq, Default)]
pub struct Song {
    /// filename
    pub file: String,
    /// name (for streams)
    pub name: Option<String>,
    /// title
    pub title: Option<String>,
    /// last modification time
    pub last_mod: Option<Tm>,
    /// duration (in seconds resolution)
    pub duration: Option<Duration>,
    /// place in the queue (if queued for playback)
    pub place: Option<QueuePlace>,
    /// range to play (if queued for playback and range was set)
    pub range: Option<Range>,
    /// arbitrary tags, like album, artist etc
    pub tags: BTreeMap<String, String>,
}

impl Encodable for Song {
    fn encode<S: Encoder>(&self, e: &mut S) -> Result<(), S::Error> {
        e.emit_struct("Song", 7, |e|
            e.emit_struct_field("file", 0, |e| self.file.encode(e)).and_then(|_|
            e.emit_struct_field("name", 1, |e| self.name.encode(e))).and_then(|_|
            e.emit_struct_field("last_mod", 2, |e| e.emit_option(
                    |e| self.last_mod.as_ref().map(|m| e.emit_option_some(|e| m.to_timespec().sec.encode(e))).unwrap_or_else(|| e.emit_option_none())))).and_then(|_|
            e.emit_struct_field("duration", 3, |e| e.emit_option(
                    |e| self.duration.as_ref().map(|d| e.emit_option_some(|e| d.num_seconds().encode(e))).unwrap_or_else(|| e.emit_option_none())
                    ))).and_then(|_|
            e.emit_struct_field("place", 4, |e| self.place.encode(e))).and_then(|_|
            e.emit_struct_field("range", 5, |e| self.range.encode(e))).and_then(|_|
            e.emit_struct_field("tags", 6, |e| self.tags.encode(e))))
    }
}

impl FromIter for Song {
    /// build song from map
    fn from_iter<I: Iterator<Item=Result<(String, String), Error>>>(iter: I) -> Result<Song, Error> {
        let mut result = Song::default();

        for res in iter {
            let line = try!(res);
            match &*line.0 {
                "file" => result.file = line.1.to_owned(),
                "Title" => result.title = Some(line.1.to_owned()),
                "Last-Modified" => result.last_mod = try!(strptime(&*line.1, "%Y-%m-%dT%H:%M:%S%Z").map_err(ParseError::BadTime).map(Some)),
                "Name" => result.name = Some(line.1.to_owned()),
                "Time" => result.duration = Some(Duration::seconds(try!(line.1.parse()))),
                "Range" => result.range = Some(try!(line.1.parse())),
                "Id" => match result.place {
                    None => result.place = Some(QueuePlace { id: Id(try!(line.1.parse())), pos: 0, prio: 0 }),
                    Some(ref mut place) => place.id = Id(try!(line.1.parse())),
                },
                "Pos" => match result.place {
                    None => result.place = Some(QueuePlace { pos: try!(line.1.parse()), id: Id(0), prio: 0 }),
                    Some(ref mut place) => place.pos = try!(line.1.parse()),
                },
                "Prio" => match result.place {
                    None => result.place = Some(QueuePlace { prio: try!(line.1.parse()), id: Id(0), pos: 0 }),
                    Some(ref mut place) => place.prio = try!(line.1.parse()),
                },
                _ => { result.tags.insert(line.0, line.1); }
            }
        }

        Ok(result)
    }
}

<|endoftext|>


<commit_before>use std::collections::{hash_map::Entry, HashMap, VecDeque};
use std::convert::TryFrom;
use std::num::NonZeroU32;
use std::ops::Not;

use rustc_index::vec::{Idx, IndexVec};

use crate::*;

/// We cannot use the `newtype_index!` macro because we have to use 0 as a
/// sentinel value meaning that the identifier is not assigned. This is because
/// the pthreads static initializers initialize memory with zeros (see the
/// `src/shims/sync.rs` file).
macro_rules! declare_id {
    ($name: ident) => {
        /// 0 is used to indicate that the id was not yet assigned and,
        /// therefore, is not a valid identifier.
        #[derive(Clone, Copy, Debug, PartialOrd, Ord, PartialEq, Eq, Hash)]
        pub struct $name(NonZeroU32);

        impl $name {
            // Panics if `id == 0`.
            pub fn from_u32(id: u32) -> Self {
                Self(NonZeroU32::new(id).unwrap())
            }
        }

        impl Idx for $name {
            fn new(idx: usize) -> Self {
                // We use 0 as a sentinel value (see the comment above) and,
                // therefore, need to shift by one when converting from an index
                // into a vector.
                let shifted_idx = u32::try_from(idx).unwrap().checked_add(1).unwrap();
                $name(NonZeroU32::new(shifted_idx).unwrap())
            }
            fn index(self) -> usize {
                // See the comment in `Self::new`.
                // (This cannot underflow because self is NonZeroU32.)
                usize::try_from(self.0.get() - 1).unwrap()
            }
        }

        impl $name {
            pub fn to_u32_scalar<'tcx>(&self) -> Scalar<Tag> {
                Scalar::from_u32(self.0.get())
            }
        }
    };
}

declare_id!(MutexId);

/// The mutex state.
#[derive(Default, Debug)]
struct Mutex {
    /// The thread that currently owns the lock.
    owner: Option<ThreadId>,
    /// How many times the mutex was locked by the owner.
    lock_count: usize,
    /// The queue of threads waiting for this mutex.
    queue: VecDeque<ThreadId>,
}

declare_id!(RwLockId);

/// The read-write lock state.
#[derive(Default, Debug)]
struct RwLock {
    /// The writer thread that currently owns the lock.
    writer: Option<ThreadId>,
    /// The readers that currently own the lock and how many times they acquired
    /// the lock.
    readers: HashMap<ThreadId, usize>,
    /// The queue of writer threads waiting for this lock.
    writer_queue: VecDeque<ThreadId>,
    /// The queue of reader threads waiting for this lock.
    reader_queue: VecDeque<ThreadId>,
}

declare_id!(CondvarId);

/// A thread waiting on a conditional variable.
#[derive(Debug)]
struct CondvarWaiter {
    /// The thread that is waiting on this variable.
    thread: ThreadId,
    /// The mutex on which the thread is waiting.
    mutex: MutexId,
}

/// The conditional variable state.
#[derive(Default, Debug)]
struct Condvar {
    waiters: VecDeque<CondvarWaiter>,
}

/// The state of all synchronization variables.
#[derive(Default, Debug)]
pub(super) struct SynchronizationState {
    mutexes: IndexVec<MutexId, Mutex>,
    rwlocks: IndexVec<RwLockId, RwLock>,
    condvars: IndexVec<CondvarId, Condvar>,
}

// Public interface to synchronization primitives. Please note that in most
// cases, the function calls are infallible and it is the client's (shim
// implementation's) responsibility to detect and deal with erroneous
// situations.
impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriEvalContext<'mir, 'tcx> {}
pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx> {
    #[inline]
    /// Create state for a new mutex.
    fn mutex_create(&mut self) -> MutexId {
        let this = self.eval_context_mut();
        this.machine.threads.sync.mutexes.push(Default::default())
    }

    #[inline]
    /// Get the id of the thread that currently owns this lock.
    fn mutex_get_owner(&mut self, id: MutexId) -> ThreadId {
        let this = self.eval_context_ref();
        this.machine.threads.sync.mutexes[id].owner.unwrap()
    }

    #[inline]
    /// Check if locked.
    fn mutex_is_locked(&mut self, id: MutexId) -> bool {
        let this = self.eval_context_mut();
        this.machine.threads.sync.mutexes[id].owner.is_some()
    }

    /// Lock by setting the mutex owner and increasing the lock count.
    fn mutex_lock(&mut self, id: MutexId, thread: ThreadId) {
        let this = self.eval_context_mut();
        let mutex = &mut this.machine.threads.sync.mutexes[id];
        if let Some(current_owner) = mutex.owner {
            assert_eq!(thread, current_owner, "mutex already locked by another thread");
            assert!(
                mutex.lock_count > 0,
                "invariant violation: lock_count == 0 iff the thread is unlocked"
            );
        } else {
            mutex.owner = Some(thread);
        }
        mutex.lock_count = mutex.lock_count.checked_add(1).unwrap();
    }

    /// Try unlocking by decreasing the lock count and returning the old owner
    /// and the old lock count. If the lock count reaches 0, release the lock
    /// and potentially give to a new owner. If the lock was not locked, return
    /// `None`.
    ///
    /// Note: It is the caller's responsibility to check that the thread that
    /// unlocked the lock actually is the same one, which owned it.
    fn mutex_unlock(
        &mut self,
        id: MutexId,
        expected_owner: ThreadId,
    ) -> InterpResult<'tcx, Option<usize>> {
        let this = self.eval_context_mut();
        let mutex = &mut this.machine.threads.sync.mutexes[id];
        if let Some(current_owner) = mutex.owner {
            // Mutex is locked.
            if current_owner != expected_owner {
                // Only the owner can unlock the mutex.
                return Ok(None);
            }
            let old_lock_count = mutex.lock_count;
            mutex.lock_count = old_lock_count
                .checked_sub(1)
                .expect("invariant violation: lock_count == 0 iff the thread is unlocked");
            if mutex.lock_count == 0 {
                mutex.owner = None;
                // The mutex is completely unlocked. Try transfering ownership
                // to another thread.
                if let Some(new_owner) = this.mutex_dequeue(id) {
                    this.mutex_lock(id, new_owner);
                    this.unblock_thread(new_owner)?;
                }
            }
            Ok(Some(old_lock_count))
        } else {
            // Mutex is unlocked.
            Ok(None)
        }
    }

    #[inline]
    /// Put the thread into the queue waiting for the lock.
    fn mutex_enqueue(&mut self, id: MutexId, thread: ThreadId) {
        let this = self.eval_context_mut();
        assert!(this.mutex_is_locked(id), "queing on unlocked mutex");
        this.machine.threads.sync.mutexes[id].queue.push_back(thread);
    }

    #[inline]
    /// Take a thread out of the queue waiting for the lock.
    fn mutex_dequeue(&mut self, id: MutexId) -> Option<ThreadId> {
        let this = self.eval_context_mut();
        this.machine.threads.sync.mutexes[id].queue.pop_front()
    }

    #[inline]
    /// Create state for a new read write lock.
    fn rwlock_create(&mut self) -> RwLockId {
        let this = self.eval_context_mut();
        this.machine.threads.sync.rwlocks.push(Default::default())
    }

    #[inline]
    /// Check if locked.
    fn rwlock_is_locked(&mut self, id: RwLockId) -> bool {
        let this = self.eval_context_mut();
        this.machine.threads.sync.rwlocks[id].writer.is_some()
            || this.machine.threads.sync.rwlocks[id].readers.is_empty().not()
    }

    #[inline]
    /// Check if write locked.
    fn rwlock_is_write_locked(&mut self, id: RwLockId) -> bool {
        let this = self.eval_context_mut();
        this.machine.threads.sync.rwlocks[id].writer.is_some()
    }

    /// Read-lock the lock by adding the `reader` the list of threads that own
    /// this lock.
    fn rwlock_reader_lock(&mut self, id: RwLockId, reader: ThreadId) {
        let this = self.eval_context_mut();
        assert!(!this.rwlock_is_write_locked(id), "the lock is write locked");
        let count = this.machine.threads.sync.rwlocks[id].readers.entry(reader).or_insert(0);
        *count = count.checked_add(1).expect("the reader counter overflowed");
    }

    /// Try read-unlock the lock for `reader`. Returns `true` if succeeded,
    /// `false` if this `reader` did not hold the lock.
    fn rwlock_reader_unlock(&mut self, id: RwLockId, reader: ThreadId) -> bool {
        let this = self.eval_context_mut();
        match this.machine.threads.sync.rwlocks[id].readers.entry(reader) {
            Entry::Occupied(mut entry) => {
                let count = entry.get_mut();
                *count -= 1;
                if *count == 0 {
                    entry.remove();
                }
                true
            }
            Entry::Vacant(_) => false,
        }
    }

    #[inline]
    /// Put the reader in the queue waiting for the lock and block it.
    fn rwlock_enqueue_and_block_reader(
        &mut self,
        id: RwLockId,
        reader: ThreadId,
    ) -> InterpResult<'tcx> {
        let this = self.eval_context_mut();
        assert!(this.rwlock_is_write_locked(id), "queueing on not write locked lock");
        this.machine.threads.sync.rwlocks[id].reader_queue.push_back(reader);
        this.block_thread(reader)
    }

    #[inline]
    /// Take a reader out the queue waiting for the lock.
    fn rwlock_dequeue_reader(&mut self, id: RwLockId) -> Option<ThreadId> {
        let this = self.eval_context_mut();
        this.machine.threads.sync.rwlocks[id].reader_queue.pop_front()
    }

    #[inline]
    /// Lock by setting the writer that owns the lock.
    fn rwlock_writer_lock(&mut self, id: RwLockId, writer: ThreadId) {
        let this = self.eval_context_mut();
        assert!(!this.rwlock_is_locked(id), "the lock is already locked");
        this.machine.threads.sync.rwlocks[id].writer = Some(writer);
    }

    #[inline]
    /// Try to unlock by removing the writer.
    fn rwlock_writer_unlock(&mut self, id: RwLockId) -> Option<ThreadId> {
        let this = self.eval_context_mut();
        this.machine.threads.sync.rwlocks[id].writer.take()
    }

    #[inline]
    /// Put the writer in the queue waiting for the lock.
    fn rwlock_enqueue_and_block_writer(
        &mut self,
        id: RwLockId,
        writer: ThreadId,
    ) -> InterpResult<'tcx> {
        let this = self.eval_context_mut();
        assert!(this.rwlock_is_locked(id), "queueing on unlocked lock");
        this.machine.threads.sync.rwlocks[id].writer_queue.push_back(writer);
        this.block_thread(writer)
    }

    #[inline]
    /// Take the writer out the queue waiting for the lock.
    fn rwlock_dequeue_writer(&mut self, id: RwLockId) -> Option<ThreadId> {
        let this = self.eval_context_mut();
        this.machine.threads.sync.rwlocks[id].writer_queue.pop_front()
    }

    #[inline]
    /// Create state for a new conditional variable.
    fn condvar_create(&mut self) -> CondvarId {
        let this = self.eval_context_mut();
        this.machine.threads.sync.condvars.push(Default::default())
    }

    #[inline]
    /// Is the conditional variable awaited?
    fn condvar_is_awaited(&mut self, id: CondvarId) -> bool {
        let this = self.eval_context_mut();
        !this.machine.threads.sync.condvars[id].waiters.is_empty()
    }

    /// Mark that the thread is waiting on the conditional variable.
    fn condvar_wait(&mut self, id: CondvarId, thread: ThreadId, mutex: MutexId) {
        let this = self.eval_context_mut();
        let waiters = &mut this.machine.threads.sync.condvars[id].waiters;
        assert!(waiters.iter().all(|waiter| waiter.thread != thread), "thread is already waiting");
        waiters.push_back(CondvarWaiter { thread, mutex });
    }

    /// Wake up some thread (if there is any) sleeping on the conditional
    /// variable.
    fn condvar_signal(&mut self, id: CondvarId) -> Option<(ThreadId, MutexId)> {
        let this = self.eval_context_mut();
        this.machine.threads.sync.condvars[id]
            .waiters
            .pop_front()
            .map(|waiter| (waiter.thread, waiter.mutex))
    }

    #[inline]
    /// Remove the thread from the queue of threads waiting on this conditional variable.
    fn condvar_remove_waiter(&mut self, id: CondvarId, thread: ThreadId) {
        let this = self.eval_context_mut();
        this.machine.threads.sync.condvars[id].waiters.retain(|waiter| waiter.thread != thread);
    }
}
<commit_msg>add an assertion<commit_after>use std::collections::{hash_map::Entry, HashMap, VecDeque};
use std::convert::TryFrom;
use std::num::NonZeroU32;
use std::ops::Not;

use rustc_index::vec::{Idx, IndexVec};

use crate::*;

/// We cannot use the `newtype_index!` macro because we have to use 0 as a
/// sentinel value meaning that the identifier is not assigned. This is because
/// the pthreads static initializers initialize memory with zeros (see the
/// `src/shims/sync.rs` file).
macro_rules! declare_id {
    ($name: ident) => {
        /// 0 is used to indicate that the id was not yet assigned and,
        /// therefore, is not a valid identifier.
        #[derive(Clone, Copy, Debug, PartialOrd, Ord, PartialEq, Eq, Hash)]
        pub struct $name(NonZeroU32);

        impl $name {
            // Panics if `id == 0`.
            pub fn from_u32(id: u32) -> Self {
                Self(NonZeroU32::new(id).unwrap())
            }
        }

        impl Idx for $name {
            fn new(idx: usize) -> Self {
                // We use 0 as a sentinel value (see the comment above) and,
                // therefore, need to shift by one when converting from an index
                // into a vector.
                let shifted_idx = u32::try_from(idx).unwrap().checked_add(1).unwrap();
                $name(NonZeroU32::new(shifted_idx).unwrap())
            }
            fn index(self) -> usize {
                // See the comment in `Self::new`.
                // (This cannot underflow because self is NonZeroU32.)
                usize::try_from(self.0.get() - 1).unwrap()
            }
        }

        impl $name {
            pub fn to_u32_scalar<'tcx>(&self) -> Scalar<Tag> {
                Scalar::from_u32(self.0.get())
            }
        }
    };
}

declare_id!(MutexId);

/// The mutex state.
#[derive(Default, Debug)]
struct Mutex {
    /// The thread that currently owns the lock.
    owner: Option<ThreadId>,
    /// How many times the mutex was locked by the owner.
    lock_count: usize,
    /// The queue of threads waiting for this mutex.
    queue: VecDeque<ThreadId>,
}

declare_id!(RwLockId);

/// The read-write lock state.
#[derive(Default, Debug)]
struct RwLock {
    /// The writer thread that currently owns the lock.
    writer: Option<ThreadId>,
    /// The readers that currently own the lock and how many times they acquired
    /// the lock.
    readers: HashMap<ThreadId, usize>,
    /// The queue of writer threads waiting for this lock.
    writer_queue: VecDeque<ThreadId>,
    /// The queue of reader threads waiting for this lock.
    reader_queue: VecDeque<ThreadId>,
}

declare_id!(CondvarId);

/// A thread waiting on a conditional variable.
#[derive(Debug)]
struct CondvarWaiter {
    /// The thread that is waiting on this variable.
    thread: ThreadId,
    /// The mutex on which the thread is waiting.
    mutex: MutexId,
}

/// The conditional variable state.
#[derive(Default, Debug)]
struct Condvar {
    waiters: VecDeque<CondvarWaiter>,
}

/// The state of all synchronization variables.
#[derive(Default, Debug)]
pub(super) struct SynchronizationState {
    mutexes: IndexVec<MutexId, Mutex>,
    rwlocks: IndexVec<RwLockId, RwLock>,
    condvars: IndexVec<CondvarId, Condvar>,
}

// Public interface to synchronization primitives. Please note that in most
// cases, the function calls are infallible and it is the client's (shim
// implementation's) responsibility to detect and deal with erroneous
// situations.
impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriEvalContext<'mir, 'tcx> {}
pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx> {
    #[inline]
    /// Create state for a new mutex.
    fn mutex_create(&mut self) -> MutexId {
        let this = self.eval_context_mut();
        this.machine.threads.sync.mutexes.push(Default::default())
    }

    #[inline]
    /// Get the id of the thread that currently owns this lock.
    fn mutex_get_owner(&mut self, id: MutexId) -> ThreadId {
        let this = self.eval_context_ref();
        this.machine.threads.sync.mutexes[id].owner.unwrap()
    }

    #[inline]
    /// Check if locked.
    fn mutex_is_locked(&mut self, id: MutexId) -> bool {
        let this = self.eval_context_mut();
        this.machine.threads.sync.mutexes[id].owner.is_some()
    }

    /// Lock by setting the mutex owner and increasing the lock count.
    fn mutex_lock(&mut self, id: MutexId, thread: ThreadId) {
        let this = self.eval_context_mut();
        let mutex = &mut this.machine.threads.sync.mutexes[id];
        if let Some(current_owner) = mutex.owner {
            assert_eq!(thread, current_owner, "mutex already locked by another thread");
            assert!(
                mutex.lock_count > 0,
                "invariant violation: lock_count == 0 iff the thread is unlocked"
            );
        } else {
            mutex.owner = Some(thread);
        }
        mutex.lock_count = mutex.lock_count.checked_add(1).unwrap();
    }

    /// Try unlocking by decreasing the lock count and returning the old owner
    /// and the old lock count. If the lock count reaches 0, release the lock
    /// and potentially give to a new owner. If the lock was not locked, return
    /// `None`.
    ///
    /// Note: It is the caller's responsibility to check that the thread that
    /// unlocked the lock actually is the same one, which owned it.
    fn mutex_unlock(
        &mut self,
        id: MutexId,
        expected_owner: ThreadId,
    ) -> InterpResult<'tcx, Option<usize>> {
        let this = self.eval_context_mut();
        let mutex = &mut this.machine.threads.sync.mutexes[id];
        if let Some(current_owner) = mutex.owner {
            // Mutex is locked.
            if current_owner != expected_owner {
                // Only the owner can unlock the mutex.
                return Ok(None);
            }
            let old_lock_count = mutex.lock_count;
            mutex.lock_count = old_lock_count
                .checked_sub(1)
                .expect("invariant violation: lock_count == 0 iff the thread is unlocked");
            if mutex.lock_count == 0 {
                mutex.owner = None;
                // The mutex is completely unlocked. Try transfering ownership
                // to another thread.
                if let Some(new_owner) = this.mutex_dequeue(id) {
                    this.mutex_lock(id, new_owner);
                    this.unblock_thread(new_owner)?;
                }
            }
            Ok(Some(old_lock_count))
        } else {
            // Mutex is unlocked.
            Ok(None)
        }
    }

    #[inline]
    /// Put the thread into the queue waiting for the lock.
    fn mutex_enqueue(&mut self, id: MutexId, thread: ThreadId) {
        let this = self.eval_context_mut();
        assert!(this.mutex_is_locked(id), "queing on unlocked mutex");
        this.machine.threads.sync.mutexes[id].queue.push_back(thread);
    }

    #[inline]
    /// Take a thread out of the queue waiting for the lock.
    fn mutex_dequeue(&mut self, id: MutexId) -> Option<ThreadId> {
        let this = self.eval_context_mut();
        this.machine.threads.sync.mutexes[id].queue.pop_front()
    }

    #[inline]
    /// Create state for a new read write lock.
    fn rwlock_create(&mut self) -> RwLockId {
        let this = self.eval_context_mut();
        this.machine.threads.sync.rwlocks.push(Default::default())
    }

    #[inline]
    /// Check if locked.
    fn rwlock_is_locked(&mut self, id: RwLockId) -> bool {
        let this = self.eval_context_mut();
        this.machine.threads.sync.rwlocks[id].writer.is_some()
            || this.machine.threads.sync.rwlocks[id].readers.is_empty().not()
    }

    #[inline]
    /// Check if write locked.
    fn rwlock_is_write_locked(&mut self, id: RwLockId) -> bool {
        let this = self.eval_context_mut();
        this.machine.threads.sync.rwlocks[id].writer.is_some()
    }

    /// Read-lock the lock by adding the `reader` the list of threads that own
    /// this lock.
    fn rwlock_reader_lock(&mut self, id: RwLockId, reader: ThreadId) {
        let this = self.eval_context_mut();
        assert!(!this.rwlock_is_write_locked(id), "the lock is write locked");
        let count = this.machine.threads.sync.rwlocks[id].readers.entry(reader).or_insert(0);
        *count = count.checked_add(1).expect("the reader counter overflowed");
    }

    /// Try read-unlock the lock for `reader`. Returns `true` if succeeded,
    /// `false` if this `reader` did not hold the lock.
    fn rwlock_reader_unlock(&mut self, id: RwLockId, reader: ThreadId) -> bool {
        let this = self.eval_context_mut();
        match this.machine.threads.sync.rwlocks[id].readers.entry(reader) {
            Entry::Occupied(mut entry) => {
                let count = entry.get_mut();
                assert!(*count > 0, "rwlock locked with count == 0");
                *count -= 1;
                if *count == 0 {
                    entry.remove();
                }
                true
            }
            Entry::Vacant(_) => false,
        }
    }

    #[inline]
    /// Put the reader in the queue waiting for the lock and block it.
    fn rwlock_enqueue_and_block_reader(
        &mut self,
        id: RwLockId,
        reader: ThreadId,
    ) -> InterpResult<'tcx> {
        let this = self.eval_context_mut();
        assert!(this.rwlock_is_write_locked(id), "queueing on not write locked lock");
        this.machine.threads.sync.rwlocks[id].reader_queue.push_back(reader);
        this.block_thread(reader)
    }

    #[inline]
    /// Take a reader out the queue waiting for the lock.
    fn rwlock_dequeue_reader(&mut self, id: RwLockId) -> Option<ThreadId> {
        let this = self.eval_context_mut();
        this.machine.threads.sync.rwlocks[id].reader_queue.pop_front()
    }

    #[inline]
    /// Lock by setting the writer that owns the lock.
    fn rwlock_writer_lock(&mut self, id: RwLockId, writer: ThreadId) {
        let this = self.eval_context_mut();
        assert!(!this.rwlock_is_locked(id), "the lock is already locked");
        this.machine.threads.sync.rwlocks[id].writer = Some(writer);
    }

    #[inline]
    /// Try to unlock by removing the writer.
    fn rwlock_writer_unlock(&mut self, id: RwLockId) -> Option<ThreadId> {
        let this = self.eval_context_mut();
        this.machine.threads.sync.rwlocks[id].writer.take()
    }

    #[inline]
    /// Put the writer in the queue waiting for the lock.
    fn rwlock_enqueue_and_block_writer(
        &mut self,
        id: RwLockId,
        writer: ThreadId,
    ) -> InterpResult<'tcx> {
        let this = self.eval_context_mut();
        assert!(this.rwlock_is_locked(id), "queueing on unlocked lock");
        this.machine.threads.sync.rwlocks[id].writer_queue.push_back(writer);
        this.block_thread(writer)
    }

    #[inline]
    /// Take the writer out the queue waiting for the lock.
    fn rwlock_dequeue_writer(&mut self, id: RwLockId) -> Option<ThreadId> {
        let this = self.eval_context_mut();
        this.machine.threads.sync.rwlocks[id].writer_queue.pop_front()
    }

    #[inline]
    /// Create state for a new conditional variable.
    fn condvar_create(&mut self) -> CondvarId {
        let this = self.eval_context_mut();
        this.machine.threads.sync.condvars.push(Default::default())
    }

    #[inline]
    /// Is the conditional variable awaited?
    fn condvar_is_awaited(&mut self, id: CondvarId) -> bool {
        let this = self.eval_context_mut();
        !this.machine.threads.sync.condvars[id].waiters.is_empty()
    }

    /// Mark that the thread is waiting on the conditional variable.
    fn condvar_wait(&mut self, id: CondvarId, thread: ThreadId, mutex: MutexId) {
        let this = self.eval_context_mut();
        let waiters = &mut this.machine.threads.sync.condvars[id].waiters;
        assert!(waiters.iter().all(|waiter| waiter.thread != thread), "thread is already waiting");
        waiters.push_back(CondvarWaiter { thread, mutex });
    }

    /// Wake up some thread (if there is any) sleeping on the conditional
    /// variable.
    fn condvar_signal(&mut self, id: CondvarId) -> Option<(ThreadId, MutexId)> {
        let this = self.eval_context_mut();
        this.machine.threads.sync.condvars[id]
            .waiters
            .pop_front()
            .map(|waiter| (waiter.thread, waiter.mutex))
    }

    #[inline]
    /// Remove the thread from the queue of threads waiting on this conditional variable.
    fn condvar_remove_waiter(&mut self, id: CondvarId, thread: ThreadId) {
        let this = self.eval_context_mut();
        this.machine.threads.sync.condvars[id].waiters.retain(|waiter| waiter.thread != thread);
    }
}
<|endoftext|>


<commit_before>//! [Lambda terms](https://en.wikipedia.org/wiki/Lambda_calculus#Lambda_terms)

use self::Term::*;
use self::Error::*;
use std::fmt;
use std::borrow::Cow;
use std::char::from_u32;

/// Set to `true` for λ or `false` for \ when displaying lambda terms. The default is `true`.
pub const DISPLAY_PRETTY: bool = true;

/// Set to `true` for classic lambda mode or `false` for the De Bruijn index display mode when
/// displaying lambda terms. The default is `false`.
pub const DISPLAY_CLASSIC: bool = false;

/// A lambda term that is either a variable with a De Bruijn index, an abstraction over a term or
/// an applicaction of one term to another.
#[derive(Debug, PartialEq, Clone)]
pub enum Term {
    Var(usize),
    Abs(Box<Term>),
    App(Box<Term>, Box<Term>)
}

/// An error that can be returned when an inapplicable function is applied to a term.
#[derive(Debug, PartialEq, Clone)]
pub enum Error {
    NotAVar,
    NotAnAbs,
    NotAnApp,
    NotANum,
    NotAPair,
    NotAList
}

impl Term {
    /// Applies `self` to another term without substitution or reduction.
    ///
    /// # Example
    /// ```
    /// use lambda_calculus::term::Term::*;
    /// use lambda_calculus::arithmetic::{zero, succ};
    ///
    /// assert_eq!(succ().app(zero()), App(Box::new(succ()), Box::new(zero())));
    /// ```
    pub fn app(self, argument: Term) -> Term { App(Box::new(self), Box::new(argument)) }

    /// Consumes a lambda variable and returns its De Bruijn index.
    ///
    /// # Example
    /// ```
    /// use lambda_calculus::term::Term::*;
    ///
    /// assert_eq!(Var(1).unvar(), Ok(1));
    /// ```
    pub fn unvar(self) -> Result<usize, Error> {
        match self {
            Var(n) => Ok(n),
            _ => Err(NotAVar)
        }
    }

    /// Returns a reference to a variable's index.
    ///
    /// # Example
    /// ```
    /// use lambda_calculus::term::Term::*;
    ///
    /// assert_eq!(Var(1).unvar_ref(), Ok(&1));
    /// ```
    pub fn unvar_ref(&self) -> Result<&usize, Error> {
        match *self {
            Var(ref n) => Ok(&n),
            _ => Err(NotAVar)
        }
    }

    /// Consumes an abstraction and returns its underlying term.
    ///
    /// # Example
    /// ```
    /// use lambda_calculus::term::Term::*;
    /// use lambda_calculus::term::abs;
    ///
    /// assert_eq!(abs(Var(1)).unabs(), Ok(Var(1)));
    /// ```
    pub fn unabs(self) -> Result<Term, Error> {
        match self {
            Abs(x) => Ok(*x),
            _ => Err(NotAnAbs)
        }
    }

    /// Returns a reference to an abstraction's underlying term.
    ///
    /// # Example
    /// ```
    /// use lambda_calculus::term::Term::*;
    /// use lambda_calculus::term::abs;
    ///
    /// assert_eq!(abs(Var(1)).unabs_ref(), Ok(&Var(1)));
    /// ```
    pub fn unabs_ref(&self) -> Result<&Term, Error> {
        match *self {
            Abs(ref x) => Ok(&*x),
            _ => Err(NotAnAbs)
        }
    }

    /// Returns a mutable reference to an abstraction's underlying term.
    ///
    /// # Example
    /// ```
    /// use lambda_calculus::term::Term::*;
    /// use lambda_calculus::term::abs;
    ///
    /// assert_eq!(abs(Var(1)).unabs_ref_mut(), Ok(&mut Var(1)));
    /// ```
    pub fn unabs_ref_mut(&mut self) -> Result<&mut Term, Error> {
        match *self {
            Abs(ref mut x) => Ok(&mut *x),
            _ => Err(NotAnAbs)
        }
    }

    /// Consumes an application and returns a pair containing its underlying terms.
    ///
    /// # Example
    /// ```
    /// use lambda_calculus::term::Term::*;
    ///
    /// assert_eq!(Var(0).app(Var(1)).unapp(), Ok((Var(0), Var(1))));
    /// ```
    pub fn unapp(self) -> Result<(Term, Term), Error> {
        match self {
            App(lhs, rhs) => Ok((*lhs, *rhs)),
            _ => Err(NotAnApp)
        }
    }

    /// Returns a pair containing references to an application's underlying terms.
    ///
    /// # Example
    /// ```
    /// use lambda_calculus::term::Term::*;
    ///
    /// assert_eq!(Var(0).app(Var(1)).unapp_ref(), Ok((&Var(0), &Var(1))));
    /// ```
    pub fn unapp_ref(&self) -> Result<(&Term, &Term), Error> {
        match *self {
            App(ref lhs, ref rhs) => Ok((&*lhs, &*rhs)),
            _ => Err(NotAnApp)
        }
    }

    /// Returns a pair containing mutable references to an application's underlying terms.
    ///
    /// # Example
    /// ```
    /// use lambda_calculus::term::Term::*;
    ///
    /// assert_eq!(Var(0).app(Var(1)).unapp_ref_mut(), Ok((&mut Var(0), &mut Var(1))));
    /// ```
    pub fn unapp_ref_mut(&mut self) -> Result<(&mut Term, &mut Term), Error> {
        match *self {
            App(ref mut lhs, ref mut rhs) => Ok((&mut *lhs, &mut *rhs)),
            _ => Err(NotAnApp)
        }
    }

    /// Returns the left-hand side term of an application. Consumes `self`.
    ///
    /// # Example
    /// ```
    /// use lambda_calculus::term::Term::*;
    ///
    /// assert_eq!(Var(0).app(Var(1)).lhs(), Ok(Var(0)));
    /// ```
    pub fn lhs(self) -> Result<Term, Error> {
        if let Ok((lhs, _)) = self.unapp() { Ok(lhs) } else { Err(NotAnApp) }
    }

    /// Returns a reference to the left-hand side term of an application.
    ///
    /// # Example
    /// ```
    /// use lambda_calculus::term::Term::*;
    ///
    /// assert_eq!(Var(0).app(Var(1)).lhs_ref(), Ok(&Var(0)));
    /// ```
    pub fn lhs_ref(&self) -> Result<&Term, Error> {
        if let Ok((lhs, _)) = self.unapp_ref() { Ok(lhs) } else { Err(NotAnApp) }
    }

    /// Returns a mutable reference to the left-hand side term of an application.
    ///
    /// # Example
    /// ```
    /// use lambda_calculus::term::Term::*;
    ///
    /// assert_eq!(Var(0).app(Var(1)).lhs_ref_mut(), Ok(&mut Var(0)));
    /// ```
    pub fn lhs_ref_mut(&mut self) -> Result<&mut Term, Error> {
        if let Ok((lhs, _)) = self.unapp_ref_mut() { Ok(lhs) } else { Err(NotAnApp) }
    }

    /// Returns the right-hand side term of an application. Consumes `self`.
    ///
    /// # Example
    /// ```
    /// use lambda_calculus::term::Term::*;
    ///
    /// assert_eq!(Var(0).app(Var(1)).rhs(), Ok(Var(1)));
    /// ```
    pub fn rhs(self) -> Result<Term, Error> {
        if let Ok((_, rhs)) = self.unapp() { Ok(rhs) } else { Err(NotAnApp) }
    }

    /// Returns a reference to the right-hand side term of an application.
    ///
    /// # Example
    /// ```
    /// use lambda_calculus::term::Term::*;
    ///
    /// assert_eq!(Var(0).app(Var(1)).rhs_ref(), Ok(&Var(1)));
    /// ```
    pub fn rhs_ref(&self) -> Result<&Term, Error> {
        if let Ok((_, rhs)) = self.unapp_ref() { Ok(rhs) } else { Err(NotAnApp) }
    }

    /// Returns a mutable reference to the right-hand side term of an application.
    ///
    /// # Example
    /// ```
    /// use lambda_calculus::term::Term::*;
    ///
    /// assert_eq!(Var(0).app(Var(1)).rhs_ref_mut(), Ok(&mut Var(1)));
    /// ```
    pub fn rhs_ref_mut(&mut self) -> Result<&mut Term, Error> {
        if let Ok((_, rhs)) = self.unapp_ref_mut() { Ok(rhs) } else { Err(NotAnApp) }
    }
}

/// Wraps a term in an abstraction. Consumes its argument.
///
/// # Example
/// ```
/// use lambda_calculus::term::Term::*;
/// use lambda_calculus::term::abs;
///
/// assert_eq!(abs(Var(1)), Abs(Box::new(Var(1))));
/// ```
pub fn abs(term: Term) -> Term { Abs(Box::new(term)) }

/// Produces an application of its arguments without substitution or reduction, consuming them in
/// the process.
///
/// # Example
/// ```
/// use lambda_calculus::term::Term::*;
/// use lambda_calculus::term::app;
///
/// assert_eq!(app(Var(0), Var(1)), App(Box::new(Var(0)), Box::new(Var(1))));
/// ```
pub fn app(lhs: Term, rhs: Term) -> Term { App(Box::new(lhs), Box::new(rhs)) }

impl fmt::Display for Term {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", show_precedence(self, 0, 0))
    }
}

// TODO: make it safer (unwraps)
#[doc(hidden)]
pub fn show_precedence(term: &Term, context_precedence: usize, depth: u32) -> String {
    match *term {
        Var(i) => if DISPLAY_CLASSIC {
            if depth >= i as u32 {
                format!("{}", from_u32(depth + 97 - i as u32).unwrap())
            } else {
                format!("{}", from_u32(depth + 96 + i as u32).unwrap())
            }
        } else {
            format!("{:X}", i)
        },
        Abs(ref t) => {
            let ret = if DISPLAY_CLASSIC {
                format!("{}{}. {}", if DISPLAY_PRETTY { 'λ' } else { '\\' }, from_u32(depth + 97).unwrap(), show_precedence(t, 0, depth + 1))
            } else {
                format!("{}{}", if DISPLAY_PRETTY { 'λ' } else { '\\' }, t)
            };
            parenthesize_if(&ret, context_precedence > 1).into()
        },
        App(ref t1, ref t2) => {
            let ret = if DISPLAY_CLASSIC {
                format!("{} {}", show_precedence(t1, 2, depth), show_precedence(t2, 3, depth))
            } else {
                format!("{}{}", show_precedence(t1, 2, depth), show_precedence(t2, 3, depth))
            };
            parenthesize_if(&ret, context_precedence == 3).into()
        }
    }
}

fn parenthesize_if(input: &str, condition: bool) -> Cow<str> {
    if condition {
        format!("({})", input).into()
    } else {
        input.into()
    }
}

#[cfg(test)]
mod test {
    use super::DISPLAY_CLASSIC;
    use arithmetic::{zero, succ, pred};

    #[test]
    fn display_modes() {
        if DISPLAY_CLASSIC {
            assert_eq!(&format!("{}", zero()), "λa. λb. b");
            assert_eq!(&format!("{}", succ()), "λa. λb. λc. b (a b c)");
            assert_eq!(&format!("{}", pred()), "λa. λb. λc. a (λd. λe. e (d b)) (λd. c) (λd. d)");
        } else {
            assert_eq!(&format!("{}", zero()), "λλ1");
            assert_eq!(&format!("{}", succ()), "λλλ2(321)");
            assert_eq!(&format!("{}", pred()), "λλλ3(λλ1(24))(λ2)(λ1)");
        }
    }
}
<commit_msg>small improvements<commit_after>//! [Lambda terms](https://en.wikipedia.org/wiki/Lambda_calculus#Lambda_terms)

use self::Term::*;
use self::Error::*;
use std::fmt;
use std::borrow::Cow;
use std::char::from_u32;

/// Set to `true` for λ or `false` for \ when displaying lambda terms. The default is `true`.
pub const DISPLAY_PRETTY: bool = true;

/// Set to `true` for classic lambda mode or `false` for the De Bruijn index display mode when
/// displaying lambda terms. The default is `false`.
pub const DISPLAY_CLASSIC: bool = false;

/// A lambda term that is either a variable with a De Bruijn index, an abstraction over a term or
/// an applicaction of one term to another.
#[derive(Debug, PartialEq, Clone)]
pub enum Term {
    /// a variable
    Var(usize),
    /// an abstraction
    Abs(Box<Term>),
    /// an application
    App(Box<Term>, Box<Term>)
}

/// An error that can be returned when an inapplicable function is applied to a term.
#[derive(Debug, PartialEq)]
pub enum Error {
    NotAVar,
    NotAnAbs,
    NotAnApp,
    NotANum,
    NotAPair,
    NotAList
}

impl Term {
    /// Applies `self` to another term without substitution or reduction.
    ///
    /// # Example
    /// ```
    /// use lambda_calculus::term::Term::*;
    /// use lambda_calculus::arithmetic::{zero, succ};
    ///
    /// assert_eq!(succ().app(zero()), App(Box::new(succ()), Box::new(zero())));
    /// ```
    pub fn app(self, argument: Term) -> Term { App(Box::new(self), Box::new(argument)) }

    /// Consumes a lambda variable and returns its De Bruijn index.
    ///
    /// # Example
    /// ```
    /// use lambda_calculus::term::Term::*;
    ///
    /// assert_eq!(Var(1).unvar(), Ok(1));
    /// ```
    pub fn unvar(self) -> Result<usize, Error> {
        match self {
            Var(n) => Ok(n),
            _ => Err(NotAVar)
        }
    }

    /// Returns a reference to a variable's index.
    ///
    /// # Example
    /// ```
    /// use lambda_calculus::term::Term::*;
    ///
    /// assert_eq!(Var(1).unvar_ref(), Ok(&1));
    /// ```
    pub fn unvar_ref(&self) -> Result<&usize, Error> {
        match *self {
            Var(ref n) => Ok(&n),
            _ => Err(NotAVar)
        }
    }

    /// Consumes an abstraction and returns its underlying term.
    ///
    /// # Example
    /// ```
    /// use lambda_calculus::term::Term::*;
    /// use lambda_calculus::term::abs;
    ///
    /// assert_eq!(abs(Var(1)).unabs(), Ok(Var(1)));
    /// ```
    pub fn unabs(self) -> Result<Term, Error> {
        match self {
            Abs(x) => Ok(*x),
            _ => Err(NotAnAbs)
        }
    }

    /// Returns a reference to an abstraction's underlying term.
    ///
    /// # Example
    /// ```
    /// use lambda_calculus::term::Term::*;
    /// use lambda_calculus::term::abs;
    ///
    /// assert_eq!(abs(Var(1)).unabs_ref(), Ok(&Var(1)));
    /// ```
    pub fn unabs_ref(&self) -> Result<&Term, Error> {
        match *self {
            Abs(ref x) => Ok(&*x),
            _ => Err(NotAnAbs)
        }
    }

    /// Returns a mutable reference to an abstraction's underlying term.
    ///
    /// # Example
    /// ```
    /// use lambda_calculus::term::Term::*;
    /// use lambda_calculus::term::abs;
    ///
    /// assert_eq!(abs(Var(1)).unabs_ref_mut(), Ok(&mut Var(1)));
    /// ```
    pub fn unabs_ref_mut(&mut self) -> Result<&mut Term, Error> {
        match *self {
            Abs(ref mut x) => Ok(&mut *x),
            _ => Err(NotAnAbs)
        }
    }

    /// Consumes an application and returns a pair containing its underlying terms.
    ///
    /// # Example
    /// ```
    /// use lambda_calculus::term::Term::*;
    ///
    /// assert_eq!(Var(0).app(Var(1)).unapp(), Ok((Var(0), Var(1))));
    /// ```
    pub fn unapp(self) -> Result<(Term, Term), Error> {
        match self {
            App(lhs, rhs) => Ok((*lhs, *rhs)),
            _ => Err(NotAnApp)
        }
    }

    /// Returns a pair containing references to an application's underlying terms.
    ///
    /// # Example
    /// ```
    /// use lambda_calculus::term::Term::*;
    ///
    /// assert_eq!(Var(0).app(Var(1)).unapp_ref(), Ok((&Var(0), &Var(1))));
    /// ```
    pub fn unapp_ref(&self) -> Result<(&Term, &Term), Error> {
        match *self {
            App(ref lhs, ref rhs) => Ok((&*lhs, &*rhs)),
            _ => Err(NotAnApp)
        }
    }

    /// Returns a pair containing mutable references to an application's underlying terms.
    ///
    /// # Example
    /// ```
    /// use lambda_calculus::term::Term::*;
    ///
    /// assert_eq!(Var(0).app(Var(1)).unapp_ref_mut(), Ok((&mut Var(0), &mut Var(1))));
    /// ```
    pub fn unapp_ref_mut(&mut self) -> Result<(&mut Term, &mut Term), Error> {
        match *self {
            App(ref mut lhs, ref mut rhs) => Ok((&mut *lhs, &mut *rhs)),
            _ => Err(NotAnApp)
        }
    }

    /// Returns the left-hand side term of an application. Consumes `self`.
    ///
    /// # Example
    /// ```
    /// use lambda_calculus::term::Term::*;
    ///
    /// assert_eq!(Var(0).app(Var(1)).lhs(), Ok(Var(0)));
    /// ```
    pub fn lhs(self) -> Result<Term, Error> {
        if let Ok((lhs, _)) = self.unapp() { Ok(lhs) } else { Err(NotAnApp) }
    }

    /// Returns a reference to the left-hand side term of an application.
    ///
    /// # Example
    /// ```
    /// use lambda_calculus::term::Term::*;
    ///
    /// assert_eq!(Var(0).app(Var(1)).lhs_ref(), Ok(&Var(0)));
    /// ```
    pub fn lhs_ref(&self) -> Result<&Term, Error> {
        if let Ok((lhs, _)) = self.unapp_ref() { Ok(lhs) } else { Err(NotAnApp) }
    }

    /// Returns a mutable reference to the left-hand side term of an application.
    ///
    /// # Example
    /// ```
    /// use lambda_calculus::term::Term::*;
    ///
    /// assert_eq!(Var(0).app(Var(1)).lhs_ref_mut(), Ok(&mut Var(0)));
    /// ```
    pub fn lhs_ref_mut(&mut self) -> Result<&mut Term, Error> {
        if let Ok((lhs, _)) = self.unapp_ref_mut() { Ok(lhs) } else { Err(NotAnApp) }
    }

    /// Returns the right-hand side term of an application. Consumes `self`.
    ///
    /// # Example
    /// ```
    /// use lambda_calculus::term::Term::*;
    ///
    /// assert_eq!(Var(0).app(Var(1)).rhs(), Ok(Var(1)));
    /// ```
    pub fn rhs(self) -> Result<Term, Error> {
        if let Ok((_, rhs)) = self.unapp() { Ok(rhs) } else { Err(NotAnApp) }
    }

    /// Returns a reference to the right-hand side term of an application.
    ///
    /// # Example
    /// ```
    /// use lambda_calculus::term::Term::*;
    ///
    /// assert_eq!(Var(0).app(Var(1)).rhs_ref(), Ok(&Var(1)));
    /// ```
    pub fn rhs_ref(&self) -> Result<&Term, Error> {
        if let Ok((_, rhs)) = self.unapp_ref() { Ok(rhs) } else { Err(NotAnApp) }
    }

    /// Returns a mutable reference to the right-hand side term of an application.
    ///
    /// # Example
    /// ```
    /// use lambda_calculus::term::Term::*;
    ///
    /// assert_eq!(Var(0).app(Var(1)).rhs_ref_mut(), Ok(&mut Var(1)));
    /// ```
    pub fn rhs_ref_mut(&mut self) -> Result<&mut Term, Error> {
        if let Ok((_, rhs)) = self.unapp_ref_mut() { Ok(rhs) } else { Err(NotAnApp) }
    }
}

/// Wraps a term in an abstraction. Consumes its argument.
///
/// # Example
/// ```
/// use lambda_calculus::term::Term::*;
/// use lambda_calculus::term::abs;
///
/// assert_eq!(abs(Var(1)), Abs(Box::new(Var(1))));
/// ```
pub fn abs(term: Term) -> Term { Abs(Box::new(term)) }

/// Produces an application of its arguments without substitution or reduction, consuming them in
/// the process.
///
/// # Example
/// ```
/// use lambda_calculus::term::Term::*;
/// use lambda_calculus::term::app;
///
/// assert_eq!(app(Var(0), Var(1)), App(Box::new(Var(0)), Box::new(Var(1))));
/// ```
pub fn app(lhs: Term, rhs: Term) -> Term { App(Box::new(lhs), Box::new(rhs)) }

impl fmt::Display for Term {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", show_precedence(self, 0, 0))
    }
}

// TODO: make it safer (unwraps)
#[doc(hidden)]
pub fn show_precedence(term: &Term, context_precedence: usize, depth: u32) -> String {
    match *term {
        Var(i) => if DISPLAY_CLASSIC {
            if depth >= i as u32 {
                format!("{}", from_u32(depth + 97 - i as u32).unwrap())
            } else {
                format!("{}", from_u32(depth + 96 + i as u32).unwrap())
            }
        } else {
            format!("{:X}", i)
        },
        Abs(ref t) => {
            let ret = if DISPLAY_CLASSIC {
                format!("{}{}. {}", if DISPLAY_PRETTY { 'λ' } else { '\\' }, from_u32(depth + 97).unwrap(), show_precedence(t, 0, depth + 1))
            } else {
                format!("{}{}", if DISPLAY_PRETTY { 'λ' } else { '\\' }, t)
            };
            parenthesize_if(&ret, context_precedence > 1).into()
        },
        App(ref t1, ref t2) => {
            let ret = if DISPLAY_CLASSIC {
                format!("{} {}", show_precedence(t1, 2, depth), show_precedence(t2, 3, depth))
            } else {
                format!("{}{}", show_precedence(t1, 2, depth), show_precedence(t2, 3, depth))
            };
            parenthesize_if(&ret, context_precedence == 3).into()
        }
    }
}

fn parenthesize_if(input: &str, condition: bool) -> Cow<str> {
    if condition {
        format!("({})", input).into()
    } else {
        input.into()
    }
}

#[cfg(test)]
mod test {
    use super::DISPLAY_CLASSIC;
    use arithmetic::{zero, succ, pred};

    #[test]
    fn display_modes() {
        if DISPLAY_CLASSIC {
            assert_eq!(&format!("{}", zero()), "λa. λb. b");
            assert_eq!(&format!("{}", succ()), "λa. λb. λc. b (a b c)");
            assert_eq!(&format!("{}", pred()), "λa. λb. λc. a (λd. λe. e (d b)) (λd. c) (λd. d)");
        } else {
            assert_eq!(&format!("{}", zero()), "λλ1");
            assert_eq!(&format!("{}", succ()), "λλλ2(321)");
            assert_eq!(&format!("{}", pred()), "λλλ3(λλ1(24))(λ2)(λ1)");
        }
    }
}
<|endoftext|>


<commit_before>use std::io::{Read, Write};
use std::net::{TcpStream, TcpListener};
use std::process::Command;

use super::*;

#[test]
fn connect_google() {
    let mut builder = ClientBuilder::new().unwrap();
    let s = TcpStream::connect("google.com:443").unwrap();
    let mut socket = builder.handshake("google.com", s).unwrap();

    socket.write_all(b"GET / HTTP/1.0\r\n\r\n").unwrap();
    let mut result = vec![];
    socket.read_to_end(&mut result).unwrap();

    println!("{}", String::from_utf8_lossy(&result));
    assert!(result.starts_with(b"HTTP/1.0"));
    assert!(result.ends_with(b"\r\n") || result.ends_with(b""));
}

#[test]
fn connect_bad_hostname() {
    let mut builder = ClientBuilder::new().unwrap();
    let s = TcpStream::connect("wrong.host.badssl.com:443").unwrap();
    assert!(builder.handshake("wrong.host.badssl.com", s).is_err());
}

#[test]
fn server() {
    let buf = include_bytes!("../test/identity.p12");
    let pkcs12 = Pkcs12::parse(buf, "mypass").unwrap();
    let mut builder = ServerBuilder::new(pkcs12.identity, pkcs12.chain).unwrap();

    let listener = TcpListener::bind("0.0.0.0:0").unwrap();
    let port = listener.local_addr().unwrap().port();

    let python = if cfg!(windows) {
        "python.exe"
    } else {
        "python2"
    };

    let mut client = Command::new(python)
        .arg("client.py")
        .arg(port.to_string())
        .current_dir("test")
        .spawn()
        .unwrap();

    let socket = listener.accept().unwrap().0;
    let mut socket = builder.handshake(socket).unwrap();
    let mut buf = [0; 5];
    socket.read_exact(&mut buf).unwrap();
    assert_eq!(&buf, b"hello");

    socket.write_all(b"world").unwrap();
    drop(socket);

    let status = client.wait().unwrap();
    assert!(status.success());
}
<commit_msg>Don't pick python2 specifically<commit_after>use std::io::{Read, Write};
use std::net::{TcpStream, TcpListener};
use std::process::Command;

use super::*;

#[test]
fn connect_google() {
    let mut builder = ClientBuilder::new().unwrap();
    let s = TcpStream::connect("google.com:443").unwrap();
    let mut socket = builder.handshake("google.com", s).unwrap();

    socket.write_all(b"GET / HTTP/1.0\r\n\r\n").unwrap();
    let mut result = vec![];
    socket.read_to_end(&mut result).unwrap();

    println!("{}", String::from_utf8_lossy(&result));
    assert!(result.starts_with(b"HTTP/1.0"));
    assert!(result.ends_with(b"\r\n") || result.ends_with(b""));
}

#[test]
fn connect_bad_hostname() {
    let mut builder = ClientBuilder::new().unwrap();
    let s = TcpStream::connect("wrong.host.badssl.com:443").unwrap();
    assert!(builder.handshake("wrong.host.badssl.com", s).is_err());
}

#[test]
fn server() {
    let buf = include_bytes!("../test/identity.p12");
    let pkcs12 = Pkcs12::parse(buf, "mypass").unwrap();
    let mut builder = ServerBuilder::new(pkcs12.identity, pkcs12.chain).unwrap();

    let listener = TcpListener::bind("0.0.0.0:0").unwrap();
    let port = listener.local_addr().unwrap().port();

    let python = if cfg!(windows) {
        "python.exe"
    } else {
        "python"
    };

    let mut client = Command::new(python)
        .arg("client.py")
        .arg(port.to_string())
        .current_dir("test")
        .spawn()
        .unwrap();

    let socket = listener.accept().unwrap().0;
    let mut socket = builder.handshake(socket).unwrap();
    let mut buf = [0; 5];
    socket.read_exact(&mut buf).unwrap();
    assert_eq!(&buf, b"hello");

    socket.write_all(b"world").unwrap();
    drop(socket);

    let status = client.wait().unwrap();
    assert!(status.success());
}
<|endoftext|>


<commit_before>extern crate sync;

use std::os::args;
use std::path::Path;
use std::io::{File, TempDir, stdio};

#[allow(dead_code)]
mod gdal;

fn main() {
    let memory_driver = gdal::driver::get_driver("MEM").unwrap();
    let png_driver = gdal::driver::get_driver("PNG").unwrap();

    let source = gdal::dataset::open(&Path::new(args()[1])).unwrap();
    assert!(stdio::stderr().write(format!(
        "size: {}, bands: {}",
        source.get_raster_size(),
        source.get_raster_count()
    ).as_bytes()).is_ok());

    let tile = memory_driver.create("", 256, 256, 3).unwrap();
    for band in range(1, 4) {
        let raster = source.read_raster(band, 10000, 1600, 3000, 2000, 256, 256);
        tile.write_raster(band, 0, 0, 256, 256, raster);
    }

    let tmp = TempDir::new("rustile").unwrap();
    let tile_path = tmp.path().join("tile.png");
    tile.create_copy(png_driver, tile_path.as_str().unwrap());
    let tile_data = File::open(&tile_path).read_to_end().unwrap();
    assert!(stdio::stdout_raw().write(tile_data).is_ok());
}
<commit_msg>calculate source window using Point2D and coords<commit_after>extern crate sync;
extern crate geom;

use std::os::args;
use std::path::Path;
use std::io::{File, TempDir, stdio};
use geom::point::Point2D;

#[allow(dead_code)]
mod gdal;

fn main() {
    let memory_driver = gdal::driver::get_driver("MEM").unwrap();
    let png_driver = gdal::driver::get_driver("PNG").unwrap();

    let source = gdal::dataset::open(&Path::new(args()[1])).unwrap();
    let (width, height) = source.get_raster_size();
    let source_bounds = Point2D(width as f64, height as f64);
    assert!(stdio::stderr().write(format!(
        "size: {}, bands: {}",
        (width, height),
        source.get_raster_count()
    ).as_bytes()).is_ok());

    fn xy(lng_lat: &Point2D<f64>, source_bounds: &Point2D<f64>) -> Point2D<f64> {
        let x = (lng_lat.x + 180.) / 360. * source_bounds.x;
        let y = (90. - lng_lat.y) / 180. * source_bounds.y;
        return Point2D(x, y);
    }

    let tile = memory_driver.create("", 256, 256, 3).unwrap();
    for band in range(1, 4) {
        let nw: Point2D<f64> = Point2D(-13., 64.);
        let se: Point2D<f64> = Point2D(37., 30.);

        let xy_min = xy(&nw, &source_bounds);
        let xy_max = xy(&se, &source_bounds);
        let xy_bounds = xy_max - xy_min;

        let raster = source.read_raster(
            band,
            xy_min.x as int,
            xy_min.y as int,
            xy_bounds.x as uint,
            xy_bounds.y as uint,
            256,
            256
        );
        tile.write_raster(band, 0, 0, 256, 256, raster);
    }

    let tmp = TempDir::new("rustile").unwrap();
    let tile_path = tmp.path().join("tile.png");
    tile.create_copy(png_driver, tile_path.as_str().unwrap());
    let tile_data = File::open(&tile_path).read_to_end().unwrap();
    assert!(stdio::stdout_raw().write(tile_data).is_ok());
}
<|endoftext|>


<commit_before>//
// FSUIPC library
// Copyright (c) 2015 Alvaro Polo
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

use std::ffi::CString;
use std::io;
use std::os::raw::c_void;
use std::ptr;

use kernel32::*;
use user32::{FindWindowExA, RegisterWindowMessageA, SendMessageA};
use winapi::memoryapi::FILE_MAP_WRITE;
use winapi::minwindef::ATOM;
use winapi::windef::HWND;
use winapi::winnt::{HANDLE, PAGE_READWRITE};

use super::{Handle, Session};
use super::ipc::*;
use super::raw::{MutRawBytes, RawBytes};

pub struct UserHandle {
    handle: HWND,
    file_mapping_atom: ATOM,
    file_mapping: HANDLE,
    msg_id: u32,
    data: *mut u8,
}

impl UserHandle {
    pub fn new() -> io::Result<Self> {
        unsafe {
            let win_name = CString::new("UIPCMAIN").unwrap();
            let handle = FindWindowExA(
                ptr::null_mut(),
                ptr::null_mut(),
                win_name.as_ptr(),
                ptr::null_mut());
            if handle == ptr::null_mut() {
                return Err(io::Error::new(
                    io::ErrorKind::ConnectionRefused,
                    "cannot connect to user FSUIPC: cannot create window handle"));
            }
            let msg_name = CString::new("FsasmLib:IPC").unwrap();
            let msg_id = RegisterWindowMessageA(msg_name.as_ptr());
            if msg_id == 0 {
                return Err(io::Error::new(
                    io::ErrorKind::ConnectionRefused,
                    "cannot connect to user FSUIPC: cannot register window message"));
            }

            let file_mapping_name = CString::new(
                format!("FsasmLib:IPC:{:x}:{:x}",
                    GetCurrentProcessId(),
                    next_file_mapping_index())).unwrap();

            let file_mapping_atom = GlobalAddAtomA(file_mapping_name.as_ptr());
            if file_mapping_atom == 0 {
                return Err(io::Error::new(
                    io::ErrorKind::ConnectionRefused,
                    "cannot connect to user FSUIPC: cannot add global atom"));
            }

            let file_mapping = CreateFileMappingA(
                0xffffffff as HANDLE,
                ptr::null_mut(),
                PAGE_READWRITE,
                0, FILE_MAPPING_LEN as u32,
                file_mapping_name.as_ptr());
            if file_mapping == ptr::null_mut() {
                return Err(io::Error::new(
                    io::ErrorKind::ConnectionRefused,
                    "cannot connect to user FSUIPC: cannot create file mapping"));
            }
            let data = MapViewOfFile(file_mapping, FILE_MAP_WRITE, 0, 0, 0) as *mut u8;
            if data == ptr::null_mut() {
                return Err(io::Error::new(
                    io::ErrorKind::ConnectionRefused,
                    "cannot connect to user FSUIPC: cannot map view of file"));
            }
            Ok(UserHandle {
                handle: handle,
                file_mapping_atom: file_mapping_atom,
                file_mapping: file_mapping,
                msg_id: msg_id,
                data: data,
            })
        }
    }
}

impl<'a> Handle<'a> for UserHandle {
    type Sess = UserSession<'a>;

    fn session(&'a mut self) -> UserSession<'a> {
        let data = self.data;
        UserSession {
            handle: self,
            buffer: MutRawBytes::new(data, FILE_MAPPING_LEN)
        }
    }
}

impl Drop for UserHandle {
    fn drop(&mut self) {
        unsafe {
            GlobalDeleteAtom(self.file_mapping_atom);
            UnmapViewOfFile(self.data as *const c_void);
            CloseHandle(self.file_mapping);
        }
    }
}

pub struct UserSession<'a> {
    handle: &'a mut UserHandle,
    buffer: MutRawBytes,
}

impl<'a> Session for UserSession<'a> {
    fn read_bytes(&mut self, offset: u16, dest: *mut u8, len: usize) -> io::Result<usize> {
        self.buffer.write_rsd(offset, dest, len)
    }

    fn write_bytes(&mut self, offset: u16, src: *const u8, len: usize) -> io::Result<usize> {
        self.buffer.write_wsd(offset, src, len)
    }

    fn process(mut self) -> io::Result<usize> {
        unsafe {
            try!(self.buffer.write_header(&MsgHeader::TerminationMark));
            let send_result = SendMessageA(
                self.handle.handle,
                self.handle.msg_id,
                self.handle.file_mapping_atom as WinUInt,
                0);
            if send_result != FS6IPC_MESSAGE_SUCCESS {
                return Err(io::Error::new(io::ErrorKind::InvalidData, format!(
                    "FSUIPC rejected the requests with error {}; possible buffer corruption",
                    send_result)));
            }
            let mut buffer = RawBytes::new(self.handle.data, FILE_MAPPING_LEN);
            loop {
                let header = try!(buffer.read_header());
                match &header {
                    &MsgHeader::ReadStateData { offset: _, len, target } => {
                        let mut output = MutRawBytes::new(target, len);
                        try!(buffer.read_body(&header, &mut output));
                    },
                    &MsgHeader::WriteStateData { offset: _, len: _ } => {
                        let mut output = io::sink();
                        try!(buffer.read_body(&header, &mut output));
                    },
                    &MsgHeader::TerminationMark => return Ok(buffer.consumed()),
                }
            }
        }
    }
}

fn next_file_mapping_index() -> u32 {
    unsafe {
        let next = FILE_MAPPING_INDEX;
        FILE_MAPPING_INDEX += 1;
        next
    }
}

const FS6IPC_MESSAGE_SUCCESS: WinInt = 1;
const FILE_MAPPING_LEN: usize = 64*1024;

static mut FILE_MAPPING_INDEX: u32 = 0;
<commit_msg>INVALID_HANDLE_VALUE has different values on x86 & x86_64<commit_after>//
// FSUIPC library
// Copyright (c) 2015 Alvaro Polo
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

use std::ffi::CString;
use std::io;
use std::os::raw::c_void;
use std::ptr;

use kernel32::*;
use user32::{FindWindowExA, RegisterWindowMessageA, SendMessageA};
use winapi::INVALID_HANDLE_VALUE;
use winapi::memoryapi::FILE_MAP_WRITE;
use winapi::minwindef::ATOM;
use winapi::windef::HWND;
use winapi::winnt::{HANDLE, PAGE_READWRITE};

use super::{Handle, Session};
use super::ipc::*;
use super::raw::{MutRawBytes, RawBytes};

pub struct UserHandle {
    handle: HWND,
    file_mapping_atom: ATOM,
    file_mapping: HANDLE,
    msg_id: u32,
    data: *mut u8,
}

impl UserHandle {
    pub fn new() -> io::Result<Self> {
        unsafe {
            let win_name = CString::new("UIPCMAIN").unwrap();
            let handle = FindWindowExA(
                ptr::null_mut(),
                ptr::null_mut(),
                win_name.as_ptr(),
                ptr::null_mut());
            if handle == ptr::null_mut() {
                return Err(io::Error::new(
                    io::ErrorKind::ConnectionRefused,
                    "cannot connect to user FSUIPC: cannot create window handle"));
            }
            let msg_name = CString::new("FsasmLib:IPC").unwrap();
            let msg_id = RegisterWindowMessageA(msg_name.as_ptr());
            if msg_id == 0 {
                return Err(io::Error::new(
                    io::ErrorKind::ConnectionRefused,
                    "cannot connect to user FSUIPC: cannot register window message"));
            }

            let file_mapping_name = CString::new(
                format!("FsasmLib:IPC:{:x}:{:x}",
                    GetCurrentProcessId(),
                    next_file_mapping_index())).unwrap();

            let file_mapping_atom = GlobalAddAtomA(file_mapping_name.as_ptr());
            if file_mapping_atom == 0 {
                return Err(io::Error::new(
                    io::ErrorKind::ConnectionRefused,
                    "cannot connect to user FSUIPC: cannot add global atom"));
            }

            let file_mapping = CreateFileMappingA(
                INVALID_HANDLE_VALUE,
                ptr::null_mut(),
                PAGE_READWRITE,
                0, FILE_MAPPING_LEN as u32,
                file_mapping_name.as_ptr());
            if file_mapping == ptr::null_mut() {
                return Err(io::Error::new(
                    io::ErrorKind::ConnectionRefused,
                    "cannot connect to user FSUIPC: cannot create file mapping"));
            }
            let data = MapViewOfFile(file_mapping, FILE_MAP_WRITE, 0, 0, 0) as *mut u8;
            if data == ptr::null_mut() {
                return Err(io::Error::new(
                    io::ErrorKind::ConnectionRefused,
                    "cannot connect to user FSUIPC: cannot map view of file"));
            }
            Ok(UserHandle {
                handle: handle,
                file_mapping_atom: file_mapping_atom,
                file_mapping: file_mapping,
                msg_id: msg_id,
                data: data,
            })
        }
    }
}

impl<'a> Handle<'a> for UserHandle {
    type Sess = UserSession<'a>;

    fn session(&'a mut self) -> UserSession<'a> {
        let data = self.data;
        UserSession {
            handle: self,
            buffer: MutRawBytes::new(data, FILE_MAPPING_LEN)
        }
    }
}

impl Drop for UserHandle {
    fn drop(&mut self) {
        unsafe {
            GlobalDeleteAtom(self.file_mapping_atom);
            UnmapViewOfFile(self.data as *const c_void);
            CloseHandle(self.file_mapping);
        }
    }
}

pub struct UserSession<'a> {
    handle: &'a mut UserHandle,
    buffer: MutRawBytes,
}

impl<'a> Session for UserSession<'a> {
    fn read_bytes(&mut self, offset: u16, dest: *mut u8, len: usize) -> io::Result<usize> {
        self.buffer.write_rsd(offset, dest, len)
    }

    fn write_bytes(&mut self, offset: u16, src: *const u8, len: usize) -> io::Result<usize> {
        self.buffer.write_wsd(offset, src, len)
    }

    fn process(mut self) -> io::Result<usize> {
        unsafe {
            try!(self.buffer.write_header(&MsgHeader::TerminationMark));
            let send_result = SendMessageA(
                self.handle.handle,
                self.handle.msg_id,
                self.handle.file_mapping_atom as WinUInt,
                0);
            if send_result != FS6IPC_MESSAGE_SUCCESS {
                return Err(io::Error::new(io::ErrorKind::InvalidData, format!(
                    "FSUIPC rejected the requests with error {}; possible buffer corruption",
                    send_result)));
            }
            let mut buffer = RawBytes::new(self.handle.data, FILE_MAPPING_LEN);
            loop {
                let header = try!(buffer.read_header());
                match &header {
                    &MsgHeader::ReadStateData { offset: _, len, target } => {
                        let mut output = MutRawBytes::new(target, len);
                        try!(buffer.read_body(&header, &mut output));
                    },
                    &MsgHeader::WriteStateData { offset: _, len: _ } => {
                        let mut output = io::sink();
                        try!(buffer.read_body(&header, &mut output));
                    },
                    &MsgHeader::TerminationMark => return Ok(buffer.consumed()),
                }
            }
        }
    }
}

fn next_file_mapping_index() -> u32 {
    unsafe {
        let next = FILE_MAPPING_INDEX;
        FILE_MAPPING_INDEX += 1;
        next
    }
}

const FS6IPC_MESSAGE_SUCCESS: WinInt = 1;
const FILE_MAPPING_LEN: usize = 64*1024;

static mut FILE_MAPPING_INDEX: u32 = 0;
<|endoftext|>


<commit_before>use std::ffi::CString;
use libc;

pub fn c_string(s: &str) ->  CString {
    CString::new(s).unwrap()
}

pub fn string(raw: *const libc::c_char) -> String {
    unsafe {
        CString::from_raw(raw as *mut libc::c_char).into_string().unwrap()
    }
}
<commit_msg>Fix segfault bug<commit_after>use std::ffi::{CString,CStr};
use libc;

pub fn c_string(s: &str) ->  CString {
    CString::new(s).unwrap()
}

pub fn string(raw: *const libc::c_char) -> String {
    unsafe { CStr::from_ptr(raw).to_str().unwrap().to_owned() }
}
<|endoftext|>