<commit_before>use std::sync::Arc;
use std::sync::mpsc::{self, Sender, Receiver};
use std::thread;

use bip_util::sha::ShaHash;
use crossbeam::sync::MsQueue;

use accessor::Accessor;
use builder::buffer::{PieceBuffers, PieceBuffer};
use error::ParseResult;

/// Messages sent to the master hasher.
pub enum MasterMessage {
    /// Accepts the piece hash with the given piece index.
    AcceptPiece(usize, ShaHash),
    /// One of our workers has finished and shut down.
    WorkerFinished,
}

/// Message sent to a worker hasher.
enum WorkerMessage {
    /// Start processing the given memory region.
    HashPiece(usize, PieceBuffer),
    /// Worker should exit it's thread.
    Finish,
}

/// Starts a number of hasher workers which will generate the hash pieces for the files we send to it.
pub fn start_hasher_workers<A, C>(accessor: A,
                                  piece_length: usize,
                                  num_pieces: u64,
                                  num_workers: usize,
                                  progress: C)
                                  -> ParseResult<Vec<(usize, ShaHash)>>
    where A: Accessor,
          C: FnMut(f64) + Send + 'static
{
    // Create channels to communicate with the master
    let (master_send, master_recv) = mpsc::channel();
    let (prog_send, prog_recv) = mpsc::channel();

    // Create queue to push work to and pull work from
    let work_queue = Arc::new(MsQueue::new());

    // Create buffer allocator to reuse pre allocated buffers
    let piece_buffers = Arc::new(PieceBuffers::new(piece_length, num_workers));

    // Create n worker threads that pull work from the queue
    for _ in 0..num_workers {
        let share_master_send = master_send.clone();
        let share_work_queue = work_queue.clone();
        let share_piece_buffers = piece_buffers.clone();

        thread::spawn(move || {
            start_hash_worker(share_master_send, share_work_queue, share_piece_buffers);
        });
    }

    // Create a worker thread to execute the user callback for the progress update
    thread::spawn(move || {
        start_progress_updater(prog_recv, num_pieces, progress);
    });

    // Create the master worker to coordinate between the workers
    start_hash_master(accessor,
                      num_workers,
                      master_recv,
                      work_queue,
                      piece_buffers,
                      prog_send)
}

// ----------------------------------------------------------------------------//

/// Start a master hasher which will take care of chunking sequential/overlapping pieces from the data given to it and giving
/// updates to the hasher workers.
fn start_hash_master<A>(accessor: A,
                        num_workers: usize,
                        recv: Receiver<MasterMessage>,
                        work: Arc<MsQueue<WorkerMessage>>,
                        buffers: Arc<PieceBuffers>,
                        progress_sender: Sender<usize>)
                        -> ParseResult<Vec<(usize, ShaHash)>>
    where A: Accessor
{
    let mut pieces = Vec::new();
    let mut piece_index = 0;

    // Our closure may be called multiple times, save partial pieces buffers between calls
    let mut opt_piece_buffer = None;
    try!(accessor.access_pieces(|piece_region| {
        let mut curr_piece_buffer = if let Some(piece_buffer) = opt_piece_buffer.take() {
            piece_buffer
        } else {
            buffers.checkout()
        };

        let mut end_of_region = false;
        while !end_of_region {
            end_of_region =
                try!(curr_piece_buffer.write_bytes(|buffer| piece_region.read(buffer))) == 0;

            if curr_piece_buffer.is_whole() {
                println!("ASD");
                work.push(WorkerMessage::HashPiece(piece_index, curr_piece_buffer));

                piece_index += 1;
                curr_piece_buffer = buffers.checkout();

                if progress_sender.send(piece_index).is_err() {
                    // TODO: Add logging here
                }
            }
        }

        opt_piece_buffer = Some(curr_piece_buffer);

        Ok(())
    }));

    // If we still have a partial piece left over, push it to the workers
    if let Some(piece_buffer) = opt_piece_buffer {
        if !piece_buffer.is_empty() {
            work.push(WorkerMessage::HashPiece(piece_index, piece_buffer));

            piece_index += 1;
            if progress_sender.send(piece_index).is_err() {
                // TODO: Add logging here
            }
        }
    }

    // No more entries, tell workers to shut down
    for _ in 0..num_workers {
        work.push(WorkerMessage::Finish);
    }

    // Wait for all of the workers to finish up the last pieces
    let mut workers_finished = 0;
    while workers_finished < num_workers {
        match recv.recv() {
            Ok(MasterMessage::AcceptPiece(index, piece)) => pieces.push((index, piece)),
            Ok(MasterMessage::WorkerFinished) => workers_finished += 1,
            Err(_) => panic!("bip_metainfo: Master failed to verify all workers shutdown..."),
        }
    }

    // Sort our list to make sure the pieces are in order before we send them off
    pieces.sort_by(|one, two| one.0.cmp(&two.0));

    Ok(pieces)
}

// ----------------------------------------------------------------------------//

fn start_progress_updater<C>(recv: Receiver<usize>, num_pieces: u64, mut progress: C)
    where C: FnMut(f64)
{
    for finished_piece in recv {
        let percent_complete = (finished_piece as f64) / (num_pieces as f64);

        progress(percent_complete);
    }
}

// ----------------------------------------------------------------------------//

/// Starts a hasher worker which will hash all of the buffers it receives.
fn start_hash_worker(send: Sender<MasterMessage>,
                     work: Arc<MsQueue<WorkerMessage>>,
                     buffers: Arc<PieceBuffers>) {
    let mut work_to_do = true;

    // Loop until we are instructed to stop working
    while work_to_do {
        let work_item = work.pop();

        match work_item {
            WorkerMessage::Finish => {
                work_to_do = false;
            }
            WorkerMessage::HashPiece(index, buffer) => {
                let hash = ShaHash::from_bytes(buffer.as_slice());

                send.send(MasterMessage::AcceptPiece(index, hash)).unwrap();
                buffers.checkin(buffer);
            }
        }
    }

    // Let the master know we have exited our thread
    send.send(MasterMessage::WorkerFinished).unwrap();
}

#[cfg(test)]
mod tests {
    use std::ops::{Range, Index};
    use std::io::{self, Cursor, Read};
    use std::path::Path;
    use std::sync::mpsc;

    use bip_util::sha::ShaHash;
    use rand::{self, Rng};

    use accessor::Accessor;
    use builder::worker;

    // Keep these numbers fairly small to avoid lengthy tests
    const DEFAULT_PIECE_LENGTH: usize = 1024;
    const DEFAULT_NUM_PIECES: usize = 300;

    // Mock object for providing direct access to bytes via DataEntry.
    #[derive(Clone)]
    struct MockAccessor {
        buffer_ranges: Vec<Range<usize>>,
        contiguous_buffer: Vec<u8>,
    }

    impl MockAccessor {
        fn new() -> MockAccessor {
            MockAccessor {
                buffer_ranges: Vec::new(),
                contiguous_buffer: Vec::new(),
            }
        }

        fn create_region(&mut self, num_bytes: usize) {
            let mut buffer = vec![0u8; num_bytes];
            let mut rng = rand::thread_rng();

            rng.fill_bytes(&mut buffer);

            let (begin, end) = (self.contiguous_buffer.len(),
                                self.contiguous_buffer.len() + buffer.len());

            self.contiguous_buffer.extend_from_slice(&buffer);
            self.buffer_ranges.push(begin..end);
        }

        fn as_slice(&self) -> &[u8] {
            &self.contiguous_buffer
        }
    }

    impl Accessor for MockAccessor {
        /// Access the directory that all files should be relative to.
        fn access_directory(&self) -> Option<&str> {
            panic!("Accessor::access_directory should not be called with MockAccessor...");
        }

        /// Access the metadata for all files including their length and path.
        fn access_metadata<C>(&self, _: C) -> io::Result<()>
            where C: FnMut(u64, &Path)
        {
            panic!("Accessor::access_metadata should not be called with MockAccessor...");
        }

        /// Access the sequential pieces that make up all of the files.
        fn access_pieces<C>(&self, mut callback: C) -> io::Result<()>
            where C: FnMut(&mut Read) -> io::Result<()>
        {
            for range in self.buffer_ranges.iter() {
                let mut next_region = Cursor::new(self.contiguous_buffer.index(range.clone()));

                try!(callback(&mut next_region));
            }

            Ok(())
        }
    }

    fn validate_entries_pieces(accessor: MockAccessor, piece_length: usize, num_threads: usize) {
        let (prog_send, prog_recv) = mpsc::channel();

        let total_num_pieces = ((accessor.as_slice().len() as f64) / (piece_length as f64))
            .ceil() as u64;
        let received_pieces = worker::start_hasher_workers(&accessor,
                                                           piece_length,
                                                           total_num_pieces,
                                                           num_threads,
                                                           move |update| {
                                                               prog_send.send(update).unwrap();
                                                           })
            .unwrap();

        let computed_pieces = accessor.as_slice()
            .chunks(piece_length)
            .enumerate()
            .map(|(index, chunk)| (index, ShaHash::from_bytes(chunk)))
            .collect::<Vec<(usize, ShaHash)>>();

        let updates_received = prog_recv.iter().count() as u64;

        assert_eq!(total_num_pieces, updates_received);
        assert_eq!(received_pieces, computed_pieces);
    }

    #[test]
    fn positive_piece_length_divisible_region_single_thread() {
        let mut accessor = MockAccessor::new();

        let region_length = DEFAULT_PIECE_LENGTH * DEFAULT_NUM_PIECES;
        accessor.create_region(region_length);

        validate_entries_pieces(accessor, DEFAULT_PIECE_LENGTH, 1);
    }

    #[test]
    fn positive_piece_length_divisible_region_multiple_threads() {
        let mut accessor = MockAccessor::new();

        let region_length = DEFAULT_PIECE_LENGTH * DEFAULT_NUM_PIECES;
        accessor.create_region(region_length);

        validate_entries_pieces(accessor, DEFAULT_PIECE_LENGTH, 4);
    }

    #[test]
    fn positive_piece_length_undivisible_region_single_thread() {
        let mut accessor = MockAccessor::new();

        let region_length = DEFAULT_PIECE_LENGTH * DEFAULT_NUM_PIECES + 1;
        accessor.create_region(region_length);

        validate_entries_pieces(accessor, DEFAULT_PIECE_LENGTH, 1);
    }

    #[test]
    fn positive_piece_length_undivisible_region_multiple_threads() {
        let mut accessor = MockAccessor::new();

        let region_length = DEFAULT_PIECE_LENGTH * DEFAULT_NUM_PIECES + 1;
        accessor.create_region(region_length);

        validate_entries_pieces(accessor, DEFAULT_PIECE_LENGTH, 4);
    }

    #[test]
    fn positive_piece_length_divisible_regions_single_thread() {
        let mut accessor = MockAccessor::new();

        let region_lengths = [DEFAULT_PIECE_LENGTH * DEFAULT_NUM_PIECES,
                              DEFAULT_PIECE_LENGTH * 1,
                              DEFAULT_PIECE_LENGTH * 50];
        for &region_length in region_lengths.into_iter() {
            accessor.create_region(region_length);
        }

        validate_entries_pieces(accessor, DEFAULT_PIECE_LENGTH, 1);
    }

    #[test]
    fn positive_piece_length_divisible_regions_multiple_threads() {
        let mut accessor = MockAccessor::new();

        let region_lengths = [DEFAULT_PIECE_LENGTH * DEFAULT_NUM_PIECES,
                              DEFAULT_PIECE_LENGTH * 1,
                              DEFAULT_PIECE_LENGTH * 50];
        for &region_length in region_lengths.into_iter() {
            accessor.create_region(region_length);
        }

        validate_entries_pieces(accessor, DEFAULT_PIECE_LENGTH, 4);
    }

    #[test]
    fn positive_piece_length_undivisible_regions_single_thread() {
        let mut accessor = MockAccessor::new();

        let region_lengths = [DEFAULT_PIECE_LENGTH / 2 * DEFAULT_NUM_PIECES,
                              DEFAULT_PIECE_LENGTH / 4 * DEFAULT_NUM_PIECES,
                              DEFAULT_PIECE_LENGTH * 1,
                              (DEFAULT_PIECE_LENGTH * 2 - 1) * 2];
        for &region_length in region_lengths.into_iter() {
            accessor.create_region(region_length);
        }

        validate_entries_pieces(accessor, DEFAULT_PIECE_LENGTH, 1);
    }

    #[test]
    fn positive_piece_length_undivisible_regions_multiple_threads() {
        let mut accessor = MockAccessor::new();

        let region_lengths = [DEFAULT_PIECE_LENGTH / 2 * DEFAULT_NUM_PIECES,
                              DEFAULT_PIECE_LENGTH / 4 * DEFAULT_NUM_PIECES,
                              DEFAULT_PIECE_LENGTH * 1,
                              (DEFAULT_PIECE_LENGTH * 2 - 1) * 2];
        for &region_length in region_lengths.into_iter() {
            accessor.create_region(region_length);
        }

        validate_entries_pieces(accessor, DEFAULT_PIECE_LENGTH, 4);
    }
}
<commit_msg>Remove println Statement From Hash Worker bip_metainfo<commit_after>use std::sync::Arc;
use std::sync::mpsc::{self, Sender, Receiver};
use std::thread;

use bip_util::sha::ShaHash;
use crossbeam::sync::MsQueue;

use accessor::Accessor;
use builder::buffer::{PieceBuffers, PieceBuffer};
use error::ParseResult;

/// Messages sent to the master hasher.
pub enum MasterMessage {
    /// Accepts the piece hash with the given piece index.
    AcceptPiece(usize, ShaHash),
    /// One of our workers has finished and shut down.
    WorkerFinished,
}

/// Message sent to a worker hasher.
enum WorkerMessage {
    /// Start processing the given memory region.
    HashPiece(usize, PieceBuffer),
    /// Worker should exit it's thread.
    Finish,
}

/// Starts a number of hasher workers which will generate the hash pieces for the files we send to it.
pub fn start_hasher_workers<A, C>(accessor: A,
                                  piece_length: usize,
                                  num_pieces: u64,
                                  num_workers: usize,
                                  progress: C)
                                  -> ParseResult<Vec<(usize, ShaHash)>>
    where A: Accessor,
          C: FnMut(f64) + Send + 'static
{
    // Create channels to communicate with the master
    let (master_send, master_recv) = mpsc::channel();
    let (prog_send, prog_recv) = mpsc::channel();

    // Create queue to push work to and pull work from
    let work_queue = Arc::new(MsQueue::new());

    // Create buffer allocator to reuse pre allocated buffers
    let piece_buffers = Arc::new(PieceBuffers::new(piece_length, num_workers));

    // Create n worker threads that pull work from the queue
    for _ in 0..num_workers {
        let share_master_send = master_send.clone();
        let share_work_queue = work_queue.clone();
        let share_piece_buffers = piece_buffers.clone();

        thread::spawn(move || {
            start_hash_worker(share_master_send, share_work_queue, share_piece_buffers);
        });
    }

    // Create a worker thread to execute the user callback for the progress update
    thread::spawn(move || {
        start_progress_updater(prog_recv, num_pieces, progress);
    });

    // Create the master worker to coordinate between the workers
    start_hash_master(accessor,
                      num_workers,
                      master_recv,
                      work_queue,
                      piece_buffers,
                      prog_send)
}

// ----------------------------------------------------------------------------//

/// Start a master hasher which will take care of chunking sequential/overlapping pieces from the data given to it and giving
/// updates to the hasher workers.
fn start_hash_master<A>(accessor: A,
                        num_workers: usize,
                        recv: Receiver<MasterMessage>,
                        work: Arc<MsQueue<WorkerMessage>>,
                        buffers: Arc<PieceBuffers>,
                        progress_sender: Sender<usize>)
                        -> ParseResult<Vec<(usize, ShaHash)>>
    where A: Accessor
{
    let mut pieces = Vec::new();
    let mut piece_index = 0;

    // Our closure may be called multiple times, save partial pieces buffers between calls
    let mut opt_piece_buffer = None;
    try!(accessor.access_pieces(|piece_region| {
        let mut curr_piece_buffer = if let Some(piece_buffer) = opt_piece_buffer.take() {
            piece_buffer
        } else {
            buffers.checkout()
        };

        let mut end_of_region = false;
        while !end_of_region {
            end_of_region =
                try!(curr_piece_buffer.write_bytes(|buffer| piece_region.read(buffer))) == 0;

            if curr_piece_buffer.is_whole() {
                work.push(WorkerMessage::HashPiece(piece_index, curr_piece_buffer));

                piece_index += 1;
                curr_piece_buffer = buffers.checkout();

                if progress_sender.send(piece_index).is_err() {
                    // TODO: Add logging here
                }
            }
        }

        opt_piece_buffer = Some(curr_piece_buffer);

        Ok(())
    }));

    // If we still have a partial piece left over, push it to the workers
    if let Some(piece_buffer) = opt_piece_buffer {
        if !piece_buffer.is_empty() {
            work.push(WorkerMessage::HashPiece(piece_index, piece_buffer));

            piece_index += 1;
            if progress_sender.send(piece_index).is_err() {
                // TODO: Add logging here
            }
        }
    }

    // No more entries, tell workers to shut down
    for _ in 0..num_workers {
        work.push(WorkerMessage::Finish);
    }

    // Wait for all of the workers to finish up the last pieces
    let mut workers_finished = 0;
    while workers_finished < num_workers {
        match recv.recv() {
            Ok(MasterMessage::AcceptPiece(index, piece)) => pieces.push((index, piece)),
            Ok(MasterMessage::WorkerFinished) => workers_finished += 1,
            Err(_) => panic!("bip_metainfo: Master failed to verify all workers shutdown..."),
        }
    }

    // Sort our list to make sure the pieces are in order before we send them off
    pieces.sort_by(|one, two| one.0.cmp(&two.0));

    Ok(pieces)
}

// ----------------------------------------------------------------------------//

fn start_progress_updater<C>(recv: Receiver<usize>, num_pieces: u64, mut progress: C)
    where C: FnMut(f64)
{
    for finished_piece in recv {
        let percent_complete = (finished_piece as f64) / (num_pieces as f64);

        progress(percent_complete);
    }
}

// ----------------------------------------------------------------------------//

/// Starts a hasher worker which will hash all of the buffers it receives.
fn start_hash_worker(send: Sender<MasterMessage>,
                     work: Arc<MsQueue<WorkerMessage>>,
                     buffers: Arc<PieceBuffers>) {
    let mut work_to_do = true;

    // Loop until we are instructed to stop working
    while work_to_do {
        let work_item = work.pop();

        match work_item {
            WorkerMessage::Finish => {
                work_to_do = false;
            }
            WorkerMessage::HashPiece(index, buffer) => {
                let hash = ShaHash::from_bytes(buffer.as_slice());

                send.send(MasterMessage::AcceptPiece(index, hash)).unwrap();
                buffers.checkin(buffer);
            }
        }
    }

    // Let the master know we have exited our thread
    send.send(MasterMessage::WorkerFinished).unwrap();
}

#[cfg(test)]
mod tests {
    use std::ops::{Range, Index};
    use std::io::{self, Cursor, Read};
    use std::path::Path;
    use std::sync::mpsc;

    use bip_util::sha::ShaHash;
    use rand::{self, Rng};

    use accessor::Accessor;
    use builder::worker;

    // Keep these numbers fairly small to avoid lengthy tests
    const DEFAULT_PIECE_LENGTH: usize = 1024;
    const DEFAULT_NUM_PIECES: usize = 300;

    // Mock object for providing direct access to bytes via DataEntry.
    #[derive(Clone)]
    struct MockAccessor {
        buffer_ranges: Vec<Range<usize>>,
        contiguous_buffer: Vec<u8>,
    }

    impl MockAccessor {
        fn new() -> MockAccessor {
            MockAccessor {
                buffer_ranges: Vec::new(),
                contiguous_buffer: Vec::new(),
            }
        }

        fn create_region(&mut self, num_bytes: usize) {
            let mut buffer = vec![0u8; num_bytes];
            let mut rng = rand::thread_rng();

            rng.fill_bytes(&mut buffer);

            let (begin, end) = (self.contiguous_buffer.len(),
                                self.contiguous_buffer.len() + buffer.len());

            self.contiguous_buffer.extend_from_slice(&buffer);
            self.buffer_ranges.push(begin..end);
        }

        fn as_slice(&self) -> &[u8] {
            &self.contiguous_buffer
        }
    }

    impl Accessor for MockAccessor {
        /// Access the directory that all files should be relative to.
        fn access_directory(&self) -> Option<&str> {
            panic!("Accessor::access_directory should not be called with MockAccessor...");
        }

        /// Access the metadata for all files including their length and path.
        fn access_metadata<C>(&self, _: C) -> io::Result<()>
            where C: FnMut(u64, &Path)
        {
            panic!("Accessor::access_metadata should not be called with MockAccessor...");
        }

        /// Access the sequential pieces that make up all of the files.
        fn access_pieces<C>(&self, mut callback: C) -> io::Result<()>
            where C: FnMut(&mut Read) -> io::Result<()>
        {
            for range in self.buffer_ranges.iter() {
                let mut next_region = Cursor::new(self.contiguous_buffer.index(range.clone()));

                try!(callback(&mut next_region));
            }

            Ok(())
        }
    }

    fn validate_entries_pieces(accessor: MockAccessor, piece_length: usize, num_threads: usize) {
        let (prog_send, prog_recv) = mpsc::channel();

        let total_num_pieces = ((accessor.as_slice().len() as f64) / (piece_length as f64))
            .ceil() as u64;
        let received_pieces = worker::start_hasher_workers(&accessor,
                                                           piece_length,
                                                           total_num_pieces,
                                                           num_threads,
                                                           move |update| {
                                                               prog_send.send(update).unwrap();
                                                           }).unwrap();

        let computed_pieces = accessor.as_slice()
            .chunks(piece_length)
            .enumerate()
            .map(|(index, chunk)| (index, ShaHash::from_bytes(chunk)))
            .collect::<Vec<(usize, ShaHash)>>();

        let updates_received = prog_recv.iter().count() as u64;

        assert_eq!(total_num_pieces, updates_received);
        assert_eq!(received_pieces, computed_pieces);
    }

    #[test]
    fn positive_piece_length_divisible_region_single_thread() {
        let mut accessor = MockAccessor::new();

        let region_length = DEFAULT_PIECE_LENGTH * DEFAULT_NUM_PIECES;
        accessor.create_region(region_length);

        validate_entries_pieces(accessor, DEFAULT_PIECE_LENGTH, 1);
    }

    #[test]
    fn positive_piece_length_divisible_region_multiple_threads() {
        let mut accessor = MockAccessor::new();

        let region_length = DEFAULT_PIECE_LENGTH * DEFAULT_NUM_PIECES;
        accessor.create_region(region_length);

        validate_entries_pieces(accessor, DEFAULT_PIECE_LENGTH, 4);
    }

    #[test]
    fn positive_piece_length_undivisible_region_single_thread() {
        let mut accessor = MockAccessor::new();

        let region_length = DEFAULT_PIECE_LENGTH * DEFAULT_NUM_PIECES + 1;
        accessor.create_region(region_length);

        validate_entries_pieces(accessor, DEFAULT_PIECE_LENGTH, 1);
    }

    #[test]
    fn positive_piece_length_undivisible_region_multiple_threads() {
        let mut accessor = MockAccessor::new();

        let region_length = DEFAULT_PIECE_LENGTH * DEFAULT_NUM_PIECES + 1;
        accessor.create_region(region_length);

        validate_entries_pieces(accessor, DEFAULT_PIECE_LENGTH, 4);
    }

    #[test]
    fn positive_piece_length_divisible_regions_single_thread() {
        let mut accessor = MockAccessor::new();

        let region_lengths = [DEFAULT_PIECE_LENGTH * DEFAULT_NUM_PIECES,
                              DEFAULT_PIECE_LENGTH * 1,
                              DEFAULT_PIECE_LENGTH * 50];
        for &region_length in region_lengths.into_iter() {
            accessor.create_region(region_length);
        }

        validate_entries_pieces(accessor, DEFAULT_PIECE_LENGTH, 1);
    }

    #[test]
    fn positive_piece_length_divisible_regions_multiple_threads() {
        let mut accessor = MockAccessor::new();

        let region_lengths = [DEFAULT_PIECE_LENGTH * DEFAULT_NUM_PIECES,
                              DEFAULT_PIECE_LENGTH * 1,
                              DEFAULT_PIECE_LENGTH * 50];
        for &region_length in region_lengths.into_iter() {
            accessor.create_region(region_length);
        }

        validate_entries_pieces(accessor, DEFAULT_PIECE_LENGTH, 4);
    }

    #[test]
    fn positive_piece_length_undivisible_regions_single_thread() {
        let mut accessor = MockAccessor::new();

        let region_lengths = [DEFAULT_PIECE_LENGTH / 2 * DEFAULT_NUM_PIECES,
                              DEFAULT_PIECE_LENGTH / 4 * DEFAULT_NUM_PIECES,
                              DEFAULT_PIECE_LENGTH * 1,
                              (DEFAULT_PIECE_LENGTH * 2 - 1) * 2];
        for &region_length in region_lengths.into_iter() {
            accessor.create_region(region_length);
        }

        validate_entries_pieces(accessor, DEFAULT_PIECE_LENGTH, 1);
    }

    #[test]
    fn positive_piece_length_undivisible_regions_multiple_threads() {
        let mut accessor = MockAccessor::new();

        let region_lengths = [DEFAULT_PIECE_LENGTH / 2 * DEFAULT_NUM_PIECES,
                              DEFAULT_PIECE_LENGTH / 4 * DEFAULT_NUM_PIECES,
                              DEFAULT_PIECE_LENGTH * 1,
                              (DEFAULT_PIECE_LENGTH * 2 - 1) * 2];
        for &region_length in region_lengths.into_iter() {
            accessor.create_region(region_length);
        }

        validate_entries_pieces(accessor, DEFAULT_PIECE_LENGTH, 4);
    }
}
<|endoftext|>


<commit_before>const DATA: &'static str = include_str!("../data/input_24.txt");

use std::cmp;
use std::usize;
use std::cell::Cell;

pub fn main() -> Vec<String> {
    if let Ok(mut v) = DATA.lines()
                           .map(|l| l.parse::<u64>())
                           .collect::<Result<Vec<u64>, _>>() {
        v.sort_by(|a, b| b.cmp(a));

        let weight = v.iter().sum::<u64>() / 3;
        let s1 = min_qe(&v, weight).unwrap().to_string();

        let weight = v.iter().sum::<u64>() / 4;
        let s2 = min_qe(&v, weight).unwrap().to_string();

        vec![s1, s2]
    } else {
        vec![]
    }
}

fn min_qe(data: &[u64], weight: u64) -> Option<u64> {
    let best_size: Cell<usize> = Cell::new(usize::MAX);
    let stop = |ss: &[u64]| (ss.iter().sum::<u64>() > weight) || (ss.len() > best_size.get());
    let ps = PowerSet::with_prune_condition(&data, stop);
    let subsets = ps.filter(|ss| ss.iter().sum::<u64>() == weight)
                    .inspect(|ss| best_size.set(cmp::min(best_size.get(), ss.len())))
                    .collect::<Vec<_>>();
    subsets.iter()
           .filter(|ss| ss.len() == best_size.get())
           .map(|ss| ss.iter().product::<u64>())
           .min()
}

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

    #[test]
    fn example_1() {
        let data = [1, 2, 3, 4, 5, 7, 8, 9, 10, 11];
        assert_eq!(min_qe(&data, data.iter().sum::<u64>() / 3), Some(99));
    }

    #[test]
    fn example_2() {
        let data = [1, 2, 3, 4, 5, 7, 8, 9, 10, 11];
        assert_eq!(min_qe(&data, data.iter().sum::<u64>() / 4), Some(44));
    }
}

struct PowerSet<'a, T>
    where T: 'a + Copy
{
    stack: Vec<(Vec<T>, &'a [T])>,
    stop: Box<Fn(&[T]) -> bool + 'a>,
}

impl<'a, T> PowerSet<'a, T> where T: 'a + Copy
{
    fn new(data: &'a [T]) -> PowerSet<'a, T> {
        let mut stack = Vec::new();
        if let Some((selected, remaining)) = data.split_last() {
            stack.push((vec![*selected], remaining));
            stack.push((vec![], remaining));
        } else {
            stack.push((vec![], data))
        }
        PowerSet {
            stack: stack,
            stop: box |_| false,
        }
    }

    fn with_prune_condition<F>(data: &'a [T], stop: F) -> PowerSet<'a, T>
        where F: 'a + Fn(&[T]) -> bool
    {
        PowerSet { stop: box stop, ..PowerSet::new(data) }
    }
}

impl<'a, T> Iterator for PowerSet<'a, T> where T: 'a + Copy
{
    type Item = Vec<T>;

    fn next(&mut self) -> Option<Vec<T>> {
        if let Some((selected, remaining)) = self.stack.pop() {
            if let Some((sel, rem)) = remaining.split_last() {
                if !(self.stop)(&selected) {
                    let mut r = selected.clone();
                    r.push(*sel);
                    self.stack.push((r, rem));
                    self.stack.push((selected, rem));
                }
                self.next()
            } else {
                Some(selected)
            }
        } else {
            None
        }
    }
}
<commit_msg>more bikeshedding on 24<commit_after>const DATA: &'static str = include_str!("../data/input_24.txt");

use std::cmp;
use std::{usize, u64};
use std::cell::Cell;

pub fn main() -> Vec<String> {
    if let Ok(mut v) = DATA.lines()
                           .map(|l| l.parse::<u64>())
                           .collect::<Result<Vec<u64>, _>>() {
        v.sort_by(|a, b| b.cmp(a));

        let weight = v.iter().sum::<u64>() / 3;
        let s1 = min_qe(&v, weight).unwrap().to_string();

        let weight = v.iter().sum::<u64>() / 4;
        let s2 = min_qe(&v, weight).unwrap().to_string();

        vec![s1, s2]
    } else {
        vec![]
    }
}

fn min_qe(data: &[u64], weight: u64) -> Option<u64> {
    let best = Cell::new((usize::MAX, u64::MAX));
    let stop = |ss: &[u64]| {
        (ss.iter().sum::<u64>() > weight) || ((ss.len(), ss.iter().product()) > best.get())
    };
    let ps = PowerSet::with_prune_condition(&data, stop);
    return ps.filter(|ss| ss.iter().sum::<u64>() == weight)
             .map(|ss| (ss.len(), ss.iter().product::<u64>()))
             .inspect(|&k| best.set(cmp::min(best.get(), k)))
             .min()
             .map(|k| k.1);
}

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

    #[test]
    fn example_1() {
        let data = [1, 2, 3, 4, 5, 7, 8, 9, 10, 11];
        assert_eq!(min_qe(&data, data.iter().sum::<u64>() / 3), Some(99));
    }

    #[test]
    fn example_2() {
        let data = [1, 2, 3, 4, 5, 7, 8, 9, 10, 11];
        assert_eq!(min_qe(&data, data.iter().sum::<u64>() / 4), Some(44));
    }
}

struct PowerSet<'a, T>
    where T: 'a + Copy
{
    stack: Vec<(Vec<T>, &'a [T])>,
    stop: Box<Fn(&[T]) -> bool + 'a>,
}

impl<'a, T> PowerSet<'a, T> where T: 'a + Copy
{
    fn new(data: &'a [T]) -> PowerSet<'a, T> {
        let mut stack = Vec::new();
        if let Some((selected, remaining)) = data.split_last() {
            stack.push((vec![*selected], remaining));
            stack.push((vec![], remaining));
        } else {
            stack.push((vec![], data))
        }
        PowerSet {
            stack: stack,
            stop: box |_| false,
        }
    }

    fn with_prune_condition<F>(data: &'a [T], stop: F) -> PowerSet<'a, T>
        where F: 'a + Fn(&[T]) -> bool
    {
        PowerSet { stop: box stop, ..PowerSet::new(data) }
    }
}

impl<'a, T> Iterator for PowerSet<'a, T> where T: 'a + Copy
{
    type Item = Vec<T>;

    fn next(&mut self) -> Option<Vec<T>> {
        if let Some((selected, remaining)) = self.stack.pop() {
            if let Some((sel, rem)) = remaining.split_last() {
                if !(self.stop)(&selected) {
                    let mut r = selected.clone();
                    r.push(*sel);
                    self.stack.push((r, rem));
                    self.stack.push((selected, rem));
                }
                self.next()
            } else {
                Some(selected)
            }
        } else {
            None
        }
    }
}
<|endoftext|>


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

use std;
use std::fmt::{self, Display};
use std::iter::FromIterator;

use proc_macro2::{
    Delimiter, Group, Ident, LexError, Literal, Punct, Spacing, Span, TokenStream, TokenTree,
};
#[cfg(feature = "printing")]
use quote::ToTokens;

use buffer::Cursor;
use thread::ThreadBound;

/// The result of a Syn parser.
pub type Result<T> = std::result::Result<T, Error>;

/// Error returned when a Syn parser cannot parse the input tokens.
///
/// Refer to the [module documentation] for details about parsing in Syn.
///
/// [module documentation]: index.html
///
/// *This type is available if Syn is built with the `"parsing"` feature.*
#[derive(Debug)]
pub struct Error {
    // Span is implemented as an index into a thread-local interner to keep the
    // size small. It is not safe to access from a different thread. We want
    // errors to be Send and Sync to play nicely with the Failure crate, so pin
    // the span we're given to its original thread and assume it is
    // Span::call_site if accessed from any other thread.
    start_span: ThreadBound<Span>,
    end_span: ThreadBound<Span>,
    message: String,
}

#[cfg(test)]
struct _Test where Error: Send + Sync;

impl Error {
    /// Usually the [`ParseStream::error`] method will be used instead, which
    /// automatically uses the correct span from the current position of the
    /// parse stream.
    ///
    /// Use `Error::new` when the error needs to be triggered on some span other
    /// than where the parse stream is currently positioned.
    ///
    /// [`ParseStream::error`]: struct.ParseBuffer.html#method.error
    ///
    /// # Example
    ///
    /// ```
    /// #[macro_use]
    /// extern crate syn;
    ///
    /// use syn::{Ident, LitStr};
    /// use syn::parse::{Error, ParseStream, Result};
    ///
    /// // Parses input that looks like `name = "string"` where the key must be
    /// // the identifier `name` and the value may be any string literal.
    /// // Returns the string literal.
    /// fn parse_name(input: ParseStream) -> Result<LitStr> {
    ///     let name_token: Ident = input.parse()?;
    ///     if name_token != "name" {
    ///         // Trigger an error not on the current position of the stream,
    ///         // but on the position of the unexpected identifier.
    ///         return Err(Error::new(name_token.span(), "expected `name`"));
    ///     }
    ///     input.parse::<Token![=]>()?;
    ///     let s: LitStr = input.parse()?;
    ///     Ok(s)
    /// }
    /// #
    /// # fn main() {}
    /// ```
    pub fn new<T: Display>(span: Span, message: T) -> Self {
        Error {
            start_span: ThreadBound::new(span),
            end_span: ThreadBound::new(span),
            message: message.to_string(),
        }
    }

    /// Creates an error which spans the items provided with the specified
    /// message.
    ///
    /// Unlike the `new` constructor this constructors takes a spanned item (the
    /// first argument here). This allows the `Error` returned to attempt to
    /// ensure it spans all the tokens inside of `tokens`. While you typically
    /// can use the `Spanned` trait with the above `new` constructor
    /// implementation limitations today mean that this constructor may provide
    /// a higher-quality error message on stable Rust.
    ///
    /// When in doubt it's recommended to stick to `Error::new` (or
    /// `ParseStream::error`)!
    #[cfg(feature = "printing")]
    pub fn new_spanned<T: ToTokens, U: Display>(tokens: T, message: U) -> Self {
        let mut iter = tokens.into_token_stream().into_iter();
        let start = iter.next().map(|t| t.span()).unwrap_or(Span::call_site());
        let end = iter.last().map(|t| t.span()).unwrap_or(Span::call_site());
        Error {
            start_span: ThreadBound::new(start),
            end_span: ThreadBound::new(end),
            message: message.to_string(),
        }
    }

    /// The source location of the error.
    ///
    /// Spans are not thread-safe so this function returns `Span::call_site()`
    /// if called from a different thread than the one on which the `Error` was
    /// originally created.
    pub fn span(&self) -> Span {
        let start = match self.start_span.get() {
            Some(span) => *span,
            None => return Span::call_site(),
        };

        #[cfg(procmacro2_semver_exempt)]
        {
            let end = match self.end_span.get() {
                Some(span) => *span,
                None => return Span::call_site(),
            };
            start.join(end).unwrap_or(start)
        }
        #[cfg(not(procmacro2_semver_exempt))]
        {
            start
        }
    }

    /// Render the error as an invocation of [`compile_error!`].
    ///
    /// The [`parse_macro_input!`] macro provides a convenient way to invoke
    /// this method correctly in a procedural macro.
    ///
    /// [`compile_error!`]: https://doc.rust-lang.org/std/macro.compile_error.html
    /// [`parse_macro_input!`]: ../macro.parse_macro_input.html
    pub fn to_compile_error(&self) -> TokenStream {
        let start = self.start_span.get().cloned().unwrap_or(Span::call_site());
        let end = self.end_span.get().cloned().unwrap_or(Span::call_site());

        // compile_error!($message)
        TokenStream::from_iter(vec![
            TokenTree::Ident(Ident::new("compile_error", start)),
            TokenTree::Punct({
                let mut punct = Punct::new('!', Spacing::Alone);
                punct.set_span(start);
                punct
            }),
            TokenTree::Group({
                let mut group = Group::new(Delimiter::Brace, {
                    TokenStream::from_iter(vec![TokenTree::Literal({
                        let mut string = Literal::string(&self.message);
                        string.set_span(end);
                        string
                    })])
                });
                group.set_span(end);
                group
            }),
        ])
    }
}

pub fn new_at<T: Display>(scope: Span, cursor: Cursor, message: T) -> Error {
    if cursor.eof() {
        Error::new(scope, format!("unexpected end of input, {}", message))
    } else {
        Error::new(cursor.span(), message)
    }
}

impl Display for Error {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        formatter.write_str(&self.message)
    }
}

impl Clone for Error {
    fn clone(&self) -> Self {
        let start = self.start_span.get().cloned().unwrap_or(Span::call_site());
        let end = self.end_span.get().cloned().unwrap_or(Span::call_site());
        Error {
            start_span: ThreadBound::new(start),
            end_span: ThreadBound::new(end),
            message: self.message.clone(),
        }
    }
}

impl std::error::Error for Error {
    fn description(&self) -> &str {
        "parse error"
    }
}

impl From<LexError> for Error {
    fn from(err: LexError) -> Self {
        Error::new(Span::call_site(), format!("{:?}", err))
    }
}
<commit_msg>Better error message from new_spanned when input is a single token<commit_after>// Copyright 2018 Syn Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use std;
use std::fmt::{self, Display};
use std::iter::FromIterator;

use proc_macro2::{
    Delimiter, Group, Ident, LexError, Literal, Punct, Spacing, Span, TokenStream, TokenTree,
};
#[cfg(feature = "printing")]
use quote::ToTokens;

use buffer::Cursor;
use thread::ThreadBound;

/// The result of a Syn parser.
pub type Result<T> = std::result::Result<T, Error>;

/// Error returned when a Syn parser cannot parse the input tokens.
///
/// Refer to the [module documentation] for details about parsing in Syn.
///
/// [module documentation]: index.html
///
/// *This type is available if Syn is built with the `"parsing"` feature.*
#[derive(Debug)]
pub struct Error {
    // Span is implemented as an index into a thread-local interner to keep the
    // size small. It is not safe to access from a different thread. We want
    // errors to be Send and Sync to play nicely with the Failure crate, so pin
    // the span we're given to its original thread and assume it is
    // Span::call_site if accessed from any other thread.
    start_span: ThreadBound<Span>,
    end_span: ThreadBound<Span>,
    message: String,
}

#[cfg(test)]
struct _Test where Error: Send + Sync;

impl Error {
    /// Usually the [`ParseStream::error`] method will be used instead, which
    /// automatically uses the correct span from the current position of the
    /// parse stream.
    ///
    /// Use `Error::new` when the error needs to be triggered on some span other
    /// than where the parse stream is currently positioned.
    ///
    /// [`ParseStream::error`]: struct.ParseBuffer.html#method.error
    ///
    /// # Example
    ///
    /// ```
    /// #[macro_use]
    /// extern crate syn;
    ///
    /// use syn::{Ident, LitStr};
    /// use syn::parse::{Error, ParseStream, Result};
    ///
    /// // Parses input that looks like `name = "string"` where the key must be
    /// // the identifier `name` and the value may be any string literal.
    /// // Returns the string literal.
    /// fn parse_name(input: ParseStream) -> Result<LitStr> {
    ///     let name_token: Ident = input.parse()?;
    ///     if name_token != "name" {
    ///         // Trigger an error not on the current position of the stream,
    ///         // but on the position of the unexpected identifier.
    ///         return Err(Error::new(name_token.span(), "expected `name`"));
    ///     }
    ///     input.parse::<Token![=]>()?;
    ///     let s: LitStr = input.parse()?;
    ///     Ok(s)
    /// }
    /// #
    /// # fn main() {}
    /// ```
    pub fn new<T: Display>(span: Span, message: T) -> Self {
        Error {
            start_span: ThreadBound::new(span),
            end_span: ThreadBound::new(span),
            message: message.to_string(),
        }
    }

    /// Creates an error which spans the items provided with the specified
    /// message.
    ///
    /// Unlike the `new` constructor this constructors takes a spanned item (the
    /// first argument here). This allows the `Error` returned to attempt to
    /// ensure it spans all the tokens inside of `tokens`. While you typically
    /// can use the `Spanned` trait with the above `new` constructor
    /// implementation limitations today mean that this constructor may provide
    /// a higher-quality error message on stable Rust.
    ///
    /// When in doubt it's recommended to stick to `Error::new` (or
    /// `ParseStream::error`)!
    #[cfg(feature = "printing")]
    pub fn new_spanned<T: ToTokens, U: Display>(tokens: T, message: U) -> Self {
        let mut iter = tokens.into_token_stream().into_iter();
        let start = iter.next().map(|t| t.span()).unwrap_or(Span::call_site());
        let end = iter.last().map(|t| t.span()).unwrap_or(start);
        Error {
            start_span: ThreadBound::new(start),
            end_span: ThreadBound::new(end),
            message: message.to_string(),
        }
    }

    /// The source location of the error.
    ///
    /// Spans are not thread-safe so this function returns `Span::call_site()`
    /// if called from a different thread than the one on which the `Error` was
    /// originally created.
    pub fn span(&self) -> Span {
        let start = match self.start_span.get() {
            Some(span) => *span,
            None => return Span::call_site(),
        };

        #[cfg(procmacro2_semver_exempt)]
        {
            let end = match self.end_span.get() {
                Some(span) => *span,
                None => return Span::call_site(),
            };
            start.join(end).unwrap_or(start)
        }
        #[cfg(not(procmacro2_semver_exempt))]
        {
            start
        }
    }

    /// Render the error as an invocation of [`compile_error!`].
    ///
    /// The [`parse_macro_input!`] macro provides a convenient way to invoke
    /// this method correctly in a procedural macro.
    ///
    /// [`compile_error!`]: https://doc.rust-lang.org/std/macro.compile_error.html
    /// [`parse_macro_input!`]: ../macro.parse_macro_input.html
    pub fn to_compile_error(&self) -> TokenStream {
        let start = self.start_span.get().cloned().unwrap_or(Span::call_site());
        let end = self.end_span.get().cloned().unwrap_or(Span::call_site());

        // compile_error!($message)
        TokenStream::from_iter(vec![
            TokenTree::Ident(Ident::new("compile_error", start)),
            TokenTree::Punct({
                let mut punct = Punct::new('!', Spacing::Alone);
                punct.set_span(start);
                punct
            }),
            TokenTree::Group({
                let mut group = Group::new(Delimiter::Brace, {
                    TokenStream::from_iter(vec![TokenTree::Literal({
                        let mut string = Literal::string(&self.message);
                        string.set_span(end);
                        string
                    })])
                });
                group.set_span(end);
                group
            }),
        ])
    }
}

pub fn new_at<T: Display>(scope: Span, cursor: Cursor, message: T) -> Error {
    if cursor.eof() {
        Error::new(scope, format!("unexpected end of input, {}", message))
    } else {
        Error::new(cursor.span(), message)
    }
}

impl Display for Error {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        formatter.write_str(&self.message)
    }
}

impl Clone for Error {
    fn clone(&self) -> Self {
        let start = self.start_span.get().cloned().unwrap_or(Span::call_site());
        let end = self.end_span.get().cloned().unwrap_or(Span::call_site());
        Error {
            start_span: ThreadBound::new(start),
            end_span: ThreadBound::new(end),
            message: self.message.clone(),
        }
    }
}

impl std::error::Error for Error {
    fn description(&self) -> &str {
        "parse error"
    }
}

impl From<LexError> for Error {
    fn from(err: LexError) -> Self {
        Error::new(Span::call_site(), format!("{:?}", err))
    }
}
<|endoftext|>


<commit_before>use std::io::{IoError,IoErrorKind,IoResult};
use std::io::net::ip::{Ipv4Addr,SocketAddr};
use std::io::net::tcp::{TcpStream};

// TODO: need a much better system for identifying the messages (by type) than this simple hard-coded list, but wtf...
static HPV_MSG_ID_JOIN: u8 = 0;
static HPV_MSG_ID_FORWARD_JOIN: u8 = 1;
static HPV_MSG_ID_JOIN_ACK: u8 = 2;
static HPV_MSG_ID_DISCONNECT: u8 = 3;
static HPV_MSG_ID_NEIGHBOR_REQUEST: u8 = 4;
static HPV_MSG_ID_NEIGHBOR_RESPONSE: u8 = 5;
static HPV_MSG_ID_SHUFFLE: u8 = 6;
static HPV_MSG_ID_SHUFFLE_REPLY: u8 = 7;

#[derive(Copy,Show,PartialEq)]
pub enum Priority {
    High,
    Low
}

#[derive(Copy,Show)]
pub enum Result {
    Accept,
    Reject
}

#[derive(Show)]
pub enum HyParViewMessage {
    JoinMessage(Join,SocketAddr),
    ForwardJoinMessage(ForwardJoin,SocketAddr),
    JoinAckMessage(JoinAck,SocketAddr),
    DisconnectMessage(Disconnect,SocketAddr),
    NeighborRequestMessage(NeighborRequest,SocketAddr),
    NeighborResponseMessage(NeighborResponse,SocketAddr),
    ShuffleMessage(Shuffle,SocketAddr),
    ShuffleReplyMessage(ShuffleReply,SocketAddr),
}

/// top-level function for serializing a HyParView message.
pub fn deserialize(reader: &mut TcpStream) -> IoResult<HyParViewMessage> {
    let header = match Header::deserialize(reader) {
        Ok(header) => header,
        Err(e) => return Err(e),
    };

    match header.msg_id {
        0 => Ok(HyParViewMessage::JoinMessage(Join::new(), header.sender)),
        1 => Ok(HyParViewMessage::ForwardJoinMessage(ForwardJoin::deserialize(reader).ok().expect("failed to deserailize the forward join"), header.sender)),
        2 => Ok(HyParViewMessage::JoinAckMessage(JoinAck::new(), header.sender)),
        3 => Ok(HyParViewMessage::DisconnectMessage(Disconnect::new(), header.sender)),
        4 => Ok(HyParViewMessage::NeighborRequestMessage(NeighborRequest::deserialize(reader).ok().expect("failed to deserailize the neighbor request"), header.sender)),
        5 => Ok(HyParViewMessage::NeighborResponseMessage(NeighborResponse::deserialize(reader).ok().expect("failed to deserailize the neighbor response"), header.sender)),
        6 => Ok(HyParViewMessage::ShuffleMessage(Shuffle::deserialize(reader).ok().expect("failed to deserailize the shuffle"), header.sender)),
        7 => Ok(HyParViewMessage::ShuffleReplyMessage(ShuffleReply::deserialize(reader).ok().expect("failed to deserailize the shuffle reply"), header.sender)),
        _ => Err(IoError{ kind: IoErrorKind::InvalidInput, desc: "unknown message id passed in".as_slice(), detail: None }),
    }
}

struct Header {
    sender: SocketAddr,
    msg_id: u8,
}
impl Header {
    fn new(sender: &SocketAddr, msg_id: u8) -> Header {
        Header { sender: *sender, msg_id: msg_id }
    }

    fn serailize(&self, writer: &mut Writer) -> IoResult<int> {
        let mut cnt = 1;
        match serialize_socket_addr(&self.sender, writer) {
            Ok(c) => cnt += c,
            Err(e) => return Err(e),
        }
        writer.write_u8(self.msg_id).ok();
        cnt += 1;
        Ok(cnt)
    }

    fn deserialize(reader: &mut Reader) -> IoResult<Header> {
        // TODO: this is a bit verbose, both match clauses
        let sender = match deserialize_socket_addr(reader) {
            Ok(socket) => socket,
            Err(e) => return Err(e),
        };

        let msg_id = match reader.read_u8() {
            Ok(id) => id,
            Err(e) => return Err(e),
        };
        Ok(Header { sender: sender, msg_id: msg_id })
    }
}

/// helper function to efficiently serialize a SocketAddr
fn serialize_socket_addr(sa: &SocketAddr, writer: &mut Writer) -> IoResult<int> {
    match sa.ip {
        Ipv4Addr(a, b, c, d) => {
            writer.write_u8(a).ok();
            writer.write_u8(b).ok();
            writer.write_u8(c).ok();
            writer.write_u8(d).ok();
            writer.write_be_u16(sa.port).ok();
        },
        _ => println!("dont care yet!"),
    }
    Ok(4 + 2)
}

/// helper function to efficiently deserialize a SocketAddr
fn deserialize_socket_addr(reader: &mut Reader) -> IoResult<SocketAddr> {
//    let mut buf = [0u8, ..4];
    let mut buf = Vec::with_capacity(4);
    let mut i = 0;
    while i < buf.len() {
        buf[i] = reader.read_u8().ok().expect("couldn't read next byte for ip address");
        i += 1;
    }
    let ip = Ipv4Addr (buf[0], buf[1], buf[2], buf[3]);
    let port = reader.read_be_u16().ok().expect("couldn't read port for socket address");

    let sa: SocketAddr = SocketAddr { ip: ip , port: port };
    Ok(sa)
}

#[derive(Copy,Show)]
//TODO: add a message uuid so we can register a callback (to make sure the join message gets a reponse, else resend the request)
pub struct Join;
impl Join {
    pub fn new() -> Join {
        Join
    }

    pub fn serialize(&self, writer: &mut Writer, sender: &SocketAddr) -> IoResult<int> {
        Header::new(sender, HPV_MSG_ID_JOIN).serailize(writer)
    }
}

#[derive(Copy,Show)]
pub struct ForwardJoin {
    pub originator: SocketAddr,
    pub arwl: u8,
    pub prwl: u8,
    pub ttl: u8
}
impl ForwardJoin {
    pub fn new(addr: &SocketAddr, arwl: u8, prwl: u8, ttl: u8) -> ForwardJoin {
        ForwardJoin { originator: *addr, arwl: arwl, prwl: prwl, ttl: ttl }
    }

    pub fn deserialize(reader: &mut Reader) -> IoResult<ForwardJoin> {
        match deserialize_socket_addr(reader) {
            Ok(socket) => {
                let arwl = reader.read_u8().ok().expect("could not read arwl from stream");
                let prwl = reader.read_u8().ok().expect("could not read prwl from stream");
                let ttl = reader.read_u8().ok().expect("could not read ttl from stream");
                Ok(ForwardJoin::new(&socket, arwl, prwl, ttl))
            },
            Err(e) => Err(e),
        }
    }

    pub fn serialize(&self, writer: &mut Writer, sender: &SocketAddr) -> IoResult<int> {
        let mut cnt = 0;
        let header = Header::new(sender, HPV_MSG_ID_FORWARD_JOIN);
        match header.serailize(writer) {
            Ok(c) => cnt += c,
            Err(e) => return Err(e),
        }

        match serialize_socket_addr(&self.originator, writer) {
            Ok(c) => cnt += c,
            Err(e) => return Err(e),
        }

        writer.write_u8(self.arwl).ok();
        cnt += 1;
        writer.write_u8(self.prwl).ok();
        cnt += 1;
        writer.write_u8(self.ttl).ok();
        cnt += 1;
        Ok(cnt)
    }
}

#[test]
fn test_join_serialization() {
    use std::io::{MemReader,BufferedWriter};
    use std::io::net::ip::{SocketAddr};

    let arwl = 6u8;
    let prwl = 3u8;
    let ttl = 4u8;

    let sock_addr: SocketAddr = from_str("127.0.0.1:9090").expect("invalid socket addr");
    let fjoin_msg = ForwardJoin::new(&sock_addr, arwl, prwl, ttl);
    let vec = Vec::new();
    let mut writer = BufferedWriter::new(vec);
    let result = fjoin_msg.serialize(&mut writer);

    let vec = writer.into_inner();
    let mut reader = MemReader::new(vec);
    let header = reader.read_u8().ok().expect("failed to read the header");
    let return_fjoin_msg = ForwardJoin::deserialize(&mut reader).ok().expect("failed to parse socket addr");
    assert!(return_fjoin_msg.originator.eq(&sock_addr));
    assert_eq!(return_fjoin_msg.arwl, arwl);
    assert_eq!(return_fjoin_msg.prwl, prwl);
    assert_eq!(return_fjoin_msg.ttl, ttl);
}

#[derive(Copy,Show)]
pub struct Disconnect;
impl Disconnect {
    pub fn new() -> Disconnect {
        Disconnect
    }

     pub fn serialize(&self, writer: &mut Writer, sender: &SocketAddr) -> IoResult<int> {
        Header::new(sender, HPV_MSG_ID_DISCONNECT).serailize(writer)
    }
}

#[derive(Copy,Show)]
pub struct JoinAck;
impl JoinAck {
    pub fn new() -> JoinAck {
        JoinAck
    }

    pub fn serialize(&self, writer: &mut Writer, sender: &SocketAddr) -> IoResult<int> {
        Header::new(sender, HPV_MSG_ID_JOIN_ACK).serailize(writer)
    }
}

#[derive(Copy,Show)]
pub struct NeighborRequest {
    pub priority: Priority,
}
impl NeighborRequest {
    pub fn new(priority: Priority) -> NeighborRequest {
        NeighborRequest { priority: priority}
    }

    pub fn deserialize(reader: &mut Reader) -> IoResult<NeighborRequest> {
        let p = match reader.read_u8().ok().expect("could not read priority from stream") {
            0 => Priority::Low,
            1 => Priority::High,
            //println!("received unknown priority level, defaulting to low priority");
            _ =>  Priority::Low,
        };
        Ok(NeighborRequest::new(p))
    }

    pub fn serialize(&self, writer: &mut Writer, sender: &SocketAddr) -> IoResult<int> {
        let mut cnt = 0;
        let header = Header::new(sender, HPV_MSG_ID_NEIGHBOR_REQUEST);
        match header.serailize(writer) {
            Ok(c) => cnt += c,
            Err(e) => return Err(e),
        }

        let p: u8 = match self.priority {
            Priority::Low => 0,
            Priority::High => 1,
        };
        writer.write_u8(p).ok();
        cnt += 1;
        Ok(cnt)
    }
}

#[derive(Copy,Show)]
pub struct NeighborResponse {
    pub result: Result,
}
impl NeighborResponse {
    pub fn new(result: Result) -> NeighborResponse {
        NeighborResponse { result: result }
    }

    pub fn deserialize(reader: &mut Reader) -> IoResult<NeighborResponse> {
        let r = match reader.read_u8().ok().expect("could not read result from stream") {
            0 => Result::Accept,
            1 => Result::Reject,
            // if we can't undertand the result code, just default to reject
            _ => Result::Reject
        };
        Ok(NeighborResponse::new(r))
    }

    pub fn serialize(&self, writer: &mut Writer, sender: &SocketAddr) -> IoResult<int> {
        let mut cnt = 0;
        let header = Header::new(sender, HPV_MSG_ID_NEIGHBOR_RESPONSE);
        match header.serailize(writer) {
            Ok(c) => cnt += c,
            Err(e) => return Err(e),
        }

        let p: u8 = match self.result {
            Result::Accept => 0,
            Result::Reject => 1,
        };
        writer.write_u8(p).ok();
        cnt += 1;
        Ok(cnt)
    }
}

#[derive(Show)]
pub struct Shuffle {
    pub originator: SocketAddr,
    pub nodes: Vec<SocketAddr>,
    pub ttl: u8,
}
impl Shuffle {
    pub fn new(originator: SocketAddr, nodes: Vec<SocketAddr>, ttl: u8) -> Shuffle {
        Shuffle { originator: originator, nodes: nodes, ttl: ttl }
    }

    pub fn deserialize(reader: &mut Reader) -> IoResult<Shuffle> {
        let originator = deserialize_socket_addr(reader).ok().expect("could not read socket addr from stream");
        let nodes = deserialize_socket_addrs(reader);
        let ttl = reader.read_u8().ok().expect("could not read ttl from stream");
        Ok(Shuffle::new(originator, nodes, ttl))
    }

    pub fn serialize(&self, writer: &mut Writer, sender: &SocketAddr) -> IoResult<int> {
        let mut cnt = 0;
        let header = Header::new(sender, HPV_MSG_ID_SHUFFLE);
        match header.serailize(writer) {
            Ok(c) => cnt += c,
            Err(e) => return Err(e),
        }

        match serialize_socket_addr(&self.originator, writer) {
            Ok(c) => cnt += c,
            Err(e) => return Err(e),
        }

        match serialize_socket_addrs(&self.nodes, writer) {
            Ok(c) => cnt += c,
            Err(e) => return Err(e),
        }

        writer.write_u8(self.ttl).ok();
        cnt += 1;
        Ok(cnt)
    }
}

fn deserialize_socket_addrs(reader: &mut Reader) -> Vec<SocketAddr> {
    let len = reader.read_u8().ok().expect("could not read vector size from stream") as uint;
    let mut nodes = Vec::with_capacity(len);

    for _ in range (0u, len) {
        match deserialize_socket_addr(reader) {
            Ok(socket) => nodes.push(socket),
            Err(_) => println!("failed"),
        }
    }
    nodes
}

fn serialize_socket_addrs(nodes: &Vec<SocketAddr>, writer: &mut Writer) -> IoResult<int> {
    let mut cnt = 0;
    writer.write_u8(nodes.len() as u8).ok().expect("failed to write vec len");
    cnt += 1;

    for node in nodes.iter() {
        match serialize_socket_addr(node, writer) {
            Ok(c) => cnt += c,
            Err(e) => return Err(e),
        }
    }
    Ok(cnt)
}

#[derive(Show)]
pub struct ShuffleReply {
    /// return the vector of nodes the originator first sent out; that way the originator does not need to keep track of that.
    pub sent_nodes: Vec<SocketAddr>,
    pub nodes: Vec<SocketAddr>,
}
impl ShuffleReply {
    pub fn new(sent_nodes: Vec<SocketAddr>, nodes: Vec<SocketAddr>) -> ShuffleReply {
        ShuffleReply { sent_nodes: sent_nodes, nodes: nodes }
    }

    pub fn deserialize(reader: &mut Reader) -> IoResult<ShuffleReply> {
        let sent_nodes = deserialize_socket_addrs(reader);
        let nodes = deserialize_socket_addrs(reader);
        Ok(ShuffleReply::new(sent_nodes, nodes))
    }

    pub fn serialize(&self, writer: &mut Writer, sender: &SocketAddr) -> IoResult<int> {
        let mut cnt = 0;
        let header = Header::new(sender, HPV_MSG_ID_SHUFFLE_REPLY);
        match header.serailize(writer) {
            Ok(c) => cnt += c,
            Err(e) => return Err(e),
        }

        match serialize_socket_addrs(&self.sent_nodes, writer) {
            Ok(c) => cnt += c,
            Err(e) => return Err(e),
        }

        match serialize_socket_addrs(&self.nodes, writer) {
            Ok(c) => cnt += c,
            Err(e) => return Err(e),
        }
        Ok(cnt)
    }
}
<commit_msg>fixed minor bug wrt derializing socket addrs<commit_after>use std::io::{IoError,IoErrorKind,IoResult};
use std::io::net::ip::{Ipv4Addr,SocketAddr};
use std::io::net::tcp::{TcpStream};

// TODO: need a much better system for identifying the messages (by type) than this simple hard-coded list, but wtf...
static HPV_MSG_ID_JOIN: u8 = 0;
static HPV_MSG_ID_FORWARD_JOIN: u8 = 1;
static HPV_MSG_ID_JOIN_ACK: u8 = 2;
static HPV_MSG_ID_DISCONNECT: u8 = 3;
static HPV_MSG_ID_NEIGHBOR_REQUEST: u8 = 4;
static HPV_MSG_ID_NEIGHBOR_RESPONSE: u8 = 5;
static HPV_MSG_ID_SHUFFLE: u8 = 6;
static HPV_MSG_ID_SHUFFLE_REPLY: u8 = 7;

#[derive(Copy,Show,PartialEq)]
pub enum Priority {
    High,
    Low
}

#[derive(Copy,Show)]
pub enum Result {
    Accept,
    Reject
}

#[derive(Show)]
pub enum HyParViewMessage {
    JoinMessage(Join,SocketAddr),
    ForwardJoinMessage(ForwardJoin,SocketAddr),
    JoinAckMessage(JoinAck,SocketAddr),
    DisconnectMessage(Disconnect,SocketAddr),
    NeighborRequestMessage(NeighborRequest,SocketAddr),
    NeighborResponseMessage(NeighborResponse,SocketAddr),
    ShuffleMessage(Shuffle,SocketAddr),
    ShuffleReplyMessage(ShuffleReply,SocketAddr),
}

/// top-level function for serializing a HyParView message.
pub fn deserialize(reader: &mut TcpStream) -> IoResult<HyParViewMessage> {
    let header = match Header::deserialize(reader) {
        Ok(header) => header,
        Err(e) => return Err(e),
    };

    match header.msg_id {
        0 => Ok(HyParViewMessage::JoinMessage(Join::new(), header.sender)),
        1 => Ok(HyParViewMessage::ForwardJoinMessage(ForwardJoin::deserialize(reader).ok().expect("failed to deserailize the forward join"), header.sender)),
        2 => Ok(HyParViewMessage::JoinAckMessage(JoinAck::new(), header.sender)),
        3 => Ok(HyParViewMessage::DisconnectMessage(Disconnect::new(), header.sender)),
        4 => Ok(HyParViewMessage::NeighborRequestMessage(NeighborRequest::deserialize(reader).ok().expect("failed to deserailize the neighbor request"), header.sender)),
        5 => Ok(HyParViewMessage::NeighborResponseMessage(NeighborResponse::deserialize(reader).ok().expect("failed to deserailize the neighbor response"), header.sender)),
        6 => Ok(HyParViewMessage::ShuffleMessage(Shuffle::deserialize(reader).ok().expect("failed to deserailize the shuffle"), header.sender)),
        7 => Ok(HyParViewMessage::ShuffleReplyMessage(ShuffleReply::deserialize(reader).ok().expect("failed to deserailize the shuffle reply"), header.sender)),
        _ => Err(IoError{ kind: IoErrorKind::InvalidInput, desc: "unknown message id passed in".as_slice(), detail: None }),
    }
}

struct Header {
    sender: SocketAddr,
    msg_id: u8,
}
impl Header {
    fn new(sender: &SocketAddr, msg_id: u8) -> Header {
        Header { sender: *sender, msg_id: msg_id }
    }

    fn serailize(&self, writer: &mut Writer) -> IoResult<int> {
        let mut cnt = 1;
        match serialize_socket_addr(&self.sender, writer) {
            Ok(c) => cnt += c,
            Err(e) => return Err(e),
        }
        writer.write_u8(self.msg_id).ok();
        cnt += 1;
        Ok(cnt)
    }

    fn deserialize(reader: &mut Reader) -> IoResult<Header> {
        // TODO: this is a bit verbose, both match clauses
        let sender = match deserialize_socket_addr(reader) {
            Ok(socket) => socket,
            Err(e) => return Err(e),
        };

        let msg_id = match reader.read_u8() {
            Ok(id) => id,
            Err(e) => return Err(e),
        };
        Ok(Header { sender: sender, msg_id: msg_id })
    }
}

/// helper function to efficiently serialize a SocketAddr
fn serialize_socket_addr(sa: &SocketAddr, writer: &mut Writer) -> IoResult<int> {
    match sa.ip {
        Ipv4Addr(a, b, c, d) => {
            writer.write_u8(a).ok();
            writer.write_u8(b).ok();
            writer.write_u8(c).ok();
            writer.write_u8(d).ok();
            writer.write_be_u16(sa.port).ok();
        },
        _ => println!("dont care yet!"),
    }
    Ok(4 + 2)
}

/// helper function to efficiently deserialize a SocketAddr
fn deserialize_socket_addr(reader: &mut Reader) -> IoResult<SocketAddr> {
    let mut buf = Vec::with_capacity(4);
    let mut i = 0;
    while i < 4 {
        buf.push(reader.read_u8().ok().expect("couldn't read next byte for ip address"));
        i += 1;
    }
    let ip = Ipv4Addr (buf[0], buf[1], buf[2], buf[3]);
    let port = reader.read_be_u16().ok().expect("couldn't read port for socket address");

    let sa: SocketAddr = SocketAddr { ip: ip , port: port };
    Ok(sa)
}

#[derive(Copy,Show)]
//TODO: add a message uuid so we can register a callback (to make sure the join message gets a reponse, else resend the request)
pub struct Join;
impl Join {
    pub fn new() -> Join {
        Join
    }

    pub fn serialize(&self, writer: &mut Writer, sender: &SocketAddr) -> IoResult<int> {
        Header::new(sender, HPV_MSG_ID_JOIN).serailize(writer)
    }
}

#[derive(Copy,Show)]
pub struct ForwardJoin {
    pub originator: SocketAddr,
    pub arwl: u8,
    pub prwl: u8,
    pub ttl: u8
}
impl ForwardJoin {
    pub fn new(addr: &SocketAddr, arwl: u8, prwl: u8, ttl: u8) -> ForwardJoin {
        ForwardJoin { originator: *addr, arwl: arwl, prwl: prwl, ttl: ttl }
    }

    pub fn deserialize(reader: &mut Reader) -> IoResult<ForwardJoin> {
        match deserialize_socket_addr(reader) {
            Ok(socket) => {
                let arwl = reader.read_u8().ok().expect("could not read arwl from stream");
                let prwl = reader.read_u8().ok().expect("could not read prwl from stream");
                let ttl = reader.read_u8().ok().expect("could not read ttl from stream");
                Ok(ForwardJoin::new(&socket, arwl, prwl, ttl))
            },
            Err(e) => Err(e),
        }
    }

    pub fn serialize(&self, writer: &mut Writer, sender: &SocketAddr) -> IoResult<int> {
        let mut cnt = 0;
        let header = Header::new(sender, HPV_MSG_ID_FORWARD_JOIN);
        match header.serailize(writer) {
            Ok(c) => cnt += c,
            Err(e) => return Err(e),
        }

        match serialize_socket_addr(&self.originator, writer) {
            Ok(c) => cnt += c,
            Err(e) => return Err(e),
        }

        writer.write_u8(self.arwl).ok();
        cnt += 1;
        writer.write_u8(self.prwl).ok();
        cnt += 1;
        writer.write_u8(self.ttl).ok();
        cnt += 1;
        Ok(cnt)
    }
}

#[test]
fn test_join_serialization() {
    use std::io::{MemReader,BufferedWriter};
    use std::io::net::ip::{SocketAddr};

    let arwl = 6u8;
    let prwl = 3u8;
    let ttl = 4u8;

    let sock_addr: SocketAddr = from_str("127.0.0.1:9090").expect("invalid socket addr");
    let fjoin_msg = ForwardJoin::new(&sock_addr, arwl, prwl, ttl);
    let vec = Vec::new();
    let mut writer = BufferedWriter::new(vec);
    let result = fjoin_msg.serialize(&mut writer);

    let vec = writer.into_inner();
    let mut reader = MemReader::new(vec);
    let header = reader.read_u8().ok().expect("failed to read the header");
    let return_fjoin_msg = ForwardJoin::deserialize(&mut reader).ok().expect("failed to parse socket addr");
    assert!(return_fjoin_msg.originator.eq(&sock_addr));
    assert_eq!(return_fjoin_msg.arwl, arwl);
    assert_eq!(return_fjoin_msg.prwl, prwl);
    assert_eq!(return_fjoin_msg.ttl, ttl);
}

#[derive(Copy,Show)]
pub struct Disconnect;
impl Disconnect {
    pub fn new() -> Disconnect {
        Disconnect
    }

     pub fn serialize(&self, writer: &mut Writer, sender: &SocketAddr) -> IoResult<int> {
        Header::new(sender, HPV_MSG_ID_DISCONNECT).serailize(writer)
    }
}

#[derive(Copy,Show)]
pub struct JoinAck;
impl JoinAck {
    pub fn new() -> JoinAck {
        JoinAck
    }

    pub fn serialize(&self, writer: &mut Writer, sender: &SocketAddr) -> IoResult<int> {
        Header::new(sender, HPV_MSG_ID_JOIN_ACK).serailize(writer)
    }
}

#[derive(Copy,Show)]
pub struct NeighborRequest {
    pub priority: Priority,
}
impl NeighborRequest {
    pub fn new(priority: Priority) -> NeighborRequest {
        NeighborRequest { priority: priority}
    }

    pub fn deserialize(reader: &mut Reader) -> IoResult<NeighborRequest> {
        let p = match reader.read_u8().ok().expect("could not read priority from stream") {
            0 => Priority::Low,
            1 => Priority::High,
            //println!("received unknown priority level, defaulting to low priority");
            _ =>  Priority::Low,
        };
        Ok(NeighborRequest::new(p))
    }

    pub fn serialize(&self, writer: &mut Writer, sender: &SocketAddr) -> IoResult<int> {
        let mut cnt = 0;
        let header = Header::new(sender, HPV_MSG_ID_NEIGHBOR_REQUEST);
        match header.serailize(writer) {
            Ok(c) => cnt += c,
            Err(e) => return Err(e),
        }

        let p: u8 = match self.priority {
            Priority::Low => 0,
            Priority::High => 1,
        };
        writer.write_u8(p).ok();
        cnt += 1;
        Ok(cnt)
    }
}

#[derive(Copy,Show)]
pub struct NeighborResponse {
    pub result: Result,
}
impl NeighborResponse {
    pub fn new(result: Result) -> NeighborResponse {
        NeighborResponse { result: result }
    }

    pub fn deserialize(reader: &mut Reader) -> IoResult<NeighborResponse> {
        let r = match reader.read_u8().ok().expect("could not read result from stream") {
            0 => Result::Accept,
            1 => Result::Reject,
            // if we can't undertand the result code, just default to reject
            _ => Result::Reject
        };
        Ok(NeighborResponse::new(r))
    }

    pub fn serialize(&self, writer: &mut Writer, sender: &SocketAddr) -> IoResult<int> {
        let mut cnt = 0;
        let header = Header::new(sender, HPV_MSG_ID_NEIGHBOR_RESPONSE);
        match header.serailize(writer) {
            Ok(c) => cnt += c,
            Err(e) => return Err(e),
        }

        let p: u8 = match self.result {
            Result::Accept => 0,
            Result::Reject => 1,
        };
        writer.write_u8(p).ok();
        cnt += 1;
        Ok(cnt)
    }
}

#[derive(Show)]
pub struct Shuffle {
    pub originator: SocketAddr,
    pub nodes: Vec<SocketAddr>,
    pub ttl: u8,
}
impl Shuffle {
    pub fn new(originator: SocketAddr, nodes: Vec<SocketAddr>, ttl: u8) -> Shuffle {
        Shuffle { originator: originator, nodes: nodes, ttl: ttl }
    }

    pub fn deserialize(reader: &mut Reader) -> IoResult<Shuffle> {
        let originator = deserialize_socket_addr(reader).ok().expect("could not read socket addr from stream");
        let nodes = deserialize_socket_addrs(reader);
        let ttl = reader.read_u8().ok().expect("could not read ttl from stream");
        Ok(Shuffle::new(originator, nodes, ttl))
    }

    pub fn serialize(&self, writer: &mut Writer, sender: &SocketAddr) -> IoResult<int> {
        let mut cnt = 0;
        let header = Header::new(sender, HPV_MSG_ID_SHUFFLE);
        match header.serailize(writer) {
            Ok(c) => cnt += c,
            Err(e) => return Err(e),
        }

        match serialize_socket_addr(&self.originator, writer) {
            Ok(c) => cnt += c,
            Err(e) => return Err(e),
        }

        match serialize_socket_addrs(&self.nodes, writer) {
            Ok(c) => cnt += c,
            Err(e) => return Err(e),
        }

        writer.write_u8(self.ttl).ok();
        cnt += 1;
        Ok(cnt)
    }
}

fn deserialize_socket_addrs(reader: &mut Reader) -> Vec<SocketAddr> {
    let len = reader.read_u8().ok().expect("could not read vector size from stream") as uint;
    let mut nodes = Vec::with_capacity(len);

    for _ in range (0u, len) {
        match deserialize_socket_addr(reader) {
            Ok(socket) => nodes.push(socket),
            Err(_) => println!("failed"),
        }
    }
    nodes
}

fn serialize_socket_addrs(nodes: &Vec<SocketAddr>, writer: &mut Writer) -> IoResult<int> {
    let mut cnt = 0;
    writer.write_u8(nodes.len() as u8).ok().expect("failed to write vec len");
    cnt += 1;

    for node in nodes.iter() {
        match serialize_socket_addr(node, writer) {
            Ok(c) => cnt += c,
            Err(e) => return Err(e),
        }
    }
    Ok(cnt)
}

#[derive(Show)]
pub struct ShuffleReply {
    /// return the vector of nodes the originator first sent out; that way the originator does not need to keep track of that.
    pub sent_nodes: Vec<SocketAddr>,
    pub nodes: Vec<SocketAddr>,
}
impl ShuffleReply {
    pub fn new(sent_nodes: Vec<SocketAddr>, nodes: Vec<SocketAddr>) -> ShuffleReply {
        ShuffleReply { sent_nodes: sent_nodes, nodes: nodes }
    }

    pub fn deserialize(reader: &mut Reader) -> IoResult<ShuffleReply> {
        let sent_nodes = deserialize_socket_addrs(reader);
        let nodes = deserialize_socket_addrs(reader);
        Ok(ShuffleReply::new(sent_nodes, nodes))
    }

    pub fn serialize(&self, writer: &mut Writer, sender: &SocketAddr) -> IoResult<int> {
        let mut cnt = 0;
        let header = Header::new(sender, HPV_MSG_ID_SHUFFLE_REPLY);
        match header.serailize(writer) {
            Ok(c) => cnt += c,
            Err(e) => return Err(e),
        }

        match serialize_socket_addrs(&self.sent_nodes, writer) {
            Ok(c) => cnt += c,
            Err(e) => return Err(e),
        }

        match serialize_socket_addrs(&self.nodes, writer) {
            Ok(c) => cnt += c,
            Err(e) => return Err(e),
        }
        Ok(cnt)
    }
}
<|endoftext|>


<commit_before>// Copyright (c) 2015 David Stainton <dstainton415@gmail.com>
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! TCP packet abstraction

use packet::Packet;
use packet::ip::IpNextHeaderProtocol;

use pnet_macros::types::*;

use std::net::{Ipv4Addr, Ipv6Addr};

/// Represents a TCP Packet
#[packet]
pub struct Tcp {
    source: u16be,
    destination: u16be,
    length: u16be,
    #[payload]
    payload: Vec<u8>
}

#[test]
fn tcp_header_ipv4_test() {
    use pnet::packet::ip::IpNextHeaderProtocols;
    use pnet::packet::ipv4::MutableIpv4Packet;

    let mut packet = [0u8; 20 + 8 + 4];
    let ipv4_source = Ipv4Addr::new(192, 168, 0, 1);
    let ipv4_destination = Ipv4Addr::new(192, 168, 0, 199);
    let next_level_protocol = IpNextHeaderProtocols::Tcp;
    {
        let mut ip_header = MutableIpv4Packet::new(&mut packet[..]).unwrap();
        ip_header.set_next_level_protocol(next_level_protocol);
        ip_header.set_source(ipv4_source);
        ip_header.set_destination(ipv4_destination);
    }

    // Set data
    packet[20 + 8 + 0] = 't' as u8;
    packet[20 + 8 + 1] = 'e' as u8;
    packet[20 + 8 + 2] = 's' as u8;
    packet[20 + 8 + 3] = 't' as u8;

    {
        let mut tcp_header = MutableTcpPacket::new(&mut packet[20..]).unwrap();
        tcp_header.set_source(12345);
        assert_eq!(tcp_header.get_source(), 12345);

        tcp_header.set_destination(54321);
        assert_eq!(tcp_header.get_destination(), 54321);

        tcp_header.set_length(8 + 4);
        assert_eq!(tcp_header.get_length(), 8 + 4);
    }

    let ref_packet = [0x30, 0x39, /* source */
                     0xd4, 0x31,  /* destination */
                     0x00, 0x0c]; /* length */
    assert_eq!(&ref_packet[..], &packet[20 .. 26]);
}

#[test]
fn tcp_header_ipv6_test() {
    use packet::ip::{IpNextHeaderProtocols};
    use packet::ipv6::{MutableIpv6Packet};

    let mut packet = [0u8; 40 + 8 + 4];
    let next_header = IpNextHeaderProtocols::Tcp;
    let ipv6_source = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1);
    let ipv6_destination = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1);
    {
        let mut ip_header = MutableIpv6Packet::new(&mut packet[..]).unwrap();
        ip_header.set_next_header(next_header);
        ip_header.set_source(ipv6_source);
        ip_header.set_destination(ipv6_destination);
    }

    // Set data
    packet[40 + 8 + 0] = 't' as u8;
    packet[40 + 8 + 1] = 'e' as u8;
    packet[40 + 8 + 2] = 's' as u8;
    packet[40 + 8 + 3] = 't' as u8;

    {
        let mut tcp_header = MutableTcpPacket::new(&mut packet[40..]).unwrap();
        tcp_header.set_source(12345);
        assert_eq!(tcp_header.get_source(), 12345);

        tcp_header.set_destination(54321);
        assert_eq!(tcp_header.get_destination(), 54321);

        tcp_header.set_length(8 + 4);
        assert_eq!(tcp_header.get_length(), 8 + 4);
    }

    let ref_packet = [0x30, 0x39, /* source */
                     0xd4, 0x31,  /* destination */
                     0x00, 0x0c]; /* length */
    assert_eq!(&ref_packet[..], &packet[40 .. 46]);
}
<commit_msg>Remove ``length`` field that was borrowed from udp.rs<commit_after>// Copyright (c) 2015 David Stainton <dstainton415@gmail.com>
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! TCP packet abstraction

use packet::Packet;
use packet::ip::IpNextHeaderProtocol;

use pnet_macros::types::*;

use std::net::{Ipv4Addr, Ipv6Addr};

/// Represents a TCP Packet
#[packet]
pub struct Tcp {
    source: u16be,
    destination: u16be,
    #[payload]
    payload: Vec<u8>
}

#[test]
fn tcp_header_ipv4_test() {
    use pnet::packet::ip::IpNextHeaderProtocols;
    use pnet::packet::ipv4::MutableIpv4Packet;

    let mut packet = [0u8; 20 + 8 + 4];
    let ipv4_source = Ipv4Addr::new(192, 168, 0, 1);
    let ipv4_destination = Ipv4Addr::new(192, 168, 0, 199);
    let next_level_protocol = IpNextHeaderProtocols::Tcp;
    {
        let mut ip_header = MutableIpv4Packet::new(&mut packet[..]).unwrap();
        ip_header.set_next_level_protocol(next_level_protocol);
        ip_header.set_source(ipv4_source);
        ip_header.set_destination(ipv4_destination);
    }

    // Set data
    packet[20 + 8 + 0] = 't' as u8;
    packet[20 + 8 + 1] = 'e' as u8;
    packet[20 + 8 + 2] = 's' as u8;
    packet[20 + 8 + 3] = 't' as u8;

    {
        let mut tcp_header = MutableTcpPacket::new(&mut packet[20..]).unwrap();
        tcp_header.set_source(12345);
        assert_eq!(tcp_header.get_source(), 12345);

        tcp_header.set_destination(54321);
        assert_eq!(tcp_header.get_destination(), 54321);

    }

    let ref_packet = [0x30, 0x39, /* source */
                     0xd4, 0x31];  /* destination */
    assert_eq!(&ref_packet[..], &packet[20 .. 24]);
}

#[test]
fn tcp_header_ipv6_test() {
    use packet::ip::{IpNextHeaderProtocols};
    use packet::ipv6::{MutableIpv6Packet};

    let mut packet = [0u8; 40 + 8 + 4];
    let next_header = IpNextHeaderProtocols::Tcp;
    let ipv6_source = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1);
    let ipv6_destination = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1);
    {
        let mut ip_header = MutableIpv6Packet::new(&mut packet[..]).unwrap();
        ip_header.set_next_header(next_header);
        ip_header.set_source(ipv6_source);
        ip_header.set_destination(ipv6_destination);
    }

    // Set data
    packet[40 + 8 + 0] = 't' as u8;
    packet[40 + 8 + 1] = 'e' as u8;
    packet[40 + 8 + 2] = 's' as u8;
    packet[40 + 8 + 3] = 't' as u8;

    {
        let mut tcp_header = MutableTcpPacket::new(&mut packet[40..]).unwrap();
        tcp_header.set_source(12345);
        assert_eq!(tcp_header.get_source(), 12345);

        tcp_header.set_destination(54321);
        assert_eq!(tcp_header.get_destination(), 54321);
    }

    let ref_packet = [0x30, 0x39,  /* source */
                     0xd4, 0x31];  /* destination */
    assert_eq!(&ref_packet[..], &packet[40 .. 44]);
}
<|endoftext|>


<commit_before>//! Implementation of line-based codec for Tokio.

use std::io;
use std::io::prelude::*;
use encoding::{DecoderTrap, EncoderTrap, Encoding};
use tokio_core::io::{Codec, EasyBuf};

/// A line-based codec parameterized by an encoding.
pub struct LineCodec<E: Encoding> {
    encoding: E,
}

impl<E> Codec for LineCodec<E> where E: Encoding {
    type In = String;
    type Out = String;

    fn decode(&mut self, buf: &mut EasyBuf) -> io::Result<Option<String>> {
        if let Some(n) = buf.as_ref().iter().position(|b| *b == b'\n') {
            // Remove the next frame from the buffer.
            let line = buf.drain_to(n);

            // Remove the new-line from the buffer.
            buf.drain_to(1);

            // Decode the line using the codec's encoding.
            match self.encoding.decode(line.as_ref(), DecoderTrap::Replace) {
                Ok(data) => Ok(Some(data)),
                Err(data) => Err(io::Error::new(
                    io::ErrorKind::InvalidInput,
                    &format!("Failed to decode {} as {}.", data, self.encoding.name())[..]
                ))
            }
        } else {
            Ok(None)
        }
    }

    fn encode(&mut self, msg: String, buf: &mut Vec<u8>) -> io::Result<()> {
        // Encode the message using the codec's encoding.
        let data = try!(self.encoding.encode(&msg, EncoderTrap::Replace).map_err(|data| {
            io::Error::new(
                io::ErrorKind::InvalidInput,
                &format!("Failed to encode {} as {}.", data, self.encoding.name())[..]
            )
        }));

        // Write the encoded message to the output buffer.
        try!(buf.write_all(&data));

        // Flush the output buffer.
        buf.flush()
    }
}
<commit_msg>Removed parameterization of LineCodec on encoding.<commit_after>//! Implementation of line-delimiting codec for Tokio.

use std::io;
use std::io::prelude::*;
use encoding::{DecoderTrap, EncoderTrap, EncodingRef};
use encoding::label::encoding_from_whatwg_label;
use tokio_core::io::{Codec, EasyBuf};

/// A line-based codec parameterized by an encoding.
pub struct LineCodec {
    encoding: EncodingRef,
}

impl LineCodec {
    /// Creates a new instance of LineCodec from the specified encoding.
    pub fn new(label: &str) -> io::Result<LineCodec> {
        encoding_from_whatwg_label(label).map(|enc| LineCodec { encoding: enc }).ok_or(
            io::Error::new(
                io::ErrorKind::InvalidInput,
                &format!("Attempted to use unknown codec {}.", label)[..]
            )
        )
    }
}

impl Codec for LineCodec {
    type In = String;
    type Out = String;

    fn decode(&mut self, buf: &mut EasyBuf) -> io::Result<Option<String>> {
        if let Some(n) = buf.as_ref().iter().position(|b| *b == b'\n') {
            // Remove the next frame from the buffer.
            let line = buf.drain_to(n);

            // Remove the new-line from the buffer.
            buf.drain_to(1);

            // Decode the line using the codec's encoding.
            match self.encoding.decode(line.as_ref(), DecoderTrap::Replace) {
                Ok(data) => Ok(Some(data)),
                Err(data) => Err(io::Error::new(
                    io::ErrorKind::InvalidInput,
                    &format!("Failed to decode {} as {}.", data, self.encoding.name())[..]
                ))
            }
        } else {
            Ok(None)
        }
    }

    fn encode(&mut self, msg: String, buf: &mut Vec<u8>) -> io::Result<()> {
        // Encode the message using the codec's encoding.
        let data = try!(self.encoding.encode(&msg, EncoderTrap::Replace).map_err(|data| {
            io::Error::new(
                io::ErrorKind::InvalidInput,
                &format!("Failed to encode {} as {}.", data, self.encoding.name())[..]
            )
        }));

        // Write the encoded message to the output buffer.
        try!(buf.write_all(&data));

        // Flush the output buffer.
        buf.flush()
    }
}
<|endoftext|>


<commit_before>use core::{arch::asm, mem};
use goblin::elf::sym;

use crate::paging::{KernelMapper, TableKind, VirtualAddress};

/// Get a stack trace
//TODO: Check for stack being mapped before dereferencing
#[inline(never)]
pub unsafe fn stack_trace() {
    let mut fp: usize;
    asm!("mov {}, fp", out(reg) fp);

    println!("TRACE: {:>016x}", fp);

    /*TODO: implement using rmm
    //Maximum 64 frames
    let active_ktable = ActivePageTable::new(TableKind::Kernel);
    let active_utable = ActivePageTable::new(TableKind::User);
    let in_kernel_or_user_table = |ptr| {
        active_ktable.translate(VirtualAddress::new(ptr)).is_some() ||
        active_utable.translate(VirtualAddress::new(ptr)).is_some()
    };
    for _frame in 0..64 {
        if let Some(pc_fp) = fp.checked_add(mem::size_of::<usize>()) {
            if in_kernel_or_user_table(fp) && in_kernel_or_user_table(pc_fp) {
                let pc = *(pc_fp as *const usize);
                if pc == 0 {
                    println!(" {:>016x}: EMPTY RETURN", fp);
                    break;
                }
                println!("  FP {:>016x}: PC {:>016x}", fp, pc);
                fp = *(fp as *const usize);
                //TODO symbol_trace(pc);
            } else {
                println!("  {:>016x}: GUARD PAGE", fp);
                break;
            }
        } else {
            println!("  {:>016x}: fp OVERFLOW", fp);
        }
    }
    */
}
///
/// Get a symbol
//TODO: Do not create Elf object for every symbol lookup
#[inline(never)]
pub unsafe fn symbol_trace(addr: usize) {
    use core::slice;
    use core::sync::atomic::Ordering;

    use crate::elf::Elf;
    use crate::start::{KERNEL_BASE, KERNEL_SIZE};

    let kernel_ptr = (KERNEL_BASE.load(Ordering::SeqCst) + crate::KERNEL_OFFSET) as *const u8;
    let kernel_slice = slice::from_raw_parts(kernel_ptr, KERNEL_SIZE.load(Ordering::SeqCst));

    println!("symbol_trace: 0, kernel_ptr = 0x{:x}", kernel_ptr as usize);

    match Elf::from(kernel_slice) {
        Ok(elf) => {
            println!("symbol_trace: 1");
            let mut strtab_opt = None;
            for section in elf.sections() {
                if section.sh_type == ::goblin::elf::section_header::SHT_STRTAB {
                    strtab_opt = Some(section);
                    break;
                }
            }

            println!("symbol_trace: 2");

            if let Some(symbols) = elf.symbols() {
                println!("symbol_trace: 3");
                for sym in symbols {
                    if sym::st_type(sym.st_info) == sym::STT_FUNC
                        && addr >= sym.st_value as usize
                            && addr < (sym.st_value + sym.st_size) as usize
                            {
                                println!("    {:>016X}+{:>04X}", sym.st_value, addr - sym.st_value as usize);

                                if let Some(strtab) = strtab_opt {
                                    let start = strtab.sh_offset as usize + sym.st_name as usize;
                                    let mut end = start;
                                    while end < elf.data.len() {
                                        let b = elf.data[end];
                                        end += 1;
                                        if b == 0 {
                                            break;
                                        }
                                    }

                                    if end > start {
                                        let sym_name = &elf.data[start .. end];

                                        print!("    ");

                                        if sym_name.starts_with(b"_ZN") {
                                            // Skip _ZN
                                            let mut i = 3;
                                            let mut first = true;
                                            while i < sym_name.len() {
                                                // E is the end character
                                                if sym_name[i] == b'E' {
                                                    break;
                                                }

                                                // Parse length string
                                                let mut len = 0;
                                                while i < sym_name.len() {
                                                    let b = sym_name[i];
                                                    if b >= b'0' && b <= b'9' {
                                                        i += 1;
                                                        len *= 10;
                                                        len += (b - b'0') as usize;
                                                    } else {
                                                        break;
                                                    }
                                                }

                                                // Print namespace seperator, if required
                                                if first {
                                                    first = false;
                                                } else {
                                                    print!("::");
                                                }

                                                // Print name string
                                                let end = i + len;
                                                while i < sym_name.len() && i < end {
                                                    print!("{}", sym_name[i] as char);
                                                    i += 1;
                                                }
                                            }
                                        } else {
                                            for &b in sym_name.iter() {
                                                print!("{}", b as char);
                                            }
                                        }

                                        println!("");
                                    }
                                }
                            }
                }
            }
        },
        Err(_e) => {
            println!("WTF ?");
        }
    }
}
<commit_msg>Partially implement stack trace on aarch64<commit_after>use core::{arch::asm, mem};
use goblin::elf::sym;

use crate::paging::{KernelMapper, TableKind, VirtualAddress};

/// Get a stack trace
//TODO: Check for stack being mapped before dereferencing
#[inline(never)]
pub unsafe fn stack_trace() {
    let mut fp: usize;
    asm!("mov {}, fp", out(reg) fp);

    println!("TRACE: {:>016x}", fp);

    let mapper = KernelMapper::lock();

    //Maximum 64 frames
    for _frame in 0..64 {
        if let Some(pc_fp) = fp.checked_add(mem::size_of::<usize>()) {
            if mapper.translate(VirtualAddress::new(fp)).is_some()
            && mapper.translate(VirtualAddress::new(pc_fp)).is_some() {
                let pc = *(pc_fp as *const usize);
                if pc == 0 {
                    println!(" {:>016x}: EMPTY RETURN", fp);
                    break;
                }
                println!("  FP {:>016x}: PC {:>016x}", fp, pc);
                fp = *(fp as *const usize);
                //TODO symbol_trace(pc);
            } else {
                println!("  {:>016x}: GUARD PAGE", fp);
                break;
            }
        } else {
            println!("  {:>016x}: fp OVERFLOW", fp);
        }
    }
}
///
/// Get a symbol
//TODO: Do not create Elf object for every symbol lookup
#[inline(never)]
pub unsafe fn symbol_trace(addr: usize) {
    use core::slice;
    use core::sync::atomic::Ordering;

    use crate::elf::Elf;
    use crate::start::{KERNEL_BASE, KERNEL_SIZE};

    let kernel_ptr = (KERNEL_BASE.load(Ordering::SeqCst) + crate::KERNEL_OFFSET) as *const u8;
    let kernel_slice = slice::from_raw_parts(kernel_ptr, KERNEL_SIZE.load(Ordering::SeqCst));

    println!("symbol_trace: 0, kernel_ptr = 0x{:x}", kernel_ptr as usize);

    match Elf::from(kernel_slice) {
        Ok(elf) => {
            println!("symbol_trace: 1");
            let mut strtab_opt = None;
            for section in elf.sections() {
                if section.sh_type == ::goblin::elf::section_header::SHT_STRTAB {
                    strtab_opt = Some(section);
                    break;
                }
            }

            println!("symbol_trace: 2");

            if let Some(symbols) = elf.symbols() {
                println!("symbol_trace: 3");
                for sym in symbols {
                    if sym::st_type(sym.st_info) == sym::STT_FUNC
                        && addr >= sym.st_value as usize
                            && addr < (sym.st_value + sym.st_size) as usize
                            {
                                println!("    {:>016X}+{:>04X}", sym.st_value, addr - sym.st_value as usize);

                                if let Some(strtab) = strtab_opt {
                                    let start = strtab.sh_offset as usize + sym.st_name as usize;
                                    let mut end = start;
                                    while end < elf.data.len() {
                                        let b = elf.data[end];
                                        end += 1;
                                        if b == 0 {
                                            break;
                                        }
                                    }

                                    if end > start {
                                        let sym_name = &elf.data[start .. end];

                                        print!("    ");

                                        if sym_name.starts_with(b"_ZN") {
                                            // Skip _ZN
                                            let mut i = 3;
                                            let mut first = true;
                                            while i < sym_name.len() {
                                                // E is the end character
                                                if sym_name[i] == b'E' {
                                                    break;
                                                }

                                                // Parse length string
                                                let mut len = 0;
                                                while i < sym_name.len() {
                                                    let b = sym_name[i];
                                                    if b >= b'0' && b <= b'9' {
                                                        i += 1;
                                                        len *= 10;
                                                        len += (b - b'0') as usize;
                                                    } else {
                                                        break;
                                                    }
                                                }

                                                // Print namespace seperator, if required
                                                if first {
                                                    first = false;
                                                } else {
                                                    print!("::");
                                                }

                                                // Print name string
                                                let end = i + len;
                                                while i < sym_name.len() && i < end {
                                                    print!("{}", sym_name[i] as char);
                                                    i += 1;
                                                }
                                            }
                                        } else {
                                            for &b in sym_name.iter() {
                                                print!("{}", b as char);
                                            }
                                        }

                                        println!("");
                                    }
                                }
                            }
                }
            }
        },
        Err(_e) => {
            println!("WTF ?");
        }
    }
}
<|endoftext|>