<commit_before>use std::cell::Cell;
use std::cmp::Ordering;

use typed_arena::Arena;

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

struct Thing<'a> {
    node_arena: &'a Arena<Node<'a>>,
    leaves: Vec<Leaf>,
    lists: Vec<List<'a>>,
}

#[derive(Debug)]
struct Node<'a> {
    weight: usize,
    count: usize,
    tail: Cell<Option<&'a Node<'a>>>,
}

#[derive(Debug)]
struct Leaf {
    weight: usize,
    count: 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, Clone)]
struct List<'a> {
    lookahead0: &'a Node<'a>,
    lookahead1: &'a Node<'a>,
}

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

    // Count used symbols and place them in the leaves.
    let mut leaves: Vec<_> = frequencies.iter()
        .enumerate()
        .filter(|&(_, &freq)| freq != 0)
        .map(|(i, &freq)| Leaf { weight: freq, count: i })
        .collect();

    let num_symbols = leaves.len();

    // Short circuit some special cases

    // TODO:
    // if ((1 << maxbits) < numsymbols) {
    //   free(leaves);
    //   return 1;  /* Error, too few maxbits to represent symbols. */
    // }

    if num_symbols == 0 {
        // There are no non-zero frequencies.
        return bit_lengths;
    }
    if num_symbols == 1 {
        bit_lengths[leaves[0].count] = 1;
        return bit_lengths;
    }
    if num_symbols == 2 {
        bit_lengths[leaves[0].count] = 1;
        bit_lengths[leaves[1].count] = 1;
        return bit_lengths;
    }

    // Sort the leaves from least frequent to most frequent.
    leaves.sort();

    let max_bits = if num_symbols - 1 < max_bits {
        num_symbols - 1
    } else {
        max_bits
    };

    let arena_capacity = max_bits * 2 * num_symbols;
    let node_arena: Arena<Node> = Arena::with_capacity(arena_capacity);

    let node0 = node_arena.alloc(Node {
        weight: leaves[0].weight,
        count: 1,
        tail: Cell::new(None),
    });

    let node1 = node_arena.alloc(Node {
        weight: leaves[1].weight,
        count: 2,
        tail: Cell::new(None),
    });

    let lists: Vec<List> = vec![
        List {
            lookahead0: node0,
            lookahead1: node1,
        };
        max_bits
    ];

    let mut thing = Thing {
        node_arena: &node_arena,
        leaves,
        lists,
    };

    // In the last list, 2 * num_symbols - 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 = 2 * num_symbols - 4;
    for _ in 0..num_boundary_pm_runs - 1 {
        thing.boundary_pm(max_bits - 1);
    }

    thing.boundary_pm_final(max_bits - 1);

    // let mut a = lists.pop().unwrap().lookahead1.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] {
    //         bit_lengths[leaf.count] = bitlength_value;
    //     }
    //     bitlength_value += 1;
    // }

    bit_lengths
}

impl<'a> Thing<'a> {
    fn boundary_pm(&mut self, index: usize) {
        let num_symbols = self.leaves.len();

        let last_count = self.lists[index].lookahead1.count; // Count of last chain of list.

        if index == 0 && last_count >= num_symbols {
            return
        }

        self.lists[index].lookahead0 = self.lists[index].lookahead1;

        if index == 0 {
            // New leaf node in list 0.
            let new_chain = self.node_arena.alloc(Node {
               weight: self.leaves[last_count].weight,
               count: last_count + 1,
               tail: self.lists[index].lookahead0.tail.clone(),
            });
            self.lists[index].lookahead1 = new_chain;
        } else {
            let weight_sum = {
                let previous_list = &self.lists[index - 1];
                previous_list.lookahead0.weight + previous_list.lookahead1.weight
            };

            if last_count < num_symbols && weight_sum > self.leaves[last_count].weight {
                // New leaf inserted in list, so count is incremented.
                let new_chain = self.node_arena.alloc(Node {
                   weight: self.leaves[last_count].weight,
                   count: last_count + 1,
                   tail: self.lists[index].lookahead0.tail.clone(),
                });
                self.lists[index].lookahead1 = new_chain;
            } else {
                let new_chain = self.node_arena.alloc(Node {
                   weight: weight_sum,
                   count: last_count,
                   tail: Cell::new(Some(self.lists[index - 1].lookahead1)),
                });
                self.lists[index].lookahead1 = new_chain;

                // Two lookahead chains of previous list used up, create new ones.
                self.boundary_pm(index - 1);
                self.boundary_pm(index - 1);
            }
        }
    }

    fn boundary_pm_final(&mut self, index: usize) {
        let num_symbols = self.leaves.len();

        // Count of last chain of list.
        let last_count = self.lists[index].lookahead1.count;

        let weight_sum = {
            let previous_list = &self.lists[index - 1];
            previous_list.lookahead0.weight + previous_list.lookahead1.weight
        };

        if last_count < num_symbols && weight_sum > self.leaves[last_count].weight {
            let new_chain = self.node_arena.alloc(Node {
               weight: 0,
               count: last_count + 1,
               tail: self.lists[index].lookahead1.tail.clone(),
            });
            self.lists[index].lookahead1 = new_chain;
        } else {
            self.lists[index].lookahead1.tail.set(Some(self.lists[index - 1].lookahead1));
        }
    }
}

// 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.lookahead1.weight = leaves[current_list.next_leaf_index].weight;
//     current_list.lookahead1.leaf_counts.clear();
//     current_list.lookahead1.leaf_counts.extend_from_slice(&current_list.lookahead0.leaf_counts);
//     let last_index = current_list.lookahead1.leaf_counts.len() - 1;
//     current_list.lookahead1.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.lookahead1.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.lookahead1.weight = weight_sum;
//         current_list.lookahead1.leaf_counts.clear();
//
//         current_list.lookahead1.leaf_counts.extend_from_slice(previous_list_leaf_counts);
//         current_list.lookahead1.leaf_counts.push(*current_list.lookahead0.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;
//     let num_symbols = leaves.len();
//
//     if current_list_index == 0 && next_leaf_index == num_symbols {
//         // We've added all the leaves to the lowest list, so we're done here
//         return;
//     }
//
//     mem::swap(&mut lists[current_list_index].lookahead0, &mut lists[current_list_index].lookahead1);
//
//     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.lookahead0.weight + previous_list.lookahead1.weight
//         };
//
//         if next_leaf_index < num_symbols && 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 max_bits_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 max_bits_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>Refactored and the tests are all passing!!!!<commit_after>use std::cell::Cell;
use std::cmp::Ordering;

use typed_arena::Arena;

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

struct Thing<'a> {
    node_arena: &'a Arena<Node<'a>>,
    leaves: Vec<Leaf>,
    lists: Vec<List<'a>>,
}

#[derive(Debug)]
struct Node<'a> {
    weight: usize,
    count: usize,
    tail: Cell<Option<&'a Node<'a>>>,
}

#[derive(Debug)]
struct Leaf {
    weight: usize,
    count: 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, Clone)]
struct List<'a> {
    lookahead0: &'a Node<'a>,
    lookahead1: &'a Node<'a>,
}

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

    // Count used symbols and place them in the leaves.
    let mut leaves: Vec<_> = frequencies.iter()
        .enumerate()
        .filter(|&(_, &freq)| freq != 0)
        .map(|(i, &freq)| Leaf { weight: freq, count: i })
        .collect();

    let num_symbols = leaves.len();

    // Short circuit some special cases

    // TODO:
    // if ((1 << maxbits) < numsymbols) {
    //   free(leaves);
    //   return 1;  /* Error, too few maxbits to represent symbols. */
    // }

    if num_symbols == 0 {
        // There are no non-zero frequencies.
        return vec![0; num_freqs];
    }
    if num_symbols == 1 {
        let mut bit_lengths = vec![0; num_freqs];
        bit_lengths[leaves[0].count] = 1;
        return bit_lengths;
    }
    if num_symbols == 2 {
        let mut bit_lengths = vec![0; num_freqs];
        bit_lengths[leaves[0].count] = 1;
        bit_lengths[leaves[1].count] = 1;
        return bit_lengths;
    }

    // Sort the leaves from least frequent to most frequent.
    leaves.sort();

    let max_bits = if num_symbols - 1 < max_bits {
        num_symbols - 1
    } else {
        max_bits
    };

    let arena_capacity = max_bits * 2 * num_symbols;
    let node_arena: Arena<Node> = Arena::with_capacity(arena_capacity);

    let node0 = node_arena.alloc(Node {
        weight: leaves[0].weight,
        count: 1,
        tail: Cell::new(None),
    });

    let node1 = node_arena.alloc(Node {
        weight: leaves[1].weight,
        count: 2,
        tail: Cell::new(None),
    });

    let lists: Vec<List> = vec![
        List {
            lookahead0: node0,
            lookahead1: node1,
        };
        max_bits
    ];

    let mut thing = Thing {
        node_arena: &node_arena,
        leaves,
        lists,
    };

    // In the last list, 2 * num_symbols - 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 = 2 * num_symbols - 4;
    for _ in 0..num_boundary_pm_runs - 1 {
        thing.boundary_pm(max_bits - 1);
    }

    thing.boundary_pm_final(max_bits - 1);

    thing.extract_bit_lengths(max_bits, num_freqs)
}

impl<'a> Thing<'a> {
    fn boundary_pm(&mut self, index: usize) {
        let num_symbols = self.leaves.len();

        let last_count = self.lists[index].lookahead1.count; // Count of last chain of list.

        if index == 0 && last_count >= num_symbols {
            return
        }

        self.lists[index].lookahead0 = self.lists[index].lookahead1;

        if index == 0 {
            // New leaf node in list 0.
            let new_chain = self.node_arena.alloc(Node {
               weight: self.leaves[last_count].weight,
               count: last_count + 1,
               tail: self.lists[index].lookahead0.tail.clone(),
            });
            self.lists[index].lookahead1 = new_chain;
        } else {
            let weight_sum = {
                let previous_list = &self.lists[index - 1];
                previous_list.lookahead0.weight + previous_list.lookahead1.weight
            };

            if last_count < num_symbols && weight_sum > self.leaves[last_count].weight {
                // New leaf inserted in list, so count is incremented.
                let new_chain = self.node_arena.alloc(Node {
                   weight: self.leaves[last_count].weight,
                   count: last_count + 1,
                   tail: self.lists[index].lookahead0.tail.clone(),
                });
                self.lists[index].lookahead1 = new_chain;
            } else {
                let new_chain = self.node_arena.alloc(Node {
                   weight: weight_sum,
                   count: last_count,
                   tail: Cell::new(Some(self.lists[index - 1].lookahead1)),
                });
                self.lists[index].lookahead1 = new_chain;

                // Two lookahead chains of previous list used up, create new ones.
                self.boundary_pm(index - 1);
                self.boundary_pm(index - 1);
            }
        }
    }

    fn boundary_pm_final(&mut self, index: usize) {
        let num_symbols = self.leaves.len();

        // Count of last chain of list.
        let last_count = self.lists[index].lookahead1.count;

        let weight_sum = {
            let previous_list = &self.lists[index - 1];
            previous_list.lookahead0.weight + previous_list.lookahead1.weight
        };

        if last_count < num_symbols && weight_sum > self.leaves[last_count].weight {
            let new_chain = self.node_arena.alloc(Node {
               weight: 0,
               count: last_count + 1,
               tail: self.lists[index].lookahead1.tail.clone(),
            });
            self.lists[index].lookahead1 = new_chain;
        } else {
            self.lists[index].lookahead1.tail.set(Some(self.lists[index - 1].lookahead1));
        }
    }

    fn extract_bit_lengths(&self, max_bits: usize, num_freqs: usize) -> Vec<u32> {
        let mut counts = [0; 16];
        let mut end = 16;
        let mut ptr = 15;
        let mut value = 1;

        let mut node = self.lists[max_bits - 1].lookahead1;

        end -= 1;
        counts[end] = node.count;

        while let Some(tail) = node.tail.get() {
            end -= 1;
            counts[end] = tail.count;
            node = tail;
        }

        let mut val = counts[15];

        let mut bit_lengths = vec![0; num_freqs];

        while ptr >= end {
            while val > counts[ptr - 1] {
                bit_lengths[self.leaves[val - 1].count] = value;
                val -= 1;
            }
            ptr -= 1;
            value += 1;
        }

        bit_lengths
    }
}

// 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.lookahead1.weight = leaves[current_list.next_leaf_index].weight;
//     current_list.lookahead1.leaf_counts.clear();
//     current_list.lookahead1.leaf_counts.extend_from_slice(&current_list.lookahead0.leaf_counts);
//     let last_index = current_list.lookahead1.leaf_counts.len() - 1;
//     current_list.lookahead1.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.lookahead1.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.lookahead1.weight = weight_sum;
//         current_list.lookahead1.leaf_counts.clear();
//
//         current_list.lookahead1.leaf_counts.extend_from_slice(previous_list_leaf_counts);
//         current_list.lookahead1.leaf_counts.push(*current_list.lookahead0.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;
//     let num_symbols = leaves.len();
//
//     if current_list_index == 0 && next_leaf_index == num_symbols {
//         // We've added all the leaves to the lowest list, so we're done here
//         return;
//     }
//
//     mem::swap(&mut lists[current_list_index].lookahead0, &mut lists[current_list_index].lookahead1);
//
//     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.lookahead0.weight + previous_list.lookahead1.weight
//         };
//
//         if next_leaf_index < num_symbols && 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 max_bits_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 max_bits_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>use std::env;
use std::path::PathBuf;
use std::fs::PathExt;
use reporter::report_path;

pub struct Paths {
   pub version: String,

   pub archive: String,

   pub http_location: String,

   pub target_path: PathBuf,

   pub archive_path: PathBuf,

   pub extract_path: PathBuf,

   pub configure_path: PathBuf,

   pub ngxconf_prefix_path: PathBuf,

   pub ngxconf_path: PathBuf,

   pub ngxconf_source_path: PathBuf,

   pub module_dir_path: PathBuf,
}

impl Paths {

   pub fn new(version: String) -> Self {
      let extract_dir = format!("nginx-{}", version);
      let archive = format!("{}.tar.gz", extract_dir);

      let http_location = format!("http://nginx.org/download/{}", archive);

      let exe_path = Paths::get_exe_path();

      let target_slice = exe_path.parent().unwrap();
      let root_slice = target_slice.parent().unwrap();

      let root_path = PathBuf::new(root_slice);
      report_path("root", &root_path);

      let target_path = PathBuf::new(target_slice);
      report_path("target", &target_path);

      let archive_path = target_path.join(&archive);
      report_path("archive", &archive_path);

      let extract_path = target_path.join(&extract_dir);
      report_path("extract", &extract_path);

      let configure_path = extract_path.join("configure");
      report_path("configure", &configure_path);

      let ngxconf_prefix_path = target_path.join("conf");
      report_path("ngxconf_prefix", &ngxconf_prefix_path);

      let ngxconf_path = ngxconf_prefix_path.join("nginx.conf");
      report_path("ngxconf", &ngxconf_path);

      let ngxconf_source_path = root_path.join("conf").join("nginx.conf");
      report_path("ngxconf_source", &ngxconf_source_path);

      let module_dir_path = root_path.join("module");
      report_path("module_dir", &module_dir_path);

      Paths {
         version: version,
         archive: archive,
         http_location: http_location,
         target_path: target_path,
         archive_path: archive_path,
         extract_path: extract_path,
         configure_path: configure_path,
         ngxconf_prefix_path: ngxconf_prefix_path,
         ngxconf_path: ngxconf_path,
         ngxconf_source_path: ngxconf_source_path,
         module_dir_path: module_dir_path,
      }
   }

   pub fn already_downloaded(&self) -> bool {
      self.archive_path.exists() && self.archive_path.is_file()
   }

   pub fn already_extracted(&self) -> bool {
      self.extract_path.exists() && self.extract_path.is_dir()
   }

   fn get_exe_path() -> PathBuf {
      let exe_path = env::current_exe().unwrap_or_else(|_| {
         panic!("Cannot retrieve current executable location.")
      });

      exe_path
   }
}
<commit_msg>Fixing root path initialization for the project.<commit_after>use std::env;
use std::path::PathBuf;
use std::fs::PathExt;
use reporter::report_path;

pub struct Paths {
   pub version: String,

   pub archive: String,

   pub http_location: String,

   pub target_path: PathBuf,

   pub archive_path: PathBuf,

   pub extract_path: PathBuf,

   pub configure_path: PathBuf,

   pub ngxconf_prefix_path: PathBuf,

   pub ngxconf_path: PathBuf,

   pub ngxconf_source_path: PathBuf,

   pub module_dir_path: PathBuf,
}

impl Paths {

   pub fn new(version: String) -> Self {
      let extract_dir = format!("nginx-{}", version);
      let archive = format!("{}.tar.gz", extract_dir);

      let http_location = format!("http://nginx.org/download/{}", archive);

      let exe_path = Paths::get_exe_path();

      let target_slice = exe_path.parent().unwrap();

      let root_path = Paths::get_root_path();
      report_path("root", &root_path);

      let target_path = PathBuf::new(target_slice);
      report_path("target", &target_path);

      let archive_path = target_path.join(&archive);
      report_path("archive", &archive_path);

      let extract_path = target_path.join(&extract_dir);
      report_path("extract", &extract_path);

      let configure_path = extract_path.join("configure");
      report_path("configure", &configure_path);

      let ngxconf_prefix_path = target_path.join("conf");
      report_path("ngxconf_prefix", &ngxconf_prefix_path);

      let ngxconf_path = ngxconf_prefix_path.join("nginx.conf");
      report_path("ngxconf", &ngxconf_path);

      let ngxconf_source_path = root_path.join("conf").join("nginx.conf");
      report_path("ngxconf_source", &ngxconf_source_path);

      let module_dir_path = root_path.join("module");
      report_path("module_dir", &module_dir_path);

      Paths {
         version: version,
         archive: archive,
         http_location: http_location,
         target_path: target_path,
         archive_path: archive_path,
         extract_path: extract_path,
         configure_path: configure_path,
         ngxconf_prefix_path: ngxconf_prefix_path,
         ngxconf_path: ngxconf_path,
         ngxconf_source_path: ngxconf_source_path,
         module_dir_path: module_dir_path,
      }
   }

   pub fn already_downloaded(&self) -> bool {
      self.archive_path.exists() && self.archive_path.is_file()
   }

   pub fn already_extracted(&self) -> bool {
      self.extract_path.exists() && self.extract_path.is_dir()
   }

   fn get_exe_path() -> PathBuf {
      let exe_path = env::current_exe().unwrap_or_else(|_| {
         panic!("Cannot retrieve current executable location.")
      });

      exe_path
   }

   fn get_root_path() -> PathBuf {
      let root_path = env::var("CARGO_MANIFEST_DIR").unwrap_or_else(|_| {
         panic!("Cannot retrieve root dir – CARGO_MANIFEST_DIR.")
      });

      PathBuf::new(root_path.as_slice())
   }
}
<|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::HasPseudoheader;
use packet::checksum::rfc1071_checksum;
use pnet_macros::types::*;

/// Represents a TCP Packet
#[packet]
pub struct Tcp {
    source: u16be,
    destination: u16be,
    sequence: u32be,
    acknowledgement: u32be,
    data_offset: u4,
    reserved: u4,
    control_bits: u8,
    window: u16be,
    checksum: u16be,
    urgent_pointer: u16be,
    #[length_fn = "tcp_options_length"]
    options: Vec<TcpOptions>,
    #[length_fn = "tcp_padding_length"]
    padding: Vec<TcpPadding>,
    #[payload]
    payload: Vec<u8>
}

fn tcp_options_length<'a>(tcp: &TcpPacket<'a>) -> usize {
    /* The data offset field specifies the total size of the TCP header
       in 32-bit words. The minimum size of a TCP header is 20 bytes and thus
       TCP headers must have data offset set to 5 or more.
     */
    let size = tcp.get_data_offset() as usize;
    return size - 5
}

/// Represents the TCP Option fields
#[packet]
pub struct TcpOptions {
    kind: u8,
    #[payload]
    data: Vec<u8>
}

fn tcp_padding_length<'a>(tcp: &TcpPacket<'a>) -> usize {
    /* The TCP header padding is used to ensure that the entire header
       ends on a 32 bit boundary.
     */
    return tcp.get_data_offset() as usize % 4;
}

/// Represents the TCP header padding
#[packet]
pub struct TcpPadding {
    #[payload]
    data: Vec<u8>
}

/// Calculates the checksum of a TCP packet
pub fn checksum<'a, T: HasPseudoheader>(packet: &mut MutableTcpPacket<'a>, encapsulating_packet: T) -> u16be {
    let mut sum = encapsulating_packet.pseudoheader_checksum();
    let length = packet.packet().len() as u32;
    sum = sum + length & 0xffff;
    sum = sum + length >> 16;
    packet.set_checksum(0);
    return rfc1071_checksum(packet.packet(), sum);
}

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

    const TCP_MIN_HEADER_LEN: usize = 20;
    const TCP_OPTIONS_LEN: usize = 12;
    const PAYLOAD_LEN: usize = 5;

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

        const IPV4_HEADER_LEN: usize = 20;

        let mut packet = [0u8; IPV4_HEADER_LEN + TCP_MIN_HEADER_LEN + TCP_OPTIONS_LEN + PAYLOAD_LEN];
        let ipv4_source = Ipv4Addr::new(127, 0, 0, 1);
        let ipv4_destination = Ipv4Addr::new(127, 0, 0, 1);
        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);
        }

        {
            generate_simple_tcp_header(&mut packet[IPV4_HEADER_LEN..]);
        }

        // Set payload data
        packet[IPV4_HEADER_LEN + TCP_MIN_HEADER_LEN + TCP_OPTIONS_LEN + 0] = 'm' as u8;
        packet[IPV4_HEADER_LEN + TCP_MIN_HEADER_LEN + TCP_OPTIONS_LEN + 1] = 'e' as u8;
        packet[IPV4_HEADER_LEN + TCP_MIN_HEADER_LEN + TCP_OPTIONS_LEN + 2] = 'o' as u8;
        packet[IPV4_HEADER_LEN + TCP_MIN_HEADER_LEN + TCP_OPTIONS_LEN + 3] = 'w' as u8;
        packet[IPV4_HEADER_LEN + TCP_MIN_HEADER_LEN + TCP_OPTIONS_LEN + 4] = '\n' as u8;

        let ref_tcp_packet = [0xe0, 0x0f, // source port
                              0x25, 0xc2, // dest port
                              0xdf, 0x06, // sequence
                              0xe6, 0xe6,
                              0xc9, 0x2d, // acknowledgement
                              0x98, 0x71,
                              0x80,       // header length + reserved
                              0x18,       // control bits
                              0x02, 0xab, // window
                              0xfe, 0x2d, // checksum
                              0x00, 0x00, // urgent pointer
                              0x01, 0x01, // tcp option no-op
                              0x08, 0x0a, // tcp option timestamp, options length == 10 bytes
                              0x1d, 0xfc, // 4-byte send timestamp
                              0xcb, 0x76,
                              0x1d, 0xfc, // 4-byte latest replied timestamp
                              0xbe, 0x62,
                              0x6d, 0x65, // payload
                              0x6f, 0x77, 0x0a];
        assert_eq!(&ref_tcp_packet[..], &packet[IPV4_HEADER_LEN..]);

        //tcp/ipv4 == "45, 00 00 39 58 89 40 00 40 06 e4 33 7f 00 00 01 7f 00 00 01 e0 0f 25 c2 df 06 e6 e6 c9 2d 98 71 80 18 02 ab fe 2d 00 00 01 01 08 0a 1d fc cb 76 1d fc be 62 6d 65 6f 77 0a";

    }

    fn generate_simple_tcp_header<'p>(packet: &'p mut [u8]) {
        let mut tcp_header = MutableTcpPacket::new(&mut packet[..]).unwrap();
        tcp_header.set_source(57359);
        assert_eq!(tcp_header.get_source(), 57359);

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

        tcp_header.set_sequence(3741771494);
        assert_eq!(tcp_header.get_sequence(), 3741771494);

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

        tcp_header.set_data_offset(0x8);
        // XXX assert_eq!(tcp_header.get_data_offset(), 0x8);

        tcp_header.set_reserved(0x0);
        assert_eq!(tcp_header.get_reserved(), 0x0);

        tcp_header.set_control_bits(0x18);
        assert_eq!(tcp_header.get_control_bits(), 0x18);

        tcp_header.set_window(0x02ab);
        assert_eq!(tcp_header.get_window(), 0x02ab);

        tcp_header.set_checksum(0xfe2d);
        assert_eq!(tcp_header.get_checksum(), 0xfe2d);

        tcp_header.set_urgent_pointer(0x0000);
        assert_eq!(tcp_header.get_urgent_pointer(), 0x0000);

        let mut opts: Vec<TcpOptions> = Vec::new();
        let tcp_option = TcpOptions{
            kind: 0x1,
            data: vec![0x01,0x08,0x0a,0x1d,0xfc,0xcb,0x76,0x1d,0xfc,0xbe,0x62],
        };
        opts.push(tcp_option);
        tcp_header.set_options(opts);
    }
}
<commit_msg>Fix basic tcp header unit test<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::HasPseudoheader;
use packet::checksum::rfc1071_checksum;
use pnet_macros::types::*;

/// Represents a TCP Packet
#[packet]
pub struct Tcp {
    source: u16be,
    destination: u16be,
    sequence: u32be,
    acknowledgement: u32be,
    data_offset_and_reserved: u8,
    control_bits: u8,
    window: u16be,
    checksum: u16be,
    urgent_pointer: u16be,
    #[length_fn = "tcp_options_length"]
    options: Vec<TcpOptions>,
    #[length_fn = "tcp_padding_length"]
    padding: Vec<TcpPadding>,
    #[payload]
    payload: Vec<u8>
}

fn tcp_options_length<'a>(tcp: &TcpPacket<'a>) -> usize {
    /* The data offset field specifies the total size of the TCP header
       in 32-bit words. The minimum size of a TCP header is 20 bytes and thus
       TCP headers must have data offset set to 5 or more.
     */
    let size = tcp.get_data_offset_and_reserved() as usize;
    return (size / 4) - 5 // XXX the "reserved" 4-bit word is zeros and is ignored when we divide by 4
}

/// Represents the TCP Option fields
#[packet]
pub struct TcpOptions {
    kind: u8,
    #[payload]
    data: Vec<u8>
}

fn tcp_padding_length<'a>(tcp: &TcpPacket<'a>) -> usize {
    /* The TCP header padding is used to ensure that the entire header
       ends on a 32 bit boundary.
     */
    return tcp.get_data_offset_and_reserved() as usize % 4;
}

/// Represents the TCP header padding
#[packet]
pub struct TcpPadding {
    #[payload]
    data: Vec<u8>
}

/// Calculates the checksum of a TCP packet
pub fn checksum<'a, T: HasPseudoheader>(packet: &mut MutableTcpPacket<'a>, encapsulating_packet: T) -> u16be {
    let mut sum = encapsulating_packet.pseudoheader_checksum();
    let length = packet.packet().len() as u32;
    sum = sum + length & 0xffff;
    sum = sum + length >> 16;
    packet.set_checksum(0);
    return rfc1071_checksum(packet.packet(), sum);
}

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

    const TCP_MIN_HEADER_LEN: usize = 20;
    const TCP_OPTIONS_LEN: usize = 12;
    const PAYLOAD_LEN: usize = 5;

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

        const IPV4_HEADER_LEN: usize = 20;

        let mut packet = [0u8; IPV4_HEADER_LEN + TCP_MIN_HEADER_LEN + TCP_OPTIONS_LEN + PAYLOAD_LEN];
        let ipv4_source = Ipv4Addr::new(127, 0, 0, 1);
        let ipv4_destination = Ipv4Addr::new(127, 0, 0, 1);
        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);
        }

        {
            generate_simple_tcp_header(&mut packet[IPV4_HEADER_LEN..]);
        }

        // Set payload data
        packet[IPV4_HEADER_LEN + TCP_MIN_HEADER_LEN + TCP_OPTIONS_LEN + 0] = 'm' as u8;
        packet[IPV4_HEADER_LEN + TCP_MIN_HEADER_LEN + TCP_OPTIONS_LEN + 1] = 'e' as u8;
        packet[IPV4_HEADER_LEN + TCP_MIN_HEADER_LEN + TCP_OPTIONS_LEN + 2] = 'o' as u8;
        packet[IPV4_HEADER_LEN + TCP_MIN_HEADER_LEN + TCP_OPTIONS_LEN + 3] = 'w' as u8;
        packet[IPV4_HEADER_LEN + TCP_MIN_HEADER_LEN + TCP_OPTIONS_LEN + 4] = '\n' as u8;

        let ref_tcp_packet = [0xe0, 0x0f, // source port
                              0x25, 0xc2, // dest port
                              0xdf, 0x06, // sequence
                              0xe6, 0xe6,
                              0xc9, 0x2d, // acknowledgement
                              0x98, 0x71,
                              0x80,       // header length + reserved
                              0x18,       // control bits
                              0x02, 0xab, // window
                              0xfe, 0x2d, // checksum
                              0x00, 0x00, // urgent pointer
                              0x01, 0x01, // tcp option no-op
                              0x08, 0x0a, // tcp option timestamp, options length == 10 bytes
                              0x1d, 0xfc, // 4-byte send timestamp
                              0xcb, 0x76,
                              0x1d, 0xfc, // 4-byte latest replied timestamp
                              0xbe, 0x62,
                              0x6d, 0x65, // payload
                              0x6f, 0x77, 0x0a];
        assert_eq!(&ref_tcp_packet[..], &packet[IPV4_HEADER_LEN..]);

        //tcp/ipv4 == "45, 00 00 39 58 89 40 00 40 06 e4 33 7f 00 00 01 7f 00 00 01 e0 0f 25 c2 df 06 e6 e6 c9 2d 98 71 80 18 02 ab fe 2d 00 00 01 01 08 0a 1d fc cb 76 1d fc be 62 6d 65 6f 77 0a";

    }

    fn generate_simple_tcp_header<'p>(packet: &'p mut [u8]) {
        let mut tcp_header = MutableTcpPacket::new(&mut packet[..]).unwrap();
        tcp_header.set_source(57359);
        assert_eq!(tcp_header.get_source(), 57359);

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

        tcp_header.set_sequence(3741771494);
        assert_eq!(tcp_header.get_sequence(), 3741771494);

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

        tcp_header.set_data_offset_and_reserved(0x80);
        assert_eq!(tcp_header.get_data_offset_and_reserved(), 0x80);

        tcp_header.set_control_bits(0x18);
        assert_eq!(tcp_header.get_control_bits(), 0x18);

        tcp_header.set_window(0x02ab);
        assert_eq!(tcp_header.get_window(), 0x02ab);

        tcp_header.set_checksum(0xfe2d);
        assert_eq!(tcp_header.get_checksum(), 0xfe2d);

        tcp_header.set_urgent_pointer(0x0000);
        assert_eq!(tcp_header.get_urgent_pointer(), 0x0000);

        let mut opts: Vec<TcpOptions> = Vec::new();
        let tcp_option = TcpOptions{
            kind: 0x1,
            data: vec![0x01,0x08,0x0a,0x1d,0xfc,0xcb,0x76,0x1d,0xfc,0xbe,0x62],
        };
        opts.push(tcp_option);
        tcp_header.set_options(opts);
    }
}
<|endoftext|>


<commit_before>//! This crate defines a
//! [Wadler-style](http://homepages.inf.ed.ac.uk/wadler/papers/prettier/prettier.pdf)
//! pretty-printing API.
//!
//! See `Doc` and
extern crate typed_arena;

use doc::Doc::{Append, Group, Nest, Newline, Nil, Space, Text};
use std::borrow::Cow;
use std::fmt;
use std::ops::Deref;

mod doc;

#[derive(Clone, Eq, Ord, PartialEq, PartialOrd)]
pub struct BoxDoc<'a>(Box<doc::Doc<'a, BoxDoc<'a>>>);

impl<'a> fmt::Debug for BoxDoc<'a> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.0.fmt(f)
    }
}

impl<'a> BoxDoc<'a> {
    fn new(doc: doc::Doc<'a, BoxDoc<'a>>) -> BoxDoc<'a> {
        BoxDoc(Box::new(doc))
    }
}

impl<'a> Deref for BoxDoc<'a> {
    type Target = doc::Doc<'a, BoxDoc<'a>>;

    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

/// The `DocBuilder` type allows for convenient appending of documents even for arena allocated
/// documents by storing the arena inline.
#[derive(Eq, Ord, PartialEq, PartialOrd)]
pub struct DocBuilder<'a, A: ?Sized>(pub &'a A, pub doc::Doc<'a, A::Doc>)
    where A: DocAllocator<'a> + 'a;

impl<'a, A: DocAllocator<'a> + 'a> Clone for DocBuilder<'a, A> {
    fn clone(&self) -> Self {
        DocBuilder(self.0, self.1.clone())
    }
}

impl<'a, A: ?Sized> Into<doc::Doc<'a, A::Doc>> for DocBuilder<'a, A>
    where A: DocAllocator<'a>
{
    fn into(self) -> doc::Doc<'a, A::Doc> {
        self.1
    }
}

/// The `DocAllocator` trait abstracts over a type which can allocate (pointers to) `Doc`.
pub trait DocAllocator<'a> {
    type Doc: Deref<Target = doc::Doc<'a, Self::Doc>> + Clone;
    fn alloc(&'a self, doc::Doc<'a, Self::Doc>) -> Self::Doc;

    #[inline]
    fn nil(&'a self) -> DocBuilder<'a, Self> {
        DocBuilder(self, Nil)
    }

    #[inline]
    fn newline(&'a self) -> DocBuilder<'a, Self> {
        DocBuilder(self, Newline)
    }

    #[inline]
    fn space(&'a self) -> DocBuilder<'a, Self> {
        DocBuilder(self, Space)
    }

    #[inline]
    fn as_string<T: ToString>(&'a self, t: T) -> DocBuilder<'a, Self> {
        self.text(t.to_string())
    }

    #[inline]
    fn text<T: Into<Cow<'a, str>>>(&'a self, data: T) -> DocBuilder<'a, Self> {
        DocBuilder(self, Text(data.into()))
    }

    #[inline]
    fn concat<I>(&'a self, docs: I) -> DocBuilder<'a, Self>
        where I: IntoIterator,
              I::Item: Into<doc::Doc<'a, Self::Doc>>
    {
        docs.into_iter().fold(self.nil(), |a, b| a.append(b))
    }
}

impl<'a, 's, A: ?Sized> DocBuilder<'a, A>
    where A: DocAllocator<'a>
{
    #[inline]
    pub fn append<B>(self, that: B) -> DocBuilder<'a, A>
        where B: Into<doc::Doc<'a, A::Doc>>
    {
        let DocBuilder(allocator, this) = self;
        let that = that.into();
        let doc = match this {
            Nil => that,
            _ => {
                match that {
                    Nil => this,
                    _ => Append(allocator.alloc(this), allocator.alloc(that)),
                }
            }
        };
        DocBuilder(allocator, doc)
    }

    #[inline]
    pub fn group(self) -> DocBuilder<'a, A> {
        let DocBuilder(allocator, this) = self;
        DocBuilder(allocator, Group(allocator.alloc(this)))
    }

    #[inline]
    pub fn nest(self, offset: usize) -> DocBuilder<'a, A> {
        let DocBuilder(allocator, this) = self;
        DocBuilder(allocator, Nest(offset, allocator.alloc(this)))
    }
}

/// Newtype wrapper for `&doc::Doc`
#[derive(Clone, Eq, Ord, PartialEq, PartialOrd)]
pub struct RefDoc<'a>(&'a doc::Doc<'a, RefDoc<'a>>);

impl<'a> fmt::Debug for RefDoc<'a> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.0.fmt(f)
    }
}

impl<'a> Deref for RefDoc<'a> {
    type Target = doc::Doc<'a, RefDoc<'a>>;

    fn deref(&self) -> &doc::Doc<'a, RefDoc<'a>> {
        &self.0
    }
}

/// An arena which can be used to allocate `Doc` values.
pub type Arena<'a> = typed_arena::Arena<doc::Doc<'a, RefDoc<'a>>>;

impl<'a> DocAllocator<'a> for Arena<'a> {
    type Doc = RefDoc<'a>;

    fn alloc(&'a self, doc: doc::Doc<'a, Self::Doc>) -> Self::Doc {
        RefDoc(Arena::alloc(self, doc))
    }
}

pub struct BoxAllocator;

static BOX_ALLOCATOR: BoxAllocator = BoxAllocator;

impl<'a> DocAllocator<'a> for BoxAllocator {
    type Doc = BoxDoc<'a>;

    fn alloc(&'a self, doc: doc::Doc<'a, Self::Doc>) -> Self::Doc {
        BoxDoc::new(doc)
    }
}

pub use doc::Doc;

impl<'a, B> Doc<'a, B> {
    #[inline]
    pub fn nil() -> Doc<'a, B> {
        Nil
    }

    #[inline]
    pub fn as_string<T: ToString>(t: T) -> Doc<'a, B> {
        Doc::text(t.to_string())
    }

    #[inline]
    pub fn newline() -> Doc<'a, B> {
        Newline
    }

    #[inline]
    pub fn text<T: Into<Cow<'a, str>>>(data: T) -> Doc<'a, B> {
        Text(data.into())
    }

    #[inline]
    pub fn space() -> Doc<'a, B> {
        Space
    }
}

impl<'a> Doc<'a, BoxDoc<'a>> {
    #[inline]
    pub fn append(self, that: Doc<'a, BoxDoc<'a>>) -> Doc<'a, BoxDoc<'a>> {
        DocBuilder(&BOX_ALLOCATOR, self).append(that).into()
    }

    #[inline]
    pub fn concat<I>(&'a self, docs: I) -> Doc<'a, BoxDoc<'a>>
        where I: IntoIterator<Item = Doc<'a, BoxDoc<'a>>>
    {
        docs.into_iter().fold(Doc::nil(), |a, b| a.append(b))
    }

    #[inline]
    pub fn group(self) -> Doc<'a, BoxDoc<'a>> {
        DocBuilder(&BOX_ALLOCATOR, self).group().into()
    }

    #[inline]
    pub fn nest(self, offset: usize) -> Doc<'a, BoxDoc<'a>> {
        DocBuilder(&BOX_ALLOCATOR, self).nest(offset).into()
    }
}

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

    macro_rules! test {
        ($size: expr, $actual: expr, $expected: expr) => {
            let mut vec = Vec::new();
            $actual.render($size, &mut vec).unwrap();
            assert_eq!(from_utf8(&vec).unwrap(), $expected);
        };
        ($actual: expr, $expected: expr) => {
            test!(70, $actual, $expected)
        }
    }

    #[test]
    fn box_doc_inference() {
        let doc = Doc::group(Doc::text("test").append(Doc::space()).append(Doc::text("test")));
        test!(doc, "test test");
    }

    #[test]
    fn forced_newline() {
        let doc = Doc::group(Doc::text("test").append(Doc::newline()).append(Doc::text("test")));
        test!(doc, "test\ntest");
    }

    #[test]
    fn block() {
        let doc = Doc::group(Doc::text("{")
            .append(Doc::space()
                .append(Doc::text("test"))
                .append(Doc::space())
                .append(Doc::text("test"))
                .nest(2))
            .append(Doc::space())
            .append(Doc::text("}")));
        test!(5, doc, "{\n  test\n  test\n}");
    }
}
<commit_msg>refactor: Add a debug assertion that no newlines are in text documents<commit_after>//! This crate defines a
//! [Wadler-style](http://homepages.inf.ed.ac.uk/wadler/papers/prettier/prettier.pdf)
//! pretty-printing API.
//!
//! See `Doc` and
extern crate typed_arena;

use doc::Doc::{Append, Group, Nest, Newline, Nil, Space, Text};
use std::borrow::Cow;
use std::fmt;
use std::ops::Deref;

mod doc;

#[derive(Clone, Eq, Ord, PartialEq, PartialOrd)]
pub struct BoxDoc<'a>(Box<doc::Doc<'a, BoxDoc<'a>>>);

impl<'a> fmt::Debug for BoxDoc<'a> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.0.fmt(f)
    }
}

impl<'a> BoxDoc<'a> {
    fn new(doc: doc::Doc<'a, BoxDoc<'a>>) -> BoxDoc<'a> {
        BoxDoc(Box::new(doc))
    }
}

impl<'a> Deref for BoxDoc<'a> {
    type Target = doc::Doc<'a, BoxDoc<'a>>;

    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

/// The `DocBuilder` type allows for convenient appending of documents even for arena allocated
/// documents by storing the arena inline.
#[derive(Eq, Ord, PartialEq, PartialOrd)]
pub struct DocBuilder<'a, A: ?Sized>(pub &'a A, pub doc::Doc<'a, A::Doc>)
    where A: DocAllocator<'a> + 'a;

impl<'a, A: DocAllocator<'a> + 'a> Clone for DocBuilder<'a, A> {
    fn clone(&self) -> Self {
        DocBuilder(self.0, self.1.clone())
    }
}

impl<'a, A: ?Sized> Into<doc::Doc<'a, A::Doc>> for DocBuilder<'a, A>
    where A: DocAllocator<'a>
{
    fn into(self) -> doc::Doc<'a, A::Doc> {
        self.1
    }
}

/// The `DocAllocator` trait abstracts over a type which can allocate (pointers to) `Doc`.
pub trait DocAllocator<'a> {
    type Doc: Deref<Target = doc::Doc<'a, Self::Doc>> + Clone;
    fn alloc(&'a self, doc::Doc<'a, Self::Doc>) -> Self::Doc;

    #[inline]
    fn nil(&'a self) -> DocBuilder<'a, Self> {
        DocBuilder(self, Nil)
    }

    #[inline]
    fn newline(&'a self) -> DocBuilder<'a, Self> {
        DocBuilder(self, Newline)
    }

    #[inline]
    fn space(&'a self) -> DocBuilder<'a, Self> {
        DocBuilder(self, Space)
    }

    #[inline]
    fn as_string<T: ToString>(&'a self, t: T) -> DocBuilder<'a, Self> {
        self.text(t.to_string())
    }

    #[inline]
    fn text<T: Into<Cow<'a, str>>>(&'a self, data: T) -> DocBuilder<'a, Self> {
        let text = data.into();
        debug_assert!(!text.contains(|c: char| c == '\n' || c == '\r'));
        DocBuilder(self, Text(text))
    }

    #[inline]
    fn concat<I>(&'a self, docs: I) -> DocBuilder<'a, Self>
        where I: IntoIterator,
              I::Item: Into<doc::Doc<'a, Self::Doc>>
    {
        docs.into_iter().fold(self.nil(), |a, b| a.append(b))
    }
}

impl<'a, 's, A: ?Sized> DocBuilder<'a, A>
    where A: DocAllocator<'a>
{
    #[inline]
    pub fn append<B>(self, that: B) -> DocBuilder<'a, A>
        where B: Into<doc::Doc<'a, A::Doc>>
    {
        let DocBuilder(allocator, this) = self;
        let that = that.into();
        let doc = match this {
            Nil => that,
            _ => {
                match that {
                    Nil => this,
                    _ => Append(allocator.alloc(this), allocator.alloc(that)),
                }
            }
        };
        DocBuilder(allocator, doc)
    }

    #[inline]
    pub fn group(self) -> DocBuilder<'a, A> {
        let DocBuilder(allocator, this) = self;
        DocBuilder(allocator, Group(allocator.alloc(this)))
    }

    #[inline]
    pub fn nest(self, offset: usize) -> DocBuilder<'a, A> {
        let DocBuilder(allocator, this) = self;
        DocBuilder(allocator, Nest(offset, allocator.alloc(this)))
    }
}

/// Newtype wrapper for `&doc::Doc`
#[derive(Clone, Eq, Ord, PartialEq, PartialOrd)]
pub struct RefDoc<'a>(&'a doc::Doc<'a, RefDoc<'a>>);

impl<'a> fmt::Debug for RefDoc<'a> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.0.fmt(f)
    }
}

impl<'a> Deref for RefDoc<'a> {
    type Target = doc::Doc<'a, RefDoc<'a>>;

    fn deref(&self) -> &doc::Doc<'a, RefDoc<'a>> {
        &self.0
    }
}

/// An arena which can be used to allocate `Doc` values.
pub type Arena<'a> = typed_arena::Arena<doc::Doc<'a, RefDoc<'a>>>;

impl<'a> DocAllocator<'a> for Arena<'a> {
    type Doc = RefDoc<'a>;

    fn alloc(&'a self, doc: doc::Doc<'a, Self::Doc>) -> Self::Doc {
        RefDoc(Arena::alloc(self, doc))
    }
}

pub struct BoxAllocator;

static BOX_ALLOCATOR: BoxAllocator = BoxAllocator;

impl<'a> DocAllocator<'a> for BoxAllocator {
    type Doc = BoxDoc<'a>;

    fn alloc(&'a self, doc: doc::Doc<'a, Self::Doc>) -> Self::Doc {
        BoxDoc::new(doc)
    }
}

pub use doc::Doc;

impl<'a, B> Doc<'a, B> {
    #[inline]
    pub fn nil() -> Doc<'a, B> {
        Nil
    }

    #[inline]
    pub fn as_string<T: ToString>(t: T) -> Doc<'a, B> {
        Doc::text(t.to_string())
    }

    #[inline]
    pub fn newline() -> Doc<'a, B> {
        Newline
    }

    #[inline]
    pub fn text<T: Into<Cow<'a, str>>>(data: T) -> Doc<'a, B> {
        let text = data.into();
        debug_assert!(!text.contains(|c: char| c == '\n' || c == '\r'));
        Text(text)
    }

    #[inline]
    pub fn space() -> Doc<'a, B> {
        Space
    }
}

impl<'a> Doc<'a, BoxDoc<'a>> {
    #[inline]
    pub fn append(self, that: Doc<'a, BoxDoc<'a>>) -> Doc<'a, BoxDoc<'a>> {
        DocBuilder(&BOX_ALLOCATOR, self).append(that).into()
    }

    #[inline]
    pub fn concat<I>(&'a self, docs: I) -> Doc<'a, BoxDoc<'a>>
        where I: IntoIterator<Item = Doc<'a, BoxDoc<'a>>>
    {
        docs.into_iter().fold(Doc::nil(), |a, b| a.append(b))
    }

    #[inline]
    pub fn group(self) -> Doc<'a, BoxDoc<'a>> {
        DocBuilder(&BOX_ALLOCATOR, self).group().into()
    }

    #[inline]
    pub fn nest(self, offset: usize) -> Doc<'a, BoxDoc<'a>> {
        DocBuilder(&BOX_ALLOCATOR, self).nest(offset).into()
    }
}

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

    macro_rules! test {
        ($size: expr, $actual: expr, $expected: expr) => {
            let mut vec = Vec::new();
            $actual.render($size, &mut vec).unwrap();
            assert_eq!(from_utf8(&vec).unwrap(), $expected);
        };
        ($actual: expr, $expected: expr) => {
            test!(70, $actual, $expected)
        }
    }

    #[test]
    fn box_doc_inference() {
        let doc = Doc::group(Doc::text("test").append(Doc::space()).append(Doc::text("test")));
        test!(doc, "test test");
    }

    #[test]
    fn forced_newline() {
        let doc = Doc::group(Doc::text("test").append(Doc::newline()).append(Doc::text("test")));
        test!(doc, "test\ntest");
    }

    #[test]
    fn block() {
        let doc = Doc::group(Doc::text("{")
            .append(Doc::space()
                .append(Doc::text("test"))
                .append(Doc::space())
                .append(Doc::text("test"))
                .nest(2))
            .append(Doc::space())
            .append(Doc::text("}")));
        test!(5, doc, "{\n  test\n  test\n}");
    }
}
<|endoftext|>


<commit_before>use std::sync::mpsc::Receiver;
use std::sync::{Arc, RwLock};
use std::thread::Thread;
use subject::Subject;

pub struct Event<A> {
    subject: Arc<RwLock<Subject<A>>>,
}

impl<A: Send + Sync + Clone> Event<A> {
    pub fn new() -> Event<A> {
        Event { subject: Arc::new(RwLock::new(Subject::new())) }
    }

    pub fn send(&self, a: A) {
        self.subject.write().unwrap().send(a);
    }

    pub fn listen(&self) -> Receiver<A> {
        self.subject.write().unwrap().listen()
    }

    pub fn map<B: Send + Sync + Clone, F: Fn(A) -> B + Send>(&self, f: F) -> Event<B> {
        let event = Event::new();
        let source = self.listen();
        let subject = event.subject.clone();
        Thread::spawn(move || {
            for a in source.iter() {
                subject.write().unwrap().send(f(a))
            }
        });
        event
    }

    pub fn filter<F: Fn(&A) -> bool + Send>(&self, f: F) -> Event<A> {
        let event = Event::new();
        let source = self.listen();
        let subject = event.subject.clone();
        Thread::spawn(move || {
            for a in source.iter().filter(|a| f(a)) {
                subject.write().unwrap().send(a);
            }
        });
        event
    }
}

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

    #[test]
    fn sink() {
        let sink = Event::new();
        let r = sink.listen();
        sink.send(1);
        assert_eq!(r.recv(), Ok(1))
    }

    #[test]
    fn map() {
        let sink = Event::new();
        let triple = sink.map(|x| 3 * x);
        let r = triple.listen();
        sink.send(1);
        assert_eq!(r.recv(), Ok(3));
    }

    #[test]
    fn filter() {
        let sink: Event<i32> = Event::new();
        let positive = sink.filter(|&x| x > 0);
        let r = positive.listen();
        sink.send(-2);
        sink.send(3);
        assert_eq!(r.recv(), Ok(3));
    }
}
<commit_msg>Implement Event::merge<commit_after>use std::sync::mpsc::Receiver;
use std::sync::{Arc, RwLock};
use std::thread::Thread;
use subject::Subject;

pub struct Event<A> {
    subject: Arc<RwLock<Subject<A>>>,
}

impl<A: Send + Sync + Clone> Event<A> {
    pub fn new() -> Event<A> {
        Event { subject: Arc::new(RwLock::new(Subject::new())) }
    }

    pub fn send(&self, a: A) {
        self.subject.write().unwrap().send(a);
    }

    pub fn listen(&self) -> Receiver<A> {
        self.subject.write().unwrap().listen()
    }

    pub fn map<B: Send + Sync + Clone, F: Fn(A) -> B + Send>(&self, f: F) -> Event<B> {
        let event = Event::new();
        let source = self.listen();
        let subject = event.subject.clone();
        Thread::spawn(move || {
            for a in source.iter() {
                subject.write().unwrap().send(f(a))
            }
        });
        event
    }

    pub fn filter<F: Fn(&A) -> bool + Send>(&self, f: F) -> Event<A> {
        let event = Event::new();
        let source = self.listen();
        let subject = event.subject.clone();
        Thread::spawn(move || {
            for a in source.iter().filter(|a| f(a)) {
                subject.write().unwrap().send(a);
            }
        });
        event
    }

    pub fn merge(&self, other: &Event<A>) -> Event<A> {
        let event = Event::new();
        for source in [self, other].iter().map(|x| x.listen()) {
            let subject = event.subject.clone();
            Thread::spawn(move || {
                for a in source.iter() {
                    subject.write().unwrap().send(a);
                }
            });
        }
        event
    }
}

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

    #[test]
    fn sink() {
        let sink = Event::new();
        let r = sink.listen();
        sink.send(1);
        assert_eq!(r.recv(), Ok(1))
    }

    #[test]
    fn map() {
        let sink = Event::new();
        let triple = sink.map(|x| 3 * x);
        let r = triple.listen();
        sink.send(1);
        assert_eq!(r.recv(), Ok(3));
    }

    #[test]
    fn filter() {
        let sink: Event<i32> = Event::new();
        let positive = sink.filter(|&x| x > 0);
        let r = positive.listen();
        sink.send(-2);
        sink.send(3);
        assert_eq!(r.recv(), Ok(3));
    }

    #[test]
    fn merge() {
        let sink1 = Event::new();
        let sink2 = Event::new();
        let merge = sink1.merge(&sink2);
        let r = merge.listen();
        sink1.send(3);
        sink2.send(4);
        assert_eq!(r.recv(), Ok(3));
        assert_eq!(r.recv(), Ok(4));
    }
}
<|endoftext|>


<commit_before>// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// 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.

//! This module defines the `__rust_probestack` intrinsic which is used in the
//! implementation of "stack probes" on certain platforms.
//!
//! The purpose of a stack probe is to provide a static guarantee that if a
//! thread has a guard page then a stack overflow is guaranteed to hit that
//! guard page. If a function did not have a stack probe then there's a risk of
//! having a stack frame *larger* than the guard page, so a function call could
//! skip over the guard page entirely and then later hit maybe the heap or
//! another thread, possibly leading to security vulnerabilities such as [The
//! Stack Clash], for example.
//!
//! [The Stack Clash]: https://blog.qualys.com/securitylabs/2017/06/19/the-stack-clash
//!
//! The `__rust_probestack` is called in the prologue of functions whose stack
//! size is larger than the guard page, for example larger than 4096 bytes on
//! x86. This function is then responsible for "touching" all pages relevant to
//! the stack to ensure that that if any of them are the guard page we'll hit
//! them guaranteed.
//!
//! The precise ABI for how this function operates is defined by LLVM. There's
//! no real documentation as to what this is, so you'd basically need to read
//! the LLVM source code for reference. Often though the test cases can be
//! illuminating as to the ABI that's generated, or just looking at the output
//! of `llc`.
//!
//! Note that `#[naked]` is typically used here for the stack probe because the
//! ABI corresponds to no actual ABI.
//!
//! Finally it's worth noting that at the time of this writing LLVM only has
//! support for stack probes on x86 and x86_64. There's no support for stack
//! probes on any other architecture like ARM or PowerPC64. LLVM I'm sure would
//! be more than welcome to accept such a change!

#![cfg(not(feature = "mangled-names"))]
// Windows already has builtins to do this.
#![cfg(not(windows))]
// We only define stack probing for these architectures today.
#![cfg(any(target_arch = "x86_64", target_arch = "x86"))]

extern "C" {
    pub fn __rust_probestack();
}

// A wrapper for our implementation of __rust_probestack, which allows us to
// keep the assembly inline while controlling all CFI directives in the assembly
// emitted for the function.
//
// This is the ELF version.
#[cfg(not(any(target_vendor = "apple", target_os = "uefi")))]
macro_rules! define_rust_probestack {
    ($body: expr) => {
        concat!(
            "
            .pushsection .text.__rust_probestack
            .globl __rust_probestack
            .type  __rust_probestack, @function
        __rust_probestack:
            ",
            $body,
            "
            .size __rust_probestack, . - __rust_probestack
            .popsection
            "
        )
    };
}

// Same as above, but for Mach-O.
#[cfg(any(target_vendor = "apple", target_os = "uefi"))]
macro_rules! define_rust_probestack {
    ($body: expr) => {
        concat!(
            "
            .globl ___rust_probestack
        ___rust_probestack:
            ",
            $body
        )
    };
}

// Our goal here is to touch each page between %rsp+8 and %rsp+8-%rax,
// ensuring that if any pages are unmapped we'll make a page fault.
//
// The ABI here is that the stack frame size is located in `%rax`. Upon
// return we're not supposed to modify `%rsp` or `%rax`.
#[cfg(target_arch = "x86_64")]
global_asm!(define_rust_probestack!(
    "
    .cfi_startproc
    pushq  %rbp
    .cfi_adjust_cfa_offset 8
    .cfi_offset %rbp, -16
    movq   %rsp, %rbp
    .cfi_def_cfa_register %rbp

    mov    %rax,%r11        // duplicate %rax as we're clobbering %r11

    // Main loop, taken in one page increments. We're decrementing rsp by
    // a page each time until there's less than a page remaining. We're
    // guaranteed that this function isn't called unless there's more than a
    // page needed.
    //
    // Note that we're also testing against `8(%rsp)` to account for the 8
    // bytes pushed on the stack orginally with our return address. Using
    // `8(%rsp)` simulates us testing the stack pointer in the caller's
    // context.

    // It's usually called when %rax >= 0x1000, but that's not always true.
    // Dynamic stack allocation, which is needed to implement unsized
    // rvalues, triggers stackprobe even if %rax < 0x1000.
    // Thus we have to check %r11 first to avoid segfault.
    cmp    $0x1000,%r11
    jna    3f
2:
    sub    $0x1000,%rsp
    test   %rsp,8(%rsp)
    sub    $0x1000,%r11
    cmp    $0x1000,%r11
    ja     2b

3:
    // Finish up the last remaining stack space requested, getting the last
    // bits out of r11
    sub    %r11,%rsp
    test   %rsp,8(%rsp)

    // Restore the stack pointer to what it previously was when entering
    // this function. The caller will readjust the stack pointer after we
    // return.
    add    %rax,%rsp

    leave
    .cfi_def_cfa_register %rsp
    .cfi_adjust_cfa_offset -8
    ret
    .cfi_endproc
    "
));

#[cfg(target_arch = "x86")]
// This is the same as x86_64 above, only translated for 32-bit sizes. Note
// that on Unix we're expected to restore everything as it was, this
// function basically can't tamper with anything.
//
// The ABI here is the same as x86_64, except everything is 32-bits large.
global_asm!(define_rust_probestack!(
    "
    .cfi_startproc
    push   %ebp
    .cfi_adjust_cfa_offset 4
    .cfi_offset %ebp, -8
    mov    %esp, %ebp
    .cfi_def_cfa_register %ebp
    push   %ecx
    mov    %eax,%ecx

    cmp    $0x1000,%ecx
    jna    3f
2:
    sub    $0x1000,%esp
    test   %esp,8(%esp)
    sub    $0x1000,%ecx
    cmp    $0x1000,%ecx
    ja     2b

3:
    sub    %ecx,%esp
    test   %esp,8(%esp)

    add    %eax,%esp
    pop    %ecx
    leave
    .cfi_def_cfa_register %esp
    .cfi_adjust_cfa_offset -4
    ret
    .cfi_endproc
    "
));
<commit_msg>Add separate rust_probestack definition for uefi (#335)<commit_after>// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// 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.

//! This module defines the `__rust_probestack` intrinsic which is used in the
//! implementation of "stack probes" on certain platforms.
//!
//! The purpose of a stack probe is to provide a static guarantee that if a
//! thread has a guard page then a stack overflow is guaranteed to hit that
//! guard page. If a function did not have a stack probe then there's a risk of
//! having a stack frame *larger* than the guard page, so a function call could
//! skip over the guard page entirely and then later hit maybe the heap or
//! another thread, possibly leading to security vulnerabilities such as [The
//! Stack Clash], for example.
//!
//! [The Stack Clash]: https://blog.qualys.com/securitylabs/2017/06/19/the-stack-clash
//!
//! The `__rust_probestack` is called in the prologue of functions whose stack
//! size is larger than the guard page, for example larger than 4096 bytes on
//! x86. This function is then responsible for "touching" all pages relevant to
//! the stack to ensure that that if any of them are the guard page we'll hit
//! them guaranteed.
//!
//! The precise ABI for how this function operates is defined by LLVM. There's
//! no real documentation as to what this is, so you'd basically need to read
//! the LLVM source code for reference. Often though the test cases can be
//! illuminating as to the ABI that's generated, or just looking at the output
//! of `llc`.
//!
//! Note that `#[naked]` is typically used here for the stack probe because the
//! ABI corresponds to no actual ABI.
//!
//! Finally it's worth noting that at the time of this writing LLVM only has
//! support for stack probes on x86 and x86_64. There's no support for stack
//! probes on any other architecture like ARM or PowerPC64. LLVM I'm sure would
//! be more than welcome to accept such a change!

#![cfg(not(feature = "mangled-names"))]
// Windows already has builtins to do this.
#![cfg(not(windows))]
// We only define stack probing for these architectures today.
#![cfg(any(target_arch = "x86_64", target_arch = "x86"))]

extern "C" {
    pub fn __rust_probestack();
}

// A wrapper for our implementation of __rust_probestack, which allows us to
// keep the assembly inline while controlling all CFI directives in the assembly
// emitted for the function.
//
// This is the ELF version.
#[cfg(not(any(target_vendor = "apple", target_os = "uefi")))]
macro_rules! define_rust_probestack {
    ($body: expr) => {
        concat!(
            "
            .pushsection .text.__rust_probestack
            .globl __rust_probestack
            .type  __rust_probestack, @function
        __rust_probestack:
            ",
            $body,
            "
            .size __rust_probestack, . - __rust_probestack
            .popsection
            "
        )
    };
}

#[cfg(target_os = "uefi")]
macro_rules! define_rust_probestack {
    ($body: expr) => {
        concat!(
            "
            .globl __rust_probestack
        __rust_probestack:
            ",
            $body
        )
    };
}

// Same as above, but for Mach-O. Note that the triple underscore
// is deliberate
#[cfg(target_vendor = "apple")]
macro_rules! define_rust_probestack {
    ($body: expr) => {
        concat!(
            "
            .globl ___rust_probestack
        ___rust_probestack:
            ",
            $body
        )
    };
}

// Our goal here is to touch each page between %rsp+8 and %rsp+8-%rax,
// ensuring that if any pages are unmapped we'll make a page fault.
//
// The ABI here is that the stack frame size is located in `%rax`. Upon
// return we're not supposed to modify `%rsp` or `%rax`.
#[cfg(target_arch = "x86_64")]
global_asm!(define_rust_probestack!(
    "
    .cfi_startproc
    pushq  %rbp
    .cfi_adjust_cfa_offset 8
    .cfi_offset %rbp, -16
    movq   %rsp, %rbp
    .cfi_def_cfa_register %rbp

    mov    %rax,%r11        // duplicate %rax as we're clobbering %r11

    // Main loop, taken in one page increments. We're decrementing rsp by
    // a page each time until there's less than a page remaining. We're
    // guaranteed that this function isn't called unless there's more than a
    // page needed.
    //
    // Note that we're also testing against `8(%rsp)` to account for the 8
    // bytes pushed on the stack orginally with our return address. Using
    // `8(%rsp)` simulates us testing the stack pointer in the caller's
    // context.

    // It's usually called when %rax >= 0x1000, but that's not always true.
    // Dynamic stack allocation, which is needed to implement unsized
    // rvalues, triggers stackprobe even if %rax < 0x1000.
    // Thus we have to check %r11 first to avoid segfault.
    cmp    $0x1000,%r11
    jna    3f
2:
    sub    $0x1000,%rsp
    test   %rsp,8(%rsp)
    sub    $0x1000,%r11
    cmp    $0x1000,%r11
    ja     2b

3:
    // Finish up the last remaining stack space requested, getting the last
    // bits out of r11
    sub    %r11,%rsp
    test   %rsp,8(%rsp)

    // Restore the stack pointer to what it previously was when entering
    // this function. The caller will readjust the stack pointer after we
    // return.
    add    %rax,%rsp

    leave
    .cfi_def_cfa_register %rsp
    .cfi_adjust_cfa_offset -8
    ret
    .cfi_endproc
    "
));

#[cfg(target_arch = "x86")]
// This is the same as x86_64 above, only translated for 32-bit sizes. Note
// that on Unix we're expected to restore everything as it was, this
// function basically can't tamper with anything.
//
// The ABI here is the same as x86_64, except everything is 32-bits large.
global_asm!(define_rust_probestack!(
    "
    .cfi_startproc
    push   %ebp
    .cfi_adjust_cfa_offset 4
    .cfi_offset %ebp, -8
    mov    %esp, %ebp
    .cfi_def_cfa_register %ebp
    push   %ecx
    mov    %eax,%ecx

    cmp    $0x1000,%ecx
    jna    3f
2:
    sub    $0x1000,%esp
    test   %esp,8(%esp)
    sub    $0x1000,%ecx
    cmp    $0x1000,%ecx
    ja     2b

3:
    sub    %ecx,%esp
    test   %esp,8(%esp)

    add    %eax,%esp
    pop    %ecx
    leave
    .cfi_def_cfa_register %esp
    .cfi_adjust_cfa_offset -4
    ret
    .cfi_endproc
    "
));
<|endoftext|>


<commit_before>use core::marker::PhantomData;

#[derive(Debug)]
#[repr(C)]
pub struct MemoryMapTag {
    typ: u32,
    size: u32,
    entry_size: u32,
    entry_version: u32,
    first_area: MemoryArea,
}

impl MemoryMapTag {
    pub fn memory_areas(&self) -> MemoryAreaIter {
        let self_ptr = self as *const MemoryMapTag;
        let start_area = (&self.first_area) as *const MemoryArea;
        MemoryAreaIter {
            current_area: start_area as u64,
            last_area: (self_ptr as u64 + (self.size - self.entry_size) as u64),
            entry_size: self.entry_size,
            phantom: PhantomData,
        }
    }
}

#[derive(Debug)]
#[repr(C)]
pub struct MemoryArea {
    base_addr: u64,
    length: u64,
    typ: u32,
    _reserved: u32,
}

impl MemoryArea {
    pub fn start_address(&self) -> u64 {
        self.base_addr
    }

    pub fn end_address(&self) -> u64 {
        (self.base_addr + self.length)
    }

    pub fn size(&self) -> u64 {
        self.length
    }
}

#[derive(Clone, Debug)]
pub struct MemoryAreaIter<'a> {
    current_area: u64,
    last_area: u64,
    entry_size: u32,
    phantom: PhantomData<&'a MemoryArea>,
}

impl<'a> Iterator for MemoryAreaIter<'a> {
    type Item = &'a MemoryArea;
    fn next(&mut self) -> Option<&'a MemoryArea> {
        if self.current_area > self.last_area {
            None
        } else {
            let area = unsafe{&*(self.current_area as *const MemoryArea)};
            self.current_area = self.current_area + (self.entry_size as u64);
            if area.typ == 1 {
                Some(area)
            } else {self.next()}
        }
    }
}
<commit_msg>Add MemoryAreaType enum<commit_after>use core::marker::PhantomData;

#[derive(Debug)]
#[repr(C)]
pub struct MemoryMapTag {
    typ: u32,
    size: u32,
    entry_size: u32,
    entry_version: u32,
    first_area: MemoryArea,
}

impl MemoryMapTag {
    pub fn memory_areas(&self) -> MemoryAreaIter {
        let self_ptr = self as *const MemoryMapTag;
        let start_area = (&self.first_area) as *const MemoryArea;
        MemoryAreaIter {
            current_area: start_area as u64,
            last_area: (self_ptr as u64 + (self.size - self.entry_size) as u64),
            entry_size: self.entry_size,
            phantom: PhantomData,
        }
    }
}

#[derive(Debug)]
#[repr(C)]
pub struct MemoryArea {
    base_addr: u64,
    length: u64,
    typ: u32,
    _reserved: u32,
}

impl MemoryArea {
    pub fn start_address(&self) -> u64 {
        self.base_addr
    }

    pub fn end_address(&self) -> u64 {
        (self.base_addr + self.length)
    }

    pub fn size(&self) -> u64 {
        self.length
    }

    pub fn typ(&self) -> MemoryAreaType {
        match self.typ {
            1 => MemoryAreaType::Available,
            3 => MemoryAreaType::AcpiAvailable,
            4 => MemoryAreaType::ReservedHibernate,
            5 => MemoryAreaType::Defective,
            _ => MemoryAreaType::Reserved,
        }
    }
}

#[derive(Debug, PartialEq, Eq)]
pub enum MemoryAreaType {
    Reserved,
    Available,
    AcpiAvailable,
    ReservedHibernate,
    Defective,
}

#[derive(Clone, Debug)]
pub struct MemoryAreaIter<'a> {
    current_area: u64,
    last_area: u64,
    entry_size: u32,
    phantom: PhantomData<&'a MemoryArea>,
}

impl<'a> Iterator for MemoryAreaIter<'a> {
    type Item = &'a MemoryArea;
    fn next(&mut self) -> Option<&'a MemoryArea> {
        if self.current_area > self.last_area {
            None
        } else {
            let area = unsafe{&*(self.current_area as *const MemoryArea)};
            self.current_area = self.current_area + (self.entry_size as u64);
            if area.typ == 1 {
                Some(area)
            } else {self.next()}
        }
    }
}
<|endoftext|>


<commit_before>// http://rosettacode.org/wiki/Gaussian_elimination

struct Idx(usize, usize);

struct Matrix<'a, T:'a> where T:  'a + Copy {
    m : &'a mut [T],
    n : usize,
}

impl<'a, T:'a> Matrix<'a, T> where T: 'a + Copy {
    fn new<'b> (_m : &'b mut [T], _n : usize) -> Matrix<'b, T> {
        Matrix{m : _m, n : _n}
    }

    fn val(&self, idx : Idx) -> & T  {
        & (*self.m)[idx.0 + idx.1 * self.n]
    }

    fn val_mut<'b>(&'b mut self, idx : Idx) -> &'b mut T {
        & mut (*self.m)[idx.0 + idx.1 * self.n]
    }

    fn get_row_slice(&self, row: usize) -> &[T]  {
        & self.m[row * self.n .. row * self.n + self.n ]
    }
}

struct MatrixRowIter<'a, T:'a> where T: Copy {
    m : &'a Matrix<'a, T>,
    row : usize,
    col : usize,
    used: &'a [bool]
}

impl<'a, T> MatrixRowIter<'a, T> where T: Copy {
    fn new (_m : &'a Matrix<'a, T>, _used: &'a mut [bool], _col : usize) -> MatrixRowIter<'a, T> {
        MatrixRowIter{m : _m, row : 0, col : _col, used : _used }
    }
}

impl<'a, T> Iterator for MatrixRowIter<'a, T> where T: Copy {
    type Item = (T, usize);
    fn next(&mut self) -> Option<(T, usize)> {
        loop {
            if self.row >= self.m.n {
                return None
            }

            if !self.used[self.row] {
                break;
            }

            self.row += 1;
        }

        let v = self.m.val(Idx(self.col, self.row));
        let ret = self.row;
        self.row += 1;
        Some((*v, ret))
    }
}

fn main() {

    const MAT_SIZE : usize = 6;

    let mut v : Vec<f64> = vec![
    1.00, 0.00, 0.00,  0.00,  0.00, 0.00,
    1.00, 0.63, 0.39,  0.25,  0.16, 0.10,
    1.00, 1.26, 1.58,  1.98,  2.49, 3.13,
    1.00, 1.88, 3.55,  6.70, 12.62, 23.80,
    1.00, 2.51, 6.32, 15.88, 39.90, 100.28,
    1.00, 3.14, 9.87, 31.01, 97.41, 306.02  ];

    let b: [f64; MAT_SIZE] = [-0.01, 0.61, 0.91, 0.99, 0.60, 0.02];

    let mat = Matrix::new(&mut v, MAT_SIZE);

    let mut r : Vec<f64> = Vec::new();
    let mut used: [bool; MAT_SIZE] = [false; MAT_SIZE];

    let mut bm: [f64; MAT_SIZE] = unsafe{std::mem::uninitialized()};

    for i in 0..MAT_SIZE {
        let max = {
            let mat_iter = MatrixRowIter::new(&mat, &mut used, i);
            mat_iter.fold((0.0, -1), |max, item| if item.0.abs() >= max.0 { item } else { max } )
        };

        used[max.1] = true;

        r.extend(mat.get_row_slice(max.1).iter().cloned());
        bm[i] = b[max.1];
    }

    let mut mat_out = Matrix::new(&mut r, MAT_SIZE);

    for dia in 0..mat_out.n {
        for row in dia+1..mat_out.n {
            let tmp = *mat_out.val(Idx(dia, row)) / *mat_out.val(Idx(dia, dia));
            for col in dia+1..mat_out.n {
                *mat_out.val_mut(Idx(col, row)) -= tmp * *mat_out.val(Idx(col, dia));
            }
            *mat_out.val_mut(Idx(dia, row)) = 0.0;
            bm[row] -= tmp * bm[dia];
        }
    }

    let mut x: [f64; MAT_SIZE] = unsafe{std::mem::uninitialized()};

    for row in (0 .. MAT_SIZE).rev() {
        let mut tmp = bm[row];
        for j in (row+1 .. MAT_SIZE).rev() {
            tmp -= x[j] * *mat_out.val(Idx(j, row));
        }
        x[row] = tmp / *mat_out.val(Idx(row, row));
    }

    for j in 0..MAT_SIZE {
        print!("{:9.5} ", x[j]);
    }
    println!("");

}

<commit_msg>some refactor and heap allocation free<commit_after>// http://rosettacode.org/wiki/Gaussian_elimination

struct Idx(usize, usize);

struct Matrix<'a, T:'a> where T:  'a + Copy {
    m : &'a mut [T],
    n : usize,
}

impl<'a, T:'a> Matrix<'a, T> where T: 'a + Copy {
    fn new<'b> (_m : &'b mut [T], _n : usize) -> Matrix<'b, T> {
        Matrix{m : _m, n : _n}
    }

    fn val<'b>(&'b mut self, idx : Idx) -> &'b mut T {
        & mut (*self.m)[idx.0 + idx.1 * self.n]
    }
}

fn get_row_slice<T>(m : &[T], n : usize, row: usize) -> &[T]  {
    & m[ row * n .. row * n + n ]
}

struct MatrixRowIter<'a, T:'a> where T: Copy {
    m : &'a [T],
    n : usize,
    row : usize,
    col : usize,
    used: &'a [bool]
}

impl<'a, T> MatrixRowIter<'a, T> where T: Copy {
    fn new (_m : &'a [T], _n: usize, _used: &'a mut [bool], _col : usize) -> MatrixRowIter<'a, T> {
        MatrixRowIter{m : _m, n: _n, row : 0, col : _col, used : _used }
    }
}

impl<'a, T> Iterator for MatrixRowIter<'a, T> where T: Copy {
    type Item = (T, usize);
    fn next(&mut self) -> Option<(T, usize)> {
        loop {
            if self.row >= self.n {
                return None
            }

            if !self.used[self.row] {
                break;
            }

            self.row += 1;
        }

        let v = self.m[self.col + self.row * self.n];
        let ret = self.row;
        self.row += 1;
        Some((v, ret))
    }
}

fn main() {

    const MAT_SIZE : usize = 6;

    let v : Vec<f64> = vec![
	    1.00, 0.00, 0.00,  0.00,  0.00, 0.00,
	    1.00, 0.63, 0.39,  0.25,  0.16, 0.10,
	    1.00, 1.26, 1.58,  1.98,  2.49, 3.13,
	    1.00, 1.88, 3.55,  6.70, 12.62, 23.80,
	    1.00, 2.51, 6.32, 15.88, 39.90, 100.28,
	    1.00, 3.14, 9.87, 31.01, 97.41, 306.02  ];

    let b: [f64; MAT_SIZE] = [-0.01, 0.61, 0.91, 0.99, 0.60, 0.02];

    let mut used: [bool; MAT_SIZE] = [false; MAT_SIZE];

    let mut bm: [f64; MAT_SIZE] = unsafe{std::mem::uninitialized()};

    let mut r: [f64; MAT_SIZE*MAT_SIZE] = unsafe{std::mem::uninitialized()};

    for i in 0..MAT_SIZE {
        let max = {
            let mat_iter = MatrixRowIter::new(&v, MAT_SIZE, &mut used, i);
            mat_iter.fold((0.0, -1), |max, item| if item.0.abs() >= max.0 { item } else { max } )
        };

        used[max.1] = true;

		    for (i, o) in get_row_slice(&v, MAT_SIZE, max.1).iter()
		    																								.zip(r[ i * MAT_SIZE .. (i+1) * MAT_SIZE ]
		    																										.iter_mut()) {
		        *o = i.clone();
		    }

        bm[i] = b[max.1];
    }

    let mut mat_out = Matrix::new(&mut r, MAT_SIZE);

    for dia in 0..mat_out.n {
        for row in dia+1..mat_out.n {
            let tmp = *mat_out.val(Idx(dia, row)) / *mat_out.val(Idx(dia, dia));
            for col in dia+1..mat_out.n {
                *mat_out.val(Idx(col, row)) -= tmp * *mat_out.val(Idx(col, dia));
            }
            *mat_out.val(Idx(dia, row)) = 0.0;
            bm[row] -= tmp * bm[dia];
        }
    }

    let mut x: [f64; MAT_SIZE] = unsafe{std::mem::uninitialized()};

    for row in (0 .. MAT_SIZE).rev() {
        let mut tmp = bm[row];
        for j in (row+1 .. MAT_SIZE).rev() {
            tmp -= x[j] * *mat_out.val(Idx(j, row));
        }
        x[row] = tmp / *mat_out.val(Idx(row, row));
    }

    for j in 0..MAT_SIZE {
        print!("{:9.5} ", x[j]);
    }
    println!("");

}

<|endoftext|>