<commit_before>use bb::*;
use gen::pawn::PAWN_CAPTURE_FILE_MASKS;
use mv_list::MoveList;
use piece::*;
use position::Position;
use side::{Side, WHITE};
use square::Square;
use square;

// Generates pawn moves along pin rays
// NOTE: this is quigte expensive unfortunately
pub fn pawn_pin_ray_moves<L: MoveList>(
    position: &Position,
    capture_mask: BB,
    push_mask: BB,
    king_sq: Square,
    pinned: BB,
    stm: Side,
    list: &mut L,
) {
    let empty_squares = position.bb_empty();
    let piece = PAWN.pc(stm);
    let movers = position.bb_pc(piece) & pinned;

    let push_shift = if stm == WHITE { 8 } else { 64 - 8 };
    let double_push_mask = if stm == WHITE { ROW_4 } else { ROW_5 };

    let can_push = movers & king_sq.file_mask();
    let king_diags = king_sq.both_diagonals();
    let can_capture = movers & king_diags;

    // For pinned pawns, only possible moves are those along the king file
    for (_, pawn) in can_push.iter() {
        let single_pushes = pawn.rot_left(push_shift as u32) & empty_squares & push_mask;
        list.add_pawn_pushes(push_shift, single_pushes);
        let double_pushes =
            single_pushes.rot_left(push_shift as u32) & empty_squares & double_push_mask & push_mask;
        let double_push_shift = (push_shift * 2) % 64;
        list.add_pawn_pushes(double_push_shift, double_pushes);
    }

    for &(shift, file_mask) in PAWN_CAPTURE_FILE_MASKS[stm.to_usize()].iter() {
        let targets = can_capture.rot_left(shift as u32)
            & file_mask
            & capture_mask
            & king_diags;

        list.add_pawn_captures(shift, targets);
    }

    if position.state().ep_square.is_some() {
        for &(shift, file_mask) in PAWN_CAPTURE_FILE_MASKS[stm.to_usize()].iter() {
            let targets = can_capture.rot_left(shift as u32) & file_mask;

            let ep = position.state().ep_square.unwrap();
            let ep_captures = targets & BB::new(ep) & king_diags;

            for (to, to_bb) in ep_captures.iter() {
                let from = to.rotate_right(shift as square::Internal);

                let capture_sq = from.along_row_with_col(to);
                let capture_sq_bb = BB::new(capture_sq);

                // can only make ep capture if moving to push_mask, or capturing on capture mask
                if ((to_bb & push_mask) | (capture_sq_bb & capture_mask)).any() {
                    let from_bb = to_bb.rot_right(shift as u32);
                    list.add_pawn_ep_capture(from_bb.bitscan(), ep);
                }
            }
        }
    }
}

#[cfg(test)]
mod test {
    use super::*;
    use gen::util::assert_list_includes_moves;
    use mv_list::MoveVec;
    use position::Position;
    use square::*;

    #[test]
    fn test_pawn_pin_ray_moves() {
        // test pawn capture along pin ray
        let position =
            Position::from_fen("rnb2k1r/pp1Pbppp/2p5/q7/1PB5/8/PP2N1PP/RNB1K2R w KQ - 3 9")
                .unwrap();

        let mut list = MoveVec::new();
        pawn_pin_ray_moves(&position, BB::new(A5), !EMPTY, E1, BB::new(B4), WHITE, &mut list);
        assert_eq!(list.len(), 1);
        assert_list_includes_moves(&list, &["b4xa5"]);
    }

    #[test]
    fn test_pawn_pin_ray_moves_2() {
        // test pawn move along pin ray
        let position =
            Position::from_fen("rnb2k1r/pp1Pbppp/2p5/4q3/8/8/PP2P1PP/RNB1KNBR w KQ - 3 9").unwrap();

        let mut list = MoveVec::new();
        pawn_pin_ray_moves(&position, BB::new(E5), !EMPTY, E1, BB::new(E2), WHITE, &mut list);
        assert_eq!(list.len(), 2);
        assert_list_includes_moves(&list, &["e2e3", "e2e4"]);
    }

    #[test]
    fn test_pawn_pin_ray_moves_3() {
        // test pawn capture along pin ray when multiple pinners
        let position =
            Position::from_fen("r1b2k2/pp1Pbppp/2p5/q1n1r3/1PB5/4R3/P4PPP/RNB1K3 w Q - 3 9")
                .unwrap();

        let mut list = MoveVec::new();
        pawn_pin_ray_moves(
            &position,
            BB::new(A5) | BB::new(E5),
            !EMPTY,
            E1,
            BB::new(B4) | BB::new(E3),
            WHITE,
            &mut list,
        );
        assert_eq!(list.len(), 1);
        assert_list_includes_moves(&list, &["b4xa5"]);
    }
}
<commit_msg>remove comment<commit_after>use bb::*;
use gen::pawn::PAWN_CAPTURE_FILE_MASKS;
use mv_list::MoveList;
use piece::*;
use position::Position;
use side::{Side, WHITE};
use square::Square;
use square;

// Generates pawn moves along pin rays
pub fn pawn_pin_ray_moves<L: MoveList>(
    position: &Position,
    capture_mask: BB,
    push_mask: BB,
    king_sq: Square,
    pinned: BB,
    stm: Side,
    list: &mut L,
) {
    let empty_squares = position.bb_empty();
    let piece = PAWN.pc(stm);
    let movers = position.bb_pc(piece) & pinned;

    let push_shift = if stm == WHITE { 8 } else { 64 - 8 };
    let double_push_mask = if stm == WHITE { ROW_4 } else { ROW_5 };

    let can_push = movers & king_sq.file_mask();
    let king_diags = king_sq.both_diagonals();
    let can_capture = movers & king_diags;

    // For pinned pawns, only possible moves are those along the king file
    for (_, pawn) in can_push.iter() {
        let single_pushes = pawn.rot_left(push_shift as u32) & empty_squares & push_mask;
        list.add_pawn_pushes(push_shift, single_pushes);
        let double_pushes =
            single_pushes.rot_left(push_shift as u32) & empty_squares & double_push_mask & push_mask;
        let double_push_shift = (push_shift * 2) % 64;
        list.add_pawn_pushes(double_push_shift, double_pushes);
    }

    for &(shift, file_mask) in PAWN_CAPTURE_FILE_MASKS[stm.to_usize()].iter() {
        let targets = can_capture.rot_left(shift as u32)
            & file_mask
            & capture_mask
            & king_diags;

        list.add_pawn_captures(shift, targets);
    }

    if position.state().ep_square.is_some() {
        for &(shift, file_mask) in PAWN_CAPTURE_FILE_MASKS[stm.to_usize()].iter() {
            let targets = can_capture.rot_left(shift as u32) & file_mask;

            let ep = position.state().ep_square.unwrap();
            let ep_captures = targets & BB::new(ep) & king_diags;

            for (to, to_bb) in ep_captures.iter() {
                let from = to.rotate_right(shift as square::Internal);

                let capture_sq = from.along_row_with_col(to);
                let capture_sq_bb = BB::new(capture_sq);

                // can only make ep capture if moving to push_mask, or capturing on capture mask
                if ((to_bb & push_mask) | (capture_sq_bb & capture_mask)).any() {
                    let from_bb = to_bb.rot_right(shift as u32);
                    list.add_pawn_ep_capture(from_bb.bitscan(), ep);
                }
            }
        }
    }
}

#[cfg(test)]
mod test {
    use super::*;
    use gen::util::assert_list_includes_moves;
    use mv_list::MoveVec;
    use position::Position;
    use square::*;

    #[test]
    fn test_pawn_pin_ray_moves() {
        // test pawn capture along pin ray
        let position =
            Position::from_fen("rnb2k1r/pp1Pbppp/2p5/q7/1PB5/8/PP2N1PP/RNB1K2R w KQ - 3 9")
                .unwrap();

        let mut list = MoveVec::new();
        pawn_pin_ray_moves(&position, BB::new(A5), !EMPTY, E1, BB::new(B4), WHITE, &mut list);
        assert_eq!(list.len(), 1);
        assert_list_includes_moves(&list, &["b4xa5"]);
    }

    #[test]
    fn test_pawn_pin_ray_moves_2() {
        // test pawn move along pin ray
        let position =
            Position::from_fen("rnb2k1r/pp1Pbppp/2p5/4q3/8/8/PP2P1PP/RNB1KNBR w KQ - 3 9").unwrap();

        let mut list = MoveVec::new();
        pawn_pin_ray_moves(&position, BB::new(E5), !EMPTY, E1, BB::new(E2), WHITE, &mut list);
        assert_eq!(list.len(), 2);
        assert_list_includes_moves(&list, &["e2e3", "e2e4"]);
    }

    #[test]
    fn test_pawn_pin_ray_moves_3() {
        // test pawn capture along pin ray when multiple pinners
        let position =
            Position::from_fen("r1b2k2/pp1Pbppp/2p5/q1n1r3/1PB5/4R3/P4PPP/RNB1K3 w Q - 3 9")
                .unwrap();

        let mut list = MoveVec::new();
        pawn_pin_ray_moves(
            &position,
            BB::new(A5) | BB::new(E5),
            !EMPTY,
            E1,
            BB::new(B4) | BB::new(E3),
            WHITE,
            &mut list,
        );
        assert_eq!(list.len(), 1);
        assert_list_includes_moves(&list, &["b4xa5"]);
    }
}
<|endoftext|>


<commit_before>/// A genetic algorithm in Rust
/// Copyright (C) 2015  Andrew Schwartzmeyer

use std::cmp::{Eq, PartialEq, Ordering, PartialOrd};
use std::mem;
use rand::Rng;
use rand::distributions::{IndependentSample, Range};

/// Schwefel's Evolutionary Computation benchmark [problem][]
/// Evaluated on the hypercube with x_i in [-500, 500] and dim(x) = 50
/// Global minimum: f(x*) = 0, at x* = (420.9687, ...)
/// [problem]: http://www.sfu.ca/~ssurjano/schwef.html
fn schwefel(solution: &[f64]) -> f64 {
    418.9829_f64 * solution.len() as f64
        - solution.iter().fold(0_f64, |sum, x| {
            sum + x * x.abs().sqrt().sin()
        })
}

/// An Orderable, Cloneable solution with a cached fitness
pub struct Individual {
    pub solution: Vec<f64>,
    pub fitness: f64,
}

impl Individual {
    /// Constructs a new Individual with 50 random values in the range
    pub fn new<R: Rng>(range: &Range<f64>, rng: &mut R) -> Self {
        let solution: Vec<_> = (0..50).map(|_| range.ind_sample(rng)).collect();
        let fitness = schwefel(&solution);
        Individual { solution: solution, fitness: fitness }
    }

    /// Mutates 0 or 1 random genes to a new value in the range
    pub fn mutate<R: Rng>(&mut self, range: &Range<f64>, rng: &mut R) {
        for _ in 0..rng.gen_range(0, 2) {
            let i = rng.gen_range(0, self.solution.len());
            self.solution[i] = range.ind_sample(rng);
        }
        self.fitness = schwefel(&self.solution);
    }

    /// Recombines two Individuals with a 1 in 2 chance via two-point crossover
    pub fn combine<R: Rng>(x: &mut Individual, y: &mut Individual, rng: &mut R) {
        if rng.gen_weighted_bool(2) {
            let len = x.solution.len();
            let (begin, n) = (rng.gen_range(0, len), rng.gen_range(0, len));
            for i in begin..(begin + n) % len {
                mem::swap(&mut x.solution[i], &mut y.solution[i]);
            }
            x.fitness = schwefel(&x.solution);
            y.fitness = schwefel(&y.solution);
        }
    }
}

impl Clone for Individual {
    fn clone(&self) -> Self {
        Individual { solution: self.solution.clone(), fitness: self.fitness }
    }
}

impl Eq for Individual {}

impl Ord for Individual {
    /// This dangerously delegates to `partial_cmp`; NaN will panic
    fn cmp(&self, other: &Self) -> Ordering {
        if let Some(result) = self.fitness.partial_cmp(&other.fitness) {
            return result;
        }
        unimplemented!();
    }
}

impl PartialEq<Individual> for Individual {
    /// This doesn't use `fitness.eq()` because it needs to be
    /// consistent with `Eq`
    fn eq(&self, other: &Individual) -> bool {
        if let Some(result) = self.fitness.partial_cmp(&other.fitness) {
            return result == Ordering::Equal;
        }
        unimplemented!();
    }
}

impl PartialOrd for Individual {
    /// This delegates to `fitness.partial_cmp()`
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        self.fitness.partial_cmp(&other.fitness)
    }
}
<commit_msg>Decrease complexity of fitness evaluation<commit_after>/// A genetic algorithm in Rust
/// Copyright (C) 2015  Andrew Schwartzmeyer

use std::cmp::{Eq, PartialEq, Ordering, PartialOrd};
use std::mem;
use rand::Rng;
use rand::distributions::{IndependentSample, Range};

/// Schwefel's Evolutionary Computation benchmark [problem][]
/// Evaluated on the hypercube with x_i in [-500, 500] and dim(x) = 50
/// Global minimum: f(x*) = 0, at x* = (420.9687, ...)
/// [problem]: http://www.sfu.ca/~ssurjano/schwef.html
fn schwefel(solution: &[f64]) -> f64 {
    418.9829_f64 * solution.len() as f64
        - solution.iter().fold(0_f64, |sum, x| {
            sum + x * x.abs().sqrt().sin()
        })
}

/// An Orderable, Cloneable solution with a cached fitness
pub struct Individual {
    pub solution: Vec<f64>,
    pub fitness: f64,
}

impl Individual {
    /// Constructs a new Individual with 50 random values in the range
    pub fn new<R: Rng>(range: &Range<f64>, rng: &mut R) -> Self {
        let solution: Vec<_> = (0..50).map(|_| range.ind_sample(rng)).collect();
        let fitness = schwefel(&solution);
        Individual { solution: solution, fitness: fitness }
    }

    /// Mutates 0 or 1 random genes to a new value in the range
    /// Fitness is NOT evaluated as it is ALWAYS done in `combine()`
    pub fn mutate<R: Rng>(&mut self, range: &Range<f64>, rng: &mut R) {
        for _ in 0..rng.gen_range(0, 2) {
            let i = rng.gen_range(0, self.solution.len());
            self.solution[i] = range.ind_sample(rng);
        }
    }

    /// Recombines two Individuals with a 1 in 2 chance via two-point crossover
    /// Fitness is ALWAYS evaluated because it is NOT done in mutate()
    pub fn combine<R: Rng>(x: &mut Individual, y: &mut Individual, rng: &mut R) {
        if rng.gen_weighted_bool(2) {
            let len = x.solution.len();
            let (begin, n) = (rng.gen_range(0, len), rng.gen_range(0, len));
            for i in begin..(begin + n) % len {
                mem::swap(&mut x.solution[i], &mut y.solution[i]);
            }
        }
        x.fitness = schwefel(&x.solution);
        y.fitness = schwefel(&y.solution);
    }
}

impl Clone for Individual {
    fn clone(&self) -> Self {
        Individual { solution: self.solution.clone(), fitness: self.fitness }
    }
}

impl Eq for Individual {}

impl Ord for Individual {
    /// This dangerously delegates to `partial_cmp`; NaN will panic
    fn cmp(&self, other: &Self) -> Ordering {
        if let Some(result) = self.fitness.partial_cmp(&other.fitness) {
            return result;
        }
        unimplemented!();
    }
}

impl PartialEq<Individual> for Individual {
    /// This doesn't use `fitness.eq()` because it needs to be
    /// consistent with `Eq`
    fn eq(&self, other: &Individual) -> bool {
        if let Some(result) = self.fitness.partial_cmp(&other.fitness) {
            return result == Ordering::Equal;
        }
        unimplemented!();
    }
}

impl PartialOrd for Individual {
    /// This delegates to `fitness.partial_cmp()`
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        self.fitness.partial_cmp(&other.fitness)
    }
}
<|endoftext|>


<commit_before>use std::cmp::Ordering;
use std::{mem};

// Bounded package merge algorithm, based on the paper
// "A Fast and Space-Economical Algorithm for Length-Limited Coding
// Jyrki Katajainen, Alistair Moffat, Andrew Turpin".

#[derive(Debug)]
struct Node {
    weight: usize,
    leaf_counts: Vec<usize>,
}

impl Node {
    fn new(weight: usize, initial_count: usize, capacity: usize) -> Node {
        let mut n = Node {
            weight: weight,
            leaf_counts: Vec::with_capacity(capacity),
        };
        n.leaf_counts.push(initial_count);
        n
    }
}

#[derive(Debug)]
struct Leaf {
    weight: usize,
    index: usize,
}
impl PartialEq for Leaf {
    fn eq(&self, other: &Self) -> bool {
        self.weight == other.weight
    }
}
impl Eq for Leaf { }
impl Ord for Leaf {
    fn cmp(&self, other: &Self) -> Ordering {
        self.weight.cmp(&other.weight)
    }
}
impl PartialOrd for Leaf {
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        Some(self.cmp(other))
    }
}

#[derive(Debug)]
struct List {
    lookahead1: Node,
    lookahead2: Node,
    next_leaf_index: usize,
}

/// Calculates the bitlengths for the Huffman tree, based on the counts of each
/// symbol.
pub fn length_limited_code_lengths(frequencies: &[usize], maxbits: i32) -> Vec<u32> {
    let num_freqs = frequencies.len();
    let mut leaves = vec![];

    // Count used symbols and place them in the leaves.
    for (i, &freq) in frequencies.iter().enumerate() {
        if freq != 0 {
            leaves.push(Leaf { weight: freq, index: i });
        }
    }

    // Short circuit some special cases
    if leaves.is_empty() {
        // There are no non-zero frequencies.
        return vec![0; num_freqs];
    }
    if leaves.len() == 1 {
        let mut result = vec![0; num_freqs];
        result[leaves[0].index] = 1;
        return result;
    }
    if leaves.len() == 2 {
        let mut result = vec![0; num_freqs];
        result[leaves[0].index] = 1;
        result[leaves[1].index] = 1;
        return result;
    }

    // Sort the leaves from least frequent to most frequent.
    // Add index into the same variable for stable sorting.
    for leaf in &mut leaves {
        leaf.weight = (leaf.weight << 9) | leaf.index;
    }
    leaves.sort();
    for leaf in &mut leaves {
        leaf.weight >>= 9;
    }

    let max_num_leaves = 2 * leaves.len() - 2;

    let mut lists = Vec::with_capacity(maxbits as usize);
    for _ in 0..maxbits {
        lists.push(List {
            lookahead1: Node::new(leaves[0].weight, 1, max_num_leaves),
            lookahead2: Node::new(leaves[1].weight, 2, max_num_leaves),
            next_leaf_index: 2,
        });
    }

    // In the last list, 2 * numsymbols - 2 active chains need to be created. Two
    // are already created in the initialization. Each boundary_pm run creates one.
    let num_boundary_pm_runs = max_num_leaves - 2;
    for _ in 0..num_boundary_pm_runs {
        boundary_pm_toplevel(&mut lists[..], &leaves);
    }

    let n = num_freqs;
    let mut result = vec![0; n];

    let mut a = lists.pop().unwrap().lookahead2.leaf_counts.into_iter().rev().peekable();

    let mut bitlength_value = 1;
    while let Some(leaf_count) = a.next() {
        let next_count = *a.peek().unwrap_or(&0);
        for leaf in &leaves[next_count..leaf_count] {
            result[leaf.index] = bitlength_value;
        }
        bitlength_value += 1;
    }

    result
}

fn lowest_list(lists: &mut [List], leaves: &[Leaf]) {
    // We're in the lowest list, just add another leaf to the lookaheads
    // There will always be more leaves to be added on level 0 so this is safe.
    let mut current_list = &mut lists[0];
    let next_leaf = &leaves[current_list.next_leaf_index];
    current_list.lookahead2.weight = next_leaf.weight;

    current_list.lookahead2.leaf_counts[0] = current_list.lookahead1.leaf_counts.last().unwrap() + 1;
    current_list.next_leaf_index += 1;
}

fn next_leaf(lists: &mut [List], leaves: &[Leaf], current_list_index: usize) {
    let mut current_list = &mut lists[current_list_index];

    // The next leaf goes next; counting itself makes the leaf_count increase by one.
    current_list.lookahead2.weight = leaves[current_list.next_leaf_index].weight;
    current_list.lookahead2.leaf_counts.clear();
    current_list.lookahead2.leaf_counts.extend_from_slice(&current_list.lookahead1.leaf_counts);
    let last_index = current_list.lookahead2.leaf_counts.len() - 1;
    current_list.lookahead2.leaf_counts[last_index] += 1;
    current_list.next_leaf_index += 1;
}

fn next_tree(weight_sum: usize, lists: &mut [List], leaves: &[Leaf], current_list_index: usize) {
    {
        let (head, tail) = lists.split_at_mut(current_list_index);
        let prev_list = head.last_mut().unwrap();
        let current_list = tail.first_mut().unwrap();

        let previous_list_leaf_counts = &prev_list.lookahead2.leaf_counts;

        // Make a tree from the lookaheads from the previous list; that goes next.
        // This is not a leaf node, so the leaf count stays the same.
        current_list.lookahead2.weight = weight_sum;
        current_list.lookahead2.leaf_counts.clear();

        current_list.lookahead2.leaf_counts.extend_from_slice(previous_list_leaf_counts);
        current_list.lookahead2.leaf_counts.push(*current_list.lookahead1.leaf_counts.last().unwrap());
    }

    // The previous list needs two new lookahead nodes.
    boundary_pm(lists, leaves, current_list_index - 1);
    boundary_pm(lists, leaves, current_list_index - 1);
}

fn boundary_pm_toplevel(lists: &mut [List], leaves: &[Leaf]) {
    let last_index = lists.len() - 1;
    boundary_pm(lists, leaves, last_index);
}

fn boundary_pm(lists: &mut [List], leaves: &[Leaf], current_list_index: usize) {
    let next_leaf_index = lists[current_list_index].next_leaf_index;

    if current_list_index == 0 && next_leaf_index == leaves.len() {
        // We've added all the leaves to the lowest list, so we're done here
        return;
    }

    mem::swap(&mut lists[current_list_index].lookahead1, &mut lists[current_list_index].lookahead2);

    if current_list_index == 0 {
        lowest_list(lists, leaves);
    } else {
        // We're at a list other than the lowest list.
        let weight_sum = {
            let previous_list = &lists[current_list_index - 1];
            previous_list.lookahead1.weight + previous_list.lookahead2.weight
        };

        if next_leaf_index < leaves.len() && weight_sum > leaves[next_leaf_index].weight {
            next_leaf(lists, leaves, current_list_index);
        } else {
            next_tree(weight_sum, lists, leaves, current_list_index);
        }
    }
}

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

    #[test]
    fn test_from_paper_3() {
        let input = [1, 1, 5, 7, 10, 14];
        let output = length_limited_code_lengths(&input, 3);
        let answer = vec![3, 3, 3, 3, 2, 2];
        assert_eq!(output, answer);
    }

    #[test]
    fn test_from_paper_4() {
        let input = [1, 1, 5, 7, 10, 14];
        let output = length_limited_code_lengths(&input, 4);
        let answer = vec![4, 4, 3, 2, 2, 2];
        assert_eq!(output, answer);
    }

    #[test]
    fn maxbits_7() {
        let input = [252, 0, 1, 6, 9, 10, 6, 3, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
        let output = length_limited_code_lengths(&input, 7);
        let answer = vec![1, 0, 6, 4, 3, 3, 3, 5, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
        assert_eq!(output, answer);
    }

    #[test]
    fn maxbits_15() {
        let input = [0, 0, 0, 0, 0, 0, 18, 0, 6, 0, 12, 2, 14, 9, 27, 15, 23, 15, 17, 8, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
        let output = length_limited_code_lengths(&input, 15);
        let answer = vec! [0, 0, 0, 0, 0, 0, 3, 0, 5, 0, 4, 6, 4, 4, 3, 4, 3, 3, 3, 4, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
        assert_eq!(output, answer);
    }

    #[test]
    fn no_frequencies() {
        let input = [0, 0, 0, 0, 0];
        let output = length_limited_code_lengths(&input, 7);
        let answer = vec![0, 0, 0, 0, 0];
        assert_eq!(output, answer);
    }

    #[test]
    fn only_one_frequency() {
        let input = [0, 10, 0];
        let output = length_limited_code_lengths(&input, 7);
        let answer = vec![0, 1, 0];
        assert_eq!(output, answer);
    }

    #[test]
    fn only_two_frequencies() {
        let input = [0, 0, 0, 0, 252, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
        let output = length_limited_code_lengths(&input, 7);
        let answer = [0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
        assert_eq!(output, answer);
    }
}
<commit_msg>Create vector with a capacity<commit_after>use std::cmp::Ordering;
use std::{mem};

// Bounded package merge algorithm, based on the paper
// "A Fast and Space-Economical Algorithm for Length-Limited Coding
// Jyrki Katajainen, Alistair Moffat, Andrew Turpin".

#[derive(Debug)]
struct Node {
    weight: usize,
    leaf_counts: Vec<usize>,
}

impl Node {
    fn new(weight: usize, initial_count: usize, capacity: usize) -> Node {
        let mut n = Node {
            weight: weight,
            leaf_counts: Vec::with_capacity(capacity),
        };
        n.leaf_counts.push(initial_count);
        n
    }
}

#[derive(Debug)]
struct Leaf {
    weight: usize,
    index: usize,
}
impl PartialEq for Leaf {
    fn eq(&self, other: &Self) -> bool {
        self.weight == other.weight
    }
}
impl Eq for Leaf { }
impl Ord for Leaf {
    fn cmp(&self, other: &Self) -> Ordering {
        self.weight.cmp(&other.weight)
    }
}
impl PartialOrd for Leaf {
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        Some(self.cmp(other))
    }
}

#[derive(Debug)]
struct List {
    lookahead1: Node,
    lookahead2: Node,
    next_leaf_index: usize,
}

/// Calculates the bitlengths for the Huffman tree, based on the counts of each
/// symbol.
pub fn length_limited_code_lengths(frequencies: &[usize], maxbits: i32) -> Vec<u32> {
    let num_freqs = frequencies.len();
    let mut leaves = Vec::with_capacity(num_freqs);

    // Count used symbols and place them in the leaves.
    for (i, &freq) in frequencies.iter().enumerate() {
        if freq != 0 {
            leaves.push(Leaf { weight: freq, index: i });
        }
    }

    // Short circuit some special cases
    if leaves.is_empty() {
        // There are no non-zero frequencies.
        return vec![0; num_freqs];
    }
    if leaves.len() == 1 {
        let mut result = vec![0; num_freqs];
        result[leaves[0].index] = 1;
        return result;
    }
    if leaves.len() == 2 {
        let mut result = vec![0; num_freqs];
        result[leaves[0].index] = 1;
        result[leaves[1].index] = 1;
        return result;
    }

    // Sort the leaves from least frequent to most frequent.
    // Add index into the same variable for stable sorting.
    for leaf in &mut leaves {
        leaf.weight = (leaf.weight << 9) | leaf.index;
    }
    leaves.sort();
    for leaf in &mut leaves {
        leaf.weight >>= 9;
    }

    let max_num_leaves = 2 * leaves.len() - 2;

    let mut lists = Vec::with_capacity(maxbits as usize);
    for _ in 0..maxbits {
        lists.push(List {
            lookahead1: Node::new(leaves[0].weight, 1, max_num_leaves),
            lookahead2: Node::new(leaves[1].weight, 2, max_num_leaves),
            next_leaf_index: 2,
        });
    }

    // In the last list, 2 * numsymbols - 2 active chains need to be created. Two
    // are already created in the initialization. Each boundary_pm run creates one.
    let num_boundary_pm_runs = max_num_leaves - 2;
    for _ in 0..num_boundary_pm_runs {
        boundary_pm_toplevel(&mut lists[..], &leaves);
    }

    let n = num_freqs;
    let mut result = vec![0; n];

    let mut a = lists.pop().unwrap().lookahead2.leaf_counts.into_iter().rev().peekable();

    let mut bitlength_value = 1;
    while let Some(leaf_count) = a.next() {
        let next_count = *a.peek().unwrap_or(&0);
        for leaf in &leaves[next_count..leaf_count] {
            result[leaf.index] = bitlength_value;
        }
        bitlength_value += 1;
    }

    result
}

fn lowest_list(lists: &mut [List], leaves: &[Leaf]) {
    // We're in the lowest list, just add another leaf to the lookaheads
    // There will always be more leaves to be added on level 0 so this is safe.
    let mut current_list = &mut lists[0];
    let next_leaf = &leaves[current_list.next_leaf_index];
    current_list.lookahead2.weight = next_leaf.weight;

    current_list.lookahead2.leaf_counts[0] = current_list.lookahead1.leaf_counts.last().unwrap() + 1;
    current_list.next_leaf_index += 1;
}

fn next_leaf(lists: &mut [List], leaves: &[Leaf], current_list_index: usize) {
    let mut current_list = &mut lists[current_list_index];

    // The next leaf goes next; counting itself makes the leaf_count increase by one.
    current_list.lookahead2.weight = leaves[current_list.next_leaf_index].weight;
    current_list.lookahead2.leaf_counts.clear();
    current_list.lookahead2.leaf_counts.extend_from_slice(&current_list.lookahead1.leaf_counts);
    let last_index = current_list.lookahead2.leaf_counts.len() - 1;
    current_list.lookahead2.leaf_counts[last_index] += 1;
    current_list.next_leaf_index += 1;
}

fn next_tree(weight_sum: usize, lists: &mut [List], leaves: &[Leaf], current_list_index: usize) {
    {
        let (head, tail) = lists.split_at_mut(current_list_index);
        let prev_list = head.last_mut().unwrap();
        let current_list = tail.first_mut().unwrap();

        let previous_list_leaf_counts = &prev_list.lookahead2.leaf_counts;

        // Make a tree from the lookaheads from the previous list; that goes next.
        // This is not a leaf node, so the leaf count stays the same.
        current_list.lookahead2.weight = weight_sum;
        current_list.lookahead2.leaf_counts.clear();

        current_list.lookahead2.leaf_counts.extend_from_slice(previous_list_leaf_counts);
        current_list.lookahead2.leaf_counts.push(*current_list.lookahead1.leaf_counts.last().unwrap());
    }

    // The previous list needs two new lookahead nodes.
    boundary_pm(lists, leaves, current_list_index - 1);
    boundary_pm(lists, leaves, current_list_index - 1);
}

fn boundary_pm_toplevel(lists: &mut [List], leaves: &[Leaf]) {
    let last_index = lists.len() - 1;
    boundary_pm(lists, leaves, last_index);
}

fn boundary_pm(lists: &mut [List], leaves: &[Leaf], current_list_index: usize) {
    let next_leaf_index = lists[current_list_index].next_leaf_index;

    if current_list_index == 0 && next_leaf_index == leaves.len() {
        // We've added all the leaves to the lowest list, so we're done here
        return;
    }

    mem::swap(&mut lists[current_list_index].lookahead1, &mut lists[current_list_index].lookahead2);

    if current_list_index == 0 {
        lowest_list(lists, leaves);
    } else {
        // We're at a list other than the lowest list.
        let weight_sum = {
            let previous_list = &lists[current_list_index - 1];
            previous_list.lookahead1.weight + previous_list.lookahead2.weight
        };

        if next_leaf_index < leaves.len() && weight_sum > leaves[next_leaf_index].weight {
            next_leaf(lists, leaves, current_list_index);
        } else {
            next_tree(weight_sum, lists, leaves, current_list_index);
        }
    }
}

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

    #[test]
    fn test_from_paper_3() {
        let input = [1, 1, 5, 7, 10, 14];
        let output = length_limited_code_lengths(&input, 3);
        let answer = vec![3, 3, 3, 3, 2, 2];
        assert_eq!(output, answer);
    }

    #[test]
    fn test_from_paper_4() {
        let input = [1, 1, 5, 7, 10, 14];
        let output = length_limited_code_lengths(&input, 4);
        let answer = vec![4, 4, 3, 2, 2, 2];
        assert_eq!(output, answer);
    }

    #[test]
    fn maxbits_7() {
        let input = [252, 0, 1, 6, 9, 10, 6, 3, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
        let output = length_limited_code_lengths(&input, 7);
        let answer = vec![1, 0, 6, 4, 3, 3, 3, 5, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
        assert_eq!(output, answer);
    }

    #[test]
    fn maxbits_15() {
        let input = [0, 0, 0, 0, 0, 0, 18, 0, 6, 0, 12, 2, 14, 9, 27, 15, 23, 15, 17, 8, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
        let output = length_limited_code_lengths(&input, 15);
        let answer = vec! [0, 0, 0, 0, 0, 0, 3, 0, 5, 0, 4, 6, 4, 4, 3, 4, 3, 3, 3, 4, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
        assert_eq!(output, answer);
    }

    #[test]
    fn no_frequencies() {
        let input = [0, 0, 0, 0, 0];
        let output = length_limited_code_lengths(&input, 7);
        let answer = vec![0, 0, 0, 0, 0];
        assert_eq!(output, answer);
    }

    #[test]
    fn only_one_frequency() {
        let input = [0, 10, 0];
        let output = length_limited_code_lengths(&input, 7);
        let answer = vec![0, 1, 0];
        assert_eq!(output, answer);
    }

    #[test]
    fn only_two_frequencies() {
        let input = [0, 0, 0, 0, 252, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
        let output = length_limited_code_lengths(&input, 7);
        let answer = [0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
        assert_eq!(output, answer);
    }
}
<|endoftext|>


<commit_before>//! Singular-value decomposition

use lapacke;
use num_traits::Zero;

use crate::error::*;
use crate::layout::MatrixLayout;
use crate::types::*;

use super::into_result;

#[repr(u8)]
enum FlagSVD {
    All = b'A',
    // OverWrite = b'O',
    // Separately = b'S',
    No = b'N',
}

/// Result of SVD
pub struct SVDOutput<A: Scalar> {
    /// diagonal values
    pub s: Vec<A::Real>,
    /// Unitary matrix for destination space
    pub u: Option<Vec<A>>,
    /// Unitary matrix for departure space
    pub vt: Option<Vec<A>>,
}

/// Wraps `*gesvd`
pub trait SVD_: Scalar {
    unsafe fn svd(l: MatrixLayout, calc_u: bool, calc_vt: bool, a: &mut [Self]) -> Result<SVDOutput<Self>>;
}

macro_rules! impl_svd {
    ($scalar:ty, $gesvd:path) => {
        impl SVD_ for $scalar {
            unsafe fn svd(l: MatrixLayout, calc_u: bool, calc_vt: bool, mut a: &mut [Self]) -> Result<SVDOutput<Self>> {
                let (m, n) = l.size();
                let k = ::std::cmp::min(n, m);
                let lda = l.lda();
                let (ju, ldu, mut u) = if calc_u {
                    (FlagSVD::All, m, vec![Self::zero(); (m * m) as usize])
                } else {
                    (FlagSVD::No, 1, Vec::new())
                };
                let (jvt, ldvt, mut vt) = if calc_vt {
                    (FlagSVD::All, n, vec![Self::zero(); (n * n) as usize])
                } else {
                    (FlagSVD::No, n, Vec::new())
                };
                let mut s = vec![Self::Real::zero(); k as usize];
                let mut superb = vec![Self::Real::zero(); (k - 1) as usize];
                dbg!(ldvt);
                let info = $gesvd(
                    l.lapacke_layout(),
                    ju as u8,
                    jvt as u8,
                    m,
                    n,
                    &mut a,
                    lda,
                    &mut s,
                    &mut u,
                    ldu,
                    &mut vt,
                    ldvt,
                    &mut superb,
                );
                into_result(
                    info,
                    SVDOutput {
                        s: s,
                        u: if calc_u { Some(u) } else { None },
                        vt: if calc_vt { Some(vt) } else { None },
                    },
                )
            }
        }
    };
} // impl_svd!

impl_svd!(f64, lapacke::dgesvd);
impl_svd!(f32, lapacke::sgesvd);
impl_svd!(c64, lapacke::zgesvd);
impl_svd!(c32, lapacke::cgesvd);
<commit_msg>rm dbg<commit_after>//! Singular-value decomposition

use lapacke;
use num_traits::Zero;

use crate::error::*;
use crate::layout::MatrixLayout;
use crate::types::*;

use super::into_result;

#[repr(u8)]
enum FlagSVD {
    All = b'A',
    // OverWrite = b'O',
    // Separately = b'S',
    No = b'N',
}

/// Result of SVD
pub struct SVDOutput<A: Scalar> {
    /// diagonal values
    pub s: Vec<A::Real>,
    /// Unitary matrix for destination space
    pub u: Option<Vec<A>>,
    /// Unitary matrix for departure space
    pub vt: Option<Vec<A>>,
}

/// Wraps `*gesvd`
pub trait SVD_: Scalar {
    unsafe fn svd(l: MatrixLayout, calc_u: bool, calc_vt: bool, a: &mut [Self]) -> Result<SVDOutput<Self>>;
}

macro_rules! impl_svd {
    ($scalar:ty, $gesvd:path) => {
        impl SVD_ for $scalar {
            unsafe fn svd(l: MatrixLayout, calc_u: bool, calc_vt: bool, mut a: &mut [Self]) -> Result<SVDOutput<Self>> {
                let (m, n) = l.size();
                let k = ::std::cmp::min(n, m);
                let lda = l.lda();
                let (ju, ldu, mut u) = if calc_u {
                    (FlagSVD::All, m, vec![Self::zero(); (m * m) as usize])
                } else {
                    (FlagSVD::No, 1, Vec::new())
                };
                let (jvt, ldvt, mut vt) = if calc_vt {
                    (FlagSVD::All, n, vec![Self::zero(); (n * n) as usize])
                } else {
                    (FlagSVD::No, n, Vec::new())
                };
                let mut s = vec![Self::Real::zero(); k as usize];
                let mut superb = vec![Self::Real::zero(); (k - 1) as usize];
                let info = $gesvd(
                    l.lapacke_layout(),
                    ju as u8,
                    jvt as u8,
                    m,
                    n,
                    &mut a,
                    lda,
                    &mut s,
                    &mut u,
                    ldu,
                    &mut vt,
                    ldvt,
                    &mut superb,
                );
                into_result(
                    info,
                    SVDOutput {
                        s: s,
                        u: if calc_u { Some(u) } else { None },
                        vt: if calc_vt { Some(vt) } else { None },
                    },
                )
            }
        }
    };
} // impl_svd!

impl_svd!(f64, lapacke::dgesvd);
impl_svd!(f32, lapacke::sgesvd);
impl_svd!(c64, lapacke::zgesvd);
impl_svd!(c32, lapacke::cgesvd);
<|endoftext|>


<commit_before>use std::convert::AsRef;
use std::io;
use std::io::Write;

/// The level of information to display to a logger#
#[derive(Debug, PartialEq, Eq, PartialOrd, Clone, Copy)]
pub enum InfoLevel {
    /// Debug: the lowest level
    Debug = 0,
    /// Info: won't be displayed by default
    Warning,
    /// Warning: the default level
    Info,
    /// Error
    Error
}

use self::InfoLevel::*;

/// Logs info and warning message and choose whether to display them
/// according to verbosity
#[derive(Debug)]
pub struct Logger {
    verbosity: InfoLevel,
}

impl Logger {
    /// Creates a new logger with defined verbosity
    pub fn new(verbosity: InfoLevel) -> Logger {
        Logger {
            verbosity: verbosity
        }
    }

    /// Sets verbosity
    pub fn set_verbosity(&mut self, verbosity: InfoLevel) {
        self.verbosity = verbosity;
    }

    /// Prints a message if logger's verbosity <= level
    pub fn log<S: AsRef<str>>(&self, level: InfoLevel, s: S) {
        if level >= self.verbosity {
            match level {
                Debug => writeln!(&mut io::stderr(),
                                  "{}{}{}{}",
                                  SHELL_COLOUR_BLUE,
                                  "Debug: ",
                                  SHELL_COLOUR_OFF,
                                  s.as_ref())
                    .unwrap(),
                Info => writeln!(&mut io::stderr(),
                                 "{}{}",
                                 "Info: ",
                                 s.as_ref())
                    .unwrap(),
                Warning => writeln!(&mut io::stderr(),
                                    "{}{}{}{}",
                                    SHELL_COLOUR_ORANGE,
                                    "Warning: ",
                                    SHELL_COLOUR_OFF,
                                    s.as_ref())
                    .unwrap(),
                Error => writeln!(&mut io::stderr(),
                                  "{}{}{}{}",
                                  SHELL_COLOUR_RED,
                                  "Error: ",
                                  SHELL_COLOUR_OFF,
                                  s.as_ref())
                    .unwrap()
            }
        }
    }

    /// Equivalent of log(Debug, s)
    pub fn debug<S: AsRef<str>>(&self, s: S) {
        self.log(InfoLevel::Debug, s);
    }

    /// Equivalent of log(Info, s)
    pub fn info<S: AsRef<str>>(&self, s: S) {
        self.log(InfoLevel::Info, s);
    }

    /// Equivalent of log(Warning, s)
    pub fn warning<S: AsRef<str>>(&self, s: S) {
        self.log(InfoLevel::Warning, s);
    }

    /// Equivalent of log(Error, s)
    pub fn error<S: AsRef<str>>(&self, s: S) {
        self.log(InfoLevel::Error, s);
    }
}

// Code to end shell colouring
const SHELL_COLOUR_OFF: &'static str = "\x1B[0m";
const SHELL_COLOUR_RED: &'static str = "\x1B[31m";
const SHELL_COLOUR_BLUE: &'static str = "\x1B[36m";
const SHELL_COLOUR_ORANGE: &'static str = "\x1B[33m";
<commit_msg>Make logger output infolevel in bold<commit_after>use std::convert::AsRef;
use std::io;
use std::io::Write;

/// The level of information to display to a logger#
#[derive(Debug, PartialEq, Eq, PartialOrd, Clone, Copy)]
pub enum InfoLevel {
    /// Debug: the lowest level
    Debug = 0,
    /// Info: won't be displayed by default
    Warning,
    /// Warning: the default level
    Info,
    /// Error
    Error
}

use self::InfoLevel::*;

/// Logs info and warning message and choose whether to display them
/// according to verbosity
#[derive(Debug)]
pub struct Logger {
    verbosity: InfoLevel,
}

impl Logger {
    /// Creates a new logger with defined verbosity
    pub fn new(verbosity: InfoLevel) -> Logger {
        Logger {
            verbosity: verbosity
        }
    }

    /// Sets verbosity
    pub fn set_verbosity(&mut self, verbosity: InfoLevel) {
        self.verbosity = verbosity;
    }

    /// Prints a message if logger's verbosity <= level
    pub fn log<S: AsRef<str>>(&self, level: InfoLevel, s: S) {
        if level >= self.verbosity {
            match level {
                Debug => writeln!(&mut io::stderr(),
                                  "{}{}{}{}",
                                  SHELL_COLOUR_BLUE,
                                  "Debug: ",
                                  SHELL_COLOUR_OFF,
                                  s.as_ref())
                    .unwrap(),
                Info => writeln!(&mut io::stderr(),
                                 "{}{}{}{}",
                                 SHELL_COLOUR_GREEN,
                                 "Info: ",
                                 SHELL_COLOUR_OFF,
                                 s.as_ref())
                    .unwrap(),
                Warning => writeln!(&mut io::stderr(),
                                    "{}{}{}{}",
                                    SHELL_COLOUR_ORANGE,
                                    "Warning: ",
                                    SHELL_COLOUR_OFF,
                                    s.as_ref())
                    .unwrap(),
                Error => writeln!(&mut io::stderr(),
                                  "{}{}{}{}",
                                  SHELL_COLOUR_RED,
                                  "Error: ",
                                  SHELL_COLOUR_OFF,
                                  s.as_ref())
                    .unwrap()
            }
        }
    }

    /// Equivalent of log(Debug, s)
    pub fn debug<S: AsRef<str>>(&self, s: S) {
        self.log(InfoLevel::Debug, s);
    }

    /// Equivalent of log(Info, s)
    pub fn info<S: AsRef<str>>(&self, s: S) {
        self.log(InfoLevel::Info, s);
    }

    /// Equivalent of log(Warning, s)
    pub fn warning<S: AsRef<str>>(&self, s: S) {
        self.log(InfoLevel::Warning, s);
    }

    /// Equivalent of log(Error, s)
    pub fn error<S: AsRef<str>>(&self, s: S) {
        self.log(InfoLevel::Error, s);
    }
}

// Code to end shell colouring
const SHELL_COLOUR_OFF: &'static str = "\x1B[0m";
const SHELL_COLOUR_RED: &'static str = "\x1B[1m\x1B[31m";
const SHELL_COLOUR_BLUE: &'static str = "\x1B[1m\x1B[36m";
const SHELL_COLOUR_ORANGE: &'static str = "\x1B[1m\x1B[33m";
const SHELL_COLOUR_GREEN: &'static str = "\x1B[1m\x1B[32m";
<|endoftext|>


<commit_before>use byteorder::{ReadBytesExt, LittleEndian};
use rwinstructs::timestamp::{WinTimestamp};
use rwinstructs::guid::{Guid};
use rshellitems::shellitem::{ShellItem};
use rshellitems::shelllist::{ShellList};
use lnkpkg::locationinfo::{LocationInfo};
use lnkpkg::datablocks::{ExtraDataBlocks};
use lnkpkg::flags::{DataFlags,FileFlags};
use lnkpkg::flags;
use lnkpkg::errors::{LnkError};
use lnkpkg::utils;
use std::io::Read;
use std::io::Seek;
use std::io::Cursor;

#[derive(Serialize,Debug)]
// 76 bytes long,
pub struct ShellLinkHeader {
    pub header_size: u32,
    pub guid: Guid,
    pub data_flags: DataFlags,
    pub file_flags: FileFlags,
    pub created: WinTimestamp,
    pub accessed: WinTimestamp,
    pub modified: WinTimestamp,
    pub file_size: u32,
    pub icon_offset: i32,
    pub window_flag: u32,
    pub hot_key: u16,
    #[serde(skip_serializing)]
    pub unknown1: u16,
    #[serde(skip_serializing)]
    pub unknown2: u32,
    #[serde(skip_serializing)]
    pub unknown3: u32
}
impl ShellLinkHeader {
    pub fn new<R: Read>(mut reader: R) -> Result<ShellLinkHeader,LnkError> {
        let header_size = reader.read_u32::<LittleEndian>()?;
        let mut guid = Guid([0; 16]);
        reader.read_exact(&mut guid.0)?;

        let data_flags = DataFlags::from_bits_truncate(
            reader.read_u32::<LittleEndian>()?
        );

        let file_flags = FileFlags::from_bits_truncate(
            reader.read_u32::<LittleEndian>()?
        );
        let created = WinTimestamp(reader.read_u64::<LittleEndian>()?);
        let accessed = WinTimestamp(reader.read_u64::<LittleEndian>()?);
        let modified = WinTimestamp(reader.read_u64::<LittleEndian>()?);
        let file_size = reader.read_u32::<LittleEndian>()?;
        let icon_offset = reader.read_i32::<LittleEndian>()?;
        let window_flag = reader.read_u32::<LittleEndian>()?;
        let hot_key = reader.read_u16::<LittleEndian>()?;
        let unknown1 = reader.read_u16::<LittleEndian>()?;
        let unknown2 = reader.read_u32::<LittleEndian>()?;
        let unknown3 = reader.read_u32::<LittleEndian>()?;

        Ok(
            ShellLinkHeader {
                header_size: header_size,
                guid: guid,
                data_flags: data_flags,
                file_flags: file_flags,
                created: created,
                accessed: accessed,
                modified: modified,
                file_size: file_size,
                icon_offset: icon_offset,
                window_flag: window_flag,
                hot_key: hot_key,
                unknown1: unknown1,
                unknown2: unknown2,
                unknown3: unknown3
            }
        )
    }

    pub fn get_data_flags(&self) -> DataFlags {
        self.data_flags
    }
}

#[derive(Serialize,Debug)]
pub struct TargetIdList {
    pub list_size: u16,
    pub shell_items: ShellList
}

impl TargetIdList{
    pub fn new<R: Read>(mut reader: R) -> Result<TargetIdList, LnkError> {
        let list_size = reader.read_u16::<LittleEndian>()?;
        let mut buffer = vec![0; list_size as usize];
        reader.read_exact(&mut buffer)?;

        let mut shell_items = ShellList::new(
            Cursor::new(buffer)
        )?;

        Ok(
            TargetIdList {
                list_size: list_size,
                shell_items: shell_items
            }
        )
    }

    pub fn get_size(&self) -> u16 {
        self.list_size
    }
}

#[derive(Serialize,Debug)]
pub struct DataStrings {
    pub description: Option<String>,
    pub relative_path: Option<String>,
    pub working_directory: Option<String>,
    pub command_line_args: Option<String>,
    pub icon_location: Option<String>
}
impl DataStrings {
    pub fn new<R: Read>(mut reader: R, data_flags: DataFlags) -> Result<DataStrings,LnkError> {
        let unicode_flag = data_flags.contains(flags::IS_UNICODE);

        let mut description = None;
        if data_flags.contains(flags::HAS_NAME) {
            if unicode_flag {
                description = Some(utils::read_string_u16_w_size(&mut reader)?);
            } else {
                description = Some(utils::read_string_u8_w_size(&mut reader)?);
            }
        }

        let mut relative_path = None;
        if data_flags.contains(flags::HAS_RELATIVE_PATH) {
            if unicode_flag {
                relative_path = Some(utils::read_string_u16_w_size(&mut reader)?);
            } else {
                relative_path = Some(utils::read_string_u8_w_size(&mut reader)?);
            }
        }

        let mut working_directory = None;
        if data_flags.contains(flags::HAS_WORKING_DIR) {
            if unicode_flag {
                working_directory = Some(utils::read_string_u16_w_size(&mut reader)?);
            } else {
                working_directory = Some(utils::read_string_u8_w_size(&mut reader)?);
            }
        }

        let mut command_line_args = None;
        if data_flags.contains(flags::HAS_ARGUMENTS) {
            if unicode_flag {
                command_line_args = Some(utils::read_string_u16_w_size(&mut reader)?);
            } else {
                command_line_args = Some(utils::read_string_u8_w_size(&mut reader)?);
            }
        }

        let mut icon_location = None;
        if data_flags.contains(flags::HAS_ICON_LOCATION) {
            if unicode_flag {
                icon_location = Some(utils::read_string_u16_w_size(&mut reader)?);
            } else {
                icon_location = Some(utils::read_string_u8_w_size(&mut reader)?);
            }
        }

        Ok(
            DataStrings {
                description: description,
                relative_path: relative_path,
                working_directory: working_directory,
                command_line_args: command_line_args,
                icon_location: icon_location
            }
        )
    }
}

#[derive(Serialize,Debug)]
pub struct Lnk {
    pub header: ShellLinkHeader,
    pub target_list: Option<TargetIdList>,
    pub location_info: Option<LocationInfo>,
    pub data_strings: DataStrings,
    pub extra_data: ExtraDataBlocks
}

impl Lnk {
    pub fn new<Rs: Read+Seek>(mut reader: Rs) -> Result<Lnk,LnkError> {
        let header = ShellLinkHeader::new(&mut reader)?;
        let header_flags = header.get_data_flags();

        let mut target_list = None;
        if header_flags.contains(flags::HAS_TARGET_ID_LIST) {
            // println!("target_list starting offset: {}",reader.seek(SeekFrom::Current(0))?);
            target_list = Some(TargetIdList::new(&mut reader)?);
        }

        let mut location_info = None;
        if header_flags.contains(flags::HAS_LINK_INFO) {
            // println!("location_info starting offset: {}",reader.seek(SeekFrom::Current(0))?);
            location_info = Some(LocationInfo::new(&mut reader)?);
        }

        // println!("data_strings starting offset: {}",reader.seek(SeekFrom::Current(0))?);
        let data_strings = DataStrings::new(
            &mut reader,
            header_flags
        )?;

        let extra_data = ExtraDataBlocks::new(&mut reader)?;

        Ok(
            Lnk {
                header: header,
                target_list: target_list,
                location_info: location_info,
                data_strings: data_strings,
                extra_data: extra_data
            }
        )
    }

    fn get_shell_list() {

    }
}
<commit_msg>clean up<commit_after>use byteorder::{ReadBytesExt, LittleEndian};
use rwinstructs::timestamp::{WinTimestamp};
use rwinstructs::guid::{Guid};
use rshellitems::shelllist::{ShellList};
use lnkpkg::locationinfo::{LocationInfo};
use lnkpkg::datablocks::{ExtraDataBlocks};
use lnkpkg::flags::{DataFlags,FileFlags};
use lnkpkg::flags;
use lnkpkg::errors::{LnkError};
use lnkpkg::utils;
use std::io::Read;
use std::io::Seek;
use std::io::Cursor;

#[derive(Serialize,Debug)]
// 76 bytes long,
pub struct ShellLinkHeader {
    pub header_size: u32,
    pub guid: Guid,
    pub data_flags: DataFlags,
    pub file_flags: FileFlags,
    pub created: WinTimestamp,
    pub accessed: WinTimestamp,
    pub modified: WinTimestamp,
    pub file_size: u32,
    pub icon_offset: i32,
    pub window_flag: u32,
    pub hot_key: u16,
    #[serde(skip_serializing)]
    pub unknown1: u16,
    #[serde(skip_serializing)]
    pub unknown2: u32,
    #[serde(skip_serializing)]
    pub unknown3: u32
}
impl ShellLinkHeader {
    pub fn new<R: Read>(mut reader: R) -> Result<ShellLinkHeader,LnkError> {
        let header_size = reader.read_u32::<LittleEndian>()?;
        let mut guid = Guid([0; 16]);
        reader.read_exact(&mut guid.0)?;

        let data_flags = DataFlags::from_bits_truncate(
            reader.read_u32::<LittleEndian>()?
        );

        let file_flags = FileFlags::from_bits_truncate(
            reader.read_u32::<LittleEndian>()?
        );
        let created = WinTimestamp(reader.read_u64::<LittleEndian>()?);
        let accessed = WinTimestamp(reader.read_u64::<LittleEndian>()?);
        let modified = WinTimestamp(reader.read_u64::<LittleEndian>()?);
        let file_size = reader.read_u32::<LittleEndian>()?;
        let icon_offset = reader.read_i32::<LittleEndian>()?;
        let window_flag = reader.read_u32::<LittleEndian>()?;
        let hot_key = reader.read_u16::<LittleEndian>()?;
        let unknown1 = reader.read_u16::<LittleEndian>()?;
        let unknown2 = reader.read_u32::<LittleEndian>()?;
        let unknown3 = reader.read_u32::<LittleEndian>()?;

        Ok(
            ShellLinkHeader {
                header_size: header_size,
                guid: guid,
                data_flags: data_flags,
                file_flags: file_flags,
                created: created,
                accessed: accessed,
                modified: modified,
                file_size: file_size,
                icon_offset: icon_offset,
                window_flag: window_flag,
                hot_key: hot_key,
                unknown1: unknown1,
                unknown2: unknown2,
                unknown3: unknown3
            }
        )
    }

    pub fn get_data_flags(&self) -> DataFlags {
        self.data_flags
    }
}

#[derive(Serialize,Debug)]
pub struct TargetIdList {
    pub list_size: u16,
    pub shell_items: ShellList
}

impl TargetIdList{
    pub fn new<R: Read>(mut reader: R) -> Result<TargetIdList, LnkError> {
        let list_size = reader.read_u16::<LittleEndian>()?;
        let mut buffer = vec![0; list_size as usize];
        reader.read_exact(&mut buffer)?;

        let shell_items = ShellList::new(
            Cursor::new(buffer)
        )?;

        Ok(
            TargetIdList {
                list_size: list_size,
                shell_items: shell_items
            }
        )
    }

    pub fn get_size(&self) -> u16 {
        self.list_size
    }
}

#[derive(Serialize,Debug)]
pub struct DataStrings {
    pub description: Option<String>,
    pub relative_path: Option<String>,
    pub working_directory: Option<String>,
    pub command_line_args: Option<String>,
    pub icon_location: Option<String>
}
impl DataStrings {
    pub fn new<R: Read>(mut reader: R, data_flags: DataFlags) -> Result<DataStrings,LnkError> {
        let unicode_flag = data_flags.contains(flags::IS_UNICODE);

        let mut description = None;
        if data_flags.contains(flags::HAS_NAME) {
            if unicode_flag {
                description = Some(utils::read_string_u16_w_size(&mut reader)?);
            } else {
                description = Some(utils::read_string_u8_w_size(&mut reader)?);
            }
        }

        let mut relative_path = None;
        if data_flags.contains(flags::HAS_RELATIVE_PATH) {
            if unicode_flag {
                relative_path = Some(utils::read_string_u16_w_size(&mut reader)?);
            } else {
                relative_path = Some(utils::read_string_u8_w_size(&mut reader)?);
            }
        }

        let mut working_directory = None;
        if data_flags.contains(flags::HAS_WORKING_DIR) {
            if unicode_flag {
                working_directory = Some(utils::read_string_u16_w_size(&mut reader)?);
            } else {
                working_directory = Some(utils::read_string_u8_w_size(&mut reader)?);
            }
        }

        let mut command_line_args = None;
        if data_flags.contains(flags::HAS_ARGUMENTS) {
            if unicode_flag {
                command_line_args = Some(utils::read_string_u16_w_size(&mut reader)?);
            } else {
                command_line_args = Some(utils::read_string_u8_w_size(&mut reader)?);
            }
        }

        let mut icon_location = None;
        if data_flags.contains(flags::HAS_ICON_LOCATION) {
            if unicode_flag {
                icon_location = Some(utils::read_string_u16_w_size(&mut reader)?);
            } else {
                icon_location = Some(utils::read_string_u8_w_size(&mut reader)?);
            }
        }

        Ok(
            DataStrings {
                description: description,
                relative_path: relative_path,
                working_directory: working_directory,
                command_line_args: command_line_args,
                icon_location: icon_location
            }
        )
    }
}

#[derive(Serialize,Debug)]
pub struct Lnk {
    pub header: ShellLinkHeader,
    pub target_list: Option<TargetIdList>,
    pub location_info: Option<LocationInfo>,
    pub data_strings: DataStrings,
    pub extra_data: ExtraDataBlocks
}

impl Lnk {
    pub fn new<Rs: Read+Seek>(mut reader: Rs) -> Result<Lnk,LnkError> {
        let header = ShellLinkHeader::new(&mut reader)?;
        let header_flags = header.get_data_flags();

        let mut target_list = None;
        if header_flags.contains(flags::HAS_TARGET_ID_LIST) {
            // println!("target_list starting offset: {}",reader.seek(SeekFrom::Current(0))?);
            target_list = Some(TargetIdList::new(&mut reader)?);
        }

        let mut location_info = None;
        if header_flags.contains(flags::HAS_LINK_INFO) {
            // println!("location_info starting offset: {}",reader.seek(SeekFrom::Current(0))?);
            location_info = Some(LocationInfo::new(&mut reader)?);
        }

        // println!("data_strings starting offset: {}",reader.seek(SeekFrom::Current(0))?);
        let data_strings = DataStrings::new(
            &mut reader,
            header_flags
        )?;

        let extra_data = ExtraDataBlocks::new(&mut reader)?;

        Ok(
            Lnk {
                header: header,
                target_list: target_list,
                location_info: location_info,
                data_strings: data_strings,
                extra_data: extra_data
            }
        )
    }
}
<|endoftext|>


<commit_before>pub fn max_matrix_sum(matrix: Vec<Vec<i32>>) -> i64 {
    todo!()
}

fn main() {
    println!("{}", max_matrix_sum(vec![vec![1, -1], vec![-1, 1]])); // 4
    println!(
        "{}",
        max_matrix_sum(vec![vec![1, 2, 3], vec![-1, -2, -3], vec![1, 2, 3]])
    ); // 16
    println!(
        "{}",
        max_matrix_sum(vec![
            vec![1, 2, 3, 4],
            vec![-1, -2, -3, 4],
            vec![1, 2, 3, 4],
            vec![1, 2, 3, 4]
        ])
    ); // 38
    println!(
        "{}",
        max_matrix_sum(vec![
            vec![1, 2, 3, 4],
            vec![-1, -2, -3, -4],
            vec![1, 2, 3, 4],
            vec![1, 2, 3, 4]
        ])
    ); // 40
    println!(
        "{}",
        max_matrix_sum(vec![
            vec![1, 2, 3, 4, 5],
            vec![1, 2, 3, 4, 5],
            vec![1, 2, -3, 4, 5],
            vec![1, 2, 3, 4, 5],
            vec![1, 2, 3, 4, 5],
        ])
    ); // 73
}
<commit_msg>Solve problem 1975<commit_after>use std::cmp;

pub fn max_matrix_sum(matrix: Vec<Vec<i32>>) -> i64 {
    let mut sum: i64 = 0;
    let mut negative_count = 0;
    let mut smallest = i32::MAX;
    for i in 0..matrix.len() {
        for j in 0..matrix[0].len() {
            sum += i64::abs(matrix[i][j] as i64);
            negative_count += if matrix[i][j] < 0 { 1 } else { 0 };
            smallest = cmp::min(smallest, i32::abs(matrix[i][j]));
        }
    }
    if negative_count % 2 == 0 {
        sum
    } else {
        sum - (smallest as i64 * 2)
    }
}

fn main() {
    println!("{}", max_matrix_sum(vec![vec![1, -1], vec![-1, 1]])); // 4
    println!(
        "{}",
        max_matrix_sum(vec![vec![1, 2, 3], vec![-1, -2, -3], vec![1, 2, 3]])
    ); // 16
    println!(
        "{}",
        max_matrix_sum(vec![
            vec![1, 2, 3, 4],
            vec![-1, -2, -3, 4],
            vec![1, 2, 3, 4],
            vec![1, 2, 3, 4]
        ])
    ); // 38
    println!(
        "{}",
        max_matrix_sum(vec![
            vec![1, 2, 3, 4],
            vec![-1, -2, -3, -4],
            vec![1, 2, 3, 4],
            vec![1, 2, 3, 4]
        ])
    ); // 40
    println!(
        "{}",
        max_matrix_sum(vec![
            vec![1, 2, 3, 4, 5],
            vec![1, 2, 3, 4, 5],
            vec![1, 2, -3, 4, 5],
            vec![1, 2, 3, 4, 5],
            vec![1, 2, 3, 4, 5],
        ])
    ); // 73
}
<|endoftext|>


<commit_before>// https://leetcode.com/problems/minimum-deletions-to-make-array-beautiful/
pub fn min_deletion(nums: Vec<i32>) -> i32 {
    todo!()
}

fn main() {
    println!("{}", min_deletion(vec![1, 1, 2, 3, 5])); // 1
    println!("{}", min_deletion(vec![1, 1, 2, 2, 3, 3])); // 2
    println!("{}", min_deletion(vec![1, 1, 2, 2, 3])); // 1
    println!("{}", min_deletion(vec![1, 1, 1, 1, 1])); // 5
}
<commit_msg>Solve problem 2216<commit_after>// https://leetcode.com/problems/minimum-deletions-to-make-array-beautiful/
pub fn min_deletion(nums: Vec<i32>) -> i32 {
    let mut answer = 0;
    let mut count = 0;
    let mut even = true;
    let mut i = 0;
    while i < nums.len() {
        if even && i + 1 < nums.len() && nums[i] == nums[i + 1] {
            answer += 1;
        } else {
            even = !even;
            count += 1;
        }
        i += 1;
    }
    if count % 2 == 0 {
        answer
    } else {
        answer + 1
    }
}

fn main() {
    println!("{}", min_deletion(vec![1, 1, 2, 3, 5])); // 1
    println!("{}", min_deletion(vec![1, 1, 2, 2, 3, 3])); // 2
    println!("{}", min_deletion(vec![1, 1, 2, 2, 3])); // 1
    println!("{}", min_deletion(vec![1, 1, 1, 1, 1])); // 5
}
<|endoftext|>


<commit_before>// https://leetcode.com/problems/fair-distribution-of-cookies/
pub fn distribute_cookies(cookies: Vec<i32>, k: i32) -> i32 {
    todo!()
}

fn main() {
    println!("{}", distribute_cookies(vec![8, 15, 10, 20, 8], 2)); // 31
    println!("{}", distribute_cookies(vec![6, 1, 3, 2, 2, 4, 1, 3], 2)); // 7
}
<commit_msg>Solve problem 2305<commit_after>use std::cmp;

// https://leetcode.com/problems/fair-distribution-of-cookies/
pub fn distribute_cookies(cookies: Vec<i32>, k: i32) -> i32 {
    fn f(cookies: &Vec<i32>, k: i32, index: i32, children: &mut Vec<i32>, min: &mut i32) {
        if index as usize == cookies.len() {
            let max = children.iter().max().unwrap().to_owned();
            *min = cmp::min(*min, max);
            return;
        }
        for i in 0..k {
            children[i as usize] += cookies[index as usize];
            f(cookies, k, index + 1, children, min);
            children[i as usize] -= cookies[index as usize];
        }
    }
    let mut children = vec![0; k as usize];
    let mut answer = i32::MAX;
    f(&cookies, k, 0, &mut children, &mut answer);
    answer
}

fn main() {
    println!("{}", distribute_cookies(vec![8, 15, 10, 20, 8], 2)); // 31
    println!("{}", distribute_cookies(vec![6, 1, 3, 2, 2, 4, 1, 2], 3)); // 7
}
<|endoftext|>


<commit_before>extern crate sdl2;
extern crate toffee;

use std::time;
use sdl2::keyboard::Keycode;
use sdl2::event::Event;
use toffee::font::FontDefinition;
use toffee::terminal::Terminal;
use toffee::renderer::Renderer;
use toffee::event::Events;
use toffee::colors;

pub fn main() {
    let font = FontDefinition {
        image_path: "fonts/grim_10x12.png",
        width: 10,
        height: 12,
        padding: 0,
        transparent: false,
    };
    let mut term = Terminal::new(50, 20);
    let mut term_renderer = Renderer::new(&term, font);
    let mut event_handler = Events::new(&term);

    term.print_center(5, "It seems to be working!", colors::WHITE, colors::BLUE);

    let mut last_update = time::SystemTime::now();
    let mut frames = 0;
    let mut fps = 0;

    let mut x = 0;
    let mut y = 0;

    'mainloop: loop {

        for event in event_handler.event_pump.poll_iter() {
            match event {
                Event::Quit { .. } |
                Event::KeyDown { keycode: Some(Keycode::Escape), .. } => break 'mainloop,
                _ => {}
            }
        }

        term.print(0,
                   0,
                   format!("FPS: {}", fps).as_str(),
                   colors::YELLOW,
                   colors::BLACK);

        term_renderer.draw(&mut term);
        frames += 1;

        let now = time::SystemTime::now();
        let seconds_since_last =
            time::SystemTime::now().duration_since(last_update).unwrap().as_secs();

        if seconds_since_last >= 1 {
            fps = frames;
            frames = 0;
            last_update = now;
        }
    }
}
<commit_msg>removed unused vars from example<commit_after>extern crate sdl2;
extern crate toffee;

use std::time;
use sdl2::keyboard::Keycode;
use sdl2::event::Event;
use toffee::font::FontDefinition;
use toffee::terminal::Terminal;
use toffee::renderer::Renderer;
use toffee::event::Events;
use toffee::colors;

pub fn main() {
    let font = FontDefinition {
        image_path: "fonts/grim_10x12.png",
        width: 10,
        height: 12,
        padding: 0,
        transparent: false,
    };
    let mut term = Terminal::new(50, 20);
    let mut term_renderer = Renderer::new(&term, font);
    let mut event_handler = Events::new(&term);

    term.print_center(5, "It seems to be working!", colors::WHITE, colors::BLUE);

    let mut last_update = time::SystemTime::now();
    let mut frames = 0;
    let mut fps = 0;

    'mainloop: loop {

        for event in event_handler.event_pump.poll_iter() {
            match event {
                Event::Quit { .. } |
                Event::KeyDown { keycode: Some(Keycode::Escape), .. } => break 'mainloop,
                _ => {}
            }
        }

        term.print(0,
                   0,
                   format!("FPS: {}", fps).as_str(),
                   colors::YELLOW,
                   colors::BLACK);

        term_renderer.draw(&mut term);
        frames += 1;

        let now = time::SystemTime::now();
        let seconds_since_last =
            time::SystemTime::now().duration_since(last_update).unwrap().as_secs();

        if seconds_since_last >= 1 {
            fps = frames;
            frames = 0;
            last_update = now;
        }
    }
}
<|endoftext|>


<commit_before>
use {Field, Borrowed, Value};
use vecmath::{relative_round_rectangle, margin_round_rectangle,
rotate_radians, multiply, translate, scale, shear, identity};
use {Transform2d, Matrix2d, RoundRectangle, Color};
use {Fill, Clear, BackEnd};
use {RelativeRectangle, View};
use triangulation::{
    with_round_rectangle_tri_list_xy_f32_rgba_f32
};

/// A rectangle color context.
pub struct RoundRectangleColorContext<'a> {
    /// Base/original transformation.
    pub base: Field<'a, Matrix2d>,
    /// Current transformation.
    pub transform: Field<'a, Matrix2d>,
    /// Current rectangle.
    pub round_rect: Field<'a, RoundRectangle>,
    /// Current color.
    pub color: Field<'a, Color>,
}

impl<'a> Transform2d<'a> for RoundRectangleColorContext<'a> {
    #[inline(always)]
    fn trans(&'a self, x: f64, y: f64) -> RoundRectangleColorContext<'a> {
        RoundRectangleColorContext {
            base: Borrowed(self.base.get()),
            transform: {
                let trans = translate(x, y);
                Value(multiply(&trans, self.transform.get()))
            },
            round_rect: Borrowed(self.round_rect.get()),
            color: Borrowed(self.color.get()),
        }
    }

    #[inline(always)]
    fn trans_local(&'a self, x: f64, y: f64) -> RoundRectangleColorContext<'a> {
        RoundRectangleColorContext {
            base: Borrowed(self.base.get()),
            transform: {
                let trans = translate(x, y);
                Value(multiply(self.transform.get(), &trans))
            },
            round_rect: Borrowed(self.round_rect.get()),
            color: Borrowed(self.color.get()),
        }
    }

    #[inline(always)]
    fn rot_rad(&'a self, angle: f64) -> RoundRectangleColorContext<'a> {
        RoundRectangleColorContext {
            base: Borrowed(self.base.get()),
            transform: {
                let rot = rotate_radians(angle);
                Value(multiply(&rot, self.transform.get()))
            },
            round_rect: Borrowed(self.round_rect.get()),
            color: Borrowed(self.color.get()),
        }
    }

    #[inline(always)]
    fn rot_rad_local(&'a self, angle: f64) -> RoundRectangleColorContext<'a> {
        RoundRectangleColorContext {
            base: Borrowed(self.base.get()),
            transform: {
                let rot = rotate_radians(angle);
                Value(multiply(self.transform.get(), &rot))
            },
            round_rect: Borrowed(self.round_rect.get()),
            color: Borrowed(self.color.get()),
        }
    }

    #[inline(always)]
    fn scale(&'a self, sx: f64, sy: f64) -> RoundRectangleColorContext<'a> {
        RoundRectangleColorContext {
            base: Borrowed(self.base.get()),
            transform: {
                let scale = scale(sx, sy);
                Value(multiply(&scale, self.transform.get()))
            },
            round_rect: Borrowed(self.round_rect.get()),
            color: Borrowed(self.color.get()),
        }
    }

    #[inline(always)]
    fn scale_local(&'a self, sx: f64, sy: f64) -> RoundRectangleColorContext<'a> {
        RoundRectangleColorContext {
            base: Borrowed(self.base.get()),
            transform: {
                let scale = scale(sx, sy);
                Value(multiply(self.transform.get(), &scale))
            },
            round_rect: Borrowed(self.round_rect.get()),
            color: Borrowed(self.color.get()),
        }
    }

    #[inline(always)]
    fn shear(&'a self, sx: f64, sy: f64) -> RoundRectangleColorContext<'a> {
        RoundRectangleColorContext {
            base: Borrowed(self.base.get()),
            transform: {
                let shear = shear(sx, sy);
                Value(multiply(&shear, self.transform.get()))
            },
            round_rect: Borrowed(self.round_rect.get()),
            color: Borrowed(self.color.get()),
        }
    }

    #[inline(always)]
    fn shear_local(&'a self, sx: f64, sy: f64) -> RoundRectangleColorContext<'a> {
        RoundRectangleColorContext {
            base: Borrowed(self.base.get()),
            transform: {
                let shear = shear(sx, sy);
                Value(multiply(self.transform.get(), &shear))
            },
            round_rect: Borrowed(self.round_rect.get()),
            color: Borrowed(self.color.get()),
        }
    }
}

impl<'a> Clear for RoundRectangleColorContext<'a> {
    fn clear<B: BackEnd>(&self, back_end: &mut B) {
        if back_end.supports_clear_rgba() {
            let color = self.color.get();
            back_end.clear_rgba(color[0], color[1], color[2], color[3]);
        } else {
            unimplemented!();
        }
    }
}

impl<'a> RelativeRectangle<'a> for RoundRectangleColorContext<'a> {
    #[inline(always)]
    fn margin(&'a self, m: f64) -> RoundRectangleColorContext<'a> {
        RoundRectangleColorContext {
            base: Borrowed(self.base.get()),
            transform: Borrowed(self.transform.get()),
            color: Borrowed(self.color.get()),
            round_rect: Value(margin_round_rectangle(self.round_rect.get(), m)),
        }
    }

    #[inline(always)]
    fn rel(&'a self, x: f64, y: f64) -> RoundRectangleColorContext<'a> {
        RoundRectangleColorContext {
            base: Borrowed(self.base.get()),
            transform: Borrowed(self.transform.get()),
            color: Borrowed(self.color.get()),
            round_rect: Value(relative_round_rectangle(self.round_rect.get(), x, y)),
        }
    }
}

impl<'a> Fill<'a> for RoundRectangleColorContext<'a> {
    fn fill<B: BackEnd>(&'a self, back_end: &mut B) {
        if back_end.supports_tri_list_xy_f32_rgba_f32() {
            let round_rect = self.round_rect.get();
            let color = self.color.get();
            let color: [f32, ..4] = [color[0], color[1], color[2], color[3]];
            // Complete transparency does not need to be rendered.
            if color[3] == 0.0 { return; }
            // Turn on alpha blending if not completely opaque.
            let needs_alpha = color[3] != 1.0;
            if needs_alpha { back_end.enable_alpha_blend(); }
            with_round_rectangle_tri_list_xy_f32_rgba_f32(
                32,
                self.transform.get(),
                round_rect,
                color,
                |vertices, colors| {
                    back_end.tri_list_xy_f32_rgba_f32(vertices, colors)
                }
            );
            if needs_alpha { back_end.disable_alpha_blend(); }
        } else {
            unimplemented!();
        }
    }
}

impl<'a> View<'a> for RoundRectangleColorContext<'a> {
    #[inline(always)]
    fn view(&'a self) -> RoundRectangleColorContext<'a> {
        RoundRectangleColorContext {
            base: Borrowed(self.base.get()),
            transform: Borrowed(self.base.get()),
            round_rect: Borrowed(self.round_rect.get()),
            color: Borrowed(self.color.get()),
        }
    }

    #[inline(always)]
    fn reset(&'a self) -> RoundRectangleColorContext<'a> {
        RoundRectangleColorContext {
            base: Borrowed(self.base.get()),
            transform: Value(identity()),
            round_rect: Borrowed(self.round_rect.get()),
            color: Borrowed(self.color.get()),
        }
    }

    #[inline(always)]
    fn store_view(&'a self) -> RoundRectangleColorContext<'a> {
        RoundRectangleColorContext {
            base: Borrowed(self.transform.get()),
            transform: Borrowed(self.transform.get()),
            round_rect: Borrowed(self.round_rect.get()),
            color: Borrowed(self.color.get()),
        }
    }
}

<commit_msg>Sorted use alphabetically<commit_after>
use {
    BackEnd,
    Borrowed,
    Clear,
    Color,
    Field,
    Fill,
    Matrix2d,
    RelativeRectangle,
    RoundRectangle,
    Transform2d,
    Value,
    View,
};
use vecmath::{
    identity,
    margin_round_rectangle,
    multiply,
    relative_round_rectangle,
    rotate_radians,
    scale,
    shear,
    translate,
};
use triangulation::{
    with_round_rectangle_tri_list_xy_f32_rgba_f32
};

/// A rectangle color context.
pub struct RoundRectangleColorContext<'a> {
    /// Base/original transformation.
    pub base: Field<'a, Matrix2d>,
    /// Current transformation.
    pub transform: Field<'a, Matrix2d>,
    /// Current rectangle.
    pub round_rect: Field<'a, RoundRectangle>,
    /// Current color.
    pub color: Field<'a, Color>,
}

impl<'a> Transform2d<'a> for RoundRectangleColorContext<'a> {
    #[inline(always)]
    fn trans(&'a self, x: f64, y: f64) -> RoundRectangleColorContext<'a> {
        RoundRectangleColorContext {
            base: Borrowed(self.base.get()),
            transform: {
                let trans = translate(x, y);
                Value(multiply(&trans, self.transform.get()))
            },
            round_rect: Borrowed(self.round_rect.get()),
            color: Borrowed(self.color.get()),
        }
    }

    #[inline(always)]
    fn trans_local(&'a self, x: f64, y: f64) -> RoundRectangleColorContext<'a> {
        RoundRectangleColorContext {
            base: Borrowed(self.base.get()),
            transform: {
                let trans = translate(x, y);
                Value(multiply(self.transform.get(), &trans))
            },
            round_rect: Borrowed(self.round_rect.get()),
            color: Borrowed(self.color.get()),
        }
    }

    #[inline(always)]
    fn rot_rad(&'a self, angle: f64) -> RoundRectangleColorContext<'a> {
        RoundRectangleColorContext {
            base: Borrowed(self.base.get()),
            transform: {
                let rot = rotate_radians(angle);
                Value(multiply(&rot, self.transform.get()))
            },
            round_rect: Borrowed(self.round_rect.get()),
            color: Borrowed(self.color.get()),
        }
    }

    #[inline(always)]
    fn rot_rad_local(&'a self, angle: f64) -> RoundRectangleColorContext<'a> {
        RoundRectangleColorContext {
            base: Borrowed(self.base.get()),
            transform: {
                let rot = rotate_radians(angle);
                Value(multiply(self.transform.get(), &rot))
            },
            round_rect: Borrowed(self.round_rect.get()),
            color: Borrowed(self.color.get()),
        }
    }

    #[inline(always)]
    fn scale(&'a self, sx: f64, sy: f64) -> RoundRectangleColorContext<'a> {
        RoundRectangleColorContext {
            base: Borrowed(self.base.get()),
            transform: {
                let scale = scale(sx, sy);
                Value(multiply(&scale, self.transform.get()))
            },
            round_rect: Borrowed(self.round_rect.get()),
            color: Borrowed(self.color.get()),
        }
    }

    #[inline(always)]
    fn scale_local(&'a self, sx: f64, sy: f64) -> RoundRectangleColorContext<'a> {
        RoundRectangleColorContext {
            base: Borrowed(self.base.get()),
            transform: {
                let scale = scale(sx, sy);
                Value(multiply(self.transform.get(), &scale))
            },
            round_rect: Borrowed(self.round_rect.get()),
            color: Borrowed(self.color.get()),
        }
    }

    #[inline(always)]
    fn shear(&'a self, sx: f64, sy: f64) -> RoundRectangleColorContext<'a> {
        RoundRectangleColorContext {
            base: Borrowed(self.base.get()),
            transform: {
                let shear = shear(sx, sy);
                Value(multiply(&shear, self.transform.get()))
            },
            round_rect: Borrowed(self.round_rect.get()),
            color: Borrowed(self.color.get()),
        }
    }

    #[inline(always)]
    fn shear_local(&'a self, sx: f64, sy: f64) -> RoundRectangleColorContext<'a> {
        RoundRectangleColorContext {
            base: Borrowed(self.base.get()),
            transform: {
                let shear = shear(sx, sy);
                Value(multiply(self.transform.get(), &shear))
            },
            round_rect: Borrowed(self.round_rect.get()),
            color: Borrowed(self.color.get()),
        }
    }
}

impl<'a> Clear for RoundRectangleColorContext<'a> {
    fn clear<B: BackEnd>(&self, back_end: &mut B) {
        if back_end.supports_clear_rgba() {
            let color = self.color.get();
            back_end.clear_rgba(color[0], color[1], color[2], color[3]);
        } else {
            unimplemented!();
        }
    }
}

impl<'a> RelativeRectangle<'a> for RoundRectangleColorContext<'a> {
    #[inline(always)]
    fn margin(&'a self, m: f64) -> RoundRectangleColorContext<'a> {
        RoundRectangleColorContext {
            base: Borrowed(self.base.get()),
            transform: Borrowed(self.transform.get()),
            color: Borrowed(self.color.get()),
            round_rect: Value(margin_round_rectangle(self.round_rect.get(), m)),
        }
    }

    #[inline(always)]
    fn rel(&'a self, x: f64, y: f64) -> RoundRectangleColorContext<'a> {
        RoundRectangleColorContext {
            base: Borrowed(self.base.get()),
            transform: Borrowed(self.transform.get()),
            color: Borrowed(self.color.get()),
            round_rect: Value(relative_round_rectangle(self.round_rect.get(), x, y)),
        }
    }
}

impl<'a> Fill<'a> for RoundRectangleColorContext<'a> {
    fn fill<B: BackEnd>(&'a self, back_end: &mut B) {
        if back_end.supports_tri_list_xy_f32_rgba_f32() {
            let round_rect = self.round_rect.get();
            let color = self.color.get();
            let color: [f32, ..4] = [color[0], color[1], color[2], color[3]];
            // Complete transparency does not need to be rendered.
            if color[3] == 0.0 { return; }
            // Turn on alpha blending if not completely opaque.
            let needs_alpha = color[3] != 1.0;
            if needs_alpha { back_end.enable_alpha_blend(); }
            with_round_rectangle_tri_list_xy_f32_rgba_f32(
                32,
                self.transform.get(),
                round_rect,
                color,
                |vertices, colors| {
                    back_end.tri_list_xy_f32_rgba_f32(vertices, colors)
                }
            );
            if needs_alpha { back_end.disable_alpha_blend(); }
        } else {
            unimplemented!();
        }
    }
}

impl<'a> View<'a> for RoundRectangleColorContext<'a> {
    #[inline(always)]
    fn view(&'a self) -> RoundRectangleColorContext<'a> {
        RoundRectangleColorContext {
            base: Borrowed(self.base.get()),
            transform: Borrowed(self.base.get()),
            round_rect: Borrowed(self.round_rect.get()),
            color: Borrowed(self.color.get()),
        }
    }

    #[inline(always)]
    fn reset(&'a self) -> RoundRectangleColorContext<'a> {
        RoundRectangleColorContext {
            base: Borrowed(self.base.get()),
            transform: Value(identity()),
            round_rect: Borrowed(self.round_rect.get()),
            color: Borrowed(self.color.get()),
        }
    }

    #[inline(always)]
    fn store_view(&'a self) -> RoundRectangleColorContext<'a> {
        RoundRectangleColorContext {
            base: Borrowed(self.transform.get()),
            transform: Borrowed(self.transform.get()),
            round_rect: Borrowed(self.round_rect.get()),
            color: Borrowed(self.color.get()),
        }
    }
}

<|endoftext|>


<commit_before>use rusqlite::Connection;
use std::result;

#[derive(Debug)]
pub struct JobRequireVariable {
    id: i32,
    fk_job: i32,
    fk_variable: i32,
}

pub fn table_create_job_require_variable(conn: &Connection) {
    conn.execute(
        "CREATE TABLE JOB_REQUIRE_VARIABLE (
                  id                    INTEGER PRIMARY KEY ASC,
                  fk_job                INTEGER NOT NULL,
                  fk_variable           INTEGER NOT NULL,
                  FOREIGN KEY(fk_job) REFERENCES JOB(id) ON UPDATE CASCADE
                  FOREIGN KEY(fk_variable) REFERENCES JOB_REQUIRE_VARIABLE(id) ON UPDATE CASCADE
                  )",
        &[],
    ).unwrap();
}

pub fn insert_job_require_variable(
    conn: &Connection,
    job: &i32,
    variable: &i32,
) -> Result<i32, &'static str> {
    let me = JobRequireVariable {
        id: 0,
        fk_job: *job,
        fk_variable: *variable,
    };
    let job_require_variable_instance = conn.execute(
        "INSERT INTO JOB_REQUIRE_VARIABLE (fk_job, fk_variable)
                  VALUES (?1, ?2)",
        &[&me.fk_job, &me.fk_variable],
    );
    if job_require_variable_instance.is_err() {
        return Err("Insert failed");
    }
    job_require_variable_instance.unwrap();
    return Ok(0);
}

pub fn list_job_require_variable(conn: &Connection) -> Vec<JobRequireVariable> {
    let mut stmt = conn.prepare("SELECT id, fk_job, fk_variable  FROM JOB_REQUIRE_VARIABLE")
        .unwrap();
    let wraped_fs_file_iter = stmt.query_map(&[], |row| {
        JobRequireVariable {
            id: row.get(0),
            fk_job: row.get(1),
            fk_variable: row.get(2),
        }
    });
    let mut items = Vec::<JobRequireVariable>::new();
    if wraped_fs_file_iter.is_err() {
        return items;

    }
    let fs_file_iter = wraped_fs_file_iter.unwrap();
    for person in fs_file_iter {

        items.push(person.unwrap());
    }
    return items;
}

pub fn job_require_variable_list(conn: &Connection) {
    let mut stmt = conn.prepare("SELECT id, fk_job, fk_variable  FROM JOB_REQUIRE_VARIABLE")
        .unwrap();
    let person_iter = stmt.query_map(&[], |row| {
        JobRequireVariable {
            id: row.get(0),
            fk_job: row.get(1),
            fk_variable: row.get(2),
        }
    }).unwrap();

    for person in person_iter {
        println!("Found job_require_variable {:?}", person.unwrap());
    }
}

pub fn pk_job_require_variable_by_name(
    conn: &Connection,
    job: &i32,
    variable: &i32,
    pk: &mut i32,
) -> Result<i32, &'static str> {
    let mut stmt = conn.prepare("SELECT id, fk_job, fk_variable  FROM JOB_REQUIRE_VARIABLE WHERE fk_job = ?1 AND fk_variable = ?2").unwrap();
    let job_require_variable_iter = stmt.query_map(&[job, variable], |row| {
        JobRequireVariable {
            id: row.get(0),
            fk_job: row.get(1),
            fk_variable: row.get(2),
        }
    });
    if job_require_variable_iter.is_err() {
        return Err("Insert failed dfdf");
    }
    let result = job_require_variable_iter.unwrap();
    let mut found = 0;
    let mut items = Vec::<i32>::new();
    for person in result {
        let bill = person.unwrap();
        *pk = bill.id;
        found = 1;
    }
    if found != 0 {
        return Ok(found);
    }
    return Err("None found");
}
<commit_msg>Use Logging<commit_after>use rusqlite::Connection;
use std::result;
use log;

#[derive(Debug)]
pub struct JobRequireVariable {
    id: i32,
    fk_job: i32,
    fk_variable: i32,
}

pub fn table_create_job_require_variable(conn: &Connection) {
    conn.execute(
        "CREATE TABLE JOB_REQUIRE_VARIABLE (
                  id                    INTEGER PRIMARY KEY ASC,
                  fk_job                INTEGER NOT NULL,
                  fk_variable           INTEGER NOT NULL,
                  FOREIGN KEY(fk_job) REFERENCES JOB(id) ON UPDATE CASCADE
                  FOREIGN KEY(fk_variable) REFERENCES JOB_REQUIRE_VARIABLE(id) ON UPDATE CASCADE
                  )",
        &[],
    ).unwrap();
}

pub fn insert_job_require_variable(
    conn: &Connection,
    job: &i32,
    variable: &i32,
) -> Result<i32, &'static str> {
    let me = JobRequireVariable {
        id: 0,
        fk_job: *job,
        fk_variable: *variable,
    };
    let job_require_variable_instance = conn.execute(
        "INSERT INTO JOB_REQUIRE_VARIABLE (fk_job, fk_variable)
                  VALUES (?1, ?2)",
        &[&me.fk_job, &me.fk_variable],
    );
    if job_require_variable_instance.is_err() {
        return Err("Insert failed");
    }
    job_require_variable_instance.unwrap();
    return Ok(0);
}

pub fn list_job_require_variable(conn: &Connection) -> Vec<JobRequireVariable> {
    let mut stmt = conn.prepare("SELECT id, fk_job, fk_variable  FROM JOB_REQUIRE_VARIABLE")
        .unwrap();
    let wraped_fs_file_iter = stmt.query_map(&[], |row| {
        JobRequireVariable {
            id: row.get(0),
            fk_job: row.get(1),
            fk_variable: row.get(2),
        }
    });
    let mut items = Vec::<JobRequireVariable>::new();
    if wraped_fs_file_iter.is_err() {
        return items;

    }
    let fs_file_iter = wraped_fs_file_iter.unwrap();
    for person in fs_file_iter {

        items.push(person.unwrap());
    }
    return items;
}

pub fn job_require_variable_list(conn: &Connection) {
    let mut stmt = conn.prepare("SELECT id, fk_job, fk_variable  FROM JOB_REQUIRE_VARIABLE")
        .unwrap();
    let person_iter = stmt.query_map(&[], |row| {
        JobRequireVariable {
            id: row.get(0),
            fk_job: row.get(1),
            fk_variable: row.get(2),
        }
    }).unwrap();

    for person in person_iter {
        info!("Found job_require_variable {:?}", person.unwrap());
    }
}

pub fn pk_job_require_variable_by_name(
    conn: &Connection,
    job: &i32,
    variable: &i32,
    pk: &mut i32,
) -> Result<i32, &'static str> {
    let mut stmt = conn.prepare("SELECT id, fk_job, fk_variable  FROM JOB_REQUIRE_VARIABLE WHERE fk_job = ?1 AND fk_variable = ?2").unwrap();
    let job_require_variable_iter = stmt.query_map(&[job, variable], |row| {
        JobRequireVariable {
            id: row.get(0),
            fk_job: row.get(1),
            fk_variable: row.get(2),
        }
    });
    if job_require_variable_iter.is_err() {
        return Err("Insert failed dfdf");
    }
    let result = job_require_variable_iter.unwrap();
    let mut found = 0;
    let mut items = Vec::<i32>::new();
    for person in result {
        let bill = person.unwrap();
        *pk = bill.id;
        found = 1;
    }
    if found != 0 {
        return Ok(found);
    }
    return Err("None found");
}
<|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,
    sequence: u32be,
    acknowledgement: u32be,
    #[payload]
    payload: Vec<u8>
}

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

    const IPV4_HEADER_LEN: usize = 20;
    const TCP_HEADER_LEN: usize = 12;
    const PAYLOAD_LEN: usize = 4;

    let mut packet = [0u8; IPV4_HEADER_LEN + TCP_HEADER_LEN + PAYLOAD_LEN];

    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[IPV4_HEADER_LEN + TCP_HEADER_LEN + 0] = 't' as u8;
    packet[IPV4_HEADER_LEN + TCP_HEADER_LEN + 1] = 'e' as u8;
    packet[IPV4_HEADER_LEN + TCP_HEADER_LEN + 2] = 's' as u8;
    packet[IPV4_HEADER_LEN + TCP_HEADER_LEN + 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_sequence(3456);
        assert_eq!(tcp_header.get_sequence(), 3456);

        tcp_header.set_acknowledgement(7799);
        assert_eq!(tcp_header.get_acknowledgement(), 7799);
    }

    let ref_packet = [0x30, 0x39,  // source
                      0xd4, 0x31,  // destination
                      0x00, 0x00,  // sequence
                      0x0d, 0x80,
                      0x00, 0x00,  // acknowledgement
                      0x1e, 0x77];

    assert_eq!(&ref_packet[..], &packet[IPV4_HEADER_LEN .. IPV4_HEADER_LEN + TCP_HEADER_LEN]);
}

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

    const IPV6_HEADER_LEN: usize = 40;
    const TCP_HEADER_LEN: usize = 12;
    const PAYLOAD_LEN: usize = 4;

    let mut packet = [0u8; IPV6_HEADER_LEN + TCP_HEADER_LEN + PAYLOAD_LEN];

    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[IPV6_HEADER_LEN + TCP_HEADER_LEN + 0] = 't' as u8;
    packet[IPV6_HEADER_LEN + TCP_HEADER_LEN + 1] = 'e' as u8;
    packet[IPV6_HEADER_LEN + TCP_HEADER_LEN + 2] = 's' as u8;
    packet[IPV6_HEADER_LEN + TCP_HEADER_LEN + 3] = 't' as u8;

    {
        let mut tcp_header = MutableTcpPacket::new(&mut packet[IPV6_HEADER_LEN..]).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_sequence(3456);
        assert_eq!(tcp_header.get_sequence(), 3456);

        tcp_header.set_acknowledgement(7799);
        assert_eq!(tcp_header.get_acknowledgement(), 7799);
    }

    let ref_packet = [0x30, 0x39,  // source
                      0xd4, 0x31,  // destination
                      0x00, 0x00,  // sequence
                      0x0d, 0x80,
                      0x00, 0x00,  // acknowledgement
                      0x1e, 0x77];

    assert_eq!(&ref_packet[..], &packet[IPV6_HEADER_LEN .. IPV6_HEADER_LEN + TCP_HEADER_LEN]);
}
<commit_msg>Add the rest of the TCP header options<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,
    sequence: u32be,
    acknowledgement: u32be,
    data_offset_reserved: u8, // data offset field & reserved field
    control_bits: u8, // the first 5 bits are used; the rest is reserved
    window: u16be,
    checksum: u16be,
    urgent_pointer: u16be,
    simple_no_options: u8, // XXX replace with something more complex later
    #[payload]
    payload: Vec<u8>
}

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

    const IPV4_HEADER_LEN: usize = 20;
    const TCP_HEADER_LEN: usize = 21;
    const PAYLOAD_LEN: usize = 4;

    let mut packet = [0u8; IPV4_HEADER_LEN + TCP_HEADER_LEN + PAYLOAD_LEN];

    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[IPV4_HEADER_LEN + TCP_HEADER_LEN + 0] = 't' as u8;
    packet[IPV4_HEADER_LEN + TCP_HEADER_LEN + 1] = 'e' as u8;
    packet[IPV4_HEADER_LEN + TCP_HEADER_LEN + 2] = 's' as u8;
    packet[IPV4_HEADER_LEN + TCP_HEADER_LEN + 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_sequence(3456);
        assert_eq!(tcp_header.get_sequence(), 3456);

        tcp_header.set_acknowledgement(7799);
        assert_eq!(tcp_header.get_acknowledgement(), 7799);

        tcp_header.set_data_offset_reserved(0x80);
        assert_eq!(tcp_header.get_data_offset_reserved(), 0x80);
    }

    let ref_packet = [0x30, 0x39,  // source
                      0xd4, 0x31,  // destination
                      0x00, 0x00,  // sequence
                      0x0d, 0x80,
                      0x00, 0x00,  // acknowledgement
                      0x1e, 0x77,
                      0x80,        // header length + reserved
                      0x00,        // control bits
                      0x00, 0x00,  // window
                      0x00, 0x00,  // checksum
                      0x00, 0x00,  // urgent pointer
                      0x00];       // simple no tcp header options

    assert_eq!(&ref_packet[..], &packet[IPV4_HEADER_LEN .. IPV4_HEADER_LEN + TCP_HEADER_LEN]);
}

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

    const IPV6_HEADER_LEN: usize = 40;
    const TCP_HEADER_LEN: usize = 21;
    const PAYLOAD_LEN: usize = 4;

    let mut packet = [0u8; IPV6_HEADER_LEN + TCP_HEADER_LEN + PAYLOAD_LEN];

    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[IPV6_HEADER_LEN + TCP_HEADER_LEN + 0] = 't' as u8;
    packet[IPV6_HEADER_LEN + TCP_HEADER_LEN + 1] = 'e' as u8;
    packet[IPV6_HEADER_LEN + TCP_HEADER_LEN + 2] = 's' as u8;
    packet[IPV6_HEADER_LEN + TCP_HEADER_LEN + 3] = 't' as u8;

    {
        let mut tcp_header = MutableTcpPacket::new(&mut packet[IPV6_HEADER_LEN..]).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_sequence(3456);
        assert_eq!(tcp_header.get_sequence(), 3456);

        tcp_header.set_acknowledgement(7799);
        assert_eq!(tcp_header.get_acknowledgement(), 7799);

        tcp_header.set_data_offset_reserved(0x80);
        assert_eq!(tcp_header.get_data_offset_reserved(), 0x80);
    }

    let ref_packet = [0x30, 0x39,  // source
                      0xd4, 0x31,  // destination
                      0x00, 0x00,  // sequence
                      0x0d, 0x80,
                      0x00, 0x00,  // acknowledgement
                      0x1e, 0x77,
                      0x80,        // header length + reserved
                      0x00,        // control bits
                      0x00, 0x00,  // window
                      0x00, 0x00,  // checksum
                      0x00, 0x00,  // urgent pointer
                      0x00];       // simple no tcp header options

    assert_eq!(&ref_packet[..], &packet[IPV6_HEADER_LEN .. IPV6_HEADER_LEN + TCP_HEADER_LEN]);
}
<|endoftext|>