<commit_before>use bullet::BulletDrawable;
use bullet::bullets::Bullets;
use cgmath;
use cgmath::{Deg, Point2};
use character::controls::CharacterInputState;
use critter::CritterData;
use data;
use game::get_random_bool;
use game::constants::{ASPECT_RATIO, NORMAL_DEATH_SPRITE_OFFSET, SPRITE_OFFSET, ZOMBIE_STILL_SPRITE_OFFSET, ZOMBIESHEET_TOTAL_WIDTH};
use gfx;
use gfx_app::{ColorFormat, DepthFormat};
use graphics::orientation::{Orientation, Stance};
use graphics::{Dimensions, load_texture, overlaps};
use graphics::camera::CameraInputState;
use shaders::{critter_pipeline, VertexData, CharacterSheet, Position, Projection};
use specs;
use specs::{Fetch, ReadStorage, WriteStorage};
use zombie::zombies::Zombies;

pub mod zombies;

const SHADER_VERT: &[u8] = include_bytes!("../shaders/character.v.glsl");
const SHADER_FRAG: &[u8] = include_bytes!("../shaders/character.f.glsl");

#[derive(Debug, Clone)]
pub struct ZombieDrawable {
  projection: Projection,
  pub position: Position,
  previous_position: Position,
  offset_delta: Position,
  orientation: Orientation,
  pub stance: Stance,
  direction: Orientation,
  pub movement_direction: Point2<f32>,
  zombie_idx: usize,
  zombie_death_idx: usize,
}

impl ZombieDrawable {
  pub fn new(position: Position) -> ZombieDrawable {
    let view = Dimensions::get_view_matrix();
    ZombieDrawable {
      projection: Projection {
        model: view.into(),
        view: view.into(),
        proj: cgmath::perspective(Deg(60.0f32), ASPECT_RATIO, 0.1, 4000.0).into(),
      },
      position,
      previous_position: Position {
        position: [0.0, 0.0],
      },
      offset_delta: Position {
        position: [0.0, 0.0],
      },
      orientation: Orientation::Left,
      stance: Stance::Still,
      direction: Orientation::Left,
      movement_direction: Point2 {
        x: 0.0,
        y: 0.0,
      },
      zombie_idx: 0,
      zombie_death_idx: 0,
    }
  }

  pub fn update(&mut self, world_to_clip: &Projection, ci: &CharacterInputState, bullets: &[BulletDrawable]) {
    self.projection = *world_to_clip;

    self.offset_delta =
      Position {
        position: [ci.x_movement - self.previous_position.position[0], ci.y_movement - self.previous_position.position[1]]
      };

    self.previous_position = Position {
      position: [
        ci.x_movement,
        ci.y_movement
      ]
    };

    self.position = Position {
      position: [
        self.position.position[0] + self.offset_delta.position[0] + (self.movement_direction.x),
        self.position.position[1] + self.offset_delta.position[1] - (self.movement_direction.y)
      ]
    };
    bullets.iter().for_each(|bullet| {
      if overlaps(self.position, bullet.position, 80.0, 80.0) && self.stance != Stance::NormalDeath && self.stance != Stance::CriticalDeath {
        self.stance =
          if get_random_bool() {
            Stance::NormalDeath
          } else {
            Stance::CriticalDeath
          };
      }
    });
  }

  pub fn update_walk(&mut self) {
    if self.zombie_idx < 7 {
      self.zombie_idx += 1;
    } else {
      self.zombie_idx = 0;
    }
  }

  pub fn update_still(&mut self) {
    if self.zombie_idx < 3 {
      self.zombie_idx += 1;
    } else {
      self.zombie_idx = 0;
    }
  }

  pub fn update_normal_death(&mut self) {
    if self.zombie_death_idx < 5 {
      self.zombie_death_idx += 1;
    }
  }

  pub fn update_critical_death(&mut self) {
    if self.zombie_death_idx < 7 {
      self.zombie_death_idx += 1;
    }
  }
}

pub struct ZombieDrawSystem<R: gfx::Resources> {
  bundle: gfx::pso::bundle::Bundle<R, critter_pipeline::Data<R>>,
  data: Vec<CritterData>,
}

impl<R: gfx::Resources> ZombieDrawSystem<R> {
  pub fn new<F>(factory: &mut F,
                rtv: gfx::handle::RenderTargetView<R, ColorFormat>,
                dsv: gfx::handle::DepthStencilView<R, DepthFormat>) -> ZombieDrawSystem<R>
    where F: gfx::Factory<R> {
    use gfx::traits::FactoryExt;

    let zombie_bytes = include_bytes!("../../assets/zombie.png");

    let vertex_data: Vec<VertexData> =
      vec![
        VertexData::new([-25.0, -35.0, 0.0], [0.0, 1.0]),
        VertexData::new([25.0, -35.0, 0.0], [1.0, 1.0]),
        VertexData::new([25.0, 35.0, 0.0], [1.0, 0.0]),
        VertexData::new([-25.0, -35.0, 0.0], [0.0, 1.0]),
        VertexData::new([25.0, 35.0, 0.0], [1.0, 0.0]),
        VertexData::new([-25.0, 35.0, 0.0], [0.0, 0.0]),
      ];

    let (vertex_buf, slice) = factory.create_vertex_buffer_with_slice(&vertex_data, ());

    let char_texture = load_texture(factory, zombie_bytes).unwrap();
    let pso = factory
      .create_pipeline_simple(SHADER_VERT,
                              SHADER_FRAG,
                              critter_pipeline::new())
      .unwrap();

    let pipeline_data = critter_pipeline::Data {
      vbuf: vertex_buf,
      projection_cb: factory.create_constant_buffer(1),
      position_cb: factory.create_constant_buffer(1),
      character_sprite_cb: factory.create_constant_buffer(1),
      charactersheet: (char_texture, factory.create_sampler_linear()),
      out_color: rtv,
      out_depth: dsv,
    };

    let data = data::load_zombie();

    ZombieDrawSystem {
      bundle: gfx::Bundle::new(slice, pso, pipeline_data),
      data
    }
  }

  fn get_next_sprite(&self, drawable: &mut ZombieDrawable) -> CharacterSheet {
    let zombie_sprite =
      if drawable.stance == Stance::Still {
        let sprite_idx = (drawable.direction as usize * 4 + drawable.zombie_idx) as usize;
        (&self.data[sprite_idx], sprite_idx)
      } else if drawable.orientation != Orientation::Still && drawable.stance == Stance::Walking {
        let sprite_idx = (drawable.direction as usize * 8 + drawable.zombie_idx + ZOMBIE_STILL_SPRITE_OFFSET) as usize;
        (&self.data[sprite_idx], sprite_idx)
      } else if drawable.orientation != Orientation::Still && drawable.stance == Stance::NormalDeath {
        let sprite_idx = (drawable.direction as usize * 6 + drawable.zombie_death_idx + NORMAL_DEATH_SPRITE_OFFSET) as usize;
        (&self.data[sprite_idx], sprite_idx)
      } else if drawable.orientation != Orientation::Still && drawable.stance == Stance::CriticalDeath {
        let sprite_idx = (drawable.direction as usize * 8 + drawable.zombie_death_idx) as usize;
        (&self.data[sprite_idx], sprite_idx)
      } else {
        drawable.direction = drawable.orientation;
        let sprite_idx = (drawable.orientation as usize * 8 + drawable.zombie_idx + ZOMBIE_STILL_SPRITE_OFFSET) as usize;
        (&self.data[sprite_idx], sprite_idx)
      };

    let (y_div, row_idx) = if drawable.stance == Stance::NormalDeath || drawable.stance == Stance::CriticalDeath {
      (0.0, 2)
    } else {
      (1.0, 2)
    };

    let elements_x = ZOMBIESHEET_TOTAL_WIDTH / (zombie_sprite.0.data[2] + SPRITE_OFFSET);
    CharacterSheet {
      x_div: elements_x,
      y_div,
      row_idx,
      index: zombie_sprite.1 as f32
    }
  }

  pub fn draw<C>(&mut self,
                 mut drawable: &mut ZombieDrawable,
                 encoder: &mut gfx::Encoder<R, C>)
    where C: gfx::CommandBuffer<R> {
    encoder.update_constant_buffer(&self.bundle.data.projection_cb, &drawable.projection);
    encoder.update_constant_buffer(&self.bundle.data.position_cb, &drawable.position);
    encoder.update_constant_buffer(&self.bundle.data.character_sprite_cb,
                                   &self.get_next_sprite(&mut drawable));
    self.bundle.encode(encoder);
  }
}

#[derive(Debug)]
pub struct PreDrawSystem;

impl PreDrawSystem {
  pub fn new() -> PreDrawSystem {
    PreDrawSystem {}
  }
}

impl<'a> specs::System<'a> for PreDrawSystem {
  #[cfg_attr(feature = "cargo-clippy", allow(type_complexity))]
  type SystemData = (WriteStorage<'a, Zombies>,
                     ReadStorage<'a, CameraInputState>,
                     ReadStorage<'a, CharacterInputState>,
                     ReadStorage<'a, Bullets>,
                     Fetch<'a, Dimensions>);

  fn run(&mut self, (mut zombies, camera_input, character_input, bullets, dim): Self::SystemData) {
    use specs::Join;

    for (zs, camera, ci, bs) in (&mut zombies, &camera_input, &character_input, &bullets).join() {
      let world_to_clip = dim.world_to_projection(camera);

      for z in &mut zs.zombies {
        z.update(&world_to_clip, ci, &bs.bullets);
      }
    }
  }
}
<commit_msg>Update zombie direction while player moves<commit_after>use bullet::BulletDrawable;
use bullet::bullets::Bullets;
use cgmath;
use cgmath::{Deg, Point2};
use character::CharacterDrawable;
use character::controls::CharacterInputState;
use critter::CritterData;
use data;
use game::get_random_bool;
use game::constants::{ASPECT_RATIO, NORMAL_DEATH_SPRITE_OFFSET, SPRITE_OFFSET, ZOMBIE_STILL_SPRITE_OFFSET, ZOMBIESHEET_TOTAL_WIDTH};
use gfx;
use gfx_app::{ColorFormat, DepthFormat};
use graphics::orientation::{Orientation, Stance};
use graphics::{Dimensions, get_orientation, load_texture, overlaps};
use graphics::camera::CameraInputState;
use shaders::{critter_pipeline, VertexData, CharacterSheet, Position, Projection};
use specs;
use specs::{Fetch, ReadStorage, WriteStorage};
use zombie::zombies::Zombies;

pub mod zombies;

const SHADER_VERT: &[u8] = include_bytes!("../shaders/character.v.glsl");
const SHADER_FRAG: &[u8] = include_bytes!("../shaders/character.f.glsl");

#[derive(Debug, Clone)]
pub struct ZombieDrawable {
  projection: Projection,
  pub position: Position,
  previous_position: Position,
  offset_delta: Position,
  orientation: Orientation,
  pub stance: Stance,
  direction: Orientation,
  pub movement_direction: Point2<f32>,
  zombie_idx: usize,
  zombie_death_idx: usize,
}

impl ZombieDrawable {
  pub fn new(position: Position) -> ZombieDrawable {
    let view = Dimensions::get_view_matrix();
    ZombieDrawable {
      projection: Projection {
        model: view.into(),
        view: view.into(),
        proj: cgmath::perspective(Deg(60.0f32), ASPECT_RATIO, 0.1, 4000.0).into(),
      },
      position,
      previous_position: Position {
        position: [0.0, 0.0],
      },
      offset_delta: Position {
        position: [0.0, 0.0],
      },
      orientation: Orientation::Left,
      stance: Stance::Still,
      direction: Orientation::Left,
      movement_direction: Point2 {
        x: 0.0,
        y: 0.0,
      },
      zombie_idx: 0,
      zombie_death_idx: 0,
    }
  }

  pub fn update(&mut self, world_to_clip: &Projection, ci: &CharacterInputState, c: &CharacterDrawable, bullets: &[BulletDrawable]) {
    self.projection = *world_to_clip;

    self.offset_delta =
      Position {
        position: [ci.x_movement - self.previous_position.position[0], ci.y_movement - self.previous_position.position[1]]
      };

    self.previous_position = Position {
      position: [
        ci.x_movement,
        ci.y_movement
      ]
    };

    if self.stance != Stance::NormalDeath && self.stance != Stance::CriticalDeath {
      self.direction = get_orientation(
        Point2::new(self.position.position[0], self.position.position[1]),
        Point2::new(c.position.position[0], c.position.position[1]));
    }

    self.position = Position {
      position: [
        self.position.position[0] + self.offset_delta.position[0] + (self.movement_direction.x),
        self.position.position[1] + self.offset_delta.position[1] - (self.movement_direction.y)
      ]
    };
    bullets.iter().for_each(|bullet| {
      if overlaps(self.position, bullet.position, 80.0, 80.0) && self.stance != Stance::NormalDeath && self.stance != Stance::CriticalDeath {
        self.stance =
          if get_random_bool() {
            Stance::NormalDeath
          } else {
            Stance::CriticalDeath
          };
      }
    });
  }

  pub fn update_walk(&mut self) {
    if self.zombie_idx < 7 {
      self.zombie_idx += 1;
    } else {
      self.zombie_idx = 0;
    }
  }

  pub fn update_still(&mut self) {
    if self.zombie_idx < 3 {
      self.zombie_idx += 1;
    } else {
      self.zombie_idx = 0;
    }
  }

  pub fn update_normal_death(&mut self) {
    if self.zombie_death_idx < 5 {
      self.zombie_death_idx += 1;
    }
  }

  pub fn update_critical_death(&mut self) {
    if self.zombie_death_idx < 7 {
      self.zombie_death_idx += 1;
    }
  }
}

pub struct ZombieDrawSystem<R: gfx::Resources> {
  bundle: gfx::pso::bundle::Bundle<R, critter_pipeline::Data<R>>,
  data: Vec<CritterData>,
}

impl<R: gfx::Resources> ZombieDrawSystem<R> {
  pub fn new<F>(factory: &mut F,
                rtv: gfx::handle::RenderTargetView<R, ColorFormat>,
                dsv: gfx::handle::DepthStencilView<R, DepthFormat>) -> ZombieDrawSystem<R>
    where F: gfx::Factory<R> {
    use gfx::traits::FactoryExt;

    let zombie_bytes = include_bytes!("../../assets/zombie.png");

    let vertex_data: Vec<VertexData> =
      vec![
        VertexData::new([-25.0, -35.0, 0.0], [0.0, 1.0]),
        VertexData::new([25.0, -35.0, 0.0], [1.0, 1.0]),
        VertexData::new([25.0, 35.0, 0.0], [1.0, 0.0]),
        VertexData::new([-25.0, -35.0, 0.0], [0.0, 1.0]),
        VertexData::new([25.0, 35.0, 0.0], [1.0, 0.0]),
        VertexData::new([-25.0, 35.0, 0.0], [0.0, 0.0]),
      ];

    let (vertex_buf, slice) = factory.create_vertex_buffer_with_slice(&vertex_data, ());

    let char_texture = load_texture(factory, zombie_bytes).unwrap();
    let pso = factory
      .create_pipeline_simple(SHADER_VERT,
                              SHADER_FRAG,
                              critter_pipeline::new())
      .unwrap();

    let pipeline_data = critter_pipeline::Data {
      vbuf: vertex_buf,
      projection_cb: factory.create_constant_buffer(1),
      position_cb: factory.create_constant_buffer(1),
      character_sprite_cb: factory.create_constant_buffer(1),
      charactersheet: (char_texture, factory.create_sampler_linear()),
      out_color: rtv,
      out_depth: dsv,
    };

    let data = data::load_zombie();

    ZombieDrawSystem {
      bundle: gfx::Bundle::new(slice, pso, pipeline_data),
      data
    }
  }

  fn get_next_sprite(&self, drawable: &mut ZombieDrawable) -> CharacterSheet {
    let zombie_sprite =
      if drawable.stance == Stance::Still {
        let sprite_idx = (drawable.direction as usize * 4 + drawable.zombie_idx) as usize;
        (&self.data[sprite_idx], sprite_idx)
      } else if drawable.orientation != Orientation::Still && drawable.stance == Stance::Walking {
        let sprite_idx = (drawable.direction as usize * 8 + drawable.zombie_idx + ZOMBIE_STILL_SPRITE_OFFSET) as usize;
        (&self.data[sprite_idx], sprite_idx)
      } else if drawable.orientation != Orientation::Still && drawable.stance == Stance::NormalDeath {
        let sprite_idx = (drawable.direction as usize * 6 + drawable.zombie_death_idx + NORMAL_DEATH_SPRITE_OFFSET) as usize;
        (&self.data[sprite_idx], sprite_idx)
      } else if drawable.orientation != Orientation::Still && drawable.stance == Stance::CriticalDeath {
        let sprite_idx = (drawable.direction as usize * 8 + drawable.zombie_death_idx) as usize;
        (&self.data[sprite_idx], sprite_idx)
      } else {
        drawable.direction = drawable.orientation;
        let sprite_idx = (drawable.orientation as usize * 8 + drawable.zombie_idx + ZOMBIE_STILL_SPRITE_OFFSET) as usize;
        (&self.data[sprite_idx], sprite_idx)
      };

    let (y_div, row_idx) = if drawable.stance == Stance::NormalDeath || drawable.stance == Stance::CriticalDeath {
      (0.0, 2)
    } else {
      (1.0, 2)
    };

    let elements_x = ZOMBIESHEET_TOTAL_WIDTH / (zombie_sprite.0.data[2] + SPRITE_OFFSET);
    CharacterSheet {
      x_div: elements_x,
      y_div,
      row_idx,
      index: zombie_sprite.1 as f32
    }
  }

  pub fn draw<C>(&mut self,
                 mut drawable: &mut ZombieDrawable,
                 encoder: &mut gfx::Encoder<R, C>)
    where C: gfx::CommandBuffer<R> {
    encoder.update_constant_buffer(&self.bundle.data.projection_cb, &drawable.projection);
    encoder.update_constant_buffer(&self.bundle.data.position_cb, &drawable.position);
    encoder.update_constant_buffer(&self.bundle.data.character_sprite_cb,
                                   &self.get_next_sprite(&mut drawable));
    self.bundle.encode(encoder);
  }
}

#[derive(Debug)]
pub struct PreDrawSystem;

impl PreDrawSystem {
  pub fn new() -> PreDrawSystem {
    PreDrawSystem {}
  }
}

impl<'a> specs::System<'a> for PreDrawSystem {
  #[cfg_attr(feature = "cargo-clippy", allow(type_complexity))]
  type SystemData = (WriteStorage<'a, Zombies>,
                     ReadStorage<'a, CameraInputState>,
                     ReadStorage<'a, CharacterInputState>,
                     ReadStorage<'a, CharacterDrawable>,
                     ReadStorage<'a, Bullets>,
                     Fetch<'a, Dimensions>);

  fn run(&mut self, (mut zombies, camera_input, character_input, character, bullets, dim): Self::SystemData) {
    use specs::Join;

    for (zs, camera, ci, c, bs) in (&mut zombies, &camera_input, &character_input, &character, &bullets).join() {
      let world_to_clip = dim.world_to_projection(camera);

      for z in &mut zs.zombies {
        z.update(&world_to_clip, ci, c, &bs.bullets);
      }
    }
  }
}
<|endoftext|>


<commit_before>// This shit should be inplace. This one is not inplace.

impl Solution {
    pub fn duplicate_zeros(arr: &mut Vec<i32>) {
        let length = arr.len();
        let mut tmp = Vec::with_capacity(arr.len());

        for i in arr.clone() {
            if tmp.len() >= length { break; }
            tmp.push(i);

            if tmp.len() >= length { break; }
            if i == 0 { tmp.push(0); } // push one more time
        }

        *arr = tmp;
    }
}

// Inplace version

impl Solution {
    pub fn duplicate_zeros(arr: &mut Vec<i32>) {
        let length = arr.len();
        let mut zeroes = 0;

        for i in arr.iter() {
            if *i == 0 { zeroes += 1 }
        }

        for i in (0..length).rev() {
            Self::shift(arr, length, i, zeroes);
            if (arr[i] == 0) { zeroes -= 1 }
        }
    }

    fn shift(arr: &mut Vec<i32>, length: usize, index: usize, shift: usize) {
        if (index + shift < length) {
            arr[index+shift] = arr[index];
        }

        // we should not only copy zero to shifted position, but also duplicate it on -1 position
        if (index - 1 + shift < length && arr[index] == 0) {
            arr[index+shift-1] = arr[index]
        }
    }
}
<commit_msg>[katas] one more update<commit_after>// This shit should be inplace. This one is not inplace.

impl Solution {
    pub fn duplicate_zeros(arr: &mut Vec<i32>) {
        let length = arr.len();
        let mut tmp = Vec::with_capacity(arr.len());

        for i in arr.clone() {
            if tmp.len() >= length { break; }
            tmp.push(i);

            if tmp.len() >= length { break; }
            if i == 0 { tmp.push(0); } // push one more time
        }

        *arr = tmp;
    }
}

// Inplace version
impl Solution {
    pub fn duplicate_zeros(arr: &mut Vec<i32>) {
        let length = arr.len();
        let mut zeroes = arr.iter().fold(
            0,
            |zeroes, x| if *x == 0 { zeroes + 1 } else { zeroes }
        );

        for i in (0..length).rev() {
            Self::shift(arr, length, i, zeroes);
            if (arr[i] == 0) { zeroes -= 1 }
        }
    }

    fn shift(arr: &mut Vec<i32>, length: usize, index: usize, shift: usize) {
        // move element according to the shift
        if (index + shift < length) {
            arr[index+shift] = arr[index];
        }

        // we should not only copy 0 to shifted position, but also duplicate it on -1 position
        if (index - 1 + shift < length && arr[index] == 0) {
            arr[index+shift-1] = arr[index]
        }
    }
}
<|endoftext|>


<commit_before>// Copyright (c) 2016 The vulkano developers
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT
// license <LICENSE-MIT or http://opensource.org/licenses/MIT>,
// at your option. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.

use std::error;
use std::ffi::CString;
use std::fmt;
use std::ptr;
use std::str;

use Error;
use OomError;
use instance::loader;
use instance::loader::LoadingError;
use vk;
use check_errors;

macro_rules! extensions {
    ($sname:ident, $($ext:ident => $s:expr,)*) => (
        /// List of extensions that are enabled or available.
        #[derive(Copy, Clone, PartialEq, Eq)]
        #[allow(missing_docs)]
        pub struct $sname {
            $(
                pub $ext: bool,
            )*

            /// This field ensures that an instance of this `Extensions` struct
            /// can only be created through Vulkano functions and the update
            /// syntax. This way, extensions can be added to Vulkano without
            /// breaking existing code.
            pub _unbuildable: Unbuildable,
        }

        impl $sname {
            /// Returns an `Extensions` object with all members set to `false`.
            #[inline]
            pub fn none() -> $sname {
                $sname {
                    $($ext: false,)*
                    _unbuildable: Unbuildable(())
                }
            }

            /// Builds a Vec containing the list of extensions.
            pub fn build_extensions_list(&self) -> Vec<CString> {
                let mut data = Vec::new();
                $(if self.$ext { data.push(CString::new(&$s[..]).unwrap()); })*
                data
            }

            /// Returns the intersection of this list and another list.
            #[inline]
            pub fn intersection(&self, other: &$sname) -> $sname {
                $sname {
                    $(
                        $ext: self.$ext && other.$ext,
                    )*
                    _unbuildable: Unbuildable(())
                }
            }
        }

        impl fmt::Debug for $sname {
            #[allow(unused_assignments)]
            fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                try!(write!(f, "["));

                let mut first = true;

                $(
                    if self.$ext {
                        if !first { try!(write!(f, ", ")); }
                        else { first = false; }
                        try!(f.write_str(str::from_utf8($s).unwrap()));
                    }
                )*

                write!(f, "]")
            }
        }
    );
}

macro_rules! instance_extensions {
    ($sname:ident, $($ext:ident => $s:expr,)*) => (
        extensions! {
            $sname,
            $( $ext => $s,)*
        }

        impl $sname {
            /// See the docs of supported_by_core().
            pub fn supported_by_core_raw() -> Result<$sname, SupportedExtensionsError> {
                let entry_points = try!(loader::entry_points());

                let properties: Vec<vk::ExtensionProperties> = unsafe {
                    let mut num = 0;
                    try!(check_errors(entry_points.EnumerateInstanceExtensionProperties(
                        ptr::null(), &mut num, ptr::null_mut())));

                    let mut properties = Vec::with_capacity(num as usize);
                    try!(check_errors(entry_points.EnumerateInstanceExtensionProperties(
                        ptr::null(), &mut num, properties.as_mut_ptr())));
                    properties.set_len(num as usize);
                    properties
                };

                let mut extensions = $sname::none();
                for property in properties {
                    let name = property.extensionName;
                    $(
                        // TODO: this is VERY inefficient
                        // TODO: Check specVersion?
                        let same = {
                            let mut i = 0;
                            while name[i] != 0 && $s[i] != 0 && name[i] as u8 == $s[i] && i < $s.len() { i += 1; }
                            name[i] == 0 && (i >= $s.len() || name[i] as u8 == $s[i])
                        };
                        if same {
                            extensions.$ext = true;
                        }
                    )*
                }

                Ok(extensions)
            }

            /// Returns an `Extensions` object with extensions supported by the core driver.
            pub fn supported_by_core() -> Result<$sname, LoadingError> {
                match $sname::supported_by_core_raw() {
                    Ok(l) => Ok(l),
                    Err(SupportedExtensionsError::LoadingError(e)) => Err(e),
                    Err(SupportedExtensionsError::OomError(e)) => panic!("{:?}", e),
                }
            }
        }
    );
}

instance_extensions! {
    InstanceExtensions,
    khr_surface => b"VK_KHR_surface",
    khr_display => b"VK_KHR_display",
    khr_xlib_surface => b"VK_KHR_xlib_surface",
    khr_xcb_surface => b"VK_KHR_xcb_surface",
    khr_wayland_surface => b"VK_KHR_wayland_surface",
    khr_mir_surface => b"VK_KHR_mir_surface",
    khr_android_surface => b"VK_KHR_android_surface",
    khr_win32_surface => b"VK_KHR_win32_surface",
    ext_debug_report => b"VK_EXT_debug_report",
    nn_vi_surface => b"VK_NN_vi_surface",
    ext_swapchain_colorspace => b"VK_EXT_swapchain_colorspace",
    khr_get_physical_device_properties2 => b"VK_KHR_get_physical_device_properties2",
}

extensions! {
    DeviceExtensions,
    khr_swapchain => b"VK_KHR_swapchain",
    khr_display_swapchain => b"VK_KHR_display_swapchain",
    khr_sampler_mirror_clamp_to_edge => b"VK_KHR_sampler_mirror_clamp_to_edge",
    khr_shader_draw_parameters => b"VK_KHR_shader_draw_parameters",
}

/// Error that can happen when loading the list of layers.
#[derive(Clone, Debug)]
pub enum SupportedExtensionsError {
    /// Failed to load the Vulkan shared library.
    LoadingError(LoadingError),
    /// Not enough memory.
    OomError(OomError),
}

impl error::Error for SupportedExtensionsError {
    #[inline]
    fn description(&self) -> &str {
        match *self {
            SupportedExtensionsError::LoadingError(_) => "failed to load the Vulkan shared library",
            SupportedExtensionsError::OomError(_) => "not enough memory available",
        }
    }

    #[inline]
    fn cause(&self) -> Option<&error::Error> {
        match *self {
            SupportedExtensionsError::LoadingError(ref err) => Some(err),
            SupportedExtensionsError::OomError(ref err) => Some(err),
        }
    }
}

impl fmt::Display for SupportedExtensionsError {
    #[inline]
    fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        write!(fmt, "{}", error::Error::description(self))
    }
}

impl From<OomError> for SupportedExtensionsError {
    #[inline]
    fn from(err: OomError) -> SupportedExtensionsError {
        SupportedExtensionsError::OomError(err)
    }
}

impl From<LoadingError> for SupportedExtensionsError {
    #[inline]
    fn from(err: LoadingError) -> SupportedExtensionsError {
        SupportedExtensionsError::LoadingError(err)
    }
}

impl From<Error> for SupportedExtensionsError {
    #[inline]
    fn from(err: Error) -> SupportedExtensionsError {
        match err {
            err @ Error::OutOfHostMemory => {
                SupportedExtensionsError::OomError(OomError::from(err))
            },
            err @ Error::OutOfDeviceMemory => {
                SupportedExtensionsError::OomError(OomError::from(err))
            },
            _ => panic!("unexpected error: {:?}", err)
        }
    }
}

/// This helper type can only be instantiated inside this module.
/// See `*Extensions::_unbuildable`.
#[doc(hidden)]
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub struct Unbuildable(());

#[cfg(test)]
mod tests {
    use instance::InstanceExtensions;
    use instance::DeviceExtensions;

    #[test]
    fn empty_extensions() {
        let i = InstanceExtensions::none().build_extensions_list();
        assert!(i.is_empty());

        let d = DeviceExtensions::none().build_extensions_list();
        assert!(d.is_empty());
    }
}
<commit_msg>Remove more unsupported extensions<commit_after>// Copyright (c) 2016 The vulkano developers
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT
// license <LICENSE-MIT or http://opensource.org/licenses/MIT>,
// at your option. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.

use std::error;
use std::ffi::CString;
use std::fmt;
use std::ptr;
use std::str;

use Error;
use OomError;
use instance::loader;
use instance::loader::LoadingError;
use vk;
use check_errors;

macro_rules! extensions {
    ($sname:ident, $($ext:ident => $s:expr,)*) => (
        /// List of extensions that are enabled or available.
        #[derive(Copy, Clone, PartialEq, Eq)]
        #[allow(missing_docs)]
        pub struct $sname {
            $(
                pub $ext: bool,
            )*

            /// This field ensures that an instance of this `Extensions` struct
            /// can only be created through Vulkano functions and the update
            /// syntax. This way, extensions can be added to Vulkano without
            /// breaking existing code.
            pub _unbuildable: Unbuildable,
        }

        impl $sname {
            /// Returns an `Extensions` object with all members set to `false`.
            #[inline]
            pub fn none() -> $sname {
                $sname {
                    $($ext: false,)*
                    _unbuildable: Unbuildable(())
                }
            }

            /// Builds a Vec containing the list of extensions.
            pub fn build_extensions_list(&self) -> Vec<CString> {
                let mut data = Vec::new();
                $(if self.$ext { data.push(CString::new(&$s[..]).unwrap()); })*
                data
            }

            /// Returns the intersection of this list and another list.
            #[inline]
            pub fn intersection(&self, other: &$sname) -> $sname {
                $sname {
                    $(
                        $ext: self.$ext && other.$ext,
                    )*
                    _unbuildable: Unbuildable(())
                }
            }
        }

        impl fmt::Debug for $sname {
            #[allow(unused_assignments)]
            fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                try!(write!(f, "["));

                let mut first = true;

                $(
                    if self.$ext {
                        if !first { try!(write!(f, ", ")); }
                        else { first = false; }
                        try!(f.write_str(str::from_utf8($s).unwrap()));
                    }
                )*

                write!(f, "]")
            }
        }
    );
}

macro_rules! instance_extensions {
    ($sname:ident, $($ext:ident => $s:expr,)*) => (
        extensions! {
            $sname,
            $( $ext => $s,)*
        }

        impl $sname {
            /// See the docs of supported_by_core().
            pub fn supported_by_core_raw() -> Result<$sname, SupportedExtensionsError> {
                let entry_points = try!(loader::entry_points());

                let properties: Vec<vk::ExtensionProperties> = unsafe {
                    let mut num = 0;
                    try!(check_errors(entry_points.EnumerateInstanceExtensionProperties(
                        ptr::null(), &mut num, ptr::null_mut())));

                    let mut properties = Vec::with_capacity(num as usize);
                    try!(check_errors(entry_points.EnumerateInstanceExtensionProperties(
                        ptr::null(), &mut num, properties.as_mut_ptr())));
                    properties.set_len(num as usize);
                    properties
                };

                let mut extensions = $sname::none();
                for property in properties {
                    let name = property.extensionName;
                    $(
                        // TODO: this is VERY inefficient
                        // TODO: Check specVersion?
                        let same = {
                            let mut i = 0;
                            while name[i] != 0 && $s[i] != 0 && name[i] as u8 == $s[i] && i < $s.len() { i += 1; }
                            name[i] == 0 && (i >= $s.len() || name[i] as u8 == $s[i])
                        };
                        if same {
                            extensions.$ext = true;
                        }
                    )*
                }

                Ok(extensions)
            }

            /// Returns an `Extensions` object with extensions supported by the core driver.
            pub fn supported_by_core() -> Result<$sname, LoadingError> {
                match $sname::supported_by_core_raw() {
                    Ok(l) => Ok(l),
                    Err(SupportedExtensionsError::LoadingError(e)) => Err(e),
                    Err(SupportedExtensionsError::OomError(e)) => panic!("{:?}", e),
                }
            }
        }
    );
}

instance_extensions! {
    InstanceExtensions,
    khr_surface => b"VK_KHR_surface",
    khr_display => b"VK_KHR_display",
    khr_xlib_surface => b"VK_KHR_xlib_surface",
    khr_xcb_surface => b"VK_KHR_xcb_surface",
    khr_wayland_surface => b"VK_KHR_wayland_surface",
    khr_mir_surface => b"VK_KHR_mir_surface",
    khr_android_surface => b"VK_KHR_android_surface",
    khr_win32_surface => b"VK_KHR_win32_surface",
    ext_debug_report => b"VK_EXT_debug_report",
    nn_vi_surface => b"VK_NN_vi_surface",
    ext_swapchain_colorspace => b"VK_EXT_swapchain_colorspace",
}

extensions! {
    DeviceExtensions,
    khr_swapchain => b"VK_KHR_swapchain",
    khr_display_swapchain => b"VK_KHR_display_swapchain",
    khr_sampler_mirror_clamp_to_edge => b"VK_KHR_sampler_mirror_clamp_to_edge",
}

/// Error that can happen when loading the list of layers.
#[derive(Clone, Debug)]
pub enum SupportedExtensionsError {
    /// Failed to load the Vulkan shared library.
    LoadingError(LoadingError),
    /// Not enough memory.
    OomError(OomError),
}

impl error::Error for SupportedExtensionsError {
    #[inline]
    fn description(&self) -> &str {
        match *self {
            SupportedExtensionsError::LoadingError(_) => "failed to load the Vulkan shared library",
            SupportedExtensionsError::OomError(_) => "not enough memory available",
        }
    }

    #[inline]
    fn cause(&self) -> Option<&error::Error> {
        match *self {
            SupportedExtensionsError::LoadingError(ref err) => Some(err),
            SupportedExtensionsError::OomError(ref err) => Some(err),
        }
    }
}

impl fmt::Display for SupportedExtensionsError {
    #[inline]
    fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        write!(fmt, "{}", error::Error::description(self))
    }
}

impl From<OomError> for SupportedExtensionsError {
    #[inline]
    fn from(err: OomError) -> SupportedExtensionsError {
        SupportedExtensionsError::OomError(err)
    }
}

impl From<LoadingError> for SupportedExtensionsError {
    #[inline]
    fn from(err: LoadingError) -> SupportedExtensionsError {
        SupportedExtensionsError::LoadingError(err)
    }
}

impl From<Error> for SupportedExtensionsError {
    #[inline]
    fn from(err: Error) -> SupportedExtensionsError {
        match err {
            err @ Error::OutOfHostMemory => {
                SupportedExtensionsError::OomError(OomError::from(err))
            },
            err @ Error::OutOfDeviceMemory => {
                SupportedExtensionsError::OomError(OomError::from(err))
            },
            _ => panic!("unexpected error: {:?}", err)
        }
    }
}

/// This helper type can only be instantiated inside this module.
/// See `*Extensions::_unbuildable`.
#[doc(hidden)]
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub struct Unbuildable(());

#[cfg(test)]
mod tests {
    use instance::InstanceExtensions;
    use instance::DeviceExtensions;

    #[test]
    fn empty_extensions() {
        let i = InstanceExtensions::none().build_extensions_list();
        assert!(i.is_empty());

        let d = DeviceExtensions::none().build_extensions_list();
        assert!(d.is_empty());
    }
}
<|endoftext|>


<commit_before>use rustc::hir::def_id::DefId;
use rustc::traits::{self, Reveal, SelectionContext};
use rustc::ty::subst::{Substs, Subst};
use rustc::ty;

use super::EvalContext;
use error::EvalResult;
use memory::Pointer;
use super::terminator::{get_impl_method, ImplMethod};

impl<'a, 'tcx> EvalContext<'a, 'tcx> {
    /// Creates a returns a dynamic vtable for the given type and vtable origin.
    /// This is used only for objects.
    ///
    /// The `trait_ref` encodes the erased self type. Hence if we are
    /// making an object `Foo<Trait>` from a value of type `Foo<T>`, then
    /// `trait_ref` would map `T:Trait`.
    pub fn get_vtable(&mut self, trait_ref: ty::PolyTraitRef<'tcx>) -> EvalResult<'tcx, Pointer> {
        let tcx = self.tcx;

        debug!("get_vtable(trait_ref={:?})", trait_ref);

        let methods: Vec<_> = traits::supertraits(tcx, trait_ref.clone()).flat_map(|trait_ref| {
            match self.fulfill_obligation(trait_ref.clone()) {
                // Should default trait error here?
                traits::VtableDefaultImpl(_) |
                traits::VtableBuiltin(_) => {
                    Vec::new().into_iter()
                }
                traits::VtableImpl(
                    traits::VtableImplData {
                        impl_def_id: id,
                        substs,
                        nested: _ }) => {
                    self.get_vtable_methods(id, substs)
                        .into_iter()
                        .map(|opt_mth| opt_mth.map(|mth| {
                            self.memory.create_fn_ptr(mth.method.def_id, mth.substs, mth.method.fty)
                        }))
                        .collect::<Vec<_>>()
                        .into_iter()
                }
                traits::VtableClosure(
                    traits::VtableClosureData {
                        closure_def_id,
                        substs,
                        nested: _ }) => {
                    let closure_type = self.tcx.closure_type(closure_def_id, substs);
                    let fn_ty = ty::BareFnTy {
                        unsafety: closure_type.unsafety,
                        abi: closure_type.abi,
                        sig: closure_type.sig,
                    };
                    let _fn_ty = self.tcx.mk_bare_fn(fn_ty);
                    unimplemented!()
                    //vec![Some(self.memory.create_fn_ptr(closure_def_id, substs.func_substs, fn_ty))].into_iter()
                }
                traits::VtableFnPointer(
                    traits::VtableFnPointerData {
                        fn_ty: _bare_fn_ty,
                        nested: _ }) => {
                    let _trait_closure_kind = tcx.lang_items.fn_trait_kind(trait_ref.def_id()).unwrap();
                    //vec![trans_fn_pointer_shim(ccx, trait_closure_kind, bare_fn_ty)].into_iter()
                    unimplemented!()
                }
                traits::VtableObject(ref data) => {
                    // this would imply that the Self type being erased is
                    // an object type; this cannot happen because we
                    // cannot cast an unsized type into a trait object
                    bug!("cannot get vtable for an object type: {:?}",
                         data);
                }
                vtable @ traits::VtableParam(..) => {
                    bug!("resolved vtable for {:?} to bad vtable {:?} in trans",
                         trait_ref,
                         vtable);
                }
            }
        }).collect();

        let size = self.type_size(trait_ref.self_ty());
        let align = self.type_align(trait_ref.self_ty());

        let ptr_size = self.memory.pointer_size();
        let vtable = self.memory.allocate(ptr_size * (3 + methods.len()), ptr_size)?;

        // FIXME: generate a destructor for the vtable.
        // trans does this with glue::get_drop_glue(ccx, trait_ref.self_ty())

        self.memory.write_usize(vtable.offset(ptr_size as isize), size as u64)?;
        self.memory.write_usize(vtable.offset((ptr_size * 2) as isize), align as u64)?;

        for (i, method) in methods.into_iter().enumerate() {
            if let Some(method) = method {
                self.memory.write_ptr(vtable.offset(ptr_size as isize * (3 + i as isize)), method)?;
            }
        }

        Ok(vtable)
    }

    fn get_vtable_methods(&mut self, impl_id: DefId, substs: &'tcx Substs<'tcx>) -> Vec<Option<ImplMethod<'tcx>>> {
        debug!("get_vtable_methods(impl_id={:?}, substs={:?}", impl_id, substs);

        let trait_id = match self.tcx.impl_trait_ref(impl_id) {
            Some(t_id) => t_id.def_id,
            None       => bug!("make_impl_vtable: don't know how to \
                                make a vtable for a type impl!")
        };

        self.tcx.populate_implementations_for_trait_if_necessary(trait_id);

        let trait_item_def_ids = self.tcx.trait_item_def_ids(trait_id);
        trait_item_def_ids
            .iter()

            // Filter out non-method items.
            .filter_map(|item_def_id| {
                match *item_def_id {
                    ty::MethodTraitItemId(def_id) => Some(def_id),
                    _ => None,
                }
            })

            // Now produce pointers for each remaining method. If the
            // method could never be called from this object, just supply
            // null.
            .map(|trait_method_def_id| {
                debug!("get_vtable_methods: trait_method_def_id={:?}",
                       trait_method_def_id);

                let trait_method_type = match self.tcx.impl_or_trait_item(trait_method_def_id) {
                    ty::MethodTraitItem(m) => m,
                    _ => bug!("should be a method, not other assoc item"),
                };
                let name = trait_method_type.name;

                // Some methods cannot be called on an object; skip those.
                if !self.tcx.is_vtable_safe_method(trait_id, &trait_method_type) {
                    debug!("get_vtable_methods: not vtable safe");
                    return None;
                }

                debug!("get_vtable_methods: trait_method_type={:?}",
                       trait_method_type);

                // the method may have some early-bound lifetimes, add
                // regions for those
                let method_substs = Substs::for_item(self.tcx, trait_method_def_id,
                                                     |_, _| self.tcx.mk_region(ty::ReErased),
                                                     |_, _| self.tcx.types.err);

                // The substitutions we have are on the impl, so we grab
                // the method type from the impl to substitute into.
                let mth = get_impl_method(self.tcx, method_substs, impl_id, substs, name);

                debug!("get_vtable_methods: mth={:?}", mth);

                // If this is a default method, it's possible that it
                // relies on where clauses that do not hold for this
                // particular set of type parameters. Note that this
                // method could then never be called, so we do not want to
                // try and trans it, in that case. Issue #23435.
                if mth.is_provided {
                    let predicates = mth.method.predicates.predicates.subst(self.tcx, &mth.substs);
                    if !self.normalize_and_test_predicates(predicates) {
                        debug!("get_vtable_methods: predicates do not hold");
                        return None;
                    }
                }

                Some(mth)
            })
            .collect()
    }

    /// Normalizes the predicates and checks whether they hold.  If this
    /// returns false, then either normalize encountered an error or one
    /// of the predicates did not hold. Used when creating vtables to
    /// check for unsatisfiable methods.
    fn normalize_and_test_predicates(&mut self, predicates: Vec<ty::Predicate<'tcx>>) -> bool {
        debug!("normalize_and_test_predicates(predicates={:?})",
               predicates);

        self.tcx.infer_ctxt(None, None, Reveal::All).enter(|infcx| {
            let mut selcx = SelectionContext::new(&infcx);
            let mut fulfill_cx = traits::FulfillmentContext::new();
            let cause = traits::ObligationCause::dummy();
            let traits::Normalized { value: predicates, obligations } =
                traits::normalize(&mut selcx, cause.clone(), &predicates);
            for obligation in obligations {
                fulfill_cx.register_predicate_obligation(&infcx, obligation);
            }
            for predicate in predicates {
                let obligation = traits::Obligation::new(cause.clone(), predicate);
                fulfill_cx.register_predicate_obligation(&infcx, obligation);
            }

            fulfill_cx.select_all_or_error(&infcx).is_ok()
        })
    }
}
<commit_msg>Fix comment wording.<commit_after>use rustc::hir::def_id::DefId;
use rustc::traits::{self, Reveal, SelectionContext};
use rustc::ty::subst::{Substs, Subst};
use rustc::ty;

use super::EvalContext;
use error::EvalResult;
use memory::Pointer;
use super::terminator::{get_impl_method, ImplMethod};

impl<'a, 'tcx> EvalContext<'a, 'tcx> {
    /// Creates a dynamic vtable for the given type and vtable origin. This is used only for
    /// objects.
    ///
    /// The `trait_ref` encodes the erased self type. Hence if we are
    /// making an object `Foo<Trait>` from a value of type `Foo<T>`, then
    /// `trait_ref` would map `T:Trait`.
    pub fn get_vtable(&mut self, trait_ref: ty::PolyTraitRef<'tcx>) -> EvalResult<'tcx, Pointer> {
        let tcx = self.tcx;

        debug!("get_vtable(trait_ref={:?})", trait_ref);

        let methods: Vec<_> = traits::supertraits(tcx, trait_ref.clone()).flat_map(|trait_ref| {
            match self.fulfill_obligation(trait_ref.clone()) {
                // Should default trait error here?
                traits::VtableDefaultImpl(_) |
                traits::VtableBuiltin(_) => {
                    Vec::new().into_iter()
                }
                traits::VtableImpl(
                    traits::VtableImplData {
                        impl_def_id: id,
                        substs,
                        nested: _ }) => {
                    self.get_vtable_methods(id, substs)
                        .into_iter()
                        .map(|opt_mth| opt_mth.map(|mth| {
                            self.memory.create_fn_ptr(mth.method.def_id, mth.substs, mth.method.fty)
                        }))
                        .collect::<Vec<_>>()
                        .into_iter()
                }
                traits::VtableClosure(
                    traits::VtableClosureData {
                        closure_def_id,
                        substs,
                        nested: _ }) => {
                    let closure_type = self.tcx.closure_type(closure_def_id, substs);
                    let fn_ty = ty::BareFnTy {
                        unsafety: closure_type.unsafety,
                        abi: closure_type.abi,
                        sig: closure_type.sig,
                    };
                    let _fn_ty = self.tcx.mk_bare_fn(fn_ty);
                    unimplemented!()
                    //vec![Some(self.memory.create_fn_ptr(closure_def_id, substs.func_substs, fn_ty))].into_iter()
                }
                traits::VtableFnPointer(
                    traits::VtableFnPointerData {
                        fn_ty: _bare_fn_ty,
                        nested: _ }) => {
                    let _trait_closure_kind = tcx.lang_items.fn_trait_kind(trait_ref.def_id()).unwrap();
                    //vec![trans_fn_pointer_shim(ccx, trait_closure_kind, bare_fn_ty)].into_iter()
                    unimplemented!()
                }
                traits::VtableObject(ref data) => {
                    // this would imply that the Self type being erased is
                    // an object type; this cannot happen because we
                    // cannot cast an unsized type into a trait object
                    bug!("cannot get vtable for an object type: {:?}",
                         data);
                }
                vtable @ traits::VtableParam(..) => {
                    bug!("resolved vtable for {:?} to bad vtable {:?} in trans",
                         trait_ref,
                         vtable);
                }
            }
        }).collect();

        let size = self.type_size(trait_ref.self_ty());
        let align = self.type_align(trait_ref.self_ty());

        let ptr_size = self.memory.pointer_size();
        let vtable = self.memory.allocate(ptr_size * (3 + methods.len()), ptr_size)?;

        // FIXME: generate a destructor for the vtable.
        // trans does this with glue::get_drop_glue(ccx, trait_ref.self_ty())

        self.memory.write_usize(vtable.offset(ptr_size as isize), size as u64)?;
        self.memory.write_usize(vtable.offset((ptr_size * 2) as isize), align as u64)?;

        for (i, method) in methods.into_iter().enumerate() {
            if let Some(method) = method {
                self.memory.write_ptr(vtable.offset(ptr_size as isize * (3 + i as isize)), method)?;
            }
        }

        Ok(vtable)
    }

    fn get_vtable_methods(&mut self, impl_id: DefId, substs: &'tcx Substs<'tcx>) -> Vec<Option<ImplMethod<'tcx>>> {
        debug!("get_vtable_methods(impl_id={:?}, substs={:?}", impl_id, substs);

        let trait_id = match self.tcx.impl_trait_ref(impl_id) {
            Some(t_id) => t_id.def_id,
            None       => bug!("make_impl_vtable: don't know how to \
                                make a vtable for a type impl!")
        };

        self.tcx.populate_implementations_for_trait_if_necessary(trait_id);

        let trait_item_def_ids = self.tcx.trait_item_def_ids(trait_id);
        trait_item_def_ids
            .iter()

            // Filter out non-method items.
            .filter_map(|item_def_id| {
                match *item_def_id {
                    ty::MethodTraitItemId(def_id) => Some(def_id),
                    _ => None,
                }
            })

            // Now produce pointers for each remaining method. If the
            // method could never be called from this object, just supply
            // null.
            .map(|trait_method_def_id| {
                debug!("get_vtable_methods: trait_method_def_id={:?}",
                       trait_method_def_id);

                let trait_method_type = match self.tcx.impl_or_trait_item(trait_method_def_id) {
                    ty::MethodTraitItem(m) => m,
                    _ => bug!("should be a method, not other assoc item"),
                };
                let name = trait_method_type.name;

                // Some methods cannot be called on an object; skip those.
                if !self.tcx.is_vtable_safe_method(trait_id, &trait_method_type) {
                    debug!("get_vtable_methods: not vtable safe");
                    return None;
                }

                debug!("get_vtable_methods: trait_method_type={:?}",
                       trait_method_type);

                // the method may have some early-bound lifetimes, add
                // regions for those
                let method_substs = Substs::for_item(self.tcx, trait_method_def_id,
                                                     |_, _| self.tcx.mk_region(ty::ReErased),
                                                     |_, _| self.tcx.types.err);

                // The substitutions we have are on the impl, so we grab
                // the method type from the impl to substitute into.
                let mth = get_impl_method(self.tcx, method_substs, impl_id, substs, name);

                debug!("get_vtable_methods: mth={:?}", mth);

                // If this is a default method, it's possible that it
                // relies on where clauses that do not hold for this
                // particular set of type parameters. Note that this
                // method could then never be called, so we do not want to
                // try and trans it, in that case. Issue #23435.
                if mth.is_provided {
                    let predicates = mth.method.predicates.predicates.subst(self.tcx, &mth.substs);
                    if !self.normalize_and_test_predicates(predicates) {
                        debug!("get_vtable_methods: predicates do not hold");
                        return None;
                    }
                }

                Some(mth)
            })
            .collect()
    }

    /// Normalizes the predicates and checks whether they hold.  If this
    /// returns false, then either normalize encountered an error or one
    /// of the predicates did not hold. Used when creating vtables to
    /// check for unsatisfiable methods.
    fn normalize_and_test_predicates(&mut self, predicates: Vec<ty::Predicate<'tcx>>) -> bool {
        debug!("normalize_and_test_predicates(predicates={:?})",
               predicates);

        self.tcx.infer_ctxt(None, None, Reveal::All).enter(|infcx| {
            let mut selcx = SelectionContext::new(&infcx);
            let mut fulfill_cx = traits::FulfillmentContext::new();
            let cause = traits::ObligationCause::dummy();
            let traits::Normalized { value: predicates, obligations } =
                traits::normalize(&mut selcx, cause.clone(), &predicates);
            for obligation in obligations {
                fulfill_cx.register_predicate_obligation(&infcx, obligation);
            }
            for predicate in predicates {
                let obligation = traits::Obligation::new(cause.clone(), predicate);
                fulfill_cx.register_predicate_obligation(&infcx, obligation);
            }

            fulfill_cx.select_all_or_error(&infcx).is_ok()
        })
    }
}
<|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::{os::unix::io::RawFd, sync::Arc};

use tokio::sync::Mutex;

use crate::{
    engine::{Engine, KeyDescription, MappingCreateAction, MappingDeleteAction, PoolUuid},
    stratis::StratisResult,
};

/// This method sets a key in the kernel keyring. It accepts an optional keyfile path
/// and if this is not provided, the user is prompted for a passphrase. When `no_tty`
/// is true, this command assumes that no TTY is available for setting terminal
/// settings and settings such as `NOECHO` are not set. This option should be
/// used carefully as it will cause the password to be echoed on the screen if
/// invoked interactively.
// stratis-min key set
pub async fn key_set(
    engine: Arc<Mutex<dyn Engine>>,
    key_desc: &KeyDescription,
    key_fd: RawFd,
) -> StratisResult<Option<bool>> {
    Ok(
        match engine
            .lock()
            .await
            .get_key_handler_mut()
            .set(key_desc, key_fd)?
        {
            MappingCreateAction::Created(_) => Some(false),
            MappingCreateAction::ValueChanged(_) => Some(true),
            MappingCreateAction::Identity => None,
        },
    )
}

pub async fn key_unset(
    engine: Arc<Mutex<dyn Engine>>,
    key_desc: &KeyDescription,
) -> StratisResult<bool> {
    Ok(
        match engine.lock().await.get_key_handler_mut().unset(key_desc)? {
            MappingDeleteAction::Deleted(_) => true,
            MappingDeleteAction::Identity => false,
        },
    )
}

pub async fn key_list(engine: Arc<Mutex<dyn Engine>>) -> StratisResult<Vec<KeyDescription>> {
    Ok(engine
        .lock()
        .await
        .get_key_handler_mut()
        .list()?
        .into_iter()
        .collect())
}

pub async fn key_get_desc(
    engine: Arc<Mutex<dyn Engine>>,
    pool_uuid: PoolUuid,
) -> Option<KeyDescription> {
    let locked_pools = engine.lock().await.locked_pools();
    locked_pools
        .get(&pool_uuid)
        .and_then(|info| info.info.key_description.to_owned())
}
<commit_msg>Fix comments in server/key.rs<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::{os::unix::io::RawFd, sync::Arc};

use tokio::sync::Mutex;

use crate::{
    engine::{Engine, KeyDescription, MappingCreateAction, MappingDeleteAction, PoolUuid},
    stratis::StratisResult,
};

// stratis-min key set
pub async fn key_set(
    engine: Arc<Mutex<dyn Engine>>,
    key_desc: &KeyDescription,
    key_fd: RawFd,
) -> StratisResult<Option<bool>> {
    Ok(
        match engine
            .lock()
            .await
            .get_key_handler_mut()
            .set(key_desc, key_fd)?
        {
            MappingCreateAction::Created(_) => Some(false),
            MappingCreateAction::ValueChanged(_) => Some(true),
            MappingCreateAction::Identity => None,
        },
    )
}

// stratis-min key unset
pub async fn key_unset(
    engine: Arc<Mutex<dyn Engine>>,
    key_desc: &KeyDescription,
) -> StratisResult<bool> {
    Ok(
        match engine.lock().await.get_key_handler_mut().unset(key_desc)? {
            MappingDeleteAction::Deleted(_) => true,
            MappingDeleteAction::Identity => false,
        },
    )
}

// stratis-min key [list]
pub async fn key_list(engine: Arc<Mutex<dyn Engine>>) -> StratisResult<Vec<KeyDescription>> {
    Ok(engine
        .lock()
        .await
        .get_key_handler_mut()
        .list()?
        .into_iter()
        .collect())
}

pub async fn key_get_desc(
    engine: Arc<Mutex<dyn Engine>>,
    pool_uuid: PoolUuid,
) -> Option<KeyDescription> {
    let locked_pools = engine.lock().await.locked_pools();
    locked_pools
        .get(&pool_uuid)
        .and_then(|info| info.info.key_description.to_owned())
}
<|endoftext|>


<commit_before>//! The Rust Prelude.
//!
//! Rust comes with a variety of things in its standard library. However, if
//! you had to manually import every single thing that you used, it would be
//! very verbose. But importing a lot of things that a program never uses isn't
//! good either. A balance needs to be struck.
//!
//! The *prelude* is the list of things that Rust automatically imports into
//! every Rust program. It's kept as small as possible, and is focused on
//! things, particularly traits, which are used in almost every single Rust
//! program.
//!
//! On a technical level, Rust inserts
//!
//! ```
//! # #[allow(unused_extern_crates)]
//! extern crate std;
//! ```
//!
//! into the crate root of every crate, and
//!
//! ```
//! # #[allow(unused_imports)]
//! use std::prelude::v1::*;
//! ```
//!
//! into every module.
//!
//! # Other preludes
//!
//! Preludes can be seen as a pattern to make using multiple types more
//! convenient. As such, you'll find other preludes in the standard library,
//! such as [`std::io::prelude`]. Various libraries in the Rust ecosystem may
//! also define their own preludes.
//!
//! [`std::io::prelude`]: ../io/prelude/index.html
//!
//! The difference between 'the prelude' and these other preludes is that they
//! are not automatically `use`'d, and must be imported manually. This is still
//! easier than importing all of their constituent components.
//!
//! # Prelude contents
//!
//! The current version of the prelude (version 1) lives in
//! [`std::prelude::v1`], and re-exports the following.
//!
//! * [`std::marker`]::{[`Copy`], [`Send`], [`Sized`], [`Sync`], [`Unpin`]}. The
//!   marker traits indicate fundamental properties of types.
//! * [`std::ops`]::{[`Drop`], [`Fn`], [`FnMut`], [`FnOnce`]}. Various
//!   operations for both destructors and overloading `()`.
//! * [`std::mem`]::[`drop`][`mem::drop`], a convenience function for explicitly
//!   dropping a value.
//! * [`std::boxed`]::[`Box`], a way to allocate values on the heap.
//! * [`std::borrow`]::[`ToOwned`], The conversion trait that defines
//!   [`to_owned`], the generic method for creating an owned type from a
//!   borrowed type.
//! * [`std::clone`]::[`Clone`], the ubiquitous trait that defines
//!   [`clone`][`Clone::clone`], the method for producing a copy of a value.
//! * [`std::cmp`]::{[`PartialEq`], [`PartialOrd`], [`Eq`], [`Ord`] }. The
//!   comparison traits, which implement the comparison operators and are often
//!   seen in trait bounds.
//! * [`std::convert`]::{[`AsRef`], [`AsMut`], [`Into`], [`From`]}. Generic
//!   conversions, used by savvy API authors to create overloaded methods.
//! * [`std::default`]::[`Default`], types that have default values.
//! * [`std::iter`]::{[`Iterator`], [`Extend`], [`IntoIterator`],
//!   [`DoubleEndedIterator`], [`ExactSizeIterator`]}. Iterators of various
//!   kinds.
//! * [`std::option`]::[`Option`]::{`self`, `Some`, `None`}. A type which
//!   expresses the presence or absence of a value. This type is so commonly
//!   used, its variants are also exported.
//! * [`std::result`]::[`Result`]::{`self`, `Ok`, `Err`}. A type for functions
//!   that may succeed or fail. Like [`Option`], its variants are exported as
//!   well.
//! * [`std::string`]::{[`String`], [`ToString`]}, heap allocated strings.
//! * [`std::vec`]::[`Vec`](../vec/struct.Vec.html), a growable, heap-allocated
//!   vector.
//!
//! [`AsMut`]: ../convert/trait.AsMut.html
//! [`AsRef`]: ../convert/trait.AsRef.html
//! [`Box`]: ../boxed/struct.Box.html
//! [`Clone`]: ../clone/trait.Clone.html
//! [`Copy`]: ../marker/trait.Copy.html
//! [`Default`]: ../default/trait.Default.html
//! [`DoubleEndedIterator`]: ../iter/trait.DoubleEndedIterator.html
//! [`Drop`]: ../ops/trait.Drop.html
//! [`Eq`]: ../cmp/trait.Eq.html
//! [`ExactSizeIterator`]: ../iter/trait.ExactSizeIterator.html
//! [`Extend`]: ../iter/trait.Extend.html
//! [`FnMut`]: ../ops/trait.FnMut.html
//! [`FnOnce`]: ../ops/trait.FnOnce.html
//! [`Fn`]: ../ops/trait.Fn.html
//! [`From`]: ../convert/trait.From.html
//! [`IntoIterator`]: ../iter/trait.IntoIterator.html
//! [`Into`]: ../convert/trait.Into.html
//! [`Iterator`]: ../iter/trait.Iterator.html
//! [`Option`]: ../option/enum.Option.html
//! [`Ord`]: ../cmp/trait.Ord.html
//! [`PartialEq`]: ../cmp/trait.PartialEq.html
//! [`PartialOrd`]: ../cmp/trait.PartialOrd.html
//! [`Result`]: ../result/enum.Result.html
//! [`Send`]: ../marker/trait.Send.html
//! [`Sized`]: ../marker/trait.Sized.html
//! [`SliceConcatExt`]: ../slice/trait.SliceConcatExt.html
//! [`String`]: ../string/struct.String.html
//! [`Sync`]: ../marker/trait.Sync.html
//! [`ToOwned`]: ../borrow/trait.ToOwned.html
//! [`ToString`]: ../string/trait.ToString.html
//! [`Unpin`]: ../marker/trait.Unpin.html
//! [`Vec`]: ../vec/struct.Vec.html
//! [`Clone::clone`]: ../clone/trait.Clone.html#tymethod.clone
//! [`mem::drop`]: ../mem/fn.drop.html
//! [`std::borrow`]: ../borrow/index.html
//! [`std::boxed`]: ../boxed/index.html
//! [`std::clone`]: ../clone/index.html
//! [`std::cmp`]: ../cmp/index.html
//! [`std::convert`]: ../convert/index.html
//! [`std::default`]: ../default/index.html
//! [`std::iter`]: ../iter/index.html
//! [`std::marker`]: ../marker/index.html
//! [`std::mem`]: ../mem/index.html
//! [`std::ops`]: ../ops/index.html
//! [`std::option`]: ../option/index.html
//! [`std::prelude::v1`]: v1/index.html
//! [`std::result`]: ../result/index.html
//! [`std::slice`]: ../slice/index.html
//! [`std::string`]: ../string/index.html
//! [`std::vec`]: ../vec/index.html
//! [`to_owned`]: ../borrow/trait.ToOwned.html#tymethod.to_owned
//! [book-closures]: ../../book/ch13-01-closures.html
//! [book-dtor]: ../../book/ch15-03-drop.html
//! [book-enums]: ../../book/ch06-01-defining-an-enum.html
//! [book-iter]: ../../book/ch13-02-iterators.html

#![stable(feature = "rust1", since = "1.0.0")]

pub mod v1;
<commit_msg>Rollup merge of #73484 - poliorcetics:use-prelude-doc, r=sfackler<commit_after>//! The Rust Prelude.
//!
//! Rust comes with a variety of things in its standard library. However, if
//! you had to manually import every single thing that you used, it would be
//! very verbose. But importing a lot of things that a program never uses isn't
//! good either. A balance needs to be struck.
//!
//! The *prelude* is the list of things that Rust automatically imports into
//! every Rust program. It's kept as small as possible, and is focused on
//! things, particularly traits, which are used in almost every single Rust
//! program.
//!
//! # Other preludes
//!
//! Preludes can be seen as a pattern to make using multiple types more
//! convenient. As such, you'll find other preludes in the standard library,
//! such as [`std::io::prelude`]. Various libraries in the Rust ecosystem may
//! also define their own preludes.
//!
//! [`std::io::prelude`]: ../io/prelude/index.html
//!
//! The difference between 'the prelude' and these other preludes is that they
//! are not automatically `use`'d, and must be imported manually. This is still
//! easier than importing all of their constituent components.
//!
//! # Prelude contents
//!
//! The current version of the prelude (version 1) lives in
//! [`std::prelude::v1`], and re-exports the following.
//!
//! * [`std::marker`]::{[`Copy`], [`Send`], [`Sized`], [`Sync`], [`Unpin`]}. The
//!   marker traits indicate fundamental properties of types.
//! * [`std::ops`]::{[`Drop`], [`Fn`], [`FnMut`], [`FnOnce`]}. Various
//!   operations for both destructors and overloading `()`.
//! * [`std::mem`]::[`drop`][`mem::drop`], a convenience function for explicitly
//!   dropping a value.
//! * [`std::boxed`]::[`Box`], a way to allocate values on the heap.
//! * [`std::borrow`]::[`ToOwned`], The conversion trait that defines
//!   [`to_owned`], the generic method for creating an owned type from a
//!   borrowed type.
//! * [`std::clone`]::[`Clone`], the ubiquitous trait that defines
//!   [`clone`][`Clone::clone`], the method for producing a copy of a value.
//! * [`std::cmp`]::{[`PartialEq`], [`PartialOrd`], [`Eq`], [`Ord`] }. The
//!   comparison traits, which implement the comparison operators and are often
//!   seen in trait bounds.
//! * [`std::convert`]::{[`AsRef`], [`AsMut`], [`Into`], [`From`]}. Generic
//!   conversions, used by savvy API authors to create overloaded methods.
//! * [`std::default`]::[`Default`], types that have default values.
//! * [`std::iter`]::{[`Iterator`], [`Extend`], [`IntoIterator`],
//!   [`DoubleEndedIterator`], [`ExactSizeIterator`]}. Iterators of various
//!   kinds.
//! * [`std::option`]::[`Option`]::{`self`, `Some`, `None`}. A type which
//!   expresses the presence or absence of a value. This type is so commonly
//!   used, its variants are also exported.
//! * [`std::result`]::[`Result`]::{`self`, `Ok`, `Err`}. A type for functions
//!   that may succeed or fail. Like [`Option`], its variants are exported as
//!   well.
//! * [`std::string`]::{[`String`], [`ToString`]}, heap allocated strings.
//! * [`std::vec`]::[`Vec`](../vec/struct.Vec.html), a growable, heap-allocated
//!   vector.
//!
//! [`AsMut`]: ../convert/trait.AsMut.html
//! [`AsRef`]: ../convert/trait.AsRef.html
//! [`Box`]: ../boxed/struct.Box.html
//! [`Clone`]: ../clone/trait.Clone.html
//! [`Copy`]: ../marker/trait.Copy.html
//! [`Default`]: ../default/trait.Default.html
//! [`DoubleEndedIterator`]: ../iter/trait.DoubleEndedIterator.html
//! [`Drop`]: ../ops/trait.Drop.html
//! [`Eq`]: ../cmp/trait.Eq.html
//! [`ExactSizeIterator`]: ../iter/trait.ExactSizeIterator.html
//! [`Extend`]: ../iter/trait.Extend.html
//! [`FnMut`]: ../ops/trait.FnMut.html
//! [`FnOnce`]: ../ops/trait.FnOnce.html
//! [`Fn`]: ../ops/trait.Fn.html
//! [`From`]: ../convert/trait.From.html
//! [`IntoIterator`]: ../iter/trait.IntoIterator.html
//! [`Into`]: ../convert/trait.Into.html
//! [`Iterator`]: ../iter/trait.Iterator.html
//! [`Option`]: ../option/enum.Option.html
//! [`Ord`]: ../cmp/trait.Ord.html
//! [`PartialEq`]: ../cmp/trait.PartialEq.html
//! [`PartialOrd`]: ../cmp/trait.PartialOrd.html
//! [`Result`]: ../result/enum.Result.html
//! [`Send`]: ../marker/trait.Send.html
//! [`Sized`]: ../marker/trait.Sized.html
//! [`SliceConcatExt`]: ../slice/trait.SliceConcatExt.html
//! [`String`]: ../string/struct.String.html
//! [`Sync`]: ../marker/trait.Sync.html
//! [`ToOwned`]: ../borrow/trait.ToOwned.html
//! [`ToString`]: ../string/trait.ToString.html
//! [`Unpin`]: ../marker/trait.Unpin.html
//! [`Vec`]: ../vec/struct.Vec.html
//! [`Clone::clone`]: ../clone/trait.Clone.html#tymethod.clone
//! [`mem::drop`]: ../mem/fn.drop.html
//! [`std::borrow`]: ../borrow/index.html
//! [`std::boxed`]: ../boxed/index.html
//! [`std::clone`]: ../clone/index.html
//! [`std::cmp`]: ../cmp/index.html
//! [`std::convert`]: ../convert/index.html
//! [`std::default`]: ../default/index.html
//! [`std::iter`]: ../iter/index.html
//! [`std::marker`]: ../marker/index.html
//! [`std::mem`]: ../mem/index.html
//! [`std::ops`]: ../ops/index.html
//! [`std::option`]: ../option/index.html
//! [`std::prelude::v1`]: v1/index.html
//! [`std::result`]: ../result/index.html
//! [`std::slice`]: ../slice/index.html
//! [`std::string`]: ../string/index.html
//! [`std::vec`]: ../vec/index.html
//! [`to_owned`]: ../borrow/trait.ToOwned.html#tymethod.to_owned
//! [book-closures]: ../../book/ch13-01-closures.html
//! [book-dtor]: ../../book/ch15-03-drop.html
//! [book-enums]: ../../book/ch06-01-defining-an-enum.html
//! [book-iter]: ../../book/ch13-02-iterators.html

#![stable(feature = "rust1", since = "1.0.0")]

pub mod v1;
<|endoftext|>


<commit_before>
#[derive(Clone,PartialEq,Eq,Debug)]
pub enum Token {
  And,
  Break,
  Do,
  Else,
  Elseif,
  End,
  False,
  For,
  Function,
  If,
  In,
  Local,
  Nil,
  Not,
  Or,
  Repeat,
  Return,
  Then,
  True,
  Until,
  While,

  Plus,
  Minus,
  Times,
  Divide,
  Mod,
  Exp,
  Len,
  Eq,
  Neq,
  Leq,
  Geq,
  Lt,
  Gt,
  Assign,
  LParen,
  RParen,
  LBrace,
  RBrace,
  LSquare,
  RSquare,
  Semi,
  Colon,
  Comma,
  Dot,
  Dotdot,
  Dotdotdot,

  String(String),
  Number(String),
  Name(String),

  EOF
}

<commit_msg>Add impl Display for Token<commit_after>use std::fmt::{Display, Formatter, Error};

#[derive(Clone,PartialEq,Eq,Debug)]
pub enum Token {
  And,
  Break,
  Do,
  Else,
  Elseif,
  End,
  False,
  For,
  Function,
  If,
  In,
  Local,
  Nil,
  Not,
  Or,
  Repeat,
  Return,
  Then,
  True,
  Until,
  While,

  Plus,
  Minus,
  Times,
  Divide,
  Mod,
  Exp,
  Len,
  Eq,
  Neq,
  Leq,
  Geq,
  Lt,
  Gt,
  Assign,
  LParen,
  RParen,
  LBrace,
  RBrace,
  LSquare,
  RSquare,
  Semi,
  Colon,
  Comma,
  Dot,
  Dotdot,
  Dotdotdot,

  String(String),
  Number(String),
  Name(String),

  EOF
}

impl Display for Token {
  fn fmt(&self, f : &mut Formatter) -> Result<(), Error> {
    let repr = match *self {
      Token::And => "'and'",
      Token::Break => "'break'",
      Token::Do => "'do'",
      Token::Else => "'else'",
      Token::Elseif => "'elseif'",
      Token::End => "'end'",
      Token::False => "'false'",
      Token::For => "'for'",
      Token::Function => "'function'",
      Token::If => "'if'",
      Token::In => "'in'",
      Token::Local => "'local'",
      Token::Nil => "'nil'",
      Token::Not => "'not'",
      Token::Or => "'or'",
      Token::Repeat => "'repeat'",
      Token::Return => "'return'",
      Token::Then => "'then'",
      Token::True => "'true'",
      Token::Until => "'until'",
      Token::While => "'while'",

      Token::Plus => "'+'",
      Token::Minus => "'-'",
      Token::Times => "'*'",
      Token::Divide => "'/'",
      Token::Mod => "'%'",
      Token::Exp => "'^'",
      Token::Len => "'#'",
      Token::Eq => "'=='",
      Token::Neq => "'~='",
      Token::Leq => "'<='",
      Token::Geq => "'>='",
      Token::Lt => "'<'",
      Token::Gt => "'>'",
      Token::Assign => "'='",
      Token::LParen => "'('",
      Token::RParen => "')'",
      Token::LBrace => "'{'",
      Token::RBrace => "'}'",
      Token::LSquare => "'['",
      Token::RSquare => "']'",
      Token::Semi => "';'",
      Token::Colon => "':'",
      Token::Comma => "','",
      Token::Dot => "'.'",
      Token::Dotdot => "'..'",
      Token::Dotdotdot => "'...'",

      Token::String(_) => "string literal",
      Token::Number(_) => "number literal",
      Token::Name(_)   => "name",

      Token::EOF => "<eof>"
    };

    try!(f.write_str(repr));

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


<commit_before>#![feature(custom_test_frameworks)]
// Custom test runner, to avoid libtest being wrapped around compiletest which wraps libtest.
#![test_runner(test_runner)]

use std::env;
use std::path::PathBuf;

use colored::*;
use compiletest_rs as compiletest;

fn miri_path() -> PathBuf {
    if rustc_test_suite().is_some() {
        PathBuf::from(option_env!("MIRI_PATH").unwrap())
    } else {
        PathBuf::from(env!("CARGO_BIN_EXE_miri"))
    }
}

fn rustc_test_suite() -> Option<PathBuf> {
    option_env!("RUSTC_TEST_SUITE").map(PathBuf::from)
}

fn rustc_lib_path() -> PathBuf {
    option_env!("RUSTC_LIB_PATH").unwrap().into()
}

fn run_tests(mode: &str, path: &str, target: &str) {
    let in_rustc_test_suite = rustc_test_suite().is_some();
    // Add some flags we always want.
    let mut flags = Vec::new();
    flags.push("--edition 2018".to_owned());
    if in_rustc_test_suite {
        // Less aggressive warnings to make the rustc toolstate management less painful.
        // (We often get warnings when e.g. a feature gets stabilized or some lint gets added/improved.)
        flags.push("-Astable-features".to_owned());
    } else {
        flags.push("-Dwarnings -Dunused".to_owned()); // overwrite the -Aunused in compiletest-rs
    }
    if let Ok(sysroot) = std::env::var("MIRI_SYSROOT") {
        flags.push(format!("--sysroot {}", sysroot));
    }
    if let Ok(extra_flags) = std::env::var("MIRI_TEST_FLAGS") {
        flags.push(extra_flags);
    }

    let flags = flags.join(" ");
    eprintln!("   Compiler flags: {}", flags);

    // The rest of the configuration.
    let mut config = compiletest::Config::default().tempdir();
    config.mode = mode.parse().expect("Invalid mode");
    config.rustc_path = miri_path();
    if in_rustc_test_suite {
        config.run_lib_path = rustc_lib_path();
        config.compile_lib_path = rustc_lib_path();
    }
    config.filter = env::args().nth(1);
    config.host = get_host();
    config.src_base = PathBuf::from(path);
    config.target = target.to_owned();
    config.target_rustcflags = Some(flags);
    compiletest::run_tests(&config);
}

fn compile_fail(path: &str, target: &str) {
    eprintln!(
        "{}",
        format!(
            "## Running compile-fail tests in {} against miri for target {}",
            path, target
        )
        .green()
        .bold()
    );

    run_tests("compile-fail", path, target);
}

fn miri_pass(path: &str, target: &str) {
    eprintln!(
        "{}",
        format!(
            "## Running run-pass tests in {} against miri for target {}",
            path, target
        )
        .green()
        .bold()
    );

    run_tests("ui", path, target);
}

fn get_host() -> String {
    let rustc = rustc_test_suite().unwrap_or(PathBuf::from("rustc"));
    let rustc_version = std::process::Command::new(rustc)
        .arg("-vV")
        .output()
        .expect("rustc not found for -vV")
        .stdout;
    let rustc_version = std::str::from_utf8(&rustc_version).expect("rustc -vV is not utf8");
    let version_meta = rustc_version::version_meta_for(&rustc_version)
        .expect("failed to parse rustc version info");
    version_meta.host
}

fn get_target() -> String {
    std::env::var("MIRI_TEST_TARGET").unwrap_or_else(|_| get_host())
}

fn test_runner(_tests: &[&()]) {
    // Add a test env var to do environment communication tests.
    std::env::set_var("MIRI_ENV_VAR_TEST", "0");
    // Let the tests know where to store temp files (they might run for a different target, which can make this hard to find).
    std::env::set_var("MIRI_TEMP", std::env::temp_dir());

    let target = get_target();
    miri_pass("tests/run-pass", &target);
    compile_fail("tests/compile-fail", &target);
}
<commit_msg>compiletest: no need to call rustc here<commit_after>#![feature(custom_test_frameworks)]
// Custom test runner, to avoid libtest being wrapped around compiletest which wraps libtest.
#![test_runner(test_runner)]

use std::env;
use std::path::PathBuf;

use colored::*;
use compiletest_rs as compiletest;

fn miri_path() -> PathBuf {
    PathBuf::from(option_env!("MIRI_PATH").unwrap_or(env!("CARGO_BIN_EXE_miri")))
}

fn run_tests(mode: &str, path: &str, target: &str) {
    let in_rustc_test_suite = option_env!("RUSTC_STAGE").is_some();
    // Add some flags we always want.
    let mut flags = Vec::new();
    flags.push("--edition 2018".to_owned());
    if in_rustc_test_suite {
        // Less aggressive warnings to make the rustc toolstate management less painful.
        // (We often get warnings when e.g. a feature gets stabilized or some lint gets added/improved.)
        flags.push("-Astable-features".to_owned());
    } else {
        flags.push("-Dwarnings -Dunused".to_owned()); // overwrite the -Aunused in compiletest-rs
    }
    if let Ok(sysroot) = std::env::var("MIRI_SYSROOT") {
        flags.push(format!("--sysroot {}", sysroot));
    }
    if let Ok(extra_flags) = std::env::var("MIRI_TEST_FLAGS") {
        flags.push(extra_flags);
    }

    let flags = flags.join(" ");
    eprintln!("   Compiler flags: {}", flags);

    // The rest of the configuration.
    let mut config = compiletest::Config::default().tempdir();
    config.mode = mode.parse().expect("Invalid mode");
    config.rustc_path = miri_path();
    if let Some(lib_path) = option_env!("RUSTC_LIB_PATH") {
        config.run_lib_path = PathBuf::from(lib_path);
        config.compile_lib_path = PathBuf::from(lib_path);
    }
    config.filter = env::args().nth(1);
    config.host = get_host();
    config.src_base = PathBuf::from(path);
    config.target = target.to_owned();
    config.target_rustcflags = Some(flags);
    compiletest::run_tests(&config);
}

fn compile_fail(path: &str, target: &str) {
    eprintln!(
        "{}",
        format!(
            "## Running compile-fail tests in {} against miri for target {}",
            path, target
        )
        .green()
        .bold()
    );

    run_tests("compile-fail", path, target);
}

fn miri_pass(path: &str, target: &str) {
    eprintln!(
        "{}",
        format!(
            "## Running run-pass tests in {} against miri for target {}",
            path, target
        )
        .green()
        .bold()
    );

    run_tests("ui", path, target);
}

fn get_host() -> String {
    let version_meta = rustc_version::VersionMeta::for_command(
        std::process::Command::new(miri_path())
    ).expect("failed to parse rustc version info");
    version_meta.host
}

fn get_target() -> String {
    std::env::var("MIRI_TEST_TARGET").unwrap_or_else(|_| get_host())
}

fn test_runner(_tests: &[&()]) {
    // Add a test env var to do environment communication tests.
    std::env::set_var("MIRI_ENV_VAR_TEST", "0");
    // Let the tests know where to store temp files (they might run for a different target, which can make this hard to find).
    std::env::set_var("MIRI_TEMP", std::env::temp_dir());

    let target = get_target();
    miri_pass("tests/run-pass", &target);
    compile_fail("tests/compile-fail", &target);
}
<|endoftext|>


<commit_before>extern crate wikipedia;

#[cfg(feature = "http-client")]
mod tests {
    use wikipedia::Wikipedia;
    use wikipedia::http;
    use std::collections::HashSet;

    fn w() -> Wikipedia<http::default::Client> {
        Wikipedia::default()
    }

    #[test]
    fn search() {
        let wikipedia = w();
        let results = wikipedia.search("hello world").unwrap();
        assert!(results.len() > 0);
        assert!(results.contains(&"\"Hello, World!\" program".to_owned()));
    }

    #[test]
    fn geosearch() {
        let wikipedia = w();
        let results = wikipedia.geosearch(-34.603333, -58.381667, 10).unwrap();
        assert!(results.len() > 0);
        assert!(results.contains(&"Buenos Aires".to_owned()));
    }

    #[test]
    fn random() {
        let wikipedia = w();
        wikipedia.random().unwrap().unwrap();
    }

    #[test]
    fn random_count() {
        let wikipedia = w();
        assert_eq!(wikipedia.random_count(3).unwrap().len(), 3);
    }

    #[test]
    fn page_content() {
        let wikipedia = w();
        let page = wikipedia.page_from_title("Parkinson's law of triviality".to_owned());
        assert!(page.get_content().unwrap().contains("bike-shedding"));
    }

    #[test]
    fn title() {
        let wikipedia = w();
        let page = wikipedia.page_from_title("Parkinson's law of triviality".to_owned());
        assert_eq!(page.get_title().unwrap(), "Parkinson's law of triviality".to_owned());
        let page = wikipedia.page_from_pageid("4138548".to_owned());
        assert_eq!(page.get_title().unwrap(), "Law of triviality".to_owned());
    }

    #[test]
    fn pageid() {
        let wikipedia = w();
        let page = wikipedia.page_from_title("Parkinson's law of triviality".to_owned());
        assert_eq!(page.get_pageid().unwrap(), "4138548".to_owned());
        let page = wikipedia.page_from_title("Bikeshedding".to_owned());
        assert_eq!(page.get_pageid().unwrap(), "4138548".to_owned());
        let page = wikipedia.page_from_pageid("4138548".to_owned());
        assert_eq!(page.get_pageid().unwrap(), "4138548".to_owned());
    }

    #[test]
    fn page_html_content() {
        let wikipedia = w();
        let page = wikipedia.page_from_pageid("4138548".to_owned());
        let html = page.get_html_content().unwrap();
        assert!(html.contains("bike-shedding"));
        assert!(html.contains("
")); // it would not be html otherwise
    }

    #[test]
    fn page_summary() {
        let wikipedia = w();
        let page = wikipedia.page_from_title("Parkinson's law of triviality".to_owned());
        let summary = page.get_summary().unwrap();
        let content = page.get_content().unwrap();
        assert!(summary.contains("bike-shedding"));
        assert!(summary.len() < content.len());
    }

    #[test]
    fn page_redirect_summary() {
        let wikipedia = w();
        let page = wikipedia.page_from_title("Bikeshedding".to_owned());
        let summary = page.get_summary().unwrap();
        let content = page.get_content().unwrap();
        assert!(summary.contains("bike-shedding"));
        assert!(summary.len() < content.len());
    }

    #[test]
    fn page_images() {
        let mut wikipedia = w();
        wikipedia.images_results = "5".to_owned();
        let page = wikipedia.page_from_title("Argentina".to_owned());
        let images = page.get_images().unwrap();
        let mut c = 0;
        let mut set = HashSet::new();
        for i in images {
            assert!(i.title.len() > 0);
            assert!(i.url.len() > 0);
            assert!(i.description_url.len() > 0);
            c += 1;
            set.insert(i.title);
            if c == 11 {
                break;
            }
        }
        assert_eq!(set.len(), 11);
    }

    #[test]
    fn coordinates() {
        let wikipedia = w();
        let page = wikipedia.page_from_title("San Francisco".to_owned());
        let (lat, lon) = page.get_coordinates().unwrap().unwrap();
        assert!(lat > 0.0);
        assert!(lon < 0.0);
    }

    #[test]
    fn no_coordinates() {
        let wikipedia = w();
        let page = wikipedia.page_from_title("Bikeshedding".to_owned());
        assert!(page.get_coordinates().unwrap().is_none());
    }

    #[test]
    fn references() {
        let mut wikipedia = w();
        wikipedia.links_results = "3".to_owned();
        let page = wikipedia.page_from_title("Argentina".to_owned());
        let references = page.get_references().unwrap();
        let mut c = 0;
        let mut set = HashSet::new();
        for r in references {
            assert!(r.url.starts_with("http"));
            c += 1;
            set.insert(r.url);
            if c == 7 {
                break;
            }
        }
        assert_eq!(set.len(), 7);
    }

    #[test]
    fn links() {
        let mut wikipedia = w();
        wikipedia.links_results = "3".to_owned();
        let page = wikipedia.page_from_title("Argentina".to_owned());
        let links = page.get_links().unwrap();
        let mut c = 0;
        let mut set = HashSet::new();
        for r in links {
            c += 1;
            set.insert(r.title);
            if c == 7 {
                break;
            }
        }
        assert_eq!(set.len(), 7);
    }

    #[test]
    fn categories() {
        let mut wikipedia = w();
        wikipedia.categories_results = "3".to_owned();
        let page = wikipedia.page_from_title("Argentina".to_owned());
        let categories = page.get_links().unwrap();
        let mut c = 0;
        let mut set = HashSet::new();
        for ca in categories {
            c += 1;
            set.insert(ca.title);
            if c == 7 {
                break;
            }
        }
        assert_eq!(set.len(), 7);
    }

    #[test]
    fn sections() {
        let wikipedia = w();
        let page = wikipedia.page_from_title("Bikeshedding".to_owned());
        assert_eq!(
                page.get_sections().unwrap(),
                vec![
                "Argument".to_owned(),
                "Examples".to_owned(),
                "Related principles and formulations".to_owned(),
                "See also".to_owned(),
                "References".to_owned(),
                "Further reading".to_owned(),
                "External links".to_owned(),
                ]
                )
    }

    #[test]
    fn sections2() {
        let wikipedia = w();
        let page = wikipedia.page_from_pageid("4138548".to_owned());
        assert_eq!(
                page.get_sections().unwrap(),
                vec![
                "Argument".to_owned(),
                "Examples".to_owned(),
                "Related principles and formulations".to_owned(),
                "See also".to_owned(),
                "References".to_owned(),
                "Further reading".to_owned(),
                "External links".to_owned(),
                ]
                )
    }

    #[test]
    fn section_content() {
        let wikipedia = w();
        let page = wikipedia.page_from_pageid("4138548".to_owned());
        assert!(page.get_section_content("Examples").unwrap().unwrap()
                .contains("finance committee meeting"))
    }

    #[test]
    fn languages() {
        let languages = w().get_languages().unwrap();
        assert!(languages.contains(&("en".to_owned(), "English".to_owned())));
        assert!(languages.contains(&("es".to_owned(), "español".to_owned())));
    }
}
<commit_msg>Add unit test for langlinks<commit_after>extern crate wikipedia;

#[cfg(feature = "http-client")]
mod tests {
    use wikipedia::Wikipedia;
    use wikipedia::http;
    use std::collections::HashSet;

    fn w() -> Wikipedia<http::default::Client> {
        Wikipedia::default()
    }

    #[test]
    fn search() {
        let wikipedia = w();
        let results = wikipedia.search("hello world").unwrap();
        assert!(results.len() > 0);
        assert!(results.contains(&"\"Hello, World!\" program".to_owned()));
    }

    #[test]
    fn geosearch() {
        let wikipedia = w();
        let results = wikipedia.geosearch(-34.603333, -58.381667, 10).unwrap();
        assert!(results.len() > 0);
        assert!(results.contains(&"Buenos Aires".to_owned()));
    }

    #[test]
    fn random() {
        let wikipedia = w();
        wikipedia.random().unwrap().unwrap();
    }

    #[test]
    fn random_count() {
        let wikipedia = w();
        assert_eq!(wikipedia.random_count(3).unwrap().len(), 3);
    }

    #[test]
    fn page_content() {
        let wikipedia = w();
        let page = wikipedia.page_from_title("Parkinson's law of triviality".to_owned());
        assert!(page.get_content().unwrap().contains("bike-shedding"));
    }

    #[test]
    fn title() {
        let wikipedia = w();
        let page = wikipedia.page_from_title("Parkinson's law of triviality".to_owned());
        assert_eq!(page.get_title().unwrap(), "Parkinson's law of triviality".to_owned());
        let page = wikipedia.page_from_pageid("4138548".to_owned());
        assert_eq!(page.get_title().unwrap(), "Law of triviality".to_owned());
    }

    #[test]
    fn pageid() {
        let wikipedia = w();
        let page = wikipedia.page_from_title("Parkinson's law of triviality".to_owned());
        assert_eq!(page.get_pageid().unwrap(), "4138548".to_owned());
        let page = wikipedia.page_from_title("Bikeshedding".to_owned());
        assert_eq!(page.get_pageid().unwrap(), "4138548".to_owned());
        let page = wikipedia.page_from_pageid("4138548".to_owned());
        assert_eq!(page.get_pageid().unwrap(), "4138548".to_owned());
    }

    #[test]
    fn page_html_content() {
        let wikipedia = w();
        let page = wikipedia.page_from_pageid("4138548".to_owned());
        let html = page.get_html_content().unwrap();
        assert!(html.contains("bike-shedding"));
        assert!(html.contains("
")); // it would not be html otherwise
    }

    #[test]
    fn page_summary() {
        let wikipedia = w();
        let page = wikipedia.page_from_title("Parkinson's law of triviality".to_owned());
        let summary = page.get_summary().unwrap();
        let content = page.get_content().unwrap();
        assert!(summary.contains("bike-shedding"));
        assert!(summary.len() < content.len());
    }

    #[test]
    fn page_redirect_summary() {
        let wikipedia = w();
        let page = wikipedia.page_from_title("Bikeshedding".to_owned());
        let summary = page.get_summary().unwrap();
        let content = page.get_content().unwrap();
        assert!(summary.contains("bike-shedding"));
        assert!(summary.len() < content.len());
    }

    #[test]
    fn page_images() {
        let mut wikipedia = w();
        wikipedia.images_results = "5".to_owned();
        let page = wikipedia.page_from_title("Argentina".to_owned());
        let images = page.get_images().unwrap();
        let mut c = 0;
        let mut set = HashSet::new();
        for i in images {
            assert!(i.title.len() > 0);
            assert!(i.url.len() > 0);
            assert!(i.description_url.len() > 0);
            c += 1;
            set.insert(i.title);
            if c == 11 {
                break;
            }
        }
        assert_eq!(set.len(), 11);
    }

    #[test]
    fn coordinates() {
        let wikipedia = w();
        let page = wikipedia.page_from_title("San Francisco".to_owned());
        let (lat, lon) = page.get_coordinates().unwrap().unwrap();
        assert!(lat > 0.0);
        assert!(lon < 0.0);
    }

    #[test]
    fn no_coordinates() {
        let wikipedia = w();
        let page = wikipedia.page_from_title("Bikeshedding".to_owned());
        assert!(page.get_coordinates().unwrap().is_none());
    }

    #[test]
    fn references() {
        let mut wikipedia = w();
        wikipedia.links_results = "3".to_owned();
        let page = wikipedia.page_from_title("Argentina".to_owned());
        let references = page.get_references().unwrap();
        let mut c = 0;
        let mut set = HashSet::new();
        for r in references {
            assert!(r.url.starts_with("http"));
            c += 1;
            set.insert(r.url);
            if c == 7 {
                break;
            }
        }
        assert_eq!(set.len(), 7);
    }

    #[test]
    fn links() {
        let mut wikipedia = w();
        wikipedia.links_results = "3".to_owned();
        let page = wikipedia.page_from_title("Argentina".to_owned());
        let links = page.get_links().unwrap();
        let mut c = 0;
        let mut set = HashSet::new();
        for r in links {
            c += 1;
            set.insert(r.title);
            if c == 7 {
                break;
            }
        }
        assert_eq!(set.len(), 7);
    }

    #[test]
    fn langlinks() {
        let mut wikipedia = w();
        wikipedia.links_results = "3".to_owned();
        let page = wikipedia.page_from_title("Law of triviality".to_owned());
        let langlinks = page.get_langlinks().unwrap().collect::<Vec<_>>();
        assert_eq!(
            langlinks
                .iter()
                .filter(|ll| ll.lang == "nl".to_owned())
                .next()
                .unwrap()
                .title,
            Some("Trivialiteitswet van Parkinson".into()),
        );
        assert_eq!(
            langlinks
                .iter()
                .filter(|ll| ll.lang == "fr".to_owned())
                .next()
                .unwrap()
                .title,
            Some("Loi de futilité de Parkinson".into()),
        );
    }

    #[test]
    fn categories() {
        let mut wikipedia = w();
        wikipedia.categories_results = "3".to_owned();
        let page = wikipedia.page_from_title("Argentina".to_owned());
        let categories = page.get_links().unwrap();
        let mut c = 0;
        let mut set = HashSet::new();
        for ca in categories {
            c += 1;
            set.insert(ca.title);
            if c == 7 {
                break;
            }
        }
        assert_eq!(set.len(), 7);
    }

    #[test]
    fn sections() {
        let wikipedia = w();
        let page = wikipedia.page_from_title("Bikeshedding".to_owned());
        assert_eq!(
                page.get_sections().unwrap(),
                vec![
                "Argument".to_owned(),
                "Examples".to_owned(),
                "Related principles and formulations".to_owned(),
                "See also".to_owned(),
                "References".to_owned(),
                "Further reading".to_owned(),
                "External links".to_owned(),
                ]
                )
    }

    #[test]
    fn sections2() {
        let wikipedia = w();
        let page = wikipedia.page_from_pageid("4138548".to_owned());
        assert_eq!(
                page.get_sections().unwrap(),
                vec![
                "Argument".to_owned(),
                "Examples".to_owned(),
                "Related principles and formulations".to_owned(),
                "See also".to_owned(),
                "References".to_owned(),
                "Further reading".to_owned(),
                "External links".to_owned(),
                ]
                )
    }

    #[test]
    fn section_content() {
        let wikipedia = w();
        let page = wikipedia.page_from_pageid("4138548".to_owned());
        assert!(page.get_section_content("Examples").unwrap().unwrap()
                .contains("finance committee meeting"))
    }

    #[test]
    fn languages() {
        let languages = w().get_languages().unwrap();
        assert!(languages.contains(&("en".to_owned(), "English".to_owned())));
        assert!(languages.contains(&("es".to_owned(), "español".to_owned())));
    }
}
<|endoftext|>