<commit_before>use std::collections::HashMap;
use vm_state::VMState;
use prog_state::{ProgState, ProgOutput};

/// The Brainfuck VM
pub struct VM {
    vms : VMState,
    prg : ProgState,
    jmps : HashMap<i16, i16>,
}
impl VM {
    /// parses the imput string, only keeping valid characters. Also generates the
    /// jump table used for the '[' and ']' characters.
    fn parse(input: &str) -> Option<(String,HashMap<i16,i16>)> {
        let mut out_str = String::new();
        let mut jump_tbl: HashMap<i16,i16> = HashMap::new();
        let mut jmps = Vec::new(); // used to store the intermediate locations
                                   // for the jumps.
        for chr in input.chars() {
            match chr {
                '+' => out_str.push(chr),
                '-' => out_str.push(chr),
                '>' => out_str.push(chr),
                '<' => out_str.push(chr),
                '.' => out_str.push(chr),
                ',' => out_str.push(chr),
                '[' => {
                        out_str.push(chr);
                        jmps.push(out_str.len()-1);
                       },
                ']' => {
                        out_str.push(chr);
                        //TODO: Error recovery
                        let jmp = jmps.pop().unwrap() as i16;
                        jump_tbl.insert(jmp, (out_str.len()-1) as i16 );
                       },
                _ => (),
            }
        }
        Some((out_str,jump_tbl))
    }
    /// runs the VM with the specified input string. Returns and output object containing
    /// the final runtime status of the program as well as any collected output.
    pub fn run_with_input (input: &str) -> ProgOutput {
        let (prg_str, jmp_tbl) = VM::parse(input).unwrap();
        let mut bf_prog = VM {
            vms: VMState::new(),
            prg: ProgState::new( prg_str.to_string() ),
            jmps: jmp_tbl,
        };
        let output = bf_prog.run();
        output
    }
    fn run (&mut self) -> ProgOutput {
        let mut std_out = "".to_string();
        let mut output = ProgOutput {
            status: None,
            std_out: std_out,
        };
        let mut running = true;
        while(running){
            // Execute the current instruction
            match self.prg.get_next() {
                '+' => (),
                '-' => (),
                '>' => (),
                '<' => (),
                '.' => (),
                ',' => (),
                '[' => {
                        ();
                       },
                ']' => {
                        ();
                       },
                _ => (),
            }
            // Inc. program pointer if we have more program to execute
            if self.prg.get_pp() < self.prg.get_len() {
                self.prg.inc_pp();
            } else {
                running = false;
            }
        }
        output
    }
}

#[cfg(test)]
mod test {
    use super::VM;
    #[test]
    fn test_parse_invalid_symbols() {
        let in_str = r#"[]++++++++++[>>+>+>++++++[<<+<+++>>>-]<<<<-]
            "A*$";?@![#>>+<<]>[>>]<<<<[>++<[-]]>.>."#;
        let out_str = r#"[]++++++++++[>>+>+>++++++[<<+<+++>>>-]<<<<-][>>+<<]>[>>]<<<<[>++<[-]]>.>."#;
        let o_res = out_str.to_string();
        let (res,jmp_tbl) = VM::parse(in_str).unwrap();
        assert_eq!(res, o_res);
    }
    #[test]
    fn test_run_with_input() {
        let in_str = r#"[]++++++++++[>>+>+>++++++[<<+<+++>>>-]<<<<-]
            "A*$";?@![#>>+<<]>[>>]<<<<[>++<[-]]>.>."#;
        let out_str = r#"[]++++++++++[>>+>+>++++++[<<+<+++>>>-]<<<<-][>>+<<]>[>>]<<<<[>++<[-]]>.>."#;
        let o_res = out_str.to_string();
        let output = VM::run_with_input(in_str);
        println!("{:?}", output);
        assert!(false);
    }
}
<commit_msg>added instruction loop items.<commit_after>use std::collections::HashMap;
use vm_state::VMState;
use prog_state::{ProgState, ProgOutput};

/// The Brainfuck VM
pub struct VM {
    vms : VMState,
    prg : ProgState,
    jmps : HashMap<i16, i16>,
}
impl VM {
    /// parses the imput string, only keeping valid characters.
    /// Also generates the jump table used for the '[' and ']' characters.
    fn parse(input: &str) -> Option<(String,HashMap<i16,i16>)> {
        let mut out_str = String::new();
        let mut jump_tbl: HashMap<i16,i16> = HashMap::new();
        let mut jmps = Vec::new(); // used to store the intermediate locations
                                   // for the jumps.
        for chr in input.chars() {
            match chr {
                '+' => out_str.push(chr),
                '-' => out_str.push(chr),
                '>' => out_str.push(chr),
                '<' => out_str.push(chr),
                '.' => out_str.push(chr),
                ',' => out_str.push(chr),
                '[' => {
                        out_str.push(chr);
                        jmps.push(out_str.len()-1);
                       },
                ']' => {
                        out_str.push(chr);
                        //TODO: Error recovery
                        let jmp = jmps.pop().unwrap() as i16;
                        jump_tbl.insert(jmp, (out_str.len()-1) as i16 );
                       },
                _ => (),
            }
        }
        Some((out_str,jump_tbl))
    }
    /// runs the VM with the specified input string.
    /// Returns and output object containing the final runtime status of
    /// the program as well as any collected output.
    pub fn run_with_input (input: &str) -> ProgOutput {
        let (prg_str, jmp_tbl) = VM::parse(input).unwrap();
        let mut bf_prog = VM {
            vms: VMState::new(),
            prg: ProgState::new( prg_str.to_string() ),
            jmps: jmp_tbl,
        };
        let output = bf_prog.run();
        output
    }
    fn run (&mut self) -> ProgOutput {
        let mut std_out = "".to_string();
        let mut output = ProgOutput {
            status: None,
            std_out: std_out,
        };
        let mut running = true;
        while(running){
            // Execute the current instruction
            match self.prg.get_next() {
                '+' => self.vms.inc_val(),
                '-' => self.vms.dec_val(),
                '>' => self.vms.inc_ptr(),
                '<' => self.vms.dec_ptr(),
                '.' => (),
                ',' => (),
                '[' => {
                        ();
                       },
                ']' => {
                        ();
                       },
                _ => (),
            }
            // Inc. program pointer if we have more program to execute
            if self.prg.get_pp() < self.prg.get_len() {
                self.prg.inc_pp();
            } else {
                running = false;
            }
        }
        output
    }
}

#[cfg(test)]
mod test {
    use super::VM;
    #[test]
    fn test_parse_invalid_symbols() {
        let in_str = r#"[]++++++++++[>>+>+>++++++[<<+<+++>>>-]<<<<-]
            "A*$";?@![#>>+<<]>[>>]<<<<[>++<[-]]>.>."#;
        let out_str = r#"[]++++++++++[>>+>+>++++++[<<+<+++>>>-]<<<<-][>>+<<]>[>>]<<<<[>++<[-]]>.>."#;
        let o_res = out_str.to_string();
        let (res,jmp_tbl) = VM::parse(in_str).unwrap();
        assert_eq!(res, o_res);
    }
    #[test]
    fn test_run_with_input() {
        let in_str = r#"[]++++++++++[>>+>+>++++++[<<+<+++>>>-]<<<<-]
            "A*$";?@![#>>+<<]>[>>]<<<<[>++<[-]]>.>."#;
        let out_str = r#"[]++++++++++[>>+>+>++++++[<<+<+++>>>-]<<<<-][>>+<<]>[>>]<<<<[>++<[-]]>.>."#;
        let o_res = out_str.to_string();
        let output = VM::run_with_input(in_str);
        println!("{:?}", output);
        assert!(false);
    }
}
<|endoftext|>


<commit_before>use std::io;
use std::io::prelude::*;

type SudokuCandidate = u64;
const SUDOKU_DIGIT_BASE: u32 = 10;
const SUDOKU_CANDIDATE_SIZE: usize = 9;
const SUDOKU_BOX_SIZE: usize = 3;
const SUDOKU_GROUP_SIZE: usize = 9;
const SUDOKU_CELL_SIZE: usize = 81;
const SUDOKU_ALL_CANDIDATES: SudokuCandidate = ((1 << SUDOKU_CANDIDATE_SIZE) - 1);

#[derive(Clone, Copy)]
struct SudokuCell {
    candidates: SudokuCandidate
}

impl SudokuCell {
    fn new() -> SudokuCell {
        SudokuCell { candidates: SUDOKU_ALL_CANDIDATES }
    }

    // '1'..'9'
    fn preset_candidate(&mut self, ch: char) {
        let code_digit_base = '1'.to_digit(SUDOKU_DIGIT_BASE).unwrap();
        match ch {
            '1'...'9' => {
                let number = (ch.to_digit(SUDOKU_DIGIT_BASE).unwrap() - code_digit_base) as SudokuCandidate;
                self.candidates = self.digit_to_candidate(&number);
                ()
            }
            _ => {()}
        }
    }

    fn digit_to_candidate(&self, candidate: &SudokuCandidate) -> SudokuCandidate {
        (1 as SudokuCandidate) << candidate
    }

    fn has_candidate(&self, candidate: &SudokuCandidate) -> bool {
        (self.candidates & self.digit_to_candidate(&candidate)) != 0
    }

    fn to_string(&self) -> String {
        let mut line = String::new();
        for candidate in 0..(SUDOKU_CANDIDATE_SIZE as SudokuCandidate) {
            if self.has_candidate(&candidate) {
                line.push_str(&(candidate+1).to_string());
            }
        }
        line
    }

    fn clear_candidate(&mut self) {
        self.candidates = 0
    }

    fn has_unique_candidate(&self) -> bool {
        (self.candidates & (self.candidates - 1)) == 0
    }

    fn can_merge(&mut self, candidates: SudokuCandidate) -> bool {
        (self.candidates & self.digit_to_candidate(&candidates)) != 0
    }

    fn merge_unique_candidate(&mut self, rhs: &SudokuCell) -> bool {
        if rhs.has_unique_candidate() {
            if (self.candidates & rhs.candidates) != 0 {
                return true;
            }
            self.candidates |= rhs.candidates;
        }
        false
    }

    fn merge_candidate(&mut self, rhs: &SudokuCell) {
        self.candidates |= rhs.candidates;
    }

    fn mask_candidate(&mut self, rhs: &SudokuCell) {
        if rhs.count_candidates() == 1 && (self.candidates & rhs.candidates) != 0 {
            self.candidates -= rhs.candidates;
        }
    }

    fn has_all_candidates(&self) -> bool {
        self.candidates == SUDOKU_ALL_CANDIDATES
    }

    fn overwrite_candidate(&mut self, candidate: SudokuCandidate) {
        if self.count_candidates() > 1 {
            self.candidates = self.digit_to_candidate(&candidate);
        }
    }

    fn count_candidates(&self) -> usize {
        let mut count = 0;
        for candidate in 0..(SUDOKU_CANDIDATE_SIZE as SudokuCandidate) {
            if (self.candidates & self.digit_to_candidate(&candidate)) != 0 {
                count += 1;
            }
        }
        count
    }
}

struct SudokuGroupGen {
    index: usize
}

impl SudokuGroupGen {
    fn new() -> SudokuGroupGen {
        SudokuGroupGen { index:0 }
    }

    fn next(&mut self) -> Option<Vec<usize>> {
        if self.index < SUDOKU_GROUP_SIZE {
            let lower = self.index * SUDOKU_GROUP_SIZE;
            let upper = (self.index + 1) * SUDOKU_GROUP_SIZE;
            self.index += 1;
            Some((lower..upper).collect::<Vec<_>>())
        } else if self.index < (SUDOKU_GROUP_SIZE * 2) {
            let column = self.index - SUDOKU_GROUP_SIZE;
            self.index += 1;
            Some((0..SUDOKU_GROUP_SIZE).map(|i| column + i * SUDOKU_GROUP_SIZE).collect::<Vec<_>>())
        } else if self.index < (SUDOKU_GROUP_SIZE * 3) {
            let box_index = self.index - SUDOKU_GROUP_SIZE * 2;
            let offset = (box_index % 3) * 3  + (box_index / 3) * SUDOKU_GROUP_SIZE * 3;
            let mut indexes : Vec<usize> = Vec::new();
            for row in 0..SUDOKU_BOX_SIZE {
                let x = (0..SUDOKU_BOX_SIZE).map(|column| row * SUDOKU_GROUP_SIZE + column + offset).collect::<Vec<_>>();
                indexes.extend(x);
            }
            self.index += 1;
            Some(indexes)
        } else {
            None
        }
    }
}

struct SudokuMap {
    cells : Vec<SudokuCell>
}

impl SudokuMap {
    fn new(line: &str) -> SudokuMap {
        let mut cells = vec![SudokuCell::new(); SUDOKU_CELL_SIZE];
        for (index, ch) in line.chars().enumerate() {
            cells[index].preset_candidate(ch);
        }
        SudokuMap { cells:cells }
    }

    fn to_string(&self) -> String {
        let mut full_text = String::new();

        for row in 0..SUDOKU_GROUP_SIZE {
            let mut line = String::new();
            for column in 0..SUDOKU_GROUP_SIZE {
                let index = row * SUDOKU_GROUP_SIZE + column;
                let cell_str = self.cells[index].to_string();
                line.push_str(&cell_str);
                line.push_str(":");
            }
            line.push_str("\n");
            full_text.push_str(&line);
        }
        full_text
    }

    fn solve(&mut self) -> bool {
        self.solve_from(0)
    }

    fn filter_unique_candidates(&mut self) {
        let mut group_gen = SudokuGroupGen::new();
        while let Some(indexes) = group_gen.next() {
            let froms = indexes.clone();
            for index in froms {
                let cell = self.cells[index];
                let targets = indexes.clone();
                for target in targets {
                    if target != index {
                        self.cells[target].mask_candidate(&cell);
                    }
                }
            }
        }
    }

    fn solve_from(&mut self, start_pos : usize) -> bool {
        self.filter_unique_candidates();
        if !self.is_consistent() {
            return false;
        }

        for i in start_pos..SUDOKU_CELL_SIZE {
            let count = self.cells[i].count_candidates();
            if count == 0 {
                return false;
            } else if count == 1 {
                continue;
            }
            for candidate in 0..(SUDOKU_CANDIDATE_SIZE as SudokuCandidate) {
                let mut target_cell = self.cells[i].clone();
                if target_cell.can_merge(candidate) {
                    let mut new_map = SudokuMap::new("");
                    new_map.cells = self.cells.clone();
                    new_map.cells[i].overwrite_candidate(candidate);
                    if new_map.solve_from(start_pos + 1) {
                        self.cells = new_map.cells;
                        return true;
                    }
                }
            }
        }

        self.is_solved()
    }

    fn is_solved(&self) -> bool {
        let mut group_gen = SudokuGroupGen::new();
        while let Some(indexes) = group_gen.next() {
            if !self.is_group_solved(indexes) {
                return false;
            }
        }
        true
    }

    fn is_group_solved(&self, cell_indexes: Vec<usize>) -> bool {
        let mut sum = SudokuCell::new();
        let mut conflict = false;
        sum.clear_candidate();
        for cell_index in cell_indexes {
            conflict |= sum.merge_unique_candidate(&self.cells[cell_index]);
        }
        sum.has_all_candidates() && !conflict
    }

    fn is_consistent(&self) -> bool {
        let mut group_gen = SudokuGroupGen::new();
        while let Some(indexes) = group_gen.next() {
            if !self.is_group_consistent(indexes) {
                return false;
            }
        }
        true
    }

    fn is_group_consistent(&self, cell_indexes: Vec<usize>) -> bool {
        let mut all_candidates = SudokuCell::new();
        let mut unique_candidates = SudokuCell::new();
        let mut conflict = false;
        all_candidates.clear_candidate();
        unique_candidates.clear_candidate();

        for cell_index in cell_indexes {
            all_candidates.merge_candidate(&self.cells[cell_index]);
            conflict |= unique_candidates.merge_unique_candidate(&self.cells[cell_index]);
        }
        all_candidates.has_all_candidates() && !conflict
    }
}

fn main() {
    let stdin = io::stdin();

    for line in stdin.lock().lines() {
        let line = line.unwrap();
        let mut sudoku_map = SudokuMap::new(&line);
        let result = sudoku_map.solve();
        let answer = sudoku_map.to_string();
        if result {
            println!("Solved\n{}", answer);
        } else {
            println!("Not solved\n{}", answer);
        }
    }
}
<commit_msg>Improve the Rust solver<commit_after>use std::io;
use std::io::prelude::*;

type SudokuCandidate = u64;
const SUDOKU_DIGIT_BASE: u32 = 10;
const SUDOKU_CANDIDATE_SIZE: usize = 9;
const SUDOKU_BOX_SIZE: usize = 3;
const SUDOKU_GROUP_SIZE: usize = 9;
const SUDOKU_CELL_SIZE: usize = 81;
const SUDOKU_ALL_CANDIDATES: SudokuCandidate = ((1 << SUDOKU_CANDIDATE_SIZE) - 1);

// Sudoku cell that contains candidates as a bitboard
#[derive(Clone, Copy)]
struct SudokuCell {
    candidates: SudokuCandidate
}

impl SudokuCell {
    fn new() -> SudokuCell {
        SudokuCell { candidates: SUDOKU_ALL_CANDIDATES }
    }

    fn to_string(&self) -> String {
        let mut line = String::new();
        for candidate in 0..(SUDOKU_CANDIDATE_SIZE as SudokuCandidate) {
            if self.has_candidate(&candidate) {
                line.push_str(&(candidate+1).to_string());
            }
        }
        line
    }

    // Input '1'..'9'
    fn preset_candidate(&mut self, ch: char) {
        let code_digit_base = '1'.to_digit(SUDOKU_DIGIT_BASE).unwrap();
        match ch {
            '1'...'9' => {
                let number = (ch.to_digit(SUDOKU_DIGIT_BASE).unwrap() - code_digit_base) as SudokuCandidate;
                self.candidates = self.digit_to_candidate(&number);
            }
            _ => {}
        }
    }

    fn clear_candidate(&mut self) {
        self.candidates = 0;
    }

    // Input 0..8
    fn overwrite_candidate(&mut self, candidate: SudokuCandidate) {
        if self.count_candidates() > 1 {
            self.candidates = self.digit_to_candidate(&candidate);
        }
    }

    fn count_candidates(&self) -> usize {
        let f = |candidate| {
            if (self.candidates & self.digit_to_candidate(&candidate))
                != 0 { 1 } else { 0 } };
        (0..SUDOKU_CANDIDATE_SIZE as SudokuCandidate).fold(
            0, |sum, candidates| sum + f(candidates))
    }

    fn has_unique_candidate(&self) -> bool {
        // Check whether only one bit is set
        (self.candidates & (self.candidates - 1)) == 0
    }

    fn has_all_candidates(&self) -> bool {
        self.candidates == SUDOKU_ALL_CANDIDATES
    }

    // Input 0..8
    fn can_mask(&mut self, candidates: SudokuCandidate) -> bool {
        (self.candidates & self.digit_to_candidate(&candidates)) != 0
    }

    fn mask_candidate(&mut self, rhs: &SudokuCell) {
        if rhs.count_candidates() == 1 {
            self.candidates &= !rhs.candidates;
        }
    }

    fn merge_candidate(&mut self, rhs: &SudokuCell) {
        self.candidates |= rhs.candidates;
    }

    // Returns whether no candidates are merged
    fn merge_unique_candidate(&mut self, rhs: &SudokuCell) -> bool {
        if rhs.has_unique_candidate() {
            if (self.candidates & rhs.candidates) != 0 {
                return true;
            }
            self.candidates |= rhs.candidates;
        }
        false
    }

    // Inner methods
    // Input 0..8
    fn digit_to_candidate(&self, candidate: &SudokuCandidate) -> SudokuCandidate {
        (1 as SudokuCandidate) << candidate
    }

    // Input 0..8
    fn has_candidate(&self, candidate: &SudokuCandidate) -> bool {
        (self.candidates & self.digit_to_candidate(&candidate)) != 0
    }
}

// Generator for sudoku cellgroups
struct SudokuGroupGen {
    index: usize
}

impl SudokuGroupGen {
    fn new() -> SudokuGroupGen {
        SudokuGroupGen { index:0 }
    }

    fn next(&mut self) -> Option<Vec<usize>> {
        if self.index < SUDOKU_GROUP_SIZE {
            let lower = self.index * SUDOKU_GROUP_SIZE;
            let upper = (self.index + 1) * SUDOKU_GROUP_SIZE;
            self.index += 1;
            Some((lower..upper).collect::<Vec<_>>())
        } else if self.index < (SUDOKU_GROUP_SIZE * 2) {
            let column = self.index - SUDOKU_GROUP_SIZE;
            self.index += 1;
            Some((0..SUDOKU_GROUP_SIZE).map(|i| column + i * SUDOKU_GROUP_SIZE).collect::<Vec<_>>())
        } else if self.index < (SUDOKU_GROUP_SIZE * 3) {
            let box_index = self.index - SUDOKU_GROUP_SIZE * 2;
            let offset = (box_index % 3) * 3  + (box_index / 3) * SUDOKU_GROUP_SIZE * 3;
            let mut indexes : Vec<usize> = Vec::new();
            for row in 0..SUDOKU_BOX_SIZE {
                let x = (0..SUDOKU_BOX_SIZE).map(|column| row * SUDOKU_GROUP_SIZE + column + offset).collect::<Vec<_>>();
                indexes.extend(x);
            }
            self.index += 1;
            Some(indexes)
        } else {
            None
        }
    }
}

// Sudoku cell map
struct SudokuMap {
    cells : Vec<SudokuCell>
}

impl SudokuMap {
    fn new(line: &str) -> SudokuMap {
        let mut cells = vec![SudokuCell::new(); SUDOKU_CELL_SIZE];
        for (index, ch) in line.chars().enumerate() {
            cells[index].preset_candidate(ch);
        }
        SudokuMap { cells:cells }
    }

    fn to_string(&self) -> String {
        let mut full_text = String::new();

        for row in 0..SUDOKU_GROUP_SIZE {
            let mut line = String::new();
            for column in 0..SUDOKU_GROUP_SIZE {
                let index = row * SUDOKU_GROUP_SIZE + column;
                let cell_str = self.cells[index].to_string();
                line.push_str(&cell_str);
                line.push_str(":");
            }
            line.push_str("\n");
            full_text.push_str(&line);
        }
        full_text
    }

    fn solve(&mut self) -> bool {
        self.solve_from(0)
    }

    fn solve_from(&mut self, start_pos : usize) -> bool {
        self.filter_unique_candidates();
        if !self.is_consistent() {
            return false;
        }

        for i in start_pos..SUDOKU_CELL_SIZE {
            let count = self.cells[i].count_candidates();
            match count {
                0 => return false,
                1 => continue,
                _ => (),
            }

            for candidate in 0..(SUDOKU_CANDIDATE_SIZE as SudokuCandidate) {
                let mut target_cell = self.cells[i].clone();
                if target_cell.can_mask(candidate) {
                    let mut new_map = SudokuMap::new("");
                    new_map.cells = self.cells.clone();
                    new_map.cells[i].overwrite_candidate(candidate);
                    if new_map.solve_from(start_pos + 1) {
                        self.cells = new_map.cells;
                        return true;
                    }
                }
            }
        }

        self.is_solved()
    }

    fn filter_unique_candidates(&mut self) {
        let mut group_gen = SudokuGroupGen::new();
        while let Some(indexes) = group_gen.next() {
            let froms = indexes.clone();
            for index in froms {
                let cell = self.cells[index];
                let targets = indexes.clone();
                for target in targets {
                    if target != index {
                        self.cells[target].mask_candidate(&cell);
                    }
                }
            }
        }
    }

    fn is_solved(&self) -> bool {
        let mut group_gen = SudokuGroupGen::new();
        while let Some(indexes) = group_gen.next() {
            if !self.is_group_solved(indexes) {
                return false;
            }
        }
        true
    }

    fn is_group_solved(&self, cell_indexes: Vec<usize>) -> bool {
        let mut sum = SudokuCell::new();
        let mut conflict = false;
        sum.clear_candidate();
        for cell_index in cell_indexes {
            conflict |= sum.merge_unique_candidate(&self.cells[cell_index]);
        }
        sum.has_all_candidates() && !conflict
    }

    fn is_consistent(&self) -> bool {
        let mut group_gen = SudokuGroupGen::new();
        while let Some(indexes) = group_gen.next() {
            if !self.is_group_consistent(indexes) {
                return false;
            }
        }
        true
    }

    fn is_group_consistent(&self, cell_indexes: Vec<usize>) -> bool {
        let mut all_candidates = SudokuCell::new();
        let mut unique_candidates = SudokuCell::new();
        let mut conflict = false;
        all_candidates.clear_candidate();
        unique_candidates.clear_candidate();

        for cell_index in cell_indexes {
            all_candidates.merge_candidate(&self.cells[cell_index]);
            conflict |= unique_candidates.merge_unique_candidate(&self.cells[cell_index]);
        }
        all_candidates.has_all_candidates() && !conflict
    }
}

fn main() {
    let stdin = io::stdin();

    for line in stdin.lock().lines() {
        let line = line.unwrap();
        let mut sudoku_map = SudokuMap::new(&line);
        let result = sudoku_map.solve();
        let answer = sudoku_map.to_string();
        if result {
            println!("Solved\n{}", answer);
        } else {
            println!("Not solved\n{}", answer);
        }
    }
}
<|endoftext|>


<commit_before>//! Diagnostic emitted for files that aren't part of any crate.

use hir::db::DefDatabase;
use ide_db::{
    base_db::{FileId, FileLoader, SourceDatabase, SourceDatabaseExt},
    source_change::SourceChange,
    RootDatabase,
};
use syntax::{
    ast::{self, ModuleItemOwner, NameOwner},
    AstNode, TextRange, TextSize,
};
use text_edit::TextEdit;

use crate::{fix, Assist, Diagnostic, DiagnosticsContext};

// Diagnostic: unlinked-file
//
// This diagnostic is shown for files that are not included in any crate, or files that are part of
// crates rust-analyzer failed to discover. The file will not have IDE features available.
pub(crate) fn unlinked_file(ctx: &DiagnosticsContext, acc: &mut Vec<Diagnostic>, file_id: FileId) {
    // Limit diagnostic to the first few characters in the file. This matches how VS Code
    // renders it with the full span, but on other editors, and is less invasive.
    let range = ctx.sema.db.parse(file_id).syntax_node().text_range();
    // FIXME: This is wrong if one of the first three characters is not ascii: `//Ы`.
    let range = range.intersect(TextRange::up_to(TextSize::of("..."))).unwrap_or(range);

    acc.push(
        Diagnostic::new("unlinked-file", "file not included in module tree", range)
            .with_fixes(fixes(ctx, file_id)),
    );
}

fn fixes(ctx: &DiagnosticsContext, file_id: FileId) -> Option<Vec<Assist>> {
    // If there's an existing module that could add `mod` or `pub mod` items to include the unlinked file,
    // suggest that as a fix.

    let source_root = ctx.sema.db.source_root(ctx.sema.db.file_source_root(file_id));
    let our_path = source_root.path_for_file(&file_id)?;
    let module_name = our_path.name_and_extension()?.0;

    // Candidates to look for:
    // - `mod.rs` in the same folder
    //   - we also check `main.rs` and `lib.rs`
    // - `$dir.rs` in the parent folder, where `$dir` is the directory containing `self.file_id`
    let parent = our_path.parent()?;
    let mut paths = vec![parent.join("mod.rs")?, parent.join("lib.rs")?, parent.join("main.rs")?];

    // `submod/bla.rs` -> `submod.rs`
    if let Some(newmod) = (|| {
        let name = parent.name_and_extension()?.0;
        parent.parent()?.join(&format!("{}.rs", name))
    })() {
        paths.push(newmod);
    }

    for path in &paths {
        if let Some(parent_id) = source_root.file_for_path(path) {
            for krate in ctx.sema.db.relevant_crates(*parent_id).iter() {
                let crate_def_map = ctx.sema.db.crate_def_map(*krate);
                for (_, module) in crate_def_map.modules() {
                    if module.origin.is_inline() {
                        // We don't handle inline `mod parent {}`s, they use different paths.
                        continue;
                    }

                    if module.origin.file_id() == Some(*parent_id) {
                        return make_fixes(ctx.sema.db, *parent_id, module_name, file_id);
                    }
                }
            }
        }
    }

    None
}

fn make_fixes(
    db: &RootDatabase,
    parent_file_id: FileId,
    new_mod_name: &str,
    added_file_id: FileId,
) -> Option<Vec<Assist>> {
    fn is_outline_mod(item: &ast::Item) -> bool {
        matches!(item, ast::Item::Module(m) if m.item_list().is_none())
    }

    let mod_decl = format!("mod {};", new_mod_name);
    let pub_mod_decl = format!("pub mod {};", new_mod_name);

    let ast: ast::SourceFile = db.parse(parent_file_id).tree();

    let mut mod_decl_builder = TextEdit::builder();
    let mut pub_mod_decl_builder = TextEdit::builder();

    // If there's an existing `mod m;` statement matching the new one, don't emit a fix (it's
    // probably `#[cfg]`d out).
    for item in ast.items() {
        if let ast::Item::Module(m) = item {
            if let Some(name) = m.name() {
                if m.item_list().is_none() && name.to_string() == new_mod_name {
                    cov_mark::hit!(unlinked_file_skip_fix_when_mod_already_exists);
                    return None;
                }
            }
        }
    }

    // If there are existing `mod m;` items, append after them (after the first group of them, rather).
    match ast
        .items()
        .skip_while(|item| !is_outline_mod(item))
        .take_while(|item| is_outline_mod(item))
        .last()
    {
        Some(last) => {
            cov_mark::hit!(unlinked_file_append_to_existing_mods);
            let offset = last.syntax().text_range().end();
            mod_decl_builder.insert(offset, format!("\n{}", mod_decl));
            pub_mod_decl_builder.insert(offset, format!("\n{}", pub_mod_decl));
        }
        None => {
            // Prepend before the first item in the file.
            match ast.items().next() {
                Some(item) => {
                    cov_mark::hit!(unlinked_file_prepend_before_first_item);
                    let offset = item.syntax().text_range().start();
                    mod_decl_builder.insert(offset, format!("{}\n\n", mod_decl));
                    pub_mod_decl_builder.insert(offset, format!("{}\n\n", pub_mod_decl));
                }
                None => {
                    // No items in the file, so just append at the end.
                    cov_mark::hit!(unlinked_file_empty_file);
                    let offset = ast.syntax().text_range().end();
                    mod_decl_builder.insert(offset, format!("{}\n", mod_decl));
                    pub_mod_decl_builder.insert(offset, format!("{}\n", pub_mod_decl));
                }
            }
        }
    }

    let trigger_range = db.parse(added_file_id).tree().syntax().text_range();
    Some(vec![
        fix(
            "add_mod_declaration",
            &format!("Insert `{}`", mod_decl),
            SourceChange::from_text_edit(parent_file_id, mod_decl_builder.finish()),
            trigger_range,
        ),
        fix(
            "add_pub_mod_declaration",
            &format!("Insert `{}`", pub_mod_decl),
            SourceChange::from_text_edit(parent_file_id, pub_mod_decl_builder.finish()),
            trigger_range,
        ),
    ])
}

#[cfg(test)]
mod tests {
    use crate::tests::{check_diagnostics, check_fix, check_fixes, check_no_fix};

    #[test]
    fn unlinked_file_prepend_first_item() {
        cov_mark::check!(unlinked_file_prepend_before_first_item);
        // Only tests the first one for `pub mod` since the rest are the same
        check_fixes(
            r#"
//- /main.rs
fn f() {}
//- /foo.rs
$0
"#,
            vec![
                r#"
mod foo;

fn f() {}
"#,
                r#"
pub mod foo;

fn f() {}
"#,
            ],
        );
    }

    #[test]
    fn unlinked_file_append_mod() {
        cov_mark::check!(unlinked_file_append_to_existing_mods);
        check_fix(
            r#"
//- /main.rs
//! Comment on top

mod preexisting;

mod preexisting2;

struct S;

mod preexisting_bottom;)
//- /foo.rs
$0
"#,
            r#"
//! Comment on top

mod preexisting;

mod preexisting2;
mod foo;

struct S;

mod preexisting_bottom;)
"#,
        );
    }

    #[test]
    fn unlinked_file_insert_in_empty_file() {
        cov_mark::check!(unlinked_file_empty_file);
        check_fix(
            r#"
//- /main.rs
//- /foo.rs
$0
"#,
            r#"
mod foo;
"#,
        );
    }

    #[test]
    fn unlinked_file_old_style_modrs() {
        check_fix(
            r#"
//- /main.rs
mod submod;
//- /submod/mod.rs
// in mod.rs
//- /submod/foo.rs
$0
"#,
            r#"
// in mod.rs
mod foo;
"#,
        );
    }

    #[test]
    fn unlinked_file_new_style_mod() {
        check_fix(
            r#"
//- /main.rs
mod submod;
//- /submod.rs
//- /submod/foo.rs
$0
"#,
            r#"
mod foo;
"#,
        );
    }

    #[test]
    fn unlinked_file_with_cfg_off() {
        cov_mark::check!(unlinked_file_skip_fix_when_mod_already_exists);
        check_no_fix(
            r#"
//- /main.rs
#[cfg(never)]
mod foo;

//- /foo.rs
$0
"#,
        );
    }

    #[test]
    fn unlinked_file_with_cfg_on() {
        check_diagnostics(
            r#"
//- /main.rs
#[cfg(not(never))]
mod foo;

//- /foo.rs
"#,
        );
    }
}
<commit_msg>Make unlinked_file diagnostic a hint again<commit_after>//! Diagnostic emitted for files that aren't part of any crate.

use hir::db::DefDatabase;
use ide_db::{
    base_db::{FileId, FileLoader, SourceDatabase, SourceDatabaseExt},
    source_change::SourceChange,
    RootDatabase,
};
use syntax::{
    ast::{self, ModuleItemOwner, NameOwner},
    AstNode, TextRange, TextSize,
};
use text_edit::TextEdit;

use crate::{fix, Assist, Diagnostic, DiagnosticsContext, Severity};

// Diagnostic: unlinked-file
//
// This diagnostic is shown for files that are not included in any crate, or files that are part of
// crates rust-analyzer failed to discover. The file will not have IDE features available.
pub(crate) fn unlinked_file(ctx: &DiagnosticsContext, acc: &mut Vec<Diagnostic>, file_id: FileId) {
    // Limit diagnostic to the first few characters in the file. This matches how VS Code
    // renders it with the full span, but on other editors, and is less invasive.
    let range = ctx.sema.db.parse(file_id).syntax_node().text_range();
    // FIXME: This is wrong if one of the first three characters is not ascii: `//Ы`.
    let range = range.intersect(TextRange::up_to(TextSize::of("..."))).unwrap_or(range);

    acc.push(
        Diagnostic::new("unlinked-file", "file not included in module tree", range)
            .severity(Severity::WeakWarning)
            .with_fixes(fixes(ctx, file_id)),
    );
}

fn fixes(ctx: &DiagnosticsContext, file_id: FileId) -> Option<Vec<Assist>> {
    // If there's an existing module that could add `mod` or `pub mod` items to include the unlinked file,
    // suggest that as a fix.

    let source_root = ctx.sema.db.source_root(ctx.sema.db.file_source_root(file_id));
    let our_path = source_root.path_for_file(&file_id)?;
    let module_name = our_path.name_and_extension()?.0;

    // Candidates to look for:
    // - `mod.rs` in the same folder
    //   - we also check `main.rs` and `lib.rs`
    // - `$dir.rs` in the parent folder, where `$dir` is the directory containing `self.file_id`
    let parent = our_path.parent()?;
    let mut paths = vec![parent.join("mod.rs")?, parent.join("lib.rs")?, parent.join("main.rs")?];

    // `submod/bla.rs` -> `submod.rs`
    if let Some(newmod) = (|| {
        let name = parent.name_and_extension()?.0;
        parent.parent()?.join(&format!("{}.rs", name))
    })() {
        paths.push(newmod);
    }

    for path in &paths {
        if let Some(parent_id) = source_root.file_for_path(path) {
            for krate in ctx.sema.db.relevant_crates(*parent_id).iter() {
                let crate_def_map = ctx.sema.db.crate_def_map(*krate);
                for (_, module) in crate_def_map.modules() {
                    if module.origin.is_inline() {
                        // We don't handle inline `mod parent {}`s, they use different paths.
                        continue;
                    }

                    if module.origin.file_id() == Some(*parent_id) {
                        return make_fixes(ctx.sema.db, *parent_id, module_name, file_id);
                    }
                }
            }
        }
    }

    None
}

fn make_fixes(
    db: &RootDatabase,
    parent_file_id: FileId,
    new_mod_name: &str,
    added_file_id: FileId,
) -> Option<Vec<Assist>> {
    fn is_outline_mod(item: &ast::Item) -> bool {
        matches!(item, ast::Item::Module(m) if m.item_list().is_none())
    }

    let mod_decl = format!("mod {};", new_mod_name);
    let pub_mod_decl = format!("pub mod {};", new_mod_name);

    let ast: ast::SourceFile = db.parse(parent_file_id).tree();

    let mut mod_decl_builder = TextEdit::builder();
    let mut pub_mod_decl_builder = TextEdit::builder();

    // If there's an existing `mod m;` statement matching the new one, don't emit a fix (it's
    // probably `#[cfg]`d out).
    for item in ast.items() {
        if let ast::Item::Module(m) = item {
            if let Some(name) = m.name() {
                if m.item_list().is_none() && name.to_string() == new_mod_name {
                    cov_mark::hit!(unlinked_file_skip_fix_when_mod_already_exists);
                    return None;
                }
            }
        }
    }

    // If there are existing `mod m;` items, append after them (after the first group of them, rather).
    match ast
        .items()
        .skip_while(|item| !is_outline_mod(item))
        .take_while(|item| is_outline_mod(item))
        .last()
    {
        Some(last) => {
            cov_mark::hit!(unlinked_file_append_to_existing_mods);
            let offset = last.syntax().text_range().end();
            mod_decl_builder.insert(offset, format!("\n{}", mod_decl));
            pub_mod_decl_builder.insert(offset, format!("\n{}", pub_mod_decl));
        }
        None => {
            // Prepend before the first item in the file.
            match ast.items().next() {
                Some(item) => {
                    cov_mark::hit!(unlinked_file_prepend_before_first_item);
                    let offset = item.syntax().text_range().start();
                    mod_decl_builder.insert(offset, format!("{}\n\n", mod_decl));
                    pub_mod_decl_builder.insert(offset, format!("{}\n\n", pub_mod_decl));
                }
                None => {
                    // No items in the file, so just append at the end.
                    cov_mark::hit!(unlinked_file_empty_file);
                    let offset = ast.syntax().text_range().end();
                    mod_decl_builder.insert(offset, format!("{}\n", mod_decl));
                    pub_mod_decl_builder.insert(offset, format!("{}\n", pub_mod_decl));
                }
            }
        }
    }

    let trigger_range = db.parse(added_file_id).tree().syntax().text_range();
    Some(vec![
        fix(
            "add_mod_declaration",
            &format!("Insert `{}`", mod_decl),
            SourceChange::from_text_edit(parent_file_id, mod_decl_builder.finish()),
            trigger_range,
        ),
        fix(
            "add_pub_mod_declaration",
            &format!("Insert `{}`", pub_mod_decl),
            SourceChange::from_text_edit(parent_file_id, pub_mod_decl_builder.finish()),
            trigger_range,
        ),
    ])
}

#[cfg(test)]
mod tests {
    use crate::tests::{check_diagnostics, check_fix, check_fixes, check_no_fix};

    #[test]
    fn unlinked_file_prepend_first_item() {
        cov_mark::check!(unlinked_file_prepend_before_first_item);
        // Only tests the first one for `pub mod` since the rest are the same
        check_fixes(
            r#"
//- /main.rs
fn f() {}
//- /foo.rs
$0
"#,
            vec![
                r#"
mod foo;

fn f() {}
"#,
                r#"
pub mod foo;

fn f() {}
"#,
            ],
        );
    }

    #[test]
    fn unlinked_file_append_mod() {
        cov_mark::check!(unlinked_file_append_to_existing_mods);
        check_fix(
            r#"
//- /main.rs
//! Comment on top

mod preexisting;

mod preexisting2;

struct S;

mod preexisting_bottom;)
//- /foo.rs
$0
"#,
            r#"
//! Comment on top

mod preexisting;

mod preexisting2;
mod foo;

struct S;

mod preexisting_bottom;)
"#,
        );
    }

    #[test]
    fn unlinked_file_insert_in_empty_file() {
        cov_mark::check!(unlinked_file_empty_file);
        check_fix(
            r#"
//- /main.rs
//- /foo.rs
$0
"#,
            r#"
mod foo;
"#,
        );
    }

    #[test]
    fn unlinked_file_old_style_modrs() {
        check_fix(
            r#"
//- /main.rs
mod submod;
//- /submod/mod.rs
// in mod.rs
//- /submod/foo.rs
$0
"#,
            r#"
// in mod.rs
mod foo;
"#,
        );
    }

    #[test]
    fn unlinked_file_new_style_mod() {
        check_fix(
            r#"
//- /main.rs
mod submod;
//- /submod.rs
//- /submod/foo.rs
$0
"#,
            r#"
mod foo;
"#,
        );
    }

    #[test]
    fn unlinked_file_with_cfg_off() {
        cov_mark::check!(unlinked_file_skip_fix_when_mod_already_exists);
        check_no_fix(
            r#"
//- /main.rs
#[cfg(never)]
mod foo;

//- /foo.rs
$0
"#,
        );
    }

    #[test]
    fn unlinked_file_with_cfg_on() {
        check_diagnostics(
            r#"
//- /main.rs
#[cfg(not(never))]
mod foo;

//- /foo.rs
"#,
        );
    }
}
<|endoftext|>


<commit_before>//  * This file is part of the uutils coreutils package.
//  *
//  * (c) Yury Krivopalov <ykrivopalov@yandex.ru>
//  *
//  * For the full copyright and license information, please view the LICENSE
//  * file that was distributed with this source code.

// spell-checker:ignore N'th M'th

#[macro_use]
extern crate uucore;

use crate::format::format_and_print;
use crate::options::*;
use crate::units::{Result, Unit};
use clap::{crate_version, App, AppSettings, Arg, ArgMatches};
use std::io::{BufRead, Write};
use uucore::display::Quotable;
use uucore::ranges::Range;

pub mod format;
pub mod options;
mod units;

static ABOUT: &str = "Convert numbers from/to human-readable strings";
static LONG_HELP: &str = "UNIT options:
   none   no auto-scaling is done; suffixes will trigger an error

   auto   accept optional single/two letter suffix:

          1K = 1000, 1Ki = 1024, 1M = 1000000, 1Mi = 1048576,

   si     accept optional single letter suffix:

          1K = 1000, 1M = 1000000, ...

   iec    accept optional single letter suffix:

          1K = 1024, 1M = 1048576, ...

   iec-i  accept optional two-letter suffix:

          1Ki = 1024, 1Mi = 1048576, ...

FIELDS supports cut(1) style field ranges:
  N    N'th field, counted from 1
  N-   from N'th field, to end of line
  N-M  from N'th to M'th field (inclusive)
  -M   from first to M'th field (inclusive)
  -    all fields
Multiple fields/ranges can be separated with commas
";

fn usage() -> String {
    format!("{0} [OPTION]... [NUMBER]...", uucore::execution_phrase())
}

fn handle_args<'a>(args: impl Iterator<Item = &'a str>, options: NumfmtOptions) -> Result<()> {
    for l in args {
        format_and_print(l, &options)?;
    }

    Ok(())
}

fn handle_stdin(options: NumfmtOptions) -> Result<()> {
    let stdin = std::io::stdin();
    let locked_stdin = stdin.lock();

    let mut lines = locked_stdin.lines();
    for l in lines.by_ref().take(options.header) {
        l.map(|s| println!("{}", s)).map_err(|e| e.to_string())?;
    }

    for l in lines {
        l.map_err(|e| e.to_string())
            .and_then(|l| format_and_print(&l, &options))?;
    }

    Ok(())
}

fn parse_unit(s: &str) -> Result<Unit> {
    match s {
        "auto" => Ok(Unit::Auto),
        "si" => Ok(Unit::Si),
        "iec" => Ok(Unit::Iec(false)),
        "iec-i" => Ok(Unit::Iec(true)),
        "none" => Ok(Unit::None),
        _ => Err("Unsupported unit is specified".to_owned()),
    }
}

fn parse_options(args: &ArgMatches) -> Result<NumfmtOptions> {
    let from = parse_unit(args.value_of(options::FROM).unwrap())?;
    let to = parse_unit(args.value_of(options::TO).unwrap())?;

    let transform = TransformOptions { from, to };

    let padding = match args.value_of(options::PADDING) {
        Some(s) => s.parse::<isize>().map_err(|err| err.to_string()),
        None => Ok(0),
    }?;

    let header = match args.occurrences_of(options::HEADER) {
        0 => Ok(0),
        _ => {
            let value = args.value_of(options::HEADER).unwrap();

            value
                .parse::<usize>()
                .map_err(|_| value)
                .and_then(|n| match n {
                    0 => Err(value),
                    _ => Ok(n),
                })
                .map_err(|value| format!("invalid header value {}", value.quote()))
        }
    }?;

    let fields = match args.value_of(options::FIELD).unwrap() {
        "-" => vec![Range {
            low: 1,
            high: std::usize::MAX,
        }],
        v => Range::from_list(v)?,
    };

    let delimiter = args.value_of(options::DELIMITER).map_or(Ok(None), |arg| {
        if arg.len() == 1 {
            Ok(Some(arg.to_string()))
        } else {
            Err("the delimiter must be a single character".to_string())
        }
    })?;

    // unwrap is fine because the argument has a default value
    let round = match args.value_of(options::ROUND).unwrap() {
        "up" => RoundMethod::Up,
        "down" => RoundMethod::Down,
        "from-zero" => RoundMethod::FromZero,
        "towards-zero" => RoundMethod::TowardsZero,
        "nearest" => RoundMethod::Nearest,
        _ => unreachable!("Should be restricted by clap"),
    };

    Ok(NumfmtOptions {
        transform,
        padding,
        header,
        fields,
        delimiter,
        round,
    })
}

pub fn uumain(args: impl uucore::Args) -> i32 {
    let usage = usage();

    let matches = uu_app().usage(&usage[..]).get_matches_from(args);

    let result =
        parse_options(&matches).and_then(|options| match matches.values_of(options::NUMBER) {
            Some(values) => handle_args(values, options),
            None => handle_stdin(options),
        });

    match result {
        Err(e) => {
            std::io::stdout().flush().expect("error flushing stdout");
            show_error!("{}", e);
            1
        }
        _ => 0,
    }
}

pub fn uu_app() -> App<'static, 'static> {
    App::new(uucore::util_name())
        .version(crate_version!())
        .about(ABOUT)
        .after_help(LONG_HELP)
        .setting(AppSettings::AllowNegativeNumbers)
        .arg(
            Arg::with_name(options::DELIMITER)
                .short("d")
                .long(options::DELIMITER)
                .value_name("X")
                .help("use X instead of whitespace for field delimiter"),
        )
        .arg(
            Arg::with_name(options::FIELD)
                .long(options::FIELD)
                .help("replace the numbers in these input fields (default=1) see FIELDS below")
                .value_name("FIELDS")
                .default_value(options::FIELD_DEFAULT),
        )
        .arg(
            Arg::with_name(options::FROM)
                .long(options::FROM)
                .help("auto-scale input numbers to UNITs; see UNIT below")
                .value_name("UNIT")
                .default_value(options::FROM_DEFAULT),
        )
        .arg(
            Arg::with_name(options::TO)
                .long(options::TO)
                .help("auto-scale output numbers to UNITs; see UNIT below")
                .value_name("UNIT")
                .default_value(options::TO_DEFAULT),
        )
        .arg(
            Arg::with_name(options::PADDING)
                .long(options::PADDING)
                .help(
                    "pad the output to N characters; positive N will \
                     right-align; negative N will left-align; padding is \
                     ignored if the output is wider than N; the default is \
                     to automatically pad if a whitespace is found",
                )
                .value_name("N"),
        )
        .arg(
            Arg::with_name(options::HEADER)
                .long(options::HEADER)
                .help(
                    "print (without converting) the first N header lines; \
                     N defaults to 1 if not specified",
                )
                .value_name("N")
                .default_value(options::HEADER_DEFAULT)
                .hide_default_value(true),
        )
        .arg(
            Arg::with_name(options::ROUND)
                .long(options::ROUND)
                .help(
                    "use METHOD for rounding when scaling; METHOD can be: up,\
                    down, from-zero (default), towards-zero, nearest",
                )
                .value_name("METHOD")
                .default_value("from-zero")
                .possible_values(&["up", "down", "from-zero", "towards-zero", "nearest"]),
        )
        .arg(Arg::with_name(options::NUMBER).hidden(true).multiple(true))
}
<commit_msg>numfmt: return UResult from uumain() function<commit_after>//  * This file is part of the uutils coreutils package.
//  *
//  * (c) Yury Krivopalov <ykrivopalov@yandex.ru>
//  *
//  * For the full copyright and license information, please view the LICENSE
//  * file that was distributed with this source code.

// spell-checker:ignore N'th M'th

use crate::format::format_and_print;
use crate::options::*;
use crate::units::{Result, Unit};
use clap::{crate_version, App, AppSettings, Arg, ArgMatches};
use std::io::{BufRead, Write};
use uucore::display::Quotable;
use uucore::error::{UResult, USimpleError};
use uucore::ranges::Range;

pub mod format;
pub mod options;
mod units;

static ABOUT: &str = "Convert numbers from/to human-readable strings";
static LONG_HELP: &str = "UNIT options:
   none   no auto-scaling is done; suffixes will trigger an error

   auto   accept optional single/two letter suffix:

          1K = 1000, 1Ki = 1024, 1M = 1000000, 1Mi = 1048576,

   si     accept optional single letter suffix:

          1K = 1000, 1M = 1000000, ...

   iec    accept optional single letter suffix:

          1K = 1024, 1M = 1048576, ...

   iec-i  accept optional two-letter suffix:

          1Ki = 1024, 1Mi = 1048576, ...

FIELDS supports cut(1) style field ranges:
  N    N'th field, counted from 1
  N-   from N'th field, to end of line
  N-M  from N'th to M'th field (inclusive)
  -M   from first to M'th field (inclusive)
  -    all fields
Multiple fields/ranges can be separated with commas
";

fn usage() -> String {
    format!("{0} [OPTION]... [NUMBER]...", uucore::execution_phrase())
}

fn handle_args<'a>(args: impl Iterator<Item = &'a str>, options: NumfmtOptions) -> Result<()> {
    for l in args {
        format_and_print(l, &options)?;
    }

    Ok(())
}

fn handle_stdin(options: NumfmtOptions) -> Result<()> {
    let stdin = std::io::stdin();
    let locked_stdin = stdin.lock();

    let mut lines = locked_stdin.lines();
    for l in lines.by_ref().take(options.header) {
        l.map(|s| println!("{}", s)).map_err(|e| e.to_string())?;
    }

    for l in lines {
        l.map_err(|e| e.to_string())
            .and_then(|l| format_and_print(&l, &options))?;
    }

    Ok(())
}

fn parse_unit(s: &str) -> Result<Unit> {
    match s {
        "auto" => Ok(Unit::Auto),
        "si" => Ok(Unit::Si),
        "iec" => Ok(Unit::Iec(false)),
        "iec-i" => Ok(Unit::Iec(true)),
        "none" => Ok(Unit::None),
        _ => Err("Unsupported unit is specified".to_owned()),
    }
}

fn parse_options(args: &ArgMatches) -> Result<NumfmtOptions> {
    let from = parse_unit(args.value_of(options::FROM).unwrap())?;
    let to = parse_unit(args.value_of(options::TO).unwrap())?;

    let transform = TransformOptions { from, to };

    let padding = match args.value_of(options::PADDING) {
        Some(s) => s.parse::<isize>().map_err(|err| err.to_string()),
        None => Ok(0),
    }?;

    let header = match args.occurrences_of(options::HEADER) {
        0 => Ok(0),
        _ => {
            let value = args.value_of(options::HEADER).unwrap();

            value
                .parse::<usize>()
                .map_err(|_| value)
                .and_then(|n| match n {
                    0 => Err(value),
                    _ => Ok(n),
                })
                .map_err(|value| format!("invalid header value {}", value.quote()))
        }
    }?;

    let fields = match args.value_of(options::FIELD).unwrap() {
        "-" => vec![Range {
            low: 1,
            high: std::usize::MAX,
        }],
        v => Range::from_list(v)?,
    };

    let delimiter = args.value_of(options::DELIMITER).map_or(Ok(None), |arg| {
        if arg.len() == 1 {
            Ok(Some(arg.to_string()))
        } else {
            Err("the delimiter must be a single character".to_string())
        }
    })?;

    // unwrap is fine because the argument has a default value
    let round = match args.value_of(options::ROUND).unwrap() {
        "up" => RoundMethod::Up,
        "down" => RoundMethod::Down,
        "from-zero" => RoundMethod::FromZero,
        "towards-zero" => RoundMethod::TowardsZero,
        "nearest" => RoundMethod::Nearest,
        _ => unreachable!("Should be restricted by clap"),
    };

    Ok(NumfmtOptions {
        transform,
        padding,
        header,
        fields,
        delimiter,
        round,
    })
}

#[uucore_procs::gen_uumain]
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
    let usage = usage();

    let matches = uu_app().usage(&usage[..]).get_matches_from(args);

    let result =
        parse_options(&matches).and_then(|options| match matches.values_of(options::NUMBER) {
            Some(values) => handle_args(values, options),
            None => handle_stdin(options),
        });

    match result {
        Err(e) => {
            std::io::stdout().flush().expect("error flushing stdout");
            // TODO Change `handle_args()` and `handle_stdin()` so that
            // they return `UResult`.
            return Err(USimpleError::new(1, e));
        }
        _ => Ok(()),
    }
}

pub fn uu_app() -> App<'static, 'static> {
    App::new(uucore::util_name())
        .version(crate_version!())
        .about(ABOUT)
        .after_help(LONG_HELP)
        .setting(AppSettings::AllowNegativeNumbers)
        .arg(
            Arg::with_name(options::DELIMITER)
                .short("d")
                .long(options::DELIMITER)
                .value_name("X")
                .help("use X instead of whitespace for field delimiter"),
        )
        .arg(
            Arg::with_name(options::FIELD)
                .long(options::FIELD)
                .help("replace the numbers in these input fields (default=1) see FIELDS below")
                .value_name("FIELDS")
                .default_value(options::FIELD_DEFAULT),
        )
        .arg(
            Arg::with_name(options::FROM)
                .long(options::FROM)
                .help("auto-scale input numbers to UNITs; see UNIT below")
                .value_name("UNIT")
                .default_value(options::FROM_DEFAULT),
        )
        .arg(
            Arg::with_name(options::TO)
                .long(options::TO)
                .help("auto-scale output numbers to UNITs; see UNIT below")
                .value_name("UNIT")
                .default_value(options::TO_DEFAULT),
        )
        .arg(
            Arg::with_name(options::PADDING)
                .long(options::PADDING)
                .help(
                    "pad the output to N characters; positive N will \
                     right-align; negative N will left-align; padding is \
                     ignored if the output is wider than N; the default is \
                     to automatically pad if a whitespace is found",
                )
                .value_name("N"),
        )
        .arg(
            Arg::with_name(options::HEADER)
                .long(options::HEADER)
                .help(
                    "print (without converting) the first N header lines; \
                     N defaults to 1 if not specified",
                )
                .value_name("N")
                .default_value(options::HEADER_DEFAULT)
                .hide_default_value(true),
        )
        .arg(
            Arg::with_name(options::ROUND)
                .long(options::ROUND)
                .help(
                    "use METHOD for rounding when scaling; METHOD can be: up,\
                    down, from-zero (default), towards-zero, nearest",
                )
                .value_name("METHOD")
                .default_value("from-zero")
                .possible_values(&["up", "down", "from-zero", "towards-zero", "nearest"]),
        )
        .arg(Arg::with_name(options::NUMBER).hidden(true).multiple(true))
}
<|endoftext|>


<commit_before>//! # C API for rav1e
//!
//! [rav1e](https://github.com/xiph/rav1e/) is an [AV1](https://aomediacodec.github.io/av1-spec/)
//! encoder written in [Rust](https://rust-lang.org)
//!
//! This is the C-compatible API to it

extern crate rav1e;

use std::slice;
use std::sync::Arc;

use std::ffi::CStr;
use std::os::raw::c_char;
use std::os::raw::c_int;

/// Raw video Frame
///
/// It can be allocated throught rav1e_frame_new(), populated using rav1e_frame_fill_plane()
/// and freed using rav1e_frame_unref().
pub struct Frame(Arc<rav1e::Frame>);

type EncoderStatus=rav1e::EncoderStatus;

/// Encoder configuration
///
/// Instantiate it using rav1e_config_default() and fine-tune it using
/// rav1e_config_parse().
///
/// Use rav1e_config_unref() to free its memory.
pub struct Config {
    cfg: rav1e::Config,
    last_err: Option<EncoderStatus>,
}

/// Encoder context
///
/// Contains the encoding state, it is created by rav1e_context_new() using an
/// Encoder configuration.
///
/// Use rav1e_context_unref() to free its memory.
pub struct Context {
    ctx: rav1e::Context,
    last_err: Option<EncoderStatus>,
}

type FrameType = rav1e::FrameType;

/// Encoded Packet
///
/// The encoded packets are retrieved using rav1e_receive_packet().
///
/// Use rav1e_packet_unref() to free its memory.
#[repr(C)]
pub struct Packet {
    /// Encoded data buffer
    pub data: *const u8,
    /// Encoded data buffer size
    pub len: u64,
    /// Frame sequence number
    pub number: u64,
    /// Frame type
    pub frame_type: FrameType,
}

type ChromaSampling=rav1e::ChromaSampling;
type Rational=rav1e::Rational;

#[no_mangle]
pub unsafe extern "C" fn rav1e_config_default(
    width: u32,
    height: u32,
    bit_depth: u8,
    chroma_sampling: ChromaSampling,
    timebase: Rational,
) -> *mut Config {
    let cfg = rav1e::Config {
        frame_info: rav1e::FrameInfo {
            width: width as usize,
            height: height as usize,
            bit_depth: bit_depth as usize,
            chroma_sampling,
        },
        timebase,
        enc: Default::default(),
    };

    let c = Box::new(Config {
        cfg,
        last_err: None,
    });

    Box::into_raw(c)
}

#[no_mangle]
pub unsafe extern "C" fn rav1e_config_unref(cfg: *mut Config) {
    let _ = Box::from_raw(cfg);
}

/// Set a configuration parameter using its key and value
///
/// Available keys and values
/// - "quantizer": 0-255, default 100
/// - "speed": 0-10, default 3
/// - "tune": "psnr"-"psychovisual", default "psnr"
///
/// Returns a negative value on non-zero.
#[no_mangle]
pub unsafe extern "C" fn rav1e_config_parse(
    cfg: *mut Config,
    key: *const c_char,
    value: *const c_char,
) -> c_int {
    let key = CStr::from_ptr(key).to_string_lossy();
    let value = CStr::from_ptr(value).to_string_lossy();

    (*cfg)
        .cfg
        .parse(&key, &value)
        .map(|_v| {
            (*cfg).last_err = None;
            0
        }).map_err(|e| (*cfg).last_err = Some(e))
        .unwrap_or(-1)
}

/// Generate a new encoding context from a populated encoder configuration
///
/// Multiple contexts can be generated through it.
#[no_mangle]
pub unsafe extern "C" fn rav1e_context_new(cfg: *const Config) -> *mut Context {
    let ctx = Context {
        ctx: (*cfg).cfg.new_context(),
        last_err: None,
    };

    Box::into_raw(Box::new(ctx))
}

#[no_mangle]
pub unsafe extern "C" fn rav1e_context_unref(ctx: *mut Context) {
    let _ = Box::from_raw(ctx);
}

/// Produce a new frame from the encoding context
///
/// It must be populated using rav1e_frame_fill_plane().
///
/// The frame is reference counted and must be released passing it to rav1e_frame_unref(),
/// see rav1e_send_frame().
#[no_mangle]
pub unsafe extern "C" fn rav1e_frame_new(ctx: *const Context) -> *mut Frame {
    let f = (*ctx).ctx.new_frame();
    let frame = Box::new(Frame(f));

    Box::into_raw(frame)
}

#[no_mangle]
pub unsafe extern "C" fn rav1e_frame_unref(frame: *mut Frame) {
    let _ = Arc::from_raw(frame);
}

/// Send the frame for encoding
///
/// The function increases the frame internal reference count and it can be passed multiple
/// times to different rav1e_send_frame().
#[no_mangle]
pub unsafe extern "C" fn rav1e_send_frame(ctx: *mut Context, frame: *const Frame) -> c_int {
    let frame = if frame.is_null() {
        None
    } else {
        Some((*frame).0.clone())
    };

    (*ctx)
        .ctx
        .send_frame(frame)
        .map(|_v| {
            (*ctx).last_err = None;
            0
        }).map_err(|e| (*ctx).last_err = Some(e))
        .unwrap_or(-1)
}

/// Receive encoded data
#[no_mangle]
pub unsafe extern "C" fn rav1e_receive_packet(
    ctx: *mut Context,
    pkt: *mut *mut Packet,
) -> c_int {
    (*ctx)
        .ctx
        .receive_packet()
        .map(|p| {
            (*ctx).last_err = None;
            let packet = Packet {
                data: p.data.as_ptr(),
                len: p.data.len() as u64,
                number: p.number,
                frame_type: p.frame_type,
            };
            *pkt = Box::into_raw(Box::new(packet));
            0
        }).map_err(|e| (*ctx).last_err = Some(e))
        .unwrap_or(-1)
}

#[no_mangle]
pub unsafe extern fn rav1e_packet_unref(pkt: *mut Packet) {
    let _ = Box::from_raw(pkt);
}

/// Produce a sequence header matching the current encoding context
///
/// Its format is compatible with the AV1 Matroska and ISOBMFF specification.
#[no_mangle]
pub unsafe extern fn rav1e_container_sequence_header(ctx: *mut Context, buf_size: *mut usize) -> *mut u8 {
    let buf = (*ctx).ctx.container_sequence_header();

    *buf_size = buf.len();
    Box::into_raw(buf.into_boxed_slice()) as *mut u8
}

#[no_mangle]
pub unsafe extern fn rav1e_container_sequence_header_unref(sequence: *mut u8) {
    let _ = Box::from_raw(sequence);
}

/// Fill a frame plane
///
/// Currently the frame contains 3 planes, the first is luminance followed by
/// chrominance.
///
/// The data is copied and this function has to be called for each plane.
#[no_mangle]
pub unsafe extern "C" fn rav1e_frame_fill_plane(
    frame: *mut Frame,
    plane: usize,
    data: *const u8,
    data_len: usize,
    stride: usize,
    bytewidth: usize,
) {
    let input = Arc::get_mut(&mut (*frame).0).unwrap();
    let data_slice = slice::from_raw_parts(data, data_len);

    input.planes[plane].copy_from_raw_u8(data_slice, stride, bytewidth);
}
<commit_msg>crav1e: Use the libc::size_t and libc::ptrdiff_t<commit_after>//! # C API for rav1e
//!
//! [rav1e](https://github.com/xiph/rav1e/) is an [AV1](https://aomediacodec.github.io/av1-spec/)
//! encoder written in [Rust](https://rust-lang.org)
//!
//! This is the C-compatible API

extern crate rav1e;
extern crate libc;

use std::slice;
use std::sync::Arc;

use std::ffi::CStr;
use std::os::raw::c_char;
use std::os::raw::c_int;

use libc::size_t;
use libc::ptrdiff_t;

/// Raw video Frame
///
/// It can be allocated throught rav1e_frame_new(), populated using rav1e_frame_fill_plane()
/// and freed using rav1e_frame_unref().
pub struct Frame(Arc<rav1e::Frame>);

type EncoderStatus=rav1e::EncoderStatus;

/// Encoder configuration
///
/// Instantiate it using rav1e_config_default() and fine-tune it using
/// rav1e_config_parse().
///
/// Use rav1e_config_unref() to free its memory.
pub struct Config {
    cfg: rav1e::Config,
    last_err: Option<EncoderStatus>,
}

/// Encoder context
///
/// Contains the encoding state, it is created by rav1e_context_new() using an
/// Encoder configuration.
///
/// Use rav1e_context_unref() to free its memory.
pub struct Context {
    ctx: rav1e::Context,
    last_err: Option<EncoderStatus>,
}

type FrameType = rav1e::FrameType;

/// Encoded Packet
///
/// The encoded packets are retrieved using rav1e_receive_packet().
///
/// Use rav1e_packet_unref() to free its memory.
#[repr(C)]
pub struct Packet {
    /// Encoded data buffer
    pub data: *const u8,
    /// Encoded data buffer size
    pub len: size_t,
    /// Frame sequence number
    pub number: u64,
    /// Frame type
    pub frame_type: FrameType,
}

type ChromaSampling=rav1e::ChromaSampling;
type Rational=rav1e::Rational;

#[no_mangle]
pub unsafe extern "C" fn rav1e_config_default(
    width: u32,
    height: u32,
    bit_depth: u8,
    chroma_sampling: ChromaSampling,
    timebase: Rational,
) -> *mut Config {
    let cfg = rav1e::Config {
        frame_info: rav1e::FrameInfo {
            width: width as usize,
            height: height as usize,
            bit_depth: bit_depth as usize,
            chroma_sampling,
        },
        timebase,
        enc: Default::default(),
    };

    let c = Box::new(Config {
        cfg,
        last_err: None,
    });

    Box::into_raw(c)
}

#[no_mangle]
pub unsafe extern "C" fn rav1e_config_unref(cfg: *mut Config) {
    let _ = Box::from_raw(cfg);
}

/// Set a configuration parameter using its key and value
///
/// Available keys and values
/// - "quantizer": 0-255, default 100
/// - "speed": 0-10, default 3
/// - "tune": "psnr"-"psychovisual", default "psnr"
///
/// Returns a negative value on non-zero.
#[no_mangle]
pub unsafe extern "C" fn rav1e_config_parse(
    cfg: *mut Config,
    key: *const c_char,
    value: *const c_char,
) -> c_int {
    let key = CStr::from_ptr(key).to_string_lossy();
    let value = CStr::from_ptr(value).to_string_lossy();

    (*cfg)
        .cfg
        .parse(&key, &value)
        .map(|_v| {
            (*cfg).last_err = None;
            0
        }).map_err(|e| (*cfg).last_err = Some(e))
        .unwrap_or(-1)
}

/// Generate a new encoding context from a populated encoder configuration
///
/// Multiple contexts can be generated through it.
#[no_mangle]
pub unsafe extern "C" fn rav1e_context_new(cfg: *const Config) -> *mut Context {
    let ctx = Context {
        ctx: (*cfg).cfg.new_context(),
        last_err: None,
    };

    Box::into_raw(Box::new(ctx))
}

#[no_mangle]
pub unsafe extern "C" fn rav1e_context_unref(ctx: *mut Context) {
    let _ = Box::from_raw(ctx);
}

/// Produce a new frame from the encoding context
///
/// It must be populated using rav1e_frame_fill_plane().
///
/// The frame is reference counted and must be released passing it to rav1e_frame_unref(),
/// see rav1e_send_frame().
#[no_mangle]
pub unsafe extern "C" fn rav1e_frame_new(ctx: *const Context) -> *mut Frame {
    let f = (*ctx).ctx.new_frame();
    let frame = Box::new(Frame(f));

    Box::into_raw(frame)
}

#[no_mangle]
pub unsafe extern "C" fn rav1e_frame_unref(frame: *mut Frame) {
    let _ = Arc::from_raw(frame);
}

/// Send the frame for encoding
///
/// The function increases the frame internal reference count and it can be passed multiple
/// times to different rav1e_send_frame().
#[no_mangle]
pub unsafe extern "C" fn rav1e_send_frame(ctx: *mut Context, frame: *const Frame) -> c_int {
    let frame = if frame.is_null() {
        None
    } else {
        Some((*frame).0.clone())
    };

    (*ctx)
        .ctx
        .send_frame(frame)
        .map(|_v| {
            (*ctx).last_err = None;
            0
        }).map_err(|e| (*ctx).last_err = Some(e))
        .unwrap_or(-1)
}

/// Receive encoded data
#[no_mangle]
pub unsafe extern "C" fn rav1e_receive_packet(
    ctx: *mut Context,
    pkt: *mut *mut Packet,
) -> c_int {
    (*ctx)
        .ctx
        .receive_packet()
        .map(|p| {
            (*ctx).last_err = None;
            let packet = Packet {
                data: p.data.as_ptr(),
                len: p.data.len(),
                number: p.number,
                frame_type: p.frame_type,
            };
            *pkt = Box::into_raw(Box::new(packet));
            0
        }).map_err(|e| (*ctx).last_err = Some(e))
        .unwrap_or(-1)
}

#[no_mangle]
pub unsafe extern fn rav1e_packet_unref(pkt: *mut Packet) {
    let _ = Box::from_raw(pkt);
}

/// Produce a sequence header matching the current encoding context
///
/// Its format is compatible with the AV1 Matroska and ISOBMFF specification.
///
/// Use rav1e_container_sequence_header_unref() to free it.
#[no_mangle]
pub unsafe extern fn rav1e_container_sequence_header(ctx: *mut Context, buf_size: *mut size_t) -> *mut u8 {
    let buf = (*ctx).ctx.container_sequence_header();

    *buf_size = buf.len();
    Box::into_raw(buf.into_boxed_slice()) as *mut u8
}

#[no_mangle]
pub unsafe extern fn rav1e_container_sequence_header_unref(sequence: *mut u8) {
    let _ = Box::from_raw(sequence);
}

/// Fill a frame plane
///
/// Currently the frame contains 3 planes, the first is luminance followed by
/// chrominance.
///
/// The data is copied and this function has to be called for each plane.
///
/// frame: A frame provided by rav1e_frame_new()
/// plane: The index of the plane starting from 0
/// data: The data to be copied
/// data_len: Lenght of the buffer
/// stride: Plane line in bytes, including padding
/// bytewidth: Number of bytes per component, either 1 or 2
#[no_mangle]
pub unsafe extern "C" fn rav1e_frame_fill_plane(
    frame: *mut Frame,
    plane: c_int,
    data: *const u8,
    data_len: size_t,
    stride: ptrdiff_t,
    bytewidth: c_int,
) {
    let input = Arc::get_mut(&mut (*frame).0).unwrap();
    let data_slice = slice::from_raw_parts(data, data_len as usize);

    input.planes[plane as usize].copy_from_raw_u8(data_slice, stride as usize, bytewidth as usize);
}
<|endoftext|>


<commit_before>use geom::point::Point2D;
use geom::rect::Rect;
use geom::size::Size2D;
use num::{Num, from_int};

pub enum Au = i32;

impl Au : Num {
    pure fn add(other: &Au) -> Au        { Au(*self + **other) }
    pure fn sub(other: &Au) -> Au        { Au(*self - **other) }
    pure fn mul(other: &Au) -> Au        { Au(*self * **other) }
    pure fn div(other: &Au) -> Au        { Au(*self / **other) }
    pure fn modulo(other: &Au) -> Au     { Au(*self % **other) }
    pure fn neg() -> Au                   { Au(-*self)         }

    pure fn to_int() -> int               { *self as int       }

    static pure fn from_int(n: int) -> Au {
        Au((n & (i32::max_value as int)) as i32)
    }
}

impl Au : cmp::Ord {
    pure fn lt(other: &Au) -> bool { *self <  **other }
    pure fn le(other: &Au) -> bool { *self <= **other }
    pure fn ge(other: &Au) -> bool { *self >= **other }
    pure fn gt(other: &Au) -> bool { *self >  **other }
}

impl Au : cmp::Eq {
    pure fn eq(other: &Au) -> bool { *self == **other }
    pure fn ne(other: &Au) -> bool { *self != **other }
}

pub pure fn min(x: Au, y: Au) -> Au { if x < y { x } else { y } }
pub pure fn max(x: Au, y: Au) -> Au { if x > y { x } else { y } }

pub fn box<A:Copy Num>(x: A, y: A, w: A, h: A) -> Rect<A> {
    Rect(Point2D(x, y), Size2D(w, h))
}

impl Au {
    pub pure fn scale_by(factor: float) -> Au {
        Au(((*self as float) * factor) as i32)
    }

    static pub pure fn from_px(i: int) -> Au {
        from_int(i * 60)
    }

    pub pure fn to_px(&const self) -> int {
        (**self / 60) as int
    }

    static pub pure fn zero_point() -> Point2D<Au> {
        Point2D(Au(0), Au(0))
    }

    static pub pure fn zero_rect() -> Rect<Au> {
        let z = Au(0);
        Rect(Point2D(z, z), Size2D(z, z))
    }

    // assumes 72 points per inch, and 96 px per inch
    static pub pure fn from_pt(f: float) -> Au {
        from_px((f / 72f * 96f) as int)
    }

    static pub pure fn from_frac_px(f: float) -> Au {
        Au((f * 60f) as i32)
    }

    static pub pure fn min(x: Au, y: Au) -> Au { if *x < *y { x } else { y } }
    static pub pure fn max(x: Au, y: Au) -> Au { if *x > *y { x } else { y } }
}

pub pure fn zero_rect() -> Rect<Au> {
    let z = Au(0);
    Rect(Point2D(z, z), Size2D(z, z))
}

pub pure fn zero_point() -> Point2D<Au> {
    Point2D(Au(0), Au(0))
}

pub pure fn zero_size() -> Size2D<Au> {
    Size2D(Au(0), Au(0))
}

pub pure fn from_frac_px(f: float) -> Au {
    Au((f * 60f) as i32)
}

pub pure fn from_px(i: int) -> Au {
    from_int(i * 60)
}

pub pure fn to_px(au: Au) -> int {
    (*au / 60) as int
}

pub pure fn to_frac_px(au: Au) -> float {
    (*au as float) / 60f
}

// assumes 72 points per inch, and 96 px per inch
pub pure fn from_pt(f: float) -> Au {
    from_px((f / 72f * 96f) as int)
}
<commit_msg>Add pixel-snapping method to Au.<commit_after>use geom::point::Point2D;
use geom::rect::Rect;
use geom::size::Size2D;
use num::{Num, from_int};

pub enum Au = i32;

impl Au : Num {
    pure fn add(other: &Au) -> Au        { Au(*self + **other) }
    pure fn sub(other: &Au) -> Au        { Au(*self - **other) }
    pure fn mul(other: &Au) -> Au        { Au(*self * **other) }
    pure fn div(other: &Au) -> Au        { Au(*self / **other) }
    pure fn modulo(other: &Au) -> Au     { Au(*self % **other) }
    pure fn neg() -> Au                   { Au(-*self)         }

    pure fn to_int() -> int               { *self as int       }

    static pure fn from_int(n: int) -> Au {
        Au((n & (i32::max_value as int)) as i32)
    }
}

impl Au : cmp::Ord {
    pure fn lt(other: &Au) -> bool { *self <  **other }
    pure fn le(other: &Au) -> bool { *self <= **other }
    pure fn ge(other: &Au) -> bool { *self >= **other }
    pure fn gt(other: &Au) -> bool { *self >  **other }
}

impl Au : cmp::Eq {
    pure fn eq(other: &Au) -> bool { *self == **other }
    pure fn ne(other: &Au) -> bool { *self != **other }
}

pub pure fn min(x: Au, y: Au) -> Au { if x < y { x } else { y } }
pub pure fn max(x: Au, y: Au) -> Au { if x > y { x } else { y } }

pub fn box<A:Copy Num>(x: A, y: A, w: A, h: A) -> Rect<A> {
    Rect(Point2D(x, y), Size2D(w, h))
}

impl Au {
    pub pure fn scale_by(factor: float) -> Au {
        Au(((*self as float) * factor) as i32)
    }

    static pub pure fn from_px(i: int) -> Au {
        from_int(i * 60)
    }

    pub pure fn to_px(&const self) -> int {
        (**self / 60) as int
    }

    pub pure fn to_snapped(&const self) -> Au {
        let res = **self % 60i32;
        return if res >= 30i32 { return Au(**self - res + 60i32) }
                       else { return Au(**self - res) };
    }

    static pub pure fn zero_point() -> Point2D<Au> {
        Point2D(Au(0), Au(0))
    }

    static pub pure fn zero_rect() -> Rect<Au> {
        let z = Au(0);
        Rect(Point2D(z, z), Size2D(z, z))
    }

    // assumes 72 points per inch, and 96 px per inch
    static pub pure fn from_pt(f: float) -> Au {
        from_px((f / 72f * 96f) as int)
    }

    static pub pure fn from_frac_px(f: float) -> Au {
        Au((f * 60f) as i32)
    }

    static pub pure fn min(x: Au, y: Au) -> Au { if *x < *y { x } else { y } }
    static pub pure fn max(x: Au, y: Au) -> Au { if *x > *y { x } else { y } }
}

pub pure fn zero_rect() -> Rect<Au> {
    let z = Au(0);
    Rect(Point2D(z, z), Size2D(z, z))
}

pub pure fn zero_point() -> Point2D<Au> {
    Point2D(Au(0), Au(0))
}

pub pure fn zero_size() -> Size2D<Au> {
    Size2D(Au(0), Au(0))
}

pub pure fn from_frac_px(f: float) -> Au {
    Au((f * 60f) as i32)
}

pub pure fn from_px(i: int) -> Au {
    from_int(i * 60)
}

pub pure fn to_px(au: Au) -> int {
    (*au / 60) as int
}

pub pure fn to_frac_px(au: Au) -> float {
    (*au as float) / 60f
}

// assumes 72 points per inch, and 96 px per inch
pub pure fn from_pt(f: float) -> Au {
    from_px((f / 72f * 96f) as int)
}
<|endoftext|>


<commit_before>extern crate html2text;
extern crate termion;
extern crate argparse;
use std::io::{self, Write};
use html2text::render::text_renderer::{RichAnnotation};
use argparse::{ArgumentParser, Store, StoreOption};

fn to_style(tag: &Vec<RichAnnotation>) -> String {
    let mut style = String::new();

    for ann in tag {
        match *ann {
            RichAnnotation::Default => (),
            RichAnnotation::Link(_) => {
                style.push_str(&format!("{}", termion::style::Underline));
            },
            RichAnnotation::Image => {
                style.push_str(&format!("{}", termion::color::Fg(termion::color::LightBlue)));
            },
        }
    }
    style
}

fn main() {
    let stdin = io::stdin();
    let mut filename = String::new();
    {
        let mut ap = ArgumentParser::new();
        /*
        ap.refer(&mut ini)
          .add_option(&["--init"], Store, "Set Lua init/config script path");
        ap.refer(&mut script)
          .add_option(&["--script"], Store, "Set Lua script path");
        ap.refer(&mut immcmd)
          .add_option(&["-c"], StoreOption, "Run Lua from the command line.  If specified, the main script (--script) is ignored.");
          */
        ap.refer(&mut filename)
          .add_argument("filename", Store, "Set HTML filename");
        ap.parse_args_or_exit();
    }

    let (width, _) = termion::terminal_size().unwrap();

    let mut file = std::fs::File::open(filename).expect("Tried to open file");
    let annotated = html2text::from_read_rich(&mut file, width as usize);
    for line in annotated {
        for (s, tag) in line.iter() {
            let style = to_style(tag);
            write!(io::stdout(), "{}{}{}", style, s, termion::style::Reset).unwrap();
        }
        write!(io::stdout(), "\n").unwrap();
    }
}<commit_msg>Remove commented out code.<commit_after>extern crate html2text;
extern crate termion;
extern crate argparse;
use std::io::{self, Write};
use html2text::render::text_renderer::{RichAnnotation};
use argparse::{ArgumentParser, Store, StoreOption};

fn to_style(tag: &Vec<RichAnnotation>) -> String {
    let mut style = String::new();

    for ann in tag {
        match *ann {
            RichAnnotation::Default => (),
            RichAnnotation::Link(_) => {
                style.push_str(&format!("{}", termion::style::Underline));
            },
            RichAnnotation::Image => {
                style.push_str(&format!("{}", termion::color::Fg(termion::color::LightBlue)));
            },
        }
    }
    style
}

fn main() {
    let stdin = io::stdin();
    let mut filename = String::new();
    {
        let mut ap = ArgumentParser::new();
        ap.refer(&mut filename)
          .add_argument("filename", Store, "Set HTML filename");
        ap.parse_args_or_exit();
    }

    let (width, _) = termion::terminal_size().unwrap();

    let mut file = std::fs::File::open(filename).expect("Tried to open file");
    let annotated = html2text::from_read_rich(&mut file, width as usize);
    for line in annotated {
        for (s, tag) in line.iter() {
            let style = to_style(tag);
            write!(io::stdout(), "{}{}{}", style, s, termion::style::Reset).unwrap();
        }
        write!(io::stdout(), "\n").unwrap();
    }
}<|endoftext|>


<commit_before>#![cfg(test)]

use std::sync::Arc;
use std::sync::atomic::{AtomicUsize, Ordering};

use Configuration;
use join;
use super::ThreadPool;
use unwind;

#[test]
#[should_panic(expected = "Hello, world!")]
fn panic_propagate() {
    let thread_pool = ThreadPool::new(Configuration::new()).unwrap();
    thread_pool.install(|| {
                            panic!("Hello, world!");
                        });
}

#[test]
fn workers_stop() {
    let registry;

    {
        // once we exit this block, thread-pool will be dropped
        let thread_pool = ThreadPool::new(Configuration::new().num_threads(22)).unwrap();
        registry = thread_pool.install(|| {
                                           // do some work on these threads
                                           join_a_lot(22);

                                           thread_pool.registry.clone()
                                       });
        assert_eq!(registry.num_threads(), 22);
    }

    // once thread-pool is dropped, registry should terminate, which
    // should lead to worker threads stopping
    registry.wait_until_stopped();
}

fn join_a_lot(n: usize) {
    if n > 0 {
        join(|| join_a_lot(n - 1), || join_a_lot(n - 1));
    }
}

#[test]
fn sleeper_stop() {
    use std::{thread, time};

    let registry;

    {
        // once we exit this block, thread-pool will be dropped
        let thread_pool = ThreadPool::new(Configuration::new().num_threads(22)).unwrap();
        registry = thread_pool.registry.clone();

        // Give time for at least some of the thread pool to fall asleep.
        thread::sleep(time::Duration::from_secs(1));
    }

    // once thread-pool is dropped, registry should terminate, which
    // should lead to worker threads stopping
    registry.wait_until_stopped();
}

/// Create a start/exit handler that increments an atomic counter.
fn count_handler() -> (Arc<AtomicUsize>, Box<::StartHandler>) {
    let count = Arc::new(AtomicUsize::new(0));
    (count.clone(), Box::new(move |_| { count.fetch_add(1, Ordering::SeqCst); }))
}

/// Immediately unwrap a counter, asserting that it's no longer shared.
fn unwrap_counter(counter: Arc<AtomicUsize>) -> usize {
    Arc::try_unwrap(counter)
        .expect("Counter is still shared!")
        .into_inner()
}

/// Wait until a counter is no longer shared, then return its value.
fn wait_for_counter(mut counter: Arc<AtomicUsize>) -> usize {
    use std::{thread, time};

    for _ in 0..60 {
        counter = match Arc::try_unwrap(counter) {
            Ok(counter) => return counter.into_inner(),
            Err(counter) => {
                thread::sleep(time::Duration::from_secs(1));
                counter
            }
        };
    }

    // That's too long -- do it now!
    unwrap_counter(counter)
}

/// For some reason, macs do not error out here.
#[cfg_attr(target_os="macos", ignore)]
#[test]
fn failed_thread_stack() {
    let (start_count, start_handler) = count_handler();
    let (exit_count, exit_handler) = count_handler();
    let config = Configuration::new()
        .stack_size(::std::usize::MAX)
        .start_handler(move |i| start_handler(i))
        .exit_handler(move |i| exit_handler(i));

    let pool = ThreadPool::new(config);
    assert!(pool.is_err(), "thread stack should have failed!");

    // With an impossible stack, we don't expect to have seen any threads,
    // nor should there be any remaining references to the counters.
    assert_eq!(0, unwrap_counter(start_count));
    assert_eq!(0, unwrap_counter(exit_count));
}

#[test]
fn panic_thread_name() {
    let (start_count, start_handler) = count_handler();
    let (exit_count, exit_handler) = count_handler();
    let config = Configuration::new()
        .num_threads(10)
        .start_handler(move |i| start_handler(i))
        .exit_handler(move |i| exit_handler(i))
        .thread_name(|i| {
                         if i >= 5 {
                             panic!();
                         }
                         format!("panic_thread_name#{}", i)
                     });

    let pool = unwind::halt_unwinding(|| ThreadPool::new(config));
    assert!(pool.is_err(), "thread-name panic should propagate!");

    // Assuming they're created in order, threads 0 through 4 should have
    // been started already, and then terminated by the panic.
    assert_eq!(5, wait_for_counter(start_count));
    assert_eq!(5, wait_for_counter(exit_count));
}
<commit_msg>Make `Builder::spawn` fail more consistently<commit_after>#![cfg(test)]

use std::sync::Arc;
use std::sync::atomic::{AtomicUsize, Ordering};

use Configuration;
use join;
use super::ThreadPool;
use unwind;

#[test]
#[should_panic(expected = "Hello, world!")]
fn panic_propagate() {
    let thread_pool = ThreadPool::new(Configuration::new()).unwrap();
    thread_pool.install(|| {
                            panic!("Hello, world!");
                        });
}

#[test]
fn workers_stop() {
    let registry;

    {
        // once we exit this block, thread-pool will be dropped
        let thread_pool = ThreadPool::new(Configuration::new().num_threads(22)).unwrap();
        registry = thread_pool.install(|| {
                                           // do some work on these threads
                                           join_a_lot(22);

                                           thread_pool.registry.clone()
                                       });
        assert_eq!(registry.num_threads(), 22);
    }

    // once thread-pool is dropped, registry should terminate, which
    // should lead to worker threads stopping
    registry.wait_until_stopped();
}

fn join_a_lot(n: usize) {
    if n > 0 {
        join(|| join_a_lot(n - 1), || join_a_lot(n - 1));
    }
}

#[test]
fn sleeper_stop() {
    use std::{thread, time};

    let registry;

    {
        // once we exit this block, thread-pool will be dropped
        let thread_pool = ThreadPool::new(Configuration::new().num_threads(22)).unwrap();
        registry = thread_pool.registry.clone();

        // Give time for at least some of the thread pool to fall asleep.
        thread::sleep(time::Duration::from_secs(1));
    }

    // once thread-pool is dropped, registry should terminate, which
    // should lead to worker threads stopping
    registry.wait_until_stopped();
}

/// Create a start/exit handler that increments an atomic counter.
fn count_handler() -> (Arc<AtomicUsize>, Box<::StartHandler>) {
    let count = Arc::new(AtomicUsize::new(0));
    (count.clone(), Box::new(move |_| { count.fetch_add(1, Ordering::SeqCst); }))
}

/// Wait until a counter is no longer shared, then return its value.
fn wait_for_counter(mut counter: Arc<AtomicUsize>) -> usize {
    use std::{thread, time};

    for _ in 0..60 {
        counter = match Arc::try_unwrap(counter) {
            Ok(counter) => return counter.into_inner(),
            Err(counter) => {
                thread::sleep(time::Duration::from_secs(1));
                counter
            }
        };
    }

    // That's too long!
    panic!("Counter is still shared!");
}

#[test]
fn failed_thread_stack() {
    // Note: we first tried to force failure with a `usize::MAX` stack, but
    // macOS and Windows weren't fazed, or at least didn't fail the way we want.
    // They work with `isize::MAX`, but 32-bit platforms may feasibly allocate a
    // 2GB stack, so it might not fail until the second thread.
    let stack_size = ::std::isize::MAX as usize;

    let (start_count, start_handler) = count_handler();
    let (exit_count, exit_handler) = count_handler();
    let config = Configuration::new()
        .num_threads(10)
        .stack_size(stack_size)
        .start_handler(move |i| start_handler(i))
        .exit_handler(move |i| exit_handler(i));

    let pool = ThreadPool::new(config);
    assert!(pool.is_err(), "thread stack should have failed!");

    // With such a huge stack, 64-bit will probably fail on the first thread;
    // 32-bit might manage the first 2GB, but certainly fail the second.
    let start_count = wait_for_counter(start_count);
    assert!(start_count <= 1);
    assert_eq!(start_count, wait_for_counter(exit_count));
}

#[test]
fn panic_thread_name() {
    let (start_count, start_handler) = count_handler();
    let (exit_count, exit_handler) = count_handler();
    let config = Configuration::new()
        .num_threads(10)
        .start_handler(move |i| start_handler(i))
        .exit_handler(move |i| exit_handler(i))
        .thread_name(|i| {
                         if i >= 5 {
                             panic!();
                         }
                         format!("panic_thread_name#{}", i)
                     });

    let pool = unwind::halt_unwinding(|| ThreadPool::new(config));
    assert!(pool.is_err(), "thread-name panic should propagate!");

    // Assuming they're created in order, threads 0 through 4 should have
    // been started already, and then terminated by the panic.
    assert_eq!(5, wait_for_counter(start_count));
    assert_eq!(5, wait_for_counter(exit_count));
}
<|endoftext|>


<commit_before>pub fn xor(lhs: &[u8], rhs: &[u8]) -> Vec<u8> {
    lhs.iter().zip(rhs).map(|(x, y)| x ^ y).collect()
}

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

    #[test]
    fn test_xor() {
        assert_eq!(vec![3, 1], xor(&[1, 2], &[2, 3]));
    }
}
<commit_msg>one-time pad encrypt and decrypt wrappers<commit_after>use std::io;
use key;

/// Currently doesn't accept a key because there should be only one key per message
pub fn encrypt(message: &[u8]) -> io::Result<(Vec<u8>, Vec<u8>)> {
    let key = key::new(message.len())?;
    let ciphertext = xor(&key, &message);
    Ok((key, ciphertext))
}

pub fn decrypt(key: &[u8], ciphertext: &[u8]) -> Vec<u8> {
    xor(&key, &ciphertext)
}

fn xor(lhs: &[u8], rhs: &[u8]) -> Vec<u8> {
    lhs.iter().zip(rhs).map(|(x, y)| x ^ y).collect()
}

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

    #[test]
    fn test_xor() {
        assert_eq!(vec![3, 1], xor(&[1, 2], &[2, 3]));
    }

    #[test]
    fn test_encrypt_decrypt() {
        fn check(message: &str) {
            let (key, ciphertext) = encrypt(message.as_bytes()).unwrap();
            assert_eq!(
                message,
                str::from_utf8(&decrypt(&key, &ciphertext)).unwrap()
            );
        }

        check("Hello!");
        check("How are you?");
        check("1 + 1 = 2");
    }
}
<|endoftext|>


<commit_before>#![feature(macro_rules)]
extern crate string_telephone;

use string_telephone::{ConnectionConfig, ClientConnectionConfig, Server, Packet, PollEmpty, PacketConnect, PacketMessage, PacketDisconnect, PollDisconnected, Command};
use std::io::net::ip::{Ipv4Addr, SocketAddr};
use std::time::duration::Duration;
use std::io::net::udp::UdpSocket;

mod test_shared;

macro_rules! with_bound_socket(
    (($variable:ident)$code:block) => (
        spawn(proc() {
            match UdpSocket::bind(SocketAddr{ ip: Ipv4Addr(0, 0, 0, 0), port: 0 }) {
                Ok(mut $variable) => $code,
                Err(e) => fail!(e)
            }
        });
    )
)

fn generate_settings(port: u16, protocol_id: u32) -> (SocketAddr, ConnectionConfig<Vec<u8>>) {
    let my_addr = SocketAddr{ ip: Ipv4Addr(127, 0, 0, 1), port: port };
    let settings = ConnectionConfig::new(protocol_id, Duration::seconds(10), test_shared::deserializer, test_shared::serializer);
    (my_addr, settings)
}

/**
 * Test we can start listening
 */
#[test]
fn create_server() {
    let socket = 64000;
    let (my_addr, settings) = generate_settings(socket, 121);
    match Server::new(my_addr, settings) {
        Ok(_) => (), //passed
        Err(t) => fail!("Failed to create a server - {}", t)
    };
}

/**
 * Test we get empty polls when we have no clients
 */
#[test]
fn empty_poll() {
    let socket = 64001;
    let (my_addr, settings) = generate_settings(socket, 121);
    match Server::new(my_addr, settings) {
        Ok(ref mut server) => {
            assert!(server.poll().is_none())
        },
        Err(t) => fail!("Failed to create a server - {}", t)
    };
}

/**
 * Test we reject bad connection attempts
 */
#[test]
fn bad_client_attempt() {
    let socket = 64002;
    let (my_addr, settings) = generate_settings(socket, 121);
    let (tx, rx) = channel();

    match Server::new(my_addr, settings) {
        Ok(ref mut server) => {
            with_bound_socket!((socket) {
                socket.send_to(Packet::connect(122).serialize().unwrap()[], my_addr).ok().expect("Couldn't send a message");
                tx.send(());
            });
            rx.recv();
            assert!(server.poll().is_none())
            assert!(server.all_connections().len() == 0);
        },
        Err(t) => fail!("Failed to create a server - {}", t)
    };
}

/**
 * Test we can take a single client
 */
#[test]
fn single_client() {
    let socket = 64003;
    let (my_addr, settings) = generate_settings(socket, 121);
    let (tx, rx) = channel();

    match Server::new(my_addr, settings) {
        Ok(ref mut server) => {
            with_bound_socket!((socket) {
                socket.send_to(Packet::connect(121).serialize().unwrap()[], my_addr).ok().expect("Couldn't send a message");
                tx.send(());
            });
            rx.recv();
            match server.poll() {
                Some((Command(PacketConnect), _))=> (),
                _ => fail!("Unexpected poll result")
            }
            assert!(server.all_connections().len() == 1);
        },
        Err(t) => fail!("Failed to create a server - {}", t)
    };
}

/**
 * Test we can take multiple clients
 */
#[test]
fn multiple_clients() {
    unimplemented!()
}

/**
 * Test we can cull old clients
 */
#[test]
fn cull() {
    unimplemented!()
}

/**
 * Test we can send to one
 */
#[test]
fn send_to_one() {
    unimplemented!()
}

/**
 * Test we can't send to folks who aren't connected
 */
#[test]
fn send_to_disconnected() {
    unimplemented!()
}

/**
 * Test we can send to multiple folks
 */
#[test]
fn send_to_many() {
    unimplemented!()
}

/**
 * Test we can send to everyone connected
 */
#[test]
fn send_to_all() {
    unimplemented!()
}
<commit_msg>Single client test case now works<commit_after>#![feature(macro_rules)]
extern crate string_telephone;

use string_telephone::{ConnectionConfig, ClientConnectionConfig, Server, Packet, PollEmpty, PacketConnect, PacketMessage, PacketDisconnect, PollDisconnected, Command};
use std::io::net::ip::{Ipv4Addr, SocketAddr};
use std::time::duration::Duration;
use std::io::net::udp::UdpSocket;
use std::io::Timer;

mod test_shared;

macro_rules! with_bound_socket(
    (($variable:ident)$code:block) => (
        spawn(proc() {
            match UdpSocket::bind(SocketAddr{ ip: Ipv4Addr(0, 0, 0, 0), port: 0 }) {
                Ok(mut $variable) => $code,
                Err(e) => fail!(e)
            }
        });
    )
)

fn generate_settings(port: u16, protocol_id: u32) -> (SocketAddr, ConnectionConfig<Vec<u8>>) {
    let my_addr = SocketAddr{ ip: Ipv4Addr(127, 0, 0, 1), port: port };
    let settings = ConnectionConfig::new(protocol_id, Duration::seconds(10), test_shared::deserializer, test_shared::serializer);
    (my_addr, settings)
}

/**
 * Test we can start listening
 */
#[test]
fn create_server() {
    let socket = 64000;
    let (my_addr, settings) = generate_settings(socket, 121);
    match Server::new(my_addr, settings) {
        Ok(_) => (), //passed
        Err(t) => fail!("Failed to create a server - {}", t)
    };
}

/**
 * Test we get empty polls when we have no clients
 */
#[test]
fn empty_poll() {
    let socket = 64001;
    let (my_addr, settings) = generate_settings(socket, 121);
    match Server::new(my_addr, settings) {
        Ok(ref mut server) => {
            assert!(server.poll().is_none())
        },
        Err(t) => fail!("Failed to create a server - {}", t)
    };
}

/**
 * Test we reject bad connection attempts
 */
#[test]
fn bad_client_attempt() {
    let socket = 64002;
    let (my_addr, settings) = generate_settings(socket, 121);
    let (tx, rx) = channel();

    match Server::new(my_addr, settings) {
        Ok(ref mut server) => {
            with_bound_socket!((socket) {
                socket.send_to(Packet::connect(122).serialize().unwrap()[], my_addr).ok().expect("Couldn't send a message");
                tx.send(());
            });
            rx.recv();
            Timer::new().unwrap().sleep(Duration::seconds(1));
            assert!(server.poll().is_none())
            assert!(server.all_connections().len() == 0);
        },
        Err(t) => fail!("Failed to create a server - {}", t)
    };
}

/**
 * Test we can take a single client
 */
#[test]
fn single_client() {
    let socket = 64003;
    let (my_addr, settings) = generate_settings(socket, 121);
    let (tx, rx) = channel();

    match Server::new(my_addr, settings) {
        Ok(ref mut server) => {
            with_bound_socket!((socket) {
                socket.send_to(Packet::connect(121).serialize().unwrap()[], my_addr).ok().expect("Couldn't send a message");
                tx.send(());
            });
            rx.recv();
            Timer::new().unwrap().sleep(Duration::seconds(1));
            match server.poll() {
                Some((Command(PacketConnect), _))=> (),
                None => fail!("No result found"),
                _ => fail!("Unexpected poll result")
            }
            assert!(server.all_connections().len() == 1);
        },
        Err(t) => fail!("Failed to create a server - {}", t)
    };
}

/**
 * Test we can take multiple clients
 */
#[test]
fn multiple_clients() {
    unimplemented!()
}

/**
 * Test we can cull old clients
 */
#[test]
fn cull() {
    unimplemented!()
}

/**
 * Test we can send to one
 */
#[test]
fn send_to_one() {
    unimplemented!()
}

/**
 * Test we can't send to folks who aren't connected
 */
#[test]
fn send_to_disconnected() {
    unimplemented!()
}

/**
 * Test we can send to multiple folks
 */
#[test]
fn send_to_many() {
    unimplemented!()
}

/**
 * Test we can send to everyone connected
 */
#[test]
fn send_to_all() {
    unimplemented!()
}
<|endoftext|>