<commit_before>// Copyright (c) 2016 The vulkano developers
// 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. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.

use std::mem;
use std::ptr;
use std::sync::Arc;
use smallvec::SmallVec;

use device::Device;
use memory::DeviceMemory;
use memory::MemoryRequirements;
use sync::Sharing;

use check_errors;
use OomError;
use VulkanObject;
use VulkanPointers;
use vk;

/// Data storage in a GPU-accessible location.
///
/// # Safety
///
///
#[derive(Debug)]
pub struct UnsafeBuffer {
    buffer: vk::Buffer,
    device: Arc<Device>,
    size: usize,
    usage: vk::BufferUsageFlags,
}

impl UnsafeBuffer {
    /// Creates a new buffer of the given size.
    ///
    /// See the module's documentation for information about safety.
    pub unsafe fn new<'a, I>(device: &Arc<Device>, size: usize, usage: &Usage, sharing: Sharing<I>)
                             -> Result<(UnsafeBuffer, MemoryRequirements), OomError>
        where I: Iterator<Item = u32>
    {
        let vk = device.pointers();

        let usage = usage.to_usage_bits();

        let buffer = {
            let (sh_mode, sh_indices) = match sharing {
                Sharing::Exclusive => (vk::SHARING_MODE_EXCLUSIVE, SmallVec::<[u32; 8]>::new()),
                Sharing::Concurrent(ids) => (vk::SHARING_MODE_CONCURRENT, ids.collect()),
            };

            let infos = vk::BufferCreateInfo {
                sType: vk::STRUCTURE_TYPE_BUFFER_CREATE_INFO,
                pNext: ptr::null(),
                flags: 0,       // TODO: sparse resources binding
                size: size as u64,
                usage: usage,
                sharingMode: sh_mode,
                queueFamilyIndexCount: sh_indices.len() as u32,
                pQueueFamilyIndices: sh_indices.as_ptr(),
            };

            let mut output = mem::uninitialized();
            try!(check_errors(vk.CreateBuffer(device.internal_object(), &infos,
                                              ptr::null(), &mut output)));
            output
        };

        let mem_reqs: vk::MemoryRequirements = {
            let mut output = mem::uninitialized();
            vk.GetBufferMemoryRequirements(device.internal_object(), buffer, &mut output);
            debug_assert!(output.size >= size as u64);
            debug_assert!(output.memoryTypeBits != 0);
            output
        };

        let obj = UnsafeBuffer {
            buffer: buffer,
            device: device.clone(),
            size: size as usize,
            usage: usage,
        };

        Ok((obj, mem_reqs.into()))
    }

    pub unsafe fn bind_memory(&self, memory: &DeviceMemory, offset: usize)
                              -> Result<(), OomError>
    {
        let vk = self.device.pointers();

        // We check for correctness in debug mode.
        debug_assert!({
            let mut mem_reqs = mem::uninitialized();
            vk.GetBufferMemoryRequirements(self.device.internal_object(), self.buffer,
                                           &mut mem_reqs);
            mem_reqs.size <= (memory.size() - offset) as u64 &&
            (offset as u64 % mem_reqs.alignment) == 0 &&
            mem_reqs.memoryTypeBits & (1 << memory.memory_type().id()) != 0
        });

        try!(check_errors(vk.BindBufferMemory(self.device.internal_object(), self.buffer,
                                              memory.internal_object(), offset as vk::DeviceSize)));
        Ok(())
    }

    /// Returns the device used to create this buffer.
    #[inline]
    pub fn device(&self) -> &Arc<Device> {
        &self.device
    }

    /// Returns the size of the buffer in bytes.
    #[inline]
    pub fn size(&self) -> usize {
        self.size
    }

    #[inline]
    pub fn usage_transfer_src(&self) -> bool {
        (self.usage & vk::BUFFER_USAGE_TRANSFER_SRC_BIT) != 0
    }

    #[inline]
    pub fn usage_transfer_dest(&self) -> bool {
        (self.usage & vk::BUFFER_USAGE_TRANSFER_DST_BIT) != 0
    }

    #[inline]
    pub fn usage_uniform_texel_buffer(&self) -> bool {
        (self.usage & vk::BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT) != 0
    }

    #[inline]
    pub fn usage_storage_texel_buffer(&self) -> bool {
        (self.usage & vk::BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT) != 0
    }

    #[inline]
    pub fn usage_uniform_buffer(&self) -> bool {
        (self.usage & vk::BUFFER_USAGE_UNIFORM_BUFFER_BIT) != 0
    }

    #[inline]
    pub fn usage_storage_buffer(&self) -> bool {
        (self.usage & vk::BUFFER_USAGE_STORAGE_BUFFER_BIT) != 0
    }

    #[inline]
    pub fn usage_index_buffer(&self) -> bool {
        (self.usage & vk::BUFFER_USAGE_INDEX_BUFFER_BIT) != 0
    }

    #[inline]
    pub fn usage_vertex_buffer(&self) -> bool {
        (self.usage & vk::BUFFER_USAGE_VERTEX_BUFFER_BIT) != 0
    }

    #[inline]
    pub fn usage_indirect_buffer(&self) -> bool {
        (self.usage & vk::BUFFER_USAGE_INDIRECT_BUFFER_BIT) != 0
    }
}

unsafe impl VulkanObject for UnsafeBuffer {
    type Object = vk::Buffer;

    #[inline]
    fn internal_object(&self) -> vk::Buffer {
        self.buffer
    }
}

impl Drop for UnsafeBuffer {
    #[inline]
    fn drop(&mut self) {
        unsafe {
            let vk = self.device.pointers();
            vk.DestroyBuffer(self.device.internal_object(), self.buffer, ptr::null());
        }
    }
}

/// Describes how a buffer is going to be used. This is **not** an optimization.
///
/// If you try to use a buffer in a way that you didn't declare, a panic will happen.
///
/// Some methods are provided to build `Usage` structs for some common situations. However
/// there is no restriction in the combination of usages that can be enabled.
#[derive(Debug, Copy, Clone)]
pub struct Usage {
    pub transfer_source: bool,
    pub transfer_dest: bool,
    pub uniform_texel_buffer: bool,
    pub storage_texel_buffer: bool,
    pub uniform_buffer: bool,
    pub storage_buffer: bool,
    pub index_buffer: bool,
    pub vertex_buffer: bool,
    pub indirect_buffer: bool,
}

impl Usage {
    /// Builds a `Usage` with all values set to false.
    #[inline]
    pub fn none() -> Usage {
        Usage {
            transfer_source: false,
            transfer_dest: false,
            uniform_texel_buffer: false,
            storage_texel_buffer: false,
            uniform_buffer: false,
            storage_buffer: false,
            index_buffer: false,
            vertex_buffer: false,
            indirect_buffer: false,
        }
    }

    /// Builds a `Usage` with all values set to true. Can be used for quick prototyping.
    #[inline]
    pub fn all() -> Usage {
        Usage {
            transfer_source: true,
            transfer_dest: true,
            uniform_texel_buffer: true,
            storage_texel_buffer: true,
            uniform_buffer: true,
            storage_buffer: true,
            index_buffer: true,
            vertex_buffer: true,
            indirect_buffer: true,
        }
    }

    /// Builds a `Usage` with `transfer_source` set to true and the rest to false.
    #[inline]
    pub fn transfer_source() -> Usage {
        Usage {
            transfer_source: true,
            .. Usage::none()
        }
    }

    /// Builds a `Usage` with `vertex_buffer` set to true and the rest to false.
    #[inline]
    pub fn vertex_buffer() -> Usage {
        Usage {
            vertex_buffer: true,
            .. Usage::none()
        }
    }

    /// Builds a `Usage` with `vertex_buffer` and `transfer_dest` set to true and the rest to false.
    #[inline]
    pub fn vertex_buffer_transfer_dest() -> Usage {
        Usage {
            vertex_buffer: true,
            transfer_dest: true,
            .. Usage::none()
        }
    }

    /// Builds a `Usage` with `index_buffer` set to true and the rest to false.
    #[inline]
    pub fn index_buffer() -> Usage {
        Usage {
            index_buffer: true,
            .. Usage::none()
        }
    }

    /// Builds a `Usage` with `index_buffer` and `transfer_dest` set to true and the rest to false.
    #[inline]
    pub fn index_buffer_transfer_dest() -> Usage {
        Usage {
            index_buffer: true,
            transfer_dest: true,
            .. Usage::none()
        }
    }

    /// Builds a `Usage` with `uniform_buffer` set to true and the rest to false.
    #[inline]
    pub fn uniform_buffer() -> Usage {
        Usage {
            uniform_buffer: true,
            .. Usage::none()
        }
    }

    /// Builds a `Usage` with `uniform_buffer` and `transfer_dest` set to true and the rest
    /// to false.
    #[inline]
    pub fn uniform_buffer_transfer_dest() -> Usage {
        Usage {
            uniform_buffer: true,
            transfer_dest: true,
            .. Usage::none()
        }
    }

    #[inline]
    #[doc(hidden)]
    // TODO: shouldn't be public (it's just temporarily public)
    pub fn to_usage_bits(&self) -> vk::BufferUsageFlagBits {
        let mut result = 0;
        if self.transfer_source { result |= vk::BUFFER_USAGE_TRANSFER_SRC_BIT; }
        if self.transfer_dest { result |= vk::BUFFER_USAGE_TRANSFER_DST_BIT; }
        if self.uniform_texel_buffer { result |= vk::BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT; }
        if self.storage_texel_buffer { result |= vk::BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT; }
        if self.uniform_buffer { result |= vk::BUFFER_USAGE_UNIFORM_BUFFER_BIT; }
        if self.storage_buffer { result |= vk::BUFFER_USAGE_STORAGE_BUFFER_BIT; }
        if self.index_buffer { result |= vk::BUFFER_USAGE_INDEX_BUFFER_BIT; }
        if self.vertex_buffer { result |= vk::BUFFER_USAGE_VERTEX_BUFFER_BIT; }
        if self.indirect_buffer { result |= vk::BUFFER_USAGE_INDIRECT_BUFFER_BIT; }
        result
    }
}
<commit_msg>Add test in buffer/sys<commit_after>// Copyright (c) 2016 The vulkano developers
// 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. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.

use std::mem;
use std::ptr;
use std::sync::Arc;
use smallvec::SmallVec;

use device::Device;
use memory::DeviceMemory;
use memory::MemoryRequirements;
use sync::Sharing;

use check_errors;
use OomError;
use VulkanObject;
use VulkanPointers;
use vk;

/// Data storage in a GPU-accessible location.
///
/// # Safety
///
///
#[derive(Debug)]
pub struct UnsafeBuffer {
    buffer: vk::Buffer,
    device: Arc<Device>,
    size: usize,
    usage: vk::BufferUsageFlags,
}

impl UnsafeBuffer {
    /// Creates a new buffer of the given size.
    ///
    /// See the module's documentation for information about safety.
    pub unsafe fn new<'a, I>(device: &Arc<Device>, size: usize, usage: &Usage, sharing: Sharing<I>)
                             -> Result<(UnsafeBuffer, MemoryRequirements), OomError>
        where I: Iterator<Item = u32>
    {
        let vk = device.pointers();

        let usage = usage.to_usage_bits();

        let buffer = {
            let (sh_mode, sh_indices) = match sharing {
                Sharing::Exclusive => (vk::SHARING_MODE_EXCLUSIVE, SmallVec::<[u32; 8]>::new()),
                Sharing::Concurrent(ids) => (vk::SHARING_MODE_CONCURRENT, ids.collect()),
            };

            let infos = vk::BufferCreateInfo {
                sType: vk::STRUCTURE_TYPE_BUFFER_CREATE_INFO,
                pNext: ptr::null(),
                flags: 0,       // TODO: sparse resources binding
                size: size as u64,
                usage: usage,
                sharingMode: sh_mode,
                queueFamilyIndexCount: sh_indices.len() as u32,
                pQueueFamilyIndices: sh_indices.as_ptr(),
            };

            let mut output = mem::uninitialized();
            try!(check_errors(vk.CreateBuffer(device.internal_object(), &infos,
                                              ptr::null(), &mut output)));
            output
        };

        let mem_reqs: vk::MemoryRequirements = {
            let mut output = mem::uninitialized();
            vk.GetBufferMemoryRequirements(device.internal_object(), buffer, &mut output);
            debug_assert!(output.size >= size as u64);
            debug_assert!(output.memoryTypeBits != 0);
            output
        };

        let obj = UnsafeBuffer {
            buffer: buffer,
            device: device.clone(),
            size: size as usize,
            usage: usage,
        };

        Ok((obj, mem_reqs.into()))
    }

    pub unsafe fn bind_memory(&self, memory: &DeviceMemory, offset: usize)
                              -> Result<(), OomError>
    {
        let vk = self.device.pointers();

        // We check for correctness in debug mode.
        debug_assert!({
            let mut mem_reqs = mem::uninitialized();
            vk.GetBufferMemoryRequirements(self.device.internal_object(), self.buffer,
                                           &mut mem_reqs);
            mem_reqs.size <= (memory.size() - offset) as u64 &&
            (offset as u64 % mem_reqs.alignment) == 0 &&
            mem_reqs.memoryTypeBits & (1 << memory.memory_type().id()) != 0
        });

        try!(check_errors(vk.BindBufferMemory(self.device.internal_object(), self.buffer,
                                              memory.internal_object(), offset as vk::DeviceSize)));
        Ok(())
    }

    /// Returns the device used to create this buffer.
    #[inline]
    pub fn device(&self) -> &Arc<Device> {
        &self.device
    }

    /// Returns the size of the buffer in bytes.
    #[inline]
    pub fn size(&self) -> usize {
        self.size
    }

    #[inline]
    pub fn usage_transfer_src(&self) -> bool {
        (self.usage & vk::BUFFER_USAGE_TRANSFER_SRC_BIT) != 0
    }

    #[inline]
    pub fn usage_transfer_dest(&self) -> bool {
        (self.usage & vk::BUFFER_USAGE_TRANSFER_DST_BIT) != 0
    }

    #[inline]
    pub fn usage_uniform_texel_buffer(&self) -> bool {
        (self.usage & vk::BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT) != 0
    }

    #[inline]
    pub fn usage_storage_texel_buffer(&self) -> bool {
        (self.usage & vk::BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT) != 0
    }

    #[inline]
    pub fn usage_uniform_buffer(&self) -> bool {
        (self.usage & vk::BUFFER_USAGE_UNIFORM_BUFFER_BIT) != 0
    }

    #[inline]
    pub fn usage_storage_buffer(&self) -> bool {
        (self.usage & vk::BUFFER_USAGE_STORAGE_BUFFER_BIT) != 0
    }

    #[inline]
    pub fn usage_index_buffer(&self) -> bool {
        (self.usage & vk::BUFFER_USAGE_INDEX_BUFFER_BIT) != 0
    }

    #[inline]
    pub fn usage_vertex_buffer(&self) -> bool {
        (self.usage & vk::BUFFER_USAGE_VERTEX_BUFFER_BIT) != 0
    }

    #[inline]
    pub fn usage_indirect_buffer(&self) -> bool {
        (self.usage & vk::BUFFER_USAGE_INDIRECT_BUFFER_BIT) != 0
    }
}

unsafe impl VulkanObject for UnsafeBuffer {
    type Object = vk::Buffer;

    #[inline]
    fn internal_object(&self) -> vk::Buffer {
        self.buffer
    }
}

impl Drop for UnsafeBuffer {
    #[inline]
    fn drop(&mut self) {
        unsafe {
            let vk = self.device.pointers();
            vk.DestroyBuffer(self.device.internal_object(), self.buffer, ptr::null());
        }
    }
}

/// Describes how a buffer is going to be used. This is **not** an optimization.
///
/// If you try to use a buffer in a way that you didn't declare, a panic will happen.
///
/// Some methods are provided to build `Usage` structs for some common situations. However
/// there is no restriction in the combination of usages that can be enabled.
#[derive(Debug, Copy, Clone)]
pub struct Usage {
    pub transfer_source: bool,
    pub transfer_dest: bool,
    pub uniform_texel_buffer: bool,
    pub storage_texel_buffer: bool,
    pub uniform_buffer: bool,
    pub storage_buffer: bool,
    pub index_buffer: bool,
    pub vertex_buffer: bool,
    pub indirect_buffer: bool,
}

impl Usage {
    /// Builds a `Usage` with all values set to false.
    #[inline]
    pub fn none() -> Usage {
        Usage {
            transfer_source: false,
            transfer_dest: false,
            uniform_texel_buffer: false,
            storage_texel_buffer: false,
            uniform_buffer: false,
            storage_buffer: false,
            index_buffer: false,
            vertex_buffer: false,
            indirect_buffer: false,
        }
    }

    /// Builds a `Usage` with all values set to true. Can be used for quick prototyping.
    #[inline]
    pub fn all() -> Usage {
        Usage {
            transfer_source: true,
            transfer_dest: true,
            uniform_texel_buffer: true,
            storage_texel_buffer: true,
            uniform_buffer: true,
            storage_buffer: true,
            index_buffer: true,
            vertex_buffer: true,
            indirect_buffer: true,
        }
    }

    /// Builds a `Usage` with `transfer_source` set to true and the rest to false.
    #[inline]
    pub fn transfer_source() -> Usage {
        Usage {
            transfer_source: true,
            .. Usage::none()
        }
    }

    /// Builds a `Usage` with `vertex_buffer` set to true and the rest to false.
    #[inline]
    pub fn vertex_buffer() -> Usage {
        Usage {
            vertex_buffer: true,
            .. Usage::none()
        }
    }

    /// Builds a `Usage` with `vertex_buffer` and `transfer_dest` set to true and the rest to false.
    #[inline]
    pub fn vertex_buffer_transfer_dest() -> Usage {
        Usage {
            vertex_buffer: true,
            transfer_dest: true,
            .. Usage::none()
        }
    }

    /// Builds a `Usage` with `index_buffer` set to true and the rest to false.
    #[inline]
    pub fn index_buffer() -> Usage {
        Usage {
            index_buffer: true,
            .. Usage::none()
        }
    }

    /// Builds a `Usage` with `index_buffer` and `transfer_dest` set to true and the rest to false.
    #[inline]
    pub fn index_buffer_transfer_dest() -> Usage {
        Usage {
            index_buffer: true,
            transfer_dest: true,
            .. Usage::none()
        }
    }

    /// Builds a `Usage` with `uniform_buffer` set to true and the rest to false.
    #[inline]
    pub fn uniform_buffer() -> Usage {
        Usage {
            uniform_buffer: true,
            .. Usage::none()
        }
    }

    /// Builds a `Usage` with `uniform_buffer` and `transfer_dest` set to true and the rest
    /// to false.
    #[inline]
    pub fn uniform_buffer_transfer_dest() -> Usage {
        Usage {
            uniform_buffer: true,
            transfer_dest: true,
            .. Usage::none()
        }
    }

    #[inline]
    #[doc(hidden)]
    // TODO: shouldn't be public (it's just temporarily public)
    pub fn to_usage_bits(&self) -> vk::BufferUsageFlagBits {
        let mut result = 0;
        if self.transfer_source { result |= vk::BUFFER_USAGE_TRANSFER_SRC_BIT; }
        if self.transfer_dest { result |= vk::BUFFER_USAGE_TRANSFER_DST_BIT; }
        if self.uniform_texel_buffer { result |= vk::BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT; }
        if self.storage_texel_buffer { result |= vk::BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT; }
        if self.uniform_buffer { result |= vk::BUFFER_USAGE_UNIFORM_BUFFER_BIT; }
        if self.storage_buffer { result |= vk::BUFFER_USAGE_STORAGE_BUFFER_BIT; }
        if self.index_buffer { result |= vk::BUFFER_USAGE_INDEX_BUFFER_BIT; }
        if self.vertex_buffer { result |= vk::BUFFER_USAGE_VERTEX_BUFFER_BIT; }
        if self.indirect_buffer { result |= vk::BUFFER_USAGE_INDIRECT_BUFFER_BIT; }
        result
    }
}

#[cfg(test)]
mod tests {
    use std::iter::Empty;

    use super::UnsafeBuffer;
    use super::Usage;

    use device::Device;
    use sync::Sharing;

    #[test]
    fn create() {
        let (device, _) = gfx_dev_and_queue!();
        let (buf, reqs) = unsafe {
            UnsafeBuffer::new(&device, 128, &Usage::all(), Sharing::Exclusive::<Empty<_>>)
        }.unwrap();

        assert!(reqs.size >= 128);
        assert_eq!(buf.size(), 128);
        assert_eq!(&**buf.device() as *const Device, &*device as *const Device);
    }
}
<|endoftext|>


<commit_before>use nom::*;
use std::str;

#[derive(Debug, PartialEq)]
pub struct Paragraph<'a> {
    parts: Vec<Text<'a>>,
}

#[derive(Debug, PartialEq)]
enum Text<'a> {
    Plain(&'a str),
    Bold(Paragraph<'a>),
    Italics(Paragraph<'a>),
}

impl<'a> Paragraph<'a> {
    fn new(parts: Vec<Text>) -> Paragraph {
        Paragraph {parts: parts}
    }
    pub fn to_html(&self) -> String {
        self.parts.iter()
            .map(|text| match *text {
                Text::Plain(s)       => s.to_string(),
                Text::Bold(ref p)    => ["", &p.to_html(), ""].concat(),
                Text::Italics(ref p) => ["", &p.to_html(), ""].concat(),
            })
            .collect::<Vec<_>>()
            .concat()
    }
}

named!(pub parse_paragraph<Paragraph>,
    map!(
        many1!(alt!(parse_bold | parse_italics | parse_plain)),
        Paragraph::new
    )
);

named!(parse_only_paragraph<Paragraph>, complete!(parse_paragraph));

named!(parse_plain<Text>,
    map!(
        map_res!(is_not!("_*"), str::from_utf8),
        Text::Plain
    )
);

named!(parse_bold<Text>,
    map_res!(
        delimited!(char!('*'), is_not!("*"), char!('*')),
        |bytes| {
            match parse_only_paragraph(bytes) {
                IResult::Done(_, output) => Ok(Text::Bold(output)),
                IResult::Error(err) => Err(err),
                _ => panic!("Nom complete! macro returned an IResult::Incomplete")
            }
        }
    )
);

named!(parse_italics<Text>,
    map_res!(
        delimited!(char!('_'), is_not!("_"), char!('_')),
        |bytes| {
            match parse_only_paragraph(bytes) {
                IResult::Done(_, output) => Ok(Text::Italics(output)),
                IResult::Error(err) => Err(err),
                _ => panic!("Nom complete! macro returned an IResult::Incomplete")
            }
        }
    )
);

#[test]
fn test_plain_parse() {
    if let IResult::Done(b"*World*", output) = parse_plain(b"Hello *World*") {
        assert_eq!(output, Text::Plain("Hello "));
    } else {
        panic!(r#" Plain parse failed with "Hello *World*" "#);
    }

    match parse_plain(b"*Hello World*") {
        IResult::Error(_) => (),
        _ => panic!(r#" Plain failed with "*Hello World*" "#),
    }
}

#[test]
fn test_bold_parse() {
    if let IResult::Done(b" World", output) = parse_bold(b"*Hello* World") {
        assert_eq!(output, Text::Bold(Paragraph::new(
            vec![Text::Plain("Hello")]
        )));
    } else {
        panic!(r#" Bold failed with "*Hello* World" "#);
    }

    match parse_bold(b"Hello World") {
        IResult::Error(_) => (),
        _ => panic!(r#" Bold failed with "Hello World" "#),
    };

    match parse_bold(b"*Hello World") {
        IResult::Incomplete(_) => (),
        _ => panic!(r#" Bold failed with "*Hello World" "#),
    }
}

#[test]
fn test_paragraph_parse() {
    let data = b"This *is _a_ serious* _test *of* this_ parser";
    if let IResult::Done(remaining, output) = parse_paragraph(data) {
        assert_eq!(remaining, b"");
        println!("{:#?}", output.parts);
        assert_eq!(output.parts, vec![
            Text::Plain("This "),
            Text::Bold(Paragraph::new(vec![
                Text::Plain("is "),
                Text::Italics(Paragraph::new(vec![Text::Plain("a")])),
                Text::Plain(" serious"),
            ])),
            Text::Plain(" "),
            Text::Italics(Paragraph::new(vec![
                Text::Plain("test "),
                Text::Bold(Paragraph::new(vec![Text::Plain("of")])),
                Text::Plain(" this"),
            ])),
            Text::Plain(" parser")
        ]);
    }
}

#[test]
fn test_html1() {
    let p = Paragraph::new(vec![
        Text::Plain("plaintext "),
        Text::Bold(Paragraph::new(vec![Text::Plain("bold text")]))
    ]);

    assert!(p.to_html() == "plaintext bold text".to_owned());
}

#[test]
fn test_integration() {
    let data = b"This *is _a_ serious* _test *of* this_ parser";
    if let IResult::Done(_, p) = parse_paragraph(data) {
        assert_eq!(p.to_html(),
            "This is a serious test of this parser"
        );
    } else {
        panic!("Parse failed");
    }
}
<commit_msg>Fix compilation on stable and beta<commit_after>use nom::*;
use std::str;

#[derive(Debug, PartialEq)]
pub struct Paragraph<'a> {
    parts: Vec<Text<'a>>,
}

#[derive(Debug, PartialEq)]
enum Text<'a> {
    Plain(&'a str),
    Bold(Paragraph<'a>),
    Italics(Paragraph<'a>),
}

impl<'a> Paragraph<'a> {
    fn new(parts: Vec<Text>) -> Paragraph {
        Paragraph {parts: parts}
    }
    pub fn to_html(&self) -> String {
        self.parts.iter()
            .map(|text| match *text {
                Text::Plain(s)       => s.to_string(),
                Text::Bold(ref p)    => ["", &p.to_html()[..], ""].concat(),
                Text::Italics(ref p) => ["", &p.to_html()[..], ""].concat(),
            })
            .collect::<Vec<_>>()
            .concat()
    }
}

named!(pub parse_paragraph<Paragraph>,
    map!(
        many1!(alt!(parse_bold | parse_italics | parse_plain)),
        Paragraph::new
    )
);

named!(parse_only_paragraph<Paragraph>, complete!(parse_paragraph));

named!(parse_plain<Text>,
    map!(
        map_res!(is_not!("_*"), str::from_utf8),
        Text::Plain
    )
);

named!(parse_bold<Text>,
    map_res!(
        delimited!(char!('*'), is_not!("*"), char!('*')),
        |bytes| {
            match parse_only_paragraph(bytes) {
                IResult::Done(_, output) => Ok(Text::Bold(output)),
                IResult::Error(err) => Err(err),
                _ => panic!("Nom complete! macro returned an IResult::Incomplete")
            }
        }
    )
);

named!(parse_italics<Text>,
    map_res!(
        delimited!(char!('_'), is_not!("_"), char!('_')),
        |bytes| {
            match parse_only_paragraph(bytes) {
                IResult::Done(_, output) => Ok(Text::Italics(output)),
                IResult::Error(err) => Err(err),
                _ => panic!("Nom complete! macro returned an IResult::Incomplete")
            }
        }
    )
);

#[test]
fn test_plain_parse() {
    if let IResult::Done(b"*World*", output) = parse_plain(b"Hello *World*") {
        assert_eq!(output, Text::Plain("Hello "));
    } else {
        panic!(r#" Plain parse failed with "Hello *World*" "#);
    }

    match parse_plain(b"*Hello World*") {
        IResult::Error(_) => (),
        _ => panic!(r#" Plain failed with "*Hello World*" "#),
    }
}

#[test]
fn test_bold_parse() {
    if let IResult::Done(b" World", output) = parse_bold(b"*Hello* World") {
        assert_eq!(output, Text::Bold(Paragraph::new(
            vec![Text::Plain("Hello")]
        )));
    } else {
        panic!(r#" Bold failed with "*Hello* World" "#);
    }

    match parse_bold(b"Hello World") {
        IResult::Error(_) => (),
        _ => panic!(r#" Bold failed with "Hello World" "#),
    };

    match parse_bold(b"*Hello World") {
        IResult::Incomplete(_) => (),
        _ => panic!(r#" Bold failed with "*Hello World" "#),
    }
}

#[test]
fn test_paragraph_parse() {
    let data = b"This *is _a_ serious* _test *of* this_ parser";
    if let IResult::Done(remaining, output) = parse_paragraph(data) {
        assert_eq!(remaining, b"");
        println!("{:#?}", output.parts);
        assert_eq!(output.parts, vec![
            Text::Plain("This "),
            Text::Bold(Paragraph::new(vec![
                Text::Plain("is "),
                Text::Italics(Paragraph::new(vec![Text::Plain("a")])),
                Text::Plain(" serious"),
            ])),
            Text::Plain(" "),
            Text::Italics(Paragraph::new(vec![
                Text::Plain("test "),
                Text::Bold(Paragraph::new(vec![Text::Plain("of")])),
                Text::Plain(" this"),
            ])),
            Text::Plain(" parser")
        ]);
    }
}

#[test]
fn test_html1() {
    let p = Paragraph::new(vec![
        Text::Plain("plaintext "),
        Text::Bold(Paragraph::new(vec![Text::Plain("bold text")]))
    ]);

    assert!(p.to_html() == "plaintext bold text".to_owned());
}

#[test]
fn test_integration() {
    let data = b"This *is _a_ serious* _test *of* this_ parser";
    if let IResult::Done(_, p) = parse_paragraph(data) {
        assert_eq!(p.to_html(),
            "This is a serious test of this parser"
        );
    } else {
        panic!("Parse failed");
    }
}
<|endoftext|>


<commit_before>use {Color, ColorSpace, Mix, Shade, GetHue, Hue, Rgb, Luma, Xyz, Lab, Hsv, Hsl, Saturate, LabHue, clamp};

///CIE L*C*h°, a polar version of [CIE L*a*b*](struct.Lab.html), with an alpha
///component.
///
///L*C*h° shares its range and perceptual uniformity with L*a*b*, but it's a
///cylindrical color space, like [HSL](struct.Hsl.html) and
///[HSV](struct.Hsv.html). This gives it the same ability to directly change
///the hue and colorfulness of a color, while preserving other visual aspects.
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct Lch {
    ///L* is the lightness of the color. 0.0 gives absolute black and 1.0
    ///give the brightest white.
    pub l: f32,

    ///C* is the colorfulness of the color. It's similar to saturation. 0.0
    ///gives gray scale colors, and numbers around 1.0-1.41421356 gives fully
    ///saturated colors. The upper limit of 1.41421356 (or `sqrt(2.0)`) should
    ///include the whole L*a*b* space and some more.
    pub chroma: f32,

    ///The hue of the color, in degrees. Decides if it's red, blue, purple,
    ///etc.
    pub hue: LabHue,

    ///The transparency of the color. 0.0 is completely transparent and 1.0 is
    ///completely opaque.
    pub alpha: f32,
}

impl Lch {
    ///CIE L*C*h°.
    pub fn lch(l: f32, chroma: f32, hue: LabHue) -> Lch {
        Lch {
            l: l,
            chroma: chroma,
            hue: hue,
            alpha: 1.0
        }
    }

    ///CIE L*C*h° and transparency.
    pub fn lcha(l: f32, chroma: f32, hue: LabHue, alpha: f32) -> Lch {
        Lch {
            l: l,
            chroma: chroma,
            hue: hue,
            alpha: alpha
        }
    }
}

impl ColorSpace for Lch {
    fn is_valid(&self) -> bool {
        self.l >= 0.0 && self.l <= 1.0 &&
        self.chroma >= 0.0 && self.chroma <= 1.41421356 && //should include all of L*a*b*, but will also overshoot...
        self.alpha >= 0.0 && self.alpha <= 1.0
    }

    fn clamp(&self) -> Lch {
        let mut c = *self;
        c.clamp_self();
        c
    }

    fn clamp_self(&mut self) {
        self.l = clamp(self.l, 0.0, 1.0);
        self.chroma = clamp(self.chroma, 0.0, 1.41421356); //should include all of L*a*b*, but will also overshoot...
        self.alpha = clamp(self.alpha, 0.0, 1.0);
    }
}

impl Mix for Lch {
    fn mix(&self, other: &Lch, factor: f32) -> Lch {
        let factor = clamp(factor, 0.0, 1.0);
        let hue_diff: f32 = (other.hue - self.hue).into();
        Lch {
            l: self.l + factor * (other.l - self.l),
            chroma: self.chroma + factor * (other.chroma - self.chroma),
            hue: self.hue + factor * hue_diff,
            alpha: self.alpha + factor * (other.alpha - self.alpha),
        }
    }
}

impl Shade for Lch {
    fn lighten(&self, amount: f32) -> Lch {
        Lch {
            l: self.l + amount,
            chroma: self.chroma,
            hue: self.hue,
            alpha: self.alpha,
        }
    }
}

impl GetHue for Lch {
    type Hue = LabHue;

    fn get_hue(&self) -> Option<LabHue> {
        if self.chroma <= 0.0 {
            None
        } else {
            Some(self.hue)
        }
    }
}

impl Hue for Lch {
    fn with_hue(&self, hue: LabHue) -> Lch {
        Lch {
            l: self.l,
            chroma: self.chroma,
            hue: hue,
            alpha: self.alpha,
        }
    }

    fn shift_hue(&self, amount: LabHue) -> Lch {
        Lch {
            l: self.l,
            chroma: self.chroma,
            hue: self.hue + amount,
            alpha: self.alpha,
        }
    }
}

impl Saturate for Lch {
    fn saturate(&self, factor: f32) -> Lch {
        Lch {
            l: self.l,
            chroma: self.chroma * (1.0 + factor),
            hue: self.hue,
            alpha: self.alpha,
        }
    }
}

impl Default for Lch {
    fn default() -> Lch {
        Lch::lch(0.0, 0.0, 0.0.into())
    }
}

from_color!(to Lch from Rgb, Luma, Xyz, Lab, Hsv, Hsl);

impl From<Lab> for Lch {
    fn from(lab: Lab) -> Lch {
        Lch {
            l: lab.l,
            chroma: (lab.a * lab.a + lab.b * lab.b).sqrt(),
            hue: lab.get_hue().unwrap_or(0.0.into()),
            alpha: lab.alpha,
        }
    }
}

impl From<Rgb> for Lch {
    fn from(rgb: Rgb) -> Lch {
        Lab::from(rgb).into()
    }
}

impl From<Luma> for Lch {
    fn from(luma: Luma) -> Lch {
        Lab::from(luma).into()
    }
}

impl From<Xyz> for Lch {
    fn from(xyz: Xyz) -> Lch {
        Lab::from(xyz).into()
    }
}

impl From<Hsv> for Lch {
    fn from(hsv: Hsv) -> Lch {
        Lab::from(hsv).into()
    }
}

impl From<Hsl> for Lch {
    fn from(hsl: Hsl) -> Lch {
        Lab::from(hsl).into()
    }
}
<commit_msg>Implement Add and Sub for Lch<commit_after>use std::ops::{Add, Sub};

use {Color, ColorSpace, Mix, Shade, GetHue, Hue, Rgb, Luma, Xyz, Lab, Hsv, Hsl, Saturate, LabHue, clamp};

///CIE L*C*h°, a polar version of [CIE L*a*b*](struct.Lab.html), with an alpha
///component.
///
///L*C*h° shares its range and perceptual uniformity with L*a*b*, but it's a
///cylindrical color space, like [HSL](struct.Hsl.html) and
///[HSV](struct.Hsv.html). This gives it the same ability to directly change
///the hue and colorfulness of a color, while preserving other visual aspects.
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct Lch {
    ///L* is the lightness of the color. 0.0 gives absolute black and 1.0
    ///give the brightest white.
    pub l: f32,

    ///C* is the colorfulness of the color. It's similar to saturation. 0.0
    ///gives gray scale colors, and numbers around 1.0-1.41421356 gives fully
    ///saturated colors. The upper limit of 1.41421356 (or `sqrt(2.0)`) should
    ///include the whole L*a*b* space and some more.
    pub chroma: f32,

    ///The hue of the color, in degrees. Decides if it's red, blue, purple,
    ///etc.
    pub hue: LabHue,

    ///The transparency of the color. 0.0 is completely transparent and 1.0 is
    ///completely opaque.
    pub alpha: f32,
}

impl Lch {
    ///CIE L*C*h°.
    pub fn lch(l: f32, chroma: f32, hue: LabHue) -> Lch {
        Lch {
            l: l,
            chroma: chroma,
            hue: hue,
            alpha: 1.0
        }
    }

    ///CIE L*C*h° and transparency.
    pub fn lcha(l: f32, chroma: f32, hue: LabHue, alpha: f32) -> Lch {
        Lch {
            l: l,
            chroma: chroma,
            hue: hue,
            alpha: alpha
        }
    }
}

impl ColorSpace for Lch {
    fn is_valid(&self) -> bool {
        self.l >= 0.0 && self.l <= 1.0 &&
        self.chroma >= 0.0 && self.chroma <= 1.41421356 && //should include all of L*a*b*, but will also overshoot...
        self.alpha >= 0.0 && self.alpha <= 1.0
    }

    fn clamp(&self) -> Lch {
        let mut c = *self;
        c.clamp_self();
        c
    }

    fn clamp_self(&mut self) {
        self.l = clamp(self.l, 0.0, 1.0);
        self.chroma = clamp(self.chroma, 0.0, 1.41421356); //should include all of L*a*b*, but will also overshoot...
        self.alpha = clamp(self.alpha, 0.0, 1.0);
    }
}

impl Mix for Lch {
    fn mix(&self, other: &Lch, factor: f32) -> Lch {
        let factor = clamp(factor, 0.0, 1.0);
        let hue_diff: f32 = (other.hue - self.hue).into();
        Lch {
            l: self.l + factor * (other.l - self.l),
            chroma: self.chroma + factor * (other.chroma - self.chroma),
            hue: self.hue + factor * hue_diff,
            alpha: self.alpha + factor * (other.alpha - self.alpha),
        }
    }
}

impl Shade for Lch {
    fn lighten(&self, amount: f32) -> Lch {
        Lch {
            l: self.l + amount,
            chroma: self.chroma,
            hue: self.hue,
            alpha: self.alpha,
        }
    }
}

impl GetHue for Lch {
    type Hue = LabHue;

    fn get_hue(&self) -> Option<LabHue> {
        if self.chroma <= 0.0 {
            None
        } else {
            Some(self.hue)
        }
    }
}

impl Hue for Lch {
    fn with_hue(&self, hue: LabHue) -> Lch {
        Lch {
            l: self.l,
            chroma: self.chroma,
            hue: hue,
            alpha: self.alpha,
        }
    }

    fn shift_hue(&self, amount: LabHue) -> Lch {
        Lch {
            l: self.l,
            chroma: self.chroma,
            hue: self.hue + amount,
            alpha: self.alpha,
        }
    }
}

impl Saturate for Lch {
    fn saturate(&self, factor: f32) -> Lch {
        Lch {
            l: self.l,
            chroma: self.chroma * (1.0 + factor),
            hue: self.hue,
            alpha: self.alpha,
        }
    }
}

impl Default for Lch {
    fn default() -> Lch {
        Lch::lch(0.0, 0.0, 0.0.into())
    }
}

impl Add<Lch> for Lch {
    type Output = Lch;

    fn add(self, other: Lch) -> Lch {
        Lch {
            l: self.l + other.l,
            chroma: self.chroma + other.chroma,
            hue: self.hue + other.hue,
            alpha: self.alpha + other.alpha,
        }
    }
}

impl Add<f32> for Lch {
    type Output = Lch;

    fn add(self, c: f32) -> Lch {
        Lch {
            l: self.l + c,
            chroma: self.chroma + c,
            hue: self.hue + c,
            alpha: self.alpha + c,
        }
    }
}

impl Sub<Lch> for Lch {
    type Output = Lch;

    fn sub(self, other: Lch) -> Lch {
        Lch {
            l: self.l - other.l,
            chroma: self.chroma - other.chroma,
            hue: self.hue - other.hue,
            alpha: self.alpha - other.alpha,
        }
    }
}

impl Sub<f32> for Lch {
    type Output = Lch;

    fn sub(self, c: f32) -> Lch {
        Lch {
            l: self.l - c,
            chroma: self.chroma - c,
            hue: self.hue - c,
            alpha: self.alpha - c,
        }
    }
}

from_color!(to Lch from Rgb, Luma, Xyz, Lab, Hsv, Hsl);

impl From<Lab> for Lch {
    fn from(lab: Lab) -> Lch {
        Lch {
            l: lab.l,
            chroma: (lab.a * lab.a + lab.b * lab.b).sqrt(),
            hue: lab.get_hue().unwrap_or(0.0.into()),
            alpha: lab.alpha,
        }
    }
}

impl From<Rgb> for Lch {
    fn from(rgb: Rgb) -> Lch {
        Lab::from(rgb).into()
    }
}

impl From<Luma> for Lch {
    fn from(luma: Luma) -> Lch {
        Lab::from(luma).into()
    }
}

impl From<Xyz> for Lch {
    fn from(xyz: Xyz) -> Lch {
        Lab::from(xyz).into()
    }
}

impl From<Hsv> for Lch {
    fn from(hsv: Hsv) -> Lch {
        Lab::from(hsv).into()
    }
}

impl From<Hsl> for Lch {
    fn from(hsl: Hsl) -> Lch {
        Lab::from(hsl).into()
    }
}
<|endoftext|>


<commit_before>//! Rust bindings to the libcurl C library
//!
//! This crate contains bindings for an HTTP/HTTPS client which is powered by
//! [libcurl], the same library behind the `curl` command line tool. The API
//! currently closely matches that of libcurl itself, except that a Rustic layer
//! of safety is applied on top.
//!
//! [libcurl]: https://curl.haxx.se/libcurl/
//!
//! # The "Easy" API
//!
//! The easiest way to send a request is to use the `Easy` api which corresponds
//! to `CURL` in libcurl. This handle supports a wide variety of options and can
//! be used to make a single blocking request in a thread. Callbacks can be
//! specified to deal with data as it arrives and a handle can be reused to
//! cache connections and such.
//!
//! ```rust,no_run
//! use std::io::{stdout, Write};
//!
//! use curl::easy::Easy;
//!
//! // Write the contents of rust-lang.org to stdout
//! let mut easy = Easy::new();
//! easy.url("https://www.rust-lang.org/").unwrap();
//! easy.write_function(|data| {
//!     Ok(stdout().write(data).unwrap())
//! }).unwrap();
//! easy.perform().unwrap();
//! ```
//!
//! # What about multiple concurrent HTTP requests?
//!
//! One option you have currently is to send multiple requests in multiple
//! threads, but otherwise libcurl has a "multi" interface for doing this
//! operation. Initial bindings of this interface can be found in the `multi`
//! module, but feedback is welcome!
//!
//! # Where does libcurl come from?
//!
//! This crate links to the `curl-sys` crate which is in turn responsible for
//! acquiring and linking to the libcurl library. Currently this crate will
//! build libcurl from source if one is not already detected on the system.
//!
//! There is a large number of releases for libcurl, all with different sets of
//! capabilities. Robust programs may wish to inspect `Version::get()` to test
//! what features are implemented in the linked build of libcurl at runtime.

#![deny(missing_docs)]

extern crate curl_sys;
extern crate libc;

#[cfg(all(unix, not(target_os = "macos")))]
extern crate openssl_sys;
#[cfg(all(unix, not(target_os = "macos")))]
extern crate openssl_probe;
#[cfg(windows)]
extern crate winapi;

use std::ffi::CStr;
use std::str;
use std::sync::{Once, ONCE_INIT};

pub use error::{Error, ShareError, MultiError, FormError};
mod error;

pub use version::{Version, Protocols};
mod version;

mod panic;
pub mod easy;
pub mod multi;

/// Initializes the underlying libcurl library.
///
/// It's not required to call this before the library is used, but it's
/// recommended to do so as soon as the program starts.
pub fn init() {
    static INIT: Once = ONCE_INIT;
    INIT.call_once(|| {
        platform_init();
        unsafe {
            assert_eq!(curl_sys::curl_global_init(curl_sys::CURL_GLOBAL_ALL), 0);
            libc::atexit(cleanup);
        }
    });

    extern fn cleanup() {
        unsafe { curl_sys::curl_global_cleanup(); }
    }

    #[cfg(all(unix, not(target_os = "macos")))]
    fn platform_init() {
        openssl_sys::init();
    }

    #[cfg(not(all(unix, not(target_os = "macos"))))]
    fn platform_init() {}
}

unsafe fn opt_str<'a>(ptr: *const libc::c_char) -> Option<&'a str> {
    if ptr.is_null() {
        None
    } else {
        Some(str::from_utf8(CStr::from_ptr(ptr).to_bytes()).unwrap())
    }
}

fn cvt(r: curl_sys::CURLcode) -> Result<(), Error> {
    if r == curl_sys::CURLE_OK {
        Ok(())
    } else {
        Err(Error::new(r))
    }
}
<commit_msg>Don't call curl_global_cleanup<commit_after>//! Rust bindings to the libcurl C library
//!
//! This crate contains bindings for an HTTP/HTTPS client which is powered by
//! [libcurl], the same library behind the `curl` command line tool. The API
//! currently closely matches that of libcurl itself, except that a Rustic layer
//! of safety is applied on top.
//!
//! [libcurl]: https://curl.haxx.se/libcurl/
//!
//! # The "Easy" API
//!
//! The easiest way to send a request is to use the `Easy` api which corresponds
//! to `CURL` in libcurl. This handle supports a wide variety of options and can
//! be used to make a single blocking request in a thread. Callbacks can be
//! specified to deal with data as it arrives and a handle can be reused to
//! cache connections and such.
//!
//! ```rust,no_run
//! use std::io::{stdout, Write};
//!
//! use curl::easy::Easy;
//!
//! // Write the contents of rust-lang.org to stdout
//! let mut easy = Easy::new();
//! easy.url("https://www.rust-lang.org/").unwrap();
//! easy.write_function(|data| {
//!     Ok(stdout().write(data).unwrap())
//! }).unwrap();
//! easy.perform().unwrap();
//! ```
//!
//! # What about multiple concurrent HTTP requests?
//!
//! One option you have currently is to send multiple requests in multiple
//! threads, but otherwise libcurl has a "multi" interface for doing this
//! operation. Initial bindings of this interface can be found in the `multi`
//! module, but feedback is welcome!
//!
//! # Where does libcurl come from?
//!
//! This crate links to the `curl-sys` crate which is in turn responsible for
//! acquiring and linking to the libcurl library. Currently this crate will
//! build libcurl from source if one is not already detected on the system.
//!
//! There is a large number of releases for libcurl, all with different sets of
//! capabilities. Robust programs may wish to inspect `Version::get()` to test
//! what features are implemented in the linked build of libcurl at runtime.

#![deny(missing_docs)]

extern crate curl_sys;
extern crate libc;

#[cfg(all(unix, not(target_os = "macos")))]
extern crate openssl_sys;
#[cfg(all(unix, not(target_os = "macos")))]
extern crate openssl_probe;
#[cfg(windows)]
extern crate winapi;

use std::ffi::CStr;
use std::str;
use std::sync::{Once, ONCE_INIT};

pub use error::{Error, ShareError, MultiError, FormError};
mod error;

pub use version::{Version, Protocols};
mod version;

mod panic;
pub mod easy;
pub mod multi;

/// Initializes the underlying libcurl library.
///
/// It's not required to call this before the library is used, but it's
/// recommended to do so as soon as the program starts.
pub fn init() {
    static INIT: Once = ONCE_INIT;
    INIT.call_once(|| {
        platform_init();
        unsafe {
            assert_eq!(curl_sys::curl_global_init(curl_sys::CURL_GLOBAL_ALL), 0);
        }

        // Note that we explicitly don't schedule a call to
        // `curl_global_cleanup`. The documentation for that function says
        //
        // > You must not call it when any other thread in the program (i.e. a
        // > thread sharing the same memory) is running. This doesn't just mean
        // > no other thread that is using libcurl.
        //
        // We can't ever be sure of that, so unfortunately we can't call the
        // function.
    });

    #[cfg(all(unix, not(target_os = "macos")))]
    fn platform_init() {
        openssl_sys::init();
    }

    #[cfg(not(all(unix, not(target_os = "macos"))))]
    fn platform_init() {}
}

unsafe fn opt_str<'a>(ptr: *const libc::c_char) -> Option<&'a str> {
    if ptr.is_null() {
        None
    } else {
        Some(str::from_utf8(CStr::from_ptr(ptr).to_bytes()).unwrap())
    }
}

fn cvt(r: curl_sys::CURLcode) -> Result<(), Error> {
    if r == curl_sys::CURLE_OK {
        Ok(())
    } else {
        Err(Error::new(r))
    }
}
<|endoftext|>


<commit_before>pub mod dna_base;
pub mod base4;

/// Represents the bases used in the genome string.
/// For example the bases of the DNA are adenine (A),
/// thymine (T), guanine (G) and cytosine (C).
pub trait Base: Sized + PartialEq + Eq + Copy + Clone {
    /// Returns the "successor" base, wrapping around. Used
    /// to produce the gene product.
    fn succ(self) -> Self;

    fn from_char(c: char) -> Option<Self>;
}

// Locate ```substr``` in ```s```.
fn locate_substr<T: Eq>(s: &[T], substr: &[T]) -> Option<usize> {
    assert!(substr.len() > 0);

    if s.len() < substr.len() {
        return None;
    }

    for (i, window) in s.windows(substr.len()).enumerate() {
        if window == substr {
            return Some(i);
        }
    }

    return None;
}

#[derive(Debug)]
pub struct Gene<'a, B: Base + 'a> {
    pub regulatory_region: &'a [B],
    pub gene: &'a [B],
}

impl<'a, B: Base + 'a> Gene<'a, B> {
    pub fn gene_product(&self) -> Vec<B> {
        self.gene.iter().map(|b| b.succ()).collect()
    }

    pub fn find_product_in_regulatory_region(&self, product: &[B]) -> bool {
        locate_substr(self.regulatory_region, product).is_some()
    }
}

pub struct GeneIterator<'a, 'b, B: Base + 'a + 'b> {
    start_pos: usize,
    // Genes have fixed length
    length_of_gene: usize,
    sequence: &'a [B],
    promoter: &'b [B],
}

impl<'a, 'b, B: Base + 'a + 'b> Iterator for GeneIterator<'a, 'b, B> {
    type Item = Gene<'a, B>;

    fn next(&mut self) -> Option<Self::Item> {
        match locate_substr(&self.sequence[self.start_pos..], self.promoter) {
            Some(pos) => {
                let reg_start = self.start_pos;
                let reg_end = reg_start + pos;
                let gene_start = reg_end + self.promoter.len();
                let gene_end = gene_start + self.length_of_gene;

                // gene is not complete
                if gene_end > self.sequence.len() {
                    return None;
                }

                let gene = Gene {
                    regulatory_region: &self.sequence[reg_start..reg_end],
                    gene: &self.sequence[gene_start..gene_end],
                };
                self.start_pos = gene_end;
                return Some(gene);
            }
            None => {
                return None;
            }
        }
    }
}

/// A Genome is a string of Base
pub struct Genome<B: Base> {
    pub genome: Vec<B>,
}

// Convert genome into sections, i.e. Split at the promoter.
impl<B: Base> Genome<B> {
    pub fn iter_genes<'a, 'b>(&'a self,
                              promoter: &'b [B],
                              length_of_gene: usize)
                              -> GeneIterator<'a, 'b, B> {
        GeneIterator {
            start_pos: 0,
            length_of_gene: length_of_gene,
            sequence: &self.genome,
            promoter: promoter,
        }
    }
}
<commit_msg>Get rid of start_pos in GeneIterator<commit_after>pub mod dna_base;
pub mod base4;

/// Represents the bases used in the genome string.
/// For example the bases of the DNA are adenine (A),
/// thymine (T), guanine (G) and cytosine (C).
pub trait Base: Sized + PartialEq + Eq + Copy + Clone {
    /// Returns the "successor" base, wrapping around. Used
    /// to produce the gene product.
    fn succ(self) -> Self;

    fn from_char(c: char) -> Option<Self>;
}

// Locate ```substr``` in ```s```.
fn locate_substr<T: Eq>(s: &[T], substr: &[T]) -> Option<usize> {
    assert!(substr.len() > 0);

    if s.len() < substr.len() {
        return None;
    }

    for (i, window) in s.windows(substr.len()).enumerate() {
        if window == substr {
            return Some(i);
        }
    }

    return None;
}

#[derive(Debug)]
pub struct Gene<'a, B: Base + 'a> {
    pub regulatory_region: &'a [B],
    pub gene: &'a [B],
}

impl<'a, B: Base + 'a> Gene<'a, B> {
    pub fn gene_product(&self) -> Vec<B> {
        self.gene.iter().map(|b| b.succ()).collect()
    }

    pub fn find_product_in_regulatory_region(&self, product: &[B]) -> bool {
        locate_substr(self.regulatory_region, product).is_some()
    }
}

pub struct GeneIterator<'a, 'b, B: Base + 'a + 'b> {
    // Genes have fixed length
    length_of_gene: usize,
    sequence: &'a [B],
    promoter: &'b [B],
}

impl<'a, 'b, B: Base + 'a + 'b> Iterator for GeneIterator<'a, 'b, B> {
    type Item = Gene<'a, B>;

    fn next(&mut self) -> Option<Self::Item> {
        match locate_substr(self.sequence, self.promoter) {
            Some(pos) => {
                let gene_start = pos + self.promoter.len();
                let gene_end = gene_start + self.length_of_gene;

                // gene is not complete
                if gene_end > self.sequence.len() {
                    return None;
                }

                let gene = Gene {
                    regulatory_region: &self.sequence[..pos],
                    gene: &self.sequence[gene_start..gene_end],
                };
                self.sequence = &self.sequence[gene_end..];
                return Some(gene);
            }
            None => {
                return None;
            }
        }
    }
}

/// A Genome is a string of Base
pub struct Genome<B: Base> {
    pub genome: Vec<B>,
}

// Convert genome into sections, i.e. Split at the promoter.
impl<B: Base> Genome<B> {
    pub fn iter_genes<'a, 'b>(&'a self,
                              promoter: &'b [B],
                              length_of_gene: usize)
                              -> GeneIterator<'a, 'b, B> {
        GeneIterator {
            length_of_gene: length_of_gene,
            sequence: &self.genome,
            promoter: promoter,
        }
    }
}
<|endoftext|>


<commit_before>extern crate libinspire;
extern crate libads;

/// Re-export slog
///
/// Users of this library can, but don't have to use slog to build their own loggers
#[macro_use]
pub extern crate slog ;
extern crate slog_stdlog;

use slog::DrainExt;

extern crate regex;
use regex::Regex;

pub struct Inspirer {
    logger: slog::Logger,
    inspire: libinspire::Api,
    ads: libads::Api,
}

impl Inspirer {
    /// Initialize 'Inspirer'
    ///
    /// Either provide a custom slog::Logger or default to the standard `log`
    /// crate.
    ///
    /// # Examples
    /// ```
    /// inspirer::Inspirer::init(None);
    /// ```
    pub fn init(logger: Option<slog::Logger>) -> Self {
        let logger = logger.unwrap_or_else(|| slog::Logger::root(slog_stdlog::StdLog.fuse(), o!()));

        Inspirer {
            logger: logger,
            // inspire: libinspire::Api::init(Some(logger)),
            inspire: libinspire::Api::init(None),
            ads: libads::Api::init(None),
        }
    }

    /// The `aux2key` function extracts TeX keys from LaTeX .aux files. These can be for either
    /// BibTeX or BibLaTeX.
    ///
    /// # Examples
    ///
    /// ## bibtex
    ///
    /// ```
    /// let inspirer = inspirer::Inspirer::init(None);
    ///
    /// let input =
    /// r"\relax
    /// \citation{Abramovici:1992ah}".to_string();
    ///
    /// assert_eq!(inspirer.aux2key(input), vec!("Abramovici:1992ah"));
    /// ```
    ///
    /// ## biber
    ///
    /// ```
    /// let inspirer = inspirer::Inspirer::init(None);
    ///
    /// let input =
    /// r"\relax
    /// \abx@aux@cite{Cutler:1992tc}".to_string();
    ///
    /// assert_eq!(inspirer.aux2key(input), vec!("Cutler:1992tc"));
    /// ```
    pub fn aux2key(&self, input_data: String) -> Vec<String> {

        let regex = Regex::new(r"(\\citation|\\abx@aux@cite)\{([a-zA-Z]+:\d{4}[a-z]{2,3})\}")
            .unwrap();

        regex
            .captures_iter(&input_data)
            .map(|c| c.get(2).unwrap().as_str().to_string())
            .collect()
    }

    ///  The blg2key function extracts missing references from bibtex logs
    pub fn blg2key(&self, input_data: String) -> Vec<String> {

        let regex = Regex::new(r#"(Warning--|WARN - )I didn't find a database entry for ["']([a-zA-Z]+:\d{4}[a-z]{2,3})["']"#)
            .unwrap();

        regex
            .captures_iter(&input_data)
            .map(|c| c.get(2).unwrap().as_str().to_string())
            .collect()
    }

    /// Fetch BibTeX entries
    pub fn bibtex(&self, key: &str) -> Option<String> {
        let key = Sources::from(key);

        match key {
            Sources::Inspire(k) => {
                debug!(self.logger, "Got Inspire record"; "key" => k.id);
                self.inspire.fetch_bibtex_with_key(k)
            }
            _ => {
                // debug!(self.logger, "Unknown record source"; "key" => key);
                debug!(self.logger, "Unknown record source");
                None
            }
        }
    }
}

#[derive(Debug,PartialEq)]
pub enum Sources<'a> {
    Inspire(libinspire::RecID<'a>),
    Ads,
    Arxiv,
    None,
}

/// Guess a likely source for a BibTeX key
///
/// Returns `Sources::None` if unable to make a good guess.
///
/// # Examples
/// ```
/// extern crate inspirer;
/// extern crate libinspire;
/// let inspirer = inspirer::Inspirer::init(None);
///
/// assert_eq!(
///     inspirer::Sources::from("Randall:1999ee"),
///     inspirer::Sources::Inspire(libinspire::RecID::new("Randall:1999ee").unwrap())
/// );
/// ```
impl<'a> From<&'a str> for Sources<'a> {
    fn from(s: &'a str) -> Sources<'a> {
        if libinspire::validate_recid(s) {
            Sources::Inspire(libinspire::RecID::new(s).unwrap())
        } else {
            Sources::None
        }
    }
}

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

    #[test]
    fn test_aux_bibtex_0_citations() {
        let input = r"\relax ".to_string();

        let output: Vec<String> = Vec::new();
        assert_eq!(Inspirer::init(None).aux2key(input), output);
    }

    #[test]
    fn test_aux_bibtex_1_citation() {
        let input = r"\relax
            \citation{Abramovici:1992ah}"
                .to_string();

        assert_eq!(Inspirer::init(None).aux2key(input),
                   vec!["Abramovici:1992ah"]);
    }

    #[test]
    fn test_aux_bibtex_2_citation() {
        let input = r"\relax
            \citation{Abramovici:1992ah}
            \citation{Thorne:1992sdb}"
                .to_string();

        assert_eq!(Inspirer::init(None).aux2key(input),
                   vec!["Abramovici:1992ah", "Thorne:1992sdb"]);
    }
}
<commit_msg>Sources: Implement ADS<commit_after>extern crate libinspire;
extern crate libads;

/// Re-export slog
///
/// Users of this library can, but don't have to use slog to build their own loggers
#[macro_use]
pub extern crate slog ;
extern crate slog_stdlog;

use slog::DrainExt;

extern crate regex;
use regex::Regex;

pub struct Inspirer {
    logger: slog::Logger,
    inspire: libinspire::Api,
    ads: libads::Api,
}

impl Inspirer {
    /// Initialize 'Inspirer'
    ///
    /// Either provide a custom slog::Logger or default to the standard `log`
    /// crate.
    ///
    /// # Examples
    /// ```
    /// inspirer::Inspirer::init(None);
    /// ```
    pub fn init(logger: Option<slog::Logger>) -> Self {
        let logger = logger.unwrap_or_else(|| slog::Logger::root(slog_stdlog::StdLog.fuse(), o!()));

        Inspirer {
            logger: logger,
            // inspire: libinspire::Api::init(Some(logger)),
            inspire: libinspire::Api::init(None),
            ads: libads::Api::init(None),
        }
    }

    /// The `aux2key` function extracts TeX keys from LaTeX .aux files. These can be for either
    /// BibTeX or BibLaTeX.
    ///
    /// # Examples
    ///
    /// ## bibtex
    ///
    /// ```
    /// let inspirer = inspirer::Inspirer::init(None);
    ///
    /// let input =
    /// r"\relax
    /// \citation{Abramovici:1992ah}".to_string();
    ///
    /// assert_eq!(inspirer.aux2key(input), vec!("Abramovici:1992ah"));
    /// ```
    ///
    /// ## biber
    ///
    /// ```
    /// let inspirer = inspirer::Inspirer::init(None);
    ///
    /// let input =
    /// r"\relax
    /// \abx@aux@cite{Cutler:1992tc}".to_string();
    ///
    /// assert_eq!(inspirer.aux2key(input), vec!("Cutler:1992tc"));
    /// ```
    pub fn aux2key(&self, input_data: String) -> Vec<String> {

        let regex = Regex::new(r"(\\citation|\\abx@aux@cite)\{([a-zA-Z]+:\d{4}[a-z]{2,3})\}")
            .unwrap();

        regex
            .captures_iter(&input_data)
            .map(|c| c.get(2).unwrap().as_str().to_string())
            .collect()
    }

    ///  The blg2key function extracts missing references from bibtex logs
    pub fn blg2key(&self, input_data: String) -> Vec<String> {

        let regex = Regex::new(r#"(Warning--|WARN - )I didn't find a database entry for ["']([a-zA-Z]+:\d{4}[a-z]{2,3})["']"#)
            .unwrap();

        regex
            .captures_iter(&input_data)
            .map(|c| c.get(2).unwrap().as_str().to_string())
            .collect()
    }

    /// Fetch BibTeX entries
    pub fn bibtex(&self, key: &str) -> Option<String> {
        let key = Sources::from(key);

        match key {
            Sources::Inspire(k) => {
                debug!(self.logger, "Got Inspire record"; "key" => k.id);
                self.inspire.fetch_bibtex_with_key(k)
            }
            _ => {
                // debug!(self.logger, "Unknown record source"; "key" => key);
                debug!(self.logger, "Unknown record source");
                None
            }
        }
    }
}

#[derive(Debug,PartialEq)]
pub enum Sources<'a> {
    Inspire(libinspire::RecID<'a>),
    Ads(libads::BibCode<'a>),
    Arxiv,
    None,
}

/// Guess a likely source for a BibTeX key
///
/// Returns `Sources::None` if unable to make a good guess.
///
/// # Examples
/// ```
/// extern crate inspirer;
/// extern crate libinspire;
/// let inspirer = inspirer::Inspirer::init(None);
///
/// assert_eq!(
///     inspirer::Sources::from("Randall:1999ee"),
///     inspirer::Sources::Inspire(libinspire::RecID::new("Randall:1999ee").unwrap())
/// );
/// ```
///
/// ```
/// extern crate inspirer;
/// extern crate libads;
/// let inspirer = inspirer::Inspirer::init(None);
///
/// assert_eq!(
///     inspirer::Sources::from("1999PhRvL..83.3370R"),
///     inspirer::Sources::Ads(libads::BibCode::new("1999PhRvL..83.3370R").unwrap())
/// );
/// ```
impl<'a> From<&'a str> for Sources<'a> {
    fn from(s: &'a str) -> Sources<'a> {
        if libinspire::validate_recid(s) {
            Sources::Inspire(libinspire::RecID::new(s).unwrap())
        } else if libads::validate_bib_code(s) {
            Sources::Ads(libads::BibCode::new(s).unwrap())
        } else {
            Sources::None
        }
    }
}

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

    #[test]
    fn test_aux_bibtex_0_citations() {
        let input = r"\relax ".to_string();

        let output: Vec<String> = Vec::new();
        assert_eq!(Inspirer::init(None).aux2key(input), output);
    }

    #[test]
    fn test_aux_bibtex_1_citation() {
        let input = r"\relax
            \citation{Abramovici:1992ah}"
                .to_string();

        assert_eq!(Inspirer::init(None).aux2key(input),
                   vec!["Abramovici:1992ah"]);
    }

    #[test]
    fn test_aux_bibtex_2_citation() {
        let input = r"\relax
            \citation{Abramovici:1992ah}
            \citation{Thorne:1992sdb}"
                .to_string();

        assert_eq!(Inspirer::init(None).aux2key(input),
                   vec!["Abramovici:1992ah", "Thorne:1992sdb"]);
    }
}
<|endoftext|>


<commit_before>extern crate libc;
extern crate errno;

use libc::{c_int, c_char, dev_t, utsname, sigset_t, sighandler_t, PATH_MAX, SA_RESTART, EINTR};
use libc::{SIG_ERR, SIGALRM, SIGINT, SIGUSR1, SIGQUIT};
use libc::{WSTOPSIG, WEXITSTATUS, WIFSTOPPED, WCOREDUMP, WTERMSIG, WIFSIGNALED, WIFEXITED};
use libc::{exit, _exit, sigemptyset, sigaction, sigismember, fork, waitpid};
use my_libc::{sigprocmask, execl};
use std::io::Write;
use std::ffi::CStr;
use std::mem::{zeroed, uninitialized};

/// Turns a str into a c string. Warning: the cstring only lives as long the
/// str lives. Don't e.g. assign the return value to a variable!
#[macro_export]
macro_rules! cstr {
    ($s:expr) => {{
        use std::ffi::CString;
        CString::new($s).unwrap().as_ptr()
    }}
}

#[macro_export]
macro_rules! as_void {
    ($s:expr) => {{
        extern crate libc;
        use libc::c_void;
        $s.as_ptr() as *mut c_void
    }}
}

#[macro_export]
macro_rules! as_char {
    ($s:expr) => {{
        extern crate libc;
        use libc::c_char;
        $s.as_ptr() as *mut c_char
    }}
}

#[macro_export]
macro_rules! print_err {
    ($($arg:tt)*) => (
        {
            use std::io::prelude::*;
            if let Err(e) = write!(&mut ::std::io::stderr(), "{}\n", format_args!($($arg)*)) {
                panic!("Failed to write to stderr.\
                    \nOriginal error output: {}\
                    \nSecondary error writing to stderr: {}", format!($($arg)*), e);
            }
        }
    )
}

/// turn libc result into an option
pub trait LibcResult<T> {
    /// returns None if the result is empty (-1 if an integer, Null if a pointer)
    /// and Some otherwise
    ///
    /// # Example
    /// if let Some(fd) = libc::creat(fd1, FILE_MODE).to_option() {
    ///     fd
    /// } else {
    ///     panic!("{}", io::Error::last_os_error());
    /// }
    fn to_option(&self) -> Option<T>;
}

impl LibcResult<c_int> for c_int {
    fn to_option(&self) -> Option<c_int> {
        if *self < 0 { None } else { Some(*self) }
    }
}
impl LibcResult<i64> for i64 {
    fn to_option(&self) -> Option<i64> {
        if *self < 0 { None } else { Some(*self) }
    }
}

// implementation for isize, sentinel = 0 (means end of file/buffer/... e.g. in read)
impl LibcResult<isize> for isize {
    fn to_option(&self) -> Option<isize> {
        if *self <= 0 { None } else { Some(*self) }
    }
}

impl LibcResult<sighandler_t> for sighandler_t {
    fn to_option(&self) -> Option<sighandler_t> {
        if *self == SIG_ERR { None } else { Some(*self) }
    }
}

impl<T> LibcResult<*mut T> for *mut T {
    fn to_option(&self) -> Option<*mut T> {
        if self.is_null() { None } else { Some(*self) }
    }
}

pub unsafe fn array_to_string(sl: &[i8]) -> &str {
    CStr::from_ptr(sl.as_ptr()).to_str().expect("invalid string")
}

/// Return uname -s
pub fn uname() -> Option<String> {
    let mut uc: utsname = unsafe { uninitialized() };
    unsafe {
        if libc::uname(&mut uc) == 0 {
            return Some(String::from(array_to_string(&uc.sysname)));
        }
    }
    None
}

pub fn err_sys(msg: &str) {
    std::io::stderr().write(format!("{}{}", msg, "\n").as_bytes()).unwrap();
    unsafe {
        exit(1);
    }
}

pub fn path_alloc() -> std::vec::Vec<c_char> {
    // Before POSIX.1-2001, we aren’t guaranteed that PATH_MAX includes
    // the terminating null byte. For simplicity sake we don't check for the posix
    // version and just increase by one
    Vec::with_capacity((PATH_MAX + 1) as usize)
}
// major device number, impl ported from /usr/include/sys/types.h
pub fn major(x: dev_t) -> dev_t {
    (x >> 24) & 0xff
}

// minor device number, impl ported from /usr/include/sys/types.h
pub fn minor(x: dev_t) -> dev_t {
    x & 0xffffff
}

pub fn pr_exit(status: c_int) {
    unsafe {
        if WIFEXITED(status) {
            println!("normal termination, exit status = {}", WEXITSTATUS(status));
        } else if WIFSIGNALED(status) {
            println!("abnormal termination, signal number = {} {}",
                     WTERMSIG(status),
                     if WCOREDUMP(status) {
                         " (core file generated)"
                     } else {
                         ""
                     });
        } else if WIFSTOPPED(status) {
            println!("child stopped, signal number = {}", WSTOPSIG(status));
        }
    }
}

macro_rules! print_sig {
    ($set:expr, $s:expr) => {{
        if sigismember($set, $s) == 1 {
            print!(" {}", stringify!($s));
        }
    }}
}

pub fn pr_mask(s: &str) {
    unsafe {
        let errno_save = errno::errno();
        let mut sigset: sigset_t = std::mem::uninitialized();
        sigprocmask(0, std::ptr::null(), &mut sigset).to_option().expect("sigprocmask error");
        print!("{}", s);
        print_sig!(&sigset, SIGINT);
        print_sig!(&sigset, SIGQUIT);
        print_sig!(&sigset, SIGUSR1);
        print_sig!(&sigset, SIGALRM);
        print!("\n");
        errno::set_errno(errno_save);
    }
}

// Figure 10.18: Reliable version of signal(), using POSIX sigaction()
pub unsafe fn signal(signo: i32, func: fn(c_int)) -> usize {
    let mut act: sigaction = zeroed();
    let mut oact: sigaction = uninitialized();
    act.sa_sigaction = func as usize;
    sigemptyset(&mut act.sa_mask);
    act.sa_flags = 0;
    if signo != SIGALRM {
        act.sa_flags |= SA_RESTART;
    }
    if sigaction(signo, &act, &mut oact) < 0 {
        SIG_ERR
    } else {
        oact.sa_sigaction as usize
    }
}

// Figure 8.22 The system function, without signal handling
pub unsafe fn system(cmdstring: &str) -> Option<i32> {
    if let Some(pid) = fork().to_option() {
        match pid {
            0 => {
                // child
                execl(cstr!("/bin/sh"),
                      cstr!("sh"),
                      cstr!("-c"),
                      cstr!(cmdstring),
                      0 as *const c_char);
                _exit(127);
            }
            _ => {
                // parent
                let mut status = 0;
                while waitpid(pid, &mut status, 0) < 0 {
                    if errno::errno().0 != EINTR {
                        return None;
                    }
                }
                return Some(status);
            }
        }
    } else {
        return None;
    }
}

// Figure 10.19: The signal_intr function, same as signal() above
// with the only difference that no system call is restarted
pub unsafe fn signal_intr(signo: i32, func: fn(c_int)) -> usize {
    let mut act: sigaction = zeroed();
    let mut oact: sigaction = uninitialized();
    act.sa_sigaction = func as usize;
    sigemptyset(&mut act.sa_mask);
    act.sa_flags = 0;
    if sigaction(signo, &act, &mut oact) < 0 {
        SIG_ERR
    } else {
        oact.sa_sigaction as usize
    }
}

#[allow(non_camel_case_types)]
pub mod my_libc {
    use libc::{dirent, c_int, c_char, c_long, c_ulong, pid_t, clock_t, siginfo_t, sigset_t, id_t};
    use libc::{DIR, FILE};

    #[repr(C)]
    #[derive(Copy, Clone)]
    #[derive(Debug)]
    pub struct spwd {
        pub sp_namp: *mut c_char,
        pub sp_pwdp: *mut c_char,
        pub sp_lstchg: c_long,
        pub sp_min: c_long,
        pub sp_max: c_long,
        pub sp_warn: c_long,
        pub sp_inact: c_long,
        pub sp_expire: c_long,
        pub sp_flag: c_ulong,
    }

    #[repr(C)]
    #[derive(Copy, Clone)]
    #[derive(Debug)]
    pub struct tms {
        pub tms_utime: clock_t,
        pub tms_stime: clock_t,
        pub tms_cutime: clock_t,
        pub tms_cstime: clock_t,
    }

    #[derive(Copy, Clone)]
    #[repr(u32)]
    #[derive(Debug)]
    pub enum idtype_t {
        P_ALL = 0,
        P_PID = 1,
        P_PGID = 2,
    }

    pub const WEXITED: c_int = 0x00000004;  // [XSI] Processes which have exitted
    pub const WSTOPPED: c_int = 0x00000008;  // [XSI] Any child stopped by signal
    pub const WCONTINUED: c_int = 0x00000010;  // [XSI] Any child stopped then continued
    pub const WNOWAIT: c_int = 0x00000020;  // [XSI] Leave process returned waitable

    pub const CLD_NOOP: c_int = 0;       // if only I knew...
    pub const CLD_EXITED: c_int = 1;       // [XSI] child has exited
    pub const CLD_KILLED: c_int = 2;       // [XSI] terminated abnormally, no core file
    pub const CLD_DUMPED: c_int = 3;       // [XSI] terminated abnormally, core file
    pub const CLD_TRAPPED: c_int = 4;       // [XSI] traced child has trapped
    pub const CLD_STOPPED: c_int = 5;       // [XSI] child has stopped
    pub const CLD_CONTINUED: c_int = 6;       // [XSI] stopped child has continued

    extern "C" {
        #[cfg(target_os = "macos")]
        #[link_name = "readdir$INODE64"]
        pub fn readdir(arg1: *mut DIR) -> *mut dirent;

        #[cfg(not(target_os = "macos"))]
        pub fn readdir(arg1: *mut DIR) -> *mut dirent;

        pub fn dirfd(dirp: *mut DIR) -> c_int;

        pub fn tmpnam(ptr: *mut c_char) -> *mut c_char;

        pub fn getc(arg1: *mut FILE) -> c_int;
        pub fn putc(arg1: c_int, arg2: *mut FILE) -> c_int;
        pub fn getchar() -> c_int;

        pub fn setspent();
        pub fn endspent();
        pub fn getspent() -> *mut spwd;
        pub fn getspnam(__name: *const c_char) -> *mut spwd;

        // vfork is not implemented in libc, and that's probably good so
        // as vfork is somehow deprecated
        pub fn vfork() -> pid_t;

        pub fn execl(__path: *const c_char, __arg0: *const c_char, ...) -> c_int;
        pub fn execle(__path: *const c_char, __arg0: *const c_char, ...) -> c_int;
        pub fn execlp(__file: *const c_char, __arg0: *const c_char, ...) -> c_int;

        pub fn waitid(arg1: idtype_t, arg2: id_t, arg3: *mut siginfo_t, arg4: c_int) -> c_int;

        #[cfg(target_os = "macos")]
        #[link_name = "__stdoutp"]
        pub static mut stdout: *mut FILE;

        #[cfg(not(target_os = "macos"))]
        pub static mut stdout: *mut FILE;

        pub fn times(arg1: *mut tms) -> clock_t;

        pub fn sigprocmask(arg1: c_int, arg2: *const sigset_t, arg3: *mut sigset_t) -> c_int;
        pub fn sigpending(arg1: *mut sigset_t) -> c_int;
        pub fn sigsuspend(arg1: *const sigset_t) -> c_int;
    }
}
<commit_msg>Start Figure 10.28<commit_after>extern crate libc;
extern crate errno;

use libc::{c_int, c_char, dev_t, utsname, sigset_t, sighandler_t, PATH_MAX, SA_RESTART, EINTR};
use libc::{SIG_ERR, SIG_IGN, SIGALRM, SIGINT, SIGUSR1, SIGQUIT, SIGCHLD};
use libc::{WSTOPSIG, WEXITSTATUS, WIFSTOPPED, WCOREDUMP, WTERMSIG, WIFSIGNALED, WIFEXITED};
use libc::{exit, _exit, sigemptyset, sigaddset, sigaction, sigismember, fork, waitpid};
use my_libc::{sigprocmask, execl};
use std::io::Write;
use std::ffi::CStr;
use std::mem::{zeroed, uninitialized};

/// Turns a str into a c string. Warning: the cstring only lives as long the
/// str lives. Don't e.g. assign the return value to a variable!
#[macro_export]
macro_rules! cstr {
    ($s:expr) => {{
        use std::ffi::CString;
        CString::new($s).unwrap().as_ptr()
    }}
}

#[macro_export]
macro_rules! as_void {
    ($s:expr) => {{
        extern crate libc;
        use libc::c_void;
        $s.as_ptr() as *mut c_void
    }}
}

#[macro_export]
macro_rules! as_char {
    ($s:expr) => {{
        extern crate libc;
        use libc::c_char;
        $s.as_ptr() as *mut c_char
    }}
}

#[macro_export]
macro_rules! print_err {
    ($($arg:tt)*) => (
        {
            use std::io::prelude::*;
            if let Err(e) = write!(&mut ::std::io::stderr(), "{}\n", format_args!($($arg)*)) {
                panic!("Failed to write to stderr.\
                    \nOriginal error output: {}\
                    \nSecondary error writing to stderr: {}", format!($($arg)*), e);
            }
        }
    )
}

/// turn libc result into an option
pub trait LibcResult<T> {
    /// returns None if the result is empty (-1 if an integer, Null if a pointer)
    /// and Some otherwise
    ///
    /// # Example
    /// if let Some(fd) = libc::creat(fd1, FILE_MODE).to_option() {
    ///     fd
    /// } else {
    ///     panic!("{}", io::Error::last_os_error());
    /// }
    fn to_option(&self) -> Option<T>;
}

impl LibcResult<c_int> for c_int {
    fn to_option(&self) -> Option<c_int> {
        if *self < 0 { None } else { Some(*self) }
    }
}
impl LibcResult<i64> for i64 {
    fn to_option(&self) -> Option<i64> {
        if *self < 0 { None } else { Some(*self) }
    }
}

// implementation for isize, sentinel = 0 (means end of file/buffer/... e.g. in read)
impl LibcResult<isize> for isize {
    fn to_option(&self) -> Option<isize> {
        if *self <= 0 { None } else { Some(*self) }
    }
}

impl LibcResult<sighandler_t> for sighandler_t {
    fn to_option(&self) -> Option<sighandler_t> {
        if *self == SIG_ERR { None } else { Some(*self) }
    }
}

impl<T> LibcResult<*mut T> for *mut T {
    fn to_option(&self) -> Option<*mut T> {
        if self.is_null() { None } else { Some(*self) }
    }
}

pub unsafe fn array_to_string(sl: &[i8]) -> &str {
    CStr::from_ptr(sl.as_ptr()).to_str().expect("invalid string")
}

/// Return uname -s
pub fn uname() -> Option<String> {
    let mut uc: utsname = unsafe { uninitialized() };
    unsafe {
        if libc::uname(&mut uc) == 0 {
            return Some(String::from(array_to_string(&uc.sysname)));
        }
    }
    None
}

pub fn err_sys(msg: &str) {
    std::io::stderr().write(format!("{}{}", msg, "\n").as_bytes()).unwrap();
    unsafe {
        exit(1);
    }
}

pub fn path_alloc() -> std::vec::Vec<c_char> {
    // Before POSIX.1-2001, we aren’t guaranteed that PATH_MAX includes
    // the terminating null byte. For simplicity sake we don't check for the posix
    // version and just increase by one
    Vec::with_capacity((PATH_MAX + 1) as usize)
}
// major device number, impl ported from /usr/include/sys/types.h
pub fn major(x: dev_t) -> dev_t {
    (x >> 24) & 0xff
}

// minor device number, impl ported from /usr/include/sys/types.h
pub fn minor(x: dev_t) -> dev_t {
    x & 0xffffff
}

pub fn pr_exit(status: c_int) {
    unsafe {
        if WIFEXITED(status) {
            println!("normal termination, exit status = {}", WEXITSTATUS(status));
        } else if WIFSIGNALED(status) {
            println!("abnormal termination, signal number = {} {}",
                     WTERMSIG(status),
                     if WCOREDUMP(status) {
                         " (core file generated)"
                     } else {
                         ""
                     });
        } else if WIFSTOPPED(status) {
            println!("child stopped, signal number = {}", WSTOPSIG(status));
        }
    }
}

macro_rules! print_sig {
    ($set:expr, $s:expr) => {{
        if sigismember($set, $s) == 1 {
            print!(" {}", stringify!($s));
        }
    }}
}

pub fn pr_mask(s: &str) {
    unsafe {
        let errno_save = errno::errno();
        let mut sigset: sigset_t = std::mem::uninitialized();
        sigprocmask(0, std::ptr::null(), &mut sigset).to_option().expect("sigprocmask error");
        print!("{}", s);
        print_sig!(&sigset, SIGINT);
        print_sig!(&sigset, SIGQUIT);
        print_sig!(&sigset, SIGUSR1);
        print_sig!(&sigset, SIGALRM);
        print!("\n");
        errno::set_errno(errno_save);
    }
}

// Figure 10.18: Reliable version of signal(), using POSIX sigaction()
pub unsafe fn signal(signo: i32, func: fn(c_int)) -> usize {
    let mut act: sigaction = zeroed();
    let mut oact: sigaction = uninitialized();
    act.sa_sigaction = func as usize;
    sigemptyset(&mut act.sa_mask);
    act.sa_flags = 0;
    if signo != SIGALRM {
        act.sa_flags |= SA_RESTART;
    }
    if sigaction(signo, &act, &mut oact) < 0 {
        SIG_ERR
    } else {
        oact.sa_sigaction as usize
    }
}

// Figure 8.22 The system function, without signal handling
pub unsafe fn system(cmdstring: &str) -> Option<i32> {
    if let Some(pid) = fork().to_option() {
        match pid {
            0 => {
                // child
                execl(cstr!("/bin/sh"),
                      cstr!("sh"),
                      cstr!("-c"),
                      cstr!(cmdstring),
                      0 as *const c_char);
                _exit(127);
            }
            _ => {
                // parent
                let mut status = 0;
                while waitpid(pid, &mut status, 0) < 0 {
                    if errno::errno().0 != EINTR {
                        return None;
                    }
                }
                return Some(status);
            }
        }
    } else {
        return None;
    }
}

// Figure 10.28 Correct POSIX.1 implementation of system function
// (with signal handling)
// Status: only half way done
pub unsafe fn system2(cmdstring:&str) -> Option<i8> {
    let mut ignore:sigaction = std::mem::zeroed();
    let (mut saveintr, mut chldmask) = std::mem::uninitialized();
    ignore.sa_sigaction = SIG_IGN; // ignore SIGINT and SIGQUIT
    sigemptyset(&mut ignore.sa_mask);
    ignore.sa_flags = 0;
    if sigaction(SIGINT, &ignore, &mut saveintr).to_option().is_none() {
        return None;
    }
    if sigaction(SIGQUIT, &ignore, &mut saveintr).to_option().is_none() {
        return None;
    }
    sigemptyset(&mut chldmask);
    sigaddset(&mut chldmask, SIGCHLD);

    return Some(0);
}

// Figure 10.19: The signal_intr function, same as signal() above
// with the only difference that no system call is restarted
pub unsafe fn signal_intr(signo: i32, func: fn(c_int)) -> usize {
    let mut act: sigaction = zeroed();
    let mut oact: sigaction = uninitialized();
    act.sa_sigaction = func as usize;
    sigemptyset(&mut act.sa_mask);
    act.sa_flags = 0;
    if sigaction(signo, &act, &mut oact) < 0 {
        SIG_ERR
    } else {
        oact.sa_sigaction as usize
    }
}

#[allow(non_camel_case_types)]
pub mod my_libc {
    use libc::{dirent, c_int, c_char, c_long, c_ulong, pid_t, clock_t, siginfo_t, sigset_t, id_t};
    use libc::{DIR, FILE};

    #[repr(C)]
    #[derive(Copy, Clone)]
    #[derive(Debug)]
    pub struct spwd {
        pub sp_namp: *mut c_char,
        pub sp_pwdp: *mut c_char,
        pub sp_lstchg: c_long,
        pub sp_min: c_long,
        pub sp_max: c_long,
        pub sp_warn: c_long,
        pub sp_inact: c_long,
        pub sp_expire: c_long,
        pub sp_flag: c_ulong,
    }

    #[repr(C)]
    #[derive(Copy, Clone)]
    #[derive(Debug)]
    pub struct tms {
        pub tms_utime: clock_t,
        pub tms_stime: clock_t,
        pub tms_cutime: clock_t,
        pub tms_cstime: clock_t,
    }

    #[derive(Copy, Clone)]
    #[repr(u32)]
    #[derive(Debug)]
    pub enum idtype_t {
        P_ALL = 0,
        P_PID = 1,
        P_PGID = 2,
    }

    pub const WEXITED: c_int = 0x00000004;  // [XSI] Processes which have exitted
    pub const WSTOPPED: c_int = 0x00000008;  // [XSI] Any child stopped by signal
    pub const WCONTINUED: c_int = 0x00000010;  // [XSI] Any child stopped then continued
    pub const WNOWAIT: c_int = 0x00000020;  // [XSI] Leave process returned waitable

    pub const CLD_NOOP: c_int = 0;       // if only I knew...
    pub const CLD_EXITED: c_int = 1;       // [XSI] child has exited
    pub const CLD_KILLED: c_int = 2;       // [XSI] terminated abnormally, no core file
    pub const CLD_DUMPED: c_int = 3;       // [XSI] terminated abnormally, core file
    pub const CLD_TRAPPED: c_int = 4;       // [XSI] traced child has trapped
    pub const CLD_STOPPED: c_int = 5;       // [XSI] child has stopped
    pub const CLD_CONTINUED: c_int = 6;       // [XSI] stopped child has continued

    extern "C" {
        #[cfg(target_os = "macos")]
        #[link_name = "readdir$INODE64"]
        pub fn readdir(arg1: *mut DIR) -> *mut dirent;

        #[cfg(not(target_os = "macos"))]
        pub fn readdir(arg1: *mut DIR) -> *mut dirent;

        pub fn dirfd(dirp: *mut DIR) -> c_int;

        pub fn tmpnam(ptr: *mut c_char) -> *mut c_char;

        pub fn getc(arg1: *mut FILE) -> c_int;
        pub fn putc(arg1: c_int, arg2: *mut FILE) -> c_int;
        pub fn getchar() -> c_int;

        pub fn setspent();
        pub fn endspent();
        pub fn getspent() -> *mut spwd;
        pub fn getspnam(__name: *const c_char) -> *mut spwd;

        // vfork is not implemented in libc, and that's probably good so
        // as vfork is somehow deprecated
        pub fn vfork() -> pid_t;

        pub fn execl(__path: *const c_char, __arg0: *const c_char, ...) -> c_int;
        pub fn execle(__path: *const c_char, __arg0: *const c_char, ...) -> c_int;
        pub fn execlp(__file: *const c_char, __arg0: *const c_char, ...) -> c_int;

        pub fn waitid(arg1: idtype_t, arg2: id_t, arg3: *mut siginfo_t, arg4: c_int) -> c_int;

        #[cfg(target_os = "macos")]
        #[link_name = "__stdoutp"]
        pub static mut stdout: *mut FILE;

        #[cfg(not(target_os = "macos"))]
        pub static mut stdout: *mut FILE;

        pub fn times(arg1: *mut tms) -> clock_t;

        pub fn sigprocmask(arg1: c_int, arg2: *const sigset_t, arg3: *mut sigset_t) -> c_int;
        pub fn sigpending(arg1: *mut sigset_t) -> c_int;
        pub fn sigsuspend(arg1: *const sigset_t) -> c_int;
    }
}
<|endoftext|>


<commit_before>// Copyright 2017 tokio-jsonrpc Developers
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://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.

//! A JSON RPC protocol for the [tokio](https://tokio.rs) framework.
//!
//! This implements the handling of the
//! [JSON RPC 2.0](http://www.jsonrpc.org/specification) specification. The low-level parts are in
//! the [`message`](message/index.html) and the [`codec`](codec/index.html) modules. The first
//! draft of the higher-lever API is in the [`endpoint`](endpoint/index.html) module.
//!
//! # Examples
//!
//! ```rust
//! # extern crate tokio_core;
//! # extern crate tokio_jsonrpc;
//! # extern crate futures;
//! #
//! # use tokio_core::reactor::Core;
//! # use tokio_core::net::TcpListener;
//! # use tokio_core::io::Io;
//! # use tokio_jsonrpc::LineCodec;
//! # use futures::{Stream, Sink, Future};
//! #
//! # fn main() {
//! # let mut core = Core::new().unwrap();
//! # let handle = core.handle();
//! #
//! # let listener = TcpListener::bind(&"127.0.0.1:2345".parse().unwrap(), &handle).unwrap();
//! let connections = listener.incoming();
//! let service = connections.for_each(|(stream, _)| {
//!     let messages = stream.framed(LineCodec::new());
//!     let (write, read) = messages.split();
//!     let answers = read.filter_map(|message| {
//!         match message {
//!             _ => unimplemented!(),
//!         }
//!     });
//!     handle.spawn(write.send_all(answers).map(|_| ()).map_err(|_| ()));
//!     Ok(())
//! });
//! # }
//! ```
//!
//! ```rust
//! # extern crate tokio_core;
//! # extern crate tokio_jsonrpc;
//! # extern crate futures;
//! # extern crate serde_json;
//! #
//! # use tokio_core::reactor::Core;
//! # use tokio_core::net::TcpListener;
//! # use tokio_core::io::Io;
//! # use tokio_jsonrpc::{LineCodec, Server, ServerCtl, RPCError, Endpoint};
//! # use futures::{Stream, Sink, Future};
//! # use serde_json::Value;
//! #
//! # fn main() {
//! # let mut core = Core::new().unwrap();
//! # let handle = core.handle();
//! #
//! # let listener = TcpListener::bind(&"127.0.0.1:2345".parse().unwrap(), &handle).unwrap();
//! struct UselessServer;
//!
//! impl Server for UselessServer {
//!     type Success = String;
//!     type RPCCallResult = Result<String, RPCError>;
//!     type NotificationResult = Result<(), ()>;
//!     fn rpc(&self, ctl: &ServerCtl, method: &str, params: &Option<Value>) -> Option<Self::RPCCallResult> {
//!         match method {
//!             "hello" => Some(Ok("world".to_owned())),
//!             _ => None
//!         }
//!     }
//! }
//!
//! let connections = listener.incoming().for_each(|(stream, _)| {
//!     let (client, _server_finished) = Endpoint::new(stream.framed(LineCodec::new()), UselessServer).start(&handle);
//!     client.notify("hello".to_owned(), None);
//!     Ok(())
//! });
//! # }
//! ```

extern crate serde;
// We use the json! macro only in the tests
#[cfg_attr(test, macro_use)]
extern crate serde_json;
#[macro_use]
extern crate serde_derive;
extern crate uuid;
extern crate tokio_core;
extern crate futures;
extern crate futures_mpsc;
extern crate relay;

pub mod message;
pub mod codec;
pub mod endpoint;

pub use message::{Message, Parsed, RPCError};
pub use codec::{Boundary as BoundaryCodec, Line as LineCodec};
pub use endpoint::{Endpoint, Client, Server, ServerCtl};
<commit_msg>Improve example<commit_after>// Copyright 2017 tokio-jsonrpc Developers
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://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.

//! A JSON RPC protocol for the [tokio](https://tokio.rs) framework.
//!
//! This implements the handling of the
//! [JSON RPC 2.0](http://www.jsonrpc.org/specification) specification. The low-level parts are in
//! the [`message`](message/index.html) and the [`codec`](codec/index.html) modules. The first
//! draft of the higher-lever API is in the [`endpoint`](endpoint/index.html) module.
//!
//! # Examples
//!
//! ```rust
//! # extern crate tokio_core;
//! # extern crate tokio_jsonrpc;
//! # extern crate futures;
//! #
//! # use tokio_core::reactor::Core;
//! # use tokio_core::net::TcpListener;
//! # use tokio_core::io::Io;
//! # use tokio_jsonrpc::LineCodec;
//! # use futures::{Stream, Sink, Future};
//! #
//! # fn main() {
//! # let mut core = Core::new().unwrap();
//! # let handle = core.handle();
//! #
//! # let listener = TcpListener::bind(&"127.0.0.1:2345".parse().unwrap(), &handle).unwrap();
//! let connections = listener.incoming();
//! let service = connections.for_each(|(stream, _)| {
//!     let messages = stream.framed(LineCodec::new());
//!     let (write, read) = messages.split();
//!     let answers = read.filter_map(|message| {
//!         match message {
//!             _ => unimplemented!(),
//!         }
//!     });
//!     handle.spawn(write.send_all(answers).map(|_| ()).map_err(|_| ()));
//!     Ok(())
//! });
//! # }
//! ```
//!
//! ```rust
//! # extern crate tokio_core;
//! # extern crate tokio_jsonrpc;
//! # extern crate futures;
//! # extern crate serde_json;
//! #
//! # use tokio_core::reactor::Core;
//! # use tokio_core::net::TcpListener;
//! # use tokio_core::io::Io;
//! # use tokio_jsonrpc::{LineCodec, Server, ServerCtl, RPCError, Endpoint};
//! # use futures::{Stream};
//! # use serde_json::Value;
//! #
//! # fn main() {
//! # let core = Core::new().unwrap();
//! # let handle = core.handle();
//! #
//! # let listener = TcpListener::bind(&"127.0.0.1:2346".parse().unwrap(), &handle).unwrap();
//! struct UselessServer;
//!
//! impl Server for UselessServer {
//!     type Success = String;
//!     type RPCCallResult = Result<String, RPCError>;
//!     type NotificationResult = Result<(), ()>;
//!     fn rpc(&self, ctl: &ServerCtl, method: &str, _params: &Option<Value>) -> Option<Self::RPCCallResult> {
//!         match method {
//!             "hello" => Some(Ok("world".to_owned())),
//!             "bye" => {
//!                 ctl.terminate();
//!                 Some(Ok("bye".to_owned()))
//!             },
//!             _ => None
//!         }
//!     }
//! }
//!
//! let connections = listener.incoming().for_each(|(stream, _)| {
//!     let (client, _server_finished) = Endpoint::new(stream.framed(LineCodec::new()), UselessServer).start(&handle);
//!     client.notify("hello".to_owned(), None);
//!     Ok(())
//! });
//! # drop(connections);
//! # }
//! ```

extern crate serde;
// We use the json! macro only in the tests
#[cfg_attr(test, macro_use)]
extern crate serde_json;
#[macro_use]
extern crate serde_derive;
extern crate uuid;
extern crate tokio_core;
extern crate futures;
extern crate futures_mpsc;
extern crate relay;

pub mod message;
pub mod codec;
pub mod endpoint;

pub use message::{Message, Parsed, RPCError};
pub use codec::{Boundary as BoundaryCodec, Line as LineCodec};
pub use endpoint::{Endpoint, Client, Server, ServerCtl};
<|endoftext|>


<commit_before>//! # quicksort
//!
//! Quicksort is an efficient in-line sorting algorithm created by Tony Hoare.
//!

use std::cmp::Ordering;

/// In-line sorting of a slice of T.
///
/// ```rust
/// # use ironsort::quicksort;
/// let presorted: Vec<u64> = vec![1, 1, 2, 3, 3, 4, 5, 5, 6, 9];
/// let mut vector: Vec<u64> = vec![3, 1, 4, 1, 5, 9, 2, 6, 5, 3];
/// quicksort(&mut vector);
///
/// assert_eq!(vector, presorted.as_slice());
/// ```
#[inline]
pub fn quicksort<T: Ord>(vec: &mut [T]) {
    quicksort_by(vec, &|x, y| x.cmp(y))
}

pub fn quicksort_by<T: PartialOrd, F>(vec: &mut [T], cmp: &F)
    where F: Fn(&T, &T) -> Ordering {
    if vec.len() <= 1 {
        return;
    }
    let pivot: usize = 0;
    let mut first_opened = Vec::new();
    let mut last_closed: usize = 0;

    for i in 1..vec.len() {
        first_opened.push(i);
        match cmp(&vec[i], &vec[pivot]) {
            Ordering::Less => {
                let to = first_opened.remove(0);
                vec.swap(i, to);
                last_closed = to;
            }
            _ => { }
        }
    }

    vec.swap(pivot, last_closed);
    quicksort_by(&mut vec[0..last_closed], cmp);
    quicksort_by(&mut vec[last_closed+1..], cmp);
}

#[cfg(test)]
extern crate rand;

#[cfg(test)]
mod tests {
    use rand::{self, Rng};
    use super::*;

    #[test]
    fn test_vec_of_u64() {
        let presorted: Vec<u64> = vec![1, 1, 2, 3, 3, 4, 5, 5, 6, 9];
        let mut vector: Vec<u64> = vec![3, 1, 4, 1, 5, 9, 2, 6, 5, 3];
        quicksort(&mut vector);

        assert_eq!(vector, presorted.as_slice());
    }

    #[test]
    fn test_vec_of_u8() {
        let presorted = "        Tabcdeeefghhijklmnoooopqrrstuuvwxyz".to_string().into_bytes();
        let mut vector = "The quick brown fox jumps over the lazy dog".to_string().into_bytes();
        quicksort(&mut vector);

        assert_eq!(presorted, vector);
    }

    #[test]
    fn test_array_of_u8() {
        let presorted: [u8; 10] = [1, 2, 3, 4, 5, 5, 5, 7, 9, 10];
        let mut vector: [u8; 10] = [7, 5, 3, 2, 5, 1, 4, 5, 9, 10];
        quicksort(&mut vector);

        assert_eq!(presorted, vector);
    }

    #[test]
    fn test_random() {
        let mut rng = rand::thread_rng();

        for _ in 0u64 .. 10_000u64 {
            let len: usize = rng.gen();
            let mut vector = rng.gen_iter()
                                .take((len % 64) + 1)
                                .collect::<Vec<usize>>();
            quicksort(&mut vector);

            for i in 0 .. vector.len() - 1 {
                assert!(vector[i] <= vector[i + 1])
            }
        }
    }
}
<commit_msg>Use len variable<commit_after>//! # quicksort
//!
//! Quicksort is an efficient in-line sorting algorithm created by Tony Hoare.
//!

use std::cmp::Ordering;

/// In-line sorting of a slice of T.
///
/// ```rust
/// # use ironsort::quicksort;
/// let presorted: Vec<u64> = vec![1, 1, 2, 3, 3, 4, 5, 5, 6, 9];
/// let mut vector: Vec<u64> = vec![3, 1, 4, 1, 5, 9, 2, 6, 5, 3];
/// quicksort(&mut vector);
///
/// assert_eq!(vector, presorted.as_slice());
/// ```
#[inline]
pub fn quicksort<T: Ord>(vec: &mut [T]) {
    quicksort_by(vec, &|x, y| x.cmp(y))
}

pub fn quicksort_by<T: PartialOrd, F>(vec: &mut [T], cmp: &F)
    where F: Fn(&T, &T) -> Ordering {

    let len: usize = vec.len();
    if len <= 1 {
        return;
    }
    let pivot: usize = 0;
    let mut first_opened = Vec::new();
    let mut last_closed: usize = 0;

    for i in 1..vec.len() {
        first_opened.push(i);
        match cmp(&vec[i], &vec[pivot]) {
            Ordering::Less => {
                let to = first_opened.remove(0);
                vec.swap(i, to);
                last_closed = to;
            }
            _ => { }
        }
    }

    vec.swap(pivot, last_closed);
    quicksort_by(&mut vec[0..last_closed], cmp);
    quicksort_by(&mut vec[last_closed+1..], cmp);
}

#[cfg(test)]
extern crate rand;

#[cfg(test)]
mod tests {
    use rand::{self, Rng};
    use super::*;

    #[test]
    fn test_vec_of_u64() {
        let presorted: Vec<u64> = vec![1, 1, 2, 3, 3, 4, 5, 5, 6, 9];
        let mut vector: Vec<u64> = vec![3, 1, 4, 1, 5, 9, 2, 6, 5, 3];
        quicksort(&mut vector);

        assert_eq!(vector, presorted.as_slice());
    }

    #[test]
    fn test_vec_of_u8() {
        let presorted = "        Tabcdeeefghhijklmnoooopqrrstuuvwxyz".to_string().into_bytes();
        let mut vector = "The quick brown fox jumps over the lazy dog".to_string().into_bytes();
        quicksort(&mut vector);

        assert_eq!(presorted, vector);
    }

    #[test]
    fn test_array_of_u8() {
        let presorted: [u8; 10] = [1, 2, 3, 4, 5, 5, 5, 7, 9, 10];
        let mut vector: [u8; 10] = [7, 5, 3, 2, 5, 1, 4, 5, 9, 10];
        quicksort(&mut vector);

        assert_eq!(presorted, vector);
    }

    #[test]
    fn test_random() {
        let mut rng = rand::thread_rng();

        for _ in 0u64 .. 10_000u64 {
            let len: usize = rng.gen();
            let mut vector = rng.gen_iter()
                                .take((len % 64) + 1)
                                .collect::<Vec<usize>>();
            quicksort(&mut vector);

            for i in 0 .. vector.len() - 1 {
                assert!(vector[i] <= vector[i + 1])
            }
        }
    }
}
<|endoftext|>