<commit_before>#![feature(str_char)]
extern crate regex;

use regex::Regex;
use std::env::args;

fn has_bad_characters(s: &String) -> bool {
    let bad_re = Regex::new(r"(?:(ab)|(cd)|(pq)|(xy))").unwrap();
    bad_re.is_match(&s)
}

fn at_least_three_vowels(s: &String) -> bool {
    // regex wasn't working here for some reason, and it's a linear pass
    // anyways
    s.chars().filter(
        |c| match *c {
            'a' | 'e' | 'i' | 'o' | 'u' => true,
            _                           => false,
        }
    ).count() >= 3
}

fn at_least_one_duplicate(s: &String) -> bool {
    let mut iter = s.chars().peekable();
    while iter.peek().is_some() {
        let c = iter.next().unwrap();
        if iter.peek().is_some() && c == *iter.peek().unwrap() {
            return true
        }
    }
    false
}

fn is_nice(s: &String) -> bool {
    /*
    !has_bad_characters(s) &&
        at_least_three_vowels(s) &&
        at_least_one_duplicate(s)
    */
    sandwiched(s) && repeat_pair(s)
}

fn sandwiched(s: &String) -> bool {
    // rust only supports RE2 regexes, so not backreffing on capture groups
    // otherwise this can just be: (.+).\1
    (1..(s.len() - 1)).any(|i| s.char_at(i - 1) == s.char_at(i + 1))
}

fn repeat_pair(s: &String) -> bool {
    // posix regex: (.)(.).*\1\2
    (0..(s.len() - 3)).any(
        |i| {
            let c1 = s.char_at(i);
            let c2 = s.char_at(i + 1);
            ((i + 2)..(s.len() - 1)).any(
                |j| {
                    let c3 = s.char_at(j);
                    let c4 = s.char_at(j + 1);
                    c1 == c3 && c2 == c4
                }
            )
        }
    )
}

fn main() {
    let num = args().skip(1).filter(is_nice).count();
    println!("{}", num);
}
<commit_msg>make original solution way better<commit_after>#![feature(str_char)]
extern crate regex;

use regex::Regex;
use std::env::args;

fn has_bad_characters(s: &String) -> bool {
    let bad_re = Regex::new(r"(?:(ab)|(cd)|(pq)|(xy))").unwrap();
    bad_re.is_match(&s)
}

fn at_least_three_vowels(s: &String) -> bool {
    let vowel_re = Regex::new(r"(.*[aeiou].*){3}").unwrap();
    vowel_re.is_match(s)
}

fn at_least_one_duplicate(s: &String) -> bool {
    (0..(s.len() - 1)).any(|i| s.char_at(i) == s.char_at(i + 1))
}

fn is_nice_part_one(s: &String) -> bool {
    !has_bad_characters(s) &&
        at_least_three_vowels(s) &&
        at_least_one_duplicate(s)
}

fn is_nice_part_two(s: &String) -> bool {
    sandwiched(s) && repeat_pair(s)
}

fn sandwiched(s: &String) -> bool {
    // rust only supports RE2 regexes, so not backreffing on capture groups
    // otherwise this can just be: (.+).\1
    (1..(s.len() - 1)).any(|i| s.char_at(i - 1) == s.char_at(i + 1))
}

fn repeat_pair(s: &String) -> bool {
    // posix regex: (.)(.).*\1\2
    (0..(s.len() - 3)).any(
        |i| {
            let c1 = s.char_at(i);
            let c2 = s.char_at(i + 1);
            ((i + 2)..(s.len() - 1)).any(
                |j| {
                    let c3 = s.char_at(j);
                    let c4 = s.char_at(j + 1);
                    c1 == c3 && c2 == c4
                }
            )
        }
    )
}

fn main() {
    let num_part_one = args().skip(1).filter(is_nice_part_one).count();
    let num_part_two = args().skip(1).filter(is_nice_part_two).count();
    println!("{} {}", num_part_one, num_part_two);
}
<|endoftext|>


<commit_before>#![feature(iter_arith)]
#![feature(convert)]
extern crate regex;

use std::io;
use std::io::prelude::*; // I still don't understand why I need this
use std::ops::Range;
use regex::Regex;

trait Contains<T> {
    fn contains(&self, T) -> bool;
}

impl<T: PartialOrd> Contains<T> for Range<T> {
    fn contains(&self, e: T) -> bool {
        self.start <= e && e < self.end
    }
}

fn count_where<I,F>(iterator: I, f: F) -> u32
where I: Iterator, F: Fn(&I::Item) -> bool {
    iterator.filter(f).count() as u32
}

struct HouseLights { matrix: Vec<Vec<bool>>, }
struct Point<T> { x: T, y: T }

impl HouseLights {
    fn init(dim: u32) -> HouseLights {
        let mat: Vec<Vec<bool>> =
            (0..dim).map(|_| (0..dim).map(|_| false).collect()).collect();
        HouseLights { matrix: mat, }
    }

    fn count_lights(&self, state: bool) -> u32 {
        self.matrix.iter()
            .map(|row| count_where(row.iter(), |l| state == **l))
            .sum()
    }

    fn switch<F>(&self, p1: Point<usize>, p2: Point<usize>,
                 func: F) -> HouseLights where F: Fn(bool) -> bool {
        let dim = self.matrix.len();
        let x_range = p1.x..(p2.x + 1);
        let y_range = p1.y..(p2.y + 1);

        let mat = self.matrix.iter().zip(0..dim)
            .map(|t_y| {
                let (row, y) = t_y;
                row.iter().zip(0..dim).map(|t_x| {
                    let (state, x) = t_x;
                    if x_range.contains(x) && y_range.contains(y) {
                        func(*state)
                    } else {
                        *state
                    }
                }).collect()
            }).collect();
        HouseLights{ matrix: mat, }
    }
}

fn unpack(s: String) -> (Point<usize>, Point<usize>, String) {
    let re = Regex::new(r"(\w+(?: \w+)?) (\d+),(\d+) .* (\d+),(\d+)").unwrap();
    let (action, x1, y1, x2, y2) = match re.captures(&s) {
        Some(cap) => (cap.at(1).unwrap(), cap.at(2).unwrap(),
                      cap.at(3).unwrap(), cap.at(4).unwrap(),
                      cap.at(5).unwrap()),
        None      => panic!("could not parse input line"),
    };
    let p1 = Point {
        x: usize::from_str_radix(&x1, 10).unwrap(),
        y: usize::from_str_radix(&y1, 10).unwrap(),
    };
    let p2 = Point {
        x: usize::from_str_radix(&x2, 10).unwrap(),
        y: usize::from_str_radix(&y2, 10).unwrap(),
    };
    (p1, p2, action.to_string())
}

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

    let h_1 = HouseLights::init(1000);
    let lines = stdin.lock().lines().map(|line| line.unwrap());
    let h_n = lines.map(unpack)
        .fold(h_1, |h, t| match t.2.as_str() {
            "turn on" => h.switch(t.0, t.1, |_| true),
            "turn off" => h.switch(t.0, t.1, |_| false),
            "toggle" => h.switch(t.0, t.1, |s: bool| -> bool { !s }),
            _ => panic!("could not parse input line"),
        });
    println!("{}", h_n.count_lights(true));
}
<commit_msg>day 6, part 2<commit_after>#![feature(iter_arith)]
#![feature(convert)]
extern crate regex;

use std::io;
use std::io::prelude::*; // I still don't understand why I need this
use std::ops::Range;
use regex::Regex;

trait Contains<T> {
    fn contains(&self, T) -> bool;
}

impl<T: PartialOrd> Contains<T> for Range<T> {
    fn contains(&self, e: T) -> bool {
        self.start <= e && e < self.end
    }
}

fn count_where<I,F>(iterator: I, f: F) -> u32
where I: Iterator, F: Fn(&I::Item) -> bool {
    iterator.filter(f).count() as u32
}

struct HouseLights { matrix: Vec<Vec<u32>>, }
struct Point<T> { x: T, y: T }

impl HouseLights {
    fn init(dim: u32) -> HouseLights {
        let mat: Vec<Vec<u32>> =
            (0..dim).map(|_| (0..dim).map(|_| 0).collect()).collect();
        HouseLights { matrix: mat, }
    }

    fn total_brightness(&self) -> u32 {
        // sadly, rust can't seem to infer that adding a bunch of nested u32's
        // will result in a u32
        // self.matrix.iter().map(|row| row.iter().sum()).sum()
        let row_sums: Vec<u32> = self.matrix.iter().map(|row| row.iter().sum()).collect();
        row_sums.iter().sum()
    }

    /*
    fn count_lights(&self, state: bool) -> u32 {
        self.matrix.iter()
            .map(|row| count_where(row.iter(), |l| state == **l))
            .sum()
    }
    */

    fn switch<F>(&self, p1: Point<usize>, p2: Point<usize>,
                 func: F) -> HouseLights where F: Fn(u32) -> u32 {
        let dim = self.matrix.len();
        let x_range = p1.x..(p2.x + 1);
        let y_range = p1.y..(p2.y + 1);

        let mat = self.matrix.iter().zip(0..dim)
            .map(|t_y| {
                let (row, y) = t_y;
                row.iter().zip(0..dim).map(|t_x| {
                    let (state, x) = t_x;
                    if x_range.contains(x) && y_range.contains(y) {
                        func(*state)
                    } else {
                        *state
                    }
                }).collect()
            }).collect();
        HouseLights{ matrix: mat, }
    }
}

fn unpack(s: String) -> (Point<usize>, Point<usize>, String) {
    let re = Regex::new(r"(\w+(?: \w+)?) (\d+),(\d+) .* (\d+),(\d+)").unwrap();
    let (action, x1, y1, x2, y2) = match re.captures(&s) {
        Some(cap) => (cap.at(1).unwrap(), cap.at(2).unwrap(),
                      cap.at(3).unwrap(), cap.at(4).unwrap(),
                      cap.at(5).unwrap()),
        None      => panic!("could not parse input line"),
    };
    let p1 = Point {
        x: usize::from_str_radix(&x1, 10).unwrap(),
        y: usize::from_str_radix(&y1, 10).unwrap(),
    };
    let p2 = Point {
        x: usize::from_str_radix(&x2, 10).unwrap(),
        y: usize::from_str_radix(&y2, 10).unwrap(),
    };
    (p1, p2, action.to_string())
}

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

    let h_1 = HouseLights::init(1000);
    let lines = stdin.lock().lines().map(|line| line.unwrap());
    let h_n = lines.map(unpack)
        .fold(h_1, |h, t| match t.2.as_str() {
            "turn on" => h.switch(t.0, t.1, |b: u32| -> u32 { b + 1 }),
            "turn off" => h.switch(t.0, t.1, |b: u32| -> u32 { if b < 1 { 0 } else { b - 1 } }),
            "toggle" => h.switch(t.0, t.1, |b: u32| -> u32 { b + 2 }),
            _ => panic!("could not parse input line"),
        });
    //println!("{}", h_n.count_lights(true));
    println!("{}", h_n.total_brightness());
}
<|endoftext|>


<commit_before>// ignore-windows: Concurrency on Windows is not supported yet.

use std::thread::spawn;
use std::ptr::null_mut;
use std::sync::atomic::{Ordering, AtomicPtr};

#[derive(Copy, Clone)]
struct EvilSend<T>(pub T);

unsafe impl<T> Send for EvilSend<T> {}
unsafe impl<T> Sync for EvilSend<T> {}

extern "C" {
    fn malloc(size: usize) -> *mut u8;
    fn free(ptr: *mut u8);
}

pub fn main() {
    // Shared atomic pointer
    let pointer = AtomicPtr::new(null_mut::<usize>());
    let ptr = EvilSend(&pointer as *const AtomicPtr<usize>);

    // Note: this is scheduler-dependent
    // the operations need to occur in
    // order, otherwise the allocation is
    // not visible to the other-thread to
    // detect the race:
    //  1. alloc
    //  2. write
    unsafe {
        let j1 = spawn(move || {
            // Concurrent allocate the memory.
            // Uses relaxed semantics to not generate
            // a release sequence.
            let pointer = &*ptr.0;
            pointer.store(malloc(std::mem::size_of::<usize>()) as *mut usize, Ordering::Relaxed);
        });

        let j2 = spawn(move || {
            let pointer = &*ptr.0;
            *pointer.load(Ordering::Relaxed) = 2; //~ ERROR Data race detected between Write on Thread(id = 2) and Allocate on Thread(id = 1)
        });

        j1.join().unwrap();
        j2.join().unwrap();

        // Clean up memory, will never be executed
        free(pointer.load(Ordering::Relaxed) as *mut _);
    }
}
<commit_msg>avoid importing C functions in alloc_write_race test<commit_after>// ignore-windows: Concurrency on Windows is not supported yet.
#![feature(new_uninit)]

use std::thread::spawn;
use std::ptr::null_mut;
use std::sync::atomic::{Ordering, AtomicPtr};

#[derive(Copy, Clone)]
struct EvilSend<T>(pub T);

unsafe impl<T> Send for EvilSend<T> {}
unsafe impl<T> Sync for EvilSend<T> {}

pub fn main() {
    // Shared atomic pointer
    let pointer = AtomicPtr::new(null_mut::<usize>());
    let ptr = EvilSend(&pointer as *const AtomicPtr<usize>);

    // Note: this is scheduler-dependent
    // the operations need to occur in
    // order, otherwise the allocation is
    // not visible to the other-thread to
    // detect the race:
    //  1. alloc
    //  2. write
    unsafe {
        let j1 = spawn(move || {
            // Concurrent allocate the memory.
            // Uses relaxed semantics to not generate
            // a release sequence.
            let pointer = &*ptr.0;
            pointer.store(Box::into_raw(Box::<usize>::new_uninit()) as *mut usize, Ordering::Relaxed);
        });

        let j2 = spawn(move || {
            let pointer = &*ptr.0;
            *pointer.load(Ordering::Relaxed) = 2; //~ ERROR Data race detected between Write on Thread(id = 2) and Allocate on Thread(id = 1)
        });

        j1.join().unwrap();
        j2.join().unwrap();

        // Clean up memory, will never be executed
        drop(Box::from_raw(pointer.load(Ordering::Relaxed)));
    }
}
<|endoftext|>


<commit_before>// Copyright 2017 Google Inc.
//
// 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
//
//     https://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.

// global `#[deny()]` in the processed crate affects this file as well,
// and could cause compilation-breaking warnings.
#![allow(missing_docs, warnings)]

/// Invocations of this macro instruct Rerast to replace the first expression/statement with the one
/// after the =>. For example replace!(5 => 6) says to replace all occurences of the literal 5 with
/// the literal 6.
///
/// The macro should be invoked inside a function definition. The arguments to the function
/// represent placeholders within the search and replace expressions.
#[macro_export]
macro_rules! replace {
    ($a:expr => $b:expr) => {
        // Suppress warnings about unused values in case we're replacing something like a Result.
        #[allow(unused_must_use)]
        // If we have a search or replacement pattern that is just a placeholder then this macro
        // will turn that into a statement. Normally a reference to a variable is not permitted as a
        // statement, allow it.
        #[allow(path_statements)]
        #[allow(unreachable_code)]
        {
            if false {
                use $crate::GetMode;
                match $crate::_ExprRuleMarker.get_mode() {
                    $crate::Mode::Search => {&$a;}
                    $crate::Mode::Replace => {&$b;}
                }
                // Some of the placeholders used in this replace! invocation might have been
                // moved. To avoid use-after-move errors, we mark this as unreachable.
                unreachable!();
            }
        }
    };
}

/// Replaces one type with another. This will not match trait bounds (e.g. in where clauses), since
/// they are not types. If you want to replace all references to a trait, use `replace_trait_ref!`
/// instead.
#[macro_export]
macro_rules! replace_type {
    ($a:ty => $b:ty) => {
        {
            use $crate::GetMode;
            match $crate::_TypeRuleMarker.get_mode() {
                $crate::Mode::Search => {
                    let _t: &$a;
                }
                $crate::Mode::Replace => {
                    let _t: &$b;
                }
            }
        }
    };
}

#[macro_export]
macro_rules! replace_trait_ref {
    ($a:ty => $b:ty) => {
        {
            use $crate::GetMode;
            match $crate::_TraitRefRuleMarker.get_mode() {
                $crate::Mode::Search => {
                    let _t: &$a;
                }
                $crate::Mode::Replace => {
                    let _t: &$b;
                }
            }
        }
    };
}

/// Replaces a pattern with another pattern. A placeholder is required in order to specify the types
/// of the search and replacement pattern. Although they can be the same if you're replacing a
/// pattern with another of the same type.
///
/// # Examples
///
/// ```
/// # #[macro_use] extern crate rerast;
/// # struct Foo(i32);
/// fn some_foo_to_result_foo(p1: Option<Foo>, p2: Result<Foo, ()>) {
///     replace_pattern!(Some(f1) = p1 => Result::Ok(f1) = p2);
///     replace_pattern!(None = p1 => Result::Err(()) = p2);
/// }
/// # fn main () {}
/// ```
///
/// This will transform:
///
/// ```
/// # #[derive(Copy, Clone)] struct Foo(i32);
/// # fn f() -> Option<Foo> {Some(Foo(42))}
/// match f() {
///     Some(Foo(x)) => x,
///     None => 0,
/// }
/// ```
///
/// Into:
///
/// ```
/// # fn f() -> Foo {Foo(42)}
/// match f() {
///     Result::Ok(Foo(x)) => x,
///     Result::Err(()) => 0,
/// }
/// ```
#[macro_export]
macro_rules! replace_pattern {
    ($a:pat = $at:ident => $b:pat = $bt:ident) => {
        if false {
            use $crate::GetMode;
            match $crate::_PatternRuleMarker.get_mode() {
                $crate::Mode::Search => {
                    if let Some($a) = Some($at) {};
                }
                $crate::Mode::Replace => {
                    if let Some($b) = Some($bt) {};
                }
            }
            // Some of the placeholders used in this replace_pattern! invocation might have been
            // moved. To avoid use-after-move errors, we mark this as unreachable.
            unreachable!();
        }
    }
}

/// A placeholder that matches zero or more statements
/// IMPORTANT: This is currently broken and will most likely be replaced with a macro.
pub type Statements = &'static Fn() -> _Statements;

// These types are internal markers to help rerast find and identify things in rules. They're not
// intended to be referenced directly.
pub enum Mode {
    Search,
    Replace,
}
pub struct _Statements;
pub trait GetMode {
    fn get_mode(&self) -> Mode {
        Mode::Search
    }
}
pub struct _TypeRuleMarker;
impl GetMode for _TypeRuleMarker {}
pub struct _ExprRuleMarker;
impl GetMode for _ExprRuleMarker {}
pub struct _PatternRuleMarker;
impl GetMode for _PatternRuleMarker {}
pub struct _TraitRefRuleMarker;
impl GetMode for _TraitRefRuleMarker {}

pub const _RERAST_MACROS_SRC: &'static str = include_str!("lib.rs");
<commit_msg>Add some very basic documentation for replace_trait_ref. CI just started failing due to this being absent<commit_after>// Copyright 2017 Google Inc.
//
// 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
//
//     https://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.

// global `#[deny()]` in the processed crate affects this file as well,
// and could cause compilation-breaking warnings.
#![allow(missing_docs, warnings)]

/// Invocations of this macro instruct Rerast to replace the first expression/statement with the one
/// after the =>. For example replace!(5 => 6) says to replace all occurences of the literal 5 with
/// the literal 6.
///
/// The macro should be invoked inside a function definition. The arguments to the function
/// represent placeholders within the search and replace expressions.
#[macro_export]
macro_rules! replace {
    ($a:expr => $b:expr) => {
        // Suppress warnings about unused values in case we're replacing something like a Result.
        #[allow(unused_must_use)]
        // If we have a search or replacement pattern that is just a placeholder then this macro
        // will turn that into a statement. Normally a reference to a variable is not permitted as a
        // statement, allow it.
        #[allow(path_statements)]
        #[allow(unreachable_code)]
        {
            if false {
                use $crate::GetMode;
                match $crate::_ExprRuleMarker.get_mode() {
                    $crate::Mode::Search => {&$a;}
                    $crate::Mode::Replace => {&$b;}
                }
                // Some of the placeholders used in this replace! invocation might have been
                // moved. To avoid use-after-move errors, we mark this as unreachable.
                unreachable!();
            }
        }
    };
}

/// Replaces one type with another. This will not match trait bounds (e.g. in where clauses), since
/// they are not types. If you want to replace all references to a trait, use `replace_trait_ref!`
/// instead.
#[macro_export]
macro_rules! replace_type {
    ($a:ty => $b:ty) => {
        {
            use $crate::GetMode;
            match $crate::_TypeRuleMarker.get_mode() {
                $crate::Mode::Search => {
                    let _t: &$a;
                }
                $crate::Mode::Replace => {
                    let _t: &$b;
                }
            }
        }
    };
}

/// Replaces references to a trait with references to a different trait.
#[macro_export]
macro_rules! replace_trait_ref {
    ($a:ty => $b:ty) => {
        {
            use $crate::GetMode;
            match $crate::_TraitRefRuleMarker.get_mode() {
                $crate::Mode::Search => {
                    let _t: &$a;
                }
                $crate::Mode::Replace => {
                    let _t: &$b;
                }
            }
        }
    };
}

/// Replaces a pattern with another pattern. A placeholder is required in order to specify the types
/// of the search and replacement pattern. Although they can be the same if you're replacing a
/// pattern with another of the same type.
///
/// # Examples
///
/// ```
/// # #[macro_use] extern crate rerast;
/// # struct Foo(i32);
/// fn some_foo_to_result_foo(p1: Option<Foo>, p2: Result<Foo, ()>) {
///     replace_pattern!(Some(f1) = p1 => Result::Ok(f1) = p2);
///     replace_pattern!(None = p1 => Result::Err(()) = p2);
/// }
/// # fn main () {}
/// ```
///
/// This will transform:
///
/// ```
/// # #[derive(Copy, Clone)] struct Foo(i32);
/// # fn f() -> Option<Foo> {Some(Foo(42))}
/// match f() {
///     Some(Foo(x)) => x,
///     None => 0,
/// }
/// ```
///
/// Into:
///
/// ```
/// # fn f() -> Foo {Foo(42)}
/// match f() {
///     Result::Ok(Foo(x)) => x,
///     Result::Err(()) => 0,
/// }
/// ```
#[macro_export]
macro_rules! replace_pattern {
    ($a:pat = $at:ident => $b:pat = $bt:ident) => {
        if false {
            use $crate::GetMode;
            match $crate::_PatternRuleMarker.get_mode() {
                $crate::Mode::Search => {
                    if let Some($a) = Some($at) {};
                }
                $crate::Mode::Replace => {
                    if let Some($b) = Some($bt) {};
                }
            }
            // Some of the placeholders used in this replace_pattern! invocation might have been
            // moved. To avoid use-after-move errors, we mark this as unreachable.
            unreachable!();
        }
    }
}

/// A placeholder that matches zero or more statements
/// IMPORTANT: This is currently broken and will most likely be replaced with a macro.
pub type Statements = &'static Fn() -> _Statements;

// These types are internal markers to help rerast find and identify things in rules. They're not
// intended to be referenced directly.
pub enum Mode {
    Search,
    Replace,
}
pub struct _Statements;
pub trait GetMode {
    fn get_mode(&self) -> Mode {
        Mode::Search
    }
}
pub struct _TypeRuleMarker;
impl GetMode for _TypeRuleMarker {}
pub struct _ExprRuleMarker;
impl GetMode for _ExprRuleMarker {}
pub struct _PatternRuleMarker;
impl GetMode for _PatternRuleMarker {}
pub struct _TraitRefRuleMarker;
impl GetMode for _TraitRefRuleMarker {}

pub const _RERAST_MACROS_SRC: &'static str = include_str!("lib.rs");
<|endoftext|>


<commit_before>//! Requires the 'framework' feature flag be enabled in your project's
//! `Cargo.toml`.
//!
//! This can be enabled by specifying the feature in the dependency section:
//!
//! ```toml
//! [dependencies.serenity]
//! git = "https://github.com/serenity-rs/serenity.git"
//! features = ["framework", "standard_framework"]
//! ```
mod commands;

use std::{
    collections::HashSet,
    env,
    sync::Arc,
};
use serenity::{
    async_trait,
    client::bridge::gateway::ShardManager,
    framework::{
        StandardFramework,
        standard::macros::group,
    },
    http::Http,
    model::{event::ResumedEvent, gateway::Ready},
    prelude::*,
};

use tracing::{error, info};
use tracing_subscriber::{
    FmtSubscriber,
    EnvFilter,
};

use commands::{
    math::*,
    meta::*,
    owner::*,
};

struct ShardManagerContainer;

impl TypeMapKey for ShardManagerContainer {
    type Value = Arc<Mutex<ShardManager>>;
}

struct Handler;

#[async_trait]
impl EventHandler for Handler {
    async fn ready(&self, _: Context, ready: Ready) {
        info!("Connected as {}", ready.user.name);
    }

    async fn resume(&self, _: Context, _: ResumedEvent) {
        info!("Resumed");
    }
}

#[group]
#[commands(multiply, ping, quit)]
struct General;

#[tokio::main]
async fn main() {
    // This will load the environment variables located at `./.env`, relative to
    // the CWD. See `./.env.example` for an example on how to structure this.
    dotenv::dotenv().expect("Failed to load .env file");

    // Initialize the logger to use environment variables.
    //
    // In this case, a good default is setting the environment variable
    // `RUST_LOG` to debug`.
    let subscriber = FmtSubscriber::builder()
        .with_env_filter(EnvFilter::from_default_env())
        .finish();

    tracing::subscriber::set_global_default(subscriber).expect("Failed to start the logger");

    let token = env::var("DISCORD_TOKEN")
        .expect("Expected a token in the environment");

    let http = Http::new_with_token(&token);

    // We will fetch your bot's owners and id
    let (owners, _bot_id) = match http.get_current_application_info().await {
        Ok(info) => {
            let mut owners = HashSet::new();
            owners.insert(info.owner.id);

            (owners, info.id)
        },
        Err(why) => panic!("Could not access application info: {:?}", why),
    };

    // Create the framework
    let framework = StandardFramework::new()
        .configure(|c| c
                   .owners(owners)
                   .prefix("~"))
        .group(&GENERAL_GROUP);

    let mut client = Client::builder(&token)
        .framework(framework)
        .event_handler(Handler)
        .await
        .expect("Err creating client");

    {
        let mut data = client.data.write().await;
        data.insert::<ShardManagerContainer>(client.shard_manager.clone());
    }

    let shard_manager = client.shard_manager.clone();

    tokio::spawn(async move {
        tokio::signal::ctrl_c().await.expect("Could not register ctrl+c handler");
        shard_manager.lock().await.shutdown_all().await;
    });

    if let Err(why) = client.start().await {
        error!("Client error: {:?}", why);
    }
}
<commit_msg>Make the `ShardManagerContainer` type in example 6 public (#1093)<commit_after>//! Requires the 'framework' feature flag be enabled in your project's
//! `Cargo.toml`.
//!
//! This can be enabled by specifying the feature in the dependency section:
//!
//! ```toml
//! [dependencies.serenity]
//! git = "https://github.com/serenity-rs/serenity.git"
//! features = ["framework", "standard_framework"]
//! ```
mod commands;

use std::{
    collections::HashSet,
    env,
    sync::Arc,
};
use serenity::{
    async_trait,
    client::bridge::gateway::ShardManager,
    framework::{
        StandardFramework,
        standard::macros::group,
    },
    http::Http,
    model::{event::ResumedEvent, gateway::Ready},
    prelude::*,
};

use tracing::{error, info};
use tracing_subscriber::{
    FmtSubscriber,
    EnvFilter,
};

use commands::{
    math::*,
    meta::*,
    owner::*,
};

pub struct ShardManagerContainer;

impl TypeMapKey for ShardManagerContainer {
    type Value = Arc<Mutex<ShardManager>>;
}

struct Handler;

#[async_trait]
impl EventHandler for Handler {
    async fn ready(&self, _: Context, ready: Ready) {
        info!("Connected as {}", ready.user.name);
    }

    async fn resume(&self, _: Context, _: ResumedEvent) {
        info!("Resumed");
    }
}

#[group]
#[commands(multiply, ping, quit)]
struct General;

#[tokio::main]
async fn main() {
    // This will load the environment variables located at `./.env`, relative to
    // the CWD. See `./.env.example` for an example on how to structure this.
    dotenv::dotenv().expect("Failed to load .env file");

    // Initialize the logger to use environment variables.
    //
    // In this case, a good default is setting the environment variable
    // `RUST_LOG` to debug`.
    let subscriber = FmtSubscriber::builder()
        .with_env_filter(EnvFilter::from_default_env())
        .finish();

    tracing::subscriber::set_global_default(subscriber).expect("Failed to start the logger");

    let token = env::var("DISCORD_TOKEN")
        .expect("Expected a token in the environment");

    let http = Http::new_with_token(&token);

    // We will fetch your bot's owners and id
    let (owners, _bot_id) = match http.get_current_application_info().await {
        Ok(info) => {
            let mut owners = HashSet::new();
            owners.insert(info.owner.id);

            (owners, info.id)
        },
        Err(why) => panic!("Could not access application info: {:?}", why),
    };

    // Create the framework
    let framework = StandardFramework::new()
        .configure(|c| c
                   .owners(owners)
                   .prefix("~"))
        .group(&GENERAL_GROUP);

    let mut client = Client::builder(&token)
        .framework(framework)
        .event_handler(Handler)
        .await
        .expect("Err creating client");

    {
        let mut data = client.data.write().await;
        data.insert::<ShardManagerContainer>(client.shard_manager.clone());
    }

    let shard_manager = client.shard_manager.clone();

    tokio::spawn(async move {
        tokio::signal::ctrl_c().await.expect("Could not register ctrl+c handler");
        shard_manager.lock().await.shutdown_all().await;
    });

    if let Err(why) = client.start().await {
        error!("Client error: {:?}", why);
    }
}
<|endoftext|>


<commit_before>//! Description of how types should be formatted and parsed.

mod component;
pub mod modifier;
#[cfg(feature = "alloc")]
pub(crate) mod parse;

#[cfg(feature = "alloc")]
use alloc::string::String;
#[cfg(feature = "alloc")]
use core::fmt;

pub use self::component::Component;
#[cfg(feature = "alloc")]
pub use self::parse::parse;

/// Helper methods.
#[cfg(feature = "alloc")]
mod helper {
    /// Consume all leading whitespace, advancing `index` as appropriate.
    #[must_use = "This does not modify the original slice."]
    pub(crate) fn consume_whitespace<'a>(bytes: &'a [u8], index: &mut usize) -> &'a [u8] {
        let first_non_whitespace = bytes
            .iter()
            .position(|c| !c.is_ascii_whitespace())
            .unwrap_or(bytes.len());
        *index += first_non_whitespace;
        &bytes[first_non_whitespace..]
    }
}

/// Well-known formats, typically RFCs.
pub mod well_known {
    /// The format described in [RFC 3339](https://tools.ietf.org/html/rfc3339#section-5.6).
    #[derive(Debug, Clone, Copy, PartialEq, Eq)]
    pub struct Rfc3339;
}

/// A complete description of how to format and parse a type.
#[non_exhaustive]
#[cfg_attr(not(feature = "alloc"), derive(Debug))]
#[derive(Clone, PartialEq, Eq)]
pub enum FormatItem<'a> {
    /// Bytes that are formatted as-is.
    ///
    /// **Note**: If you call the `format` method that returns a `String`, these bytes will be
    /// passed through `String::from_utf8_lossy`.
    Literal(&'a [u8]),
    /// A minimal representation of a single non-literal item.
    Component(Component),
    /// A series of literals or components that collectively form a partial or complete
    /// description.
    Compound(&'a [Self]),
}

#[cfg(feature = "alloc")]
#[cfg_attr(__time_03_docs, doc(cfg(feature = "alloc")))]
impl fmt::Debug for FormatItem<'_> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            FormatItem::Literal(literal) => f.write_str(&String::from_utf8_lossy(literal)),
            FormatItem::Component(component) => component.fmt(f),
            FormatItem::Compound(compound) => compound.fmt(f),
        }
    }
}
<commit_msg>Remove inaccurate attribute<commit_after>//! Description of how types should be formatted and parsed.

mod component;
pub mod modifier;
#[cfg(feature = "alloc")]
pub(crate) mod parse;

#[cfg(feature = "alloc")]
use alloc::string::String;
#[cfg(feature = "alloc")]
use core::fmt;

pub use self::component::Component;
#[cfg(feature = "alloc")]
pub use self::parse::parse;

/// Helper methods.
#[cfg(feature = "alloc")]
mod helper {
    /// Consume all leading whitespace, advancing `index` as appropriate.
    #[must_use = "This does not modify the original slice."]
    pub(crate) fn consume_whitespace<'a>(bytes: &'a [u8], index: &mut usize) -> &'a [u8] {
        let first_non_whitespace = bytes
            .iter()
            .position(|c| !c.is_ascii_whitespace())
            .unwrap_or(bytes.len());
        *index += first_non_whitespace;
        &bytes[first_non_whitespace..]
    }
}

/// Well-known formats, typically RFCs.
pub mod well_known {
    /// The format described in [RFC 3339](https://tools.ietf.org/html/rfc3339#section-5.6).
    #[derive(Debug, Clone, Copy, PartialEq, Eq)]
    pub struct Rfc3339;
}

/// A complete description of how to format and parse a type.
#[non_exhaustive]
#[cfg_attr(not(feature = "alloc"), derive(Debug))]
#[derive(Clone, PartialEq, Eq)]
pub enum FormatItem<'a> {
    /// Bytes that are formatted as-is.
    ///
    /// **Note**: If you call the `format` method that returns a `String`, these bytes will be
    /// passed through `String::from_utf8_lossy`.
    Literal(&'a [u8]),
    /// A minimal representation of a single non-literal item.
    Component(Component),
    /// A series of literals or components that collectively form a partial or complete
    /// description.
    Compound(&'a [Self]),
}

#[cfg(feature = "alloc")]
impl fmt::Debug for FormatItem<'_> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            FormatItem::Literal(literal) => f.write_str(&String::from_utf8_lossy(literal)),
            FormatItem::Component(component) => component.fmt(f),
            FormatItem::Compound(compound) => compound.fmt(f),
        }
    }
}
<|endoftext|>


<commit_before>#![allow(dead_code)]
use raft::raftpb::{Entry, Snapshot};
use std::collections::VecDeque;

// unstable.entris[i] has raft log position i+unstable.offset.
// Note that unstable.offset may be less than the highest log
// position in storage; this means that the next write to storage
// might need to truncate the log before persisting unstable.entries.
pub struct Unstable {
    // the incoming unstable snapshot, if any.
    snapshot: Option<Box<Snapshot>>,
    // all entries that have not yet been written to storage.
    entries: VecDeque<Entry>,
    offset: u64,
}

impl Unstable {
    // maybe_first_index returns the last index if it has at least one
    // unstable entry or snapshot.
    fn maybe_first_index(&self) -> Option<u64> {
        self.snapshot
            .as_ref()
            .map_or(None, |snap| Some(snap.get_metadata().get_index() + 1))
    }

    // maybe_last_index returns the last index if it has at least one
    // unstable entry or snapshot.
    fn maybe_last_index(&self) -> Option<u64> {
        match self.entries.len() {
            0 => {
                self.snapshot
                    .as_ref()
                    .map_or(None, |snap| Some(snap.get_metadata().get_index()))
            }
            len => Some(self.offset + len as u64 - 1),
        }
    }

    // maybe_term returns the term of the entry at index idx, if there
    // is any.
    fn maybe_term(&self, idx: u64) -> Option<u64> {
        if idx < self.offset {
            if self.snapshot.is_none() {
                return None;
            }

            let meta = self.snapshot.as_ref().unwrap().get_metadata().clone();
            if idx == meta.get_index() {
                return Some(meta.get_term());
            }
            return None;
        }
        match self.maybe_last_index() {
            None => None,
            Some(last) => {
                if idx > last {
                    return None;
                }
                Some(self.entries[(idx - self.offset) as usize].get_Term())
            }
        }
    }

    fn stable_to(&mut self, idx: u64, term: u64) {
        let t = self.maybe_term(idx);
        if t.is_none() {
            return;
        }

        if t.unwrap() == term && idx >= self.offset {
            let start = idx + 1 - self.offset;
            for _ in 0..start {
                self.entries.pop_front();
            }
            self.offset = idx + 1;
        }
    }

    fn stable_snap_to(&mut self, idx: u64) {
        if self.snapshot.is_none() {
            return;
        }
        if idx == self.snapshot.as_ref().unwrap().get_metadata().get_index() {
            self.snapshot = None;
        }
    }

    fn restore(&mut self, snap: Snapshot) {
        self.offset = snap.get_metadata().get_index() + 1;
        self.entries.clear();
        self.snapshot = Some(Box::new(snap));
    }

    fn truncate_and_append(&mut self, ents: &[Entry]) {
        let after = ents[0].get_Index() - 1;
        if after == self.offset + self.entries.len() as u64 - 1 {
            for e in ents {
                self.entries.push_back(e.clone());
            }
        } else if after < self.offset {
            // The log is being truncated to before our current offset
            // portion, so set the offset and replace the entries
            self.offset = after + 1;
            self.entries.clear();

            for e in ents {
                self.entries.push_back(e.clone());
            }
        } else {
            // truncate to after and copy to self.entries
            // then append
            let off = self.offset.clone();
            let cut_ents = self.cut_slice(off, after + 1);
            self.entries.clear();
            for e in cut_ents {
                self.entries.push_back(e);
            }

            for e in ents {
                self.entries.push_back(e.clone());
            }
        }
    }

    fn cut_slice(&mut self, lo: u64, hi: u64) -> Vec<Entry> {
        self.must_check_outofbounds(lo, hi);
        let l = lo as usize;
        let h = lo as usize;
        let off = self.offset as usize;
        return self.entries.drain(l - off..h - off).map(|e| e).collect();
    }

    fn must_check_outofbounds(&self, lo: u64, hi: u64) {
        if lo > hi {
            panic!("invalid unstable.slice {} > {}", lo, hi)
        }
        let upper = self.offset + self.entries.len() as u64;
        if lo < self.offset || hi > upper {
            panic!("unstable.slice[{}, {}] out of bound[{}, {}]",
                   lo,
                   hi,
                   self.offset,
                   upper)
        }
    }
}

mod test {
    use raft::raftpb::{Entry, Snapshot};
    use raft::log_unstable::Unstable;
    pub struct Obj {
        entry: Entry,
        offset: u64,
        snap: Option<Snapshot>,

        wok: bool,
        windex: u64,
    }

    fn new_entry(index: u64, term: u64) -> Entry {
        let mut e = Entry::new();
        e.set_Term(term);
        e.set_Index(index);
        e
    }

    fn new_obj(entry: Entry, offset: u64, snap: Option<Snapshot>, wok: bool, windex: u64) -> Obj {
        Obj {
            entry: entry,
            offset: offset,
            snap: snap,
            wok: wok,
            windex: windex,
        }
    }

    fn new_snapshot(index: u64, term: u64) -> Snapshot {
        use raft::raftpb::{SnapshotMetadata, Snapshot};
        let mut snap = Snapshot::new();
        let mut meta = SnapshotMetadata::new();
        meta.set_index(index);
        meta.set_term(term);
        snap.set_metadata(meta);
        snap
    }

    #[test]
    #[cfg(test)]
    fn test_maybe_first_index() {
        let tests: Vec<Obj> = vec![
            // no snapshot
            new_obj(new_entry(5,1), 5, None, false, 0),
            new_obj( Entry::new(), 0, None, false, 0,),
            // has snapshot
            new_obj( new_entry(5, 1), 5, Some(new_snapshot(4,1)), true, 5,),
            new_obj( Entry::new(), 5, Some(new_snapshot(4,1)), true, 5,),
        ];

        for tt in tests {
            let u = Unstable {
                entries: vec![tt.entry].into_iter().collect(),
                offset: tt.offset,
                snapshot: tt.snap.map_or(None, |snap| Some(Box::new(snap))),
            };
            let index = u.maybe_first_index();
            if index.is_none() {
                assert!(!tt.wok);
            } else {
                assert_eq!(index.unwrap(), tt.windex);
            }
        }
    }
}
<commit_msg>Tiny clean up<commit_after>#![allow(dead_code)]
use raft::raftpb::{Entry, Snapshot};
use std::collections::VecDeque;

// unstable.entris[i] has raft log position i+unstable.offset.
// Note that unstable.offset may be less than the highest log
// position in storage; this means that the next write to storage
// might need to truncate the log before persisting unstable.entries.
pub struct Unstable {
    // the incoming unstable snapshot, if any.
    snapshot: Option<Box<Snapshot>>,
    // all entries that have not yet been written to storage.
    entries: VecDeque<Entry>,
    offset: u64,
}

impl Unstable {
    // maybe_first_index returns the last index if it has at least one
    // unstable entry or snapshot.
    fn maybe_first_index(&self) -> Option<u64> {
        self.snapshot
            .as_ref()
            .map_or(None, |snap| Some(snap.get_metadata().get_index() + 1))
    }

    // maybe_last_index returns the last index if it has at least one
    // unstable entry or snapshot.
    fn maybe_last_index(&self) -> Option<u64> {
        match self.entries.len() {
            0 => {
                self.snapshot
                    .as_ref()
                    .map_or(None, |snap| Some(snap.get_metadata().get_index()))
            }
            len => Some(self.offset + len as u64 - 1),
        }
    }

    // maybe_term returns the term of the entry at index idx, if there
    // is any.
    fn maybe_term(&self, idx: u64) -> Option<u64> {
        if idx < self.offset {
            if self.snapshot.is_none() {
                return None;
            }

            let meta = self.snapshot.as_ref().unwrap().get_metadata().clone();
            if idx == meta.get_index() {
                return Some(meta.get_term());
            }
            return None;
        }
        match self.maybe_last_index() {
            None => None,
            Some(last) => {
                if idx > last {
                    return None;
                }
                Some(self.entries[(idx - self.offset) as usize].get_Term())
            }
        }
    }

    fn stable_to(&mut self, idx: u64, term: u64) {
        let t = self.maybe_term(idx);
        if t.is_none() {
            return;
        }

        if t.unwrap() == term && idx >= self.offset {
            let start = idx + 1 - self.offset;
            for _ in 0..start {
                self.entries.pop_front();
            }
            self.offset = idx + 1;
        }
    }

    fn stable_snap_to(&mut self, idx: u64) {
        if self.snapshot.is_none() {
            return;
        }
        if idx == self.snapshot.as_ref().unwrap().get_metadata().get_index() {
            self.snapshot = None;
        }
    }

    fn restore(&mut self, snap: Snapshot) {
        self.offset = snap.get_metadata().get_index() + 1;
        self.entries.clear();
        self.snapshot = Some(Box::new(snap));
    }

    fn truncate_and_append(&mut self, ents: &[Entry]) {
        let after = ents[0].get_Index() - 1;
        if after == self.offset + self.entries.len() as u64 - 1 {
            for e in ents {
                self.entries.push_back(e.clone());
            }
        } else if after < self.offset {
            // The log is being truncated to before our current offset
            // portion, so set the offset and replace the entries
            self.offset = after + 1;
            self.entries.clear();

            for e in ents {
                self.entries.push_back(e.clone());
            }
        } else {
            // truncate to after and copy to self.entries
            // then append
            let off = self.offset.clone();
            let cut_ents = self.cut_slice(off, after + 1);
            self.entries.clear();
            for e in cut_ents {
                self.entries.push_back(e);
            }

            for e in ents {
                self.entries.push_back(e.clone());
            }
        }
    }

    fn cut_slice(&mut self, lo: u64, hi: u64) -> Vec<Entry> {
        self.must_check_outofbounds(lo, hi);
        let l = lo as usize;
        let h = lo as usize;
        let off = self.offset as usize;
        return self.entries.drain(l - off..h - off).map(|e| e).collect();
    }

    fn must_check_outofbounds(&self, lo: u64, hi: u64) {
        if lo > hi {
            panic!("invalid unstable.slice {} > {}", lo, hi)
        }
        let upper = self.offset + self.entries.len() as u64;
        if lo < self.offset || hi > upper {
            panic!("unstable.slice[{}, {}] out of bound[{}, {}]",
                   lo,
                   hi,
                   self.offset,
                   upper)
        }
    }
}

mod test {
    use raft::raftpb::{Entry, Snapshot};
    use raft::log_unstable::Unstable;
    pub struct Obj {
        entry: Entry,
        offset: u64,
        snap: Option<Snapshot>,

        wok: bool,
        windex: u64,
    }

    fn new_entry(index: u64, term: u64) -> Entry {
        let mut e = Entry::new();
        e.set_Term(term);
        e.set_Index(index);
        e
    }

    fn new_obj(entry: Entry, offset: u64, snap: Option<Snapshot>, wok: bool, windex: u64) -> Obj {
        Obj {
            entry: entry,
            offset: offset,
            snap: snap,
            wok: wok,
            windex: windex,
        }
    }

    fn new_snapshot(index: u64, term: u64) -> Snapshot {
        use raft::raftpb::{SnapshotMetadata, Snapshot};
        let mut snap = Snapshot::new();
        let mut meta = SnapshotMetadata::new();
        meta.set_index(index);
        meta.set_term(term);
        snap.set_metadata(meta);
        snap
    }

    #[test]
    #[cfg(test)]
    fn test_maybe_first_index() {
        let tests: Vec<Obj> = vec![
            // no snapshot
            new_obj(new_entry(5,1), 5, None, false, 0),
            new_obj( Entry::new(), 0, None, false, 0,),
            // has snapshot
            new_obj( new_entry(5, 1), 5, Some(new_snapshot(4,1)), true, 5,),
            new_obj( Entry::new(), 5, Some(new_snapshot(4,1)), true, 5,),
        ];

        for tt in tests {
            let u = Unstable {
                entries: vec![tt.entry].into_iter().collect(),
                offset: tt.offset,
                snapshot: tt.snap.map_or(None, |snap| Some(Box::new(snap))),
            };
            let index = u.maybe_first_index();
            match index {
                None => assert!(!tt.wok),
                Some(index) => assert_eq!(index, tt.windex),
            }
        }
    }
}
<|endoftext|>


<commit_before>pub use self::DecodeError::*;
use std::fmt;

const BASE: u128 = 62;
const MAX_DECODED_LEN: usize = 111;
const ALPHABET: [u8; BASE as usize] = [
    b'0', b'1', b'2', b'3', b'4', b'5', b'6', b'7', b'8', b'9', b'A', b'B', b'C', b'D', b'E', b'F',
    b'G', b'H', b'I', b'J', b'K', b'L', b'M', b'N', b'O', b'P', b'Q', b'R', b'S', b'T', b'U', b'V',
    b'W', b'X', b'Y', b'Z', b'a', b'b', b'c', b'd', b'e', b'f', b'g', b'h', b'i', b'j', b'k', b'l',
    b'm', b'n', b'o', b'p', b'q', b'r', b's', b't', b'u', b'v', b'w', b'x', b'y', b'z',
];

#[derive(PartialEq)]
pub enum DecodeError {
    InvalidBase62Byte(char, usize),
    ArithmeticOverflow,
}

impl fmt::Debug for DecodeError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            InvalidBase62Byte(ch, idx) => {
                write!(f, "Invalid character '{}' at position {}", ch, idx)
            }
            ArithmeticOverflow => write!(f, "Decode result is too large"),
        }
    }
}

impl fmt::Display for DecodeError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Debug::fmt(&self, f)
    }
}

///Encode any uint as base64.
///Returns a String.
///
///# Example
///
///```rust
///extern crate base62;
///
///fn main() {
///    let b62 = base62::encode(1337u32);
///    println!("{}", b62);
///}
///```
#[must_use]
pub fn encode<T: Into<u128>>(num: T) -> String {
    let mut buf = String::with_capacity(MAX_DECODED_LEN);
    encode_buf(num, &mut buf);
    buf
}

///Encode any uint as base64.
///Writes into the supplied output buffer, which will grow the buffer if needed.
///
///# Example
///
///```rust
///extern crate base62;
///
///fn main() {
///    let mut buf = String::new();
///    base62::encode_buf(1337u32, &mut buf);
///    println!("{}", buf);
///}
///```
pub fn encode_buf<T: Into<u128>>(num: T, buf: &mut String) {
    let mut num = num.into();
    if num == 0 {
        *buf = "0".to_owned();
        return;
    }
    let mut bytes: [u8; MAX_DECODED_LEN] = [0; MAX_DECODED_LEN];

    let mut i: usize = MAX_DECODED_LEN;
    loop {
        if num == 0 {
            break;
        }
        i -= 1;

        bytes[i] = ALPHABET[(num % BASE) as usize];
        num /= BASE;
    }

    *buf = String::from_utf8(bytes[i..MAX_DECODED_LEN].to_vec()).unwrap();
}

///Decode from string reference as octets.
///Returns a Result containing a u128 which can be downcasted to any other uint.
///
///# Example
///
///```rust
///extern crate base62;
///
///fn main() {
///    let bytes = base62::decode("rustlang").unwrap();
///    println!("{:?}", bytes);
///}
///```
pub fn decode<T: AsRef<[u8]>>(input: T) -> Result<u128, DecodeError> {
    let mut result = 0u128;
    let input = input.as_ref();

    for (i, c) in input.iter().rev().enumerate() {
        let num = BASE.checked_pow(i as u32).ok_or(ArithmeticOverflow)?;
        match ALPHABET.binary_search(&c) {
            Ok(v) => match (v as u128).checked_mul(num) {
                Some(z) => result = result.checked_add(z as u128).ok_or(ArithmeticOverflow)?,
                None => return Err(ArithmeticOverflow),
            },
            Err(_e) => {
                return Err(InvalidBase62Byte(c.to_owned() as char, input.len() - i));
            }
        }
    }

    Ok(result)
}

#[cfg(test)]
mod tests {
    use crate::base62;
    use crate::base62::DecodeError;
    use quickcheck::{quickcheck, TestResult};

    quickcheck! {
        fn encode_decode(xs: u128) -> bool {
            let encoded = base62::encode(xs);
            xs == base62::decode(&encoded).unwrap()
        }
    }

    quickcheck! {
        fn decode_good(xs: String) -> TestResult {
            if xs.chars().all(|c| c.is_ascii() && base62::ALPHABET.binary_search(&(c as u8)).is_ok()) && !xs.is_empty() {
                return TestResult::from_bool(base62::decode(&xs).is_ok());
            } else {
                TestResult::discard()
            }
        }
    }

    quickcheck! {
        fn decode_bad(xs: String) -> TestResult {
            if xs.chars().all(|c| c.is_ascii() && base62::ALPHABET.binary_search(&(c as u8)).is_ok()) {
                TestResult::discard()
            } else {
                return TestResult::from_bool(base62::decode(&xs).is_err());
            }
        }
    }

    #[test]
    fn test_encode() {
        assert_eq!(base62::encode(u128::MAX), "7n42DGM5Tflk9n8mt7Fhc7");
        assert_eq!(base62::encode(0u8), "0");
    }

    #[test]
    fn test_encode_buf() {
        let mut buf = String::new();
        base62::encode_buf(u128::MAX, &mut buf);
        assert_eq!(buf, "7n42DGM5Tflk9n8mt7Fhc7");
    }

    #[test]
    fn test_decode() {
        assert_eq!(base62::decode("7n42DGM5Tflk9n8mt7Fhc7").unwrap(), u128::MAX);
        assert_eq!(base62::decode("").unwrap(), 0);
    }

    #[test]
    fn test_decode_invalid_char() {
        assert_eq!(
            base62::decode("ds{Z455f"),
            Err(DecodeError::InvalidBase62Byte('{', 3))
        );
    }

    #[test]
    fn test_decode_long_string() {
        assert_eq!(
            base62::decode("7n42DGM5Tflk9n8mt7Fhc7B"),
            Err(DecodeError::ArithmeticOverflow)
        );
    }
}
<commit_msg>Better use of generics<commit_after>pub use self::DecodeError::*;
use std::fmt;

const BASE: u128 = 62;
const MAX_DECODED_LEN: usize = 111;
const ALPHABET: [u8; BASE as usize] = [
    b'0', b'1', b'2', b'3', b'4', b'5', b'6', b'7', b'8', b'9', b'A', b'B', b'C', b'D', b'E', b'F',
    b'G', b'H', b'I', b'J', b'K', b'L', b'M', b'N', b'O', b'P', b'Q', b'R', b'S', b'T', b'U', b'V',
    b'W', b'X', b'Y', b'Z', b'a', b'b', b'c', b'd', b'e', b'f', b'g', b'h', b'i', b'j', b'k', b'l',
    b'm', b'n', b'o', b'p', b'q', b'r', b's', b't', b'u', b'v', b'w', b'x', b'y', b'z',
];

#[derive(PartialEq)]
pub enum DecodeError {
    InvalidBase62Byte(char, usize),
    ArithmeticOverflow,
}

impl fmt::Debug for DecodeError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            InvalidBase62Byte(ch, idx) => {
                write!(f, "Invalid character '{}' at position {}", ch, idx)
            }
            ArithmeticOverflow => write!(f, "Decode result is too large"),
        }
    }
}

impl fmt::Display for DecodeError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Debug::fmt(&self, f)
    }
}

/// Encode any uint as base64.
/// Returns a String.
///
/// # Example
///
/// ```rust
/// extern crate base62;
///
/// fn main() {
///     let b62 = base62::encode(1337u32);
///     println!("{}", b62);
/// }
/// ```
#[must_use]
pub fn encode<T: Into<u128>>(num: T) -> String {
    _encode(num.into())
}

fn _encode(num: u128) -> String {
    let mut buf = String::with_capacity(MAX_DECODED_LEN);
    encode_buf(num, &mut buf);
    buf
}

/// Encode any uint as base64.
/// Writes into the supplied output buffer, which will grow the buffer if needed.
///
/// # Example
///
/// ```rust
/// extern crate base62;
///
/// fn main() {
///     let mut buf = String::new();
///     base62::encode_buf(1337u32, &mut buf);
///     println!("{}", buf);
/// }
/// ```
pub fn encode_buf<T: Into<u128>>(num: T, buf: &mut String) {
    _encode_buf(num.into(), buf)
}

fn _encode_buf(mut num: u128, buf: &mut String) {
    if num == 0 {
        *buf = "0".to_owned();
        return;
    }
    let mut bytes: [u8; MAX_DECODED_LEN] = [0; MAX_DECODED_LEN];

    let mut i: usize = MAX_DECODED_LEN;
    loop {
        if num == 0 {
            break;
        }
        i -= 1;

        bytes[i] = ALPHABET[(num % BASE) as usize];
        num /= BASE;
    }

    *buf = String::from_utf8(bytes[i..MAX_DECODED_LEN].to_vec()).unwrap();
}

/// Decode from string reference as octets.
/// Returns a Result containing a u128 which can be downcasted to any other uint.
///
/// # Example
///
/// ```rust
/// extern crate base62;
///
/// fn main() {
///     let bytes = base62::decode("rustlang").unwrap();
///     println!("{:?}", bytes);
/// }
/// ```
pub fn decode<T: AsRef<[u8]>>(input: T) -> Result<u128, DecodeError> {
    _decode(input.as_ref())
}

fn _decode(input: &[u8]) -> Result<u128, DecodeError> {
    let mut result = 0u128;

    for (i, c) in input.iter().rev().enumerate() {
        let num = BASE.checked_pow(i as u32).ok_or(ArithmeticOverflow)?;
        match ALPHABET.binary_search(&c) {
            Ok(v) => match (v as u128).checked_mul(num) {
                Some(z) => result = result.checked_add(z as u128).ok_or(ArithmeticOverflow)?,
                None => return Err(ArithmeticOverflow),
            },
            Err(_e) => {
                return Err(InvalidBase62Byte(c.to_owned() as char, input.len() - i));
            }
        }
    }

    Ok(result)
}

#[cfg(test)]
mod tests {
    use crate::base62;
    use crate::base62::DecodeError;
    use quickcheck::{quickcheck, TestResult};

    quickcheck! {
        fn encode_decode(xs: u128) -> bool {
            let encoded = base62::encode(xs);
            xs == base62::decode(&encoded).unwrap()
        }
    }

    quickcheck! {
        fn decode_good(xs: String) -> TestResult {
            if xs.chars().all(|c| c.is_ascii() && base62::ALPHABET.binary_search(&(c as u8)).is_ok()) && !xs.is_empty() {
                return TestResult::from_bool(base62::decode(&xs).is_ok());
            } else {
                TestResult::discard()
            }
        }
    }

    quickcheck! {
        fn decode_bad(xs: String) -> TestResult {
            if xs.chars().all(|c| c.is_ascii() && base62::ALPHABET.binary_search(&(c as u8)).is_ok()) {
                TestResult::discard()
            } else {
                return TestResult::from_bool(base62::decode(&xs).is_err());
            }
        }
    }

    #[test]
    fn test_encode() {
        assert_eq!(base62::encode(u128::MAX), "7n42DGM5Tflk9n8mt7Fhc7");
        assert_eq!(base62::encode(0u8), "0");
    }

    #[test]
    fn test_encode_buf() {
        let mut buf = String::new();
        base62::encode_buf(u128::MAX, &mut buf);
        assert_eq!(buf, "7n42DGM5Tflk9n8mt7Fhc7");
    }

    #[test]
    fn test_decode() {
        assert_eq!(base62::decode("7n42DGM5Tflk9n8mt7Fhc7").unwrap(), u128::MAX);
        assert_eq!(base62::decode("").unwrap(), 0);
    }

    #[test]
    fn test_decode_invalid_char() {
        assert_eq!(
            base62::decode("ds{Z455f"),
            Err(DecodeError::InvalidBase62Byte('{', 3))
        );
    }

    #[test]
    fn test_decode_long_string() {
        assert_eq!(
            base62::decode("7n42DGM5Tflk9n8mt7Fhc7B"),
            Err(DecodeError::ArithmeticOverflow)
        );
    }
}
<|endoftext|>


<commit_before>#![deny(warnings)]

extern crate coreutils;

use std::env;
use std::fs;
use std::io::{stdout, stderr, Seek, SeekFrom, Write};
use coreutils::extra::{OptionalExt, WriteExt};

fn print_path(path: &str) {
    let stdout = stdout();
    let mut stdout = stdout.lock();
    let mut stderr = stderr();
    let mut entries = Vec::new();

    let dir = fs::read_dir(path).try(&mut stderr);

    for entry_result in dir {
        let entry = entry_result.try(&mut stderr);

        let file_type = entry.file_type().try(&mut stderr);
        let directory = file_type.is_dir();

        if let Some(path_str) = entry.file_name().to_str() {
            entries.push(path_str.to_owned());
            if directory {
                entries.last_mut().unwrap().push('/');
            }
        } else {
            stderr.writeln(b"warning: failed to convert path to a valid string.").try(&mut stderr);
        }
    }

    entries.sort();

    for entry in entries.iter() {
        let mut entry_path = path.to_owned();
        if !entry_path.ends_with('/') {
            entry_path.push('/');
        }
        entry_path.push_str(entry);

        let mut file = fs::File::open(&entry_path).try(&mut stderr);
        let size = file.seek(SeekFrom::End(0)).try(&mut stderr);

        stdout.write(((size + 1023) / 1024).to_string().as_bytes()).try(&mut stderr);
        stdout.write(b"    ").try(&mut stderr);
        stdout.writeln(entry.as_bytes()).try(&mut stderr);
    }
}
fn main() {
    if let Some(ref x) = env::args().nth(1) {
        print_path(x);
    } else {
        print_path(".");
    }
}
<commit_msg>Use fs::metadata for du (much faster)<commit_after>#![deny(warnings)]

extern crate coreutils;

use std::env;
use std::fs;
use std::io::{stdout, stderr, Write};
use coreutils::extra::{OptionalExt, WriteExt};

fn print_path(path: &str) {
    let stdout = stdout();
    let mut stdout = stdout.lock();
    let mut stderr = stderr();
    let mut entries = Vec::new();

    let dir = fs::read_dir(path).try(&mut stderr);

    for entry_result in dir {
        let entry = entry_result.try(&mut stderr);

        let file_type = entry.file_type().try(&mut stderr);
        let directory = file_type.is_dir();

        if let Some(path_str) = entry.file_name().to_str() {
            entries.push(path_str.to_owned());
            if directory {
                entries.last_mut().unwrap().push('/');
            }
        } else {
            stderr.writeln(b"warning: failed to convert path to a valid string.").try(&mut stderr);
        }
    }

    entries.sort();

    for entry in entries.iter() {
        let mut entry_path = path.to_owned();
        if !entry_path.ends_with('/') {
            entry_path.push('/');
        }
        entry_path.push_str(entry);

        let metadata = fs::metadata(&entry_path).try(&mut stderr);
        let size = metadata.len();

        stdout.write(((size + 1023) / 1024).to_string().as_bytes()).try(&mut stderr);
        stdout.write(b"    ").try(&mut stderr);
        stdout.writeln(entry.as_bytes()).try(&mut stderr);
    }
}
fn main() {
    if let Some(ref x) = env::args().nth(1) {
        print_path(x);
    } else {
        print_path(".");
    }
}
<|endoftext|>


<commit_before>use std::num::{Zero, One};

fn omit_zeros<'a, T: Zero>(v: &'a [T]) -> &'a [T] {
    let len = v.iter().rposition(|n| !n.is_zero()).map_or(0, |p| p + 1);
    return v.slice(0, len);
}

pub fn add<T: Zero + Add<T,T> + Clone>(a: &[T], b: &[T]) -> Vec<T> {
    let a = omit_zeros(a);
    let b = omit_zeros(b);

    let (min_len, max_len, rest) = match a.len().cmp(&b.len()) {
        Less    => (a.len(), b.len(), Some(b)),
        Greater => (b.len(), a.len(), Some(a)),
        Equal   => (a.len(), a.len(), None)
    };

    let mut sum = Vec::from_fn(max_len, |_i| Zero::zero());
    for i in range(0, min_len) { *sum.get_mut(i) = a[i] + b[i]; }
    rest.map(|v| { for i in range(min_len, max_len) { *sum.get_mut(i) = v[i].clone(); } });
    sum
}

pub fn mul<T: Zero + Add<T, T> + Mul<T, T>>(a: &[T], b: &[T]) -> Vec<T> {
    let a = omit_zeros(a);
    let b = omit_zeros(b);

    if a.is_empty() || b.is_empty() { return vec![]; }
    let mut prod: Vec<T> = Vec::from_fn(a.len() + b.len() - 1, |_i| Zero::zero());
    for (i, na) in a.iter().enumerate() {
        for (j, nb) in b.iter().enumerate() {
            *prod.get_mut(i + j) = *prod.get(i + j) + (*na) * (*nb);
        }
    }
    prod.move_iter().collect()
}

pub fn eval<T: Zero + One + Add<T, T> + Mul<T, T>>(a: &[T], x: T) -> T {
    let mut sum: T = Zero::zero();
    let mut x_n = One::one();
    for i in range(0, a.len()) {
        sum = sum + a[i] * x_n;
        x_n = x_n * x;
    }
    return sum;
}

pub fn to_str<T: Zero + One + Eq + Neg<T> + ToStr + Ord>(a: &[T], x: &str) -> ~str {
    let a = omit_zeros(a);
    if a.is_empty() { return "0".to_owned(); }

    let one = One::one();

    let mut s = Vec::new();
    for (i, n) in a.iter().enumerate() {
        // output n*x^i / -n*x^i
        if n.is_zero() { continue }

        let term = if i.is_zero() {
            n.to_str()
        } else if i == 1 {
            if (*n) == one { x.to_str() }
            else if (*n) == -one { format!("-{}", x) }
            else { format!("{}*{}", n.to_str(), x) }
        } else {
            if (*n) == one { format!("{}^{}", x, i) }
            else if (*n) == -one { format!("-{}^{}", x, i) }
            else { format!("{}*{}^{}", n.to_str(), x, i) }
        };

        if s.len() > 0 && (*n) > Zero::zero() { s.push("+".to_owned()); }
        s.push(term);
    }

    s.concat()
}

#[cfg(test)]
mod tests {
    #[test]
    fn test_poly_add() {
        fn check(a: &[int], b: &[int], c: &[int]) {
            assert_eq!(super::add(a, b).as_slice(), c);
            assert_eq!(super::add(b, a).as_slice(), c);
        }
        check([], [], []);
        check([0, 0], [], []);
        check([0, 0], [1], [1]);
        check([1, 0], [1], [2]);
        check([1, 0, 1], [1], [2, 0, 1]);
    }

    #[test]
    fn test_poly_mul() {
        fn check(a: &[int], b: &[int], c: &[int]) {
            assert_eq!(super::mul(a, b).as_slice(), c);
            assert_eq!(super::mul(b, a).as_slice(), c);
        }
        check([], [], []);
        check([0, 0], [], []);
        check([0, 0], [1], []);
        check([1, 0], [1], [1]);
        check([1, 0, 1], [1], [1, 0, 1]);
        check([1, 1], [1, 1], [1, 2, 1]);
        check([1, 1], [1, 0, 1], [1, 1, 1, 1]);
        check([0, 0, 1], [0, 0, 1], [0, 0, 0, 0, 1]);
    }

    #[test]
    fn test_poly_eaval() {
        fn check(pol: &[int], f: |int| -> int) {
            for n in range(-10, 10) {
                assert_eq!(super::eval(pol, n), f(n));
            }
        }
        check([], |_x| 0);
        check([1], |_x| 1);
        check([1, 1], |x| x + 1);
        check([0, 1], |x| x);
        check([10, -10, 10], |x| 10*x*x - 10 * x + 10);
    }

    #[test]
    fn test_poly_to_str() {
        assert_eq!(super::to_str::<int>([], "x"), "0".to_owned());
        assert_eq!(super::to_str([1], "x"), "1".to_owned());
        assert_eq!(super::to_str([1, 1], "x"), "1+x".to_owned());
        assert_eq!(super::to_str([1, 1, 1], "x"), "1+x+x^2".to_owned());
        assert_eq!(super::to_str([2, 2, 2], "x"), "2+2*x+2*x^2".to_owned());
        assert_eq!(super::to_str([0, 0, 0, 1], "x"), "x^3".to_owned());
        assert_eq!(super::to_str([0, 0, 0, -1], "x"), "-x^3".to_owned());
        assert_eq!(super::to_str([-1, 0, 0, -1], "x"), "-1-x^3".to_owned());
        assert_eq!(super::to_str([-1, 1, 0, -1], "x"), "-1+x-x^3".to_owned());
        assert_eq!(super::to_str([-1, 1, -1, -1], "x"), "-1+x-x^2-x^3".to_owned());
    }
}
<commit_msg>add std::poly::Poly<commit_after>use std::{cmp, fmt, num};
use std::num::{Zero, One};

#[deriving(Eq, Clone, Show)]
pub struct Poly<T> { data: Vec<T> }

impl<T: Zero> Poly<T> {
    #[inline]
    pub fn new(mut data: Vec<T>) -> Poly<T> {
        while data.last().map(|x| x.is_zero()).unwrap_or(false) {
            data.pop();
        }
        Poly { data: data }
    }
}

impl<T: Clone + Zero> Poly<T> {
    #[inline]
    pub fn from_slice(data: &[T]) -> Poly<T> {
        Poly { data: Vec::from_slice(omit_zeros(data))}
    }
}

impl<T: Zero + One> Poly<T> {
    #[inline]
    pub fn eval(&self, x: T) -> T {
        let mut sum = num::zero::<T>();
        let mut x_n = num::one::<T>();
        for n in self.data.iter() {
            sum = sum + (*n) * x_n;
            x_n = x_n * x;
        }
        sum
    }
}

impl<T> Poly<T> {
    #[inline]
    pub fn as_slice<'a>(&'a self) -> &'a [T] { self.data.as_slice() }
    #[inline]
    pub fn into_vec(self) -> Vec<T> { self.data }
}

impl<T: Zero + One + Eq + Neg<T> + Ord + fmt::Show> Poly<T> {
    pub fn pretty(&self, x: &str) -> ~str {
        if self.is_zero() { return "0".to_owned() }

        let one = One::one();
        let mut s = Vec::new();
        for (i, n) in self.data.iter().enumerate() {
            // output n*x^i / -n*x^i
            if n.is_zero() { continue }

            let term = if i.is_zero() {
                n.to_str()
            } else if i == 1 {
                if (*n) == one { x.to_str() }
                else if (*n) == -one { format!("-{}", x) }
                else { format!("{}*{}", n.to_str(), x) }
            } else {
                if (*n) == one { format!("{}^{}", x, i) }
                else if (*n) == -one { format!("-{}^{}", x, i) }
                else { format!("{}*{}^{}", n.to_str(), x, i) }
            };

            if s.len() > 0 && (*n) > Zero::zero() { s.push("+".to_owned()); }
            s.push(term);
        }

        s.concat()
    }
}

impl<T: Zero> Zero for Poly<T> {
    #[inline]
    fn zero() -> Poly<T> { Poly { data: vec![] } }
    #[inline]
    fn is_zero(&self) -> bool { self.data.is_empty() }
}

impl<T: Zero + One> One for Poly<T> {
    #[inline]
    fn one() -> Poly<T> { Poly { data: vec![One::one()] } }
}

impl<T: Neg<T> + Zero> Neg<Poly<T>> for Poly<T> {
    #[inline]
    fn neg(&self) -> Poly<T> {
        Poly::new(self.data.iter().map(|x| -(*x)).collect())
    }
}

impl<T: Zero + Add<T, T>> Add<Poly<T>, Poly<T>> for Poly<T> {
    fn add(&self, other: &Poly<T>) -> Poly<T> {
        let bigger = if self.data.len() <= other.data.len() { other } else { self };
        let min_len = cmp::min(self.data.len(), other.data.len());
        let max_len = cmp::max(self.data.len(), other.data.len());

        let mut sum = Vec::with_capacity(max_len);
        for i in range(0, min_len) {
            sum.push(*self.data.get(i) + *other.data.get(i));
        }
        for i in range(min_len, max_len) {
            sum.push(*bigger.data.get(i) + Zero::zero())
        }
        Poly::new(sum)
    }
}

impl<T: Zero + Sub<T, T>> Sub<Poly<T>, Poly<T>> for Poly<T> {
    fn sub(&self, other: &Poly<T>) -> Poly<T> {
        let min_len = cmp::min(self.data.len(), other.data.len());
        let max_len = cmp::max(self.data.len(), other.data.len());

        let mut sub = Vec::with_capacity(max_len);
        for i in range(0, min_len) {
            sub.push(*self.data.get(i) - *other.data.get(i));
        }
        if self.data.len() <= other.data.len() {
            for i in range(min_len, max_len) {
                sub.push(num::zero::<T>() - *other.data.get(i))
            }
        } else {
            for i in range(min_len, max_len) {
                sub.push(*self.data.get(i) + Zero::zero())
            }
        }
        Poly::new(sub)
    }
}

impl<T: Zero + Mul<T, T>> Mul<Poly<T>, Poly<T>> for Poly<T> {
    fn mul(&self, other: &Poly<T>) -> Poly<T> {
        if self.is_zero() || other.is_zero() { return Zero::zero() }

        let mut prod: Vec<T> = Vec::from_fn(self.data.len() + other.data.len() - 1, |_| Zero::zero());
        for (i, n) in self.data.iter().enumerate() {
            for (j, m) in other.data.iter().enumerate() {
                *prod.get_mut(i + j) = *prod.get(i + j) + (*n) * (*m);
            }
        }
        Poly::new(prod)
    }
}

fn omit_zeros<'a, T: Zero>(v: &'a [T]) -> &'a [T] {
    let len = v.iter().rposition(|n| !n.is_zero()).map_or(0, |p| p + 1);
    return v.slice(0, len);
}

pub fn add<T: Zero + Add<T,T> + Clone>(a: &[T], b: &[T]) -> Vec<T> {
    let a = omit_zeros(a);
    let b = omit_zeros(b);

    let (min_len, max_len, rest) = match a.len().cmp(&b.len()) {
        Less    => (a.len(), b.len(), Some(b)),
        Greater => (b.len(), a.len(), Some(a)),
        Equal   => (a.len(), a.len(), None)
    };

    let mut sum = Vec::from_fn(max_len, |_i| Zero::zero());
    for i in range(0, min_len) { *sum.get_mut(i) = a[i] + b[i]; }
    rest.map(|v| { for i in range(min_len, max_len) { *sum.get_mut(i) = v[i].clone(); } });
    sum
}

pub fn mul<T: Zero + Add<T, T> + Mul<T, T>>(a: &[T], b: &[T]) -> Vec<T> {
    let a = omit_zeros(a);
    let b = omit_zeros(b);

    if a.is_empty() || b.is_empty() { return vec![]; }
    let mut prod: Vec<T> = Vec::from_fn(a.len() + b.len() - 1, |_i| Zero::zero());
    for (i, na) in a.iter().enumerate() {
        for (j, nb) in b.iter().enumerate() {
            *prod.get_mut(i + j) = *prod.get(i + j) + (*na) * (*nb);
        }
    }
    prod.move_iter().collect()
}

pub fn eval<T: Zero + One + Add<T, T> + Mul<T, T>>(a: &[T], x: T) -> T {
    let mut sum: T = Zero::zero();
    let mut x_n = One::one();
    for i in range(0, a.len()) {
        sum = sum + a[i] * x_n;
        x_n = x_n * x;
    }
    return sum;
}

pub fn to_str<T: Zero + One + Eq + Neg<T> + ToStr + Ord>(a: &[T], x: &str) -> ~str {
    let a = omit_zeros(a);
    if a.is_empty() { return "0".to_owned(); }

    let one = One::one();

    let mut s = Vec::new();
    for (i, n) in a.iter().enumerate() {
        // output n*x^i / -n*x^i
        if n.is_zero() { continue }

        let term = if i.is_zero() {
            n.to_str()
        } else if i == 1 {
            if (*n) == one { x.to_str() }
            else if (*n) == -one { format!("-{}", x) }
            else { format!("{}*{}", n.to_str(), x) }
        } else {
            if (*n) == one { format!("{}^{}", x, i) }
            else if (*n) == -one { format!("-{}^{}", x, i) }
            else { format!("{}*{}^{}", n.to_str(), x, i) }
        };

        if s.len() > 0 && (*n) > Zero::zero() { s.push("+".to_owned()); }
        s.push(term);
    }

    s.concat()
}

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

        #[test]
        fn new() {
            assert_eq!(vec![1, 2, 3], Poly::new(vec![1, 2, 3]).data);
            assert_eq!(vec![1, 2, 3], Poly::new(vec![1, 2, 3, 0, 0]).data);
            assert_eq!(vec![], Poly::new(vec![0, 0, 0]).data);
        }

        #[test]
        fn neg_add_sub() {
            fn check(a: &[int], b: &[int], c: &[int]) {
                fn check_eq(a: &Poly<int>, b: &Poly<int>) {
                    assert_eq!(*a, *b);
                    assert_eq!(-(*a), -(*b));
                }
                fn check_add(sum: &Poly<int>, a: &Poly<int>, b: &Poly<int>) {
                    check_eq(sum, &((*a) + (*b)));
                    check_eq(sum, &((*b) + (*a)));
                }
                fn check_sub(sum: &Poly<int>, a: &Poly<int>, b: &Poly<int>) {
                    check_eq(a, &((*sum) - (*b)));
                    check_eq(b, &((*sum) - (*a)));
                }

                let a = Poly::from_slice(a);
                let b = Poly::from_slice(b);
                let c = Poly::from_slice(c);
                check_add(&c, &a, &b);
                check_add(&(-c), &(-a), &(-b));
                check_sub(&c, &a, &b);
                check_sub(&(-c), &(-a), &(-b));
            }
            check([], [], []);
            check([], [1], [1]);
            check([1], [1], [2]);
            check([1, 0, 1], [1], [2, 0, 1]);
            check([1, 0, -1], [-1, 0, 1], []);
        }

        #[test]
        fn mul() {
            fn check(a: &[int], b: &[int], c: &[int]) {
                let a = Poly::from_slice(a);
                let b = Poly::from_slice(b);
                let c = Poly::from_slice(c);
                assert_eq!(c, a * b);
                assert_eq!(c, b * a);
            }
            check([], [], []);
            check([0, 0], [], []);
            check([0, 0], [1], []);
            check([1, 0], [1], [1]);
            check([1, 0, 1], [1], [1, 0, 1]);
            check([1, 1], [1, 1], [1, 2, 1]);
            check([1, 1], [1, 0, 1], [1, 1, 1, 1]);
            check([0, 0, 1], [0, 0, 1], [0, 0, 0, 0, 1]);
        }

        #[test]
        fn eval() {
            fn check(pol: &[int], f: |int| -> int) {
                for n in range(-10, 10) {
                    assert_eq!(f(n), Poly::from_slice(pol).eval(n));
                }
            }
            check([], |_x| 0);
            check([1], |_x| 1);
            check([1, 1], |x| x + 1);
            check([0, 1], |x| x);
            check([10, -10, 10], |x| 10*x*x - 10 * x + 10);
        }

        #[test]
        fn pretty() {
            assert_eq!(Poly::from_slice([0]).pretty("x"), "0".to_owned());
            assert_eq!(Poly::from_slice([1]).pretty("x"), "1".to_owned());
            assert_eq!(Poly::from_slice([1, 1]).pretty("x"), "1+x".to_owned());
            assert_eq!(Poly::from_slice([1, 1, 1]).pretty("x"), "1+x+x^2".to_owned());
            assert_eq!(Poly::from_slice([2, 2, 2]).pretty("x"), "2+2*x+2*x^2".to_owned());
            assert_eq!(Poly::from_slice([0, 0, 0, 1]).pretty("x"), "x^3".to_owned());
            assert_eq!(Poly::from_slice([0, 0, 0, -1]).pretty("x"), "-x^3".to_owned());
            assert_eq!(Poly::from_slice([-1, 0, 0, -1]).pretty("x"), "-1-x^3".to_owned());
            assert_eq!(Poly::from_slice([-1, 1, 0, -1]).pretty("x"), "-1+x-x^3".to_owned());
            assert_eq!(Poly::from_slice([-1, 1, -1, -1]).pretty("x"), "-1+x-x^2-x^3".to_owned());
        }
    }
    #[test]
    fn test_poly_add() {
        fn check(a: &[int], b: &[int], c: &[int]) {
            assert_eq!(super::add(a, b).as_slice(), c);
            assert_eq!(super::add(b, a).as_slice(), c);
        }
        check([], [], []);
        check([0, 0], [], []);
        check([0, 0], [1], [1]);
        check([1, 0], [1], [2]);
        check([1, 0, 1], [1], [2, 0, 1]);
    }

    #[test]
    fn test_poly_mul() {
        fn check(a: &[int], b: &[int], c: &[int]) {
            assert_eq!(super::mul(a, b).as_slice(), c);
            assert_eq!(super::mul(b, a).as_slice(), c);
        }
        check([], [], []);
        check([0, 0], [], []);
        check([0, 0], [1], []);
        check([1, 0], [1], [1]);
        check([1, 0, 1], [1], [1, 0, 1]);
        check([1, 1], [1, 1], [1, 2, 1]);
        check([1, 1], [1, 0, 1], [1, 1, 1, 1]);
        check([0, 0, 1], [0, 0, 1], [0, 0, 0, 0, 1]);
    }

    #[test]
    fn test_poly_eval() {
        fn check(pol: &[int], f: |int| -> int) {
            for n in range(-10, 10) {
                assert_eq!(super::eval(pol, n), f(n));
            }
        }
        check([], |_x| 0);
        check([1], |_x| 1);
        check([1, 1], |x| x + 1);
        check([0, 1], |x| x);
        check([10, -10, 10], |x| 10*x*x - 10 * x + 10);
    }

    #[test]
    fn test_poly_to_str() {
        assert_eq!(super::to_str::<int>([], "x"), "0".to_owned());
        assert_eq!(super::to_str([1], "x"), "1".to_owned());
        assert_eq!(super::to_str([1, 1], "x"), "1+x".to_owned());
        assert_eq!(super::to_str([1, 1, 1], "x"), "1+x+x^2".to_owned());
        assert_eq!(super::to_str([2, 2, 2], "x"), "2+2*x+2*x^2".to_owned());
        assert_eq!(super::to_str([0, 0, 0, 1], "x"), "x^3".to_owned());
        assert_eq!(super::to_str([0, 0, 0, -1], "x"), "-x^3".to_owned());
        assert_eq!(super::to_str([-1, 0, 0, -1], "x"), "-1-x^3".to_owned());
        assert_eq!(super::to_str([-1, 1, 0, -1], "x"), "-1+x-x^3".to_owned());
        assert_eq!(super::to_str([-1, 1, -1, -1], "x"), "-1+x-x^2-x^3".to_owned());
    }
}
<|endoftext|>