<commit_before>// Copyright 2012-2014 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::cmp;
use std::hashmap::HashSet;
use std::local_data;
use std::uint;
use syntax::ast;

use clean;
use clean::Item;
use plugins;
use fold;
use fold::DocFolder;

/// Strip items marked `#[doc(hidden)]`
pub fn strip_hidden(krate: clean::Crate) -> plugins::PluginResult {
    struct Stripper;
    impl fold::DocFolder for Stripper {
        fn fold_item(&mut self, i: Item) -> Option<Item> {
            for attr in i.attrs.iter() {
                match attr {
                    &clean::List(~"doc", ref l) => {
                        for innerattr in l.iter() {
                            match innerattr {
                                &clean::Word(ref s) if "hidden" == *s => {
                                    debug!("found one in strip_hidden; removing");
                                    return None;
                                },
                                _ => (),
                            }
                        }
                    },
                    _ => ()
                }
            }
            self.fold_item_recur(i)
        }
    }
    let mut stripper = Stripper;
    let krate = stripper.fold_crate(krate);
    (krate, None)
}

/// Strip private items from the point of view of a crate or externally from a
/// crate, specified by the `xcrate` flag.
pub fn strip_private(krate: clean::Crate) -> plugins::PluginResult {
    // This stripper collects all *retained* nodes.
    let mut retained = HashSet::new();
    let exported_items = local_data::get(super::analysiskey, |analysis| {
        analysis.unwrap().exported_items.clone()
    });
    let mut krate = krate;

    // strip all private items
    {
        let mut stripper = Stripper {
            retained: &mut retained,
            exported_items: &exported_items,
        };
        krate = stripper.fold_crate(krate);
    }

    // strip all private implementations of traits
    {
        let mut stripper = ImplStripper(&retained);
        krate = stripper.fold_crate(krate);
    }
    (krate, None)
}

struct Stripper<'a> {
    retained: &'a mut HashSet<ast::NodeId>,
    exported_items: &'a HashSet<ast::NodeId>,
}

impl<'a> fold::DocFolder for Stripper<'a> {
    fn fold_item(&mut self, i: Item) -> Option<Item> {
        match i.inner {
            // These items can all get re-exported
            clean::TypedefItem(..) | clean::StaticItem(..) |
            clean::StructItem(..) | clean::EnumItem(..) |
            clean::TraitItem(..) | clean::FunctionItem(..) |
            clean::VariantItem(..) | clean::MethodItem(..) |
            clean::ForeignFunctionItem(..) | clean::ForeignStaticItem(..) => {
                if !self.exported_items.contains(&i.id) {
                    return None;
                }
            }

            clean::ViewItemItem(..) => {
                if i.visibility != Some(ast::Public) {
                    return None
                }
            }

            clean::StructFieldItem(..) => {
                if i.visibility == Some(ast::Private) {
                    return None;
                }
            }

            // handled below
            clean::ModuleItem(..) => {}

            // impls/tymethods have no control over privacy
            clean::ImplItem(..) | clean::TyMethodItem(..) => {}
        }

        let fastreturn = match i.inner {
            // nothing left to do for traits (don't want to filter their
            // methods out, visibility controlled by the trait)
            clean::TraitItem(..) => true,

            // implementations of traits are always public.
            clean::ImplItem(ref imp) if imp.trait_.is_some() => true,

            _ => false,
        };

        let i = if fastreturn {
            self.retained.insert(i.id);
            return Some(i);
        } else {
            self.fold_item_recur(i)
        };

        match i {
            Some(i) => {
                match i.inner {
                    // emptied modules/impls have no need to exist
                    clean::ModuleItem(ref m)
                        if m.items.len() == 0 &&
                           i.doc_value().is_none() => None,
                    clean::ImplItem(ref i) if i.methods.len() == 0 => None,
                    _ => {
                        self.retained.insert(i.id);
                        Some(i)
                    }
                }
            }
            None => None,
        }
    }
}

// This stripper discards all private impls of traits
struct ImplStripper<'a>(&'a HashSet<ast::NodeId>);
impl<'a> fold::DocFolder for ImplStripper<'a> {
    fn fold_item(&mut self, i: Item) -> Option<Item> {
        match i.inner {
            clean::ImplItem(ref imp) => {
                match imp.trait_ {
                    Some(clean::ResolvedPath{ id, .. }) => {
                        let ImplStripper(s) = *self;
                        if !s.contains(&id) {
                            return None;
                        }
                    }
                    Some(..) | None => {}
                }
            }
            _ => {}
        }
        self.fold_item_recur(i)
    }
}

pub fn unindent_comments(krate: clean::Crate) -> plugins::PluginResult {
    struct CommentCleaner;
    impl fold::DocFolder for CommentCleaner {
        fn fold_item(&mut self, i: Item) -> Option<Item> {
            let mut i = i;
            let mut avec: ~[clean::Attribute] = ~[];
            for attr in i.attrs.iter() {
                match attr {
                    &clean::NameValue(~"doc", ref s) => avec.push(
                        clean::NameValue(~"doc", unindent(*s))),
                    x => avec.push(x.clone())
                }
            }
            i.attrs = avec;
            self.fold_item_recur(i)
        }
    }
    let mut cleaner = CommentCleaner;
    let krate = cleaner.fold_crate(krate);
    (krate, None)
}

pub fn collapse_docs(krate: clean::Crate) -> plugins::PluginResult {
    struct Collapser;
    impl fold::DocFolder for Collapser {
        fn fold_item(&mut self, i: Item) -> Option<Item> {
            let mut docstr = ~"";
            let mut i = i;
            for attr in i.attrs.iter() {
                match *attr {
                    clean::NameValue(~"doc", ref s) => {
                        docstr.push_str(s.clone());
                        docstr.push_char('\n');
                    },
                    _ => ()
                }
            }
            let mut a: ~[clean::Attribute] = i.attrs.iter().filter(|&a| match a {
                &clean::NameValue(~"doc", _) => false,
                _ => true
            }).map(|x| x.clone()).collect();
            if "" != docstr {
                a.push(clean::NameValue(~"doc", docstr));
            }
            i.attrs = a;
            self.fold_item_recur(i)
        }
    }
    let mut collapser = Collapser;
    let krate = collapser.fold_crate(krate);
    (krate, None)
}

pub fn unindent(s: &str) -> ~str {
    let lines = s.lines_any().collect::<~[&str]>();
    let mut saw_first_line = false;
    let mut saw_second_line = false;
    let min_indent = lines.iter().fold(uint::MAX, |min_indent, line| {

        // After we see the first non-whitespace line, look at
        // the line we have. If it is not whitespace, and therefore
        // part of the first paragraph, then ignore the indentation
        // level of the first line
        let ignore_previous_indents =
            saw_first_line &&
            !saw_second_line &&
            !line.is_whitespace();

        let min_indent = if ignore_previous_indents {
            uint::MAX
        } else {
            min_indent
        };

        if saw_first_line {
            saw_second_line = true;
        }

        if line.is_whitespace() {
            min_indent
        } else {
            saw_first_line = true;
            let mut spaces = 0;
            line.chars().all(|char| {
                // Only comparing against space because I wouldn't
                // know what to do with mixed whitespace chars
                if char == ' ' {
                    spaces += 1;
                    true
                } else {
                    false
                }
            });
            cmp::min(min_indent, spaces)
        }
    });

    match lines {
        [head, .. tail] => {
            let mut unindented = ~[ head.trim() ];
            unindented.push_all(tail.map(|&line| {
                if line.is_whitespace() {
                    line
                } else {
                    assert!(line.len() >= min_indent);
                    line.slice_from(min_indent)
                }
            }));
            unindented.connect("\n")
        }
        [] => s.to_owned()
    }
}

#[cfg(test)]
mod unindent_tests {
    use super::unindent;

    #[test]
    fn should_unindent() {
        let s = ~"    line1\n    line2";
        let r = unindent(s);
        assert_eq!(r, ~"line1\nline2");
    }

    #[test]
    fn should_unindent_multiple_paragraphs() {
        let s = ~"    line1\n\n    line2";
        let r = unindent(s);
        assert_eq!(r, ~"line1\n\nline2");
    }

    #[test]
    fn should_leave_multiple_indent_levels() {
        // Line 2 is indented another level beyond the
        // base indentation and should be preserved
        let s = ~"    line1\n\n        line2";
        let r = unindent(s);
        assert_eq!(r, ~"line1\n\n    line2");
    }

    #[test]
    fn should_ignore_first_line_indent() {
        // Thi first line of the first paragraph may not be indented as
        // far due to the way the doc string was written:
        //
        // #[doc = "Start way over here
        //          and continue here"]
        let s = ~"line1\n    line2";
        let r = unindent(s);
        assert_eq!(r, ~"line1\nline2");
    }

    #[test]
    fn should_not_ignore_first_line_indent_in_a_single_line_para() {
        let s = ~"line1\n\n    line2";
        let r = unindent(s);
        assert_eq!(r, ~"line1\n\n    line2");
    }
}
<commit_msg>auto merge of #12195 : kballard/rust/rustdoc-strip-impls-of-stripped, r=cmr<commit_after>// Copyright 2012-2014 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::cmp;
use std::hashmap::HashSet;
use std::local_data;
use std::uint;
use syntax::ast;

use clean;
use clean::Item;
use plugins;
use fold;
use fold::DocFolder;

/// Strip items marked `#[doc(hidden)]`
pub fn strip_hidden(krate: clean::Crate) -> plugins::PluginResult {
    let mut stripped = HashSet::new();

    // strip all #[doc(hidden)] items
    let krate = {
        struct Stripper<'a> {
            stripped: &'a mut HashSet<ast::NodeId>
        };
        impl<'a> fold::DocFolder for Stripper<'a> {
            fn fold_item(&mut self, i: Item) -> Option<Item> {
                for attr in i.attrs.iter() {
                    match attr {
                        &clean::List(~"doc", ref l) => {
                            for innerattr in l.iter() {
                                match innerattr {
                                    &clean::Word(ref s) if "hidden" == *s => {
                                        debug!("found one in strip_hidden; removing");
                                        self.stripped.insert(i.id);
                                        return None;
                                    },
                                    _ => (),
                                }
                            }
                        },
                        _ => ()
                    }
                }
                self.fold_item_recur(i)
            }
        }
        let mut stripper = Stripper{ stripped: &mut stripped };
        stripper.fold_crate(krate)
    };

    // strip any traits implemented on stripped items
    let krate = {
        struct ImplStripper<'a> {
            stripped: &'a mut HashSet<ast::NodeId>
        };
        impl<'a> fold::DocFolder for ImplStripper<'a> {
            fn fold_item(&mut self, i: Item) -> Option<Item> {
                match i.inner {
                    clean::ImplItem(clean::Impl{ for_: clean::ResolvedPath{ id: for_id, .. },
                                                 .. }) => {
                        if self.stripped.contains(&for_id) {
                            return None;
                        }
                    }
                    _ => {}
                }
                self.fold_item_recur(i)
            }
        }
        let mut stripper = ImplStripper{ stripped: &mut stripped };
        stripper.fold_crate(krate)
    };

    (krate, None)
}

/// Strip private items from the point of view of a crate or externally from a
/// crate, specified by the `xcrate` flag.
pub fn strip_private(krate: clean::Crate) -> plugins::PluginResult {
    // This stripper collects all *retained* nodes.
    let mut retained = HashSet::new();
    let exported_items = local_data::get(super::analysiskey, |analysis| {
        analysis.unwrap().exported_items.clone()
    });
    let mut krate = krate;

    // strip all private items
    {
        let mut stripper = Stripper {
            retained: &mut retained,
            exported_items: &exported_items,
        };
        krate = stripper.fold_crate(krate);
    }

    // strip all private implementations of traits
    {
        let mut stripper = ImplStripper(&retained);
        krate = stripper.fold_crate(krate);
    }
    (krate, None)
}

struct Stripper<'a> {
    retained: &'a mut HashSet<ast::NodeId>,
    exported_items: &'a HashSet<ast::NodeId>,
}

impl<'a> fold::DocFolder for Stripper<'a> {
    fn fold_item(&mut self, i: Item) -> Option<Item> {
        match i.inner {
            // These items can all get re-exported
            clean::TypedefItem(..) | clean::StaticItem(..) |
            clean::StructItem(..) | clean::EnumItem(..) |
            clean::TraitItem(..) | clean::FunctionItem(..) |
            clean::VariantItem(..) | clean::MethodItem(..) |
            clean::ForeignFunctionItem(..) | clean::ForeignStaticItem(..) => {
                if !self.exported_items.contains(&i.id) {
                    return None;
                }
            }

            clean::ViewItemItem(..) => {
                if i.visibility != Some(ast::Public) {
                    return None
                }
            }

            clean::StructFieldItem(..) => {
                if i.visibility == Some(ast::Private) {
                    return None;
                }
            }

            // handled below
            clean::ModuleItem(..) => {}

            // trait impls for private items should be stripped
            clean::ImplItem(clean::Impl{ for_: clean::ResolvedPath{ id: ref for_id, .. }, .. }) => {
                if !self.exported_items.contains(for_id) {
                    return None;
                }
            }
            clean::ImplItem(..) => {}

            // tymethods have no control over privacy
            clean::TyMethodItem(..) => {}
        }

        let fastreturn = match i.inner {
            // nothing left to do for traits (don't want to filter their
            // methods out, visibility controlled by the trait)
            clean::TraitItem(..) => true,

            // implementations of traits are always public.
            clean::ImplItem(ref imp) if imp.trait_.is_some() => true,

            _ => false,
        };

        let i = if fastreturn {
            self.retained.insert(i.id);
            return Some(i);
        } else {
            self.fold_item_recur(i)
        };

        match i {
            Some(i) => {
                match i.inner {
                    // emptied modules/impls have no need to exist
                    clean::ModuleItem(ref m)
                        if m.items.len() == 0 &&
                           i.doc_value().is_none() => None,
                    clean::ImplItem(ref i) if i.methods.len() == 0 => None,
                    _ => {
                        self.retained.insert(i.id);
                        Some(i)
                    }
                }
            }
            None => None,
        }
    }
}

// This stripper discards all private impls of traits
struct ImplStripper<'a>(&'a HashSet<ast::NodeId>);
impl<'a> fold::DocFolder for ImplStripper<'a> {
    fn fold_item(&mut self, i: Item) -> Option<Item> {
        match i.inner {
            clean::ImplItem(ref imp) => {
                match imp.trait_ {
                    Some(clean::ResolvedPath{ id, .. }) => {
                        let ImplStripper(s) = *self;
                        if !s.contains(&id) {
                            return None;
                        }
                    }
                    Some(..) | None => {}
                }
            }
            _ => {}
        }
        self.fold_item_recur(i)
    }
}

pub fn unindent_comments(krate: clean::Crate) -> plugins::PluginResult {
    struct CommentCleaner;
    impl fold::DocFolder for CommentCleaner {
        fn fold_item(&mut self, i: Item) -> Option<Item> {
            let mut i = i;
            let mut avec: ~[clean::Attribute] = ~[];
            for attr in i.attrs.iter() {
                match attr {
                    &clean::NameValue(~"doc", ref s) => avec.push(
                        clean::NameValue(~"doc", unindent(*s))),
                    x => avec.push(x.clone())
                }
            }
            i.attrs = avec;
            self.fold_item_recur(i)
        }
    }
    let mut cleaner = CommentCleaner;
    let krate = cleaner.fold_crate(krate);
    (krate, None)
}

pub fn collapse_docs(krate: clean::Crate) -> plugins::PluginResult {
    struct Collapser;
    impl fold::DocFolder for Collapser {
        fn fold_item(&mut self, i: Item) -> Option<Item> {
            let mut docstr = ~"";
            let mut i = i;
            for attr in i.attrs.iter() {
                match *attr {
                    clean::NameValue(~"doc", ref s) => {
                        docstr.push_str(s.clone());
                        docstr.push_char('\n');
                    },
                    _ => ()
                }
            }
            let mut a: ~[clean::Attribute] = i.attrs.iter().filter(|&a| match a {
                &clean::NameValue(~"doc", _) => false,
                _ => true
            }).map(|x| x.clone()).collect();
            if "" != docstr {
                a.push(clean::NameValue(~"doc", docstr));
            }
            i.attrs = a;
            self.fold_item_recur(i)
        }
    }
    let mut collapser = Collapser;
    let krate = collapser.fold_crate(krate);
    (krate, None)
}

pub fn unindent(s: &str) -> ~str {
    let lines = s.lines_any().collect::<~[&str]>();
    let mut saw_first_line = false;
    let mut saw_second_line = false;
    let min_indent = lines.iter().fold(uint::MAX, |min_indent, line| {

        // After we see the first non-whitespace line, look at
        // the line we have. If it is not whitespace, and therefore
        // part of the first paragraph, then ignore the indentation
        // level of the first line
        let ignore_previous_indents =
            saw_first_line &&
            !saw_second_line &&
            !line.is_whitespace();

        let min_indent = if ignore_previous_indents {
            uint::MAX
        } else {
            min_indent
        };

        if saw_first_line {
            saw_second_line = true;
        }

        if line.is_whitespace() {
            min_indent
        } else {
            saw_first_line = true;
            let mut spaces = 0;
            line.chars().all(|char| {
                // Only comparing against space because I wouldn't
                // know what to do with mixed whitespace chars
                if char == ' ' {
                    spaces += 1;
                    true
                } else {
                    false
                }
            });
            cmp::min(min_indent, spaces)
        }
    });

    match lines {
        [head, .. tail] => {
            let mut unindented = ~[ head.trim() ];
            unindented.push_all(tail.map(|&line| {
                if line.is_whitespace() {
                    line
                } else {
                    assert!(line.len() >= min_indent);
                    line.slice_from(min_indent)
                }
            }));
            unindented.connect("\n")
        }
        [] => s.to_owned()
    }
}

#[cfg(test)]
mod unindent_tests {
    use super::unindent;

    #[test]
    fn should_unindent() {
        let s = ~"    line1\n    line2";
        let r = unindent(s);
        assert_eq!(r, ~"line1\nline2");
    }

    #[test]
    fn should_unindent_multiple_paragraphs() {
        let s = ~"    line1\n\n    line2";
        let r = unindent(s);
        assert_eq!(r, ~"line1\n\nline2");
    }

    #[test]
    fn should_leave_multiple_indent_levels() {
        // Line 2 is indented another level beyond the
        // base indentation and should be preserved
        let s = ~"    line1\n\n        line2";
        let r = unindent(s);
        assert_eq!(r, ~"line1\n\n    line2");
    }

    #[test]
    fn should_ignore_first_line_indent() {
        // Thi first line of the first paragraph may not be indented as
        // far due to the way the doc string was written:
        //
        // #[doc = "Start way over here
        //          and continue here"]
        let s = ~"line1\n    line2";
        let r = unindent(s);
        assert_eq!(r, ~"line1\nline2");
    }

    #[test]
    fn should_not_ignore_first_line_indent_in_a_single_line_para() {
        let s = ~"line1\n\n    line2";
        let r = unindent(s);
        assert_eq!(r, ~"line1\n\n    line2");
    }
}
<|endoftext|>


<commit_before>// Copyright (c) 2017-2018, The rav1e contributors. All rights reserved
//
// This source code is subject to the terms of the BSD 2 Clause License and
// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
// was not distributed with this source code in the LICENSE file, you can
// obtain it at www.aomedia.org/license/software. If the Alliance for Open
// Media Patent License 1.0 was not distributed with this source code in the
// PATENTS file, you can obtain it at www.aomedia.org/license/patent.

use context::BlockOffset;
use context::BLOCK_TO_PLANE_SHIFT;
use context::MI_SIZE;
use partition::*;
use plane::*;
use FrameInvariants;
use FrameState;

#[inline(always)]
pub fn get_sad(
  plane_org: &mut PlaneSlice, plane_ref: &mut PlaneSlice, blk_h: usize,
  blk_w: usize
) -> u32 {
  let mut sum = 0 as u32;

  for _r in 0..blk_h {
    {
      let slice_org = plane_org.as_slice_w_width(blk_w);
      let slice_ref = plane_ref.as_slice_w_width(blk_w);
      sum += slice_org
        .iter()
        .zip(slice_ref)
        .map(|(&a, &b)| (a as i32 - b as i32).abs() as u32)
        .sum::<u32>();
    }
    plane_org.y += 1;
    plane_ref.y += 1;
  }

  sum
}

pub fn motion_estimation(
  fi: &FrameInvariants, fs: &mut FrameState, bsize: BlockSize,
  bo: &BlockOffset, ref_frame: usize
) -> MotionVector {
  match fi.rec_buffer.frames[fi.ref_frames[ref_frame - LAST_FRAME]] {
    Some(ref rec) => {
      let po = PlaneOffset {
        x: (bo.x as isize) << BLOCK_TO_PLANE_SHIFT,
        y: (bo.y as isize) << BLOCK_TO_PLANE_SHIFT
      };
      let range = 32 as isize;
      let blk_w = bsize.width();
      let blk_h = bsize.height();
      let border_w = 128 + blk_w as isize * 8;
      let border_h = 128 + blk_h as isize * 8;
      let cols = (rec.frame.planes[0].cfg.width + MI_SIZE - 1) / MI_SIZE;
      let rows = (rec.frame.planes[0].cfg.height + MI_SIZE - 1) / MI_SIZE;
      let x_min = -(bo.x as isize) * (8 * MI_SIZE) as isize - border_w;
      let x_max = (cols - bo.x - blk_w / MI_SIZE) as isize * (8 * MI_SIZE) as isize + border_w;
      let y_min = -(bo.y as isize) * (8 * MI_SIZE) as isize - border_h;
      let y_max = (rows - bo.y - blk_h / MI_SIZE) as isize * (8 * MI_SIZE) as isize + border_h;
      let x_lo = po.x - (range.max(x_min / 8));
      let x_hi = po.x + (range.min(x_max / 8));
      let y_lo = po.y - (range.max(y_min / 8));
      let y_hi = po.y + (range.min(y_max / 8));

      let mut lowest_sad = 128 * 128 * 4096 as u32;
      let mut best_mv = MotionVector { row: 0, col: 0 };

      for y in (y_lo..y_hi).step_by(2) {
        for x in (x_lo..x_hi).step_by(2) {
          let mut plane_org = fs.input.planes[0].slice(&po);
          let mut plane_ref = rec.frame.planes[0].slice(&PlaneOffset { x, y });

          let sad = get_sad(&mut plane_org, &mut plane_ref, blk_h, blk_w);

          if sad < lowest_sad {
            lowest_sad = sad;
            best_mv = MotionVector {
              row: 8 * (y as i16 - po.y as i16),
              col: 8 * (x as i16 - po.x as i16)
            }
          }
        }
      }

      let mode = PredictionMode::NEWMV;
      let mut tmp_plane = Plane::new(blk_w, blk_h, 0, 0, 0, 0);

      let mut steps = vec![8, 4, 2];
      if fi.allow_high_precision_mv {
        steps.push(1);
      }

      for step in steps {
        let center_mv_h = best_mv;
        for i in 0..3 {
          for j in 0..3 {
            // Skip the center point that was already tested
            if i == 1 && j == 1 {
              continue;
            }

            let cand_mv = MotionVector {
              row: center_mv_h.row + step * (i as i16 - 1),
              col: center_mv_h.col + step * (j as i16 - 1)
            };

            if (cand_mv.col as isize) < x_min || (cand_mv.col as isize) > x_max {
              continue;
            }
            if (cand_mv.row as isize) < y_min || (cand_mv.row as isize) > y_max {
              continue;
            }

            {
              let tmp_slice =
                &mut tmp_plane.mut_slice(&PlaneOffset { x: 0, y: 0 });

              mode.predict_inter(
                fi, 0, &po, tmp_slice, blk_w, blk_h, ref_frame, &cand_mv, 8,
              );
            }

            let mut plane_org = fs.input.planes[0].slice(&po);
            let mut plane_ref = tmp_plane.slice(&PlaneOffset { x: 0, y: 0 });

            let sad = get_sad(&mut plane_org, &mut plane_ref, blk_h, blk_w);

            if sad < lowest_sad {
              lowest_sad = sad;
              best_mv = cand_mv;
            }
          }
        }
      }

      best_mv
    }

    None => MotionVector { row: 0, col: 0 }
  }
}
<commit_msg>Fix ME search range<commit_after>// Copyright (c) 2017-2018, The rav1e contributors. All rights reserved
//
// This source code is subject to the terms of the BSD 2 Clause License and
// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
// was not distributed with this source code in the LICENSE file, you can
// obtain it at www.aomedia.org/license/software. If the Alliance for Open
// Media Patent License 1.0 was not distributed with this source code in the
// PATENTS file, you can obtain it at www.aomedia.org/license/patent.

use context::BlockOffset;
use context::BLOCK_TO_PLANE_SHIFT;
use context::MI_SIZE;
use partition::*;
use plane::*;
use FrameInvariants;
use FrameState;

#[inline(always)]
pub fn get_sad(
  plane_org: &mut PlaneSlice, plane_ref: &mut PlaneSlice, blk_h: usize,
  blk_w: usize
) -> u32 {
  let mut sum = 0 as u32;

  for _r in 0..blk_h {
    {
      let slice_org = plane_org.as_slice_w_width(blk_w);
      let slice_ref = plane_ref.as_slice_w_width(blk_w);
      sum += slice_org
        .iter()
        .zip(slice_ref)
        .map(|(&a, &b)| (a as i32 - b as i32).abs() as u32)
        .sum::<u32>();
    }
    plane_org.y += 1;
    plane_ref.y += 1;
  }

  sum
}

pub fn motion_estimation(
  fi: &FrameInvariants, fs: &mut FrameState, bsize: BlockSize,
  bo: &BlockOffset, ref_frame: usize
) -> MotionVector {
  match fi.rec_buffer.frames[fi.ref_frames[ref_frame - LAST_FRAME]] {
    Some(ref rec) => {
      let po = PlaneOffset {
        x: (bo.x as isize) << BLOCK_TO_PLANE_SHIFT,
        y: (bo.y as isize) << BLOCK_TO_PLANE_SHIFT
      };
      let range = 32 as isize;
      let blk_w = bsize.width();
      let blk_h = bsize.height();
      let border_w = 128 + blk_w as isize * 8;
      let border_h = 128 + blk_h as isize * 8;
      let cols = (rec.frame.planes[0].cfg.width + MI_SIZE - 1) / MI_SIZE;
      let rows = (rec.frame.planes[0].cfg.height + MI_SIZE - 1) / MI_SIZE;
      let x_min = -(bo.x as isize) * (8 * MI_SIZE) as isize - border_w;
      let x_max = (cols - bo.x - blk_w / MI_SIZE) as isize * (8 * MI_SIZE) as isize + border_w;
      let y_min = -(bo.y as isize) * (8 * MI_SIZE) as isize - border_h;
      let y_max = (rows - bo.y - blk_h / MI_SIZE) as isize * (8 * MI_SIZE) as isize + border_h;
      let x_lo = po.x + ((-range).max(x_min / 8));
      let x_hi = po.x + (range.min(x_max / 8));
      let y_lo = po.y + ((-range).max(y_min / 8));
      let y_hi = po.y + (range.min(y_max / 8));

      let mut lowest_sad = 128 * 128 * 4096 as u32;
      let mut best_mv = MotionVector { row: 0, col: 0 };

      for y in (y_lo..y_hi).step_by(2) {
        for x in (x_lo..x_hi).step_by(2) {
          let mut plane_org = fs.input.planes[0].slice(&po);
          let mut plane_ref = rec.frame.planes[0].slice(&PlaneOffset { x, y });

          let sad = get_sad(&mut plane_org, &mut plane_ref, blk_h, blk_w);

          if sad < lowest_sad {
            lowest_sad = sad;
            best_mv = MotionVector {
              row: 8 * (y as i16 - po.y as i16),
              col: 8 * (x as i16 - po.x as i16)
            }
          }
        }
      }

      let mode = PredictionMode::NEWMV;
      let mut tmp_plane = Plane::new(blk_w, blk_h, 0, 0, 0, 0);

      let mut steps = vec![8, 4, 2];
      if fi.allow_high_precision_mv {
        steps.push(1);
      }

      for step in steps {
        let center_mv_h = best_mv;
        for i in 0..3 {
          for j in 0..3 {
            // Skip the center point that was already tested
            if i == 1 && j == 1 {
              continue;
            }

            let cand_mv = MotionVector {
              row: center_mv_h.row + step * (i as i16 - 1),
              col: center_mv_h.col + step * (j as i16 - 1)
            };

            if (cand_mv.col as isize) < x_min || (cand_mv.col as isize) > x_max {
              continue;
            }
            if (cand_mv.row as isize) < y_min || (cand_mv.row as isize) > y_max {
              continue;
            }

            {
              let tmp_slice =
                &mut tmp_plane.mut_slice(&PlaneOffset { x: 0, y: 0 });

              mode.predict_inter(
                fi, 0, &po, tmp_slice, blk_w, blk_h, ref_frame, &cand_mv, 8,
              );
            }

            let mut plane_org = fs.input.planes[0].slice(&po);
            let mut plane_ref = tmp_plane.slice(&PlaneOffset { x: 0, y: 0 });

            let sad = get_sad(&mut plane_org, &mut plane_ref, blk_h, blk_w);

            if sad < lowest_sad {
              lowest_sad = sad;
              best_mv = cand_mv;
            }
          }
        }
      }

      best_mv
    }

    None => MotionVector { row: 0, col: 0 }
  }
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use std::env;
use std::fs::File;
use std::io::Write;
use std::path::Path;
use std::process::{Command, Stdio, exit};

#[cfg(windows)]
fn find_python() -> String {
    if Command::new("python27.exe").arg("--version").output().is_ok() {
        return "python27.exe".to_owned();
    }

    if Command::new("python.exe").arg("--version").output().is_ok() {
        return "python.exe".to_owned();
    }

    panic!("Can't find python (tried python27.exe and python.exe)! Try fixing PATH or setting the PYTHON env var");
}

#[cfg(not(windows))]
fn find_python() -> String {
    if Command::new("python2.7").arg("--version").output().unwrap().status.success() {
        "python2.7"
    } else {
        "python"
    }.to_owned()
}

fn main() {
    let python = match env::var("PYTHON") {
        Ok(python_path) => python_path,
        Err(_) => find_python(),
    };
    let style = Path::new(file!()).parent().unwrap();
    let mako = style.join("Mako-0.9.1.zip");
    let template = style.join("properties.mako.rs");
    let product = if cfg!(feature = "gecko") { "gecko" } else { "servo" };
    let result = Command::new(python)
        .env("PYTHONPATH", &mako)
        .env("TEMPLATE", &template)
        .env("PRODUCT", product)
        .arg("-c")
        .arg(r#"
import os
import sys
from mako.template import Template
from mako import exceptions
try:
    print(Template(filename=os.environ['TEMPLATE'], input_encoding='utf8').render(PRODUCT=os.environ['PRODUCT'])
                                                                          .encode('utf8'))
except:
    sys.stderr.write(exceptions.text_error_template().render().encode('utf8'))
    sys.exit(1)
"#)
        .stderr(Stdio::inherit())
        .output()
        .unwrap();
    if !result.status.success() {
        exit(1)
    }
    let out = env::var("OUT_DIR").unwrap();
    File::create(&Path::new(&out).join("properties.rs")).unwrap().write_all(&result.stdout).unwrap();
}
<commit_msg>Auto merge of #10527 - servo:cr, r=larsbergstrom<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use std::env;
use std::fs::File;
use std::io::Write;
use std::path::Path;
use std::process::{Command, Stdio, exit};

#[cfg(windows)]
fn find_python() -> String {
    if Command::new("python27.exe").arg("--version").output().is_ok() {
        return "python27.exe".to_owned();
    }

    if Command::new("python.exe").arg("--version").output().is_ok() {
        return "python.exe".to_owned();
    }

    panic!("Can't find python (tried python27.exe and python.exe)! Try fixing PATH or setting the PYTHON env var");
}

#[cfg(not(windows))]
fn find_python() -> String {
    if Command::new("python2.7").arg("--version").output().unwrap().status.success() {
        "python2.7"
    } else {
        "python"
    }.to_owned()
}

fn main() {
    let python = match env::var("PYTHON") {
        Ok(python_path) => python_path,
        Err(_) => find_python(),
    };
    let style = Path::new(file!()).parent().unwrap();
    let mako = style.join("Mako-0.9.1.zip");
    let template = style.join("properties.mako.rs");
    let product = if cfg!(feature = "gecko") { "gecko" } else { "servo" };
    let result = Command::new(python)
        .env("PYTHONPATH", &mako)
        .env("TEMPLATE", &template)
        .env("PRODUCT", product)
        .arg("-c")
        .arg(r#"
import os
import sys
from mako.template import Template
from mako import exceptions
try:
    template = Template(open(os.environ['TEMPLATE'], 'rb').read(), input_encoding='utf8')
    print(template.render(PRODUCT=os.environ['PRODUCT']).encode('utf8'))
except:
    sys.stderr.write(exceptions.text_error_template().render().encode('utf8'))
    sys.exit(1)
"#)
        .stderr(Stdio::inherit())
        .output()
        .unwrap();
    if !result.status.success() {
        exit(1)
    }
    let out = env::var("OUT_DIR").unwrap();
    File::create(&Path::new(&out).join("properties.rs")).unwrap().write_all(&result.stdout).unwrap();
}
<|endoftext|>


<commit_before>use ra_ide_db::imports_locator::ImportsLocator;
use ra_syntax::ast::{self, AstNode};

use crate::{
    assist_ctx::{Assist, AssistCtx},
    insert_use_statement, AssistId,
};
use std::collections::BTreeSet;

// Assist: auto_import
//
// If the name is unresolved, provides all possible imports for it.
//
// ```
// fn main() {
//     let map = HashMap<|>::new();
// }
// # pub mod std { pub mod collections { pub struct HashMap { } } }
// ```
// ->
// ```
// use std::collections::HashMap;
//
// fn main() {
//     let map = HashMap::new();
// }
// # pub mod std { pub mod collections { pub struct HashMap { } } }
// ```
pub(crate) fn auto_import(ctx: AssistCtx) -> Option<Assist> {
    let path_under_caret: ast::Path = ctx.find_node_at_offset()?;
    if path_under_caret.syntax().ancestors().find_map(ast::UseItem::cast).is_some() {
        return None;
    }

    let module = path_under_caret.syntax().ancestors().find_map(ast::Module::cast);
    let position = match module.and_then(|it| it.item_list()) {
        Some(item_list) => item_list.syntax().clone(),
        None => {
            let current_file =
                path_under_caret.syntax().ancestors().find_map(ast::SourceFile::cast)?;
            current_file.syntax().clone()
        }
    };
    let source_analyzer = ctx.source_analyzer(&position, None);
    let module_with_name_to_import = source_analyzer.module()?;

    let name_ref_to_import =
        path_under_caret.syntax().descendants().find_map(ast::NameRef::cast)?;
    if source_analyzer
        .resolve_path(ctx.db, &name_ref_to_import.syntax().ancestors().find_map(ast::Path::cast)?)
        .is_some()
    {
        return None;
    }

    let name_to_import = name_ref_to_import.syntax().to_string();
    let proposed_imports = ImportsLocator::new(ctx.db)
        .find_imports(&name_to_import)
        .into_iter()
        .filter_map(|module_def| module_with_name_to_import.find_use_path(ctx.db, module_def))
        .filter(|use_path| !use_path.segments.is_empty())
        .take(20)
        .collect::<BTreeSet<_>>();

    if proposed_imports.is_empty() {
        return None;
    }

    let mut group = ctx.add_assist_group(format!("Import {}", name_to_import));
    for import in proposed_imports {
        group.add_assist(AssistId("auto_import"), format!("Import `{}`", &import), |edit| {
            edit.target(path_to_import_syntax.text_range());
            insert_use_statement(
                &position,
                &path_under_caret.syntax(),
                &import,
                edit.text_edit_builder(),
            );
        });
    }
    group.finish()
}

#[cfg(test)]
mod tests {
    use crate::helpers::{check_assist, check_assist_not_applicable, check_assist_target};

    use super::*;

    #[test]
    fn applicable_when_found_an_import() {
        check_assist(
            auto_import,
            r"
            <|>PubStruct

            pub mod PubMod {
                pub struct PubStruct;
            }
            ",
            r"
            <|>use PubMod::PubStruct;

            PubStruct

            pub mod PubMod {
                pub struct PubStruct;
            }
            ",
        );
    }

    #[test]
    fn auto_imports_are_merged() {
        check_assist(
            auto_import,
            r"
            use PubMod::PubStruct1;

            struct Test {
                test: Pub<|>Struct2<u8>,
            }

            pub mod PubMod {
                pub struct PubStruct1;
                pub struct PubStruct2<T> {
                    _t: T,
                }
            }
            ",
            r"
            use PubMod::{PubStruct2, PubStruct1};

            struct Test {
                test: Pub<|>Struct2<u8>,
            }

            pub mod PubMod {
                pub struct PubStruct1;
                pub struct PubStruct2<T> {
                    _t: T,
                }
            }
            ",
        );
    }

    #[test]
    fn applicable_when_found_multiple_imports() {
        check_assist(
            auto_import,
            r"
            PubSt<|>ruct

            pub mod PubMod1 {
                pub struct PubStruct;
            }
            pub mod PubMod2 {
                pub struct PubStruct;
            }
            pub mod PubMod3 {
                pub struct PubStruct;
            }
            ",
            r"
            use PubMod1::PubStruct;

            PubSt<|>ruct

            pub mod PubMod1 {
                pub struct PubStruct;
            }
            pub mod PubMod2 {
                pub struct PubStruct;
            }
            pub mod PubMod3 {
                pub struct PubStruct;
            }
            ",
        );
    }

    #[test]
    fn not_applicable_for_already_imported_types() {
        check_assist_not_applicable(
            auto_import,
            r"
            use PubMod::PubStruct;

            PubStruct<|>

            pub mod PubMod {
                pub struct PubStruct;
            }
            ",
        );
    }

    #[test]
    fn not_applicable_for_types_with_private_paths() {
        check_assist_not_applicable(
            auto_import,
            r"
            PrivateStruct<|>

            pub mod PubMod {
                struct PrivateStruct;
            }
            ",
        );
    }

    #[test]
    fn not_applicable_when_no_imports_found() {
        check_assist_not_applicable(
            auto_import,
            "
            PubStruct<|>",
        );
    }

    #[test]
    fn not_applicable_in_import_statements() {
        check_assist_not_applicable(
            auto_import,
            r"
            use PubStruct<|>;

            pub mod PubMod {
                pub struct PubStruct;
            }",
        );
    }

    #[test]
    fn function_import() {
        check_assist(
            auto_import,
            r"
            test_function<|>

            pub mod PubMod {
                pub fn test_function() {};
            }
            ",
            r"
            use PubMod::test_function;

            test_function<|>

            pub mod PubMod {
                pub fn test_function() {};
            }
            ",
        );
    }

    #[test]
    fn auto_import_target() {
        check_assist_target(
            auto_import,
            r"
            struct AssistInfo {
                group_label: Option<<|>GroupLabel>,
            }

            mod m { pub struct GroupLabel; }
            ",
            "GroupLabel",
        )
    }

    #[test]
    fn not_applicable_when_path_start_is_imported() {
        check_assist_not_applicable(
            auto_import,
            r"
            pub mod mod1 {
                pub mod mod2 {
                    pub mod mod3 {
                        pub struct TestStruct;
                    }
                }
            }

            use mod1::mod2;
            fn main() {
                mod2::mod3::TestStruct<|>
            }
            ",
        );
    }
}
<commit_msg>Fix rebase leftovers<commit_after>use ra_ide_db::imports_locator::ImportsLocator;
use ra_syntax::ast::{self, AstNode};

use crate::{
    assist_ctx::{Assist, AssistCtx},
    insert_use_statement, AssistId,
};
use std::collections::BTreeSet;

// Assist: auto_import
//
// If the name is unresolved, provides all possible imports for it.
//
// ```
// fn main() {
//     let map = HashMap<|>::new();
// }
// # pub mod std { pub mod collections { pub struct HashMap { } } }
// ```
// ->
// ```
// use std::collections::HashMap;
//
// fn main() {
//     let map = HashMap::new();
// }
// # pub mod std { pub mod collections { pub struct HashMap { } } }
// ```
pub(crate) fn auto_import(ctx: AssistCtx) -> Option<Assist> {
    let path_under_caret: ast::Path = ctx.find_node_at_offset()?;
    if path_under_caret.syntax().ancestors().find_map(ast::UseItem::cast).is_some() {
        return None;
    }

    let module = path_under_caret.syntax().ancestors().find_map(ast::Module::cast);
    let position = match module.and_then(|it| it.item_list()) {
        Some(item_list) => item_list.syntax().clone(),
        None => {
            let current_file =
                path_under_caret.syntax().ancestors().find_map(ast::SourceFile::cast)?;
            current_file.syntax().clone()
        }
    };
    let source_analyzer = ctx.source_analyzer(&position, None);
    let module_with_name_to_import = source_analyzer.module()?;

    let name_ref_to_import =
        path_under_caret.syntax().descendants().find_map(ast::NameRef::cast)?;
    if source_analyzer
        .resolve_path(ctx.db, &name_ref_to_import.syntax().ancestors().find_map(ast::Path::cast)?)
        .is_some()
    {
        return None;
    }

    let name_to_import = name_ref_to_import.syntax().to_string();
    let proposed_imports = ImportsLocator::new(ctx.db)
        .find_imports(&name_to_import)
        .into_iter()
        .filter_map(|module_def| module_with_name_to_import.find_use_path(ctx.db, module_def))
        .filter(|use_path| !use_path.segments.is_empty())
        .take(20)
        .collect::<BTreeSet<_>>();

    if proposed_imports.is_empty() {
        return None;
    }

    let mut group = ctx.add_assist_group(format!("Import {}", name_to_import));
    for import in proposed_imports {
        group.add_assist(AssistId("auto_import"), format!("Import `{}`", &import), |edit| {
            edit.target(path_under_caret.syntax().text_range());
            insert_use_statement(
                &position,
                path_under_caret.syntax(),
                &import,
                edit.text_edit_builder(),
            );
        });
    }
    group.finish()
}

#[cfg(test)]
mod tests {
    use crate::helpers::{check_assist, check_assist_not_applicable, check_assist_target};

    use super::*;

    #[test]
    fn applicable_when_found_an_import() {
        check_assist(
            auto_import,
            r"
            <|>PubStruct

            pub mod PubMod {
                pub struct PubStruct;
            }
            ",
            r"
            <|>use PubMod::PubStruct;

            PubStruct

            pub mod PubMod {
                pub struct PubStruct;
            }
            ",
        );
    }

    #[test]
    fn auto_imports_are_merged() {
        check_assist(
            auto_import,
            r"
            use PubMod::PubStruct1;

            struct Test {
                test: Pub<|>Struct2<u8>,
            }

            pub mod PubMod {
                pub struct PubStruct1;
                pub struct PubStruct2<T> {
                    _t: T,
                }
            }
            ",
            r"
            use PubMod::{PubStruct2, PubStruct1};

            struct Test {
                test: Pub<|>Struct2<u8>,
            }

            pub mod PubMod {
                pub struct PubStruct1;
                pub struct PubStruct2<T> {
                    _t: T,
                }
            }
            ",
        );
    }

    #[test]
    fn applicable_when_found_multiple_imports() {
        check_assist(
            auto_import,
            r"
            PubSt<|>ruct

            pub mod PubMod1 {
                pub struct PubStruct;
            }
            pub mod PubMod2 {
                pub struct PubStruct;
            }
            pub mod PubMod3 {
                pub struct PubStruct;
            }
            ",
            r"
            use PubMod1::PubStruct;

            PubSt<|>ruct

            pub mod PubMod1 {
                pub struct PubStruct;
            }
            pub mod PubMod2 {
                pub struct PubStruct;
            }
            pub mod PubMod3 {
                pub struct PubStruct;
            }
            ",
        );
    }

    #[test]
    fn not_applicable_for_already_imported_types() {
        check_assist_not_applicable(
            auto_import,
            r"
            use PubMod::PubStruct;

            PubStruct<|>

            pub mod PubMod {
                pub struct PubStruct;
            }
            ",
        );
    }

    #[test]
    fn not_applicable_for_types_with_private_paths() {
        check_assist_not_applicable(
            auto_import,
            r"
            PrivateStruct<|>

            pub mod PubMod {
                struct PrivateStruct;
            }
            ",
        );
    }

    #[test]
    fn not_applicable_when_no_imports_found() {
        check_assist_not_applicable(
            auto_import,
            "
            PubStruct<|>",
        );
    }

    #[test]
    fn not_applicable_in_import_statements() {
        check_assist_not_applicable(
            auto_import,
            r"
            use PubStruct<|>;

            pub mod PubMod {
                pub struct PubStruct;
            }",
        );
    }

    #[test]
    fn function_import() {
        check_assist(
            auto_import,
            r"
            test_function<|>

            pub mod PubMod {
                pub fn test_function() {};
            }
            ",
            r"
            use PubMod::test_function;

            test_function<|>

            pub mod PubMod {
                pub fn test_function() {};
            }
            ",
        );
    }

    #[test]
    fn auto_import_target() {
        check_assist_target(
            auto_import,
            r"
            struct AssistInfo {
                group_label: Option<<|>GroupLabel>,
            }

            mod m { pub struct GroupLabel; }
            ",
            "GroupLabel",
        )
    }

    #[test]
    fn not_applicable_when_path_start_is_imported() {
        check_assist_not_applicable(
            auto_import,
            r"
            pub mod mod1 {
                pub mod mod2 {
                    pub mod mod3 {
                        pub struct TestStruct;
                    }
                }
            }

            use mod1::mod2;
            fn main() {
                mod2::mod3::TestStruct<|>
            }
            ",
        );
    }
}
<|endoftext|>


<commit_before>use std::iter::IntoIterator;

use syntax::ast;
use syntax::codemap::{DUMMY_SP, Span};
use syntax::ptr::P;

use ident::ToIdent;
use invoke::{Invoke, Identity};
use name::ToName;
use path::PathBuilder;
use qpath::QPathBuilder;

//////////////////////////////////////////////////////////////////////////////

pub struct TyBuilder<F=Identity> {
    callback: F,
    span: Span,
}

impl TyBuilder {
    pub fn new() -> Self {
        TyBuilder::with_callback(Identity)
    }
}

impl<F> TyBuilder<F>
    where F: Invoke<P<ast::Ty>>,
{
    pub fn with_callback(callback: F) -> Self {
        TyBuilder {
            callback: callback,
            span: DUMMY_SP,
        }
    }

    pub fn build(self, ty: P<ast::Ty>) -> F::Result {
        self.callback.invoke(ty)
    }

    pub fn span(mut self, span: Span) -> Self {
        self.span = span;
        self
    }

    pub fn build_ty_(self, ty_: ast::Ty_) -> F::Result {
        let span = self.span;
        self.build(P(ast::Ty {
            id: ast::DUMMY_NODE_ID,
            node: ty_,
            span: span,
        }))
    }

    pub fn id<I>(self, id: I) -> F::Result
        where I: ToIdent,
    {
        self.path().id(id).build()
    }

    pub fn build_path(self, path: ast::Path) -> F::Result {
        self.build_ty_(ast::Ty_::TyPath(None, path))
    }

    pub fn build_qpath(self, qself: ast::QSelf, path: ast::Path) -> F::Result {
        self.build_ty_(ast::Ty_::TyPath(Some(qself), path))
    }

    pub fn path(self) -> PathBuilder<TyPathBuilder<F>> {
        PathBuilder::with_callback(TyPathBuilder(self))
    }

    pub fn qpath(self) -> QPathBuilder<TyQPathBuilder<F>> {
        QPathBuilder::with_callback(TyQPathBuilder(self))
    }

    pub fn isize(self) -> F::Result {
        self.id("isize")
    }

    pub fn i8(self) -> F::Result {
        self.id("i8")
    }

    pub fn i16(self) -> F::Result {
        self.id("i16")
    }

    pub fn i32(self) -> F::Result {
        self.id("i32")
    }

    pub fn i64(self) -> F::Result {
        self.id("i64")
    }

    pub fn usize(self) -> F::Result {
        self.id("usize")
    }

    pub fn u8(self) -> F::Result {
        self.id("u8")
    }

    pub fn u16(self) -> F::Result {
        self.id("u16")
    }

    pub fn u32(self) -> F::Result {
        self.id("u32")
    }

    pub fn u64(self) -> F::Result {
        self.id("u64")
    }

    pub fn f32(self) -> F::Result {
        self.id("f32")
    }

    pub fn f64(self) -> F::Result {
        self.id("f64")
    }

    pub fn unit(self) -> F::Result {
        self.tuple().build()
    }

    pub fn tuple(self) -> TyTupleBuilder<F> {
        TyTupleBuilder {
            builder: self,
            tys: vec![],
        }
    }

    pub fn build_slice(self, ty: P<ast::Ty>) -> F::Result {
        self.build_ty_(ast::Ty_::TyVec(ty))
    }

    pub fn slice(self) -> TyBuilder<TySliceBuilder<F>> {
        TyBuilder::with_callback(TySliceBuilder(self))
    }

    pub fn ref_(self) -> TyRefBuilder<F> {
        TyRefBuilder {
            builder: self,
            lifetime: None,
            mutability: ast::MutImmutable,
        }
    }

    pub fn infer(self) -> F::Result {
        self.build_ty_(ast::TyInfer)
    }

    pub fn option(self) -> TyBuilder<TyOptionBuilder<F>> {
        TyBuilder::with_callback(TyOptionBuilder(self))
    }

    pub fn result(self) -> TyBuilder<TyResultOkBuilder<F>> {
        TyBuilder::with_callback(TyResultOkBuilder(self))
    }

    pub fn phantom_data(self) -> TyBuilder<TyPhantomDataBuilder<F>> {
        TyBuilder::with_callback(TyPhantomDataBuilder(self))
    }
}

//////////////////////////////////////////////////////////////////////////////

pub struct TyPathBuilder<F>(TyBuilder<F>);

impl<F> Invoke<ast::Path> for TyPathBuilder<F>
    where F: Invoke<P<ast::Ty>>,
{
    type Result = F::Result;

    fn invoke(self, path: ast::Path) -> F::Result {
        self.0.build_path(path)
    }
}

//////////////////////////////////////////////////////////////////////////////

pub struct TyQPathBuilder<F>(TyBuilder<F>);

impl<F> Invoke<(ast::QSelf, ast::Path)> for TyQPathBuilder<F>
    where F: Invoke<P<ast::Ty>>,
{
    type Result = F::Result;

    fn invoke(self, (qself, path): (ast::QSelf, ast::Path)) -> F::Result {
        self.0.build_qpath(qself, path)
    }
}

//////////////////////////////////////////////////////////////////////////////

pub struct TySliceBuilder<F>(TyBuilder<F>);

impl<F> Invoke<P<ast::Ty>> for TySliceBuilder<F>
    where F: Invoke<P<ast::Ty>>,
{
    type Result = F::Result;

    fn invoke(self, ty: P<ast::Ty>) -> F::Result {
        self.0.build_slice(ty)
    }
}

//////////////////////////////////////////////////////////////////////////////

pub struct TyRefBuilder<F> {
    builder: TyBuilder<F>,
    lifetime: Option<ast::Lifetime>,
    mutability: ast::Mutability,
}

impl<F> TyRefBuilder<F>
    where F: Invoke<P<ast::Ty>>,
{
    pub fn mut_(mut self) -> Self {
        self.mutability = ast::MutMutable;
        self
    }

    pub fn lifetime<N>(mut self, name: N) -> Self
        where N: ToName,
    {
        self.lifetime = Some(ast::Lifetime {
            id: ast::DUMMY_NODE_ID,
            span: self.builder.span,
            name: name.to_name(),
        });
        self
    }

    pub fn build_ty(self, ty: P<ast::Ty>) -> F::Result {
        let ty = ast::MutTy {
            ty: ty,
            mutbl: self.mutability,
        };
        self.builder.build_ty_(ast::TyRptr(self.lifetime, ty))
    }

    pub fn ty(self) -> TyBuilder<Self> {
        TyBuilder::with_callback(self)
    }
}

impl<F> Invoke<P<ast::Ty>> for TyRefBuilder<F>
    where F: Invoke<P<ast::Ty>>,
{
    type Result = F::Result;

    fn invoke(self, ty: P<ast::Ty>) -> F::Result {
        self.build_ty(ty)
    }
}

//////////////////////////////////////////////////////////////////////////////

pub struct TyOptionBuilder<F>(TyBuilder<F>);

impl<F> Invoke<P<ast::Ty>> for TyOptionBuilder<F>
    where F: Invoke<P<ast::Ty>>,
{
    type Result = F::Result;

    fn invoke(self, ty: P<ast::Ty>) -> F::Result {
        let path = PathBuilder::new()
            .global()
            .id("std")
            .id("option")
            .segment("Option")
                .with_ty(ty)
                .build()
            .build();

        self.0.build_path(path)
    }
}

//////////////////////////////////////////////////////////////////////////////

pub struct TyResultOkBuilder<F>(TyBuilder<F>);

impl<F> Invoke<P<ast::Ty>> for TyResultOkBuilder<F>
    where F: Invoke<P<ast::Ty>>,
{
    type Result = TyBuilder<TyResultErrBuilder<F>>;

    fn invoke(self, ty: P<ast::Ty>) -> TyBuilder<TyResultErrBuilder<F>> {
        TyBuilder::with_callback(TyResultErrBuilder(self.0, ty))
    }
}

pub struct TyResultErrBuilder<F>(TyBuilder<F>, P<ast::Ty>);

impl<F> Invoke<P<ast::Ty>> for TyResultErrBuilder<F>
    where F: Invoke<P<ast::Ty>>,
{
    type Result = F::Result;

    fn invoke(self, ty: P<ast::Ty>) -> F::Result {
        let path = PathBuilder::new()
            .global()
            .id("std")
            .id("result")
            .segment("Result")
                .with_ty(self.1)
                .with_ty(ty)
                .build()
            .build();

        self.0.build_path(path)
    }
}

//////////////////////////////////////////////////////////////////////////////

pub struct TyPhantomDataBuilder<F>(TyBuilder<F>);

impl<F> Invoke<P<ast::Ty>> for TyPhantomDataBuilder<F>
    where F: Invoke<P<ast::Ty>>,
{
    type Result = F::Result;

    fn invoke(self, ty: P<ast::Ty>) -> F::Result {
        let path = PathBuilder::new()
            .global()
            .id("std")
            .id("marker")
            .segment("PhantomData")
                .with_ty(ty)
                .build()
            .build();

        self.0.build_path(path)
    }
}

//////////////////////////////////////////////////////////////////////////////

pub struct TyTupleBuilder<F> {
    builder: TyBuilder<F>,
    tys: Vec<P<ast::Ty>>,
}

impl<F> TyTupleBuilder<F>
    where F: Invoke<P<ast::Ty>>,
{
    pub fn with_tys<I>(mut self, iter: I) -> Self
        where I: IntoIterator<Item=P<ast::Ty>>,
    {
        self.tys.extend(iter);
        self
    }

    pub fn with_ty(mut self, ty: P<ast::Ty>) -> Self {
        self.tys.push(ty);
        self
    }

    pub fn ty(self) -> TyBuilder<Self> {
        TyBuilder::with_callback(self)
    }

    pub fn build(self) -> F::Result {
        self.builder.build_ty_(ast::TyTup(self.tys))
    }
}

impl<F> Invoke<P<ast::Ty>> for TyTupleBuilder<F>
    where F: Invoke<P<ast::Ty>>,
{
    type Result = Self;

    fn invoke(self, ty: P<ast::Ty>) -> Self {
        self.with_ty(ty)
    }
}
<commit_msg>feat(ty): Add constructors for Box, Iterator, ObjectSum types<commit_after>use std::iter::IntoIterator;

use syntax::ast;
use syntax::codemap::{DUMMY_SP, Span};
use syntax::ptr::P;

use ident::ToIdent;
use invoke::{Invoke, Identity};
use lifetime::IntoLifetime;
use name::ToName;
use path::PathBuilder;
use qpath::QPathBuilder;
use ty_param::TyParamBoundBuilder;

//////////////////////////////////////////////////////////////////////////////

pub struct TyBuilder<F=Identity> {
    callback: F,
    span: Span,
}

impl TyBuilder {
    pub fn new() -> Self {
        TyBuilder::with_callback(Identity)
    }
}

impl<F> TyBuilder<F>
    where F: Invoke<P<ast::Ty>>,
{
    pub fn with_callback(callback: F) -> Self {
        TyBuilder {
            callback: callback,
            span: DUMMY_SP,
        }
    }

    pub fn build(self, ty: P<ast::Ty>) -> F::Result {
        self.callback.invoke(ty)
    }

    pub fn span(mut self, span: Span) -> Self {
        self.span = span;
        self
    }

    pub fn build_ty_(self, ty_: ast::Ty_) -> F::Result {
        let span = self.span;
        self.build(P(ast::Ty {
            id: ast::DUMMY_NODE_ID,
            node: ty_,
            span: span,
        }))
    }

    pub fn id<I>(self, id: I) -> F::Result
        where I: ToIdent,
    {
        self.path().id(id).build()
    }

    pub fn build_path(self, path: ast::Path) -> F::Result {
        self.build_ty_(ast::Ty_::TyPath(None, path))
    }

    pub fn build_qpath(self, qself: ast::QSelf, path: ast::Path) -> F::Result {
        self.build_ty_(ast::Ty_::TyPath(Some(qself), path))
    }

    pub fn path(self) -> PathBuilder<TyPathBuilder<F>> {
        PathBuilder::with_callback(TyPathBuilder(self))
    }

    pub fn qpath(self) -> QPathBuilder<TyQPathBuilder<F>> {
        QPathBuilder::with_callback(TyQPathBuilder(self))
    }

    pub fn isize(self) -> F::Result {
        self.id("isize")
    }

    pub fn i8(self) -> F::Result {
        self.id("i8")
    }

    pub fn i16(self) -> F::Result {
        self.id("i16")
    }

    pub fn i32(self) -> F::Result {
        self.id("i32")
    }

    pub fn i64(self) -> F::Result {
        self.id("i64")
    }

    pub fn usize(self) -> F::Result {
        self.id("usize")
    }

    pub fn u8(self) -> F::Result {
        self.id("u8")
    }

    pub fn u16(self) -> F::Result {
        self.id("u16")
    }

    pub fn u32(self) -> F::Result {
        self.id("u32")
    }

    pub fn u64(self) -> F::Result {
        self.id("u64")
    }

    pub fn f32(self) -> F::Result {
        self.id("f32")
    }

    pub fn f64(self) -> F::Result {
        self.id("f64")
    }

    pub fn unit(self) -> F::Result {
        self.tuple().build()
    }

    pub fn tuple(self) -> TyTupleBuilder<F> {
        TyTupleBuilder {
            builder: self,
            tys: vec![],
        }
    }

    pub fn build_slice(self, ty: P<ast::Ty>) -> F::Result {
        self.build_ty_(ast::Ty_::TyVec(ty))
    }

    pub fn slice(self) -> TyBuilder<TySliceBuilder<F>> {
        TyBuilder::with_callback(TySliceBuilder(self))
    }

    pub fn ref_(self) -> TyRefBuilder<F> {
        TyRefBuilder {
            builder: self,
            lifetime: None,
            mutability: ast::MutImmutable,
        }
    }

    pub fn infer(self) -> F::Result {
        self.build_ty_(ast::TyInfer)
    }

    pub fn option(self) -> TyBuilder<TyOptionBuilder<F>> {
        TyBuilder::with_callback(TyOptionBuilder(self))
    }

    pub fn result(self) -> TyBuilder<TyResultOkBuilder<F>> {
        TyBuilder::with_callback(TyResultOkBuilder(self))
    }

    pub fn phantom_data(self) -> TyBuilder<TyPhantomDataBuilder<F>> {
        TyBuilder::with_callback(TyPhantomDataBuilder(self))
    }

    pub fn box_(self) -> TyBuilder<TyBoxBuilder<F>> {
        TyBuilder::with_callback(TyBoxBuilder(self))
    }

    pub fn iterator(self) -> TyBuilder<TyIteratorBuilder<F>> {
        TyBuilder::with_callback(TyIteratorBuilder(self))
    }

    pub fn object_sum(self) -> TyBuilder<TyObjectSumBuilder<F>> {
        TyBuilder::with_callback(TyObjectSumBuilder {
            builder: self,
        })
    }
}

//////////////////////////////////////////////////////////////////////////////

pub struct TyPathBuilder<F>(TyBuilder<F>);

impl<F> Invoke<ast::Path> for TyPathBuilder<F>
    where F: Invoke<P<ast::Ty>>,
{
    type Result = F::Result;

    fn invoke(self, path: ast::Path) -> F::Result {
        self.0.build_path(path)
    }
}

//////////////////////////////////////////////////////////////////////////////

pub struct TyQPathBuilder<F>(TyBuilder<F>);

impl<F> Invoke<(ast::QSelf, ast::Path)> for TyQPathBuilder<F>
    where F: Invoke<P<ast::Ty>>,
{
    type Result = F::Result;

    fn invoke(self, (qself, path): (ast::QSelf, ast::Path)) -> F::Result {
        self.0.build_qpath(qself, path)
    }
}

//////////////////////////////////////////////////////////////////////////////

pub struct TySliceBuilder<F>(TyBuilder<F>);

impl<F> Invoke<P<ast::Ty>> for TySliceBuilder<F>
    where F: Invoke<P<ast::Ty>>,
{
    type Result = F::Result;

    fn invoke(self, ty: P<ast::Ty>) -> F::Result {
        self.0.build_slice(ty)
    }
}

//////////////////////////////////////////////////////////////////////////////

pub struct TyRefBuilder<F> {
    builder: TyBuilder<F>,
    lifetime: Option<ast::Lifetime>,
    mutability: ast::Mutability,
}

impl<F> TyRefBuilder<F>
    where F: Invoke<P<ast::Ty>>,
{
    pub fn mut_(mut self) -> Self {
        self.mutability = ast::MutMutable;
        self
    }

    pub fn lifetime<N>(mut self, name: N) -> Self
        where N: ToName,
    {
        self.lifetime = Some(ast::Lifetime {
            id: ast::DUMMY_NODE_ID,
            span: self.builder.span,
            name: name.to_name(),
        });
        self
    }

    pub fn build_ty(self, ty: P<ast::Ty>) -> F::Result {
        let ty = ast::MutTy {
            ty: ty,
            mutbl: self.mutability,
        };
        self.builder.build_ty_(ast::TyRptr(self.lifetime, ty))
    }

    pub fn ty(self) -> TyBuilder<Self> {
        TyBuilder::with_callback(self)
    }
}

impl<F> Invoke<P<ast::Ty>> for TyRefBuilder<F>
    where F: Invoke<P<ast::Ty>>,
{
    type Result = F::Result;

    fn invoke(self, ty: P<ast::Ty>) -> F::Result {
        self.build_ty(ty)
    }
}

//////////////////////////////////////////////////////////////////////////////

pub struct TyOptionBuilder<F>(TyBuilder<F>);

impl<F> Invoke<P<ast::Ty>> for TyOptionBuilder<F>
    where F: Invoke<P<ast::Ty>>,
{
    type Result = F::Result;

    fn invoke(self, ty: P<ast::Ty>) -> F::Result {
        let path = PathBuilder::new()
            .global()
            .id("std")
            .id("option")
            .segment("Option")
                .with_ty(ty)
                .build()
            .build();

        self.0.build_path(path)
    }
}

//////////////////////////////////////////////////////////////////////////////

pub struct TyResultOkBuilder<F>(TyBuilder<F>);

impl<F> Invoke<P<ast::Ty>> for TyResultOkBuilder<F>
    where F: Invoke<P<ast::Ty>>,
{
    type Result = TyBuilder<TyResultErrBuilder<F>>;

    fn invoke(self, ty: P<ast::Ty>) -> TyBuilder<TyResultErrBuilder<F>> {
        TyBuilder::with_callback(TyResultErrBuilder(self.0, ty))
    }
}

pub struct TyResultErrBuilder<F>(TyBuilder<F>, P<ast::Ty>);

impl<F> Invoke<P<ast::Ty>> for TyResultErrBuilder<F>
    where F: Invoke<P<ast::Ty>>,
{
    type Result = F::Result;

    fn invoke(self, ty: P<ast::Ty>) -> F::Result {
        let path = PathBuilder::new()
            .global()
            .id("std")
            .id("result")
            .segment("Result")
                .with_ty(self.1)
                .with_ty(ty)
                .build()
            .build();

        self.0.build_path(path)
    }
}

//////////////////////////////////////////////////////////////////////////////

pub struct TyPhantomDataBuilder<F>(TyBuilder<F>);

impl<F> Invoke<P<ast::Ty>> for TyPhantomDataBuilder<F>
    where F: Invoke<P<ast::Ty>>,
{
    type Result = F::Result;

    fn invoke(self, ty: P<ast::Ty>) -> F::Result {
        let path = PathBuilder::new()
            .global()
            .id("std")
            .id("marker")
            .segment("PhantomData")
                .with_ty(ty)
                .build()
            .build();

        self.0.build_path(path)
    }
}

//////////////////////////////////////////////////////////////////////////////

pub struct TyBoxBuilder<F>(TyBuilder<F>);

impl<F> Invoke<P<ast::Ty>> for TyBoxBuilder<F>
    where F: Invoke<P<ast::Ty>>,
{
    type Result = F::Result;

    fn invoke(self, ty: P<ast::Ty>) -> F::Result {
        let path = PathBuilder::new()
            .global()
            .id("std")
            .id("boxed")
            .segment("Box")
                .with_ty(ty)
                .build()
            .build();

        self.0.build_path(path)
    }
}

//////////////////////////////////////////////////////////////////////////////

pub struct TyIteratorBuilder<F>(TyBuilder<F>);

impl<F> Invoke<P<ast::Ty>> for TyIteratorBuilder<F>
    where F: Invoke<P<ast::Ty>>,
{
    type Result = F::Result;

    fn invoke(self, ty: P<ast::Ty>) -> F::Result {
        let path = PathBuilder::new()
            .global()
            .id("std")
            .id("iter")
            .segment("Iterator")
                .binding("Item").build(ty.clone())
                .build()
            .build();

        self.0.build_path(path)
    }
}

//////////////////////////////////////////////////////////////////////////////

pub struct TyObjectSumBuilder<F> {
    builder: TyBuilder<F>,
}

impl<F> Invoke<P<ast::Ty>> for TyObjectSumBuilder<F>
    where F: Invoke<P<ast::Ty>>,
{
    type Result = TyObjectSumTyBuilder<F>;

    fn invoke(self, ty: P<ast::Ty>) -> Self::Result {
        TyObjectSumTyBuilder {
            builder: self.builder,
            ty: ty,
            bounds: Vec::new(),
        }
    }
}

pub struct TyObjectSumTyBuilder<F> {
    builder: TyBuilder<F>,
    ty: P<ast::Ty>,
    bounds: Vec<ast::TyParamBound>,
}

impl<F> TyObjectSumTyBuilder<F>
    where F: Invoke<P<ast::Ty>>,
{
    pub fn with_bounds<I>(mut self, iter: I) -> Self
        where I: Iterator<Item=ast::TyParamBound>,
    {
        self.bounds.extend(iter);
        self
    }

    pub fn with_bound(mut self, bound: ast::TyParamBound) -> Self {
        self.bounds.push(bound);
        self
    }

    pub fn bound(self) -> TyParamBoundBuilder<Self> {
        TyParamBoundBuilder::with_callback(self)
    }

    pub fn with_generics(self, generics: ast::Generics) -> Self {
        self.with_lifetimes(
            generics.lifetimes.into_iter()
                .map(|def| def.lifetime)
        )
    }

    pub fn with_lifetimes<I, L>(mut self, lifetimes: I) -> Self
        where I: Iterator<Item=L>,
              L: IntoLifetime,
    {
        for lifetime in lifetimes {
            self = self.lifetime(lifetime);
        }

        self
    }

    pub fn lifetime<L>(self, lifetime: L) -> Self
        where L: IntoLifetime,
    {
        self.bound().lifetime(lifetime)
    }

    pub fn build(self) -> F::Result {
        let bounds = P::from_vec(self.bounds);
        self.builder.build_ty_(ast::Ty_::TyObjectSum(self.ty, bounds))
    }
}

impl<F> Invoke<ast::TyParamBound> for TyObjectSumTyBuilder<F>
    where F: Invoke<P<ast::Ty>>,
{
    type Result = Self;

    fn invoke(self, bound: ast::TyParamBound) -> Self {
        self.with_bound(bound)
    }
}

//////////////////////////////////////////////////////////////////////////////

pub struct TyTupleBuilder<F> {
    builder: TyBuilder<F>,
    tys: Vec<P<ast::Ty>>,
}

impl<F> TyTupleBuilder<F>
    where F: Invoke<P<ast::Ty>>,
{
    pub fn with_tys<I>(mut self, iter: I) -> Self
        where I: IntoIterator<Item=P<ast::Ty>>,
    {
        self.tys.extend(iter);
        self
    }

    pub fn with_ty(mut self, ty: P<ast::Ty>) -> Self {
        self.tys.push(ty);
        self
    }

    pub fn ty(self) -> TyBuilder<Self> {
        TyBuilder::with_callback(self)
    }

    pub fn build(self) -> F::Result {
        self.builder.build_ty_(ast::TyTup(self.tys))
    }
}

impl<F> Invoke<P<ast::Ty>> for TyTupleBuilder<F>
    where F: Invoke<P<ast::Ty>>,
{
    type Result = Self;

    fn invoke(self, ty: P<ast::Ty>) -> Self {
        self.with_ty(ty)
    }
}
<|endoftext|>


<commit_before>use std::io::Read;
use std::collections::HashMap;
use std::cell::RefCell;

use url;
use reqwest;
use serde_json;

use super::error::{TvdbError, TvdbResult};
use super::api::RequestClient;
use super::api::DefaultHttpClient;

/// Main interface
#[derive(Debug, Clone)]
pub struct Tvdb<'a> {
    /// Your API key from TheTVDB.com
    pub key: String,
    http_client: Option<&'a RequestClient>,
    jwt_token: RefCell<Option<String>>,
}

/// https://api.thetvdb.com/swagger#/Authentication
#[derive(Deserialize, Debug)]
struct LoginResponse {
    token: String,
}

/// List of `SeriesSearchData`, returned from a search
#[derive(Deserialize, Debug)]
pub struct SeriesSearchResult {
    data: Vec<SeriesSearchData>,
}

/// Info for a single series, as returned from search query
#[derive(Deserialize, Debug)]
pub struct SeriesSearchData {
    aliases: Option<Vec<String>>,
    banner: Option<String>,
    firstAired: Option<String>,
    id: Option<i64>,
    network: Option<String>,
    overview: Option<String>,
    seriesName: Option<String>,
    status: Option<String>,
}

impl<'a> Tvdb<'a> {
    /// Initalise API with the given API key. A key can be aquired via
    /// the [API Key Registration page](http://thetvdb.com/?tab=apiregister)
    pub fn new<S>(key: S) -> Tvdb<'a>
        where S: Into<String>,
    {
        Tvdb {
            key: key.into(),
            http_client: None,
            jwt_token: RefCell::new(None),
        }
    }

    /// Set the JWT session token
    fn set_token(&self, token: String) {
        let mut j = self.jwt_token.borrow_mut();
        *j = Some(token);
    }
    fn get_token(&self) -> Option<String> {
        let j = self.jwt_token.borrow_mut();
        match *j {
            None => None,
            Some(ref t) => Some(format!("{}", *t)),
        }
    }

    /// Authenticate with TheTVDB, storing the JWT token internally for use by
    /// other methods.
    pub fn login(&self) -> TvdbResult<bool> {
        let mut map = HashMap::new();
        map.insert("apikey", &self.key);

        let c = reqwest::Client::new().unwrap();
        let mut resp = c.post("https://api.thetvdb.com/login")
            .json(&map)
            .send()
            .map_err(|x| {
                TvdbError::CommunicationError { reason: format!("{}", x) }
            })?;
        let mut result = String::new();
        resp.read_to_string(&mut result).map_err(|x| {
            TvdbError::CommunicationError { reason: format!("Error reading response: {}", x) }
        })?;

        let deserialized: serde_json::Value = serde_json::from_str(&result).unwrap();
        let tok: String = deserialized["token"].as_str().unwrap().into();
        self.set_token(tok);

        Ok(true)
    }

    /// Sets a custom client (implementation of `RequestClient`) used to
    /// perform HTTP requests
    pub fn set_http_client(&mut self, client: &'a RequestClient) {
        self.http_client = Some::<&'a RequestClient>(client);
    }

    pub fn search(&self, name: &str) -> TvdbResult<SeriesSearchResult> {
        let mut map = HashMap::new();
        map.insert("name", name);
        //map.insert("imdbId", "json");

        let search_url = "https://api.thetvdb.com/search/series";
        let url: String = url::Url::parse_with_params(search_url, map)
            .unwrap()
            .as_str()
            .into();

        let default_client = DefaultHttpClient {}; // FIXME: Create one per instance
        let c = self.http_client.unwrap_or(&default_client);
        // Query URL
        let data = c.get_url(&url, self.get_token())?;
        // Parse result
        let result: SeriesSearchResult = serde_json::from_str(&data).unwrap();

        Ok(result)
    }

    /*
    pub fn search_imdb(&self, imdb_id: &str){
        panic!();
    }

    pub fn search_zap2it(&self, zap2it_id: &str){
        panic!();
    }
*/
}
<commit_msg>Avoid recreating default HTTP client<commit_after>use std::io::Read;
use std::collections::HashMap;
use std::cell::RefCell;

use url;
use reqwest;
use serde_json;

use super::error::{TvdbError, TvdbResult};
use super::api::RequestClient;
use super::api::DefaultHttpClient;

/// Main interface
#[derive(Debug, Clone)]
pub struct Tvdb<'a> {
    /// Your API key from TheTVDB.com
    pub key: String,
    http_client: Option<&'a RequestClient>,
    jwt_token: RefCell<Option<String>>,
    default_client: Rc<RequestClient>,

}

/// https://api.thetvdb.com/swagger#/Authentication
#[derive(Deserialize, Debug)]
struct LoginResponse {
    token: String,
}

/// List of `SeriesSearchData`, returned from a search
#[derive(Deserialize, Debug)]
pub struct SeriesSearchResult {
    data: Vec<SeriesSearchData>,
}

/// Info for a single series, as returned from search query
#[derive(Deserialize, Debug)]
pub struct SeriesSearchData {
    aliases: Option<Vec<String>>,
    banner: Option<String>,
    firstAired: Option<String>,
    id: Option<i64>,
    network: Option<String>,
    overview: Option<String>,
    seriesName: Option<String>,
    status: Option<String>,
}

impl<'a> Tvdb<'a> {
    /// Initalise API with the given API key. A key can be aquired via
    /// the [API Key Registration page](http://thetvdb.com/?tab=apiregister)
    pub fn new<S>(key: S) -> Tvdb<'a>
        where S: Into<String>,
    {
        Tvdb {
            key: key.into(),
            http_client: None,
            jwt_token: RefCell::new(None),
            default_client: Rc::new(DefaultHttpClient {}),
        }
    }

    /// Set the JWT session token
    fn set_token(&self, token: String) {
        let mut j = self.jwt_token.borrow_mut();
        *j = Some(token);
    }
    fn get_token(&self) -> Option<String> {
        let j = self.jwt_token.borrow();
        match *j {
            None => None,
            Some(ref t) => Some(format!("{}", *t)),
        }
    }

    /// Authenticate with TheTVDB, storing the JWT token internally for use by
    /// other methods.
    pub fn login(&self) -> TvdbResult<bool> {
        let mut map = HashMap::new();
        map.insert("apikey", &self.key);

        let c = reqwest::Client::new().unwrap();
        let mut resp = c.post("https://api.thetvdb.com/login")
            .json(&map)
            .send()
            .map_err(|x| {
                TvdbError::CommunicationError { reason: format!("{}", x) }
            })?;
        let mut result = String::new();
        resp.read_to_string(&mut result).map_err(|x| {
            TvdbError::CommunicationError { reason: format!("Error reading response: {}", x) }
        })?;

        let deserialized: serde_json::Value = serde_json::from_str(&result).unwrap();
        let tok: String = deserialized["token"].as_str().unwrap().into();
        self.set_token(tok);

        Ok(true)
    }

    /// Sets a custom client (implementation of `RequestClient`) used to
    /// perform HTTP requests
    pub fn set_http_client(&mut self, client: &'a RequestClient) {
        self.http_client = Some::<&'a RequestClient>(client);
    }

    pub fn search(&self, name: &str) -> TvdbResult<SeriesSearchResult> {
        let mut map = HashMap::new();
        map.insert("name", name);
        //map.insert("imdbId", "json");

        let search_url = "https://api.thetvdb.com/search/series";
        let url: String = url::Url::parse_with_params(search_url, map)
            .unwrap()
            .as_str()
            .into();

        let dc = self.default_client.as_ref();
        let c = self.http_client.unwrap_or(dc);
        // Query URL
        let data = c.get_url(&url, self.get_token())?;
        // Parse result
        let result: SeriesSearchResult = serde_json::from_str(&data).unwrap();

        Ok(result)
    }

    /*
    pub fn search_imdb(&self, imdb_id: &str){
        panic!();
    }

    pub fn search_zap2it(&self, zap2it_id: &str){
        panic!();
    }
*/
}
<|endoftext|>


<commit_before><commit_msg>Add decompression<commit_after><|endoftext|>


<commit_before><commit_msg>Workaround for thread race conditions<commit_after><|endoftext|>


<commit_before>use std::borrow::Cow;
use std::collections::HashMap;

use serde_json::{to_value, Value};

use context::get_json_pointer;
use errors::Result;
use renderer::for_loop::{ForLoop, ForLoopState};
use renderer::stack_frame::{FrameContext, FrameType, StackFrame, Val};
use template::Template;

/// Contains the user data and allows no mutation
#[derive(Debug)]
pub struct UserContext<'a> {
    /// Read-only context
    inner: &'a Value,
}

impl<'a> UserContext<'a> {
    /// Create an immutable user context to be used in the call stack
    pub fn new(context: &'a Value) -> Self {
        UserContext { inner: context }
    }

    pub fn find_value(&self, key: &str) -> Option<&'a Value> {
        self.inner.get(key)
    }

    pub fn find_value_by_pointer(self: &Self, pointer: &str) -> Option<&'a Value> {
        self.inner.pointer(pointer)
    }
}

/// Contains the stack of frames
#[derive(Debug)]
pub struct CallStack<'a> {
    /// The stack of frames
    stack: Vec<StackFrame<'a>>,
    /// User supplied context for the render
    context: UserContext<'a>,
}

impl<'a> CallStack<'a> {
    /// Create the initial call stack
    pub fn new(context: &'a Value, template: &'a Template) -> CallStack<'a> {
        CallStack {
            stack: vec![StackFrame::new(FrameType::Origin, "ORIGIN", template)],
            context: UserContext::new(context),
        }
    }

    pub fn push_for_loop_frame(&mut self, name: &'a str, for_loop: ForLoop<'a>) {
        let tpl = self.stack.last().expect("Stack frame").active_template;
        self.stack.push(StackFrame::new_for_loop(name, tpl, for_loop));
    }

    pub fn push_macro_frame(
        &mut self,
        namespace: &'a str,
        name: &'a str,
        context: FrameContext<'a>,
        tpl: &'a Template,
    ) {
        self.stack.push(StackFrame::new_macro(name, tpl, namespace, context));
    }

    pub fn push_include_frame(&mut self, name: &'a str, tpl: &'a Template) {
        self.stack.push(StackFrame::new_include(name, tpl));
    }

    /// Returns mutable reference to current `StackFrame`
    pub fn origin_frame_mut(self: &mut Self) -> &mut StackFrame<'a> {
        self.stack.first_mut().expect("Origin frame missing")
    }

    /// Returns mutable reference to current `StackFrame`
    pub fn current_frame_mut(self: &mut Self) -> &mut StackFrame<'a> {
        self.stack.last_mut().expect("No current frame exists")
    }

    /// Returns immutable reference to current `StackFrame`
    pub fn current_frame(self: &Self) -> &StackFrame<'a> {
        self.stack.last().expect("No current frame exists")
    }

    /// Pop the last frame
    pub fn pop(&mut self) {
        self.stack.pop().expect("Mistakenly popped Origin frame");
    }

    pub fn lookup(&self, key: &str) -> Option<Val<'a>> {
        for stack_frame in self.stack.iter().rev() {
            let found = stack_frame.find_value(key);
            if found.is_some() {
                return found;
            }

            // If we looked in a macro or origin frame, no point continuing
            // Origin is the last one and macro frame don't have access to parent frames
            if stack_frame.kind == FrameType::Macro || stack_frame.kind == FrameType::Origin {
                break;
            }
        }

        // Not in stack frame, look in user supplied context
        if key.contains('.') {
            return self
                .context
                .find_value_by_pointer(&get_json_pointer(key))
                .map(|v| Cow::Borrowed(v));
        } else if let Some(value) = self.context.find_value(key) {
            return Some(Cow::Borrowed(value));
        }

        None
    }

    /// Add an assignment value (via {% set ... %} and {% set_global ... %} )
    pub fn add_assignment(&mut self, key: &'a str, global: bool, value: Val<'a>) {
        if global {
            self.origin_frame_mut().insert(key, value);
        } else {
            self.current_frame_mut().insert(key, value);
        }
    }

    /// Breaks current for loop
    pub fn break_for_loop(self: &mut Self) -> Result<()> {
        match self.current_frame_mut().for_loop {
            Some(ref mut for_loop) => {
                for_loop.break_loop();
                Ok(())
            }
            None => bail!("Attempted `break` while not in `for loop`"),
        }
    }

    /// Continues current for loop
    pub fn increment_for_loop(self: &mut Self) -> Result<()> {
        match self.current_frame_mut().for_loop {
            Some(ref mut for_loop) => {
                for_loop.increment();
                Ok(())
            }
            None => bail!("Attempted `increment` while not in `for loop`"),
        }
    }

    /// Continues current for loop
    pub fn continue_for_loop(self: &mut Self) -> Result<()> {
        match self.current_frame_mut().for_loop {
            Some(ref mut for_loop) => {
                for_loop.continue_loop();
                Ok(())
            }
            None => bail!("Attempted `continue` while not in `for loop`"),
        }
    }

    /// True if should break body, applicable to `break` and `continue`
    pub fn should_break_body(&self) -> bool {
        match self.current_frame().for_loop {
            Some(ref for_loop) => {
                for_loop.state == ForLoopState::Break || for_loop.state == ForLoopState::Continue
            }
            None => false,
        }
    }

    /// True if should break loop, applicable to `break` only
    pub fn should_break_for_loop(&self) -> bool {
        match self.current_frame().for_loop {
            Some(ref for_loop) => for_loop.state == ForLoopState::Break,
            None => false,
        }
    }

    /// Grab the current frame template
    pub fn active_template(&self) -> &'a Template {
        self.current_frame().active_template
    }

    pub fn current_context_cloned(self: &Self) -> Value {
        let mut context = HashMap::new();

        // Go back the stack in reverse to see what we have access to
        for frame in self.stack.iter().rev() {
            context.extend(frame.context_owned());
            if let Some(ref for_loop) = frame.for_loop {
                context.insert(
                    for_loop.value_name.to_string(),
                    for_loop.get_current_value().into_owned(),
                );
                if for_loop.is_key_value() {
                    context.insert(
                        for_loop.key_name.clone().unwrap(),
                        Value::String(for_loop.get_current_key()),
                    );
                }
            }
            // Macros don't have access to the user context, we're done
            if frame.kind == FrameType::Macro {
                return to_value(&context).unwrap();
            }
        }

        // If we are here we take the user context
        // and add the values found in the stack to it.
        // We do it this way as we can override global variable temporarily in forloops
        match self.context.inner.clone() {
            Value::Object(mut m) => {
                for (key, val) in context {
                    m.insert(key.to_string(), val);
                }

                Value::Object(m)
            }
            _ => unreachable!("Had a context that wasn't a map?!"),
        }
    }
}
<commit_msg>Change StackFrames traversal for global context in assignments (set_global)<commit_after>use std::borrow::Cow;
use std::collections::HashMap;

use serde_json::{to_value, Value};

use context::get_json_pointer;
use errors::Result;
use renderer::for_loop::{ForLoop, ForLoopState};
use renderer::stack_frame::{FrameContext, FrameType, StackFrame, Val};
use template::Template;

/// Contains the user data and allows no mutation
#[derive(Debug)]
pub struct UserContext<'a> {
    /// Read-only context
    inner: &'a Value,
}

impl<'a> UserContext<'a> {
    /// Create an immutable user context to be used in the call stack
    pub fn new(context: &'a Value) -> Self {
        UserContext { inner: context }
    }

    pub fn find_value(&self, key: &str) -> Option<&'a Value> {
        self.inner.get(key)
    }

    pub fn find_value_by_pointer(self: &Self, pointer: &str) -> Option<&'a Value> {
        self.inner.pointer(pointer)
    }
}

/// Contains the stack of frames
#[derive(Debug)]
pub struct CallStack<'a> {
    /// The stack of frames
    stack: Vec<StackFrame<'a>>,
    /// User supplied context for the render
    context: UserContext<'a>,
}

impl<'a> CallStack<'a> {
    /// Create the initial call stack
    pub fn new(context: &'a Value, template: &'a Template) -> CallStack<'a> {
        CallStack {
            stack: vec![StackFrame::new(FrameType::Origin, "ORIGIN", template)],
            context: UserContext::new(context),
        }
    }

    pub fn push_for_loop_frame(&mut self, name: &'a str, for_loop: ForLoop<'a>) {
        let tpl = self.stack.last().expect("Stack frame").active_template;
        self.stack.push(StackFrame::new_for_loop(name, tpl, for_loop));
    }

    pub fn push_macro_frame(
        &mut self,
        namespace: &'a str,
        name: &'a str,
        context: FrameContext<'a>,
        tpl: &'a Template,
    ) {
        self.stack.push(StackFrame::new_macro(name, tpl, namespace, context));
    }

    pub fn push_include_frame(&mut self, name: &'a str, tpl: &'a Template) {
        self.stack.push(StackFrame::new_include(name, tpl));
    }

    /// Returns mutable reference to global `StackFrame`
    /// i.e gets first stack outside current for loops
    pub fn global_frame_mut(self: &mut Self) -> &mut StackFrame<'a> {
        if self.current_frame().kind == FrameType::ForLoop {
            for stack_frame in self.stack.iter_mut().rev(){
                // walk up the parent stacks until we meet the current template
                if stack_frame.kind != FrameType::ForLoop {
                    return stack_frame;
                }
            }
            unreachable!("Global frame not found when trying to break out of for loop");
        } else {
            // Macro, Origin, or Include
            return self.current_frame_mut();
        }
    }

    /// Returns mutable reference to current `StackFrame`
    pub fn current_frame_mut(self: &mut Self) -> &mut StackFrame<'a> {
        self.stack.last_mut().expect("No current frame exists")
    }

    /// Returns immutable reference to current `StackFrame`
    pub fn current_frame(self: &Self) -> &StackFrame<'a> {
        self.stack.last().expect("No current frame exists")
    }

    /// Pop the last frame
    pub fn pop(&mut self) {
        self.stack.pop().expect("Mistakenly popped Origin frame");
    }

    pub fn lookup(&self, key: &str) -> Option<Val<'a>> {
        for stack_frame in self.stack.iter().rev() {
            let found = stack_frame.find_value(key);
            if found.is_some() {
                return found;
            }

            // If we looked in a macro or origin frame, no point continuing
            // Origin is the last one and macro frame don't have access to parent frames
            if stack_frame.kind == FrameType::Macro || stack_frame.kind == FrameType::Origin {
                break;
            }
        }

        // Not in stack frame, look in user supplied context
        if key.contains('.') {
            return self
                .context
                .find_value_by_pointer(&get_json_pointer(key))
                .map(|v| Cow::Borrowed(v));
        } else if let Some(value) = self.context.find_value(key) {
            return Some(Cow::Borrowed(value));
        }

        None
    }

    /// Add an assignment value (via {% set ... %} and {% set_global ... %} )
    pub fn add_assignment(&mut self, key: &'a str, global: bool, value: Val<'a>) {
        if global {
            self.global_frame_mut().insert(key, value);
        } else {
            self.current_frame_mut().insert(key, value);
        }
    }

    /// Breaks current for loop
    pub fn break_for_loop(self: &mut Self) -> Result<()> {
        match self.current_frame_mut().for_loop {
            Some(ref mut for_loop) => {
                for_loop.break_loop();
                Ok(())
            }
            None => bail!("Attempted `break` while not in `for loop`"),
        }
    }

    /// Continues current for loop
    pub fn increment_for_loop(self: &mut Self) -> Result<()> {
        match self.current_frame_mut().for_loop {
            Some(ref mut for_loop) => {
                for_loop.increment();
                Ok(())
            }
            None => bail!("Attempted `increment` while not in `for loop`"),
        }
    }

    /// Continues current for loop
    pub fn continue_for_loop(self: &mut Self) -> Result<()> {
        match self.current_frame_mut().for_loop {
            Some(ref mut for_loop) => {
                for_loop.continue_loop();
                Ok(())
            }
            None => bail!("Attempted `continue` while not in `for loop`"),
        }
    }

    /// True if should break body, applicable to `break` and `continue`
    pub fn should_break_body(&self) -> bool {
        match self.current_frame().for_loop {
            Some(ref for_loop) => {
                for_loop.state == ForLoopState::Break || for_loop.state == ForLoopState::Continue
            }
            None => false,
        }
    }

    /// True if should break loop, applicable to `break` only
    pub fn should_break_for_loop(&self) -> bool {
        match self.current_frame().for_loop {
            Some(ref for_loop) => for_loop.state == ForLoopState::Break,
            None => false,
        }
    }

    /// Grab the current frame template
    pub fn active_template(&self) -> &'a Template {
        self.current_frame().active_template
    }

    pub fn current_context_cloned(self: &Self) -> Value {
        let mut context = HashMap::new();

        // Go back the stack in reverse to see what we have access to
        for frame in self.stack.iter().rev() {
            context.extend(frame.context_owned());
            if let Some(ref for_loop) = frame.for_loop {
                context.insert(
                    for_loop.value_name.to_string(),
                    for_loop.get_current_value().into_owned(),
                );
                if for_loop.is_key_value() {
                    context.insert(
                        for_loop.key_name.clone().unwrap(),
                        Value::String(for_loop.get_current_key()),
                    );
                }
            }
            // Macros don't have access to the user context, we're done
            if frame.kind == FrameType::Macro {
                return to_value(&context).unwrap();
            }
        }

        // If we are here we take the user context
        // and add the values found in the stack to it.
        // We do it this way as we can override global variable temporarily in forloops
        match self.context.inner.clone() {
            Value::Object(mut m) => {
                for (key, val) in context {
                    m.insert(key.to_string(), val);
                }

                Value::Object(m)
            }
            _ => unreachable!("Had a context that wasn't a map?!"),
        }
    }
}
<|endoftext|>