<commit_before>extern crate unicode_names;

use std::fmt;

use irc::client::prelude::*;

use plugin::*;

use error::ErrorKind as FrippyErrorKind;
use error::FrippyError;
use failure::Fail;
use failure::ResultExt;

struct EmojiHandle {
    symbol: char,
    count: i32,
}

impl fmt::Display for EmojiHandle {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let name = match unicode_names::name(self.symbol) {
            Some(sym) => sym.to_string().to_lowercase(),
            None => String::from("UNKNOWN"),
        };

        if self.count > 1 {
            write!(f, "{}x {}", self.count, name)
        } else {
            write!(f, "{}", name)
        }
    }
}

#[derive(PluginName, Default, Debug)]
pub struct Emoji;

impl Emoji {
    pub fn new() -> Emoji {
        Emoji {}
    }

    fn emoji(&self, content: &str) -> Option<String> {
        let emojis = self.return_emojis(content);
        if emojis.is_empty() {
            None
        } else {
            Some(emojis
                .iter()
                .map(|e| e.to_string())
                .collect::<Vec<String>>()
                .join(", "))
        }
    }

    fn return_emojis(&self, string: &str) -> Vec<EmojiHandle> {
        let mut emojis: Vec<EmojiHandle> = Vec::new();

        let mut current = EmojiHandle {
            symbol: ' ',
            count: 0,
        };

        for c in string.chars() {
            if !self.is_emoji(&c) {
                continue;
            }

            if current.symbol == c {
                current.count += 1;
            } else {
                if current.count > 0 {
                    emojis.push(current);
                }

                current = EmojiHandle {
                    symbol: c,
                    count: 1,
                }
            }
        }

        if current.count > 0 {
            emojis.push(current);
        }

        emojis
    }

    fn is_emoji(&self, c: &char) -> bool {
        // Emoji ranges from stackoverflow:
        // https://stackoverflow.com/questions/30757193/find-out-if-character-in-string-is-emoji
        match *c { '\u{1F600}'...'\u{1F64F}'     // Emoticons
            | '\u{1F300}'...'\u{1F5FF}'          // Misc Symbols and Pictographs
            | '\u{1F680}'...'\u{1F6FF}'          // Transport and Map
            | '\u{2600}' ...'\u{26FF}'           // Misc symbols
            | '\u{2700}' ...'\u{27BF}'           // Dingbats
            | '\u{FE00}' ...'\u{FE0F}'           // Variation Selectors
            | '\u{1F900}'...'\u{1F9FF}'          // Supplemental Symbols and Pictographs
            | '\u{20D0}' ...'\u{20FF}' => true,  // Combining Diacritical Marks for Symbols
            _ => false,
        }
    }
}

impl Plugin for Emoji {
    fn execute(&self, client: &IrcClient, message: &Message) -> ExecutionStatus {
        match message.command {
            Command::PRIVMSG(_, ref content) => {
                if let Some(emojis) = self.emoji(content) {
                    match client
                        .send_privmsg(message.response_target().unwrap(), &emojis)
                        {
                            Ok(_) => ExecutionStatus::Done,
                            Err(e) => ExecutionStatus::Err(e.context(FrippyErrorKind::Connection).into()),
                        }
                } else {
                    ExecutionStatus::Done
                }
            },
            _ => ExecutionStatus::Done,
        }
    }

    fn execute_threaded(&self, _: &IrcClient, _: &Message) -> Result<(), FrippyError> {
        panic!("Emoji should not use threading")
    }

    fn command(&self, client: &IrcClient, command: PluginCommand) -> Result<(), FrippyError> {
        Ok(client
            .send_notice(
                &command.source,
                "This Plugin does not implement any commands.",
            )
            .context(FrippyErrorKind::Connection)?)
    }

    fn evaluate(&self, _: &IrcClient, command: PluginCommand) -> Result<String, String> {
        if let Some(emojis) = self.emoji(&command.tokens[0]) {
            Ok(emojis)
        } else {
            Err(String::from("No emojis were found."))
        }
    }
}
<commit_msg>Emoji: Add default to EmojiHandle<commit_after>extern crate unicode_names;

use std::fmt;

use irc::client::prelude::*;

use plugin::*;

use error::ErrorKind as FrippyErrorKind;
use error::FrippyError;
use failure::Fail;
use failure::ResultExt;

#[derive(Default, Debug)]
struct EmojiHandle {
    symbol: char,
    count: i32,
}

impl fmt::Display for EmojiHandle {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let name = match unicode_names::name(self.symbol) {
            Some(sym) => sym.to_string().to_lowercase(),
            None => String::from("UNKNOWN"),
        };

        if self.count > 1 {
            write!(f, "{}x {}", self.count, name)
        } else {
            write!(f, "{}", name)
        }
    }
}

#[derive(PluginName, Default, Debug)]
pub struct Emoji;

impl Emoji {
    pub fn new() -> Emoji {
        Emoji {}
    }

    fn emoji(&self, content: &str) -> Option<String> {
        let emojis = self.return_emojis(content);
        if emojis.is_empty() {
            None
        } else {
            Some(
                emojis
                    .iter()
                    .map(|e| e.to_string())
                    .collect::<Vec<String>>()
                    .join(", "),
            )
        }
    }

    fn return_emojis(&self, string: &str) -> Vec<EmojiHandle> {
        let mut emojis: Vec<EmojiHandle> = Vec::new();

        let mut current = EmojiHandle::default();

        for c in string.chars() {
            if !self.is_emoji(&c) {
                continue;
            }

            if current.symbol == c {
                current.count += 1;
            } else {
                if current.count > 0 {
                    emojis.push(current);
                }

                current = EmojiHandle {
                    symbol: c,
                    count: 1,
                }
            }
        }

        if current.count > 0 {
            emojis.push(current);
        }

        emojis
    }

    fn is_emoji(&self, c: &char) -> bool {
        // Emoji ranges from stackoverflow:
        // https://stackoverflow.com/questions/30757193/find-out-if-character-in-string-is-emoji
        match *c { '\u{1F600}'...'\u{1F64F}'     // Emoticons
            | '\u{1F300}'...'\u{1F5FF}'          // Misc Symbols and Pictographs
            | '\u{1F680}'...'\u{1F6FF}'          // Transport and Map
            | '\u{2600}' ...'\u{26FF}'           // Misc symbols
            | '\u{2700}' ...'\u{27BF}'           // Dingbats
            | '\u{FE00}' ...'\u{FE0F}'           // Variation Selectors
            | '\u{1F900}'...'\u{1F9FF}'          // Supplemental Symbols and Pictographs
            | '\u{20D0}' ...'\u{20FF}' => true,  // Combining Diacritical Marks for Symbols
            _ => false,
        }
    }
}

impl Plugin for Emoji {
    fn execute(&self, client: &IrcClient, message: &Message) -> ExecutionStatus {
        match message.command {
            Command::PRIVMSG(_, ref content) => {
                if let Some(emojis) = self.emoji(content) {
                    match client.send_privmsg(message.response_target().unwrap(), &emojis) {
                        Ok(_) => ExecutionStatus::Done,
                        Err(e) => {
                            ExecutionStatus::Err(e.context(FrippyErrorKind::Connection).into())
                        }
                    }
                } else {
                    ExecutionStatus::Done
                }
            }
            _ => ExecutionStatus::Done,
        }
    }

    fn execute_threaded(&self, _: &IrcClient, _: &Message) -> Result<(), FrippyError> {
        panic!("Emoji should not use threading")
    }

    fn command(&self, client: &IrcClient, command: PluginCommand) -> Result<(), FrippyError> {
        Ok(client
            .send_notice(
                &command.source,
                "This Plugin does not implement any commands.",
            )
            .context(FrippyErrorKind::Connection)?)
    }

    fn evaluate(&self, _: &IrcClient, command: PluginCommand) -> Result<String, String> {
        if let Some(emojis) = self.emoji(&command.tokens[0]) {
            Ok(emojis)
        } else {
            Err(String::from("No emojis were found."))
        }
    }
}
<|endoftext|>


<commit_before>use itertools::Itertools;

use crate::ram::schema::{Field, Schema};
use crate::ram::types;
use crate::ram::types::{type_id_of, u32_io, u8_io, SharedMap, Type, SharedValue};

use super::writer::{ARRAY_TYPE_MASK, NULL_PLACEHOLDER};
use std::collections::HashMap;
use dovahkiin::types::key_hash;

fn read_field(ptr: usize, field: &Field, selected: Option<&[u64]>) -> (SharedValue, usize) {
    let mut ptr = ptr;
    if field.nullable {
        let null_byte = *u8_io::read(ptr);
        ptr += 1;
        if null_byte == 1 {
            return (SharedValue::Null, ptr);
        }
    }
    if field.is_array {
        let len = *u32_io::read(ptr);
        trace!("Got array length {}", len);
        let mut sub_field = field.clone();
        sub_field.is_array = false;
        ptr += u32_io::size(ptr);
        if field.sub_fields.is_none() {
            // maybe primitive array
            let mut ptr = ptr;
            let val = types::get_shared_prim_array_val(field.type_id, len as usize, &mut ptr);
            info!("Got array {} length {}, subs {:?}, value {:?}", field.name, len, field.sub_fields, val);
            if let Some(prim_arr) = val {
                return (SharedValue::PrimArray(prim_arr), ptr);
            } else {
                panic!("type cannot been convert to prim array: {}", field.type_id)
            }
        } else {
            let mut vals = Vec::<SharedValue>::new();
            for _ in 0..len {
                let (nxt_val, nxt_ptr) = read_field(ptr, &sub_field, None);
                ptr = nxt_ptr;
                vals.push(nxt_val);
            }
            (SharedValue::Array(vals), ptr)
        }
    } else if let Some(ref subs) = field.sub_fields {
        let mut map = SharedMap::new();
        let mut selected_pos = 0;
        for sub in subs {
            let (cval, cptr) = read_field(ptr, &sub, selected);
            map.insert_key_id(sub.name_id, cval);
            ptr = cptr;
            match selected {
                None => {}
                Some(field_ids) => {
                    if field_ids[selected_pos] == sub.name_id {
                        selected_pos += 1;
                        if field_ids.len() <= selected_pos {
                            return (SharedValue::Map(map), ptr);
                        }
                    }
                }
            }
        }
        map.fields = subs.iter().map(|sub| &sub.name).cloned().collect();
        (SharedValue::Map(map), ptr)
    } else {
        (
            types::get_shared_val(field.type_id, ptr),
            ptr + types::get_size(field.type_id, ptr),
        )
    }
}

pub fn read_attach_dynamic_part(mut tail_ptr: usize, dest: &mut SharedValue) {
    let src = read_dynamic_value(&mut tail_ptr);
    if let &mut SharedValue::Map(ref mut map_dest) = dest {
        if let SharedValue::Map(mut map_src) = src {
            map_dest.fields.append(&mut map_src.fields);
            for (k, v) in map_src.map.into_iter() {
                map_dest.insert_key_id(k, v);
            }
        }
    }
}

fn read_dynamic_value(ptr: &mut usize) -> SharedValue {
    let type_id = types::get_shared_val(type_id_of(Type::U32), *ptr).u32().unwrap();
    let is_array = type_id & ARRAY_TYPE_MASK == ARRAY_TYPE_MASK;
    *ptr += types::u32_io::size(*ptr);
    if is_array {
        let base_type = type_id & (!ARRAY_TYPE_MASK);
        let len = types::get_shared_val(type_id_of(Type::U32), *ptr).u32().unwrap();
        *ptr += types::u32_io::size(*ptr);
        if base_type != 0 {
            // Primitive array
            if let Some(prim_arr) = types::get_shared_prim_array_val(base_type, *len as usize, ptr) {
                // ptr have been moved by `get_shared_prim_array_val`
                return SharedValue::PrimArray(prim_arr);
            } else {
                panic!("Cannot read prim array for dynamic field");
            }
        } else {
            let array = (0..*len).map(|_| read_dynamic_value(ptr)).collect();
            // ptr have been moved by recursion
            return SharedValue::Array(array);
        }
    } else if *type_id == 0{
        // Map
        let len = types::get_shared_val(type_id_of(Type::U32), *ptr).u32().unwrap();
        *ptr += types::u32_io::size(*ptr);
        let field_value_pair = (0..*len).map(|_| {
            let name = types::get_shared_val(type_id_of(Type::String), *ptr).string().unwrap();
            *ptr += types::string_io::size(*ptr);
            let value = read_dynamic_value(ptr);
            (name, value)
        })
        .collect_vec();
        let mut fields = Vec::with_capacity(field_value_pair.len());
        let mut map = HashMap::with_capacity(field_value_pair.len());
        for (name, value) in field_value_pair {
            let id = key_hash(&name);
            fields.push(name.to_owned());
            map.insert(id, value);
        }
        return SharedValue::Map(SharedMap { fields, map});
    } else if *type_id == NULL_PLACEHOLDER {
        return SharedValue::Null;
    } else {
        let value = types::get_shared_val(*type_id, *ptr);
        *ptr += types::get_size(*type_id, *ptr);
        return value;
    }
}

pub fn read_by_schema(ptr: usize, schema: &Schema) -> SharedValue {
    let (mut schema_value, tail_ptr) = read_field(ptr, &schema.fields, None);
    if schema.is_dynamic {
        read_attach_dynamic_part(tail_ptr, &mut schema_value)
    }
    schema_value
}

pub fn read_by_schema_selected(ptr: usize, schema: &Schema, fields: &[u64]) -> SharedValue {
    read_field(ptr, &schema.fields, Some(fields)).0
}
<commit_msg>removed logging<commit_after>use itertools::Itertools;

use crate::ram::schema::{Field, Schema};
use crate::ram::types;
use crate::ram::types::{type_id_of, u32_io, u8_io, SharedMap, Type, SharedValue};

use super::writer::{ARRAY_TYPE_MASK, NULL_PLACEHOLDER};
use std::collections::HashMap;
use dovahkiin::types::key_hash;

fn read_field(ptr: usize, field: &Field, selected: Option<&[u64]>) -> (SharedValue, usize) {
    let mut ptr = ptr;
    if field.nullable {
        let null_byte = *u8_io::read(ptr);
        ptr += 1;
        if null_byte == 1 {
            return (SharedValue::Null, ptr);
        }
    }
    if field.is_array {
        let len = *u32_io::read(ptr);
        trace!("Got array length {}", len);
        let mut sub_field = field.clone();
        sub_field.is_array = false;
        ptr += u32_io::size(ptr);
        if field.sub_fields.is_none() {
            // maybe primitive array
            let mut ptr = ptr;
            let val = types::get_shared_prim_array_val(field.type_id, len as usize, &mut ptr);
            if let Some(prim_arr) = val {
                return (SharedValue::PrimArray(prim_arr), ptr);
            } else {
                panic!("type cannot been convert to prim array: {}", field.type_id)
            }
        } else {
            let mut vals = Vec::<SharedValue>::new();
            for _ in 0..len {
                let (nxt_val, nxt_ptr) = read_field(ptr, &sub_field, None);
                ptr = nxt_ptr;
                vals.push(nxt_val);
            }
            (SharedValue::Array(vals), ptr)
        }
    } else if let Some(ref subs) = field.sub_fields {
        let mut map = SharedMap::new();
        let mut selected_pos = 0;
        for sub in subs {
            let (cval, cptr) = read_field(ptr, &sub, selected);
            map.insert_key_id(sub.name_id, cval);
            ptr = cptr;
            match selected {
                None => {}
                Some(field_ids) => {
                    if field_ids[selected_pos] == sub.name_id {
                        selected_pos += 1;
                        if field_ids.len() <= selected_pos {
                            return (SharedValue::Map(map), ptr);
                        }
                    }
                }
            }
        }
        map.fields = subs.iter().map(|sub| &sub.name).cloned().collect();
        (SharedValue::Map(map), ptr)
    } else {
        (
            types::get_shared_val(field.type_id, ptr),
            ptr + types::get_size(field.type_id, ptr),
        )
    }
}

pub fn read_attach_dynamic_part(mut tail_ptr: usize, dest: &mut SharedValue) {
    let src = read_dynamic_value(&mut tail_ptr);
    if let &mut SharedValue::Map(ref mut map_dest) = dest {
        if let SharedValue::Map(mut map_src) = src {
            map_dest.fields.append(&mut map_src.fields);
            for (k, v) in map_src.map.into_iter() {
                map_dest.insert_key_id(k, v);
            }
        }
    }
}

fn read_dynamic_value(ptr: &mut usize) -> SharedValue {
    let type_id = types::get_shared_val(type_id_of(Type::U32), *ptr).u32().unwrap();
    let is_array = type_id & ARRAY_TYPE_MASK == ARRAY_TYPE_MASK;
    *ptr += types::u32_io::size(*ptr);
    if is_array {
        let base_type = type_id & (!ARRAY_TYPE_MASK);
        let len = types::get_shared_val(type_id_of(Type::U32), *ptr).u32().unwrap();
        *ptr += types::u32_io::size(*ptr);
        if base_type != 0 {
            // Primitive array
            if let Some(prim_arr) = types::get_shared_prim_array_val(base_type, *len as usize, ptr) {
                // ptr have been moved by `get_shared_prim_array_val`
                return SharedValue::PrimArray(prim_arr);
            } else {
                panic!("Cannot read prim array for dynamic field");
            }
        } else {
            let array = (0..*len).map(|_| read_dynamic_value(ptr)).collect();
            // ptr have been moved by recursion
            return SharedValue::Array(array);
        }
    } else if *type_id == 0{
        // Map
        let len = types::get_shared_val(type_id_of(Type::U32), *ptr).u32().unwrap();
        *ptr += types::u32_io::size(*ptr);
        let field_value_pair = (0..*len).map(|_| {
            let name = types::get_shared_val(type_id_of(Type::String), *ptr).string().unwrap();
            *ptr += types::string_io::size(*ptr);
            let value = read_dynamic_value(ptr);
            (name, value)
        })
        .collect_vec();
        let mut fields = Vec::with_capacity(field_value_pair.len());
        let mut map = HashMap::with_capacity(field_value_pair.len());
        for (name, value) in field_value_pair {
            let id = key_hash(&name);
            fields.push(name.to_owned());
            map.insert(id, value);
        }
        return SharedValue::Map(SharedMap { fields, map});
    } else if *type_id == NULL_PLACEHOLDER {
        return SharedValue::Null;
    } else {
        let value = types::get_shared_val(*type_id, *ptr);
        *ptr += types::get_size(*type_id, *ptr);
        return value;
    }
}

pub fn read_by_schema(ptr: usize, schema: &Schema) -> SharedValue {
    let (mut schema_value, tail_ptr) = read_field(ptr, &schema.fields, None);
    if schema.is_dynamic {
        read_attach_dynamic_part(tail_ptr, &mut schema_value)
    }
    schema_value
}

pub fn read_by_schema_selected(ptr: usize, schema: &Schema, fields: &[u64]) -> SharedValue {
    read_field(ptr, &schema.fields, Some(fields)).0
}
<|endoftext|>


<commit_before>use std::sync::{Arc, Mutex};
use std::collections::HashMap;
use consts::WatchedEventType;
use proto::WatchedEvent;
use zookeeper::{ZkResult, ZooKeeper};
use zookeeper_ext::ZooKeeperExt;

pub type Data = HashMap<String, Arc<Vec<u8>>>;

pub struct PathChildrenCache {
    data: Arc<Mutex<Data>>
}

impl PathChildrenCache {

    fn get_children(zk: Arc<ZooKeeper>, path: &str, data: Arc<Mutex<Data>>) -> ZkResult<()> {

        let zk1 = zk.clone();
        let data1 = data.clone();

        let watcher = move |event: &WatchedEvent| {
            match event.event_type {
                WatchedEventType::NodeChildrenChanged => {
                    let path = event.path.as_ref().expect("Path absent");
                    // Subscribe to new changes recursively
                    let _ = Self::get_children(zk1, path, data1); // ignore errors
                },
                _ => error!("Unexpected: {:?}", event)
            };
            // Send change event
        };

        let children = try!(zk.get_children_w(&path, watcher));

        let mut data_locked = data.lock().unwrap();

        for child in children.iter() {
            let child_path = path.to_owned() + "/" + child;

            if !data_locked.contains_key(&child_path) {

                let child_data = Self::get_data(zk.clone(), &child_path, data.clone());

                data_locked.insert(child_path, Arc::new(child_data));
            }
        }

        debug!("New data: {:?}", *data_locked);

        Ok(())
    }

    fn get_data(zk: Arc<ZooKeeper>, path: &str, data: Arc<Mutex<Data>>) -> Vec<u8> {

        let zk1 = zk.clone();
        let path1 = path.to_owned();

        let data_watcher = move |event: &WatchedEvent| {
            let mut data_locked = data.lock().unwrap();
            match event.event_type {
                WatchedEventType::NodeDeleted => {
                    data_locked.remove(&path1);
                },
                WatchedEventType::NodeDataChanged => {
                    // Subscribe to new changes recursively
                    let child_data = Self::get_data(zk1, &path1, data.clone());
                    data_locked.insert(path1, Arc::new(child_data));
                },
                _ => error!("Unexpected: {:?}", event)
            };

            debug!("New data: {:?}", *data_locked);

            //TODO Send change event
        };

        zk.get_data_w(path, data_watcher).unwrap().0
    }

    pub fn new(zk: Arc<ZooKeeper>, path: &str) -> ZkResult<PathChildrenCache> {

        let data = Arc::new(Mutex::new(HashMap::new()));

        try!(zk.ensure_path(path));

        try!(Self::get_children(zk, path, data.clone()));

        Ok(PathChildrenCache{data: data})
    }

    pub fn get_current_data(&self) -> Data {
        self.data.lock().unwrap().clone()
    }

    pub fn clear(&self) {
        self.data.lock().unwrap().clear()
    }
}
<commit_msg>initial path children cache api<commit_after>use std::thread;
use std::sync::{Arc, Mutex};
use std::sync::mpsc;
use std::sync::mpsc::{Sender,Receiver};
use std::collections::HashMap;
use consts::WatchedEventType;
use proto::WatchedEvent;
use zookeeper::{ZkResult, ZooKeeper};
use zookeeper_ext::ZooKeeperExt;

pub type Data = HashMap<String, Arc<Vec<u8>>>;

pub struct ChildData;

pub enum PathChildrenCacheEvent {
    Initialized,
    ConnectionSuspended,
    ConnectionLost,
    ConnectionReconnected,
    ChildRemoved(ChildData),
    ChildAdded(ChildData),
    ChildUpdated(ChildData),
}

pub enum RefreshMode {
    Standard,
    ForceGetDataAndStat,
}

pub enum Operation {
    Refresh(RefreshMode),
    Event,
    GetData(String /* path */)
}

pub struct PathChildrenCache {
    zk: Arc<ZooKeeper>,
    data: Arc<Mutex<Data>>,
    worker_thread: Option<thread::JoinHandle<()>>,
    channel: Option<Sender<()>>,
}

impl PathChildrenCache {

    fn get_children(zk: Arc<ZooKeeper>, path: &str, data: Arc<Mutex<Data>>) -> ZkResult<()> {

        let zk1 = zk.clone();
        let data1 = data.clone();

        let watcher = move |event: &WatchedEvent| {
            match event.event_type {
                WatchedEventType::NodeChildrenChanged => {
                    let path = event.path.as_ref().expect("Path absent");
                    // Subscribe to new changes recursively
                    let _ = Self::get_children(zk1, path, data1); // ignore errors
                },
                _ => error!("Unexpected: {:?}", event)
            };
            // Send change event
        };

        let children = try!(zk.get_children_w(&path, watcher));

        let mut data_locked = data.lock().unwrap();

        for child in children.iter() {
            let child_path = path.to_owned() + "/" + child;

            if !data_locked.contains_key(&child_path) {

                let child_data = Self::get_data(zk.clone(), &child_path, data.clone());

                data_locked.insert(child_path, Arc::new(child_data));
            }
        }

        debug!("New data: {:?}", *data_locked);

        Ok(())
    }

    fn get_data(zk: Arc<ZooKeeper>, path: &str, data: Arc<Mutex<Data>>) -> Vec<u8> {
        let zk1 = zk.clone();
        let path1 = path.to_owned();

        let data_watcher = move |event: &WatchedEvent| {
            let mut data_locked = data.lock().unwrap();
            match event.event_type {
                WatchedEventType::NodeDeleted => {
                    data_locked.remove(&path1);
                },
                WatchedEventType::NodeDataChanged => {
                    // Subscribe to new changes recursively
                    let child_data = Self::get_data(zk1, &path1, data.clone());
                    data_locked.insert(path1, Arc::new(child_data));
                },
                _ => error!("Unexpected: {:?}", event)
            };

            debug!("New data: {:?}", *data_locked);

            //TODO Send change event
        };

        zk.get_data_w(path, data_watcher).unwrap().0
    }

    pub fn new(zk: Arc<ZooKeeper>, path: &str) -> ZkResult<PathChildrenCache> {

        let data = Arc::new(Mutex::new(HashMap::new()));

        try!(zk.ensure_path(path));

        try!(Self::get_children(zk.clone(), path, data.clone()));

        Ok(PathChildrenCache{
            zk: zk,
            data: data,
            worker_thread: None,
            channel: None,
        })
    }

    pub fn get_current_data(&self) -> Data {
        self.data.lock().unwrap().clone()
    }

    pub fn clear(&self) {
        self.data.lock().unwrap().clear()
    }

    pub fn start(&mut self) {
        let (tx, rx) = mpsc::channel();
        self.channel = Some(tx);

        self.worker_thread = Some(thread::spawn(move || {
            rx.recv();
        }));
    }
}
<|endoftext|>


<commit_before>#![allow(dead_code)]
// This file contains the memory allocator used by the rust_alloc module
//
// The implementation in this file is a simple first-fit allocator.
//
// Invariants:
// * All blocks will be a multiple of 16B
// * All blocks will be 16B-aligned
//
// TODO: lock free list

extern crate core;
use core::mem::{transmute_copy};

static mut START: usize = 0;
static mut END: usize = 0;

static mut free_list: *mut Block = (0 as *mut Block);

// memory block
#[repr(C, packed)]
struct Block {
    magic: usize, // If this is a free block, then it is magical: 0xCAFEFACE
    size: usize,
    next: *mut Block,
    prev: *mut Block,
}

impl Block {
    // returns true if this is a valid free block
    fn is_free(&self) -> bool { self.magic == 0xCAFEFACE && self.size % 0x10 == 0 }

    // split the block into two blocks. The first block will be of the
    // given size. size must be a multiple of 16. The block must be free
    unsafe fn split(&mut self, size: usize) {
        // check that the math works out
        if !self.is_free() {
            panic!("Attempt to split non-free block 0x{:X}",
                   (self as *const Block) as usize);
        }
        if !(size % 0x10 == 0) {
            panic!("Size is not a multiple of 16: {}", size);
        }
        if size >= self.size {
            panic!("Splitting block that is too small: 0x{:X}, size {}",
                   (self as *const Block) as usize, size);
        }

        // get new block addr
        let this: usize = self as *const Block as usize;
        let new_addr: *const Block = (this + size) as *const Block;

        // create new block and set magic bits
        let mut block: Block = core::mem::transmute_copy(&*new_addr);
        block.magic = 0xCAFEFACE;
        block.size = self.size - size;

        // adjust this block's metadata
        self.size = size;

        // insert at tail of free list
        Block::free_insert(&mut block);
    }

    // coalesce this block with the next one. The two blocks must be free
    unsafe fn combine(&mut self) {
        // check that both are free!
        if !self.is_free() {
            panic!("Attempt to coalesce non-free block 0x{:X}",
                   (self as *const Block) as usize);
        } else if !(*self.get_next()).is_free() {
            panic!("Attempt to coalesce non-free block 0x{:X}",
                   self.get_next() as *const Block as usize);
        }

        let next = self.get_next();

       // increase the size of this block
       self.size += (*next).size;

       // remove next block from free list
       (*next).remove();
    }

    // remove this block from the free list and return it. The block
    // must be free. After this operation, the block's magic word is
    // set to 0xDEADBEEF. The block must be free.
    unsafe fn remove(&mut self) {
        // TODO
    }

    // inserts the given block at the tail of the free list and sets
    // the magic bits. The block cannot already be free.
    unsafe fn insert(&mut self, block: &mut Block) {
        //TODO
    }

    // get the prev block in memory
    // NOTE: this is distinct from the prev block in the free list
    // behavior is undefined if this is the last block.
    unsafe fn get_prev(&self) -> *mut Block {
        //TODO
    }

    // get the next block in memory
    // NOTE: this is distinct from the next block in the free list
    // behavior is undefined if this is the last block.
    unsafe fn get_next(&self) -> *mut Block {
        if !self.is_free() {
            panic!("Attempt to get next block of non-free block 0x{:X}",
                   (self as *const Block) as usize);
        }

        //TODO: fixme
        // get address of next block
        let this = self as *const Block as usize;
        let next_block: Block =
            core::mem::transmute_copy(&*((this + self.size) as *mut Block));

        &mut next_block
    }
}

// Init the heap
pub fn init(start: usize, end: usize) {
    // Round to nearest multiple of 16
    unsafe {
        // round START up
        START = if (start & 0xF) == 0 {start} else {(start & !0xF) + 0x10};

        // round END down
        END = end & !0xF;

        // bounds check
        if END <= START {
            panic!("No heap space");
        }

        printf! ("In heap init\nstart addr: {:x}, end addr: {:x}\n", START, END);
    }

    // TODO: create first block and free list
}

/// Return a pointer to `size` bytes of memory aligned to `align`.
///
/// On failure, return a null pointer.
///
/// Behavior is undefined if the requested size is 0 or the alignment is not a
/// power of 2. The alignment must be no larger than the largest supported page
/// size on the platform.
pub unsafe fn malloc(size: usize, align: usize) -> *mut u8 {
    0 as *mut u8 // TODO
}

/// Deallocates the memory referenced by `ptr`.
///
/// The `ptr` parameter must not be null.
///
/// The `old_size` and `align` parameters are the parameters that were used to
/// create the allocation referenced by `ptr`. The `old_size` parameter may be
/// any value in range_inclusive(requested_size, usable_size).
pub unsafe fn free(ptr: *mut u8, old_size: usize) {

}

/// Returns the usable size of an allocation created with the specified the
/// `size` and `align`.
pub fn usable_size(size: usize, align: usize) -> usize {
    0 // TODO
}

/// Prints implementation-defined allocator statistics.
///
/// These statistics may be inconsistent if other threads use the allocator
/// during the call.
pub fn print_stats() {

}
<commit_msg>Working on heap<commit_after>#![allow(dead_code)]
// This file contains the memory allocator used by the rust_alloc module
//
// The implementation in this file is a simple first-fit allocator.
//
// Invariants:
// * All blocks will be a multiple of 16B
// * All blocks will be 16B-aligned
//
// TODO: lock free list

extern crate core;
use core::mem::{transmute_copy, size_of};

static mut START: usize = 0;
static mut END: usize = 0;

static mut free_list: *mut Block = (0 as *mut Block);

// memory block
// the last word of every block is its allocation size
#[repr(C, packed)]
struct Block {
    magic: usize, // If this is a free block, then it is magical: 0xCAFEFACE
    size: usize, // Includes the size of the footer
    next: *mut Block,
    prev: *mut Block,
}

impl Block {
    // METHODS FOR ALL BLOCKS

    // returns true if this is a valid free block
    fn is_free(&self) -> bool {
        self.magic == 0xCAFEFACE && self.size % 0x10 == 0
    }

    // get the prev block in memory
    //
    // note: this is distinct from the prev block in the free list
    // behavior is undefined if this is the last block.
    unsafe fn get_prev(&self) -> *mut Block {
        //TODO: deal with first block corner case
        // get the addr of previous block's size
        let prev_foot: *const usize = (self.this() - core::mem::size_of::<usize>()) as *const usize;
        let prev_size = *prev_foot;

        // get previous block's addr
        let prev: *mut Block = (self.this() - prev_size) as *mut Block;
    }

    // get the next block in memory
    //
    // note: this is distinct from the next block in the free list
    // behavior is undefined if this is the last block.
    unsafe fn get_next(&self) -> *mut Block {
        //TODO: deal with last block corner case
        (self.this() + self.size) as *mut Block
    }

    // Set the footer for this block. This method does not error checking, so
    // be careful!
    unsafe fn set_footer(&mut self, size: usize) {
        let footer = (self.this() + self.size - core::mem::size_of::<usize>()) as *mut Block
        *footer = size;
    }

    #[inline]
    unsafe fn this(&self) -> usize {
        self as *const Block as usize;
    }

    // METHODS FOR ONLY FREE BLOCKS

    // split the block into two blocks. The first block will be of the
    // given size. The block must be free
    unsafe fn split(&mut self, size: usize) {
        // check that the math works out
        if !self.is_free() {
            panic!("Attempt to split non-free block 0x{:X}",
                   (self as *const Block) as usize);
        }
        if round_to_16(size + core::mem::size_of::<usize>) >= self.size {
            panic!("Splitting block that is too small: 0x{:X}, size {}",
                   (self as *const Block) as usize, size);
        }

        // get new block addr
        let new_size = round_to_16(size + core::mem::size_of::<usize>);
        let new_addr = (self.this() + new_size) as *const Block;

        // create new block and set magic bits
        let mut block: Block = core::mem::transmute_copy(&*new_addr);
        block.magic = 0xCAFEFACE;
        block.size = self.size - new_size;

        // adjust this block's metadata
        self.size = new_size;

        // insert at tail of free list
        block.insert();
    }

    // coalesce this block with the next one. The two blocks must be free
    unsafe fn combine(&mut self) {
        // check that both are free!
        if !self.is_free() {
            panic!("Attempt to coalesce non-free block 0x{:X}",
                   (self as *const Block) as usize);
        } else if !(*self.get_next()).is_free() {
            panic!("Attempt to coalesce non-free block 0x{:X}",
                   self.get_next() as *const Block as usize);
        }

        let next = self.get_next();

       // increase the size of this block
       self.size += (*next).size + core::mem::size_of::<usize>();

       // remove next block from free list
       (*next).remove();
    }

    // remove this block from the free list and return it. The block
    // must be free. After this operation, the block's magic word is
    // set to 0xDEADBEEF. The block must be free.
    unsafe fn remove(&mut self) {
        // TODO
    }

    // METHODS FOR ONLY USED BLOCKS

    // inserts the given block at the tail of the free list and sets
    // the magic bits. The block cannot already be free.
    unsafe fn insert(&mut self) {
        //TODO
    }
}

// Init the heap
pub fn init(start: usize, end: usize) {
    // Round to nearest multiple of 16
    unsafe {
        // round START up
        START = if (start & 0xF) == 0 {start} else {(start & !0xF) + 0x10};

        // round END down
        END = end & !0xF;

        // bounds check
        if END <= START {
            panic!("No heap space");
        }

        printf! ("In heap init\nstart addr: {:x}, end addr: {:x}\n", START, END);
    }

    // TODO: create first block and free list
}

/// Return a pointer to `size` bytes of memory aligned to `align`.
///
/// On failure, return a null pointer.
///
/// Behavior is undefined if the requested size is 0 or the alignment is not a
/// power of 2. The alignment must be no larger than the largest supported page
/// size on the platform.
pub unsafe fn malloc(size: usize, align: usize) -> *mut u8 {
    0 as *mut u8 // TODO
}

/// Deallocates the memory referenced by `ptr`.
///
/// The `ptr` parameter must not be null.
///
/// The `old_size` and `align` parameters are the parameters that were used to
/// create the allocation referenced by `ptr`. The `old_size` parameter may be
/// any value in range_inclusive(requested_size, usable_size).
pub unsafe fn free(ptr: *mut u8, old_size: usize) {

}

/// Returns the usable size of an allocation created with the specified the
/// `size` and `align`.
pub fn usable_size(size: usize, align: usize) -> usize {
    0 // TODO
}

/// Prints implementation-defined allocator statistics.
///
/// These statistics may be inconsistent if other threads use the allocator
/// during the call.
pub fn print_stats() {

}
<|endoftext|>


<commit_before>#[macro_use]
extern crate glium;
extern crate image;

use glium::Surface;
use glium::glutin;
use glium::index::PrimitiveType;
use std::path::Path;

fn main() {
    use glium::DisplayBuild;

    // building the display, ie. the main object
    let display = glutin::WindowBuilder::new()
        .with_visibility(false)
        .build_glium()
        .unwrap();

    // building the vertex buffer, which contains all the vertices that we will draw
    let vertex_buffer = {
        #[derive(Copy, Clone)]
        struct Vertex {
            position: [f32; 2],
            color: [f32; 3],
        }

        implement_vertex!(Vertex, position, color);

        glium::VertexBuffer::new(&display,
            &[
                Vertex { position: [-0.5, -0.5], color: [0.0, 1.0, 0.0] },
                Vertex { position: [ 0.0,  0.5], color: [0.0, 0.0, 1.0] },
                Vertex { position: [ 0.5, -0.5], color: [1.0, 0.0, 0.0] },
            ]
        ).unwrap()
    };

    // building the index buffer
    let index_buffer = glium::IndexBuffer::new(&display, PrimitiveType::TrianglesList,
                                               &[0u16, 1, 2]).unwrap();

    // compiling shaders and linking them together
    let program = program!(&display,
        140 => {
            vertex: "
                #version 140

                uniform mat4 matrix;

                in vec2 position;
                in vec3 color;

                out vec3 vColor;

                void main() {
                    gl_Position = vec4(position, 0.0, 1.0) * matrix;
                    vColor = color;
                }
            ",

            fragment: "
                #version 140
                in vec3 vColor;
                out vec4 f_color;

                void main() {
                    f_color = vec4(vColor, 1.0);
                }
            "
        },

        110 => {
            vertex: "
                #version 110

                uniform mat4 matrix;

                attribute vec2 position;
                attribute vec3 color;

                varying vec3 vColor;

                void main() {
                    gl_Position = vec4(position, 0.0, 1.0) * matrix;
                    vColor = color;
                }
            ",

            fragment: "
                #version 110
                varying vec3 vColor;

                void main() {
                    gl_FragColor = vec4(vColor, 1.0);
                }
            ",
        },
    ).unwrap();

    // drawing once

    // building the uniforms
    let uniforms = uniform! {
        matrix: [
            [1.0, 0.0, 0.0, 0.0],
            [0.0, 1.0, 0.0, 0.0],
            [0.0, 0.0, 1.0, 0.0],
            [0.0, 0.0, 0.0, 1.0f32]
        ]
    };

    // drawing a frame
    let mut target = display.draw();
    target.clear_color(0.0, 0.0, 0.0, 0.0);
    target.draw(&vertex_buffer, &index_buffer, &program, &uniforms, &Default::default()).unwrap();
    target.finish().unwrap();

    // reading the front buffer into an image
    let image: glium::texture::RawImage2d<u8> = display.read_front_buffer();
    let image = image::ImageBuffer::from_raw(image.width, image.height, image.data.into_owned()).unwrap();
    let image = image::DynamicImage::ImageRgba8(image);
    let mut output = std::fs::File::create(&Path::new("glium-example-screenshot.png")).unwrap();
    image.save(&mut output, image::ImageFormat::PNG).unwrap();
}
<commit_msg>Fix image orientation in screenshot example<commit_after>#[macro_use]
extern crate glium;
extern crate image;

use glium::Surface;
use glium::glutin;
use glium::index::PrimitiveType;
use std::path::Path;

fn main() {
    use glium::DisplayBuild;

    // building the display, ie. the main object
    let display = glutin::WindowBuilder::new()
        .with_visibility(false)
        .build_glium()
        .unwrap();

    // building the vertex buffer, which contains all the vertices that we will draw
    let vertex_buffer = {
        #[derive(Copy, Clone)]
        struct Vertex {
            position: [f32; 2],
            color: [f32; 3],
        }

        implement_vertex!(Vertex, position, color);

        glium::VertexBuffer::new(&display,
            &[
                Vertex { position: [-0.5, -0.5], color: [0.0, 1.0, 0.0] },
                Vertex { position: [ 0.0,  0.5], color: [0.0, 0.0, 1.0] },
                Vertex { position: [ 0.5, -0.5], color: [1.0, 0.0, 0.0] },
            ]
        ).unwrap()
    };

    // building the index buffer
    let index_buffer = glium::IndexBuffer::new(&display, PrimitiveType::TrianglesList,
                                               &[0u16, 1, 2]).unwrap();

    // compiling shaders and linking them together
    let program = program!(&display,
        140 => {
            vertex: "
                #version 140

                uniform mat4 matrix;

                in vec2 position;
                in vec3 color;

                out vec3 vColor;

                void main() {
                    gl_Position = vec4(position, 0.0, 1.0) * matrix;
                    vColor = color;
                }
            ",

            fragment: "
                #version 140
                in vec3 vColor;
                out vec4 f_color;

                void main() {
                    f_color = vec4(vColor, 1.0);
                }
            "
        },

        110 => {
            vertex: "
                #version 110

                uniform mat4 matrix;

                attribute vec2 position;
                attribute vec3 color;

                varying vec3 vColor;

                void main() {
                    gl_Position = vec4(position, 0.0, 1.0) * matrix;
                    vColor = color;
                }
            ",

            fragment: "
                #version 110
                varying vec3 vColor;

                void main() {
                    gl_FragColor = vec4(vColor, 1.0);
                }
            ",
        },
    ).unwrap();

    // drawing once

    // building the uniforms
    let uniforms = uniform! {
        matrix: [
            [1.0, 0.0, 0.0, 0.0],
            [0.0, 1.0, 0.0, 0.0],
            [0.0, 0.0, 1.0, 0.0],
            [0.0, 0.0, 0.0, 1.0f32]
        ]
    };

    // drawing a frame
    let mut target = display.draw();
    target.clear_color(0.0, 0.0, 0.0, 0.0);
    target.draw(&vertex_buffer, &index_buffer, &program, &uniforms, &Default::default()).unwrap();
    target.finish().unwrap();

    // reading the front buffer into an image
    let image: glium::texture::RawImage2d<u8> = display.read_front_buffer();
    let image = image::ImageBuffer::from_raw(image.width, image.height, image.data.into_owned()).unwrap();
    let image = image::DynamicImage::ImageRgba8(image).flipv();
    let mut output = std::fs::File::create(&Path::new("glium-example-screenshot.png")).unwrap();
    image.save(&mut output, image::ImageFormat::PNG).unwrap();
}
<|endoftext|>


<commit_before>//! Example of using urlencoded
extern crate iron;
extern crate urlencoded;

use std::io::net::ip::Ipv4Addr;

use iron::{Iron, ServerT, Request, Response, Alloy};

use urlencoded::{UrlEncoded, Encoded};

// urlencoded returns a Hashmap
// Here we create a function to log the hashmap we are storing in Alloy.
// Alloy is where your middleware can store data and we access it through
// the `find` API exposed by alloy.
fn log_hashmap(req: &mut Request, res: &mut Response, alloy: &mut Alloy) {
    let hashmap = alloy.find::<Encoded>();
    match hashmap {
        Some(&Encoded(ref encoded)) => println!("Url Encoded:\n {}", encoded),
        None => ()
    }
}

// test out the server with `curl -i "127.0.0.1:3000/?name=franklin&name=trevor"`
fn main() {
    let mut server: ServerT = Iron::new();
    server.link(UrlEncoded::new());
    server.link(log_hashmap);
    server.listen(Ipv4Addr(127, 0, 0, 1), 3000);
}
<commit_msg>(refactor) Updated for chain architecture<commit_after>//! Example of using urlencoded
extern crate iron;
extern crate urlencoded;

use std::io::net::ip::Ipv4Addr;

use iron::{Iron, ServerT, Request, Response, Alloy, Chain};

use urlencoded::{UrlEncoded, Encoded};

// urlencoded returns a Hashmap
// Here we create a function to log the hashmap we are storing in Alloy.
// Alloy is where your middleware can store data and we access it through
// the `find` API exposed by alloy.
fn log_hashmap(req: &mut Request, res: &mut Response, alloy: &mut Alloy) {
    let hashmap = alloy.find::<Encoded>();
    match hashmap {
        Some(&Encoded(ref encoded)) => println!("Url Encoded:\n {}", encoded),
        None => ()
    }
}

// test out the server with `curl -i "127.0.0.1:3000/?name=franklin&name=trevor"`
fn main() {
    let mut server: ServerT = Iron::new();
    server.chain.link(UrlEncoded::new());
    server.chain.link(log_hashmap);
    server.listen(Ipv4Addr(127, 0, 0, 1), 3000);
}
<|endoftext|>


<commit_before>#![feature(plugin)]
#![plugin(clippy)]

#![deny(needless_lifetimes)]

fn distinct_lifetimes<'a, 'b>(_x: &'a u8, _y: &'b u8, _z: u8) { } //~ERROR

fn distinct_and_static<'a, 'b>(_x: &'a u8, _y: &'b u8, _z: &'static u8) { } //~ERROR

fn same_lifetime_on_input<'a>(_x: &'a u8, _y: &'a u8) { } // no error, same lifetime on two params

fn only_static_on_input(_x: &u8, _y: &u8, _z: &'static u8) { } // no error, static involved

fn in_and_out<'a>(x: &'a u8, _y: u8) -> &'a u8 { x } //~ERROR

fn multiple_in_and_out_1<'a>(x: &'a u8, _y: &'a u8) -> &'a u8 { x } // no error, multiple input refs

fn multiple_in_and_out_2<'a, 'b>(x: &'a u8, _y: &'b u8) -> &'a u8 { x } // no error, multiple input refs

fn in_static_and_out<'a>(x: &'a u8, _y: &'static u8) -> &'a u8 { x } // no error, static involved

fn deep_reference_1<'a, 'b>(x: &'a u8, _y: &'b u8) -> Result<&'a u8, ()> { Ok(x) } // no error

fn deep_reference_2<'a>(x: Result<&'a u8, &'a u8>) -> &'a u8 { x.unwrap() } // no error, two input refs

fn deep_reference_3<'a>(x: &'a u8, _y: u8) -> Result<&'a u8, ()> { Ok(x) } //~ERROR

type Ref<'r> = &'r u8;

fn lifetime_param_1<'a>(_x: Ref<'a>, _y: &'a u8) { }

fn lifetime_param_2<'a, 'b: 'a>(_x: Ref<'a>, _y: &'b u8) { } //~ERROR

struct X {
    x: u8,
}

impl X {
    fn self_and_out<'s>(&'s self) -> &'s u8 { &self.x } //~ERROR

    fn self_and_in_out<'s, 't>(&'s self, _x: &'t u8) -> &'s u8 { &self.x } // no error, multiple input refs

    fn distinct_self_and_in<'s, 't>(&'s self, _x: &'t u8) { } //~ERROR

    fn self_and_same_in<'s>(&'s self, _x: &'s u8) { } // no error, same lifetimes on two params
}

static STATIC: u8 = 1;

fn main() {
    distinct_lifetimes(&1, &2, 3);
    distinct_and_static(&1, &2, &STATIC);
    same_lifetime_on_input(&1, &2);
    only_static_on_input(&1, &2, &STATIC);
    in_and_out(&1, 2);
    multiple_in_and_out_1(&1, &2);
    multiple_in_and_out_2(&1, &2);
    in_static_and_out(&1, &STATIC);
    let _ = deep_reference_1(&1, &2);
    let _ = deep_reference_2(Ok(&1));
    let _ = deep_reference_3(&1, 2);
    lifetime_param_1(&1, &2);
    lifetime_param_2(&1, &2);

    let foo = X { x: 1 };
    foo.self_and_out();
    foo.self_and_in_out(&1);
    foo.distinct_self_and_in(&1);
    foo.self_and_same_in(&1);
}
<commit_msg>lifetimes test: use explicit message prefix<commit_after>#![feature(plugin)]
#![plugin(clippy)]

#![deny(needless_lifetimes)]

fn distinct_lifetimes<'a, 'b>(_x: &'a u8, _y: &'b u8, _z: u8) { }
//~^ERROR explicit lifetimes given

fn distinct_and_static<'a, 'b>(_x: &'a u8, _y: &'b u8, _z: &'static u8) { }
//~^ERROR explicit lifetimes given

fn same_lifetime_on_input<'a>(_x: &'a u8, _y: &'a u8) { } // no error, same lifetime on two params

fn only_static_on_input(_x: &u8, _y: &u8, _z: &'static u8) { } // no error, static involved

fn in_and_out<'a>(x: &'a u8, _y: u8) -> &'a u8 { x }
//~^ERROR explicit lifetimes given

fn multiple_in_and_out_1<'a>(x: &'a u8, _y: &'a u8) -> &'a u8 { x } // no error, multiple input refs

fn multiple_in_and_out_2<'a, 'b>(x: &'a u8, _y: &'b u8) -> &'a u8 { x } // no error, multiple input refs

fn in_static_and_out<'a>(x: &'a u8, _y: &'static u8) -> &'a u8 { x } // no error, static involved

fn deep_reference_1<'a, 'b>(x: &'a u8, _y: &'b u8) -> Result<&'a u8, ()> { Ok(x) } // no error

fn deep_reference_2<'a>(x: Result<&'a u8, &'a u8>) -> &'a u8 { x.unwrap() } // no error, two input refs

fn deep_reference_3<'a>(x: &'a u8, _y: u8) -> Result<&'a u8, ()> { Ok(x) }
//~^ERROR explicit lifetimes given

type Ref<'r> = &'r u8;

fn lifetime_param_1<'a>(_x: Ref<'a>, _y: &'a u8) { }

fn lifetime_param_2<'a, 'b: 'a>(_x: Ref<'a>, _y: &'b u8) { }
//~^ERROR explicit lifetimes given

struct X {
    x: u8,
}

impl X {
    fn self_and_out<'s>(&'s self) -> &'s u8 { &self.x }
    //~^ERROR explicit lifetimes given

    fn self_and_in_out<'s, 't>(&'s self, _x: &'t u8) -> &'s u8 { &self.x } // no error, multiple input refs

    fn distinct_self_and_in<'s, 't>(&'s self, _x: &'t u8) { }
    //~^ERROR explicit lifetimes given

    fn self_and_same_in<'s>(&'s self, _x: &'s u8) { } // no error, same lifetimes on two params
}

static STATIC: u8 = 1;

fn main() {
    distinct_lifetimes(&1, &2, 3);
    distinct_and_static(&1, &2, &STATIC);
    same_lifetime_on_input(&1, &2);
    only_static_on_input(&1, &2, &STATIC);
    in_and_out(&1, 2);
    multiple_in_and_out_1(&1, &2);
    multiple_in_and_out_2(&1, &2);
    in_static_and_out(&1, &STATIC);
    let _ = deep_reference_1(&1, &2);
    let _ = deep_reference_2(Ok(&1));
    let _ = deep_reference_3(&1, 2);
    lifetime_param_1(&1, &2);
    lifetime_param_2(&1, &2);

    let foo = X { x: 1 };
    foo.self_and_out();
    foo.self_and_in_out(&1);
    foo.distinct_self_and_in(&1);
    foo.self_and_same_in(&1);
}
<|endoftext|>


<commit_before>// Allow unstable items until Rust hits 1.0
#![feature(core)]
#![feature(io)]
#![feature(os)]
#![feature(env)]
#![feature(path)]

extern crate yaml;

use yaml::constructor::YamlStandardData;
use yaml::ffi::YamlEncoding;
use std::env;
use std::old_io::{File, BufferedReader};

fn match_utf8(filename: &str, expected: YamlStandardData) {
    match_file(YamlEncoding::YamlUtf8Encoding, filename, expected);
}

fn match_file(encoding: yaml::ffi::YamlEncoding, filename: &str, expected: YamlStandardData) {
    let mut args = env::args();
    let this_path = args.next().unwrap().into_string().unwrap();
    let file_path = Path::new(this_path).join("../../tests/source").join(filename);
    println!("{}", file_path.display());
    let mut reader = BufferedReader::new(File::open(&file_path));
    match yaml::parse_io(&mut reader, encoding) {
        Ok(docs) => if docs.len() == 1 {
            assert_eq!(docs.as_slice().first().unwrap(), &expected)
        } else {
            panic!("too many number of documents: {:?}", docs)
        },
        Err(e) => panic!("parse failure: {:?}", e)
    }
}

macro_rules! ystr{
    ($e: expr) => (
        YamlStandardData::YamlString($e.to_string())
    )
}

macro_rules! yint{
    ($e: expr) => (
        YamlStandardData::YamlInteger($e)
    )
}

macro_rules! yfloat{
    ($e: expr) => (
        YamlStandardData::YamlFloat($e)
    )
}

macro_rules! yseq{
    ($($e:expr),*) => (
        YamlStandardData::YamlSequence(vec![$(($e),)*])
    )
}

macro_rules! ymap{
    ($($k:expr => $v:expr),*) => (
        YamlStandardData::YamlMapping(vec![$((ystr!($k), $v),)*])
    )
}

macro_rules! y_cmp_map{
    ($($k:expr => $v:expr),*) => (
        YamlStandardData::YamlMapping(vec![$(($k, $v),)*])
    )
}

#[test]
fn sequence_of_scalars() {
    match_utf8("ball_players.yml", yseq![ystr!("Mark McGwire"), ystr!("Sammy Sosa"), ystr!("Ken Griffey")]);
}

#[test]
fn scalar_mappings() {
    match_utf8("player_stat.yml", ymap!{
                                    "hr" => yint!(65),
                                    "avg" => yfloat!(0.278),
                                    "rbi" => yint!(147)
                                })
}

#[test]
fn maps_of_sequences() {
    match_utf8("ball_clubs.yml", ymap!{
                                    "american" => yseq![ystr!("Boston Red Sox"), ystr!("Detroit Tigers"), ystr!("New York Yankees")],
                                    "national" => yseq![ystr!("New York Mets"), ystr!("Chicago Cubs"), ystr!("Atlanta Braves")]
                                })
}

#[test]
fn sequence_of_maps() {
    match_utf8("multiple_player_stat.yml",
    yseq![
        ymap!{
            "name" => ystr!("Mark McGwire"),
            "hr" => yint!(65)
        },
        ymap!{
            "name" => ystr!("Sammy Sosa"),
            "hr" => yint!(63)
        }
    ])
}

#[test]
fn sequence_of_sequences() {
    match_utf8("csv.yml",
    yseq![
        yseq![ystr!("name"), ystr!("hr")],
        yseq![ystr!("Mark McGwire"), yint!(65)],
        yseq![ystr!("Sammy Sosa"), yint!(63)]
    ])
}

#[test]
fn mapping_of_mappings() {
    match_utf8("map_map.yml",
    ymap!{
        "Mark McGwire" => ymap!{ "hr" => yint!(65) },
        "Sammy Sosa" => ymap!{ "hr" => yint!(63) }
    })
}

#[test]
fn alias() {
    match_utf8("alias.yml",
    ymap!{
        "hr" => yseq![ystr!("Mark McGwire"), ystr!("Sammy Sosa")],
        "rbi" => yseq![ystr!("Sammy Sosa"), ystr!("Ken Griffey")]
    })
}

#[test]
fn complex_keys() {
    match_utf8("complex_key.yml",
    y_cmp_map!{
        yseq![ystr!("Detroit Tigers"), ystr!("Chicago Cubs")] => yseq![ystr!("2001-07-23")],
        yseq![ystr!("New York Yankees"), ystr!("Atlanta Braves")] => yseq![ystr!("2001-07-02"), ystr!("2001-08-12"), ystr!("2001-08-14")]
    })
}

#[test]
fn block_literal() {
    match_utf8("block_literal.yml", ystr!("\\//||\\/||\n// ||  ||__\n"))
}

#[test]
fn plain_scalar() {
    match_utf8("plain_scalar.yml", ystr!("Mark McGwire's year was crippled by a knee injury."))
}

#[test]
fn quoted_scalar() {
    match_utf8("quoted_scalar.yml",
    ymap!{
        "unicode" => ystr!("Sosa did fine.\u{263A}"),
        "control" => ystr!("\x081998\t1999\t2000\n"),
        "hexesc" =>  ystr!("\x13\x10 is \r\n"),
        "single" => ystr!(r#""Howdy!" he cried."#),
        "quoted" => ystr!(" # not a 'comment'."),
        "tie-fighter" => ystr!(r"|\-*-/|")
    })
}

#[test]
fn multi_line_scalar() {
    match_utf8("multi_line_scalar.yml",
    ymap!{
        "plain" => ystr!("This unquoted scalar spans many lines."),
        "quoted" => ystr!("So does this quoted scalar.\n")
    })
}

#[test]
fn utf16le() {
    match_file(YamlEncoding::YamlUtf16LeEncoding, "utf16le.yml",
               yseq![ystr!("Hello"), ystr!("世界")]
    )
}

#[test]
fn utf16be() {
    match_file(YamlEncoding::YamlUtf16BeEncoding, "utf16be.yml",
               yseq![ystr!("Hello"), ystr!("世界")]
    )
}
<commit_msg>Rust changes: std::env::args() is Iterator<Item=String><commit_after>// Allow unstable items until Rust hits 1.0
#![feature(core)]
#![feature(io)]
#![feature(os)]
#![feature(env)]
#![feature(path)]

extern crate yaml;

use yaml::constructor::YamlStandardData;
use yaml::ffi::YamlEncoding;
use std::env;
use std::old_io::{File, BufferedReader};

fn match_utf8(filename: &str, expected: YamlStandardData) {
    match_file(YamlEncoding::YamlUtf8Encoding, filename, expected);
}

fn match_file(encoding: yaml::ffi::YamlEncoding, filename: &str, expected: YamlStandardData) {
    let mut args = env::args();
    let this_path = args.next().unwrap();
    let file_path = Path::new(this_path).join("../../tests/source").join(filename);
    println!("{}", file_path.display());
    let mut reader = BufferedReader::new(File::open(&file_path));
    match yaml::parse_io(&mut reader, encoding) {
        Ok(docs) => if docs.len() == 1 {
            assert_eq!(docs.as_slice().first().unwrap(), &expected)
        } else {
            panic!("too many number of documents: {:?}", docs)
        },
        Err(e) => panic!("parse failure: {:?}", e)
    }
}

macro_rules! ystr{
    ($e: expr) => (
        YamlStandardData::YamlString($e.to_string())
    )
}

macro_rules! yint{
    ($e: expr) => (
        YamlStandardData::YamlInteger($e)
    )
}

macro_rules! yfloat{
    ($e: expr) => (
        YamlStandardData::YamlFloat($e)
    )
}

macro_rules! yseq{
    ($($e:expr),*) => (
        YamlStandardData::YamlSequence(vec![$(($e),)*])
    )
}

macro_rules! ymap{
    ($($k:expr => $v:expr),*) => (
        YamlStandardData::YamlMapping(vec![$((ystr!($k), $v),)*])
    )
}

macro_rules! y_cmp_map{
    ($($k:expr => $v:expr),*) => (
        YamlStandardData::YamlMapping(vec![$(($k, $v),)*])
    )
}

#[test]
fn sequence_of_scalars() {
    match_utf8("ball_players.yml", yseq![ystr!("Mark McGwire"), ystr!("Sammy Sosa"), ystr!("Ken Griffey")]);
}

#[test]
fn scalar_mappings() {
    match_utf8("player_stat.yml", ymap!{
                                    "hr" => yint!(65),
                                    "avg" => yfloat!(0.278),
                                    "rbi" => yint!(147)
                                })
}

#[test]
fn maps_of_sequences() {
    match_utf8("ball_clubs.yml", ymap!{
                                    "american" => yseq![ystr!("Boston Red Sox"), ystr!("Detroit Tigers"), ystr!("New York Yankees")],
                                    "national" => yseq![ystr!("New York Mets"), ystr!("Chicago Cubs"), ystr!("Atlanta Braves")]
                                })
}

#[test]
fn sequence_of_maps() {
    match_utf8("multiple_player_stat.yml",
    yseq![
        ymap!{
            "name" => ystr!("Mark McGwire"),
            "hr" => yint!(65)
        },
        ymap!{
            "name" => ystr!("Sammy Sosa"),
            "hr" => yint!(63)
        }
    ])
}

#[test]
fn sequence_of_sequences() {
    match_utf8("csv.yml",
    yseq![
        yseq![ystr!("name"), ystr!("hr")],
        yseq![ystr!("Mark McGwire"), yint!(65)],
        yseq![ystr!("Sammy Sosa"), yint!(63)]
    ])
}

#[test]
fn mapping_of_mappings() {
    match_utf8("map_map.yml",
    ymap!{
        "Mark McGwire" => ymap!{ "hr" => yint!(65) },
        "Sammy Sosa" => ymap!{ "hr" => yint!(63) }
    })
}

#[test]
fn alias() {
    match_utf8("alias.yml",
    ymap!{
        "hr" => yseq![ystr!("Mark McGwire"), ystr!("Sammy Sosa")],
        "rbi" => yseq![ystr!("Sammy Sosa"), ystr!("Ken Griffey")]
    })
}

#[test]
fn complex_keys() {
    match_utf8("complex_key.yml",
    y_cmp_map!{
        yseq![ystr!("Detroit Tigers"), ystr!("Chicago Cubs")] => yseq![ystr!("2001-07-23")],
        yseq![ystr!("New York Yankees"), ystr!("Atlanta Braves")] => yseq![ystr!("2001-07-02"), ystr!("2001-08-12"), ystr!("2001-08-14")]
    })
}

#[test]
fn block_literal() {
    match_utf8("block_literal.yml", ystr!("\\//||\\/||\n// ||  ||__\n"))
}

#[test]
fn plain_scalar() {
    match_utf8("plain_scalar.yml", ystr!("Mark McGwire's year was crippled by a knee injury."))
}

#[test]
fn quoted_scalar() {
    match_utf8("quoted_scalar.yml",
    ymap!{
        "unicode" => ystr!("Sosa did fine.\u{263A}"),
        "control" => ystr!("\x081998\t1999\t2000\n"),
        "hexesc" =>  ystr!("\x13\x10 is \r\n"),
        "single" => ystr!(r#""Howdy!" he cried."#),
        "quoted" => ystr!(" # not a 'comment'."),
        "tie-fighter" => ystr!(r"|\-*-/|")
    })
}

#[test]
fn multi_line_scalar() {
    match_utf8("multi_line_scalar.yml",
    ymap!{
        "plain" => ystr!("This unquoted scalar spans many lines."),
        "quoted" => ystr!("So does this quoted scalar.\n")
    })
}

#[test]
fn utf16le() {
    match_file(YamlEncoding::YamlUtf16LeEncoding, "utf16le.yml",
               yseq![ystr!("Hello"), ystr!("世界")]
    )
}

#[test]
fn utf16be() {
    match_file(YamlEncoding::YamlUtf16BeEncoding, "utf16be.yml",
               yseq![ystr!("Hello"), ystr!("世界")]
    )
}
<|endoftext|>


<commit_before>use crate::{codegen::general, env::Env, file_saver::save_to_file};
use log::info;
use regex::Regex;
use std::{
    io::{Result, Write},
    path::Path,
};

pub fn generate(env: &Env) {
    info!(
        "Generating sys build script for {}",
        env.config.library_name
    );

    let path = env.config.target_path.join("build.rs");

    info!("Generating file {:?}", path);
    save_to_file(&path, env.config.make_backup, |w| {
        generate_build_script(w, env)
    });
}

fn generate_build_script(w: &mut dyn Write, env: &Env) -> Result<()> {
    general::start_comments(w, &env.config)?;
    writeln!(w)?;
    write!(
        w,
        "{}",
        r##"extern crate pkg_config;

use pkg_config::{Config, Error};
use std::env;
use std::io::prelude::*;
use std::io;
use std::process;

fn main() {
    if let Err(s) = find() {
        let _ = writeln!(io::stderr(), "{}", s);
        process::exit(1);
    }
}

fn find() -> Result<(), Error> {
"##
    )?;

    let ns = env.namespaces.main();
    let regex = Regex::new(r"^lib(.+)\.(so.*|dylib)$").expect("Regex failed");
    let shared_libs: Vec<_> = ns
        .shared_libs
        .iter()
        .map(|s| {
            let lib_path = Path::new(s);
            let lib_file_name = lib_path
                .file_name()
                .expect("A 'shared-library' in the GIR file has an invalid form")
                .to_str()
                .expect("Failed to convert OsStr to str");
            regex.replace(lib_file_name, "\"$1\"")
        })
        .collect();

    writeln!(
        w,
        "\tlet package_name = \"{}\";",
        ns.package_name
            .as_ref()
            .expect("Package name doesn't exist")
    )?;
    writeln!(w, "\tlet shared_libs = [{}];", shared_libs.join(", "))?;
    write!(w, "\tlet version = ")?;
    let versions = ns
        .versions
        .iter()
        .filter(|v| **v >= env.config.min_cfg_version)
        .skip(1)
        .collect::<Vec<_>>();
    for v in versions.iter().rev() {
        write!(w, "if cfg!({}) {{\n\t\t\"{}\"\n\t}} else ", v.to_cfg(), v)?;
    }
    writeln!(w, "{{\n\t\t\"{}\"\n\t}};", env.config.min_cfg_version)?;

    writeln!(
        w,
        "{}",
        r##"
    if let Ok(inc_dir) = env::var("GTK_INCLUDE_DIR") {
        println!("cargo:include={}", inc_dir);
    }
    if let Ok(lib_dir) = env::var("GTK_LIB_DIR") {
        for lib_ in shared_libs.iter() {
            println!("cargo:rustc-link-lib=dylib={}", lib_);
        }
        println!("cargo:rustc-link-search=native={}", lib_dir);
        return Ok(())
    }

    let target = env::var("TARGET").expect("TARGET environment variable doesn't exist");
    let hardcode_shared_libs = target.contains("windows");

    let mut config = Config::new();
    config.atleast_version(version);
    config.print_system_libs(false);
    if hardcode_shared_libs {
        config.cargo_metadata(false);
    }
    match config.probe(package_name) {
        Ok(library) => {
            if let Ok(paths) = std::env::join_paths(library.include_paths) {
                println!("cargo:include={}", paths.to_string_lossy());
            }
            if hardcode_shared_libs {
                for lib_ in shared_libs.iter() {
                    println!("cargo:rustc-link-lib=dylib={}", lib_);
                }
                for path in library.link_paths.iter() {
                    println!("cargo:rustc-link-search=native={}",
                             path.to_str().expect("library path doesn't exist"));
                }
            }
            Ok(())
        }
        Err(Error::EnvNoPkgConfig(_)) | Err(Error::Command { .. }) => {
            for lib_ in shared_libs.iter() {
                println!("cargo:rustc-link-lib=dylib={}", lib_);
            }
            Ok(())
        }
        Err(err) => Err(err),
    }
}
"##
    )
}
<commit_msg>Add warning to gobject-sys's build script<commit_after>use crate::{codegen::general, env::Env, file_saver::save_to_file};
use log::info;
use regex::Regex;
use std::{
    io::{Result, Write},
    path::Path,
};

pub fn generate(env: &Env) {
    info!(
        "Generating sys build script for {}",
        env.config.library_name
    );

    let path = env.config.target_path.join("build.rs");

    info!("Generating file {:?}", path);
    save_to_file(&path, env.config.make_backup, |w| {
        generate_build_script(w, env)
    });
}

fn generate_build_script(w: &mut dyn Write, env: &Env) -> Result<()> {
    general::start_comments(w, &env.config)?;
    writeln!(w)?;
    write!(
        w,
        "{}",
        r##"extern crate pkg_config;

use pkg_config::{Config, Error};
use std::env;
use std::io::prelude::*;
use std::io;
use std::process;

fn main() {
    if let Err(s) = find() {
        let _ = writeln!(io::stderr(), "{}", s);
        process::exit(1);
    }
}

fn find() -> Result<(), Error> {
"##
    )?;

    let ns = env.namespaces.main();
    let regex = Regex::new(r"^lib(.+)\.(so.*|dylib)$").expect("Regex failed");
    let shared_libs: Vec<_> = ns
        .shared_libs
        .iter()
        .map(|s| {
            let lib_path = Path::new(s);
            let lib_file_name = lib_path
                .file_name()
                .expect("A 'shared-library' in the GIR file has an invalid form")
                .to_str()
                .expect("Failed to convert OsStr to str");
            regex.replace(lib_file_name, "\"$1\"")
        })
        .collect();

    writeln!(
        w,
        "\tlet package_name = \"{}\";",
        ns.package_name
            .as_ref()
            .expect("Package name doesn't exist")
    )?;
    writeln!(w, "\tlet shared_libs = [{}];", shared_libs.join(", "))?;
    write!(w, "\tlet version = ")?;
    let versions = ns
        .versions
        .iter()
        .filter(|v| **v >= env.config.min_cfg_version)
        .skip(1)
        .collect::<Vec<_>>();
    for v in versions.iter().rev() {
        write!(w, "if cfg!({}) {{\n\t\t\"{}\"\n\t}} else ", v.to_cfg(), v)?;
    }
    writeln!(w, "{{\n\t\t\"{}\"\n\t}};", env.config.min_cfg_version)?;

    writeln!(
        w,
        "{}",
        r##"
    if let Ok(inc_dir) = env::var("GTK_INCLUDE_DIR") {
        println!("cargo:include={}", inc_dir);
    }
    if let Ok(lib_dir) = env::var("GTK_LIB_DIR") {
        for lib_ in shared_libs.iter() {
            println!("cargo:rustc-link-lib=dylib={}", lib_);
        }
        println!("cargo:rustc-link-search=native={}", lib_dir);
        return Ok(())
    }

    let target = env::var("TARGET").expect("TARGET environment variable doesn't exist");
    let hardcode_shared_libs = target.contains("windows");

    let mut config = Config::new();
    config.atleast_version(version);
    config.print_system_libs(false);
    if hardcode_shared_libs {
        config.cargo_metadata(false);
    }
    match config.probe(package_name) {
        Ok(library) => {
            if let Ok(paths) = std::env::join_paths(library.include_paths) {
                println!("cargo:include={}", paths.to_string_lossy());
            }
            if hardcode_shared_libs {
                for lib_ in shared_libs.iter() {
                    println!("cargo:rustc-link-lib=dylib={}", lib_);
                }
                for path in library.link_paths.iter() {
                    println!("cargo:rustc-link-search=native={}",
                             path.to_str().expect("library path doesn't exist"));
                }
            }
            Ok(())
        }
        Err(Error::EnvNoPkgConfig(_)) | Err(Error::Command { .. }) => {
            for lib_ in shared_libs.iter() {
                println!("cargo:rustc-link-lib=dylib={}", lib_);
            }
            Ok(())
        }"##
    )?;
    if ns.name == "GObject" {
        writeln!(w,"{}", r##"        Err(err) => {
            #[cfg(target_os = "macos")]
            {
                let _ = writeln!(
                    io::stderr(),
                    "Failed to run pkg-config\n\
                     If you're using homebrew, try running `brew info libffi` and follow the instructions.\n\
                     See https://github.com/Homebrew/homebrew-core/issues/40179 for more details\n"
                );
            }
            Err(err)
        }
    }
}
"##)
    } else {
        writeln!(
            w,
            "{}",
            r##"        Err(err) => Err(err),
    }
}
"##
        )
    }
}
<|endoftext|>


<commit_before>use std::path::PathBuf;
use std::result::Result as RResult;

use toml::{Parser, Value};

/**
 * Errors which are related to configuration-file loading
 */
pub mod error {
    use std::error::Error;
    use std::fmt::{Display, Formatter};
    use std::fmt::Error as FmtError;

    /**
     * The kind of an error
     */
    #[derive(Clone, Debug, PartialEq)]
    pub enum ConfigErrorKind {
        ConfigParsingFailed,
        NoConfigFileFound,
    }

    /**
     * Configuration error type
     */
    #[derive(Debug)]
    pub struct ConfigError {
        kind: ConfigErrorKind,
        cause: Option<Box<Error>>,
    }

    impl ConfigError {

        /**
         * Instantiate a new ConfigError, optionally with cause
         */
        pub fn new(kind: ConfigErrorKind, cause: Option<Box<Error>>) -> ConfigError {
            ConfigError {
                kind: kind,
                cause: cause,
            }
        }

        /**
         * get the Kind of the Error
         */
        pub fn kind(&self) -> ConfigErrorKind {
            self.kind.clone()
        }

        /**
         * Get the string, the ConfigError can be described with
         */
        pub fn as_str(e: &ConfigError) -> &'static str {
            match e.kind() {
                ConfigErrorKind::ConfigParsingFailed => "Config parsing failed",
                ConfigErrorKind::NoConfigFileFound   => "No config file found",
            }
        }

    }

    impl Display for ConfigError {

        fn fmt(&self, fmt: &mut Formatter) -> Result<(), FmtError> {
            try!(write!(fmt, "{}", ConfigError::as_str(self)));
            Ok(())
        }

    }

    impl Error for ConfigError {

        fn description(&self) -> &str {
            ConfigError::as_str(self)
        }

        fn cause(&self) -> Option<&Error> {
            self.cause.as_ref().map(|e| &**e)
        }

    }

}

use self::error::{ConfigError, ConfigErrorKind};

/**
 * Result type of this module. Either T or ConfigError
 */
pub type Result<T> = RResult<T, ConfigError>;

/**
 * Configuration object
 *
 * Holds all config variables which are globally available plus the configuration object from the
 * config parser, which can be accessed.
 */
#[derive(Debug)]
pub struct Configuration {

    /**
     * The plain configuration object for direct access if necessary
     */
    config: Value,

    /**
     * The verbosity the program should run with
     */
    verbosity: bool,

    /**
     * The editor which should be used
     */
    editor: Option<String>,

    /**
     * The options the editor should get when opening some file
     */
    editor_opts: String,
}

impl Configuration {

    /**
     * Get a new configuration object.
     *
     * The passed runtimepath is used for searching the configuration file, whereas several file
     * names are tested. If that does not work, the home directory and the XDG basedir are tested
     * with all variants.
     *
     * If that doesn't work either, an error is returned.
     */
    pub fn new(rtp: &PathBuf) -> Result<Configuration> {
        fetch_config(&rtp).map(|cfg| {
            let verbosity   = get_verbosity(&cfg);
            let editor      = get_editor(&cfg);
            let editor_opts = get_editor_opts(&cfg);

            debug!("Building configuration");
            debug!("  - verbosity  : {:?}", verbosity);
            debug!("  - editor     : {:?}", editor);
            debug!("  - editor-opts: {}", editor_opts);

            Configuration {
                config: cfg,
                verbosity: verbosity,
                editor: editor,
                editor_opts: editor_opts,
            }
        })
    }

    pub fn editor(&self) -> Option<&String> {
        self.editor.as_ref()
    }

    pub fn config(&self) -> &Value {
        &self.config
    }

    pub fn store_config(&self) -> Option<&Value> {
        match &self.config {
            &Value::Table(ref tabl) => tabl.get("store"),
            _ => None,
        }
    }

}

fn get_verbosity(v: &Value) -> bool {
    match v {
        &Value::Table(ref t) => t.get("verbose")
                .map(|v| match v { &Value::Boolean(b) => b, _ => false, })
                .unwrap_or(false),
        _ => false,
    }
}

fn get_editor(v: &Value) -> Option<String> {
    match v {
        &Value::Table(ref t) => t.get("editor")
                .and_then(|v| match v { &Value::String(ref s) => Some(s.clone()), _ => None, }),
        _ => None,
    }
}

fn get_editor_opts(v: &Value) -> String {
    match v {
        &Value::Table(ref t) => t.get("editor-opts")
                .and_then(|v| match v { &Value::String(ref s) => Some(s.clone()), _ => None, })
                .unwrap_or(String::new()),
        _ => String::new(),
    }
}

/**
 * Helper to fetch the config file
 *
 * Tests several variants for the config file path and uses the first one which works.
 */
fn fetch_config(rtp: &PathBuf) -> Result<Value> {
    use std::env;
    use std::fs::File;
    use std::io::Read;
    use std::io::Write;
    use std::io::stderr;

    use xdg_basedir;
    use itertools::Itertools;

    use libimagutil::variants::generate_variants as gen_vars;

    let variants = vec!["config", "config.toml", "imagrc", "imagrc.toml"];
    let modifier = |base: &PathBuf, v: &'static str| {
        let mut base = base.clone();
        base.push(format!("{}", v));
        base
    };

    vec![
        gen_vars(rtp.clone(), variants.clone(), &modifier),

        env::var("HOME").map(|home| gen_vars(PathBuf::from(home), variants.clone(), &modifier))
                        .unwrap_or(vec![]),

        xdg_basedir::get_data_home().map(|data_dir| gen_vars(data_dir, variants.clone(), &modifier))
                                    .unwrap_or(vec![]),
    ].iter()
        .flatten()
        .filter(|path| path.exists() && path.is_file())
        .map(|path| {
            let content = {
                let mut s = String::new();
                let f = File::open(path);
                if f.is_err() {
                }
                let mut f = f.unwrap();
                f.read_to_string(&mut s).ok();
                s
            };
            let mut parser = Parser::new(&content[..]);
            let res = parser.parse();
            if res.is_none() {
                write!(stderr(), "Config file parser error:");
                for error in parser.errors {
                    write!(stderr(), "At [{}][{}] <> {}", error.lo, error.hi, error);
                    write!(stderr(), "in: '{}'", &content[error.lo..error.hi]);
                }
                None
            } else {
                res
            }
        })
        .filter(|loaded| loaded.is_some())
        .nth(0)
        .map(|inner| Value::Table(inner.unwrap()))
        .ok_or(ConfigError::new(ConfigErrorKind::NoConfigFileFound, None))
}

<commit_msg>impl Deref for Configuration<commit_after>use std::path::PathBuf;
use std::result::Result as RResult;
use std::ops::Deref;

use toml::{Parser, Value};

/**
 * Errors which are related to configuration-file loading
 */
pub mod error {
    use std::error::Error;
    use std::fmt::{Display, Formatter};
    use std::fmt::Error as FmtError;

    /**
     * The kind of an error
     */
    #[derive(Clone, Debug, PartialEq)]
    pub enum ConfigErrorKind {
        ConfigParsingFailed,
        NoConfigFileFound,
    }

    /**
     * Configuration error type
     */
    #[derive(Debug)]
    pub struct ConfigError {
        kind: ConfigErrorKind,
        cause: Option<Box<Error>>,
    }

    impl ConfigError {

        /**
         * Instantiate a new ConfigError, optionally with cause
         */
        pub fn new(kind: ConfigErrorKind, cause: Option<Box<Error>>) -> ConfigError {
            ConfigError {
                kind: kind,
                cause: cause,
            }
        }

        /**
         * get the Kind of the Error
         */
        pub fn kind(&self) -> ConfigErrorKind {
            self.kind.clone()
        }

        /**
         * Get the string, the ConfigError can be described with
         */
        pub fn as_str(e: &ConfigError) -> &'static str {
            match e.kind() {
                ConfigErrorKind::ConfigParsingFailed => "Config parsing failed",
                ConfigErrorKind::NoConfigFileFound   => "No config file found",
            }
        }

    }

    impl Display for ConfigError {

        fn fmt(&self, fmt: &mut Formatter) -> Result<(), FmtError> {
            try!(write!(fmt, "{}", ConfigError::as_str(self)));
            Ok(())
        }

    }

    impl Error for ConfigError {

        fn description(&self) -> &str {
            ConfigError::as_str(self)
        }

        fn cause(&self) -> Option<&Error> {
            self.cause.as_ref().map(|e| &**e)
        }

    }

}

use self::error::{ConfigError, ConfigErrorKind};

/**
 * Result type of this module. Either T or ConfigError
 */
pub type Result<T> = RResult<T, ConfigError>;

/**
 * Configuration object
 *
 * Holds all config variables which are globally available plus the configuration object from the
 * config parser, which can be accessed.
 */
#[derive(Debug)]
pub struct Configuration {

    /**
     * The plain configuration object for direct access if necessary
     */
    config: Value,

    /**
     * The verbosity the program should run with
     */
    verbosity: bool,

    /**
     * The editor which should be used
     */
    editor: Option<String>,

    /**
     * The options the editor should get when opening some file
     */
    editor_opts: String,
}

impl Configuration {

    /**
     * Get a new configuration object.
     *
     * The passed runtimepath is used for searching the configuration file, whereas several file
     * names are tested. If that does not work, the home directory and the XDG basedir are tested
     * with all variants.
     *
     * If that doesn't work either, an error is returned.
     */
    pub fn new(rtp: &PathBuf) -> Result<Configuration> {
        fetch_config(&rtp).map(|cfg| {
            let verbosity   = get_verbosity(&cfg);
            let editor      = get_editor(&cfg);
            let editor_opts = get_editor_opts(&cfg);

            debug!("Building configuration");
            debug!("  - verbosity  : {:?}", verbosity);
            debug!("  - editor     : {:?}", editor);
            debug!("  - editor-opts: {}", editor_opts);

            Configuration {
                config: cfg,
                verbosity: verbosity,
                editor: editor,
                editor_opts: editor_opts,
            }
        })
    }

    pub fn editor(&self) -> Option<&String> {
        self.editor.as_ref()
    }

    pub fn config(&self) -> &Value {
        &self.config
    }

    pub fn store_config(&self) -> Option<&Value> {
        match &self.config {
            &Value::Table(ref tabl) => tabl.get("store"),
            _ => None,
        }
    }

}

impl Deref for Configuration {
    type Target = Value;

    fn deref(&self) -> &Value {
        &self.config
    }

}

fn get_verbosity(v: &Value) -> bool {
    match v {
        &Value::Table(ref t) => t.get("verbose")
                .map(|v| match v { &Value::Boolean(b) => b, _ => false, })
                .unwrap_or(false),
        _ => false,
    }
}

fn get_editor(v: &Value) -> Option<String> {
    match v {
        &Value::Table(ref t) => t.get("editor")
                .and_then(|v| match v { &Value::String(ref s) => Some(s.clone()), _ => None, }),
        _ => None,
    }
}

fn get_editor_opts(v: &Value) -> String {
    match v {
        &Value::Table(ref t) => t.get("editor-opts")
                .and_then(|v| match v { &Value::String(ref s) => Some(s.clone()), _ => None, })
                .unwrap_or(String::new()),
        _ => String::new(),
    }
}

/**
 * Helper to fetch the config file
 *
 * Tests several variants for the config file path and uses the first one which works.
 */
fn fetch_config(rtp: &PathBuf) -> Result<Value> {
    use std::env;
    use std::fs::File;
    use std::io::Read;
    use std::io::Write;
    use std::io::stderr;

    use xdg_basedir;
    use itertools::Itertools;

    use libimagutil::variants::generate_variants as gen_vars;

    let variants = vec!["config", "config.toml", "imagrc", "imagrc.toml"];
    let modifier = |base: &PathBuf, v: &'static str| {
        let mut base = base.clone();
        base.push(format!("{}", v));
        base
    };

    vec![
        gen_vars(rtp.clone(), variants.clone(), &modifier),

        env::var("HOME").map(|home| gen_vars(PathBuf::from(home), variants.clone(), &modifier))
                        .unwrap_or(vec![]),

        xdg_basedir::get_data_home().map(|data_dir| gen_vars(data_dir, variants.clone(), &modifier))
                                    .unwrap_or(vec![]),
    ].iter()
        .flatten()
        .filter(|path| path.exists() && path.is_file())
        .map(|path| {
            let content = {
                let mut s = String::new();
                let f = File::open(path);
                if f.is_err() {
                }
                let mut f = f.unwrap();
                f.read_to_string(&mut s).ok();
                s
            };
            let mut parser = Parser::new(&content[..]);
            let res = parser.parse();
            if res.is_none() {
                write!(stderr(), "Config file parser error:");
                for error in parser.errors {
                    write!(stderr(), "At [{}][{}] <> {}", error.lo, error.hi, error);
                    write!(stderr(), "in: '{}'", &content[error.lo..error.hi]);
                }
                None
            } else {
                res
            }
        })
        .filter(|loaded| loaded.is_some())
        .nth(0)
        .map(|inner| Value::Table(inner.unwrap()))
        .ok_or(ConfigError::new(ConfigErrorKind::NoConfigFileFound, None))
}

<|endoftext|>


<commit_before>extern crate libc;
extern crate glib;

use std::str::FromStr;

use self::glib::translate::*;

use error::*;
use length::*;
use parsers::ParseError;

pub enum RsvgPropertyBag {}

extern "C" {
    fn rsvg_property_bag_size (pbag: *const RsvgPropertyBag) -> libc::c_uint;
    fn rsvg_property_bag_lookup (pbag: *const RsvgPropertyBag, key: *const libc::c_char) -> *const libc::c_char;
}

pub fn get_size (pbag: *const RsvgPropertyBag) -> usize {
    unsafe { rsvg_property_bag_size (pbag) as usize }
}

pub fn lookup (pbag: *const RsvgPropertyBag, key: &str) -> Option<String> {
    unsafe {
        let c_value = rsvg_property_bag_lookup (pbag, key.to_glib_none ().0);
        from_glib_none (c_value)
    }
}

pub fn length_or_none (pbag: *const RsvgPropertyBag, key: &'static str, length_dir: LengthDir) -> Result <Option<RsvgLength>, NodeError> {
    let value = lookup (pbag, key);

    if let Some (v) = value {
        RsvgLength::parse (&v, length_dir).map (|l| Some (l))
            .map_err (|e| NodeError::attribute_error (key, e))
    } else {
        Ok (None)
    }
}

pub fn length_or_default (pbag: *const RsvgPropertyBag, key: &'static str, length_dir: LengthDir) -> Result <RsvgLength, NodeError> {
    let r = length_or_none (pbag, key, length_dir);

    match r {
        Ok (Some (v)) => Ok (v),
        Ok (None)     => Ok (RsvgLength::default ()),
        Err (e)       => Err (e)
    }
}

pub fn parse_or_none<T> (pbag: *const RsvgPropertyBag, key: &'static str) -> Result <Option<T>, NodeError>
    where T: Default + FromStr<Err = AttributeError>
{
    let value = lookup (pbag, key);

    match value {
        Some (v) => {
            T::from_str (&v).map (|v| Some (v))
                .map_err (|e| NodeError::attribute_error (key, e))
        },

        None => Ok (None)
    }
}

pub fn parse_or_default<T> (pbag: *const RsvgPropertyBag, key: &'static str) -> Result <T, NodeError>
    where T: Default + FromStr<Err = AttributeError>
{
    let r = parse_or_none::<T> (pbag, key);

    match r {
        Ok (Some (v)) => Ok (v),
        Ok (None)     => Ok (T::default ()),
        Err (e)       => Err (e)
    }
}
<commit_msg>property_bag.rs: New functions length_or_value(), parse_or_value()<commit_after>extern crate libc;
extern crate glib;

use std::str::FromStr;

use self::glib::translate::*;

use error::*;
use length::*;
use parsers::ParseError;

pub enum RsvgPropertyBag {}

extern "C" {
    fn rsvg_property_bag_size (pbag: *const RsvgPropertyBag) -> libc::c_uint;
    fn rsvg_property_bag_lookup (pbag: *const RsvgPropertyBag, key: *const libc::c_char) -> *const libc::c_char;
}

pub fn get_size (pbag: *const RsvgPropertyBag) -> usize {
    unsafe { rsvg_property_bag_size (pbag) as usize }
}

pub fn lookup (pbag: *const RsvgPropertyBag, key: &str) -> Option<String> {
    unsafe {
        let c_value = rsvg_property_bag_lookup (pbag, key.to_glib_none ().0);
        from_glib_none (c_value)
    }
}

pub fn length_or_none (pbag: *const RsvgPropertyBag, key: &'static str, length_dir: LengthDir) -> Result <Option<RsvgLength>, NodeError> {
    let value = lookup (pbag, key);

    if let Some (v) = value {
        RsvgLength::parse (&v, length_dir).map (|l| Some (l))
            .map_err (|e| NodeError::attribute_error (key, e))
    } else {
        Ok (None)
    }
}

pub fn length_or_default (pbag: *const RsvgPropertyBag, key: &'static str, length_dir: LengthDir) -> Result <RsvgLength, NodeError> {
    let r = length_or_none (pbag, key, length_dir);

    match r {
        Ok (Some (v)) => Ok (v),
        Ok (None)     => Ok (RsvgLength::default ()),
        Err (e)       => Err (e)
    }
}

pub fn length_or_value (pbag: *const RsvgPropertyBag, key: &'static str, length_dir: LengthDir, length_str: &str) -> Result <RsvgLength, NodeError> {
    let r = length_or_none (pbag, key, length_dir);

    match r {
        Ok (Some (v)) => Ok (v),
        Ok (None)     => Ok (RsvgLength::parse (length_str, length_dir).unwrap ()),
        Err (e)       => Err (e)
    }
}

pub fn parse_or_none<T> (pbag: *const RsvgPropertyBag, key: &'static str) -> Result <Option<T>, NodeError>
    where T: Default + FromStr<Err = AttributeError>
{
    let value = lookup (pbag, key);

    match value {
        Some (v) => {
            T::from_str (&v).map (|v| Some (v))
                .map_err (|e| NodeError::attribute_error (key, e))
        },

        None => Ok (None)
    }
}

pub fn parse_or_default<T> (pbag: *const RsvgPropertyBag, key: &'static str) -> Result <T, NodeError>
    where T: Default + FromStr<Err = AttributeError>
{
    let r = parse_or_none::<T> (pbag, key);

    match r {
        Ok (Some (v)) => Ok (v),
        Ok (None)     => Ok (T::default ()),
        Err (e)       => Err (e)
    }
}

pub fn parse_or_value<T> (pbag: *const RsvgPropertyBag, key: &'static str, value: T) -> Result <T, NodeError>
    where T: Default + FromStr<Err = AttributeError> + Copy
{
    let r = parse_or_none::<T> (pbag, key);

    match r {
        Ok (Some (v)) => Ok (v),
        Ok (None)     => Ok (value),
        Err (e)       => Err (e)
    }
}
<|endoftext|>


<commit_before>use app_units::Au;
use webrender_traits::{FontKey, NativeFontHandle};

use freetype::freetype::{FTErrorMethods, FT_PIXEL_MODE_GRAY};
use freetype::freetype::{FT_Done_FreeType, FT_LOAD_RENDER};
use freetype::freetype::{FT_Library, FT_Set_Char_Size};
use freetype::freetype::{FT_Face, FT_Long, FT_UInt, FT_F26Dot6};
use freetype::freetype::{FT_Init_FreeType, FT_Load_Glyph};
use freetype::freetype::{FT_New_Memory_Face, FT_GlyphSlot};

use std::{mem, ptr, slice};
use std::collections::HashMap;
//use util;

struct Face {
    face: FT_Face,
}

pub struct FontContext {
    lib: FT_Library,
    faces: HashMap<FontKey, Face>,
}

pub struct RasterizedGlyph {
    pub left: i32,
    pub top: i32,
    pub width: u32,
    pub height: u32,
    pub bytes: Vec<u8>,
}

fn float_to_fixed(before: usize, f: f64) -> i32 {
    ((1i32 << before) as f64 * f) as i32
}

fn float_to_fixed_ft(f: f64) -> i32 {
    float_to_fixed(6, f)
}

impl FontContext {
    pub fn new() -> FontContext {
//        let _pf = util::ProfileScope::new("  FontContext::new");
        let mut lib: FT_Library = ptr::null_mut();
        unsafe {
            let result = FT_Init_FreeType(&mut lib);
            if !result.succeeded() { panic!("Unable to initialize FreeType library {}", result); }
        }

        FontContext {
            lib: lib,
            faces: HashMap::new(),
        }
    }

    pub fn add_raw_font(&mut self, font_key: &FontKey, bytes: &[u8]) {
        if !self.faces.contains_key(&font_key) {
            let mut face: FT_Face = ptr::null_mut();
            let face_index = 0 as FT_Long;
            let result = unsafe {
                FT_New_Memory_Face(self.lib,
                                   bytes.as_ptr(),
                                   bytes.len() as FT_Long,
                                   face_index,
                                   &mut face)
            };
            if result.succeeded() && !face.is_null() {
                self.faces.insert(*font_key, Face {
                    face: face,
                    //_bytes: bytes
                });
            } else {
                println!("WARN: webrender failed to load font {:?}", font_key);
            }
        }
    }

    pub fn add_native_font(&mut self, _font_key: &FontKey, _native_font_handle: NativeFontHandle) {
        panic!("TODO: Not supported on Linux");
    }

    pub fn get_glyph(&mut self,
                     font_key: FontKey,
                     size: Au,
                     character: u32,
                     device_pixel_ratio: f32) -> Option<RasterizedGlyph> {
        debug_assert!(self.faces.contains_key(&font_key));

        let face = self.faces.get(&font_key).unwrap();

        unsafe {
            let char_size = float_to_fixed_ft(((0.5f64 + size.to_f64_px()) *
                                               device_pixel_ratio as f64).floor());
            let result = FT_Set_Char_Size(face.face, char_size as FT_F26Dot6, 0, 0, 0);
            assert!(result.succeeded());

            let result =  FT_Load_Glyph(face.face, character as FT_UInt, FT_LOAD_RENDER);
            if result.succeeded() {

                let void_glyph = (*face.face).glyph;
                let slot: FT_GlyphSlot = mem::transmute(void_glyph);
                assert!(!slot.is_null());

                let bitmap = &(*slot).bitmap;
                assert!(bitmap.pixel_mode == FT_PIXEL_MODE_GRAY as i8);

                let buffer = slice::from_raw_parts(
                    bitmap.buffer,
                    (bitmap.width * bitmap.rows) as usize
                );

                // Convert to RGBA.
                let mut final_buffer = Vec::with_capacity(buffer.len() * 4);
                for &byte in buffer.iter() {
                    final_buffer.push_all(&[ byte, byte, byte, byte ]);
                }

                let glyph = RasterizedGlyph {
                    left: (*slot).bitmap_left as i32,
                    top: (*slot).bitmap_top as i32,
                    width: bitmap.width as u32,
                    height: bitmap.rows as u32,
                    bytes: final_buffer.to_vec(),
                };

                Some(glyph)
            } else {
                None
            }
        }
    }
}

impl Drop for FontContext {
    fn drop(&mut self) {
        unsafe {
            FT_Done_FreeType(self.lib);
        }
    }
}
<commit_msg>Fix font rendering on linux<commit_after>use app_units::Au;
use webrender_traits::{FontKey, NativeFontHandle};

use freetype::freetype::{FTErrorMethods, FT_PIXEL_MODE_GRAY};
use freetype::freetype::{FT_Done_FreeType, FT_LOAD_RENDER};
use freetype::freetype::{FT_Library, FT_Set_Char_Size};
use freetype::freetype::{FT_Face, FT_Long, FT_UInt, FT_F26Dot6};
use freetype::freetype::{FT_Init_FreeType, FT_Load_Glyph};
use freetype::freetype::{FT_New_Memory_Face, FT_GlyphSlot};

use std::{mem, ptr, slice};
use std::collections::HashMap;
//use util;

struct Face {
    face: FT_Face,
}

pub struct FontContext {
    lib: FT_Library,
    faces: HashMap<FontKey, Face>,
}

pub struct RasterizedGlyph {
    pub left: i32,
    pub top: i32,
    pub width: u32,
    pub height: u32,
    pub bytes: Vec<u8>,
}

fn float_to_fixed(before: usize, f: f64) -> i32 {
    ((1i32 << before) as f64 * f) as i32
}

fn float_to_fixed_ft(f: f64) -> i32 {
    float_to_fixed(6, f)
}

impl FontContext {
    pub fn new() -> FontContext {
//        let _pf = util::ProfileScope::new("  FontContext::new");
        let mut lib: FT_Library = ptr::null_mut();
        unsafe {
            let result = FT_Init_FreeType(&mut lib);
            if !result.succeeded() { panic!("Unable to initialize FreeType library {}", result); }
        }

        FontContext {
            lib: lib,
            faces: HashMap::new(),
        }
    }

    pub fn add_raw_font(&mut self, font_key: &FontKey, bytes: &[u8]) {
        if !self.faces.contains_key(&font_key) {
            let mut face: FT_Face = ptr::null_mut();
            let face_index = 0 as FT_Long;
            let result = unsafe {
                FT_New_Memory_Face(self.lib,
                                   bytes.as_ptr(),
                                   bytes.len() as FT_Long,
                                   face_index,
                                   &mut face)
            };
            if result.succeeded() && !face.is_null() {
                self.faces.insert(*font_key, Face {
                    face: face,
                    //_bytes: bytes
                });
            } else {
                println!("WARN: webrender failed to load font {:?}", font_key);
            }
        }
    }

    pub fn add_native_font(&mut self, _font_key: &FontKey, _native_font_handle: NativeFontHandle) {
        panic!("TODO: Not supported on Linux");
    }

    pub fn get_glyph(&mut self,
                     font_key: FontKey,
                     size: Au,
                     character: u32,
                     device_pixel_ratio: f32) -> Option<RasterizedGlyph> {
        debug_assert!(self.faces.contains_key(&font_key));

        let face = self.faces.get(&font_key).unwrap();

        unsafe {
            let char_size = float_to_fixed_ft(((0.5f64 + size.to_f64_px()) *
                                               device_pixel_ratio as f64).floor());
            let result = FT_Set_Char_Size(face.face, char_size as FT_F26Dot6, 0, 0, 0);
            assert!(result.succeeded());

            let result =  FT_Load_Glyph(face.face, character as FT_UInt, FT_LOAD_RENDER);
            if result.succeeded() {

                let void_glyph = (*face.face).glyph;
                let slot: FT_GlyphSlot = mem::transmute(void_glyph);
                assert!(!slot.is_null());

                let bitmap = &(*slot).bitmap;
                assert!(bitmap.pixel_mode == FT_PIXEL_MODE_GRAY as i8);

                let buffer = slice::from_raw_parts(
                    bitmap.buffer,
                    (bitmap.width * bitmap.rows) as usize
                );

                // Convert to RGBA.
                let mut final_buffer = Vec::with_capacity(buffer.len() * 4);
                for &byte in buffer.iter() {
                    final_buffer.push_all(&[ 0xff, 0xff, 0xff, byte ]);
                }

                let glyph = RasterizedGlyph {
                    left: (*slot).bitmap_left as i32,
                    top: (*slot).bitmap_top as i32,
                    width: bitmap.width as u32,
                    height: bitmap.rows as u32,
                    bytes: final_buffer.to_vec(),
                };

                Some(glyph)
            } else {
                None
            }
        }
    }
}

impl Drop for FontContext {
    fn drop(&mut self) {
        unsafe {
            FT_Done_FreeType(self.lib);
        }
    }
}
<|endoftext|>