<commit_before>use super::{AnimeEntry, AnimeInfo, Status, SyncBackend};
use chrono::{Datelike, NaiveDate, TimeZone, Utc};
use config::Config;
use error::BackendError;
use input;
use reqwest::header::{Accept, Authorization, Bearer, ContentType, Headers};
use reqwest::{Client, Response};
use serde_json;
use std::io;
use std::process::{Command, ExitStatus};

const LOGIN_URL: &str =
    "https://anilist.co/api/v2/oauth/authorize?client_id=427&response_type=token";

const API_URL: &str = "https://graphql.anilist.co";

macro_rules! send_query {
    ($backend:expr, $query_str:expr, {$($vars:tt)*}, $($response_root:expr)=>*) => {{
        let vars = json!({
            $($vars)*
        });

        let text = $backend.send_request($query_str, &vars)?.text()?;
        let json: serde_json::Value = serde_json::from_str(&text)?;

        json$([$response_root])*.clone()
    }};
}

pub struct Anilist {
    client: Client,
    user_id: u32,
    access_token: String,
}

impl Anilist {
    fn send_request(
        &self,
        query_str: &str,
        variables: &serde_json::Value,
    ) -> Result<Response, BackendError> {
        let body = json!({
            "query": query_str,
            "variables": variables,
        }).to_string();

        let mut headers = Headers::new();
        headers.set(ContentType::json());
        headers.set(Accept::json());
        headers.set(Authorization(Bearer {
            token: self.access_token.to_owned(),
        }));

        let response = self
            .client
            .post(API_URL)
            .headers(headers)
            .body(body)
            .send()?;
        Ok(response)
    }

    fn request_user_id(&self) -> Result<u32, BackendError> {
        let resp = send_query!(self,
            r#"
                query {
                    Viewer {
                        id
                    }
                }
            "#,
            {},
            "data" => "Viewer" => "id"
        );

        let id = serde_json::from_value(resp)?;
        Ok(id)
    }
}

impl SyncBackend for Anilist {
    fn init(config: &mut Config) -> Result<Anilist, BackendError> {
        let access_token = match config.user.access_token {
            Some(_) => config.user.decode_access_token()?,
            None => {
                // TODO: add better error reporting
                open_url(LOGIN_URL)?;

                println!("please authorize your account in the opened browser tab and paste the code below:");
                let token = input::read_line()?;
                config.user.encode_access_token(&token);

                token
            }
        };

        let mut instance = Anilist {
            client: Client::new(),
            user_id: 0,
            access_token,
        };

        instance.user_id = instance.request_user_id()?;

        Ok(instance)
    }

    fn search_by_name(&self, name: &str) -> Result<Vec<AnimeInfo>, BackendError> {
        let resp = send_query!(self,
            r#"
                query ($name: String) {
                    Page (page: 1, perPage: 30) {
                        media (search: $name, type: ANIME) {
                            id
                            title {
                                romaji
                            }
                            episodes
                        }
                    }
                }
            "#,
            { "name": name },
            "data" => "Page" => "media"
        );

        use serde_json::Value;
        let mut series = Vec::new();

        match resp {
            Value::Array(ref entries) => {
                for entry in entries {
                    let series_info: MediaData = serde_json::from_value(entry.clone())?;
                    series.push(series_info.into());
                }
            }
            _ => return Err(BackendError::InvalidJsonResponse),
        }

        Ok(series)
    }

    fn get_series_info_by_id(&self, id: u32) -> Result<AnimeInfo, BackendError> {
        let resp = send_query!(self,
            r#"
                query ($id: Int) {
                    Media (id: $id) {
                        id
                        title {
                            romaji
                        }
                        episodes
                    }
                }
            "#,
            { "id": id },
            "data" => "Media"
        );

        let info: MediaData = serde_json::from_value(resp)?;
        Ok(info.into())
    }

    fn get_list_entry(&self, info: AnimeInfo) -> Result<Option<AnimeEntry>, BackendError> {
        let resp = send_query!(self,
            r#"
                query ($id: Int, $userID: Int) {
                    MediaList(mediaId: $id, userId: $userID) {
                        progress
                        status
                        score
                        startedAt {
                            year
                            month
                            day
                        }
                        completedAt {
                            year
                            month
                            day
                        }
                    }
                }
            "#,
            { "id": info.id, "userID": self.user_id },
            "data" => "MediaList"
        );

        match resp {
            serde_json::Value::Null => Ok(None),
            _ => {
                let media_entry: MediaListEntry = serde_json::from_value(resp)?;
                Ok(Some(media_entry.into_generic_entry(info)))
            }
        }
    }

    fn update_list_entry(&self, entry: &AnimeEntry) -> Result<(), BackendError> {
        let resp = send_query!(self,
            r#"
                mutation ($mediaId: Int, $watched_eps: Int, $score: Float, $status: MediaListStatus, $start_date: FuzzyDateInput, $finish_date: FuzzyDateInput) {
                    SaveMediaListEntry (mediaId: $mediaId, progress: $watched_eps, score: $score, status: $status, startedAt: $start_date, completedAt: $finish_date) {
                        mediaId
                    }
                }
            "#,
            {
                "mediaId": entry.info.id,
                "watched_eps": entry.watched_episodes,
                "score": entry.score,
                "status": MediaStatus::from(entry.status.clone()),
                "start_date": MediaDate::from_date(entry.start_date),
                "finish_date": MediaDate::from_date(entry.finish_date),
            },
        );

        if !resp["errors"].is_null() {
            let msg = resp["errors"][0]["message"].to_string();
            return Err(BackendError::ListUpdate(msg));
        }

        Ok(())
    }
}

fn open_url(url: &str) -> io::Result<ExitStatus> {
    #[cfg(target_os = "windows")]
    const LAUNCH_PROGRAM: &str = "start";
    #[cfg(target_os = "macos")]
    const LAUNCH_PROGRAM: &str = "open";
    #[cfg(target_os = "linux")]
    const LAUNCH_PROGRAM: &str = "xdg-open";

    #[cfg(not(any(target_os = "windows", target_os = "macos", target_os = "linux")))]
    compile_error!("support for opening URL's not implemented for this platform");

    Command::new(LAUNCH_PROGRAM).arg(url).status()
}

#[derive(Deserialize)]
struct MediaData {
    id: u32,
    title: Title,
    episodes: u32,
}

#[derive(Deserialize)]
struct Title {
    romaji: String,
}

impl Into<AnimeInfo> for MediaData {
    fn into(self) -> AnimeInfo {
        AnimeInfo {
            id: self.id,
            title: self.title.romaji,
            episodes: self.episodes,
        }
    }
}

#[derive(Deserialize)]
struct MediaListEntry {
    progress: u32,
    status: MediaStatus,
    score: f32,
    #[serde(rename = "startedAt")]
    start_date: MediaDate,
    #[serde(rename = "completedAt")]
    finish_date: MediaDate,
}

impl MediaListEntry {
    fn into_generic_entry(self, info: AnimeInfo) -> AnimeEntry {
        AnimeEntry {
            info,
            watched_episodes: self.progress,
            score: self.score,
            status: self.status.into(),
            start_date: self.start_date.into_date(),
            finish_date: self.finish_date.into_date(),
        }
    }
}

#[derive(Serialize, Deserialize, Copy, Clone, PartialEq)]
enum MediaStatus {
    #[serde(rename = "CURRENT")]
    Current,
    #[serde(rename = "COMPLETED")]
    Completed,
    #[serde(rename = "PAUSED")]
    Paused,
    #[serde(rename = "DROPPED")]
    Dropped,
    #[serde(rename = "PLANNING")]
    Planning,
    #[serde(rename = "REPEATING")]
    Repeating,
}

impl Into<Status> for MediaStatus {
    fn into(self) -> Status {
        match self {
            MediaStatus::Current => Status::Watching,
            MediaStatus::Completed => Status::Completed,
            MediaStatus::Paused => Status::OnHold,
            MediaStatus::Dropped => Status::Dropped,
            MediaStatus::Planning => Status::PlanToWatch,
            MediaStatus::Repeating => Status::Rewatching,
        }
    }
}

impl From<Status> for MediaStatus {
    fn from(status: Status) -> MediaStatus {
        match status {
            Status::Watching => MediaStatus::Current,
            Status::Completed => MediaStatus::Completed,
            Status::OnHold => MediaStatus::Paused,
            Status::Dropped => MediaStatus::Dropped,
            Status::PlanToWatch => MediaStatus::Planning,
            Status::Rewatching => MediaStatus::Repeating,
        }
    }
}

#[derive(Serialize, Deserialize)]
struct MediaDate {
    year: Option<i32>,
    month: Option<u32>,
    day: Option<u32>,
}

impl MediaDate {
    fn into_date(self) -> Option<NaiveDate> {
        match (self.year, self.month, self.day) {
            (Some(year), Some(month), Some(day)) => Some(Utc.ymd(year, month, day).naive_utc()),
            _ => None,
        }
    }

    fn from_date(date: Option<NaiveDate>) -> MediaDate {
        match date {
            Some(date) => MediaDate {
                year: Some(date.year()),
                month: Some(date.month()),
                day: Some(date.day()),
            },
            None => MediaDate {
                year: None,
                month: None,
                day: None,
            },
        }
    }
}

impl From<NaiveDate> for MediaDate {
    fn from(date: NaiveDate) -> MediaDate {
        MediaDate {
            year: Some(date.year()),
            month: Some(date.month()),
            day: Some(date.day()),
        }
    }
}
<commit_msg>Let the user to open the login URL manually if automatic opening fails<commit_after>use super::{AnimeEntry, AnimeInfo, Status, SyncBackend};
use chrono::{Datelike, NaiveDate, TimeZone, Utc};
use config::Config;
use error::BackendError;
use input;
use reqwest::header::{Accept, Authorization, Bearer, ContentType, Headers};
use reqwest::{Client, Response};
use serde_json;
use std::io;
use std::process::{Command, ExitStatus};

const LOGIN_URL: &str =
    "https://anilist.co/api/v2/oauth/authorize?client_id=427&response_type=token";

const API_URL: &str = "https://graphql.anilist.co";

macro_rules! send_query {
    ($backend:expr, $query_str:expr, {$($vars:tt)*}, $($response_root:expr)=>*) => {{
        let vars = json!({
            $($vars)*
        });

        let text = $backend.send_request($query_str, &vars)?.text()?;
        let json: serde_json::Value = serde_json::from_str(&text)?;

        json$([$response_root])*.clone()
    }};
}

pub struct Anilist {
    client: Client,
    user_id: u32,
    access_token: String,
}

impl Anilist {
    fn send_request(
        &self,
        query_str: &str,
        variables: &serde_json::Value,
    ) -> Result<Response, BackendError> {
        let body = json!({
            "query": query_str,
            "variables": variables,
        }).to_string();

        let mut headers = Headers::new();
        headers.set(ContentType::json());
        headers.set(Accept::json());
        headers.set(Authorization(Bearer {
            token: self.access_token.to_owned(),
        }));

        let response = self
            .client
            .post(API_URL)
            .headers(headers)
            .body(body)
            .send()?;
        Ok(response)
    }

    fn request_user_id(&self) -> Result<u32, BackendError> {
        let resp = send_query!(self,
            r#"
                query {
                    Viewer {
                        id
                    }
                }
            "#,
            {},
            "data" => "Viewer" => "id"
        );

        let id = serde_json::from_value(resp)?;
        Ok(id)
    }
}

impl SyncBackend for Anilist {
    fn init(config: &mut Config) -> Result<Anilist, BackendError> {
        let access_token = match config.user.access_token {
            Some(_) => config.user.decode_access_token()?,
            None => {
                match open_url(LOGIN_URL) {
                    Ok(status) if status.success() => (),
                    result => {
                        eprintln!("failed to open URL in default browser. please open it manually: {}", LOGIN_URL);

                        if let Err(err) = result {
                            eprintln!("error message: {}", err);
                        }
                    }
                }

                println!("please authorize your account in the opened browser tab and paste the code below:");
                let token = input::read_line()?;
                config.user.encode_access_token(&token);

                token
            }
        };

        let mut instance = Anilist {
            client: Client::new(),
            user_id: 0,
            access_token,
        };

        instance.user_id = instance.request_user_id()?;

        Ok(instance)
    }

    fn search_by_name(&self, name: &str) -> Result<Vec<AnimeInfo>, BackendError> {
        let resp = send_query!(self,
            r#"
                query ($name: String) {
                    Page (page: 1, perPage: 30) {
                        media (search: $name, type: ANIME) {
                            id
                            title {
                                romaji
                            }
                            episodes
                        }
                    }
                }
            "#,
            { "name": name },
            "data" => "Page" => "media"
        );

        use serde_json::Value;
        let mut series = Vec::new();

        match resp {
            Value::Array(ref entries) => {
                for entry in entries {
                    let series_info: MediaData = serde_json::from_value(entry.clone())?;
                    series.push(series_info.into());
                }
            }
            _ => return Err(BackendError::InvalidJsonResponse),
        }

        Ok(series)
    }

    fn get_series_info_by_id(&self, id: u32) -> Result<AnimeInfo, BackendError> {
        let resp = send_query!(self,
            r#"
                query ($id: Int) {
                    Media (id: $id) {
                        id
                        title {
                            romaji
                        }
                        episodes
                    }
                }
            "#,
            { "id": id },
            "data" => "Media"
        );

        let info: MediaData = serde_json::from_value(resp)?;
        Ok(info.into())
    }

    fn get_list_entry(&self, info: AnimeInfo) -> Result<Option<AnimeEntry>, BackendError> {
        let resp = send_query!(self,
            r#"
                query ($id: Int, $userID: Int) {
                    MediaList(mediaId: $id, userId: $userID) {
                        progress
                        status
                        score
                        startedAt {
                            year
                            month
                            day
                        }
                        completedAt {
                            year
                            month
                            day
                        }
                    }
                }
            "#,
            { "id": info.id, "userID": self.user_id },
            "data" => "MediaList"
        );

        match resp {
            serde_json::Value::Null => Ok(None),
            _ => {
                let media_entry: MediaListEntry = serde_json::from_value(resp)?;
                Ok(Some(media_entry.into_generic_entry(info)))
            }
        }
    }

    fn update_list_entry(&self, entry: &AnimeEntry) -> Result<(), BackendError> {
        let resp = send_query!(self,
            r#"
                mutation ($mediaId: Int, $watched_eps: Int, $score: Float, $status: MediaListStatus, $start_date: FuzzyDateInput, $finish_date: FuzzyDateInput) {
                    SaveMediaListEntry (mediaId: $mediaId, progress: $watched_eps, score: $score, status: $status, startedAt: $start_date, completedAt: $finish_date) {
                        mediaId
                    }
                }
            "#,
            {
                "mediaId": entry.info.id,
                "watched_eps": entry.watched_episodes,
                "score": entry.score,
                "status": MediaStatus::from(entry.status.clone()),
                "start_date": MediaDate::from_date(entry.start_date),
                "finish_date": MediaDate::from_date(entry.finish_date),
            },
        );

        if !resp["errors"].is_null() {
            let msg = resp["errors"][0]["message"].to_string();
            return Err(BackendError::ListUpdate(msg));
        }

        Ok(())
    }
}

fn open_url(url: &str) -> io::Result<ExitStatus> {
    #[cfg(target_os = "windows")]
    const LAUNCH_PROGRAM: &str = "start";
    #[cfg(target_os = "macos")]
    const LAUNCH_PROGRAM: &str = "open";
    #[cfg(target_os = "linux")]
    const LAUNCH_PROGRAM: &str = "xdg-open";

    #[cfg(not(any(target_os = "windows", target_os = "macos", target_os = "linux")))]
    compile_error!("support for opening URL's not implemented for this platform");

    Command::new(LAUNCH_PROGRAM).arg(url).status()
}

#[derive(Deserialize)]
struct MediaData {
    id: u32,
    title: Title,
    episodes: u32,
}

#[derive(Deserialize)]
struct Title {
    romaji: String,
}

impl Into<AnimeInfo> for MediaData {
    fn into(self) -> AnimeInfo {
        AnimeInfo {
            id: self.id,
            title: self.title.romaji,
            episodes: self.episodes,
        }
    }
}

#[derive(Deserialize)]
struct MediaListEntry {
    progress: u32,
    status: MediaStatus,
    score: f32,
    #[serde(rename = "startedAt")]
    start_date: MediaDate,
    #[serde(rename = "completedAt")]
    finish_date: MediaDate,
}

impl MediaListEntry {
    fn into_generic_entry(self, info: AnimeInfo) -> AnimeEntry {
        AnimeEntry {
            info,
            watched_episodes: self.progress,
            score: self.score,
            status: self.status.into(),
            start_date: self.start_date.into_date(),
            finish_date: self.finish_date.into_date(),
        }
    }
}

#[derive(Serialize, Deserialize, Copy, Clone, PartialEq)]
enum MediaStatus {
    #[serde(rename = "CURRENT")]
    Current,
    #[serde(rename = "COMPLETED")]
    Completed,
    #[serde(rename = "PAUSED")]
    Paused,
    #[serde(rename = "DROPPED")]
    Dropped,
    #[serde(rename = "PLANNING")]
    Planning,
    #[serde(rename = "REPEATING")]
    Repeating,
}

impl Into<Status> for MediaStatus {
    fn into(self) -> Status {
        match self {
            MediaStatus::Current => Status::Watching,
            MediaStatus::Completed => Status::Completed,
            MediaStatus::Paused => Status::OnHold,
            MediaStatus::Dropped => Status::Dropped,
            MediaStatus::Planning => Status::PlanToWatch,
            MediaStatus::Repeating => Status::Rewatching,
        }
    }
}

impl From<Status> for MediaStatus {
    fn from(status: Status) -> MediaStatus {
        match status {
            Status::Watching => MediaStatus::Current,
            Status::Completed => MediaStatus::Completed,
            Status::OnHold => MediaStatus::Paused,
            Status::Dropped => MediaStatus::Dropped,
            Status::PlanToWatch => MediaStatus::Planning,
            Status::Rewatching => MediaStatus::Repeating,
        }
    }
}

#[derive(Serialize, Deserialize)]
struct MediaDate {
    year: Option<i32>,
    month: Option<u32>,
    day: Option<u32>,
}

impl MediaDate {
    fn into_date(self) -> Option<NaiveDate> {
        match (self.year, self.month, self.day) {
            (Some(year), Some(month), Some(day)) => Some(Utc.ymd(year, month, day).naive_utc()),
            _ => None,
        }
    }

    fn from_date(date: Option<NaiveDate>) -> MediaDate {
        match date {
            Some(date) => MediaDate {
                year: Some(date.year()),
                month: Some(date.month()),
                day: Some(date.day()),
            },
            None => MediaDate {
                year: None,
                month: None,
                day: None,
            },
        }
    }
}

impl From<NaiveDate> for MediaDate {
    fn from(date: NaiveDate) -> MediaDate {
        MediaDate {
            year: Some(date.year()),
            month: Some(date.month()),
            day: Some(date.day()),
        }
    }
}
<|endoftext|>


<commit_before>use log::debug;
use std::io;
use std::io::Write;

use super::Backend;
use crate::buffer::Cell;
use crate::layout::Rect;
use crate::style::{Color, Modifier, Style};

pub struct TermionBackend<W>
where
    W: Write,
{
    stdout: W,
}

impl<W> TermionBackend<W>
where
    W: Write,
{
    pub fn new(stdout: W) -> TermionBackend<W> {
        TermionBackend { stdout }
    }
}

impl<W> Write for TermionBackend<W>
where
    W: Write,
{
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        self.stdout.write(buf)
    }

    fn flush(&mut self) -> io::Result<()> {
        self.stdout.flush()
    }
}

impl<W> Backend for TermionBackend<W>
where
    W: Write,
{
    /// Clears the entire screen and move the cursor to the top left of the screen
    fn clear(&mut self) -> io::Result<()> {
        write!(self.stdout, "{}", termion::clear::All)?;
        write!(self.stdout, "{}", termion::cursor::Goto(1, 1))?;
        self.stdout.flush()
    }

    /// Hides cursor
    fn hide_cursor(&mut self) -> io::Result<()> {
        write!(self.stdout, "{}", termion::cursor::Hide)?;
        self.stdout.flush()
    }

    /// Shows cursor
    fn show_cursor(&mut self) -> io::Result<()> {
        write!(self.stdout, "{}", termion::cursor::Show)?;
        self.stdout.flush()
    }

    /// Gets cursor position (0-based index)
    fn get_cursor(&mut self) -> io::Result<(u16, u16)> {
        termion::cursor::DetectCursorPos::cursor_pos(&mut self.stdout).map(|(x, y)| (x - 1, y - 1))
    }

    /// Sets cursor position (0-based index)
    fn set_cursor(&mut self, x: u16, y: u16) -> io::Result<()> {
        write!(self.stdout, "{}", termion::cursor::Goto(x + 1, y + 1))
    }

    fn draw<'a, I>(&mut self, content: I) -> io::Result<()>
    where
        I: Iterator<Item = (u16, u16, &'a Cell)>,
    {
        let mut string = String::with_capacity(content.size_hint().0 * 3);
        let mut style = Style::default();
        let mut last_y = 0;
        let mut last_x = 0;
        let mut inst = 0;
        for (x, y, cell) in content {
            if y != last_y || x != last_x + 1 || inst == 0 {
                string.push_str(&format!("{}", termion::cursor::Goto(x + 1, y + 1)));
                inst += 1;
            }
            last_x = x;
            last_y = y;
            if cell.style.modifier != style.modifier {
                string.push_str(&cell.style.modifier.termion_modifier());
                style.modifier = cell.style.modifier;
                if style.modifier == Modifier::Reset {
                    style.bg = Color::Reset;
                    style.fg = Color::Reset;
                }
                inst += 1;
            }
            if cell.style.fg != style.fg {
                string.push_str(&cell.style.fg.termion_fg());
                style.fg = cell.style.fg;
                inst += 1;
            }
            if cell.style.bg != style.bg {
                string.push_str(&cell.style.bg.termion_bg());
                style.bg = cell.style.bg;
                inst += 1;
            }
            string.push_str(&cell.symbol);
            inst += 1;
        }
        debug!("{} instructions outputed.", inst);
        write!(
            self.stdout,
            "{}{}{}{}",
            string,
            Color::Reset.termion_fg(),
            Color::Reset.termion_bg(),
            Modifier::Reset.termion_modifier()
        )
    }

    /// Return the size of the terminal
    fn size(&self) -> io::Result<Rect> {
        let terminal = r#try!(termion::terminal_size());
        Ok(Rect::new(0, 0, terminal.0, terminal.1))
    }

    fn flush(&mut self) -> io::Result<()> {
        self.stdout.flush()
    }
}

macro_rules! termion_fg {
    ($color:ident) => {
        format!("{}", termion::color::Fg(termion::color::$color))
    };
}

macro_rules! termion_fg_rgb {
    ($r:expr, $g:expr, $b:expr) => {
        format!("{}", termion::color::Fg(termion::color::Rgb($r, $g, $b)))
    };
}

macro_rules! termion_bg {
    ($color:ident) => {
        format!("{}", termion::color::Bg(termion::color::$color))
    };
}

macro_rules! termion_bg_rgb {
    ($r:expr, $g:expr, $b:expr) => {
        format!("{}", termion::color::Bg(termion::color::Rgb($r, $g, $b)))
    };
}

macro_rules! termion_modifier {
    ($style:ident) => {
        format!("{}", termion::style::$style)
    };
}

impl Color {
    pub fn termion_fg(self) -> String {
        match self {
            Color::Reset => termion_fg!(Reset),
            Color::Black => termion_fg!(Black),
            Color::Red => termion_fg!(Red),
            Color::Green => termion_fg!(Green),
            Color::Yellow => termion_fg!(Yellow),
            Color::Blue => termion_fg!(Blue),
            Color::Magenta => termion_fg!(Magenta),
            Color::Cyan => termion_fg!(Cyan),
            Color::Gray => termion_fg!(White),
            Color::DarkGray => termion_fg!(LightBlack),
            Color::LightRed => termion_fg!(LightRed),
            Color::LightGreen => termion_fg!(LightGreen),
            Color::LightBlue => termion_fg!(LightBlue),
            Color::LightYellow => termion_fg!(LightYellow),
            Color::LightMagenta => termion_fg!(LightMagenta),
            Color::LightCyan => termion_fg!(LightCyan),
            Color::White => termion_fg!(LightWhite),
            Color::Rgb(r, g, b) => termion_fg_rgb!(r, g, b),
        }
    }
    pub fn termion_bg(self) -> String {
        match self {
            Color::Reset => termion_bg!(Reset),
            Color::Black => termion_bg!(Black),
            Color::Red => termion_bg!(Red),
            Color::Green => termion_bg!(Green),
            Color::Yellow => termion_bg!(Yellow),
            Color::Blue => termion_bg!(Blue),
            Color::Magenta => termion_bg!(Magenta),
            Color::Cyan => termion_bg!(Cyan),
            Color::Gray => termion_bg!(White),
            Color::DarkGray => termion_bg!(LightBlack),
            Color::LightRed => termion_bg!(LightRed),
            Color::LightGreen => termion_bg!(LightGreen),
            Color::LightBlue => termion_bg!(LightBlue),
            Color::LightYellow => termion_bg!(LightYellow),
            Color::LightMagenta => termion_bg!(LightMagenta),
            Color::LightCyan => termion_bg!(LightCyan),
            Color::White => termion_bg!(LightWhite),
            Color::Rgb(r, g, b) => termion_bg_rgb!(r, g, b),
        }
    }
}

impl Modifier {
    pub fn termion_modifier(self) -> String {
        match self {
            Modifier::Blink => termion_modifier!(Blink),
            Modifier::Bold => termion_modifier!(Bold),
            Modifier::CrossedOut => termion_modifier!(CrossedOut),
            Modifier::Faint => termion_modifier!(Faint),
            Modifier::Framed => termion_modifier!(Framed),
            Modifier::Invert => termion_modifier!(Invert),
            Modifier::Italic => termion_modifier!(Italic),
            Modifier::NoBlink => termion_modifier!(NoBlink),
            Modifier::NoBold => termion_modifier!(NoBold),
            Modifier::NoCrossedOut => termion_modifier!(NoCrossedOut),
            Modifier::NoFaint => termion_modifier!(NoFaint),
            Modifier::NoInvert => termion_modifier!(NoInvert),
            Modifier::NoItalic => termion_modifier!(NoItalic),
            Modifier::NoUnderline => termion_modifier!(NoUnderline),
            Modifier::Reset => termion_modifier!(Reset),
            Modifier::Underline => termion_modifier!(Underline),
        }
    }
}
<commit_msg>forgot to flush<commit_after>use log::debug;
use std::io;
use std::io::Write;

use super::Backend;
use crate::buffer::Cell;
use crate::layout::Rect;
use crate::style::{Color, Modifier, Style};

pub struct TermionBackend<W>
where
    W: Write,
{
    stdout: W,
}

impl<W> TermionBackend<W>
where
    W: Write,
{
    pub fn new(stdout: W) -> TermionBackend<W> {
        TermionBackend { stdout }
    }
}

impl<W> Write for TermionBackend<W>
where
    W: Write,
{
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        self.stdout.write(buf)
    }

    fn flush(&mut self) -> io::Result<()> {
        self.stdout.flush()
    }
}

impl<W> Backend for TermionBackend<W>
where
    W: Write,
{
    /// Clears the entire screen and move the cursor to the top left of the screen
    fn clear(&mut self) -> io::Result<()> {
        write!(self.stdout, "{}", termion::clear::All)?;
        write!(self.stdout, "{}", termion::cursor::Goto(1, 1))?;
        self.stdout.flush()
    }

    /// Hides cursor
    fn hide_cursor(&mut self) -> io::Result<()> {
        write!(self.stdout, "{}", termion::cursor::Hide)?;
        self.stdout.flush()
    }

    /// Shows cursor
    fn show_cursor(&mut self) -> io::Result<()> {
        write!(self.stdout, "{}", termion::cursor::Show)?;
        self.stdout.flush()
    }

    /// Gets cursor position (0-based index)
    fn get_cursor(&mut self) -> io::Result<(u16, u16)> {
        termion::cursor::DetectCursorPos::cursor_pos(&mut self.stdout).map(|(x, y)| (x - 1, y - 1))
    }

    /// Sets cursor position (0-based index)
    fn set_cursor(&mut self, x: u16, y: u16) -> io::Result<()> {
        write!(self.stdout, "{}", termion::cursor::Goto(x + 1, y + 1))?;
        self.stdout.flush()
    }

    fn draw<'a, I>(&mut self, content: I) -> io::Result<()>
    where
        I: Iterator<Item = (u16, u16, &'a Cell)>,
    {
        let mut string = String::with_capacity(content.size_hint().0 * 3);
        let mut style = Style::default();
        let mut last_y = 0;
        let mut last_x = 0;
        let mut inst = 0;
        for (x, y, cell) in content {
            if y != last_y || x != last_x + 1 || inst == 0 {
                string.push_str(&format!("{}", termion::cursor::Goto(x + 1, y + 1)));
                inst += 1;
            }
            last_x = x;
            last_y = y;
            if cell.style.modifier != style.modifier {
                string.push_str(&cell.style.modifier.termion_modifier());
                style.modifier = cell.style.modifier;
                if style.modifier == Modifier::Reset {
                    style.bg = Color::Reset;
                    style.fg = Color::Reset;
                }
                inst += 1;
            }
            if cell.style.fg != style.fg {
                string.push_str(&cell.style.fg.termion_fg());
                style.fg = cell.style.fg;
                inst += 1;
            }
            if cell.style.bg != style.bg {
                string.push_str(&cell.style.bg.termion_bg());
                style.bg = cell.style.bg;
                inst += 1;
            }
            string.push_str(&cell.symbol);
            inst += 1;
        }
        debug!("{} instructions outputed.", inst);
        write!(
            self.stdout,
            "{}{}{}{}",
            string,
            Color::Reset.termion_fg(),
            Color::Reset.termion_bg(),
            Modifier::Reset.termion_modifier()
        )
    }

    /// Return the size of the terminal
    fn size(&self) -> io::Result<Rect> {
        let terminal = r#try!(termion::terminal_size());
        Ok(Rect::new(0, 0, terminal.0, terminal.1))
    }

    fn flush(&mut self) -> io::Result<()> {
        self.stdout.flush()
    }
}

macro_rules! termion_fg {
    ($color:ident) => {
        format!("{}", termion::color::Fg(termion::color::$color))
    };
}

macro_rules! termion_fg_rgb {
    ($r:expr, $g:expr, $b:expr) => {
        format!("{}", termion::color::Fg(termion::color::Rgb($r, $g, $b)))
    };
}

macro_rules! termion_bg {
    ($color:ident) => {
        format!("{}", termion::color::Bg(termion::color::$color))
    };
}

macro_rules! termion_bg_rgb {
    ($r:expr, $g:expr, $b:expr) => {
        format!("{}", termion::color::Bg(termion::color::Rgb($r, $g, $b)))
    };
}

macro_rules! termion_modifier {
    ($style:ident) => {
        format!("{}", termion::style::$style)
    };
}

impl Color {
    pub fn termion_fg(self) -> String {
        match self {
            Color::Reset => termion_fg!(Reset),
            Color::Black => termion_fg!(Black),
            Color::Red => termion_fg!(Red),
            Color::Green => termion_fg!(Green),
            Color::Yellow => termion_fg!(Yellow),
            Color::Blue => termion_fg!(Blue),
            Color::Magenta => termion_fg!(Magenta),
            Color::Cyan => termion_fg!(Cyan),
            Color::Gray => termion_fg!(White),
            Color::DarkGray => termion_fg!(LightBlack),
            Color::LightRed => termion_fg!(LightRed),
            Color::LightGreen => termion_fg!(LightGreen),
            Color::LightBlue => termion_fg!(LightBlue),
            Color::LightYellow => termion_fg!(LightYellow),
            Color::LightMagenta => termion_fg!(LightMagenta),
            Color::LightCyan => termion_fg!(LightCyan),
            Color::White => termion_fg!(LightWhite),
            Color::Rgb(r, g, b) => termion_fg_rgb!(r, g, b),
        }
    }
    pub fn termion_bg(self) -> String {
        match self {
            Color::Reset => termion_bg!(Reset),
            Color::Black => termion_bg!(Black),
            Color::Red => termion_bg!(Red),
            Color::Green => termion_bg!(Green),
            Color::Yellow => termion_bg!(Yellow),
            Color::Blue => termion_bg!(Blue),
            Color::Magenta => termion_bg!(Magenta),
            Color::Cyan => termion_bg!(Cyan),
            Color::Gray => termion_bg!(White),
            Color::DarkGray => termion_bg!(LightBlack),
            Color::LightRed => termion_bg!(LightRed),
            Color::LightGreen => termion_bg!(LightGreen),
            Color::LightBlue => termion_bg!(LightBlue),
            Color::LightYellow => termion_bg!(LightYellow),
            Color::LightMagenta => termion_bg!(LightMagenta),
            Color::LightCyan => termion_bg!(LightCyan),
            Color::White => termion_bg!(LightWhite),
            Color::Rgb(r, g, b) => termion_bg_rgb!(r, g, b),
        }
    }
}

impl Modifier {
    pub fn termion_modifier(self) -> String {
        match self {
            Modifier::Blink => termion_modifier!(Blink),
            Modifier::Bold => termion_modifier!(Bold),
            Modifier::CrossedOut => termion_modifier!(CrossedOut),
            Modifier::Faint => termion_modifier!(Faint),
            Modifier::Framed => termion_modifier!(Framed),
            Modifier::Invert => termion_modifier!(Invert),
            Modifier::Italic => termion_modifier!(Italic),
            Modifier::NoBlink => termion_modifier!(NoBlink),
            Modifier::NoBold => termion_modifier!(NoBold),
            Modifier::NoCrossedOut => termion_modifier!(NoCrossedOut),
            Modifier::NoFaint => termion_modifier!(NoFaint),
            Modifier::NoInvert => termion_modifier!(NoInvert),
            Modifier::NoItalic => termion_modifier!(NoItalic),
            Modifier::NoUnderline => termion_modifier!(NoUnderline),
            Modifier::Reset => termion_modifier!(Reset),
            Modifier::Underline => termion_modifier!(Underline),
        }
    }
}
<|endoftext|>


<commit_before>#![allow(unused_imports, unused_must_use, dead_code)]
extern crate combine;

use std::io::prelude::*;
use std::fs::File;
use std::path::Path;
use std::collections::HashMap;
use std::marker::PhantomData;
use combine::{parser, between, many, many1, digit, char, Parser, ParserExt};
use combine::primitives::{State, Stream, ParseResult, Consumed};
use combine::combinator::FnParser;

//my own bencode stuff!
#[derive(Debug, Eq, PartialEq, Clone)]
pub enum Bencode {
    Int(i64),
    String(String),
    List(Vec<Bencode>),
    Dict(HashMap<String, Bencode>)
}

pub trait BencodeToString {
    fn to_bencode_string (&self) -> String;
}

//yes, we could just use the offsets from the parsed file. but we aren't keeping it around, nor
//are the parsers returning offsets right now (and as it's only needed for computing the
//hashsum... and computing this on the fly is comparatively easier than navigating through
//the sigils of combine
//
//might be worth adapting at the end as its modular, probably not worth it though)
impl BencodeToString for Bencode {
    fn to_bencode_string (&self) -> String {
        let vec: Vec<String> = match *self { //oh god... what did i do...
            Bencode::Int(ref int) =>
                vec!["i".to_string(), int.to_string(), "e".to_string()],
            Bencode::String(ref string) =>
                vec![string.len().to_string(), ":".to_string(), string.to_string()],
            Bencode::List(ref list) => {
                //borrow checker is yelling at me for an unknown reason... if i use map
                //let vec: Vec<String> = list.map::<String>(|x:Bencode| x.to_bencode_string());
                let mut vec = Vec::new();
                for v in list {
                    vec.push(v.to_bencode_string());
                }
                vec
            },
            Bencode::Dict(ref dict) => {
                let mut vec: Vec<String> = Vec::new();
                let mut kvs: Vec<(&String, &Bencode)> = dict.iter().collect();
                kvs.sort_by(|a, b| a.0.cmp(&b.0));
                vec.push("d".to_string());
                for (key_name, val) in kvs {
                    vec.push(key_name.to_string());
                    vec.push(val.to_bencode_string());
                }
                vec.push("e".to_string());
                vec
            }
        };
        vec.concat()
    }
}

/// Opens a file and returns its contents as vector of bytes
/// throws an exception for now if ENOENT
pub fn open_file <P: AsRef<Path>>(path: P) -> Vec<u8> {
    let mut fd = File::open(path).unwrap();
    let mut buffer:Vec<u8> = Vec::new();
    let _ = fd.read_to_end(&mut buffer);
    buffer
}

/// Deserializes a bencoded file
pub fn deserialize_file<P: AsRef<Path>>(path: P) -> Option<Vec<Bencode>> {
    deserialize(open_file(path))
}

/// Takes an input (vector of bytes) and returns the deserialized form as a vector of Bencode(d)
/// objects. Wrapped in an Option.
///
/// there's probably an argument that this should be a Result as opposed to an Option, as you
/// could potentially be losing error pertinent information in an Option. not going to change it over
/// right now
pub fn deserialize (byte_vector: Vec<u8>) -> Option<Vec<Bencode>> {
    //hack to coerce ascii byte values to rust array sliceof char (UTF-8). necessary to avoid substantial
    //writing of existing combine parser builtins
    let as_string: Vec<char> = byte_vector.iter().map(|x| *x as char).collect();
    match many::<Vec<Bencode>, _>(bencode_any()).parse(&as_string[..]) {
        Ok((result, _)) => Some(result),
        Err(_) => None
    }
}

/// Provides typesafe getters for a collection
pub trait TypedMethods {
    fn get_int(&self, key: &str) -> Option<i64>;
    fn get_string(&self, key: &str) -> Option<&String>;
    fn get_owned_string(&self, key: &str) -> Option<String>;
    fn get_dict(&self, key: &str) -> Option<&HashMap<String, Bencode>>;
    fn get_list(&self, key: &str) -> Option<&Vec<Bencode>>;
}

impl TypedMethods for HashMap<String, Bencode> {
    fn get_int (&self, key: &str) -> Option <i64> {
        match self.get(key) {
            Some(&Bencode::Int(a)) => Some(a),
            _ => None
        }
    }

    fn get_string (&self, key: &str) -> Option <&String> {
        match self.get(key) {
            Some(&Bencode::String(ref a)) => Some(a),
            _ => None
        }
    }

    fn get_owned_string(&self, key: &str) -> Option <String> {
        match self.get(key) {
            Some(&Bencode::String(ref a)) => Some(a.to_owned()),
            _ => None
        }
    }

    fn get_dict (&self, key: &str) -> Option <&HashMap<String, Bencode>> {
        match self.get(key) {
            Some(&Bencode::Dict(ref a)) => Some(a),
            _ => None
        }
    }

    fn get_list (&self, key: &str) -> Option <&Vec<Bencode>> {
        match self.get(key) {
            Some(&Bencode::List(ref a)) => Some(a),
            _ => None
        }
    }
}

fn bencode_integer<I>(input: State<I>) -> ParseResult<i64, I> where I: Stream<Item=char> {
    let (open, close) = (char('i'), char('e'));
    let mut int = between(open, close, many1::<String, _>(digit())).map(|x| {
        x.parse::<i64>().unwrap()
    });
    int.parse_state(input)
}

fn bencode_string<I>(input: State<I>) -> ParseResult<String, I> where I: Stream<Item=char> {
    let (len, input_) = try!(bencode_string_length_prefix(input));
    input_.combine(|input__| take(len).parse_state(input__))
}

fn bencode_string_length_prefix<I>(input: State<I>) -> ParseResult<i32, I> where I:Stream<Item=char> {
    let many_digit = many1::<String, _>(digit());
    let mut get_len = (many_digit, char(':')).map(|(length, _)| length.parse::<i32>().unwrap());
    get_len.parse_state(input)
}

fn bencode_list<I>(input: State<I>) -> ParseResult<Vec<Bencode>, I> where I: Stream<Item=char> {
    let (open, close) = (char('l'), char('e'));
    let list_contents = many::<Vec<Bencode>, _>(bencode_any());
    let mut list = between(open, close, list_contents);
    list.parse_state(input)
}

fn bencode_dict<I>(input: State<I>) -> ParseResult<HashMap<String, Bencode>, I> where I: Stream<Item=char> {
    let (open, close) = (char('d'), char('e'));
    let pairs = (parser(bencode_string), bencode_any());
    let mut dict = between(open, close, many(pairs)).map(|entries:Vec<(String, Bencode)>|{
        let mut hash_map = HashMap::new();
        for (k, v) in entries {
            hash_map.insert(k, v);
        }
        hash_map
    });
    dict.parse_state(input)
}

fn bencode_any<I>() -> FnParser<I, fn (State<I>) -> ParseResult<Bencode, I>> where I: Stream<Item=char> {
    fn bencode_any_<I>(input: State<I>) -> ParseResult<Bencode, I> where I: Stream<Item=char> {
        parser(bencode_integer).map(Bencode::Int)
            .or(parser(bencode_string).map(Bencode::String))
            .or(parser(bencode_list).map(Bencode::List))
            .or(parser(bencode_dict).map(Bencode::Dict)).parse_state(input)
    }
    parser(bencode_any_)
}

fn take <I> (num: i32) -> SizedBuffer<I> where I: Stream<Item=char> {
    SizedBuffer(num, PhantomData)
}

#[derive(Clone)]
struct SizedBuffer <I>(i32, PhantomData<I>);
impl <I> Parser for SizedBuffer<I> where I: Stream<Item=char> {
    type Input = I;
    type Output = String;
    fn parse_lazy(&mut self, mut input: State<I>) -> ParseResult<String, I> {
        let start = input.position;
        let mut vec_buf:Vec<char> = Vec::new();
        for _ in 0..self.0 {
            match input.uncons() {
                Ok((other, rest)) => {
                    vec_buf.push(other);
                    input = rest.into_inner();
                }
                Err(error) => {
                    return error.combine(|mut error| {
                        error.position = start;
                        Err(Consumed::Consumed(error))
                    })
                }
            };
        }
        Ok((vec_buf.into_iter().collect(), Consumed::Consumed(input)))
    }
}

#[test]
fn test_integer() {
    let result = parser(bencode_integer).parse("i57e");
    assert_eq!(result, Ok((57,"")));
}

#[test]
fn test_string() {
    let result = parser(bencode_string).parse("5:abcde");
    assert_eq!(result, Ok(("abcde".to_string(), "")));;
}

#[test]
fn test_list() {
    let homogenous_int_list = parser(bencode_list).parse("li57ei32ee");
    assert_eq!(homogenous_int_list, Ok((vec![Bencode::Int(57), Bencode::Int(32)], "")));

    let homogenous_str_list = parser(bencode_list).parse("l3:abc5:defghe");
    assert_eq!(homogenous_str_list, Ok((vec![Bencode::String("abc".to_string()), Bencode::String("defgh".to_string())], "")));

    let hetero_list = parser(bencode_list).parse("li32e3:abce");
    assert_eq!(hetero_list, Ok((vec![Bencode::Int(32), Bencode::String("abc".to_string())], "")));
}

#[test]
fn test_dict() {
    let (dict_result, _) = parser(bencode_dict).parse("d3:abci4e4:andyli5eee").unwrap();
    assert_eq!(*dict_result.get("abc").unwrap(), Bencode::Int(4));
    assert_eq!(*dict_result.get("andy").unwrap(), Bencode::List(vec![Bencode::Int(5)]));
    assert_eq!(dict_result.len(), 2);
}

#[test]
fn test_many() {
    let input_string = "i1ei2ei3ei10el3:abc4:defged1:ai10ee";
    let (result, _) = many::<Vec<Bencode>, _>(bencode_any()).parse(input_string).unwrap();
    let mut my_map = HashMap::new();
    my_map.insert("a".to_string(), Bencode::Int(10));
    assert_eq!(result, vec![
        Bencode::Int(1),
        Bencode::Int(2),
        Bencode::Int(3),
        Bencode::Int(10),
        Bencode::List(vec![
            Bencode::String("abc".to_string()),
            Bencode::String("defg".to_string())
            ]),
        Bencode::Dict(my_map)
    ]);
}
<commit_msg>replacing for .. in vec pattern with map in bencode<commit_after>#![allow(unused_imports, unused_must_use, dead_code)]
extern crate combine;

use std::io::prelude::*;
use std::fs::File;
use std::path::Path;
use std::collections::HashMap;
use std::marker::PhantomData;
use combine::{parser, between, many, many1, digit, char, Parser, ParserExt};
use combine::primitives::{State, Stream, ParseResult, Consumed};
use combine::combinator::FnParser;

//my own bencode stuff!
#[derive(Debug, Eq, PartialEq, Clone)]
pub enum Bencode {
    Int(i64),
    String(String),
    List(Vec<Bencode>),
    Dict(HashMap<String, Bencode>)
}

pub trait BencodeToString {
    fn to_bencode_string (&self) -> String;
}

//yes, we could just use the offsets from the parsed file. but we aren't keeping it around, nor
//are the parsers returning offsets right now (and as it's only needed for computing the
//hashsum... and computing this on the fly is comparatively easier than navigating through
//the sigils of combine
//
//might be worth adapting at the end as its modular, probably not worth it though)
impl BencodeToString for Bencode {
    fn to_bencode_string (&self) -> String {
        let vec: Vec<String> = match *self { //oh god... what did i do...
            Bencode::Int(ref int) =>
                vec!["i".to_string(), int.to_string(), "e".to_string()],
            Bencode::String(ref string) =>
                vec![string.len().to_string(), ":".to_string(), string.to_string()],
            Bencode::List(ref list) => {
                list.iter().map(|x| x.to_bencode_string()).collect::<Vec<String>>()
            },
            Bencode::Dict(ref dict) => {
                let mut vec: Vec<String> = Vec::new();
                let mut kvs: Vec<(&String, &Bencode)> = dict.iter().collect();
                kvs.sort_by(|a, b| a.0.cmp(&b.0));
                vec.push("d".to_string());
                for (key_name, val) in kvs {
                    vec.push(key_name.to_string());
                    vec.push(val.to_bencode_string());
                }
                vec.push("e".to_string());
                vec
            }
        };
        vec.concat()
    }
}

/// Opens a file and returns its contents as vector of bytes
/// throws an exception for now if ENOENT
pub fn open_file <P: AsRef<Path>>(path: P) -> Vec<u8> {
    let mut fd = File::open(path).unwrap();
    let mut buffer:Vec<u8> = Vec::new();
    let _ = fd.read_to_end(&mut buffer);
    buffer
}

/// Deserializes a bencoded file
pub fn deserialize_file<P: AsRef<Path>>(path: P) -> Option<Vec<Bencode>> {
    deserialize(open_file(path))
}

/// Takes an input (vector of bytes) and returns the deserialized form as a vector of Bencode(d)
/// objects. Wrapped in an Option.
///
/// there's probably an argument that this should be a Result as opposed to an Option, as you
/// could potentially be losing error pertinent information in an Option. not going to change it over
/// right now
pub fn deserialize (byte_vector: Vec<u8>) -> Option<Vec<Bencode>> {
    //hack to coerce ascii byte values to rust array sliceof char (UTF-8). necessary to avoid substantial
    //writing of existing combine parser builtins
    let as_string: Vec<char> = byte_vector.iter().map(|x| *x as char).collect();
    match many::<Vec<Bencode>, _>(bencode_any()).parse(&as_string[..]) {
        Ok((result, _)) => Some(result),
        Err(_) => None
    }
}

/// Provides typesafe getters for a collection
pub trait TypedMethods {
    fn get_int(&self, key: &str) -> Option<i64>;
    fn get_string(&self, key: &str) -> Option<&String>;
    fn get_owned_string(&self, key: &str) -> Option<String>;
    fn get_dict(&self, key: &str) -> Option<&HashMap<String, Bencode>>;
    fn get_list(&self, key: &str) -> Option<&Vec<Bencode>>;
}

impl TypedMethods for HashMap<String, Bencode> {
    fn get_int (&self, key: &str) -> Option <i64> {
        match self.get(key) {
            Some(&Bencode::Int(a)) => Some(a),
            _ => None
        }
    }

    fn get_string (&self, key: &str) -> Option <&String> {
        match self.get(key) {
            Some(&Bencode::String(ref a)) => Some(a),
            _ => None
        }
    }

    fn get_owned_string(&self, key: &str) -> Option <String> {
        match self.get(key) {
            Some(&Bencode::String(ref a)) => Some(a.to_owned()),
            _ => None
        }
    }

    fn get_dict (&self, key: &str) -> Option <&HashMap<String, Bencode>> {
        match self.get(key) {
            Some(&Bencode::Dict(ref a)) => Some(a),
            _ => None
        }
    }

    fn get_list (&self, key: &str) -> Option <&Vec<Bencode>> {
        match self.get(key) {
            Some(&Bencode::List(ref a)) => Some(a),
            _ => None
        }
    }
}

fn bencode_integer<I>(input: State<I>) -> ParseResult<i64, I> where I: Stream<Item=char> {
    let (open, close) = (char('i'), char('e'));
    let mut int = between(open, close, many1::<String, _>(digit())).map(|x| {
        x.parse::<i64>().unwrap()
    });
    int.parse_state(input)
}

fn bencode_string<I>(input: State<I>) -> ParseResult<String, I> where I: Stream<Item=char> {
    let (len, input_) = try!(bencode_string_length_prefix(input));
    input_.combine(|input__| take(len).parse_state(input__))
}

fn bencode_string_length_prefix<I>(input: State<I>) -> ParseResult<i32, I> where I:Stream<Item=char> {
    let many_digit = many1::<String, _>(digit());
    let mut get_len = (many_digit, char(':')).map(|(length, _)| length.parse::<i32>().unwrap());
    get_len.parse_state(input)
}

fn bencode_list<I>(input: State<I>) -> ParseResult<Vec<Bencode>, I> where I: Stream<Item=char> {
    let (open, close) = (char('l'), char('e'));
    let list_contents = many::<Vec<Bencode>, _>(bencode_any());
    let mut list = between(open, close, list_contents);
    list.parse_state(input)
}

fn bencode_dict<I>(input: State<I>) -> ParseResult<HashMap<String, Bencode>, I> where I: Stream<Item=char> {
    let (open, close) = (char('d'), char('e'));
    let pairs = (parser(bencode_string), bencode_any());
    let mut dict = between(open, close, many(pairs)).map(|entries:Vec<(String, Bencode)>|{
        let mut hash_map = HashMap::new();
        for (k, v) in entries {
            hash_map.insert(k, v);
        }
        hash_map
    });
    dict.parse_state(input)
}

fn bencode_any<I>() -> FnParser<I, fn (State<I>) -> ParseResult<Bencode, I>> where I: Stream<Item=char> {
    fn bencode_any_<I>(input: State<I>) -> ParseResult<Bencode, I> where I: Stream<Item=char> {
        parser(bencode_integer).map(Bencode::Int)
            .or(parser(bencode_string).map(Bencode::String))
            .or(parser(bencode_list).map(Bencode::List))
            .or(parser(bencode_dict).map(Bencode::Dict)).parse_state(input)
    }
    parser(bencode_any_)
}

fn take <I> (num: i32) -> SizedBuffer<I> where I: Stream<Item=char> {
    SizedBuffer(num, PhantomData)
}

#[derive(Clone)]
struct SizedBuffer <I>(i32, PhantomData<I>);
impl <I> Parser for SizedBuffer<I> where I: Stream<Item=char> {
    type Input = I;
    type Output = String;
    fn parse_lazy(&mut self, mut input: State<I>) -> ParseResult<String, I> {
        let start = input.position;
        let mut vec_buf:Vec<char> = Vec::new();
        for _ in 0..self.0 {
            match input.uncons() {
                Ok((other, rest)) => {
                    vec_buf.push(other);
                    input = rest.into_inner();
                }
                Err(error) => {
                    return error.combine(|mut error| {
                        error.position = start;
                        Err(Consumed::Consumed(error))
                    })
                }
            };
        }
        Ok((vec_buf.into_iter().collect(), Consumed::Consumed(input)))
    }
}

#[test]
fn test_integer() {
    let result = parser(bencode_integer).parse("i57e");
    assert_eq!(result, Ok((57,"")));
}

#[test]
fn test_string() {
    let result = parser(bencode_string).parse("5:abcde");
    assert_eq!(result, Ok(("abcde".to_string(), "")));;
}

#[test]
fn test_list() {
    let homogenous_int_list = parser(bencode_list).parse("li57ei32ee");
    assert_eq!(homogenous_int_list, Ok((vec![Bencode::Int(57), Bencode::Int(32)], "")));

    let homogenous_str_list = parser(bencode_list).parse("l3:abc5:defghe");
    assert_eq!(homogenous_str_list, Ok((vec![Bencode::String("abc".to_string()), Bencode::String("defgh".to_string())], "")));

    let hetero_list = parser(bencode_list).parse("li32e3:abce");
    assert_eq!(hetero_list, Ok((vec![Bencode::Int(32), Bencode::String("abc".to_string())], "")));
}

#[test]
fn test_dict() {
    let (dict_result, _) = parser(bencode_dict).parse("d3:abci4e4:andyli5eee").unwrap();
    assert_eq!(*dict_result.get("abc").unwrap(), Bencode::Int(4));
    assert_eq!(*dict_result.get("andy").unwrap(), Bencode::List(vec![Bencode::Int(5)]));
    assert_eq!(dict_result.len(), 2);
}

#[test]
fn test_many() {
    let input_string = "i1ei2ei3ei10el3:abc4:defged1:ai10ee";
    let (result, _) = many::<Vec<Bencode>, _>(bencode_any()).parse(input_string).unwrap();
    let mut my_map = HashMap::new();
    my_map.insert("a".to_string(), Bencode::Int(10));
    assert_eq!(result, vec![
        Bencode::Int(1),
        Bencode::Int(2),
        Bencode::Int(3),
        Bencode::Int(10),
        Bencode::List(vec![
            Bencode::String("abc".to_string()),
            Bencode::String("defg".to_string())
            ]),
        Bencode::Dict(my_map)
    ]);
}
<|endoftext|>


<commit_before>use std::ffi::CString;
use std::convert::Into;
use std::mem;

use libc::c_uint;

use rustc::lib::llvm;
use rustc::lib::llvm::{ ContextRef
                      , ModuleRef
                      , ValueRef
                      , BuilderRef
                      , TypeRef
                      };

use forktable::ForkTable;
use position::Positional;
use ast::{Form, DefForm};
use semantic::types::{ Type
                     , Reference
                     , Primitive
                     , ScopedState
                     , Scoped
                     };

pub type IRResult = Result<ValueRef, Positional<String>>;
pub type SymbolTable<'a> = ForkTable<'a, &'a str, ValueRef>;

#[inline] fn word_size() -> c_uint { mem::size_of::<isize>() as c_uint }

/// Trait for that which may join in The Great Work
pub trait Compile {
    fn to_ir(&self, context: LLVMContext) -> IRResult;
}

pub trait TranslateType {
    fn translate_type(&self, context: LLVMContext) -> TypeRef;
}

/// LLVM compilation context.
///
/// This is based rather loosely on MIT License code from
/// the [iron-kaleidoscope](https://github.com/jauhien/iron-kaleidoscope)
/// tutorial, and from [`librustc_trans`](https://github.com/rust-lang/rust/blob/master/src/librustc_trans/trans/mod.rs)
/// from the Rust compiler.
pub struct LLVMContext<'a> { pub llctx: ContextRef
                           , pub llmod: ModuleRef
                           , pub llbuilder: BuilderRef
                           , pub names: SymbolTable<'a>
                           }

// because we are in the Raw Pointer Sadness Zone (read: unsafe),
// it is necessary that we assert that everything exists.
macro_rules! not_null {
    ($target:expr) => ({
        let e = $target;
        if e.is_null() {
            panic!("assertion failed: {} returned null!", stringify!($target));
        } else { e }
    })
}

impl<'a> LLVMContext<'a> {

    pub fn new(module_name: &str) -> Self {
        let name = CString::new(module_name).unwrap();
        unsafe {
            let ctx = not_null!(llvm::LLVMContextCreate());
            LLVMContext {
                llctx: ctx
              , llmod: not_null!(llvm::LLVMModuleCreateWithNameInContext(name.into_raw(), ctx))
              , llbuilder: not_null!(llvm::LLVMCreateBuilderInContext(ctx))
              , names: SymbolTable::new()
            }
        }
    }

    /// Dump the module's contents to stderr for debugging
    ///
    /// Apparently this is the only reasonable way to get a textual
    /// representation of a `ModuleRef` in `librustc_llvm`...
    pub fn dump(&self) {
        unsafe { llvm::LLVMDumpModule(self.llmod); }
    }
}

impl<'a> Drop for LLVMContext<'a> {
    fn drop(&mut self) {
        unsafe {
            llvm::LLVMDisposeModule(self.llmod);
            llvm::LLVMDisposeBuilder(self.llbuilder);
            llvm::LLVMContextDispose(self.llctx);
        }
    }
}

impl<'a> Compile for Scoped<'a, Form<'a, ScopedState>> {
    fn to_ir(&self, context: LLVMContext) -> IRResult {
        match **self {
            Form::Define(ref form) => unimplemented!()
        }
    }
}

impl<'a> Compile for Scoped<'a, DefForm<'a, ScopedState>> {
    fn to_ir(&self, context: LLVMContext) -> IRResult {
        match **self {
            DefForm::TopLevel { ref name, ref value, .. } =>
                unimplemented!(),
            DefForm::Function { ref name, ref body, .. } =>
                unsafe {
                    let name_ptr // function name as C string pointer
                        = CString::new((&name.value).clone()).unwrap().as_ptr();
                    let prev_decl // check LLVM module for previous declaration
                        = llvm::LLVMGetNamedFunction(context.llmod, name_ptr);

                    if !prev_decl.is_null() { // a previous declaration exists
                        unimplemented!() // TODO: overloading rules happen here
                    } else { // new function declaration
                        unimplemented!()
                    }
                }
        }
    }
}

impl TranslateType for Type {
    fn translate_type(&self, context: LLVMContext) -> TypeRef {
        match *self {
            Type::Ref(ref reference)  => reference.translate_type(context),
            Type::Prim(ref primitive) => primitive.translate_type(context),
            _ => unimplemented!() // TODO: figure this out
        }
    }
}

impl TranslateType for Reference {
    fn translate_type(&self, context: LLVMContext) -> TypeRef {
        unimplemented!() // TODO: figure this out
    }
}

impl TranslateType for Primitive {
    fn translate_type(&self, context: LLVMContext) -> TypeRef {
        unsafe {
            not_null!(match *self {
                Primitive::Int => // Integers are machine word size
                    llvm::LLVMIntTypeInContext(context.llctx, word_size()),
                Primitive::Float => // Floats are single precision
                    llvm::LLVMFloatTypeInContext(context.llctx),
                Primitive::Double => // Doubles are obvious precision
                    llvm::LLVMDoubleTypeInContext(context.llctx),
                Primitive::Byte => // Bytes are 8 bits (duh)
                    llvm::LLVMInt8TypeInContext(context.llctx),
                _ => unimplemented!() // TODO: figure this out
            })
        }
    }
}
<commit_msg>Remove unused import<commit_after>use std::ffi::CString;
use std::mem;

use libc::c_uint;

use rustc::lib::llvm;
use rustc::lib::llvm::{ ContextRef
                      , ModuleRef
                      , ValueRef
                      , BuilderRef
                      , TypeRef
                      };

use forktable::ForkTable;
use position::Positional;
use ast::{Form, DefForm};
use semantic::types::{ Type
                     , Reference
                     , Primitive
                     , ScopedState
                     , Scoped
                     };

pub type IRResult = Result<ValueRef, Positional<String>>;
pub type SymbolTable<'a> = ForkTable<'a, &'a str, ValueRef>;

#[inline] fn word_size() -> c_uint { mem::size_of::<isize>() as c_uint }

/// Trait for that which may join in The Great Work
pub trait Compile {
    fn to_ir(&self, context: LLVMContext) -> IRResult;
}

pub trait TranslateType {
    fn translate_type(&self, context: LLVMContext) -> TypeRef;
}

/// LLVM compilation context.
///
/// This is based rather loosely on MIT License code from
/// the [iron-kaleidoscope](https://github.com/jauhien/iron-kaleidoscope)
/// tutorial, and from [`librustc_trans`](https://github.com/rust-lang/rust/blob/master/src/librustc_trans/trans/mod.rs)
/// from the Rust compiler.
pub struct LLVMContext<'a> { pub llctx: ContextRef
                           , pub llmod: ModuleRef
                           , pub llbuilder: BuilderRef
                           , pub names: SymbolTable<'a>
                           }

// because we are in the Raw Pointer Sadness Zone (read: unsafe),
// it is necessary that we assert that everything exists.
macro_rules! not_null {
    ($target:expr) => ({
        let e = $target;
        if e.is_null() {
            panic!("assertion failed: {} returned null!", stringify!($target));
        } else { e }
    })
}

impl<'a> LLVMContext<'a> {

    pub fn new(module_name: &str) -> Self {
        let name = CString::new(module_name).unwrap();
        unsafe {
            let ctx = not_null!(llvm::LLVMContextCreate());
            LLVMContext {
                llctx: ctx
              , llmod: not_null!(llvm::LLVMModuleCreateWithNameInContext(name.into_raw(), ctx))
              , llbuilder: not_null!(llvm::LLVMCreateBuilderInContext(ctx))
              , names: SymbolTable::new()
            }
        }
    }

    /// Dump the module's contents to stderr for debugging
    ///
    /// Apparently this is the only reasonable way to get a textual
    /// representation of a `ModuleRef` in `librustc_llvm`...
    pub fn dump(&self) {
        unsafe { llvm::LLVMDumpModule(self.llmod); }
    }
}

impl<'a> Drop for LLVMContext<'a> {
    fn drop(&mut self) {
        unsafe {
            llvm::LLVMDisposeModule(self.llmod);
            llvm::LLVMDisposeBuilder(self.llbuilder);
            llvm::LLVMContextDispose(self.llctx);
        }
    }
}

impl<'a> Compile for Scoped<'a, Form<'a, ScopedState>> {
    fn to_ir(&self, context: LLVMContext) -> IRResult {
        match **self {
            Form::Define(ref form) => unimplemented!()
        }
    }
}

impl<'a> Compile for Scoped<'a, DefForm<'a, ScopedState>> {
    fn to_ir(&self, context: LLVMContext) -> IRResult {
        match **self {
            DefForm::TopLevel { ref name, ref value, .. } =>
                unimplemented!(),
            DefForm::Function { ref name, ref body, .. } =>
                unsafe {
                    let name_ptr // function name as C string pointer
                        = CString::new((&name.value).clone()).unwrap().as_ptr();
                    let prev_decl // check LLVM module for previous declaration
                        = llvm::LLVMGetNamedFunction(context.llmod, name_ptr);

                    if !prev_decl.is_null() { // a previous declaration exists
                        unimplemented!() // TODO: overloading rules happen here
                    } else { // new function declaration
                        unimplemented!()
                    }
                }
        }
    }
}

impl TranslateType for Type {
    fn translate_type(&self, context: LLVMContext) -> TypeRef {
        match *self {
            Type::Ref(ref reference)  => reference.translate_type(context),
            Type::Prim(ref primitive) => primitive.translate_type(context),
            _ => unimplemented!() // TODO: figure this out
        }
    }
}

impl TranslateType for Reference {
    fn translate_type(&self, context: LLVMContext) -> TypeRef {
        unimplemented!() // TODO: figure this out
    }
}

impl TranslateType for Primitive {
    fn translate_type(&self, context: LLVMContext) -> TypeRef {
        unsafe {
            not_null!(match *self {
                Primitive::Int => // Integers are machine word size
                    llvm::LLVMIntTypeInContext(context.llctx, word_size()),
                Primitive::Float => // Floats are single precision
                    llvm::LLVMFloatTypeInContext(context.llctx),
                Primitive::Double => // Doubles are obvious precision
                    llvm::LLVMDoubleTypeInContext(context.llctx),
                Primitive::Byte => // Bytes are 8 bits (duh)
                    llvm::LLVMInt8TypeInContext(context.llctx),
                _ => unimplemented!() // TODO: figure this out
            })
        }
    }
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

mod generate_flow;

use fixture_tests::test_fixture;
use generate_flow::transform_fixture;

#[test]
fn conditional() {
    let input = include_str!("generate_flow/fixtures/conditional.graphql");
    let expected = include_str!("generate_flow/fixtures/conditional.expected");
    test_fixture(
        transform_fixture,
        "conditional.graphql",
        "generate_flow/fixtures/conditional.expected",
        input,
        expected,
    );
}

#[test]
fn fragment_spread() {
    let input = include_str!("generate_flow/fixtures/fragment-spread.graphql");
    let expected = include_str!("generate_flow/fixtures/fragment-spread.expected");
    test_fixture(
        transform_fixture,
        "fragment-spread.graphql",
        "generate_flow/fixtures/fragment-spread.expected",
        input,
        expected,
    );
}

#[test]
fn inline_fragment() {
    let input = include_str!("generate_flow/fixtures/inline-fragment.graphql");
    let expected = include_str!("generate_flow/fixtures/inline-fragment.expected");
    test_fixture(
        transform_fixture,
        "inline-fragment.graphql",
        "generate_flow/fixtures/inline-fragment.expected",
        input,
        expected,
    );
}

#[test]
fn linked_field() {
    let input = include_str!("generate_flow/fixtures/linked-field.graphql");
    let expected = include_str!("generate_flow/fixtures/linked-field.expected");
    test_fixture(
        transform_fixture,
        "linked-field.graphql",
        "generate_flow/fixtures/linked-field.expected",
        input,
        expected,
    );
}

#[test]
fn match_field() {
    let input = include_str!("generate_flow/fixtures/match-field.graphql");
    let expected = include_str!("generate_flow/fixtures/match-field.expected");
    test_fixture(
        transform_fixture,
        "match-field.graphql",
        "generate_flow/fixtures/match-field.expected",
        input,
        expected,
    );
}

#[test]
fn match_field_in_query() {
    let input = include_str!("generate_flow/fixtures/match-field-in-query.graphql");
    let expected = include_str!("generate_flow/fixtures/match-field-in-query.expected");
    test_fixture(
        transform_fixture,
        "match-field-in-query.graphql",
        "generate_flow/fixtures/match-field-in-query.expected",
        input,
        expected,
    );
}

#[test]
fn refetchable() {
    let input = include_str!("generate_flow/fixtures/refetchable.graphql");
    let expected = include_str!("generate_flow/fixtures/refetchable.expected");
    test_fixture(
        transform_fixture,
        "refetchable.graphql",
        "generate_flow/fixtures/refetchable.expected",
        input,
        expected,
    );
}

#[test]
fn mutaion_with_client_extension() {
    let input = include_str!("generate_flow/fixtures/mutaion-with-client-extension.graphql");
    let expected = include_str!("generate_flow/fixtures/mutaion-with-client-extension.expected");
    test_fixture(
        transform_fixture,
        "mutaion-with-client-extension.graphql",
        "generate_flow/fixtures/mutaion-with-client-extension.expected",
        input,
        expected,
    );
}

#[test]
fn mutaion_with_response_on_inline_fragments() {
    let input =
        include_str!("generate_flow/fixtures/mutaion-with-response-on-inline-fragments.graphql");
    let expected =
        include_str!("generate_flow/fixtures/mutaion-with-response-on-inline-fragments.expected");
    test_fixture(
        transform_fixture,
        "mutaion-with-response-on-inline-fragments.graphql",
        "generate_flow/fixtures/mutaion-with-response-on-inline-fragments.expected",
        input,
        expected,
    );
}

#[test]
fn mutation() {
    let input = include_str!("generate_flow/fixtures/mutation.graphql");
    let expected = include_str!("generate_flow/fixtures/mutation.expected");
    test_fixture(
        transform_fixture,
        "mutation.graphql",
        "generate_flow/fixtures/mutation.expected",
        input,
        expected,
    );
}

#[test]
fn mutation_input_has_array() {
    let input = include_str!("generate_flow/fixtures/mutation-input-has-array.graphql");
    let expected = include_str!("generate_flow/fixtures/mutation-input-has-array.expected");
    test_fixture(
        transform_fixture,
        "mutation-input-has-array.graphql",
        "generate_flow/fixtures/mutation-input-has-array.expected",
        input,
        expected,
    );
}

#[test]
fn mutation_with_enums_on_fragment() {
    let input = include_str!("generate_flow/fixtures/mutation-with-enums-on-fragment.graphql");
    let expected = include_str!("generate_flow/fixtures/mutation-with-enums-on-fragment.expected");
    test_fixture(
        transform_fixture,
        "mutation-with-enums-on-fragment.graphql",
        "generate_flow/fixtures/mutation-with-enums-on-fragment.expected",
        input,
        expected,
    );
}

#[test]
fn mutation_with_nested_fragments() {
    let input = include_str!("generate_flow/fixtures/mutation-with-nested-fragments.graphql");
    let expected = include_str!("generate_flow/fixtures/mutation-with-nested-fragments.expected");
    test_fixture(
        transform_fixture,
        "mutation-with-nested-fragments.graphql",
        "generate_flow/fixtures/mutation-with-nested-fragments.expected",
        input,
        expected,
    );
}

#[test]
fn plural_fragment() {
    let input = include_str!("generate_flow/fixtures/plural-fragment.graphql");
    let expected = include_str!("generate_flow/fixtures/plural-fragment.expected");
    test_fixture(
        transform_fixture,
        "plural-fragment.graphql",
        "generate_flow/fixtures/plural-fragment.expected",
        input,
        expected,
    );
}

#[test]
fn query_with_handles() {
    let input = include_str!("generate_flow/fixtures/query-with-handles.graphql");
    let expected = include_str!("generate_flow/fixtures/query-with-handles.expected");
    test_fixture(
        transform_fixture,
        "query-with-handles.graphql",
        "generate_flow/fixtures/query-with-handles.expected",
        input,
        expected,
    );
}

#[test]
fn query_with_match_fields() {
    let input = include_str!("generate_flow/fixtures/query-with-match-fields.graphql");
    let expected = include_str!("generate_flow/fixtures/query-with-match-fields.expected");
    test_fixture(
        transform_fixture,
        "query-with-match-fields.graphql",
        "generate_flow/fixtures/query-with-match-fields.expected",
        input,
        expected,
    );
}

#[test]
fn query_with_module_field() {
    let input = include_str!("generate_flow/fixtures/query-with-module-field.graphql");
    let expected = include_str!("generate_flow/fixtures/query-with-module-field.expected");
    test_fixture(
        transform_fixture,
        "query-with-module-field.graphql",
        "generate_flow/fixtures/query-with-module-field.expected",
        input,
        expected,
    );
}

#[test]
fn query_with_multiple_match_fields() {
    let input = include_str!("generate_flow/fixtures/query-with-multiple-match-fields.graphql");
    let expected = include_str!("generate_flow/fixtures/query-with-multiple-match-fields.expected");
    test_fixture(
        transform_fixture,
        "query-with-multiple-match-fields.graphql",
        "generate_flow/fixtures/query-with-multiple-match-fields.expected",
        input,
        expected,
    );
}

#[test]
fn query_with_raw_response_on_conditional() {
    let input =
        include_str!("generate_flow/fixtures/query-with-raw-response-on-conditional.graphql");
    let expected =
        include_str!("generate_flow/fixtures/query-with-raw-response-on-conditional.expected");
    test_fixture(
        transform_fixture,
        "query-with-raw-response-on-conditional.graphql",
        "generate_flow/fixtures/query-with-raw-response-on-conditional.expected",
        input,
        expected,
    );
}

#[test]
fn query_with_raw_response_on_literal_conditional() {
    let input = include_str!(
        "generate_flow/fixtures/query-with-raw-response-on-literal-conditional.graphql"
    );
    let expected = include_str!(
        "generate_flow/fixtures/query-with-raw-response-on-literal-conditional.expected"
    );
    test_fixture(
        transform_fixture,
        "query-with-raw-response-on-literal-conditional.graphql",
        "generate_flow/fixtures/query-with-raw-response-on-literal-conditional.expected",
        input,
        expected,
    );
}

#[test]
fn query_with_stream() {
    let input = include_str!("generate_flow/fixtures/query-with-stream.graphql");
    let expected = include_str!("generate_flow/fixtures/query-with-stream.expected");
    test_fixture(
        transform_fixture,
        "query-with-stream.graphql",
        "generate_flow/fixtures/query-with-stream.expected",
        input,
        expected,
    );
}

#[test]
fn query_with_stream_connection() {
    let input = include_str!("generate_flow/fixtures/query-with-stream-connection.graphql");
    let expected = include_str!("generate_flow/fixtures/query-with-stream-connection.expected");
    test_fixture(
        transform_fixture,
        "query-with-stream-connection.graphql",
        "generate_flow/fixtures/query-with-stream-connection.expected",
        input,
        expected,
    );
}

#[test]
fn recursive_fragments() {
    let input = include_str!("generate_flow/fixtures/recursive-fragments.graphql");
    let expected = include_str!("generate_flow/fixtures/recursive-fragments.expected");
    test_fixture(
        transform_fixture,
        "recursive-fragments.graphql",
        "generate_flow/fixtures/recursive-fragments.expected",
        input,
        expected,
    );
}

// #[test]
// fn refetchable_fragment() {
//     let input = include_str!("generate_flow/fixtures/refetchable-fragment.graphql");
//     let expected = include_str!("generate_flow/fixtures/refetchable-fragment.expected");
//     test_fixture(
//         transform_fixture,
//         "refetchable-fragment.graphql",
//         "generate_flow/fixtures/refetchable-fragment.expected",
//         input,
//         expected,
//     );
// }

#[test]
fn relay_client_id_field() {
    let input = include_str!("generate_flow/fixtures/relay-client-id-field.graphql");
    let expected = include_str!("generate_flow/fixtures/relay-client-id-field.expected");
    test_fixture(
        transform_fixture,
        "relay-client-id-field.graphql",
        "generate_flow/fixtures/relay-client-id-field.expected",
        input,
        expected,
    );
}

#[test]
fn roots() {
    let input = include_str!("generate_flow/fixtures/roots.graphql");
    let expected = include_str!("generate_flow/fixtures/roots.expected");
    test_fixture(
        transform_fixture,
        "roots.graphql",
        "generate_flow/fixtures/roots.expected",
        input,
        expected,
    );
}

#[test]
fn scalar_field() {
    let input = include_str!("generate_flow/fixtures/scalar-field.graphql");
    let expected = include_str!("generate_flow/fixtures/scalar-field.expected");
    test_fixture(
        transform_fixture,
        "scalar-field.graphql",
        "generate_flow/fixtures/scalar-field.expected",
        input,
        expected,
    );
}

#[test]
fn simple() {
    let input = include_str!("generate_flow/fixtures/simple.graphql");
    let expected = include_str!("generate_flow/fixtures/simple.expected");
    test_fixture(
        transform_fixture,
        "simple.graphql",
        "generate_flow/fixtures/simple.expected",
        input,
        expected,
    );
}

#[test]
fn typename_inside_with_overlapping_fields() {
    let input =
        include_str!("generate_flow/fixtures/typename-inside-with-overlapping-fields.graphql");
    let expected =
        include_str!("generate_flow/fixtures/typename-inside-with-overlapping-fields.expected");
    test_fixture(
        transform_fixture,
        "typename-inside-with-overlapping-fields.graphql",
        "generate_flow/fixtures/typename-inside-with-overlapping-fields.expected",
        input,
        expected,
    );
}

#[test]
fn typename_on_union() {
    let input = include_str!("generate_flow/fixtures/typename-on-union.graphql");
    let expected = include_str!("generate_flow/fixtures/typename-on-union.expected");
    test_fixture(
        transform_fixture,
        "typename-on-union.graphql",
        "generate_flow/fixtures/typename-on-union.expected",
        input,
        expected,
    );
}

#[test]
fn unmasked_fragment_spreads() {
    let input = include_str!("generate_flow/fixtures/unmasked-fragment-spreads.graphql");
    let expected = include_str!("generate_flow/fixtures/unmasked-fragment-spreads.expected");
    test_fixture(
        transform_fixture,
        "unmasked-fragment-spreads.graphql",
        "generate_flow/fixtures/unmasked-fragment-spreads.expected",
        input,
        expected,
    );
}
<commit_msg>Enable all generate_flow_test<commit_after>// @generated SignedSource<<9325e240ef2106433f6bf2dd5b7fff5f>>

mod generate_flow;

use generate_flow::transform_fixture;
use fixture_tests::test_fixture;

#[test]
fn conditional() {
    let input = include_str!("generate_flow/fixtures/conditional.graphql");
    let expected = include_str!("generate_flow/fixtures/conditional.expected");
    test_fixture(transform_fixture, "conditional.graphql", "generate_flow/fixtures/conditional.expected", input, expected);
}

#[test]
fn fragment_spread() {
    let input = include_str!("generate_flow/fixtures/fragment-spread.graphql");
    let expected = include_str!("generate_flow/fixtures/fragment-spread.expected");
    test_fixture(transform_fixture, "fragment-spread.graphql", "generate_flow/fixtures/fragment-spread.expected", input, expected);
}

#[test]
fn inline_fragment() {
    let input = include_str!("generate_flow/fixtures/inline-fragment.graphql");
    let expected = include_str!("generate_flow/fixtures/inline-fragment.expected");
    test_fixture(transform_fixture, "inline-fragment.graphql", "generate_flow/fixtures/inline-fragment.expected", input, expected);
}

#[test]
fn linked_field() {
    let input = include_str!("generate_flow/fixtures/linked-field.graphql");
    let expected = include_str!("generate_flow/fixtures/linked-field.expected");
    test_fixture(transform_fixture, "linked-field.graphql", "generate_flow/fixtures/linked-field.expected", input, expected);
}

#[test]
fn match_field() {
    let input = include_str!("generate_flow/fixtures/match-field.graphql");
    let expected = include_str!("generate_flow/fixtures/match-field.expected");
    test_fixture(transform_fixture, "match-field.graphql", "generate_flow/fixtures/match-field.expected", input, expected);
}

#[test]
fn match_field_in_query() {
    let input = include_str!("generate_flow/fixtures/match-field-in-query.graphql");
    let expected = include_str!("generate_flow/fixtures/match-field-in-query.expected");
    test_fixture(transform_fixture, "match-field-in-query.graphql", "generate_flow/fixtures/match-field-in-query.expected", input, expected);
}

#[test]
fn mutaion_with_client_extension() {
    let input = include_str!("generate_flow/fixtures/mutaion-with-client-extension.graphql");
    let expected = include_str!("generate_flow/fixtures/mutaion-with-client-extension.expected");
    test_fixture(transform_fixture, "mutaion-with-client-extension.graphql", "generate_flow/fixtures/mutaion-with-client-extension.expected", input, expected);
}

#[test]
fn mutaion_with_response_on_inline_fragments() {
    let input = include_str!("generate_flow/fixtures/mutaion-with-response-on-inline-fragments.graphql");
    let expected = include_str!("generate_flow/fixtures/mutaion-with-response-on-inline-fragments.expected");
    test_fixture(transform_fixture, "mutaion-with-response-on-inline-fragments.graphql", "generate_flow/fixtures/mutaion-with-response-on-inline-fragments.expected", input, expected);
}

#[test]
fn mutation() {
    let input = include_str!("generate_flow/fixtures/mutation.graphql");
    let expected = include_str!("generate_flow/fixtures/mutation.expected");
    test_fixture(transform_fixture, "mutation.graphql", "generate_flow/fixtures/mutation.expected", input, expected);
}

#[test]
fn mutation_input_has_array() {
    let input = include_str!("generate_flow/fixtures/mutation-input-has-array.graphql");
    let expected = include_str!("generate_flow/fixtures/mutation-input-has-array.expected");
    test_fixture(transform_fixture, "mutation-input-has-array.graphql", "generate_flow/fixtures/mutation-input-has-array.expected", input, expected);
}

#[test]
fn mutation_with_enums_on_fragment() {
    let input = include_str!("generate_flow/fixtures/mutation-with-enums-on-fragment.graphql");
    let expected = include_str!("generate_flow/fixtures/mutation-with-enums-on-fragment.expected");
    test_fixture(transform_fixture, "mutation-with-enums-on-fragment.graphql", "generate_flow/fixtures/mutation-with-enums-on-fragment.expected", input, expected);
}

#[test]
fn mutation_with_nested_fragments() {
    let input = include_str!("generate_flow/fixtures/mutation-with-nested-fragments.graphql");
    let expected = include_str!("generate_flow/fixtures/mutation-with-nested-fragments.expected");
    test_fixture(transform_fixture, "mutation-with-nested-fragments.graphql", "generate_flow/fixtures/mutation-with-nested-fragments.expected", input, expected);
}

#[test]
fn plural_fragment() {
    let input = include_str!("generate_flow/fixtures/plural-fragment.graphql");
    let expected = include_str!("generate_flow/fixtures/plural-fragment.expected");
    test_fixture(transform_fixture, "plural-fragment.graphql", "generate_flow/fixtures/plural-fragment.expected", input, expected);
}

#[test]
fn query_with_handles() {
    let input = include_str!("generate_flow/fixtures/query-with-handles.graphql");
    let expected = include_str!("generate_flow/fixtures/query-with-handles.expected");
    test_fixture(transform_fixture, "query-with-handles.graphql", "generate_flow/fixtures/query-with-handles.expected", input, expected);
}

#[test]
fn query_with_match_fields() {
    let input = include_str!("generate_flow/fixtures/query-with-match-fields.graphql");
    let expected = include_str!("generate_flow/fixtures/query-with-match-fields.expected");
    test_fixture(transform_fixture, "query-with-match-fields.graphql", "generate_flow/fixtures/query-with-match-fields.expected", input, expected);
}

#[test]
fn query_with_module_field() {
    let input = include_str!("generate_flow/fixtures/query-with-module-field.graphql");
    let expected = include_str!("generate_flow/fixtures/query-with-module-field.expected");
    test_fixture(transform_fixture, "query-with-module-field.graphql", "generate_flow/fixtures/query-with-module-field.expected", input, expected);
}

#[test]
fn query_with_multiple_match_fields() {
    let input = include_str!("generate_flow/fixtures/query-with-multiple-match-fields.graphql");
    let expected = include_str!("generate_flow/fixtures/query-with-multiple-match-fields.expected");
    test_fixture(transform_fixture, "query-with-multiple-match-fields.graphql", "generate_flow/fixtures/query-with-multiple-match-fields.expected", input, expected);
}

#[test]
fn query_with_raw_response_on_conditional() {
    let input = include_str!("generate_flow/fixtures/query-with-raw-response-on-conditional.graphql");
    let expected = include_str!("generate_flow/fixtures/query-with-raw-response-on-conditional.expected");
    test_fixture(transform_fixture, "query-with-raw-response-on-conditional.graphql", "generate_flow/fixtures/query-with-raw-response-on-conditional.expected", input, expected);
}

#[test]
fn query_with_raw_response_on_literal_conditional() {
    let input = include_str!("generate_flow/fixtures/query-with-raw-response-on-literal-conditional.graphql");
    let expected = include_str!("generate_flow/fixtures/query-with-raw-response-on-literal-conditional.expected");
    test_fixture(transform_fixture, "query-with-raw-response-on-literal-conditional.graphql", "generate_flow/fixtures/query-with-raw-response-on-literal-conditional.expected", input, expected);
}

#[test]
fn query_with_stream() {
    let input = include_str!("generate_flow/fixtures/query-with-stream.graphql");
    let expected = include_str!("generate_flow/fixtures/query-with-stream.expected");
    test_fixture(transform_fixture, "query-with-stream.graphql", "generate_flow/fixtures/query-with-stream.expected", input, expected);
}

#[test]
fn query_with_stream_connection() {
    let input = include_str!("generate_flow/fixtures/query-with-stream-connection.graphql");
    let expected = include_str!("generate_flow/fixtures/query-with-stream-connection.expected");
    test_fixture(transform_fixture, "query-with-stream-connection.graphql", "generate_flow/fixtures/query-with-stream-connection.expected", input, expected);
}

#[test]
fn recursive_fragments() {
    let input = include_str!("generate_flow/fixtures/recursive-fragments.graphql");
    let expected = include_str!("generate_flow/fixtures/recursive-fragments.expected");
    test_fixture(transform_fixture, "recursive-fragments.graphql", "generate_flow/fixtures/recursive-fragments.expected", input, expected);
}

#[test]
fn refetchable() {
    let input = include_str!("generate_flow/fixtures/refetchable.graphql");
    let expected = include_str!("generate_flow/fixtures/refetchable.expected");
    test_fixture(transform_fixture, "refetchable.graphql", "generate_flow/fixtures/refetchable.expected", input, expected);
}

#[test]
fn refetchable_fragment() {
    let input = include_str!("generate_flow/fixtures/refetchable-fragment.graphql");
    let expected = include_str!("generate_flow/fixtures/refetchable-fragment.expected");
    test_fixture(transform_fixture, "refetchable-fragment.graphql", "generate_flow/fixtures/refetchable-fragment.expected", input, expected);
}

#[test]
fn relay_client_id_field() {
    let input = include_str!("generate_flow/fixtures/relay-client-id-field.graphql");
    let expected = include_str!("generate_flow/fixtures/relay-client-id-field.expected");
    test_fixture(transform_fixture, "relay-client-id-field.graphql", "generate_flow/fixtures/relay-client-id-field.expected", input, expected);
}

#[test]
fn roots() {
    let input = include_str!("generate_flow/fixtures/roots.graphql");
    let expected = include_str!("generate_flow/fixtures/roots.expected");
    test_fixture(transform_fixture, "roots.graphql", "generate_flow/fixtures/roots.expected", input, expected);
}

#[test]
fn scalar_field() {
    let input = include_str!("generate_flow/fixtures/scalar-field.graphql");
    let expected = include_str!("generate_flow/fixtures/scalar-field.expected");
    test_fixture(transform_fixture, "scalar-field.graphql", "generate_flow/fixtures/scalar-field.expected", input, expected);
}

#[test]
fn simple() {
    let input = include_str!("generate_flow/fixtures/simple.graphql");
    let expected = include_str!("generate_flow/fixtures/simple.expected");
    test_fixture(transform_fixture, "simple.graphql", "generate_flow/fixtures/simple.expected", input, expected);
}

#[test]
fn typename_inside_with_overlapping_fields() {
    let input = include_str!("generate_flow/fixtures/typename-inside-with-overlapping-fields.graphql");
    let expected = include_str!("generate_flow/fixtures/typename-inside-with-overlapping-fields.expected");
    test_fixture(transform_fixture, "typename-inside-with-overlapping-fields.graphql", "generate_flow/fixtures/typename-inside-with-overlapping-fields.expected", input, expected);
}

#[test]
fn typename_on_union() {
    let input = include_str!("generate_flow/fixtures/typename-on-union.graphql");
    let expected = include_str!("generate_flow/fixtures/typename-on-union.expected");
    test_fixture(transform_fixture, "typename-on-union.graphql", "generate_flow/fixtures/typename-on-union.expected", input, expected);
}

#[test]
fn unmasked_fragment_spreads() {
    let input = include_str!("generate_flow/fixtures/unmasked-fragment-spreads.graphql");
    let expected = include_str!("generate_flow/fixtures/unmasked-fragment-spreads.expected");
    test_fixture(transform_fixture, "unmasked-fragment-spreads.graphql", "generate_flow/fixtures/unmasked-fragment-spreads.expected", input, expected);
}
<|endoftext|>


<commit_before>extern crate s3;

use std::env;
use std::str;

use s3::bucket::Bucket;
use s3::credentials::Credentials;

const BUCKET: &'static str = "example-bucket";
const REGION: &'static str = "us-east-1";
const MESSAGE: &'static str = "I want to go to S3";

fn load_credentials() -> Credentials {
    let aws_access = env::var("AWS_KEY_ID").expect("Must specify AWS_ACCESS_KEY_ID");
    let aws_secret = env::var("AWS_SECRET_KEY").expect("Must specify AWS_SECRET_ACCESS_KEY");
    Credentials::new(&aws_access, &aws_secret, None)
}

pub fn main() {
    // Create Bucket in REGION for BUCKET
    let credentials = load_credentials();
    let region = REGION.parse().unwrap();
    let bucket = Bucket::new(BUCKET, region, credentials);

    // List out contents of directory
    let results = bucket.list("", None).unwrap();
    for (list, code) in results {
        assert_eq!(200, code);
        println!("{:?}", list.contents.len());
    }

    // Make sure that our "test_file" doesn't exist, delete it if it does. Note
    // that the s3 library returns the HTTP code even if it indicates a failure
    // (i.e. 404) since we can't predict desired usage. For example, you may
    // expect a 404 to make sure a file doesn't exist.
    // let (_, code) = bucket.delete("test_file").unwrap();
    // assert_eq!(204, code);

    // // Put a "test_file" with the contents of MESSAGE at the root of the
    // // bucket.
    let (_, code) = bucket.put("test_file", MESSAGE.as_bytes(), "text/plain").unwrap();
    assert_eq!(200, code);

    // // Get the "test_file" contents and make sure that the returned message
    // // matches what we sent.
    let (data, code) = bucket.get("test_file").unwrap();
    let string = str::from_utf8(&data).unwrap();
    assert_eq!(200, code);
    assert_eq!(MESSAGE, string);
}
<commit_msg>Uncomment 204<commit_after>extern crate s3;

use std::env;
use std::str;

use s3::bucket::Bucket;
use s3::credentials::Credentials;

const BUCKET: &'static str = "example-bucket";
const REGION: &'static str = "us-east-1";
const MESSAGE: &'static str = "I want to go to S3";

fn load_credentials() -> Credentials {
    let aws_access = env::var("AWS_KEY_ID").expect("Must specify AWS_ACCESS_KEY_ID");
    let aws_secret = env::var("AWS_SECRET_KEY").expect("Must specify AWS_SECRET_ACCESS_KEY");
    Credentials::new(&aws_access, &aws_secret, None)
}

pub fn main() {
    // Create Bucket in REGION for BUCKET
    let credentials = load_credentials();
    let region = REGION.parse().unwrap();
    let bucket = Bucket::new(BUCKET, region, credentials);

    // List out contents of directory
    let results = bucket.list("", None).unwrap();
    for (list, code) in results {
        assert_eq!(200, code);
        println!("{:?}", list.contents.len());
    }

    // Make sure that our "test_file" doesn't exist, delete it if it does. Note
    // that the s3 library returns the HTTP code even if it indicates a failure
    // (i.e. 404) since we can't predict desired usage. For example, you may
    // expect a 404 to make sure a file doesn't exist.
    let (_, code) = bucket.delete("test_file").unwrap();
    assert_eq!(204, code);

    // // Put a "test_file" with the contents of MESSAGE at the root of the
    // // bucket.
    let (_, code) = bucket.put("test_file", MESSAGE.as_bytes(), "text/plain").unwrap();
    assert_eq!(200, code);

    // // Get the "test_file" contents and make sure that the returned message
    // // matches what we sent.
    let (data, code) = bucket.get("test_file").unwrap();
    let string = str::from_utf8(&data).unwrap();
    assert_eq!(200, code);
    assert_eq!(MESSAGE, string);
}
<|endoftext|>


<commit_before>
extern crate amqp_client0 as amqp;

use amqp::ConfigBuilder;

fn main() {
    let config = ConfigBuilder::without_tls()
        .plain_auth("", "")
        .channel_max(10)
        .virtual_host("/");

    print!("{:#?}", config);
}<commit_msg>[client] Update connect example to test lifetime of start<commit_after>
extern crate amqp_client0 as amqp;

use amqp::ConfigBuilder;

fn main() {
    let mut session = ConfigBuilder::without_tls()
        .port(5672)
        .plain_auth("", "")
        .channel_max(10)
        .virtual_host("/")
        .into_blocking();

    print!("{:#?}", session);
    {
        let start1 = session.connect().unwrap();
        print!("Start1: {:?}", start1);
    }

    let start2 = session.connect().unwrap();
    print!("Start2: {:?}", start2);
}<|endoftext|>