<commit_before>use std::cmp;
use std::io::prelude::*;
use std::io::{SeekFrom, ErrorKind};
use std::io;

use fs::FileSystemRef;
use dir::{FileEntryInfo, DateTime};

#[derive(Clone)]
pub struct File<'a, 'b: 'a> {
    // Note first_cluster is None if file is empty
    first_cluster: Option<u32>,
    // Note: if offset points between clusters current_cluster is the previous cluster
    current_cluster: Option<u32>,
    // current position in this file
    offset: u32,
    // file dir entry - None for root dir
    entry: Option<FileEntryInfo>,
    // should file dir entry be flushed?
    entry_dirty: bool,
    fs: FileSystemRef<'a, 'b>,
}

impl <'a, 'b> File<'a, 'b> {
    pub(crate) fn new(first_cluster: Option<u32>, entry: Option<FileEntryInfo>, fs: FileSystemRef<'a, 'b>) -> Self {
        File {
            first_cluster, entry, fs,
            current_cluster: None, // cluster before first one
            offset: 0,
            entry_dirty: false,
        }
    }

    fn update_size(&mut self) {
        let offset = self.offset;
        match self.entry {
            Some(ref mut e) => {
                if e.data.size().map_or(false, |s| offset > s) {
                    e.data.set_size(offset);
                    self.entry_dirty = true;
                }
            },
            _ => {},
        }
    }

    pub fn truncate(&mut self) -> io::Result<()> {
        let offset = self.offset;
        match self.entry {
            Some(ref mut e) => {
                if e.data.size().map_or(false, |s| offset == s) {
                    return Ok(());
                }

                e.data.set_size(self.offset);
                if self.offset == 0 {
                    e.data.set_first_cluster(None);
                }
                self.entry_dirty = true;
            },
            _ => {},
        }
        if self.offset > 0 {
            debug_assert!(self.current_cluster.is_some());
            self.fs.cluster_iter(self.current_cluster.unwrap()).truncate() // safe
        } else {
            debug_assert!(self.current_cluster.is_none());
            match self.first_cluster {
                Some(n) => self.fs.cluster_iter(n).free()?,
                _ => {},
            }
            self.first_cluster = None;
            Ok(())
        }
    }

    pub(crate) fn global_pos(&self) -> Option<u64> {
        // Returns current position relative to filesystem start
        // Note: when between clusters it returns position after previous cluster
        match self.current_cluster {
            Some(n) => {
                let cluster_size = self.fs.get_cluster_size();
                let offset_in_cluster = self.offset % cluster_size;
                let offset_in_fs = self.fs.offset_from_cluster(n) + (offset_in_cluster as u64);
                Some(offset_in_fs)
            },
            None => None,
        }
    }

    pub(crate) fn flush_dir_entry(&self) -> io::Result<()> {
        if self.entry_dirty {
            match self.entry {
                Some(ref e) => e.write(self.fs)?,
                _ => {},
            }
        }
        Ok(())
    }

    pub fn set_modified(&mut self, date_time: DateTime) {
        match self.entry {
            Some(ref mut e) => {
                e.data.set_modified(date_time);
                self.entry_dirty = true;
            },
            _ => {},
        }
    }

    fn bytes_left_in_file(&self) -> Option<usize> {
        match self.entry {
            Some(ref e) => e.data.size().map(|s| (s - self.offset) as usize),
            None => None,
        }
    }

    fn set_first_cluster(&mut self, cluster: u32) {
        self.first_cluster = Some(cluster);
        match self.entry {
            Some(ref mut e) => {
                e.data.set_first_cluster(self.first_cluster);
            },
            None => {},
        }
        self.entry_dirty = true;
    }
}

impl<'a, 'b> Drop for File<'a, 'b> {
    fn drop(&mut self) {
        self.flush().expect("flush failed");
    }
}

impl<'a, 'b> Read for File<'a, 'b> {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        let cluster_size = self.fs.get_cluster_size();
        let current_cluster_opt = if self.offset % cluster_size == 0 {
            // next cluster
            match self.current_cluster {
                None => self.first_cluster,
                Some(n) => {
                    let r = self.fs.cluster_iter(n).next();
                    match r {
                        Some(Err(err)) => return Err(err),
                        Some(Ok(n)) => Some(n),
                        None => None,
                    }
                },
            }
        } else {
            self.current_cluster
        };
        let current_cluster = match current_cluster_opt {
            Some(n) => n,
            None => return Ok(0),
        };
        let offset_in_cluster = self.offset % cluster_size;
        let bytes_left_in_cluster = (cluster_size - offset_in_cluster) as usize;
        let bytes_left_in_file = self.bytes_left_in_file().unwrap_or(bytes_left_in_cluster);
        let read_size = cmp::min(cmp::min(buf.len(), bytes_left_in_cluster), bytes_left_in_file);
        if read_size == 0 {
            return Ok(0);
        }
        trace!("read {} bytes in cluster {}", read_size, current_cluster);
        let offset_in_fs = self.fs.offset_from_cluster(current_cluster) + (offset_in_cluster as u64);
        let read_bytes = {
            let mut disk = self.fs.disk.borrow_mut();
            disk.seek(SeekFrom::Start(offset_in_fs))?;
            disk.read(&mut buf[..read_size])?
        };
        if read_bytes == 0 {
            return Ok(0);
        }
        self.offset += read_bytes as u32;
        self.current_cluster = Some(current_cluster);
        Ok(read_bytes)
    }
}

impl<'a, 'b> Write for File<'a, 'b> {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        let cluster_size = self.fs.get_cluster_size();
        let offset_in_cluster = self.offset % cluster_size;
        let bytes_left_in_cluster = (cluster_size - offset_in_cluster) as usize;
        let write_size = cmp::min(buf.len(), bytes_left_in_cluster);
        // Exit early if we are going to write no data
        if write_size == 0 {
            return Ok(0);
        }
        // Get cluster for write possibly allocating new one
        let current_cluster = if self.offset % cluster_size == 0 {
            // next cluster
            let next_cluster = match self.current_cluster {
                None => self.first_cluster,
                Some(n) => {
                    let r = self.fs.cluster_iter(n).next();
                    match r {
                        Some(Err(err)) => return Err(err),
                        Some(Ok(n)) => Some(n),
                        None => None,
                    }
                },
            };
            match next_cluster {
                Some(n) => n,
                None => {
                    // end of chain reached - allocate new cluster
                    let new_cluster = self.fs.alloc_cluster(self.current_cluster)?;
                    if self.first_cluster.is_none() {
                        self.set_first_cluster(new_cluster);
                    }
                    new_cluster
                },
            }
        } else {
            // self.current_cluster should be a valid cluster
            match self.current_cluster {
                Some(n) => n,
                None => panic!("Offset inside cluster but no cluster allocated"),
            }
        };
        trace!("write {} bytes in cluster {}", write_size, current_cluster);
        let offset_in_fs = self.fs.offset_from_cluster(current_cluster) + (offset_in_cluster as u64);
        let written_bytes = {
            let mut disk = self.fs.disk.borrow_mut();
            disk.seek(SeekFrom::Start(offset_in_fs))?;
            disk.write(&buf[..write_size])?
        };
        if written_bytes == 0 {
            return Ok(0);
        }
        self.offset += written_bytes as u32;
        self.current_cluster = Some(current_cluster);
        self.update_size();
        Ok(written_bytes)
    }

    fn flush(&mut self) -> io::Result<()> {
        self.flush_dir_entry()?;
        let mut disk = self.fs.disk.borrow_mut();
        disk.flush()
    }
}

impl<'a, 'b> Seek for File<'a, 'b> {
    fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
        let mut new_pos = match pos {
            SeekFrom::Current(x) => self.offset as i64 + x,
            SeekFrom::Start(x) => x as i64,
            SeekFrom::End(x) => self.entry.iter().next().map_or(None, |e| e.data.size()).expect("cannot seek from end if size is unknown") as i64 + x,
        };
        if new_pos < 0 {
            return Err(io::Error::new(ErrorKind::InvalidInput, "invalid seek"));
        }
        new_pos = match self.entry {
            Some(ref e) => {
                if e.data.size().map_or(false, |s| new_pos > s as i64) {
                    info!("seek beyond end of file");
                    e.data.size().unwrap() as i64 // safe
                } else {
                    new_pos
                }
            },
            _ => new_pos,
        };
        trace!("file seek {} -> {} - entry {:?}", self.offset, new_pos, self.entry);
        if new_pos == self.offset as i64 {
            return Ok(self.offset as u64);
        }
        let cluster_size = self.fs.get_cluster_size();
        let new_cluster = if new_pos == 0 {
            None
        } else {
            // get number of clusters to seek (favoring previous cluster in corner case)
            let cluster_count = ((new_pos - 1) / cluster_size as i64) as isize;
            match self.first_cluster {
                Some(n) => {
                    let mut cluster = n;
                    let mut iter = self.fs.cluster_iter(n);
                    for i in 0..cluster_count {
                        cluster = match iter.next() {
                            Some(Err(err)) => return Err(err),
                            Some(Ok(n)) => n,
                            None => {
                                // chain ends before new position - seek to end of last cluster
                                new_pos = (i + 1) as i64 * cluster_size as i64;
                                break;
                            },
                        };
                    }
                    Some(cluster)
                },
                None => {
                    // empty file - always seek to 0
                    new_pos = 0;
                    None
                },
            }
        };
        self.offset = new_pos as u32;
        self.current_cluster = new_cluster;
        Ok(self.offset as u64)
    }
}
<commit_msg>Don't recalculate cluster in seek if not needed.<commit_after>use std::cmp;
use std::io::prelude::*;
use std::io::{SeekFrom, ErrorKind};
use std::io;

use fs::FileSystemRef;
use dir::{FileEntryInfo, DateTime};

#[derive(Clone)]
pub struct File<'a, 'b: 'a> {
    // Note first_cluster is None if file is empty
    first_cluster: Option<u32>,
    // Note: if offset points between clusters current_cluster is the previous cluster
    current_cluster: Option<u32>,
    // current position in this file
    offset: u32,
    // file dir entry - None for root dir
    entry: Option<FileEntryInfo>,
    // should file dir entry be flushed?
    entry_dirty: bool,
    fs: FileSystemRef<'a, 'b>,
}

impl <'a, 'b> File<'a, 'b> {
    pub(crate) fn new(first_cluster: Option<u32>, entry: Option<FileEntryInfo>, fs: FileSystemRef<'a, 'b>) -> Self {
        File {
            first_cluster, entry, fs,
            current_cluster: None, // cluster before first one
            offset: 0,
            entry_dirty: false,
        }
    }

    fn update_size(&mut self) {
        let offset = self.offset;
        match self.entry {
            Some(ref mut e) => {
                if e.data.size().map_or(false, |s| offset > s) {
                    e.data.set_size(offset);
                    self.entry_dirty = true;
                }
            },
            _ => {},
        }
    }

    pub fn truncate(&mut self) -> io::Result<()> {
        let offset = self.offset;
        match self.entry {
            Some(ref mut e) => {
                if e.data.size().map_or(false, |s| offset == s) {
                    return Ok(());
                }

                e.data.set_size(self.offset);
                if self.offset == 0 {
                    e.data.set_first_cluster(None);
                }
                self.entry_dirty = true;
            },
            _ => {},
        }
        if self.offset > 0 {
            debug_assert!(self.current_cluster.is_some());
            self.fs.cluster_iter(self.current_cluster.unwrap()).truncate() // safe
        } else {
            debug_assert!(self.current_cluster.is_none());
            match self.first_cluster {
                Some(n) => self.fs.cluster_iter(n).free()?,
                _ => {},
            }
            self.first_cluster = None;
            Ok(())
        }
    }

    pub(crate) fn global_pos(&self) -> Option<u64> {
        // Returns current position relative to filesystem start
        // Note: when between clusters it returns position after previous cluster
        match self.current_cluster {
            Some(n) => {
                let cluster_size = self.fs.get_cluster_size();
                let offset_in_cluster = self.offset % cluster_size;
                let offset_in_fs = self.fs.offset_from_cluster(n) + (offset_in_cluster as u64);
                Some(offset_in_fs)
            },
            None => None,
        }
    }

    pub(crate) fn flush_dir_entry(&self) -> io::Result<()> {
        if self.entry_dirty {
            match self.entry {
                Some(ref e) => e.write(self.fs)?,
                _ => {},
            }
        }
        Ok(())
    }

    pub fn set_modified(&mut self, date_time: DateTime) {
        match self.entry {
            Some(ref mut e) => {
                e.data.set_modified(date_time);
                self.entry_dirty = true;
            },
            _ => {},
        }
    }

    fn bytes_left_in_file(&self) -> Option<usize> {
        match self.entry {
            Some(ref e) => e.data.size().map(|s| (s - self.offset) as usize),
            None => None,
        }
    }

    fn set_first_cluster(&mut self, cluster: u32) {
        self.first_cluster = Some(cluster);
        match self.entry {
            Some(ref mut e) => {
                e.data.set_first_cluster(self.first_cluster);
            },
            None => {},
        }
        self.entry_dirty = true;
    }
}

impl<'a, 'b> Drop for File<'a, 'b> {
    fn drop(&mut self) {
        self.flush().expect("flush failed");
    }
}

impl<'a, 'b> Read for File<'a, 'b> {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        let cluster_size = self.fs.get_cluster_size();
        let current_cluster_opt = if self.offset % cluster_size == 0 {
            // next cluster
            match self.current_cluster {
                None => self.first_cluster,
                Some(n) => {
                    let r = self.fs.cluster_iter(n).next();
                    match r {
                        Some(Err(err)) => return Err(err),
                        Some(Ok(n)) => Some(n),
                        None => None,
                    }
                },
            }
        } else {
            self.current_cluster
        };
        let current_cluster = match current_cluster_opt {
            Some(n) => n,
            None => return Ok(0),
        };
        let offset_in_cluster = self.offset % cluster_size;
        let bytes_left_in_cluster = (cluster_size - offset_in_cluster) as usize;
        let bytes_left_in_file = self.bytes_left_in_file().unwrap_or(bytes_left_in_cluster);
        let read_size = cmp::min(cmp::min(buf.len(), bytes_left_in_cluster), bytes_left_in_file);
        if read_size == 0 {
            return Ok(0);
        }
        trace!("read {} bytes in cluster {}", read_size, current_cluster);
        let offset_in_fs = self.fs.offset_from_cluster(current_cluster) + (offset_in_cluster as u64);
        let read_bytes = {
            let mut disk = self.fs.disk.borrow_mut();
            disk.seek(SeekFrom::Start(offset_in_fs))?;
            disk.read(&mut buf[..read_size])?
        };
        if read_bytes == 0 {
            return Ok(0);
        }
        self.offset += read_bytes as u32;
        self.current_cluster = Some(current_cluster);
        Ok(read_bytes)
    }
}

impl<'a, 'b> Write for File<'a, 'b> {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        let cluster_size = self.fs.get_cluster_size();
        let offset_in_cluster = self.offset % cluster_size;
        let bytes_left_in_cluster = (cluster_size - offset_in_cluster) as usize;
        let write_size = cmp::min(buf.len(), bytes_left_in_cluster);
        // Exit early if we are going to write no data
        if write_size == 0 {
            return Ok(0);
        }
        // Get cluster for write possibly allocating new one
        let current_cluster = if self.offset % cluster_size == 0 {
            // next cluster
            let next_cluster = match self.current_cluster {
                None => self.first_cluster,
                Some(n) => {
                    let r = self.fs.cluster_iter(n).next();
                    match r {
                        Some(Err(err)) => return Err(err),
                        Some(Ok(n)) => Some(n),
                        None => None,
                    }
                },
            };
            match next_cluster {
                Some(n) => n,
                None => {
                    // end of chain reached - allocate new cluster
                    let new_cluster = self.fs.alloc_cluster(self.current_cluster)?;
                    if self.first_cluster.is_none() {
                        self.set_first_cluster(new_cluster);
                    }
                    new_cluster
                },
            }
        } else {
            // self.current_cluster should be a valid cluster
            match self.current_cluster {
                Some(n) => n,
                None => panic!("Offset inside cluster but no cluster allocated"),
            }
        };
        trace!("write {} bytes in cluster {}", write_size, current_cluster);
        let offset_in_fs = self.fs.offset_from_cluster(current_cluster) + (offset_in_cluster as u64);
        let written_bytes = {
            let mut disk = self.fs.disk.borrow_mut();
            disk.seek(SeekFrom::Start(offset_in_fs))?;
            disk.write(&buf[..write_size])?
        };
        if written_bytes == 0 {
            return Ok(0);
        }
        self.offset += written_bytes as u32;
        self.current_cluster = Some(current_cluster);
        self.update_size();
        Ok(written_bytes)
    }

    fn flush(&mut self) -> io::Result<()> {
        self.flush_dir_entry()?;
        let mut disk = self.fs.disk.borrow_mut();
        disk.flush()
    }
}

impl<'a, 'b> Seek for File<'a, 'b> {
    fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
        let mut new_pos = match pos {
            SeekFrom::Current(x) => self.offset as i64 + x,
            SeekFrom::Start(x) => x as i64,
            SeekFrom::End(x) => self.entry.iter().next().map_or(None, |e| e.data.size()).expect("cannot seek from end if size is unknown") as i64 + x,
        };
        if new_pos < 0 {
            return Err(io::Error::new(ErrorKind::InvalidInput, "invalid seek"));
        }
        new_pos = match self.entry {
            Some(ref e) => {
                if e.data.size().map_or(false, |s| new_pos > s as i64) {
                    info!("seek beyond end of file");
                    e.data.size().unwrap() as i64 // safe
                } else {
                    new_pos
                }
            },
            _ => new_pos,
        };
        trace!("file seek {} -> {} - entry {:?}", self.offset, new_pos, self.entry);
        if new_pos == self.offset as i64 {
            return Ok(self.offset as u64);
        }
        let cluster_size = self.fs.get_cluster_size();
        // get number of clusters to seek (favoring previous cluster in corner case)
        let cluster_count = ((new_pos + cluster_size as i64 - 1) / cluster_size as i64 - 1) as isize;
        let old_cluster_count = ((self.offset as i64 + cluster_size as i64 - 1) / cluster_size as i64 - 1) as isize;
        let new_cluster =  if new_pos == 0 {
            None
        } else if cluster_count == old_cluster_count {
            self.current_cluster
        } else {
            match self.first_cluster {
                Some(n) => {
                    let mut cluster = n;
                    let mut iter = self.fs.cluster_iter(n);
                    for i in 0..cluster_count {
                        cluster = match iter.next() {
                            Some(r) => r?,
                            None => {
                                // chain ends before new position - seek to end of last cluster
                                new_pos = (i + 1) as i64 * cluster_size as i64;
                                break;
                            },
                        };
                    }
                    Some(cluster)
                },
                None => {
                    // empty file - always seek to 0
                    new_pos = 0;
                    None
                },
            }
        };
        self.offset = new_pos as u32;
        self.current_cluster = new_cluster;
        Ok(self.offset as u64)
    }
}
<|endoftext|>


<commit_before>use {lexer, parser, ast};
use std::io::prelude::*;
use std::io::BufReader;
use std::fs::File;
use combine;
use combine::State;
use error::*;
use eval::Env;
use token::Token;

pub fn run(path: &str, mut env: &mut Env) -> Result<()> {
    let mut token_buf = Vec::<Token>::with_capacity(1024);

    let file = File::open(path)?;
    let mut buf_reader = BufReader::new(file);
    let mut source = String::with_capacity(128);
    buf_reader.read_to_string(&mut source)?;
    // TODO: why is trimming necessary?
    exec(State::new(source.trim()), &mut token_buf, &mut env)
}

fn exec<S>(input: S, mut token_buf: &mut Vec<Token>, mut env: &mut Env) -> Result<()>
where
    S: combine::Stream<Item = char>
{
    let exprs = read(input, &mut token_buf)?;
    let result = eval(&exprs, &mut env)?;
    print(result);
    Ok(())
}

fn read<S>(input: S, mut token_buf: &mut Vec<Token>) -> Result<Vec<ast::Expr>>
where
    S: combine::Stream<Item = char>
{
    let tokens = lexer::lex(input)
        .map(|x| x.0)
        .unwrap_or(Vec::new());
    let all_tokens = token_buf.drain(..).chain(tokens).collect::<Vec<_>>();
    let token_iter = combine::from_iter(all_tokens.into_iter());
    let (exprs, unparsed) = parser::parse(combine::State::new(token_iter))?;
    token_buf.extend(unparsed.input);
    Ok(exprs)
}

fn eval(exprs: &[ast::Expr], mut env: &mut Env) -> Result<ast::Expr> {
    match exprs.split_last() {
        Some((last, rest)) => {
            for expr in rest {
                expr.eval(&mut env)?;
            }
            last.eval(&mut env)
        }
        None => Ok(ast::Expr::Nil),
    }
}

fn print(result: ast::Expr) {
    if result != ast::Expr::Nil {
        println!("{}", result);
    }
}
<commit_msg>Don't discard evaluation errors<commit_after>use {lexer, parser, ast};
use std::io::prelude::*;
use std::io::BufReader;
use std::fs::File;
use combine;
use combine::State;
use error::*;
use eval::Env;
use token::Token;

pub fn run(path: &str, mut env: &mut Env) -> Result<()> {
    let mut token_buf = Vec::<Token>::with_capacity(1024);

    let file = File::open(path)?;
    let mut buf_reader = BufReader::new(file);
    let mut source = String::with_capacity(128);
    buf_reader.read_to_string(&mut source)?;
    // TODO: why is trimming necessary?
    exec(State::new(source.trim()), &mut token_buf, &mut env)
}

fn exec<S>(input: S, mut token_buf: &mut Vec<Token>, mut env: &mut Env) -> Result<()>
where
    S: combine::Stream<Item = char>
{
    let exprs = read(input, &mut token_buf)?;
    let result = eval(&exprs, &mut env);
    print(result);
    Ok(())
}

fn read<S>(input: S, mut token_buf: &mut Vec<Token>) -> Result<Vec<ast::Expr>>
where
    S: combine::Stream<Item = char>
{
    let tokens = lexer::lex(input)
        .map(|x| x.0)
        .unwrap_or(Vec::new());
    let all_tokens = token_buf.drain(..).chain(tokens).collect::<Vec<_>>();
    let token_iter = combine::from_iter(all_tokens.into_iter());
    let (exprs, unparsed) = parser::parse(combine::State::new(token_iter))?;
    token_buf.extend(unparsed.input);
    Ok(exprs)
}

fn eval(exprs: &[ast::Expr], mut env: &mut Env) -> Result<ast::Expr> {
    for expr in exprs {
        expr.eval(&mut env)?;
    }
    Ok(ast::Expr::Nil)
}

fn print(result: Result<ast::Expr>) {
    match result {
        Err(err) => println!("Error: {}", err),
        _ => (),
    }
}
<|endoftext|>


<commit_before>//! Handles all status packets

use super::super::super::deque_buffer::DequeBuffer;
use super::super::super::game_connection::GameConnection; //It's super super super effective!

use super::super::PacketHeader;

use super::super::outgoing::OutgoingPacket;
use super::super::outgoing::status::StatusResponsePacket;

/// A packet sent from the client to make the server send a status response packet
pub struct StatusRequestPacket {

    /// The header of this StatusRequestPacket
    pub header: PacketHeader

}

impl StatusRequestPacket {

    /// Decodes this StatusRequestPacket
    ///
    /// **DO NOT DO ANYTHING EXCEPT DECODING!**
    ///
    /// Actual functionality will be handled in the handle function
    #[allow(unused_variables)]
    pub fn decode(header: PacketHeader, connection: &mut GameConnection, buffer: &mut DequeBuffer) -> StatusRequestPacket {

        // Nothing to do here

        StatusRequestPacket { header: header /*etc*/ }

    }

    /// Handles this StatusRequestPacket
    pub fn handle(&self, connection: &mut GameConnection) {
        StatusResponsePacket::new().send(connection);
    }

}

/// A list ping packet sent from the client to the server
pub struct ListPingPacket {

    /// The header of this ListPingPacket
    pub header: PacketHeader,

    /// The ping ID (usually the system time in milliseconds)
    pub payload: i64

}

impl ListPingPacket {

    /// Decodes this Packet
    ///
    /// **DO NOT DO ANYTHING EXCEPT DECODING!**
    ///
    /// Actual functionality will be handled in the handle function
    #[allow(unused_variables)]
    pub fn decode(header: PacketHeader, connection: &mut GameConnection, buffer: &mut DequeBuffer) -> ListPingPacket {

        let id: i64 = buffer.read_signed_long();

        ListPingPacket { header: header, payload: id }

    }

    /// Handles this ListPingPacket
    pub fn handle(&self, connection: &mut GameConnection) {
        super::super::outgoing::status::ListPongPacket::new(self.payload).send(connection);
    }

}<commit_msg>Shorter notation for sending the ListPongPacket<commit_after>//! Handles all status packets

use super::super::super::deque_buffer::DequeBuffer;
use super::super::super::game_connection::GameConnection; //It's super super super effective!

use super::super::PacketHeader;

use super::super::outgoing::OutgoingPacket;
use super::super::outgoing::status::{StatusResponsePacket, ListPongPacket};

/// A packet sent from the client to make the server send a status response packet
pub struct StatusRequestPacket {

    /// The header of this StatusRequestPacket
    pub header: PacketHeader

}

impl StatusRequestPacket {

    /// Decodes this StatusRequestPacket
    ///
    /// **DO NOT DO ANYTHING EXCEPT DECODING!**
    ///
    /// Actual functionality will be handled in the handle function
    #[allow(unused_variables)]
    pub fn decode(header: PacketHeader, connection: &mut GameConnection, buffer: &mut DequeBuffer) -> StatusRequestPacket {

        // Nothing to do here

        StatusRequestPacket { header: header /*etc*/ }

    }

    /// Handles this StatusRequestPacket
    pub fn handle(&self, connection: &mut GameConnection) {
        StatusResponsePacket::new().send(connection);
    }

}

/// A list ping packet sent from the client to the server
pub struct ListPingPacket {

    /// The header of this ListPingPacket
    pub header: PacketHeader,

    /// The ping ID (usually the system time in milliseconds)
    pub payload: i64

}

impl ListPingPacket {

    /// Decodes this Packet
    ///
    /// **DO NOT DO ANYTHING EXCEPT DECODING!**
    ///
    /// Actual functionality will be handled in the handle function
    #[allow(unused_variables)]
    pub fn decode(header: PacketHeader, connection: &mut GameConnection, buffer: &mut DequeBuffer) -> ListPingPacket {

        let id: i64 = buffer.read_signed_long();

        ListPingPacket { header: header, payload: id }

    }

    /// Handles this ListPingPacket
    pub fn handle(&self, connection: &mut GameConnection) {
        ListPongPacket::new(self.payload).send(connection);
    }

}
<|endoftext|>


<commit_before>use std::fmt;
use std::str::FromStr;
use nom::IResult;
use parsers;
use error::Error;

/// A Term can represent a Terminal or Nonterminal node
#[derive(PartialEq, Debug, Clone)]
pub enum Term {
    Terminal(String),
    Nonterminal(String),
}

impl Term {
    // Get `Term` by parsing a string
    pub fn from_str(s: &str) -> Result<Self, Error> {
        match parsers::term_complete(s.as_bytes()) {
            IResult::Done(_, o) => Ok(o),
            IResult::Incomplete(n) => Err(Error::from(n)),
            IResult::Error(e) => Err(Error::from(e)),
        }
    }
}

impl FromStr for Term {
    type Err = Error;
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        Self::from_str(s)
    }
}

impl fmt::Display for Term {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Term::Terminal(ref s) => write!(f, "\"{}\"", s),
            Term::Nonterminal(ref s) => write!(f, "<{}>", s),
        }
    }
}

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

    #[test]
    fn parse_complete() {
        assert_eq!(
            Ok(Term::Nonterminal(String::from("dna"))),
            Term::from_str("<dna>")
        );
    }

    #[test]
    fn parse_error() {
        let incomplete = Term::from_str("<dna");
        assert!(incomplete.is_err());

        let error = incomplete.unwrap_err();
        match error {
            Error::ParseError(ref s) => assert!(s.starts_with("Parsing error:")),
            _ => panic!("Incomplete term should be parse error"),
        }
    }

    #[test]
    fn parse_incomplete() {
        let result = Term::from_str("");
        assert!(result.is_err(), "{:?} should be err", result);
        match result {
            Err(e) => {
                match e {
                    Error::ParseIncomplete(_) => (),
                    e => panic!("should should be Error::ParseIncomplete: {:?}", e),
                }
            }
            Ok(s) => panic!("should should be Error::ParseIncomplete: {}", s),
        }
    }

    #[test]
    fn parse_error_display() {
        let incomplete = Term::from_str("<dna");
        assert!(incomplete.is_err());

        let error = incomplete.unwrap_err().to_string();
        assert!(!error.is_empty());
    }

    #[test]
    fn parse_whitespace_nonterm() {
        let some_space = String::from(" some space ");
        assert_eq!(
            Ok(Term::Nonterminal(some_space.clone())),
            Term::from_str(&format!("<{}>", some_space))
        );
    }

    #[test]
    fn parse_whitespace_term() {
        let some_space = String::from(" some space ");
        assert_eq!(
            Ok(Term::Terminal(some_space.clone())),
            Term::from_str(&format!("\"{}\"", some_space))
        );
    }
}
<commit_msg>Fix quote terminal display<commit_after>use std::fmt;
use std::str::FromStr;
use nom::IResult;
use parsers;
use error::Error;

/// A Term can represent a Terminal or Nonterminal node
#[derive(PartialEq, Debug, Clone)]
pub enum Term {
    Terminal(String),
    Nonterminal(String),
}

impl Term {
    // Get `Term` by parsing a string
    pub fn from_str(s: &str) -> Result<Self, Error> {
        match parsers::term_complete(s.as_bytes()) {
            IResult::Done(_, o) => Ok(o),
            IResult::Incomplete(n) => Err(Error::from(n)),
            IResult::Error(e) => Err(Error::from(e)),
        }
    }
}

impl FromStr for Term {
    type Err = Error;
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        Self::from_str(s)
    }
}

impl fmt::Display for Term {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Term::Terminal(ref s) => {
                if s.contains('"') {
                    write!(f, "'{}'", s)
                } else {
                    write!(f, "\"{}\"", s)
                }
            }
            Term::Nonterminal(ref s) => write!(f, "<{}>", s),
        }
    }
}

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

    #[test]
    fn parse_complete() {
        assert_eq!(
            Ok(Term::Nonterminal(String::from("dna"))),
            Term::from_str("<dna>")
        );
    }

    #[test]
    fn parse_error() {
        let incomplete = Term::from_str("<dna");
        assert!(incomplete.is_err());

        let error = incomplete.unwrap_err();
        match error {
            Error::ParseError(ref s) => assert!(s.starts_with("Parsing error:")),
            _ => panic!("Incomplete term should be parse error"),
        }
    }

    #[test]
    fn parse_incomplete() {
        let result = Term::from_str("");
        assert!(result.is_err(), "{:?} should be err", result);
        match result {
            Err(e) => {
                match e {
                    Error::ParseIncomplete(_) => (),
                    e => panic!("should should be Error::ParseIncomplete: {:?}", e),
                }
            }
            Ok(s) => panic!("should should be Error::ParseIncomplete: {}", s),
        }
    }

    #[test]
    fn parse_error_display() {
        let incomplete = Term::from_str("<dna");
        assert!(incomplete.is_err());

        let error = incomplete.unwrap_err().to_string();
        assert!(!error.is_empty());
    }

    #[test]
    fn parse_whitespace_nonterm() {
        let some_space = String::from(" some space ");
        assert_eq!(
            Ok(Term::Nonterminal(some_space.clone())),
            Term::from_str(&format!("<{}>", some_space))
        );
    }

    #[test]
    fn parse_whitespace_term() {
        let some_space = String::from(" some space ");
        assert_eq!(
            Ok(Term::Terminal(some_space.clone())),
            Term::from_str(&format!("\"{}\"", some_space))
        );
    }

    #[test]
    fn parse_quote_term() {
        let quote_term = Term::from_str("'\"'");
        assert_eq!(Ok(Term::Terminal(String::from("\""))), quote_term);
    }

    #[test]
    fn parse_single_quote_term() {
        let quote_term = Term::from_str("\"'\"");
        assert_eq!(Ok(Term::Terminal(String::from("'"))), quote_term);
    }

    #[test]
    fn quote_term_to_string_and_back() {
        let quote = Term::Terminal(String::from("\""));
        let to_string = quote.to_string();
        let from_string = Term::from_str(&to_string);
        assert_eq!(Ok(Term::Terminal(String::from("\""))), from_string);
    }
}
<|endoftext|>


<commit_before>use openssl::ssl::{SslMethod, SslConnectorBuilder};
use std::io::{Read, Write};
use std::net::{TcpStream, TcpListener};
use std::thread;

use super::*;

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

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

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

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

#[test]
fn server() {
    let buf = include_bytes!("../test/identity.p12");
    let pkcs12 = Pkcs12::from_der(buf, "mypass").unwrap();
    let builder = TlsAcceptor::builder(pkcs12).unwrap().build().unwrap();

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

    thread::spawn(move || {
        let socket = listener.accept().unwrap().0;
        let mut socket = builder.accept(socket).unwrap();

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

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

    let socket = TcpStream::connect(("localhost", port)).unwrap();
    let mut builder = SslConnectorBuilder::new(SslMethod::tls()).unwrap();
    builder.builder_mut().set_ca_file("test/root-ca.pem").unwrap();
    let connector = builder.build();
    let mut socket = connector.connect("foobar.com", socket).unwrap();
    assert_eq!(socket.ssl().version(), "TLSv1.2");
    socket.write_all(b"hello").unwrap();
    let mut buf = vec![];
    socket.read_to_end(&mut buf).unwrap();
    assert_eq!(buf, b"world");
}
<commit_msg>Add a debug print to server test<commit_after>use openssl::ssl::{SslMethod, SslConnectorBuilder};
use std::io::{Read, Write};
use std::net::{TcpStream, TcpListener};
use std::thread;

use super::*;

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

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

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

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

#[test]
fn server() {
    let buf = include_bytes!("../test/identity.p12");
    let pkcs12 = Pkcs12::from_der(buf, "mypass").unwrap();
    let builder = TlsAcceptor::builder(pkcs12).unwrap().build().unwrap();

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

    thread::spawn(move || {
        let socket = listener.accept().unwrap().0;
        let mut socket = builder.accept(socket).unwrap();

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

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

    let socket = TcpStream::connect(("localhost", port)).unwrap();
    let mut builder = SslConnectorBuilder::new(SslMethod::tls()).unwrap();
    builder.builder_mut().set_ca_file("test/root-ca.pem").unwrap();
    let connector = builder.build();
    let mut socket = connector.connect("foobar.com", socket).unwrap();
    println!("{}", socket.ssl().current_cipher().unwrap().description());
    assert_eq!(socket.ssl().version(), "TLSv1.2");
    socket.write_all(b"hello").unwrap();
    let mut buf = vec![];
    socket.read_to_end(&mut buf).unwrap();
    assert_eq!(buf, b"world");
}
<|endoftext|>


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

use super::*;

macro_rules! p {
    ($e:expr) => {
        match $e {
            Ok(r) => r,
            Err(e) => panic!("{:?}", e),
        }
    }
}

#[test]
fn connect_google() {
    let builder = p!(TlsConnector::builder());
    let builder = p!(builder.build());
    let s = p!(TcpStream::connect("google.com:443"));
    let mut socket = p!(builder.connect("google.com", s));

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

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

#[test]
fn connect_bad_hostname() {
    let builder = p!(TlsConnector::builder());
    let builder = p!(builder.build());
    let s = p!(TcpStream::connect("google.com:443"));
    builder.connect("goggle.com", s).unwrap_err();
}

#[test]
fn connect_bad_hostname_ignored() {
    let builder = p!(TlsConnector::builder());
    let builder = p!(builder.build());
    let s = p!(TcpStream::connect("google.com:443"));
    builder.danger_connect_without_providing_domain_for_certificate_verification_and_server_name_indication(s).unwrap();
}

#[test]
fn server() {
    let buf = include_bytes!("../test/identity.p12");
    let pkcs12 = p!(Pkcs12::from_der(buf, "mypass"));
    let builder = p!(TlsAcceptor::builder(pkcs12));
    let builder = p!(builder.build());

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

    let j = thread::spawn(move || {
        let socket = p!(listener.accept()).0;
        let mut socket = p!(builder.accept(socket));

        let mut buf = [0; 5];
        p!(socket.read_exact(&mut buf));
        assert_eq!(&buf, b"hello");

        p!(socket.write_all(b"world"));
    });

    let root_ca = include_bytes!("../test/root-ca.der");
    let root_ca = Certificate::from_der(root_ca).unwrap();

    let socket = p!(TcpStream::connect(("localhost", port)));
    let mut builder = p!(TlsConnector::builder());
    p!(builder.add_root_certificate(root_ca));
    let builder = p!(builder.build());
    let mut socket = p!(builder.connect("foobar.com", socket));

    p!(socket.write_all(b"hello"));
    let mut buf = vec![];
    p!(socket.read_to_end(&mut buf));
    assert_eq!(buf, b"world");

    p!(j.join());
}

#[test]
fn server_tls11_only() {
    let buf = include_bytes!("../test/identity.p12");
    let pkcs12 = p!(Pkcs12::from_der(buf, "mypass"));
    let mut builder = p!(TlsAcceptor::builder(pkcs12));
    p!(builder.supported_protocols(&[Protocol::Tlsv11]));
    let builder = p!(builder.build());

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

    let j = thread::spawn(move || {
        let socket = p!(listener.accept()).0;
        let mut socket = p!(builder.accept(socket));

        let mut buf = [0; 5];
        p!(socket.read_exact(&mut buf));
        assert_eq!(&buf, b"hello");

        p!(socket.write_all(b"world"));
    });

    let root_ca = include_bytes!("../test/root-ca.der");
    let root_ca = Certificate::from_der(root_ca).unwrap();

    let socket = p!(TcpStream::connect(("localhost", port)));
    let mut builder = p!(TlsConnector::builder());
    p!(builder.add_root_certificate(root_ca));
    p!(builder.supported_protocols(&[Protocol::Tlsv11]));
    let builder = p!(builder.build());
    let mut socket = p!(builder.connect("foobar.com", socket));

    p!(socket.write_all(b"hello"));
    let mut buf = vec![];
    p!(socket.read_to_end(&mut buf));
    assert_eq!(buf, b"world");

    p!(j.join());
}

#[test]
fn server_no_shared_protocol() {
    let buf = include_bytes!("../test/identity.p12");
    let pkcs12 = p!(Pkcs12::from_der(buf, "mypass"));
    let mut builder = p!(TlsAcceptor::builder(pkcs12));
    p!(builder.supported_protocols(&[Protocol::Tlsv12]));
    let builder = p!(builder.build());

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

    let j = thread::spawn(move || {
        let socket = p!(listener.accept()).0;
        assert!(builder.accept(socket).is_err());
    });

    let root_ca = include_bytes!("../test/root-ca.der");
    let root_ca = Certificate::from_der(root_ca).unwrap();

    let socket = p!(TcpStream::connect(("localhost", port)));
    let mut builder = p!(TlsConnector::builder());
    p!(builder.add_root_certificate(root_ca));
    p!(builder.supported_protocols(&[Protocol::Sslv3, Protocol::Tlsv10, Protocol::Tlsv11]));
    let builder = p!(builder.build());
    assert!(builder.connect("foobar.com", socket).is_err());

    p!(j.join());
}

#[test]
fn server_untrusted() {
    let buf = include_bytes!("../test/identity.p12");
    let pkcs12 = p!(Pkcs12::from_der(buf, "mypass"));
    let builder = p!(TlsAcceptor::builder(pkcs12));
    let builder = p!(builder.build());

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

    let j = thread::spawn(move || {
        let socket = p!(listener.accept()).0;
        // FIXME should assert error
        // https://github.com/steffengy/schannel-rs/issues/20
        let _ = builder.accept(socket);
    });

    let socket = p!(TcpStream::connect(("localhost", port)));
    let builder = p!(TlsConnector::builder());
    let builder = p!(builder.build());
    builder.connect("foobar.com", socket).unwrap_err();

    p!(j.join());
}

#[test]
fn shutdown() {
    let buf = include_bytes!("../test/identity.p12");
    let pkcs12 = p!(Pkcs12::from_der(buf, "mypass"));
    let builder = p!(TlsAcceptor::builder(pkcs12));
    let builder = p!(builder.build());

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

    let j = thread::spawn(move || {
        let socket = p!(listener.accept()).0;
        let mut socket = p!(builder.accept(socket));

        let mut buf = [0; 5];
        p!(socket.read_exact(&mut buf));
        assert_eq!(&buf, b"hello");

        assert_eq!(p!(socket.read(&mut buf)), 0);
        p!(socket.shutdown());
    });

    let root_ca = include_bytes!("../test/root-ca.der");
    let root_ca = Certificate::from_der(root_ca).unwrap();

    let socket = p!(TcpStream::connect(("localhost", port)));
    let mut builder = p!(TlsConnector::builder());
    p!(builder.add_root_certificate(root_ca));
    let builder = p!(builder.build());
    let mut socket = p!(builder.connect("foobar.com", socket));

    p!(socket.write_all(b"hello"));
    p!(socket.shutdown());

    p!(j.join());
}
<commit_msg>Add failing test to check testing is working.<commit_after>use std::io::{Read, Write};
use std::net::{TcpStream, TcpListener};
use std::thread;

use super::*;

macro_rules! p {
    ($e:expr) => {
        match $e {
            Ok(r) => r,
            Err(e) => panic!("{:?}", e),
        }
    }
}

#[test]
fn deliberate_failure() {
    assert!(false);
}

#[test]
fn connect_google() {
    let builder = p!(TlsConnector::builder());
    let builder = p!(builder.build());
    let s = p!(TcpStream::connect("google.com:443"));
    let mut socket = p!(builder.connect("google.com", s));

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

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

#[test]
fn connect_bad_hostname() {
    let builder = p!(TlsConnector::builder());
    let builder = p!(builder.build());
    let s = p!(TcpStream::connect("google.com:443"));
    builder.connect("goggle.com", s).unwrap_err();
}

#[test]
fn connect_bad_hostname_ignored() {
    let builder = p!(TlsConnector::builder());
    let builder = p!(builder.build());
    let s = p!(TcpStream::connect("google.com:443"));
    builder.danger_connect_without_providing_domain_for_certificate_verification_and_server_name_indication(s).unwrap();
}

#[test]
fn server() {
    let buf = include_bytes!("../test/identity.p12");
    let pkcs12 = p!(Pkcs12::from_der(buf, "mypass"));
    let builder = p!(TlsAcceptor::builder(pkcs12));
    let builder = p!(builder.build());

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

    let j = thread::spawn(move || {
        let socket = p!(listener.accept()).0;
        let mut socket = p!(builder.accept(socket));

        let mut buf = [0; 5];
        p!(socket.read_exact(&mut buf));
        assert_eq!(&buf, b"hello");

        p!(socket.write_all(b"world"));
    });

    let root_ca = include_bytes!("../test/root-ca.der");
    let root_ca = Certificate::from_der(root_ca).unwrap();

    let socket = p!(TcpStream::connect(("localhost", port)));
    let mut builder = p!(TlsConnector::builder());
    p!(builder.add_root_certificate(root_ca));
    let builder = p!(builder.build());
    let mut socket = p!(builder.connect("foobar.com", socket));

    p!(socket.write_all(b"hello"));
    let mut buf = vec![];
    p!(socket.read_to_end(&mut buf));
    assert_eq!(buf, b"world");

    p!(j.join());
}

#[test]
fn server_tls11_only() {
    let buf = include_bytes!("../test/identity.p12");
    let pkcs12 = p!(Pkcs12::from_der(buf, "mypass"));
    let mut builder = p!(TlsAcceptor::builder(pkcs12));
    p!(builder.supported_protocols(&[Protocol::Tlsv11]));
    let builder = p!(builder.build());

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

    let j = thread::spawn(move || {
        let socket = p!(listener.accept()).0;
        let mut socket = p!(builder.accept(socket));

        let mut buf = [0; 5];
        p!(socket.read_exact(&mut buf));
        assert_eq!(&buf, b"hello");

        p!(socket.write_all(b"world"));
    });

    let root_ca = include_bytes!("../test/root-ca.der");
    let root_ca = Certificate::from_der(root_ca).unwrap();

    let socket = p!(TcpStream::connect(("localhost", port)));
    let mut builder = p!(TlsConnector::builder());
    p!(builder.add_root_certificate(root_ca));
    p!(builder.supported_protocols(&[Protocol::Tlsv11]));
    let builder = p!(builder.build());
    let mut socket = p!(builder.connect("foobar.com", socket));

    p!(socket.write_all(b"hello"));
    let mut buf = vec![];
    p!(socket.read_to_end(&mut buf));
    assert_eq!(buf, b"world");

    p!(j.join());
}

#[test]
fn server_no_shared_protocol() {
    let buf = include_bytes!("../test/identity.p12");
    let pkcs12 = p!(Pkcs12::from_der(buf, "mypass"));
    let mut builder = p!(TlsAcceptor::builder(pkcs12));
    p!(builder.supported_protocols(&[Protocol::Tlsv12]));
    let builder = p!(builder.build());

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

    let j = thread::spawn(move || {
        let socket = p!(listener.accept()).0;
        assert!(builder.accept(socket).is_err());
    });

    let root_ca = include_bytes!("../test/root-ca.der");
    let root_ca = Certificate::from_der(root_ca).unwrap();

    let socket = p!(TcpStream::connect(("localhost", port)));
    let mut builder = p!(TlsConnector::builder());
    p!(builder.add_root_certificate(root_ca));
    p!(builder.supported_protocols(&[Protocol::Sslv3, Protocol::Tlsv10, Protocol::Tlsv11]));
    let builder = p!(builder.build());
    assert!(builder.connect("foobar.com", socket).is_err());

    p!(j.join());
}

#[test]
fn server_untrusted() {
    let buf = include_bytes!("../test/identity.p12");
    let pkcs12 = p!(Pkcs12::from_der(buf, "mypass"));
    let builder = p!(TlsAcceptor::builder(pkcs12));
    let builder = p!(builder.build());

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

    let j = thread::spawn(move || {
        let socket = p!(listener.accept()).0;
        // FIXME should assert error
        // https://github.com/steffengy/schannel-rs/issues/20
        let _ = builder.accept(socket);
    });

    let socket = p!(TcpStream::connect(("localhost", port)));
    let builder = p!(TlsConnector::builder());
    let builder = p!(builder.build());
    builder.connect("foobar.com", socket).unwrap_err();

    p!(j.join());
}

#[test]
fn shutdown() {
    let buf = include_bytes!("../test/identity.p12");
    let pkcs12 = p!(Pkcs12::from_der(buf, "mypass"));
    let builder = p!(TlsAcceptor::builder(pkcs12));
    let builder = p!(builder.build());

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

    let j = thread::spawn(move || {
        let socket = p!(listener.accept()).0;
        let mut socket = p!(builder.accept(socket));

        let mut buf = [0; 5];
        p!(socket.read_exact(&mut buf));
        assert_eq!(&buf, b"hello");

        assert_eq!(p!(socket.read(&mut buf)), 0);
        p!(socket.shutdown());
    });

    let root_ca = include_bytes!("../test/root-ca.der");
    let root_ca = Certificate::from_der(root_ca).unwrap();

    let socket = p!(TcpStream::connect(("localhost", port)));
    let mut builder = p!(TlsConnector::builder());
    p!(builder.add_root_certificate(root_ca));
    let builder = p!(builder.build());
    let mut socket = p!(builder.connect("foobar.com", socket));

    p!(socket.write_all(b"hello"));
    p!(socket.shutdown());

    p!(j.join());
}
<|endoftext|>


<commit_before>use dora_parser::ast::Ast;
use dora_parser::interner::Interner;
use dora_parser::lexer::reader::Reader;
use dora_parser::parser::{NodeIdGenerator, Parser};

use ctxt::VM;
use driver::cmd::Args;
use os;
use semck;

pub fn parse<F, T>(code: &'static str, f: F) -> T
where
    F: FnOnce(&VM) -> T,
{
    parse_with_errors(code, |vm| {
        if vm.diag.lock().has_errors() {
            vm.diag.lock().dump();
            println!("{}", code);
            panic!("unexpected error in test::parse()");
        }

        f(vm)
    })
}

pub fn parse_with_errors<F, T>(code: &'static str, f: F) -> T
where
    F: FnOnce(&VM) -> T,
{
    os::mem::init_page_size();

    let id_generator = NodeIdGenerator::new();
    let mut interner = Interner::new();
    let mut ast = Ast::new();
    let args: Args = Default::default();

    for file in &[
        "stdlib/Bool.dora",
        "stdlib/Byte.dora",
        "stdlib/Char.dora",
        "stdlib/Int.dora",
        "stdlib/Long.dora",
        "stdlib/Float.dora",
        "stdlib/Double.dora",

        "stdlib/Array.dora",
        "stdlib/String.dora",

        "stdlib/Exception.dora",

        "stdlib/Thread.dora",

        "stdlib/Equals.dora",
        "stdlib/Comparable.dora",
        "stdlib/Sortable.dora",
        "stdlib/Hash.dora",
        "stdlib/Default.dora",

        "stdlib/prelude.dora",
        "stdlib/Testing.dora",
    ] {
        let reader = Reader::from_file(file).unwrap();
        let mut parser = Parser::new(reader, &id_generator, &mut ast, &mut interner);
        parser.parse().unwrap()
    }

    {
        let reader = Reader::from_string(code);
        let mut parser = Parser::new(reader, &id_generator, &mut ast, &mut interner);
        parser.parse().unwrap()
    }

    let mut vm = VM::new(args, &ast, interner);

    semck::check(&mut vm);

    f(&vm)
}
<commit_msg>reformat code<commit_after>use dora_parser::ast::Ast;
use dora_parser::interner::Interner;
use dora_parser::lexer::reader::Reader;
use dora_parser::parser::{NodeIdGenerator, Parser};

use ctxt::VM;
use driver::cmd::Args;
use os;
use semck;

pub fn parse<F, T>(code: &'static str, f: F) -> T
where
    F: FnOnce(&VM) -> T,
{
    parse_with_errors(code, |vm| {
        if vm.diag.lock().has_errors() {
            vm.diag.lock().dump();
            println!("{}", code);
            panic!("unexpected error in test::parse()");
        }

        f(vm)
    })
}

pub fn parse_with_errors<F, T>(code: &'static str, f: F) -> T
where
    F: FnOnce(&VM) -> T,
{
    os::mem::init_page_size();

    let id_generator = NodeIdGenerator::new();
    let mut interner = Interner::new();
    let mut ast = Ast::new();
    let args: Args = Default::default();

    for file in &[
        "stdlib/Bool.dora",
        "stdlib/Byte.dora",
        "stdlib/Char.dora",
        "stdlib/Int.dora",
        "stdlib/Long.dora",
        "stdlib/Float.dora",
        "stdlib/Double.dora",
        "stdlib/Array.dora",
        "stdlib/String.dora",
        "stdlib/Exception.dora",
        "stdlib/Thread.dora",
        "stdlib/Equals.dora",
        "stdlib/Comparable.dora",
        "stdlib/Sortable.dora",
        "stdlib/Hash.dora",
        "stdlib/Default.dora",
        "stdlib/prelude.dora",
        "stdlib/Testing.dora",
    ] {
        let reader = Reader::from_file(file).unwrap();
        let mut parser = Parser::new(reader, &id_generator, &mut ast, &mut interner);
        parser.parse().unwrap()
    }

    {
        let reader = Reader::from_string(code);
        let mut parser = Parser::new(reader, &id_generator, &mut ast, &mut interner);
        parser.parse().unwrap()
    }

    let mut vm = VM::new(args, &ast, interner);

    semck::check(&mut vm);

    f(&vm)
}
<|endoftext|>


<commit_before>use hb;
use std;

use libc::c_void;

pub use font_funcs::FontFuncs;
use font_funcs::FontFuncsImpl;
use face::Face;
use common::{HarfbuzzObject, Owned, Shared};

use std::marker::PhantomData;
use std::ffi::CStr;

pub type Glyph = u32;
pub type FontExtents = hb::hb_font_extents_t;
pub type GlyphExtents = hb::hb_glyph_extents_t;
pub type Position = hb::hb_position_t;

pub(crate) extern "C" fn destroy_box<U>(ptr: *mut c_void) {
    unsafe { Box::from_raw(ptr as *mut U) };
}

/// A font is the most important concept in harfbuzz.
///
/// A font can be created either as a subfont of an existing font or directly from a `Face` using
/// its `create_font` function.
#[derive(Debug)]
#[repr(C)]
pub struct Font<'a> {
    _raw: hb::hb_font_t,
    _marker: PhantomData<&'a hb::hb_font_t>,
}

impl<'a> Font<'a> {
    /// Create a new font with a specified `Face`.
    pub fn new<T: Into<Shared<Face<'a>>>>(face: T) -> Owned<Self> {
        unsafe {
            let face = face.into();
            let raw_font = hb::hb_font_create(Shared::into_raw(face));
            // set default font funcs for a completely new font
            // hb::hb_ot_font_set_funcs(raw_font);
            Owned::from_raw(raw_font)
        }
    }

    /// Create a new sub font from the current font that by default inherits its parent font's
    /// face, scale, ppem and font funcs.
    pub fn create_sub_font<T: Into<Shared<Font<'a>>>>(font: T) -> Owned<Font<'a>> {
        unsafe { Owned::from_raw(hb::hb_font_create_sub_font(font.into().as_raw())) }
    }

    /// Returns the parent font.
    pub fn parent(&self) -> &Font<'a> {
        unsafe { Font::from_raw(hb::hb_font_get_parent(self.as_raw())) }
    }

    /// Returns the face which was used to create the font.
    pub fn face(&self) -> &Face<'a> {
        unsafe { Face::from_raw(hb::hb_font_get_face(self.as_raw())) }
    }

    pub fn scale(&self) -> (i32, i32) {
        let mut result = (0i32, 0i32);
        unsafe { hb::hb_font_get_scale(self.as_raw(), &mut result.0, &mut result.1) };
        result
    }

    pub fn set_scale(&mut self, x: i32, y: i32) -> &mut Font<'a> {
        unsafe { hb::hb_font_set_scale(self.as_raw(), x, y) };
        self
    }

    pub fn ppem(&self) -> (u32, u32) {
        let mut result = (0u32, 0u32);
        unsafe { hb::hb_font_get_ppem(self.as_raw(), &mut result.0, &mut result.1) };
        result
    }

    pub fn set_ppem(&mut self, x: u32, y: u32) -> &mut Font<'a> {
        unsafe { hb::hb_font_set_ppem(self.as_raw(), x, y) };
        self
    }

    pub fn set_font_funcs<FuncsType>(&mut self, funcs: FuncsType) -> &mut Font<'a>
    where
        FuncsType: 'a + Send + Sync + FontFuncs,
    {
        let funcs_impl: Owned<FontFuncsImpl<FuncsType>> = FontFuncsImpl::from_trait_impl();
        let font_data = Box::new(funcs);
        unsafe {
            hb::hb_font_set_funcs(
                self.as_raw(),
                funcs_impl.as_raw(),
                Box::into_raw(font_data) as *mut _,
                Some(destroy_box::<FuncsType>),
            )
        };
        self
    }

    // scale from parent font
    pub(crate) fn parent_scale_x_distance(&self, v: Position) -> Position {
        let parent_x_scale = self.parent().scale().0;
        let x_scale = self.scale().0;
        if parent_x_scale != x_scale {
            (v as i64 * x_scale as i64 / parent_x_scale as i64) as Position
        } else {
            v
        }
    }

    // scale from parent font
    pub(crate) fn parent_scale_y_distance(&self, v: Position) -> Position {
        let parent_y_scale = self.parent().scale().1;
        let y_scale = self.scale().1;
        if parent_y_scale != y_scale {
            (v as i64 * y_scale as i64 / parent_y_scale as i64) as Position
        } else {
            v
        }
    }

    // scale from parent font
    pub(crate) fn parent_scale_position(&self, v: (Position, Position)) -> (Position, Position) {
        (
            self.parent_scale_x_distance(v.0),
            self.parent_scale_y_distance(v.1),
        )
    }

    pub fn get_font_h_extents(&self) -> Option<FontExtents> {
        unsafe {
            let mut extents = std::mem::uninitialized::<FontExtents>();
            let result = hb::hb_font_get_h_extents(self.as_raw(), &mut extents);
            if result == 1 {
                Some(extents)
            } else {
                None
            }
        }
    }

    pub fn get_font_v_extents(&self) -> Option<FontExtents> {
        unsafe {
            let mut extents = std::mem::uninitialized::<FontExtents>();
            let result = hb::hb_font_get_v_extents(self.as_raw(), &mut extents);
            if result == 1 {
                Some(extents)
            } else {
                None
            }
        }
    }

    pub fn get_nominal_glyph(&self, c: char) -> Option<Glyph> {
        unsafe {
            let mut glyph = 0;
            let result = hb::hb_font_get_nominal_glyph(self.as_raw(), c as u32, &mut glyph);
            if result == 1 {
                Some(glyph)
            } else {
                None
            }
        }
    }

    pub fn get_variation_glyph(&self, c: char, v: char) -> Option<Glyph> {
        unsafe {
            let mut glyph = 0;
            let result =
                hb::hb_font_get_variation_glyph(self.as_raw(), c as u32, v as u32, &mut glyph);
            if result == 1 {
                Some(glyph)
            } else {
                None
            }
        }
    }

    pub fn get_glyph_h_advance(&self, glyph: Glyph) -> Position {
        unsafe { hb::hb_font_get_glyph_h_advance(self.as_raw(), glyph) }
    }

    pub fn get_glyph_v_advance(&self, glyph: Glyph) -> Position {
        unsafe { hb::hb_font_get_glyph_v_advance(self.as_raw(), glyph) }
    }

    pub fn get_glyph_h_origin(&self, glyph: Glyph) -> Option<(Position, Position)> {
        unsafe {
            let mut pos = (0, 0);
            let result =
                hb::hb_font_get_glyph_h_origin(self.as_raw(), glyph, &mut pos.0, &mut pos.1);
            if result == 1 {
                Some(pos)
            } else {
                None
            }
        }
    }

    pub fn get_glyph_v_origin(&self, glyph: Glyph) -> Option<(Position, Position)> {
        unsafe {
            let mut pos = (0, 0);
            let result =
                hb::hb_font_get_glyph_v_origin(self.as_raw(), glyph, &mut pos.0, &mut pos.1);
            if result == 1 {
                Some(pos)
            } else {
                None
            }
        }
    }

    pub fn get_glyph_h_kerning(&self, left: Glyph, right: Glyph) -> Position {
        unsafe { hb::hb_font_get_glyph_h_kerning(self.as_raw(), left, right) }
    }

    pub fn get_glyph_v_kerning(&self, before: Glyph, after: Glyph) -> Position {
        unsafe { hb::hb_font_get_glyph_v_kerning(self.as_raw(), before, after) }
    }

    pub fn get_glyph_extents(&self, glyph: Glyph) -> Option<GlyphExtents> {
        unsafe {
            let mut extents = std::mem::uninitialized::<GlyphExtents>();
            let result = hb::hb_font_get_glyph_extents(self.as_raw(), glyph, &mut extents);
            if result == 1 {
                Some(extents)
            } else {
                None
            }
        }
    }

    pub fn get_glyph_contour_point(
        &self,
        glyph: Glyph,
        point_index: u32,
    ) -> Option<(Position, Position)> {
        unsafe {
            let mut pos = (0, 0);
            let result = hb::hb_font_get_glyph_contour_point(
                self.as_raw(),
                glyph,
                point_index,
                &mut pos.0,
                &mut pos.1,
            );
            if result == 1 {
                Some(pos)
            } else {
                None
            }
        }
    }

    pub fn get_glyph_name(&self, glyph: Glyph) -> Option<String> {
        let mut buffer = [0; 256];
        let result = unsafe {
            hb::hb_font_get_glyph_name(
                self.as_raw(),
                glyph,
                buffer.as_mut_ptr() as *mut _,
                buffer.len() as u32,
            )
        };
        if result == 1 {
            let cstr = unsafe { CStr::from_ptr(buffer.as_ptr()) };
            cstr.to_str().ok().map(|y| y.to_string())
        } else {
            None
        }
    }

    pub fn get_glyph_from_name(&self, name: &str) -> Option<Glyph> {
        unsafe {
            let mut glyph = 0;
            let result = hb::hb_font_get_glyph_from_name(
                self.as_raw(),
                name.as_ptr() as *mut _,
                name.len() as i32,
                &mut glyph,
            );
            if result == 1 {
                Some(glyph)
            } else {
                None
            }
        }
    }
}

impl<'a> HarfbuzzObject for Font<'a> {
    type Raw = hb::hb_font_t;

    unsafe fn reference(&self) {
        hb::hb_font_reference(self.as_raw());
    }

    unsafe fn dereference(&self) {
        hb::hb_font_destroy(self.as_raw());
    }
}
<commit_msg>Don't return anything in Font setters<commit_after>use hb;
use std;

use libc::c_void;

pub use font_funcs::FontFuncs;
use font_funcs::FontFuncsImpl;
use face::Face;
use common::{HarfbuzzObject, Owned, Shared};

use std::marker::PhantomData;
use std::ffi::CStr;

pub type Glyph = u32;
pub type FontExtents = hb::hb_font_extents_t;
pub type GlyphExtents = hb::hb_glyph_extents_t;
pub type Position = hb::hb_position_t;

pub(crate) extern "C" fn destroy_box<U>(ptr: *mut c_void) {
    unsafe { Box::from_raw(ptr as *mut U) };
}

/// A font is the most important concept in harfbuzz.
///
/// A font can be created either as a subfont of an existing font or directly from a `Face` using
/// its `create_font` function.
#[derive(Debug)]
#[repr(C)]
pub struct Font<'a> {
    _raw: hb::hb_font_t,
    _marker: PhantomData<&'a hb::hb_font_t>,
}

impl<'a> Font<'a> {
    /// Create a new font with a specified `Face`.
    pub fn new<T: Into<Shared<Face<'a>>>>(face: T) -> Owned<Self> {
        unsafe {
            let face = face.into();
            let raw_font = hb::hb_font_create(Shared::into_raw(face));
            // set default font funcs for a completely new font
            // hb::hb_ot_font_set_funcs(raw_font);
            Owned::from_raw(raw_font)
        }
    }

    /// Create a new sub font from the current font that by default inherits its parent font's
    /// face, scale, ppem and font funcs.
    pub fn create_sub_font<T: Into<Shared<Font<'a>>>>(font: T) -> Owned<Font<'a>> {
        unsafe { Owned::from_raw(hb::hb_font_create_sub_font(font.into().as_raw())) }
    }

    /// Returns the parent font.
    pub fn parent(&self) -> &Font<'a> {
        unsafe { Font::from_raw(hb::hb_font_get_parent(self.as_raw())) }
    }

    /// Returns the face which was used to create the font.
    pub fn face(&self) -> &Face<'a> {
        unsafe { Face::from_raw(hb::hb_font_get_face(self.as_raw())) }
    }

    pub fn scale(&self) -> (i32, i32) {
        let mut result = (0i32, 0i32);
        unsafe { hb::hb_font_get_scale(self.as_raw(), &mut result.0, &mut result.1) };
        result
    }

    pub fn set_scale(&mut self, x: i32, y: i32) {
        unsafe { hb::hb_font_set_scale(self.as_raw(), x, y) };
    }

    pub fn ppem(&self) -> (u32, u32) {
        let mut result = (0u32, 0u32);
        unsafe { hb::hb_font_get_ppem(self.as_raw(), &mut result.0, &mut result.1) };
        result
    }

    pub fn set_ppem(&mut self, x: u32, y: u32) {
        unsafe { hb::hb_font_set_ppem(self.as_raw(), x, y) };
    }

    pub fn set_font_funcs<FuncsType>(&mut self, funcs: FuncsType)
    where
        FuncsType: 'a + Send + Sync + FontFuncs,
    {
        let funcs_impl: Owned<FontFuncsImpl<FuncsType>> = FontFuncsImpl::from_trait_impl();
        let font_data = Box::new(funcs);
        unsafe {
            hb::hb_font_set_funcs(
                self.as_raw(),
                funcs_impl.as_raw(),
                Box::into_raw(font_data) as *mut _,
                Some(destroy_box::<FuncsType>),
            )
        };
    }

    // scale from parent font
    pub(crate) fn parent_scale_x_distance(&self, v: Position) -> Position {
        let parent_x_scale = self.parent().scale().0;
        let x_scale = self.scale().0;
        if parent_x_scale != x_scale {
            (v as i64 * x_scale as i64 / parent_x_scale as i64) as Position
        } else {
            v
        }
    }

    // scale from parent font
    pub(crate) fn parent_scale_y_distance(&self, v: Position) -> Position {
        let parent_y_scale = self.parent().scale().1;
        let y_scale = self.scale().1;
        if parent_y_scale != y_scale {
            (v as i64 * y_scale as i64 / parent_y_scale as i64) as Position
        } else {
            v
        }
    }

    // scale from parent font
    pub(crate) fn parent_scale_position(&self, v: (Position, Position)) -> (Position, Position) {
        (
            self.parent_scale_x_distance(v.0),
            self.parent_scale_y_distance(v.1),
        )
    }

    pub fn get_font_h_extents(&self) -> Option<FontExtents> {
        unsafe {
            let mut extents = std::mem::uninitialized::<FontExtents>();
            let result = hb::hb_font_get_h_extents(self.as_raw(), &mut extents);
            if result == 1 {
                Some(extents)
            } else {
                None
            }
        }
    }

    pub fn get_font_v_extents(&self) -> Option<FontExtents> {
        unsafe {
            let mut extents = std::mem::uninitialized::<FontExtents>();
            let result = hb::hb_font_get_v_extents(self.as_raw(), &mut extents);
            if result == 1 {
                Some(extents)
            } else {
                None
            }
        }
    }

    pub fn get_nominal_glyph(&self, c: char) -> Option<Glyph> {
        unsafe {
            let mut glyph = 0;
            let result = hb::hb_font_get_nominal_glyph(self.as_raw(), c as u32, &mut glyph);
            if result == 1 {
                Some(glyph)
            } else {
                None
            }
        }
    }

    pub fn get_variation_glyph(&self, c: char, v: char) -> Option<Glyph> {
        unsafe {
            let mut glyph = 0;
            let result =
                hb::hb_font_get_variation_glyph(self.as_raw(), c as u32, v as u32, &mut glyph);
            if result == 1 {
                Some(glyph)
            } else {
                None
            }
        }
    }

    pub fn get_glyph_h_advance(&self, glyph: Glyph) -> Position {
        unsafe { hb::hb_font_get_glyph_h_advance(self.as_raw(), glyph) }
    }

    pub fn get_glyph_v_advance(&self, glyph: Glyph) -> Position {
        unsafe { hb::hb_font_get_glyph_v_advance(self.as_raw(), glyph) }
    }

    pub fn get_glyph_h_origin(&self, glyph: Glyph) -> Option<(Position, Position)> {
        unsafe {
            let mut pos = (0, 0);
            let result =
                hb::hb_font_get_glyph_h_origin(self.as_raw(), glyph, &mut pos.0, &mut pos.1);
            if result == 1 {
                Some(pos)
            } else {
                None
            }
        }
    }

    pub fn get_glyph_v_origin(&self, glyph: Glyph) -> Option<(Position, Position)> {
        unsafe {
            let mut pos = (0, 0);
            let result =
                hb::hb_font_get_glyph_v_origin(self.as_raw(), glyph, &mut pos.0, &mut pos.1);
            if result == 1 {
                Some(pos)
            } else {
                None
            }
        }
    }

    pub fn get_glyph_h_kerning(&self, left: Glyph, right: Glyph) -> Position {
        unsafe { hb::hb_font_get_glyph_h_kerning(self.as_raw(), left, right) }
    }

    pub fn get_glyph_v_kerning(&self, before: Glyph, after: Glyph) -> Position {
        unsafe { hb::hb_font_get_glyph_v_kerning(self.as_raw(), before, after) }
    }

    pub fn get_glyph_extents(&self, glyph: Glyph) -> Option<GlyphExtents> {
        unsafe {
            let mut extents = std::mem::uninitialized::<GlyphExtents>();
            let result = hb::hb_font_get_glyph_extents(self.as_raw(), glyph, &mut extents);
            if result == 1 {
                Some(extents)
            } else {
                None
            }
        }
    }

    pub fn get_glyph_contour_point(
        &self,
        glyph: Glyph,
        point_index: u32,
    ) -> Option<(Position, Position)> {
        unsafe {
            let mut pos = (0, 0);
            let result = hb::hb_font_get_glyph_contour_point(
                self.as_raw(),
                glyph,
                point_index,
                &mut pos.0,
                &mut pos.1,
            );
            if result == 1 {
                Some(pos)
            } else {
                None
            }
        }
    }

    pub fn get_glyph_name(&self, glyph: Glyph) -> Option<String> {
        let mut buffer = [0; 256];
        let result = unsafe {
            hb::hb_font_get_glyph_name(
                self.as_raw(),
                glyph,
                buffer.as_mut_ptr() as *mut _,
                buffer.len() as u32,
            )
        };
        if result == 1 {
            let cstr = unsafe { CStr::from_ptr(buffer.as_ptr()) };
            cstr.to_str().ok().map(|y| y.to_string())
        } else {
            None
        }
    }

    pub fn get_glyph_from_name(&self, name: &str) -> Option<Glyph> {
        unsafe {
            let mut glyph = 0;
            let result = hb::hb_font_get_glyph_from_name(
                self.as_raw(),
                name.as_ptr() as *mut _,
                name.len() as i32,
                &mut glyph,
            );
            if result == 1 {
                Some(glyph)
            } else {
                None
            }
        }
    }
}

impl<'a> HarfbuzzObject for Font<'a> {
    type Raw = hb::hb_font_t;

    unsafe fn reference(&self) {
        hb::hb_font_reference(self.as_raw());
    }

    unsafe fn dereference(&self) {
        hb::hb_font_destroy(self.as_raw());
    }
}
<|endoftext|>


<commit_before>use std::num::{NumCast};
use std::ops::{Add, Sub, Mul, Div, Neg};
use primitive::Primitive;
use ::{Anchor};

/// 2D geometric vector.
#[derive(Copy, Debug, PartialEq, PartialOrd, Clone, Default, RustcDecodable, RustcEncodable)]
pub struct V2<T>(pub T, pub T);

impl<T: Eq> Eq for V2<T> { }

impl<T: Add<U, Output=V>, U, V> Add<V2<U>> for V2<T> {
    type Output = V2<V>;
    fn add(self, rhs: V2<U>) -> V2<V> { V2(self.0 + rhs.0, self.1 + rhs.1) }
}

impl<T: Sub<U, Output=V>, U, V> Sub<V2<U>> for V2<T> {
    type Output = V2<V>;
    fn sub(self, rhs: V2<U>) -> V2<V> { V2(self.0 - rhs.0, self.1 - rhs.1) }
}

impl<T: Neg<Output=U>, U> Neg<> for V2<T> {
    type Output = V2<U>;
    fn neg(self) -> V2<U> { V2(-self.0, -self.1) }
}

impl<T: Mul<U, Output=V>, U: Copy, V> Mul<U> for V2<T> {
    type Output = V2<V>;
    fn mul(self, rhs: U) -> V2<V> { V2(self.0 * rhs, self.1 * rhs) }
}

impl<T: Div<U, Output=V>, U: Copy, V> Div<U> for V2<T> {
    type Output = V2<V>;
    fn div(self, rhs: U) -> V2<V> { V2(self.0 / rhs, self.1 / rhs) }
}

impl<T> V2<T> {
    pub fn to_array(self) -> [T; 2] { [self.0, self.1] }
}

impl<T> V2<T> {
    pub fn map<U, F: Fn(T) -> U>(self, f: F) -> V2<U> {
        V2(f(self.0), f(self.1))
    }
}

impl<T: Primitive> V2<T> {
    /// Componentwise multiplication.
    pub fn mul(self, rhs: V2<T>) -> V2<T> { V2(self.0 * rhs.0, self.1 * rhs.1) }

    /// Componentwise division.
    pub fn div(self, rhs: V2<T>) -> V2<T> { V2(self.0 / rhs.0, self.1 / rhs.1) }

    /// Dot product.
    pub fn dot(self, rhs: V2<T>) -> T { self.0 * rhs.0 + self.1 * rhs.1 }
}

/// 3D geometric vector
#[derive(Copy, Debug, PartialEq, PartialOrd, Clone, Default, RustcDecodable, RustcEncodable)]
pub struct V3<T>(pub T, pub T, pub T);

impl<T: Eq> Eq for V3<T> { }

impl<T: Add<U, Output=V>, U, V> Add<V3<U>> for V3<T> {
    type Output = V3<V>;
    fn add(self, rhs: V3<U>) -> V3<V> { V3(self.0 + rhs.0, self.1 + rhs.1, self.2 + rhs.2) }
}

impl<T: Sub<U, Output=V>, U, V> Sub<V3<U>> for V3<T> {
    type Output = V3<V>;
    fn sub(self, rhs: V3<U>) -> V3<V> { V3(self.0 - rhs.0, self.1 - rhs.1, self.2 - rhs.2) }
}

impl<T: Neg<Output=U>, U> Neg<> for V3<T> {
    type Output = V3<U>;
    fn neg(self) -> V3<U> { V3(-self.0, -self.1, -self.2) }
}

impl<T: Mul<U, Output=V>, U: Copy, V> Mul<U> for V3<T> {
    type Output = V3<V>;
    fn mul(self, rhs: U) -> V3<V> { V3(self.0 * rhs, self.1 * rhs, self.2 * rhs) }
}

impl<T: Div<U, Output=V>, U: Copy, V> Div<U> for V3<T> {
    type Output = V3<V>;
    fn div(self, rhs: U) -> V3<V> { V3(self.0 / rhs, self.1 / rhs, self.2 / rhs) }
}

impl<T> V3<T> {
    pub fn to_array(self) -> [T; 3] { [self.0, self.1, self.2] }
}

impl<T> V3<T> {
    pub fn map<U, F: Fn(T) -> U>(self, f: F) -> V3<U> {
        V3(f(self.0), f(self.1), f(self.2))
    }
}

impl<T: Primitive> V3<T> {
    /// Componentwise multiplication.
    pub fn mul(self, rhs: V3<T>) -> V3<T> { V3(self.0 * rhs.0, self.1 * rhs.1, self.2 * rhs.2) }

    /// Componentwise division.
    pub fn div(self, rhs: V3<T>) -> V3<T> { V3(self.0 / rhs.0, self.1 / rhs.1, self.2 / rhs.2) }

    /// Dot product.
    pub fn dot(self, rhs: V3<T>) -> T { self.0 * rhs.0 + self.1 * rhs.1 + self.2 * rhs.2 }
}

/// A rectangle type consisting of position and size vectors.
#[derive(Copy, Debug, PartialEq, PartialOrd, Clone, Default, RustcDecodable, RustcEncodable)]
pub struct Rect<T>(pub V2<T>, pub V2<T>);

impl<T: Eq> Eq for Rect<T> { }

impl<T: Primitive> Rect<T> {
    pub fn area(&self) -> T { (self.1).0 * (self.1).1 }

    pub fn mn(&self) -> V2<T> { self.0 }
    pub fn mx(&self) -> V2<T> { self.0 + self.1 }
    pub fn dim(&self) -> V2<T> { self.1 }

    pub fn point(&self, anchor: Anchor) -> V2<T> {
        match anchor {
            Anchor::TopLeft => self.mn(),
            Anchor::TopRight => V2((self.0).0 + (self.1).0, (self.0).1),
            Anchor::BottomLeft => V2((self.0).0, (self.0).1 + (self.1).1),
            Anchor::BottomRight => self.mx(),
            Anchor::Top => V2((self.0).0 + (self.1).0 / NumCast::from(2).unwrap(), (self.0).1),
            Anchor::Left => V2((self.0).0, (self.0).1 + (self.1).1 / NumCast::from(2).unwrap()),
            Anchor::Right => V2((self.0).0 + (self.1).0, (self.0).1 + (self.1).1 / NumCast::from(2).unwrap()),
            Anchor::Bottom => V2((self.0).0 + (self.1).0 / NumCast::from(2).unwrap(), (self.0).1 + (self.1).1),
            Anchor::Center => V2((self.0).0 + (self.1).0 / NumCast::from(2).unwrap(), (self.0).1 + (self.1).1 / NumCast::from(2).unwrap())
        }
    }

    /// Grow the rectangle to enclose point p.
    pub fn grow(&mut self, p: V2<T>) {
        let (mn, mx) = (self.mn(), self.mx());

        if p.0 < mn.0 {
            (self.1).0 = (self.1).0 + mn.0 - p.0;
            (self.0).0 = p.0;
        }

        if p.1 < mn.1 {
            (self.1).1 = (self.1).1 + mn.1 - p.1;
            (self.0).1 = p.1;
        }

        if p.0 > mx.0 { (self.1).0 = p.0 - mn.0; }

        if p.1 > mx.1 { (self.1).1 = p.1 - mn.1; }
    }

    pub fn intersects(&self, rhs: &Rect<T>) -> bool {
        let (mn, mx) = (self.mn(), self.mx());
        let (rmn, rmx) = (rhs.mn(), rhs.mx());

        !(mx.0 <= rmn.0 || mn.0 >= rmx.0 ||
          mx.1 <= rmn.1 || mn.1 >= rmx.1)
    }

    pub fn contains(&self, p: &V2<T>) -> bool {
        let (mn, mx) = (self.mn(), self.mx());
        p.0 >= mn.0 && p.1 >= mn.1 && p.0 < mx.0 && p.1 < mx.1
    }

    /// Return an iterator for all the points in the rectangle.
    pub fn iter(&self) -> RectIter<T> {
        RectIter {
            x: (self.0).0,
            y: (self.0).1,
            x0: (self.0).0,
            x1: (self.0).0 + (self.1).0,
            y1: (self.0).1 + (self.1).1,
        }
    }
}

impl<T: Add<U, Output=T> + Clone, U> Add<V2<U>> for Rect<T> {
    type Output = Rect<T>;
    fn add(self, rhs: V2<U>) -> Rect<T> { Rect(self.0 + rhs, self.1.clone()) }
}

/// Iterator for the integer points within a rectangle.
pub struct RectIter<T> {
    x: T,
    y: T,
    x0: T,
    x1: T,
    y1: T,
}

impl<T: Primitive> Iterator for RectIter<T> {
    type Item = V2<T>;
    fn next(&mut self) -> Option<V2<T>> {
        if self.y >= self.y1 { return None; }
        let ret = Some(V2(self.x, self.y));
        self.x = self.x + NumCast::from(1).unwrap();
        if self.x >= self.x1 {
            self.x = self.x0;
            self.y = self.y + NumCast::from(1).unwrap();
        }
        ret
    }
}
<commit_msg>Geometric primitives derive Hash<commit_after>use std::num::{NumCast};
use std::ops::{Add, Sub, Mul, Div, Neg};
use primitive::Primitive;
use ::{Anchor};

/// 2D geometric vector.
#[derive(Copy, Debug, PartialEq, PartialOrd, Clone, Default, Hash, RustcDecodable, RustcEncodable)]
pub struct V2<T>(pub T, pub T);

impl<T: Eq> Eq for V2<T> { }

impl<T: Add<U, Output=V>, U, V> Add<V2<U>> for V2<T> {
    type Output = V2<V>;
    fn add(self, rhs: V2<U>) -> V2<V> { V2(self.0 + rhs.0, self.1 + rhs.1) }
}

impl<T: Sub<U, Output=V>, U, V> Sub<V2<U>> for V2<T> {
    type Output = V2<V>;
    fn sub(self, rhs: V2<U>) -> V2<V> { V2(self.0 - rhs.0, self.1 - rhs.1) }
}

impl<T: Neg<Output=U>, U> Neg<> for V2<T> {
    type Output = V2<U>;
    fn neg(self) -> V2<U> { V2(-self.0, -self.1) }
}

impl<T: Mul<U, Output=V>, U: Copy, V> Mul<U> for V2<T> {
    type Output = V2<V>;
    fn mul(self, rhs: U) -> V2<V> { V2(self.0 * rhs, self.1 * rhs) }
}

impl<T: Div<U, Output=V>, U: Copy, V> Div<U> for V2<T> {
    type Output = V2<V>;
    fn div(self, rhs: U) -> V2<V> { V2(self.0 / rhs, self.1 / rhs) }
}

impl<T> V2<T> {
    pub fn to_array(self) -> [T; 2] { [self.0, self.1] }
}

impl<T> V2<T> {
    pub fn map<U, F: Fn(T) -> U>(self, f: F) -> V2<U> {
        V2(f(self.0), f(self.1))
    }
}

impl<T: Primitive> V2<T> {
    /// Componentwise multiplication.
    pub fn mul(self, rhs: V2<T>) -> V2<T> { V2(self.0 * rhs.0, self.1 * rhs.1) }

    /// Componentwise division.
    pub fn div(self, rhs: V2<T>) -> V2<T> { V2(self.0 / rhs.0, self.1 / rhs.1) }

    /// Dot product.
    pub fn dot(self, rhs: V2<T>) -> T { self.0 * rhs.0 + self.1 * rhs.1 }
}

/// 3D geometric vector
#[derive(Copy, Debug, PartialEq, PartialOrd, Clone, Default, Hash, RustcDecodable, RustcEncodable)]
pub struct V3<T>(pub T, pub T, pub T);

impl<T: Eq> Eq for V3<T> { }

impl<T: Add<U, Output=V>, U, V> Add<V3<U>> for V3<T> {
    type Output = V3<V>;
    fn add(self, rhs: V3<U>) -> V3<V> { V3(self.0 + rhs.0, self.1 + rhs.1, self.2 + rhs.2) }
}

impl<T: Sub<U, Output=V>, U, V> Sub<V3<U>> for V3<T> {
    type Output = V3<V>;
    fn sub(self, rhs: V3<U>) -> V3<V> { V3(self.0 - rhs.0, self.1 - rhs.1, self.2 - rhs.2) }
}

impl<T: Neg<Output=U>, U> Neg<> for V3<T> {
    type Output = V3<U>;
    fn neg(self) -> V3<U> { V3(-self.0, -self.1, -self.2) }
}

impl<T: Mul<U, Output=V>, U: Copy, V> Mul<U> for V3<T> {
    type Output = V3<V>;
    fn mul(self, rhs: U) -> V3<V> { V3(self.0 * rhs, self.1 * rhs, self.2 * rhs) }
}

impl<T: Div<U, Output=V>, U: Copy, V> Div<U> for V3<T> {
    type Output = V3<V>;
    fn div(self, rhs: U) -> V3<V> { V3(self.0 / rhs, self.1 / rhs, self.2 / rhs) }
}

impl<T> V3<T> {
    pub fn to_array(self) -> [T; 3] { [self.0, self.1, self.2] }
}

impl<T> V3<T> {
    pub fn map<U, F: Fn(T) -> U>(self, f: F) -> V3<U> {
        V3(f(self.0), f(self.1), f(self.2))
    }
}

impl<T: Primitive> V3<T> {
    /// Componentwise multiplication.
    pub fn mul(self, rhs: V3<T>) -> V3<T> { V3(self.0 * rhs.0, self.1 * rhs.1, self.2 * rhs.2) }

    /// Componentwise division.
    pub fn div(self, rhs: V3<T>) -> V3<T> { V3(self.0 / rhs.0, self.1 / rhs.1, self.2 / rhs.2) }

    /// Dot product.
    pub fn dot(self, rhs: V3<T>) -> T { self.0 * rhs.0 + self.1 * rhs.1 + self.2 * rhs.2 }
}

/// A rectangle type consisting of position and size vectors.
#[derive(Copy, Debug, PartialEq, PartialOrd, Clone, Default, Hash, RustcDecodable, RustcEncodable)]
pub struct Rect<T>(pub V2<T>, pub V2<T>);

impl<T: Eq> Eq for Rect<T> { }

impl<T: Primitive> Rect<T> {
    pub fn area(&self) -> T { (self.1).0 * (self.1).1 }

    pub fn mn(&self) -> V2<T> { self.0 }
    pub fn mx(&self) -> V2<T> { self.0 + self.1 }
    pub fn dim(&self) -> V2<T> { self.1 }

    pub fn point(&self, anchor: Anchor) -> V2<T> {
        match anchor {
            Anchor::TopLeft => self.mn(),
            Anchor::TopRight => V2((self.0).0 + (self.1).0, (self.0).1),
            Anchor::BottomLeft => V2((self.0).0, (self.0).1 + (self.1).1),
            Anchor::BottomRight => self.mx(),
            Anchor::Top => V2((self.0).0 + (self.1).0 / NumCast::from(2).unwrap(), (self.0).1),
            Anchor::Left => V2((self.0).0, (self.0).1 + (self.1).1 / NumCast::from(2).unwrap()),
            Anchor::Right => V2((self.0).0 + (self.1).0, (self.0).1 + (self.1).1 / NumCast::from(2).unwrap()),
            Anchor::Bottom => V2((self.0).0 + (self.1).0 / NumCast::from(2).unwrap(), (self.0).1 + (self.1).1),
            Anchor::Center => V2((self.0).0 + (self.1).0 / NumCast::from(2).unwrap(), (self.0).1 + (self.1).1 / NumCast::from(2).unwrap())
        }
    }

    /// Grow the rectangle to enclose point p.
    pub fn grow(&mut self, p: V2<T>) {
        let (mn, mx) = (self.mn(), self.mx());

        if p.0 < mn.0 {
            (self.1).0 = (self.1).0 + mn.0 - p.0;
            (self.0).0 = p.0;
        }

        if p.1 < mn.1 {
            (self.1).1 = (self.1).1 + mn.1 - p.1;
            (self.0).1 = p.1;
        }

        if p.0 > mx.0 { (self.1).0 = p.0 - mn.0; }

        if p.1 > mx.1 { (self.1).1 = p.1 - mn.1; }
    }

    pub fn intersects(&self, rhs: &Rect<T>) -> bool {
        let (mn, mx) = (self.mn(), self.mx());
        let (rmn, rmx) = (rhs.mn(), rhs.mx());

        !(mx.0 <= rmn.0 || mn.0 >= rmx.0 ||
          mx.1 <= rmn.1 || mn.1 >= rmx.1)
    }

    pub fn contains(&self, p: &V2<T>) -> bool {
        let (mn, mx) = (self.mn(), self.mx());
        p.0 >= mn.0 && p.1 >= mn.1 && p.0 < mx.0 && p.1 < mx.1
    }

    /// Return an iterator for all the points in the rectangle.
    pub fn iter(&self) -> RectIter<T> {
        RectIter {
            x: (self.0).0,
            y: (self.0).1,
            x0: (self.0).0,
            x1: (self.0).0 + (self.1).0,
            y1: (self.0).1 + (self.1).1,
        }
    }
}

impl<T: Add<U, Output=T> + Clone, U> Add<V2<U>> for Rect<T> {
    type Output = Rect<T>;
    fn add(self, rhs: V2<U>) -> Rect<T> { Rect(self.0 + rhs, self.1.clone()) }
}

/// Iterator for the integer points within a rectangle.
pub struct RectIter<T> {
    x: T,
    y: T,
    x0: T,
    x1: T,
    y1: T,
}

impl<T: Primitive> Iterator for RectIter<T> {
    type Item = V2<T>;
    fn next(&mut self) -> Option<V2<T>> {
        if self.y >= self.y1 { return None; }
        let ret = Some(V2(self.x, self.y));
        self.x = self.x + NumCast::from(1).unwrap();
        if self.x >= self.x1 {
            self.x = self.x0;
            self.y = self.y + NumCast::from(1).unwrap();
        }
        ret
    }
}
<|endoftext|>


<commit_before>use std::iter::{Iterator, repeat};

pub fn slice_set<T: Clone>(dest: &mut [T], src: &[T]) {
    if dest.len() != src.len() {
        panic!("destination and source slices should be the same length! ({} != {})", dest.len(),
               src.len());
    }

    for (i, v) in src.iter().enumerate() {
        dest[i] = v.clone();
    }
}

// pub fn iter_set<'a, T: Clone, A: Iterator<Item=&'a T>, B: Iterator<Item=&'a mut T>>(dest: B, src: A)
// {
//  // TODO: Fail (how?) when they are not the same length?

//  for (s, d) in src.zip(dest) {
//      *d = s.clone();
//  }
// }

pub fn iter_equals<A: Eq, T: Iterator<Item = A>, U: Iterator<Item = A>>(mut a: T,
                                                                        mut b: U)
                                                                        -> bool {
    loop {
        match (a.next(), b.next()) {
            (None, None) => return true,
            (None, _) | (_, None) => return false,
            (Some(x), Some(y)) => if x != y { return false },
        }
    }
}

pub fn string_with_repeat(c: char, n: usize) -> String {
    let v: Vec<_> = repeat(c as u8).take(n).collect();
    String::from_utf8(v).unwrap()
}

pub fn is_between<N: PartialOrd>(num: N, a: N, b: N) -> bool {
    let (smaller, larger) = if a < b { (a, b) } else { (b, a) };
    (smaller <= num) && (num <= larger)
}

pub enum OptionalIter<L, R> {
    TrueIter(L),
    FalseIter(R)
}

impl<L, R, A> Iterator for OptionalIter<L, R> where
    L: Iterator<Item=A>,
    R: Iterator<Item=A>
{
    type Item = A;
    fn next(&mut self) -> Option<Self::Item> {
        match *self {
            OptionalIter::TrueIter(ref mut it) => it.next(),
            OptionalIter::FalseIter(ref mut it) => it.next(),
        }
    }
}

pub trait IteratorOptionalExt : Iterator {
    fn optional<L, R, F, G>(self, conditional: bool, f_left: F, f_right: G) -> OptionalIter<L, R>
            where Self: Sized,
                  F: FnOnce(Self) -> L,
                  G: FnOnce(Self) -> R
    {
        if conditional {
            OptionalIter::TrueIter(f_left(self))
        } else {
            OptionalIter::FalseIter(f_right(self))
        }
    }
}

impl<T: ?Sized> IteratorOptionalExt for T where T: Iterator { }
<commit_msg>Clean up old code<commit_after>use std::iter::{Iterator, repeat};

pub fn slice_set<T: Clone>(dest: &mut [T], src: &[T]) {
    if dest.len() != src.len() {
        panic!("destination and source slices should be the same length! ({} != {})", dest.len(),
               src.len());
    }

    for (i, v) in src.iter().enumerate() {
        dest[i] = v.clone();
    }
}

pub fn iter_equals<A: Eq, T: Iterator<Item = A>, U: Iterator<Item = A>>(mut a: T,
                                                                        mut b: U)
                                                                        -> bool {
    loop {
        match (a.next(), b.next()) {
            (None, None) => return true,
            (None, _) | (_, None) => return false,
            (Some(x), Some(y)) => if x != y { return false },
        }
    }
}

pub fn string_with_repeat(c: char, n: usize) -> String {
    let v: Vec<_> = repeat(c as u8).take(n).collect();
    String::from_utf8(v).unwrap()
}

pub fn is_between<N: PartialOrd>(num: N, a: N, b: N) -> bool {
    let (smaller, larger) = if a < b { (a, b) } else { (b, a) };
    (smaller <= num) && (num <= larger)
}

pub enum OptionalIter<L, R> {
    TrueIter(L),
    FalseIter(R)
}

impl<L, R, A> Iterator for OptionalIter<L, R> where
    L: Iterator<Item=A>,
    R: Iterator<Item=A>
{
    type Item = A;
    fn next(&mut self) -> Option<Self::Item> {
        match *self {
            OptionalIter::TrueIter(ref mut it) => it.next(),
            OptionalIter::FalseIter(ref mut it) => it.next(),
        }
    }
}

pub trait IteratorOptionalExt : Iterator {
    fn optional<L, R, F, G>(self, conditional: bool, f_left: F, f_right: G) -> OptionalIter<L, R>
            where Self: Sized,
                  F: FnOnce(Self) -> L,
                  G: FnOnce(Self) -> R
    {
        if conditional {
            OptionalIter::TrueIter(f_left(self))
        } else {
            OptionalIter::FalseIter(f_right(self))
        }
    }
}

impl<T: ?Sized> IteratorOptionalExt for T where T: Iterator { }
<|endoftext|>


<commit_before>use std::fs::File;
use std::io::{Read, Write};
use std::path::Path;
use std::fs;

use toml::{Parser, Value};
use walkdir::WalkDir;

use errors::*;

pub fn cp_r(src: &Path, dst: &Path) -> Result<()> {
    for e in WalkDir::new(src) {
        let e = e.unwrap();
        let src_file = e.path();
        let relative_path = src_file.strip_prefix(src).unwrap();
        let dst_file = dst.join(relative_path);
        let metadata = e.metadata()
            .chain_err(|| {
                format!("Could not retrieve metadata of `{}`",
                e.path().display())
            })?;

        if metadata.is_dir() {
            // ensure the destination directory exists
            fs::create_dir_all(&dst_file)
                .chain_err(|| {
                    format!("Could not create directory `{}`",
                            dst_file.display())
                })?;
        } else {
            // else copy the file
            fs::copy(&src_file, &dst_file)
                .chain_err(|| {
                    format!("copying files from `{}` to `{}` failed",
                            src_file.display(),
                            dst_file.display())
                })?;
        };
    }

    Ok(())
}

pub fn mkdir(path: &Path) -> Result<()> {
    fs::create_dir(path)
        .chain_err(|| format!("couldn't create directory {}", path.display()))
}

/// Parses `path` as TOML
pub fn parse(path: &Path) -> Result<Value> {
    Ok(Value::Table(Parser::new(&read(path)?).parse()
        .ok_or_else(|| format!("{} is not valid TOML", path.display()))?))
}

pub fn read(path: &Path) -> Result<String> {
    let mut s = String::new();

    let p = path.display();
    File::open(path).chain_err(|| format!("couldn't open {}", p))?
        .read_to_string(&mut s)
        .chain_err(|| format!("couldn't read {}", p))?;

    Ok(s)
}

/// Search for `file` in `path` and its parent directories
pub fn search<'p>(mut path: &'p Path, file: &str) -> Option<&'p Path> {
    loop {
        if path.join(file).exists() {
            return Some(path);
        }

        if let Some(p) = path.parent() {
            path = p;
        } else {
            return None;
        }
    }
}

pub fn write(path: &Path, contents: &str) -> Result<()> {
    let p = path.display();
    File::create(path)
        .chain_err(|| format!("couldn't open {}", p))?
        .write_all(contents.as_bytes())
        .chain_err(|| format!("couldn't write to {}", p))
}
<commit_msg>Replaced two unwraps with clear error messages<commit_after>use std::fs::File;
use std::io::{Read, Write};
use std::path::Path;
use std::fs;

use toml::{Parser, Value};
use walkdir::WalkDir;

use errors::*;

pub fn cp_r(src: &Path, dst: &Path) -> Result<()> {
    for e in WalkDir::new(src) {
        // This is only an error when there's some sort of intermittent IO error during iteration.
        // see https://doc.rust-lang.org/std/fs/struct.ReadDir.html
        let e = e.chain_err(||{
            format!("intermittent IO error while iterating directory `{}`", src.display())
        })?;

        let src_file = e.path();
        let relative_path = src_file
            .strip_prefix(src)
            .chain_err(|| {
                format!("Could not retrieve relative path of child directory or file `{}` with regards to parent directory `{}`",
                src_file.display(),
                src.display())
            })?;

        let dst_file = dst.join(relative_path);
        let metadata = e.metadata()
            .chain_err(|| {
                format!("Could not retrieve metadata of `{}`",
                e.path().display())
            })?;

        if metadata.is_dir() {
            // ensure the destination directory exists
            fs::create_dir_all(&dst_file)
                .chain_err(|| {
                    format!("Could not create directory `{}`",
                            dst_file.display())
                })?;
        } else {
            // else copy the file
            fs::copy(&src_file, &dst_file)
                .chain_err(|| {
                    format!("copying files from `{}` to `{}` failed",
                            src_file.display(),
                            dst_file.display())
                })?;
        };
    }

    Ok(())
}

pub fn mkdir(path: &Path) -> Result<()> {
    fs::create_dir(path)
        .chain_err(|| format!("couldn't create directory {}", path.display()))
}

/// Parses `path` as TOML
pub fn parse(path: &Path) -> Result<Value> {
    Ok(Value::Table(Parser::new(&read(path)?).parse()
        .ok_or_else(|| format!("{} is not valid TOML", path.display()))?))
}

pub fn read(path: &Path) -> Result<String> {
    let mut s = String::new();

    let p = path.display();
    File::open(path).chain_err(|| format!("couldn't open {}", p))?
        .read_to_string(&mut s)
        .chain_err(|| format!("couldn't read {}", p))?;

    Ok(s)
}

/// Search for `file` in `path` and its parent directories
pub fn search<'p>(mut path: &'p Path, file: &str) -> Option<&'p Path> {
    loop {
        if path.join(file).exists() {
            return Some(path);
        }

        if let Some(p) = path.parent() {
            path = p;
        } else {
            return None;
        }
    }
}

pub fn write(path: &Path, contents: &str) -> Result<()> {
    let p = path.display();
    File::create(path)
        .chain_err(|| format!("couldn't open {}", p))?
        .write_all(contents.as_bytes())
        .chain_err(|| format!("couldn't write to {}", p))
}
<|endoftext|>