<commit_before>// `libpoly.rs`
#![feature(globs)]
#![crate_id = "poly#0.1"]
#![comment = "A Musical Instrument for Computers "]
#![license = "MIT"]
#![crate_type = "lib"]

extern crate libc;

use libc::*;

#[allow(non_camel_case_types)]
#[repr(C)]
pub enum poly_wavetype {
    poly_sine,
    poly_square,
    poly_saw,
    poly_triangle,
    poly_sample,
    poly_loopsample
}

#[allow(non_camel_case_types)]
#[allow(dead_code)]
#[link(name = "poly")]
extern "C" {
    // manage global libPOLY state
    fn poly_init(bitdepth: c_int, channels: c_int, bitrate: c_int, max: c_int, filename: *libc::c_char) -> c_int;
    fn poly_shutdown();

    // start/stop playback
    fn poly_start() -> c_int;
    fn poly_stop();

    // get generator state
    fn poly_get_init(index: c_int) -> c_char;
    fn poly_get_wavetype(index: c_int) -> poly_wavetype;
    fn poly_get_L_amp(index: c_int) -> c_float;
    fn poly_get_R_amp(index: c_int) -> c_float;
    fn poly_get_freq(index: c_int) -> c_float;
    fn poly_get_phase(index: c_int) -> c_float;
    fn poly_get_duty(index: c_int) -> c_float;
    fn poly_get_sample_bitdepth(index: c_int) -> c_int;
    fn poly_get_sample_length(index: c_int) -> c_int;
    fn poly_get_sample(index: c_int) -> *c_char;

    // set generator state
    fn poly_mute(index: c_int);
    fn poly_unmute(index: c_int);
    fn poly_set_wavetype(index: c_int, wave_type: poly_wavetype);
    fn poly_set_amplitude(index: c_int, amplitude: c_float);
    fn poly_set_L_amp(index: c_int, L_amp: c_float);
    fn poly_set_R_amp(index: c_int, R_amp: c_float);
    fn poly_bump_freq(index: c_int, freq: c_float);
    fn poly_set_freq(index: c_int, freq: c_float);
    fn poly_set_phase(index: c_int, phase: c_float);
    fn poly_set_duty(index: c_int, duty: c_float);
    fn poly_set_sample_bitdepth(index: c_int, sample_bitdepth: c_int);
    fn poly_set_sample_length(index: c_int, sample_length: c_int);
    fn poly_set_sample(index: c_int, sample: *c_char);

    // Initialize a generator with usable defaults
    fn poly_init_generator(index: c_int, wavetype: poly_wavetype, amplitute: c_float, freq: c_float);
}

#[link(name = "ao")]
extern "C" {}

pub struct Poly {
    started: bool
}

// Implement Drop so that we stop and shutdown when we go out of scope
impl Drop for Poly {
    fn drop(&mut self) {
        if self.started {
            self.stop();
        }
        unsafe {
            poly_shutdown();
        }
    }
}

impl Poly {
    /*
        Roughly equates to poly_init
    */
    pub fn new(bitdepth: int, channels: int, bitrate: int, max: int, filename: &str) -> Poly {
        let result = unsafe {
            poly_init(bitdepth as c_int, channels as c_int, bitrate as c_int, max as c_int, filename.to_c_str().unwrap()) as int
        };
        if result != 0 {
            fail!("Failed to init libpoly");
        }
        Poly{started: false}
    }

    pub fn start(&mut self) -> bool {
        let result: int = unsafe {
            poly_start() as int
        };
        if result == 0 {
            self.started = true;
        }
        self.started
    }

    pub fn stop(&mut self) {
        unsafe {
            poly_stop();
        }
        self.started = false;
    }

    pub fn get_init(&self, index: int) -> ~str {
        let result = unsafe {
            poly_get_init(index as c_int)
        };
        result.to_str()
    }

    pub fn get_wavetype(&self, index: int) -> poly_wavetype {
        unsafe {
            poly_get_wavetype(index as c_int)
        }
    }

    pub fn set_wavetype(&self, index: int, wavetype: poly_wavetype) {
        unsafe {
            poly_set_wavetype(index as c_int, wavetype)
        }
    }

    pub fn init_generator(&self, index: int, wavetype: poly_wavetype, amplitute: f64, freq: f64) {
        unsafe {
            poly_init_generator(index as c_int, wavetype, amplitute as c_float, freq as c_float)
        }
    }
}

<commit_msg>Finished writing bindings for the rest of libpoly<commit_after>// `libpoly.rs`
#![feature(globs)]
#![feature(macro_rules)]
#![crate_id = "poly#0.1"]
#![comment = "A Musical Instrument for Computers "]
#![license = "MIT"]
#![crate_type = "lib"]

extern crate libc;

use libc::*;

macro_rules! unsafe_return(
    ($func:expr $rett:ty) => (
        unsafe { $func as $rett}
    )
)

#[allow(non_camel_case_types)]
#[repr(C)]
pub enum poly_wavetype {
    poly_sine,
    poly_square,
    poly_saw,
    poly_triangle,
    poly_sample,
    poly_loopsample
}

#[allow(non_camel_case_types)]
#[allow(dead_code)]
#[link(name = "poly")]
extern "C" {
    // manage global libPOLY state
    fn poly_init(bitdepth: c_int, channels: c_int, bitrate: c_int, max: c_int, filename: *libc::c_char) -> c_int;
    fn poly_shutdown();

    // start/stop playback
    fn poly_start() -> c_int;
    fn poly_stop();

    // get generator state
    fn poly_get_init(index: c_int) -> c_char;
    fn poly_get_wavetype(index: c_int) -> poly_wavetype;
    fn poly_get_L_amp(index: c_int) -> c_float;
    fn poly_get_R_amp(index: c_int) -> c_float;
    fn poly_get_freq(index: c_int) -> c_float;
    fn poly_get_phase(index: c_int) -> c_float;
    fn poly_get_duty(index: c_int) -> c_float;
    fn poly_get_sample_bitdepth(index: c_int) -> c_int;
    fn poly_get_sample_length(index: c_int) -> c_int;
    fn poly_get_sample(index: c_int) -> *c_char;

    // set generator state
    fn poly_mute(index: c_int);
    fn poly_unmute(index: c_int);
    fn poly_set_wavetype(index: c_int, wave_type: poly_wavetype);
    fn poly_set_amplitude(index: c_int, amplitude: c_float);
    fn poly_set_L_amp(index: c_int, L_amp: c_float);
    fn poly_set_R_amp(index: c_int, R_amp: c_float);
    fn poly_bump_freq(index: c_int, freq: c_float);
    fn poly_set_freq(index: c_int, freq: c_float);
    fn poly_set_phase(index: c_int, phase: c_float);
    fn poly_set_duty(index: c_int, duty: c_float);
    fn poly_set_sample_bitdepth(index: c_int, sample_bitdepth: c_int);
    fn poly_set_sample_length(index: c_int, sample_length: c_int);
    fn poly_set_sample(index: c_int, sample: *c_char);

    // Initialize a generator with usable defaults
    fn poly_init_generator(index: c_int, wavetype: poly_wavetype, amplitute: c_float, freq: c_float);
}

#[link(name = "ao")]
extern "C" {}

pub struct Poly {
    started: bool
}

// Implement Drop so that we stop and shutdown when we go out of scope
impl Drop for Poly {
    fn drop(&mut self) {
        if self.started {
            self.stop();
        }
        unsafe {
            poly_shutdown();
        }
    }
}

impl Poly {
    /*
        Roughly equates to poly_init
    */
    pub fn new(bitdepth: int, channels: int, bitrate: int, max: int, filename: &str) -> Poly {
        let result = unsafe {
            poly_init(bitdepth as c_int, channels as c_int, bitrate as c_int, max as c_int, filename.to_c_str().unwrap()) as int
        };
        if result != 0 {
            fail!("Failed to init libpoly");
        }
        Poly{started: false}
    }

    pub fn start(&mut self) -> bool {
        let result: int = unsafe {
            poly_start() as int
        };
        if result == 0 {
            self.started = true;
        }
        self.started
    }
    pub fn stop(&mut self) {
        unsafe {
            poly_stop();
        }
        self.started = false;
    }
    pub fn init_generator(&self, index: int, wavetype: poly_wavetype, amplitude: f64, freq: f64) {
        unsafe {
            poly_init_generator(index as c_int, wavetype, amplitude as c_float,
                freq as c_float)
        }
    }

    pub fn get_init(&self, index: int) -> ~str {
        let result = unsafe {
            poly_get_init(index as c_int)
        };
        result.to_str()
    }

    pub fn get_wavetype(&self, index: int) -> poly_wavetype {
        unsafe {
            poly_get_wavetype(index as c_int)
        }
    }
    pub fn get_L_amp(&self, index: int) -> f64 {
        unsafe_return!(poly_get_L_amp(index as c_int) f64)
    }
    pub fn get_R_amp(&self, index: int) -> f64 {
        unsafe_return!(poly_get_R_amp(index as c_int) f64)
    }
    pub fn get_phase(&self, index: int) -> f64 {
        unsafe_return!(poly_get_phase(index as c_int) f64)
    }
    pub fn get_duty(&self, index: int) -> f64 {
        unsafe_return!(poly_get_duty(index as c_int) f64)
    }
    pub fn get_sample_bitdepth(&self, index: int) -> int {
        unsafe_return!(poly_get_sample_bitdepth(index as c_int) int)
    }
    pub fn get_sample_length(&self, index: int) -> int {
        unsafe_return!(poly_get_sample_length(index as c_int) int)
    }
    pub fn get_sample(&self, index: int) -> ~str {
        let result = unsafe {
            poly_get_sample(index as c_int)
        };
        result.to_str()
    }

    pub fn mute(&self, index: int) {
        unsafe { poly_mute(index as c_int) }
    }
    pub fn unmute(&self, index: int) {
        unsafe { poly_unmute(index as c_int) }
    }

    pub fn set_wavetype(&self, index: int, wavetype: poly_wavetype) {
        unsafe {
            poly_set_wavetype(index as c_int, wavetype)
        }
    }
    pub fn set_amplitude(&self, index: int, amplitude: f64) {
        unsafe { poly_set_amplitude(index as c_int, amplitude as c_float) }
    }
    pub fn set_L_amp(&self, index: int, l_amp: f64) {
        unsafe { poly_set_L_amp(index as c_int, l_amp as c_float) }
    }
    pub fn set_R_amp(&self, index: int, r_amp: f64) {
        unsafe { poly_set_R_amp(index as c_int, r_amp as c_float) }
    }
    pub fn bump_freq(&self, index: int, freq: f64) {
        unsafe { poly_bump_freq(index as c_int, freq as c_float) }
    }
    pub fn set_freq(&self, index: int, freq: f64) {
        unsafe { poly_set_freq(index as c_int, freq as c_float) }
    }
    pub fn set_phase(&self, index: int, phase: f64) {
        unsafe { poly_set_phase(index as c_int, phase as c_float)}
    }
    pub fn set_duty(&self, index: int, duty: f64) {
        unsafe { poly_set_duty(index as c_int, duty as c_float) }
    }
    pub fn set_sample_bitdepth(&self, index: int, sample_bitdepth: int) {
        unsafe { poly_set_sample_bitdepth(index as c_int, sample_bitdepth as c_int) }
    }
    pub fn set_sample_length(&self, index: int, sample_length: int) {
        unsafe { poly_set_sample_length(index as c_int, sample_length as c_int) }
    }
    pub fn set_sample(&self, index: int, sample: &str) {
        unsafe{ poly_set_sample(index as c_int, sample.to_c_str().unwrap()) }
    }
}

<|endoftext|>


<commit_before>use std::str;
use std::collections::HashMap;

use rocksdb::{DB, Writable, DBIterator, IteratorMode, Direction};
use byteorder::{ByteOrder, BigEndian, WriteBytesExt};

use RocksDBIndexStore;
use document_index::DocRef;
use key_builder::KeyBuilder;
use search::doc_id_set::DocIdSet;

#[derive(Debug)]
pub enum ChunkMergeError {
    TooManyDocs,
}

impl RocksDBIndexStore {
    pub fn merge_chunks(&mut self, source_chunks: Vec<u32>) -> Result<u32, ChunkMergeError> {
        let mut dest_chunk = self.chunks.new_chunk(&self.db);

        // Generate a mapping between the ids of the documents in the old chunks to the new one
        // This packs the id spaces of the old chunks together:
        // For example, say we have to merge 3 chunks with 100 documents each:
        //  - The first chunk's ids will be the same as before
        //  - The second chunk's ids will be remapped to 100 - 199
        //  - The third chunk's ids will be remapped to 200 - 299

        let mut doc_ref_mapping: HashMap<DocRef, u16> = HashMap::new();
        let mut current_ord: u32 = 0;

        for source_chunk in source_chunks.iter() {
            let mut kb = KeyBuilder::chunk_stat(*source_chunk, b"total_docs");
            let total_docs = match self.db.get(&kb.key()) {
                Ok(Some(total_docs_bytes)) => {
                    BigEndian::read_i64(&total_docs_bytes)
                }
                Ok(None) => continue,
                Err(e) => continue,  // TODO: Error
            };

            for source_ord in 0..total_docs {
                if current_ord >= 65536 {
                    return Err(ChunkMergeError::TooManyDocs);
                }

                let from = DocRef::from_chunk_ord(*source_chunk, source_ord as u16);
                doc_ref_mapping.insert(from, current_ord as u16);
                current_ord += 1;
            }
        }

        // Merge the term directories
        // The term directory keys are ordered to be most convenient for retrieving all the chunks
        // of for a term/field combination in one go (field/term/chunk). So we don't end up pulling
        // in a lot of unwanted data, we firstly iterate the keys, it they one of the source chunks
        // looking for then we load them and append them to our new chunk.

        /// Converts term directory key strings "d1/2/3" into tuples of 3 i32s (1, 2, 3)
        fn parse_term_directory_key(key: &[u8]) -> (u32, u32, u32) {
            let mut nums_iter = key[1..].split(|b| *b == b'/').map(|s| str::from_utf8(s).unwrap().parse::<u32>().unwrap());
            (nums_iter.next().unwrap(), nums_iter.next().unwrap(), nums_iter.next().unwrap())
        }

        let mut current_td_key: Option<(u32, u32)> = None;
        let mut current_td = Vec::new();

        for k in self.db.keys_iterator(IteratorMode::From(b"d", Direction::Forward)) {
            if k[0] != b'd' {
                // No more term directories to merge
                break;
            }

            let (field, term, chunk) = parse_term_directory_key(&k);

            if !source_chunks.contains(&chunk) {
                continue;
            }

            if current_td_key != Some((field, term)) {
                // Finished current term directory. Write it to the DB and start the next one
                if let Some((field, term)) = current_td_key {
                    let kb = KeyBuilder::chunk_dir_list(dest_chunk, field, term);
                    self.db.put(&kb.key(), &current_td);
                    current_td.clear();
                }

                current_td_key = Some((field, term));
            }

            // Merge term directory into the new one (and remap the doc ids)
            match self.db.get(&k) {
                Ok(Some(docid_set)) => {
                    for doc_id in DocIdSet::FromRDB(docid_set).iter() {
                        let doc_ref = DocRef::from_chunk_ord(chunk, doc_id);
                        let new_doc_id = doc_ref_mapping.get(&doc_ref).unwrap();
                        current_td.write_u16::<BigEndian>(*new_doc_id);
                    }
                }
                Ok(None) => {},  // FIXME
                Err(e) => {},  // FIXME
            }
        }

        // All done, write the last term directory
        if let Some((field, term)) = current_td_key {
            let kb = KeyBuilder::chunk_dir_list(dest_chunk, field, term);
            self.db.put(&kb.key(), &current_td);
            current_td.clear();
        }

        // Merge the stored values
        // All stored value keys start with the chunk id. So we need to:
        // - Iterate all stored value keys that are prefixed by one of the stored chunk ids
        // - Remap their doc ids to the one in the new chunk
        // - Write the value back with the new chunk/doc ids in the key

        /// Converts stored value key strings "v1/2/3" into tuples of 3 i32s (1, 2, 3)
        fn parse_stored_value_key(key: &[u8]) -> (u32, u32, u32) {
            let mut nums_iter = key[1..].split(|b| *b == b'/').map(|s| str::from_utf8(s).unwrap().parse::<u32>().unwrap());
            (nums_iter.next().unwrap(), nums_iter.next().unwrap(), nums_iter.next().unwrap())
        }

        for source_chunk in source_chunks.iter() {
            let kb = KeyBuilder::chunk_stored_values_prefix(*source_chunk);
            for (k, v) in self.db.iterator(IteratorMode::From(&kb.key(), Direction::Forward)) {
                if k[0] != b'v' {
                    // No more stored values to move
                    break;
                }

                let (chunk, doc_id, field) = parse_stored_value_key(&k);

                if chunk != *source_chunk {
                    // Chunk finished
                    break;
                }

                // Remap doc id
                let doc_ref = DocRef::from_chunk_ord(chunk, doc_id as u16);
                let new_doc_id = doc_ref_mapping.get(&doc_ref).unwrap();

                // Write value into new chunk
                let kb = KeyBuilder::stored_field_value(dest_chunk, *new_doc_id, field);
                self.db.put(&kb.key(), &v);
            }
        }

        // Merge the statistics
        // Like stored values, these start with chunk ids. But instead of just rewriting the
        // key, we need to sum up all the statistics across the chunks being merged.

        let mut statistics = HashMap::new();

        /// Converts statistic key strings "s1/total_docs" into tuples of 1 i32 and a Vec<u8> (1, ['t', 'o', 't', ...])
        fn parse_statistic_key(key: &[u8]) -> (u32, Vec<u8>) {
            let mut parts_iter = key[1..].split(|b| *b == b'/');
            let statistic_name = parts_iter.next().unwrap().to_vec();
            let chunk = str::from_utf8(parts_iter.next().unwrap()).unwrap().parse::<u32>().unwrap();

            (chunk, statistic_name)
        }

        // Fetch and merge statistics
        for k in self.db.keys_iterator(IteratorMode::From(b"s", Direction::Forward)) {
            if k[0] != b's' {
                // No more statistics to merge
                break;
            }

            let (chunk, statistic_name) = parse_statistic_key(&k);

            if !source_chunks.contains(&chunk) {
                continue;
            }

            match self.db.get(&k) {
                Ok(Some(val_bytes)) => {
                    let value = BigEndian::read_i64(&val_bytes);

                    let mut stat = statistics.entry(statistic_name).or_insert(0);
                    *stat += value;
                }
                Ok(None) => {},  // FIXME
                Err(e) => {},  // FIXME
            }
        }

        // Write merged statistics to new chunk
        for (stat_name, stat_value) in statistics {
            let kb = KeyBuilder::chunk_stat(dest_chunk, &stat_name);
            let mut val_bytes = [0; 8];
            BigEndian::write_i64(&mut val_bytes, stat_value);
            self.db.put(&kb.key(), &val_bytes);
        }

        // Note: Don't merge the deletion lists
        // Deletion lists can change at any time so we must lock the "document index"
        // before merging them so they can't be altered during merge. we cannot lock
        // this until the commit phase though.

        Ok(dest_chunk)
    }
}<commit_msg>Moved all the heavy lifting code into separate method<commit_after>use std::str;
use std::collections::HashMap;

use rocksdb::{DB, Writable, DBIterator, IteratorMode, Direction};
use byteorder::{ByteOrder, BigEndian, WriteBytesExt};

use RocksDBIndexStore;
use document_index::DocRef;
use key_builder::KeyBuilder;
use search::doc_id_set::DocIdSet;

#[derive(Debug)]
pub enum ChunkMergeError {
    TooManyDocs,
}

impl RocksDBIndexStore {
    fn merge_chunk_data(&self, source_chunks: Vec<u32>, dest_chunk: u32, doc_ref_mapping: &HashMap<DocRef, u16>) {
        // Merge the term directories
        // The term directory keys are ordered to be most convenient for retrieving all the chunks
        // of for a term/field combination in one go (field/term/chunk). So we don't end up pulling
        // in a lot of unwanted data, we firstly iterate the keys, it they one of the source chunks
        // looking for then we load them and append them to our new chunk.

        /// Converts term directory key strings "d1/2/3" into tuples of 3 i32s (1, 2, 3)
        fn parse_term_directory_key(key: &[u8]) -> (u32, u32, u32) {
            let mut nums_iter = key[1..].split(|b| *b == b'/').map(|s| str::from_utf8(s).unwrap().parse::<u32>().unwrap());
            (nums_iter.next().unwrap(), nums_iter.next().unwrap(), nums_iter.next().unwrap())
        }

        let mut current_td_key: Option<(u32, u32)> = None;
        let mut current_td = Vec::new();

        for k in self.db.keys_iterator(IteratorMode::From(b"d", Direction::Forward)) {
            if k[0] != b'd' {
                // No more term directories to merge
                break;
            }

            let (field, term, chunk) = parse_term_directory_key(&k);

            if !source_chunks.contains(&chunk) {
                continue;
            }

            if current_td_key != Some((field, term)) {
                // Finished current term directory. Write it to the DB and start the next one
                if let Some((field, term)) = current_td_key {
                    let kb = KeyBuilder::chunk_dir_list(dest_chunk, field, term);
                    self.db.put(&kb.key(), &current_td);
                    current_td.clear();
                }

                current_td_key = Some((field, term));
            }

            // Merge term directory into the new one (and remap the doc ids)
            match self.db.get(&k) {
                Ok(Some(docid_set)) => {
                    for doc_id in DocIdSet::FromRDB(docid_set).iter() {
                        let doc_ref = DocRef::from_chunk_ord(chunk, doc_id);
                        let new_doc_id = doc_ref_mapping.get(&doc_ref).unwrap();
                        current_td.write_u16::<BigEndian>(*new_doc_id);
                    }
                }
                Ok(None) => {},  // FIXME
                Err(e) => {},  // FIXME
            }
        }

        // All done, write the last term directory
        if let Some((field, term)) = current_td_key {
            let kb = KeyBuilder::chunk_dir_list(dest_chunk, field, term);
            self.db.put(&kb.key(), &current_td);
            current_td.clear();
        }

        // Merge the stored values
        // All stored value keys start with the chunk id. So we need to:
        // - Iterate all stored value keys that are prefixed by one of the stored chunk ids
        // - Remap their doc ids to the one in the new chunk
        // - Write the value back with the new chunk/doc ids in the key

        /// Converts stored value key strings "v1/2/3" into tuples of 3 i32s (1, 2, 3)
        fn parse_stored_value_key(key: &[u8]) -> (u32, u32, u32) {
            let mut nums_iter = key[1..].split(|b| *b == b'/').map(|s| str::from_utf8(s).unwrap().parse::<u32>().unwrap());
            (nums_iter.next().unwrap(), nums_iter.next().unwrap(), nums_iter.next().unwrap())
        }

        for source_chunk in source_chunks.iter() {
            let kb = KeyBuilder::chunk_stored_values_prefix(*source_chunk);
            for (k, v) in self.db.iterator(IteratorMode::From(&kb.key(), Direction::Forward)) {
                if k[0] != b'v' {
                    // No more stored values to move
                    break;
                }

                let (chunk, doc_id, field) = parse_stored_value_key(&k);

                if chunk != *source_chunk {
                    // Chunk finished
                    break;
                }

                // Remap doc id
                let doc_ref = DocRef::from_chunk_ord(chunk, doc_id as u16);
                let new_doc_id = doc_ref_mapping.get(&doc_ref).unwrap();

                // Write value into new chunk
                let kb = KeyBuilder::stored_field_value(dest_chunk, *new_doc_id, field);
                self.db.put(&kb.key(), &v);
            }
        }

        // Merge the statistics
        // Like stored values, these start with chunk ids. But instead of just rewriting the
        // key, we need to sum up all the statistics across the chunks being merged.

        let mut statistics = HashMap::new();

        /// Converts statistic key strings "s1/total_docs" into tuples of 1 i32 and a Vec<u8> (1, ['t', 'o', 't', ...])
        fn parse_statistic_key(key: &[u8]) -> (u32, Vec<u8>) {
            let mut parts_iter = key[1..].split(|b| *b == b'/');
            let statistic_name = parts_iter.next().unwrap().to_vec();
            let chunk = str::from_utf8(parts_iter.next().unwrap()).unwrap().parse::<u32>().unwrap();

            (chunk, statistic_name)
        }

        // Fetch and merge statistics
        for k in self.db.keys_iterator(IteratorMode::From(b"s", Direction::Forward)) {
            if k[0] != b's' {
                // No more statistics to merge
                break;
            }

            let (chunk, statistic_name) = parse_statistic_key(&k);

            if !source_chunks.contains(&chunk) {
                continue;
            }

            match self.db.get(&k) {
                Ok(Some(val_bytes)) => {
                    let value = BigEndian::read_i64(&val_bytes);

                    let mut stat = statistics.entry(statistic_name).or_insert(0);
                    *stat += value;
                }
                Ok(None) => {},  // FIXME
                Err(e) => {},  // FIXME
            }
        }

        // Write merged statistics to new chunk
        for (stat_name, stat_value) in statistics {
            let kb = KeyBuilder::chunk_stat(dest_chunk, &stat_name);
            let mut val_bytes = [0; 8];
            BigEndian::write_i64(&mut val_bytes, stat_value);
            self.db.put(&kb.key(), &val_bytes);
        }

        // Note: Don't merge the deletion lists
        // Deletion lists can change at any time so we must lock the "document index"
        // before merging them so they can't be altered during merge. we cannot lock
        // this until the commit phase though.
    }

    pub fn merge_chunks(&mut self, source_chunks: Vec<u32>) -> Result<u32, ChunkMergeError> {
        let mut dest_chunk = self.chunks.new_chunk(&self.db);

        // Generate a mapping between the ids of the documents in the old chunks to the new one
        // This packs the id spaces of the old chunks together:
        // For example, say we have to merge 3 chunks with 100 documents each:
        //  - The first chunk's ids will be the same as before
        //  - The second chunk's ids will be remapped to 100 - 199
        //  - The third chunk's ids will be remapped to 200 - 299

        let mut doc_ref_mapping: HashMap<DocRef, u16> = HashMap::new();
        let mut current_ord: u32 = 0;

        for source_chunk in source_chunks.iter() {
            let mut kb = KeyBuilder::chunk_stat(*source_chunk, b"total_docs");
            let total_docs = match self.db.get(&kb.key()) {
                Ok(Some(total_docs_bytes)) => {
                    BigEndian::read_i64(&total_docs_bytes)
                }
                Ok(None) => continue,
                Err(e) => continue,  // TODO: Error
            };

            for source_ord in 0..total_docs {
                if current_ord >= 65536 {
                    return Err(ChunkMergeError::TooManyDocs);
                }

                let from = DocRef::from_chunk_ord(*source_chunk, source_ord as u16);
                doc_ref_mapping.insert(from, current_ord as u16);
                current_ord += 1;
            }
        }

        // Merge chunk data
        self.merge_chunk_data(source_chunks, dest_chunk, &doc_ref_mapping);

        // TODO: Update document dictionary

        Ok(dest_chunk)
    }
}
<|endoftext|>


<commit_before>#![stable(feature = "futures_api", since = "1.36.0")]

use crate::ops::Try;
use crate::result::Result;

/// Indicates whether a value is available or if the current task has been
/// scheduled to receive a wakeup instead.
#[must_use = "this `Poll` may be a `Pending` variant, which should be handled"]
#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
#[stable(feature = "futures_api", since = "1.36.0")]
pub enum Poll<T> {
    /// Represents that a value is immediately ready.
    #[lang = "Ready"]
    #[stable(feature = "futures_api", since = "1.36.0")]
    Ready(#[stable(feature = "futures_api", since = "1.36.0")] T),

    /// Represents that a value is not ready yet.
    ///
    /// When a function returns `Pending`, the function *must* also
    /// ensure that the current task is scheduled to be awoken when
    /// progress can be made.
    #[lang = "Pending"]
    #[stable(feature = "futures_api", since = "1.36.0")]
    Pending,
}

impl<T> Poll<T> {
    /// Changes the ready value of this `Poll` with the closure provided.
    #[stable(feature = "futures_api", since = "1.36.0")]
    pub fn map<U, F>(self, f: F) -> Poll<U>
    where
        F: FnOnce(T) -> U,
    {
        match self {
            Poll::Ready(t) => Poll::Ready(f(t)),
            Poll::Pending => Poll::Pending,
        }
    }

    /// Returns `true` if this is `Poll::Ready`
    #[inline]
    #[rustc_const_stable(feature = "const_poll", since = "1.48.0")]
    #[stable(feature = "futures_api", since = "1.36.0")]
    pub const fn is_ready(&self) -> bool {
        matches!(*self, Poll::Ready(_))
    }

    /// Returns `true` if this is `Poll::Pending`
    #[inline]
    #[rustc_const_stable(feature = "const_poll", since = "1.48.0")]
    #[stable(feature = "futures_api", since = "1.36.0")]
    pub const fn is_pending(&self) -> bool {
        !self.is_ready()
    }
}

impl<T, E> Poll<Result<T, E>> {
    /// Changes the success value of this `Poll` with the closure provided.
    #[stable(feature = "futures_api", since = "1.36.0")]
    pub fn map_ok<U, F>(self, f: F) -> Poll<Result<U, E>>
    where
        F: FnOnce(T) -> U,
    {
        match self {
            Poll::Ready(Ok(t)) => Poll::Ready(Ok(f(t))),
            Poll::Ready(Err(e)) => Poll::Ready(Err(e)),
            Poll::Pending => Poll::Pending,
        }
    }

    /// Changes the error value of this `Poll` with the closure provided.
    #[stable(feature = "futures_api", since = "1.36.0")]
    pub fn map_err<U, F>(self, f: F) -> Poll<Result<T, U>>
    where
        F: FnOnce(E) -> U,
    {
        match self {
            Poll::Ready(Ok(t)) => Poll::Ready(Ok(t)),
            Poll::Ready(Err(e)) => Poll::Ready(Err(f(e))),
            Poll::Pending => Poll::Pending,
        }
    }
}

impl<T, E> Poll<Option<Result<T, E>>> {
    /// Changes the success value of this `Poll` with the closure provided.
    #[unstable(feature = "poll_map", issue = "63514")]
    pub fn map_ok<U, F>(self, f: F) -> Poll<Option<Result<U, E>>>
    where
        F: FnOnce(T) -> U,
    {
        match self {
            Poll::Ready(Some(Ok(t))) => Poll::Ready(Some(Ok(f(t)))),
            Poll::Ready(Some(Err(e))) => Poll::Ready(Some(Err(e))),
            Poll::Ready(None) => Poll::Ready(None),
            Poll::Pending => Poll::Pending,
        }
    }

    /// Changes the error value of this `Poll` with the closure provided.
    #[unstable(feature = "poll_map", issue = "63514")]
    pub fn map_err<U, F>(self, f: F) -> Poll<Option<Result<T, U>>>
    where
        F: FnOnce(E) -> U,
    {
        match self {
            Poll::Ready(Some(Ok(t))) => Poll::Ready(Some(Ok(t))),
            Poll::Ready(Some(Err(e))) => Poll::Ready(Some(Err(f(e)))),
            Poll::Ready(None) => Poll::Ready(None),
            Poll::Pending => Poll::Pending,
        }
    }
}

#[stable(feature = "futures_api", since = "1.36.0")]
impl<T> From<T> for Poll<T> {
    fn from(t: T) -> Poll<T> {
        Poll::Ready(t)
    }
}

#[stable(feature = "futures_api", since = "1.36.0")]
impl<T, E> Try for Poll<Result<T, E>> {
    type Ok = Poll<T>;
    type Error = E;

    #[inline]
    fn into_result(self) -> Result<Self::Ok, Self::Error> {
        match self {
            Poll::Ready(Ok(x)) => Ok(Poll::Ready(x)),
            Poll::Ready(Err(e)) => Err(e),
            Poll::Pending => Ok(Poll::Pending),
        }
    }

    #[inline]
    fn from_error(e: Self::Error) -> Self {
        Poll::Ready(Err(e))
    }

    #[inline]
    fn from_ok(x: Self::Ok) -> Self {
        x.map(Ok)
    }
}

#[stable(feature = "futures_api", since = "1.36.0")]
impl<T, E> Try for Poll<Option<Result<T, E>>> {
    type Ok = Poll<Option<T>>;
    type Error = E;

    #[inline]
    fn into_result(self) -> Result<Self::Ok, Self::Error> {
        match self {
            Poll::Ready(Some(Ok(x))) => Ok(Poll::Ready(Some(x))),
            Poll::Ready(Some(Err(e))) => Err(e),
            Poll::Ready(None) => Ok(Poll::Ready(None)),
            Poll::Pending => Ok(Poll::Pending),
        }
    }

    #[inline]
    fn from_error(e: Self::Error) -> Self {
        Poll::Ready(Some(Err(e)))
    }

    #[inline]
    fn from_ok(x: Self::Ok) -> Self {
        x.map(|x| x.map(Ok))
    }
}
<commit_msg>Bump version to 1.49.0<commit_after>#![stable(feature = "futures_api", since = "1.36.0")]

use crate::ops::Try;
use crate::result::Result;

/// Indicates whether a value is available or if the current task has been
/// scheduled to receive a wakeup instead.
#[must_use = "this `Poll` may be a `Pending` variant, which should be handled"]
#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
#[stable(feature = "futures_api", since = "1.36.0")]
pub enum Poll<T> {
    /// Represents that a value is immediately ready.
    #[lang = "Ready"]
    #[stable(feature = "futures_api", since = "1.36.0")]
    Ready(#[stable(feature = "futures_api", since = "1.36.0")] T),

    /// Represents that a value is not ready yet.
    ///
    /// When a function returns `Pending`, the function *must* also
    /// ensure that the current task is scheduled to be awoken when
    /// progress can be made.
    #[lang = "Pending"]
    #[stable(feature = "futures_api", since = "1.36.0")]
    Pending,
}

impl<T> Poll<T> {
    /// Changes the ready value of this `Poll` with the closure provided.
    #[stable(feature = "futures_api", since = "1.36.0")]
    pub fn map<U, F>(self, f: F) -> Poll<U>
    where
        F: FnOnce(T) -> U,
    {
        match self {
            Poll::Ready(t) => Poll::Ready(f(t)),
            Poll::Pending => Poll::Pending,
        }
    }

    /// Returns `true` if this is `Poll::Ready`
    #[inline]
    #[rustc_const_stable(feature = "const_poll", since = "1.49.0")]
    #[stable(feature = "futures_api", since = "1.36.0")]
    pub const fn is_ready(&self) -> bool {
        matches!(*self, Poll::Ready(_))
    }

    /// Returns `true` if this is `Poll::Pending`
    #[inline]
    #[rustc_const_stable(feature = "const_poll", since = "1.49.0")]
    #[stable(feature = "futures_api", since = "1.36.0")]
    pub const fn is_pending(&self) -> bool {
        !self.is_ready()
    }
}

impl<T, E> Poll<Result<T, E>> {
    /// Changes the success value of this `Poll` with the closure provided.
    #[stable(feature = "futures_api", since = "1.36.0")]
    pub fn map_ok<U, F>(self, f: F) -> Poll<Result<U, E>>
    where
        F: FnOnce(T) -> U,
    {
        match self {
            Poll::Ready(Ok(t)) => Poll::Ready(Ok(f(t))),
            Poll::Ready(Err(e)) => Poll::Ready(Err(e)),
            Poll::Pending => Poll::Pending,
        }
    }

    /// Changes the error value of this `Poll` with the closure provided.
    #[stable(feature = "futures_api", since = "1.36.0")]
    pub fn map_err<U, F>(self, f: F) -> Poll<Result<T, U>>
    where
        F: FnOnce(E) -> U,
    {
        match self {
            Poll::Ready(Ok(t)) => Poll::Ready(Ok(t)),
            Poll::Ready(Err(e)) => Poll::Ready(Err(f(e))),
            Poll::Pending => Poll::Pending,
        }
    }
}

impl<T, E> Poll<Option<Result<T, E>>> {
    /// Changes the success value of this `Poll` with the closure provided.
    #[unstable(feature = "poll_map", issue = "63514")]
    pub fn map_ok<U, F>(self, f: F) -> Poll<Option<Result<U, E>>>
    where
        F: FnOnce(T) -> U,
    {
        match self {
            Poll::Ready(Some(Ok(t))) => Poll::Ready(Some(Ok(f(t)))),
            Poll::Ready(Some(Err(e))) => Poll::Ready(Some(Err(e))),
            Poll::Ready(None) => Poll::Ready(None),
            Poll::Pending => Poll::Pending,
        }
    }

    /// Changes the error value of this `Poll` with the closure provided.
    #[unstable(feature = "poll_map", issue = "63514")]
    pub fn map_err<U, F>(self, f: F) -> Poll<Option<Result<T, U>>>
    where
        F: FnOnce(E) -> U,
    {
        match self {
            Poll::Ready(Some(Ok(t))) => Poll::Ready(Some(Ok(t))),
            Poll::Ready(Some(Err(e))) => Poll::Ready(Some(Err(f(e)))),
            Poll::Ready(None) => Poll::Ready(None),
            Poll::Pending => Poll::Pending,
        }
    }
}

#[stable(feature = "futures_api", since = "1.36.0")]
impl<T> From<T> for Poll<T> {
    fn from(t: T) -> Poll<T> {
        Poll::Ready(t)
    }
}

#[stable(feature = "futures_api", since = "1.36.0")]
impl<T, E> Try for Poll<Result<T, E>> {
    type Ok = Poll<T>;
    type Error = E;

    #[inline]
    fn into_result(self) -> Result<Self::Ok, Self::Error> {
        match self {
            Poll::Ready(Ok(x)) => Ok(Poll::Ready(x)),
            Poll::Ready(Err(e)) => Err(e),
            Poll::Pending => Ok(Poll::Pending),
        }
    }

    #[inline]
    fn from_error(e: Self::Error) -> Self {
        Poll::Ready(Err(e))
    }

    #[inline]
    fn from_ok(x: Self::Ok) -> Self {
        x.map(Ok)
    }
}

#[stable(feature = "futures_api", since = "1.36.0")]
impl<T, E> Try for Poll<Option<Result<T, E>>> {
    type Ok = Poll<Option<T>>;
    type Error = E;

    #[inline]
    fn into_result(self) -> Result<Self::Ok, Self::Error> {
        match self {
            Poll::Ready(Some(Ok(x))) => Ok(Poll::Ready(Some(x))),
            Poll::Ready(Some(Err(e))) => Err(e),
            Poll::Ready(None) => Ok(Poll::Ready(None)),
            Poll::Pending => Ok(Poll::Pending),
        }
    }

    #[inline]
    fn from_error(e: Self::Error) -> Self {
        Poll::Ready(Some(Err(e)))
    }

    #[inline]
    fn from_ok(x: Self::Ok) -> Self {
        x.map(|x| x.map(Ok))
    }
}
<|endoftext|>


<commit_before>use crate::error::{Error,
                   Result};
pub use crate::os::system::{uname,
                            Uname};
use std::net::{IpAddr,
               UdpSocket};

static GOOGLE_DNS: &str = "8.8.8.8:53";

pub fn ip() -> Result<IpAddr> {
    let socket = UdpSocket::bind("0.0.0.0:0").map_err(Error::IpLookupFailed)?;
    socket.connect(GOOGLE_DNS).map_err(Error::IpLookupFailed)?;
    let addr = socket.local_addr().map_err(Error::IpLookupFailed)?;
    Ok(addr.ip())
}
<commit_msg>Make ip lookup more testable<commit_after>use crate::error::{Error,
                   Result};
pub use crate::os::system::{uname,
                            Uname};
use std::{io,
          net::{IpAddr,
                Ipv4Addr,
                ToSocketAddrs,
                UdpSocket}};

const UNSPECIFIED_SOCKET_ADDR: (Ipv4Addr, u16) = (Ipv4Addr::UNSPECIFIED, 0);
const GOOGLE_DNS: &str = "8.8.8.8:53";

pub fn ip() -> Result<IpAddr> { ip_impl(GOOGLE_DNS).map_err(Error::IpLookupFailed) }

fn ip_impl(connect_addr: impl ToSocketAddrs) -> io::Result<IpAddr> {
    let socket = UdpSocket::bind(UNSPECIFIED_SOCKET_ADDR)?;
    socket.connect(connect_addr)?;
    let addr = socket.local_addr()?;
    Ok(addr.ip())
}

#[cfg(test)]
mod test {
    use super::{ip,
                ip_impl};

    #[test]
    fn ip_lookup() {
        assert!(ip_impl("an invalid socket addr").is_err());
        assert!(ip().is_ok());
    }
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use syntax::ast::{ItemKind, MetaItem};
use syntax::codemap::Span;
use syntax::ext::base::{Annotatable, ExtCtxt};
use utils::match_ty_unwrap;

pub fn expand_reflector(cx: &mut ExtCtxt, span: Span, _: &MetaItem, annotatable: &Annotatable,
                        push: &mut FnMut(Annotatable)) {
    if let &Annotatable::Item(ref item) = annotatable {
        if let ItemKind::Struct(ref def, _) = item.node {
            let struct_name = item.ident;
            // This path has to be hardcoded, unfortunately, since we can't resolve paths at expansion time
            match def.fields().iter().find(
                    |f| match_ty_unwrap(&*f.ty, &["dom", "bindings", "reflector", "Reflector"]).is_some()) {
                // If it has a field that is a Reflector, use that
                Some(f) => {
                    let field_name = f.ident;
                    let impl_item = quote_item!(cx,
                        impl ::dom::bindings::reflector::Reflectable for $struct_name {
                            fn reflector<'a>(&'a self) -> &'a ::dom::bindings::reflector::Reflector {
                                &self.$field_name
                            }
                        }
                    );
                    let impl_item_mut = quote_item!(cx,
                        impl ::dom::bindings::reflector::MutReflectable for $struct_name {
                            fn init_reflector(&mut self, obj: *mut ::js::jsapi::JSObject) {
                                self.$field_name.set_jsobject(obj);
                            }
                        }
                    );
                    impl_item.map(|it| push(Annotatable::Item(it)));
                    impl_item_mut.map(|it| push(Annotatable::Item(it)))
                },
                // Or just call it on the first field (supertype).
                None => {
                    let field_name = def.fields()[0].ident;
                    let impl_item = quote_item!(cx,
                        impl ::dom::bindings::reflector::Reflectable for $struct_name {
                            fn reflector<'a>(&'a self) -> &'a ::dom::bindings::reflector::Reflector {
                                self.$field_name.reflector()
                            }
                        }
                    );
                    let impl_item_mut = quote_item!(cx,
                        impl ::dom::bindings::reflector::MutReflectable for $struct_name {
                            fn init_reflector(&mut self, obj: *mut ::js::jsapi::JSObject) {
                                self.$field_name.init_reflector(obj);
                            }
                        }
                    );
                    impl_item.map(|it| push(Annotatable::Item(it)));
                    impl_item_mut.map(|it| push(Annotatable::Item(it)))
                }
            };

            let impl_item = quote_item!(cx,
                impl ::js::conversions::ToJSValConvertible for $struct_name {
                    #[allow(unsafe_code)]
                    unsafe fn to_jsval(&self,
                                       cx: *mut ::js::jsapi::JSContext,
                                       rval: ::js::jsapi::MutableHandleValue) {
                        let object = ::dom::bindings::reflector::Reflectable::reflector(self).get_jsobject();
                        object.to_jsval(cx, rval)
                    }
                }
            );
            impl_item.map(|it| push(Annotatable::Item(it)));
        } else {
            cx.span_err(span, "#[dom_struct] seems to have been applied to a non-struct");
        }
    }
}
<commit_msg>Don't crash when #[dom_struct] is applied on an empty struct<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use syntax::ast::{ItemKind, MetaItem};
use syntax::codemap::Span;
use syntax::ext::base::{Annotatable, ExtCtxt};
use utils::match_ty_unwrap;

pub fn expand_reflector(cx: &mut ExtCtxt, span: Span, _: &MetaItem, annotatable: &Annotatable,
                        push: &mut FnMut(Annotatable)) {
    if let &Annotatable::Item(ref item) = annotatable {
        if let ItemKind::Struct(ref def, _) = item.node {
            if def.fields().is_empty() {
                cx.span_err(span, "#[dom_struct] should have a reflector or \
                                   parent dom struct as its first field");
                return;
            }
            let struct_name = item.ident;
            // This path has to be hardcoded, unfortunately, since we can't resolve paths at expansion time
            match def.fields().iter().find(
                    |f| match_ty_unwrap(&*f.ty, &["dom", "bindings", "reflector", "Reflector"]).is_some()) {
                // If it has a field that is a Reflector, use that
                Some(f) => {
                    let field_name = f.ident;
                    let impl_item = quote_item!(cx,
                        impl ::dom::bindings::reflector::Reflectable for $struct_name {
                            fn reflector<'a>(&'a self) -> &'a ::dom::bindings::reflector::Reflector {
                                &self.$field_name
                            }
                        }
                    );
                    let impl_item_mut = quote_item!(cx,
                        impl ::dom::bindings::reflector::MutReflectable for $struct_name {
                            fn init_reflector(&mut self, obj: *mut ::js::jsapi::JSObject) {
                                self.$field_name.set_jsobject(obj);
                            }
                        }
                    );
                    impl_item.map(|it| push(Annotatable::Item(it)));
                    impl_item_mut.map(|it| push(Annotatable::Item(it)))
                },
                // Or just call it on the first field (supertype).
                None => {
                    let field_name = def.fields()[0].ident;
                    let impl_item = quote_item!(cx,
                        impl ::dom::bindings::reflector::Reflectable for $struct_name {
                            fn reflector<'a>(&'a self) -> &'a ::dom::bindings::reflector::Reflector {
                                self.$field_name.reflector()
                            }
                        }
                    );
                    let impl_item_mut = quote_item!(cx,
                        impl ::dom::bindings::reflector::MutReflectable for $struct_name {
                            fn init_reflector(&mut self, obj: *mut ::js::jsapi::JSObject) {
                                self.$field_name.init_reflector(obj);
                            }
                        }
                    );
                    impl_item.map(|it| push(Annotatable::Item(it)));
                    impl_item_mut.map(|it| push(Annotatable::Item(it)))
                }
            };

            let impl_item = quote_item!(cx,
                impl ::js::conversions::ToJSValConvertible for $struct_name {
                    #[allow(unsafe_code)]
                    unsafe fn to_jsval(&self,
                                       cx: *mut ::js::jsapi::JSContext,
                                       rval: ::js::jsapi::MutableHandleValue) {
                        let object = ::dom::bindings::reflector::Reflectable::reflector(self).get_jsobject();
                        object.to_jsval(cx, rval)
                    }
                }
            );
            impl_item.map(|it| push(Annotatable::Item(it)));
        } else {
            cx.span_err(span, "#[dom_struct] seems to have been applied to a non-struct");
        }
    }
}
<|endoftext|>


<commit_before>#[cfg(target_arch="x86")]
const B: [usize; 5] = [ 0x2, 0xC, 0xF0
                      , 0xFF00
                      , 0xFFFF0000];
#[cfg(target_arch="x86")]
const S: [usize; 5] = [ 1, 2, 4, 8, 16 ];

#[cfg(target_arch="x86_64")]
const B: [usize; 6] = [ 0x2, 0xC, 0xF0
                      , 0xFF00, 0xFFFF0000
                      , 0xFFFFFFFF00000000];
#[cfg(target_arch="x86_64")]
const S: [usize; 6] = [ 1, 2, 4, 8, 16, 32 ];

pub trait PowersOf2 {
    fn is_pow2(&self) -> bool;
    fn next_pow2(&self) -> Self;
    fn log2(&self) -> Self;
}

impl PowersOf2 for usize {
    fn is_pow2(&self) -> bool {
        *self != 0 && (self & (self - 1)) == 0
    }

    /// Returns the next power of 2
    fn next_pow2(&self) -> usize {
        let mut v = *self;
        if v == 0 {
            1
        } else {
            v -= 1;
            v = v | (v >> 1);
            v = v | (v >> 2);
            v = v | (v >> 4);
            v = v | (v >> 8);
            v = v | (v >> 16);
            v + 1
        }
    }

    #[cfg(not(any(target_arch="x86_64", target_arch="x86")))]
    fn log2(&self) -> usize {
        // This is the "obvious" log base 2 implementation. The lookup table
        // -based approach would be much faster, but we can't use it for
        // `usize` since we aren't sure what size a usize is without conditional
        // compilation.
        unimplemented!()
    }

    #[cfg(any(target_arch="x86_64", target_arch="x86"))]
    fn log2(&self) -> usize {
        // let mut r: usize = 0;
        // let mut v = *self;
        // S.iter()
        //  .zip(B.iter()) // this purely-functional implementation may be slower
        //  .fold((0, *self), // but it's cute and I had fun figuring it out
        //     |(r, v), (s, b)| if v & b != 0 { (r | s, v >> s) }
        //                      else { (r, v) })
        //   .0
        // for i in 0..S.len() {
        //     if v & B[i] != 0 {
        //         v >>= S[i];
        //         r |=  S[i];
        //     }
        // }
        // r
        //
        let mut res = 0;
        let mut num = *self >> 1;
        while num != 0 {
            res += 1;
            num >>= 1;
        }
        res
    }
}

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

    #[test]
    fn test_next_pow2() {
        assert_eq!(2usize.next_pow2(), 2);
        assert_eq!(0usize.next_pow2(), 1);
        assert_eq!(3usize.next_pow2(), 4);
        assert_eq!(5678usize.next_pow2(), 8192);
    }
}
<commit_msg>[alloc] Fixed fast log2 implementation<commit_after>#[cfg(target_arch="x86")]
const B: [usize; 5]
    = [ 0x2, 0xC, 0xF0
      , 0xFF00
      , 0xFFFF0000];
#[cfg(target_arch="x86")]
const S: [usize; 5] = [ 1, 2, 4, 8, 16 ];

#[cfg(target_arch="x86_64")]
const B: [usize; 6]
    = [ 0x2, 0xC, 0xF0
      , 0xFF00, 0xFFFF0000
      , 0xFFFFFFFF00000000];

#[cfg(target_arch="x86_64")]
const S: [usize; 6] = [ 1, 2, 4, 8, 16, 32 ];

pub trait PowersOf2 {
    fn is_pow2(&self) -> bool;
    fn next_pow2(&self) -> Self;
    fn log2(&self) -> Self;
}

impl PowersOf2 for usize {
    fn is_pow2(&self) -> bool {
        *self != 0 && (self & (self - 1)) == 0
    }

    /// Returns the next power of 2
    fn next_pow2(&self) -> usize {
        let mut v = *self;
        if v == 0 {
            1
        } else {
            v -= 1;
            v = v | (v >> 1);
            v = v | (v >> 2);
            v = v | (v >> 4);
            v = v | (v >> 8);
            v = v | (v >> 16);
            v + 1
        }
    }

    #[cfg(not(any(target_arch="x86_64", target_arch="x86")))]
    fn log2(&self) -> usize {
        // This is the "obvious" log base 2 implementation. The lookup table
        // -based approach would be much faster, but we can't use it for
        // `usize` since we aren't sure what size a usize is without conditional
        // compilation.
        let mut res = 0;
        let mut num = *self >> 1;
        while num != 0 {
            res += 1;
            num >>= 1;
        }
        res
    }

    #[cfg(any(target_arch="x86_64", target_arch="x86"))]
    fn log2(&self) -> usize {
        let mut r: usize = 0;
        let mut v = *self;
        // S.iter()
        //  .zip(B.iter()) // this purely-functional implementation may be slower
        //  .fold((0, *self), // but it's cute and I had fun figuring it out
        //     |(r, v), (s, b)| if v & b != 0 { (r | s, v >> s) }
        //                      else { (r, v) })
        //   .0
        for i in (0..S.len()).rev() {
            if v & B[i] != 0 {
                v >>= S[i];
                r |=  S[i];
            }
        }
        r
    }
}

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

    #[test]
    fn test_next_pow2() {
        assert_eq!(2usize.next_pow2(), 2);
        assert_eq!(0usize.next_pow2(), 1);
        assert_eq!(3usize.next_pow2(), 4);
        assert_eq!(5678usize.next_pow2(), 8192);
    }
}
<|endoftext|>


<commit_before>use crate::types::{
    *,
    flags::*,
    generation::*,
    parsing::*,
};

use cookie_factory::{GenError, do_gen, gen_call, gen_cond};
use nom::combinator::{flat_map, map, map_opt};

/// Protocol metadata
pub mod metadata {
    use super::*;

    /// The name of the protocol
    pub const NAME:          &str           = "{{protocol.name}}";
    /// The major version of the protocol
    pub const MAJOR_VERSION: ShortShortUInt = {{protocol.major_version}};
    /// The minor version of the protocol
    pub const MINOR_VERSION: ShortShortUInt = {{protocol.minor_version}};
    /// The revision (version) of the protocol
    pub const REVISION:      ShortShortUInt = {{protocol.revision}};
    /// The default port of the protocol
    pub const PORT:          LongUInt       = {{protocol.port}};
    /// The copyright holding the protocol
    pub const COPYRIGHT:     &str           = r#"{{protocol.copyright}}"#;
}

/// Protocol constants
pub mod constants {
    use super::*;

    {{#each protocol.constants as |constant| ~}}
    /// {{constant.name}} (Generated)
    pub const {{sanitize_name constant.name}}: {{constant.type}} = {{constant.value}};
    {{/each ~}}
}

/// An AMQP Error
#[derive(Clone, Debug, PartialEq)]
pub enum AMQPError {
    /// A soft AMQP error
    Soft(AMQPSoftError),
    /// A hard AMQP error
    Hard(AMQPHardError),
}

impl AMQPError {
    /// Get the id of the error
    pub fn get_id(&self) -> ShortUInt {
        match *self {
            AMQPError::Soft(ref s) => s.get_id(),
            AMQPError::Hard(ref h) => h.get_id(),
        }
    }

    /// Get the error corresponding to an id
    pub fn from_id(id: ShortUInt) -> Option<AMQPError> {
        AMQPSoftError::from_id(id).map(AMQPError::Soft).or_else(|| AMQPHardError::from_id(id).map(AMQPError::Hard))
    }
}

/// The available soft AMQP errors
#[derive(Clone, Debug, PartialEq)]
pub enum AMQPSoftError {
    {{#each protocol.soft_errors as |constant| ~}}
    /// {{{constant.name}}} (Generated)
    {{camel constant.name}},
    {{/each ~}}
}

impl AMQPSoftError {
    /// Get the id of the soft error
    pub fn get_id(&self) -> ShortUInt {
        match *self {
            {{#each protocol.soft_errors as |constant| ~}}
            AMQPSoftError::{{camel constant.name}} => {{constant.value}},
            {{/each ~}}
        }
    }

    /// Get the soft error corresponding to an id
    pub fn from_id(id: ShortUInt) -> Option<AMQPSoftError> {
        match id {
            {{#each protocol.soft_errors as |constant| ~}}
            {{constant.value}} => Some(AMQPSoftError::{{camel constant.name}}),
            {{/each ~}}
            _                  => None,
        }
    }
}

/// The available hard AMQP errors
#[derive(Clone, Debug, PartialEq)]
pub enum AMQPHardError {
    {{#each protocol.hard_errors as |constant| ~}}
    /// {{{constant.name}}} (Generated)
    {{camel constant.name}},
    {{/each ~}}
}

impl AMQPHardError {
    /// Get the id of the hard error
    pub fn get_id(&self) -> ShortUInt {
        match *self {
            {{#each protocol.hard_errors as |constant| ~}}
            AMQPHardError::{{camel constant.name}} => {{constant.value}},
            {{/each ~}}
        }
    }

    /// Get the hard error corresponding to an id
    pub fn from_id(id: ShortUInt) -> Option<AMQPHardError> {
        match id {
            {{#each protocol.hard_errors as |constant| ~}}
            {{constant.value}} => Some(AMQPHardError::{{camel constant.name}}),
            {{/each ~}}
            _                  => None,
        }
    }
}

{{#each protocol.classes as |class| ~}}
use self::{{snake class.name}}::parse_{{snake class.name}};
{{/each ~}}

/// Parse an AMQP class
pub fn parse_class(i: &[u8]) -> ParserResult<'_, AMQPClass> {
    map_opt(flat_map(parse_id, |id| move |i| match id {
        {{#each protocol.classes as |class| ~}}
        {{class.id}} => map(map(parse_{{snake class.name false}}, AMQPClass::{{camel class.name}}), Some)(i),
        {{/each ~}}
        _ => Ok((i, None)),
    }), std::convert::identity)(i)
}

/// Serialize an AMQP class
pub fn gen_class<'a>(input: (&'a mut [u8], usize), class: &AMQPClass) -> Result<(&'a mut [u8], usize), GenError> {
    match *class {
        {{#each protocol.classes as |class| ~}}
        AMQPClass::{{camel class.name}}(ref {{snake class.name}}) => {{snake class.name}}::gen_{{snake class.name false}}(input, {{snake class.name}}),
        {{/each ~}}
    }
}

/// The available AMQP classes
#[derive(Clone, Debug, PartialEq)]
pub enum AMQPClass {
    {{#each protocol.classes as |class| ~}}
    /// {{class.name}} (Generated)
    {{camel class.name}}({{snake class.name}}::AMQPMethod),
    {{/each ~}}
}

{{#each protocol.classes as |class|}}
/// {{class.name}} (generated)
pub mod {{snake class.name}} {
    use super::*;

    /// Parse {{class.name}} (Generated)
    pub fn parse_{{snake class.name false}}(i: &[u8]) -> ParserResult<'_, {{snake class.name}}::AMQPMethod> {
        map_opt(flat_map(parse_id, |id| move |i| match id {
            {{#each class.methods as |method| ~}}
            {{method.id}} => map(map(parse_{{snake method.name false}}, AMQPMethod::{{camel method.name}}), Some)(i),
            {{/each ~}}
            _ => Ok((i, None)),
        }), std::convert::identity)(i)
    }

    /// Serialize {{class.name}} (Generated)
    pub fn gen_{{snake class.name false}}<'a>(input: (&'a mut [u8], usize), method: &AMQPMethod) -> Result<(&'a mut [u8], usize), GenError> {
        match *method {
            {{#each class.methods as |method| ~}}
            AMQPMethod::{{camel method.name}}(ref {{snake method.name}}) => {
                do_gen!(input,
                    gen_id({{class.id}}) >>
                    gen_{{snake method.name false}}({{snake method.name}})
                )
            },
            {{/each ~}}
        }
    }

    /// The available methods in {{class.name}}
    #[derive(Clone, Debug, PartialEq)]
    pub enum AMQPMethod {
        {{#each class.methods as |method| ~}}
        /// {{method.name}} (Generated)
        {{camel method.name}}({{camel method.name}}),
        {{/each ~}}
    }

    {{#each class.methods as |method|}}
    /// {{method.name}} (Generated)
    #[derive(Clone, Debug, PartialEq)]
    pub struct {{camel method.name}} {
        {{#each_argument method.arguments as |argument| ~}}
        {{#if argument_is_value ~}}
        {{#unless argument.force_default ~}}
        /// {{argument.name}} (Generated)
        pub {{snake argument.name}}: {{argument.type}},
        {{/unless ~}}
        {{else}}
        {{#each_flag argument as |flag| ~}}
        {{#unless flag.force_default ~}}
        /// {{flag.name}} (Generated)
        pub {{snake flag.name}}: Boolean,
        {{/unless ~}}
        {{/each_flag ~}}
        {{/if ~}}
        {{/each_argument ~}}
    }

    /// Parse {{method.name}} (Generated)
    pub fn parse_{{snake method.name false}}(i: &[u8]) -> ParserResult<'_, {{camel method.name}}> {
        {{#each_argument method.arguments as |argument| ~}}
        {{#if argument_is_value ~}}
        let (i, {{#if argument.force_default ~}}_{{else}}{{snake argument.name}}{{/if ~}}) = parse_{{snake_type argument.type}}(i)?;
        {{else}}
        let (i, {{#if method.metadata.empty_flags ~}}_{{else}}flags{{/if ~}}) = parse_flags(i, &[
            {{#each_flag argument as |flag| ~}}
            "{{flag.name}}",
            {{/each_flag ~}}
        ])?;
        {{/if ~}}
        {{/each_argument ~}}
        Ok((i, {{camel method.name}} {
            {{#each_argument method.arguments as |argument| ~}}
            {{#if argument_is_value ~}}
            {{#unless argument.force_default ~}}
            {{snake argument.name}},
            {{/unless ~}}
            {{else}}
            {{#each_flag argument as |flag| ~}}
            {{#unless flag.force_default ~}}
            {{snake flag.name}}: flags.get_flag("{{snake flag.name}}").unwrap_or({{flag.default_value}}),
            {{/unless ~}}
            {{/each_flag ~}}
            {{/if ~}}
            {{/each_argument ~}}
        }))
    }

    /// Serialize {{method.name}} (Generated)
    pub fn gen_{{snake method.name false}}<'a>(input: (&'a mut [u8], usize), {{#if method.arguments ~}}{{#if method.metadata.is_empty ~}}_{{/if ~}}method{{else}}_{{/if ~}}: &{{camel method.name}}) -> Result<(&'a mut [u8],usize), GenError> {
        {{#each_argument method.arguments as |argument| ~}}
        {{#unless argument_is_value ~}}
        let mut flags = AMQPFlags::default();
        {{#each_flag argument as |flag| ~}}
        flags.add_flag("{{snake flag.name}}".to_string(), {{#if flag.force_default ~}}{{flag.default_value}}{{else}}method.{{snake flag.name}}{{/if ~}});
        {{/each_flag ~}}
        {{/unless ~}}
        {{/each_argument ~}}
        do_gen!(input,
            gen_id({{method.id}})
            {{#each_argument method.arguments as |argument| ~}}
            {{#if argument_is_value ~}}
            >> gen_{{snake_type argument.type}}({{#if argument.force_default ~}}{{amqp_value argument.default_value}}{{else}}{{#if (pass_by_ref argument.type) ~}}&{{/if ~}}method.{{snake argument.name}}{{/if ~}})
            {{else}}
            >> gen_flags(&flags)
            {{/if ~}}
            {{/each_argument ~}}
        )
    }
    {{/each ~}}
    {{#if class.properties ~}}
    /// {{class.name}} properties (Generated)
    #[derive(Clone, Debug, PartialEq)]
    pub struct AMQPProperties {
        {{#each class.properties as |property| ~}}
        {{snake property.name}}: Option<{{property.type}}>,
        {{/each ~}}
    }

    impl Default for AMQPProperties {
        fn default() -> AMQPProperties {
            AMQPProperties {
                {{#each class.properties as |property| ~}}
                {{snake property.name}}: None,
                {{/each ~}}
            }
        }
    }

    impl AMQPProperties {
        {{#each class.properties as |property| ~}}
        /// Set {{property.name}} (Generated)
        pub fn with_{{snake property.name false}}(mut self, value: {{property.type}}) -> AMQPProperties {
            self.{{snake property.name}} = Some(value);
            self
        }
        {{/each ~}}

        {{#each class.properties as |property| ~}}
        /// Get {{property.name}} (Generated)
        pub fn {{snake property.name}}(&self) -> &Option<{{property.type}}> {
            &self.{{snake property.name}}
        }
        {{/each ~}}

        /// Get the bitpask for serialization (Generated)
        #[allow(clippy::identity_op)]
        pub fn bitmask(&self) -> ShortUInt {
            {{#each class.properties as |property| ~}}
            (if self.{{snake property.name}}.is_some() { 1 << (15 - {{@index}}) } else { 0 }) {{#unless @last ~}} + {{/unless ~}}
            {{/each ~}}
        }
    }

    /// Parse {{class.name}} properties (Generated)
    #[allow(clippy::identity_op)]
    pub fn parse_properties(i: &[u8]) -> ParserResult<'_, AMQPProperties> {
        let (i, flags) = parse_short_uint(i)?;
        {{#each class.properties as |property| ~}}
        let (i, {{snake property.name}}) = if flags & (1 << (15 - {{@index}})) != 0 { map(parse_{{snake_type property.type}}, Some)(i)? } else { (i, None) };
        {{/each ~}}
        Ok((i, AMQPProperties {
            {{#each class.properties as |property| ~}}
            {{snake property.name}},
            {{/each ~}}
        }))
    }

    /// Serialize {{class.name}} properties (Generated)
    #[clippy::cyclomatic_complexity = "32"]
    pub fn gen_properties<'a>(input:(&'a mut [u8],usize), props: &AMQPProperties) -> Result<(&'a mut [u8],usize),GenError> {
        do_gen!(input,
            gen_short_uint(props.bitmask())
            {{#each class.properties as |property| ~}}
            >> gen_cond!(props.{{snake property.name}}.is_some(), gen_call!(gen_{{snake_type property.type}}, {{#if (pass_by_ref property.type) ~}}&{{/if ~}}props.{{snake property.name}}{{#if (pass_by_ref property.type) ~}}.as_ref(){{/if ~}}.unwrap()))
            {{/each ~}}
        )
    }
    {{/if ~}}
}
{{/each ~}}
<commit_msg>protocol: add amqp ids accessors<commit_after>use crate::types::{
    *,
    flags::*,
    generation::*,
    parsing::*,
};

use cookie_factory::{GenError, do_gen, gen_call, gen_cond};
use nom::combinator::{flat_map, map, map_opt};

/// Protocol metadata
pub mod metadata {
    use super::*;

    /// The name of the protocol
    pub const NAME:          &str           = "{{protocol.name}}";
    /// The major version of the protocol
    pub const MAJOR_VERSION: ShortShortUInt = {{protocol.major_version}};
    /// The minor version of the protocol
    pub const MINOR_VERSION: ShortShortUInt = {{protocol.minor_version}};
    /// The revision (version) of the protocol
    pub const REVISION:      ShortShortUInt = {{protocol.revision}};
    /// The default port of the protocol
    pub const PORT:          LongUInt       = {{protocol.port}};
    /// The copyright holding the protocol
    pub const COPYRIGHT:     &str           = r#"{{protocol.copyright}}"#;
}

/// Protocol constants
pub mod constants {
    use super::*;

    {{#each protocol.constants as |constant| ~}}
    /// {{constant.name}} (Generated)
    pub const {{sanitize_name constant.name}}: {{constant.type}} = {{constant.value}};
    {{/each ~}}
}

/// An AMQP Error
#[derive(Clone, Debug, PartialEq)]
pub enum AMQPError {
    /// A soft AMQP error
    Soft(AMQPSoftError),
    /// A hard AMQP error
    Hard(AMQPHardError),
}

impl AMQPError {
    /// Get the id of the error
    pub fn get_id(&self) -> ShortUInt {
        match *self {
            AMQPError::Soft(ref s) => s.get_id(),
            AMQPError::Hard(ref h) => h.get_id(),
        }
    }

    /// Get the error corresponding to an id
    pub fn from_id(id: ShortUInt) -> Option<AMQPError> {
        AMQPSoftError::from_id(id).map(AMQPError::Soft).or_else(|| AMQPHardError::from_id(id).map(AMQPError::Hard))
    }
}

/// The available soft AMQP errors
#[derive(Clone, Debug, PartialEq)]
pub enum AMQPSoftError {
    {{#each protocol.soft_errors as |constant| ~}}
    /// {{{constant.name}}} (Generated)
    {{camel constant.name}},
    {{/each ~}}
}

impl AMQPSoftError {
    /// Get the id of the soft error
    pub fn get_id(&self) -> ShortUInt {
        match *self {
            {{#each protocol.soft_errors as |constant| ~}}
            AMQPSoftError::{{camel constant.name}} => {{constant.value}},
            {{/each ~}}
        }
    }

    /// Get the soft error corresponding to an id
    pub fn from_id(id: ShortUInt) -> Option<AMQPSoftError> {
        match id {
            {{#each protocol.soft_errors as |constant| ~}}
            {{constant.value}} => Some(AMQPSoftError::{{camel constant.name}}),
            {{/each ~}}
            _                  => None,
        }
    }
}

/// The available hard AMQP errors
#[derive(Clone, Debug, PartialEq)]
pub enum AMQPHardError {
    {{#each protocol.hard_errors as |constant| ~}}
    /// {{{constant.name}}} (Generated)
    {{camel constant.name}},
    {{/each ~}}
}

impl AMQPHardError {
    /// Get the id of the hard error
    pub fn get_id(&self) -> ShortUInt {
        match *self {
            {{#each protocol.hard_errors as |constant| ~}}
            AMQPHardError::{{camel constant.name}} => {{constant.value}},
            {{/each ~}}
        }
    }

    /// Get the hard error corresponding to an id
    pub fn from_id(id: ShortUInt) -> Option<AMQPHardError> {
        match id {
            {{#each protocol.hard_errors as |constant| ~}}
            {{constant.value}} => Some(AMQPHardError::{{camel constant.name}}),
            {{/each ~}}
            _                  => None,
        }
    }
}

{{#each protocol.classes as |class| ~}}
use self::{{snake class.name}}::parse_{{snake class.name}};
{{/each ~}}

/// Parse an AMQP class
pub fn parse_class(i: &[u8]) -> ParserResult<'_, AMQPClass> {
    map_opt(flat_map(parse_id, |id| move |i| match id {
        {{#each protocol.classes as |class| ~}}
        {{class.id}} => map(map(parse_{{snake class.name false}}, AMQPClass::{{camel class.name}}), Some)(i),
        {{/each ~}}
        _ => Ok((i, None)),
    }), std::convert::identity)(i)
}

/// Serialize an AMQP class
pub fn gen_class<'a>(input: (&'a mut [u8], usize), class: &AMQPClass) -> Result<(&'a mut [u8], usize), GenError> {
    match *class {
        {{#each protocol.classes as |class| ~}}
        AMQPClass::{{camel class.name}}(ref {{snake class.name}}) => {{snake class.name}}::gen_{{snake class.name false}}(input, {{snake class.name}}),
        {{/each ~}}
    }
}

/// The available AMQP classes
#[derive(Clone, Debug, PartialEq)]
pub enum AMQPClass {
    {{#each protocol.classes as |class| ~}}
    /// {{class.name}} (Generated)
    {{camel class.name}}({{snake class.name}}::AMQPMethod),
    {{/each ~}}
}

impl AMQPClass {
    /// Get the AMQP class id (Generated)
    pub fn get_amqp_class_id(&self) -> u16 {
        match self {
            {{#each protocol.classes as |class| ~}}
            AMQPClass::{{camel class.name}}(_) => {{class.id}},
            {{/each ~}}
        }
    }
}

{{#each protocol.classes as |class|}}
/// {{class.name}} (generated)
pub mod {{snake class.name}} {
    use super::*;

    /// Parse {{class.name}} (Generated)
    pub fn parse_{{snake class.name false}}(i: &[u8]) -> ParserResult<'_, {{snake class.name}}::AMQPMethod> {
        map_opt(flat_map(parse_id, |id| move |i| match id {
            {{#each class.methods as |method| ~}}
            {{method.id}} => map(map(parse_{{snake method.name false}}, AMQPMethod::{{camel method.name}}), Some)(i),
            {{/each ~}}
            _ => Ok((i, None)),
        }), std::convert::identity)(i)
    }

    /// Serialize {{class.name}} (Generated)
    pub fn gen_{{snake class.name false}}<'a>(input: (&'a mut [u8], usize), method: &AMQPMethod) -> Result<(&'a mut [u8], usize), GenError> {
        match *method {
            {{#each class.methods as |method| ~}}
            AMQPMethod::{{camel method.name}}(ref {{snake method.name}}) => {
                do_gen!(input,
                    gen_id({{class.id}}) >>
                    gen_{{snake method.name false}}({{snake method.name}})
                )
            },
            {{/each ~}}
        }
    }

    /// The available methods in {{class.name}}
    #[derive(Clone, Debug, PartialEq)]
    pub enum AMQPMethod {
        {{#each class.methods as |method| ~}}
        /// {{method.name}} (Generated)
        {{camel method.name}}({{camel method.name}}),
        {{/each ~}}
    }

    {{#each class.methods as |method|}}
    /// {{method.name}} (Generated)
    #[derive(Clone, Debug, PartialEq)]
    pub struct {{camel method.name}} {
        {{#each_argument method.arguments as |argument| ~}}
        {{#if argument_is_value ~}}
        {{#unless argument.force_default ~}}
        /// {{argument.name}} (Generated)
        pub {{snake argument.name}}: {{argument.type}},
        {{/unless ~}}
        {{else}}
        {{#each_flag argument as |flag| ~}}
        {{#unless flag.force_default ~}}
        /// {{flag.name}} (Generated)
        pub {{snake flag.name}}: Boolean,
        {{/unless ~}}
        {{/each_flag ~}}
        {{/if ~}}
        {{/each_argument ~}}
    }

    impl {{camel method.name}} {
        /// Get the AMQP class id for {{method.name}} (Generated)
        pub fn get_amqp_class_id(&self) -> u16 {
            {{class.id}}
        }

        /// Get the AMQP method id for {{method.name}} (Generated)
        pub fn get_amqp_method_id(&self) -> u16 {
            {{method.id}}
        }
    }

    /// Parse {{method.name}} (Generated)
    pub fn parse_{{snake method.name false}}(i: &[u8]) -> ParserResult<'_, {{camel method.name}}> {
        {{#each_argument method.arguments as |argument| ~}}
        {{#if argument_is_value ~}}
        let (i, {{#if argument.force_default ~}}_{{else}}{{snake argument.name}}{{/if ~}}) = parse_{{snake_type argument.type}}(i)?;
        {{else}}
        let (i, {{#if method.metadata.empty_flags ~}}_{{else}}flags{{/if ~}}) = parse_flags(i, &[
            {{#each_flag argument as |flag| ~}}
            "{{flag.name}}",
            {{/each_flag ~}}
        ])?;
        {{/if ~}}
        {{/each_argument ~}}
        Ok((i, {{camel method.name}} {
            {{#each_argument method.arguments as |argument| ~}}
            {{#if argument_is_value ~}}
            {{#unless argument.force_default ~}}
            {{snake argument.name}},
            {{/unless ~}}
            {{else}}
            {{#each_flag argument as |flag| ~}}
            {{#unless flag.force_default ~}}
            {{snake flag.name}}: flags.get_flag("{{snake flag.name}}").unwrap_or({{flag.default_value}}),
            {{/unless ~}}
            {{/each_flag ~}}
            {{/if ~}}
            {{/each_argument ~}}
        }))
    }

    /// Serialize {{method.name}} (Generated)
    pub fn gen_{{snake method.name false}}<'a>(input: (&'a mut [u8], usize), {{#if method.arguments ~}}{{#if method.metadata.is_empty ~}}_{{/if ~}}method{{else}}_{{/if ~}}: &{{camel method.name}}) -> Result<(&'a mut [u8],usize), GenError> {
        {{#each_argument method.arguments as |argument| ~}}
        {{#unless argument_is_value ~}}
        let mut flags = AMQPFlags::default();
        {{#each_flag argument as |flag| ~}}
        flags.add_flag("{{snake flag.name}}".to_string(), {{#if flag.force_default ~}}{{flag.default_value}}{{else}}method.{{snake flag.name}}{{/if ~}});
        {{/each_flag ~}}
        {{/unless ~}}
        {{/each_argument ~}}
        do_gen!(input,
            gen_id({{method.id}})
            {{#each_argument method.arguments as |argument| ~}}
            {{#if argument_is_value ~}}
            >> gen_{{snake_type argument.type}}({{#if argument.force_default ~}}{{amqp_value argument.default_value}}{{else}}{{#if (pass_by_ref argument.type) ~}}&{{/if ~}}method.{{snake argument.name}}{{/if ~}})
            {{else}}
            >> gen_flags(&flags)
            {{/if ~}}
            {{/each_argument ~}}
        )
    }
    {{/each ~}}
    {{#if class.properties ~}}
    /// {{class.name}} properties (Generated)
    #[derive(Clone, Debug, PartialEq)]
    pub struct AMQPProperties {
        {{#each class.properties as |property| ~}}
        {{snake property.name}}: Option<{{property.type}}>,
        {{/each ~}}
    }

    impl Default for AMQPProperties {
        fn default() -> AMQPProperties {
            AMQPProperties {
                {{#each class.properties as |property| ~}}
                {{snake property.name}}: None,
                {{/each ~}}
            }
        }
    }

    impl AMQPProperties {
        {{#each class.properties as |property| ~}}
        /// Set {{property.name}} (Generated)
        pub fn with_{{snake property.name false}}(mut self, value: {{property.type}}) -> AMQPProperties {
            self.{{snake property.name}} = Some(value);
            self
        }
        {{/each ~}}

        {{#each class.properties as |property| ~}}
        /// Get {{property.name}} (Generated)
        pub fn {{snake property.name}}(&self) -> &Option<{{property.type}}> {
            &self.{{snake property.name}}
        }
        {{/each ~}}

        /// Get the bitpask for serialization (Generated)
        #[allow(clippy::identity_op)]
        pub fn bitmask(&self) -> ShortUInt {
            {{#each class.properties as |property| ~}}
            (if self.{{snake property.name}}.is_some() { 1 << (15 - {{@index}}) } else { 0 }) {{#unless @last ~}} + {{/unless ~}}
            {{/each ~}}
        }
    }

    /// Parse {{class.name}} properties (Generated)
    #[allow(clippy::identity_op)]
    pub fn parse_properties(i: &[u8]) -> ParserResult<'_, AMQPProperties> {
        let (i, flags) = parse_short_uint(i)?;
        {{#each class.properties as |property| ~}}
        let (i, {{snake property.name}}) = if flags & (1 << (15 - {{@index}})) != 0 { map(parse_{{snake_type property.type}}, Some)(i)? } else { (i, None) };
        {{/each ~}}
        Ok((i, AMQPProperties {
            {{#each class.properties as |property| ~}}
            {{snake property.name}},
            {{/each ~}}
        }))
    }

    /// Serialize {{class.name}} properties (Generated)
    #[clippy::cyclomatic_complexity = "32"]
    pub fn gen_properties<'a>(input:(&'a mut [u8],usize), props: &AMQPProperties) -> Result<(&'a mut [u8],usize),GenError> {
        do_gen!(input,
            gen_short_uint(props.bitmask())
            {{#each class.properties as |property| ~}}
            >> gen_cond!(props.{{snake property.name}}.is_some(), gen_call!(gen_{{snake_type property.type}}, {{#if (pass_by_ref property.type) ~}}&{{/if ~}}props.{{snake property.name}}{{#if (pass_by_ref property.type) ~}}.as_ref(){{/if ~}}.unwrap()))
            {{/each ~}}
        )
    }
    {{/if ~}}
}
{{/each ~}}
<|endoftext|>


<commit_before>use std::collections::BTreeMap;

pub fn day01_pt01(raw_input: &String) -> i64 {
    let mut twos_count = 0;
    let mut threes_count = 0;
    for line in raw_input.lines() {
        let char_freqs = frequency(line);
        if has_exact_count(2, &char_freqs) {
            twos_count += 1;
        }
        if has_exact_count(3, &char_freqs) {
            threes_count += 1;
        }
    }
    twos_count * threes_count
}

pub fn day01_pt02(raw_input: &String) -> String {
    let s = String::new();
    for id1 in raw_input.lines() {
        for id2 in raw_input.lines() {
            if id1 == id2 {
                continue;
            }

            let count = id1.chars().zip(id2.chars())
                .filter(|(c1, c2)| c1 != c2)
                .count();

            if count == 1 {
                // exit early since we don't need to process anything else.
                return id1.chars().zip(id2.chars())
                    .filter(|(c1, c2)| c1 == c2)
                    .map(|(c, _)| c)
                    .collect();
            }
        }
    }
    s
}

pub fn frequency(s: &str) -> BTreeMap<char, i64> {
    let mut char_counts : BTreeMap<char, i64> = BTreeMap::new();
    for ref c in s.chars() {
        let v = char_counts.entry(*c).or_insert(0);
        *v += 1;
    }
    char_counts
}

pub fn has_exact_count(n: i64, freq: &BTreeMap<char, i64>) -> bool {
    freq.into_iter().filter(|(_c, count)| **count == n).count() > 0
}

#[cfg(test)]
mod test {
    use super::{
        frequency,
        has_exact_count,
    };

    #[test]
    fn frequency_works() {
        assert_eq!(frequency("bandana"),
                   vec![
                    ('d', 1),
                    ('a', 3),
                    ('b', 1),
                    ('n', 2),
                   ].into_iter().collect());
    }

    #[test]
    fn str_has_exactly_works_01() {
        assert_eq!(has_exact_count(2, &frequency("hello")), true);
    }

    #[test]
    fn str_has_exactly_works_02() {
        assert_eq!(has_exact_count(3, &frequency("abbba")), true);
    }

    #[test]
    fn str_has_exactly_works_03() {
        assert_eq!(has_exact_count(3, &frequency("a")), false);
    }

    #[test]
    fn str_has_exactly_works_04() {
        assert_eq!(has_exact_count(3, &frequency("")), false);
    }

    #[test]
    fn str_has_exactly_works_05() {
        assert_eq!(has_exact_count(3, &frequency("helllooo")), true);
    }
}
<commit_msg>Rename day01 to day02<commit_after>use std::collections::BTreeMap;

pub fn day02_pt01(raw_input: &String) -> i64 {
    let mut twos_count = 0;
    let mut threes_count = 0;
    for line in raw_input.lines() {
        let char_freqs = frequency(line);
        if has_exact_count(2, &char_freqs) {
            twos_count += 1;
        }
        if has_exact_count(3, &char_freqs) {
            threes_count += 1;
        }
    }
    twos_count * threes_count
}

pub fn day02_pt02(raw_input: &String) -> String {
    let s = String::new();
    for id1 in raw_input.lines() {
        for id2 in raw_input.lines() {
            if id1 == id2 {
                continue;
            }

            let count = id1.chars().zip(id2.chars())
                .filter(|(c1, c2)| c1 != c2)
                .count();

            if count == 1 {
                // exit early since we don't need to process anything else.
                return id1.chars().zip(id2.chars())
                    .filter(|(c1, c2)| c1 == c2)
                    .map(|(c, _)| c)
                    .collect();
            }
        }
    }
    s
}

pub fn frequency(s: &str) -> BTreeMap<char, i64> {
    let mut char_counts : BTreeMap<char, i64> = BTreeMap::new();
    for ref c in s.chars() {
        let v = char_counts.entry(*c).or_insert(0);
        *v += 1;
    }
    char_counts
}

pub fn has_exact_count(n: i64, freq: &BTreeMap<char, i64>) -> bool {
    freq.into_iter().filter(|(_c, count)| **count == n).count() > 0
}

#[cfg(test)]
mod test {
    use super::{
        frequency,
        has_exact_count,
    };

    #[test]
    fn frequency_works() {
        assert_eq!(frequency("bandana"),
                   vec![
                    ('d', 1),
                    ('a', 3),
                    ('b', 1),
                    ('n', 2),
                   ].into_iter().collect());
    }

    #[test]
    fn str_has_exactly_works_01() {
        assert_eq!(has_exact_count(2, &frequency("hello")), true);
    }

    #[test]
    fn str_has_exactly_works_02() {
        assert_eq!(has_exact_count(3, &frequency("abbba")), true);
    }

    #[test]
    fn str_has_exactly_works_03() {
        assert_eq!(has_exact_count(3, &frequency("a")), false);
    }

    #[test]
    fn str_has_exactly_works_04() {
        assert_eq!(has_exact_count(3, &frequency("")), false);
    }

    #[test]
    fn str_has_exactly_works_05() {
        assert_eq!(has_exact_count(3, &frequency("helllooo")), true);
    }
}
<|endoftext|>


<commit_before>use std::hash::Hash;

mod private {
    use std::collections::HashMap;
    use std::hash::Hash;
    use std::fmt;

    #[derive(Clone)]
    #[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
    pub struct DuplicatesBy<I: Iterator, Key, F> {
        pub(crate) iter: I,
        pub(crate) meta: Meta<Key, F>,
    }

    impl<I, V, F> fmt::Debug for DuplicatesBy<I, V, F>
    where
        I: Iterator + fmt::Debug,
        V: fmt::Debug + Hash + Eq,
    {
        debug_fmt_fields!(DuplicatesBy, iter, meta.used);
    }

    impl<I: Iterator, Key: Eq + Hash, F> DuplicatesBy<I, Key, F> {
        pub(crate) fn new(iter: I, key_method: F) -> Self {
            DuplicatesBy {
                iter,
                meta: Meta {
                    used: HashMap::new(),
                    pending: 0,
                    key_method,
                },
            }
        }
    }

    #[derive(Clone)]
    pub struct Meta<Key, F> {
        used: HashMap<Key, bool>,
        pending: usize,
        key_method: F,
    }

    impl<Key, F> Meta<Key, F>
    where
        Key: Eq + Hash,
    {
        /// Takes an item and returns it back to the caller if it's the second time we see it.
        /// Otherwise the item is consumed and None is returned
        #[inline(always)]
        fn filter<I>(&mut self, item: I) -> Option<I>
        where
            F: KeyMethod<Key, I>,
        {
            let kv = self.key_method.make(item);
            match self.used.get_mut(kv.key_ref()) {
                None => {
                    self.used.insert(kv.key(), false);
                    self.pending += 1;
                    None
                }
                Some(true) => None,
                Some(produced) => {
                    *produced = true;
                    self.pending -= 1;
                    Some(kv.value())
                }
            }
        }
    }

    impl<I, Key, F> Iterator for DuplicatesBy<I, Key, F>
    where
        I: Iterator,
        Key: Eq + Hash,
        F: KeyMethod<Key, I::Item>,
    {
        type Item = I::Item;

        fn next(&mut self) -> Option<Self::Item> {
            let DuplicatesBy { iter, meta } = self;
            iter.find_map(|v| meta.filter(v))
        }

        #[inline]
        fn size_hint(&self) -> (usize, Option<usize>) {
            let (_, hi) = self.iter.size_hint();
            // There are `hi` number of items left in the base iterator. In the best case scenario,
            // these items are exactly the same as the ones pending (i.e items seen exactly once so
            // far), plus (hi - pending) / 2 pairs of never seen before items.
            let hi = hi.map(|hi| {
                let max_pending = std::cmp::min(self.meta.pending, hi);
                let max_new = hi.checked_sub(self.meta.pending).unwrap_or(0) / 2;
                max_pending + max_new
            });
            // The lower bound is always 0 since we might only get unique items from now on
            (0, hi)
        }
    }

    impl<I, Key, F> DoubleEndedIterator for DuplicatesBy<I, Key, F>
    where
        I: DoubleEndedIterator,
        Key: Eq + Hash,
        F: KeyMethod<Key, I::Item>,
    {
        fn next_back(&mut self) -> Option<Self::Item> {
            let DuplicatesBy { iter, meta } = self;
            iter.rev().find_map(|v| meta.filter(v))
        }
    }

    /// A keying method for use with `DuplicatesBy`
    pub trait KeyMethod<K, V> {
        type Container: KeyXorValue<K, V>;

        fn make(&mut self, value: V) -> Self::Container;
    }

    /// Apply the identity function to elements before checking them for equality.
    pub struct ById;
    impl<V> KeyMethod<V, V> for ById {
        type Container = JustValue<V>;

        fn make(&mut self, v: V) -> Self::Container {
            JustValue(v)
        }
    }

    /// Apply a user-supplied function to elements before checking them for equality.
    pub struct ByFn<F>(pub(crate) F);
    impl<K, V, F> KeyMethod<K, V> for ByFn<F>
    where
        F: FnMut(&V) -> K,
    {
        type Container = KeyValue<K, V>;

        fn make(&mut self, v: V) -> Self::Container {
            KeyValue((self.0)(&v), v)
        }
    }

    // Implementors of this trait can hold onto a key and a value but only give access to one of them
    // at a time. This allows the key and the value to be the same value internally
    pub trait KeyXorValue<K, V> {
        fn key_ref(&self) -> &K;
        fn key(self) -> K;
        fn value(self) -> V;
    }

    pub struct KeyValue<K, V>(K, V);
    impl<K, V> KeyXorValue<K, V> for KeyValue<K, V> {
        fn key_ref(&self) -> &K {
            &self.0
        }
        fn key(self) -> K {
            self.0
        }
        fn value(self) -> V {
            self.1
        }
    }

    pub struct JustValue<V>(V);
    impl<V> KeyXorValue<V, V> for JustValue<V> {
        fn key_ref(&self) -> &V {
            &self.0
        }
        fn key(self) -> V {
            self.0
        }
        fn value(self) -> V {
            self.0
        }
    }
}

/// An iterator adapter to filter for duplicate elements.
///
/// See [`.duplicates_by()`](crate::Itertools::duplicates_by) for more information.
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
pub type DuplicatesBy<I, V, F> = private::DuplicatesBy<I, V, private::ByFn<F>>;

/// Create a new `DuplicatesBy` iterator.
pub fn duplicates_by<I, Key, F>(iter: I, f: F) -> DuplicatesBy<I, Key, F>
where
    Key: Eq + Hash,
    F: FnMut(&I::Item) -> Key,
    I: Iterator,
{
    DuplicatesBy::new(iter, private::ByFn(f))
}

/// An iterator adapter to filter out duplicate elements.
///
/// See [`.duplicates()`](crate::Itertools::duplicates) for more information.
pub type Duplicates<I> = private::DuplicatesBy<I, <I as Iterator>::Item, private::ById>;

/// Create a new `Duplicates` iterator.
pub fn duplicates<I>(iter: I) -> Duplicates<I>
where
    I: Iterator,
    I::Item: Eq + Hash,
{
    Duplicates::new(iter, private::ById)
}

<commit_msg>Use saturating_sub as per clippy warning<commit_after>use std::hash::Hash;

mod private {
    use std::collections::HashMap;
    use std::hash::Hash;
    use std::fmt;

    #[derive(Clone)]
    #[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
    pub struct DuplicatesBy<I: Iterator, Key, F> {
        pub(crate) iter: I,
        pub(crate) meta: Meta<Key, F>,
    }

    impl<I, V, F> fmt::Debug for DuplicatesBy<I, V, F>
    where
        I: Iterator + fmt::Debug,
        V: fmt::Debug + Hash + Eq,
    {
        debug_fmt_fields!(DuplicatesBy, iter, meta.used);
    }

    impl<I: Iterator, Key: Eq + Hash, F> DuplicatesBy<I, Key, F> {
        pub(crate) fn new(iter: I, key_method: F) -> Self {
            DuplicatesBy {
                iter,
                meta: Meta {
                    used: HashMap::new(),
                    pending: 0,
                    key_method,
                },
            }
        }
    }

    #[derive(Clone)]
    pub struct Meta<Key, F> {
        used: HashMap<Key, bool>,
        pending: usize,
        key_method: F,
    }

    impl<Key, F> Meta<Key, F>
    where
        Key: Eq + Hash,
    {
        /// Takes an item and returns it back to the caller if it's the second time we see it.
        /// Otherwise the item is consumed and None is returned
        #[inline(always)]
        fn filter<I>(&mut self, item: I) -> Option<I>
        where
            F: KeyMethod<Key, I>,
        {
            let kv = self.key_method.make(item);
            match self.used.get_mut(kv.key_ref()) {
                None => {
                    self.used.insert(kv.key(), false);
                    self.pending += 1;
                    None
                }
                Some(true) => None,
                Some(produced) => {
                    *produced = true;
                    self.pending -= 1;
                    Some(kv.value())
                }
            }
        }
    }

    impl<I, Key, F> Iterator for DuplicatesBy<I, Key, F>
    where
        I: Iterator,
        Key: Eq + Hash,
        F: KeyMethod<Key, I::Item>,
    {
        type Item = I::Item;

        fn next(&mut self) -> Option<Self::Item> {
            let DuplicatesBy { iter, meta } = self;
            iter.find_map(|v| meta.filter(v))
        }

        #[inline]
        fn size_hint(&self) -> (usize, Option<usize>) {
            let (_, hi) = self.iter.size_hint();
            // There are `hi` number of items left in the base iterator. In the best case scenario,
            // these items are exactly the same as the ones pending (i.e items seen exactly once so
            // far), plus (hi - pending) / 2 pairs of never seen before items.
            let hi = hi.map(|hi| {
                let max_pending = std::cmp::min(self.meta.pending, hi);
                let max_new = hi.saturating_sub(self.meta.pending) / 2;
                max_pending + max_new
            });
            // The lower bound is always 0 since we might only get unique items from now on
            (0, hi)
        }
    }

    impl<I, Key, F> DoubleEndedIterator for DuplicatesBy<I, Key, F>
    where
        I: DoubleEndedIterator,
        Key: Eq + Hash,
        F: KeyMethod<Key, I::Item>,
    {
        fn next_back(&mut self) -> Option<Self::Item> {
            let DuplicatesBy { iter, meta } = self;
            iter.rev().find_map(|v| meta.filter(v))
        }
    }

    /// A keying method for use with `DuplicatesBy`
    pub trait KeyMethod<K, V> {
        type Container: KeyXorValue<K, V>;

        fn make(&mut self, value: V) -> Self::Container;
    }

    /// Apply the identity function to elements before checking them for equality.
    pub struct ById;
    impl<V> KeyMethod<V, V> for ById {
        type Container = JustValue<V>;

        fn make(&mut self, v: V) -> Self::Container {
            JustValue(v)
        }
    }

    /// Apply a user-supplied function to elements before checking them for equality.
    pub struct ByFn<F>(pub(crate) F);
    impl<K, V, F> KeyMethod<K, V> for ByFn<F>
    where
        F: FnMut(&V) -> K,
    {
        type Container = KeyValue<K, V>;

        fn make(&mut self, v: V) -> Self::Container {
            KeyValue((self.0)(&v), v)
        }
    }

    // Implementors of this trait can hold onto a key and a value but only give access to one of them
    // at a time. This allows the key and the value to be the same value internally
    pub trait KeyXorValue<K, V> {
        fn key_ref(&self) -> &K;
        fn key(self) -> K;
        fn value(self) -> V;
    }

    pub struct KeyValue<K, V>(K, V);
    impl<K, V> KeyXorValue<K, V> for KeyValue<K, V> {
        fn key_ref(&self) -> &K {
            &self.0
        }
        fn key(self) -> K {
            self.0
        }
        fn value(self) -> V {
            self.1
        }
    }

    pub struct JustValue<V>(V);
    impl<V> KeyXorValue<V, V> for JustValue<V> {
        fn key_ref(&self) -> &V {
            &self.0
        }
        fn key(self) -> V {
            self.0
        }
        fn value(self) -> V {
            self.0
        }
    }
}

/// An iterator adapter to filter for duplicate elements.
///
/// See [`.duplicates_by()`](crate::Itertools::duplicates_by) for more information.
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
pub type DuplicatesBy<I, V, F> = private::DuplicatesBy<I, V, private::ByFn<F>>;

/// Create a new `DuplicatesBy` iterator.
pub fn duplicates_by<I, Key, F>(iter: I, f: F) -> DuplicatesBy<I, Key, F>
where
    Key: Eq + Hash,
    F: FnMut(&I::Item) -> Key,
    I: Iterator,
{
    DuplicatesBy::new(iter, private::ByFn(f))
}

/// An iterator adapter to filter out duplicate elements.
///
/// See [`.duplicates()`](crate::Itertools::duplicates) for more information.
pub type Duplicates<I> = private::DuplicatesBy<I, <I as Iterator>::Item, private::ById>;

/// Create a new `Duplicates` iterator.
pub fn duplicates<I>(iter: I) -> Duplicates<I>
where
    I: Iterator,
    I::Item: Eq + Hash,
{
    Duplicates::new(iter, private::ById)
}

<|endoftext|>