<commit_before>// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// 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.

use std::fmt;

use syntax::ast;
use syntax::print::pprust;
use syntax::codemap::{self, Span, BytePos, CodeMap};

use lists::{itemize_list, write_list, ListTactic, SeparatorTactic, ListFormatting};
use rewrite::{Rewrite, RewriteContext};
use utils::{extra_offset, span_after};

impl Rewrite for ast::Path {
    fn rewrite(&self, context: &RewriteContext, width: usize, offset: usize) -> Option<String> {
        rewrite_path(context, None, self, width, offset)
    }
}

// Does not wrap on simple segments.
pub fn rewrite_path(context: &RewriteContext,
                    qself: Option<&ast::QSelf>,
                    path: &ast::Path,
                    width: usize,
                    offset: usize)
                    -> Option<String> {
    let skip_count = qself.map(|x| x.position).unwrap_or(0);

    let mut result = if path.global {
        "::".to_owned()
    } else {
        String::new()
    };

    let mut span_lo = path.span.lo;

    if let Some(ref qself) = qself {
        result.push('<');
        result.push_str(&pprust::ty_to_string(&qself.ty));
        result.push_str(" as ");

        let extra_offset = extra_offset(&result, offset);
        // 3 = ">::".len()
        let budget = try_opt!(width.checked_sub(extra_offset)) - 3;

        result = try_opt!(rewrite_path_segments(result,
                                                path.segments.iter().take(skip_count),
                                                span_lo,
                                                path.span.hi,
                                                context,
                                                budget,
                                                offset + extra_offset));

        result.push_str(">::");
        span_lo = qself.ty.span.hi + BytePos(1);
    }

    let extra_offset = extra_offset(&result, offset);
    let budget = try_opt!(width.checked_sub(extra_offset));
    rewrite_path_segments(result,
                          path.segments.iter().skip(skip_count),
                          span_lo,
                          path.span.hi,
                          context,
                          budget,
                          offset + extra_offset)
}

fn rewrite_path_segments<'a, I>(mut buffer: String,
                                iter: I,
                                mut span_lo: BytePos,
                                span_hi: BytePos,
                                context: &RewriteContext,
                                width: usize,
                                offset: usize)
                                -> Option<String>
    where I: Iterator<Item = &'a ast::PathSegment>
{
    let mut first = true;

    for segment in iter {
        let extra_offset = extra_offset(&buffer, offset);
        let remaining_width = try_opt!(width.checked_sub(extra_offset));
        let new_offset = offset + extra_offset;
        let segment_string = try_opt!(rewrite_segment(segment,
                                                      &mut span_lo,
                                                      span_hi,
                                                      context,
                                                      remaining_width,
                                                      new_offset));

        if first {
            first = false;
        } else {
            buffer.push_str("::");
        }

        buffer.push_str(&segment_string);
    }

    Some(buffer)
}

enum SegmentParam<'a> {
    LifeTime(&'a ast::Lifetime),
    Type(&'a ast::Ty),
    Binding(&'a ast::TypeBinding),
}

impl<'a> SegmentParam<'a> {
    fn get_span(&self) -> Span {
        match *self {
            SegmentParam::LifeTime(ref lt) => lt.span,
            SegmentParam::Type(ref ty) => ty.span,
            SegmentParam::Binding(ref binding) => binding.span,
        }
    }
}

impl<'a> fmt::Display for SegmentParam<'a> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            SegmentParam::LifeTime(ref lt) => {
                write!(f, "{}", pprust::lifetime_to_string(lt))
            }
            SegmentParam::Type(ref ty) => {
                write!(f, "{}", pprust::ty_to_string(ty))
            }
            SegmentParam::Binding(ref binding) => {
                write!(f, "{} = {}", binding.ident, pprust::ty_to_string(&*binding.ty))
            }
        }
    }
}

// This is a dirty hack to determine if we're in an expression or not. Generic
// parameters are passed differently in expressions and items. We'd declare
// a struct with Foo<A, B>, but call its functions with Foo::<A, B>::f().
// We'd really rather not do this, but there doesn't seem to be an alternative
// at this point.
// FIXME: fails with spans containing comments with the characters < or :
fn get_path_separator(codemap: &CodeMap,
                      path_start: BytePos,
                      segment_start: BytePos)
                      -> &'static str {
    let span = codemap::mk_sp(path_start, segment_start);
    let snippet = codemap.span_to_snippet(span).unwrap();

    for c in snippet.chars().rev() {
        if c == ':' {
            return "::"
        } else if c.is_whitespace() || c == '<' {
            continuecontinue
        } else {
            return "";
        }
    }

    unreachable!();
}

// Formats a path segment. There are some hacks involved to correctly determine
// the segment's associated span since it's not part of the AST.
//
// The span_lo is assumed to be greater than the end of any previous segment's
// parameters and lesser or equal than the start of current segment.
//
// span_hi is assumed equal to the end of the entire path.
//
// When the segment contains a positive number of parameters, we update span_lo
// so that invariants described above will hold for the next segment.
fn rewrite_segment(segment: &ast::PathSegment,
                   span_lo: &mut BytePos,
                   span_hi: BytePos,
                   context: &RewriteContext,
                   width: usize,
                   offset: usize)
                   -> Option<String> {
    let ident_len = segment.identifier.to_string().len();
    let width = try_opt!(width.checked_sub(ident_len));
    let offset = offset + ident_len;

    let params = match segment.parameters {
        ast::PathParameters::AngleBracketedParameters(ref data) if data.lifetimes.len() > 0 ||
                                                                   data.types.len() > 0 ||
                                                                   data.bindings.len() > 0 => {
            let param_list = data.lifetimes.iter()
                                           .map(SegmentParam::LifeTime)
                                           .chain(data.types.iter()
                                                      .map(|x| SegmentParam::Type(&*x)))
                                           .chain(data.bindings.iter()
                                                      .map(|x| SegmentParam::Binding(&*x)))
                                           .collect::<Vec<_>>();

            let next_span_lo = param_list.last().unwrap().get_span().hi + BytePos(1);
            let list_lo = span_after(codemap::mk_sp(*span_lo, span_hi), "<", context.codemap);
            let separator = get_path_separator(context.codemap, *span_lo, list_lo);

            let items = itemize_list(context.codemap,
                                     param_list.into_iter(),
                                     ">",
                                     |param| param.get_span().lo,
                                     |param| param.get_span().hi,
                                     ToString::to_string,
                                     list_lo,
                                     span_hi);

            // 1 for <
            let extra_offset = 1 + separator.len();
            // 1 for >
            let list_width = try_opt!(width.checked_sub(extra_offset + 1));

            let fmt = ListFormatting {
                tactic: ListTactic::HorizontalVertical,
                separator: ",",
                trailing_separator: SeparatorTactic::Never,
                indent: offset + extra_offset,
                h_width: list_width,
                v_width: list_width,
                ends_with_newline: false,
            };

            // update pos
            *span_lo = next_span_lo;

            format!("{}<{}>", separator, write_list(&items.collect::<Vec<_>>(), &fmt))
        }
        ast::PathParameters::ParenthesizedParameters(ref data) => {
            let output = match data.output {
                Some(ref ty) => format!(" -> {}", pprust::ty_to_string(&*ty)),
                None => String::new(),
            };

            let list_lo = span_after(codemap::mk_sp(*span_lo, span_hi), "(", context.codemap);
            let items = itemize_list(context.codemap,
                                     data.inputs.iter(),
                                     ")",
                                     |ty| ty.span.lo,
                                     |ty| ty.span.hi,
                                     |ty| pprust::ty_to_string(ty),
                                     list_lo,
                                     span_hi);

            // 2 for ()
            let budget = try_opt!(width.checked_sub(output.len() + 2));

            let fmt = ListFormatting {
                tactic: ListTactic::HorizontalVertical,
                separator: ",",
                trailing_separator: SeparatorTactic::Never,
                // 1 for (
                indent: offset + 1,
                h_width: budget,
                v_width: budget,
                ends_with_newline: false,
            };

            // update pos
            *span_lo = data.inputs.last().unwrap().span.hi + BytePos(1);

            format!("({}){}", write_list(&items.collect::<Vec<_>>(), &fmt), output)
        }
        _ => String::new(),
    };

    Some(format!("{}{}", segment.identifier, params))
}

impl Rewrite for ast::WherePredicate {
    fn rewrite(&self, context: &RewriteContext, width: usize, offset: usize) -> Option<String> {
        // TODO dead spans?
        // TODO assumes we'll always fit on one line...
        Some(match self {
                &ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate{ref bound_lifetimes,
                                                                          ref bounded_ty,
                                                                          ref bounds,
                                                                          ..}) => {
                    if bound_lifetimes.len() > 0 {
                        let lifetime_str = bound_lifetimes.iter().map(|lt| {
                                           lt.rewrite(context, width, offset).unwrap()
                                       }).collect::<Vec<_>>().join(", ");
                        let type_str = pprust::ty_to_string(bounded_ty);
                    // 8 = "for<> : ".len()
                        let used_width = lifetime_str.len() + type_str.len() + 8;
                        let bounds_str = bounds.iter().map(|ty_bound| {
                                         ty_bound.rewrite(context,
                                                          width - used_width,
                                                          offset + used_width)
                                                 .unwrap()
                                     }).collect::<Vec<_>>().join(" + ");

                        format!("for<{}> {}: {}", lifetime_str, type_str, bounds_str)
                    } else {
                        let type_str = pprust::ty_to_string(bounded_ty);
                    // 2 = ": ".len()
                        let used_width = type_str.len() + 2;
                        let bounds_str = bounds.iter().map(|ty_bound| {
                                         ty_bound.rewrite(context,
                                                          width - used_width,
                                                          offset + used_width)
                                                 .unwrap()
                                     }).collect::<Vec<_>>().join(" + ");

                        format!("{}: {}", type_str, bounds_str)
                    }
                }
                &ast::WherePredicate::RegionPredicate(ast::WhereRegionPredicate{ref lifetime,
                                                                            ref bounds,
                                                                            ..}) => {
                    format!("{}: {}",
                        pprust::lifetime_to_string(lifetime),
                        bounds.iter().map(pprust::lifetime_to_string)
                              .collect::<Vec<_>>().join(" + "))
                }
                &ast::WherePredicate::EqPredicate(ast::WhereEqPredicate{ref path, ref ty, ..}) => {
                    let ty_str = pprust::ty_to_string(ty);
                // 3 = " = ".len()
                    let used_width = 3 + ty_str.len();
                    let path_str = try_opt!(path.rewrite(context,
                                                     width - used_width,
                                                     offset + used_width));
                    format!("{} = {}", path_str, ty_str)
                }
            })
    }
}

impl Rewrite for ast::LifetimeDef {
    fn rewrite(&self, _: &RewriteContext, _: usize, _: usize) -> Option<String> {
        if self.bounds.len() == 0 {
            Some(pprust::lifetime_to_string(&self.lifetime))
        } else {
            Some(format!("{}: {}",
                         pprust::lifetime_to_string(&self.lifetime),
                         self.bounds.iter().map(pprust::lifetime_to_string)
                                    .collect::<Vec<_>>().join(" + ")))
        }
    }
}

impl Rewrite for ast::TyParamBound {
    fn rewrite(&self, context: &RewriteContext, width: usize, offset: usize) -> Option<String> {
        match *self {
            ast::TyParamBound::TraitTyParamBound(ref tref, ast::TraitBoundModifier::None) => {
                tref.rewrite(context, width, offset)
            }
            ast::TyParamBound::TraitTyParamBound(ref tref, ast::TraitBoundModifier::Maybe) => {
                Some(format!("?{}", try_opt!(tref.rewrite(context, width - 1, offset + 1))))
            }
            ast::TyParamBound::RegionTyParamBound(ref l) => {
                Some(pprust::lifetime_to_string(l))
            }
        }
    }
}

// FIXME: this assumes everything will fit on one line
impl Rewrite for ast::TyParam {
    fn rewrite(&self, context: &RewriteContext, width: usize, offset: usize) -> Option<String> {
        let mut result = String::with_capacity(128);
        result.push_str(&self.ident.to_string());
        if self.bounds.len() > 0 {
            result.push_str(": ");

            let bounds = self.bounds.iter().map(|ty_bound| {
                ty_bound.rewrite(context, width, offset).unwrap()
            }).collect::<Vec<_>>().join(" + ");

            result.push_str(&bounds);
        }
        if let Some(ref def) = self.default {
            result.push_str(" = ");
            result.push_str(&pprust::ty_to_string(&def));
        }

        Some(result)
    }
}

// FIXME: this assumes everything will fit on one line
impl Rewrite for ast::PolyTraitRef {
    fn rewrite(&self, context: &RewriteContext, width: usize, offset: usize) -> Option<String> {
        if self.bound_lifetimes.len() > 0 {
            let lifetime_str = self.bound_lifetimes.iter().map(|lt| {
                lt.rewrite(context, width, offset).unwrap()
            }).collect::<Vec<_>>().join(", ");
            // 6 is "for<> ".len()
            let extra_offset = lifetime_str.len() + 6;
            let max_path_width = try_opt!(width.checked_sub(extra_offset));
            let path_str = try_opt!(self.trait_ref.path.rewrite(context,
                                                                max_path_width,
                                                                offset + extra_offset));

            Some(format!("for<{}> {}", lifetime_str, path_str))
        } else {
            self.trait_ref.path.rewrite(context, width, offset)
        }
    }
}
<commit_msg>reformatting/rebasing<commit_after>// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// 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.

use std::fmt;

use syntax::ast;
use syntax::print::pprust;
use syntax::codemap::{self, Span, BytePos, CodeMap};

use lists::{itemize_list, write_list, ListTactic, SeparatorTactic, ListFormatting};
use rewrite::{Rewrite, RewriteContext};
use utils::{extra_offset, span_after};

impl Rewrite for ast::Path {
    fn rewrite(&self, context: &RewriteContext, width: usize, offset: usize) -> Option<String> {
        rewrite_path(context, None, self, width, offset)
    }
}

// Does not wrap on simple segments.
pub fn rewrite_path(context: &RewriteContext,
                    qself: Option<&ast::QSelf>,
                    path: &ast::Path,
                    width: usize,
                    offset: usize)
                    -> Option<String> {
    let skip_count = qself.map(|x| x.position).unwrap_or(0);

    let mut result = if path.global {
        "::".to_owned()
    } else {
        String::new()
    };

    let mut span_lo = path.span.lo;

    if let Some(ref qself) = qself {
        result.push('<');
        result.push_str(&pprust::ty_to_string(&qself.ty));
        result.push_str(" as ");

        let extra_offset = extra_offset(&result, offset);
        // 3 = ">::".len()
        let budget = try_opt!(width.checked_sub(extra_offset)) - 3;

        result = try_opt!(rewrite_path_segments(result,
                                                path.segments.iter().take(skip_count),
                                                span_lo,
                                                path.span.hi,
                                                context,
                                                budget,
                                                offset + extra_offset));

        result.push_str(">::");
        span_lo = qself.ty.span.hi + BytePos(1);
    }

    let extra_offset = extra_offset(&result, offset);
    let budget = try_opt!(width.checked_sub(extra_offset));
    rewrite_path_segments(result,
                          path.segments.iter().skip(skip_count),
                          span_lo,
                          path.span.hi,
                          context,
                          budget,
                          offset + extra_offset)
}

fn rewrite_path_segments<'a, I>(mut buffer: String,
                                iter: I,
                                mut span_lo: BytePos,
                                span_hi: BytePos,
                                context: &RewriteContext,
                                width: usize,
                                offset: usize)
                                -> Option<String>
    where I: Iterator<Item = &'a ast::PathSegment>
{
    let mut first = true;

    for segment in iter {
        let extra_offset = extra_offset(&buffer, offset);
        let remaining_width = try_opt!(width.checked_sub(extra_offset));
        let new_offset = offset + extra_offset;
        let segment_string = try_opt!(rewrite_segment(segment,
                                                      &mut span_lo,
                                                      span_hi,
                                                      context,
                                                      remaining_width,
                                                      new_offset));

        if first {
            first = false;
        } else {
            buffer.push_str("::");
        }

        buffer.push_str(&segment_string);
    }

    Some(buffer)
}

enum SegmentParam<'a> {
    LifeTime(&'a ast::Lifetime),
    Type(&'a ast::Ty),
    Binding(&'a ast::TypeBinding),
}

impl<'a> SegmentParam<'a> {
    fn get_span(&self) -> Span {
        match *self {
            SegmentParam::LifeTime(ref lt) => lt.span,
            SegmentParam::Type(ref ty) => ty.span,
            SegmentParam::Binding(ref binding) => binding.span,
        }
    }
}

impl<'a> fmt::Display for SegmentParam<'a> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            SegmentParam::LifeTime(ref lt) => {
                write!(f, "{}", pprust::lifetime_to_string(lt))
            }
            SegmentParam::Type(ref ty) => {
                write!(f, "{}", pprust::ty_to_string(ty))
            }
            SegmentParam::Binding(ref binding) => {
                write!(f, "{} = {}", binding.ident, pprust::ty_to_string(&*binding.ty))
            }
        }
    }
}

// This is a dirty hack to determine if we're in an expression or not. Generic
// parameters are passed differently in expressions and items. We'd declare
// a struct with Foo<A, B>, but call its functions with Foo::<A, B>::f().
// We'd really rather not do this, but there doesn't seem to be an alternative
// at this point.
// FIXME: fails with spans containing comments with the characters < or :
// FIXME #184 skip due to continue.
#[rustfmt_skip]
fn get_path_separator(codemap: &CodeMap,
                      path_start: BytePos,
                      segment_start: BytePos)
                      -> &'static str {
    let span = codemap::mk_sp(path_start, segment_start);
    let snippet = codemap.span_to_snippet(span).unwrap();

    for c in snippet.chars().rev() {
        if c == ':' {
            return "::";
        } else if c.is_whitespace() || c == '<' {
            continuecontinue
        } else {
            return "";
        }
    }

    unreachable!();
}

// Formats a path segment. There are some hacks involved to correctly determine
// the segment's associated span since it's not part of the AST.
//
// The span_lo is assumed to be greater than the end of any previous segment's
// parameters and lesser or equal than the start of current segment.
//
// span_hi is assumed equal to the end of the entire path.
//
// When the segment contains a positive number of parameters, we update span_lo
// so that invariants described above will hold for the next segment.
fn rewrite_segment(segment: &ast::PathSegment,
                   span_lo: &mut BytePos,
                   span_hi: BytePos,
                   context: &RewriteContext,
                   width: usize,
                   offset: usize)
                   -> Option<String> {
    let ident_len = segment.identifier.to_string().len();
    let width = try_opt!(width.checked_sub(ident_len));
    let offset = offset + ident_len;

    let params = match segment.parameters {
        ast::PathParameters::AngleBracketedParameters(ref data) if data.lifetimes.len() > 0 || data.types.len() > 0 ||
            data.bindings.len() > 0 => {
            let param_list = data.lifetimes.iter()
                                           .map(SegmentParam::LifeTime)
                                           .chain(data.types.iter()
                                                      .map(|x| SegmentParam::Type(&*x)))
                                           .chain(data.bindings.iter()
                                                      .map(|x| SegmentParam::Binding(&*x)))
                                           .collect::<Vec<_>>();

            let next_span_lo = param_list.last().unwrap().get_span().hi + BytePos(1);
            let list_lo = span_after(codemap::mk_sp(*span_lo, span_hi), "<", context.codemap);
            let separator = get_path_separator(context.codemap, *span_lo, list_lo);

            let items = itemize_list(context.codemap,
                                     param_list.into_iter(),
                                     ">",
                                     |param| param.get_span().lo,
                                     |param| param.get_span().hi,
                                     ToString::to_string,
                                     list_lo,
                                     span_hi);

            // 1 for <
            let extra_offset = 1 + separator.len();
            // 1 for >
            let list_width = try_opt!(width.checked_sub(extra_offset + 1));

            let fmt = ListFormatting {
                tactic: ListTactic::HorizontalVertical,
                separator: ",",
                trailing_separator: SeparatorTactic::Never,
                indent: offset + extra_offset,
                h_width: list_width,
                v_width: list_width,
                ends_with_newline: false,
            };

            // update pos
            *span_lo = next_span_lo;

            format!("{}<{}>", separator, write_list(&items.collect::<Vec<_>>(), &fmt))
        }
        ast::PathParameters::ParenthesizedParameters(ref data) => {
            let output = match data.output {
                Some(ref ty) => format!(" -> {}", pprust::ty_to_string(&*ty)),
                None => String::new(),
            };

            let list_lo = span_after(codemap::mk_sp(*span_lo, span_hi), "(", context.codemap);
            let items = itemize_list(context.codemap,
                                     data.inputs.iter(),
                                     ")",
                                     |ty| ty.span.lo,
                                     |ty| ty.span.hi,
                                     |ty| pprust::ty_to_string(ty),
                                     list_lo,
                                     span_hi);

            // 2 for ()
            let budget = try_opt!(width.checked_sub(output.len() + 2));

            let fmt = ListFormatting {
                tactic: ListTactic::HorizontalVertical,
                separator: ",",
                trailing_separator: SeparatorTactic::Never,
                // 1 for (
                indent: offset + 1,
                h_width: budget,
                v_width: budget,
                ends_with_newline: false,
            };

            // update pos
            *span_lo = data.inputs.last().unwrap().span.hi + BytePos(1);

            format!("({}){}", write_list(&items.collect::<Vec<_>>(), &fmt), output)
        }
        _ => String::new(),
    };

    Some(format!("{}{}", segment.identifier, params))
}

impl Rewrite for ast::WherePredicate {
    fn rewrite(&self, context: &RewriteContext, width: usize, offset: usize) -> Option<String> {
        // TODO dead spans?
        // TODO assumes we'll always fit on one line...
        Some(match self {
                &ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate{ref bound_lifetimes,
                                                                          ref bounded_ty,
                                                                          ref bounds,
                                                                          ..}) => {
                    if bound_lifetimes.len() > 0 {
                        let lifetime_str = bound_lifetimes.iter().map(|lt| {
                                           lt.rewrite(context, width, offset).unwrap()
                                       }).collect::<Vec<_>>().join(", ");
                        let type_str = pprust::ty_to_string(bounded_ty);
                    // 8 = "for<> : ".len()
                        let used_width = lifetime_str.len() + type_str.len() + 8;
                        let bounds_str = bounds.iter().map(|ty_bound| {
                                         ty_bound.rewrite(context,
                                                          width - used_width,
                                                          offset + used_width)
                                                 .unwrap()
                                     }).collect::<Vec<_>>().join(" + ");

                        format!("for<{}> {}: {}", lifetime_str, type_str, bounds_str)
                    } else {
                        let type_str = pprust::ty_to_string(bounded_ty);
                    // 2 = ": ".len()
                        let used_width = type_str.len() + 2;
                        let bounds_str = bounds.iter().map(|ty_bound| {
                                         ty_bound.rewrite(context,
                                                          width - used_width,
                                                          offset + used_width)
                                                 .unwrap()
                                     }).collect::<Vec<_>>().join(" + ");

                        format!("{}: {}", type_str, bounds_str)
                    }
                }
                &ast::WherePredicate::RegionPredicate(ast::WhereRegionPredicate{ref lifetime,
                                                                            ref bounds,
                                                                            ..}) => {
                    format!("{}: {}",
                        pprust::lifetime_to_string(lifetime),
                        bounds.iter().map(pprust::lifetime_to_string)
                              .collect::<Vec<_>>().join(" + "))
                }
                &ast::WherePredicate::EqPredicate(ast::WhereEqPredicate{ref path, ref ty, ..}) => {
                    let ty_str = pprust::ty_to_string(ty);
                // 3 = " = ".len()
                    let used_width = 3 + ty_str.len();
                    let path_str = try_opt!(path.rewrite(context,
                                                     width - used_width,
                                                     offset + used_width));
                    format!("{} = {}", path_str, ty_str)
                }
            })
    }
}

impl Rewrite for ast::LifetimeDef {
    fn rewrite(&self, _: &RewriteContext, _: usize, _: usize) -> Option<String> {
        if self.bounds.len() == 0 {
            Some(pprust::lifetime_to_string(&self.lifetime))
        } else {
            Some(format!("{}: {}",
                         pprust::lifetime_to_string(&self.lifetime),
                         self.bounds.iter().map(pprust::lifetime_to_string)
                                    .collect::<Vec<_>>().join(" + ")))
        }
    }
}

impl Rewrite for ast::TyParamBound {
    fn rewrite(&self, context: &RewriteContext, width: usize, offset: usize) -> Option<String> {
        match *self {
            ast::TyParamBound::TraitTyParamBound(ref tref, ast::TraitBoundModifier::None) => {
                tref.rewrite(context, width, offset)
            }
            ast::TyParamBound::TraitTyParamBound(ref tref, ast::TraitBoundModifier::Maybe) => {
                Some(format!("?{}", try_opt!(tref.rewrite(context, width - 1, offset + 1))))
            }
            ast::TyParamBound::RegionTyParamBound(ref l) => {
                Some(pprust::lifetime_to_string(l))
            }
        }
    }
}

// FIXME: this assumes everything will fit on one line
impl Rewrite for ast::TyParam {
    fn rewrite(&self, context: &RewriteContext, width: usize, offset: usize) -> Option<String> {
        let mut result = String::with_capacity(128);
        result.push_str(&self.ident.to_string());
        if self.bounds.len() > 0 {
            result.push_str(": ");

            let bounds = self.bounds.iter().map(|ty_bound| {
                ty_bound.rewrite(context, width, offset).unwrap()
            }).collect::<Vec<_>>().join(" + ");

            result.push_str(&bounds);
        }
        if let Some(ref def) = self.default {
            result.push_str(" = ");
            result.push_str(&pprust::ty_to_string(&def));
        }

        Some(result)
    }
}

// FIXME: this assumes everything will fit on one line
impl Rewrite for ast::PolyTraitRef {
    fn rewrite(&self, context: &RewriteContext, width: usize, offset: usize) -> Option<String> {
        if self.bound_lifetimes.len() > 0 {
            let lifetime_str = self.bound_lifetimes.iter().map(|lt| {
                lt.rewrite(context, width, offset).unwrap()
            }).collect::<Vec<_>>().join(", ");
            // 6 is "for<> ".len()
            let extra_offset = lifetime_str.len() + 6;
            let max_path_width = try_opt!(width.checked_sub(extra_offset));
            let path_str = try_opt!(self.trait_ref.path.rewrite(context,
                                                                max_path_width,
                                                                offset + extra_offset));

            Some(format!("for<{}> {}", lifetime_str, path_str))
        } else {
            self.trait_ref.path.rewrite(context, width, offset)
        }
    }
}
<|endoftext|>


<commit_before>extern crate ansi_term;
extern crate getopts;

use std;
use std::result::Result;
use std::fs::OpenOptions;
use std::io::prelude::Read;
use getopts::Options;

#[derive(Debug)]
pub enum UtilsErrors {
    IoOpen(String),
    IoRead(String),
}

impl std::fmt::Display for UtilsErrors {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        match *self {
            UtilsErrors::IoOpen(ref path) => {
                let str: String = log(&LogLevel::ERROR,
                                      format!("Unable to open file {}", path).as_str());

                write!(f, "{}", &str)
            }
            UtilsErrors::IoRead(ref path) => {
                let str: String = log(&LogLevel::ERROR,
                                      format!("Unable to read file {}", path).as_str());

                write!(f, "{}", &str)
            }
        }
    }
}

pub fn read_file_content(path: &str) -> Result<String, UtilsErrors> {
    match OpenOptions::new().read(true).open(path) {
        Ok(mut file) => {
            let mut content: String = String::new();

            match file.read_to_string(&mut content) {
                Ok(_) => Ok(content),
                Err(_) => Err(UtilsErrors::IoRead(path.into())),
            }
        }
        Err(_) => Err(UtilsErrors::IoOpen(path.into())),
    }
}

#[derive(Debug)]
pub enum LogLevel {
    INFO,
    WARNING,
    ERROR,
}

pub fn log(level: &LogLevel, content: &str) -> String {

    let prefix = match *level {
        LogLevel::INFO => ansi_term::Colour::White.paint("[INFO]"),
        LogLevel::WARNING => ansi_term::Colour::Yellow.paint("[WARNING]"),
        LogLevel::ERROR => ansi_term::Colour::Red.paint("[ERROR]"),
    };

    format!("{} {}", &prefix, content)
}

pub fn log_print(level: &LogLevel, content: &str) {
    println!("{}", log(level, content));
}

pub fn repeat_char(c: char, times: usize) -> String {
    std::iter::repeat(c).take(times).collect::<String>()
}

pub fn print_usage(program: &str, opts: &Options) {
    let brief = format!("Usage: {} FILE1 FILE2 [options]", program);
    print!("{}", opts.usage(&brief));
}<commit_msg>Better way to write log to formatter<commit_after>extern crate ansi_term;
extern crate getopts;

use std;
use std::result::Result;
use std::fs::OpenOptions;
use std::io::prelude::Read;
use getopts::Options;

#[derive(Debug)]
pub enum UtilsErrors {
    IoOpen(String),
    IoRead(String),
}

impl std::fmt::Display for UtilsErrors {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        match *self {
            UtilsErrors::IoOpen(ref path) => {
                write!(f,
                       "{}",
                       log(&LogLevel::ERROR, &format!("Unable to open file {}", path)))
            }
            UtilsErrors::IoRead(ref path) => {
                write!(f,
                       "{}",
                       log(&LogLevel::ERROR, &format!("Unable to read file {}", path)))
            }
        }
    }
}

pub fn read_file_content(path: &str) -> Result<String, UtilsErrors> {
    match OpenOptions::new().read(true).open(path) {
        Ok(mut file) => {
            let mut content: String = String::new();

            match file.read_to_string(&mut content) {
                Ok(_) => Ok(content),
                Err(_) => Err(UtilsErrors::IoRead(path.into())),
            }
        }
        Err(_) => Err(UtilsErrors::IoOpen(path.into())),
    }
}

#[derive(Debug)]
pub enum LogLevel {
    INFO,
    WARNING,
    ERROR,
}

pub fn log(level: &LogLevel, content: &str) -> String {

    let prefix = match *level {
        LogLevel::INFO => ansi_term::Colour::White.paint("[INFO]"),
        LogLevel::WARNING => ansi_term::Colour::Yellow.paint("[WARNING]"),
        LogLevel::ERROR => ansi_term::Colour::Red.paint("[ERROR]"),
    };

    format!("{} {}", &prefix, content)
}

pub fn log_print(level: &LogLevel, content: &str) {
    println!("{}", log(level, content));
}

pub fn repeat_char(c: char, times: usize) -> String {
    std::iter::repeat(c).take(times).collect::<String>()
}

pub fn print_usage(program: &str, opts: &Options) {
    let brief = format!("Usage: {} FILE1 FILE2 [options]", program);
    print!("{}", opts.usage(&brief));
}<|endoftext|>


<commit_before>use std::cmp::Ordering;

/// This function performs a binary search in a **sorted** slice
/// and returns the index of the closest element.
///
/// Returns None if it encounter an invalid value (NAN) or an empty vector
pub fn search_closest_idx(values: &[f64], target_value: &f64) -> Option<usize> {
    // avoid invalid inputs
    if values.len() == 0 || target_value.is_nan() {
        return None;
    }
    let max_idx = values.len() -1;
    // size of the dichotomie interval
    let mut step: usize = values.len() / 2;
    // current index
    let mut idx: usize = step;
    // Perform a binary search (i.e dichotomie)
	loop {
        // update the interval length
        step = (1 + step) / 2;
		match (values[idx]).partial_cmp(target_value) {
			Some(Ordering::Less) => {
                if idx < max_idx - step {
                    idx += step;
                } else {
                    idx = max_idx;
                }
            },
			Some(Ordering::Greater) => {
                if idx > step {
                    idx -= step;
                } else {
                    idx = 0;
                }
            },
			// return the index if found
			Some(Ordering::Equal) => { return Some(idx); },
			// If values[idx] is NAN, abort
			None => { return None; },
		}
        // If step == 1, we can't get any better
        // EXIT the loop
        if step == 1 {
            // Return closest between `values[idx]` and `values[idx+1]`
            if idx < max_idx && (values[idx] - target_value).abs() > (values[idx+1] - target_value).abs() {
                return Some(idx+1);
            }
            // Return closest between `values[idx]` and `values[idx-1]`
            if idx > 0 && (values[idx] - target_value).abs() > (values[idx-1] - target_value).abs() {
                return Some(idx -1);
            }
            return Some(idx);
        }
    }
}

#[test]
fn test_binary_search() {
    let values: Vec<f64> = vec![1., 3., 3.5, 5., 5.1, 6., 8., 11.];
    // search a value exactly equals to one of element
    assert_eq!(search_closest_idx(&values, &3_f64), Some(1_usize));
    // search a value not in the set
    assert_eq!(search_closest_idx(&values, &5.2), Some(4_usize));
    // search values outside the set ranges
    assert_eq!(search_closest_idx(&values, &-3.), Some(0_usize));
    assert_eq!(search_closest_idx(&values, &100.), Some(values.len() -1));
}
<commit_msg>Doc (boyscouting)<commit_after>use std::cmp::Ordering;

/// This function performs a binary search in a **sorted** slice
/// and returns the index of the closest element.
///
/// Returns None if it encounter an invalid value (NAN) or an empty vector
pub fn search_closest_idx(values: &[f64], target_value: &f64) -> Option<usize> {
    // this function performs a dichotomie search on `target_value` inside `values`
    // basically like "the price is right".

    // avoid invalid inputs
    if values.len() == 0 || target_value.is_nan() {
        return None;
    }
    let max_idx = values.len() -1;
    // size of the dichotomie interval
    let mut step: usize = values.len() / 2;
    // current index
    let mut idx: usize = step;
    // Perform a binary search (i.e dichotomie)
	loop {
        // update the interval length
        // we add one to handle odd values
        step = (1 + step) / 2;
		match (values[idx]).partial_cmp(target_value) {
            // increment `idx` of `step`
			Some(Ordering::Less) => {
                // avoid out-of-bound index
                idx = max_idx.min(idx + step);
            },
            // decrement `idx` of `step`
			Some(Ordering::Greater) => {
                // avoid out-of-bound index and overflow
                idx = if idx > step { idx - step } else { 0 };
            },
			// return the exact index if found
			Some(Ordering::Equal) => return Some(idx),
			// If values[idx] is NAN, abort
			None => return None,
		}
        // If step == 1, we can't get any better
        // EXIT the loop
        if step == 1 {
            // Return closest between `values[idx]` and `values[idx+1]`
            if idx < max_idx && (values[idx] - target_value).abs() > (values[idx+1] - target_value).abs() {
                return Some(idx+1);
            }
            // Return closest between `values[idx]` and `values[idx-1]`
            if idx > 0 && (values[idx] - target_value).abs() > (values[idx-1] - target_value).abs() {
                return Some(idx -1);
            }
            return Some(idx);
        }
    }
}

#[test]
fn test_binary_search() {
    let values: Vec<f64> = vec![1., 3., 3.5, 5., 5.1, 6., 8., 11.];
    // search a value exactly equals to one of element
    assert_eq!(search_closest_idx(&values, &3_f64), Some(1_usize));
    // search a value not in the set
    assert_eq!(search_closest_idx(&values, &5.2), Some(4_usize));
    // search values outside the set ranges
    assert_eq!(search_closest_idx(&values, &-3.), Some(0_usize));
    assert_eq!(search_closest_idx(&values, &100.), Some(values.len() -1));
}
<|endoftext|>


<commit_before>//! Value module.

use std::cmp::{Eq, Ordering};
use std::collections::BTreeMap;
use std::hash::{Hash, Hasher};

use serde::de::{DeserializeSeed, Deserializer, Error as SerdeErr, MapAccess, SeqAccess, Visitor};

use de::{Error as RonError, Result};

/// A wrapper for `f64` which guarantees that the inner value
/// is finite and thus implements `Eq`, `Hash` and `Ord`.
#[derive(Copy, Clone, Debug, PartialOrd, PartialEq)]
pub struct Number(f64);

impl Number {
    /// Panics if `v` is not a real number
    /// (infinity, NaN, ..).
    pub fn new(v: f64) -> Self {
        if !v.is_finite() {
            panic!("Tried to create Number with a NaN / infinity");
        }

        Number(v)
    }

    /// Returns the wrapped float.
    pub fn get(&self) -> f64 {
        self.0
    }
}

impl Eq for Number {}

impl Hash for Number {
    fn hash<H: Hasher>(&self, state: &mut H) {
        state.write_u64(self.0 as u64);
    }
}

impl Ord for Number {
    fn cmp(&self, other: &Self) -> Ordering {
        self.partial_cmp(other).expect("Bug: Contract violation")
    }
}

#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub enum Value {
    Bool(bool),
    Char(char),
    Map(BTreeMap<Value, Value>),
    Number(Number),
    Option(Option<Box<Value>>),
    String(String),
    Seq(Vec<Value>),
    Unit,
}

/// Deserializer implementation for RON `Value`.
/// This does not support enums (because `Value` doesn't store them).
impl<'de> Deserializer<'de> for Value {
    type Error = RonError;

    fn deserialize_any<V>(self, visitor: V) -> Result<V::Value>
    where
        V: Visitor<'de>,
    {
        match self {
            Value::Bool(b) => visitor.visit_bool(b),
            Value::Char(c) => visitor.visit_char(c),
            Value::Map(m) => visitor.visit_map(Map {
                keys: m.keys().cloned().rev().collect(),
                values: m.values().cloned().rev().collect(),
            }),
            Value::Number(n) => visitor.visit_f64(n.get()),
            Value::Option(Some(o)) => visitor.visit_some(*o),
            Value::Option(None) => visitor.visit_none(),
            Value::String(s) => visitor.visit_string(s),
            Value::Seq(mut seq) => {
                seq.reverse();

                visitor.visit_seq(Seq { seq })
            }
            Value::Unit => visitor.visit_unit(),
        }
    }

    fn deserialize_i8<V>(self, visitor: V) -> Result<V::Value>
    where
        V: Visitor<'de>,
    {
        self.deserialize_i64(visitor)
    }

    fn deserialize_i16<V>(self, visitor: V) -> Result<V::Value>
    where
        V: Visitor<'de>,
    {
        self.deserialize_i64(visitor)
    }

    fn deserialize_i32<V>(self, visitor: V) -> Result<V::Value>
    where
        V: Visitor<'de>,
    {
        self.deserialize_i64(visitor)
    }

    fn deserialize_i64<V>(self, visitor: V) -> Result<V::Value>
    where
        V: Visitor<'de>,
    {
        match self {
            Value::Number(n) => visitor.visit_i64(n.get() as i64),
            v => Err(RonError::custom(format!("Expected a number, got {:?}", v))),
        }
    }

    fn deserialize_u8<V>(self, visitor: V) -> Result<V::Value>
    where
        V: Visitor<'de>,
    {
        self.deserialize_u64(visitor)
    }

    fn deserialize_u16<V>(self, visitor: V) -> Result<V::Value>
    where
        V: Visitor<'de>,
    {
        self.deserialize_u64(visitor)
    }

    fn deserialize_u32<V>(self, visitor: V) -> Result<V::Value>
    where
        V: Visitor<'de>,
    {
        self.deserialize_u64(visitor)
    }

    fn deserialize_u64<V>(self, visitor: V) -> Result<V::Value>
    where
        V: Visitor<'de>,
    {
        match self {
            Value::Number(n) => visitor.visit_u64(n.get() as u64),
            v => Err(RonError::custom(format!("Expected a number, got {:?}", v))),
        }
    }

    forward_to_deserialize_any! {
        bool f32 f64 char str string bytes
        byte_buf option unit unit_struct newtype_struct seq tuple
        tuple_struct map struct enum identifier ignored_any
    }
}

struct Map {
    keys: Vec<Value>,
    values: Vec<Value>,
}

impl<'de> MapAccess<'de> for Map {
    type Error = RonError;

    fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>>
    where
        K: DeserializeSeed<'de>,
    {
        // The `Vec` is reversed, so we can pop to get the originally first element
        self.keys
            .pop()
            .map_or(Ok(None), |v| seed.deserialize(v).map(Some))
    }

    fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value>
    where
        V: DeserializeSeed<'de>,
    {
        // The `Vec` is reversed, so we can pop to get the originally first element
        self.values
            .pop()
            .map(|v| seed.deserialize(v))
            .expect("Contract violation")
    }
}

struct Seq {
    seq: Vec<Value>,
}

impl<'de> SeqAccess<'de> for Seq {
    type Error = RonError;

    fn next_element_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>>
    where
        T: DeserializeSeed<'de>,
    {
        // The `Vec` is reversed, so we can pop to get the originally first element
        self.seq
            .pop()
            .map_or(Ok(None), |v| seed.deserialize(v).map(Some))
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use serde::Deserialize;
    use std::fmt::Debug;

    fn assert_same<'de, T>(s: &'de str)
    where
        T: Debug + Deserialize<'de> + PartialEq,
    {
        use de::from_str;

        let direct: T = from_str(s).unwrap();
        let value: Value = from_str(s).unwrap();
        let value = T::deserialize(value).unwrap();

        assert_eq!(direct, value, "Deserialization for {:?} is not the same", s);
    }

    #[test]
    fn boolean() {
        assert_same::<bool>("true");
        assert_same::<bool>("false");
    }

    #[test]
    fn float() {
        assert_same::<f64>("0.123");
        assert_same::<f64>("-4.19");
    }

    #[test]
    fn int() {
        assert_same::<u32>("626");
        assert_same::<i32>("-50");
    }

    #[test]
    fn char() {
        assert_same::<char>("'4'");
        assert_same::<char>("'c'");
    }

    #[test]
    fn map() {
        assert_same::<BTreeMap<char, String>>(
            "{
'a': \"Hello\",
'b': \"Bye\",
        }",
        );
    }

    #[test]
    fn option() {
        assert_same::<Option<char>>("Some('a')");
        assert_same::<Option<char>>("None");
    }

    #[test]
    fn seq() {
        assert_same::<Vec<f64>>("[1.0, 2.0, 3.0, 4.0]");
    }

    #[test]
    fn unit() {
        assert_same::<()>("()");
    }
}
<commit_msg>Implement Value::into_rust<commit_after>//! Value module.

use std::cmp::{Eq, Ordering};
use std::collections::BTreeMap;
use std::hash::{Hash, Hasher};

use serde::de::{DeserializeOwned, DeserializeSeed, Deserializer, Error as SerdeErr, MapAccess, SeqAccess, Visitor};

use de::{Error as RonError, Result};

/// A wrapper for `f64` which guarantees that the inner value
/// is finite and thus implements `Eq`, `Hash` and `Ord`.
#[derive(Copy, Clone, Debug, PartialOrd, PartialEq)]
pub struct Number(f64);

impl Number {
    /// Panics if `v` is not a real number
    /// (infinity, NaN, ..).
    pub fn new(v: f64) -> Self {
        if !v.is_finite() {
            panic!("Tried to create Number with a NaN / infinity");
        }

        Number(v)
    }

    /// Returns the wrapped float.
    pub fn get(&self) -> f64 {
        self.0
    }
}

impl Eq for Number {}

impl Hash for Number {
    fn hash<H: Hasher>(&self, state: &mut H) {
        state.write_u64(self.0 as u64);
    }
}

impl Ord for Number {
    fn cmp(&self, other: &Self) -> Ordering {
        self.partial_cmp(other).expect("Bug: Contract violation")
    }
}

#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub enum Value {
    Bool(bool),
    Char(char),
    Map(BTreeMap<Value, Value>),
    Number(Number),
    Option(Option<Box<Value>>),
    String(String),
    Seq(Vec<Value>),
    Unit,
}

impl Value {
    /// Tries to deserialize this `Value` into `T`.
    pub fn into_rust<T>(self) -> Result<T>
    where
        T: DeserializeOwned,
    {
        T::deserialize(self)
    }
}

/// Deserializer implementation for RON `Value`.
/// This does not support enums (because `Value` doesn't store them).
impl<'de> Deserializer<'de> for Value {
    type Error = RonError;

    fn deserialize_any<V>(self, visitor: V) -> Result<V::Value>
    where
        V: Visitor<'de>,
    {
        match self {
            Value::Bool(b) => visitor.visit_bool(b),
            Value::Char(c) => visitor.visit_char(c),
            Value::Map(m) => visitor.visit_map(Map {
                keys: m.keys().cloned().rev().collect(),
                values: m.values().cloned().rev().collect(),
            }),
            Value::Number(n) => visitor.visit_f64(n.get()),
            Value::Option(Some(o)) => visitor.visit_some(*o),
            Value::Option(None) => visitor.visit_none(),
            Value::String(s) => visitor.visit_string(s),
            Value::Seq(mut seq) => {
                seq.reverse();

                visitor.visit_seq(Seq { seq })
            }
            Value::Unit => visitor.visit_unit(),
        }
    }

    fn deserialize_i8<V>(self, visitor: V) -> Result<V::Value>
    where
        V: Visitor<'de>,
    {
        self.deserialize_i64(visitor)
    }

    fn deserialize_i16<V>(self, visitor: V) -> Result<V::Value>
    where
        V: Visitor<'de>,
    {
        self.deserialize_i64(visitor)
    }

    fn deserialize_i32<V>(self, visitor: V) -> Result<V::Value>
    where
        V: Visitor<'de>,
    {
        self.deserialize_i64(visitor)
    }

    fn deserialize_i64<V>(self, visitor: V) -> Result<V::Value>
    where
        V: Visitor<'de>,
    {
        match self {
            Value::Number(n) => visitor.visit_i64(n.get() as i64),
            v => Err(RonError::custom(format!("Expected a number, got {:?}", v))),
        }
    }

    fn deserialize_u8<V>(self, visitor: V) -> Result<V::Value>
    where
        V: Visitor<'de>,
    {
        self.deserialize_u64(visitor)
    }

    fn deserialize_u16<V>(self, visitor: V) -> Result<V::Value>
    where
        V: Visitor<'de>,
    {
        self.deserialize_u64(visitor)
    }

    fn deserialize_u32<V>(self, visitor: V) -> Result<V::Value>
    where
        V: Visitor<'de>,
    {
        self.deserialize_u64(visitor)
    }

    fn deserialize_u64<V>(self, visitor: V) -> Result<V::Value>
    where
        V: Visitor<'de>,
    {
        match self {
            Value::Number(n) => visitor.visit_u64(n.get() as u64),
            v => Err(RonError::custom(format!("Expected a number, got {:?}", v))),
        }
    }

    forward_to_deserialize_any! {
        bool f32 f64 char str string bytes
        byte_buf option unit unit_struct newtype_struct seq tuple
        tuple_struct map struct enum identifier ignored_any
    }
}

struct Map {
    keys: Vec<Value>,
    values: Vec<Value>,
}

impl<'de> MapAccess<'de> for Map {
    type Error = RonError;

    fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>>
    where
        K: DeserializeSeed<'de>,
    {
        // The `Vec` is reversed, so we can pop to get the originally first element
        self.keys
            .pop()
            .map_or(Ok(None), |v| seed.deserialize(v).map(Some))
    }

    fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value>
    where
        V: DeserializeSeed<'de>,
    {
        // The `Vec` is reversed, so we can pop to get the originally first element
        self.values
            .pop()
            .map(|v| seed.deserialize(v))
            .expect("Contract violation")
    }
}

struct Seq {
    seq: Vec<Value>,
}

impl<'de> SeqAccess<'de> for Seq {
    type Error = RonError;

    fn next_element_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>>
    where
        T: DeserializeSeed<'de>,
    {
        // The `Vec` is reversed, so we can pop to get the originally first element
        self.seq
            .pop()
            .map_or(Ok(None), |v| seed.deserialize(v).map(Some))
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use serde::Deserialize;
    use std::fmt::Debug;

    fn assert_same<'de, T>(s: &'de str)
    where
        T: Debug + Deserialize<'de> + PartialEq,
    {
        use de::from_str;

        let direct: T = from_str(s).unwrap();
        let value: Value = from_str(s).unwrap();
        let value = T::deserialize(value).unwrap();

        assert_eq!(direct, value, "Deserialization for {:?} is not the same", s);
    }

    #[test]
    fn boolean() {
        assert_same::<bool>("true");
        assert_same::<bool>("false");
    }

    #[test]
    fn float() {
        assert_same::<f64>("0.123");
        assert_same::<f64>("-4.19");
    }

    #[test]
    fn int() {
        assert_same::<u32>("626");
        assert_same::<i32>("-50");
    }

    #[test]
    fn char() {
        assert_same::<char>("'4'");
        assert_same::<char>("'c'");
    }

    #[test]
    fn map() {
        assert_same::<BTreeMap<char, String>>(
            "{
'a': \"Hello\",
'b': \"Bye\",
        }",
        );
    }

    #[test]
    fn option() {
        assert_same::<Option<char>>("Some('a')");
        assert_same::<Option<char>>("None");
    }

    #[test]
    fn seq() {
        assert_same::<Vec<f64>>("[1.0, 2.0, 3.0, 4.0]");
    }

    #[test]
    fn unit() {
        assert_same::<()>("()");
    }
}
<|endoftext|>


<commit_before>use std::io;

use {
    TimescaleUnit,
    Value,
    IdCode,
    Scope,
    Var,
    ReferenceIndex,
    ScopeItem,
    SimulationCommand,
    Header,
    ScopeType,
    VarType,
    Command
};

/// Struct wrapping an `io::Write` with methods for writing VCD commands and data.
pub struct Writer<'w> {
	writer: &'w mut io::Write,
    next_id_code: IdCode,
    scope_depth: usize,
}

impl<'s> Writer<'s> {
    /// Creates a Writer, wrapping an io::Write.
    ///
    /// ```
    /// let mut buf = Vec::new();
    /// let mut vcd = vcd::Writer::new(&mut buf);
    /// ```
    pub fn new(writer: &mut io::Write) -> Writer {
        Writer { writer: writer, next_id_code: IdCode::FIRST, scope_depth: 0 }
    }

    /// Writes a complete header with the fields from a `Header` struct from the parser.
    pub fn header(&mut self, h: &Header) -> io::Result<()> {
        if let Some(ref s) = h.date     { try!(self.date(s)); }
        if let Some(ref s) = h.version  { try!(self.version(s)); }
        if let Some(ref s) = h.comment  { try!(self.comment(s)); }
        if let Some((v, u)) = h.timescale { try!(self.timescale(v, u)); }
        for i in &h.items {
            match *i {
                ScopeItem::Var(ref v) => try!(self.var(v)),
                ScopeItem::Scope(ref s) => try!(self.scope(s)),
            }
        }
        self.enddefinitions()
    }

    /// Writes a `$comment` command.
    pub fn comment(&mut self, v: &str) -> io::Result<()> {
        writeln!(self.writer, "$comment\n    {}\n$end", v)
    }

    /// Writes a `$date` command.
    pub fn date(&mut self, v: &str) -> io::Result<()> {
        writeln!(self.writer, "$date\n    {}\n$end", v)
    }

    /// Writes a `$version` command.
    pub fn version(&mut self, v: &str) -> io::Result<()> {
        writeln!(self.writer, "$version\n    {}\n$end", v)
    }

    /// Writes a `$timescale` command.
    pub fn timescale(&mut self, ts: u32, unit: TimescaleUnit) -> io::Result<()> {
        writeln!(self.writer, "$timescale {} {} $end", ts, unit)
    }

    /// Writes a `$scope` command.
    pub fn scope_def(&mut self, t: ScopeType, i: &str) -> io::Result<()> {
        self.scope_depth += 1;
        writeln!(self.writer, "$scope {} {} $end", t, i)
    }

    /// Writes a `$scope` command for a module.
    ///
    /// Convenience wrapper around `scope_def`.
    pub fn add_module(&mut self, identifier: &str) -> io::Result<()> {
        self.scope_def(ScopeType::Module, identifier)
    }

    /// Writes an `$upscope` command.
    pub fn upscope(&mut self) -> io::Result<()> {
        debug_assert!(self.scope_depth > 0, "Generating invalid VCD: upscope without a matching scope");
        self.scope_depth -= 1;
        writeln!(self.writer, "$upscope $end")
    }

    /// Writes a `$scope` command, a series of `$var` commands, and an `$upscope` commands from
    /// a `Scope` structure from the parser.
    pub fn scope(&mut self, s: &Scope) -> io::Result<()> {
        try!(self.scope_def(s.scope_type, &s.identifier[..]));
        for i in &s.children {
            match *i {
                ScopeItem::Var(ref v) => try!(self.var(v)),
                ScopeItem::Scope(ref s) => try!(self.scope(s)),
            }
        }
        self.upscope()
    }

    /// Writes a `$var` command with a specified id.
    pub fn var_def(&mut self, var_type: VarType, width: u32, id: IdCode, reference: &str, index: Option<ReferenceIndex>) -> io::Result<()> {
        debug_assert!(self.scope_depth > 0, "Generating invalid VCD: variable must be in a scope");
        if id >= self.next_id_code {
            self.next_id_code = id.next();
        }
        match index {
            Some(idx) => writeln!(self.writer, "$var {} {} {} {} {} $end", var_type, width, id, reference, idx),
            None => writeln!(self.writer, "$var {} {} {} {} $end", var_type, width, id, reference),
        }
    }

    /// Writes a `$var` command with the next available ID, returning the assigned ID.
    ///
    /// Convenience wrapper around `var_def`.
    pub fn add_var(&mut self, var_type: VarType, width: u32, reference: &str, index: Option<ReferenceIndex>) -> io::Result<IdCode> {
        let id = self.next_id_code;
        self.var_def(var_type, width, id, reference, index)?;
        Ok(id)
    }

    /// Adds a `$var` for a wire with the next available ID, returning the assigned ID.
    ///
    /// Convenience wrapper around `add_var`.
    pub fn add_wire(&mut self, width: u32, reference: &str) -> io::Result<IdCode> {
        self.add_var(VarType::Wire, width, reference, None)
    }

    /// Writes a `$var` command from a `Var` structure from the parser.
    pub fn var(&mut self, v: &Var) -> io::Result<()> {
        self.var_def(v.var_type, v.size, v.code, &v.reference[..], v.index)
    }

    /// Writes a `$enddefinitions` command to end the header.
    pub fn enddefinitions(&mut self) -> io::Result<()> {
        debug_assert!(self.scope_depth == 0, "Generating invalid VCD: {} scopes must be closed with $upscope before $enddefinitions");
        writeln!(self.writer, "$enddefinitions $end")
    }

    /// Writes a `#xxx` timestamp.
    pub fn timestamp(&mut self, ts: u64) -> io::Result<()> {
        writeln!(self.writer, "#{}", ts)
    }

    /// Writes a change to a scalar variable.
    pub fn change_scalar<V: Into<Value>>(&mut self, id: IdCode, v: V) -> io::Result<()> {
        writeln!(self.writer, "{}{}", v.into(), id)
    }

    /// Writes a change to a vector variable.
    pub fn change_vector(&mut self, id: IdCode, v: &[Value]) -> io::Result<()> {
        try!(write!(self.writer, "b"));
        for i in v { try!(write!(self.writer, "{}", i)) }
        writeln!(self.writer, " {}", id)
    }

    /// Writes a change to a real variable.
    pub fn change_real(&mut self, id: IdCode, v: f64) -> io::Result<()> {
        writeln!(self.writer, "r{} {}", v, id)
    }

    /// Writes a change to a string variable.
    pub fn change_string(&mut self, id: IdCode, v: &str) -> io::Result<()> {
        writeln!(self.writer, "s{} {}", v, id)
    }

    /// Writes the beginning of a simulation command.
    pub fn begin(&mut self, c: SimulationCommand) -> io::Result<()> {
        writeln!(self.writer, "${}", c)
    }

    /// Writes an `$end` to end a simulation command.
    pub fn end(&mut self) -> io::Result<()> {
        writeln!(self.writer, "$end")
    }

    /// Writes a command from a `Command` enum as parsed by the parser.
    pub fn command(&mut self, c: &Command) -> io::Result<()> {
        use super::Command::*;
        match *c {
            Comment(ref c) => self.comment(&c[..]),
            Date(ref c) => self.date(&c[..]),
            Version(ref c) => self.version(&c[..]),
            Timescale(v, u) => self.timescale(v, u),
            ScopeDef(t, ref i) => self.scope_def(t, &i[..]),
            Upscope => self.upscope(),
            VarDef(t, s, i, ref r, idx) => self.var_def(t, s, i, &r[..], idx),
            Enddefinitions => self.enddefinitions(),
            Timestamp(t) => self.timestamp(t),
            ChangeScalar(i, v) => self.change_scalar(i, v),
            ChangeVector(i, ref v) => self.change_vector(i, &v[..]),
            ChangeReal(i, v) => self.change_real(i, v),
            ChangeString(i, ref v) => self.change_string(i, v),
            Begin(c) => self.begin(c),
            End(_) => self.end(),
        }
    }
}
<commit_msg>Add `dyn` to fix deprecation warnings<commit_after>use std::io;

use {
    TimescaleUnit,
    Value,
    IdCode,
    Scope,
    Var,
    ReferenceIndex,
    ScopeItem,
    SimulationCommand,
    Header,
    ScopeType,
    VarType,
    Command
};

/// Struct wrapping an `io::Write` with methods for writing VCD commands and data.
pub struct Writer<'w> {
	writer: &'w mut dyn io::Write,
    next_id_code: IdCode,
    scope_depth: usize,
}

impl<'s> Writer<'s> {
    /// Creates a Writer, wrapping an io::Write.
    ///
    /// ```
    /// let mut buf = Vec::new();
    /// let mut vcd = vcd::Writer::new(&mut buf);
    /// ```
    pub fn new(writer: &mut dyn io::Write) -> Writer {
        Writer { writer: writer, next_id_code: IdCode::FIRST, scope_depth: 0 }
    }

    /// Writes a complete header with the fields from a `Header` struct from the parser.
    pub fn header(&mut self, h: &Header) -> io::Result<()> {
        if let Some(ref s) = h.date     { try!(self.date(s)); }
        if let Some(ref s) = h.version  { try!(self.version(s)); }
        if let Some(ref s) = h.comment  { try!(self.comment(s)); }
        if let Some((v, u)) = h.timescale { try!(self.timescale(v, u)); }
        for i in &h.items {
            match *i {
                ScopeItem::Var(ref v) => try!(self.var(v)),
                ScopeItem::Scope(ref s) => try!(self.scope(s)),
            }
        }
        self.enddefinitions()
    }

    /// Writes a `$comment` command.
    pub fn comment(&mut self, v: &str) -> io::Result<()> {
        writeln!(self.writer, "$comment\n    {}\n$end", v)
    }

    /// Writes a `$date` command.
    pub fn date(&mut self, v: &str) -> io::Result<()> {
        writeln!(self.writer, "$date\n    {}\n$end", v)
    }

    /// Writes a `$version` command.
    pub fn version(&mut self, v: &str) -> io::Result<()> {
        writeln!(self.writer, "$version\n    {}\n$end", v)
    }

    /// Writes a `$timescale` command.
    pub fn timescale(&mut self, ts: u32, unit: TimescaleUnit) -> io::Result<()> {
        writeln!(self.writer, "$timescale {} {} $end", ts, unit)
    }

    /// Writes a `$scope` command.
    pub fn scope_def(&mut self, t: ScopeType, i: &str) -> io::Result<()> {
        self.scope_depth += 1;
        writeln!(self.writer, "$scope {} {} $end", t, i)
    }

    /// Writes a `$scope` command for a module.
    ///
    /// Convenience wrapper around `scope_def`.
    pub fn add_module(&mut self, identifier: &str) -> io::Result<()> {
        self.scope_def(ScopeType::Module, identifier)
    }

    /// Writes an `$upscope` command.
    pub fn upscope(&mut self) -> io::Result<()> {
        debug_assert!(self.scope_depth > 0, "Generating invalid VCD: upscope without a matching scope");
        self.scope_depth -= 1;
        writeln!(self.writer, "$upscope $end")
    }

    /// Writes a `$scope` command, a series of `$var` commands, and an `$upscope` commands from
    /// a `Scope` structure from the parser.
    pub fn scope(&mut self, s: &Scope) -> io::Result<()> {
        try!(self.scope_def(s.scope_type, &s.identifier[..]));
        for i in &s.children {
            match *i {
                ScopeItem::Var(ref v) => try!(self.var(v)),
                ScopeItem::Scope(ref s) => try!(self.scope(s)),
            }
        }
        self.upscope()
    }

    /// Writes a `$var` command with a specified id.
    pub fn var_def(&mut self, var_type: VarType, width: u32, id: IdCode, reference: &str, index: Option<ReferenceIndex>) -> io::Result<()> {
        debug_assert!(self.scope_depth > 0, "Generating invalid VCD: variable must be in a scope");
        if id >= self.next_id_code {
            self.next_id_code = id.next();
        }
        match index {
            Some(idx) => writeln!(self.writer, "$var {} {} {} {} {} $end", var_type, width, id, reference, idx),
            None => writeln!(self.writer, "$var {} {} {} {} $end", var_type, width, id, reference),
        }
    }

    /// Writes a `$var` command with the next available ID, returning the assigned ID.
    ///
    /// Convenience wrapper around `var_def`.
    pub fn add_var(&mut self, var_type: VarType, width: u32, reference: &str, index: Option<ReferenceIndex>) -> io::Result<IdCode> {
        let id = self.next_id_code;
        self.var_def(var_type, width, id, reference, index)?;
        Ok(id)
    }

    /// Adds a `$var` for a wire with the next available ID, returning the assigned ID.
    ///
    /// Convenience wrapper around `add_var`.
    pub fn add_wire(&mut self, width: u32, reference: &str) -> io::Result<IdCode> {
        self.add_var(VarType::Wire, width, reference, None)
    }

    /// Writes a `$var` command from a `Var` structure from the parser.
    pub fn var(&mut self, v: &Var) -> io::Result<()> {
        self.var_def(v.var_type, v.size, v.code, &v.reference[..], v.index)
    }

    /// Writes a `$enddefinitions` command to end the header.
    pub fn enddefinitions(&mut self) -> io::Result<()> {
        debug_assert!(self.scope_depth == 0, "Generating invalid VCD: {} scopes must be closed with $upscope before $enddefinitions");
        writeln!(self.writer, "$enddefinitions $end")
    }

    /// Writes a `#xxx` timestamp.
    pub fn timestamp(&mut self, ts: u64) -> io::Result<()> {
        writeln!(self.writer, "#{}", ts)
    }

    /// Writes a change to a scalar variable.
    pub fn change_scalar<V: Into<Value>>(&mut self, id: IdCode, v: V) -> io::Result<()> {
        writeln!(self.writer, "{}{}", v.into(), id)
    }

    /// Writes a change to a vector variable.
    pub fn change_vector(&mut self, id: IdCode, v: &[Value]) -> io::Result<()> {
        try!(write!(self.writer, "b"));
        for i in v { try!(write!(self.writer, "{}", i)) }
        writeln!(self.writer, " {}", id)
    }

    /// Writes a change to a real variable.
    pub fn change_real(&mut self, id: IdCode, v: f64) -> io::Result<()> {
        writeln!(self.writer, "r{} {}", v, id)
    }

    /// Writes a change to a string variable.
    pub fn change_string(&mut self, id: IdCode, v: &str) -> io::Result<()> {
        writeln!(self.writer, "s{} {}", v, id)
    }

    /// Writes the beginning of a simulation command.
    pub fn begin(&mut self, c: SimulationCommand) -> io::Result<()> {
        writeln!(self.writer, "${}", c)
    }

    /// Writes an `$end` to end a simulation command.
    pub fn end(&mut self) -> io::Result<()> {
        writeln!(self.writer, "$end")
    }

    /// Writes a command from a `Command` enum as parsed by the parser.
    pub fn command(&mut self, c: &Command) -> io::Result<()> {
        use super::Command::*;
        match *c {
            Comment(ref c) => self.comment(&c[..]),
            Date(ref c) => self.date(&c[..]),
            Version(ref c) => self.version(&c[..]),
            Timescale(v, u) => self.timescale(v, u),
            ScopeDef(t, ref i) => self.scope_def(t, &i[..]),
            Upscope => self.upscope(),
            VarDef(t, s, i, ref r, idx) => self.var_def(t, s, i, &r[..], idx),
            Enddefinitions => self.enddefinitions(),
            Timestamp(t) => self.timestamp(t),
            ChangeScalar(i, v) => self.change_scalar(i, v),
            ChangeVector(i, ref v) => self.change_vector(i, &v[..]),
            ChangeReal(i, v) => self.change_real(i, v),
            ChangeString(i, ref v) => self.change_string(i, v),
            Begin(c) => self.begin(c),
            End(_) => self.end(),
        }
    }
}
<|endoftext|>


<commit_before>use num::{PrimInt, Signed};

/// Right-shift an integer, but round to nearest, with ties rounding to even.
///
/// This minimizes error, and avoids a directional bias.
pub fn right_shift_nicely_rounded <T: PrimInt> (input: T, shift: usize)->T {
  let divisor = T::one() << shift;
  let mask = divisor - T::one();
  if (input & mask) << 1 == divisor {
    let shifted = input >> shift;
    shifted + (shifted & T::one())
  } else {
    (input + (divisor >> 1)) >> shift
  }
}

/// Approximately evaluate an integer polynomial at an input in the range [-0.5, 0.5].
///
/// The input is represented as an integer combined with a right-shift size.
/// Each coefficient, except the constant one, must obey coefficient.abs() <= T::max_value() >> shift.
/// The constant coefficient must obey coefficient.abs() <= T::max_value() - (T::max_value() >> shift),
/// i.e. be small enough that you can add one of the other coefficients to it without overflowing.
/// Given these conditions, the result is guaranteed to be strictly within 1 of the ideal result.
/// For instance, if the ideal result was 2.125, this function could return 2 or 3,
/// but if it was 2, this function can only return exactly 2.
pub fn evaluate_polynomial_at_small_input <Coefficient: Copy, T: PrimInt + Signed + From <Coefficient>> (coefficients: & [Coefficient], input: T, shift: usize)->T {
  let half = (T::one() << shift) >> 1;
  assert!(-half <= input && input <= half, "inputs to evaluate_polynomial_at_small_input must be in the range [-0.5, 0.5]");

  if coefficients.len () == 0 {return T::zero()}

  let mut result = T::zero();
  for coefficient in coefficients.iter().skip(1).rev() {
    result = right_shift_nicely_rounded ((result + (*coefficient).into())*input, shift);
  }
  result + coefficients [0].into()
}

#[cfg (test)]
mod tests {
  use super::*;
  use num::{Zero, One, FromPrimitive};
  use num::bigint::BigInt;
  use num::rational::{Ratio, BigRational};
  use rand::distributions::Distribution;
  use rand::distributions::range::{Range};
  use rand::{Rng, SeedableRng};

  fn evaluate_polynomial_exactly <Coefficient: Copy, T: PrimInt + Signed + From <Coefficient>> (coefficients: & [Coefficient], input: T, shift: usize)->BigRational
    where BigInt: From <Coefficient> + From <T> {
    let mut result: BigRational = Ratio::zero();
    let input = Ratio::new(BigInt::from (input), BigInt::one() << shift);
    for coefficient in coefficients.iter().rev() {
      result = result*&input + BigInt::from(*coefficient);
    }
    result
  }

  #[test]
  fn test_right_shift_nicely_rounded() {
    let inputs: Vec<(i64, usize, i64)> = vec![
      (0, 0, 0), (0, 5, 0), (1, 3, 0), (4, 3, 0), (5, 3, 1),
      (999, 1, 500), (998, 1, 499), (997, 1, 498)
    ];
    for (input, shift, result) in inputs {
      assert_eq!(right_shift_nicely_rounded (input, shift), result);
      assert_eq!(right_shift_nicely_rounded (-input, shift), -result);
    }
  }

  #[test]
  fn test_evaluate_polynomial_at_small_input() {
    let mut generator =::rand::chacha::ChaChaRng::from_seed ([33; 32]) ;
    for shift in 0..5 {
      let shift = 1 << shift;
      let half = 1i64 << (shift - 1);
      let maximum = i64::max_value() >> shift;
      let constant_maximum = i64::max_value() - maximum;
      let range = Range::new_inclusive (- maximum, maximum) ;
      let constant_range = Range::new_inclusive (- constant_maximum, constant_maximum);
      let mut test_inputs = vec![- half, - half + 1, - 1, 0, 1, half - 1, half];
      if half > 2 {for _ in 0..6 {test_inputs.push (generator.gen_range (- half + 2, half - 1));}}
      for _ in 0..40 {
        let mut coefficients = vec![constant_range.sample (&mut generator)];
        while generator.gen() {coefficients.push (range.sample (&mut generator));}
        for input in test_inputs.iter() {
          let result = evaluate_polynomial_at_small_input (& coefficients,*input, shift);

          let perfect_result = evaluate_polynomial_exactly (& coefficients,*input, shift);
          let difference = Ratio::from_integer (FromPrimitive::from_i64 (result).unwrap()) - perfect_result;
          assert!(difference < Ratio::from_integer (FromPrimitive::from_i64 (1).unwrap()));
        }
      }
    }
  }
}
<commit_msg>Implemented translate_polynomial()<commit_after>use num::{PrimInt, Signed};
use std::mem;

/// Right-shift an integer, but round to nearest, with ties rounding to even.
///
/// This minimizes error, and avoids a directional bias.
pub fn right_shift_nicely_rounded <T: PrimInt> (input: T, shift: usize)->T {
  let divisor = T::one() << shift;
  let mask = divisor - T::one();
  if (input & mask) << 1 == divisor {
    let shifted = input >> shift;
    shifted + (shifted & T::one())
  } else {
    (input + (divisor >> 1)) >> shift
  }
}

/// Approximately evaluate an integer polynomial at an input in the range [-0.5, 0.5].
///
/// The input is represented as an integer combined with a right-shift size.
/// Each coefficient, except the constant one, must obey coefficient.abs() <= T::max_value() >> shift.
/// The constant coefficient must obey coefficient.abs() <= T::max_value() - (T::max_value() >> shift),
/// i.e. be small enough that you can add one of the other coefficients to it without overflowing.
/// Given these conditions, the result is guaranteed to be strictly within 1 of the ideal result.
/// For instance, if the ideal result was 2.125, this function could return 2 or 3,
/// but if it was 2, this function can only return exactly 2.
pub fn evaluate_polynomial_at_small_input <Coefficient: Copy, T: PrimInt + Signed + From <Coefficient>> (coefficients: & [Coefficient], input: T, shift: usize)->T {
  let half = (T::one() << shift) >> 1;
  assert!(-half <= input && input <= half, "inputs to evaluate_polynomial_at_small_input must be in the range [-0.5, 0.5]");

  if coefficients.len () == 0 {return T::zero()}

  let mut result = T::zero();
  for coefficient in coefficients.iter().skip(1).rev() {
    result = right_shift_nicely_rounded ((result + (*coefficient).into())*input, shift);
  }
  result + coefficients [0].into()
}

/// Translate a polynomial horizontally, letting it take inputs relative to a given input instead of relative to 0.
///
/// This is equivalent to replacing its coefficients with its Taylor coefficients at the given input.
/// This is equivalent to translating the graph *left* by the given input amount.
///
/// To avoid overflow, each term, when evaluating that the given input,
/// must obey term.abs() <= T::max_value() >> (coefficients.len() - 1).
/// If this condition is broken, translate_polynomial() returns Err and makes no changes.
pub fn translate_polynomial <T: PrimInt + Signed> (coefficients: &mut [T], input: T)->Result <(),()> {
  if coefficients.len() == 0 {return Ok(());}
  let maximum = T::max_value() >> (coefficients.len() - 1) ;
  let mut factor = T::one();
  for (index, coefficient) in coefficients.iter().enumerate() {
    if coefficient == &T::min_value() {return Err (());}
    match coefficient.abs().checked_mul (&factor) {
      None => return Err (()),
      Some (term) => if term > maximum {return Err (());},
    }
    if index + 1 < coefficients.len() { match factor.checked_mul (&input) {
      None => return Err (()),
      Some (next_factor) => factor = next_factor,
    }}
  }
  translate_polynomial_unchecked (coefficients, input) ;
  Ok (())
}

/// Same as translate_polynomial(), but assume no overflow will occur.
///
/// Useful in performance-critical code when you already know there won't be overflow,
/// such as in the range returned by TODO.
pub fn translate_polynomial_unchecked <T: PrimInt + Signed> (coefficients: &mut [T], input: T) {
  coefficients.reverse();
  for index in 0..coefficients.len() {
    let coefficient = mem::replace (&mut coefficients [index], T::zero());
    for derivative in (1..(index + 1)).rev() {
      coefficients [derivative] = coefficients [derivative]*input + coefficients [derivative - 1]
    }
    coefficients [0] = coefficients [0]*input + coefficient
  }
}

#[cfg (test)]
mod tests {
  use super::*;
  use num::{Zero, One, FromPrimitive};
  use num::bigint::BigInt;
  use num::rational::{Ratio, BigRational};
  use rand::distributions::Distribution;
  use rand::distributions::range::{Range};
  use rand::{Rng, SeedableRng};

  fn evaluate_polynomial_exactly <Coefficient: Copy, T: PrimInt + Signed + From <Coefficient>> (coefficients: & [Coefficient], input: T, shift: usize)->BigRational
    where BigInt: From <Coefficient> + From <T> {
    let mut result: BigRational = Ratio::zero();
    let input = Ratio::new(BigInt::from (input), BigInt::one() << shift);
    for coefficient in coefficients.iter().rev() {
      result = result*&input + BigInt::from(*coefficient);
    }
    result
  }

  #[test]
  fn test_right_shift_nicely_rounded() {
    let inputs: Vec<(i64, usize, i64)> = vec![
      (0, 0, 0), (0, 5, 0), (1, 3, 0), (4, 3, 0), (5, 3, 1),
      (999, 1, 500), (998, 1, 499), (997, 1, 498)
    ];
    for (input, shift, result) in inputs {
      assert_eq!(right_shift_nicely_rounded (input, shift), result);
      assert_eq!(right_shift_nicely_rounded (-input, shift), -result);
    }
  }

  #[test]
  fn test_evaluate_polynomial_at_small_input() {
    let mut generator =::rand::chacha::ChaChaRng::from_seed ([33; 32]) ;
    for shift in 0..5 {
      let shift = 1 << shift;
      let half = 1i64 << (shift - 1);
      let maximum = i64::max_value() >> shift;
      let constant_maximum = i64::max_value() - maximum;
      let range = Range::new_inclusive (- maximum, maximum) ;
      let constant_range = Range::new_inclusive (- constant_maximum, constant_maximum);
      let mut test_inputs = vec![- half, - half + 1, - 1, 0, 1, half - 1, half];
      if half > 2 {for _ in 0..6 {test_inputs.push (generator.gen_range (- half + 2, half - 1));}}
      for _ in 0..40 {
        let mut coefficients = vec![constant_range.sample (&mut generator)];
        while generator.gen() {coefficients.push (range.sample (&mut generator));}
        for input in test_inputs.iter() {
          let result = evaluate_polynomial_at_small_input (& coefficients,*input, shift);

          let perfect_result = evaluate_polynomial_exactly (& coefficients,*input, shift);
          let difference = Ratio::from_integer (FromPrimitive::from_i64 (result).unwrap()) - perfect_result;
          assert!(difference < Ratio::from_integer (FromPrimitive::from_i64 (1).unwrap()));
        }
      }
    }
  }
}
<|endoftext|>