<commit_before>#[macro_use]
extern crate clap;

extern crate regex;

use std::io::prelude::*;
use std::fs::File;
use std::collections::{VecDeque, BTreeSet, BTreeMap};
use regex::Regex;

type ElementId = usize;
type FloorNum = usize;

const BOTTOM_FLOOR: FloorNum = 0;
const TOP_FLOOR: FloorNum = 3;

#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
enum Item {
    Rtg(ElementId),
    Chip(ElementId),
}

impl Item {
    fn is_rtg(&self) -> bool {
        match *self {
            Item::Rtg(_) => true,
            Item::Chip(_) => false,
        }
    }
    fn is_chip(&self) -> bool {
        match *self {
            Item::Chip(_) => true,
            Item::Rtg(_) => false,
        }
    }
    fn element_id(&self) -> ElementId {
        match *self {
            Item::Chip(id) | Item::Rtg(id) => id,
        }
    }
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum Direction {
    Up,
    Down,
}

#[derive(Debug, Clone, PartialEq, Eq)]
struct Move {
    item1: Item,
    item2: Option<Item>,
    direction: Direction,
}

#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
struct CompareState {
    current_floor: FloorNum,
    pairs: Vec<(FloorNum, FloorNum)>, /* list of pairs, and each element within
                                       * each pair, must be kept in order */
}

#[derive(Debug, Clone, PartialEq, Eq)]
struct State {
    moves: Vec<Move>,
    current_floor: FloorNum,
    floors: Vec<BTreeSet<Item>>,
}

impl State {
    fn compare(&self) -> CompareState {
        let mut pairs = Vec::new();
        let mut unpaired = BTreeMap::new();
        for floor in 0..self.floors.len() {
            for item in &self.floors[floor] {
                if let Some(paired_floor) = unpaired.remove(&item.element_id()) {
                    if floor <= paired_floor {
                        pairs.push((floor, paired_floor));
                    } else {
                        pairs.push((paired_floor, floor));
                    }
                } else {
                    unpaired.insert(item.element_id(), floor);
                }
            }
        }
        if !unpaired.is_empty() {
            panic!("Set contained unpaired items! {:?}", unpaired);
        }
        pairs.sort();
        CompareState {
            current_floor: self.current_floor,
            pairs: pairs,
        }
    }
    fn possible_moves(&self) -> Vec<Move> {
        let mut moves = Vec::new();
        let floor_items = &self.floors[self.current_floor];
        for item1 in floor_items.iter().cloned() {
            for item2 in floor_items.iter()
                .cloned()
                .map(Some)
                .chain([None].iter().cloned()) {
                if item2 == Some(item1) {
                    continue;
                }
                if self.current_floor != TOP_FLOOR {
                    moves.push(Move {
                        item1: item1,
                        item2: item2,
                        direction: Direction::Up,
                    })
                }
                if self.current_floor != BOTTOM_FLOOR {
                    moves.push(Move {
                        item1: item1,
                        item2: item2,
                        direction: Direction::Down,
                    })
                }
            }
        }
        moves
    }
    fn make_move(&self, mov: Move) -> State {
        if self.current_floor == BOTTOM_FLOOR && mov.direction == Direction::Down ||
           self.current_floor == TOP_FLOOR && mov.direction == Direction::Up {
            panic!("tried to go to invalid floor");
        }
        let mut next = self.clone();
        next.current_floor = match mov.direction {
            Direction::Up => self.current_floor + 1,
            Direction::Down => self.current_floor - 1,
        };
        next.floors[self.current_floor].remove(&mov.item1);
        next.floors[next.current_floor].insert(mov.item1);
        if let Some(item) = mov.item2 {
            next.floors[self.current_floor].remove(&item);
            next.floors[next.current_floor].insert(item);
        }
        next.moves.push(mov);
        next
    }
    fn is_valid(&self) -> bool {
        for chip in self.floors[self.current_floor].iter().filter(|it| it.is_chip()) {
            let mut shielded = false;
            let mut in_danger = false;
            for rtg in self.floors[self.current_floor].iter().filter(|it| it.is_rtg()) {
                if chip.element_id() == rtg.element_id() {
                    shielded = true
                } else {
                    in_danger = true
                }
            }
            if !shielded && in_danger {
                return false;
            }
        }
        true
    }
    fn end_state(&self) -> CompareState {
        let mut end = State {
            moves: Vec::new(),
            current_floor: TOP_FLOOR,
            floors: vec![BTreeSet::new(); self.floors.len()],
        };
        for item in self.floors.iter().flat_map(|floor| floor.iter()) {
            end.floors[TOP_FLOOR].insert(*item);
        }
        end.compare()
    }
}

impl std::str::FromStr for State {
    type Err = String;
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        let microchip_re = Regex::new(r"(?P<elem>[:alpha:]+)-compatible microchip").unwrap();
        let rtg_re = Regex::new(r"(?P<elem>[:alpha:]+) generator").unwrap();
        let mut elem_ids = BTreeMap::new();
        let mut floors = vec![BTreeSet::new(); 4];
        let mut current_id = 0;
        let mut lines = s.lines();
        for mut floor in &mut floors {
            let line = match lines.next() {
                Some(l) => l,
                None => return Err("Not enough lines".into()),
            };
            for cap in microchip_re.captures_iter(line) {
                let elem_name = &cap["elem"];
                if !elem_ids.contains_key(elem_name) {
                    elem_ids.insert(elem_name.to_owned(), current_id);
                    current_id += 1;
                }
                floor.insert(Item::Chip(elem_ids[elem_name]));
            }
            for cap in rtg_re.captures_iter(line) {
                let elem_name = &cap["elem"];
                if !elem_ids.contains_key(elem_name) {
                    elem_ids.insert(elem_name.to_owned(), current_id);
                    current_id += 1;
                }
                floor.insert(Item::Rtg(elem_ids[elem_name]));
            }
        }
        Ok(State {
            moves: Vec::new(),
            current_floor: 0,
            floors: floors,
        })
    }
}

fn solve(begin: &State) -> Option<Vec<Move>> {
    let end = begin.end_state();
    let mut state_queue = VecDeque::new();
    state_queue.push_back(begin.clone());
    let mut visited = BTreeSet::new();
    visited.insert(begin.compare());
    while let Some(state) = state_queue.pop_front() {
        for mov in state.possible_moves() {
            let possibility = state.make_move(mov);
            let compare = possibility.compare();
            if possibility.is_valid() && !visited.contains(&compare) {
                if possibility.compare() == end {
                    return Some(possibility.moves);
                }
                state_queue.push_back(possibility);
                visited.insert(compare);
            }
        }
    }
    None
}

fn parse_args() -> std::io::Result<String> {
    let matches = clap::App::new("Day 10")
        .author("Devon Hollowood")
        .arg(clap::Arg::with_name("instructions")
            .index(1)
            .short("f")
            .long("instructions")
            .help("instructions to run. Reads from stdin otherwise")
            .takes_value(true))
        .get_matches();
    let source = matches.value_of_os("instructions");
    let mut contents = String::new();
    match source {
        Some(filename) => {
            let mut input = File::open(filename)?;
            input.read_to_string(&mut contents)?;
        }
        None => {
            let mut input = std::io::stdin();
            input.read_to_string(&mut contents)?;
        }
    }
    Ok(contents)
}

fn main() {
    let input = parse_args().unwrap_or_else(|err| panic!("Error reading input: {}", err));
    let begin: State = input.parse().unwrap_or_else(|err| panic!("Error parsing input: {}", err));
    match solve(&begin) {
        Some(moves) => println!("{}", moves.len()),
        None => println!("No solution found!"),
    }
}

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

    #[test]
    fn example() {
        use std::iter::FromIterator;
        let begin = State {
            moves: Vec::new(),
            current_floor: BOTTOM_FLOOR,
            floors: vec![
                BTreeSet::from_iter(vec![Item::Chip(0), Item::Chip(1)]),
                BTreeSet::from_iter(vec![Item::Rtg(0)]),
                BTreeSet::from_iter(vec![Item::Rtg(1)]),
                BTreeSet::new(),
            ],
        };
        if let Some(solution) = solve(&begin) {
            assert_eq!(solution.len(), 11)
        } else {
            panic!("No solution found!")
        }
    }
}
<commit_msg>Day 11 part 2<commit_after>#[macro_use]
extern crate clap;

extern crate regex;

use std::io::prelude::*;
use std::fs::File;
use std::collections::{VecDeque, BTreeSet, BTreeMap};
use regex::Regex;

type ElementId = usize;
type FloorNum = usize;

const BOTTOM_FLOOR: FloorNum = 0;
const TOP_FLOOR: FloorNum = 3;

#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
enum Item {
    Rtg(ElementId),
    Chip(ElementId),
}

impl Item {
    fn is_rtg(&self) -> bool {
        match *self {
            Item::Rtg(_) => true,
            Item::Chip(_) => false,
        }
    }
    fn is_chip(&self) -> bool {
        match *self {
            Item::Chip(_) => true,
            Item::Rtg(_) => false,
        }
    }
    fn element_id(&self) -> ElementId {
        match *self {
            Item::Chip(id) | Item::Rtg(id) => id,
        }
    }
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum Direction {
    Up,
    Down,
}

#[derive(Debug, Clone, PartialEq, Eq)]
struct Move {
    item1: Item,
    item2: Option<Item>,
    direction: Direction,
}

#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
struct CompareState {
    current_floor: FloorNum,
    pairs: Vec<(FloorNum, FloorNum)>, /* list of pairs, and each element within
                                       * each pair, must be kept in order */
}

#[derive(Debug, Clone, PartialEq, Eq)]
struct State {
    moves: Vec<Move>,
    current_floor: FloorNum,
    floors: Vec<BTreeSet<Item>>,
}

impl State {
    fn compare(&self) -> CompareState {
        let mut pairs = Vec::new();
        let mut unpaired = BTreeMap::new();
        for floor in 0..self.floors.len() {
            for item in &self.floors[floor] {
                if let Some(paired_floor) = unpaired.remove(&item.element_id()) {
                    if floor <= paired_floor {
                        pairs.push((floor, paired_floor));
                    } else {
                        pairs.push((paired_floor, floor));
                    }
                } else {
                    unpaired.insert(item.element_id(), floor);
                }
            }
        }
        if !unpaired.is_empty() {
            panic!("Set contained unpaired items! {:?}", unpaired);
        }
        pairs.sort();
        CompareState {
            current_floor: self.current_floor,
            pairs: pairs,
        }
    }
    fn possible_moves(&self) -> Vec<Move> {
        let mut moves = Vec::new();
        let floor_items = &self.floors[self.current_floor];
        for item1 in floor_items.iter().cloned() {
            for item2 in floor_items.iter()
                .cloned()
                .map(Some)
                .chain([None].iter().cloned()) {
                if item2 == Some(item1) {
                    continue;
                }
                if self.current_floor != TOP_FLOOR {
                    moves.push(Move {
                        item1: item1,
                        item2: item2,
                        direction: Direction::Up,
                    })
                }
                if self.current_floor != BOTTOM_FLOOR {
                    moves.push(Move {
                        item1: item1,
                        item2: item2,
                        direction: Direction::Down,
                    })
                }
            }
        }
        moves
    }
    fn make_move(&self, mov: Move) -> State {
        if self.current_floor == BOTTOM_FLOOR && mov.direction == Direction::Down ||
           self.current_floor == TOP_FLOOR && mov.direction == Direction::Up {
            panic!("tried to go to invalid floor");
        }
        let mut next = self.clone();
        next.current_floor = match mov.direction {
            Direction::Up => self.current_floor + 1,
            Direction::Down => self.current_floor - 1,
        };
        next.floors[self.current_floor].remove(&mov.item1);
        next.floors[next.current_floor].insert(mov.item1);
        if let Some(item) = mov.item2 {
            next.floors[self.current_floor].remove(&item);
            next.floors[next.current_floor].insert(item);
        }
        next.moves.push(mov);
        next
    }
    fn is_valid(&self) -> bool {
        for chip in self.floors[self.current_floor].iter().filter(|it| it.is_chip()) {
            let mut shielded = false;
            let mut in_danger = false;
            for rtg in self.floors[self.current_floor].iter().filter(|it| it.is_rtg()) {
                if chip.element_id() == rtg.element_id() {
                    shielded = true
                } else {
                    in_danger = true
                }
            }
            if !shielded && in_danger {
                return false;
            }
        }
        true
    }
    fn end_state(&self) -> CompareState {
        let mut end = State {
            moves: Vec::new(),
            current_floor: TOP_FLOOR,
            floors: vec![BTreeSet::new(); self.floors.len()],
        };
        for item in self.floors.iter().flat_map(|floor| floor.iter()) {
            end.floors[TOP_FLOOR].insert(*item);
        }
        end.compare()
    }
}

fn solve(begin: &State) -> Option<Vec<Move>> {
    let end = begin.end_state();
    let mut state_queue = VecDeque::new();
    state_queue.push_back(begin.clone());
    let mut visited = BTreeSet::new();
    visited.insert(begin.compare());
    while let Some(state) = state_queue.pop_front() {
        for mov in state.possible_moves() {
            let possibility = state.make_move(mov);
            let compare = possibility.compare();
            if possibility.is_valid() && !visited.contains(&compare) {
                if possibility.compare() == end {
                    return Some(possibility.moves);
                }
                state_queue.push_back(possibility);
                visited.insert(compare);
            }
        }
    }
    None
}

fn parse_state(s: &str) -> Result<(State, BTreeMap<String, ElementId>), String> {
    let microchip_re = Regex::new(r"(?P<elem>[:alpha:]+)-compatible microchip").unwrap();
    let rtg_re = Regex::new(r"(?P<elem>[:alpha:]+) generator").unwrap();
    let mut elem_ids = BTreeMap::new();
    let mut floors = vec![BTreeSet::new(); 4];
    let mut current_id = 0;
    let mut lines = s.lines();
    for mut floor in &mut floors {
        let line = match lines.next() {
            Some(l) => l,
            None => return Err("Not enough lines".into()),
        };
        for cap in microchip_re.captures_iter(line) {
            let elem_name = &cap["elem"];
            if !elem_ids.contains_key(elem_name) {
                elem_ids.insert(elem_name.to_owned(), current_id);
                current_id += 1;
            }
            floor.insert(Item::Chip(elem_ids[elem_name]));
        }
        for cap in rtg_re.captures_iter(line) {
            let elem_name = &cap["elem"];
            if !elem_ids.contains_key(elem_name) {
                elem_ids.insert(elem_name.to_owned(), current_id);
                current_id += 1;
            }
            floor.insert(Item::Rtg(elem_ids[elem_name]));
        }
    }
    Ok((State {
        moves: Vec::new(),
        current_floor: 0,
        floors: floors,
    },
        elem_ids))
}

fn parse_args() -> std::io::Result<String> {
    let matches = clap::App::new("Day 11")
        .author("Devon Hollowood")
        .arg(clap::Arg::with_name("manifest")
            .index(1)
            .short("f")
            .long("manifest")
            .help("manifest to solve. Reads from stdin otherwise")
            .takes_value(true))
        .get_matches();
    let source = matches.value_of_os("manifest");
    let mut contents = String::new();
    match source {
        Some(filename) => {
            let mut input = File::open(filename)?;
            input.read_to_string(&mut contents)?;
        }
        None => {
            let mut input = std::io::stdin();
            input.read_to_string(&mut contents)?;
        }
    }
    Ok(contents)
}

fn move_string(mov: &Move, id_elems: &BTreeMap<ElementId, String>) -> String {
    use std::fmt::Write;
    fn item_type(item: &Item) -> &str {
        match *item {
            Item::Rtg(_) => "RTG",
            Item::Chip(_) => "microchip",
        }
    }
    let mut s = String::new();
    write!(s,
           "Move {} {} ",
           id_elems[&mov.item1.element_id()],
           item_type(&mov.item1))
        .unwrap();
    if let Some(item) = mov.item2 {
        write!(s,
               "and {} {} ",
               id_elems[&item.element_id()],
               item_type(&item))
            .unwrap();
    }
    write!(s,
           "{}",
           match mov.direction {
               Direction::Up => "up",
               Direction::Down => "down",
           })
        .unwrap();
    s
}

fn main() {
    let input = parse_args().unwrap_or_else(|err| panic!("Error reading input: {}", err));
    let (begin1, mut elem_ids) = parse_state(&input)
        .unwrap_or_else(|err| panic!("Error parsing input: {}", err));
    let next_id = elem_ids.values().cloned().max().unwrap_or_default() + 1;
    elem_ids.insert("elerium".to_owned(), next_id);
    elem_ids.insert("dilithium".to_owned(), next_id + 1);
    let id_elems = elem_ids.into_iter().map(|(elem, id)| (id, elem)).collect();
    let mut begin2 = begin1.clone();
    begin2.floors[BOTTOM_FLOOR].extend(vec![Item::Rtg(next_id),
                                            Item::Chip(next_id),
                                            Item::Rtg(next_id + 1),
                                            Item::Chip(next_id + 1)]);
    let puzzles = [begin1, begin2];
    for puzzle_num in 1..puzzles.len() + 1 {
        match solve(&puzzles[puzzle_num - 1]) {
            Some(moves) => {
                println!("Part {} solution:", puzzle_num);
                for mov in &moves {
                    println!("{}", move_string(&mov, &id_elems));
                }
                println!("Number of moves (part {}): {}", puzzle_num, moves.len());
            }
            None => println!("No part {} solution found!", puzzle_num),
        }
        println!();
    }
}

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

    #[test]
    fn example() {
        use std::iter::FromIterator;
        let begin = State {
            moves: Vec::new(),
            current_floor: BOTTOM_FLOOR,
            floors: vec![
                BTreeSet::from_iter(vec![Item::Chip(0), Item::Chip(1)]),
                BTreeSet::from_iter(vec![Item::Rtg(0)]),
                BTreeSet::from_iter(vec![Item::Rtg(1)]),
                BTreeSet::new(),
            ],
        };
        if let Some(solution) = solve(&begin) {
            assert_eq!(solution.len(), 11)
        } else {
            panic!("No solution found!")
        }
    }
}
<|endoftext|>


<commit_before>use graphene::core::constraint::UnilaterallyConnectedGraph;
use crate::mock_graph::{MockGraph, MockEdgeWeight, MockVertexWeight};
use graphene::core::{Directed, ImplGraph, ImplGraphMut, Constrainer, Graph, AddEdge, NewVertex, Edge};
use crate::mock_graph::arbitrary::{GuidedArbGraph, Limit, ArbEdgeIn};
use std::collections::hash_map::RandomState;
use std::ops::RangeBounds;
use std::collections::HashSet;
use quickcheck::{Gen, Arbitrary};
use rand::Rng;

///
/// An arbitrary graph that is unilaterally connected
///
#[derive(Clone, Debug)]
pub struct ArbUnilatralGraph(pub UnilaterallyConnectedGraph<MockGraph<Directed>>);

impl ImplGraph for ArbUnilatralGraph
{
	type Graph = UnilaterallyConnectedGraph<MockGraph<Directed>>;

	fn graph(&self) -> &Self::Graph {
		&self.0
	}
}
impl ImplGraphMut for ArbUnilatralGraph
{
	fn graph_mut(&mut self) -> &mut Self::Graph {
		&mut self.0
	}
}

impl GuidedArbGraph for ArbUnilatralGraph
{
	fn arbitrary_guided<G: Gen>(g: &mut G, v_range: impl RangeBounds<usize>,
								e_range: impl RangeBounds<usize>) -> Self
	{
		let (v_min, v_max, e_min, e_max) = Self::validate_ranges(g, v_range, e_range);
		// If we are asked to make the singleton or empty graph, we just do
		if v_max <= 2 {
			return Self(UnilaterallyConnectedGraph::new(MockGraph::arbitrary_guided(g,
				v_min..v_max, e_min..e_max)))
		}

		// If the exact size of the graph hasn't been decided yet, do so.
		if (v_min + 1) != v_max {
			let v_count = g.gen_range(v_min, v_max);
			return Self::arbitrary_guided(g, v_count..v_count + 1, e_min..e_max)
		}

		let mut graph;
		// If the target is exactly 2 vertices, just create it
		if v_min == 2 {
			graph = MockGraph::empty();

			let v1 = graph.new_vertex_weighted(MockVertexWeight::arbitrary(g)).unwrap();
			let v2 = graph.new_vertex_weighted(MockVertexWeight::arbitrary(g)).unwrap();

			// Create a path between the edges to guarantee unilateralism.
			if g.gen_bool(0.5) {
				graph.add_edge_weighted((v1,v2,MockEdgeWeight::arbitrary(g))).unwrap();
			} else {
				graph.add_edge_weighted((v2,v1,MockEdgeWeight::arbitrary(g))).unwrap();
			}

			// Randomly add another edge
			if g.gen_bool(0.5) {
				if g.gen_bool(0.5) {
					graph.add_edge_weighted((v1,v2,MockEdgeWeight::arbitrary(g))).unwrap();
				} else {
					graph.add_edge_weighted((v2,v1,MockEdgeWeight::arbitrary(g))).unwrap();
				}
			}

		} else {
			// For larger graphs, we start by making a unilateral graph with 1 less vertex
			// and get an edge
			let ArbEdgeIn(graph, edge) = ArbEdgeIn::<Self>::
				arbitrary_guided(g, v_min-1..v_min, e_min..e_max);
			let mut graph = graph.0.unconstrain_single();

			// Add a new vertex to the graph
			let v = graph.new_vertex_weighted(MockVertexWeight::arbitrary(g)).unwrap();

			// Break the edge between the existing vertices, and substiture it with a path that
			// connects the existing vertices through the new vertex.

			unimplemented!()
		}

		Self(UnilaterallyConnectedGraph::new(graph))
	}

	fn shrink_guided(&self, _limits: HashSet<Limit, RandomState>) -> Box<dyn Iterator<Item=Self>> {
		unimplemented!()
	}
}

impl Arbitrary for ArbUnilatralGraph
{
	fn arbitrary<G: Gen>(g: &mut G) -> Self {
		let graph = Self::arbitrary_guided(g, .., ..).0.unconstrain_single();
		Self(UnilaterallyConnectedGraph::new(graph))
	}

	fn shrink(&self) -> Box<dyn Iterator<Item=Self>> {
		self.shrink_guided(HashSet::new())
	}
}

<commit_msg>Implemented GuidedArbGraph::arbitrary_guided() for ArbUnilateralGraph.<commit_after>use graphene::core::constraint::UnilaterallyConnectedGraph;
use crate::mock_graph::{MockGraph, MockEdgeWeight, MockVertexWeight};
use graphene::core::{Directed, ImplGraph, ImplGraphMut, RemoveEdge, Constrainer, Graph, AddEdge, NewVertex, Edge};
use crate::mock_graph::arbitrary::{GuidedArbGraph, Limit, ArbEdgeIn, ArbTwoVerticesIn, ArbVertexIn};
use std::collections::hash_map::RandomState;
use std::ops::RangeBounds;
use std::collections::HashSet;
use quickcheck::{Gen, Arbitrary};
use rand::Rng;

///
/// An arbitrary graph that is unilaterally connected
///
#[derive(Clone, Debug)]
pub struct ArbUnilatralGraph(pub UnilaterallyConnectedGraph<MockGraph<Directed>>);

impl ImplGraph for ArbUnilatralGraph
{
	type Graph = UnilaterallyConnectedGraph<MockGraph<Directed>>;

	fn graph(&self) -> &Self::Graph {
		&self.0
	}
}
impl ImplGraphMut for ArbUnilatralGraph
{
	fn graph_mut(&mut self) -> &mut Self::Graph {
		&mut self.0
	}
}

impl GuidedArbGraph for ArbUnilatralGraph
{
	fn arbitrary_guided<G: Gen>(g: &mut G, v_range: impl RangeBounds<usize>,
								e_range: impl RangeBounds<usize>) -> Self
	{
		let (v_min, v_max, e_min, e_max) = Self::validate_ranges(g, v_range, e_range);
		// If we are asked to make the empty graph, we just do
		if v_max <= 1{
			return Self(UnilaterallyConnectedGraph::new(MockGraph::arbitrary_guided(g,
				v_min..v_max, v_min..v_max)))
		}

		// If the exact size of the graph hasn't been decided yet, do so.
		if (v_min + 1) != v_max {
			let v_count = g.gen_range(v_min, v_max);
			return Self::arbitrary_guided(g, v_count..v_count + 1, e_min..e_max)
		}

		let mut graph;
		let v;
		// If the target is exactly 1 vertex, just create it
		if v_min == 1 {
			graph = MockGraph::empty();
			v = graph.new_vertex_weighted(MockVertexWeight::arbitrary(g)).unwrap();
		} else {
			// For larger graphs, we start by making a unilateral graph with 1 less vertex
			// and get an edge
			let arb = ArbVertexIn::<Self>::arbitrary_guided(g, v_min-1..v_min, e_min..e_max);
			graph = (arb.0).0.unconstrain_single();
			let v_original = arb.1;

			// Add a new vertex to the graph
			v = graph.new_vertex_weighted(MockVertexWeight::arbitrary(g)).unwrap();

			// Add an edge to/from the new and old vertices
			if g.gen_bool(0.5) {
				// To ensure unilateralism, take all outgoing edges from the original vertex
				// and move them to the new one.
				let outgoing_sinks  = graph.edges_sourced_in(v_original)
					.map(|e|  e.sink()).collect::<Vec<_>>();
				for sink in outgoing_sinks {
					let weight = graph.remove_edge((v_original, sink)).unwrap();
					graph.add_edge_weighted((v, sink, weight)).unwrap();
				}

				graph.add_edge_weighted((v_original, v, MockEdgeWeight::arbitrary(g))).unwrap();
			} else {
				// To ensure unilateralism, take all the incoming edges from the original vertex
				// and move them to the new one.
				let sources  = graph.edges_sinked_in(v_original)
					.map(|e|  e.source()).collect::<Vec<_>>();
				for source in sources {
					let weight = graph.remove_edge((source, v_original)).unwrap();
					graph.add_edge_weighted((source, v, weight)).unwrap();
				}

				graph.add_edge_weighted((v, v_original, MockEdgeWeight::arbitrary(g))).unwrap();

			}
		}

		// We now randomly create additional edges from/to the new vertex
		let p = 0.5/(v_min as f64);
		for v_other in graph.all_vertices().collect::<Vec<_>>() {
			if g.gen_bool(p) {
				graph.add_edge_weighted((v, v_other, MockEdgeWeight::arbitrary(g))).unwrap();
			}
			if g.gen_bool(p) {
				graph.add_edge_weighted((v_other, v, MockEdgeWeight::arbitrary(g))).unwrap();
			}
		}

		Self(UnilaterallyConnectedGraph::new(graph))
	}

	fn shrink_guided(&self, _limits: HashSet<Limit, RandomState>) -> Box<dyn Iterator<Item=Self>> {
		unimplemented!()
	}
}

impl Arbitrary for ArbUnilatralGraph
{
	fn arbitrary<G: Gen>(g: &mut G) -> Self {
		let graph = Self::arbitrary_guided(g, .., ..).0.unconstrain_single();
		Self(UnilaterallyConnectedGraph::new(graph))
	}

	fn shrink(&self) -> Box<dyn Iterator<Item=Self>> {
		self.shrink_guided(HashSet::new())
	}
}

<|endoftext|>


<commit_before>#![cfg(test)]

use problem1::{sum};
use problem2::{mat_mult};

#[test]
fn test_sum() {
    let array = [1,1,2,3,5,8];
    assert_eq!(sum(&array), 20);
}

#[test]
fn test_matmul() {
    let mat1 = vec![vec![1.;3]; 3];
    let mat2 = vec![vec![1.;3]; 3];
    let result = mat_mult(&mat1, &mat2);
    let desired = vec![vec![3.;3]; 3];
    for i in 0..result.len() {
        for j in 0..result[i].len() {
            assert_eq!(result[i][j], desired[i][j]);
        }
    }
}
<commit_msg>more tests<commit_after>#![cfg(test)]

use problem1::{sum};
use problem2::{mat_mult};
use problem3::{sieve};
use problem4::{hanoi,Peg};

//
// Problem 1
//

#[test]
fn test_sum() {
    let array = [1,1,2,3,5,8];
    assert_eq!(sum(&array), 20);
}

//
// Problem 2
//

#[test]
fn test_matmul() {
    let mat1 = vec![vec![1.;3]; 3];
    let mat2 = vec![vec![1.;3]; 3];
    let result = mat_mult(&mat1, &mat2);
    let desired = vec![vec![3.;3]; 3];
    for i in 0..result.len() {
        for j in 0..result[i].len() {
            assert_eq!(result[i][j], desired[i][j]);
        }
    }
}

//
// Problem 3
//

#[test]
fn test_sieve() {
    assert_eq!(vec![2,3,5,7,11,13,17,19,21], sieve(22));
}

//
// Problem 4
//

#[test]
fn test_hanoi_2_disks() {
    let result = hanoi(2, Peg::A, Peg::B, Peg::C);
    assert_eq!(vec![(Peg::A, Peg::B),
                    (Peg::A, Peg::C),
                    (Peg::B, Peg::C)], result);
    assert_eq!(3, result.len());
}
<|endoftext|>


<commit_before>extern crate capnp;
extern crate clap;

use std::io;
use std::process;

use clap::{Arg, App, SubCommand};

mod entry_capnp;

fn process_entry<R: io::Read>(mut from: &mut R, cmd: &Vec<&str>) -> io::Result<bool> {

    let entry = entry_capnp::read_entry(&mut from).expect("TODO: error type mapping");
    if entry.is_none() {
        return Ok(false);
    }

    let entry: entry_capnp::FileEntry = entry.unwrap();

    // skip others; assuming they're empty
    if !entry.normal_file {
        assert_eq!(0, entry.len);
        return Ok(true);
    }

    if !entry.content_follows {
        return Err(io::Error::new(io::ErrorKind::UnexpectedEof,
                                  "Can't do anything for contentless streams"));
    }

    let mut child = process::Command::new(cmd[0])
        .args(&cmd[1..])
        .env("TAR_REALNAME", join_backwards(&entry.paths, "/ /"))
        .env("TAR_FILENAME", entry.paths[0].to_string())
        .env("TAR_SIZE", format!("{}", entry.len))
        .stdin(process::Stdio::piped())
        .stdout(process::Stdio::inherit())
        .stderr(process::Stdio::inherit())
        .spawn()?;

    assert_eq!(entry.len, copy_upto(&mut from, &mut child.stdin.as_mut().unwrap(), entry.len)?);

    assert!(child.wait()?.success());

    Ok(true)
}

fn copy_upto<R: ?Sized, W: ?Sized>(reader: &mut R, writer: &mut W, how_much: u64) -> io::Result<u64>
    where R: io::Read, W: io::Write
{
    let mut buf = [0; 8 * 1024];
    let mut written = 0;
    loop {
        let max_to_read = std::cmp::min(how_much - written, buf.len() as u64) as usize;
        let len = match reader.read(&mut buf[0..max_to_read]) {
            Ok(0) => return Ok(written),
            Ok(len) => len,
            Err(ref e) if e.kind() == io::ErrorKind::Interrupted => continue,
            Err(e) => return Err(e),
        };
        writer.write_all(&buf[..len])?;
        written += len as u64;
    }
}

fn join_backwards(what: &Vec<String>, join: &str) -> String {
    let mut ret = String::with_capacity(what.len() * 40);

    for i in (1..(what.len() - 1)).rev() {
        ret.push_str(what[i].as_str());
        ret.push_str(join);
    }
    ret.push_str(what[0].as_str());
    ret
}

fn main() {
    match App::new("contentin")
        .setting(clap::AppSettings::SubcommandRequiredElseHelp)
        .subcommand(SubCommand::with_name("run")
                        .setting(clap::AppSettings::TrailingVarArg)
                        .setting(clap::AppSettings::DontDelimitTrailingValues)
                        .arg(Arg::with_name("sh")
                            .long("sh")
                            .help("Run with `sh -c`, and ssh-like quoting behaviour"))
//                      .arg(Arg::with_name("command-failure")
//                          .long("command-failure")
//                          .takes_value(true)
//                          .use_delimiter(false)
//                          .default_value("fatal")
//                          .possible_values(&[
//                              "fatal",
//                              "ignore",
//                          ])
                        .arg(Arg::with_name("command")
                            .required(true)
                            .help("Command to run, and its arguments")
                            .multiple(true))
        )
        .get_matches().subcommand() {

        ("run", Some(matches)) => {
            let raw_command: Vec<&str> = matches.values_of("command").unwrap().collect();
            let as_dumb_line = raw_command.join(" ");

            let cmd = if matches.is_present("sh") {
                vec!("sh", "-c", as_dumb_line.as_str())
            } else {
                raw_command
            };

            let stdin = io::stdin();
            while process_entry(&mut stdin.lock(), &cmd).expect("TODO: handle error") {
            }
        },
        _ => unreachable!(),
    }
}
<commit_msg>ci-pipe can cat; currently pretty useless<commit_after>extern crate capnp;
extern crate clap;

use std::io;
use std::process;

use clap::{Arg, App, SubCommand};

mod entry_capnp;

fn cat<R: io::Read, W: io::Write>(mut from: &mut R, mut to: &mut W) -> io::Result<bool> {
    let entry = entry_capnp::read_entry(&mut from).expect("TODO: error type mapping");
    if entry.is_none() {
        return Ok(false);
    }

    let entry: entry_capnp::FileEntry = entry.unwrap();

    assert_eq!(entry.len, copy_upto(&mut from, &mut to, entry.len)?);

    Ok(true)
}

fn direct_run<R: io::Read>(mut from: &mut R, cmd: &Vec<&str>) -> io::Result<bool> {

    let entry = entry_capnp::read_entry(&mut from).expect("TODO: error type mapping");
    if entry.is_none() {
        return Ok(false);
    }

    let entry: entry_capnp::FileEntry = entry.unwrap();

    // skip others; assuming they're empty
    if !entry.normal_file {
        assert_eq!(0, entry.len);
        return Ok(true);
    }

    if !entry.content_follows {
        return Err(io::Error::new(io::ErrorKind::UnexpectedEof,
                                  "Can't do anything for contentless streams"));
    }

    let mut child = process::Command::new(cmd[0])
        .args(&cmd[1..])
        .env("TAR_REALNAME", join_backwards(&entry.paths, "/ /"))
        .env("TAR_FILENAME", entry.paths[0].to_string())
        .env("TAR_SIZE", format!("{}", entry.len))
        .stdin(process::Stdio::piped())
        .stdout(process::Stdio::inherit())
        .stderr(process::Stdio::inherit())
        .spawn()?;

    assert_eq!(entry.len, copy_upto(&mut from, &mut child.stdin.as_mut().unwrap(), entry.len)?);

    assert!(child.wait()?.success());

    Ok(true)
}

fn copy_upto<R: ?Sized, W: ?Sized>(reader: &mut R, writer: &mut W, how_much: u64) -> io::Result<u64>
    where R: io::Read, W: io::Write
{
    let mut buf = [0; 8 * 1024];
    let mut written = 0;
    loop {
        let max_to_read = std::cmp::min(how_much - written, buf.len() as u64) as usize;
        let len = match reader.read(&mut buf[0..max_to_read]) {
            Ok(0) => return Ok(written),
            Ok(len) => len,
            Err(ref e) if e.kind() == io::ErrorKind::Interrupted => continue,
            Err(e) => return Err(e),
        };
        writer.write_all(&buf[..len])?;
        written += len as u64;
    }
}

fn join_backwards(what: &Vec<String>, join: &str) -> String {
    let mut ret = String::with_capacity(what.len() * 40);

    for i in (1..(what.len() - 1)).rev() {
        ret.push_str(what[i].as_str());
        ret.push_str(join);
    }
    ret.push_str(what[0].as_str());
    ret
}

fn main() {
    let from = io::stdin();
    let mut from = from.lock();

    match App::new("contentin")
        .setting(clap::AppSettings::SubcommandRequiredElseHelp)
        .subcommand(SubCommand::with_name("run")
                        .setting(clap::AppSettings::TrailingVarArg)
                        .setting(clap::AppSettings::DontDelimitTrailingValues)
                        .arg(Arg::with_name("sh")
                            .long("sh")
                            .help("Run with `sh -c`, and ssh-like quoting behaviour"))
//                      .arg(Arg::with_name("command-failure")
//                          .long("command-failure")
//                          .takes_value(true)
//                          .use_delimiter(false)
//                          .default_value("fatal")
//                          .possible_values(&[
//                              "fatal",
//                              "ignore",
//                          ])
                        .arg(Arg::with_name("command")
                            .required(true)
                            .help("Command to run, and its arguments")
                            .multiple(true))
        )
        .subcommand(SubCommand::with_name("cat")
        )
        .get_matches().subcommand() {
        ("cat", Some(_)) => {
            let stdout = io::stdout();
            let mut stdout = stdout.lock();
            while cat(&mut from, &mut stdout).expect("TODO: handle error") {
            }
        }
        ("run", Some(matches)) => {
            let raw_command: Vec<&str> = matches.values_of("command").unwrap().collect();
            let as_dumb_line = raw_command.join(" ");

            let cmd = if matches.is_present("sh") {
                vec!("sh", "-c", as_dumb_line.as_str())
            } else {
                raw_command
            };

            while direct_run(&mut from, &cmd).expect("TODO: handle error") {
            }
        },
        _ => unreachable!(),
    }
}
<|endoftext|>


<commit_before>fn main() {
	let subject = "world";

    println!("Hello, {}!", subject);
    println!("Goodbye, {}!", subject);
}
<commit_msg>Save code after episode is recorded<commit_after>fn main() {
	let mut subject = "world";

    println!("Hello, {}!", subject);
    println!("Goodbye, {}!", subject);

    subject = "moon";

    println!("Hello, {}!", subject);
    println!("Goodbye, {}!", subject);
}
<|endoftext|>


<commit_before>#![feature(plugin)]
#![plugin(rocket_codegen)]

extern crate rocket;

#[cfg(test)] mod tests;

#[get("/hello/<name>/<age>")]
fn hello(name: &str, age: i8) -> String {
    format!("Hello, {} year old named {}!", age, name)
}

#[get("/hello/<name>")]
fn hi<'r>(name: &'r str) -> &'r str {
    name
}

fn main() {
    rocket::ignite().mount("/<test>", routes![hello, hi]).launch();
}
<commit_msg>Revert hello_person to pre-testing.<commit_after>#![feature(plugin)]
#![plugin(rocket_codegen)]

extern crate rocket;

#[cfg(test)] mod tests;

#[get("/hello/<name>/<age>")]
fn hello(name: &str, age: i8) -> String {
    format!("Hello, {} year old named {}!", age, name)
}

#[get("/hello/<name>")]
fn hi<'r>(name: &'r str) -> &'r str {
    name
}

fn main() {
    rocket::ignite().mount("/", routes![hello, hi]).launch();
}
<|endoftext|>


<commit_before>// * This file is part of the uutils coreutils package.
// *
// * (c) 2015 Wiktor Kuropatwa <wiktor.kuropatwa@gmail.com>
// * (c) 2020 nicoo            <nicoo@debian.org>
// *
// * For the full copyright and license information, please view the LICENSE file
// * that was distributed with this source code.

use num_traits::{
    identities::{One, Zero},
    int::PrimInt,
    ops::wrapping::{WrappingMul, WrappingNeg, WrappingSub},
};
use std::fmt::{Debug, Display};
use std::mem::swap;

// This is incorrectly reported as dead code,
//  presumably when included in build.rs.
#[allow(dead_code)]
pub(crate) fn gcd(mut a: u64, mut b: u64) -> u64 {
    while b > 0 {
        a %= b;
        swap(&mut a, &mut b);
    }
    a
}

pub(crate) trait Arithmetic: Copy + Sized {
    // The type of integers mod m, in some opaque representation
    type ModInt: Copy + Sized + Eq;

    fn new(m: u64) -> Self;
    fn modulus(&self) -> u64;
    fn from_u64(&self, n: u64) -> Self::ModInt;
    fn to_u64(&self, n: Self::ModInt) -> u64;
    fn add(&self, a: Self::ModInt, b: Self::ModInt) -> Self::ModInt;
    fn mul(&self, a: Self::ModInt, b: Self::ModInt) -> Self::ModInt;

    fn pow(&self, mut a: Self::ModInt, mut b: u64) -> Self::ModInt {
        let (_a, _b) = (a, b);
        let mut result = self.one();
        while b > 0 {
            if b & 1 != 0 {
                result = self.mul(result, a);
            }
            a = self.mul(a, a);
            b >>= 1;
        }

        // Check that r (reduced back to the usual representation) equals
        //  a^b % n, unless the latter computation overflows
        // Temporarily commented-out, as there u64::checked_pow is not available
        //  on the minimum supported Rust version, nor is an appropriate method
        //  for compiling the check conditionally.
        //debug_assert!(self
        //    .to_u64(_a)
        //    .checked_pow(_b as u32)
        //    .map(|r| r % self.modulus() == self.to_u64(result))
        //    .unwrap_or(true));

        result
    }

    fn one(&self) -> Self::ModInt {
        self.from_u64(1)
    }
    fn minus_one(&self) -> Self::ModInt {
        self.from_u64(self.modulus() - 1)
    }
    fn zero(&self) -> Self::ModInt {
        self.from_u64(0)
    }
}

#[derive(Clone, Copy, Debug)]
pub(crate) struct Montgomery<T: DoubleInt> {
    a: T,
    n: T,
}

impl<T: DoubleInt> Montgomery<T> {
    /// computes x/R mod n efficiently
    fn reduce(&self, x: T::Double) -> T {
        let t_bits = T::zero().count_zeros() as usize;

        debug_assert!(x < (self.n.as_double()) << t_bits);
        // TODO: optimiiiiiiise
        let Montgomery { a, n } = self;
        let m = T::from_double(x).wrapping_mul(a);
        let nm = (n.as_double()) * (m.as_double());
        let (xnm, overflow) = x.overflowing_add_(nm); // x + n*m
        debug_assert_eq!(
            xnm % (T::Double::one() << T::zero().count_zeros() as usize),
            T::Double::zero()
        );

        // (x + n*m) / R
        // in case of overflow, this is (2¹²⁸ + xnm)/2⁶⁴ - n = xnm/2⁶⁴ + (2⁶⁴ - n)
        let y = T::from_double(xnm >> t_bits)
            + if !overflow {
                T::zero()
            } else {
                n.wrapping_neg()
            };

        if y >= *n {
            y - *n
        } else {
            y
        }
    }
}

impl<T: DoubleInt> Arithmetic for Montgomery<T> {
    // Montgomery transform, R=2⁶⁴
    // Provides fast arithmetic mod n (n odd, u64)
    type ModInt = T;

    fn new(n: u64) -> Self {
        debug_assert!(T::zero().count_zeros() >= 64 || n < (1 << T::zero().count_zeros() as usize));
        let n = T::from_u64(n);
        let a = modular_inverse(n).wrapping_neg();
        debug_assert_eq!(n.wrapping_mul(&a), T::one().wrapping_neg());
        Montgomery { a, n }
    }

    fn modulus(&self) -> u64 {
        self.n.as_u64()
    }

    fn from_u64(&self, x: u64) -> Self::ModInt {
        // TODO: optimise!
        debug_assert!(x < self.n.as_u64());
        let r = T::from_double(
            ((T::Double::from_u64(x)) << T::zero().count_zeros() as usize) % self.n.as_double(),
        );
        debug_assert_eq!(x, self.to_u64(r));
        r
    }

    fn to_u64(&self, n: Self::ModInt) -> u64 {
        self.reduce(n.as_double()).as_u64()
    }

    fn add(&self, a: Self::ModInt, b: Self::ModInt) -> Self::ModInt {
        let (r, overflow) = a.overflowing_add_(b);

        // In case of overflow, a+b = 2⁶⁴ + r = (2⁶⁴ - n) + r (working mod n)
        let r = if !overflow {
            r
        } else {
            r + self.n.wrapping_neg()
        };

        // Normalise to [0; n[
        let r = if r < self.n { r } else { r - self.n };

        // Check that r (reduced back to the usual representation) equals
        // a+b % n
        #[cfg(debug_assertions)]
        {
            let a_r = self.to_u64(a) as u128;
            let b_r = self.to_u64(b) as u128;
            let r_r = self.to_u64(r);
            let r_2 = ((a_r + b_r) % self.n.as_u128()) as u64;
            debug_assert_eq!(
                r_r, r_2,
                "[{}] = {} ≠ {} = {} + {} = [{}] + [{}] mod {}; a = {}",
                r, r_r, r_2, a_r, b_r, a, b, self.n, self.a
            );
        }
        r
    }

    fn mul(&self, a: Self::ModInt, b: Self::ModInt) -> Self::ModInt {
        let r = self.reduce(a.as_double() * b.as_double());

        // Check that r (reduced back to the usual representation) equals
        // a*b % n
        #[cfg(debug_assertions)]
        {
            let a_r = self.to_u64(a) as u128;
            let b_r = self.to_u64(b) as u128;
            let r_r = self.to_u64(r);
            let r_2: u64 = ((a_r * b_r) % self.n.as_u128()) as u64;
            debug_assert_eq!(
                r_r, r_2,
                "[{}] = {} ≠ {} = {} * {} = [{}] * [{}] mod {}; a = {}",
                r, r_r, r_2, a_r, b_r, a, b, self.n, self.a
            );
        }
        r
    }
}

// NOTE: Trait can be removed once num-traits adds a similar one;
//       see https://github.com/rust-num/num-traits/issues/168
pub(crate) trait OverflowingAdd: Sized {
    fn overflowing_add_(self, n: Self) -> (Self, bool);
}
impl OverflowingAdd for u32 {
    fn overflowing_add_(self, n: Self) -> (Self, bool) {
        self.overflowing_add(n)
    }
}
impl OverflowingAdd for u64 {
    fn overflowing_add_(self, n: Self) -> (Self, bool) {
        self.overflowing_add(n)
    }
}
impl OverflowingAdd for u128 {
    fn overflowing_add_(self, n: Self) -> (Self, bool) {
        self.overflowing_add(n)
    }
}

pub(crate) trait Int:
    Display + Debug + PrimInt + OverflowingAdd + WrappingNeg + WrappingSub + WrappingMul
{
    fn as_u64(&self) -> u64;
    fn from_u64(n: u64) -> Self;
    #[cfg(debug_assertions)]
    fn as_u128(&self) -> u128;
    #[cfg(debug_assertions)]
    fn from_u128(n: u64) -> Self;
}

pub(crate) trait DoubleInt: Int {
    type Double: Int;

    fn as_double(self) -> Self::Double;
    fn from_double(n: Self::Double) -> Self;
}

impl Int for u32 {
    fn as_u64(&self) -> u64 {
        *self as _
    }
    fn from_u64(n: u64) -> Self {
        n as _
    }
    #[cfg(debug_assertions)]
    fn as_u128(&self) -> u128 {
        *self as _
    }
    #[cfg(debug_assertions)]
    fn from_u128(n: u64) -> Self {
        n as _
    }
}
impl Int for u64 {
    fn as_u64(&self) -> u64 {
        *self as _
    }
    fn from_u64(n: u64) -> Self {
        n as _
    }
    #[cfg(debug_assertions)]
    fn as_u128(&self) -> u128 {
        *self as _
    }
    #[cfg(debug_assertions)]
    fn from_u128(n: u64) -> Self {
        n as _
    }
}
impl Int for u128 {
    fn as_u64(&self) -> u64 {
        *self as _
    }
    fn from_u64(n: u64) -> Self {
        n as _
    }
    #[cfg(debug_assertions)]
    fn as_u128(&self) -> u128 {
        *self as _
    }
    #[cfg(debug_assertions)]
    fn from_u128(n: u64) -> Self {
        n as _
    }
}

impl DoubleInt for u64 {
    type Double = u128;

    fn as_double(self) -> u128 {
        self as _
    }
    fn from_double(n: u128) -> u64 {
        n as _
    }
}
impl DoubleInt for u32 {
    type Double = u64;

    fn as_double(self) -> u64 {
        self as _
    }
    fn from_double(n: u64) -> u32 {
        n as _
    }
}

// extended Euclid algorithm
// precondition: a is odd
pub(crate) fn modular_inverse<T: Int>(a: T) -> T {
    let zero = T::zero();
    let one = T::one();
    debug_assert!(a % (one + one) == one, "{:?} is not odd", a);

    let mut t = zero;
    let mut newt = one;
    let mut r = zero;
    let mut newr = a;

    while newr != zero {
        let quot = if r == zero {
            // special case when we're just starting out
            // This works because we know that
            // a does not divide 2^64, so floor(2^64 / a) == floor((2^64-1) / a);
            T::max_value()
        } else {
            r
        } / newr;

        let newtp = t.wrapping_sub(&quot.wrapping_mul(&newt));
        t = newt;
        newt = newtp;

        let newrp = r.wrapping_sub(&quot.wrapping_mul(&newr));
        r = newr;
        newr = newrp;
    }

    debug_assert_eq!(r, one);
    t
}

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

    fn test_inverter<T: Int>() {
        // All odd integers from 1 to 20 000
        let one = T::from(1).unwrap();
        let two = T::from(2).unwrap();
        let mut test_values = (0..10_000)
            .map(|i| T::from(i).unwrap())
            .map(|i| two * i + one);

        assert!(test_values.all(|x| x.wrapping_mul(&modular_inverse(x)) == one));
    }

    #[test]
    fn test_inverter_u32() {
        test_inverter::<u32>()
    }

    #[test]
    fn test_inverter_u64() {
        test_inverter::<u64>()
    }

    fn test_add<A: Arithmetic>() {
        for n in 0..100 {
            let n = 2 * n + 1;
            let m = A::new(n);
            for x in 0..n {
                let m_x = m.from_u64(x);
                for y in 0..=x {
                    let m_y = m.from_u64(y);
                    println!("{n:?}, {x:?}, {y:?}", n = n, x = x, y = y);
                    assert_eq!((x + y) % n, m.to_u64(m.add(m_x, m_y)));
                }
            }
        }
    }

    #[test]
    fn test_add_m32() {
        test_add::<Montgomery<u32>>()
    }

    #[test]
    fn test_add_m64() {
        test_add::<Montgomery<u64>>()
    }

    fn test_mult<A: Arithmetic>() {
        for n in 0..100 {
            let n = 2 * n + 1;
            let m = A::new(n);
            for x in 0..n {
                let m_x = m.from_u64(x);
                for y in 0..=x {
                    let m_y = m.from_u64(y);
                    assert_eq!((x * y) % n, m.to_u64(m.mul(m_x, m_y)));
                }
            }
        }
    }

    #[test]
    fn test_mult_m32() {
        test_mult::<Montgomery<u32>>()
    }

    #[test]
    fn test_mult_m64() {
        test_mult::<Montgomery<u64>>()
    }

    fn test_roundtrip<A: Arithmetic>() {
        for n in 0..100 {
            let n = 2 * n + 1;
            let m = A::new(n);
            for x in 0..n {
                let x_ = m.from_u64(x);
                assert_eq!(x, m.to_u64(x_));
            }
        }
    }

    #[test]
    fn test_roundtrip_m32() {
        test_roundtrip::<Montgomery<u32>>()
    }

    #[test]
    fn test_roundtrip_m64() {
        test_roundtrip::<Montgomery<u64>>()
    }
}
<commit_msg>factor::numeric: Generate implementations of Int with a macro<commit_after>// * This file is part of the uutils coreutils package.
// *
// * (c) 2015 Wiktor Kuropatwa <wiktor.kuropatwa@gmail.com>
// * (c) 2020 nicoo            <nicoo@debian.org>
// *
// * For the full copyright and license information, please view the LICENSE file
// * that was distributed with this source code.

use num_traits::{
    identities::{One, Zero},
    int::PrimInt,
    ops::wrapping::{WrappingMul, WrappingNeg, WrappingSub},
};
use std::fmt::{Debug, Display};
use std::mem::swap;

// This is incorrectly reported as dead code,
//  presumably when included in build.rs.
#[allow(dead_code)]
pub(crate) fn gcd(mut a: u64, mut b: u64) -> u64 {
    while b > 0 {
        a %= b;
        swap(&mut a, &mut b);
    }
    a
}

pub(crate) trait Arithmetic: Copy + Sized {
    // The type of integers mod m, in some opaque representation
    type ModInt: Copy + Sized + Eq;

    fn new(m: u64) -> Self;
    fn modulus(&self) -> u64;
    fn from_u64(&self, n: u64) -> Self::ModInt;
    fn to_u64(&self, n: Self::ModInt) -> u64;
    fn add(&self, a: Self::ModInt, b: Self::ModInt) -> Self::ModInt;
    fn mul(&self, a: Self::ModInt, b: Self::ModInt) -> Self::ModInt;

    fn pow(&self, mut a: Self::ModInt, mut b: u64) -> Self::ModInt {
        let (_a, _b) = (a, b);
        let mut result = self.one();
        while b > 0 {
            if b & 1 != 0 {
                result = self.mul(result, a);
            }
            a = self.mul(a, a);
            b >>= 1;
        }

        // Check that r (reduced back to the usual representation) equals
        //  a^b % n, unless the latter computation overflows
        // Temporarily commented-out, as there u64::checked_pow is not available
        //  on the minimum supported Rust version, nor is an appropriate method
        //  for compiling the check conditionally.
        //debug_assert!(self
        //    .to_u64(_a)
        //    .checked_pow(_b as u32)
        //    .map(|r| r % self.modulus() == self.to_u64(result))
        //    .unwrap_or(true));

        result
    }

    fn one(&self) -> Self::ModInt {
        self.from_u64(1)
    }
    fn minus_one(&self) -> Self::ModInt {
        self.from_u64(self.modulus() - 1)
    }
    fn zero(&self) -> Self::ModInt {
        self.from_u64(0)
    }
}

#[derive(Clone, Copy, Debug)]
pub(crate) struct Montgomery<T: DoubleInt> {
    a: T,
    n: T,
}

impl<T: DoubleInt> Montgomery<T> {
    /// computes x/R mod n efficiently
    fn reduce(&self, x: T::Double) -> T {
        let t_bits = T::zero().count_zeros() as usize;

        debug_assert!(x < (self.n.as_double()) << t_bits);
        // TODO: optimiiiiiiise
        let Montgomery { a, n } = self;
        let m = T::from_double(x).wrapping_mul(a);
        let nm = (n.as_double()) * (m.as_double());
        let (xnm, overflow) = x.overflowing_add_(nm); // x + n*m
        debug_assert_eq!(
            xnm % (T::Double::one() << T::zero().count_zeros() as usize),
            T::Double::zero()
        );

        // (x + n*m) / R
        // in case of overflow, this is (2¹²⁸ + xnm)/2⁶⁴ - n = xnm/2⁶⁴ + (2⁶⁴ - n)
        let y = T::from_double(xnm >> t_bits)
            + if !overflow {
                T::zero()
            } else {
                n.wrapping_neg()
            };

        if y >= *n {
            y - *n
        } else {
            y
        }
    }
}

impl<T: DoubleInt> Arithmetic for Montgomery<T> {
    // Montgomery transform, R=2⁶⁴
    // Provides fast arithmetic mod n (n odd, u64)
    type ModInt = T;

    fn new(n: u64) -> Self {
        debug_assert!(T::zero().count_zeros() >= 64 || n < (1 << T::zero().count_zeros() as usize));
        let n = T::from_u64(n);
        let a = modular_inverse(n).wrapping_neg();
        debug_assert_eq!(n.wrapping_mul(&a), T::one().wrapping_neg());
        Montgomery { a, n }
    }

    fn modulus(&self) -> u64 {
        self.n.as_u64()
    }

    fn from_u64(&self, x: u64) -> Self::ModInt {
        // TODO: optimise!
        debug_assert!(x < self.n.as_u64());
        let r = T::from_double(
            ((T::Double::from_u64(x)) << T::zero().count_zeros() as usize) % self.n.as_double(),
        );
        debug_assert_eq!(x, self.to_u64(r));
        r
    }

    fn to_u64(&self, n: Self::ModInt) -> u64 {
        self.reduce(n.as_double()).as_u64()
    }

    fn add(&self, a: Self::ModInt, b: Self::ModInt) -> Self::ModInt {
        let (r, overflow) = a.overflowing_add_(b);

        // In case of overflow, a+b = 2⁶⁴ + r = (2⁶⁴ - n) + r (working mod n)
        let r = if !overflow {
            r
        } else {
            r + self.n.wrapping_neg()
        };

        // Normalise to [0; n[
        let r = if r < self.n { r } else { r - self.n };

        // Check that r (reduced back to the usual representation) equals
        // a+b % n
        #[cfg(debug_assertions)]
        {
            let a_r = self.to_u64(a) as u128;
            let b_r = self.to_u64(b) as u128;
            let r_r = self.to_u64(r);
            let r_2 = ((a_r + b_r) % self.n.as_u128()) as u64;
            debug_assert_eq!(
                r_r, r_2,
                "[{}] = {} ≠ {} = {} + {} = [{}] + [{}] mod {}; a = {}",
                r, r_r, r_2, a_r, b_r, a, b, self.n, self.a
            );
        }
        r
    }

    fn mul(&self, a: Self::ModInt, b: Self::ModInt) -> Self::ModInt {
        let r = self.reduce(a.as_double() * b.as_double());

        // Check that r (reduced back to the usual representation) equals
        // a*b % n
        #[cfg(debug_assertions)]
        {
            let a_r = self.to_u64(a) as u128;
            let b_r = self.to_u64(b) as u128;
            let r_r = self.to_u64(r);
            let r_2: u64 = ((a_r * b_r) % self.n.as_u128()) as u64;
            debug_assert_eq!(
                r_r, r_2,
                "[{}] = {} ≠ {} = {} * {} = [{}] * [{}] mod {}; a = {}",
                r, r_r, r_2, a_r, b_r, a, b, self.n, self.a
            );
        }
        r
    }
}

// NOTE: Trait can be removed once num-traits adds a similar one;
//       see https://github.com/rust-num/num-traits/issues/168
pub(crate) trait OverflowingAdd: Sized {
    fn overflowing_add_(self, n: Self) -> (Self, bool);
}
impl OverflowingAdd for u32 {
    fn overflowing_add_(self, n: Self) -> (Self, bool) {
        self.overflowing_add(n)
    }
}
impl OverflowingAdd for u64 {
    fn overflowing_add_(self, n: Self) -> (Self, bool) {
        self.overflowing_add(n)
    }
}
impl OverflowingAdd for u128 {
    fn overflowing_add_(self, n: Self) -> (Self, bool) {
        self.overflowing_add(n)
    }
}

pub(crate) trait Int:
    Display + Debug + PrimInt + OverflowingAdd + WrappingNeg + WrappingSub + WrappingMul
{
    fn as_u64(&self) -> u64;
    fn from_u64(n: u64) -> Self;
    #[cfg(debug_assertions)]
    fn as_u128(&self) -> u128;
    #[cfg(debug_assertions)]
    fn from_u128(n: u64) -> Self;
}

pub(crate) trait DoubleInt: Int {
    type Double: Int;

    fn as_double(self) -> Self::Double;
    fn from_double(n: Self::Double) -> Self;
}

macro_rules! int {
    ( $x:ty ) => {
        impl Int for $x {
            fn as_u64(&self) -> u64 {
                *self as u64
            }
            fn from_u64(n: u64) -> Self {
                n as _
            }
            #[cfg(debug_assertions)]
            fn as_u128(&self) -> u128 {
                *self as u128
            }
            #[cfg(debug_assertions)]
            fn from_u128(n: u64) -> Self {
                n as _
            }
        }
    };
}

int!(u32);
int!(u64);
int!(u128);

impl DoubleInt for u64 {
    type Double = u128;

    fn as_double(self) -> u128 {
        self as _
    }
    fn from_double(n: u128) -> u64 {
        n as _
    }
}
impl DoubleInt for u32 {
    type Double = u64;

    fn as_double(self) -> u64 {
        self as _
    }
    fn from_double(n: u64) -> u32 {
        n as _
    }
}

// extended Euclid algorithm
// precondition: a is odd
pub(crate) fn modular_inverse<T: Int>(a: T) -> T {
    let zero = T::zero();
    let one = T::one();
    debug_assert!(a % (one + one) == one, "{:?} is not odd", a);

    let mut t = zero;
    let mut newt = one;
    let mut r = zero;
    let mut newr = a;

    while newr != zero {
        let quot = if r == zero {
            // special case when we're just starting out
            // This works because we know that
            // a does not divide 2^64, so floor(2^64 / a) == floor((2^64-1) / a);
            T::max_value()
        } else {
            r
        } / newr;

        let newtp = t.wrapping_sub(&quot.wrapping_mul(&newt));
        t = newt;
        newt = newtp;

        let newrp = r.wrapping_sub(&quot.wrapping_mul(&newr));
        r = newr;
        newr = newrp;
    }

    debug_assert_eq!(r, one);
    t
}

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

    fn test_inverter<T: Int>() {
        // All odd integers from 1 to 20 000
        let one = T::from(1).unwrap();
        let two = T::from(2).unwrap();
        let mut test_values = (0..10_000)
            .map(|i| T::from(i).unwrap())
            .map(|i| two * i + one);

        assert!(test_values.all(|x| x.wrapping_mul(&modular_inverse(x)) == one));
    }

    #[test]
    fn test_inverter_u32() {
        test_inverter::<u32>()
    }

    #[test]
    fn test_inverter_u64() {
        test_inverter::<u64>()
    }

    fn test_add<A: Arithmetic>() {
        for n in 0..100 {
            let n = 2 * n + 1;
            let m = A::new(n);
            for x in 0..n {
                let m_x = m.from_u64(x);
                for y in 0..=x {
                    let m_y = m.from_u64(y);
                    println!("{n:?}, {x:?}, {y:?}", n = n, x = x, y = y);
                    assert_eq!((x + y) % n, m.to_u64(m.add(m_x, m_y)));
                }
            }
        }
    }

    #[test]
    fn test_add_m32() {
        test_add::<Montgomery<u32>>()
    }

    #[test]
    fn test_add_m64() {
        test_add::<Montgomery<u64>>()
    }

    fn test_mult<A: Arithmetic>() {
        for n in 0..100 {
            let n = 2 * n + 1;
            let m = A::new(n);
            for x in 0..n {
                let m_x = m.from_u64(x);
                for y in 0..=x {
                    let m_y = m.from_u64(y);
                    assert_eq!((x * y) % n, m.to_u64(m.mul(m_x, m_y)));
                }
            }
        }
    }

    #[test]
    fn test_mult_m32() {
        test_mult::<Montgomery<u32>>()
    }

    #[test]
    fn test_mult_m64() {
        test_mult::<Montgomery<u64>>()
    }

    fn test_roundtrip<A: Arithmetic>() {
        for n in 0..100 {
            let n = 2 * n + 1;
            let m = A::new(n);
            for x in 0..n {
                let x_ = m.from_u64(x);
                assert_eq!(x, m.to_u64(x_));
            }
        }
    }

    #[test]
    fn test_roundtrip_m32() {
        test_roundtrip::<Montgomery<u32>>()
    }

    #[test]
    fn test_roundtrip_m64() {
        test_roundtrip::<Montgomery<u64>>()
    }
}
<|endoftext|>


<commit_before>// Copyright (c) The Libra Core Contributors
// SPDX-License-Identifier: Apache-2.0

#![forbid(unsafe_code)]

use compiled_stdlib::{transaction_scripts::StdlibScript, StdLibOptions};
use libra_types::{
    access_path::AccessPath,
    block_metadata::BlockMetadata,
    on_chain_config::{LibraVersion, VMPublishingOption},
    transaction::{ChangeSet, Script, Transaction, TransactionArgument},
    write_set::{WriteOp, WriteSetMut},
};
use move_core_types::language_storage::TypeTag;
use std::convert::TryFrom;
pub use transaction_builder_generated::stdlib::*;

/// Encode `stdlib_script` with arguments `args`.
/// Note: this is not type-safe; the individual type-safe wrappers below should be used when
/// possible.
pub fn encode_stdlib_script(
    stdlib_script: StdlibScript,
    type_args: Vec<TypeTag>,
    args: Vec<TransactionArgument>,
) -> Script {
    Script::new(stdlib_script.compiled_bytes().into_vec(), type_args, args)
}

pub fn encode_modify_publishing_option_script(config: VMPublishingOption) -> Script {
    let bytes = lcs::to_bytes(&config).expect("Cannot deserialize VMPublishingOption");
    transaction_builder_generated::stdlib::encode_modify_publishing_option_script(bytes)
}

pub fn encode_update_libra_version_script(libra_version: LibraVersion) -> Script {
    transaction_builder_generated::stdlib::encode_update_libra_version_script(
        libra_version.major as u64,
    )
}

// TODO: this should go away once we are no longer using it in tests
pub fn encode_block_prologue_script(block_metadata: BlockMetadata) -> Transaction {
    Transaction::BlockMetadata(block_metadata)
}

/// Update WriteSet
pub fn encode_stdlib_upgrade_transaction(option: StdLibOptions) -> ChangeSet {
    let mut write_set = WriteSetMut::new(vec![]);
    let stdlib = compiled_stdlib::stdlib_modules(option);
    for module in stdlib {
        let mut bytes = vec![];
        module
            .serialize(&mut bytes)
            .expect("Failed to serialize module");
        write_set.push((
            AccessPath::code_access_path(&module.self_id()),
            WriteOp::Value(bytes),
        ));
    }
    ChangeSet::new(
        write_set.freeze().expect("Failed to create writeset"),
        vec![],
    )
}

// TODO: delete and use StdlibScript::try_from directly if it's ok to drop the "_transaction"?
/// Returns a user friendly mnemonic for the transaction type if the transaction is
/// for a known, white listed, transaction.
pub fn get_transaction_name(code: &[u8]) -> String {
    StdlibScript::try_from(code).map_or("<unknown transaction>".to_string(), |name| {
        format!("{}_transaction", name)
    })
}
<commit_msg>[transaction builder] remove unused and unsafe fn encode_stdlib_script<commit_after>// Copyright (c) The Libra Core Contributors
// SPDX-License-Identifier: Apache-2.0

#![forbid(unsafe_code)]

use compiled_stdlib::{transaction_scripts::StdlibScript, StdLibOptions};
use libra_types::{
    access_path::AccessPath,
    block_metadata::BlockMetadata,
    on_chain_config::{LibraVersion, VMPublishingOption},
    transaction::{ChangeSet, Script, Transaction},
    write_set::{WriteOp, WriteSetMut},
};
use std::convert::TryFrom;
pub use transaction_builder_generated::stdlib::*;

pub fn encode_modify_publishing_option_script(config: VMPublishingOption) -> Script {
    let bytes = lcs::to_bytes(&config).expect("Cannot deserialize VMPublishingOption");
    transaction_builder_generated::stdlib::encode_modify_publishing_option_script(bytes)
}

pub fn encode_update_libra_version_script(libra_version: LibraVersion) -> Script {
    transaction_builder_generated::stdlib::encode_update_libra_version_script(
        libra_version.major as u64,
    )
}

// TODO: this should go away once we are no longer using it in tests
pub fn encode_block_prologue_script(block_metadata: BlockMetadata) -> Transaction {
    Transaction::BlockMetadata(block_metadata)
}

/// Update WriteSet
pub fn encode_stdlib_upgrade_transaction(option: StdLibOptions) -> ChangeSet {
    let mut write_set = WriteSetMut::new(vec![]);
    let stdlib = compiled_stdlib::stdlib_modules(option);
    for module in stdlib {
        let mut bytes = vec![];
        module
            .serialize(&mut bytes)
            .expect("Failed to serialize module");
        write_set.push((
            AccessPath::code_access_path(&module.self_id()),
            WriteOp::Value(bytes),
        ));
    }
    ChangeSet::new(
        write_set.freeze().expect("Failed to create writeset"),
        vec![],
    )
}

// TODO: delete and use StdlibScript::try_from directly if it's ok to drop the "_transaction"?
/// Returns a user friendly mnemonic for the transaction type if the transaction is
/// for a known, white listed, transaction.
pub fn get_transaction_name(code: &[u8]) -> String {
    StdlibScript::try_from(code).map_or("<unknown transaction>".to_string(), |name| {
        format!("{}_transaction", name)
    })
}
<|endoftext|>


<commit_before>#![warn(bad_style,
        unused, unused_extern_crates, unused_import_braces,
        unused_qualifications, unused_results)]

extern crate twitter_api as twitter;
extern crate rustc_serialize as rustc_serialize;
extern crate oauth_client as oauth;

use std::io;
use std::io::prelude::*;
use std::env;
use std::fs::{File, OpenOptions};
use std::path::Path;
use std::path::PathBuf;
use rustc_serialize::Decodable;
use rustc_serialize::json::{self, Json};
use oauth::Token;

const TWITTER_CONF_FILENAME: &'static str = ".twitter.conf";

fn get_home_dir() -> PathBuf{
    match env::home_dir() {
        Some(p) => p,
        None => {
            panic!("Impossible to get your home dir!");
        }
    }
}

#[derive(Debug, RustcEncodable, RustcDecodable)]
pub struct Config {
    pub consumer_key: String,
    pub consumer_secret: String,
    pub access_key: String,
    pub access_secret: String
}

impl Config {
    pub fn read(path_file : &Path) -> Option<Config> {
        let mut file = match File::open(path_file) {
            Ok(f) => f,
            Err(_) => return None
        };
        let conf = Json::from_reader(&mut file).unwrap();
        Decodable::decode(&mut json::Decoder::new(conf)).ok()
    }

    pub fn write(&self, path_file : &Path) {
        let mut file = match OpenOptions::new().write(true).open(path_file) {
            Ok(f) => f,
            Err(e) => panic!("{}", e)
        };
        let _ = write!(&mut file, "{}\n", &json::encode(self).unwrap());
    }

    pub fn create(path_file : &Path) {
        match File::create(path_file) {
            Ok(_) => println!("File created!"),
            Err(_) => panic!("Problem to create the file...\nProgram aborted!")
        }
    }
}

fn console_input(prompt: &str) -> String {
    println!("{} : ", prompt);
    let mut line = String::new();
    let _ = io::stdin().read_line(&mut line).unwrap();
    line.trim().to_string()
}

fn main() {
    //Get the full path of the Twitter configuration path
    let mut twitter_conf_file_path : PathBuf = get_home_dir();
    twitter_conf_file_path.push(Path::new(TWITTER_CONF_FILENAME));

    let conf = match Config::read(&twitter_conf_file_path) {
        Some(c) => c,
        None => {

            Config::create(&twitter_conf_file_path);

            let consumer_key    = console_input("input your consumer key:");
            let consumer_secret = console_input("input your consumer secret:");
            let consumer = Token::new(consumer_key, consumer_secret);

            let request = twitter::get_request_token(&consumer);
            println!("open the following url:");
            println!("\t{}", twitter::get_authorize_url(&request));
            let pin = console_input("input pin:");
            let access = twitter::get_access_token(&consumer, &request, &pin);

            let c = Config {
                consumer_key: consumer.key.to_string(),
                consumer_secret: consumer.secret.to_string(),
                access_key: access.key.to_string(),
                access_secret: access.secret.to_string()
            };

            c.write(&twitter_conf_file_path);
            c
        }
    };

    let consumer = Token::new(conf.consumer_key, conf.consumer_secret);
    let access = Token::new(conf.access_key, conf.access_secret);

    let status = console_input("What's happening?");
    twitter::update_status(&consumer, &access, &status);
}
<commit_msg>examples/tweet.rs : Simple matching to know what to do<commit_after>#![warn(bad_style,
        unused, unused_extern_crates, unused_import_braces,
        unused_qualifications, unused_results)]

extern crate twitter_api as twitter;
extern crate rustc_serialize as rustc_serialize;
extern crate oauth_client as oauth;

use std::io;
use std::io::prelude::*;
use std::env;
use std::fs::{File, OpenOptions};
use std::path::Path;
use std::path::PathBuf;
use rustc_serialize::Decodable;
use rustc_serialize::json::{self, Json};
use oauth::Token;

const TWITTER_CONF_FILENAME: &'static str = ".twitter.conf";

fn get_home_dir() -> PathBuf{
    match env::home_dir() {
        Some(p) => p,
        None => {
            panic!("Impossible to get your home dir!");
        }
    }
}

#[derive(Debug, RustcEncodable, RustcDecodable)]
pub struct Config {
    pub consumer_key: String,
    pub consumer_secret: String,
    pub access_key: String,
    pub access_secret: String
}

impl Config {
    pub fn read(path_file : &Path) -> Option<Config> {
        let mut file = match File::open(path_file) {
            Ok(f) => f,
            Err(_) => return None
        };
        let conf = Json::from_reader(&mut file).unwrap();
        Decodable::decode(&mut json::Decoder::new(conf)).ok()
    }

    pub fn write(&self, path_file : &Path) {
        let mut file = match OpenOptions::new().write(true).open(path_file) {
            Ok(f) => f,
            Err(e) => panic!("{}", e)
        };
        let _ = write!(&mut file, "{}\n", &json::encode(self).unwrap());
    }

    pub fn create(path_file : &Path) {
        match File::create(path_file) {
            Ok(_) => println!("File created!"),
            Err(_) => panic!("Problem to create the file...\nProgram aborted!")
        }
    }
}

fn console_input(prompt: &str) -> String {
    println!("{} : ", prompt);
    let mut line = String::new();
    let _ = io::stdin().read_line(&mut line).unwrap();
    line.trim().to_string()
}

fn main() {
    //Get the full path of the Twitter configuration path
    let mut twitter_conf_file_path : PathBuf = get_home_dir();
    twitter_conf_file_path.push(Path::new(TWITTER_CONF_FILENAME));

    let conf = match Config::read(&twitter_conf_file_path) {
        Some(c) => c,
        None => {

            Config::create(&twitter_conf_file_path);

            let consumer_key    = console_input("input your consumer key:");
            let consumer_secret = console_input("input your consumer secret:");
            let consumer = Token::new(consumer_key, consumer_secret);

            let request = twitter::get_request_token(&consumer);
            println!("open the following url:");
            println!("\t{}", twitter::get_authorize_url(&request));
            let pin = console_input("input pin:");
            let access = twitter::get_access_token(&consumer, &request, &pin);

            let c = Config {
                consumer_key: consumer.key.to_string(),
                consumer_secret: consumer.secret.to_string(),
                access_key: access.key.to_string(),
                access_secret: access.secret.to_string()
            };

            c.write(&twitter_conf_file_path);
            c
        }
    };

    let consumer = Token::new(conf.consumer_key, conf.consumer_secret);
    let access = Token::new(conf.access_key, conf.access_secret);

    loop {
        let make_your_choice = console_input("What do you want to do?");

        match make_your_choice.as_ref() {
            "update status" => {
                let status = console_input("What's happening?");
                twitter::update_status(&consumer, &access, &status);
            },
            "get timeline" => {
                twitter::get_last_tweets(&consumer, &access);
            },
            _ => break
        }
    }
}
<|endoftext|>


<commit_before>// TODOs
// - add tests
// - add a feature stopping the server
// - add common packet id-handler mapper using macro.

use bytes::BytesMut;

use protobuf::{parse_from_bytes, Message};

use tokio::net::TcpListener;
use tokio::io::{BufReader, AsyncReadExt};
use tokio::prelude::*;

use echoserver02::protos::AuthServer::{Packet, Packet_Id};

#[tokio::main]
async fn main() -> io::Result<()> {
    let mut listener = TcpListener::bind("127.0.0.1:8080").await?;

    loop {
        let (mut socket, _) = listener.accept().await?;

        tokio::spawn(async move {
            let (rd, mut wr) = socket.split();
            let mut reader = BufReader::new(rd);

            loop {
                let len = match reader.read_u32().await {
                    Ok(v) => v,
                    Err(e) => {
                        eprintln!("failed to read len from socket; err = {:?}", e);
                        return;
                    }
                };

                let mut raw_packet = BytesMut::with_capacity(len as usize);
                let _n = match reader.read_buf(&mut raw_packet).await {
                    Ok(n) if n == 0 => { println!("end of stream. (read 0 byte)"); return; },
                    Ok(n) => n,
                    Err(e) => {
                        eprintln!("failed to read from socket; err= {:?}", e);
                        return;
                    }
                };

                let mut packet = match parse_from_bytes::<Packet>(&raw_packet) {
                    Ok(v) => v,
                    Err(e) => {
                        eprintln!("invalid login packet; err = {:?}", e);
                        continue;
                    }
                };

                println!("request packet : {:?}", packet);

                // TODO: build packet id-handler mapper here.

                if packet.id != Packet_Id::LOGIN || !packet.has_login() {
                    eprintln!("request packet is need to be login packet");
                    continue;
                }

                packet.mut_login().mut_account().set_user_id("123456".to_owned());

                let raw_response_packet = packet.write_to_bytes().unwrap();

                if let Err(e) = wr.write_u32(raw_response_packet.len() as u32).await {
                    eprintln!("failed to write len to socket; err = {:?}", e);
                    return;
                }

                if let Err(e) = wr.write_all(&raw_response_packet).await {
                    eprintln!("failed to write to socket; err = {:?}", e);
                    return;
                }
            }
        });
    }
}

<commit_msg>Rust_TokioRs: echoserver02 - implementing macro<commit_after>// TODOs
// - add tests
// - add a feature stopping the server
// - add common packet id-handler mapper using macro.

use bytes::BytesMut;

use protobuf::{parse_from_bytes, Message};

use tokio::net::TcpListener;
use tokio::io::{BufReader, AsyncReadExt};
use tokio::prelude::*;

use echoserver02::protos::AuthServer::{Packet, Packet_Id};

#[tokio::main]
async fn main() -> io::Result<()> {
    let mut listener = TcpListener::bind("127.0.0.1:8080").await?;

    loop {
        let (mut socket, _) = listener.accept().await?;

        tokio::spawn(async move {
            let (rd, mut wr) = socket.split();
            let mut reader = BufReader::new(rd);

            loop {
                let len = match reader.read_u32().await {
                    Ok(v) => v,
                    Err(e) => {
                        eprintln!("failed to read len from socket; err = {:?}", e);
                        return;
                    }
                };

                let mut raw_packet = BytesMut::with_capacity(len as usize);
                let _n = match reader.read_buf(&mut raw_packet).await {
                    Ok(n) if n == 0 => { println!("end of stream. (read 0 byte)"); return; },
                    Ok(n) => n,
                    Err(e) => {
                        eprintln!("failed to read from socket; err= {:?}", e);
                        return;
                    }
                };

                let mut packet = match parse_from_bytes::<Packet>(&raw_packet) {
                    Ok(v) => v,
                    Err(e) => {
                        eprintln!("invalid login packet; err = {:?}", e);
                        continue;
                    }
                };

                println!("request packet : {:?}", packet);

                // TODO: build packet id-handler mapper here.

                if packet.id != Packet_Id::LOGIN || !packet.has_login() {
                    eprintln!("request packet is need to be login packet");
                    continue;
                }

                packet.mut_login().mut_account().set_user_id("123456".to_owned());

                let raw_response_packet = packet.write_to_bytes().unwrap();

                if let Err(e) = wr.write_u32(raw_response_packet.len() as u32).await {
                    eprintln!("failed to write len to socket; err = {:?}", e);
                    return;
                }

                if let Err(e) = wr.write_all(&raw_response_packet).await {
                    eprintln!("failed to write to socket; err = {:?}", e);
                    return;
                }
            }
        });
    }
}

macro_rules! map_handler {
    ( $received_packet: expr, $( ( $packetid: path => $handler: expr ) ),* ) => {
        {
            match $received_packet.id {
                $(
                    $packetid => tokio::spawn(async move { $handler($received_packet) }),
                )*
            }
        }
    };
}

#[tokio::test]
async fn macrotest() {
    let mut pkt = Packet::new();
    pkt.set_id(Packet_Id::LOGIN);
    map_handler!(
        pkt,
        ( Packet_Id::PING => |_p: Packet| { println!("ping"); } ),
        ( Packet_Id::LOGIN => |_p: Packet| { println!("login"); } )
    );

    tokio::time::delay_for(tokio::time::Duration::from_millis(1000)).await;
}<|endoftext|>