<commit_before>use super::*;
use memory::alloc::Allocator;

use core::ptr;

extern "C" {
    /// We need this to allocate aligned memory for our heap.
    fn memalign(alignment: usize, size: usize) -> *mut u8;

    // Release our memory.
    fn free(ptr: *mut u8);
}

const HEAP_ALIGN: usize = 4096;
const HEAP_SIZE: usize = 256;

#[test]
fn test_allocation_size_and_order() {
    unsafe {
        let mem = memalign(HEAP_ALIGN, HEAP_SIZE);
        let mut free_lists: [FreeList; 5]
            = [ FreeList::new(), FreeList::new()
              , FreeList::new(), FreeList::new()
              , FreeList::new()
              ];
        let heap = BuddyHeapAllocator::new( mem
                                          , &mut free_lists
                                          , HEAP_SIZE );

        // TEST NEEDED: Can't align beyond MIN_HEAP_ALIGN.

        // Can't align beyond heap_size.
        assert_eq!(None, heap.alloc_size(256, 256*2));

        // Simple allocations just round up to next block size.
        assert_eq!(Some(16), heap.alloc_size(0, 1));
        assert_eq!(Some(16), heap.alloc_size(1, 1));
        assert_eq!(Some(16), heap.alloc_size(16, 1));
        assert_eq!(Some(32), heap.alloc_size(17, 1));
        assert_eq!(Some(32), heap.alloc_size(32, 32));
        assert_eq!(Some(256), heap.alloc_size(256, 256));

        // Aligned allocations use alignment as block size.
        assert_eq!(Some(64), heap.alloc_size(16, 64));

        // Block orders.
        assert_eq!(Some(0), heap.alloc_order(0, 1));
        assert_eq!(Some(0), heap.alloc_order(1, 1));
        assert_eq!(Some(0), heap.alloc_order(16, 16));
        assert_eq!(Some(1), heap.alloc_order(32, 32));
        assert_eq!(Some(2), heap.alloc_order(64, 64));
        assert_eq!(Some(3), heap.alloc_order(128, 128));
        assert_eq!(Some(4), heap.alloc_order(256, 256));
        assert_eq!(None, heap.alloc_order(512, 512));

        free(mem);
    }
}

#[test]
fn test_get_buddy() {
    unsafe {
        let mem = memalign(HEAP_ALIGN, HEAP_SIZE);
        let mut free_lists: [FreeList; 5]
            = [ FreeList::new(), FreeList::new()
              , FreeList::new(), FreeList::new()
              , FreeList::new()
              ];
        let heap = BuddyHeapAllocator::new( mem
                                          , &mut free_lists
                                          , HEAP_SIZE );
        let block_16_0 = mem;
        let block_16_1 = mem.offset(16);
        assert_eq!(Some(block_16_1), heap.get_buddy(0, block_16_0));
        assert_eq!(Some(block_16_0), heap.get_buddy(0, block_16_1));

        let block_32_0 = mem;
        let block_32_1 = mem.offset(32);
        assert_eq!(Some(block_32_1), heap.get_buddy(1, block_32_0));
        assert_eq!(Some(block_32_0), heap.get_buddy(1, block_32_1));

        let block_32_2 = mem.offset(64);
        let block_32_3 = mem.offset(96);
        assert_eq!(Some(block_32_3), heap.get_buddy(1, block_32_2));
        assert_eq!(Some(block_32_2), heap.get_buddy(1, block_32_3));

        let block_256_0 = mem;
        assert_eq!(None, heap.get_buddy(4, block_256_0));

        free(mem);
    }
}

#[test]
fn test_alloc_and_dealloc() {
    unsafe {
        let mem = memalign(HEAP_ALIGN, HEAP_SIZE);
        let mut free_lists: [FreeList; 5]
            = [ FreeList::new(), FreeList::new()
              , FreeList::new(), FreeList::new()
              , FreeList::new()
              ];
        let mut heap = BuddyHeapAllocator::new( mem
                                              , &mut free_lists
                                              , HEAP_SIZE );

        let block_128_0 = heap.allocate(128, 128);
        assert_eq!(Some(mem.offset(0)), block_128_0);

        heap.deallocate(block_128_0.unwrap(), 128,128);

        let block_16_0 = heap.allocate(8, 8);
        assert_eq!(Some(mem), block_16_0);

        let bigger_than_heap = heap.allocate(4096, HEAP_SIZE);
        assert_eq!(None, bigger_than_heap);

        let bigger_than_free = heap.allocate(HEAP_SIZE, HEAP_SIZE);
        assert_eq!(None, bigger_than_free);

        let block_16_1 = heap.allocate(8, 8);
        assert_eq!(Some(mem.offset(16)), block_16_1);

        let block_16_2 = heap.allocate(8, 8);
        assert_eq!(Some(mem.offset(32)), block_16_2);

        let block_32_2 = heap.allocate(32, 32);
        assert_eq!(Some(mem.offset(64)), block_32_2);

        let block_16_3 = heap.allocate(8, 8);
        assert_eq!(Some(mem.offset(48)), block_16_3);

        // let too_fragmented = heap.allocate(64, 64);
        // assert_eq!(None, too_fragmented);
        heap.deallocate(block_16_0.unwrap(), 8, 8);
        heap.deallocate(block_16_3.unwrap(), 8, 8);
        heap.deallocate(block_16_1.unwrap(), 8, 8);
        heap.deallocate(block_16_2.unwrap(), 8, 8);

        heap.deallocate(block_32_2.unwrap(), 32, 32);

        let block_128_0 = heap.allocate(128, 128);
        assert_eq!(Some(mem.offset(0)), block_128_0);

        let block_128_1 = heap.allocate(128, 128);
        assert_eq!(Some(mem.offset(128)), block_128_1);

        heap.deallocate(block_128_1.unwrap(), 128, 128);
        heap.deallocate(block_128_0.unwrap(), 128, 128);

        // And allocate the whole heap, just to make sure everything
        // got cleaned up correctly.
        let block_256_0 = heap.allocate(256, 256).unwrap();
        assert_eq!(mem.offset(0), block_256_0);

        free(mem);
    }
}
<commit_msg>[alloc] fix tests for buddy-block allocator<commit_after>use super::*;

use ::Allocator;

use core::ptr;

extern "C" {
    /// We need this to allocate aligned memory for our heap.
    fn memalign(alignment: usize, size: usize) -> *mut u8;

    // Release our memory.
    fn free(ptr: *mut u8);
}

const HEAP_ALIGN: usize = 4096;
const HEAP_SIZE: usize = 256;

#[test]
fn test_allocation_size_and_order() {
    unsafe {
        let mem = memalign(HEAP_ALIGN, HEAP_SIZE);
        let mut free_lists: [FreeList; 5]
            = [ FreeList::new(), FreeList::new()
              , FreeList::new(), FreeList::new()
              , FreeList::new()
              ];
        let heap = BuddyHeapAllocator::new( mem
                                          , &mut free_lists
                                          , HEAP_SIZE );

        // TEST NEEDED: Can't align beyond MIN_HEAP_ALIGN.

        // Can't align beyond heap_size.
        assert_eq!(None, heap.alloc_size(256, 256*2));

        // Simple allocations just round up to next block size.
        assert_eq!(Some(16), heap.alloc_size(0, 1));
        assert_eq!(Some(16), heap.alloc_size(1, 1));
        assert_eq!(Some(16), heap.alloc_size(16, 1));
        assert_eq!(Some(32), heap.alloc_size(17, 1));
        assert_eq!(Some(32), heap.alloc_size(32, 32));
        assert_eq!(Some(256), heap.alloc_size(256, 256));

        // Aligned allocations use alignment as block size.
        assert_eq!(Some(64), heap.alloc_size(16, 64));

        // Block orders.
        assert_eq!(Some(0), heap.alloc_order(0, 1));
        assert_eq!(Some(0), heap.alloc_order(1, 1));
        assert_eq!(Some(0), heap.alloc_order(16, 16));
        assert_eq!(Some(1), heap.alloc_order(32, 32));
        assert_eq!(Some(2), heap.alloc_order(64, 64));
        assert_eq!(Some(3), heap.alloc_order(128, 128));
        assert_eq!(Some(4), heap.alloc_order(256, 256));
        assert_eq!(None, heap.alloc_order(512, 512));

        free(mem);
    }
}

#[test]
fn test_get_buddy() {
    unsafe {
        let mem = memalign(HEAP_ALIGN, HEAP_SIZE);
        let mut free_lists: [FreeList; 5]
            = [ FreeList::new(), FreeList::new()
              , FreeList::new(), FreeList::new()
              , FreeList::new()
              ];
        let heap = BuddyHeapAllocator::new( mem
                                          , &mut free_lists
                                          , HEAP_SIZE );
        let block_16_0 = mem;
        let block_16_1 = mem.offset(16);
        assert_eq!(Some(block_16_1), heap.get_buddy(0, block_16_0));
        assert_eq!(Some(block_16_0), heap.get_buddy(0, block_16_1));

        let block_32_0 = mem;
        let block_32_1 = mem.offset(32);
        assert_eq!(Some(block_32_1), heap.get_buddy(1, block_32_0));
        assert_eq!(Some(block_32_0), heap.get_buddy(1, block_32_1));

        let block_32_2 = mem.offset(64);
        let block_32_3 = mem.offset(96);
        assert_eq!(Some(block_32_3), heap.get_buddy(1, block_32_2));
        assert_eq!(Some(block_32_2), heap.get_buddy(1, block_32_3));

        let block_256_0 = mem;
        assert_eq!(None, heap.get_buddy(4, block_256_0));

        free(mem);
    }
}

#[test]
fn test_alloc_and_dealloc() {
    unsafe {
        let mem = memalign(HEAP_ALIGN, HEAP_SIZE);
        let mut free_lists: [FreeList; 5]
            = [ FreeList::new(), FreeList::new()
              , FreeList::new(), FreeList::new()
              , FreeList::new()
              ];
        let mut heap = BuddyHeapAllocator::new( mem
                                              , &mut free_lists
                                              , HEAP_SIZE );

        let block_128_0 = heap.allocate(128, 128);
        assert_eq!(Some(mem.offset(0)), block_128_0);

        heap.deallocate(block_128_0.unwrap(), 128,128);

        let block_16_0 = heap.allocate(8, 8);
        assert_eq!(Some(mem), block_16_0);

        let bigger_than_heap = heap.allocate(4096, HEAP_SIZE);
        assert_eq!(None, bigger_than_heap);

        let bigger_than_free = heap.allocate(HEAP_SIZE, HEAP_SIZE);
        assert_eq!(None, bigger_than_free);

        let block_16_1 = heap.allocate(8, 8);
        assert_eq!(Some(mem.offset(16)), block_16_1);

        let block_16_2 = heap.allocate(8, 8);
        assert_eq!(Some(mem.offset(32)), block_16_2);

        let block_32_2 = heap.allocate(32, 32);
        assert_eq!(Some(mem.offset(64)), block_32_2);

        let block_16_3 = heap.allocate(8, 8);
        assert_eq!(Some(mem.offset(48)), block_16_3);

        // let too_fragmented = heap.allocate(64, 64);
        // assert_eq!(None, too_fragmented);
        heap.deallocate(block_16_0.unwrap(), 8, 8);
        heap.deallocate(block_16_3.unwrap(), 8, 8);
        heap.deallocate(block_16_1.unwrap(), 8, 8);
        heap.deallocate(block_16_2.unwrap(), 8, 8);

        heap.deallocate(block_32_2.unwrap(), 32, 32);

        let block_128_0 = heap.allocate(128, 128);
        assert_eq!(Some(mem.offset(0)), block_128_0);

        let block_128_1 = heap.allocate(128, 128);
        assert_eq!(Some(mem.offset(128)), block_128_1);

        heap.deallocate(block_128_1.unwrap(), 128, 128);
        heap.deallocate(block_128_0.unwrap(), 128, 128);

        // And allocate the whole heap, just to make sure everything
        // got cleaned up correctly.
        let block_256_0 = heap.allocate(256, 256).unwrap();
        assert_eq!(mem.offset(0), block_256_0);

        free(mem);
    }
}
<|endoftext|>


<commit_before>/*
 * Copyright 2015-2018 Ben Ashford
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

//! Implementation of ElasticSearch [highlight](https://www.elastic.co/guide/en/elasticsearch/reference/current/search-request-highlighting.html)

use std::collections::HashMap;

use serde::ser::{Serializer};
use serde::Serialize;

#[derive(Debug, Clone)]
pub enum Encoders {
    Default,
    HTML,
}

impl Serialize for Encoders {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        match self {
            Encoders::Default => "default",
            Encoders::HTML => "html",
        }
        .serialize(serializer)
    }
}

#[derive(Debug, Clone)]
pub enum SettingTypes {
    Plain,
    FVH,
    Postings,
}

impl Serialize for SettingTypes {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        match self {
            SettingTypes::Plain => "plain",
            SettingTypes::FVH => "fvh",
            SettingTypes::Postings => "postings",
        }
        .serialize(serializer)
    }
}

#[derive(Debug, Clone)]
pub enum IndexOptions {
    Offsets,
}

impl Serialize for IndexOptions {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        match self {
            IndexOptions::Offsets => "offsets",
        }
        .serialize(serializer)
    }
}

#[derive(Debug, Clone)]
pub enum TermVector {
    WithPositionsOffsets,
    BoundaryChars,
    BoundaryMaxScan,
}

impl Serialize for TermVector {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        match self {
            TermVector::WithPositionsOffsets => "with_positions_offsets",
            TermVector::BoundaryChars => "boundary_chars",
            TermVector::BoundaryMaxScan => "boundary_max_scan",
        }
        .serialize(serializer)
    }
}

#[derive(Debug, Serialize, Clone)]
pub struct Setting {
    #[serde(rename = "type")]
    pub setting_type: Option<SettingTypes>,
    #[cfg(not(feature = "es5"))]
    pub index_options: Option<IndexOptions>,
    #[cfg(not(feature = "es5"))]
    pub term_vector: Option<TermVector>,
    pub force_source: bool,
    pub fragment_size: u32,
    pub number_of_fragments: u32,
    pub no_match_size: u32,
    pub matched_fields: Option<Vec<String>>,
}

impl Default for Setting {
    fn default() -> Self {
        Setting {
            setting_type: None,
            force_source: false,
            fragment_size: 150,
            number_of_fragments: 5,
            no_match_size: 0,
            matched_fields: None,

            #[cfg(not(feature = "es5"))]
            index_options: None,

            #[cfg(not(feature = "es5"))]
            term_vector: None,
        }
    }
}

impl Setting {
    pub fn new() -> Self {
        Default::default()
    }

    pub fn with_type(&mut self, setting_type: SettingTypes) -> &mut Setting {
        self.setting_type = Some(setting_type);
        self
    }

    #[cfg(not(feature = "es5"))]
    pub fn with_index_options(&mut self, index_options: IndexOptions) -> &mut Setting {
        self.index_options = Some(index_options);
        self
    }

    #[cfg(not(feature = "es5"))]
    pub fn with_term_vector(&mut self, term_vector: TermVector) -> &mut Setting {
        self.term_vector = Some(term_vector);
        self
    }

    pub fn with_force_source(&mut self, force_source: bool) -> &mut Setting {
        self.force_source = force_source;
        self
    }

    pub fn with_fragment_size(&mut self, fragment_size: u32) -> &mut Setting {
        self.fragment_size = fragment_size;
        self
    }

    pub fn with_number_of_fragments(&mut self, number_of_fragments: u32) -> &mut Setting {
        self.number_of_fragments = number_of_fragments;
        self
    }

    pub fn with_no_match_size(&mut self, no_match_size: u32) -> &mut Setting {
        self.no_match_size = no_match_size;
        self
    }

    pub fn with_matched_fields(&mut self, matched_fields: Vec<String>) -> &mut Setting {
        self.matched_fields = Some(matched_fields);
        self
    }
}

#[derive(Debug, Default, Serialize, Clone)]
pub struct Highlight {
    pub fields: HashMap<String, Setting>,
    pub pre_tags: Option<Vec<String>>,
    pub post_tags: Option<Vec<String>>,
    pub encoder: Option<Encoders>,
}

impl Highlight {
    /// Create an Highlight entity without any field or setting
    /// specified as they are supposed to be added via the `add`
    /// method.
    ///
    /// # Examples
    ///
    /// ```
    /// use rs_es::operations::search::highlight::{Highlight, Setting, SettingTypes, Encoders};
    ///
    /// let mut highlight = Highlight::new().with_encoder(Encoders::HTML).to_owned();
    /// let setting = Setting::new().with_type(SettingTypes::Plain).to_owned();
    /// highlight.add_setting("first_name".to_owned(), setting);
    /// ```
    pub fn new() -> Highlight {
        Highlight {
            fields: HashMap::new(),
            pre_tags: None,
            post_tags: None,
            encoder: None,
        }
    }

    pub fn with_encoder(&mut self, encoder: Encoders) -> &mut Highlight {
        self.encoder = Some(encoder);
        self
    }

    pub fn with_pre_tags(&mut self, pre_tags: Vec<String>) -> &mut Highlight {
        self.pre_tags = Some(pre_tags);
        self
    }

    pub fn with_post_tags(&mut self, post_tags: Vec<String>) -> &mut Highlight {
        self.post_tags = Some(post_tags);
        self
    }

    /// Add a field to highlight to the set
    pub fn add_setting(&mut self, name: String, setting: Setting) {
        self.fields.insert(name, setting);
    }
}

/// The fields containing found terms
pub type HighlightResult = HashMap<String, Vec<String>>;
<commit_msg>Skip serializing some highlighter fields when they are None<commit_after>/*
 * Copyright 2015-2018 Ben Ashford
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

//! Implementation of ElasticSearch [highlight](https://www.elastic.co/guide/en/elasticsearch/reference/current/search-request-highlighting.html)
use crate::json::ShouldSkip;

use std::collections::HashMap;

use serde::ser::{Serializer};
use serde::Serialize;

#[derive(Debug, Clone)]
pub enum Encoders {
    Default,
    HTML,
}

impl Serialize for Encoders {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        match self {
            Encoders::Default => "default",
            Encoders::HTML => "html",
        }
        .serialize(serializer)
    }
}

#[derive(Debug, Clone)]
pub enum SettingTypes {
    Plain,
    FVH,
    Postings,
}

impl Serialize for SettingTypes {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        match self {
            SettingTypes::Plain => "plain",
            SettingTypes::FVH => "fvh",
            SettingTypes::Postings => "postings",
        }
        .serialize(serializer)
    }
}

#[derive(Debug, Clone)]
pub enum IndexOptions {
    Offsets,
}

impl Serialize for IndexOptions {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        match self {
            IndexOptions::Offsets => "offsets",
        }
        .serialize(serializer)
    }
}

#[derive(Debug, Clone)]
pub enum TermVector {
    WithPositionsOffsets,
    BoundaryChars,
    BoundaryMaxScan,
}

impl Serialize for TermVector {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        match self {
            TermVector::WithPositionsOffsets => "with_positions_offsets",
            TermVector::BoundaryChars => "boundary_chars",
            TermVector::BoundaryMaxScan => "boundary_max_scan",
        }
        .serialize(serializer)
    }
}

#[derive(Debug, Serialize, Clone)]
pub struct Setting {
    #[serde(rename = "type")]
    pub setting_type: Option<SettingTypes>,
    #[cfg(not(feature = "es5"))]
    pub index_options: Option<IndexOptions>,
    #[cfg(not(feature = "es5"))]
    pub term_vector: Option<TermVector>,
    pub force_source: bool,
    pub fragment_size: u32,
    pub number_of_fragments: u32,
    pub no_match_size: u32,
    #[serde(skip_serializing_if = "ShouldSkip::should_skip")]
    pub matched_fields: Option<Vec<String>>,
}

impl Default for Setting {
    fn default() -> Self {
        Setting {
            setting_type: None,
            force_source: false,
            fragment_size: 150,
            number_of_fragments: 5,
            no_match_size: 0,
            matched_fields: None,

            #[cfg(not(feature = "es5"))]
            index_options: None,

            #[cfg(not(feature = "es5"))]
            term_vector: None,
        }
    }
}

impl Setting {
    pub fn new() -> Self {
        Default::default()
    }

    pub fn with_type(&mut self, setting_type: SettingTypes) -> &mut Setting {
        self.setting_type = Some(setting_type);
        self
    }

    #[cfg(not(feature = "es5"))]
    pub fn with_index_options(&mut self, index_options: IndexOptions) -> &mut Setting {
        self.index_options = Some(index_options);
        self
    }

    #[cfg(not(feature = "es5"))]
    pub fn with_term_vector(&mut self, term_vector: TermVector) -> &mut Setting {
        self.term_vector = Some(term_vector);
        self
    }

    pub fn with_force_source(&mut self, force_source: bool) -> &mut Setting {
        self.force_source = force_source;
        self
    }

    pub fn with_fragment_size(&mut self, fragment_size: u32) -> &mut Setting {
        self.fragment_size = fragment_size;
        self
    }

    pub fn with_number_of_fragments(&mut self, number_of_fragments: u32) -> &mut Setting {
        self.number_of_fragments = number_of_fragments;
        self
    }

    pub fn with_no_match_size(&mut self, no_match_size: u32) -> &mut Setting {
        self.no_match_size = no_match_size;
        self
    }

    pub fn with_matched_fields(&mut self, matched_fields: Vec<String>) -> &mut Setting {
        self.matched_fields = Some(matched_fields);
        self
    }
}

#[derive(Debug, Default, Serialize, Clone)]
pub struct Highlight {
    pub fields: HashMap<String, Setting>,
    #[serde(skip_serializing_if = "ShouldSkip::should_skip")]
    pub pre_tags: Option<Vec<String>>,
    #[serde(skip_serializing_if = "ShouldSkip::should_skip")]
    pub post_tags: Option<Vec<String>>,
    #[serde(skip_serializing_if = "ShouldSkip::should_skip")]
    pub encoder: Option<Encoders>,
}

impl Highlight {
    /// Create an Highlight entity without any field or setting
    /// specified as they are supposed to be added via the `add`
    /// method.
    ///
    /// # Examples
    ///
    /// ```
    /// use rs_es::operations::search::highlight::{Highlight, Setting, SettingTypes, Encoders};
    ///
    /// let mut highlight = Highlight::new().with_encoder(Encoders::HTML).to_owned();
    /// let setting = Setting::new().with_type(SettingTypes::Plain).to_owned();
    /// highlight.add_setting("first_name".to_owned(), setting);
    /// ```
    pub fn new() -> Highlight {
        Highlight {
            fields: HashMap::new(),
            pre_tags: None,
            post_tags: None,
            encoder: None,
        }
    }

    pub fn with_encoder(&mut self, encoder: Encoders) -> &mut Highlight {
        self.encoder = Some(encoder);
        self
    }

    pub fn with_pre_tags(&mut self, pre_tags: Vec<String>) -> &mut Highlight {
        self.pre_tags = Some(pre_tags);
        self
    }

    pub fn with_post_tags(&mut self, post_tags: Vec<String>) -> &mut Highlight {
        self.post_tags = Some(post_tags);
        self
    }

    /// Add a field to highlight to the set
    pub fn add_setting(&mut self, name: String, setting: Setting) {
        self.fields.insert(name, setting);
    }
}

/// The fields containing found terms
pub type HighlightResult = HashMap<String, Vec<String>>;
<|endoftext|>


<commit_before>use std::ffi::{CStr, CString};
use std::marker::PhantomData;
use std::path::Path;
use std::ptr;

use openexr_sys::*;

use error::*;
use frame_buffer::FrameBuffer;
use Header;

pub struct ScanlineOutputFile<'a> {
    handle: *mut CEXR_OutputFile,
    header_ref: Header,
    _phantom_1: PhantomData<CEXR_OutputFile>,
    _phantom_2: PhantomData<&'a mut [u8]>,
}

impl<'a> ScanlineOutputFile<'a> {
    pub fn new(path: &Path, header: &Header) -> Result<ScanlineOutputFile<'static>> {
        let c_path = CString::new(path.to_str()
                                      .expect("non-unicode path handling is unimplemented")
                                      .as_bytes())
                .unwrap();
        let mut error_out = ptr::null();
        let mut out = ptr::null_mut();
        let error = unsafe {
            // NOTE: we don't need to keep a copy of the header, because this
            // function makes a deep copy that is stored in the CEXR_OutputFile.
            CEXR_OutputFile_from_file(c_path.as_ptr(), header.handle, 1, &mut out, &mut error_out)
        };
        if error != 0 {
            let msg = unsafe { CStr::from_ptr(error_out) };
            Err(Error::Generic(msg.to_string_lossy().into_owned()))
        } else {
            Ok(ScanlineOutputFile {
                   handle: out,
                   header_ref: Header {
                       // NOTE: We're casting to *mut here to satisfy the
                       // field's type, but importantly we only return a
                       // const & of the Header so it retains const semantics.
                       handle: unsafe { CEXR_OutputFile_header(out) } as *mut CEXR_Header,
                       owned: false,
                       _phantom: PhantomData,
                   },
                _phantom_1: PhantomData,
                _phantom_2: PhantomData,
               })
        }
    }

    pub fn write_pixels(&mut self, framebuffer: &mut FrameBuffer) -> Result<()> {
        framebuffer.validate_header_for_output(self.header())?;

        let mut error_out = ptr::null();

        let error = unsafe {
            CEXR_OutputFile_set_framebuffer(self.handle, framebuffer.handle(), &mut error_out)
        };
        if error != 0 {
            let msg = unsafe { CStr::from_ptr(error_out) };
            return Err(Error::Generic(msg.to_string_lossy().into_owned()));
        }

        let error = unsafe {
            CEXR_OutputFile_write_pixels(self.handle,
                                         framebuffer.dimensions().1 as i32,
                                         &mut error_out)
        };
        if error != 0 {
            let msg = unsafe { CStr::from_ptr(error_out) };
            Err(Error::Generic(msg.to_string_lossy().into_owned()))
        } else {
            Ok(())
        }
    }

    pub fn header(&self) -> &Header {
        &self.header_ref
    }
}

impl<'a> Drop for ScanlineOutputFile<'a> {
    fn drop(&mut self) {
        unsafe { CEXR_OutputFile_delete(self.handle) };
    }
}
<commit_msg>Fix write_pixels FrameBuffer mutability<commit_after>use std::ffi::{CStr, CString};
use std::marker::PhantomData;
use std::path::Path;
use std::ptr;

use openexr_sys::*;

use error::*;
use frame_buffer::FrameBuffer;
use Header;

pub struct ScanlineOutputFile<'a> {
    handle: *mut CEXR_OutputFile,
    header_ref: Header,
    _phantom_1: PhantomData<CEXR_OutputFile>,
    _phantom_2: PhantomData<&'a mut [u8]>,
}

impl<'a> ScanlineOutputFile<'a> {
    pub fn new(path: &Path, header: &Header) -> Result<ScanlineOutputFile<'static>> {
        let c_path = CString::new(path.to_str()
                                      .expect("non-unicode path handling is unimplemented")
                                      .as_bytes())
                .unwrap();
        let mut error_out = ptr::null();
        let mut out = ptr::null_mut();
        let error = unsafe {
            // NOTE: we don't need to keep a copy of the header, because this
            // function makes a deep copy that is stored in the CEXR_OutputFile.
            CEXR_OutputFile_from_file(c_path.as_ptr(), header.handle, 1, &mut out, &mut error_out)
        };
        if error != 0 {
            let msg = unsafe { CStr::from_ptr(error_out) };
            Err(Error::Generic(msg.to_string_lossy().into_owned()))
        } else {
            Ok(ScanlineOutputFile {
                   handle: out,
                   header_ref: Header {
                       // NOTE: We're casting to *mut here to satisfy the
                       // field's type, but importantly we only return a
                       // const & of the Header so it retains const semantics.
                       handle: unsafe { CEXR_OutputFile_header(out) } as *mut CEXR_Header,
                       owned: false,
                       _phantom: PhantomData,
                   },
                _phantom_1: PhantomData,
                _phantom_2: PhantomData,
               })
        }
    }

    pub fn write_pixels(&mut self, framebuffer: &FrameBuffer) -> Result<()> {
        framebuffer.validate_header_for_output(self.header())?;

        let mut error_out = ptr::null();

        let error = unsafe {
            CEXR_OutputFile_set_framebuffer(self.handle, framebuffer.handle(), &mut error_out)
        };
        if error != 0 {
            let msg = unsafe { CStr::from_ptr(error_out) };
            return Err(Error::Generic(msg.to_string_lossy().into_owned()));
        }

        let error = unsafe {
            CEXR_OutputFile_write_pixels(self.handle,
                                         framebuffer.dimensions().1 as i32,
                                         &mut error_out)
        };
        if error != 0 {
            let msg = unsafe { CStr::from_ptr(error_out) };
            Err(Error::Generic(msg.to_string_lossy().into_owned()))
        } else {
            Ok(())
        }
    }

    pub fn header(&self) -> &Header {
        &self.header_ref
    }
}

impl<'a> Drop for ScanlineOutputFile<'a> {
    fn drop(&mut self) {
        unsafe { CEXR_OutputFile_delete(self.handle) };
    }
}
<|endoftext|>


<commit_before>//! Tidy check to enforce rules about platform-specific code in std.
//!
//! This is intended to maintain existing standards of code
//! organization in hopes that the standard library will continue to
//! be refactored to isolate platform-specific bits, making porting
//! easier; where "standard library" roughly means "all the
//! dependencies of the std and test crates".
//!
//! This generally means placing restrictions on where `cfg(unix)`,
//! `cfg(windows)`, `cfg(target_os)` and `cfg(target_env)` may appear,
//! the basic objective being to isolate platform-specific code to the
//! platform-specific `std::sys` modules, and to the allocation,
//! unwinding, and libc crates.
//!
//! Following are the basic rules, though there are currently
//! exceptions:
//!
//! - core may not have platform-specific code.
//! - libpanic_abort may have platform-specific code.
//! - libpanic_unwind may have platform-specific code.
//! - libunwind may have platform-specific code.
//! - other crates in the std facade may not.
//! - std may have platform-specific code in the following places:
//!   - `sys/unix/`
//!   - `sys/windows/`
//!   - `os/`
//!
//! `std/sys_common` should _not_ contain platform-specific code.
//! Finally, because std contains tests with platform-specific
//! `ignore` attributes, once the parser encounters `mod tests`,
//! platform-specific cfgs are allowed. Not sure yet how to deal with
//! this in the long term.

use std::fs::File;
use std::io::Read;
use std::path::Path;
use std::iter::Iterator;

// Paths that may contain platform-specific code.
const EXCEPTION_PATHS: &[&str] = &[
    // std crates
    "src/libpanic_abort",
    "src/libpanic_unwind",
    "src/libunwind",
    // black_box implementation is LLVM-version specific and it uses
    // target_os to tell targets with different LLVM-versions appart
    // (e.g. `wasm32-unknown-emscripten` vs `wasm32-unknown-unknown`):
    "src/libcore/hint.rs",
    "src/libstd/sys/", // Platform-specific code for std lives here.
                       // This has the trailing slash so that sys_common is not excepted.
    "src/libstd/os", // Platform-specific public interfaces
    "src/rtstartup", // Not sure what to do about this. magic stuff for mingw

    // temporary exceptions
    "src/libstd/lib.rs",
    "src/libstd/path.rs",
    "src/libstd/f32.rs",
    "src/libstd/f64.rs",
    // Integration test for platform-specific run-time feature detection:
    "src/libstd/tests/run-time-detect.rs" ,
    "src/libstd/net/test.rs",
    "src/libstd/sys_common/mod.rs",
    "src/libstd/sys_common/net.rs",
    "src/libstd/sys_common/backtrace.rs",
    "src/libterm", // Not sure how to make this crate portable, but test crate needs it.
    "src/libtest", // Probably should defer to unstable `std::sys` APIs.
    "src/libstd/sync/mpsc", // some tests are only run on non-emscripten

    // std testing crates, okay for now at least
    "src/libcore/tests",
    "src/liballoc/tests/lib.rs",

    // The `VaList` implementation must have platform specific code.
    // The Windows implementation of a `va_list` is always a character
    // pointer regardless of the target architecture. As a result,
    // we must use `#[cfg(windows)]` to conditionally compile the
    // correct `VaList` structure for windows.
    "src/libcore/ffi.rs",

    // non-std crates
    "src/test",
    "src/tools",
    "src/librustc",
    "src/librustdoc",
    "src/libsyntax",
    "src/bootstrap",
];

pub fn check(path: &Path, bad: &mut bool) {
    let mut contents = String::new();
    // Sanity check that the complex parsing here works.
    let mut saw_target_arch = false;
    let mut saw_cfg_bang = false;
    super::walk(path, &mut super::filter_dirs, &mut |file| {
        let filestr = file.to_string_lossy().replace("\\", "/");
        if !filestr.ends_with(".rs") { return }

        let is_exception_path = EXCEPTION_PATHS.iter().any(|s| filestr.contains(&**s));
        if is_exception_path { return }

        check_cfgs(&mut contents, &file, bad, &mut saw_target_arch, &mut saw_cfg_bang);
    });

    assert!(saw_target_arch);
    assert!(saw_cfg_bang);
}

fn check_cfgs(contents: &mut String, file: &Path,
              bad: &mut bool, saw_target_arch: &mut bool, saw_cfg_bang: &mut bool) {
    contents.truncate(0);
    t!(t!(File::open(file), file).read_to_string(contents));

    // For now it's ok to have platform-specific code after 'mod tests'.
    let mod_tests_idx = find_test_mod(contents);
    let contents = &contents[..mod_tests_idx];
    // Pull out all `cfg(...)` and `cfg!(...)` strings.
    let cfgs = parse_cfgs(contents);

    let mut line_numbers: Option<Vec<usize>> = None;
    let mut err = |idx: usize, cfg: &str| {
        if line_numbers.is_none() {
            line_numbers = Some(contents.match_indices('\n').map(|(i, _)| i).collect());
        }
        let line_numbers = line_numbers.as_ref().expect("");
        let line = match line_numbers.binary_search(&idx) {
            Ok(_) => unreachable!(),
            Err(i) => i + 1
        };
        tidy_error!(bad, "{}:{}: platform-specific cfg: {}", file.display(), line, cfg);
    };

    for (idx, cfg) in cfgs {
        // Sanity check that the parsing here works.
        if !*saw_target_arch && cfg.contains("target_arch") { *saw_target_arch = true }
        if !*saw_cfg_bang && cfg.contains("cfg!") { *saw_cfg_bang = true }

        let contains_platform_specific_cfg =
            cfg.contains("target_os")
            || cfg.contains("target_env")
            || cfg.contains("target_vendor")
            || cfg.contains("unix")
            || cfg.contains("windows");

        if !contains_platform_specific_cfg { continue }

        let preceeded_by_doc_comment = {
            let pre_contents = &contents[..idx];
            let pre_newline = pre_contents.rfind('\n');
            let pre_doc_comment = pre_contents.rfind("///");
            match (pre_newline, pre_doc_comment) {
                (Some(n), Some(c)) => n < c,
                (None, Some(_)) => true,
                (_, None) => false,
            }
        };

        if preceeded_by_doc_comment { continue }

        err(idx, cfg);
    }
}

fn find_test_mod(contents: &str) -> usize {
    if let Some(mod_tests_idx) = contents.find("mod tests") {
        // Also capture a previous line indicating that "mod tests" is cfg'd out.
        let prev_newline_idx = contents[..mod_tests_idx].rfind('\n').unwrap_or(mod_tests_idx);
        let prev_newline_idx = contents[..prev_newline_idx].rfind('\n');
        if let Some(nl) = prev_newline_idx {
            let prev_line = &contents[nl + 1 .. mod_tests_idx];
            if prev_line.contains("cfg(all(test, not(target_os")
                || prev_line.contains("cfg(all(test, not(any(target_os") {
                nl
            } else {
                mod_tests_idx
            }
        } else {
            mod_tests_idx
        }
    } else {
        contents.len()
    }
}

fn parse_cfgs<'a>(contents: &'a str) -> Vec<(usize, &'a str)> {
    let candidate_cfgs = contents.match_indices("cfg");
    let candidate_cfg_idxs = candidate_cfgs.map(|(i, _)| i);
    // This is puling out the indexes of all "cfg" strings
    // that appear to be tokens followed by a parenthesis.
    let cfgs = candidate_cfg_idxs.filter(|i| {
        let pre_idx = i.saturating_sub(*i);
        let succeeds_non_ident = !contents.as_bytes().get(pre_idx)
            .cloned()
            .map(char::from)
            .map(char::is_alphanumeric)
            .unwrap_or(false);
        let contents_after = &contents[*i..];
        let first_paren = contents_after.find('(');
        let paren_idx = first_paren.map(|ip| i + ip);
        let preceeds_whitespace_and_paren = paren_idx.map(|ip| {
            let maybe_space = &contents[*i + "cfg".len() .. ip];
            maybe_space.chars().all(|c| char::is_whitespace(c) || c == '!')
        }).unwrap_or(false);

        succeeds_non_ident && preceeds_whitespace_and_paren
    });

    cfgs.map(|i| {
        let mut depth = 0;
        let contents_from = &contents[i..];
        for (j, byte) in contents_from.bytes().enumerate() {
            match byte {
                b'(' => {
                    depth += 1;
                }
                b')' => {
                    depth -= 1;
                    if depth == 0 {
                        return (i, &contents_from[..=j]);
                    }
                }
                _ => { }
            }
        }

        unreachable!()
    }).collect()
}
<commit_msg>Rollup merge of #61496 - Mark-Simulacrum:tidy-unbalanced-parens, r=varkor<commit_after>//! Tidy check to enforce rules about platform-specific code in std.
//!
//! This is intended to maintain existing standards of code
//! organization in hopes that the standard library will continue to
//! be refactored to isolate platform-specific bits, making porting
//! easier; where "standard library" roughly means "all the
//! dependencies of the std and test crates".
//!
//! This generally means placing restrictions on where `cfg(unix)`,
//! `cfg(windows)`, `cfg(target_os)` and `cfg(target_env)` may appear,
//! the basic objective being to isolate platform-specific code to the
//! platform-specific `std::sys` modules, and to the allocation,
//! unwinding, and libc crates.
//!
//! Following are the basic rules, though there are currently
//! exceptions:
//!
//! - core may not have platform-specific code.
//! - libpanic_abort may have platform-specific code.
//! - libpanic_unwind may have platform-specific code.
//! - libunwind may have platform-specific code.
//! - other crates in the std facade may not.
//! - std may have platform-specific code in the following places:
//!   - `sys/unix/`
//!   - `sys/windows/`
//!   - `os/`
//!
//! `std/sys_common` should _not_ contain platform-specific code.
//! Finally, because std contains tests with platform-specific
//! `ignore` attributes, once the parser encounters `mod tests`,
//! platform-specific cfgs are allowed. Not sure yet how to deal with
//! this in the long term.

use std::fs::File;
use std::io::Read;
use std::path::Path;
use std::iter::Iterator;

// Paths that may contain platform-specific code.
const EXCEPTION_PATHS: &[&str] = &[
    // std crates
    "src/libpanic_abort",
    "src/libpanic_unwind",
    "src/libunwind",
    // black_box implementation is LLVM-version specific and it uses
    // target_os to tell targets with different LLVM-versions appart
    // (e.g. `wasm32-unknown-emscripten` vs `wasm32-unknown-unknown`):
    "src/libcore/hint.rs",
    "src/libstd/sys/", // Platform-specific code for std lives here.
                       // This has the trailing slash so that sys_common is not excepted.
    "src/libstd/os", // Platform-specific public interfaces
    "src/rtstartup", // Not sure what to do about this. magic stuff for mingw

    // temporary exceptions
    "src/libstd/lib.rs",
    "src/libstd/path.rs",
    "src/libstd/f32.rs",
    "src/libstd/f64.rs",
    // Integration test for platform-specific run-time feature detection:
    "src/libstd/tests/run-time-detect.rs" ,
    "src/libstd/net/test.rs",
    "src/libstd/sys_common/mod.rs",
    "src/libstd/sys_common/net.rs",
    "src/libstd/sys_common/backtrace.rs",
    "src/libterm", // Not sure how to make this crate portable, but test crate needs it.
    "src/libtest", // Probably should defer to unstable `std::sys` APIs.
    "src/libstd/sync/mpsc", // some tests are only run on non-emscripten

    // std testing crates, okay for now at least
    "src/libcore/tests",
    "src/liballoc/tests/lib.rs",

    // The `VaList` implementation must have platform specific code.
    // The Windows implementation of a `va_list` is always a character
    // pointer regardless of the target architecture. As a result,
    // we must use `#[cfg(windows)]` to conditionally compile the
    // correct `VaList` structure for windows.
    "src/libcore/ffi.rs",

    // non-std crates
    "src/test",
    "src/tools",
    "src/librustc",
    "src/librustdoc",
    "src/libsyntax",
    "src/bootstrap",
];

pub fn check(path: &Path, bad: &mut bool) {
    let mut contents = String::new();
    // Sanity check that the complex parsing here works.
    let mut saw_target_arch = false;
    let mut saw_cfg_bang = false;
    super::walk(path, &mut super::filter_dirs, &mut |file| {
        let filestr = file.to_string_lossy().replace("\\", "/");
        if !filestr.ends_with(".rs") { return }

        let is_exception_path = EXCEPTION_PATHS.iter().any(|s| filestr.contains(&**s));
        if is_exception_path { return }

        check_cfgs(&mut contents, &file, bad, &mut saw_target_arch, &mut saw_cfg_bang);
    });

    assert!(saw_target_arch);
    assert!(saw_cfg_bang);
}

fn check_cfgs(contents: &mut String, file: &Path,
              bad: &mut bool, saw_target_arch: &mut bool, saw_cfg_bang: &mut bool) {
    contents.truncate(0);
    t!(t!(File::open(file), file).read_to_string(contents));

    // For now it's ok to have platform-specific code after 'mod tests'.
    let mod_tests_idx = find_test_mod(contents);
    let contents = &contents[..mod_tests_idx];
    // Pull out all `cfg(...)` and `cfg!(...)` strings.
    let cfgs = parse_cfgs(contents);

    let mut line_numbers: Option<Vec<usize>> = None;
    let mut err = |idx: usize, cfg: &str| {
        if line_numbers.is_none() {
            line_numbers = Some(contents.match_indices('\n').map(|(i, _)| i).collect());
        }
        let line_numbers = line_numbers.as_ref().expect("");
        let line = match line_numbers.binary_search(&idx) {
            Ok(_) => unreachable!(),
            Err(i) => i + 1
        };
        tidy_error!(bad, "{}:{}: platform-specific cfg: {}", file.display(), line, cfg);
    };

    for (idx, cfg) in cfgs {
        // Sanity check that the parsing here works.
        if !*saw_target_arch && cfg.contains("target_arch") { *saw_target_arch = true }
        if !*saw_cfg_bang && cfg.contains("cfg!") { *saw_cfg_bang = true }

        let contains_platform_specific_cfg =
            cfg.contains("target_os")
            || cfg.contains("target_env")
            || cfg.contains("target_vendor")
            || cfg.contains("unix")
            || cfg.contains("windows");

        if !contains_platform_specific_cfg { continue }

        let preceeded_by_doc_comment = {
            let pre_contents = &contents[..idx];
            let pre_newline = pre_contents.rfind('\n');
            let pre_doc_comment = pre_contents.rfind("///");
            match (pre_newline, pre_doc_comment) {
                (Some(n), Some(c)) => n < c,
                (None, Some(_)) => true,
                (_, None) => false,
            }
        };

        if preceeded_by_doc_comment { continue }

        err(idx, cfg);
    }
}

fn find_test_mod(contents: &str) -> usize {
    if let Some(mod_tests_idx) = contents.find("mod tests") {
        // Also capture a previous line indicating that "mod tests" is cfg'd out.
        let prev_newline_idx = contents[..mod_tests_idx].rfind('\n').unwrap_or(mod_tests_idx);
        let prev_newline_idx = contents[..prev_newline_idx].rfind('\n');
        if let Some(nl) = prev_newline_idx {
            let prev_line = &contents[nl + 1 .. mod_tests_idx];
            if prev_line.contains("cfg(all(test, not(target_os")
                || prev_line.contains("cfg(all(test, not(any(target_os") {
                nl
            } else {
                mod_tests_idx
            }
        } else {
            mod_tests_idx
        }
    } else {
        contents.len()
    }
}

fn parse_cfgs<'a>(contents: &'a str) -> Vec<(usize, &'a str)> {
    let candidate_cfgs = contents.match_indices("cfg");
    let candidate_cfg_idxs = candidate_cfgs.map(|(i, _)| i);
    // This is puling out the indexes of all "cfg" strings
    // that appear to be tokens followed by a parenthesis.
    let cfgs = candidate_cfg_idxs.filter(|i| {
        let pre_idx = i.saturating_sub(*i);
        let succeeds_non_ident = !contents.as_bytes().get(pre_idx)
            .cloned()
            .map(char::from)
            .map(char::is_alphanumeric)
            .unwrap_or(false);
        let contents_after = &contents[*i..];
        let first_paren = contents_after.find('(');
        let paren_idx = first_paren.map(|ip| i + ip);
        let preceeds_whitespace_and_paren = paren_idx.map(|ip| {
            let maybe_space = &contents[*i + "cfg".len() .. ip];
            maybe_space.chars().all(|c| char::is_whitespace(c) || c == '!')
        }).unwrap_or(false);

        succeeds_non_ident && preceeds_whitespace_and_paren
    });

    cfgs.flat_map(|i| {
        let mut depth = 0;
        let contents_from = &contents[i..];
        for (j, byte) in contents_from.bytes().enumerate() {
            match byte {
                b'(' => {
                    depth += 1;
                }
                b')' => {
                    depth -= 1;
                    if depth == 0 {
                        return Some((i, &contents_from[..=j]));
                    }
                }
                _ => { }
            }
        }

        // if the parentheses are unbalanced just ignore this cfg -- it'll be caught when attempting
        // to run the compiler, and there's no real reason to lint it separately here
        None
    }).collect()
}
<|endoftext|>


<commit_before>

/// A given integer was so big that its representation as a C integer would be
/// negative.
#[derive(Debug)]
pub enum IntegerOrSdlError {
    IntegerOverflows(&'static str, u32),
    SdlError(String)
}

/// Validates and converts the given u32 to a positive C integer.
pub fn validate_int(value: u32, name: &'static str)
        -> Result<::libc::c_int, IntegerOrSdlError> {
    use self::IntegerOrSdlError::*;
    // Many SDL functions will accept `int` values, even if it doesn't make sense
    // for the values to be negative.
    // In the cases that SDL doesn't check negativity, passing negative values
    // could be unsafe.
    // For example, `SDL_JoystickGetButton` uses the index argument to access an
    // array without checking if it's negative, which could potentially lead to
    // segmentation faults.
    if value >= 1 << 31 {
        Err(IntegerOverflows(name, value))
    } else {
        Ok(value as ::libc::c_int)
    }
}

#[cfg(test)]
mod test {
}
<commit_msg>Implement Error for IntegerOrSdlError<commit_after>use std::error::Error;
use std::fmt;

/// A given integer was so big that its representation as a C integer would be
/// negative.
#[derive(Debug)]
pub enum IntegerOrSdlError {
    IntegerOverflows(&'static str, u32),
    SdlError(String)
}

/// Validates and converts the given u32 to a positive C integer.
pub fn validate_int(value: u32, name: &'static str)
        -> Result<::libc::c_int, IntegerOrSdlError> {
    use self::IntegerOrSdlError::*;
    // Many SDL functions will accept `int` values, even if it doesn't make sense
    // for the values to be negative.
    // In the cases that SDL doesn't check negativity, passing negative values
    // could be unsafe.
    // For example, `SDL_JoystickGetButton` uses the index argument to access an
    // array without checking if it's negative, which could potentially lead to
    // segmentation faults.
    if value >= 1 << 31 {
        Err(IntegerOverflows(name, value))
    } else {
        Ok(value as ::libc::c_int)
    }
}

impl fmt::Display for IntegerOrSdlError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use self::IntegerOrSdlError::*;

        match *self {
            IntegerOverflows(name, value) => write!(f, "Integer '{}' overflows ({})", name, value),
            SdlError(ref e) => write!(f, "SDL error: {}", e),
        }
    }
}

impl Error for IntegerOrSdlError {
    fn description(&self) -> &str {
        use self::IntegerOrSdlError::*;

        match *self {
            IntegerOverflows(_, _) => "integer overflow",
            SdlError(ref e) => e,
        }
    }
}
<|endoftext|>


<commit_before>use libc;
use libc::funcs::bsd44;
use std::fs::File;
use std::fs::OpenOptions;
use std::os::unix::io::*;

#[cfg(target_os="macos")]
const TIOCGWINSZ: libc::c_ulong = 0x40087468;

#[cfg(target_os="linux")]
const TIOCGWINSZ: libc::c_int = 0x5413;

pub struct Window {
    pub tty: File,
    pub size: WindowSize,
}

impl Window {
    pub fn new() -> Window {
        Window {
            tty: {
                OpenOptions::new()
                    .read(true)
                    .write(true)
                    .open("/dev/tty").unwrap()
            },
            size: WindowSize::new(),
        }
    }

    pub fn update_size(&mut self) {
        unsafe {
            bsd44::ioctl(self.tty.as_raw_fd(), TIOCGWINSZ, &self.size)
        };
    }

    pub fn rows(&self) -> u16 {
        self.size.ws_row as u16
    }

    pub fn cols(&self) -> u16 {
        self.size.ws_col as u16
    }
}

#[repr(C)]
pub struct WindowSize {
    pub ws_row: libc::c_ushort,
    pub ws_col: libc::c_ushort,
    pub ws_xpixel: libc::c_ushort,
    pub ws_ypixel: libc::c_ushort,
}

impl WindowSize {
    pub fn new() -> WindowSize {
        WindowSize {
            ws_row: 0,
            ws_col: 0,
            ws_xpixel: 0,
            ws_ypixel: 0,
        }
    }
}

<commit_msg>make windowsize private<commit_after>use libc;
use libc::funcs::bsd44;
use std::fs::File;
use std::fs::OpenOptions;
use std::os::unix::io::*;

#[cfg(target_os="macos")]
const TIOCGWINSZ: libc::c_ulong = 0x40087468;

#[cfg(target_os="linux")]
const TIOCGWINSZ: libc::c_int = 0x5413;

pub struct Window {
    pub tty: File,
    size: WindowSize,
}

impl Window {
    pub fn new() -> Window {
        Window {
            tty: {
                OpenOptions::new()
                    .read(true)
                    .write(true)
                    .open("/dev/tty").unwrap()
            },
            size: WindowSize::new(),
        }
    }

    pub fn update_size(&mut self) {
        unsafe {
            bsd44::ioctl(self.tty.as_raw_fd(), TIOCGWINSZ, &self.size)
        };
    }

    pub fn rows(&self) -> u16 {
        self.size.ws_row as u16
    }

    pub fn cols(&self) -> u16 {
        self.size.ws_col as u16
    }
}

#[repr(C)]
struct WindowSize {
    ws_row: libc::c_ushort,
    ws_col: libc::c_ushort,
    ws_xpixel: libc::c_ushort,
    ws_ypixel: libc::c_ushort,
}

impl WindowSize {
    fn new() -> WindowSize {
        WindowSize {
            ws_row: 0,
            ws_col: 0,
            ws_xpixel: 0,
            ws_ypixel: 0,
        }
    }
}

<|endoftext|>


<commit_before>#![cfg(test)]

use std::collections::HashMap;
use rustc_serialize::json;
use rustc_serialize::json::{decode, Json, Object};
use rustc_serialize::{Decoder, Decodable};
use std::io::prelude::*;
use std::fs::File;
use token::{Token, ReservedWord};

pub struct ExpectPass {
    source: String,
    expected: Json,
    options: Option<Json>
}

pub struct ExpectFail {
    source: String,
    error: String,
    options: Option<Json>
}

pub enum TestCase {
    Pass(ExpectPass),
    Fail(ExpectFail)
}

trait JsonExt {
    fn into_array(self) -> json::Array;
    fn into_string(self) -> String;
    fn into_string_opt(self) -> Option<String>;
}

impl JsonExt for Json {
    fn into_array(self) -> json::Array {
        match self {
            Json::Array(array) => array,
            _ => panic!("expected array")
        }
    }
    fn into_string(self) -> String {
        match self {
            Json::String(string) => string,
            _ => panic!("expected string")
        }
    }
    fn into_string_opt(self) -> Option<String> {
        match self {
            Json::Null => None,
            Json::String(string) => Some(string),
            _ => panic!("expected string or null")
        }
    }
}

fn parse_expect_fail(test: &mut Object) -> ExpectFail {
    ExpectFail {
        source: test.remove("source").unwrap().into_string(),
        error: test.remove("error").unwrap().into_string(),
        options: None
    }
}

fn parse_expect_pass(test: &mut Object) -> ExpectPass {
    ExpectPass {
        source: test.remove("source").unwrap().into_string(),
        expected: test.remove("expected").unwrap(),
        options: None
    }
}

trait Matcher {
    fn test(self: Box<Self>, arg: &mut Object) -> Option<Token>;
}

impl<F> Matcher for F
    where F: FnOnce(&mut Object) -> Option<Token>
{
    fn test(self: Box<F>, arg: &mut Object) -> Option<Token> {
        self(arg)
    }
}

fn matcher<F:FnOnce(&mut Object) -> Option<Token> + 'static>(f: F) -> Box<Matcher> {
    Box::new(f)
}

fn nullary(token: Token) -> Box<Matcher> {
    matcher(|_| { Some(token) })
}

fn unary_string<F:Fn(String) -> Token>(f: F) -> Box<Matcher> {
    matcher(|data| {
        data.remove("value")
            .map(|str| f(str.into_string()))
    })
}

fn deserialize_token(mut data: Json) -> Token {
    let mut obj = data.as_object_mut().unwrap();
    let ty = obj.remove("type").unwrap().into_string();

    let mut matchers: HashMap<&str, Box<Matcher>> = HashMap::new();
    matchers.insert("LBrace", nullary(Token::LBrace));
    matchers.insert("DecimalInt", matcher(|data| -> Option<Token> {
        match data.remove("value") {
            None => None,
            Some(str) => Some(Token::DecimalInt(str.into_string()))
        }
    }));
    matchers.insert("String", unary_string(Token::String));

    let f = matchers.remove("DecimalInt").unwrap();
    let mut data = Json::from_str("{\"type\":\"DecimalInt\",\"value\":\"11.3\"}").unwrap();
    let obj = data.as_object_mut().unwrap();
    f.test(obj).unwrap()
}

fn parse_test(mut test: Json) -> TestCase {
    let obj = test.as_object_mut().unwrap();
    if obj.contains_key("error") {
        TestCase::Fail(parse_expect_fail(obj))
    } else {
        TestCase::Pass(parse_expect_pass(obj))
    }
}

pub fn read_tests(path: &str) -> Vec<TestCase> {
    let mut f: File = File::open(path).unwrap();
    let mut s = String::new();
    f.read_to_string(&mut s);
    parse_tests(&s)
}

pub fn parse_tests(src: &str) -> Vec<TestCase> {
    let data: Json = src.parse().unwrap();
    data.into_array()
        .into_iter()
        .map(parse_test)
        .collect()
}
<commit_msg>tried adding 'static bound as the error suggested, still a lifetime error src/test/mod.rs:93:13: 96:6 error: `f` does not live long enough src/test/mod.rs:93     matcher(|data| { src/test/mod.rs:94         data.remove("value") src/test/mod.rs:95             .map(|str| f(str.into_string())) src/test/mod.rs:96     }) note: reference must be valid for the static lifetime... src/test/mod.rs:92:72: 97:2 note: ...but borrowed value is only valid for the block at 92:71 src/test/mod.rs:92 fn unary_string<F:Fn(String) -> Token + 'static>(f: F) -> Box<Matcher> { src/test/mod.rs:93     matcher(|data| { src/test/mod.rs:94         data.remove("value") src/test/mod.rs:95             .map(|str| f(str.into_string())) src/test/mod.rs:96     }) src/test/mod.rs:97 }<commit_after>#![cfg(test)]

use std::collections::HashMap;
use rustc_serialize::json;
use rustc_serialize::json::{decode, Json, Object};
use rustc_serialize::{Decoder, Decodable};
use std::io::prelude::*;
use std::fs::File;
use token::{Token, ReservedWord};

pub struct ExpectPass {
    source: String,
    expected: Json,
    options: Option<Json>
}

pub struct ExpectFail {
    source: String,
    error: String,
    options: Option<Json>
}

pub enum TestCase {
    Pass(ExpectPass),
    Fail(ExpectFail)
}

trait JsonExt {
    fn into_array(self) -> json::Array;
    fn into_string(self) -> String;
    fn into_string_opt(self) -> Option<String>;
}

impl JsonExt for Json {
    fn into_array(self) -> json::Array {
        match self {
            Json::Array(array) => array,
            _ => panic!("expected array")
        }
    }
    fn into_string(self) -> String {
        match self {
            Json::String(string) => string,
            _ => panic!("expected string")
        }
    }
    fn into_string_opt(self) -> Option<String> {
        match self {
            Json::Null => None,
            Json::String(string) => Some(string),
            _ => panic!("expected string or null")
        }
    }
}

fn parse_expect_fail(test: &mut Object) -> ExpectFail {
    ExpectFail {
        source: test.remove("source").unwrap().into_string(),
        error: test.remove("error").unwrap().into_string(),
        options: None
    }
}

fn parse_expect_pass(test: &mut Object) -> ExpectPass {
    ExpectPass {
        source: test.remove("source").unwrap().into_string(),
        expected: test.remove("expected").unwrap(),
        options: None
    }
}

trait Matcher {
    fn test(self: Box<Self>, arg: &mut Object) -> Option<Token>;
}

impl<F> Matcher for F
    where F: FnOnce(&mut Object) -> Option<Token>
{
    fn test(self: Box<F>, arg: &mut Object) -> Option<Token> {
        self(arg)
    }
}

fn matcher<F:FnOnce(&mut Object) -> Option<Token> + 'static>(f: F) -> Box<Matcher> {
    Box::new(f)
}

fn nullary(token: Token) -> Box<Matcher> {
    matcher(|_| { Some(token) })
}

fn unary_string<F:Fn(String) -> Token + 'static>(f: F) -> Box<Matcher> {
    matcher(|data| {
        data.remove("value")
            .map(|str| f(str.into_string()))
    })
}

fn deserialize_token(mut data: Json) -> Token {
    let mut obj = data.as_object_mut().unwrap();
    let ty = obj.remove("type").unwrap().into_string();

    let mut matchers: HashMap<&str, Box<Matcher>> = HashMap::new();
    matchers.insert("LBrace", nullary(Token::LBrace));
    matchers.insert("DecimalInt", matcher(|data| -> Option<Token> {
        match data.remove("value") {
            None => None,
            Some(str) => Some(Token::DecimalInt(str.into_string()))
        }
    }));
    matchers.insert("String", unary_string(Token::String));

    let f = matchers.remove("DecimalInt").unwrap();
    let mut data = Json::from_str("{\"type\":\"DecimalInt\",\"value\":\"11.3\"}").unwrap();
    let obj = data.as_object_mut().unwrap();
    f.test(obj).unwrap()
}

fn parse_test(mut test: Json) -> TestCase {
    let obj = test.as_object_mut().unwrap();
    if obj.contains_key("error") {
        TestCase::Fail(parse_expect_fail(obj))
    } else {
        TestCase::Pass(parse_expect_pass(obj))
    }
}

pub fn read_tests(path: &str) -> Vec<TestCase> {
    let mut f: File = File::open(path).unwrap();
    let mut s = String::new();
    f.read_to_string(&mut s);
    parse_tests(&s)
}

pub fn parse_tests(src: &str) -> Vec<TestCase> {
    let data: Json = src.parse().unwrap();
    data.into_array()
        .into_iter()
        .map(parse_test)
        .collect()
}
<|endoftext|>


<commit_before>//! The following code generates a 1s long, 16-bit, 440Hz sinewave at a 44100Hz sample rate.
//! It then writes the generated samples into a 44100Hz WAV file at `out/sine.wav`.
//!
//! ```ignore
//! use synthrs::wave::SineWave;
//! use synthrs::writer::write_wav;
//! use synthrs::synthesizer::{quantize_samples, make_samples};
//!
//! write_wav("out/sine.wav", 44100,
//!     quantize_samples::<i16>(make_samples(1.0, 44100, SineWave(440.0)))
//! ).ok().expect("failed");
//! ```
//!
//! See: `examples/simple.rs`

use std::mem::size_of;

use num::Float;
use num::traits::FromPrimitive;

use filter;
use music;
use midi;
use wave;

/// Quantizes a `f64` sample into `T`.
pub fn quantize<T>(input: f64) -> T where T: FromPrimitive {
    let quantization_levels = 2.0.powf(size_of::<T>() as f64 * 8.0) - 1.0;
    // Convert from [-1, 1] to take up full quantization range
    T::from_f64(input * (quantization_levels / 2.0)).expect("failed to quantize to given type")
}

/// Quantizes a `Vec<f64>` of samples into `Vec<T>`.
///
/// This creates a 16-bit SineWave at 440Hz:
///
/// ```
/// use synthrs::wave::SineWave;
/// use synthrs::synthesizer::{quantize_samples, make_samples};
///
/// quantize_samples::<i16>(make_samples(1.0, 44100, SineWave(440.0)));
/// ```
pub fn quantize_samples<T>(input: Vec<f64>) -> Vec<T> where T: FromPrimitive {
    input.iter().map(|s| { quantize::<T>(*s) }).collect()
}

/// Invokes the waveform function `f` at time `t` to return the amplitude at that time.
pub fn generate<F>(t: f64, f: &F) -> f64 where F: Fn(f64) -> f64 {
    f.call((t, ))
}

pub fn make_samples<F>(length: f64, sample_rate: usize, waveform: F) -> Vec<f64> where F: Fn(f64) -> f64 {
    let num_samples = (sample_rate as f64 * length).floor() as usize;
    let mut samples: Vec<f64> = Vec::with_capacity(num_samples);

    for i in 0usize..num_samples {
        let t = i as f64 / sample_rate as f64;
        samples.push(generate(t, &waveform));
    }

    samples
}

/// Peak normalizes a `Vec<f64>` of samples such that the maximum and minimum amplitudes of the
/// `Vec<f64>` samples are within the range [-1.0, 1.0]
pub fn peak_normalize(samples: Vec<f64>) -> Vec<f64> {
    let peak = samples.iter().fold(0.0f64, |acc, &sample| {
        acc.max(sample)
    });

    samples.iter().map(|&sample| {
        sample / peak
    }).collect()
}

// This is really awful, is there a more elegant way to do this?
// TODO: Make the instrument a parameter (perhaps using an Instrument trait?)
pub fn make_samples_from_midi(sample_rate: usize, filename: &str) -> Vec<f64> {
    let song = midi::read_midi(filename).unwrap();
    let length = (60.0 * song.max_time as f64) / (song.bpm * song.time_unit as f64);

    let mut notes_on_for_ticks: Vec<Vec<(u8, u8, usize)>> = Vec::new();
    for _ in 0..song.max_time {
        let notes_on_for_tick: Vec<(u8, u8, usize)> = Vec::new();
        notes_on_for_ticks.push(notes_on_for_tick);
    }

    for track in song.tracks.iter() {
        for i in 0..track.events.len() {
            let event = track.events[i];
            if event.event_type == midi::EventType::NoteOn {
                let start_tick = event.time;
                let note = event.value1;
                let velocity = event.value2.unwrap();

                let mut end_tick = song.max_time;
                for j in i..track.events.len() {
                    let event_cursor = track.events[j];

                    if event_cursor.value1 == note && event_cursor.is_note_terminating() {
                        end_tick = event_cursor.time;
                        break;
                    }
                }

                for tick in start_tick..end_tick {
                    notes_on_for_ticks[tick].push((note as u8, velocity as u8, start_tick));
                }
            }
        }
    }

    let midi_frequency_function = |t: f64| -> f64 {
        let tick = (t * song.bpm * song.time_unit as f64 / 60.0) as usize;
        let mut out = 0.0;

        if tick < notes_on_for_ticks.len() {
            for &(note, velocity, start_tick) in notes_on_for_ticks[tick].iter() {
                let frequency = music::note_midi(440.0, note as usize);
                let loudness = (6.908 * (velocity as f64 / 255.0)).exp() / 1000.0;
                let attack = 0.01;
                let decay = 1.0;
                let start_t = start_tick as f64 * 60.0 / song.bpm as f64 / song.time_unit as f64;
                let relative_t = t - start_t;
                out += loudness * wave::SquareWave(frequency)(t) * filter::envelope(relative_t, attack, decay)

            }
        }

        out
    };

    let num_samples = (sample_rate as f64 * length).floor() as usize;
    let mut samples: Vec<f64> = Vec::with_capacity(num_samples);

    for i in 0usize..num_samples {
        let t = i as f64 / sample_rate as f64;
        samples.push(midi_frequency_function(t));
    }

    peak_normalize(samples)
}
<commit_msg>Consider <= -1 when normalising peaks<commit_after>//! The following code generates a 1s long, 16-bit, 440Hz sinewave at a 44100Hz sample rate.
//! It then writes the generated samples into a 44100Hz WAV file at `out/sine.wav`.
//!
//! ```ignore
//! use synthrs::wave::SineWave;
//! use synthrs::writer::write_wav;
//! use synthrs::synthesizer::{quantize_samples, make_samples};
//!
//! write_wav("out/sine.wav", 44100,
//!     quantize_samples::<i16>(make_samples(1.0, 44100, SineWave(440.0)))
//! ).ok().expect("failed");
//! ```
//!
//! See: `examples/simple.rs`

use std::mem::size_of;

use num::Float;
use num::traits::FromPrimitive;

use filter;
use music;
use midi;
use wave;

/// Quantizes a `f64` sample into `T`.
pub fn quantize<T>(input: f64) -> T where T: FromPrimitive {
    let quantization_levels = 2.0.powf(size_of::<T>() as f64 * 8.0) - 1.0;
    // Convert from [-1, 1] to take up full quantization range
    T::from_f64(input * (quantization_levels / 2.0)).expect("failed to quantize to given type")
}

/// Quantizes a `Vec<f64>` of samples into `Vec<T>`.
///
/// This creates a 16-bit SineWave at 440Hz:
///
/// ```
/// use synthrs::wave::SineWave;
/// use synthrs::synthesizer::{quantize_samples, make_samples};
///
/// quantize_samples::<i16>(make_samples(1.0, 44100, SineWave(440.0)));
/// ```
pub fn quantize_samples<T>(input: Vec<f64>) -> Vec<T> where T: FromPrimitive {
    input.iter().map(|s| { quantize::<T>(*s) }).collect()
}

/// Invokes the waveform function `f` at time `t` to return the amplitude at that time.
pub fn generate<F>(t: f64, f: &F) -> f64 where F: Fn(f64) -> f64 {
    f.call((t, ))
}

pub fn make_samples<F>(length: f64, sample_rate: usize, waveform: F) -> Vec<f64> where F: Fn(f64) -> f64 {
    let num_samples = (sample_rate as f64 * length).floor() as usize;
    let mut samples: Vec<f64> = Vec::with_capacity(num_samples);

    for i in 0usize..num_samples {
        let t = i as f64 / sample_rate as f64;
        samples.push(generate(t, &waveform));
    }

    samples
}

/// Peak normalizes a `Vec<f64>` of samples such that the maximum and minimum amplitudes of the
/// `Vec<f64>` samples are within the range [-1.0, 1.0]
pub fn peak_normalize(samples: Vec<f64>) -> Vec<f64> {
    let peak = samples.iter().fold(0.0f64, |acc, &sample| {
        acc.max(sample).max(-sample)
    });

    samples.iter().map(|&sample| {
        sample / peak
    }).collect()
}

// This is really awful, is there a more elegant way to do this?
// TODO: Make the instrument a parameter (perhaps using an Instrument trait?)
pub fn make_samples_from_midi(sample_rate: usize, filename: &str) -> Vec<f64> {
    let song = midi::read_midi(filename).unwrap();
    let length = (60.0 * song.max_time as f64) / (song.bpm * song.time_unit as f64);

    let mut notes_on_for_ticks: Vec<Vec<(u8, u8, usize)>> = Vec::new();
    for _ in 0..song.max_time {
        let notes_on_for_tick: Vec<(u8, u8, usize)> = Vec::new();
        notes_on_for_ticks.push(notes_on_for_tick);
    }

    for track in song.tracks.iter() {
        for i in 0..track.events.len() {
            let event = track.events[i];
            if event.event_type == midi::EventType::NoteOn {
                let start_tick = event.time;
                let note = event.value1;
                let velocity = event.value2.unwrap();

                let mut end_tick = song.max_time;
                for j in i..track.events.len() {
                    let event_cursor = track.events[j];

                    if event_cursor.value1 == note && event_cursor.is_note_terminating() {
                        end_tick = event_cursor.time;
                        break;
                    }
                }

                for tick in start_tick..end_tick {
                    notes_on_for_ticks[tick].push((note as u8, velocity as u8, start_tick));
                }
            }
        }
    }

    let midi_frequency_function = |t: f64| -> f64 {
        let tick = (t * song.bpm * song.time_unit as f64 / 60.0) as usize;
        let mut out = 0.0;

        if tick < notes_on_for_ticks.len() {
            for &(note, velocity, start_tick) in notes_on_for_ticks[tick].iter() {
                let frequency = music::note_midi(440.0, note as usize);
                let loudness = (6.908 * (velocity as f64 / 255.0)).exp() / 1000.0;
                let attack = 0.01;
                let decay = 1.0;
                let start_t = start_tick as f64 * 60.0 / song.bpm as f64 / song.time_unit as f64;
                let relative_t = t - start_t;
                out += loudness * wave::SquareWave(frequency)(t) * filter::envelope(relative_t, attack, decay)

            }
        }

        out
    };

    let num_samples = (sample_rate as f64 * length).floor() as usize;
    let mut samples: Vec<f64> = Vec::with_capacity(num_samples);

    for i in 0usize..num_samples {
        let t = i as f64 / sample_rate as f64;
        samples.push(midi_frequency_function(t));
    }

    peak_normalize(samples)
}
<|endoftext|>


<commit_before>use Context;
use math::{multiply, shear, scale, orient, rotate_radians, translate, Matrix2d, Vec2d, Scalar};
use radians::Radians;

/// Implemented by contexts that can transform.
pub trait Transformed: Sized {
    /// Appends transform to the current one.
    fn append_transform(self, transform: Matrix2d) -> Self;

    /// Prepends transform to the current one.
    fn prepend_transform(self, transform: Matrix2d) -> Self;

    /// Translate x an y in local coordinates.
    fn trans(self, x: Scalar, y: Scalar) -> Self;

    /// Rotates degrees in local coordinates.
    #[inline(always)]
    fn rot_deg(self, angle: Scalar) -> Self {
        let pi: Scalar = Radians::_180();
        self.rot_rad(angle * pi / 180.0)
    }

    /// Rotate radians in local coordinates.
    fn rot_rad(self, angle: Scalar) -> Self;

    /// Orients x axis to look at point locally.
    ///
    /// Leaves x axis unchanged if the point to
    /// look at is the origin.
    fn orient(self, x: Scalar, y: Scalar) -> Self;

    /// Scales in local coordinates.
    fn scale(self, sx: Scalar, sy: Scalar) -> Self;

    /// Scales in both directions in local coordinates.
    #[inline(always)]
    fn zoom(self, s: Scalar) -> Self {
        self.scale(s, s)
    }

    /// Flips vertically in local coordinates.
    #[inline(always)]
    fn flip_v(self) -> Self {
        self.scale(1.0, -1.0)
    }

    /// Flips horizontally in local coordinates.
    #[inline(always)]
    fn flip_h(self) -> Self {
        self.scale(-1.0, 1.0)
    }

    /// Flips horizontally and vertically in local coordinates.
    #[inline(always)]
    fn flip_hv(self) -> Self {
        self.scale(-1.0, -1.0)
    }

    /// Shears in local coordinates.
    fn shear(self, v: Vec2d) -> Self;
}

impl Transformed for Matrix2d {
    #[inline(always)]
    fn append_transform(self, transform: Matrix2d) -> Self {
        multiply(self, transform)
    }

    #[inline(always)]
    fn prepend_transform(self, transform: Matrix2d) -> Self {
        multiply(transform, self)
    }

    #[inline(always)]
    fn trans(self, x: Scalar, y: Scalar) -> Self {
        let trans = translate([x, y]);
        multiply(self, trans)
    }

    #[inline(always)]
    fn rot_rad(self, angle: Scalar) -> Self {
        let rot = rotate_radians(angle);
        multiply(self, rot)
    }

    #[inline(always)]
    fn orient(self, x: Scalar, y: Scalar) -> Self {
        let orient = orient(x, y);
        multiply(self, orient)
    }

    #[inline(always)]
    fn scale(self, sx: Scalar, sy: Scalar) -> Self {
        let scale = scale(sx, sy);
        multiply(self, scale)
    }

    #[inline(always)]
    fn shear(self, v: Vec2d) -> Self {
        let shear = shear(v);
        multiply(self, shear)
    }
}

impl Transformed for Context {
    #[inline(always)]
    fn append_transform(mut self, transform: Matrix2d) -> Self {
        self.transform = self.transform.append_transform(transform);
        self
    }

    #[inline(always)]
    fn prepend_transform(mut self, transform: Matrix2d) -> Self {
        self.transform = self.transform.prepend_transform(transform);
        self
    }

    #[inline(always)]
    fn trans(mut self, x: Scalar, y: Scalar) -> Self {
        self.transform = self.transform.trans(x, y);
        self
    }

    #[inline(always)]
    fn rot_rad(mut self, angle: Scalar) -> Self {
        self.transform = self.transform.rot_rad(angle);
        self
    }

    #[inline(always)]
    fn orient(mut self, x: Scalar, y: Scalar) -> Self {
        self.transform = self.transform.orient(x, y);
        self
    }

    #[inline(always)]
    fn scale(mut self, sx: Scalar, sy: Scalar) -> Self {
        self.transform = self.transform.scale(sx, sy);
        self
    }

    #[inline(always)]
    fn shear(mut self, v: Vec2d) -> Self {
        self.transform = self.transform.shear(v);
        self
    }
}
<commit_msg>`x an y` -> `x and y`<commit_after>use Context;
use math::{multiply, shear, scale, orient, rotate_radians, translate, Matrix2d, Vec2d, Scalar};
use radians::Radians;

/// Implemented by contexts that can transform.
pub trait Transformed: Sized {
    /// Appends transform to the current one.
    fn append_transform(self, transform: Matrix2d) -> Self;

    /// Prepends transform to the current one.
    fn prepend_transform(self, transform: Matrix2d) -> Self;

    /// Translate x and y in local coordinates.
    fn trans(self, x: Scalar, y: Scalar) -> Self;

    /// Rotates degrees in local coordinates.
    #[inline(always)]
    fn rot_deg(self, angle: Scalar) -> Self {
        let pi: Scalar = Radians::_180();
        self.rot_rad(angle * pi / 180.0)
    }

    /// Rotate radians in local coordinates.
    fn rot_rad(self, angle: Scalar) -> Self;

    /// Orients x axis to look at point locally.
    ///
    /// Leaves x axis unchanged if the point to
    /// look at is the origin.
    fn orient(self, x: Scalar, y: Scalar) -> Self;

    /// Scales in local coordinates.
    fn scale(self, sx: Scalar, sy: Scalar) -> Self;

    /// Scales in both directions in local coordinates.
    #[inline(always)]
    fn zoom(self, s: Scalar) -> Self {
        self.scale(s, s)
    }

    /// Flips vertically in local coordinates.
    #[inline(always)]
    fn flip_v(self) -> Self {
        self.scale(1.0, -1.0)
    }

    /// Flips horizontally in local coordinates.
    #[inline(always)]
    fn flip_h(self) -> Self {
        self.scale(-1.0, 1.0)
    }

    /// Flips horizontally and vertically in local coordinates.
    #[inline(always)]
    fn flip_hv(self) -> Self {
        self.scale(-1.0, -1.0)
    }

    /// Shears in local coordinates.
    fn shear(self, v: Vec2d) -> Self;
}

impl Transformed for Matrix2d {
    #[inline(always)]
    fn append_transform(self, transform: Matrix2d) -> Self {
        multiply(self, transform)
    }

    #[inline(always)]
    fn prepend_transform(self, transform: Matrix2d) -> Self {
        multiply(transform, self)
    }

    #[inline(always)]
    fn trans(self, x: Scalar, y: Scalar) -> Self {
        let trans = translate([x, y]);
        multiply(self, trans)
    }

    #[inline(always)]
    fn rot_rad(self, angle: Scalar) -> Self {
        let rot = rotate_radians(angle);
        multiply(self, rot)
    }

    #[inline(always)]
    fn orient(self, x: Scalar, y: Scalar) -> Self {
        let orient = orient(x, y);
        multiply(self, orient)
    }

    #[inline(always)]
    fn scale(self, sx: Scalar, sy: Scalar) -> Self {
        let scale = scale(sx, sy);
        multiply(self, scale)
    }

    #[inline(always)]
    fn shear(self, v: Vec2d) -> Self {
        let shear = shear(v);
        multiply(self, shear)
    }
}

impl Transformed for Context {
    #[inline(always)]
    fn append_transform(mut self, transform: Matrix2d) -> Self {
        self.transform = self.transform.append_transform(transform);
        self
    }

    #[inline(always)]
    fn prepend_transform(mut self, transform: Matrix2d) -> Self {
        self.transform = self.transform.prepend_transform(transform);
        self
    }

    #[inline(always)]
    fn trans(mut self, x: Scalar, y: Scalar) -> Self {
        self.transform = self.transform.trans(x, y);
        self
    }

    #[inline(always)]
    fn rot_rad(mut self, angle: Scalar) -> Self {
        self.transform = self.transform.rot_rad(angle);
        self
    }

    #[inline(always)]
    fn orient(mut self, x: Scalar, y: Scalar) -> Self {
        self.transform = self.transform.orient(x, y);
        self
    }

    #[inline(always)]
    fn scale(mut self, sx: Scalar, sy: Scalar) -> Self {
        self.transform = self.transform.scale(sx, sy);
        self
    }

    #[inline(always)]
    fn shear(mut self, v: Vec2d) -> Self {
        self.transform = self.transform.shear(v);
        self
    }
}
<|endoftext|>


<commit_before>use std::collections::HashMap;
use uuid::Uuid;
use IntoBytes;
use super::*;
use std::convert::Into;
use std::hash::Hash;
use std::cmp::Eq;

use std::fmt::Debug;

/// Types of Cassandra value: normal value (bits), null value and not-set value
#[derive(Debug, Clone)]
pub enum ValueType {
    Normal(i32),
    Null,
    NotSet,
}

impl IntoBytes for ValueType {
    fn into_cbytes(&self) -> Vec<u8> {
        return match *self {
            ValueType::Normal(n) => to_int(n),
            ValueType::Null => i_to_n_bytes(-1, INT_LEN),
            ValueType::NotSet => i_to_n_bytes(-2, INT_LEN),
        };
    }
}

/// Cassandra value which could be an array of bytes, null and non-set values.
#[derive(Debug, Clone)]
pub struct Value {
    pub body: Vec<u8>,
    pub value_type: ValueType,
}

impl Value {
    /// The factory method which creates a normal type value basing on provided bytes.
    pub fn new_normal<B>(v: B) -> Value
        where B: Into<Bytes>
    {
        let bytes = v.into().0;
        let l = bytes.len() as i32;
        return Value {
            body: bytes.to_vec(),
            value_type: ValueType::Normal(l),
        };
    }

    /// The factory method which creates null Cassandra value.
    pub fn new_null() -> Value {
        return Value {
            body: vec![],
            value_type: ValueType::Null,
        };
    }

    /// The factory method which creates non-set Cassandra value.
    pub fn new_not_set() -> Value {
        return Value {
            body: vec![],
            value_type: ValueType::NotSet,
        };
    }
}

impl IntoBytes for Value {
    fn into_cbytes(&self) -> Vec<u8> {
        let mut v: Vec<u8> = vec![];
        v.extend_from_slice(self.value_type.into_cbytes().as_slice());
        v.extend_from_slice(self.body.as_slice());
        return v;
    }
}

impl<T: Into<Bytes>> From<T> for Value {
    fn from(b: T) -> Value {
        Value::new_normal(b.into())
    }
}

#[derive(Debug)]
pub struct Bytes(Vec<u8>);

impl Bytes {
    pub fn new(bytes: Vec<u8>) -> Bytes {
        Bytes(bytes)
    }
}

impl Into<Bytes> for String {
    fn into(self) -> Bytes {
        Bytes(self.into_bytes())
    }
}

impl<'a> Into<Bytes> for &'a str {
    fn into(self) -> Bytes {
        Bytes(self.as_bytes().to_vec())
    }
}

impl Into<Bytes> for i8 {
    fn into(self) -> Bytes {
        Bytes(vec![self as u8])
    }
}

impl Into<Bytes> for i16 {
    fn into(self) -> Bytes {
        Bytes(to_short(self))
    }
}

impl Into<Bytes> for i32 {
    fn into(self) -> Bytes {
        Bytes(to_int(self))
    }
}

impl Into<Bytes> for i64 {
    fn into(self) -> Bytes {
        Bytes(to_bigint(self))
    }
}

impl Into<Bytes> for u8 {
    fn into(self) -> Bytes {
        Bytes(vec![self])
    }
}

impl Into<Bytes> for u16 {
    fn into(self) -> Bytes {
        Bytes(to_u_short(self))
    }
}

impl Into<Bytes> for u32 {
    fn into(self) -> Bytes {
        Bytes(to_u(self))
    }
}

impl Into<Bytes> for u64 {
    fn into(self) -> Bytes {
        Bytes(to_u_big(self))
    }
}

impl Into<Bytes> for bool {
    fn into(self) -> Bytes {
        if self { Bytes(vec![1]) } else { Bytes(vec![0]) }
    }
}

impl Into<Bytes> for Uuid {
    fn into(self) -> Bytes {
        Bytes(self.as_bytes().to_vec())
    }
}

impl Into<Bytes> for f32 {
    fn into(self) -> Bytes {
        Bytes(to_float(self))
    }
}

impl Into<Bytes> for f64 {
    fn into(self) -> Bytes {
        Bytes(to_float_big(self))
    }
}

impl<T: Into<Bytes> + Clone + Debug> From<Vec<T>> for Bytes {
    fn from(vec: Vec<T>) -> Bytes {
        let mut bytes: Vec<u8> = vec![];
        bytes.extend_from_slice(to_int(vec.len() as i32).as_slice());
        bytes = vec.iter()
            .fold(bytes, |mut acc, v| {
                let b: Bytes = v.clone().into();
                acc.extend_from_slice(Value::new_normal(b).into_cbytes().as_slice());
                acc
            });
        Bytes(bytes)
    }
}

impl<K, V> From<HashMap<K, V>> for Bytes
    where K: Into<Bytes> + Clone + Debug + Hash + Eq,
          V: Into<Bytes> + Clone + Debug
{
    fn from(map: HashMap<K, V>) -> Bytes {
        let mut bytes: Vec<u8> = vec![];
        bytes.extend_from_slice(to_int(map.len() as i32).as_slice());
        bytes = map.iter()
            .fold(bytes, |mut acc, (k, v)| {
                let key_bytes: Bytes = k.clone().into();
                let val_bytes: Bytes = v.clone().into();
                acc.extend_from_slice(Value::new_normal(key_bytes).into_cbytes().as_slice());
                acc.extend_from_slice(Value::new_normal(val_bytes).into_cbytes().as_slice());
                acc
            });
        Bytes(bytes)
    }
}

#[cfg(test)]
mod tests {

    use super::*;
    use IntoBytes;

    #[test]
    fn test_value_type_into_cbytes() {
        // normal value types
        let normal_type = ValueType::Normal(1);
        assert_eq!(normal_type.into_cbytes(), vec![0, 0, 0, 1]);
        // null value types
        let null_type = ValueType::Null;
        assert_eq!(null_type.into_cbytes(), vec![255, 255, 255, 255]);
        // not set value types
        let not_set = ValueType::NotSet;
        assert_eq!(not_set.into_cbytes(), vec![255, 255, 255, 254])
    }

    #[test]
    fn test_new_normal_value() {
        let plain_value = "hello";
        let len = plain_value.len() as i32;
        let normal_value = Value::new_normal(plain_value);
        assert_eq!(normal_value.body, b"hello");
        match normal_value.value_type {
            ValueType::Normal(l) => assert_eq!(l, len),
            _ => unreachable!(),
        }
    }

    #[test]
    fn test_new_normal_value_all_types() {
        let _ = Value::new_normal("hello");
        let _ = Value::new_normal("hello".to_string());
        let _ = Value::new_normal(1 as u8);
        let _ = Value::new_normal(1 as u16);
        let _ = Value::new_normal(1 as u32);
        let _ = Value::new_normal(1 as u64);
        let _ = Value::new_normal(1 as i8);
        let _ = Value::new_normal(1 as i16);
        let _ = Value::new_normal(1 as i32);
        let _ = Value::new_normal(1 as i64);
        let _ = Value::new_normal(true);
    }

    #[test]
    fn test_new_null_value() {
        let null_value = Value::new_null();
        assert_eq!(null_value.body, vec![]);
        match null_value.value_type {
            ValueType::Null => assert!(true),
            _ => unreachable!(),
        }
    }

    #[test]
    fn test_new_not_set_value() {
        let not_set_value = Value::new_not_set();
        assert_eq!(not_set_value.body, vec![]);
        match not_set_value.value_type {
            ValueType::NotSet => assert!(true),
            _ => unreachable!(),
        }
    }

    #[test]
    fn test_value_into_cbytes() {
        let value = Value::new_normal(1 as u8);
        assert_eq!(value.into_cbytes(), vec![0, 0, 0, 1, 1]);
    }

}
<commit_msg>Implement From<Option<T>> for Value<commit_after>use std::collections::HashMap;
use uuid::Uuid;
use IntoBytes;
use super::*;
use std::convert::Into;
use std::hash::Hash;
use std::cmp::Eq;

use std::fmt::Debug;

/// Types of Cassandra value: normal value (bits), null value and not-set value
#[derive(Debug, Clone)]
pub enum ValueType {
    Normal(i32),
    Null,
    NotSet,
}

impl IntoBytes for ValueType {
    fn into_cbytes(&self) -> Vec<u8> {
        return match *self {
            ValueType::Normal(n) => to_int(n),
            ValueType::Null => i_to_n_bytes(-1, INT_LEN),
            ValueType::NotSet => i_to_n_bytes(-2, INT_LEN),
        };
    }
}

/// Cassandra value which could be an array of bytes, null and non-set values.
#[derive(Debug, Clone)]
pub struct Value {
    pub body: Vec<u8>,
    pub value_type: ValueType,
}

impl Value {
    /// The factory method which creates a normal type value basing on provided bytes.
    pub fn new_normal<B>(v: B) -> Value
        where B: Into<Bytes>
    {
        let bytes = v.into().0;
        let l = bytes.len() as i32;
        return Value {
            body: bytes.to_vec(),
            value_type: ValueType::Normal(l),
        };
    }

    /// The factory method which creates null Cassandra value.
    pub fn new_null() -> Value {
        return Value {
            body: vec![],
            value_type: ValueType::Null,
        };
    }

    /// The factory method which creates non-set Cassandra value.
    pub fn new_not_set() -> Value {
        return Value {
            body: vec![],
            value_type: ValueType::NotSet,
        };
    }
}

impl IntoBytes for Value {
    fn into_cbytes(&self) -> Vec<u8> {
        let mut v: Vec<u8> = vec![];
        v.extend_from_slice(self.value_type.into_cbytes().as_slice());
        v.extend_from_slice(self.body.as_slice());
        return v;
    }
}

impl<T: Into<Bytes>> From<T> for Value {
    fn from(b: T) -> Value {
        Value::new_normal(b.into())
    }
}

impl<T: Into<Bytes>> From<Option<T>> for Value {
    fn from(b: Option<T>) -> Value {
        match b {
            Some(b) => Value::new_normal(b.into()),
            None => Value::new_null(),
        }
    }
}

#[derive(Debug)]
pub struct Bytes(Vec<u8>);

impl Bytes {
    pub fn new(bytes: Vec<u8>) -> Bytes {
        Bytes(bytes)
    }
}

impl Into<Bytes> for String {
    fn into(self) -> Bytes {
        Bytes(self.into_bytes())
    }
}

impl<'a> Into<Bytes> for &'a str {
    fn into(self) -> Bytes {
        Bytes(self.as_bytes().to_vec())
    }
}

impl Into<Bytes> for i8 {
    fn into(self) -> Bytes {
        Bytes(vec![self as u8])
    }
}

impl Into<Bytes> for i16 {
    fn into(self) -> Bytes {
        Bytes(to_short(self))
    }
}

impl Into<Bytes> for i32 {
    fn into(self) -> Bytes {
        Bytes(to_int(self))
    }
}

impl Into<Bytes> for i64 {
    fn into(self) -> Bytes {
        Bytes(to_bigint(self))
    }
}

impl Into<Bytes> for u8 {
    fn into(self) -> Bytes {
        Bytes(vec![self])
    }
}

impl Into<Bytes> for u16 {
    fn into(self) -> Bytes {
        Bytes(to_u_short(self))
    }
}

impl Into<Bytes> for u32 {
    fn into(self) -> Bytes {
        Bytes(to_u(self))
    }
}

impl Into<Bytes> for u64 {
    fn into(self) -> Bytes {
        Bytes(to_u_big(self))
    }
}

impl Into<Bytes> for bool {
    fn into(self) -> Bytes {
        if self { Bytes(vec![1]) } else { Bytes(vec![0]) }
    }
}

impl Into<Bytes> for Uuid {
    fn into(self) -> Bytes {
        Bytes(self.as_bytes().to_vec())
    }
}

impl Into<Bytes> for f32 {
    fn into(self) -> Bytes {
        Bytes(to_float(self))
    }
}

impl Into<Bytes> for f64 {
    fn into(self) -> Bytes {
        Bytes(to_float_big(self))
    }
}

impl<T: Into<Bytes> + Clone + Debug> From<Vec<T>> for Bytes {
    fn from(vec: Vec<T>) -> Bytes {
        let mut bytes: Vec<u8> = vec![];
        bytes.extend_from_slice(to_int(vec.len() as i32).as_slice());
        bytes = vec.iter()
            .fold(bytes, |mut acc, v| {
                let b: Bytes = v.clone().into();
                acc.extend_from_slice(Value::new_normal(b).into_cbytes().as_slice());
                acc
            });
        Bytes(bytes)
    }
}

impl<K, V> From<HashMap<K, V>> for Bytes
    where K: Into<Bytes> + Clone + Debug + Hash + Eq,
          V: Into<Bytes> + Clone + Debug
{
    fn from(map: HashMap<K, V>) -> Bytes {
        let mut bytes: Vec<u8> = vec![];
        bytes.extend_from_slice(to_int(map.len() as i32).as_slice());
        bytes = map.iter()
            .fold(bytes, |mut acc, (k, v)| {
                let key_bytes: Bytes = k.clone().into();
                let val_bytes: Bytes = v.clone().into();
                acc.extend_from_slice(Value::new_normal(key_bytes).into_cbytes().as_slice());
                acc.extend_from_slice(Value::new_normal(val_bytes).into_cbytes().as_slice());
                acc
            });
        Bytes(bytes)
    }
}

#[cfg(test)]
mod tests {

    use super::*;
    use IntoBytes;

    #[test]
    fn test_value_type_into_cbytes() {
        // normal value types
        let normal_type = ValueType::Normal(1);
        assert_eq!(normal_type.into_cbytes(), vec![0, 0, 0, 1]);
        // null value types
        let null_type = ValueType::Null;
        assert_eq!(null_type.into_cbytes(), vec![255, 255, 255, 255]);
        // not set value types
        let not_set = ValueType::NotSet;
        assert_eq!(not_set.into_cbytes(), vec![255, 255, 255, 254])
    }

    #[test]
    fn test_new_normal_value() {
        let plain_value = "hello";
        let len = plain_value.len() as i32;
        let normal_value = Value::new_normal(plain_value);
        assert_eq!(normal_value.body, b"hello");
        match normal_value.value_type {
            ValueType::Normal(l) => assert_eq!(l, len),
            _ => unreachable!(),
        }
    }

    #[test]
    fn test_new_normal_value_all_types() {
        let _ = Value::new_normal("hello");
        let _ = Value::new_normal("hello".to_string());
        let _ = Value::new_normal(1 as u8);
        let _ = Value::new_normal(1 as u16);
        let _ = Value::new_normal(1 as u32);
        let _ = Value::new_normal(1 as u64);
        let _ = Value::new_normal(1 as i8);
        let _ = Value::new_normal(1 as i16);
        let _ = Value::new_normal(1 as i32);
        let _ = Value::new_normal(1 as i64);
        let _ = Value::new_normal(true);
    }

    #[test]
    fn test_new_null_value() {
        let null_value = Value::new_null();
        assert_eq!(null_value.body, vec![]);
        match null_value.value_type {
            ValueType::Null => assert!(true),
            _ => unreachable!(),
        }
    }

    #[test]
    fn test_new_not_set_value() {
        let not_set_value = Value::new_not_set();
        assert_eq!(not_set_value.body, vec![]);
        match not_set_value.value_type {
            ValueType::NotSet => assert!(true),
            _ => unreachable!(),
        }
    }

    #[test]
    fn test_value_into_cbytes() {
        let value = Value::new_normal(1 as u8);
        assert_eq!(value.into_cbytes(), vec![0, 0, 0, 1, 1]);
    }

}
<|endoftext|>