<commit_before>use std::io::{self, Write};

const HEADER_LEN: usize = 110;

pub struct Builder {
    name: String,
    ino: u32,
    mode: u32,
    uid: u32,
    gid: u32,
    nlink: u32,
    mtime: u32,
    dev_major: u32,
    dev_minor: u32,
    rdev_major: u32,
    rdev_minor: u32,
}

pub struct Writer<W: Write> {
    inner: W,
    written: u32,
    file_size: u32,
    header_size: usize,
    header: Vec<u8>,
}

fn pad(len: usize) -> Option<Vec<u8>> {
    // pad out to a multiple of 4 bytes
    let overhang = len % 4;
    if overhang != 0 {
        let repeat = 4 - overhang;
        Some(vec![0u8; repeat])
    } else {
        None
    }
}

impl Builder {
    pub fn new(name: &str) -> Builder {
        Builder {
            name: name.to_string(),
            ino: 0,
            mode: 0,
            uid: 0,
            gid: 0,
            nlink: 1,
            mtime: 0,
            dev_major: 0,
            dev_minor: 0,
            rdev_major: 0,
            rdev_minor: 0,
        }
    }

    pub fn ino(mut self, ino: u32) -> Builder {
        self.ino = ino;
        self
    }

    pub fn mode(mut self, mode: u32) -> Builder {
        self.mode = mode;
        self
    }

    pub fn uid(mut self, uid: u32) -> Builder {
        self.uid = uid;
        self
    }

    pub fn gid(mut self, gid: u32) -> Builder {
        self.gid = gid;
        self
    }

    pub fn nlink(mut self, nlink: u32) -> Builder {
        self.nlink = nlink;
        self
    }

    pub fn mtime(mut self, mtime: u32) -> Builder {
        self.mtime = mtime;
        self
    }

    pub fn dev_major(mut self, dev_major: u32) -> Builder {
        self.dev_major = dev_major;
        self
    }

    pub fn dev_minor(mut self, dev_minor: u32) -> Builder {
        self.dev_minor = dev_minor;
        self
    }

    pub fn rdev_major(mut self, rdev_major: u32) -> Builder {
        self.rdev_major = rdev_major;
        self
    }

    pub fn rdev_minor(mut self, rdev_minor: u32) -> Builder {
        self.rdev_minor = rdev_minor;
        self
    }

    pub fn write<W: Write>(self, w: W, file_size: u32) -> Writer<W> {
        let header = self.into_header(file_size);

        Writer {
            inner: w,
            written: 0,
            file_size: file_size,
            header_size: header.len(),
            header: header,
        }
    }

    fn into_header(self, file_size: u32) -> Vec<u8> {
        let mut header = Vec::with_capacity(HEADER_LEN);

        // char    c_magic[6];
        header.extend("070701".to_string().as_bytes());
        // char    c_ino[8];
        header.extend(format!("{:08x}", self.ino).as_bytes());
        // char    c_mode[8];
        header.extend(format!("{:08x}", self.mode).as_bytes());
        // char    c_uid[8];
        header.extend(format!("{:08x}", self.uid).as_bytes());
        // char    c_gid[8];
        header.extend(format!("{:08x}", self.gid).as_bytes());
        // char    c_nlink[8];
        header.extend(format!("{:08x}", self.nlink).as_bytes());
        // char    c_mtime[8];
        header.extend(format!("{:08x}", self.mtime).as_bytes());
        // char    c_filesize[8];
        header.extend(format!("{:08x}", file_size).as_bytes());
        // char    c_devmajor[8];
        header.extend(format!("{:08x}", self.dev_major).as_bytes());
        // char    c_devminor[8];
        header.extend(format!("{:08x}", self.dev_minor).as_bytes());
        // char    c_rdevmajor[8];
        header.extend(format!("{:08x}", self.rdev_major).as_bytes());
        // char    c_rdevminor[8];
        header.extend(format!("{:08x}", self.rdev_minor).as_bytes());
        // char    c_namesize[8];
        let name_len = self.name.len() + 1;
        header.extend(format!("{:08x}", name_len).as_bytes());
        // char    c_check[8];
        header.extend(format!("{:08x}", 0).as_bytes());

        // append the name to the end of the header
        header.extend(self.name.as_bytes());
        header.push(0u8);

        // pad out to a multiple of 4 bytes
        if let Some(pad) = pad(HEADER_LEN + name_len) {
            header.extend(pad);
        }

        header
    }
}

impl<W: Write> Writer<W> {
    pub fn finish(mut self) -> io::Result<W> {
        try!(self.do_finish());
        Ok(self.inner)
    }

    fn try_write_header(&mut self) -> io::Result<()> {
        if self.header.len() != 0 {
            try!(self.inner.write_all(&self.header));
            self.header.truncate(0);
        }
        Ok(())
    }

    fn do_finish(&mut self) -> io::Result<()> {
        try!(self.try_write_header());

        if self.written == self.file_size {
            if let Some(pad) = pad(self.header_size + self.file_size as usize) {
                try!(self.inner.write(&pad));
                try!(self.inner.flush());
            }
        }

        Ok(())
    }
}

impl<W: Write> Write for Writer<W> {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        if self.written + buf.len() as u32 <= self.file_size {
            try!(self.try_write_header());

            let n = try!(self.inner.write(buf));
            self.written += n as u32;
            Ok(n)
        } else {
            Err(io::Error::new(io::ErrorKind::UnexpectedEof,
                               "trying to write more than the specified file size"))
        }
    }

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

pub fn trailer<W: Write>(w: W) -> io::Result<()> {
    let b = Builder::new("TRAILER!!!").nlink(0);
    let writer = b.write(w, 0);
    let _ = try!(writer.finish());
    Ok(())
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::fs::File;
    use std::io::Write;

    #[test]
    fn test_single_file() {
        let data = "Hello, World".to_string();

        let fp = File::create("/tmp/test_single.cpio").unwrap();

        let b = Builder::new("./hello_world");
        let mut writer = b.write(fp, data.len() as u32);
        writer.write_all(data.as_bytes()).unwrap();
        writer.flush().unwrap();
        let fp = writer.finish().unwrap();
        trailer(fp).unwrap();
    }

    #[test]
    fn test_multi_file() {
        let data = "Hello, World".to_string();

        let fp = File::create("/tmp/test_multi.cpio").unwrap();

        let b = Builder::new("./hello_world")
            .ino(1)
            .uid(1000)
            .gid(1000)
            .mode(0o100644);
        let mut writer = b.write(fp, data.len() as u32);
        writer.write_all(data.as_bytes()).unwrap();
        writer.flush().unwrap();
        let fp = writer.finish().unwrap();

        let b = Builder::new("./hello_world2")
            .ino(2)
            .uid(1000)
            .gid(1000)
            .mode(0o100644);
        let mut writer = b.write(fp, data.len() as u32);
        writer.write_all(data.as_bytes()).unwrap();
        writer.flush().unwrap();
        let fp = writer.finish().unwrap();

        trailer(fp).unwrap();
    }
}
<commit_msg>read and write using Cursors in the tests<commit_after>use std::io::{self, Write};

const HEADER_LEN: usize = 110;

pub struct Builder {
    name: String,
    ino: u32,
    mode: u32,
    uid: u32,
    gid: u32,
    nlink: u32,
    mtime: u32,
    dev_major: u32,
    dev_minor: u32,
    rdev_major: u32,
    rdev_minor: u32,
}

pub struct Writer<W: Write> {
    inner: W,
    written: u32,
    file_size: u32,
    header_size: usize,
    header: Vec<u8>,
}

fn pad(len: usize) -> Option<Vec<u8>> {
    // pad out to a multiple of 4 bytes
    let overhang = len % 4;
    if overhang != 0 {
        let repeat = 4 - overhang;
        Some(vec![0u8; repeat])
    } else {
        None
    }
}

impl Builder {
    pub fn new(name: &str) -> Builder {
        Builder {
            name: name.to_string(),
            ino: 0,
            mode: 0,
            uid: 0,
            gid: 0,
            nlink: 1,
            mtime: 0,
            dev_major: 0,
            dev_minor: 0,
            rdev_major: 0,
            rdev_minor: 0,
        }
    }

    pub fn ino(mut self, ino: u32) -> Builder {
        self.ino = ino;
        self
    }

    pub fn mode(mut self, mode: u32) -> Builder {
        self.mode = mode;
        self
    }

    pub fn uid(mut self, uid: u32) -> Builder {
        self.uid = uid;
        self
    }

    pub fn gid(mut self, gid: u32) -> Builder {
        self.gid = gid;
        self
    }

    pub fn nlink(mut self, nlink: u32) -> Builder {
        self.nlink = nlink;
        self
    }

    pub fn mtime(mut self, mtime: u32) -> Builder {
        self.mtime = mtime;
        self
    }

    pub fn dev_major(mut self, dev_major: u32) -> Builder {
        self.dev_major = dev_major;
        self
    }

    pub fn dev_minor(mut self, dev_minor: u32) -> Builder {
        self.dev_minor = dev_minor;
        self
    }

    pub fn rdev_major(mut self, rdev_major: u32) -> Builder {
        self.rdev_major = rdev_major;
        self
    }

    pub fn rdev_minor(mut self, rdev_minor: u32) -> Builder {
        self.rdev_minor = rdev_minor;
        self
    }

    pub fn write<W: Write>(self, w: W, file_size: u32) -> Writer<W> {
        let header = self.into_header(file_size);

        Writer {
            inner: w,
            written: 0,
            file_size: file_size,
            header_size: header.len(),
            header: header,
        }
    }

    fn into_header(self, file_size: u32) -> Vec<u8> {
        let mut header = Vec::with_capacity(HEADER_LEN);

        // char    c_magic[6];
        header.extend("070701".to_string().as_bytes());
        // char    c_ino[8];
        header.extend(format!("{:08x}", self.ino).as_bytes());
        // char    c_mode[8];
        header.extend(format!("{:08x}", self.mode).as_bytes());
        // char    c_uid[8];
        header.extend(format!("{:08x}", self.uid).as_bytes());
        // char    c_gid[8];
        header.extend(format!("{:08x}", self.gid).as_bytes());
        // char    c_nlink[8];
        header.extend(format!("{:08x}", self.nlink).as_bytes());
        // char    c_mtime[8];
        header.extend(format!("{:08x}", self.mtime).as_bytes());
        // char    c_filesize[8];
        header.extend(format!("{:08x}", file_size).as_bytes());
        // char    c_devmajor[8];
        header.extend(format!("{:08x}", self.dev_major).as_bytes());
        // char    c_devminor[8];
        header.extend(format!("{:08x}", self.dev_minor).as_bytes());
        // char    c_rdevmajor[8];
        header.extend(format!("{:08x}", self.rdev_major).as_bytes());
        // char    c_rdevminor[8];
        header.extend(format!("{:08x}", self.rdev_minor).as_bytes());
        // char    c_namesize[8];
        let name_len = self.name.len() + 1;
        header.extend(format!("{:08x}", name_len).as_bytes());
        // char    c_check[8];
        header.extend(format!("{:08x}", 0).as_bytes());

        // append the name to the end of the header
        header.extend(self.name.as_bytes());
        header.push(0u8);

        // pad out to a multiple of 4 bytes
        if let Some(pad) = pad(HEADER_LEN + name_len) {
            header.extend(pad);
        }

        header
    }
}

impl<W: Write> Writer<W> {
    pub fn finish(mut self) -> io::Result<W> {
        try!(self.do_finish());
        Ok(self.inner)
    }

    fn try_write_header(&mut self) -> io::Result<()> {
        if self.header.len() != 0 {
            try!(self.inner.write_all(&self.header));
            self.header.truncate(0);
        }
        Ok(())
    }

    fn do_finish(&mut self) -> io::Result<()> {
        try!(self.try_write_header());

        if self.written == self.file_size {
            if let Some(pad) = pad(self.header_size + self.file_size as usize) {
                try!(self.inner.write(&pad));
                try!(self.inner.flush());
            }
        }

        Ok(())
    }
}

impl<W: Write> Write for Writer<W> {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        if self.written + buf.len() as u32 <= self.file_size {
            try!(self.try_write_header());

            let n = try!(self.inner.write(buf));
            self.written += n as u32;
            Ok(n)
        } else {
            Err(io::Error::new(io::ErrorKind::UnexpectedEof,
                               "trying to write more than the specified file size"))
        }
    }

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

pub fn trailer<W: Write>(w: W) -> io::Result<()> {
    let b = Builder::new("TRAILER!!!").nlink(0);
    let writer = b.write(w, 0);
    let _ = try!(writer.finish());
    Ok(())
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::io::{copy, Cursor};

    #[test]
    fn test_single_file() {
        // Set up our input file
        let data = "Hello, World".to_string();
        let length = data.len() as u32;
        let mut input = Cursor::new(data);

        // Set up our output file
        let output = Cursor::new(vec![]);

        // Set up the descriptor of our input file
        let b = Builder::new("./hello_world");
        // and get a writer for that input file
        let mut writer = b.write(output, length);

        // Copy the input file into our CPIO archive
        copy(&mut input, &mut writer).unwrap();
        let output = writer.finish().unwrap();

        // Finish up by writing the trailer for the archive
        trailer(output).unwrap();
    }

    #[test]
    fn test_multi_file() {
        // Set up our input files
        let data1 = "Hello, World".to_string();
        let length1 = data1.len() as u32;
        let mut input1 = Cursor::new(data1);

        let data2 = "Hello, World 2".to_string();
        let length2 = data2.len() as u32;
        let mut input2 = Cursor::new(data2);

        // Set up our output file
        let output = Cursor::new(vec![]);

        // Set up the descriptor of our input file
        let b = Builder::new("./hello_world")
            .ino(1)
            .uid(1000)
            .gid(1000)
            .mode(0o100644);
        // and get a writer for that input file
        let mut writer = b.write(output, length1);

        // Copy the input file into our CPIO archive
        copy(&mut input1, &mut writer).unwrap();
        let output = writer.finish().unwrap();

        // Set up the descriptor of our second input file
        let b = Builder::new("./hello_world2")
            .ino(2)
            .uid(1000)
            .gid(1000)
            .mode(0o100644);
        // and get a writer for that input file
        let mut writer = b.write(output, length2);

        // Copy the second input file into our CPIO archive
        copy(&mut input2, &mut writer).unwrap();
        let output = writer.finish().unwrap();

        // Finish up by writing the trailer for the archive
        trailer(output).unwrap();
    }
}
<|endoftext|>


<commit_before>use std;
use std::default::Default;
use libc::c_void;

use ffi;
use ffi::{Direction, MeasureMode, Size};
use context::Context;
use measure::measure;

#[derive(Debug)]
pub struct Node {
    pub _node: *mut ffi::Node, // TODO Into/From trait
}

impl Default for Node {
    fn default() -> Node {
        Node::new()
    }
}

impl Node {
    pub fn new() -> Node {
        Node { _node: unsafe { ffi::YGNodeNew() } }
    }

    pub fn get_instance_count() -> i32 {
        unsafe { ffi::YGNodeGetInstanceCount() }
    }

    pub fn reset(&mut self) {
        unsafe { ffi::YGNodeReset(self._node) }
    }

    pub fn free(self) {
        unsafe { ffi::YGNodeFree(self._node) }
    }

    pub fn free_recursive(self) {
        unsafe { ffi::YGNodeFreeRecursive(self._node) }
    }

    pub fn set_direction(&mut self, value: ffi::Direction) {
        unsafe { ffi::YGNodeStyleSetDirection(self._node, value) }
    }

    pub fn get_direction(&self) -> ffi::Direction {
        unsafe { ffi::YGNodeStyleGetDirection(self._node) }
    }

    pub fn set_flex_direction(&mut self, value: ffi::FlexDirection) {
        unsafe { ffi::YGNodeStyleSetFlexDirection(self._node, value) }
    }

    pub fn get_flex_direction(&self) -> ffi::FlexDirection {
        unsafe { ffi::YGNodeStyleGetFlexDirection(self._node) }
    }

    pub fn set_width(&mut self, width: f32) {
        unsafe { ffi::YGNodeStyleSetWidth(self._node, width) }
    }

    pub fn get_width(&self) -> f32 {
        unsafe { ffi::YGNodeStyleGetWidth(self._node) }
    }

    pub fn set_height(&mut self, height: f32) {
        unsafe { ffi::YGNodeStyleSetHeight(self._node, height) }
    }

    pub fn get_height(&self) -> f32 {
        unsafe { ffi::YGNodeStyleGetHeight(self._node) }
    }

    pub fn calculate_layout(&mut self) {
        unsafe {
            ffi::YGNodeCalculateLayout(self._node, std::f32::NAN, std::f32::NAN, Direction::LTR)
        }
    }

    pub fn get_layout_width(&self) -> f32 {
        unsafe { ffi::YGNodeLayoutGetWidth(self._node) }
    }

    pub fn get_layout_height(&self) -> f32 {
        unsafe { ffi::YGNodeLayoutGetHeight(self._node) }
    }

    pub fn get_layout_left(&self) -> f32 {
        unsafe { ffi::YGNodeLayoutGetLeft(self._node) }
    }

    pub fn get_layout_top(&self) -> f32 {
        unsafe { ffi::YGNodeLayoutGetTop(self._node) }
    }

    pub fn get_layout_direction(&self) -> ffi::Direction {
        unsafe { ffi::YGNodeLayoutGetDirection(self._node) }
    }

    pub fn insert_child(&mut self, child: &Node, index: u32) {
        unsafe { ffi::YGNodeInsertChild(self._node, child._node, index) }
    }

    pub fn remove_child(&mut self, child: &Node) {
        unsafe { ffi::YGNodeRemoveChild(self._node, child._node) }
    }

    pub fn get_child(&self, index: u32) -> Node {
        // FIXME this is wrong
        // also prevents Drop impl for Node
        unsafe { Node { _node: ffi::YGNodeGetChild(self._node, index) } }
    }

    pub fn get_child_count(&self) -> u32 {
        unsafe { ffi::YGNodeGetChildCount(self._node) }
    }

    pub fn get_parent(&self) -> Node {
        // FIXME this is wrong
        // also prevents Drop impl for Node
        unsafe { Node { _node: ffi::YGNodeGetParent(self._node) } }
    }

    pub fn set_justify_content(&mut self, value: ffi::JustifyContent) {
        unsafe { ffi::YGNodeStyleSetJustifyContent(self._node, value) }
    }

    pub fn get_justify_content(&self) -> ffi::JustifyContent {
        unsafe { ffi::YGNodeStyleGetJustifyContent(self._node) }
    }

    pub fn get_align_items(&self) -> ffi::Align {
        unsafe { ffi::YGNodeStyleGetAlignItems(self._node) }
    }

    pub fn set_align_items(&mut self, value: ffi::Align) {
        unsafe { ffi::YGNodeStyleSetAlignItems(self._node, value) }
    }

    pub fn get_align_self(&self) -> ffi::Align {
        unsafe { ffi::YGNodeStyleGetAlignSelf(self._node) }
    }

    pub fn set_align_self(&mut self, value: ffi::Align) {
        unsafe { ffi::YGNodeStyleSetAlignSelf(self._node, value) }
    }

    pub fn get_align_content(&self) -> ffi::Align {
        unsafe { ffi::YGNodeStyleGetAlignContent(self._node) }
    }

    pub fn set_align_content(&mut self, value: ffi::Align) {
        unsafe { ffi::YGNodeStyleSetAlignContent(self._node, value) }
    }

    pub fn get_position_type(&self) -> ffi::PositionType {
        unsafe { ffi::YGNodeStyleGetPositionType(self._node) }
    }

    pub fn set_position_type(&mut self, value: ffi::PositionType) {
        unsafe { ffi::YGNodeStyleSetPositionType(self._node, value) }
    }

    pub fn get_flex_wrap(&self) -> ffi::FlexWrap {
        unsafe { ffi::YGNodeStyleGetFlexWrap(self._node) }
    }

    pub fn set_flex_wrap(&mut self, value: ffi::FlexWrap) {
        unsafe { ffi::YGNodeStyleSetFlexWrap(self._node, value) }
    }

    pub fn get_overflow(&self) -> ffi::Overflow {
        unsafe { ffi::YGNodeStyleGetOverflow(self._node) }
    }

    pub fn set_overflow(&mut self, value: ffi::Overflow) {
        unsafe { ffi::YGNodeStyleSetOverflow(self._node, value) }
    }

    pub fn set_flex(&mut self, value: f32) {
        unsafe { ffi::YGNodeStyleSetFlex(self._node, value) }
    }

    pub fn get_flex_grow(&self) -> f32 {
        unsafe { ffi::YGNodeStyleGetFlexGrow(self._node) }
    }

    pub fn set_flex_grow(&mut self, value: f32) {
        unsafe { ffi::YGNodeStyleSetFlexGrow(self._node, value) }
    }

    pub fn get_flex_shrink(&self) -> f32 {
        unsafe { ffi::YGNodeStyleGetFlexShrink(self._node) }
    }

    pub fn set_flex_shrink(&mut self, value: f32) {
        unsafe { ffi::YGNodeStyleSetFlexShrink(self._node, value) }
    }

    pub fn get_flex_basis(&self) -> f32 {
        unsafe { ffi::YGNodeStyleGetFlexBasis(self._node) }
    }

    pub fn set_flex_basis(&mut self, value: f32) {
        unsafe { ffi::YGNodeStyleSetFlexBasis(self._node, value) }
    }

    pub fn get_margin(&self, edge: ffi::Edge) -> f32 {
        unsafe { ffi::YGNodeStyleGetMargin(self._node, edge) }
    }

    pub fn set_margin(&mut self, edge: ffi::Edge, value: f32) {
        unsafe { ffi::YGNodeStyleSetMargin(self._node, edge, value) }
    }

    pub fn get_padding(&self, edge: ffi::Edge) -> f32 {
        unsafe { ffi::YGNodeStyleGetPadding(self._node, edge) }
    }

    pub fn set_padding(&mut self, edge: ffi::Edge, value: f32) {
        unsafe { ffi::YGNodeStyleSetPadding(self._node, edge, value) }
    }

    pub fn get_border(&self, edge: ffi::Edge) -> f32 {
        unsafe { ffi::YGNodeStyleGetBorder(self._node, edge) }
    }

    pub fn set_border(&mut self, edge: ffi::Edge, value: f32) {
        unsafe { ffi::YGNodeStyleSetBorder(self._node, edge, value) }
    }

    pub fn get_position(&self, edge: ffi::Edge) -> f32 {
        unsafe { ffi::YGNodeStyleGetPosition(self._node, edge) }
    }

    pub fn set_position(&mut self, edge: ffi::Edge, value: f32) {
        unsafe { ffi::YGNodeStyleSetPosition(self._node, edge, value) }
    }

    pub fn set_measure_func(&mut self,
                            func: extern "C" fn(*mut ffi::Node,
                                                f32,
                                                MeasureMode,
                                                f32,
                                                MeasureMode)
                                                -> Size) {
        unsafe { ffi::YGNodeSetMeasureFunc(self._node, func) }
    }

    pub fn mark_dirty(&mut self) {
        unsafe { ffi::YGNodeMarkDirty(self._node) }
    }

    pub fn is_dirty(&self) -> bool {
        unsafe { ffi::YGNodeIsDirty(self._node) }
    }

    pub fn set_context(&mut self, context: *mut Context) {
        unsafe { ffi::YGNodeSetContext(self._node, context as *mut c_void) }
    }

    pub fn get_context(&self) -> &Context {
        unsafe {
            let context = ffi::YGNodeGetContext(self._node);
            let ref ctx: Context = *(context as *mut Context);
            ctx
        }
    }
}

#[cfg(test)]
mod tests {
    use Context;
    use Measures;
    use Node;
    use Size;
    use measure::measure;

    struct Measurer {}

    impl Measures for Measurer {
        fn measure(&self, text: &str) -> Size {
            Size {
                width: text.len() as f32,
                height: 1.0,
            }
        }
    }

    #[test]
    fn dirty_works() {
        let mut node = Node::new();
        node.set_measure_func(measure);
        assert!(!node.is_dirty());
        node.mark_dirty();
        assert!(node.is_dirty());
        node.free();
    }

    #[test]
    fn context_works() {
        let mut node = Node::new();
        node.set_context(&mut Context::new("Yo!", &Measurer {}));
        {
            let context = node.get_context();
            assert!(context.measure().width == 3.0);
        }
        node.free();
    }

    #[test]
    fn measure_works() {
        let mut node = Node::new();
        node.set_measure_func(measure);
        node.set_context(&mut Context::new("Yo!!", &Measurer {}));
        node.calculate_layout();
        assert!(node.get_layout_width() == 4.0);
        assert!(node.get_layout_height() == 1.0);
        node.free();
    }

    #[test]
    fn get_instance_count() {
        assert!(Node::get_instance_count() == 0);
        let mut node = Node::new();
        assert!(Node::get_instance_count() == 1);
        node.free();
        assert!(Node::get_instance_count() == 0);
    }

    #[test]
    fn get_child_count() {
        let mut p1 = Node::new();
        let mut c1 = Node::new();
        let mut c2 = Node::new();
        p1.insert_child(&c1, 0);
        p1.insert_child(&c2, 1);
        assert!(p1.get_child_count() == 2);
        p1.free();
        c1.free();
        c2.free();
    }

    #[test]
    fn get_child() {
        let mut p1 = Node::new();

        let mut c1 = Node::new();
        c1.set_width(1.0);

        let mut c2 = Node::new();
        c2.set_width(2.0);

        p1.insert_child(&c1, 0);
        p1.insert_child(&c2, 1);

        assert!(p1.get_child(0).get_width() == 1.0);
        assert!(p1.get_child(1).get_width() == 2.0);
        p1.free();
        c1.free();
        c2.free();
    }
}
<commit_msg>chore(context): shorter syntax<commit_after>use std;
use std::default::Default;
use libc::c_void;

use ffi;
use ffi::{Direction, MeasureMode, Size};
use context::Context;
use measure::measure;

#[derive(Debug)]
pub struct Node {
    pub _node: *mut ffi::Node, // TODO Into/From trait
}

impl Default for Node {
    fn default() -> Node {
        Node::new()
    }
}

impl Node {
    pub fn new() -> Node {
        Node { _node: unsafe { ffi::YGNodeNew() } }
    }

    pub fn get_instance_count() -> i32 {
        unsafe { ffi::YGNodeGetInstanceCount() }
    }

    pub fn reset(&mut self) {
        unsafe { ffi::YGNodeReset(self._node) }
    }

    pub fn free(self) {
        unsafe { ffi::YGNodeFree(self._node) }
    }

    pub fn free_recursive(self) {
        unsafe { ffi::YGNodeFreeRecursive(self._node) }
    }

    pub fn set_direction(&mut self, value: ffi::Direction) {
        unsafe { ffi::YGNodeStyleSetDirection(self._node, value) }
    }

    pub fn get_direction(&self) -> ffi::Direction {
        unsafe { ffi::YGNodeStyleGetDirection(self._node) }
    }

    pub fn set_flex_direction(&mut self, value: ffi::FlexDirection) {
        unsafe { ffi::YGNodeStyleSetFlexDirection(self._node, value) }
    }

    pub fn get_flex_direction(&self) -> ffi::FlexDirection {
        unsafe { ffi::YGNodeStyleGetFlexDirection(self._node) }
    }

    pub fn set_width(&mut self, width: f32) {
        unsafe { ffi::YGNodeStyleSetWidth(self._node, width) }
    }

    pub fn get_width(&self) -> f32 {
        unsafe { ffi::YGNodeStyleGetWidth(self._node) }
    }

    pub fn set_height(&mut self, height: f32) {
        unsafe { ffi::YGNodeStyleSetHeight(self._node, height) }
    }

    pub fn get_height(&self) -> f32 {
        unsafe { ffi::YGNodeStyleGetHeight(self._node) }
    }

    pub fn calculate_layout(&mut self) {
        unsafe {
            ffi::YGNodeCalculateLayout(self._node, std::f32::NAN, std::f32::NAN, Direction::LTR)
        }
    }

    pub fn get_layout_width(&self) -> f32 {
        unsafe { ffi::YGNodeLayoutGetWidth(self._node) }
    }

    pub fn get_layout_height(&self) -> f32 {
        unsafe { ffi::YGNodeLayoutGetHeight(self._node) }
    }

    pub fn get_layout_left(&self) -> f32 {
        unsafe { ffi::YGNodeLayoutGetLeft(self._node) }
    }

    pub fn get_layout_top(&self) -> f32 {
        unsafe { ffi::YGNodeLayoutGetTop(self._node) }
    }

    pub fn get_layout_direction(&self) -> ffi::Direction {
        unsafe { ffi::YGNodeLayoutGetDirection(self._node) }
    }

    pub fn insert_child(&mut self, child: &Node, index: u32) {
        unsafe { ffi::YGNodeInsertChild(self._node, child._node, index) }
    }

    pub fn remove_child(&mut self, child: &Node) {
        unsafe { ffi::YGNodeRemoveChild(self._node, child._node) }
    }

    pub fn get_child(&self, index: u32) -> Node {
        // FIXME this is wrong
        // also prevents Drop impl for Node
        unsafe { Node { _node: ffi::YGNodeGetChild(self._node, index) } }
    }

    pub fn get_child_count(&self) -> u32 {
        unsafe { ffi::YGNodeGetChildCount(self._node) }
    }

    pub fn get_parent(&self) -> Node {
        // FIXME this is wrong
        // also prevents Drop impl for Node
        unsafe { Node { _node: ffi::YGNodeGetParent(self._node) } }
    }

    pub fn set_justify_content(&mut self, value: ffi::JustifyContent) {
        unsafe { ffi::YGNodeStyleSetJustifyContent(self._node, value) }
    }

    pub fn get_justify_content(&self) -> ffi::JustifyContent {
        unsafe { ffi::YGNodeStyleGetJustifyContent(self._node) }
    }

    pub fn get_align_items(&self) -> ffi::Align {
        unsafe { ffi::YGNodeStyleGetAlignItems(self._node) }
    }

    pub fn set_align_items(&mut self, value: ffi::Align) {
        unsafe { ffi::YGNodeStyleSetAlignItems(self._node, value) }
    }

    pub fn get_align_self(&self) -> ffi::Align {
        unsafe { ffi::YGNodeStyleGetAlignSelf(self._node) }
    }

    pub fn set_align_self(&mut self, value: ffi::Align) {
        unsafe { ffi::YGNodeStyleSetAlignSelf(self._node, value) }
    }

    pub fn get_align_content(&self) -> ffi::Align {
        unsafe { ffi::YGNodeStyleGetAlignContent(self._node) }
    }

    pub fn set_align_content(&mut self, value: ffi::Align) {
        unsafe { ffi::YGNodeStyleSetAlignContent(self._node, value) }
    }

    pub fn get_position_type(&self) -> ffi::PositionType {
        unsafe { ffi::YGNodeStyleGetPositionType(self._node) }
    }

    pub fn set_position_type(&mut self, value: ffi::PositionType) {
        unsafe { ffi::YGNodeStyleSetPositionType(self._node, value) }
    }

    pub fn get_flex_wrap(&self) -> ffi::FlexWrap {
        unsafe { ffi::YGNodeStyleGetFlexWrap(self._node) }
    }

    pub fn set_flex_wrap(&mut self, value: ffi::FlexWrap) {
        unsafe { ffi::YGNodeStyleSetFlexWrap(self._node, value) }
    }

    pub fn get_overflow(&self) -> ffi::Overflow {
        unsafe { ffi::YGNodeStyleGetOverflow(self._node) }
    }

    pub fn set_overflow(&mut self, value: ffi::Overflow) {
        unsafe { ffi::YGNodeStyleSetOverflow(self._node, value) }
    }

    pub fn set_flex(&mut self, value: f32) {
        unsafe { ffi::YGNodeStyleSetFlex(self._node, value) }
    }

    pub fn get_flex_grow(&self) -> f32 {
        unsafe { ffi::YGNodeStyleGetFlexGrow(self._node) }
    }

    pub fn set_flex_grow(&mut self, value: f32) {
        unsafe { ffi::YGNodeStyleSetFlexGrow(self._node, value) }
    }

    pub fn get_flex_shrink(&self) -> f32 {
        unsafe { ffi::YGNodeStyleGetFlexShrink(self._node) }
    }

    pub fn set_flex_shrink(&mut self, value: f32) {
        unsafe { ffi::YGNodeStyleSetFlexShrink(self._node, value) }
    }

    pub fn get_flex_basis(&self) -> f32 {
        unsafe { ffi::YGNodeStyleGetFlexBasis(self._node) }
    }

    pub fn set_flex_basis(&mut self, value: f32) {
        unsafe { ffi::YGNodeStyleSetFlexBasis(self._node, value) }
    }

    pub fn get_margin(&self, edge: ffi::Edge) -> f32 {
        unsafe { ffi::YGNodeStyleGetMargin(self._node, edge) }
    }

    pub fn set_margin(&mut self, edge: ffi::Edge, value: f32) {
        unsafe { ffi::YGNodeStyleSetMargin(self._node, edge, value) }
    }

    pub fn get_padding(&self, edge: ffi::Edge) -> f32 {
        unsafe { ffi::YGNodeStyleGetPadding(self._node, edge) }
    }

    pub fn set_padding(&mut self, edge: ffi::Edge, value: f32) {
        unsafe { ffi::YGNodeStyleSetPadding(self._node, edge, value) }
    }

    pub fn get_border(&self, edge: ffi::Edge) -> f32 {
        unsafe { ffi::YGNodeStyleGetBorder(self._node, edge) }
    }

    pub fn set_border(&mut self, edge: ffi::Edge, value: f32) {
        unsafe { ffi::YGNodeStyleSetBorder(self._node, edge, value) }
    }

    pub fn get_position(&self, edge: ffi::Edge) -> f32 {
        unsafe { ffi::YGNodeStyleGetPosition(self._node, edge) }
    }

    pub fn set_position(&mut self, edge: ffi::Edge, value: f32) {
        unsafe { ffi::YGNodeStyleSetPosition(self._node, edge, value) }
    }

    pub fn set_measure_func(&mut self,
                            func: extern "C" fn(*mut ffi::Node,
                                                f32,
                                                MeasureMode,
                                                f32,
                                                MeasureMode)
                                                -> Size) {
        unsafe { ffi::YGNodeSetMeasureFunc(self._node, func) }
    }

    pub fn mark_dirty(&mut self) {
        unsafe { ffi::YGNodeMarkDirty(self._node) }
    }

    pub fn is_dirty(&self) -> bool {
        unsafe { ffi::YGNodeIsDirty(self._node) }
    }

    pub fn set_context(&mut self, context: *mut Context) {
        unsafe { ffi::YGNodeSetContext(self._node, context as *mut c_void) }
    }

    pub fn get_context(&self) -> &Context {
        unsafe { &*(ffi::YGNodeGetContext(self._node) as *mut Context) }
    }
}

#[cfg(test)]
mod tests {
    use Context;
    use Measures;
    use Node;
    use Size;
    use measure::measure;

    struct Measurer {}

    impl Measures for Measurer {
        fn measure(&self, text: &str) -> Size {
            Size {
                width: text.len() as f32,
                height: 1.0,
            }
        }
    }

    #[test]
    fn dirty_works() {
        let mut node = Node::new();
        node.set_measure_func(measure);
        assert!(!node.is_dirty());
        node.mark_dirty();
        assert!(node.is_dirty());
        node.free();
    }

    #[test]
    fn context_works() {
        let mut node = Node::new();
        node.set_context(&mut Context::new("Yo!", &Measurer {}));
        {
            let context = node.get_context();
            assert!(context.measure().width == 3.0);
        }
        node.free();
    }

    #[test]
    fn measure_works() {
        let mut node = Node::new();
        node.set_measure_func(measure);
        node.set_context(&mut Context::new("Yo!!", &Measurer {}));
        node.calculate_layout();
        assert!(node.get_layout_width() == 4.0);
        assert!(node.get_layout_height() == 1.0);
        node.free();
    }

    #[test]
    fn get_instance_count() {
        assert!(Node::get_instance_count() == 0);
        let mut node = Node::new();
        assert!(Node::get_instance_count() == 1);
        node.free();
        assert!(Node::get_instance_count() == 0);
    }

    #[test]
    fn get_child_count() {
        let mut p1 = Node::new();
        let mut c1 = Node::new();
        let mut c2 = Node::new();
        p1.insert_child(&c1, 0);
        p1.insert_child(&c2, 1);
        assert!(p1.get_child_count() == 2);
        p1.free();
        c1.free();
        c2.free();
    }

    #[test]
    fn get_child() {
        let mut p1 = Node::new();

        let mut c1 = Node::new();
        c1.set_width(1.0);

        let mut c2 = Node::new();
        c2.set_width(2.0);

        p1.insert_child(&c1, 0);
        p1.insert_child(&c2, 1);

        assert!(p1.get_child(0).get_width() == 1.0);
        assert!(p1.get_child(1).get_width() == 2.0);
        p1.free();
        c1.free();
        c2.free();
    }
}
<|endoftext|>


<commit_before>use std::path::PathBuf;

use structopt::clap::AppSettings;
use structopt::StructOpt;

use crate::filter::Filter;

#[derive(StructOpt)]
#[structopt(bin_name = "cargo")]
pub enum Opts {
    /// Show the result of macro expansion.
    #[structopt(
        name = "expand",
        raw(
            setting = "AppSettings::UnifiedHelpMessage",
            setting = "AppSettings::DeriveDisplayOrder",
            setting = "AppSettings::DontCollapseArgsInUsage"
        )
    )]
    Expand(Args),
}

#[derive(StructOpt, Debug)]
#[structopt(rename_all = "kebab-case")]
pub struct Args {
    /// Space-separated list of features to activate
    #[structopt(long, value_name = "FEATURES")]
    pub features: Option<String>,

    /// Activate all available features
    #[structopt(long)]
    pub all_features: bool,

    /// Do not activate the `default` feature
    #[structopt(long)]
    pub no_default_features: bool,

    /// Build only this package's library
    #[structopt(long)]
    pub lib: bool,

    /// Build only the specified binary
    #[structopt(long, value_name = "NAME")]
    pub bin: Option<String>,

    /// Build only the specified example
    #[structopt(long, value_name = "NAME")]
    pub example: Option<String>,

    /// Build only the specified test target
    #[structopt(long, value_name = "NAME")]
    pub test: Option<String>,

    /// Include tests when expanding the lib or bin
    #[structopt(long)]
    pub tests: bool,

    /// Build only the specified bench target
    #[structopt(long, value_name = "NAME")]
    pub bench: Option<String>,

    /// Target triple which compiles will be for
    #[structopt(long, value_name = "TARGET")]
    pub target: Option<String>,

    /// Directory for all generated artifacts
    #[structopt(long, value_name = "DIRECTORY", parse(from_os_str))]
    pub target_dir: Option<PathBuf>,

    /// Path to Cargo.toml
    #[structopt(long, value_name = "PATH", parse(from_os_str))]
    pub manifest_path: Option<PathBuf>,

    /// Number of parallel jobs, defaults to # of CPUs
    #[structopt(short, long, value_name = "N")]
    pub jobs: Option<u64>,

    /// Coloring: auto, always, never
    #[structopt(long, value_name = "WHEN")]
    pub color: Option<String>,

    /// Require Cargo.lock and cache are up to date
    #[structopt(long)]
    pub frozen: bool,

    /// Require Cargo.lock is up to date
    #[structopt(long)]
    pub locked: bool,

    /// Unstable (nightly-only) flags to Cargo
    #[structopt(short = "Z", value_name = "FLAG")]
    pub unstable_flags: Vec<String>,

    /// Do not attempt to run rustfmt
    #[structopt(long)]
    pub ugly: bool,

    /// Local path to module or other named item to expand, e.g. os::unix::ffi
    #[structopt(value_name = "ITEM")]
    pub item: Option<Filter>,
}
<commit_msg>Rephrase help text of target flags<commit_after>use std::path::PathBuf;

use structopt::clap::AppSettings;
use structopt::StructOpt;

use crate::filter::Filter;

#[derive(StructOpt)]
#[structopt(bin_name = "cargo")]
pub enum Opts {
    /// Show the result of macro expansion.
    #[structopt(
        name = "expand",
        raw(
            setting = "AppSettings::UnifiedHelpMessage",
            setting = "AppSettings::DeriveDisplayOrder",
            setting = "AppSettings::DontCollapseArgsInUsage"
        )
    )]
    Expand(Args),
}

#[derive(StructOpt, Debug)]
#[structopt(rename_all = "kebab-case")]
pub struct Args {
    /// Space-separated list of features to activate
    #[structopt(long, value_name = "FEATURES")]
    pub features: Option<String>,

    /// Activate all available features
    #[structopt(long)]
    pub all_features: bool,

    /// Do not activate the `default` feature
    #[structopt(long)]
    pub no_default_features: bool,

    /// Expand only this package's library
    #[structopt(long)]
    pub lib: bool,

    /// Expand only the specified binary
    #[structopt(long, value_name = "NAME")]
    pub bin: Option<String>,

    /// Expand only the specified example
    #[structopt(long, value_name = "NAME")]
    pub example: Option<String>,

    /// Expand only the specified test target
    #[structopt(long, value_name = "NAME")]
    pub test: Option<String>,

    /// Include tests when expanding the lib or bin
    #[structopt(long)]
    pub tests: bool,

    /// Expand only the specified bench target
    #[structopt(long, value_name = "NAME")]
    pub bench: Option<String>,

    /// Target triple which compiles will be for
    #[structopt(long, value_name = "TARGET")]
    pub target: Option<String>,

    /// Directory for all generated artifacts
    #[structopt(long, value_name = "DIRECTORY", parse(from_os_str))]
    pub target_dir: Option<PathBuf>,

    /// Path to Cargo.toml
    #[structopt(long, value_name = "PATH", parse(from_os_str))]
    pub manifest_path: Option<PathBuf>,

    /// Number of parallel jobs, defaults to # of CPUs
    #[structopt(short, long, value_name = "N")]
    pub jobs: Option<u64>,

    /// Coloring: auto, always, never
    #[structopt(long, value_name = "WHEN")]
    pub color: Option<String>,

    /// Require Cargo.lock and cache are up to date
    #[structopt(long)]
    pub frozen: bool,

    /// Require Cargo.lock is up to date
    #[structopt(long)]
    pub locked: bool,

    /// Unstable (nightly-only) flags to Cargo
    #[structopt(short = "Z", value_name = "FLAG")]
    pub unstable_flags: Vec<String>,

    /// Do not attempt to run rustfmt
    #[structopt(long)]
    pub ugly: bool,

    /// Local path to module or other named item to expand, e.g. os::unix::ffi
    #[structopt(value_name = "ITEM")]
    pub item: Option<Filter>,
}
<|endoftext|>


<commit_before>// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Tidy check to enforce various stylistic guidelines on the Rust codebase.
//!
//! Example checks are:
//!
//! * No lines over 100 characters
//! * No tabs
//! * No trailing whitespace
//! * No CR characters
//! * No `TODO` or `XXX` directives
//! * A valid license header is at the top
//! * No unexplained ` ```ignore ` or ` ```rust,ignore ` doc tests
//!
//! A number of these checks can be opted-out of with various directives like
//! `// ignore-tidy-linelength`.

use std::fs::File;
use std::io::prelude::*;
use std::path::Path;

const COLS: usize = 100;
const LICENSE: &'static str = "\
Copyright <year> The Rust Project Developers. See the COPYRIGHT
file at the top-level directory of this distribution and at
http://rust-lang.org/COPYRIGHT.

Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
<LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
option. This file may not be copied, modified, or distributed
except according to those terms.";

const UNEXPLAINED_IGNORE_DOCTEST_INFO: &str = r#"unexplained "```ignore" doctest; try one:

* make the test actually pass, by adding necessary imports and declarations, or
* use "```text", if the code is not Rust code, or
* use "```compile_fail,Ennnn", if the code is expected to fail at compile time, or
* use "```should_panic", if the code is expected to fail at run time, or
* use "```no_run", if the code should type-check but not necessary linkable/runnable, or
* explain it like "```ignore (cannot-test-this-because-xxxx)", if the annotation cannot be avoided.

"#;

/// Parser states for line_is_url.
#[derive(PartialEq)]
#[allow(non_camel_case_types)]
enum LIUState { EXP_COMMENT_START,
                EXP_LINK_LABEL_OR_URL,
                EXP_URL,
                EXP_END }

/// True if LINE appears to be a line comment containing an URL,
/// possibly with a Markdown link label in front, and nothing else.
/// The Markdown link label, if present, may not contain whitespace.
/// Lines of this form are allowed to be overlength, because Markdown
/// offers no way to split a line in the middle of a URL, and the lengths
/// of URLs to external references are beyond our control.
fn line_is_url(line: &str) -> bool {
    use self::LIUState::*;
    let mut state: LIUState = EXP_COMMENT_START;

    for tok in line.split_whitespace() {
        match (state, tok) {
            (EXP_COMMENT_START, "//") => state = EXP_LINK_LABEL_OR_URL,
            (EXP_COMMENT_START, "///") => state = EXP_LINK_LABEL_OR_URL,
            (EXP_COMMENT_START, "//!") => state = EXP_LINK_LABEL_OR_URL,

            (EXP_LINK_LABEL_OR_URL, w)
                if w.len() >= 4 && w.starts_with("[") && w.ends_with("]:")
                => state = EXP_URL,

            (EXP_LINK_LABEL_OR_URL, w)
                if w.starts_with("http://") || w.starts_with("https://")
                => state = EXP_END,

            (EXP_URL, w)
                if w.starts_with("http://") || w.starts_with("https://")
                => state = EXP_END,

            (_, _) => return false,
        }
    }

    state == EXP_END
}

/// True if LINE is allowed to be longer than the normal limit.
/// Currently there is only one exception, for long URLs, but more
/// may be added in the future.
fn long_line_is_ok(line: &str) -> bool {
    if line_is_url(line) {
        return true;
    }

    false
}

pub fn check(path: &Path, bad: &mut bool) {
    let mut contents = String::new();
    super::walk(path, &mut super::filter_dirs, &mut |file| {
        let filename = file.file_name().unwrap().to_string_lossy();
        let extensions = [".rs", ".py", ".js", ".sh", ".c", ".h"];
        if extensions.iter().all(|e| !filename.ends_with(e)) ||
           filename.starts_with(".#") {
            return
        }

        contents.truncate(0);
        t!(t!(File::open(file), file).read_to_string(&mut contents));

        if contents.is_empty() {
            tidy_error!(bad, "{}: empty file", file.display());
        }

        let skip_cr = contents.contains("ignore-tidy-cr");
        let skip_tab = contents.contains("ignore-tidy-tab");
        let skip_length = contents.contains("ignore-tidy-linelength");
        let skip_end_whitespace = contents.contains("ignore-tidy-end-whitespace");
        for (i, line) in contents.split("\n").enumerate() {
            let mut err = |msg: &str| {
                tidy_error!(bad, "{}:{}: {}", file.display(), i + 1, msg);
            };
            if !skip_length && line.chars().count() > COLS
                && !long_line_is_ok(line) {
                    err(&format!("line longer than {} chars", COLS));
            }
            if line.contains("\t") && !skip_tab {
                err("tab character");
            }
            if !skip_end_whitespace && (line.ends_with(" ") || line.ends_with("\t")) {
                err("trailing whitespace");
            }
            if line.contains("\r") && !skip_cr {
                err("CR character");
            }
            if filename != "style.rs" {
                if line.contains("TODO") {
                    err("TODO is deprecated; use FIXME")
                }
                if line.contains("//") && line.contains(" XXX") {
                    err("XXX is deprecated; use FIXME")
                }
            }
            if line.ends_with("```ignore") || line.ends_with("```rust,ignore") {
                err(UNEXPLAINED_IGNORE_DOCTEST_INFO);
            }
        }
        if !licenseck(file, &contents) {
            tidy_error!(bad, "{}: incorrect license", file.display());
        }
    })
}

fn licenseck(file: &Path, contents: &str) -> bool {
    if contents.contains("ignore-license") {
        return true
    }
    let exceptions = [
        "libstd/sync/mpsc/mpsc_queue.rs",
        "libstd/sync/mpsc/spsc_queue.rs",
    ];
    if exceptions.iter().any(|f| file.ends_with(f)) {
        return true
    }

    // Skip the BOM if it's there
    let bom = "\u{feff}";
    let contents = if contents.starts_with(bom) {&contents[3..]} else {contents};

    // See if the license shows up in the first 100 lines
    let lines = contents.lines().take(100).collect::<Vec<_>>();
    lines.windows(LICENSE.lines().count()).any(|window| {
        let offset = if window.iter().all(|w| w.starts_with("//")) {
            2
        } else if window.iter().all(|w| w.starts_with('#')) {
            1
        } else if window.iter().all(|w| w.starts_with(" *")) {
            2
        } else {
            return false
        };
        window.iter().map(|a| a[offset..].trim())
              .zip(LICENSE.lines()).all(|(a, b)| {
            a == b || match b.find("<year>") {
                Some(i) => a.starts_with(&b[..i]) && a.ends_with(&b[i+6..]),
                None => false,
            }
        })
    })

}
<commit_msg>Detect relative urls in tidy check<commit_after>// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Tidy check to enforce various stylistic guidelines on the Rust codebase.
//!
//! Example checks are:
//!
//! * No lines over 100 characters
//! * No tabs
//! * No trailing whitespace
//! * No CR characters
//! * No `TODO` or `XXX` directives
//! * A valid license header is at the top
//! * No unexplained ` ```ignore ` or ` ```rust,ignore ` doc tests
//!
//! A number of these checks can be opted-out of with various directives like
//! `// ignore-tidy-linelength`.

use std::fs::File;
use std::io::prelude::*;
use std::path::Path;

const COLS: usize = 100;
const LICENSE: &'static str = "\
Copyright <year> The Rust Project Developers. See the COPYRIGHT
file at the top-level directory of this distribution and at
http://rust-lang.org/COPYRIGHT.

Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
<LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
option. This file may not be copied, modified, or distributed
except according to those terms.";

const UNEXPLAINED_IGNORE_DOCTEST_INFO: &str = r#"unexplained "```ignore" doctest; try one:

* make the test actually pass, by adding necessary imports and declarations, or
* use "```text", if the code is not Rust code, or
* use "```compile_fail,Ennnn", if the code is expected to fail at compile time, or
* use "```should_panic", if the code is expected to fail at run time, or
* use "```no_run", if the code should type-check but not necessary linkable/runnable, or
* explain it like "```ignore (cannot-test-this-because-xxxx)", if the annotation cannot be avoided.

"#;

/// Parser states for line_is_url.
#[derive(PartialEq)]
#[allow(non_camel_case_types)]
enum LIUState { EXP_COMMENT_START,
                EXP_LINK_LABEL_OR_URL,
                EXP_URL,
                EXP_END }

/// True if LINE appears to be a line comment containing an URL,
/// possibly with a Markdown link label in front, and nothing else.
/// The Markdown link label, if present, may not contain whitespace.
/// Lines of this form are allowed to be overlength, because Markdown
/// offers no way to split a line in the middle of a URL, and the lengths
/// of URLs to external references are beyond our control.
fn line_is_url(line: &str) -> bool {
    use self::LIUState::*;
    let mut state: LIUState = EXP_COMMENT_START;

    for tok in line.split_whitespace() {
        match (state, tok) {
            (EXP_COMMENT_START, "//") => state = EXP_LINK_LABEL_OR_URL,
            (EXP_COMMENT_START, "///") => state = EXP_LINK_LABEL_OR_URL,
            (EXP_COMMENT_START, "//!") => state = EXP_LINK_LABEL_OR_URL,

            (EXP_LINK_LABEL_OR_URL, w)
                if w.len() >= 4 && w.starts_with("[") && w.ends_with("]:")
                => state = EXP_URL,

            (EXP_LINK_LABEL_OR_URL, w)
                if w.starts_with("http://") || w.starts_with("https://") || w.starts_with("../")
                => state = EXP_END,

            (EXP_URL, w)
                if w.starts_with("http://") || w.starts_with("https://") || w.starts_with("../")
                => state = EXP_END,

            (_, _) => return false,
        }
    }

    state == EXP_END
}

/// True if LINE is allowed to be longer than the normal limit.
/// Currently there is only one exception, for long URLs, but more
/// may be added in the future.
fn long_line_is_ok(line: &str) -> bool {
    if line_is_url(line) {
        return true;
    }

    false
}

pub fn check(path: &Path, bad: &mut bool) {
    let mut contents = String::new();
    super::walk(path, &mut super::filter_dirs, &mut |file| {
        let filename = file.file_name().unwrap().to_string_lossy();
        let extensions = [".rs", ".py", ".js", ".sh", ".c", ".h"];
        if extensions.iter().all(|e| !filename.ends_with(e)) ||
           filename.starts_with(".#") {
            return
        }

        contents.truncate(0);
        t!(t!(File::open(file), file).read_to_string(&mut contents));

        if contents.is_empty() {
            tidy_error!(bad, "{}: empty file", file.display());
        }

        let skip_cr = contents.contains("ignore-tidy-cr");
        let skip_tab = contents.contains("ignore-tidy-tab");
        let skip_length = contents.contains("ignore-tidy-linelength");
        let skip_end_whitespace = contents.contains("ignore-tidy-end-whitespace");
        for (i, line) in contents.split("\n").enumerate() {
            let mut err = |msg: &str| {
                tidy_error!(bad, "{}:{}: {}", file.display(), i + 1, msg);
            };
            if !skip_length && line.chars().count() > COLS
                && !long_line_is_ok(line) {
                    err(&format!("line longer than {} chars", COLS));
            }
            if line.contains("\t") && !skip_tab {
                err("tab character");
            }
            if !skip_end_whitespace && (line.ends_with(" ") || line.ends_with("\t")) {
                err("trailing whitespace");
            }
            if line.contains("\r") && !skip_cr {
                err("CR character");
            }
            if filename != "style.rs" {
                if line.contains("TODO") {
                    err("TODO is deprecated; use FIXME")
                }
                if line.contains("//") && line.contains(" XXX") {
                    err("XXX is deprecated; use FIXME")
                }
            }
            if line.ends_with("```ignore") || line.ends_with("```rust,ignore") {
                err(UNEXPLAINED_IGNORE_DOCTEST_INFO);
            }
        }
        if !licenseck(file, &contents) {
            tidy_error!(bad, "{}: incorrect license", file.display());
        }
    })
}

fn licenseck(file: &Path, contents: &str) -> bool {
    if contents.contains("ignore-license") {
        return true
    }
    let exceptions = [
        "libstd/sync/mpsc/mpsc_queue.rs",
        "libstd/sync/mpsc/spsc_queue.rs",
    ];
    if exceptions.iter().any(|f| file.ends_with(f)) {
        return true
    }

    // Skip the BOM if it's there
    let bom = "\u{feff}";
    let contents = if contents.starts_with(bom) {&contents[3..]} else {contents};

    // See if the license shows up in the first 100 lines
    let lines = contents.lines().take(100).collect::<Vec<_>>();
    lines.windows(LICENSE.lines().count()).any(|window| {
        let offset = if window.iter().all(|w| w.starts_with("//")) {
            2
        } else if window.iter().all(|w| w.starts_with('#')) {
            1
        } else if window.iter().all(|w| w.starts_with(" *")) {
            2
        } else {
            return false
        };
        window.iter().map(|a| a[offset..].trim())
              .zip(LICENSE.lines()).all(|(a, b)| {
            a == b || match b.find("<year>") {
                Some(i) => a.starts_with(&b[..i]) && a.ends_with(&b[i+6..]),
                None => false,
            }
        })
    })

}
<|endoftext|>


<commit_before>extern crate rustbox;
use std::comm::{Receiver};
use std::io::{File, Open, ReadWrite, BufferedReader};

pub struct Editor {
    pub events: Receiver<rustbox::Event>,
    pub buffers: Vec<Buf>
}

pub struct Buf {
    pub first_line: Vec<Line>,
    pub last_line: Vec<Line>,
}

pub struct Line {
    pub data: Vec<u8>,
}

enum Response {
    Continue,
    Quit,
}

impl Editor {
    pub fn handle_key_event(&self, ch: u32) -> Response {
        match std::char::from_u32(ch) {
            Some('q') => Quit,
            _ => Continue,
        }
    }

    pub fn start(&self) -> bool {
        loop {
            let status = match self.events.recv() {
                rustbox::KeyEvent(_, _, ch) => {
                    let status = self.handle_key_event(ch);
                    match status {
                        Quit => { false },
                        _ => { true },
                    }
                },
                _ => { true }
            };
            if status == false {
                return false;
            }
        }
    }

    pub fn open_file(&self, fp: &str) {
        let path = Path::new(fp);
        let file = match File::open(&path) {
            Ok(f) => f,
            Err(e) => fail!("New file - not implemented"),
        };

        let mut buf = BufferedReader::new(file);

        for (index, line) in buf.lines().enumerate() {
            rustbox::print(1, index + 1, rustbox::Bold, rustbox::White, rustbox::Black, line.unwrap());
            rustbox::present();
        }
    }
}

<commit_msg>Fix compile-time warnings<commit_after>extern crate rustbox;
use std::comm::{Receiver};
use std::io::{File, BufferedReader};

pub struct Editor {
    pub events: Receiver<rustbox::Event>,
    pub buffers: Vec<Buf>
}

pub struct Buf {
    pub first_line: Vec<Line>,
    pub last_line: Vec<Line>,
}

pub struct Line {
    pub data: Vec<u8>,
}

pub enum Response {
    Continue,
    Quit,
}

impl Editor {
    pub fn handle_key_event(&self, ch: u32) -> Response {
        match std::char::from_u32(ch) {
            Some('q') => Quit,
            _ => Continue,
        }
    }

    pub fn start(&self) -> bool {
        loop {
            let status = match self.events.recv() {
                rustbox::KeyEvent(_, _, ch) => {
                    let status = self.handle_key_event(ch);
                    match status {
                        Quit => { false },
                        _ => { true },
                    }
                },
                _ => { true }
            };
            if status == false {
                return false;
            }
        }
    }

    pub fn open_file(&self, fp: &str) {
        let path = Path::new(fp);
        let file = match File::open(&path) {
            Ok(f) => f,
            Err(_) => fail!("New file - not implemented"),
        };

        let mut buf = BufferedReader::new(file);

        for (index, line) in buf.lines().enumerate() {
            rustbox::print(1, index + 1, rustbox::Bold, rustbox::White, rustbox::Black, line.unwrap());
            rustbox::present();
        }
    }
}

<|endoftext|>


<commit_before>use FswSession;

fn get_default_session() -> FswSession {
  FswSession::default().unwrap()
}

#[test]
fn create_and_destroy_session() {
  let handle = {
    let session = get_default_session();
    session.handle
  };
  // Check that the handle was created successfully.
  assert!(handle != ::FSW_INVALID_HANDLE);
  // Check that trying to destroy the handle after the session wrapper goes out of scope fails.
  // This should fail because the wrapper going out of scope should automatically destroy the
  // session.
  assert!(unsafe { ::fsw_destroy_session(handle) } != ::FSW_OK);
}

#[test]
fn add_path() {
  let session = get_default_session();
  session.add_path("./").unwrap();
}

#[test]
fn add_property() {
  let session = get_default_session();
  session.add_property("test_name", "test_value").unwrap();
}

#[test]
fn set_allow_overflow() {
  let session = get_default_session();
  session.set_allow_overflow(true).unwrap();
}

#[test]
fn set_callback() {
  let session = get_default_session();
  session.set_callback(|_| {
    println!("Hi!");
  }).unwrap();
}

#[test]
#[should_panic]
fn start_empty() {
  get_default_session().start_monitor().unwrap();
}

#[test]
fn start_without_callback() {
  let session = get_default_session();
  session.add_path("./").unwrap();
  assert!(session.start_monitor().is_err());
}

#[test]
fn start_without_path() {
  let session = get_default_session();
  session.set_callback(|_| println!("Hello")).unwrap();
  assert!(session.start_monitor().is_err());
}
<commit_msg>fix: use new modules in tests<commit_after>use {ffi, FswSession};

fn get_default_session() -> FswSession {
  FswSession::default().unwrap()
}

#[test]
fn create_and_destroy_session() {
  let handle = {
    let session = get_default_session();
    session.handle
  };
  // Check that the handle was created successfully.
  assert!(handle != ffi::FSW_INVALID_HANDLE);
  // Check that trying to destroy the handle after the session wrapper goes out of scope fails.
  // This should fail because the wrapper going out of scope should automatically destroy the
  // session.
  assert!(unsafe { ffi::fsw_destroy_session(handle) } != ffi::FSW_OK);
}

#[test]
fn add_path() {
  let session = get_default_session();
  session.add_path("./").unwrap();
}

#[test]
fn add_property() {
  let session = get_default_session();
  session.add_property("test_name", "test_value").unwrap();
}

#[test]
fn set_allow_overflow() {
  let session = get_default_session();
  session.set_allow_overflow(true).unwrap();
}

#[test]
fn set_callback() {
  let session = get_default_session();
  session.set_callback(|_| {
    println!("Hi!");
  }).unwrap();
}

#[test]
#[should_panic]
fn start_empty() {
  get_default_session().start_monitor().unwrap();
}

#[test]
fn start_without_callback() {
  let session = get_default_session();
  session.add_path("./").unwrap();
  assert!(session.start_monitor().is_err());
}

#[test]
fn start_without_path() {
  let session = get_default_session();
  session.set_callback(|_| println!("Hello")).unwrap();
  assert!(session.start_monitor().is_err());
}
<|endoftext|>


<commit_before>// Copyright (c) 2013-2015 Sandstorm Development Group, Inc. and contributors
// Licensed under the MIT License:
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

//! UTF-8 encoded text.

pub type Reader<'a> = &'a str;

static EMPTY : &'static str = "";

// len does not include the required null terminator at the end
pub fn new_reader<'a>(p : *const u8, len : u32) -> Result<Reader<'a>, ::std::str::Utf8Error> {
    // XXX The empty case is special and I don't know why.
    if len == 0 { return Ok(EMPTY); }
    let v : &'a [u8] = unsafe { ::std::slice::from_raw_parts(p, len as usize) };
    ::std::str::from_utf8(v)
}

impl <'a> ::traits::FromPointerReader<'a> for Reader<'a> {
    fn get_from_pointer(reader : &::private::layout::PointerReader<'a>) -> Reader<'a> {
        reader.get_text(::std::ptr::null(), 0)
    }
}

pub struct Builder<'a> {
    bytes : &'a mut [u8],
    pos : usize,
}

impl <'a> Builder <'a> {

    pub fn new<'b>(bytes : &'b mut [u8], pos : u32) -> Result<Builder<'b>, ::std::str::Utf8Error> {
        if pos != 0 {
            match ::std::str::from_utf8(bytes) {
                Err(e) => return Err(e),
                _ => {}
            }
        }
        Ok(Builder { bytes : bytes, pos : pos as usize })
    }

    pub fn push_ascii(&mut self, ascii : u8) {
        assert!(ascii < 128);
        self.bytes[self.pos] = ascii;
        self.pos += 1;
    }

    pub fn push_str(&mut self, string : &str) {
        let bytes = string.as_bytes();
        ::std::slice::bytes::copy_memory(&mut self.bytes[self.pos ..], bytes);
        self.pos += bytes.len();
    }
}

impl <'a> ::std::ops::Deref for Builder <'a> {
    type Target = str;
    fn deref<'b>(&'b self) -> &'b str {
        unsafe { ::std::str::from_utf8_unchecked(self.bytes) }
    }
}

impl <'a> ::std::str::Str for Builder<'a> {
    fn as_slice<'b>(&'b self) -> &'b str {
        unsafe { ::std::str::from_utf8_unchecked(self.bytes) }
    }
}

impl <'a> ::traits::FromPointerBuilder<'a> for Builder<'a> {
    fn init_pointer(builder : ::private::layout::PointerBuilder<'a>, size : u32) -> Builder<'a> {
        builder.init_text(size)
    }
    fn get_from_pointer(builder : ::private::layout::PointerBuilder<'a>) -> Builder<'a> {
        builder.get_text(::std::ptr::null(), 0)
    }
}

impl <'a> ::traits::SetPointerBuilder<Builder<'a>> for Reader<'a> {
    fn set_pointer_builder<'b>(pointer : ::private::layout::PointerBuilder<'b>, value : Reader<'a>) {
        pointer.set_text(value);
    }
}
<commit_msg>Remove special handling for empty text::Reader.<commit_after>// Copyright (c) 2013-2015 Sandstorm Development Group, Inc. and contributors
// Licensed under the MIT License:
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

//! UTF-8 encoded text.

pub type Reader<'a> = &'a str;

// len does not include the required null terminator at the end
pub fn new_reader<'a>(p : *const u8, len : u32) -> Result<Reader<'a>, ::std::str::Utf8Error> {
    let v : &'a [u8] = unsafe { ::std::slice::from_raw_parts(p, len as usize) };
    ::std::str::from_utf8(v)
}

impl <'a> ::traits::FromPointerReader<'a> for Reader<'a> {
    fn get_from_pointer(reader : &::private::layout::PointerReader<'a>) -> Reader<'a> {
        reader.get_text(::std::ptr::null(), 0)
    }
}

pub struct Builder<'a> {
    bytes : &'a mut [u8],
    pos : usize,
}

impl <'a> Builder <'a> {

    pub fn new<'b>(bytes : &'b mut [u8], pos : u32) -> Result<Builder<'b>, ::std::str::Utf8Error> {
        if pos != 0 {
            match ::std::str::from_utf8(bytes) {
                Err(e) => return Err(e),
                _ => {}
            }
        }
        Ok(Builder { bytes : bytes, pos : pos as usize })
    }

    pub fn push_ascii(&mut self, ascii : u8) {
        assert!(ascii < 128);
        self.bytes[self.pos] = ascii;
        self.pos += 1;
    }

    pub fn push_str(&mut self, string : &str) {
        let bytes = string.as_bytes();
        ::std::slice::bytes::copy_memory(&mut self.bytes[self.pos ..], bytes);
        self.pos += bytes.len();
    }
}

impl <'a> ::std::ops::Deref for Builder <'a> {
    type Target = str;
    fn deref<'b>(&'b self) -> &'b str {
        unsafe { ::std::str::from_utf8_unchecked(self.bytes) }
    }
}

impl <'a> ::std::str::Str for Builder<'a> {
    fn as_slice<'b>(&'b self) -> &'b str {
        unsafe { ::std::str::from_utf8_unchecked(self.bytes) }
    }
}

impl <'a> ::traits::FromPointerBuilder<'a> for Builder<'a> {
    fn init_pointer(builder : ::private::layout::PointerBuilder<'a>, size : u32) -> Builder<'a> {
        builder.init_text(size)
    }
    fn get_from_pointer(builder : ::private::layout::PointerBuilder<'a>) -> Builder<'a> {
        builder.get_text(::std::ptr::null(), 0)
    }
}

impl <'a> ::traits::SetPointerBuilder<Builder<'a>> for Reader<'a> {
    fn set_pointer_builder<'b>(pointer : ::private::layout::PointerBuilder<'b>, value : Reader<'a>) {
        pointer.set_text(value);
    }
}
<|endoftext|>


<commit_before>use yoga_wrapper;

use renderable::Renderable;
use style::Style;

#[derive(Debug, Default)]
pub struct Text<'text> {
    node: yoga_wrapper::Node,
    text: &'text str,
    style: Style,
}

impl<'text> Text<'text> {
    pub fn new(text: &'text str) -> Text<'text> {
        Text { text: text, ..Default::default() }
    }

    pub fn set_width(&mut self, width: f32) {
        self.style.set_width(width)
    }

    pub fn set_height(&mut self, height: f32) {
        self.style.set_height(height)
    }

    pub fn set_align_self(&mut self, value: yoga_wrapper::Align) {
        self.style.set_align_self(value)
    }

    pub fn set_flex_grow(&mut self, value: f32) {
        self.style.set_flex_grow(value)
    }
}

impl<'text> Renderable for Text<'text> {
    fn get_layout_width(&self) -> f32 {
        self.style.get_layout_width()
    }

    fn get_layout_height(&self) -> f32 {
        self.style.get_layout_height()
    }

    fn get_layout_top(&self) -> f32 {
        self.style.get_layout_top()
    }

    fn get_layout_left(&self) -> f32 {
        self.style.get_layout_left()
    }

    fn calculate_layout(&mut self) {
        self.style.calculate_layout()
    }

    fn get_child_count(&self) -> usize {
        0
    }

    fn get_child(&self, _: usize) -> Option<&Renderable> {
        None
    }

    fn get_node(&self) -> &yoga_wrapper::Node {
        &self.style.get_node()
    }
}

#[cfg(test)]
mod tests {
    use yoga_wrapper;

    use Text;
    use Backend;
    use Renders;

    struct Renderer {}

    impl Renders for Renderer {
        fn render(&mut self, node: &yoga_wrapper::Node) {}
    }

    struct Measurer {}

    impl yoga_wrapper::Measures for Measurer {
        fn measure(&self, text: &str) -> yoga_wrapper::Size {
            yoga_wrapper::Size {
                width: text.len() as f32,
                height: 1.0,
            }
        }
    }

    struct TestBackend {
        renderer: Renderer,
        measurer: Measurer,
    }

    impl TestBackend {
        pub fn new() -> TestBackend {
            TestBackend {
                renderer: Renderer {},
                measurer: Measurer {},
            }
        }
    }

    impl<'meas> Backend<'meas> for TestBackend {
        type Color = i32;
        type Renderer = Renderer;
        type Measurer = Measurer;

        fn render(&mut self, node: &yoga_wrapper::Node) {}

        fn get_renderer(&mut self) -> &mut Self::Renderer {
            &mut self.renderer
        }

        fn create_context<'text>(&'meas self,
                                 text: &'text str)
                                 -> yoga_wrapper::Context<'text, 'meas> {
            yoga_wrapper::Context::new(text, &self.measurer)
        }
    }

    #[test]
    fn it_works() {
        let be = TestBackend::new();
        let _ = Text::new("yo!");
    }
}
<commit_msg>chore(tests): fix 'em<commit_after>use yoga_wrapper;

use renderable::Renderable;
use style::Style;

#[derive(Debug, Default)]
pub struct Text<'text> {
    node: yoga_wrapper::Node,
    text: &'text str,
    style: Style,
}

impl<'text> Text<'text> {
    pub fn new(text: &'text str) -> Text<'text> {
        Text { text: text, ..Default::default() }
    }

    pub fn set_width(&mut self, width: f32) {
        self.style.set_width(width)
    }

    pub fn set_height(&mut self, height: f32) {
        self.style.set_height(height)
    }

    pub fn set_align_self(&mut self, value: yoga_wrapper::Align) {
        self.style.set_align_self(value)
    }

    pub fn set_flex_grow(&mut self, value: f32) {
        self.style.set_flex_grow(value)
    }
}

impl<'text> Renderable for Text<'text> {
    fn get_layout_width(&self) -> f32 {
        self.style.get_layout_width()
    }

    fn get_layout_height(&self) -> f32 {
        self.style.get_layout_height()
    }

    fn get_layout_top(&self) -> f32 {
        self.style.get_layout_top()
    }

    fn get_layout_left(&self) -> f32 {
        self.style.get_layout_left()
    }

    fn calculate_layout(&mut self) {
        self.style.calculate_layout()
    }

    fn get_child_count(&self) -> usize {
        0
    }

    fn get_child(&self, _: usize) -> Option<&Renderable> {
        None
    }

    fn get_node(&self) -> &yoga_wrapper::Node {
        &self.style.get_node()
    }
}

#[cfg(test)]
mod tests {
    use yoga_wrapper;

    use Text;
    use Backend;
    use Renders;
    use Renderable;

    struct Renderer {}

    impl<R: Renderable + ?Sized> Renders<R> for Renderer {
        fn render(&mut self, node: &R) {}
    }

    struct Measurer {}

    impl yoga_wrapper::Measures for Measurer {
        fn measure(&self, text: &str) -> yoga_wrapper::Size {
            yoga_wrapper::Size {
                width: text.len() as f32,
                height: 1.0,
            }
        }
    }

    struct TestBackend {
        renderer: Renderer,
        measurer: Measurer,
    }

    impl TestBackend {
        pub fn new() -> TestBackend {
            TestBackend {
                renderer: Renderer {},
                measurer: Measurer {},
            }
        }
    }

    impl<'meas> Backend<'meas> for TestBackend {
        type Color = i32;
        type Renderer = Renderer;
        type Measurer = Measurer;

        fn render(&mut self, node: &Renderable) {}

        fn get_renderer(&mut self) -> &mut Self::Renderer {
            &mut self.renderer
        }

        fn create_context<'text>(&'meas self,
                                 text: &'text str)
                                 -> yoga_wrapper::Context<'text, 'meas> {
            yoga_wrapper::Context::new(text, &self.measurer)
        }
    }

    #[test]
    fn it_works() {
        let be = TestBackend::new();
        let _ = Text::new("yo!");
    }
}
<|endoftext|>


<commit_before>//!Constants and structures from time classes
//!
//! This includes include/uapi/linux/time.h, //include/linux/time.h, and /include/linux/time64.h

///A structure that contains the number of seconds and nanoseconds since an epoch.
///
///If in doubt, assume we're talking about the UNIX epoch.
#[repr(C)]
pub struct timespec {
    ///The number of seconds contained in this timespec
    pub tv_sec: ::time_t,

    ///The number of nanoseconds contained in this timespec
    pub tv_nsec: ::c_long
}

///A structure that contains the number of seconds and microseconds since an epoch.
///
///If in doubt, assume we're talking about the UNIX epoch.
#[repr(C)]
pub struct timeval {
    ///The number of seconds contained in this timeval
    pub tv_sec: ::time_t,

    ///The number of microseconds contained in this timeval
    pub tv_usec: ::suseconds_t
}

///A structure containing information on the time-based location of a timezone
///
///Please note that this does not include the name or country code, only the minutes west of Greenwich and the type of DST correction
#[repr(C)]
pub struct timezone {
    ///The number of minutes west of Greenwich
    pub tz_minuteswest: ::c_int,

    ///The type of Daylight Savings Time correction
    pub tz_dsttime: ::c_int
}

//Names of the interval timers

///An interval timer that decrements in real time
///
///On expiration, a SIGALRM is delivered
pub const ITIMER_REAL: ::c_int = 0;

///An interval timer that decrements only when the process is executing.
///
///On expiration, a SIGVTALRM is delivered
pub const ITIMER_VIRTUAL: ::c_int = 1;

///Decrements both while the process is executing and while the system is executing on behalf of the process
///
///This is usually used to profile kernel-space and user-space concurrently.
///
///If coupled with ITIMER_VIRTUAL, you can separate the two values - What is left when ITIMER_VIRTUAL's value is removed is kernel time
pub const ITIMER_PROF: ::c_int = 2;

///An interval timer based on a `timespec`
#[repr(C)]
pub struct itimerspec {
    ///The period of time this timer should run for (Need to verify)
    pub it_interval: timespec,

    ///The amount of time left until expiration (Need to verify)
    pub it_value: timespec
}

///An interval timer based on a `timeval`
#[repr(C)]
pub struct itimerval {
    ///The period of time this timer should run for (Need to verify)
    pub it_interval: timeval,

    ///The amount of time left until expiration (Need to verify)
    pub it_value: timeval
}

///A system-wide clock that measures time from the "real world"
///
///This clock **is** affected by discontinuous jumps in system time, NTP, and user changes
pub const CLOCK_REALTIME: ::clockid_t = 0;

///A clock that measures monotonic time since an unspecified starting point
///
///Unless you manage to break your system, this unspecified point is usually when your computer powers on.
///
///This is not affected by user changes, but is by `adjtime` and NTP.
pub const CLOCK_MONOTONIC: ::clockid_t = 1;

///A high-resolution per-process timer from the processor.
pub const CLOCK_PROCESS_CPUTIME_ID: ::clockid_t = 2;

///A (high-resolution?) thread-specific timer from the processor
pub const CLOCK_THREAD_CPUTIME_ID: ::clockid_t = 3;

///A hardware-based version of `CLOCK_MONOTONIC` that is not subject to changes
pub const CLOCK_MONOTONIC_RAW: ::clockid_t = 4;

///A faster but less precise version of `CLOCK_REALTIME`, measuring time in the "real world"
pub const CLOCK_REALTIME_COARSE: ::clockid_t = 5;

///A faster but less precise version of `CLOCK_MONOTONIC`, measuring time since an unspecified starting point
pub const CLOCK_MONOTONIC_COARSE: ::clockid_t = 6;

///Identical to `CLOCK_MONOTONIC`, but includes any time that the system is suspended.
pub const CLOCK_BOOTIME: ::clockid_t = 7;

///Identical to `CLOCK_REALTIME`, but timers exposed via this will wake the system if suspended
pub const CLOCK_REALTIME_ALARM: ::clockid_t = 8;

///Identical to `CLOCK_BOOTIME`, but timers exposed via this will wake the system if suspended
pub const CLOCK_BOOTTIME_ALARM: ::clockid_t = 9;

///A clock used for SGI systems. Need to investigate
pub const CLOCK_SGI_CYCLE: ::clockid_t = 10;

///A clock that shows International Atomic Time
pub const CLOCK_TAI: ::clockid_t = 11;

///The maximum clock ID that the system is allowed to have
pub const MAX_CLOCKS: ::clockid_t = 16; //Resolves to c_int. Please let me know if this should be c_int on it's own

///A mask for supported clocks
///
///Needs to be investigated
pub const CLOCKS_MASK: ::clockid_t = CLOCK_REALTIME | CLOCK_MONOTONIC;

///A shorthand variant of CLOCK_MONOTONIC.
///
///This isn't used in the kernel. Is it left over from an old change that was reverted?
pub const CLOCKS_MONO: ::clockid_t = CLOCK_MONOTONIC;

///A flag indicating time is absolute
pub const TIMER_ABSTIME: ::c_int = 0x01;

///The type used for 64-bit time
pub type time64_t = i64;

///The number of milliseconds in a second
pub const MSEC_PER_SEC: ::c_long = 1000;

///The number of microseconds in a millisecond
pub const USEC_PER_MSEC: ::c_long = 1000;

///The number of nanoseconds in a microsecond
pub const NSEC_PER_USEC: ::c_long = 1000;

///The number of nanoseconds in a millisecond
pub const NSEC_PER_MSEC: ::c_long = 1000000;

///The number of microseconds in a second
pub const USEC_PER_SEC: ::c_long = 1000000;

///The number of nanoseconds in a second
pub const NSEC_PER_SEC: ::c_long = 1000000000;

///The number of femtoseconds in a second
pub const FSEC_PER_SEC: ::c_longlong = 1000000000000000;

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

    #[test]
    fn test_per_sec_accuracy() {
        assert_eq!(NSEC_PER_MSEC, NSEC_PER_USEC * USEC_PER_MSEC);
        assert_eq!(NSEC_PER_SEC, NSEC_PER_MSEC * MSEC_PER_SEC);
    }
}<commit_msg>Add some more constants from time.h<commit_after>//!Constants and structures from time classes
//!
//! This includes include/uapi/linux/time.h, //include/linux/time.h, and /include/linux/time64.h

///A structure that contains the number of seconds and nanoseconds since an epoch.
///
///If in doubt, assume we're talking about the UNIX epoch.
#[repr(C)]
pub struct timespec {
    ///The number of seconds contained in this timespec
    pub tv_sec: ::time_t,

    ///The number of nanoseconds contained in this timespec
    pub tv_nsec: ::c_long
}

///A structure that contains the number of seconds and microseconds since an epoch.
///
///If in doubt, assume we're talking about the UNIX epoch.
#[repr(C)]
pub struct timeval {
    ///The number of seconds contained in this timeval
    pub tv_sec: ::time_t,

    ///The number of microseconds contained in this timeval
    pub tv_usec: ::suseconds_t
}

///A structure containing information on the time-based location of a timezone
///
///Please note that this does not include the name or country code, only the minutes west of Greenwich and the type of DST correction
#[repr(C)]
pub struct timezone {
    ///The number of minutes west of Greenwich
    pub tz_minuteswest: ::c_int,

    ///The type of Daylight Savings Time correction
    pub tz_dsttime: ::c_int
}

//Names of the interval timers

///An interval timer that decrements in real time
///
///On expiration, a SIGALRM is delivered
pub const ITIMER_REAL: ::c_int = 0;

///An interval timer that decrements only when the process is executing.
///
///On expiration, a SIGVTALRM is delivered
pub const ITIMER_VIRTUAL: ::c_int = 1;

///Decrements both while the process is executing and while the system is executing on behalf of the process
///
///This is usually used to profile kernel-space and user-space concurrently.
///
///If coupled with ITIMER_VIRTUAL, you can separate the two values - What is left when ITIMER_VIRTUAL's value is removed is kernel time
pub const ITIMER_PROF: ::c_int = 2;

///An interval timer based on a `timespec`
#[repr(C)]
pub struct itimerspec {
    ///The period of time this timer should run for (Need to verify)
    pub it_interval: timespec,

    ///The amount of time left until expiration (Need to verify)
    pub it_value: timespec
}

///An interval timer based on a `timeval`
#[repr(C)]
pub struct itimerval {
    ///The period of time this timer should run for (Need to verify)
    pub it_interval: timeval,

    ///The amount of time left until expiration (Need to verify)
    pub it_value: timeval
}

///A system-wide clock that measures time from the "real world"
///
///This clock **is** affected by discontinuous jumps in system time, NTP, and user changes
pub const CLOCK_REALTIME: ::clockid_t = 0;

///A clock that measures monotonic time since an unspecified starting point
///
///Unless you manage to break your system, this unspecified point is usually when your computer powers on.
///
///This is not affected by user changes, but is by `adjtime` and NTP.
pub const CLOCK_MONOTONIC: ::clockid_t = 1;

///A high-resolution per-process timer from the processor.
pub const CLOCK_PROCESS_CPUTIME_ID: ::clockid_t = 2;

///A (high-resolution?) thread-specific timer from the processor
pub const CLOCK_THREAD_CPUTIME_ID: ::clockid_t = 3;

///A hardware-based version of `CLOCK_MONOTONIC` that is not subject to changes
pub const CLOCK_MONOTONIC_RAW: ::clockid_t = 4;

///A faster but less precise version of `CLOCK_REALTIME`, measuring time in the "real world"
pub const CLOCK_REALTIME_COARSE: ::clockid_t = 5;

///A faster but less precise version of `CLOCK_MONOTONIC`, measuring time since an unspecified starting point
pub const CLOCK_MONOTONIC_COARSE: ::clockid_t = 6;

///Identical to `CLOCK_MONOTONIC`, but includes any time that the system is suspended.
pub const CLOCK_BOOTIME: ::clockid_t = 7;

///Identical to `CLOCK_REALTIME`, but timers exposed via this will wake the system if suspended
pub const CLOCK_REALTIME_ALARM: ::clockid_t = 8;

///Identical to `CLOCK_BOOTIME`, but timers exposed via this will wake the system if suspended
pub const CLOCK_BOOTTIME_ALARM: ::clockid_t = 9;

///A clock used for SGI systems. Need to investigate
pub const CLOCK_SGI_CYCLE: ::clockid_t = 10;

///A clock that shows International Atomic Time
pub const CLOCK_TAI: ::clockid_t = 11;

///The maximum clock ID that the system is allowed to have
pub const MAX_CLOCKS: ::clockid_t = 16; //Resolves to c_int. Please let me know if this should be c_int on it's own

///A mask for supported clocks
///
///Needs to be investigated
pub const CLOCKS_MASK: ::clockid_t = CLOCK_REALTIME | CLOCK_MONOTONIC;

///A shorthand variant of CLOCK_MONOTONIC.
///
///This isn't used in the kernel. Is it left over from an old change that was reverted?
pub const CLOCKS_MONO: ::clockid_t = CLOCK_MONOTONIC;

///A flag indicating time is absolute
pub const TIMER_ABSTIME: ::c_int = 0x01;

///The type used for 64-bit time
pub type time64_t = i64;

///The number of milliseconds in a second
pub const MSEC_PER_SEC: ::c_long = 1000;

///The number of microseconds in a millisecond
pub const USEC_PER_MSEC: ::c_long = 1000;

///The number of nanoseconds in a microsecond
pub const NSEC_PER_USEC: ::c_long = 1000;

///The number of nanoseconds in a millisecond
pub const NSEC_PER_MSEC: ::c_long = 1000000;

///The number of microseconds in a second
pub const USEC_PER_SEC: ::c_long = 1000000;

///The number of nanoseconds in a second
pub const NSEC_PER_SEC: ::c_long = 1000000000;

///The number of femtoseconds in a second
pub const FSEC_PER_SEC: ::c_longlong = 1000000000000000;

///The maximim value of a time64_t
pub const TIME64_MAX: ::c_longlong = ((1u64 << 63) as i64);

///The maximum value of a ktime_t
pub const KTIME_MAX: ::c_longlong = ((1u64 << 63) as i64);

///The maximum number of seconds in a ktime_t
pub const KTIME_SEC_MAX: ::c_longlong = KTIME_MAX / NSEC_PER_SEC;

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

    #[test]
    fn test_per_sec_accuracy() {
        assert_eq!(NSEC_PER_MSEC, NSEC_PER_USEC * USEC_PER_MSEC);
        assert_eq!(NSEC_PER_SEC, NSEC_PER_MSEC * MSEC_PER_SEC);
    }
}<|endoftext|>