<commit_before>
#[macro_use]
pub mod errors;

use parser::errors::{ErrorKind, ParseError};
use std::str;

pub type ParseResult<T> = Result<T, ParseError>;

#[derive(Debug)]
pub enum Message {
    Settings(SettingsValue),
    SetupMap(SetupMapValue),
    PickStartingRegion{time_left: u64, ids: Vec<u64>},
    UpdateMap,
    GoPlaceArmies,
    GoAttackTranser,
}

#[derive(Debug)]
pub enum SettingsValue {
    Timebank(u64),
    TimePerMove(u64),
    MaxRounds(u64),
    YourBot(String),
    OpponentBot(String),
    StartingRegions(Vec<u64>),
    StartingPickAmount(u64),
    StartingArmies(u64)
}

#[derive(Debug)]
pub enum SetupMapValue {
    SuperRegions(Vec<(u64, u64)>),
    Regions(Vec<(u64, u64)>),
    Neighbors(Vec<(u64, Vec<u64>)>),
    Wastelands(Vec<u64>),
    OpponentStartingRegions(Vec<u64>)
}

pub fn parse(line: &'static str) -> ParseResult<Message> {
    let mut words = line.trim().split(' ');
    match words.next().unwrap() {
        "settings" => parse_settings(words),
        "setup_map" => parse_setup_map(words),
        _ => fail!((ErrorKind::UnknownCommand, "got an unknown command", line.to_owned()))
    }
}

fn parse_settings(mut parts: str::Split<char>) -> ParseResult<Message> {
    let command = try!(parts.next().ok_or((ErrorKind::MalformedCommand, "Got setting without type")));

    match command {
        "timebank" => {
            let value = try!(parts_to_u64(parts, command.to_owned()));
            Ok(Message::Settings(SettingsValue::Timebank(value)))
        }
        "time_per_move" => {
            let value = try!(parts_to_u64(parts, command.to_owned()));
            Ok(Message::Settings(SettingsValue::TimePerMove(value)))
        }
        "max_rounds" => {
            let value = try!(parts_to_u64(parts, command.to_owned()));
            Ok(Message::Settings(SettingsValue::MaxRounds(value)))
        }
        "starting_pick_amount" => {
            let value = try!(parts_to_u64(parts, command.to_owned()));
            Ok(Message::Settings(SettingsValue::StartingPickAmount(value)))
        }
        "starting_armies" => {
            let value = try!(parts_to_u64(parts, command.to_owned()));
            Ok(Message::Settings(SettingsValue::StartingArmies(value)))
        }
        "starting_regions" => {
            let mut peeker = parts.peekable();
            try!(peeker.peek().ok_or((ErrorKind::MalformedCommand, "Got starting_regions without any arguments")));
            let mut value = Vec::new();
            for word in peeker {
                value.push(try!(u64::from_str_radix(word, 10)));
            }
            Ok(Message::Settings(SettingsValue::StartingRegions(value)))
        }
        "your_bot" => {
            let raw_value = try!(parts.next().ok_or((
                ErrorKind::MalformedCommand,
                "Got your_bot without an argument"
            )));
            Ok(Message::Settings(SettingsValue::YourBot(raw_value.to_owned())))
        }
        "opponent_bot" => {
            let raw_value = try!(parts.next().ok_or((
                ErrorKind::MalformedCommand,
                "Got opponent_bot without an argument"
            )));
            Ok(Message::Settings(SettingsValue::OpponentBot(raw_value.to_owned())))
        }
        _ => fail!((ErrorKind::UnknownCommand, "got an unknown setting type", command.to_owned()))
    }
}

fn parse_setup_map(mut parts: str::Split<char>) -> ParseResult<Message> {
    let command = try!(parts.next().ok_or((ErrorKind::MalformedCommand, "Got setup_map without type")));
    fail!((ErrorKind::UnknownCommand, "not implemented"))
    // match command {
    //     "super_regions" => {
    //     }
    // }
}

fn parts_to_u64(mut parts: str::Split<char>, command: String) -> ParseResult<u64> {
    let raw_value = try!(parts.next().ok_or((
        ErrorKind::MalformedCommand,
        "missing argument numeric argument",
        command
    )));
    Ok(try!(u64::from_str_radix(raw_value, 10)))
}

#[test]
fn blank() {
    match parse("").unwrap_err().kind() {
        ErrorKind::UnknownCommand => {},
        _ => panic!("got an error of unexpected kind")
    }
}

#[test]
fn setting_blank() {
    match parse("settings").unwrap_err().kind() {
        ErrorKind::MalformedCommand => {},
        _ => panic!("got an error of unexpected kind")
    }
}

#[test]
fn setting_timebank_blank() {
    match parse("settings timebank").unwrap_err().kind() {
        ErrorKind::MalformedCommand => {},
        _ => panic!("got an error of unexpected kind")
    }
}

#[test]
fn setting_timebank_bad_value() {
    match parse("settings timebank five").unwrap_err().kind() {
        ErrorKind::MalformedCommand => {},
        _ => panic!("got an error of unexpected kind")
    }
}

#[test]
fn setting_timebank_proper() {
    match parse("settings timebank 10000").unwrap() {
        Message::Settings(setting) => match setting {
            SettingsValue::Timebank(value) => assert_eq!(value, 10000),
            _ => panic!("got a setting that wasn't a timebank")
        },
        _ => panic!("didn't get a settings object")
    }
}

#[test]
fn setting_timebank_proper_with_leading_space() {
    match parse(" settings timebank 10000").unwrap() {
        Message::Settings(setting) => match setting {
            SettingsValue::Timebank(value) => assert_eq!(value, 10000),
            _ => panic!("got a setting that wasn't a timebank")
        },
        _ => panic!("didn't get a settings object")
    }
}

#[test]
fn setting_time_per_move_blank() {
    match parse("settings time_per_move").unwrap_err().kind() {
        ErrorKind::MalformedCommand => {},
        _ => panic!("got an error of unexpected kind")
    }
}

#[test]
fn setting_time_per_move_bad_value() {
    match parse("settings time_per_move five").unwrap_err().kind() {
        ErrorKind::MalformedCommand => {},
        _ => panic!("got an error of unexpected kind")
    }
}

#[test]
fn setting_time_per_move_proper() {
    match parse("settings time_per_move 10000").unwrap() {
        Message::Settings(setting) => match setting {
            SettingsValue::TimePerMove(value) => assert_eq!(value, 10000),
            _ => panic!("got a setting that wasn't a time_per_move")
        },
        _ => panic!("didn't get a settings object")
    }
}

#[test]
fn setting_max_rounds_blank() {
    match parse("settings max_rounds").unwrap_err().kind() {
        ErrorKind::MalformedCommand => {},
        _ => panic!("got an error of unexpected kind")
    }
}

#[test]
fn setting_max_rounds_bad_value() {
    match parse("settings max_rounds five").unwrap_err().kind() {
        ErrorKind::MalformedCommand => {},
        _ => panic!("got an error of unexpected kind")
    }
}

#[test]
fn setting_max_rounds_proper() {
    match parse("settings max_rounds 10000").unwrap() {
        Message::Settings(setting) => match setting {
            SettingsValue::MaxRounds(value) => assert_eq!(value, 10000),
            _ => panic!("got a setting that wasn't a max_rounds")
        },
        _ => panic!("didn't get a settings object")
    }
}

#[test]
fn setting_starting_pick_amount_blank() {
    match parse("settings starting_pick_amount").unwrap_err().kind() {
        ErrorKind::MalformedCommand => {},
        _ => panic!("got an error of unexpected kind")
    }
}

#[test]
fn setting_starting_pick_amount_bad_value() {
    match parse("settings starting_pick_amount five").unwrap_err().kind() {
        ErrorKind::MalformedCommand => {},
        _ => panic!("got an error of unexpected kind")
    }
}

#[test]
fn setting_starting_pick_amount_proper() {
    match parse("settings starting_pick_amount 10000").unwrap() {
        Message::Settings(setting) => match setting {
            SettingsValue::StartingPickAmount(value) => assert_eq!(value, 10000),
            _ => panic!("got a setting that wasn't a starting_pick_amount")
        },
        _ => panic!("didn't get a settings object")
    }
}

#[test]
fn setting_starting_armies_blank() {
    match parse("settings starting_armies").unwrap_err().kind() {
        ErrorKind::MalformedCommand => {},
        _ => panic!("got an error of unexpected kind")
    }
}

#[test]
fn setting_starting_armies_bad_value() {
    match parse("settings starting_armies five").unwrap_err().kind() {
        ErrorKind::MalformedCommand => {},
        _ => panic!("got an error of unexpected kind")
    }
}

#[test]
fn setting_starting_armies_proper() {
    match parse("settings starting_armies 10000").unwrap() {
        Message::Settings(setting) => match setting {
            SettingsValue::StartingArmies(value) => assert_eq!(value, 10000),
            _ => panic!("got a setting that wasn't a starting_armies")
        },
        _ => panic!("didn't get a settings object")
    }
}

#[test]
fn setting_starting_regions_blank() {
    match parse("settings starting_regions").unwrap_err().kind() {
        ErrorKind::MalformedCommand => {},
        _ => panic!("got an error of unexpected kind")
    }
}

#[test]
fn setting_starting_regions_bad_value() {
    match parse("settings starting_regions five 50").unwrap_err().kind() {
        ErrorKind::MalformedCommand => {},
        _ => panic!("got an error of unexpected kind")
    }
}

#[test]
fn setting_starting_regions_proper() {
    match parse("settings starting_regions 4 7 11").unwrap() {
        Message::Settings(setting) => match setting {
            SettingsValue::StartingRegions(value) => assert_eq!(value, vec![4, 7, 11]),
            _ => panic!("got a setting that wasn't a starting_regions")
        },
        _ => panic!("didn't get a settings object")
    }
}

#[test]
fn setting_your_bot_blank() {
    match parse("settings your_bot").unwrap_err().kind() {
        ErrorKind::MalformedCommand => {},
        _ => panic!("got an error of unexpected kind")
    }
}

#[test]
fn setting_your_bot_proper() {
    match parse("settings your_bot fig").unwrap() {
        Message::Settings(setting) => match setting {
            SettingsValue::YourBot(value) => assert_eq!(value, "fig".to_owned()),
            _ => panic!("got a setting that wasn't a your_bot")
        },
        _ => panic!("didn't get a settings object")
    }
}

#[test]
fn setting_opponent_bot_blank() {
    match parse("settings opponent_bot").unwrap_err().kind() {
        ErrorKind::MalformedCommand => {},
        _ => panic!("got an error of unexpected kind")
    }
}

#[test]
fn setting_opponent_bot_proper() {
    match parse("settings opponent_bot fig").unwrap() {
        Message::Settings(setting) => match setting {
            SettingsValue::OpponentBot(value) => assert_eq!(value, "fig".to_owned()),
            _ => panic!("got a setting that wasn't a opponent_bot")
        },
        _ => panic!("didn't get a settings object")
    }
}
<commit_msg>fix some error messages<commit_after>
#[macro_use]
pub mod errors;

use parser::errors::{ErrorKind, ParseError};
use std::str;

pub type ParseResult<T> = Result<T, ParseError>;

#[derive(Debug)]
pub enum Message {
    Settings(SettingsValue),
    SetupMap(SetupMapValue),
    PickStartingRegion{time_left: u64, ids: Vec<u64>},
    UpdateMap,
    GoPlaceArmies,
    GoAttackTranser,
}

#[derive(Debug)]
pub enum SettingsValue {
    Timebank(u64),
    TimePerMove(u64),
    MaxRounds(u64),
    YourBot(String),
    OpponentBot(String),
    StartingRegions(Vec<u64>),
    StartingPickAmount(u64),
    StartingArmies(u64)
}

#[derive(Debug)]
pub enum SetupMapValue {
    SuperRegions(Vec<(u64, u64)>),
    Regions(Vec<(u64, u64)>),
    Neighbors(Vec<(u64, Vec<u64>)>),
    Wastelands(Vec<u64>),
    OpponentStartingRegions(Vec<u64>)
}

pub fn parse(line: &'static str) -> ParseResult<Message> {
    let mut words = line.trim().split(' ');
    match words.next().unwrap() {
        "settings" => parse_settings(words),
        "setup_map" => parse_setup_map(words),
        _ => fail!((ErrorKind::UnknownCommand, "Got an unknown command", line.to_owned()))
    }
}

fn parse_settings(mut parts: str::Split<char>) -> ParseResult<Message> {
    let command = try!(parts.next().ok_or((ErrorKind::MalformedCommand, "Got setting without type")));

    match command {
        "timebank" => {
            let value = try!(parts_to_u64(parts, command.to_owned()));
            Ok(Message::Settings(SettingsValue::Timebank(value)))
        }
        "time_per_move" => {
            let value = try!(parts_to_u64(parts, command.to_owned()));
            Ok(Message::Settings(SettingsValue::TimePerMove(value)))
        }
        "max_rounds" => {
            let value = try!(parts_to_u64(parts, command.to_owned()));
            Ok(Message::Settings(SettingsValue::MaxRounds(value)))
        }
        "starting_pick_amount" => {
            let value = try!(parts_to_u64(parts, command.to_owned()));
            Ok(Message::Settings(SettingsValue::StartingPickAmount(value)))
        }
        "starting_armies" => {
            let value = try!(parts_to_u64(parts, command.to_owned()));
            Ok(Message::Settings(SettingsValue::StartingArmies(value)))
        }
        "starting_regions" => {
            let mut peeker = parts.peekable();
            try!(peeker.peek().ok_or((ErrorKind::MalformedCommand, "Got starting_regions without any arguments")));
            let mut value = Vec::new();
            for word in peeker {
                value.push(try!(u64::from_str_radix(word, 10)));
            }
            Ok(Message::Settings(SettingsValue::StartingRegions(value)))
        }
        "your_bot" => {
            let raw_value = try!(parts.next().ok_or((
                ErrorKind::MalformedCommand,
                "Got your_bot without an argument"
            )));
            Ok(Message::Settings(SettingsValue::YourBot(raw_value.to_owned())))
        }
        "opponent_bot" => {
            let raw_value = try!(parts.next().ok_or((
                ErrorKind::MalformedCommand,
                "Got opponent_bot without an argument"
            )));
            Ok(Message::Settings(SettingsValue::OpponentBot(raw_value.to_owned())))
        }
        _ => fail!((ErrorKind::UnknownCommand, "got an unknown setting type", command.to_owned()))
    }
}

fn parse_setup_map(mut parts: str::Split<char>) -> ParseResult<Message> {
    let command = try!(parts.next().ok_or((ErrorKind::MalformedCommand, "Got setup_map without type")));
    fail!((ErrorKind::UnknownCommand, "Not implemented"))
    // match command {
    //     "super_regions" => {
    //     }
    // }
}

fn parts_to_u64(mut parts: str::Split<char>, command: String) -> ParseResult<u64> {
    let raw_value = try!(parts.next().ok_or((
        ErrorKind::MalformedCommand,
        "Missing numeric argument",
        command
    )));
    Ok(try!(u64::from_str_radix(raw_value, 10)))
}

#[test]
fn blank() {
    match parse("").unwrap_err().kind() {
        ErrorKind::UnknownCommand => {},
        _ => panic!("got an error of unexpected kind")
    }
}

#[test]
fn setting_blank() {
    match parse("settings").unwrap_err().kind() {
        ErrorKind::MalformedCommand => {},
        _ => panic!("got an error of unexpected kind")
    }
}

#[test]
fn setting_timebank_blank() {
    match parse("settings timebank").unwrap_err().kind() {
        ErrorKind::MalformedCommand => {},
        _ => panic!("got an error of unexpected kind")
    }
}

#[test]
fn setting_timebank_bad_value() {
    match parse("settings timebank five").unwrap_err().kind() {
        ErrorKind::MalformedCommand => {},
        _ => panic!("got an error of unexpected kind")
    }
}

#[test]
fn setting_timebank_proper() {
    match parse("settings timebank 10000").unwrap() {
        Message::Settings(setting) => match setting {
            SettingsValue::Timebank(value) => assert_eq!(value, 10000),
            _ => panic!("got a setting that wasn't a timebank")
        },
        _ => panic!("didn't get a settings object")
    }
}

#[test]
fn setting_timebank_proper_with_leading_space() {
    match parse(" settings timebank 10000").unwrap() {
        Message::Settings(setting) => match setting {
            SettingsValue::Timebank(value) => assert_eq!(value, 10000),
            _ => panic!("got a setting that wasn't a timebank")
        },
        _ => panic!("didn't get a settings object")
    }
}

#[test]
fn setting_time_per_move_blank() {
    match parse("settings time_per_move").unwrap_err().kind() {
        ErrorKind::MalformedCommand => {},
        _ => panic!("got an error of unexpected kind")
    }
}

#[test]
fn setting_time_per_move_bad_value() {
    match parse("settings time_per_move five").unwrap_err().kind() {
        ErrorKind::MalformedCommand => {},
        _ => panic!("got an error of unexpected kind")
    }
}

#[test]
fn setting_time_per_move_proper() {
    match parse("settings time_per_move 10000").unwrap() {
        Message::Settings(setting) => match setting {
            SettingsValue::TimePerMove(value) => assert_eq!(value, 10000),
            _ => panic!("got a setting that wasn't a time_per_move")
        },
        _ => panic!("didn't get a settings object")
    }
}

#[test]
fn setting_max_rounds_blank() {
    match parse("settings max_rounds").unwrap_err().kind() {
        ErrorKind::MalformedCommand => {},
        _ => panic!("got an error of unexpected kind")
    }
}

#[test]
fn setting_max_rounds_bad_value() {
    match parse("settings max_rounds five").unwrap_err().kind() {
        ErrorKind::MalformedCommand => {},
        _ => panic!("got an error of unexpected kind")
    }
}

#[test]
fn setting_max_rounds_proper() {
    match parse("settings max_rounds 10000").unwrap() {
        Message::Settings(setting) => match setting {
            SettingsValue::MaxRounds(value) => assert_eq!(value, 10000),
            _ => panic!("got a setting that wasn't a max_rounds")
        },
        _ => panic!("didn't get a settings object")
    }
}

#[test]
fn setting_starting_pick_amount_blank() {
    match parse("settings starting_pick_amount").unwrap_err().kind() {
        ErrorKind::MalformedCommand => {},
        _ => panic!("got an error of unexpected kind")
    }
}

#[test]
fn setting_starting_pick_amount_bad_value() {
    match parse("settings starting_pick_amount five").unwrap_err().kind() {
        ErrorKind::MalformedCommand => {},
        _ => panic!("got an error of unexpected kind")
    }
}

#[test]
fn setting_starting_pick_amount_proper() {
    match parse("settings starting_pick_amount 10000").unwrap() {
        Message::Settings(setting) => match setting {
            SettingsValue::StartingPickAmount(value) => assert_eq!(value, 10000),
            _ => panic!("got a setting that wasn't a starting_pick_amount")
        },
        _ => panic!("didn't get a settings object")
    }
}

#[test]
fn setting_starting_armies_blank() {
    match parse("settings starting_armies").unwrap_err().kind() {
        ErrorKind::MalformedCommand => {},
        _ => panic!("got an error of unexpected kind")
    }
}

#[test]
fn setting_starting_armies_bad_value() {
    match parse("settings starting_armies five").unwrap_err().kind() {
        ErrorKind::MalformedCommand => {},
        _ => panic!("got an error of unexpected kind")
    }
}

#[test]
fn setting_starting_armies_proper() {
    match parse("settings starting_armies 10000").unwrap() {
        Message::Settings(setting) => match setting {
            SettingsValue::StartingArmies(value) => assert_eq!(value, 10000),
            _ => panic!("got a setting that wasn't a starting_armies")
        },
        _ => panic!("didn't get a settings object")
    }
}

#[test]
fn setting_starting_regions_blank() {
    match parse("settings starting_regions").unwrap_err().kind() {
        ErrorKind::MalformedCommand => {},
        _ => panic!("got an error of unexpected kind")
    }
}

#[test]
fn setting_starting_regions_bad_value() {
    match parse("settings starting_regions five 50").unwrap_err().kind() {
        ErrorKind::MalformedCommand => {},
        _ => panic!("got an error of unexpected kind")
    }
}

#[test]
fn setting_starting_regions_proper() {
    match parse("settings starting_regions 4 7 11").unwrap() {
        Message::Settings(setting) => match setting {
            SettingsValue::StartingRegions(value) => assert_eq!(value, vec![4, 7, 11]),
            _ => panic!("got a setting that wasn't a starting_regions")
        },
        _ => panic!("didn't get a settings object")
    }
}

#[test]
fn setting_your_bot_blank() {
    match parse("settings your_bot").unwrap_err().kind() {
        ErrorKind::MalformedCommand => {},
        _ => panic!("got an error of unexpected kind")
    }
}

#[test]
fn setting_your_bot_proper() {
    match parse("settings your_bot fig").unwrap() {
        Message::Settings(setting) => match setting {
            SettingsValue::YourBot(value) => assert_eq!(value, "fig".to_owned()),
            _ => panic!("got a setting that wasn't a your_bot")
        },
        _ => panic!("didn't get a settings object")
    }
}

#[test]
fn setting_opponent_bot_blank() {
    match parse("settings opponent_bot").unwrap_err().kind() {
        ErrorKind::MalformedCommand => {},
        _ => panic!("got an error of unexpected kind")
    }
}

#[test]
fn setting_opponent_bot_proper() {
    match parse("settings opponent_bot fig").unwrap() {
        Message::Settings(setting) => match setting {
            SettingsValue::OpponentBot(value) => assert_eq!(value, "fig".to_owned()),
            _ => panic!("got a setting that wasn't a opponent_bot")
        },
        _ => panic!("didn't get a settings object")
    }
}
<|endoftext|>


<commit_before>use chrono::naive::NaiveDateTime;
use exif::{Exif, In, Tag};
use serde::{Deserialize, Serialize};
use validator::Validate;

use anyhow::{Error, Result};
use image::GenericImageView;
use image::{imageops, DynamicImage};

use crate::schema::pictures;
use crate::utils::image_base_path;

#[derive(Debug, Clone, Queryable, Insertable, Serialize, Deserialize)]
pub struct Picture {
    pub id: i32,
    pub author_id: i32,

    pub in_reply_to: Option<String>,
    pub webmentions_count: i32,

    pub image_file_name: String,
    pub image_content_type: String,
    pub image_file_size: i32,
    pub image_updated_at: NaiveDateTime,

    pub inserted_at: NaiveDateTime,
    pub updated_at: NaiveDateTime,

    pub title: String,

    pub posse: bool,
    pub show_in_index: bool,

    pub content: String,

    pub lang: String,
    pub alt: Option<String>,
}

#[derive(Deserialize, Serialize, Debug, Insertable, Clone, Validate, Default)]
#[table_name = "pictures"]
pub struct NewPicture {
    pub author_id: Option<i32>,
    #[validate(length(min = 5))]
    pub title: String,
    #[validate(length(min = 5))]
    pub alt: Option<String>,
    #[validate(url)]
    pub in_reply_to: Option<String>,
    #[validate(length(min = 2, max = 2))]
    pub lang: String,
    #[serde(default)]
    pub posse: bool,
    #[serde(default)]
    pub show_in_index: bool,
    #[validate(required, length(min = 5))]
    pub content: Option<String>,

    pub image_file_name: Option<String>,
    pub image_content_type: Option<String>,
    pub image_file_size: Option<i32>,
    pub image_updated_at: Option<NaiveDateTime>,

    pub inserted_at: Option<NaiveDateTime>,
    pub updated_at: Option<NaiveDateTime>,
}

#[derive(Deserialize, Serialize, Debug)]
pub struct NewJsonPicture {
    #[serde(flatten)]
    pub new_picture: NewPicture,
    pub picture: Option<String>,
}

const THUMB_ASPEC_RATIO: f32 = 1.0;

fn read_exif(path: &str) -> Result<Exif, Error> {
    let file = std::fs::File::open(path)?;
    let mut bufreader = std::io::BufReader::new(&file);
    let exifreader = exif::Reader::new();

    Ok(exifreader
        .read_from_container(&mut bufreader)
        .map_err(|_| anyhow!("error reading file"))?)
}

fn correct_orientation(mut img: DynamicImage, orientation: u32) -> DynamicImage {
    if orientation <= 1 || orientation > 8 {
        return img;
    }

    if orientation >= 5 {
        img = img.rotate90().fliph();
    }

    if orientation == 3 || orientation == 4 || orientation == 7 || orientation == 8 {
        img = img.rotate180();
    }

    if orientation % 2 == 0 {
        img = img.fliph();
    }

    img
}

pub fn generate_pictures(picture: &Picture) -> Result<()> {
    let path = format!(
        "{}/{}/original/{}",
        image_base_path(),
        picture.id,
        picture.image_file_name
    );
    let exif = read_exif(&path)?;

    let orientation = match exif.get_field(Tag::Orientation, In::PRIMARY) {
        Some(orientation) => match orientation.value.get_uint(0) {
            Some(v @ 1..=8) => v,
            _ => 0,
        },
        None => 0,
    };

    let mut img = image::open(path)?;
    img = correct_orientation(img, orientation);

    let path = format!("{}/{}/large/{}", image_base_path(), picture.id, picture.image_file_name);
    let new_img = img.resize(800, 600, imageops::FilterType::CatmullRom);
    new_img.save(path)?;

    let path = format!(
        "{}/{}/thumbnail/{}",
        image_base_path(),
        picture.id,
        picture.image_file_name
    );
    let (width, height) = img.dimensions();
    let aspect_ratio = width as f32 / height as f32;

    let img = if aspect_ratio != THUMB_ASPEC_RATIO {
        let mid_x = width / 2;
        let mid_y = height / 2;

        if width > height {
            img.crop(mid_x - (height / 2), mid_y - (height / 2), height, height)
        } else {
            img.crop(mid_x - (width / 2), mid_y - (width / 2), width, width)
        }
    } else {
        img
    };

    let new_img = img.resize_exact(600, 600, imageops::FilterType::CatmullRom);
    new_img.save(path)?;

    Ok(())
}
<commit_msg>enforce JPEG format for pictures<commit_after>use chrono::naive::NaiveDateTime;
use exif::{Exif, In, Tag};
use serde::{Deserialize, Serialize};
use validator::Validate;

use anyhow::{Error, Result};
use image::GenericImageView;
use image::{imageops, DynamicImage};

use crate::schema::pictures;
use crate::utils::image_base_path;

#[derive(Debug, Clone, Queryable, Insertable, Serialize, Deserialize)]
pub struct Picture {
    pub id: i32,
    pub author_id: i32,

    pub in_reply_to: Option<String>,
    pub webmentions_count: i32,

    pub image_file_name: String,
    pub image_content_type: String,
    pub image_file_size: i32,
    pub image_updated_at: NaiveDateTime,

    pub inserted_at: NaiveDateTime,
    pub updated_at: NaiveDateTime,

    pub title: String,

    pub posse: bool,
    pub show_in_index: bool,

    pub content: String,

    pub lang: String,
    pub alt: Option<String>,
}

#[derive(Deserialize, Serialize, Debug, Insertable, Clone, Validate, Default)]
#[table_name = "pictures"]
pub struct NewPicture {
    pub author_id: Option<i32>,
    #[validate(length(min = 5))]
    pub title: String,
    #[validate(length(min = 5))]
    pub alt: Option<String>,
    #[validate(url)]
    pub in_reply_to: Option<String>,
    #[validate(length(min = 2, max = 2))]
    pub lang: String,
    #[serde(default)]
    pub posse: bool,
    #[serde(default)]
    pub show_in_index: bool,
    #[validate(required, length(min = 5))]
    pub content: Option<String>,

    pub image_file_name: Option<String>,
    pub image_content_type: Option<String>,
    pub image_file_size: Option<i32>,
    pub image_updated_at: Option<NaiveDateTime>,

    pub inserted_at: Option<NaiveDateTime>,
    pub updated_at: Option<NaiveDateTime>,
}

#[derive(Deserialize, Serialize, Debug)]
pub struct NewJsonPicture {
    #[serde(flatten)]
    pub new_picture: NewPicture,
    pub picture: Option<String>,
}

const THUMB_ASPEC_RATIO: f32 = 1.0;

fn read_exif(path: &str) -> Result<Exif, Error> {
    let file = std::fs::File::open(path)?;
    let mut bufreader = std::io::BufReader::new(&file);
    let exifreader = exif::Reader::new();

    Ok(exifreader
        .read_from_container(&mut bufreader)
        .map_err(|_| anyhow!("error reading file"))?)
}

fn correct_orientation(mut img: DynamicImage, orientation: u32) -> DynamicImage {
    if orientation <= 1 || orientation > 8 {
        return img;
    }

    if orientation >= 5 {
        img = img.rotate90().fliph();
    }

    if orientation == 3 || orientation == 4 || orientation == 7 || orientation == 8 {
        img = img.rotate180();
    }

    if orientation % 2 == 0 {
        img = img.fliph();
    }

    img
}

pub fn generate_pictures(picture: &Picture) -> Result<()> {
    let path = format!(
        "{}/{}/original/{}",
        image_base_path(),
        picture.id,
        picture.image_file_name
    );
    let exif = read_exif(&path)?;

    let orientation = match exif.get_field(Tag::Orientation, In::PRIMARY) {
        Some(orientation) => match orientation.value.get_uint(0) {
            Some(v @ 1..=8) => v,
            _ => 0,
        },
        None => 0,
    };

    let orig_path = path.clone();
    let mut img = image::open(path)?;

    if !orig_path.ends_with(".png") && !orig_path.ends_with(".gif") {
        img.save_with_format(orig_path, image::ImageFormat::Jpeg)?;
    }

    img = correct_orientation(img, orientation);

    let path = format!("{}/{}/large/{}", image_base_path(), picture.id, picture.image_file_name);
    let new_img = img.resize(800, 600, imageops::FilterType::CatmullRom);
    if !path.ends_with(".png") && !path.ends_with(".gif") {
        new_img.save_with_format(path, image::ImageFormat::Jpeg)?;
    } else {
        new_img.save(path)?;
    }

    let path = format!(
        "{}/{}/thumbnail/{}",
        image_base_path(),
        picture.id,
        picture.image_file_name
    );
    let (width, height) = img.dimensions();
    let aspect_ratio = width as f32 / height as f32;

    let img = if aspect_ratio != THUMB_ASPEC_RATIO {
        let mid_x = width / 2;
        let mid_y = height / 2;

        if width > height {
            img.crop(mid_x - (height / 2), mid_y - (height / 2), height, height)
        } else {
            img.crop(mid_x - (width / 2), mid_y - (width / 2), width, width)
        }
    } else {
        img
    };

    let new_img = img.resize_exact(600, 600, imageops::FilterType::CatmullRom);

    if !path.ends_with(".png") && !path.ends_with(".gif") {
        new_img.save_with_format(path, image::ImageFormat::Jpeg)?;
    } else {
        new_img.save(path)?;
    }

    Ok(())
}
<|endoftext|>


<commit_before>//! The parser module is responsible for parsing FITS files.

use std::str;
use std::str::FromStr;
use super::types::{Keyword, BlankRecord};

named!(fits<&[u8], ((Vec<Keyword>, Keyword, Vec<BlankRecord>), Vec<&[u8]>) >,
       pair!(primary_header, many0!( take!(2880) )));

named!(primary_header<&[u8], (Vec<Keyword>, Keyword, Vec<BlankRecord>)>,
       tuple!(
           many0!(keyword_record),
           end_record,
           many0!(blank_record)
       ));

named!(keyword_record<&[u8], Keyword>,
       map_res!( // TODO should use map_res!
           tuple!(
               take!(8),
               tag!("="),
               take!(71)
           ), |(slice, _, _) : (&[u8], &[u8], &[u8])| {
               Keyword::from_str("OBJECT") // TODO obviously wrong, correct it
           }));

named!(keyword<&[u8], Keyword>,
       map_res!(
           map_res!(
               take!(8),
               str::from_utf8),
           Keyword::from_str
       ));

named!(end_record<&[u8], Keyword>,
       map!(
           pair!(tag!("END"), count!(tag!(" "), 77)),
           |_| { Keyword::END }
       ));

named!(blank_record<&[u8], BlankRecord>,
       map!(
           count!(tag!(" "), 80),
           |_| { BlankRecord }
       ));

#[cfg(test)]
mod tests {
    use nom::{IResult};
    use super::super::types::{Keyword, BlankRecord};
    use super::{fits, primary_header, keyword_record, keyword, end_record, blank_record};

    #[test]
    fn it_should_parse_a_fits_file(){
        let data = include_bytes!("../../assets/images/k2-trappist1-unofficial-tpf-long-cadence.fits");

        let result = fits(data);

        match result {
            IResult::Done(_, (header, blocks)) => {
                assert_eq!(blocks.len(), 3675);
            },
            IResult::Error(_) => panic!("Did not expect an error"),
            IResult::Incomplete(_) => panic!("Did not expect to be incomplete")
        }
    }

    #[test]
    fn primary_header_should_parse_a_primary_header(){
        let data = include_bytes!("../../assets/images/k2-trappist1-unofficial-tpf-long-cadence.fits");

        let result = primary_header(&data[0..(2*2880)]);

        match result {
            IResult::Done(_, (headers, _, _)) => assert_eq!(headers.len(), 55),
            IResult::Error(_) => panic!("Did not expect an error"),
            IResult::Incomplete(_) => panic!("Did not expect to be incomplete")
        }
    }

    #[test]
    fn keyword_record_should_parse_a_keyword_record(){
        let data = "OBJECT  = 'EPIC 200164267'     / string version of target id                    "
            .as_bytes();

        let result = keyword_record(data);

        match result {
            IResult::Done(_,k) => assert_eq!(k, Keyword::OBJECT),
            IResult::Error(_) => panic!("Did not expect an error"),
            IResult::Incomplete(_) => panic!("Did not expect to be incomplete")
        }
    }

    #[test]
    fn keyword_should_parse_a_keyword(){
        let data = "OBJECT  "
            .as_bytes();

        let result = keyword(data);

        match result {
            IResult::Done(_, keyword) => assert_eq!(keyword, Keyword::OBJECT),
            IResult::Error(_) => panic!("Did not expect an error"),
            IResult::Incomplete(_) => panic!("Did not expect to be incomplete")
        }
    }

    #[test]
    fn end_record_should_parse_an_END_record(){
        let data = "END                                                                             "
            .as_bytes();

        let result = end_record(data);

        match result {
            IResult::Done(_, keyword) => assert_eq!(keyword, Keyword::END),
            IResult::Error(_) => panic!("Did not expect an error"),
            IResult::Incomplete(_) => panic!("Did not expect to be incomplete")
        }
    }

    #[test]
    fn blank_record_should_parse_a_BLANK_record(){
        let data = "                                                                                "
            .as_bytes();

        let result = blank_record(data);

        match result {
            IResult::Done(_, record) => assert_eq!(record, BlankRecord),
            IResult::Error(_) => panic!("Did not expect an error"),
            IResult::Incomplete(_) => panic!("Did not expect to be incomplete")
        }
    }
}
<commit_msg>Slightly better, but still obviously wrong<commit_after>//! The parser module is responsible for parsing FITS files.

use std::str;
use std::str::FromStr;
use super::types::{Keyword, BlankRecord};

named!(fits<&[u8], ((Vec<Keyword>, Keyword, Vec<BlankRecord>), Vec<&[u8]>) >,
       pair!(primary_header, many0!( take!(2880) )));

named!(primary_header<&[u8], (Vec<Keyword>, Keyword, Vec<BlankRecord>)>,
       tuple!(
           many0!(keyword_record),
           end_record,
           many0!(blank_record)
       ));

named!(keyword_record<&[u8], Keyword>,
       map_res!( // TODO should use map_res!
           map!(
               tuple!(
                   take!(8),
                   tag!("="),
                   take!(71)
               ), |(slice, _, _) : (&[u8], &[u8], &[u8])| {
                   "OBJECT" // TODO obviously wrong, correct it
               }),
           Keyword::from_str));

named!(keyword<&[u8], Keyword>,
       map_res!(
           map_res!(
               take!(8),
               str::from_utf8),
           Keyword::from_str
       ));

named!(end_record<&[u8], Keyword>,
       map!(
           pair!(tag!("END"), count!(tag!(" "), 77)),
           |_| { Keyword::END }
       ));

named!(blank_record<&[u8], BlankRecord>,
       map!(
           count!(tag!(" "), 80),
           |_| { BlankRecord }
       ));

#[cfg(test)]
mod tests {
    use nom::{IResult};
    use super::super::types::{Keyword, BlankRecord};
    use super::{fits, primary_header, keyword_record, keyword, end_record, blank_record};

    #[test]
    fn it_should_parse_a_fits_file(){
        let data = include_bytes!("../../assets/images/k2-trappist1-unofficial-tpf-long-cadence.fits");

        let result = fits(data);

        match result {
            IResult::Done(_, (header, blocks)) => {
                assert_eq!(blocks.len(), 3675);
            },
            IResult::Error(_) => panic!("Did not expect an error"),
            IResult::Incomplete(_) => panic!("Did not expect to be incomplete")
        }
    }

    #[test]
    fn primary_header_should_parse_a_primary_header(){
        let data = include_bytes!("../../assets/images/k2-trappist1-unofficial-tpf-long-cadence.fits");

        let result = primary_header(&data[0..(2*2880)]);

        match result {
            IResult::Done(_, (headers, _, _)) => assert_eq!(headers.len(), 55),
            IResult::Error(_) => panic!("Did not expect an error"),
            IResult::Incomplete(_) => panic!("Did not expect to be incomplete")
        }
    }

    #[test]
    fn keyword_record_should_parse_a_keyword_record(){
        let data = "OBJECT  = 'EPIC 200164267'     / string version of target id                    "
            .as_bytes();

        let result = keyword_record(data);

        match result {
            IResult::Done(_,k) => assert_eq!(k, Keyword::OBJECT),
            IResult::Error(_) => panic!("Did not expect an error"),
            IResult::Incomplete(_) => panic!("Did not expect to be incomplete")
        }
    }

    #[test]
    fn keyword_should_parse_a_keyword(){
        let data = "OBJECT  "
            .as_bytes();

        let result = keyword(data);

        match result {
            IResult::Done(_, keyword) => assert_eq!(keyword, Keyword::OBJECT),
            IResult::Error(_) => panic!("Did not expect an error"),
            IResult::Incomplete(_) => panic!("Did not expect to be incomplete")
        }
    }

    #[test]
    fn end_record_should_parse_an_END_record(){
        let data = "END                                                                             "
            .as_bytes();

        let result = end_record(data);

        match result {
            IResult::Done(_, keyword) => assert_eq!(keyword, Keyword::END),
            IResult::Error(_) => panic!("Did not expect an error"),
            IResult::Incomplete(_) => panic!("Did not expect to be incomplete")
        }
    }

    #[test]
    fn blank_record_should_parse_a_BLANK_record(){
        let data = "                                                                                "
            .as_bytes();

        let result = blank_record(data);

        match result {
            IResult::Done(_, record) => assert_eq!(record, BlankRecord),
            IResult::Error(_) => panic!("Did not expect an error"),
            IResult::Incomplete(_) => panic!("Did not expect to be incomplete")
        }
    }
}
<|endoftext|>


<commit_before>extern crate moho;
extern crate sdl2_image;
extern crate sdl2;

use self::sdl2::event::Event;
use self::sdl2::keyboard::Keycode;
use self::sdl2::rect;

use self::sdl2_image::{LoadTexture, INIT_PNG, INIT_JPG};
use std::error::Error;
use std::path::Path;

pub fn run() -> Result<(), Box<Error>> {
    let (mut renderer, mut event_pump) = try!(moho::init("Master Smasher", 800, 600));
    let _image_context = try!(sdl2_image::init(INIT_PNG | INIT_JPG));
    let mut input_manager = moho::input_manager::InputManager::new();
    let background_path = Path::new("resources/background_game.png");
    let meteor_path = Path::new("resources/meteor.png");
    let background_texture = try!(renderer.load_texture(background_path));
    let meteor_texture = try!(renderer.load_texture(meteor_path));
    let query = meteor_texture.query();
    let mut dst = rect::Rect::new(0, 0, query.width, query.height);

    'running: loop {
        for event in event_pump.poll_iter() {
            match event {
                Event::Quit { .. } => break 'running,
                Event::KeyDown { keycode: Some(key), .. } => {
                    input_manager.press_key(key);
                }
                Event::KeyUp { keycode: Some(key), .. } => {
                    input_manager.release_key(key);
                }
                _ => {}
            }
        }

        if input_manager.is_key_down(Keycode::Escape) {
            break;
        }

        if input_manager.is_key_down(Keycode::Down) {
            dst.offset(0, 1);
        }

        if input_manager.is_key_down(Keycode::Up) {
            dst.offset(0, -1);
        }

        if input_manager.is_key_down(Keycode::Left) {
            dst.offset(-1, 0);
        }

        if input_manager.is_key_down(Keycode::Right) {
            dst.offset(1, 0);
        }

        // The rest of the game loop goes here...
        renderer.clear();
        try!(renderer.copy(&background_texture, None, None));
        try!(renderer.copy(&meteor_texture, None, Some(dst)));
        renderer.present();
    }

    Ok(())
}
<commit_msg>wrapping WIP<commit_after>extern crate moho;
extern crate sdl2_image;
extern crate sdl2;

use self::sdl2::event::Event;
use self::sdl2::keyboard::Keycode;
use self::sdl2::rect;

use self::sdl2_image::{LoadTexture, INIT_PNG, INIT_JPG};
use std::error::Error;
use std::path::Path;

pub fn run() -> Result<(), Box<Error>> {
    const WINDOW_HEIGHT: u32 = 600;
    const WINDOW_WIDTH: u32 = 800;
    let (mut renderer, mut event_pump) =
        try!(moho::init("Master Smasher", WINDOW_WIDTH, WINDOW_HEIGHT));
    let _image_context = try!(sdl2_image::init(INIT_PNG | INIT_JPG));
    let mut input_manager = moho::input_manager::InputManager::new();
    let background_path = Path::new("resources/background_game.png");
    let meteor_path = Path::new("resources/meteor.png");
    let background_texture = try!(renderer.load_texture(background_path));
    let meteor_texture = try!(renderer.load_texture(meteor_path));
    let query = meteor_texture.query();
    let mut dst = rect::Rect::new(0, 0, query.width, query.height);
    let mut dst2 = None;

    'running: loop {
        for event in event_pump.poll_iter() {
            match event {
                Event::Quit { .. } => break 'running,
                Event::KeyDown { keycode: Some(key), .. } => {
                    input_manager.press_key(key);
                }
                Event::KeyUp { keycode: Some(key), .. } => {
                    input_manager.release_key(key);
                }
                _ => {}
            }
        }

        if input_manager.is_key_down(Keycode::Escape) {
            break;
        }

        if input_manager.is_key_down(Keycode::Down) {
            dst.offset(0, 1);

            if (dst.top() > WINDOW_HEIGHT as i32) {
                let top = dst.top() % WINDOW_HEIGHT as i32;
                dst.set_y(top);
                dst2 = None
            }

            if (dst.bottom() > WINDOW_HEIGHT as i32) {
                let mut clone_rect = dst.clone();
                clone_rect.set_bottom(dst.bottom() % WINDOW_HEIGHT as i32);
                dst2 = Some(clone_rect);
            }
        }

        if input_manager.is_key_down(Keycode::Up) {
            dst.offset(0, -1);
        }

        if input_manager.is_key_down(Keycode::Left) {
            dst.offset(-1, 0);
        }

        if input_manager.is_key_down(Keycode::Right) {
            dst.offset(1, 0);
        }

        // The rest of the game loop goes here...
        renderer.clear();
        try!(renderer.copy(&background_texture, None, None));
        try!(renderer.copy(&meteor_texture, None, Some(dst)));

        match dst2 {
            Some(_) => {
                try!(renderer.copy(&meteor_texture, None, dst2));
            }
            None => {}
        }

        renderer.present();
    }

    Ok(())
}
<|endoftext|>


<commit_before>#![allow(dead_code)]
#![allow(unused_variable)]

#[deriving(Show)]
#[deriving(Clone)]
pub enum Doc {
    Nil,
    Append(Box<Doc>, Box<Doc>),
    Nest(uint, Box<Doc>),
    Text(String),
    Break(uint, uint),
    Newline,
    Group(Box<Doc>)
}

impl Doc {
    pub fn append(&self, e:Doc) -> Doc {
        match self {
            &Nil => e,
            x => match e {
                Nil => x.clone(),
                y => Append(box x.clone(), box y)
            }
        }
    }
}

fn concat(ds:&[Doc]) -> Doc {
    ds.iter().fold(Nil, |a, b| Append(box a, box b.clone()))
}

fn int(i:int) -> Doc {
    Text(format!("{}", i))
}

fn char(c:char) -> Doc {
    Text(format!("{}", c))
}

fn bool(b:bool) -> Doc {
    if b {
        Text(String::from_str("true"))
    } else {
        Text(String::from_str("false"))
    }
}

mod mode {
    #[deriving(Clone)]
    pub enum Mode {
        Flat,
        Break
    }
}

fn replicate<A:Clone>(x:A, l:uint) -> Vec<A> {
    let i = 0u;
    let mut res = Vec::new();
    for _ in range(i,l) {
        res.push(x.clone());
    }
    res
}
fn pad_right(c:char, l:uint, str:String) -> String {
    let str_len = str.len();
    if l > str_len {
        let padding = replicate(String::from_chars([c]), l - str_len).concat();
        let mut res = str.clone();
        res.push_str(padding.as_slice());
        res
    } else {
        str
    }
}
fn pad_left(c:char, l:uint, str:String) -> String {
    let str_len = str.len();
    if l > str_len {
      let mut res = replicate(String::from_chars([c]), l - str_len).concat();
      res.push_str(str.as_slice());
      res
    } else {
        str
    }
}

fn nlspace(s:Vec<String>, i:uint) -> Vec<String> {
    prepend(s, pad_right(' ', i + String::from_str("\n").len(), String::from_str("\n")))
}

fn spaces(s:Vec<String>, i:uint) -> Vec<String> {
    prepend(s, pad_left(' ', i, String::from_str("")))
}

fn fitting(xs:&Vec<(uint,mode::Mode,Doc)>, left:uint) -> bool {
    if left as int >= 0 {
        match xs.as_slice() {
            [] => true,
            [(ref i, ref mode, ref doc), ref rest..] => match *doc {
                Nil => fitting(&rest.to_vec(), left),
                Append(ref x, ref y) => {
                    let mut ys = [(*i,*mode,*x.clone()), (*i,*mode,*y.clone())].to_vec();
                    ys.push_all(*rest);
                    fitting(&ys,left)
                },
                Nest(j, ref x) => {
                    let mut ys = [(*i+j,*mode,*x.clone())].to_vec();
                    ys.push_all(*rest);
                    fitting(&ys, left)
                },
                Text(ref str) => fitting(&rest.to_vec(), left - str.len()),
                Break(sp, _) => match *mode {
                    mode::Flat => fitting(&rest.to_vec(), left - sp),
                    mode::Break => true
                },
                Newline => true,
                Group(ref x) => {
                    let mut ys = [(*i,*mode, *x.clone())].to_vec();
                    ys.push_all(*rest);
                    fitting(&ys, left)
                }
            }
        }
    }
    else {
        false
    }
}

fn prepend<A:Clone>(v: Vec<A>, x:A) -> Vec<A> {
    let mut res = v;
    res.insert(0,x);
    res
}

fn best(w:uint, s:Vec<String>, x:Doc) -> Vec<String> {
    fn go(w:uint, s:Vec<String>, k:uint, xs:Vec<(uint,mode::Mode,Doc)>) -> Vec<String> {
        match xs.as_slice() {
            [] => s.clone(),
            [(ref i, ref mode, ref doc), ref rest..] => match *doc {
                Nil => go(w, s, k, rest.to_vec()),
                Append(ref x, ref y) => {
                    let mut zs = [(*i, *mode, *x.clone()), (*i, *mode, *y.clone())].to_vec();
                    zs.push_all(*rest);
                    go(w, s, k, zs)
                },
                Nest(j, ref x) => {
                    let mut zs = [(*i + j, *mode, *x.clone())].to_vec();
                    zs.push_all(*rest);
                    go(w, s, k, zs)
                },
                Text(ref str) => {
                    let ss = prepend(s, str.clone());
                    go(w, ss, k + str.len(), rest.to_vec())
                },
                Newline => {
                    let ss = nlspace(s, *i);
                    go(w, ss, *i, rest.to_vec())
                },
                Break(sp, off) => {
                    match *mode {
                        mode::Flat => {
                            let ss = spaces(s.clone(), sp);
                            go(w, ss, k + sp, rest.to_vec())
                        },
                        mode::Break => {
                            let ss = nlspace(s.clone(), i + off);
                            go(w, ss, i + off, rest.to_vec())
                        }
                    }
                },
                Group(ref x) => {
                    match *mode {
                        mode::Flat => {
                            let mut zs = [(*i,mode::Flat,*x.clone())].to_vec();
                            zs.push_all(*rest);
                            go(w, s, k, zs)
                        },
                        mode::Break => {
                            let mut ys = [(*i,mode::Flat,*x.clone())].to_vec();
                            ys.push_all(*rest);
                            if fitting(&ys, w - k) {
                                go(w, s, k, ys)
                            } else {
                                let mut zs = [(*i,mode::Break,*x.clone())].to_vec();
                                zs.push_all(*rest);
                                go(w, s, k, zs)
                            }
                        }
                    }
                }
            }
        }
    }
    go(w, s, 0, [(0,mode::Break,x)].to_vec())
}

impl Doc {
    pub fn to_string(&self, w:uint) -> String {
        let mut strs = best(w, [].to_vec(), self.clone());
        strs.reverse();
        strs.push(String::from_str("\n"));
        strs.concat()
    }
}
<commit_msg>Minor improvements<commit_after>#![allow(dead_code)]
#![allow(unused_variable)]

#[deriving(Show)]
#[deriving(Clone)]
pub enum Doc {
    Nil,
    Append(Box<Doc>, Box<Doc>),
    Nest(uint, Box<Doc>),
    Text(String),
    Break(uint, uint),
    Newline,
    Group(Box<Doc>)
}

mod mode {
    #[deriving(Clone)]
    pub enum Mode {
        Flat,
        Break
    }
}

fn replicate<A:Clone>(x:A, l:uint) -> Vec<A> {
    let i = 0u;
    let mut res = Vec::new();
    for _ in range(i,l) {
        res.push(x.clone());
    }
    res
}

fn pad_right(c:char, l:uint, str:String) -> String {
    let str_len = str.len();
    if l > str_len {
        let padding = replicate(String::from_chars([c]), l - str_len).concat();
        let mut res = str.clone();
        res.push_str(padding.as_slice());
        res
    } else {
        str
    }
}
fn pad_left(c:char, l:uint, str:String) -> String {
    let str_len = str.len();
    if l > str_len {
      let mut res = replicate(String::from_chars([c]), l - str_len).concat();
      res.push_str(str.as_slice());
      res
    } else {
        str
    }
}

fn nlspace(s:Vec<String>, i:uint) -> Vec<String> {
    prepend(s, pad_right(' ', i + String::from_str("\n").len(), String::from_str("\n")))
}

fn spaces(s:Vec<String>, i:uint) -> Vec<String> {
    prepend(s, pad_left(' ', i, String::from_str("")))
}

fn fitting(xs:&Vec<(uint,mode::Mode,Doc)>, left:uint) -> bool {
    if left as int >= 0 {
        match xs.as_slice() {
            [] => true,
            [(ref i, ref mode, ref doc), ref rest..] => match *doc {
                Nil => fitting(&rest.to_vec(), left),
                Append(ref x, ref y) => {
                    let mut ys = [(*i,*mode,*x.clone()), (*i,*mode,*y.clone())].to_vec();
                    ys.push_all(*rest);
                    fitting(&ys,left)
                },
                Nest(j, ref x) => {
                    let mut ys = [(*i+j,*mode,*x.clone())].to_vec();
                    ys.push_all(*rest);
                    fitting(&ys, left)
                },
                Text(ref str) => fitting(&rest.to_vec(), left - str.len()),
                Break(sp, _) => match *mode {
                    mode::Flat => fitting(&rest.to_vec(), left - sp),
                    mode::Break => true
                },
                Newline => true,
                Group(ref x) => {
                    let mut ys = [(*i,*mode, *x.clone())].to_vec();
                    ys.push_all(*rest);
                    fitting(&ys, left)
                }
            }
        }
    }
    else {
        false
    }
}

fn prepend<A:Clone>(v: Vec<A>, x:A) -> Vec<A> {
    let mut res = v;
    res.insert(0,x);
    res
}

fn best(w:uint, s:Vec<String>, x:Doc) -> Vec<String> {
    fn go(w:uint, s:Vec<String>, k:uint, xs:Vec<(uint,mode::Mode,Doc)>) -> Vec<String> {
        match xs.as_slice() {
            [] => s.clone(),
            [(ref i, ref mode, ref doc), ref rest..] => match *doc {
                Nil => go(w, s, k, rest.to_vec()),
                Append(ref x, ref y) => {
                    let mut zs = [(*i, *mode, *x.clone()), (*i, *mode, *y.clone())].to_vec();
                    zs.push_all(*rest);
                    go(w, s, k, zs)
                },
                Nest(j, ref x) => {
                    let mut zs = [(*i + j, *mode, *x.clone())].to_vec();
                    zs.push_all(*rest);
                    go(w, s, k, zs)
                },
                Text(ref str) => {
                    let ss = prepend(s, str.clone());
                    go(w, ss, k + str.len(), rest.to_vec())
                },
                Newline => {
                    let ss = nlspace(s, *i);
                    go(w, ss, *i, rest.to_vec())
                },
                Break(sp, off) => {
                    match *mode {
                        mode::Flat => {
                            let ss = spaces(s.clone(), sp);
                            go(w, ss, k + sp, rest.to_vec())
                        },
                        mode::Break => {
                            let ss = nlspace(s.clone(), i + off);
                            go(w, ss, i + off, rest.to_vec())
                        }
                    }
                },
                Group(ref x) => {
                    match *mode {
                        mode::Flat => {
                            let mut zs = [(*i,mode::Flat,*x.clone())].to_vec();
                            zs.push_all(*rest);
                            go(w, s, k, zs)
                        },
                        mode::Break => {
                            let mut ys = [(*i,mode::Flat,*x.clone())].to_vec();
                            ys.push_all(*rest);
                            if fitting(&ys, w - k) {
                                go(w, s, k, ys)
                            } else {
                                let mut zs = [(*i,mode::Break,*x.clone())].to_vec();
                                zs.push_all(*rest);
                                go(w, s, k, zs)
                            }
                        }
                    }
                }
            }
        }
    }
    go(w, s, 0, [(0,mode::Break,x)].to_vec())
}

impl Doc {
    pub fn append(&self, e:Doc) -> Doc {
        match *self {
            Nil => e,
            ref x => match e {
                Nil => x.clone(),
                y => Append(box x.clone(), box y)
            }
        }
    }

    pub fn to_string(&self, w:uint) -> String {
        let mut strs = best(w, [].to_vec(), self.clone());
        strs.reverse();
        strs.push(String::from_str("\n"));
        strs.concat()
    }
}

pub fn concat(ds:&[Doc]) -> Doc {
    ds.iter().fold(Nil, |a, b| a.append(b.clone()))
}

pub fn int(i:int) -> Doc {
    Text(format!("{}", i))
}

pub fn char(c:char) -> Doc {
    Text(format!("{}", c))
}

pub fn bool(b:bool) -> Doc {
    if b {
        Text(String::from_str("true"))
    } else {
        Text(String::from_str("false"))
    }
}

<|endoftext|>


<commit_before>// Copyright (c) 2016-2017 Chef Software Inc. and/or applicable contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::path::PathBuf;

use linux_users;
use linux_users::os::unix::UserExt;

pub fn get_uid_by_name(owner: &str) -> Option<u32> {
    linux_users::get_user_by_name(owner).map(|u| u.uid())
}

pub fn get_gid_by_name(group: &str) -> Option<u32> {
    linux_users::get_group_by_name(&group.as_ref()).map(|g| g.gid())
}

pub fn get_current_username() -> Option<String> {
    linux_users::get_current_username()
}

pub fn get_current_groupname() -> Option<String> {
    linux_users::get_current_groupname()
}

pub fn get_effective_username() -> Option<String> {
    linux_users::get_effective_username()
}

pub fn get_effective_uid() -> u32 {
    linux_users::get_effective_uid()
}

pub fn get_effective_gid() -> u32 {
    linux_users::get_effective_gid()
}

pub fn get_effective_groupname() -> Option<String> {
    linux_users::get_effective_groupname()
}

pub fn get_home_for_user(username: &str) -> Option<PathBuf> {
    linux_users::get_user_by_name(username).map(|u| PathBuf::from(u.home_dir()))
}

pub fn root_level_account() -> String {
    "root".to_string()
}
<commit_msg>Exposes members from group struct via new fn<commit_after>// Copyright (c) 2016-2017 Chef Software Inc. and/or applicable contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::path::PathBuf;

use linux_users;
use linux_users::os::unix::{GroupExt, UserExt};

pub fn get_uid_by_name(owner: &str) -> Option<u32> {
    linux_users::get_user_by_name(owner).map(|u| u.uid())
}

pub fn get_gid_by_name(group: &str) -> Option<u32> {
    linux_users::get_group_by_name(&group.as_ref()).map(|g| g.gid())
}

pub fn get_members_by_groupname(group: &str) -> Option<Vec<String>> {
    linux_users::get_group_by_name(&group.as_ref()).map(|g| g.members().to_vec())
}

pub fn get_current_username() -> Option<String> {
    linux_users::get_current_username()
}

pub fn get_current_groupname() -> Option<String> {
    linux_users::get_current_groupname()
}

pub fn get_effective_username() -> Option<String> {
    linux_users::get_effective_username()
}

pub fn get_effective_uid() -> u32 {
    linux_users::get_effective_uid()
}

pub fn get_effective_gid() -> u32 {
    linux_users::get_effective_gid()
}

pub fn get_effective_groupname() -> Option<String> {
    linux_users::get_effective_groupname()
}

pub fn get_home_for_user(username: &str) -> Option<PathBuf> {
    linux_users::get_user_by_name(username).map(|u| PathBuf::from(u.home_dir()))
}

pub fn root_level_account() -> String {
    "root".to_string()
}
<|endoftext|>


<commit_before>use std::net::{SocketAddr, ToSocketAddrs, lookup_host};
use std::str::FromStr;
use std::iter::Iterator;
use std::io::Result as IoResult;
use mioco;
use mioco::tcp::{TcpListener, TcpStream};
use request::Request;
use response::Response;
use connection::{Connection, ConnResult};

///
/// HTTP Proxy Server implemenation
///
pub struct RainyProxy {
    pub addr: SocketAddr,
}

impl RainyProxy {
    pub fn new<T: ToSocketAddrs>(addr: &T) -> RainyProxy {
        let sock = addr.to_socket_addrs().unwrap().next().unwrap();
        RainyProxy { addr: sock }
    }

    pub fn serve(&self) -> IoResult<()> {
        let listener = try!(TcpListener::bind(&self.addr));
        debug!("Proxy server listen at {}", &self.addr);

        mioco::start(move || {
            for _ in 0..mioco::thread_num() {
                let listener: TcpListener = try!(listener.try_clone());
                mioco::spawn(move || -> IoResult<()> {
                    loop {
                        let mut src_conn = Connection::new(try!(listener.accept()));
                        mioco::spawn(move || -> IoResult<()> {
                            loop {
                                // recieve source request
                                let mut request: Request = match src_conn.recieve() {
                                    ConnResult::Ok(req) => req,
                                    ConnResult::ParseErr(p_err) => break,
                                    ConnResult::IoError(io_err) => break,
                                };

                                // lookup and connect to destination host
                                let addr = match lookup_dest(&mut request) {
                                    Some(sock) => sock,
                                    None => {
                                        debug!("cannot lookup host {:?}", request.path);
                                        break;
                                    }
                                };
                                request.path = Some(request.path
                                                           .as_ref()
                                                           .unwrap()
                                                           .split("/")
                                                           .skip(3)
                                                           .fold(String::from(""),
                                                                 |acc, s| acc + "/" + s));

                                let mut dest_conn = Connection::new(TcpStream::connect(&addr)
                                                                        .unwrap());
                                debug!("connecting to server {}", addr);

                                // send request to destination host
                                match dest_conn.send(&request) {
                                    ConnResult::Ok(()) => {}
                                    ConnResult::ParseErr(p_err) => break,
                                    ConnResult::IoError(io_err) => break,
                                }

                                debug!("send to server.");

                                // recieve destination response
                                let response: Response = match dest_conn.recieve() {
                                    ConnResult::Ok(req) => req,
                                    ConnResult::ParseErr(p_err) => break,
                                    ConnResult::IoError(io_err) => break,
                                };

                                debug!("recieved from server.");

                                // send response to source host
                                match src_conn.send(&response) {
                                    ConnResult::Ok(()) => {}
                                    ConnResult::ParseErr(p_err) => break,
                                    ConnResult::IoError(io_err) => break,
                                };

                                debug!("send to client");
                            }

                            Ok(())
                        });
                    }
                });
            }

            Ok(())
        });
        Ok(())
    }
}

fn lookup_dest(req: &mut Request) -> Option<SocketAddr> {
    if req.path.is_none() {
        return None;
    }

    let path = req.path.as_ref().unwrap();
    let host = extract_host(&path);
    let mut lookuped: SocketAddr = match lookup_host(&host) {
        Ok(mut lkup_host) => lkup_host.nth(0).unwrap().unwrap(),
        Err(e) => return None,
    };

    let to_port = extract_port(path).unwrap_or(80);
    lookuped.set_port(to_port);
    debug!("forword host: {}", &lookuped);

    return Some(lookuped);
}

fn extract_host(path: &str) -> String {
    path.trim_left_matches("http://")
        .split("/")
        .nth(0)
        .unwrap()
        .split(":")
        .nth(0)
        .unwrap()
        .to_string()
}

fn extract_port(path: &str) -> Option<u16> {
    let port_str = match path.split(":").nth(2) {
                       Some(s) => s,
                       None => return None,
                   }
                   .split("/")
                   .nth(0)
                   .unwrap();
    FromStr::from_str(port_str).ok()
}
<commit_msg>create common error flow macro.<commit_after>use std::net::{SocketAddr, ToSocketAddrs, lookup_host};
use std::str::FromStr;
use std::iter::Iterator;
use std::io::Result as IoResult;
use mioco;
use mioco::tcp::{TcpListener, TcpStream};
use request::Request;
use response::Response;
use connection::{Connection, ConnResult};

macro_rules! try_com {
    ($com: expr, err => $errexpr: expr) => {
        match $com {
            ConnResult::Ok(x) => x,
            ConnResult::ParseErr(_) => $errexpr,
            ConnResult::IoError(_) => $errexpr,
        }
    }
}

///
/// HTTP Proxy Server implemenation
///
pub struct RainyProxy {
    pub addr: SocketAddr,
}

impl RainyProxy {
    pub fn new<T: ToSocketAddrs>(addr: &T) -> RainyProxy {
        let sock = addr.to_socket_addrs().unwrap().next().unwrap();
        RainyProxy { addr: sock }
    }

    pub fn serve(&self) -> IoResult<()> {
        let listener = try!(TcpListener::bind(&self.addr));
        debug!("Proxy server listen at {}", &self.addr);

        mioco::start(move || {
            for _ in 0..mioco::thread_num() {
                let listener: TcpListener = try!(listener.try_clone());
                mioco::spawn(move || -> IoResult<()> {
                    loop {
                        let mut src_conn = Connection::new(try!(listener.accept()));
                        mioco::spawn(move || -> IoResult<()> {
                            loop {
                                // recieve source request
                                let mut request: Request = try_com!(src_conn.recieve(), err=>break);

                                // lookup and connect to destination host
                                let addr = match lookup_dest(&mut request) {
                                    Some(sock) => sock,
                                    None => {
                                        debug!("cannot lookup host {:?}", request.path);
                                        break;
                                    }
                                };
                                request.path = Some(request.path
                                                           .as_ref()
                                                           .unwrap()
                                                           .split("/")
                                                           .skip(3)
                                                           .fold(String::from(""),
                                                                 |acc, s| acc + "/" + s));

                                let mut dest_conn = Connection::new(TcpStream::connect(&addr)
                                                                        .unwrap());
                                debug!("connecting to server {}", addr);

                                // send request to destination host
                                try_com!(dest_conn.send(&request), err=>break);

                                debug!("send to server.");

                                // recieve destination response
                                let response: Response = try_com!(dest_conn.recieve(), err=>break);

                                debug!("recieved from server.");

                                // send response to source host
                                try_com!(src_conn.send(&response), err=>break);

                                debug!("send to client");
                            }

                            Ok(())
                        });
                    }
                });
            }

            Ok(())
        });
        Ok(())
    }
}

fn lookup_dest(req: &mut Request) -> Option<SocketAddr> {
    if req.path.is_none() {
        return None;
    }

    let path = req.path.as_ref().unwrap();
    let host = extract_host(&path);
    let mut lookuped: SocketAddr = match lookup_host(&host) {
        Ok(mut lkup_host) => lkup_host.nth(0).unwrap().unwrap(),
        Err(e) => return None,
    };

    let to_port = extract_port(path).unwrap_or(80);
    lookuped.set_port(to_port);
    debug!("forword host: {}", &lookuped);

    return Some(lookuped);
}

fn extract_host(path: &str) -> String {
    path.trim_left_matches("http://")
        .split("/")
        .nth(0)
        .unwrap()
        .split(":")
        .nth(0)
        .unwrap()
        .to_string()
}

fn extract_port(path: &str) -> Option<u16> {
    let port_str = match path.split(":").nth(2) {
                       Some(s) => s,
                       None => return None,
                   }
                   .split("/")
                   .nth(0)
                   .unwrap();
    FromStr::from_str(port_str).ok()
}
<|endoftext|>


<commit_before>// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// https://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! The implementations of `Rand` for the built-in types.

use core::{char, mem};

use {Rand, Rng, SeedableRng};

impl Rand for isize {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> isize {
        if mem::size_of::<isize>() == 4 {
            rng.gen::<i32>() as isize
        } else {
            rng.gen::<i64>() as isize
        }
    }
}

impl Rand for i8 {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> i8 {
        rng.next_u32() as i8
    }
}

impl Rand for i16 {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> i16 {
        rng.next_u32() as i16
    }
}

impl Rand for i32 {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> i32 {
        rng.next_u32() as i32
    }
}

impl Rand for i64 {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> i64 {
        rng.next_u64() as i64
    }
}

#[cfg(feature = "i128_support")]
impl Rand for i128 {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> i128 {
        rng.gen::<u128>() as i128
    }
}

impl Rand for usize {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> usize {
        if mem::size_of::<usize>() == 4 {
            rng.gen::<u32>() as usize
        } else {
            rng.gen::<u64>() as usize
        }
    }
}

impl Rand for u8 {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> u8 {
        rng.next_u32() as u8
    }
}

impl Rand for u16 {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> u16 {
        rng.next_u32() as u16
    }
}

impl Rand for u32 {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> u32 {
        rng.next_u32()
    }
}

impl Rand for u64 {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> u64 {
        rng.next_u64()
    }
}

#[cfg(feature = "i128_support")]
impl Rand for u128 {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> u128 {
        ((rng.next_u64() as u128) << 64) | (rng.next_u64() as u128)
    }
}

macro_rules! float_impls {
    ($mod_name:ident, $ty:ty, $mantissa_bits:expr, $method_name:ident) => {
        mod $mod_name {
            use {Rand, Rng, Open01, Closed01};

            const SCALE: $ty = (1u64 << $mantissa_bits) as $ty;

            impl Rand for $ty {
                /// Generate a floating point number in the half-open
                /// interval `[0,1)`.
                ///
                /// See `Closed01` for the closed interval `[0,1]`,
                /// and `Open01` for the open interval `(0,1)`.
                #[inline]
                fn rand<R: Rng>(rng: &mut R) -> $ty {
                    rng.$method_name()
                }
            }
            impl Rand for Open01<$ty> {
                #[inline]
                fn rand<R: Rng>(rng: &mut R) -> Open01<$ty> {
                    // add a small amount (specifically 2 bits below
                    // the precision of f64/f32 at 1.0), so that small
                    // numbers are larger than 0, but large numbers
                    // aren't pushed to/above 1.
                    Open01(rng.$method_name() + 0.25 / SCALE)
                }
            }
            impl Rand for Closed01<$ty> {
                #[inline]
                fn rand<R: Rng>(rng: &mut R) -> Closed01<$ty> {
                    // rescale so that 1.0 - epsilon becomes 1.0
                    // precisely.
                    Closed01(rng.$method_name() * SCALE / (SCALE - 1.0))
                }
            }
        }
    }
}
float_impls! { f64_rand_impls, f64, 53, next_f64 }
float_impls! { f32_rand_impls, f32, 24, next_f32 }

impl Rand for char {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> char {
        // a char is 21 bits
        const CHAR_MASK: u32 = 0x001f_ffff;
        loop {
            // Rejection sampling. About 0.2% of numbers with at most
            // 21-bits are invalid codepoints (surrogates), so this
            // will succeed first go almost every time.
            match char::from_u32(rng.next_u32() & CHAR_MASK) {
                Some(c) => return c,
                None => {}
            }
        }
    }
}

impl Rand for bool {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> bool {
        rng.gen::<u8>() & 1 == 1
    }
}

macro_rules! tuple_impl {
    // use variables to indicate the arity of the tuple
    ($($tyvar:ident),* ) => {
        // the trailing commas are for the 1 tuple
        impl<
            $( $tyvar : Rand ),*
            > Rand for ( $( $tyvar ),* , ) {

            #[inline]
            fn rand<R: Rng>(_rng: &mut R) -> ( $( $tyvar ),* , ) {
                (
                    // use the $tyvar's to get the appropriate number of
                    // repeats (they're not actually needed)
                    $(
                        _rng.gen::<$tyvar>()
                    ),*
                    ,
                )
            }
        }
    }
}

impl Rand for () {
    #[inline]
    fn rand<R: Rng>(_: &mut R) -> () { () }
}
tuple_impl!{A}
tuple_impl!{A, B}
tuple_impl!{A, B, C}
tuple_impl!{A, B, C, D}
tuple_impl!{A, B, C, D, E}
tuple_impl!{A, B, C, D, E, F}
tuple_impl!{A, B, C, D, E, F, G}
tuple_impl!{A, B, C, D, E, F, G, H}
tuple_impl!{A, B, C, D, E, F, G, H, I}
tuple_impl!{A, B, C, D, E, F, G, H, I, J}
tuple_impl!{A, B, C, D, E, F, G, H, I, J, K}
tuple_impl!{A, B, C, D, E, F, G, H, I, J, K, L}

macro_rules! array_impl {
    {$n:expr, $t:ident, $($ts:ident,)*} => {
        array_impl!{($n - 1), $($ts,)*}

        impl<T> Rand for [T; $n] where T: Rand {
            #[inline]
            fn rand<R: Rng>(_rng: &mut R) -> [T; $n] {
                [_rng.gen::<$t>(), $(_rng.gen::<$ts>()),*]
            }
        }
    };
    {$n:expr,} => {
        impl<T> Rand for [T; $n] {
            fn rand<R: Rng>(_rng: &mut R) -> [T; $n] { [] }
        }
    };
}

array_impl!{32, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,}

impl<T:Rand> Rand for Option<T> {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> Option<T> {
        if rng.gen() {
            Some(rng.gen())
        } else {
            None
        }
    }
}

impl<T: SeedableRng> Rand for T {
    fn rand<R: Rng>(rng: &mut R) -> Self {
        Self::from_rng(rng).unwrap()
    }
}

#[cfg(test)]
mod tests {
    use impls;
    use {Rng, Open01, Closed01};

    struct ConstantRng(u64);
    impl Rng for ConstantRng {
        fn next_u32(&mut self) -> u32 {
            let ConstantRng(v) = *self;
            v as u32
        }
        fn next_u64(&mut self) -> u64 {
            let ConstantRng(v) = *self;
            v
        }

        fn fill_bytes(&mut self, dest: &mut [u8]) {
            impls::fill_bytes_via_u64(self, dest)
        }
    }

    #[test]
    fn floating_point_edge_cases() {
        // the test for exact equality is correct here.
        assert!(ConstantRng(0xffff_ffff).gen::<f32>() != 1.0);
        assert!(ConstantRng(0xffff_ffff_ffff_ffff).gen::<f64>() != 1.0);
    }

    #[test]
    fn rand_open() {
        // this is unlikely to catch an incorrect implementation that
        // generates exactly 0 or 1, but it keeps it sane.
        let mut rng = ::test::rng(501);
        for _ in 0..1_000 {
            // strict inequalities
            let Open01(f) = rng.gen::<Open01<f64>>();
            assert!(0.0 < f && f < 1.0);

            let Open01(f) = rng.gen::<Open01<f32>>();
            assert!(0.0 < f && f < 1.0);
        }
    }

    #[test]
    fn rand_closed() {
        let mut rng = ::test::rng(502);
        for _ in 0..1_000 {
            // strict inequalities
            let Closed01(f) = rng.gen::<Closed01<f64>>();
            assert!(0.0 <= f && f <= 1.0);

            let Closed01(f) = rng.gen::<Closed01<f32>>();
            assert!(0.0 <= f && f <= 1.0);
        }
    }
}
<commit_msg>Test floating point edge-cases<commit_after>// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// https://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! The implementations of `Rand` for the built-in types.

use core::{char, mem};

use {Rand, Rng, SeedableRng};

impl Rand for isize {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> isize {
        if mem::size_of::<isize>() == 4 {
            rng.gen::<i32>() as isize
        } else {
            rng.gen::<i64>() as isize
        }
    }
}

impl Rand for i8 {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> i8 {
        rng.next_u32() as i8
    }
}

impl Rand for i16 {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> i16 {
        rng.next_u32() as i16
    }
}

impl Rand for i32 {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> i32 {
        rng.next_u32() as i32
    }
}

impl Rand for i64 {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> i64 {
        rng.next_u64() as i64
    }
}

#[cfg(feature = "i128_support")]
impl Rand for i128 {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> i128 {
        rng.gen::<u128>() as i128
    }
}

impl Rand for usize {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> usize {
        if mem::size_of::<usize>() == 4 {
            rng.gen::<u32>() as usize
        } else {
            rng.gen::<u64>() as usize
        }
    }
}

impl Rand for u8 {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> u8 {
        rng.next_u32() as u8
    }
}

impl Rand for u16 {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> u16 {
        rng.next_u32() as u16
    }
}

impl Rand for u32 {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> u32 {
        rng.next_u32()
    }
}

impl Rand for u64 {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> u64 {
        rng.next_u64()
    }
}

#[cfg(feature = "i128_support")]
impl Rand for u128 {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> u128 {
        ((rng.next_u64() as u128) << 64) | (rng.next_u64() as u128)
    }
}

macro_rules! float_impls {
    ($mod_name:ident, $ty:ty, $mantissa_bits:expr, $method_name:ident) => {
        mod $mod_name {
            use {Rand, Rng, Open01, Closed01};

            const SCALE: $ty = (1u64 << $mantissa_bits) as $ty;

            impl Rand for $ty {
                /// Generate a floating point number in the half-open
                /// interval `[0,1)`.
                ///
                /// See `Closed01` for the closed interval `[0,1]`,
                /// and `Open01` for the open interval `(0,1)`.
                #[inline]
                fn rand<R: Rng>(rng: &mut R) -> $ty {
                    rng.$method_name()
                }
            }
            impl Rand for Open01<$ty> {
                #[inline]
                fn rand<R: Rng>(rng: &mut R) -> Open01<$ty> {
                    // add a small amount (specifically 2 bits below
                    // the precision of f64/f32 at 1.0), so that small
                    // numbers are larger than 0, but large numbers
                    // aren't pushed to/above 1.
                    Open01(rng.$method_name() + 0.25 / SCALE)
                }
            }
            impl Rand for Closed01<$ty> {
                #[inline]
                fn rand<R: Rng>(rng: &mut R) -> Closed01<$ty> {
                    // rescale so that 1.0 - epsilon becomes 1.0
                    // precisely.
                    Closed01(rng.$method_name() * SCALE / (SCALE - 1.0))
                }
            }
        }
    }
}
float_impls! { f64_rand_impls, f64, 53, next_f64 }
float_impls! { f32_rand_impls, f32, 24, next_f32 }

impl Rand for char {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> char {
        // a char is 21 bits
        const CHAR_MASK: u32 = 0x001f_ffff;
        loop {
            // Rejection sampling. About 0.2% of numbers with at most
            // 21-bits are invalid codepoints (surrogates), so this
            // will succeed first go almost every time.
            match char::from_u32(rng.next_u32() & CHAR_MASK) {
                Some(c) => return c,
                None => {}
            }
        }
    }
}

impl Rand for bool {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> bool {
        rng.gen::<u8>() & 1 == 1
    }
}

macro_rules! tuple_impl {
    // use variables to indicate the arity of the tuple
    ($($tyvar:ident),* ) => {
        // the trailing commas are for the 1 tuple
        impl<
            $( $tyvar : Rand ),*
            > Rand for ( $( $tyvar ),* , ) {

            #[inline]
            fn rand<R: Rng>(_rng: &mut R) -> ( $( $tyvar ),* , ) {
                (
                    // use the $tyvar's to get the appropriate number of
                    // repeats (they're not actually needed)
                    $(
                        _rng.gen::<$tyvar>()
                    ),*
                    ,
                )
            }
        }
    }
}

impl Rand for () {
    #[inline]
    fn rand<R: Rng>(_: &mut R) -> () { () }
}
tuple_impl!{A}
tuple_impl!{A, B}
tuple_impl!{A, B, C}
tuple_impl!{A, B, C, D}
tuple_impl!{A, B, C, D, E}
tuple_impl!{A, B, C, D, E, F}
tuple_impl!{A, B, C, D, E, F, G}
tuple_impl!{A, B, C, D, E, F, G, H}
tuple_impl!{A, B, C, D, E, F, G, H, I}
tuple_impl!{A, B, C, D, E, F, G, H, I, J}
tuple_impl!{A, B, C, D, E, F, G, H, I, J, K}
tuple_impl!{A, B, C, D, E, F, G, H, I, J, K, L}

macro_rules! array_impl {
    {$n:expr, $t:ident, $($ts:ident,)*} => {
        array_impl!{($n - 1), $($ts,)*}

        impl<T> Rand for [T; $n] where T: Rand {
            #[inline]
            fn rand<R: Rng>(_rng: &mut R) -> [T; $n] {
                [_rng.gen::<$t>(), $(_rng.gen::<$ts>()),*]
            }
        }
    };
    {$n:expr,} => {
        impl<T> Rand for [T; $n] {
            fn rand<R: Rng>(_rng: &mut R) -> [T; $n] { [] }
        }
    };
}

array_impl!{32, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,}

impl<T:Rand> Rand for Option<T> {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> Option<T> {
        if rng.gen() {
            Some(rng.gen())
        } else {
            None
        }
    }
}

impl<T: SeedableRng> Rand for T {
    fn rand<R: Rng>(rng: &mut R) -> Self {
        Self::from_rng(rng).unwrap()
    }
}

#[cfg(test)]
mod tests {
    use impls;
    use {Rng, Open01, Closed01};

    const EPSILON32: f32 = ::core::f32::EPSILON;
    const EPSILON64: f64 = ::core::f64::EPSILON;

    struct ConstantRng(u64);
    impl Rng for ConstantRng {
        fn next_u32(&mut self) -> u32 {
            let ConstantRng(v) = *self;
            v as u32
        }
        fn next_u64(&mut self) -> u64 {
            let ConstantRng(v) = *self;
            v
        }

        fn fill_bytes(&mut self, dest: &mut [u8]) {
            impls::fill_bytes_via_u64(self, dest)
        }
    }

    #[test]
    fn floating_point_edge_cases() {
        let mut zeros = ConstantRng(0);
        assert_eq!(zeros.gen::<f32>(), 0.0);
        assert_eq!(zeros.gen::<f64>(), 0.0);

        let mut one = ConstantRng(1);
        assert_eq!(one.gen::<f32>(), EPSILON32);
        assert_eq!(one.gen::<f64>(), EPSILON64);

        let mut max = ConstantRng(!0);
        assert_eq!(max.gen::<f32>(), 1.0 - EPSILON32);
        assert_eq!(max.gen::<f64>(), 1.0 - EPSILON64);
    }

    #[test]
    fn fp_closed_edge_cases() {
        let mut zeros = ConstantRng(0);
        let Closed01(zero32) = zeros.gen::<Closed01<f32>>();
        let Closed01(zero64) = zeros.gen::<Closed01<f64>>();
        assert_eq!(zero32, 0.0);
        assert_eq!(zero64, 0.0);

        let mut one = ConstantRng(1);
        let Closed01(one32) = one.gen::<Closed01<f32>>();
        let Closed01(one64) = one.gen::<Closed01<f64>>();
        assert!(EPSILON32 < one32 && one32 < EPSILON32 * 1.01);
        assert!(EPSILON64 < one64 && one64 < EPSILON64 * 1.01);

        let mut max = ConstantRng(!0);
        let Closed01(max32) = max.gen::<Closed01<f32>>();
        let Closed01(max64) = max.gen::<Closed01<f64>>();
        assert_eq!(max32, 1.0 - EPSILON32 / 2.0);  // FIXME
        assert_eq!(max64, 1.0 - EPSILON64 / 2.0);  // FIXME
    }

    #[test]
    fn fp_open_edge_cases() {
        let mut zeros = ConstantRng(0);
        let Open01(zero32) = zeros.gen::<Open01<f32>>();
        let Open01(zero64) = zeros.gen::<Open01<f64>>();
        assert_eq!(zero32, 0.0 + EPSILON32 / 8.0);
        assert_eq!(zero64, 0.0 + EPSILON64 / 8.0);

        let mut one = ConstantRng(1);
        let Open01(one32) = one.gen::<Open01<f32>>();
        let Open01(one64) = one.gen::<Open01<f64>>();
        assert!(EPSILON32 < one32 && one32 < EPSILON32 * 1.2);
        assert!(EPSILON64 < one64 && one64 < EPSILON64 * 1.2);

        let mut max = ConstantRng(!0);
        let Open01(max32) = max.gen::<Open01<f32>>();
        let Open01(max64) = max.gen::<Open01<f64>>();
        assert_eq!(max32, 1.0 - EPSILON32);
        assert_eq!(max64, 1.0 - EPSILON64);
    }

    #[test]
    fn rand_open() {
        // this is unlikely to catch an incorrect implementation that
        // generates exactly 0 or 1, but it keeps it sane.
        let mut rng = ::test::rng(501);
        for _ in 0..1_000 {
            // strict inequalities
            let Open01(f) = rng.gen::<Open01<f64>>();
            assert!(0.0 < f && f < 1.0);

            let Open01(f) = rng.gen::<Open01<f32>>();
            assert!(0.0 < f && f < 1.0);
        }
    }

    #[test]
    fn rand_closed() {
        let mut rng = ::test::rng(502);
        for _ in 0..1_000 {
            // strict inequalities
            let Closed01(f) = rng.gen::<Closed01<f64>>();
            assert!(0.0 <= f && f <= 1.0);

            let Closed01(f) = rng.gen::<Closed01<f32>>();
            assert!(0.0 <= f && f <= 1.0);
        }
    }
}
<|endoftext|>


<commit_before>mod prelude {
    pub use conduit::{Handler, Request, Response};
    pub use conduit_middleware::{AroundMiddleware, Middleware};
    pub use std::error::Error;
}

pub use self::app::AppMiddleware;
pub use self::current_user::CurrentUser;
pub use self::debug::*;
pub use self::ember_index_rewrite::EmberIndexRewrite;
pub use self::head::Head;
pub use self::security_headers::SecurityHeaders;
pub use self::static_or_continue::StaticOrContinue;

pub mod app;
mod block_ips;
pub mod current_user;
mod debug;
mod ember_index_rewrite;
mod ensure_well_formed_500;
mod head;
mod log_request;
mod require_user_agent;
mod security_headers;
mod static_or_continue;

use conduit_conditional_get::ConditionalGet;
use conduit_cookie::{Middleware as Cookie, SessionMiddleware};
use conduit_middleware::MiddlewareBuilder;

use cookie;
use std::env;
use std::sync::Arc;

use router::R404;
use {App, Env};

pub fn build_middleware(app: Arc<App>, endpoints: R404) -> MiddlewareBuilder {
    let mut m = MiddlewareBuilder::new(endpoints);
    let env = app.config.env;

    if env != Env::Test {
        m.add(ensure_well_formed_500::EnsureWellFormed500);
    }

    if env == Env::Development {
        // Print a log for each request.
        m.add(Debug);
        // Locally serve crates and readmes
        m.around(StaticOrContinue::new("local_uploads"));
    }

    if env::var_os("DEBUG_REQUESTS").is_some() {
        m.add(DebugRequest);
    }

    m.add(ConditionalGet);

    m.add(Cookie::new());
    m.add(SessionMiddleware::new(
        "cargo_session",
        cookie::Key::from_master(app.session_key.as_bytes()),
        env == Env::Production,
    ));

    if env == Env::Production {
        m.add(SecurityHeaders::new(&app.config.uploader));
    }
    m.add(AppMiddleware::new(app));

    // Sets the current user on each request.
    m.add(CurrentUser);

    // Serve the static files in the *dist* directory, which are the frontend assets.
    // Not needed for the backend tests.
    if env != Env::Test {
        m.around(StaticOrContinue::new("dist"));
        m.around(EmberIndexRewrite::default());
        m.around(StaticOrContinue::new("dist"));
        // Note: around middleware is run from bottom to top, so the rewrite occurs first
    }

    m.around(Head::default());

    if let Ok(ip_list) = env::var("BLOCKED_IPS") {
        let ips = ip_list.split(',').map(String::from).collect();
        m.around(block_ips::BlockIps::new(ips));
    }
    m.around(require_user_agent::RequireUserAgent::default());

    if env != Env::Test {
        m.around(log_request::LogRequests::default());
    }

    m
}
<commit_msg>Temporarily disable the requirement of a User-Agent header<commit_after>mod prelude {
    pub use conduit::{Handler, Request, Response};
    pub use conduit_middleware::{AroundMiddleware, Middleware};
    pub use std::error::Error;
}

pub use self::app::AppMiddleware;
pub use self::current_user::CurrentUser;
pub use self::debug::*;
pub use self::ember_index_rewrite::EmberIndexRewrite;
pub use self::head::Head;
pub use self::security_headers::SecurityHeaders;
pub use self::static_or_continue::StaticOrContinue;

pub mod app;
mod block_ips;
pub mod current_user;
mod debug;
mod ember_index_rewrite;
mod ensure_well_formed_500;
mod head;
mod log_request;
mod require_user_agent;
mod security_headers;
mod static_or_continue;

use conduit_conditional_get::ConditionalGet;
use conduit_cookie::{Middleware as Cookie, SessionMiddleware};
use conduit_middleware::MiddlewareBuilder;

use cookie;
use std::env;
use std::sync::Arc;

use router::R404;
use {App, Env};

pub fn build_middleware(app: Arc<App>, endpoints: R404) -> MiddlewareBuilder {
    let mut m = MiddlewareBuilder::new(endpoints);
    let env = app.config.env;

    if env != Env::Test {
        m.add(ensure_well_formed_500::EnsureWellFormed500);
    }

    if env == Env::Development {
        // Print a log for each request.
        m.add(Debug);
        // Locally serve crates and readmes
        m.around(StaticOrContinue::new("local_uploads"));
    }

    if env::var_os("DEBUG_REQUESTS").is_some() {
        m.add(DebugRequest);
    }

    m.add(ConditionalGet);

    m.add(Cookie::new());
    m.add(SessionMiddleware::new(
        "cargo_session",
        cookie::Key::from_master(app.session_key.as_bytes()),
        env == Env::Production,
    ));

    if env == Env::Production {
        m.add(SecurityHeaders::new(&app.config.uploader));
    }
    m.add(AppMiddleware::new(app));

    // Sets the current user on each request.
    m.add(CurrentUser);

    // Serve the static files in the *dist* directory, which are the frontend assets.
    // Not needed for the backend tests.
    if env != Env::Test {
        m.around(StaticOrContinue::new("dist"));
        m.around(EmberIndexRewrite::default());
        m.around(StaticOrContinue::new("dist"));
        // Note: around middleware is run from bottom to top, so the rewrite occurs first
    }

    m.around(Head::default());

    if let Ok(ip_list) = env::var("BLOCKED_IPS") {
        let ips = ip_list.split(',').map(String::from).collect();
        m.around(block_ips::BlockIps::new(ips));
    }
    // Note: Temporarily disabled because cargo-vendor doesn't include a
    // User-Agent header and Rust's CI broke. If this is still commented out
    // by Nov 7, 2018 we need to ping some folks
    // m.around(require_user_agent::RequireUserAgent::default());

    if env != Env::Test {
        m.around(log_request::LogRequests::default());
    }

    m
}
<|endoftext|>