<commit_before>use bytes::{BufMut, Bytes};
use chrono::{TimeZone, UTC};
use error::{Error, HyperError};
use futures::{Async, Future, Poll, Stream};
use futures::stream::Fuse;
use serde::de::{Deserialize, Deserializer, Error as SerdeError};
use std::time::Duration;
use tokio_core::reactor::{Handle, Timeout};
use types::DateTime;

macro_rules! string_enums {
    (
        $(
            $(#[$attr:meta])*
            pub enum $E:ident {
                $(
                    $(#[$v_attr:meta])*
                    :$V:ident($by:expr) // The leading (ugly) colon is to suppress local ambiguity error.
                ),*;
                $(#[$u_attr:meta])*
                :$U:ident(_),
            }
        )*
    ) => {
        $(
            $(#[$attr])*
            pub enum $E {
                $(
                    $(#[$v_attr])*
                    $V,
                )*
                $(#[$u_attr])*
                $U(String),
            }

            impl<'x> ::serde::Deserialize<'x> for $E {
                fn deserialize<D: ::serde::Deserializer<'x>>(d: D) -> ::std::result::Result<Self, D::Error> {
                    struct V;

                    impl<'x> ::serde::de::Visitor<'x> for V {
                        type Value = $E;

                        fn visit_str<E>(self, s: &str) -> ::std::result::Result<$E, E> {
                            match s {
                                $($by => Ok($E::$V),)*
                                _ => Ok($E::$U(s.to_owned())),
                            }
                        }

                        fn visit_string<E>(self, s: String) -> ::std::result::Result<$E, E> {
                            match s.as_str() {
                                $($by => Ok($E::$V),)*
                                _ => Ok($E::$U(s)),
                            }
                        }

                        fn expecting(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
                            write!(f, "a string")
                        }
                    }

                    d.deserialize_string(V)
                }
            }

            impl ::std::convert::AsRef<str> for $E {
                fn as_ref(&self) -> &str {
                    match *self {
                        $($E::$V => $by,)*
                        $E::$U(ref s) => s,
                    }
                }
            }

            impl ::std::cmp::PartialEq for $E {
                fn eq(&self, other: &$E) -> bool {
                    match *self {
                        $($E::$V => match *other {
                            $E::$V => true,
                            $E::$U(ref s) if $by == s => true,
                            _ => false,
                        },)*
                        $E::$U(ref s) => match *other {
                            $($E::$V => $by == s,)*
                            $E::$U(ref t) => s == t,
                        },
                    }
                }
            }

            impl ::std::hash::Hash for $E {
                fn hash<H: ::std::hash::Hasher>(&self, state: &mut H) {
                    match *self {
                        $($E::$V => $by.hash(state),)*
                        $E::$U(ref s) => s.hash(state),
                    }
                }
            }

            impl ::std::cmp::Eq for $E {}
        )*
    }
}

pub struct BaseTimeout {
    dur: Duration,
    handle: Handle,
    timer: Timeout,
}

/// Adds a timeout to a `Stream`. Inspired by `tokio_timer::TimeoutStream`.
pub struct TimeoutStream<S> {
    stream: S,
    inner: Option<BaseTimeout>,
}

/// A stream over the lines (delimited by CRLF) of a `Body`.
pub struct Lines<B> where B: Stream {
    inner: Fuse<B>,
    buf: Bytes,
}

impl BaseTimeout {
    pub fn new(dur: Duration, handle: Handle) -> Option<Self> {
        Timeout::new(dur, &handle).ok().map(|timer| {
            BaseTimeout {
                dur: dur,
                handle: handle,
                timer: timer,
            }
        })
    }

    pub fn for_stream<S>(self, stream: S) -> TimeoutStream<S> {
        TimeoutStream {
            stream: stream,
            inner: Timeout::new(self.dur, &self.handle).ok().map(move |timer| {
                BaseTimeout {
                    timer: timer,
                    ..self
                }
            }),
        }
    }

    pub fn timer_mut(&mut self) -> &mut Timeout {
        &mut self.timer
    }
}

impl<S> TimeoutStream<S> {
    pub fn never(stream: S) -> Self {
        TimeoutStream {
            stream: stream,
            inner: None,
        }
    }
}

impl<S> Stream for TimeoutStream<S> where S: Stream<Error=HyperError> {
    type Item = S::Item;
    type Error = Error;

    fn poll(&mut self) -> Poll<Option<S::Item>, Error> {
        let ret;

        if let Some(ref mut inner) = self.inner {
            match self.stream.poll() {
                Ok(Async::Ready(Some(v))) => {
                    ret = Ok(Some(v).into());
                    if let Ok(timer) = Timeout::new(inner.dur, &inner.handle) {
                        inner.timer = timer;
                        return ret;
                    }
                    // goto timeout_new_failed;
                },
                Ok(Async::NotReady) => match inner.timer.poll() {
                    Ok(Async::Ready(())) => return Err(Error::TimedOut),
                    Ok(Async::NotReady) => return Ok(Async::NotReady),
                    Err(_) => unreachable!(), // `Timeout` never fails.
                },
                v => return v.map_err(Error::Hyper),
            }
        } else {
            return self.stream.poll().map_err(Error::Hyper);
        }

        // timeout_new_failed:
        self.inner = None;
        ret
    }
}

impl<B> Lines<B> where B: Stream {
    pub fn new(body: B) -> Self {
        Lines {
            inner: body.fuse(),
            buf: Bytes::new(),
        }
    }
}

impl<B> Stream for Lines<B> where B: Stream, B::Item: Into<Bytes> {
    type Item = Bytes;
    type Error = B::Error;

    fn poll(&mut self) -> Poll<Option<Bytes>, B::Error> {
        use std::mem;

        macro_rules! try_ready_some {
            ($poll:expr) => {{
                let poll = $poll;
                match try_ready!(poll) {
                    Some(v) => v,
                    None    => return Ok(None.into()),
                }
            }};
        }

        if self.buf.is_empty() {
            self.buf = try_ready_some!(self.inner.poll()).into();
        }

        fn remove_next_line(buf: &mut Bytes) -> Option<Bytes> {
            (buf as &Bytes).into_iter().enumerate()
                .find(|&(i, b)| b'\r' == b && Some(&b'\n') == buf.get(i + 1))
                .map(|(i, _)| buf.split_off(i + 2))
        }

        if let Some(buf) = remove_next_line(&mut self.buf) {
            let ret = mem::replace(&mut self.buf, buf);
            return Ok(Some(ret).into());
        }

        if self.buf.is_empty() {
            self.buf = try_ready_some!(self.inner.poll()).into();
        }

        // Extend the buffer until a newline is found:
        loop {
            match try_ready!(self.inner.poll()) {
                Some(chunk) => {
                    let mut chunk = chunk.into();
                    if &b'\r' == self.buf.last().unwrap() && Some(&b'\n') == chunk.first() {
                        let i = self.buf.len() + 1;
                        extend_from_bytes(&mut self.buf, chunk);
                        let next = self.buf.split_off(i);
                        let ret = mem::replace(&mut self.buf, next);
                        return Ok(Some(ret).into());
                    } else if let Some(next) = remove_next_line(&mut chunk) {
                        extend_from_bytes(&mut self.buf, chunk);
                        let ret = mem::replace(&mut self.buf, next);
                        return Ok(Some(ret).into());
                    } else {
                        extend_from_bytes(&mut self.buf, chunk);
                    }
                },
                None => {
                    let ret = mem::replace(&mut self.buf, Bytes::new());
                    return Ok(Some(ret).into());
                },
            };
        }
    }
}

pub fn parse_datetime(s: &str) -> ::chrono::format::ParseResult<DateTime> {
    UTC.datetime_from_str(s, "%a %b %e %H:%M:%S %z %Y")
}

pub fn deserialize_datetime<'x, D: Deserializer<'x>>(d: D) -> Result<DateTime, D::Error> {
    parse_datetime(&String::deserialize(d)?).map_err(|e| D::Error::custom(e.to_string()))
}

// XXX: possibly can be replaced with carllerche/bytes#85
fn extend_from_bytes(dst: &mut Bytes, src: Bytes) {
    use std::mem;

    if src.is_empty() { return; }

    // Temporary swap just to take the ownership
    let buf = mem::replace(dst, src);

    *dst = match buf.try_mut() {
        Ok(mut buf) => {
            buf.reserve(dst.len());
            buf.put_slice(dst);
            buf.freeze()
        },
        Err(buf) => {
            let mut vec = Vec::with_capacity(buf.len() + dst.len());
            vec.extend_from_slice(&buf);
            vec.extend_from_slice(dst);
            vec.into()
        },
    };
}

#[cfg(test)]
mod test {
    use bytes::Bytes;
    use futures::stream;
    use super::*;

    #[test]
    fn lines() {
        let lines = vec![
            "abc\r\n",
            "d\r\n",
            "efg\r\n",
            "hijk\r\n",
            "\r\n",
            "lmn\r\n",
            "opq\rrs\r\n",
            "\n\rtuv\r\r\n",
            "wxyz",
        ];
        let body = vec![
            Bytes::from(b"abc\r\n".to_vec()),
            Bytes::from(b"d\r\nefg\r\n".to_vec()),
            Bytes::from(b"hi".to_vec()),
            Bytes::from(b"jk".to_vec()),
            Bytes::from(b"\r\n".to_vec()),
            Bytes::from(b"\r\n".to_vec()),
            Bytes::from(b"lmn\r\nop".to_vec()),
            Bytes::from(b"q\rrs\r".to_vec()),
            Bytes::from(b"\n\n\rtuv\r\r\n".to_vec()),
            Bytes::from(b"wxyz".to_vec()),
        ];

        let mut iter1 = lines.iter().cloned();
        let mut iter2 = Lines::new(stream::iter::<_,_,()>(body.into_iter().map(Ok)))
            .wait().map(|s| String::from_utf8(s.unwrap().to_vec()).unwrap());

        for _ in 0..(lines.len()+1) {
            assert_eq!(
                iter1.next(),
                iter2.next().as_ref().map(String::as_str)
            );
        }
    }
}
<commit_msg>Minor refactoring<commit_after>use bytes::{BufMut, Bytes};
use chrono::{TimeZone, UTC};
use error::{Error, HyperError};
use futures::{Async, Future, Poll, Stream};
use futures::stream::Fuse;
use serde::de::{Deserialize, Deserializer, Error as SerdeError};
use std::time::Duration;
use tokio_core::reactor::{Handle, Timeout};
use types::DateTime;

macro_rules! string_enums {
    (
        $(
            $(#[$attr:meta])*
            pub enum $E:ident {
                $(
                    $(#[$v_attr:meta])*
                    :$V:ident($by:expr) // The leading (ugly) colon is to suppress local ambiguity error.
                ),*;
                $(#[$u_attr:meta])*
                :$U:ident(_),
            }
        )*
    ) => {
        $(
            $(#[$attr])*
            pub enum $E {
                $(
                    $(#[$v_attr])*
                    $V,
                )*
                $(#[$u_attr])*
                $U(String),
            }

            impl<'x> ::serde::Deserialize<'x> for $E {
                fn deserialize<D: ::serde::Deserializer<'x>>(d: D) -> ::std::result::Result<Self, D::Error> {
                    struct V;

                    impl<'x> ::serde::de::Visitor<'x> for V {
                        type Value = $E;

                        fn visit_str<E>(self, s: &str) -> ::std::result::Result<$E, E> {
                            match s {
                                $($by => Ok($E::$V),)*
                                _ => Ok($E::$U(s.to_owned())),
                            }
                        }

                        fn visit_string<E>(self, s: String) -> ::std::result::Result<$E, E> {
                            match s.as_str() {
                                $($by => Ok($E::$V),)*
                                _ => Ok($E::$U(s)),
                            }
                        }

                        fn expecting(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
                            write!(f, "a string")
                        }
                    }

                    d.deserialize_string(V)
                }
            }

            impl ::std::convert::AsRef<str> for $E {
                fn as_ref(&self) -> &str {
                    match *self {
                        $($E::$V => $by,)*
                        $E::$U(ref s) => s,
                    }
                }
            }

            impl ::std::cmp::PartialEq for $E {
                fn eq(&self, other: &$E) -> bool {
                    match *self {
                        $($E::$V => match *other {
                            $E::$V => true,
                            $E::$U(ref s) if $by == s => true,
                            _ => false,
                        },)*
                        $E::$U(ref s) => match *other {
                            $($E::$V => $by == s,)*
                            $E::$U(ref t) => s == t,
                        },
                    }
                }
            }

            impl ::std::hash::Hash for $E {
                fn hash<H: ::std::hash::Hasher>(&self, state: &mut H) {
                    match *self {
                        $($E::$V => $by.hash(state),)*
                        $E::$U(ref s) => s.hash(state),
                    }
                }
            }

            impl ::std::cmp::Eq for $E {}
        )*
    }
}

pub struct BaseTimeout {
    dur: Duration,
    handle: Handle,
    timer: Timeout,
}

/// Adds a timeout to a `Stream`. Inspired by `tokio_timer::TimeoutStream`.
pub struct TimeoutStream<S> {
    stream: S,
    inner: Option<BaseTimeout>,
}

/// A stream over the lines (delimited by CRLF) of a `Body`.
pub struct Lines<B> where B: Stream {
    inner: Fuse<B>,
    buf: Bytes,
}

impl BaseTimeout {
    pub fn new(dur: Duration, handle: Handle) -> Option<Self> {
        Timeout::new(dur, &handle).ok().map(|timer| {
            BaseTimeout {
                dur: dur,
                handle: handle,
                timer: timer,
            }
        })
    }

    pub fn for_stream<S>(self, stream: S) -> TimeoutStream<S> {
        TimeoutStream {
            stream: stream,
            inner: Timeout::new(self.dur, &self.handle).ok().map(move |timer| {
                BaseTimeout {
                    timer: timer,
                    ..self
                }
            }),
        }
    }

    pub fn timer_mut(&mut self) -> &mut Timeout {
        &mut self.timer
    }
}

impl<S> TimeoutStream<S> {
    pub fn never(stream: S) -> Self {
        TimeoutStream {
            stream: stream,
            inner: None,
        }
    }
}

impl<S> Stream for TimeoutStream<S> where S: Stream<Error=HyperError> {
    type Item = S::Item;
    type Error = Error;

    fn poll(&mut self) -> Poll<Option<S::Item>, Error> {
        let ret;

        if let Some(ref mut inner) = self.inner {
            match self.stream.poll() {
                Ok(Async::Ready(Some(v))) => {
                    ret = Ok(Some(v).into());
                    if let Ok(timer) = Timeout::new(inner.dur, &inner.handle) {
                        inner.timer = timer;
                        return ret;
                    }
                    // goto timeout_new_failed;
                },
                Ok(Async::NotReady) => match inner.timer.poll() {
                    Ok(Async::Ready(())) => return Err(Error::TimedOut),
                    Ok(Async::NotReady) => return Ok(Async::NotReady),
                    Err(_) => unreachable!(), // `Timeout` never fails.
                },
                v => return v.map_err(Error::Hyper),
            }
        } else {
            return self.stream.poll().map_err(Error::Hyper);
        }

        // timeout_new_failed:
        self.inner = None;
        ret
    }
}

impl<B> Lines<B> where B: Stream {
    pub fn new(body: B) -> Self {
        Lines {
            inner: body.fuse(),
            buf: Bytes::new(),
        }
    }
}

impl<B> Stream for Lines<B> where B: Stream, B::Item: Into<Bytes> {
    type Item = Bytes;
    type Error = B::Error;

    fn poll(&mut self) -> Poll<Option<Bytes>, B::Error> {
        use std::mem;

        macro_rules! try_ready_some {
            ($poll:expr) => {{
                let poll = $poll;
                match try_ready!(poll) {
                    Some(v) => v,
                    None    => return Ok(None.into()),
                }
            }};
        }

        if self.buf.is_empty() {
            self.buf = try_ready_some!(self.inner.poll()).into();
        }

        fn remove_first_line(buf: &mut Bytes) -> Option<Bytes> {
            (buf as &Bytes).into_iter().enumerate()
                .find(|&(i, b)| b'\r' == b && Some(&b'\n') == buf.get(i + 1))
                .map(|(i, _)| buf.split_to(i + 2))
        }

        if let Some(buf) = remove_first_line(&mut self.buf) {
            return Ok(Some(buf).into());
        }

        if self.buf.is_empty() {
            self.buf = try_ready_some!(self.inner.poll()).into();
        }

        // Extend the buffer until a newline is found:
        loop {
            match try_ready!(self.inner.poll()) {
                Some(chunk) => {
                    let mut chunk = chunk.into();
                    if &b'\r' == self.buf.last().unwrap() && Some(&b'\n') == chunk.first() {
                        let i = self.buf.len() + 1;
                        extend_from_bytes(&mut self.buf, chunk);
                        let next = self.buf.split_off(i);
                        let ret = mem::replace(&mut self.buf, next);
                        return Ok(Some(ret).into());
                    } else if let Some(tail) = remove_first_line(&mut chunk) {
                        extend_from_bytes(&mut self.buf, tail);
                        let ret = mem::replace(&mut self.buf, chunk);
                        return Ok(Some(ret).into());
                    } else {
                        extend_from_bytes(&mut self.buf, chunk);
                    }
                },
                None => {
                    let ret = mem::replace(&mut self.buf, Bytes::new());
                    return Ok(Some(ret).into());
                },
            };
        }
    }
}

pub fn parse_datetime(s: &str) -> ::chrono::format::ParseResult<DateTime> {
    UTC.datetime_from_str(s, "%a %b %e %H:%M:%S %z %Y")
}

pub fn deserialize_datetime<'x, D: Deserializer<'x>>(d: D) -> Result<DateTime, D::Error> {
    parse_datetime(&String::deserialize(d)?).map_err(|e| D::Error::custom(e.to_string()))
}

// XXX: possibly can be replaced with carllerche/bytes#85
fn extend_from_bytes(dst: &mut Bytes, src: Bytes) {
    use std::mem;

    if src.is_empty() { return; }

    // Temporary swap just to take the ownership
    let buf = mem::replace(dst, src);

    *dst = match buf.try_mut() {
        Ok(mut buf) => {
            buf.reserve(dst.len());
            buf.put_slice(dst);
            buf.freeze()
        },
        Err(buf) => {
            let mut vec = Vec::with_capacity(buf.len() + dst.len());
            vec.extend_from_slice(&buf);
            vec.extend_from_slice(dst);
            vec.into()
        },
    };
}

#[cfg(test)]
mod test {
    use bytes::Bytes;
    use futures::stream;
    use super::*;

    #[test]
    fn lines() {
        let lines = vec![
            "abc\r\n",
            "d\r\n",
            "efg\r\n",
            "hijk\r\n",
            "\r\n",
            "lmn\r\n",
            "opq\rrs\r\n",
            "\n\rtuv\r\r\n",
            "wxyz",
        ];
        let body = vec![
            Bytes::from(b"abc\r\n".to_vec()),
            Bytes::from(b"d\r\nefg\r\n".to_vec()),
            Bytes::from(b"hi".to_vec()),
            Bytes::from(b"jk".to_vec()),
            Bytes::from(b"\r\n".to_vec()),
            Bytes::from(b"\r\n".to_vec()),
            Bytes::from(b"lmn\r\nop".to_vec()),
            Bytes::from(b"q\rrs\r".to_vec()),
            Bytes::from(b"\n\n\rtuv\r\r\n".to_vec()),
            Bytes::from(b"wxyz".to_vec()),
        ];

        let mut iter1 = lines.iter().cloned();
        let mut iter2 = Lines::new(stream::iter::<_,_,()>(body.into_iter().map(Ok)))
            .wait().map(|s| String::from_utf8(s.unwrap().to_vec()).unwrap());

        for _ in 0..(lines.len()+1) {
            assert_eq!(
                iter1.next(),
                iter2.next().as_ref().map(String::as_str)
            );
        }
    }
}
<|endoftext|>


<commit_before>extern crate clipboard_win;

use clipboard_win::{set_clipboard, ClipboardManager};
use std::process::Command;

///Trimm all lines in string.
///Return None if string is not changed.
fn trim_lines(text: &String) -> Option<String> {
let orig_len = text.len();
let last_char = text.chars().last().unwrap();
let mut text = text.lines().fold(String::new(), |acc, line| acc + line.trim() + "\n");

if last_char != '\n' {
text.pop();
}

if orig_len == text.len() { return None; }
Some(text)
}

fn handler_clip_text(text: &String) {
if text.len() == 0 { return; }

if text.starts_with("wget") {
println!("wget download:");
let status = Command::new("powershell").arg("-Command").arg(format!("cd D:/Downloads; {}", &text)).status().unwrap();
if !status.success() {
println!("Failed to run wget.");
}
return;
}

println!("Clipboard content:\n{}", &text);
if let Some(trim_text) = trim_lines(&text) {
if set_clipboard(&trim_text).is_err() {
println!("Failed to update clipboard");
}
}
}

fn main() {
println!("Clipboard monitor");
ClipboardManager::new().ok_callback(handler_clip_text).run();
}
<commit_msg>Clipboard_monitor: trim right only<commit_after>extern crate clipboard_win;

use clipboard_win::{set_clipboard, ClipboardManager};
use std::process::Command;

///Trimm all lines in string.
///Return None if string is not changed.
fn trim_lines(text: &String) -> Option<String> {
    let orig_len = text.len();
    let last_char = text.chars().last().unwrap();
    let mut text = text.lines().fold(String::new(), |acc, line| acc + line.trim_right() + "\n");

    if last_char != '\n' {
        text.pop();
    }

    if orig_len == text.len() { return None; }
    Some(text)
}

fn handler_clip_text(text: &String) {
    if text.len() == 0 { return; }

    if text.starts_with("wget") {
        println!("wget download:");
        let status = Command::new("powershell").arg("-Command").arg(format!("cd D:/Downloads; {}", &text)).status().unwrap();
        if !status.success() {
            println!("Failed to run wget.");
        }
        return;
    }

    println!("Clipboard content:\n{}", &text);
    if let Some(trim_text) = trim_lines(&text) {
        if set_clipboard(&trim_text).is_err() {
            println!("Failed to update clipboard");
        }
    }
}

fn main() {
    println!("Clipboard monitor");
    ClipboardManager::new().ok_callback(handler_clip_text).run();
}
<|endoftext|>


<commit_before>use crate::abort_on_panic;
use libnewsboat::fslock::FsLock;
use std::ffi::CStr;

#[no_mangle]
pub extern "C" fn rs_fslock_new() -> *mut FsLock {
    Box::into_raw(Box::new(FsLock::default()))
}

#[no_mangle]
pub extern "C" fn rs_fslock_free(ptr: *mut FsLock) {
    abort_on_panic(|| {
        if ptr.is_null() {
            return;
        }
        unsafe { Box::from_raw(ptr) };
    })
}

#[no_mangle]
pub extern "C" fn rs_fslock_try_lock(
    ptr: *mut FsLock,
    new_lock_filepath: *const libc::c_char,
    pid: *mut libc::pid_t,
) -> bool {
    abort_on_panic(|| {
        let fslock = unsafe {
            assert!(!ptr.is_null());
            &mut *ptr
        };
        let new_lock_filepath = unsafe {
            assert!(!new_lock_filepath.is_null());
            CStr::from_ptr(new_lock_filepath)
        };
        let pid = unsafe { &mut *pid };
        let new_lock_filepath = new_lock_filepath.to_string_lossy().into_owned();
        fslock.try_lock(new_lock_filepath.as_ref(), pid)
    })
}
<commit_msg>fixup! Port FsLock to Rust<commit_after>use crate::abort_on_panic;
use libnewsboat::fslock::FsLock;
use std::ffi::CStr;

#[no_mangle]
pub extern "C" fn rs_fslock_new() -> *mut FsLock {
    Box::into_raw(Box::new(FsLock::default()))
}

#[no_mangle]
pub unsafe extern "C" fn rs_fslock_free(ptr: *mut FsLock) {
    abort_on_panic(|| {
        if ptr.is_null() {
            return;
        }
        Box::from_raw(ptr);
    })
}

#[no_mangle]
pub unsafe extern "C" fn rs_fslock_try_lock(
    ptr: *mut FsLock,
    new_lock_filepath: *const libc::c_char,
    pid: *mut libc::pid_t,
) -> bool {
    abort_on_panic(|| {
        let fslock = {
            assert!(!ptr.is_null());
            &mut *ptr
        };
        let new_lock_filepath = {
            assert!(!new_lock_filepath.is_null());
            CStr::from_ptr(new_lock_filepath)
        };
        let pid = { &mut *pid };
        let new_lock_filepath = new_lock_filepath.to_string_lossy().into_owned();
        fslock.try_lock(new_lock_filepath.as_ref(), pid)
    })
}
<|endoftext|>


<commit_before>use std::ops::{Index, IndexMut};
use std::fmt::Debug;

use num::{zero, Zero};

/// The logarithm (in base-2) of the block size. This ensures that the block size is a power of 2.
/// In this case, 3 means a block size of 8.
const LOG_BLOCK_SIZE: usize = 3;
const BLOCK_SIZE: usize = 1 << LOG_BLOCK_SIZE;

#[derive(Debug)]
pub struct BlockedArray<T> {
    u_res: usize,
    v_res: usize,
    u_blocks: usize,
    log_block_size: usize,
    block_size: usize,
    data: Vec<T>,
}

impl<T> BlockedArray<T>
where
    T: Copy + Zero + Debug,
{
    pub fn new(u_res: usize, v_res: usize) -> BlockedArray<T> {
        let data = vec![zero(); round_up(u_res) * round_up(v_res)];

        BlockedArray {
            u_res: u_res,
            v_res: v_res,
            u_blocks: round_up(u_res) >> LOG_BLOCK_SIZE,
            log_block_size: LOG_BLOCK_SIZE,
            block_size: BLOCK_SIZE,
            data: data,
        }
    }

    pub fn new_from(u_res: usize, v_res: usize, d: &[T]) -> BlockedArray<T> {
        let mut ba = Self::new(u_res, v_res);

        for u in 0..u_res {
            for v in 0..v_res {
                ba[(u, v)] = d[v * u_res + u]
            }
        }

        ba
    }

    pub fn u_size(&self) -> usize {
        self.u_res
    }

    pub fn v_size(&self) -> usize {
        self.v_res
    }

    pub fn block_size(&self) -> usize {
        self.block_size
    }

    pub fn block(&self, a: usize) -> usize {
        a >> self.log_block_size
    }

    pub fn offset(&self, a: usize) -> usize {
        a & (self.block_size() - 1)
    }
}

fn round_up(x: usize) -> usize {
    (x + BLOCK_SIZE - 1) & !(BLOCK_SIZE - 1)
}

impl<T> Index<(usize, usize)> for BlockedArray<T>
where
    T: Copy,
    T: Zero,
    T: Debug,
{
    type Output = T;

    fn index(&self, i: (usize, usize)) -> &T {
        let (u, v) = i;
        let bu = self.block(u);
        let bv = self.block(v);
        let ou = self.offset(u);
        let ov = self.offset(v);
        let offset = self.block_size() * self.block_size() * (self.u_blocks * bv + bu)
            + self.block_size() * ov + ou;
        &self.data[offset]
    }
}

impl<T> IndexMut<(usize, usize)> for BlockedArray<T>
where
    T: Copy,
    T: Zero,
    T: Debug,
{
    fn index_mut(&mut self, i: (usize, usize)) -> &mut T {
        let (u, v) = i;
        let bu = self.block(u);
        let bv = self.block(v);
        let ou = self.offset(u);
        let ov = self.offset(v);
        let offset = self.block_size() * self.block_size() * (self.u_blocks * bv + bu)
            + self.block_size() * ov + ou;
        &mut self.data[offset]
    }
}
<commit_msg>Small cleanups<commit_after>use std::ops::{Index, IndexMut};
use std::fmt::Debug;

use num::{zero, Zero};

/// The logarithm (in base-2) of the block size. This ensures that the block size is a power of 2.
/// In this case, 3 means a block size of 8.
const LOG_BLOCK_SIZE: usize = 3;
const BLOCK_SIZE: usize = 1 << LOG_BLOCK_SIZE;

#[derive(Debug)]
pub struct BlockedArray<T> {
    u_res: usize,
    v_res: usize,
    u_blocks: usize,
    log_block_size: usize,
    block_size: usize,
    data: Vec<T>,
}

impl<T> BlockedArray<T>
where
    T: Copy + Zero + Debug,
{
    pub fn new(u_res: usize, v_res: usize) -> BlockedArray<T> {
        let data = vec![zero(); round_up(u_res) * round_up(v_res)];

        BlockedArray {
            u_res: u_res,
            v_res: v_res,
            u_blocks: round_up(u_res) >> LOG_BLOCK_SIZE,
            log_block_size: LOG_BLOCK_SIZE,
            block_size: BLOCK_SIZE,
            data: data,
        }
    }

    pub fn new_from(u_res: usize, v_res: usize, d: &[T]) -> BlockedArray<T> {
        let mut ba = Self::new(u_res, v_res);

        for v in 0..v_res {
            for u in 0..u_res {
                ba[(u, v)] = d[v * u_res + u]
            }
        }

        ba
    }

    pub fn u_size(&self) -> usize {
        self.u_res
    }

    pub fn v_size(&self) -> usize {
        self.v_res
    }

    pub fn block_size(&self) -> usize {
        self.block_size
    }

    pub fn block(&self, a: usize) -> usize {
        a >> self.log_block_size
    }

    pub fn offset(&self, a: usize) -> usize {
        a & (self.block_size() - 1)
    }
}

fn round_up(x: usize) -> usize {
    (x + BLOCK_SIZE - 1) & !(BLOCK_SIZE - 1)
}

impl<T> Index<(usize, usize)> for BlockedArray<T>
where
    T: Copy,
    T: Zero,
    T: Debug,
{
    type Output = T;

    fn index(&self, (u, v): (usize, usize)) -> &T {
        let bu = self.block(u);
        let bv = self.block(v);
        let ou = self.offset(u);
        let ov = self.offset(v);
        let offset = self.block_size() * self.block_size() * (self.u_blocks * bv + bu)
            + self.block_size() * ov + ou;
        &self.data[offset]
    }
}

impl<T> IndexMut<(usize, usize)> for BlockedArray<T>
where
    T: Copy,
    T: Zero,
    T: Debug,
{
    fn index_mut(&mut self, (u, v): (usize, usize)) -> &mut T {
        let bu = self.block(u);
        let bv = self.block(v);
        let ou = self.offset(u);
        let ov = self.offset(v);
        let offset = self.block_size() * self.block_size() * (self.u_blocks * bv + bu)
            + self.block_size() * ov + ou;
        &mut self.data[offset]
    }
}
<|endoftext|>


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

#[macro_use]
extern crate log;
extern crate chrono;
extern crate fern;

extern crate dirs;

extern crate xi_core_lib;
extern crate xi_rpc;

use std::io;
use std::fs;
use std::path::PathBuf;

use xi_core_lib::XiCore;
use xi_rpc::RpcLoop;

const XI_DIRECTORY: &'static str = "xi-core";
const XI_LOG_FILE: &'static str = "xi-core.log";

fn get_logging_directory() -> Option<PathBuf> {
    if let Some(mut log_dir) = dirs::data_local_dir() {
        log_dir.push(XI_DIRECTORY);
        Some(log_dir)
    } else {
        eprintln!("[WARNING] The dir library was not able to find a directory for this platform");
        None
    }
}

fn path_for_log_file<P: AsRef<str>>(filename: P) -> Option<PathBuf> {
    if let Some(mut logging_directory) = get_logging_directory() {
        // Create the logging directory
        match fs::create_dir_all(&logging_directory) {
            Ok(_) => (), Err(why) => eprintln!("[WARNING] {:?}", why)
        }
        logging_directory.push(filename.as_ref());
        Some(logging_directory)
    } else { None }
}

fn setup_logging() -> Result<(), fern::InitError> {
    let level_filter = match std::env::var("XI_LOG") {
        Ok(level) => match level.to_lowercase().as_ref() {
            "trace" => log::LevelFilter::Trace,
            "debug" => log::LevelFilter::Debug,
            _ => log::LevelFilter::Info,
        },
        // Default to info
        Err(_) => log::LevelFilter::Info,
    };

    let fern_dispatch = fern::Dispatch::new()
        .format(|out, message, record| {
            out.finish(format_args!(
                "{}[{}][{}] {}",
                chrono::Local::now().format("[%Y-%m-%d][%H:%M:%S]"),
                record.target(),
                record.level(),
                message,
            ))
        })
        .level(level_filter)
        .chain(io::stderr());

    if let Some(logging_file_path) = path_for_log_file(XI_LOG_FILE) {
        fern_dispatch
            .chain(fern::log_file(logging_file_path)?)
            .apply()?;
    } else {
        eprintln!("[WARNING] There was an issue getting the path for the log file, using stdout");
        fern_dispatch
            .chain(io::stdout())
            .apply()?;
    }
    info!("Logging with fern setup");
    Ok(())
}

fn main() {
    let mut state = XiCore::new();
    let stdin = io::stdin();
    let stdout = io::stdout();
    let mut rpc_looper = RpcLoop::new(stdout);

    if let Err(e) = setup_logging() {
        eprintln!("[ERROR] setup_logging returned error, logging disabled: {:?}", e);
    }

    match rpc_looper.mainloop(|| stdin.lock(), &mut state) {
        Ok(_) => (),
        Err(err) => error!("xi-core exited with error:\n{:?}", err),
    }
}
<commit_msg>Fixed formatting with `rustfmt`. Removed the stdio bit! But still starting fern with just stderr if the log file stuff fails.<commit_after>// Copyright 2016 The xi-editor Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#[macro_use]
extern crate log;
extern crate chrono;
extern crate fern;

extern crate dirs;

extern crate xi_core_lib;
extern crate xi_rpc;

use std::fs;
use std::io;
use std::path::PathBuf;

use xi_core_lib::XiCore;
use xi_rpc::RpcLoop;

const XI_DIRECTORY: &str = "xi-core";
const XI_LOG_FILE: &str = "xi-core.log";

fn get_logging_directory() -> Option<PathBuf> {
    if let Some(mut log_dir) = dirs::data_local_dir() {
        log_dir.push(XI_DIRECTORY);
        Some(log_dir)
    } else {
        eprintln!("[WARNING] The dir library was not able to find a directory for this platform");
        None
    }
}

fn path_for_log_file<P: AsRef<str>>(filename: P) -> Option<PathBuf> {
    if let Some(mut logging_directory) = get_logging_directory() {
        // Create the logging directory
        match fs::create_dir_all(&logging_directory) {
            Ok(_) => (),
            Err(why) => eprintln!("[WARNING] {:?}", why),
        }
        logging_directory.push(filename.as_ref());
        Some(logging_directory)
    } else {
        None
    }
}

fn setup_logging() -> Result<(), fern::InitError> {
    let level_filter = match std::env::var("XI_LOG") {
        Ok(level) => match level.to_lowercase().as_ref() {
            "trace" => log::LevelFilter::Trace,
            "debug" => log::LevelFilter::Debug,
            _ => log::LevelFilter::Info,
        },
        // Default to info
        Err(_) => log::LevelFilter::Info,
    };

    let mut fern_dispatch = fern::Dispatch::new()
        .format(|out, message, record| {
            out.finish(format_args!(
                "{}[{}][{}] {}",
                chrono::Local::now().format("[%Y-%m-%d][%H:%M:%S]"),
                record.target(),
                record.level(),
                message,
            ))
        }).level(level_filter)
        .chain(io::stderr());

    if let Some(logging_file_path) = path_for_log_file(XI_LOG_FILE) {
        fern_dispatch = fern_dispatch.chain(fern::log_file(logging_file_path)?)
    } else {
        eprintln!(
            "[WARNING] There was an issue getting the path for the log file, just using stderr"
        );
    }
    fern_dispatch.apply()?;
    info!("Logging with fern is setup");
    Ok(())
}

fn main() {
    let mut state = XiCore::new();
    let stdin = io::stdin();
    let stdout = io::stdout();
    let mut rpc_looper = RpcLoop::new(stdout);

    if let Err(e) = setup_logging() {
        eprintln!(
            "[ERROR] setup_logging returned error, logging disabled: {:?}",
            e
        );
    }

    match rpc_looper.mainloop(|| stdin.lock(), &mut state) {
        Ok(_) => (),
        Err(err) => error!("xi-core exited with error:\n{:?}", err),
    }
}
<|endoftext|>


<commit_before>// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// See https://users.rust-lang.org/t/psa-dealing-with-warning-unused-import-std-ascii-asciiext-in-today-s-nightly/13726
#[allow(unused_imports)]
use std::ascii::AsciiExt;

use std::str::FromStr;

use self::RenameRule::*;

#[derive(Debug, PartialEq)]
pub enum RenameRule {
    /// Don't apply a default rename rule.
    None,
    /// Rename direct children to "lowercase" style.
    LowerCase,
    /// Rename direct children to "PascalCase" style, as typically used for enum variants.
    PascalCase,
    /// Rename direct children to "camelCase" style.
    CamelCase,
    /// Rename direct children to "snake_case" style, as commonly used for fields.
    SnakeCase,
    /// Rename direct children to "SCREAMING_SNAKE_CASE" style, as commonly used for constants.
    ScreamingSnakeCase,
    /// Rename direct children to "kebab-case" style.
    KebabCase,
    /// Rename direct children to "SCREAMING-KEBAB-CASE" style.
    ScreamingKebabCase,
}

impl RenameRule {
    pub fn apply_to_variant(&self, variant: &str) -> String {
        match *self {
            None | PascalCase => variant.to_owned(),
            LowerCase => variant.to_ascii_lowercase(),
            CamelCase => variant[..1].to_ascii_lowercase() + &variant[1..],
            SnakeCase => {
                let mut snake = String::new();
                for (i, ch) in variant.char_indices() {
                    if i > 0 && ch.is_uppercase() {
                        snake.push('_');
                    }
                    snake.push(ch.to_ascii_lowercase());
                }
                snake
            }
            ScreamingSnakeCase => SnakeCase.apply_to_variant(variant).to_ascii_uppercase(),
            KebabCase => SnakeCase.apply_to_variant(variant).replace('_', "-"),
            ScreamingKebabCase => ScreamingSnakeCase
                .apply_to_variant(variant)
                .replace('_', "-"),
        }
    }

    pub fn apply_to_field(&self, field: &str) -> String {
        match *self {
            None | LowerCase | SnakeCase => field.to_owned(),
            PascalCase => {
                let mut pascal = String::new();
                let mut capitalize = true;
                for ch in field.chars() {
                    if ch == '_' {
                        capitalize = true;
                    } else if capitalize {
                        pascal.push(ch.to_ascii_uppercase());
                        capitalize = false;
                    } else {
                        pascal.push(ch);
                    }
                }
                pascal
            }
            CamelCase => {
                let pascal = PascalCase.apply_to_field(field);
                pascal[..1].to_ascii_lowercase() + &pascal[1..]
            }
            ScreamingSnakeCase => field.to_ascii_uppercase(),
            KebabCase => field.replace('_', "-"),
            ScreamingKebabCase => ScreamingSnakeCase.apply_to_field(field).replace('_', "-"),
        }
    }
}

impl FromStr for RenameRule {
    type Err = ();

    fn from_str(rename_all_str: &str) -> Result<Self, Self::Err> {
        match rename_all_str {
            "lowercase" => Ok(LowerCase),
            "PascalCase" => Ok(PascalCase),
            "camelCase" => Ok(CamelCase),
            "snake_case" => Ok(SnakeCase),
            "SCREAMING_SNAKE_CASE" => Ok(ScreamingSnakeCase),
            "kebab-case" => Ok(KebabCase),
            "SCREAMING-KEBAB-CASE" => Ok(ScreamingKebabCase),
            _ => Err(()),
        }
    }
}

#[test]
fn rename_variants() {
    for &(original, lower, camel, snake, screaming, kebab, screaming_kebab) in &[
        (
            "Outcome",
            "outcome",
            "outcome",
            "outcome",
            "OUTCOME",
            "outcome",
            "OUTCOME",
        ),
        (
            "VeryTasty",
            "verytasty",
            "veryTasty",
            "very_tasty",
            "VERY_TASTY",
            "very-tasty",
            "VERY-TASTY",
        ),
        ("A", "a", "a", "a", "A", "a", "A"),
        ("Z42", "z42", "z42", "z42", "Z42", "z42", "Z42"),
    ] {
        assert_eq!(None.apply_to_variant(original), original);
        assert_eq!(LowerCase.apply_to_variant(original), lower);
        assert_eq!(PascalCase.apply_to_variant(original), original);
        assert_eq!(CamelCase.apply_to_variant(original), camel);
        assert_eq!(SnakeCase.apply_to_variant(original), snake);
        assert_eq!(ScreamingSnakeCase.apply_to_variant(original), screaming);
        assert_eq!(KebabCase.apply_to_variant(original), kebab);
        assert_eq!(
            ScreamingKebabCase.apply_to_variant(original),
            screaming_kebab
        );
    }
}

#[test]
fn rename_fields() {
    for &(original, pascal, camel, screaming, kebab, screaming_kebab) in &[
        (
            "outcome",
            "Outcome",
            "outcome",
            "OUTCOME",
            "outcome",
            "OUTCOME",
        ),
        (
            "very_tasty",
            "VeryTasty",
            "veryTasty",
            "VERY_TASTY",
            "very-tasty",
            "VERY-TASTY",
        ),
        ("a", "A", "a", "A", "a", "A"),
        ("z42", "Z42", "z42", "Z42", "z42", "Z42"),
    ] {
        assert_eq!(None.apply_to_field(original), original);
        assert_eq!(PascalCase.apply_to_field(original), pascal);
        assert_eq!(CamelCase.apply_to_field(original), camel);
        assert_eq!(SnakeCase.apply_to_field(original), original);
        assert_eq!(ScreamingSnakeCase.apply_to_field(original), screaming);
        assert_eq!(KebabCase.apply_to_field(original), kebab);
        assert_eq!(ScreamingKebabCase.apply_to_field(original), screaming_kebab);
    }
}
<commit_msg>Add UPPERCASE to rename_all<commit_after>// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// See https://users.rust-lang.org/t/psa-dealing-with-warning-unused-import-std-ascii-asciiext-in-today-s-nightly/13726
#[allow(unused_imports)]
use std::ascii::AsciiExt;

use std::str::FromStr;

use self::RenameRule::*;

#[derive(Debug, PartialEq)]
pub enum RenameRule {
    /// Don't apply a default rename rule.
    None,
    /// Rename direct children to "lowercase" style.
    LowerCase,
    /// Rename direct children to "UPPERCASE" style.
    UPPERCASE,
    /// Rename direct children to "PascalCase" style, as typically used for enum variants.
    PascalCase,
    /// Rename direct children to "camelCase" style.
    CamelCase,
    /// Rename direct children to "snake_case" style, as commonly used for fields.
    SnakeCase,
    /// Rename direct children to "SCREAMING_SNAKE_CASE" style, as commonly used for constants.
    ScreamingSnakeCase,
    /// Rename direct children to "kebab-case" style.
    KebabCase,
    /// Rename direct children to "SCREAMING-KEBAB-CASE" style.
    ScreamingKebabCase,
}

impl RenameRule {
    pub fn apply_to_variant(&self, variant: &str) -> String {
        match *self {
            None | PascalCase => variant.to_owned(),
            LowerCase => variant.to_ascii_lowercase(),
            UPPERCASE => variant.to_ascii_uppercase(),
            CamelCase => variant[..1].to_ascii_lowercase() + &variant[1..],
            SnakeCase => {
                let mut snake = String::new();
                for (i, ch) in variant.char_indices() {
                    if i > 0 && ch.is_uppercase() {
                        snake.push('_');
                    }
                    snake.push(ch.to_ascii_lowercase());
                }
                snake
            }
            ScreamingSnakeCase => SnakeCase.apply_to_variant(variant).to_ascii_uppercase(),
            KebabCase => SnakeCase.apply_to_variant(variant).replace('_', "-"),
            ScreamingKebabCase => ScreamingSnakeCase
                .apply_to_variant(variant)
                .replace('_', "-"),
        }
    }

    pub fn apply_to_field(&self, field: &str) -> String {
        match *self {
            None | LowerCase | SnakeCase => field.to_owned(),
            UPPERCASE => field.to_ascii_uppercase(),
            PascalCase => {
                let mut pascal = String::new();
                let mut capitalize = true;
                for ch in field.chars() {
                    if ch == '_' {
                        capitalize = true;
                    } else if capitalize {
                        pascal.push(ch.to_ascii_uppercase());
                        capitalize = false;
                    } else {
                        pascal.push(ch);
                    }
                }
                pascal
            }
            CamelCase => {
                let pascal = PascalCase.apply_to_field(field);
                pascal[..1].to_ascii_lowercase() + &pascal[1..]
            }
            ScreamingSnakeCase => field.to_ascii_uppercase(),
            KebabCase => field.replace('_', "-"),
            ScreamingKebabCase => ScreamingSnakeCase.apply_to_field(field).replace('_', "-"),
        }
    }
}

impl FromStr for RenameRule {
    type Err = ();

    fn from_str(rename_all_str: &str) -> Result<Self, Self::Err> {
        match rename_all_str {
            "lowercase" => Ok(LowerCase),
            "UPPERCASE" => Ok(UPPERCASE),
            "PascalCase" => Ok(PascalCase),
            "camelCase" => Ok(CamelCase),
            "snake_case" => Ok(SnakeCase),
            "SCREAMING_SNAKE_CASE" => Ok(ScreamingSnakeCase),
            "kebab-case" => Ok(KebabCase),
            "SCREAMING-KEBAB-CASE" => Ok(ScreamingKebabCase),
            _ => Err(()),
        }
    }
}

#[test]
fn rename_variants() {
    for &(original, lower, upper, camel, snake, screaming, kebab, screaming_kebab) in &[
        (
            "Outcome",
            "outcome",
            "OUTCOME",
            "outcome",
            "outcome",
            "OUTCOME",
            "outcome",
            "OUTCOME",
        ),
        (
            "VeryTasty",
            "verytasty",
            "VERYTASTY",
            "veryTasty",
            "very_tasty",
            "VERY_TASTY",
            "very-tasty",
            "VERY-TASTY",
        ),
        ("A", "a", "A", "a", "a", "A", "a", "A"),
        ("Z42", "z42", "Z42", "z42", "z42", "Z42", "z42", "Z42"),
    ] {
        assert_eq!(None.apply_to_variant(original), original);
        assert_eq!(LowerCase.apply_to_variant(original), lower);
        assert_eq!(UPPERCASE.apply_to_variant(original), upper);
        assert_eq!(PascalCase.apply_to_variant(original), original);
        assert_eq!(CamelCase.apply_to_variant(original), camel);
        assert_eq!(SnakeCase.apply_to_variant(original), snake);
        assert_eq!(ScreamingSnakeCase.apply_to_variant(original), screaming);
        assert_eq!(KebabCase.apply_to_variant(original), kebab);
        assert_eq!(
            ScreamingKebabCase.apply_to_variant(original),
            screaming_kebab
        );
    }
}

#[test]
fn rename_fields() {
    for &(original, upper, pascal, camel, screaming, kebab, screaming_kebab) in &[
        (
            "outcome",
            "OUTCOME",
            "Outcome",
            "outcome",
            "OUTCOME",
            "outcome",
            "OUTCOME",
        ),
        (
            "very_tasty",
            "VERY_TASTY",
            "VeryTasty",
            "veryTasty",
            "VERY_TASTY",
            "very-tasty",
            "VERY-TASTY",
        ),
        ("a", "A", "A", "a", "A", "a", "A"),
        ("z42", "Z42", "Z42", "z42", "Z42", "z42", "Z42"),
    ] {
        assert_eq!(None.apply_to_field(original), original);
        assert_eq!(UPPERCASE.apply_to_field(original), upper);
        assert_eq!(PascalCase.apply_to_field(original), pascal);
        assert_eq!(CamelCase.apply_to_field(original), camel);
        assert_eq!(SnakeCase.apply_to_field(original), original);
        assert_eq!(ScreamingSnakeCase.apply_to_field(original), screaming);
        assert_eq!(KebabCase.apply_to_field(original), kebab);
        assert_eq!(ScreamingKebabCase.apply_to_field(original), screaming_kebab);
    }
}
<|endoftext|>


<commit_before>use std::{borrow::Cow, io, io::prelude::Write};

use super::OutputFormatter;
use crate::{
    console::{ConsoleTestState, OutputLocation},
    test_result::TestResult,
    time,
    types::TestDesc,
};

pub(crate) struct JsonFormatter<T> {
    out: OutputLocation<T>,
}

impl<T: Write> JsonFormatter<T> {
    pub fn new(out: OutputLocation<T>) -> Self {
        Self { out }
    }

    fn writeln_message(&mut self, s: &str) -> io::Result<()> {
        assert!(!s.contains('\n'));

        self.out.write_all(s.as_ref())?;
        self.out.write_all(b"\n")
    }

    fn write_message(&mut self, s: &str) -> io::Result<()> {
        assert!(!s.contains('\n'));

        self.out.write_all(s.as_ref())
    }

    fn write_event(
        &mut self,
        ty: &str,
        name: &str,
        evt: &str,
        exec_time: Option<&time::TestExecTime>,
        stdout: Option<Cow<'_, str>>,
        extra: Option<&str>,
    ) -> io::Result<()> {
        self.write_message(&*format!(
            r#"{{ "type": "{}", "name": "{}", "event": "{}""#,
            ty, name, evt
        ))?;
        if let Some(exec_time) = exec_time {
            self.write_message(&*format!(r#", "exec_time": "{}""#, exec_time))?;
        }
        if let Some(stdout) = stdout {
            self.write_message(&*format!(r#", "stdout": "{}""#, EscapedString(stdout)))?;
        }
        if let Some(extra) = extra {
            self.write_message(&*format!(r#", {}"#, extra))?;
        }
        self.writeln_message(" }")
    }
}

impl<T: Write> OutputFormatter for JsonFormatter<T> {
    fn write_run_start(&mut self, test_count: usize) -> io::Result<()> {
        self.writeln_message(&*format!(
            r#"{{ "type": "suite", "event": "started", "test_count": {} }}"#,
            test_count
        ))
    }

    fn write_test_start(&mut self, desc: &TestDesc) -> io::Result<()> {
        self.writeln_message(&*format!(
            r#"{{ "type": "test", "event": "started", "name": "{}" }}"#,
            desc.name
        ))
    }

    fn write_result(
        &mut self,
        desc: &TestDesc,
        result: &TestResult,
        exec_time: Option<&time::TestExecTime>,
        stdout: &[u8],
        state: &ConsoleTestState,
    ) -> io::Result<()> {
        let display_stdout = state.options.display_output || *result != TestResult::TrOk;
        let stdout = if display_stdout && !stdout.is_empty() {
            Some(String::from_utf8_lossy(stdout))
        } else {
            None
        };
        match *result {
            TestResult::TrOk => {
                self.write_event("test", desc.name.as_slice(), "ok", exec_time, stdout, None)
            }

            TestResult::TrFailed => {
                self.write_event("test", desc.name.as_slice(), "failed", exec_time, stdout, None)
            }

            TestResult::TrTimedFail => self.write_event(
                "test",
                desc.name.as_slice(),
                "failed",
                exec_time,
                stdout,
                Some(r#""reason": "time limit exceeded""#),
            ),

            TestResult::TrFailedMsg(ref m) => self.write_event(
                "test",
                desc.name.as_slice(),
                "failed",
                exec_time,
                stdout,
                Some(&*format!(r#""message": "{}""#, EscapedString(m))),
            ),

            TestResult::TrIgnored => {
                self.write_event("test", desc.name.as_slice(), "ignored", exec_time, stdout, None)
            }

            TestResult::TrAllowedFail => self.write_event(
                "test",
                desc.name.as_slice(),
                "allowed_failure",
                exec_time,
                stdout,
                None,
            ),

            TestResult::TrBench(ref bs) => {
                let median = bs.ns_iter_summ.median as usize;
                let deviation = (bs.ns_iter_summ.max - bs.ns_iter_summ.min) as usize;

                let mbps = if bs.mb_s == 0 {
                    String::new()
                } else {
                    format!(r#", "mib_per_second": {}"#, bs.mb_s)
                };

                let line = format!(
                    "{{ \"type\": \"bench\", \
                     \"name\": \"{}\", \
                     \"median\": {}, \
                     \"deviation\": {}{} }}",
                    desc.name, median, deviation, mbps
                );

                self.writeln_message(&*line)
            }
        }
    }

    fn write_timeout(&mut self, desc: &TestDesc) -> io::Result<()> {
        self.writeln_message(&*format!(
            r#"{{ "type": "test", "event": "timeout", "name": "{}" }}"#,
            desc.name
        ))
    }

    fn write_run_finish(&mut self, state: &ConsoleTestState) -> io::Result<bool> {
        self.writeln_message(&*format!(
            "{{ \"type\": \"suite\", \
             \"event\": \"{}\", \
             \"passed\": {}, \
             \"failed\": {}, \
             \"allowed_fail\": {}, \
             \"ignored\": {}, \
             \"measured\": {}, \
             \"filtered_out\": {} }}",
            if state.failed == 0 { "ok" } else { "failed" },
            state.passed,
            state.failed + state.allowed_fail,
            state.allowed_fail,
            state.ignored,
            state.measured,
            state.filtered_out
        ))?;

        Ok(state.failed == 0)
    }
}

/// A formatting utility used to print strings with characters in need of escaping.
/// Base code taken form `libserialize::json::escape_str`
struct EscapedString<S: AsRef<str>>(S);

impl<S: AsRef<str>> ::std::fmt::Display for EscapedString<S> {
    fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
        let mut start = 0;

        for (i, byte) in self.0.as_ref().bytes().enumerate() {
            let escaped = match byte {
                b'"' => "\\\"",
                b'\\' => "\\\\",
                b'\x00' => "\\u0000",
                b'\x01' => "\\u0001",
                b'\x02' => "\\u0002",
                b'\x03' => "\\u0003",
                b'\x04' => "\\u0004",
                b'\x05' => "\\u0005",
                b'\x06' => "\\u0006",
                b'\x07' => "\\u0007",
                b'\x08' => "\\b",
                b'\t' => "\\t",
                b'\n' => "\\n",
                b'\x0b' => "\\u000b",
                b'\x0c' => "\\f",
                b'\r' => "\\r",
                b'\x0e' => "\\u000e",
                b'\x0f' => "\\u000f",
                b'\x10' => "\\u0010",
                b'\x11' => "\\u0011",
                b'\x12' => "\\u0012",
                b'\x13' => "\\u0013",
                b'\x14' => "\\u0014",
                b'\x15' => "\\u0015",
                b'\x16' => "\\u0016",
                b'\x17' => "\\u0017",
                b'\x18' => "\\u0018",
                b'\x19' => "\\u0019",
                b'\x1a' => "\\u001a",
                b'\x1b' => "\\u001b",
                b'\x1c' => "\\u001c",
                b'\x1d' => "\\u001d",
                b'\x1e' => "\\u001e",
                b'\x1f' => "\\u001f",
                b'\x7f' => "\\u007f",
                _ => {
                    continue;
                }
            };

            if start < i {
                f.write_str(&self.0.as_ref()[start..i])?;
            }

            f.write_str(escaped)?;

            start = i + 1;
        }

        if start != self.0.as_ref().len() {
            f.write_str(&self.0.as_ref()[start..])?;
        }

        Ok(())
    }
}
<commit_msg>Fixing escaping to ensure generation of welformed json.<commit_after>use std::{borrow::Cow, io, io::prelude::Write};

use super::OutputFormatter;
use crate::{
    console::{ConsoleTestState, OutputLocation},
    test_result::TestResult,
    time,
    types::TestDesc,
};

pub(crate) struct JsonFormatter<T> {
    out: OutputLocation<T>,
}

impl<T: Write> JsonFormatter<T> {
    pub fn new(out: OutputLocation<T>) -> Self {
        Self { out }
    }

    fn writeln_message(&mut self, s: &str) -> io::Result<()> {
        assert!(!s.contains('\n'));

        self.out.write_all(s.as_ref())?;
        self.out.write_all(b"\n")
    }

    fn write_message(&mut self, s: &str) -> io::Result<()> {
        assert!(!s.contains('\n'));

        self.out.write_all(s.as_ref())
    }

    fn write_event(
        &mut self,
        ty: &str,
        name: &str,
        evt: &str,
        exec_time: Option<&time::TestExecTime>,
        stdout: Option<Cow<'_, str>>,
        extra: Option<&str>,
    ) -> io::Result<()> {
        // A doc test's name includes a filename which must be escaped for correct json.
        self.write_message(&*format!(
            r#"{{ "type": "{}", "name": "{}", "event": "{}""#,
            ty,
            EscapedString(name),
            evt
        ))?;
        if let Some(exec_time) = exec_time {
            self.write_message(&*format!(r#", "exec_time": "{}""#, exec_time))?;
        }
        if let Some(stdout) = stdout {
            self.write_message(&*format!(r#", "stdout": "{}""#, EscapedString(stdout)))?;
        }
        if let Some(extra) = extra {
            self.write_message(&*format!(r#", {}"#, extra))?;
        }
        self.writeln_message(" }")
    }
}

impl<T: Write> OutputFormatter for JsonFormatter<T> {
    fn write_run_start(&mut self, test_count: usize) -> io::Result<()> {
        self.writeln_message(&*format!(
            r#"{{ "type": "suite", "event": "started", "test_count": {} }}"#,
            test_count
        ))
    }

    fn write_test_start(&mut self, desc: &TestDesc) -> io::Result<()> {
        self.writeln_message(&*format!(
            r#"{{ "type": "test", "event": "started", "name": "{}" }}"#,
            EscapedString(desc.name.as_slice())
        ))
    }

    fn write_result(
        &mut self,
        desc: &TestDesc,
        result: &TestResult,
        exec_time: Option<&time::TestExecTime>,
        stdout: &[u8],
        state: &ConsoleTestState,
    ) -> io::Result<()> {
        let display_stdout = state.options.display_output || *result != TestResult::TrOk;
        let stdout = if display_stdout && !stdout.is_empty() {
            Some(String::from_utf8_lossy(stdout))
        } else {
            None
        };
        match *result {
            TestResult::TrOk => {
                self.write_event("test", desc.name.as_slice(), "ok", exec_time, stdout, None)
            }

            TestResult::TrFailed => {
                self.write_event("test", desc.name.as_slice(), "failed", exec_time, stdout, None)
            }

            TestResult::TrTimedFail => self.write_event(
                "test",
                desc.name.as_slice(),
                "failed",
                exec_time,
                stdout,
                Some(r#""reason": "time limit exceeded""#),
            ),

            TestResult::TrFailedMsg(ref m) => self.write_event(
                "test",
                desc.name.as_slice(),
                "failed",
                exec_time,
                stdout,
                Some(&*format!(r#""message": "{}""#, EscapedString(m))),
            ),

            TestResult::TrIgnored => {
                self.write_event("test", desc.name.as_slice(), "ignored", exec_time, stdout, None)
            }

            TestResult::TrAllowedFail => self.write_event(
                "test",
                desc.name.as_slice(),
                "allowed_failure",
                exec_time,
                stdout,
                None,
            ),

            TestResult::TrBench(ref bs) => {
                let median = bs.ns_iter_summ.median as usize;
                let deviation = (bs.ns_iter_summ.max - bs.ns_iter_summ.min) as usize;

                let mbps = if bs.mb_s == 0 {
                    String::new()
                } else {
                    format!(r#", "mib_per_second": {}"#, bs.mb_s)
                };

                let line = format!(
                    "{{ \"type\": \"bench\", \
                     \"name\": \"{}\", \
                     \"median\": {}, \
                     \"deviation\": {}{} }}",
                    EscapedString(desc.name.as_slice()),
                    median,
                    deviation,
                    mbps
                );

                self.writeln_message(&*line)
            }
        }
    }

    fn write_timeout(&mut self, desc: &TestDesc) -> io::Result<()> {
        self.writeln_message(&*format!(
            r#"{{ "type": "test", "event": "timeout", "name": "{}" }}"#,
            EscapedString(desc.name.as_slice())
        ))
    }

    fn write_run_finish(&mut self, state: &ConsoleTestState) -> io::Result<bool> {
        self.writeln_message(&*format!(
            "{{ \"type\": \"suite\", \
             \"event\": \"{}\", \
             \"passed\": {}, \
             \"failed\": {}, \
             \"allowed_fail\": {}, \
             \"ignored\": {}, \
             \"measured\": {}, \
             \"filtered_out\": {} }}",
            if state.failed == 0 { "ok" } else { "failed" },
            state.passed,
            state.failed + state.allowed_fail,
            state.allowed_fail,
            state.ignored,
            state.measured,
            state.filtered_out
        ))?;

        Ok(state.failed == 0)
    }
}

/// A formatting utility used to print strings with characters in need of escaping.
/// Base code taken form `libserialize::json::escape_str`
struct EscapedString<S: AsRef<str>>(S);

impl<S: AsRef<str>> ::std::fmt::Display for EscapedString<S> {
    fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
        let mut start = 0;

        for (i, byte) in self.0.as_ref().bytes().enumerate() {
            let escaped = match byte {
                b'"' => "\\\"",
                b'\\' => "\\\\",
                b'\x00' => "\\u0000",
                b'\x01' => "\\u0001",
                b'\x02' => "\\u0002",
                b'\x03' => "\\u0003",
                b'\x04' => "\\u0004",
                b'\x05' => "\\u0005",
                b'\x06' => "\\u0006",
                b'\x07' => "\\u0007",
                b'\x08' => "\\b",
                b'\t' => "\\t",
                b'\n' => "\\n",
                b'\x0b' => "\\u000b",
                b'\x0c' => "\\f",
                b'\r' => "\\r",
                b'\x0e' => "\\u000e",
                b'\x0f' => "\\u000f",
                b'\x10' => "\\u0010",
                b'\x11' => "\\u0011",
                b'\x12' => "\\u0012",
                b'\x13' => "\\u0013",
                b'\x14' => "\\u0014",
                b'\x15' => "\\u0015",
                b'\x16' => "\\u0016",
                b'\x17' => "\\u0017",
                b'\x18' => "\\u0018",
                b'\x19' => "\\u0019",
                b'\x1a' => "\\u001a",
                b'\x1b' => "\\u001b",
                b'\x1c' => "\\u001c",
                b'\x1d' => "\\u001d",
                b'\x1e' => "\\u001e",
                b'\x1f' => "\\u001f",
                b'\x7f' => "\\u007f",
                _ => {
                    continue;
                }
            };

            if start < i {
                f.write_str(&self.0.as_ref()[start..i])?;
            }

            f.write_str(escaped)?;

            start = i + 1;
        }

        if start != self.0.as_ref().len() {
            f.write_str(&self.0.as_ref()[start..])?;
        }

        Ok(())
    }
}
<|endoftext|>


<commit_before>extern crate ansi_term;
extern crate rand;

use ansi_term::Colour::*;
use rand::Rng;
use std::io;

enum Card {
    ClubsAce,
    ClubsTen,
    ClubsKing,
    ClubsQueen,
    ClubsJack,
    ClubsNine,
    ClubsEight,
    ClubsSeven,
    SpadesAce,
    SpadesTen,
    SpadesKing,
    SpadesQueen,
    SpadesJack,
    SpadesNine,
    SpadesEight,
    SpadesSeven,
    HeartsAce,
    HeartsTen,
    HeartsKing,
    HeartsQueen,
    HeartsJack,
    HeartsNine,
    HeartsEight,
    HeartsSeven,
    DiamondsAce,
    DiamondsTen,
    DiamondsKing,
    DiamondsQueen,
    DiamondsJack,
    DiamondsNine,
    DiamondsEight,
    DiamondsSeven,
}

enum Game {
    Suit,
    Grand,
    Null,
}

enum Player {
    A,
    B,
    C,
}

fn announce(player: u8) -> Game {
    Game::Suit
}

fn bid(dealer: u8) -> (u8, u8) {
    let winner: u8 = dealer;
    let highest: u8 = 18;
    // TODO
    (winner, highest)
}

fn deal(dealer: u8) {
    let mut cards: Vec<u8> = Vec::new();
    // print sorted cards
    for n in 0..32 {
        cards.push(n);
    }
    for n in 0..8 {
        print_card(n);
    };
    println!("");
    for n in 8..16 {
        print_card(n);
    }
    println!("");
    for n in 16..24 {
        print_card(n);
    };
    println!("");
    for n in 24..32 {
        print_card(n);
    };
    println!("");
    println!("");
    // TODO: shuffle cards
    // print shuffled cards (per player plus Skat)
    for n in 0..10 {
        print_card(n);
    };
    println!("");
    for n in 10..20 {
        print_card(n);
    }
    println!("");
    for n in 20..30 {
        print_card(n);
    };
    println!("");
    for n in 30..32 {
        print_card(n);
    };
    println!("");
}

fn print_card(card: u8) {
    let club    = "♣";
    let spade   = "♠";
    let heart   = "♥";
    let diamond = "♦";
    match card {
        0 => {
            let mut ace = " A".to_string();
            ace.push_str(club);
            print!("{} ", Black.bold().paint(&ace));
        },
        1 => {
            let mut ten = "10".to_string();
            ten.push_str(club);
            print!("{} ", Black.bold().paint(&ten));
        },
        2 => {
            let mut king = " K".to_string();
            king.push_str(club);
            print!("{} ", Black.bold().paint(&king));
        },
        3 => {
            let mut queen = " Q".to_string();
            queen.push_str(club);
            print!("{} ", Black.bold().paint(&queen));
        },
        4 => {
            let mut jack = " J".to_string();
            jack.push_str(club);
            print!("{} ", Black.bold().paint(&jack));
        },
        5 => {
            let mut nine = " 9".to_string();
            nine.push_str(club);
            print!("{} ", Black.bold().paint(&nine));
        },
        6 => {
            let mut eight = " 8".to_string();
            eight.push_str(club);
            print!("{} ", Black.bold().paint(&eight));
        },
        7 => {
            let mut seven = " 7".to_string();
            seven.push_str(club);
            print!("{} ", Black.bold().paint(&seven));
        },
        8 => {
            let mut ace = " A".to_string();
            ace.push_str(spade);
            print!("{} ", Green.bold().paint(&ace));
        },
        9 => {
            let mut ten = "10".to_string();
            ten.push_str(spade);
            print!("{} ", Green.bold().paint(&ten));
        },
        10 => {
            let mut king = " K".to_string();
            king.push_str(spade);
            print!("{} ", Green.bold().paint(&king));
        },
        11 => {
            let mut queen = " Q".to_string();
            queen.push_str(spade);
            print!("{} ", Green.bold().paint(&queen));
        },
        12 => {
            let mut jack = " J".to_string();
            jack.push_str(spade);
            print!("{} ", Green.bold().paint(&jack));
        },
        13 => {
            let mut nine = " 9".to_string();
            nine.push_str(spade);
            print!("{} ", Green.bold().paint(&nine));
        },
        14 => {
            let mut eight = " 8".to_string();
            eight.push_str(spade);
            print!("{} ", Green.bold().paint(&eight));
        },
        15 => {
            let mut seven = " 7".to_string();
            seven.push_str(spade);
            print!("{} ", Green.bold().paint(&seven));
        },
        16 => {
            let mut ace = " A".to_string();
            ace.push_str(heart);
            print!("{} ", Red.bold().paint(&ace));
        },
        17 => {
            let mut ten = "10".to_string();
            ten.push_str(heart);
            print!("{} ", Red.bold().paint(&ten));
        },
        18 => {
            let mut king = " K".to_string();
            king.push_str(heart);
            print!("{} ", Red.bold().paint(&king));
        },
        19 => {
            let mut queen = " Q".to_string();
            queen.push_str(heart);
            print!("{} ", Red.bold().paint(&queen));
        },
        20 => {
            let mut jack = " J".to_string();
            jack.push_str(heart);
            print!("{} ", Red.bold().paint(&jack));
        },
        21 => {
            let mut nine = " 9".to_string();
            nine.push_str(heart);
            print!("{} ", Red.bold().paint(&nine));
        },
        22 => {
            let mut eight = " 8".to_string();
            eight.push_str(heart);
            print!("{} ", Red.bold().paint(&eight));
        },
        23 => {
            let mut seven = " 7".to_string();
            seven.push_str(heart);
            print!("{} ", Red.bold().paint(&seven));
        },
        24 => {
            let mut ace = " A".to_string();
            ace.push_str(diamond);
            print!("{} ", Yellow.bold().paint(&ace));
        },
        25 => {
            let mut ten = "10".to_string();
            ten.push_str(diamond);
            print!("{} ", Yellow.bold().paint(&ten));
        },
        26 => {
            let mut king = " K".to_string();
            king.push_str(diamond);
            print!("{} ", Yellow.bold().paint(&king));
        },
        27 => {
            let mut queen = " Q".to_string();
            queen.push_str(diamond);
            print!("{} ", Yellow.bold().paint(&queen));
        },
        28 => {
            let mut jack = " J".to_string();
            jack.push_str(diamond);
            print!("{} ", Yellow.bold().paint(&jack));
        },
        29 => {
            let mut nine = " 9".to_string();
            nine.push_str(diamond);
            print!("{} ", Yellow.bold().paint(&nine));
        },
        30 => {
            let mut eight = " 8".to_string();
            eight.push_str(diamond);
            print!("{} ", Yellow.bold().paint(&eight));
        },
        31 => {
            let mut seven = " 7".to_string();
            seven.push_str(diamond);
            print!("{} ", Yellow.bold().paint(&seven));
        },
        _ => panic!("Unknown card"),
    }
}

fn main() {
    // randomly select player
    let player_number: u8 = rand::thread_rng().gen_range(0, 3);
    match player_number {
        0 => println!("player A:"),
        1 => println!("player B:"),
        2 => println!("player C:"),
        _ => panic!("Unknown player {}", player_number),
    }
    loop {
        // player player_number is dealing
        deal(player_number);
        // bid
        let (player, bid) = bid(player_number);
        // announce
        let game = announce(player);
        // play 10 tricks in a row
        for trick in 0..10 {
            println!("trick #{}:", trick);
            // ask for input
            let mut input = String::new();
            io::stdin().read_line(&mut input)
                .ok()
                .expect("failed to read line");
            let input: u8 = match input.trim().parse() {
                Ok(num) => num,
                Err(_) => break,
            };
            // is input valid?
        };
        println!("New game?");
        let mut input = String::new();
        io::stdin().read_line(&mut input)
            .ok()
            .expect("failed to read line");
        let input: u8 = match input.trim().parse() {
            Ok(num) => num,
            Err(_) => break,
        };
        println!("your input: {}", input);
        if input != 1 {
            break;
        }
    }
}
<commit_msg>Shuffle cards and print the resulting distribution.<commit_after>extern crate ansi_term;
extern crate rand;

use ansi_term::Colour::*;
use rand::Rng;
use std::io;

enum Card {
    ClubsAce,
    ClubsTen,
    ClubsKing,
    ClubsQueen,
    ClubsJack,
    ClubsNine,
    ClubsEight,
    ClubsSeven,
    SpadesAce,
    SpadesTen,
    SpadesKing,
    SpadesQueen,
    SpadesJack,
    SpadesNine,
    SpadesEight,
    SpadesSeven,
    HeartsAce,
    HeartsTen,
    HeartsKing,
    HeartsQueen,
    HeartsJack,
    HeartsNine,
    HeartsEight,
    HeartsSeven,
    DiamondsAce,
    DiamondsTen,
    DiamondsKing,
    DiamondsQueen,
    DiamondsJack,
    DiamondsNine,
    DiamondsEight,
    DiamondsSeven,
}

enum Game {
    Suit,
    Grand,
    Null,
}

enum Player {
    A,
    B,
    C,
}

fn announce(player: u8) -> Game {
    Game::Suit
}

fn bid(dealer: u8) -> (u8, u8) {
    let winner: u8 = dealer;
    let highest: u8 = 18;
    // TODO
    (winner, highest)
}

fn deal(dealer: u8) {
    let mut cards: Vec<u8> = Vec::new();
    // print sorted cards
    for n in 0..32 {
        cards.push(n);
    }
    for n in 0..8 {
        print_card(n);
    };
    println!("");
    for n in 8..16 {
        print_card(n);
    }
    println!("");
    for n in 16..24 {
        print_card(n);
    };
    println!("");
    for n in 24..32 {
        print_card(n);
    };
    println!("");
    println!("");
    // shuffle cards
    let mut upper: u8 = 32;
    let mut shuffled: Vec<u8> = Vec::new();
    for n in 0..32 {
        // randomly select card
        let pile_index: u8 = rand::thread_rng().gen_range(0, upper - n);
        // remove selected card from old pile
        let card = cards.remove(pile_index as usize);
        // add selected card to new pile
        shuffled.push(card);
    }
    // print shuffled cards (per player plus Skat)
    for n in 0..10 {
        print_card(shuffled[n]);
    };
    println!("");
    for n in 10..20 {
        print_card(shuffled[n]);
    }
    println!("");
    for n in 20..30 {
        print_card(shuffled[n]);
    };
    println!("");
    for n in 30..32 {
        print_card(shuffled[n]);
    };
    println!("");
}

fn print_card(card: u8) {
    let club    = "♣";
    let spade   = "♠";
    let heart   = "♥";
    let diamond = "♦";
    match card {
        0 => {
            let mut ace = " A".to_string();
            ace.push_str(club);
            print!("{} ", Black.bold().paint(&ace));
        },
        1 => {
            let mut ten = "10".to_string();
            ten.push_str(club);
            print!("{} ", Black.bold().paint(&ten));
        },
        2 => {
            let mut king = " K".to_string();
            king.push_str(club);
            print!("{} ", Black.bold().paint(&king));
        },
        3 => {
            let mut queen = " Q".to_string();
            queen.push_str(club);
            print!("{} ", Black.bold().paint(&queen));
        },
        4 => {
            let mut jack = " J".to_string();
            jack.push_str(club);
            print!("{} ", Black.bold().paint(&jack));
        },
        5 => {
            let mut nine = " 9".to_string();
            nine.push_str(club);
            print!("{} ", Black.bold().paint(&nine));
        },
        6 => {
            let mut eight = " 8".to_string();
            eight.push_str(club);
            print!("{} ", Black.bold().paint(&eight));
        },
        7 => {
            let mut seven = " 7".to_string();
            seven.push_str(club);
            print!("{} ", Black.bold().paint(&seven));
        },
        8 => {
            let mut ace = " A".to_string();
            ace.push_str(spade);
            print!("{} ", Green.bold().paint(&ace));
        },
        9 => {
            let mut ten = "10".to_string();
            ten.push_str(spade);
            print!("{} ", Green.bold().paint(&ten));
        },
        10 => {
            let mut king = " K".to_string();
            king.push_str(spade);
            print!("{} ", Green.bold().paint(&king));
        },
        11 => {
            let mut queen = " Q".to_string();
            queen.push_str(spade);
            print!("{} ", Green.bold().paint(&queen));
        },
        12 => {
            let mut jack = " J".to_string();
            jack.push_str(spade);
            print!("{} ", Green.bold().paint(&jack));
        },
        13 => {
            let mut nine = " 9".to_string();
            nine.push_str(spade);
            print!("{} ", Green.bold().paint(&nine));
        },
        14 => {
            let mut eight = " 8".to_string();
            eight.push_str(spade);
            print!("{} ", Green.bold().paint(&eight));
        },
        15 => {
            let mut seven = " 7".to_string();
            seven.push_str(spade);
            print!("{} ", Green.bold().paint(&seven));
        },
        16 => {
            let mut ace = " A".to_string();
            ace.push_str(heart);
            print!("{} ", Red.bold().paint(&ace));
        },
        17 => {
            let mut ten = "10".to_string();
            ten.push_str(heart);
            print!("{} ", Red.bold().paint(&ten));
        },
        18 => {
            let mut king = " K".to_string();
            king.push_str(heart);
            print!("{} ", Red.bold().paint(&king));
        },
        19 => {
            let mut queen = " Q".to_string();
            queen.push_str(heart);
            print!("{} ", Red.bold().paint(&queen));
        },
        20 => {
            let mut jack = " J".to_string();
            jack.push_str(heart);
            print!("{} ", Red.bold().paint(&jack));
        },
        21 => {
            let mut nine = " 9".to_string();
            nine.push_str(heart);
            print!("{} ", Red.bold().paint(&nine));
        },
        22 => {
            let mut eight = " 8".to_string();
            eight.push_str(heart);
            print!("{} ", Red.bold().paint(&eight));
        },
        23 => {
            let mut seven = " 7".to_string();
            seven.push_str(heart);
            print!("{} ", Red.bold().paint(&seven));
        },
        24 => {
            let mut ace = " A".to_string();
            ace.push_str(diamond);
            print!("{} ", Yellow.bold().paint(&ace));
        },
        25 => {
            let mut ten = "10".to_string();
            ten.push_str(diamond);
            print!("{} ", Yellow.bold().paint(&ten));
        },
        26 => {
            let mut king = " K".to_string();
            king.push_str(diamond);
            print!("{} ", Yellow.bold().paint(&king));
        },
        27 => {
            let mut queen = " Q".to_string();
            queen.push_str(diamond);
            print!("{} ", Yellow.bold().paint(&queen));
        },
        28 => {
            let mut jack = " J".to_string();
            jack.push_str(diamond);
            print!("{} ", Yellow.bold().paint(&jack));
        },
        29 => {
            let mut nine = " 9".to_string();
            nine.push_str(diamond);
            print!("{} ", Yellow.bold().paint(&nine));
        },
        30 => {
            let mut eight = " 8".to_string();
            eight.push_str(diamond);
            print!("{} ", Yellow.bold().paint(&eight));
        },
        31 => {
            let mut seven = " 7".to_string();
            seven.push_str(diamond);
            print!("{} ", Yellow.bold().paint(&seven));
        },
        _ => panic!("Unknown card"),
    }
}

fn main() {
    // randomly select player
    let player_number: u8 = rand::thread_rng().gen_range(0, 3);
    match player_number {
        0 => println!("player A:"),
        1 => println!("player B:"),
        2 => println!("player C:"),
        _ => panic!("Unknown player {}", player_number),
    }
    loop {
        // player player_number is dealing
        deal(player_number);
        // bid
        let (player, bid) = bid(player_number);
        // announce
        let game = announce(player);
        // play 10 tricks in a row
        for trick in 0..10 {
            println!("trick #{}:", trick);
            // ask for input
            let mut input = String::new();
            io::stdin().read_line(&mut input)
                .ok()
                .expect("failed to read line");
            let input: u8 = match input.trim().parse() {
                Ok(num) => num,
                Err(_) => break,
            };
            // is input valid?
        };
        println!("New game?");
        let mut input = String::new();
        io::stdin().read_line(&mut input)
            .ok()
            .expect("failed to read line");
        let input: u8 = match input.trim().parse() {
            Ok(num) => num,
            Err(_) => break,
        };
        println!("your input: {}", input);
        if input != 1 {
            break;
        }
    }
}
<|endoftext|>