<commit_before>use graphics::{DrawState, Transformed, rectangle};
use graphics::polygon::Polygon;
use graphics::line::Line;
use opengl_graphics::GlGraphics;
use piston::input::Key;
use rand::Rng;
use std::f64::consts::PI;

pub struct Spaceship {
    x: f64,
    y: f64,
    v: f64,
    v_theta: f64,
    theta: f64,
    accel: f64,
    reverse: f64,
    left: f64,
    right: f64,
    firing: bool,
    cooldown: f64,
}

const SPACESHIP_POINTS: [[f64; 2]; 3] = [
    [5.0, 7.0],
    [-5.0, 7.0],
    [0.0, -13.0],
];

impl Spaceship {
    pub fn new() -> Spaceship {
        return Spaceship{
            x: 100.0,
            y: 100.0,
            v: 0.0,
            v_theta: 0.0,
            theta: 0.0,
            accel: 0.0,
            reverse: 0.0,
            left: 0.0,
            right: 0.0,
            firing: false,
            cooldown: 0.0,
        };
    }

    pub fn handle_press(&mut self, key: Key) {
        match key {
            Key::Up => self.accel = 1.0,
            Key::Down => self.reverse = 1.0,
            Key::Left => self.left = 0.05,
            Key::Right => self.right = 0.05,
            Key::Space => self.firing = true,
            _ => (),
        }
    }

    pub fn handle_release(&mut self, key: Key) {
        match key {
            Key::Up => self.accel = 0.0,
            Key::Down => self.reverse = 0.0,
            Key::Left => self.left = 0.0,
            Key::Right => self.right = 0.0,
            Key::Space => self.firing = false,
            _ => (),
        }
    }

    pub fn draw(&mut self, color: [f32; 4], ds: &DrawState, t: [[f64; 3]; 2], gl: &mut GlGraphics) {
        Polygon::new(color).draw(
            &SPACESHIP_POINTS,
            ds,
            t
                .trans(self.x, self.y)
                .rot_rad(self.theta),
            gl,
        );
    }

    pub fn go(&mut self, dt: f64, x_max: f64, y_max: f64) {
        self.x = (self.x + self.v_theta.sin()*self.v*dt + x_max) % x_max;
        self.y = (self.y - self.v_theta.cos()*self.v*dt + y_max) % y_max;
    }

    pub fn accelerate(&mut self, dt: f64) {
        let net_accel = (self.accel - self.reverse)*dt*100.0;
        let dx = self.v_theta.sin()*self.v;
        let dy = -self.v_theta.cos()*self.v;
        let new_dx = dx + self.theta.sin()*net_accel;
        let new_dy = dy - self.theta.cos()*net_accel;
        self.v = (new_dx*new_dx+new_dy*new_dy).sqrt().min(200.0).max(-200.0);
        self.v_theta = new_dx.atan2(-new_dy);
    }

    pub fn turn(&mut self, dt: f64) {
        self.theta += (self.right - self.left)*dt*100.0;
    }

    pub fn cooldown(&mut self, dt: f64) {
        self.cooldown = (self.cooldown - dt).max(0.0);
    }

    pub fn ready_to_fire(&self) -> bool {
        return self.cooldown == 0.0;
    }

    pub fn is_firing(&self) -> bool {
        return self.firing;
    }

    pub fn fire(&mut self, bullets: &mut Vec<Bullet>) {
        self.cooldown = 0.5;
        bullets.push(Bullet::new(self.x, self.y, self.theta));
    }
}

pub struct Bullet {
    x: f64,
    y: f64,
    theta: f64,
    distance: f64,
}

impl Bullet {
    fn new(x: f64, y: f64, theta: f64) -> Bullet {
        return Bullet{
            x: x,
            y: y,
            theta: theta,
            distance: 0.0,
        };
    }

    pub fn draw(&self, color: [f32; 4], t: [[f64; 3]; 2], gl: &mut GlGraphics) {
        rectangle(color, rectangle::square(self.x, self.y, 2.0), t, gl);
    }

    pub fn go(&mut self, dt: f64, x_max: f64, y_max: f64) {
        let v = 100.0;
        self.x = (self.x + self.theta.sin()*v*dt + x_max) % x_max;
        self.y = (self.y - self.theta.cos()*v*dt + y_max) % y_max;
        self.distance += v*dt;
    }

    pub fn is_alive(&self) -> bool {
        return self.distance < 100.0;
    }
}

const ASTROID_BORDER: [[f64; 4]; 4] = [
    [-5.0, 0.0, 0.0, 5.0],
    [0.0, 5.0, 5.0, 0.0],
    [5.0, 0.0, 0.0, -5.0],
    [0.0, -5.0, -5.0, 0.0],
];

pub struct Astroid {
    x: f64,
    y: f64,
    v: f64,
    theta: f64,
}

impl Astroid {
    pub fn new<R: Rng>(rng: &mut R) -> Astroid {
        return Astroid {
            x: rng.gen_range(0.0, 100.0),
            y: rng.gen_range(0.0, 100.0),
            v: rng.gen_range(40.0, 60.0),
            theta: rng.gen_range(0.0, 2.0*PI),
        }
    }

    pub fn draw(&self, color: [f32; 4], ds: &DrawState, t: [[f64; 3]; 2], gl: &mut GlGraphics) {
        let line_info = Line::new(color, 1.0);
        for line_points in ASTROID_BORDER.iter() {
            line_info.draw(*line_points, ds, t.trans(self.x, self.y), gl);
        }
    }

    pub fn go(&mut self, dt: f64, x_max: f64, y_max: f64) {
        self.x = (self.x + self.theta.sin()*self.v*dt + x_max) % x_max;
        self.y = (self.y - self.theta.cos()*self.v*dt + y_max) % y_max;
    }
}<commit_msg>Added three different astroid sizes<commit_after>use graphics::{DrawState, Transformed, rectangle};
use graphics::polygon::Polygon;
use graphics::line::Line;
use opengl_graphics::GlGraphics;
use piston::input::Key;
use rand::Rng;
use std::f64::consts::PI;

pub struct Spaceship {
    x: f64,
    y: f64,
    v: f64,
    v_theta: f64,
    theta: f64,
    accel: f64,
    reverse: f64,
    left: f64,
    right: f64,
    firing: bool,
    cooldown: f64,
}

const SPACESHIP_POINTS: [[f64; 2]; 3] = [
    [5.0, 7.0],
    [-5.0, 7.0],
    [0.0, -13.0],
];

impl Spaceship {
    pub fn new() -> Spaceship {
        return Spaceship{
            x: 100.0,
            y: 100.0,
            v: 0.0,
            v_theta: 0.0,
            theta: 0.0,
            accel: 0.0,
            reverse: 0.0,
            left: 0.0,
            right: 0.0,
            firing: false,
            cooldown: 0.0,
        };
    }

    pub fn handle_press(&mut self, key: Key) {
        match key {
            Key::Up => self.accel = 1.0,
            Key::Down => self.reverse = 1.0,
            Key::Left => self.left = 0.05,
            Key::Right => self.right = 0.05,
            Key::Space => self.firing = true,
            _ => (),
        }
    }

    pub fn handle_release(&mut self, key: Key) {
        match key {
            Key::Up => self.accel = 0.0,
            Key::Down => self.reverse = 0.0,
            Key::Left => self.left = 0.0,
            Key::Right => self.right = 0.0,
            Key::Space => self.firing = false,
            _ => (),
        }
    }

    pub fn draw(&mut self, color: [f32; 4], ds: &DrawState, t: [[f64; 3]; 2], gl: &mut GlGraphics) {
        Polygon::new(color).draw(
            &SPACESHIP_POINTS,
            ds,
            t
                .trans(self.x, self.y)
                .rot_rad(self.theta),
            gl,
        );
    }

    pub fn go(&mut self, dt: f64, x_max: f64, y_max: f64) {
        self.x = (self.x + self.v_theta.sin()*self.v*dt + x_max) % x_max;
        self.y = (self.y - self.v_theta.cos()*self.v*dt + y_max) % y_max;
    }

    pub fn accelerate(&mut self, dt: f64) {
        let net_accel = (self.accel - self.reverse)*dt*100.0;
        let dx = self.v_theta.sin()*self.v;
        let dy = -self.v_theta.cos()*self.v;
        let new_dx = dx + self.theta.sin()*net_accel;
        let new_dy = dy - self.theta.cos()*net_accel;
        self.v = (new_dx*new_dx+new_dy*new_dy).sqrt().min(200.0).max(-200.0);
        self.v_theta = new_dx.atan2(-new_dy);
    }

    pub fn turn(&mut self, dt: f64) {
        self.theta += (self.right - self.left)*dt*100.0;
    }

    pub fn cooldown(&mut self, dt: f64) {
        self.cooldown = (self.cooldown - dt).max(0.0);
    }

    pub fn ready_to_fire(&self) -> bool {
        return self.cooldown == 0.0;
    }

    pub fn is_firing(&self) -> bool {
        return self.firing;
    }

    pub fn fire(&mut self, bullets: &mut Vec<Bullet>) {
        self.cooldown = 0.5;
        bullets.push(Bullet::new(self.x, self.y, self.theta));
    }
}

pub struct Bullet {
    x: f64,
    y: f64,
    theta: f64,
    distance: f64,
}

impl Bullet {
    fn new(x: f64, y: f64, theta: f64) -> Bullet {
        return Bullet{
            x: x,
            y: y,
            theta: theta,
            distance: 0.0,
        };
    }

    pub fn draw(&self, color: [f32; 4], t: [[f64; 3]; 2], gl: &mut GlGraphics) {
        rectangle(color, rectangle::square(self.x, self.y, 2.0), t, gl);
    }

    pub fn go(&mut self, dt: f64, x_max: f64, y_max: f64) {
        let v = 100.0;
        self.x = (self.x + self.theta.sin()*v*dt + x_max) % x_max;
        self.y = (self.y - self.theta.cos()*v*dt + y_max) % y_max;
        self.distance += v*dt;
    }

    pub fn is_alive(&self) -> bool {
        return self.distance < 100.0;
    }
}

const LARGE_ASTROID_BORDER: [[f64; 4]; 4] = [
    [-15.0, 0.0, 0.0, 15.0],
    [0.0, 15.0, 15.0, 0.0],
    [15.0, 0.0, 0.0, -15.0],
    [0.0, -15.0, -15.0, 0.0],
];

const ASTROID_BORDER: [[f64; 4]; 4] = [
    [-10.0, 0.0, 0.0, 10.0],
    [0.0, 10.0, 10.0, 0.0],
    [10.0, 0.0, 0.0, -10.0],
    [0.0, -10.0, -10.0, 0.0],
];

const SMALL_ASTROID_BORDER: [[f64; 4]; 4] = [
    [-5.0, 0.0, 0.0, 5.0],
    [0.0, 5.0, 5.0, 0.0],
    [5.0, 0.0, 0.0, -5.0],
    [0.0, -5.0, -5.0, 0.0],
];

const ASTROID_BORDERS: [&'static[[f64; 4]; 4]; 3] = [&LARGE_ASTROID_BORDER, &ASTROID_BORDER, &SMALL_ASTROID_BORDER];

pub struct Astroid {
    x: f64,
    y: f64,
    v: f64,
    theta: f64,
    border: &'static[[f64; 4]; 4],
}

impl Astroid {
    pub fn new<R: Rng>(rng: &mut R) -> Astroid {
        use rand::sample;
        return Astroid {
            x: rng.gen_range(0.0, 100.0),
            y: rng.gen_range(0.0, 100.0),
            v: rng.gen_range(40.0, 60.0),
            theta: rng.gen_range(0.0, 2.0*PI),
            border: sample(rng, ASTROID_BORDERS.iter(), 1)[0],
        }
    }

    pub fn draw(&self, color: [f32; 4], ds: &DrawState, t: [[f64; 3]; 2], gl: &mut GlGraphics) {
        let line_info = Line::new(color, 0.5);
        for line_points in self.border.iter() {
            line_info.draw(*line_points, ds, t.trans(self.x, self.y), gl);
        }
    }

    pub fn go(&mut self, dt: f64, x_max: f64, y_max: f64) {
        self.x = (self.x + self.theta.sin()*self.v*dt + x_max) % x_max;
        self.y = (self.y - self.theta.cos()*self.v*dt + y_max) % y_max;
    }
}<|endoftext|>


<commit_before>/*
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

use fnv::FnvHashSet;
use graphql_ir::{Program, ValidationResult};
use graphql_transforms::{
    apply_fragment_arguments, client_extensions, defer_stream, flatten, generate_id_field,
    generate_typename, handle_field_transform, inline_fragments, mask, remove_base_fragments,
    skip_client_extensions, skip_redundant_nodes, skip_unreachable_node, transform_connections,
    ConnectionInterface,
};
use interner::StringKey;

pub struct Programs<'schema> {
    pub source: Program<'schema>,
    pub reader: Program<'schema>,
    pub normalization: Program<'schema>,
    pub operation_text: Program<'schema>,
}

pub fn apply_transforms<'schema, TConnectionInterface: ConnectionInterface>(
    program: Program<'schema>,
    base_fragment_names: &FnvHashSet<StringKey>,
    connection_interface: &TConnectionInterface,
) -> ValidationResult<Programs<'schema>> {
    // common
    //  |- reader
    //  |- operation
    //     |- normalization
    //     |- operation_text
    let common_program = apply_common_transforms(&program, connection_interface)?;
    let reader_program = apply_reader_transforms(&common_program, base_fragment_names);
    let operation_program = apply_operation_transforms(&common_program)?;
    let normalization_program = apply_normalization_transforms(&operation_program);
    let operation_text_program = apply_operation_text_transforms(&operation_program);

    Ok(Programs {
        source: program,
        reader: reader_program,
        normalization: normalization_program,
        operation_text: operation_text_program,
    })
}

/// Applies transforms that apply to every output.
fn apply_common_transforms<'schema, TConnectionInterface: ConnectionInterface>(
    program: &Program<'schema>,
    connection_interface: &TConnectionInterface,
) -> ValidationResult<Program<'schema>> {
    // JS compiler
    // - DisallowIdAsAlias
    // - ConnectionTransform
    // - RelayDirectiveTransform
    // - MaskTransform
    // - MatchTransform
    // - RefetchableFragmentTransform
    // - DeferStreamTransform

    let program = transform_connections(program, connection_interface);
    let program = defer_stream(&program)?;
    let program = mask(&program);

    Ok(program)
}

/// Applies transforms only for generated reader code.
/// Corresponds to the "fragment transforms" in the JS compiler.
fn apply_reader_transforms<'schema>(
    program: &Program<'schema>,
    base_fragment_names: &FnvHashSet<StringKey>,
) -> Program<'schema> {
    // JS compiler
    // - ClientExtensionsTransform
    // - FieldHandleTransform
    // - InlineDataFragmentTransform
    // - FlattenTransform, flattenAbstractTypes: true
    // - SkipRedundantNodesTransform
    let program = handle_field_transform(&program);
    let program = remove_base_fragments(&program, base_fragment_names);
    let program = flatten(&program, true);
    client_extensions(&program)
}

/// Applies transforms that apply to all operation artifacts.
/// Corresponds to the "query transforms" in the JS compiler.
fn apply_operation_transforms<'schema>(
    program: &Program<'schema>,
) -> ValidationResult<Program<'schema>> {
    // JS compiler
    // - ValidateUnusedVariablesTransform
    // - ApplyFragmentArgumentTransform
    // - ValidateGlobalVariablesTransform
    // - GenerateIDFieldTransform
    // - TestOperationTransform
    let program = apply_fragment_arguments(&program)?;
    let program = generate_id_field(&program);

    Ok(program)
}

/// After the operation transforms, this applies further transforms that only
/// apply to the generated normalization code.
///
/// Corresponds to the "codegen transforms" in the JS compiler
fn apply_normalization_transforms<'schema>(program: &Program<'schema>) -> Program<'schema> {
    // JS compiler
    // - SkipUnreachableNodeTransform
    // - SplitModuleImportTransform
    // - InlineFragmentsTransform
    // - ClientExtensionsTransform
    // - FlattenTransform, flattenAbstractTypes: true
    // - SkipRedundantNodesTransform
    // - GenerateTypeNameTransform
    // - ValidateServerOnlyDirectivesTransform

    let program = skip_unreachable_node(&program);
    let program = inline_fragments(&program);
    let program = flatten(&program, true);
    let program = skip_redundant_nodes(&program);
    let program = client_extensions(&program);
    generate_typename(&program)
}

/// After the operation transforms, this applies further transforms that only
/// apply to the printed operation text.
///
/// Corresponds to the "print transforms" in the JS compiler
fn apply_operation_text_transforms<'schema>(program: &Program<'schema>) -> Program<'schema> {
    // JS compiler
    // - ClientExtensionsTransform
    // - SkipClientExtensionsTransform
    // - SkipUnreachableNodeTransform
    // - FlattenTransform, flattenAbstractTypes: false
    // - GenerateTypeNameTransform
    // - SkipHandleFieldTransform
    // - FilterDirectivesTransform
    // - SkipUnusedVariablesTransform
    // - ValidateRequiredArgumentsTransform

    let program = skip_client_extensions(&program);
    let program = skip_unreachable_node(&program);
    let program = flatten(&program, false);
    generate_typename(&program)
}
<commit_msg>run `defer_stream` last in common transforms (as in JS)<commit_after>/*
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

use fnv::FnvHashSet;
use graphql_ir::{Program, ValidationResult};
use graphql_transforms::{
    apply_fragment_arguments, client_extensions, defer_stream, flatten, generate_id_field,
    generate_typename, handle_field_transform, inline_fragments, mask, remove_base_fragments,
    skip_client_extensions, skip_redundant_nodes, skip_unreachable_node, transform_connections,
    ConnectionInterface,
};
use interner::StringKey;

pub struct Programs<'schema> {
    pub source: Program<'schema>,
    pub reader: Program<'schema>,
    pub normalization: Program<'schema>,
    pub operation_text: Program<'schema>,
}

pub fn apply_transforms<'schema, TConnectionInterface: ConnectionInterface>(
    program: Program<'schema>,
    base_fragment_names: &FnvHashSet<StringKey>,
    connection_interface: &TConnectionInterface,
) -> ValidationResult<Programs<'schema>> {
    // common
    //  |- reader
    //  |- operation
    //     |- normalization
    //     |- operation_text
    let common_program = apply_common_transforms(&program, connection_interface)?;
    let reader_program = apply_reader_transforms(&common_program, base_fragment_names);
    let operation_program = apply_operation_transforms(&common_program)?;
    let normalization_program = apply_normalization_transforms(&operation_program);
    let operation_text_program = apply_operation_text_transforms(&operation_program);

    Ok(Programs {
        source: program,
        reader: reader_program,
        normalization: normalization_program,
        operation_text: operation_text_program,
    })
}

/// Applies transforms that apply to every output.
fn apply_common_transforms<'schema, TConnectionInterface: ConnectionInterface>(
    program: &Program<'schema>,
    connection_interface: &TConnectionInterface,
) -> ValidationResult<Program<'schema>> {
    // JS compiler
    // - DisallowIdAsAlias
    // - ConnectionTransform
    // - RelayDirectiveTransform
    // - MaskTransform
    // - MatchTransform
    // - RefetchableFragmentTransform
    // - DeferStreamTransform

    let program = transform_connections(program, connection_interface);
    let program = mask(&program);
    let program = defer_stream(&program)?;

    Ok(program)
}

/// Applies transforms only for generated reader code.
/// Corresponds to the "fragment transforms" in the JS compiler.
fn apply_reader_transforms<'schema>(
    program: &Program<'schema>,
    base_fragment_names: &FnvHashSet<StringKey>,
) -> Program<'schema> {
    // JS compiler
    // - ClientExtensionsTransform
    // - FieldHandleTransform
    // - InlineDataFragmentTransform
    // - FlattenTransform, flattenAbstractTypes: true
    // - SkipRedundantNodesTransform
    let program = handle_field_transform(&program);
    let program = remove_base_fragments(&program, base_fragment_names);
    let program = flatten(&program, true);
    client_extensions(&program)
}

/// Applies transforms that apply to all operation artifacts.
/// Corresponds to the "query transforms" in the JS compiler.
fn apply_operation_transforms<'schema>(
    program: &Program<'schema>,
) -> ValidationResult<Program<'schema>> {
    // JS compiler
    // - ValidateUnusedVariablesTransform
    // - ApplyFragmentArgumentTransform
    // - ValidateGlobalVariablesTransform
    // - GenerateIDFieldTransform
    // - TestOperationTransform
    let program = apply_fragment_arguments(&program)?;
    let program = generate_id_field(&program);

    Ok(program)
}

/// After the operation transforms, this applies further transforms that only
/// apply to the generated normalization code.
///
/// Corresponds to the "codegen transforms" in the JS compiler
fn apply_normalization_transforms<'schema>(program: &Program<'schema>) -> Program<'schema> {
    // JS compiler
    // - SkipUnreachableNodeTransform
    // - SplitModuleImportTransform
    // - InlineFragmentsTransform
    // - ClientExtensionsTransform
    // - FlattenTransform, flattenAbstractTypes: true
    // - SkipRedundantNodesTransform
    // - GenerateTypeNameTransform
    // - ValidateServerOnlyDirectivesTransform

    let program = skip_unreachable_node(&program);
    let program = inline_fragments(&program);
    let program = flatten(&program, true);
    let program = skip_redundant_nodes(&program);
    let program = client_extensions(&program);
    generate_typename(&program)
}

/// After the operation transforms, this applies further transforms that only
/// apply to the printed operation text.
///
/// Corresponds to the "print transforms" in the JS compiler
fn apply_operation_text_transforms<'schema>(program: &Program<'schema>) -> Program<'schema> {
    // JS compiler
    // - ClientExtensionsTransform
    // - SkipClientExtensionsTransform
    // - SkipUnreachableNodeTransform
    // - FlattenTransform, flattenAbstractTypes: false
    // - GenerateTypeNameTransform
    // - SkipHandleFieldTransform
    // - FilterDirectivesTransform
    // - SkipUnusedVariablesTransform
    // - ValidateRequiredArgumentsTransform

    let program = skip_client_extensions(&program);
    let program = skip_unreachable_node(&program);
    let program = flatten(&program, false);
    generate_typename(&program)
}
<|endoftext|>


<commit_before>use super::MaxPQ;

const INITIAL_PRIORITY_QUEUE_CAPACITY: usize = 512;

pub struct BinaryHeapPQ<Key> {
    pq: Vec<Option<Key>>,
    n: usize
}

impl<Key: PartialOrd> BinaryHeapPQ<Key> {
    pub fn with_capacity(capacity: usize) -> BinaryHeapPQ<Key> {
        let mut pq = Vec::with_capacity(capacity + 1);
        unsafe {
            pq.set_len(capacity + 1);
        }
        BinaryHeapPQ {
            pq: pq,
            n: 0
        }
    }

    fn swim(&mut self, k: usize) {
        let mut k = k;
        while k > 1 && self.pq[k/2] < self.pq[k] {
            self.pq.swap(k, k/2);
            k = k/2;
        }
    }

    fn sink(&mut self, k: usize) {
        let mut k = k;
        while 2*k <= self.n {
            let mut j = 2*k;
            if j < self.n && self.pq[j] < self.pq[j+1] {
                j += 1;
            }
            if self.pq[k] >= self.pq[j] {
                break;
            }
            self.pq.swap(k, j);
            k = j;
        }
    }
}

impl<Key: PartialOrd>  MaxPQ<Key> for BinaryHeapPQ<Key> {
    /// create an empty priority queue
    fn new() -> Self {
        BinaryHeapPQ::with_capacity(INITIAL_PRIORITY_QUEUE_CAPACITY)
    }
    /// create a priority queue with given keys
    fn from_vec(a: Vec<Key>) -> Self {
        let mut pq = Self::new();
        let len = a.len();
        pq.pq.move_from(a.map_in_place(Some), 0, len);
        pq
    }
    /// insert a key into the priority queue
    fn insert(&mut self, x: Key) {
        self.n += 1;
        let n = self.n;
        self.pq[n] = Some(x);
        self.swim(n);
    }
    /// return and remove the largest key
    fn del_max(&mut self) -> Option<Key> {
        let max = self.pq[1].take();
        self.pq.swap(1, self.n);
        self.n -= 1;
        self.sink(1);
        max
    }
    /// is the priority queue empty?
    #[inline]
    fn is_empty(&self) -> bool {
        self.n == 0
    }
    /// return the largest key
    fn max(&self) -> Option<&Key> {
        self.pq[1].as_ref()
    }
    /// number of entries in the priority queue
    fn size(&self) -> usize {
        self.n
    }
}

#[test]
fn test_binary_priority_queue() {
    let mut pq: BinaryHeapPQ<char> = MaxPQ::new();

    pq.insert('P');
    pq.insert('Q');
    pq.insert('E');

    assert_eq!(pq.size(), 3);
    println!("==> {:?}", pq.pq);
    assert_eq!(pq.del_max().unwrap(), 'Q');
    assert_eq!(pq.size(), 2);

    pq.insert('X');
    pq.insert('A');
    pq.insert('M');

    assert_eq!(pq.del_max().unwrap(), 'X');

    pq.insert('P');
    pq.insert('L');
    pq.insert('E');

    assert_eq!(pq.del_max().unwrap(), 'P');

    assert_eq!(pq.size(), 6);
}
<commit_msg>priority_queues/binary_heaps: rename BinaryHeapPQ to BinaryHeapMaxPQ<commit_after>use super::MaxPQ;

const INITIAL_PRIORITY_QUEUE_CAPACITY: usize = 512;

pub struct BinaryHeapMaxPQ<Key> {
    pq: Vec<Option<Key>>,
    n: usize
}

impl<Key: PartialOrd> BinaryHeapMaxPQ<Key> {
    pub fn with_capacity(capacity: usize) -> BinaryHeapMaxPQ<Key> {
        let mut pq = Vec::with_capacity(capacity + 1);
        unsafe {
            pq.set_len(capacity + 1);
        }
        BinaryHeapMaxPQ {
            pq: pq,
            n: 0
        }
    }

    fn swim(&mut self, k: usize) {
        let mut k = k;
        while k > 1 && self.pq[k/2] < self.pq[k] {
            self.pq.swap(k, k/2);
            k = k/2;
        }
    }

    fn sink(&mut self, k: usize) {
        let mut k = k;
        while 2*k <= self.n {
            let mut j = 2*k;
            if j < self.n && self.pq[j] < self.pq[j+1] {
                j += 1;
            }
            if self.pq[k] >= self.pq[j] {
                break;
            }
            self.pq.swap(k, j);
            k = j;
        }
    }
}

impl<Key: PartialOrd>  MaxPQ<Key> for BinaryHeapMaxPQ<Key> {
    /// create an empty priority queue
    fn new() -> Self {
        BinaryHeapMaxPQ::with_capacity(INITIAL_PRIORITY_QUEUE_CAPACITY)
    }
    /// create a priority queue with given keys
    fn from_vec(a: Vec<Key>) -> Self {
        let mut pq = Self::new();
        let len = a.len();
        pq.pq.move_from(a.map_in_place(Some), 0, len);
        pq
    }
    /// insert a key into the priority queue
    fn insert(&mut self, x: Key) {
        self.n += 1;
        let n = self.n;
        self.pq[n] = Some(x);
        self.swim(n);
    }
    /// return and remove the largest key
    fn del_max(&mut self) -> Option<Key> {
        let max = self.pq[1].take();
        self.pq.swap(1, self.n);
        self.n -= 1;
        self.sink(1);
        max
    }
    /// is the priority queue empty?
    #[inline]
    fn is_empty(&self) -> bool {
        self.n == 0
    }
    /// return the largest key
    fn max(&self) -> Option<&Key> {
        self.pq[1].as_ref()
    }
    /// number of entries in the priority queue
    fn size(&self) -> usize {
        self.n
    }
}

#[test]
fn test_binary_priority_queue() {
    let mut pq: BinaryHeapMaxPQ<char> = MaxPQ::new();

    pq.insert('P');
    pq.insert('Q');
    pq.insert('E');

    assert_eq!(pq.size(), 3);
    println!("==> {:?}", pq.pq);
    assert_eq!(pq.del_max().unwrap(), 'Q');
    assert_eq!(pq.size(), 2);

    pq.insert('X');
    pq.insert('A');
    pq.insert('M');

    assert_eq!(pq.del_max().unwrap(), 'X');

    pq.insert('P');
    pq.insert('L');
    pq.insert('E');

    assert_eq!(pq.del_max().unwrap(), 'P');

    assert_eq!(pq.size(), 6);
}

#[test]
fn test_empty() {
    let mut pq: BinaryHeapMaxPQ<char> = MaxPQ::new();
    pq.insert('P');
    assert_eq!(pq.is_empty(), false);
    assert_eq!(pq.size(), 1);
    pq.del_max();
    assert_eq!(pq.size(), 0);
    assert_eq!(pq.is_empty(), true);
}
<|endoftext|>


<commit_before>extern crate glob;

use std::path::{Path,PathBuf};

use self::glob::{Pattern,PatternError};

pub struct NotificationFilter {
    cwd: PathBuf,
    filters: Vec<Pattern>,
    ignores: Vec<Pattern>
}

impl NotificationFilter {
    pub fn new(current_dir: &Path) -> NotificationFilter {
        NotificationFilter {
            cwd: current_dir.to_path_buf(),
            filters: vec![],
            ignores: vec![]
        }
    }

    pub fn add_extension(&mut self, extension: &str) -> Result<(), PatternError> {
        let mut pattern = String::new();

        for ext in extension.split(",") {
            pattern.clear();
            pattern.push_str("*");

            if !ext.starts_with(".") {
                pattern.push_str(".");
            }
            pattern.push_str(ext);

            try!(self.add_filter(&pattern));
        }

        Ok(())
    }

    pub fn add_filter(&mut self, pattern: &str) -> Result<(), PatternError> {
        let compiled = try!(self.pattern_for(pattern));
        self.filters.push(compiled.clone());

        Ok(())
    }

    pub fn add_ignore(&mut self, pattern: &str) -> Result<(), PatternError> {
        let compiled = try!(self.pattern_for(pattern));
        self.ignores.push(compiled.clone());

        Ok(())
    }

    fn pattern_for(&self, p: &str) -> Result<Pattern, PatternError> {
        let mut path = PathBuf::from(p);
        if path.is_relative() {
            path = self.cwd.join(path.as_path());
        }

        if let Ok(metadata) = path.metadata() {
            if metadata.is_dir() {
                path = path.join("*");
            }
        }

        Pattern::new(path.to_str().unwrap())
    }

    pub fn is_excluded(&self, path: &Path) -> bool {
        let path_as_str = path.to_str().unwrap();

        for pattern in &self.ignores {
            if pattern.matches(path_as_str) {
                return true;
            }
        }

        for pattern in &self.filters {
            if pattern.matches(path_as_str) {
                return false;
            }
        }

        self.filters.len() > 0
    }
}
<commit_msg>Remove unnecessary clone<commit_after>extern crate glob;

use std::path::{Path,PathBuf};

use self::glob::{Pattern,PatternError};

pub struct NotificationFilter {
    cwd: PathBuf,
    filters: Vec<Pattern>,
    ignores: Vec<Pattern>
}

impl NotificationFilter {
    pub fn new(current_dir: &Path) -> NotificationFilter {
        NotificationFilter {
            cwd: current_dir.to_path_buf(),
            filters: vec![],
            ignores: vec![]
        }
    }

    pub fn add_extension(&mut self, extension: &str) -> Result<(), PatternError> {
        let mut pattern = String::new();

        for ext in extension.split(",") {
            pattern.clear();
            pattern.push_str("*");

            if !ext.starts_with(".") {
                pattern.push_str(".");
            }
            pattern.push_str(ext);

            try!(self.add_filter(&pattern));
        }

        Ok(())
    }

    pub fn add_filter(&mut self, pattern: &str) -> Result<(), PatternError> {
        let compiled = try!(self.pattern_for(pattern));
        self.filters.push(compiled);

        Ok(())
    }

    pub fn add_ignore(&mut self, pattern: &str) -> Result<(), PatternError> {
        let compiled = try!(self.pattern_for(pattern));
        self.ignores.push(compiled);

        Ok(())
    }

    fn pattern_for(&self, p: &str) -> Result<Pattern, PatternError> {
        let mut path = PathBuf::from(p);
        if path.is_relative() {
            path = self.cwd.join(path.as_path());
        }

        if let Ok(metadata) = path.metadata() {
            if metadata.is_dir() {
                path = path.join("*");
            }
        }

        Pattern::new(path.to_str().unwrap())
    }

    pub fn is_excluded(&self, path: &Path) -> bool {
        let path_as_str = path.to_str().unwrap();

        for pattern in &self.ignores {
            if pattern.matches(path_as_str) {
                return true;
            }
        }

        for pattern in &self.filters {
            if pattern.matches(path_as_str) {
                return false;
            }
        }

        self.filters.len() > 0
    }
}
<|endoftext|>


<commit_before>extern crate objectify_html;

use objectify_html::*;
use std::env;

fn main() {
    let args: Vec<_> = env::args().collect();
    let mut compile_option = String::new();
    let mut build_option = String::new();
    let mut add_c_option = false;
    let mut add_b_option = false;

    for i in args {
        if add_c_option {
            compile_option = i.clone();
            add_c_option = false;
        } else if add_b_option {
            build_option = i.clone();
            add_b_option = false;
        }

        if i == "-c" {
            add_c_option = true;
        } else if i == "-b" {
            add_b_option = true;
        }
    }

    // If a compile_option was not supplied, we can't continue.
    if compile_option == "" {
        println!("No compile (-c) option was supplied! Aborting.");
    } else {
        if build_option == "" {
            build_option = ".build".to_string();
        }

        let main_data = get_file_contents(&*compile_option); // :String

        let data_to_write = inline_replace_html_file(main_data, build_option);

        println!("{}", data_to_write);
    }
}

///////////////////////////////////////
/////////////// TESTS ////////////////
//////////////////////////////////////

#[cfg(test)]
mod test {
    use objectify_html::*;

    #[test]
    fn it_works() {
    }

    #[test]
    fn test_get_attribute() {
        let attribute = get_attribute("
".to_string(), "id".to_string(), 0);

        if attribute != "Test" {
            assert!(false);
        }
    }

    #[test]
    fn test_get_tag_name() {
        let tag_name = get_tag_name("
".to_string(), 0);

        if tag_name != "div" {
            assert!(false);
        }
    }

    #[test]
    fn test_get_substrings_from_delims() {
        let substrings = get_substrings_from_delims("[foo][bar]".to_string(), '[', ']');

        if substrings[0] != "foo".to_string() || substrings[1] != "bar".to_string() {
            assert!(false);
        }

        if get_substrings_from_delims("[foo][bar]".to_string(), 'X', 'Z').len() != 0 {
            assert!(false);
        }
    }

    #[test]
    fn test_get_params() {
        let params = get_params("
".to_string(), 0);

        if params.children[1].param_name != "@p1@".to_string() || params.children[1].param_content != "foo".to_string() {
            assert!(false);
        }

        if params.children[2].param_name != "@p2@".to_string() || params.children[2].param_content != "bar".to_string() {
            assert!(false);
        }
    }

    #[test]
    fn test_get_non_existing_params() {
        let params = get_params("div id=\"thing\"/>".to_string(), 0);

        if params.children.len() != 1 {
            assert!(false);
        }
    }

    #[test]
    fn test_get_first_location_of_string() {
        let loc = get_first_location_of_string("The quick brown fox jumped.".to_string(), "brown".to_string());

        if loc != 10 {
            assert!(false);
        }

        let loc2 = get_first_location_of_string("The quick brown fox jumped.".to_string(), "Hello".to_string());
        let loc3 = get_first_location_of_string("".to_string(), "Thing".to_string());

        if loc2 != -1 && loc3 != -1 {
            assert!(false);
        }
    }

    #[test]
    fn test_insert_parameters() {
        let string_to_test = "
".to_string();
        let params = ParamContainer{children: vec![ParamChild{param_name: "@p1@".to_string(), param_content: "foo".to_string()}]};

        let return_stuff = insert_parameters(string_to_test, params);
        println!("Return value = {}", return_stuff);

        if return_stuff != "
" {
            assert!(false);
        }
    }

    #[test]
    fn test_get_total_tag_length() {
        let string_to_test = "
".to_string();
        let return_number = get_total_tag_length(string_to_test, 0);

        if return_number != 15 {
            assert!(false);
        }
    }

    #[test]
    fn test_get_replacement_id() {
        let string_to_test = "
".to_string();
        let return_data = get_replacement_id(string_to_test.clone(), 0);
        let return_data_2 = get_replacement_id(string_to_test.clone(), 1);

        if return_data != "foo".to_string() && return_data_2 != "foo".to_string() {
            assert!(false);
        }
    }

    #[test]
    fn test_get_file_contents() {
        let file = "test.html".to_string();
        let proper_response = "\n  \n    <include object=\"test\"/>\n  \n\n".to_string();
        let return_data = get_file_contents(&*file);

        if return_data != proper_response {
            assert!(false);
        }
    }

    #[test]
    #[should_panic]
    fn test_get_non_existing_file_contents() {
        get_file_contents("a-non-existing-file.txt");
    }

    #[test]
    fn test_remove_substring_at_pos() {
        let string_to_test = "Hello world. Testing 1 2 3.".to_string();
        let expected_result = "Hell. Testing 1 2 3.".to_string();
        let result = remove_substring_at_pos(string_to_test, 4, 10);

        if result != expected_result {
            assert!(false);
        }
    }
}<commit_msg>Attempt to fix test coverage failure by removing module<commit_after>extern crate objectify_html;

use objectify_html::*;
use std::env;

fn main() {
    let args: Vec<_> = env::args().collect();
    let mut compile_option = String::new();
    let mut build_option = String::new();
    let mut add_c_option = false;
    let mut add_b_option = false;

    for i in args {
        if add_c_option {
            compile_option = i.clone();
            add_c_option = false;
        } else if add_b_option {
            build_option = i.clone();
            add_b_option = false;
        }

        if i == "-c" {
            add_c_option = true;
        } else if i == "-b" {
            add_b_option = true;
        }
    }

    // If a compile_option was not supplied, we can't continue.
    if compile_option == "" {
        println!("No compile (-c) option was supplied! Aborting.");
    } else {
        if build_option == "" {
            build_option = ".build".to_string();
        }

        let main_data = get_file_contents(&*compile_option); // :String

        let data_to_write = inline_replace_html_file(main_data, build_option);

        println!("{}", data_to_write);
    }
}

///////////////////////////////////////
/////////////// TESTS ////////////////
//////////////////////////////////////

    #[test]
    fn it_works() {
    }

    #[test]
    fn test_get_attribute() {
        let attribute = get_attribute("
".to_string(), "id".to_string(), 0);

        if attribute != "Test" {
            assert!(false);
        }
    }

    #[test]
    fn test_get_tag_name() {
        let tag_name = get_tag_name("
".to_string(), 0);

        if tag_name != "div" {
            assert!(false);
        }
    }

    #[test]
    fn test_get_substrings_from_delims() {
        let substrings = get_substrings_from_delims("[foo][bar]".to_string(), '[', ']');

        if substrings[0] != "foo".to_string() || substrings[1] != "bar".to_string() {
            assert!(false);
        }

        if get_substrings_from_delims("[foo][bar]".to_string(), 'X', 'Z').len() != 0 {
            assert!(false);
        }
    }

    #[test]
    fn test_get_params() {
        let params = get_params("
".to_string(), 0);

        if params.children[1].param_name != "@p1@".to_string() || params.children[1].param_content != "foo".to_string() {
            assert!(false);
        }

        if params.children[2].param_name != "@p2@".to_string() || params.children[2].param_content != "bar".to_string() {
            assert!(false);
        }
    }

    #[test]
    fn test_get_non_existing_params() {
        let params = get_params("div id=\"thing\"/>".to_string(), 0);

        if params.children.len() != 1 {
            assert!(false);
        }
    }

    #[test]
    fn test_get_first_location_of_string() {
        let loc = get_first_location_of_string("The quick brown fox jumped.".to_string(), "brown".to_string());

        if loc != 10 {
            assert!(false);
        }

        let loc2 = get_first_location_of_string("The quick brown fox jumped.".to_string(), "Hello".to_string());
        let loc3 = get_first_location_of_string("".to_string(), "Thing".to_string());

        if loc2 != -1 && loc3 != -1 {
            assert!(false);
        }
    }

    #[test]
    fn test_insert_parameters() {
        let string_to_test = "
".to_string();
        let params = ParamContainer{children: vec![ParamChild{param_name: "@p1@".to_string(), param_content: "foo".to_string()}]};

        let return_stuff = insert_parameters(string_to_test, params);
        println!("Return value = {}", return_stuff);

        if return_stuff != "
" {
            assert!(false);
        }
    }

    #[test]
    fn test_get_total_tag_length() {
        let string_to_test = "
".to_string();
        let return_number = get_total_tag_length(string_to_test, 0);

        if return_number != 15 {
            assert!(false);
        }
    }

    #[test]
    fn test_get_replacement_id() {
        let string_to_test = "
".to_string();
        let return_data = get_replacement_id(string_to_test.clone(), 0);
        let return_data_2 = get_replacement_id(string_to_test.clone(), 1);

        if return_data != "foo".to_string() && return_data_2 != "foo".to_string() {
            assert!(false);
        }
    }

    #[test]
    fn test_get_file_contents() {
        let file = "test.html".to_string();
        let proper_response = "\n  \n    <include object=\"test\"/>\n  \n\n".to_string();
        let return_data = get_file_contents(&*file);

        if return_data != proper_response {
            assert!(false);
        }
    }

    #[test]
    #[should_panic]
    fn test_get_non_existing_file_contents() {
        get_file_contents("a-non-existing-file.txt");
    }

    #[test]
    fn test_remove_substring_at_pos() {
        let string_to_test = "Hello world. Testing 1 2 3.".to_string();
        let expected_result = "Hell. Testing 1 2 3.".to_string();
        let result = remove_substring_at_pos(string_to_test, 4, 10);

        if result != expected_result {
            assert!(false);
        }
    }<|endoftext|>


<commit_before>// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// This test case tests the incremental compilation hash (ICH) implementation
// for let expressions.

// The general pattern followed here is: Change one thing between rev1 and rev2
// and make sure that the hash has changed, then change nothing between rev2 and
// rev3 and make sure that the hash has not changed.

// compile-pass
// revisions: cfail1 cfail2 cfail3
// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans

#![allow(warnings)]
#![feature(rustc_attrs)]
#![crate_type="rlib"]

// Change Name -----------------------------------------------------------------
#[cfg(cfail1)]
pub fn change_name() {
    let _x = 2u64;
}

#[cfg(not(cfail1))]
#[rustc_clean(cfg="cfail2",
    except="HirBody,MirValidated,MirOptimized")]
#[rustc_clean(cfg="cfail3")]
pub fn change_name() {
    let _y = 2u64;
}

// Add Type --------------------------------------------------------------------
#[cfg(cfail1)]
pub fn add_type() {
    let _x = 2u32;
}

#[cfg(not(cfail1))]
#[rustc_clean(cfg="cfail2",
    except="HirBody,TypeckTables,MirValidated")]
#[rustc_clean(cfg="cfail3")]
pub fn add_type() {
    let _x: u32 = 2u32;
}

// Change Type -----------------------------------------------------------------
#[cfg(cfail1)]
pub fn change_type() {
    let _x: u64 = 2;
}

#[cfg(not(cfail1))]
#[rustc_clean(cfg="cfail2",
    except="HirBody,TypeckTables,MirValidated,MirOptimized")]
#[rustc_clean(cfg="cfail3")]
pub fn change_type() {
    let _x: u8 = 2;
}

// Change Mutability of Reference Type -----------------------------------------
#[cfg(cfail1)]
pub fn change_mutability_of_reference_type() {
    let _x: &u64;
}

#[cfg(not(cfail1))]
#[rustc_clean(cfg="cfail2",
    except="HirBody,TypeckTables,MirValidated")]
#[rustc_clean(cfg="cfail3")]
pub fn change_mutability_of_reference_type() {
    let _x: &mut u64;
}

// Change Mutability of Slot ---------------------------------------------------
#[cfg(cfail1)]
pub fn change_mutability_of_slot() {
    let mut _x: u64 = 0;
}

#[cfg(not(cfail1))]
#[rustc_clean(cfg="cfail2",
    except="HirBody,TypeckTables,MirValidated,MirOptimized")]
#[rustc_clean(cfg="cfail3")]
pub fn change_mutability_of_slot() {
    let _x: u64 = 0;
}

// Change Simple Binding to Pattern --------------------------------------------
#[cfg(cfail1)]
pub fn change_simple_binding_to_pattern() {
    let _x = (0u8, 'x');
}

#[cfg(not(cfail1))]
#[rustc_clean(cfg="cfail2",
    except="HirBody,TypeckTables,MirValidated,MirOptimized")]
#[rustc_clean(cfg="cfail3")]
pub fn change_simple_binding_to_pattern() {
    let (_a, _b) = (0u8, 'x');
}

// Change Name in Pattern ------------------------------------------------------
#[cfg(cfail1)]
pub fn change_name_in_pattern() {
    let (_a, _b) = (1u8, 'y');
}

#[cfg(not(cfail1))]
#[rustc_clean(cfg="cfail2",
    except="HirBody,MirValidated,MirOptimized")]
#[rustc_clean(cfg="cfail3")]
pub fn change_name_in_pattern() {
    let (_a, _c) = (1u8, 'y');
}

// Add `ref` in Pattern --------------------------------------------------------
#[cfg(cfail1)]
pub fn add_ref_in_pattern() {
    let (_a, _b) = (1u8, 'y');
}

#[cfg(not(cfail1))]
#[rustc_clean(cfg="cfail2",
    except="HirBody,TypeckTables,MirValidated,MirOptimized")]
#[rustc_clean(cfg="cfail3")]
pub fn add_ref_in_pattern() {
    let (ref _a, _b) = (1u8, 'y');
}

// Add `&` in Pattern ----------------------------------------------------------
#[cfg(cfail1)]
pub fn add_amp_in_pattern() {
    let (_a, _b) = (&1u8, 'y');
}

#[cfg(not(cfail1))]
#[rustc_clean(cfg="cfail2",
    except="HirBody,TypeckTables,MirValidated,MirOptimized")]
#[rustc_clean(cfg="cfail3")]
pub fn add_amp_in_pattern() {
    let (&_a, _b) = (&1u8, 'y');
}

// Change Mutability of Binding in Pattern -------------------------------------
#[cfg(cfail1)]
pub fn change_mutability_of_binding_in_pattern() {
    let (_a, _b) = (99u8, 'q');
}

#[cfg(not(cfail1))]
#[rustc_clean(cfg="cfail2",
    except="HirBody,TypeckTables,MirValidated,MirOptimized")]
#[rustc_clean(cfg="cfail3")]
pub fn change_mutability_of_binding_in_pattern() {
    let (mut _a, _b) = (99u8, 'q');
}

// Add Initializer -------------------------------------------------------------
#[cfg(cfail1)]
pub fn add_initializer() {
    let _x: i16;
}

#[cfg(not(cfail1))]
#[rustc_clean(cfg="cfail2",
    except="HirBody,TypeckTables,MirValidated,MirOptimized")]
#[rustc_clean(cfg="cfail3")]
pub fn add_initializer() {
    let _x: i16 = 3i16;
}

// Change Initializer ----------------------------------------------------------
#[cfg(cfail1)]
pub fn change_initializer() {
    let _x = 4u16;
}

#[cfg(not(cfail1))]
#[rustc_clean(cfg="cfail2",
    except="HirBody,MirValidated,MirOptimized")]
#[rustc_clean(cfg="cfail3")]
pub fn change_initializer() {
    let _x = 5u16;
}
<commit_msg>fix incremental test<commit_after>// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// This test case tests the incremental compilation hash (ICH) implementation
// for let expressions.

// The general pattern followed here is: Change one thing between rev1 and rev2
// and make sure that the hash has changed, then change nothing between rev2 and
// rev3 and make sure that the hash has not changed.

// compile-pass
// revisions: cfail1 cfail2 cfail3
// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans

#![allow(warnings)]
#![feature(rustc_attrs)]
#![crate_type="rlib"]

// Change Name -----------------------------------------------------------------
#[cfg(cfail1)]
pub fn change_name() {
    let _x = 2u64;
}

#[cfg(not(cfail1))]
#[rustc_clean(cfg="cfail2",
    except="HirBody,MirValidated,MirOptimized")]
#[rustc_clean(cfg="cfail3")]
pub fn change_name() {
    let _y = 2u64;
}

// Add Type --------------------------------------------------------------------
#[cfg(cfail1)]
pub fn add_type() {
    let _x = 2u32;
}

#[cfg(not(cfail1))]
#[rustc_clean(cfg="cfail2",
    except="HirBody,TypeckTables,MirValidated,MirOptimized")]
#[rustc_clean(cfg="cfail3")]
pub fn add_type() {
    let _x: u32 = 2u32;
}

// Change Type -----------------------------------------------------------------
#[cfg(cfail1)]
pub fn change_type() {
    let _x: u64 = 2;
}

#[cfg(not(cfail1))]
#[rustc_clean(cfg="cfail2",
    except="HirBody,TypeckTables,MirValidated,MirOptimized")]
#[rustc_clean(cfg="cfail3")]
pub fn change_type() {
    let _x: u8 = 2;
}

// Change Mutability of Reference Type -----------------------------------------
#[cfg(cfail1)]
pub fn change_mutability_of_reference_type() {
    let _x: &u64;
}

#[cfg(not(cfail1))]
#[rustc_clean(cfg="cfail2",
    except="HirBody,TypeckTables,MirValidated")]
#[rustc_clean(cfg="cfail3")]
pub fn change_mutability_of_reference_type() {
    let _x: &mut u64;
}

// Change Mutability of Slot ---------------------------------------------------
#[cfg(cfail1)]
pub fn change_mutability_of_slot() {
    let mut _x: u64 = 0;
}

#[cfg(not(cfail1))]
#[rustc_clean(cfg="cfail2",
    except="HirBody,TypeckTables,MirValidated,MirOptimized")]
#[rustc_clean(cfg="cfail3")]
pub fn change_mutability_of_slot() {
    let _x: u64 = 0;
}

// Change Simple Binding to Pattern --------------------------------------------
#[cfg(cfail1)]
pub fn change_simple_binding_to_pattern() {
    let _x = (0u8, 'x');
}

#[cfg(not(cfail1))]
#[rustc_clean(cfg="cfail2",
    except="HirBody,TypeckTables,MirValidated,MirOptimized")]
#[rustc_clean(cfg="cfail3")]
pub fn change_simple_binding_to_pattern() {
    let (_a, _b) = (0u8, 'x');
}

// Change Name in Pattern ------------------------------------------------------
#[cfg(cfail1)]
pub fn change_name_in_pattern() {
    let (_a, _b) = (1u8, 'y');
}

#[cfg(not(cfail1))]
#[rustc_clean(cfg="cfail2",
    except="HirBody,MirValidated,MirOptimized")]
#[rustc_clean(cfg="cfail3")]
pub fn change_name_in_pattern() {
    let (_a, _c) = (1u8, 'y');
}

// Add `ref` in Pattern --------------------------------------------------------
#[cfg(cfail1)]
pub fn add_ref_in_pattern() {
    let (_a, _b) = (1u8, 'y');
}

#[cfg(not(cfail1))]
#[rustc_clean(cfg="cfail2",
    except="HirBody,TypeckTables,MirValidated,MirOptimized")]
#[rustc_clean(cfg="cfail3")]
pub fn add_ref_in_pattern() {
    let (ref _a, _b) = (1u8, 'y');
}

// Add `&` in Pattern ----------------------------------------------------------
#[cfg(cfail1)]
pub fn add_amp_in_pattern() {
    let (_a, _b) = (&1u8, 'y');
}

#[cfg(not(cfail1))]
#[rustc_clean(cfg="cfail2",
    except="HirBody,TypeckTables,MirValidated,MirOptimized")]
#[rustc_clean(cfg="cfail3")]
pub fn add_amp_in_pattern() {
    let (&_a, _b) = (&1u8, 'y');
}

// Change Mutability of Binding in Pattern -------------------------------------
#[cfg(cfail1)]
pub fn change_mutability_of_binding_in_pattern() {
    let (_a, _b) = (99u8, 'q');
}

#[cfg(not(cfail1))]
#[rustc_clean(cfg="cfail2",
    except="HirBody,TypeckTables,MirValidated,MirOptimized")]
#[rustc_clean(cfg="cfail3")]
pub fn change_mutability_of_binding_in_pattern() {
    let (mut _a, _b) = (99u8, 'q');
}

// Add Initializer -------------------------------------------------------------
#[cfg(cfail1)]
pub fn add_initializer() {
    let _x: i16;
}

#[cfg(not(cfail1))]
#[rustc_clean(cfg="cfail2",
    except="HirBody,TypeckTables,MirValidated,MirOptimized")]
#[rustc_clean(cfg="cfail3")]
pub fn add_initializer() {
    let _x: i16 = 3i16;
}

// Change Initializer ----------------------------------------------------------
#[cfg(cfail1)]
pub fn change_initializer() {
    let _x = 4u16;
}

#[cfg(not(cfail1))]
#[rustc_clean(cfg="cfail2",
    except="HirBody,MirValidated,MirOptimized")]
#[rustc_clean(cfg="cfail3")]
pub fn change_initializer() {
    let _x = 5u16;
}
<|endoftext|>


<commit_before>// Copyright (c) The Diem Core Contributors
// SPDX-License-Identifier: Apache-2.0

use crate::async_client::{
    defaults, types as jsonrpc, BroadcastHttpClient, Error, HttpClient, JsonRpcResponse, Request,
    Response, RetryStrategy, SimpleHttpClient, State, WaitForTransactionError,
};
use diem_crypto::hash::CryptoHash;
use diem_types::{
    account_address::AccountAddress,
    transaction::{SignedTransaction, Transaction},
};

use serde::de::DeserializeOwned;

use std::{convert::TryInto, sync::Arc, time::Duration};

pub struct Client<R> {
    pub http_client: Arc<dyn HttpClient>,
    pub retry: R,
}

impl<R: RetryStrategy> Client<R> {
    pub fn from_url<T: reqwest::IntoUrl>(server_url: T, retry: R) -> Result<Self, reqwest::Error> {
        Ok(Self {
            http_client: Arc::new(SimpleHttpClient::new(server_url)?),
            retry,
        })
    }

    pub fn from_url_list<T: reqwest::IntoUrl>(
        server_urls: Vec<T>,
        num_parallel_requests: usize,
        retry: R,
    ) -> Result<Self, String> {
        Ok(Self {
            http_client: Arc::new(BroadcastHttpClient::new(
                server_urls,
                num_parallel_requests,
            )?),
            retry,
        })
    }

    pub async fn wait_for_signed_transaction(
        &self,
        txn: &SignedTransaction,
        timeout: Option<Duration>,
        delay: Option<Duration>,
    ) -> Result<Response<jsonrpc::Transaction>, WaitForTransactionError> {
        self.wait_for_transaction(
            &txn.sender(),
            txn.sequence_number(),
            txn.expiration_timestamp_secs(),
            &Transaction::UserTransaction(txn.clone()).hash().to_hex(),
            timeout,
            delay,
        )
        .await
    }

    pub async fn wait_for_transaction(
        &self,
        address: &AccountAddress,
        seq: u64,
        expiration_time_secs: u64,
        txn_hash: &str,
        timeout: Option<Duration>,
        delay: Option<Duration>,
    ) -> Result<Response<jsonrpc::Transaction>, WaitForTransactionError> {
        let start = std::time::Instant::now();
        while start.elapsed() < timeout.unwrap_or(defaults::TIMEOUT) {
            let txn_resp = self
                .get_account_transaction(address, seq, true)
                .await
                .map_err(WaitForTransactionError::GetTransactionError)?;
            if let Some(txn) = txn_resp.result {
                if txn.hash != txn_hash {
                    return Err(WaitForTransactionError::TransactionHashMismatchError(txn));
                }
                if let Some(ref vm_status) = txn.vm_status {
                    if vm_status.r#type != jsonrpc::VM_STATUS_EXECUTED {
                        return Err(WaitForTransactionError::TransactionExecutionFailed(txn));
                    }
                }
                return Ok(Response {
                    result: txn,
                    state: txn_resp.state,
                });
            }
            if let Some(state) = self.http_client.last_known_state() {
                if expiration_time_secs <= state.timestamp_usecs / 1_000_000 {
                    return Err(WaitForTransactionError::TransactionExpired(
                        state.timestamp_usecs,
                    ));
                }
            }
            tokio::time::delay_for(delay.unwrap_or(defaults::WAIT_DELAY)).await;
        }
        Err(WaitForTransactionError::Timeout(start.elapsed()))
    }

    pub fn last_known_state(&self) -> Option<State> {
        self.http_client.last_known_state()
    }

    pub async fn get_metadata(&self) -> Result<Response<jsonrpc::Metadata>, Error> {
        self.send(Request::get_metadata()).await
    }

    pub async fn get_metadata_by_version(
        &self,
        version: u64,
    ) -> Result<Response<jsonrpc::Metadata>, Error> {
        self.send(Request::get_metadata_by_version(version)).await
    }

    pub async fn get_account(
        &self,
        address: &AccountAddress,
    ) -> Result<Response<Option<jsonrpc::Account>>, Error> {
        self.send_opt(Request::get_account(address)).await
    }

    pub async fn get_account_transaction(
        &self,
        address: &AccountAddress,
        seq: u64,
        include_events: bool,
    ) -> Result<Response<Option<jsonrpc::Transaction>>, Error> {
        self.send_opt(Request::get_account_transaction(
            address,
            seq,
            include_events,
        ))
        .await
    }

    pub async fn get_account_transactions(
        &self,
        address: &AccountAddress,
        start_seq: u64,
        limit: u64,
        include_events: bool,
    ) -> Result<Response<Vec<jsonrpc::Transaction>>, Error> {
        self.send(Request::get_account_transactions(
            address,
            start_seq,
            limit,
            include_events,
        ))
        .await
    }

    pub async fn get_transactions(
        &self,
        start_seq: u64,
        limit: u64,
        include_events: bool,
    ) -> Result<Response<Vec<jsonrpc::Transaction>>, Error> {
        self.send(Request::get_transactions(start_seq, limit, include_events))
            .await
    }

    pub async fn get_events(
        &self,
        key: &str,
        start_seq: u64,
        limit: u64,
    ) -> Result<Response<Vec<jsonrpc::Event>>, Error> {
        self.send(Request::get_events(key, start_seq, limit)).await
    }

    pub async fn get_currencies(&self) -> Result<Response<Vec<jsonrpc::CurrencyInfo>>, Error> {
        self.send(Request::get_currencies()).await
    }

    pub async fn get_state_proof(
        &self,
        from_version: u64,
    ) -> Result<Response<jsonrpc::StateProof>, Error> {
        self.send(Request::get_state_proof(from_version)).await
    }

    pub async fn get_account_state_with_proof(
        &self,
        address: &AccountAddress,
        from_version: Option<u64>,
        to_version: Option<u64>,
    ) -> Result<Response<jsonrpc::AccountStateWithProof>, Error> {
        self.send(Request::get_account_state_with_proof(
            address,
            from_version,
            to_version,
        ))
        .await
    }

    pub async fn submit(&self, txn: &SignedTransaction) -> Result<Response<()>, Error> {
        let req = Request::submit(txn).map_err(Error::unexpected_lcs_error)?;
        let resp = self.http_client.single_request(&req).await?;
        Ok(Response {
            result: (),
            state: State::from_response(&resp),
        })
    }

    pub async fn send<T: DeserializeOwned>(&self, request: Request) -> Result<Response<T>, Error> {
        self.send_with_retry(&request).await?.try_into()
    }

    pub async fn send_opt<T: DeserializeOwned>(
        &self,
        request: Request,
    ) -> Result<Response<Option<T>>, Error> {
        let resp = self.send_with_retry(&request).await?;
        let state = State::from_response(&resp);
        let result = match resp.result {
            Some(ret) => {
                Some(serde_json::from_value(ret).map_err(Error::DeserializeResponseJsonError)?)
            }
            None => None,
        };
        Ok(Response { result, state })
    }

    pub async fn send_with_retry(&self, request: &Request) -> Result<JsonRpcResponse, Error> {
        let mut retries: u32 = 0;
        loop {
            let ret = self.http_client.single_request(request).await;
            match ret {
                Ok(r) => return Ok(r),
                Err(err) => retries = self.handle_retry_error(retries, err).await?,
            }
        }
    }

    /// Batch requests into one JSON-RPC batch request.
    /// To keep interface simple, this method returns error when any error occurs.
    /// When batch responses contain partial success response, we will return the first
    /// error it hit.
    ///
    /// Caller can convert `JsonRpcResponse` into `Response<T>`
    /// in order of given requests:
    ///
    /// ```rust
    /// use diem_json_rpc_client::async_client::{
    ///     types as jsonrpc, Client, Error, Request, Response, Retry,
    /// };
    /// use std::convert::{TryInto};
    ///
    /// # async fn doc() -> Result<(), Error> {
    /// let client = Client::from_url("http://testnet.diem.com/v1", Retry::default()).unwrap();
    /// let mut res = client
    ///     .batch_send(vec![Request::get_metadata(), Request::get_currencies()])
    ///     .await?;
    ///
    /// let metadata: Response<jsonrpc::Metadata> = res
    ///     .remove(0)
    ///     .try_into()?;
    ///
    /// let currencies: Response<jsonrpc::CurrencyInfo> = res
    ///     .remove(0)
    ///     .try_into()?;
    /// # Ok(())
    /// # }
    /// ```
    ///
    /// For get_account and get_account_transaction request, the above convert will return
    /// result not found error instead of None.
    ///
    /// This function calls to batch_send_with_retry, when you batch submit transactions,
    /// to avoid re-submit errors, it is better to use batch_send_without_retry and handle errors
    /// by yourself.
    pub async fn batch_send(&self, requests: Vec<Request>) -> Result<Vec<JsonRpcResponse>, Error> {
        self.batch_send_with_retry(&requests).await
    }

    pub async fn batch_send_with_retry(
        &self,
        requests: &[Request],
    ) -> Result<Vec<JsonRpcResponse>, Error> {
        let mut retries: u32 = 0;
        loop {
            let ret = self.http_client.batch_request(requests).await;
            match ret {
                Ok(r) => return Ok(r),
                Err(err) => retries = self.handle_retry_error(retries, err).await?,
            }
        }
    }

    async fn handle_retry_error(&self, mut retries: u32, err: Error) -> Result<u32, Error> {
        if !self.retry.is_retriable(&err) {
            return Err(err);
        }
        if retries < self.retry.max_retries(&err) {
            match retries.checked_add(1) {
                Some(i) if i < self.retry.max_retries(&err) => {
                    retries = i;
                }
                _ => return Err(err),
            };
            tokio::time::delay_for(self.retry.delay(&err, retries)).await;
            Ok(retries)
        } else {
            Err(err)
        }
    }
}
<commit_msg>Add custom retry strategy per request<commit_after>// Copyright (c) The Diem Core Contributors
// SPDX-License-Identifier: Apache-2.0

use crate::async_client::{
    defaults, types as jsonrpc, BroadcastHttpClient, Error, HttpClient, JsonRpcResponse, Request,
    Response, RetryStrategy, SimpleHttpClient, State, WaitForTransactionError,
};
use diem_crypto::hash::CryptoHash;
use diem_types::{
    account_address::AccountAddress,
    transaction::{SignedTransaction, Transaction},
};

use serde::de::DeserializeOwned;

use std::{convert::TryInto, sync::Arc, time::Duration};

pub struct Client<R> {
    pub http_client: Arc<dyn HttpClient>,
    pub retry: R,
}

impl<R: RetryStrategy> Client<R> {
    pub fn from_url<T: reqwest::IntoUrl>(server_url: T, retry: R) -> Result<Self, reqwest::Error> {
        Ok(Self {
            http_client: Arc::new(SimpleHttpClient::new(server_url)?),
            retry,
        })
    }

    pub fn from_url_list<T: reqwest::IntoUrl>(
        server_urls: Vec<T>,
        num_parallel_requests: usize,
        retry: R,
    ) -> Result<Self, String> {
        Ok(Self {
            http_client: Arc::new(BroadcastHttpClient::new(
                server_urls,
                num_parallel_requests,
            )?),
            retry,
        })
    }

    pub async fn wait_for_signed_transaction(
        &self,
        txn: &SignedTransaction,
        timeout: Option<Duration>,
        delay: Option<Duration>,
    ) -> Result<Response<jsonrpc::Transaction>, WaitForTransactionError> {
        self.wait_for_transaction(
            &txn.sender(),
            txn.sequence_number(),
            txn.expiration_timestamp_secs(),
            &Transaction::UserTransaction(txn.clone()).hash().to_hex(),
            timeout,
            delay,
        )
        .await
    }

    pub async fn wait_for_transaction(
        &self,
        address: &AccountAddress,
        seq: u64,
        expiration_time_secs: u64,
        txn_hash: &str,
        timeout: Option<Duration>,
        delay: Option<Duration>,
    ) -> Result<Response<jsonrpc::Transaction>, WaitForTransactionError> {
        let start = std::time::Instant::now();
        while start.elapsed() < timeout.unwrap_or(defaults::TIMEOUT) {
            let txn_resp = self
                .get_account_transaction(address, seq, true)
                .await
                .map_err(WaitForTransactionError::GetTransactionError)?;
            if let Some(txn) = txn_resp.result {
                if txn.hash != txn_hash {
                    return Err(WaitForTransactionError::TransactionHashMismatchError(txn));
                }
                if let Some(ref vm_status) = txn.vm_status {
                    if vm_status.r#type != jsonrpc::VM_STATUS_EXECUTED {
                        return Err(WaitForTransactionError::TransactionExecutionFailed(txn));
                    }
                }
                return Ok(Response {
                    result: txn,
                    state: txn_resp.state,
                });
            }
            if let Some(state) = self.http_client.last_known_state() {
                if expiration_time_secs <= state.timestamp_usecs / 1_000_000 {
                    return Err(WaitForTransactionError::TransactionExpired(
                        state.timestamp_usecs,
                    ));
                }
            }
            tokio::time::delay_for(delay.unwrap_or(defaults::WAIT_DELAY)).await;
        }
        Err(WaitForTransactionError::Timeout(start.elapsed()))
    }

    pub fn last_known_state(&self) -> Option<State> {
        self.http_client.last_known_state()
    }

    pub async fn get_metadata(&self) -> Result<Response<jsonrpc::Metadata>, Error> {
        self.send(Request::get_metadata()).await
    }

    pub async fn get_metadata_by_version(
        &self,
        version: u64,
    ) -> Result<Response<jsonrpc::Metadata>, Error> {
        self.send(Request::get_metadata_by_version(version)).await
    }

    pub async fn get_account(
        &self,
        address: &AccountAddress,
    ) -> Result<Response<Option<jsonrpc::Account>>, Error> {
        self.send_opt(Request::get_account(address)).await
    }

    pub async fn get_account_transaction(
        &self,
        address: &AccountAddress,
        seq: u64,
        include_events: bool,
    ) -> Result<Response<Option<jsonrpc::Transaction>>, Error> {
        self.send_opt(Request::get_account_transaction(
            address,
            seq,
            include_events,
        ))
        .await
    }

    pub async fn get_account_transactions(
        &self,
        address: &AccountAddress,
        start_seq: u64,
        limit: u64,
        include_events: bool,
    ) -> Result<Response<Vec<jsonrpc::Transaction>>, Error> {
        self.send(Request::get_account_transactions(
            address,
            start_seq,
            limit,
            include_events,
        ))
        .await
    }

    pub async fn get_transactions(
        &self,
        start_seq: u64,
        limit: u64,
        include_events: bool,
    ) -> Result<Response<Vec<jsonrpc::Transaction>>, Error> {
        self.send(Request::get_transactions(start_seq, limit, include_events))
            .await
    }

    pub async fn get_events(
        &self,
        key: &str,
        start_seq: u64,
        limit: u64,
    ) -> Result<Response<Vec<jsonrpc::Event>>, Error> {
        self.send(Request::get_events(key, start_seq, limit)).await
    }

    pub async fn get_currencies(&self) -> Result<Response<Vec<jsonrpc::CurrencyInfo>>, Error> {
        self.send(Request::get_currencies()).await
    }

    pub async fn get_state_proof(
        &self,
        from_version: u64,
    ) -> Result<Response<jsonrpc::StateProof>, Error> {
        self.send(Request::get_state_proof(from_version)).await
    }

    pub async fn get_account_state_with_proof(
        &self,
        address: &AccountAddress,
        from_version: Option<u64>,
        to_version: Option<u64>,
    ) -> Result<Response<jsonrpc::AccountStateWithProof>, Error> {
        self.send(Request::get_account_state_with_proof(
            address,
            from_version,
            to_version,
        ))
        .await
    }

    pub async fn submit(&self, txn: &SignedTransaction) -> Result<Response<()>, Error> {
        let req = Request::submit(txn).map_err(Error::unexpected_lcs_error)?;
        let resp = self.http_client.single_request(&req).await?;
        Ok(Response {
            result: (),
            state: State::from_response(&resp),
        })
    }

    pub async fn send<T: DeserializeOwned>(&self, request: Request) -> Result<Response<T>, Error> {
        self.send_with_retry(&request, &self.retry)
            .await?
            .try_into()
    }

    pub async fn send_opt<T: DeserializeOwned>(
        &self,
        request: Request,
    ) -> Result<Response<Option<T>>, Error> {
        let resp = self.send_with_retry(&request, &self.retry).await?;
        let state = State::from_response(&resp);
        let result = match resp.result {
            Some(ret) => {
                Some(serde_json::from_value(ret).map_err(Error::DeserializeResponseJsonError)?)
            }
            None => None,
        };
        Ok(Response { result, state })
    }

    pub async fn send_with_retry<RS: RetryStrategy>(
        &self,
        request: &Request,
        retry: &RS,
    ) -> Result<JsonRpcResponse, Error> {
        let mut retries: u32 = 0;
        loop {
            let ret = self.http_client.single_request(request).await;
            match ret {
                Ok(r) => return Ok(r),
                Err(err) => retries = self.handle_retry_error(retries, err, retry).await?,
            }
        }
    }

    /// Batch requests into one JSON-RPC batch request.
    /// To keep interface simple, this method returns error when any error occurs.
    /// When batch responses contain partial success response, we will return the first
    /// error it hit.
    ///
    /// Caller can convert `JsonRpcResponse` into `Response<T>`
    /// in order of given requests:
    ///
    /// ```rust
    /// use diem_json_rpc_client::async_client::{
    ///     types as jsonrpc, Client, Error, Request, Response, Retry,
    /// };
    /// use std::convert::{TryInto};
    ///
    /// # async fn doc() -> Result<(), Error> {
    /// let client = Client::from_url("http://testnet.diem.com/v1", Retry::default()).unwrap();
    /// let mut res = client
    ///     .batch_send(vec![Request::get_metadata(), Request::get_currencies()])
    ///     .await?;
    ///
    /// let metadata: Response<jsonrpc::Metadata> = res
    ///     .remove(0)
    ///     .try_into()?;
    ///
    /// let currencies: Response<jsonrpc::CurrencyInfo> = res
    ///     .remove(0)
    ///     .try_into()?;
    /// # Ok(())
    /// # }
    /// ```
    ///
    /// For get_account and get_account_transaction request, the above convert will return
    /// result not found error instead of None.
    ///
    /// This function calls to batch_send_with_retry, when you batch submit transactions,
    /// to avoid re-submit errors, it is better to use batch_send_without_retry and handle errors
    /// by yourself.
    pub async fn batch_send(&self, requests: Vec<Request>) -> Result<Vec<JsonRpcResponse>, Error> {
        self.batch_send_with_retry(&requests, &self.retry).await
    }

    pub async fn batch_send_with_retry<RS: RetryStrategy>(
        &self,
        requests: &[Request],
        retry: &RS,
    ) -> Result<Vec<JsonRpcResponse>, Error> {
        let mut retries: u32 = 0;
        loop {
            let ret = self.http_client.batch_request(requests).await;
            match ret {
                Ok(r) => return Ok(r),
                Err(err) => retries = self.handle_retry_error(retries, err, retry).await?,
            }
        }
    }

    async fn handle_retry_error<RS: RetryStrategy>(
        &self,
        mut retries: u32,
        err: Error,
        retry: &RS,
    ) -> Result<u32, Error> {
        if !retry.is_retriable(&err) {
            return Err(err);
        }
        if retries < retry.max_retries(&err) {
            match retries.checked_add(1) {
                Some(i) if i < retry.max_retries(&err) => {
                    retries = i;
                }
                _ => return Err(err),
            };
            tokio::time::delay_for(retry.delay(&err, retries)).await;
            Ok(retries)
        } else {
            Err(err)
        }
    }
}
<|endoftext|>


<commit_before>fn main() {}

const fn unsize(x: &[u8; 3]) -> &[u8] { x }
//~^ ERROR unsizing casts are not allowed in const fn
const fn closure() -> fn() { || {} }
//~^ ERROR function pointers in const fn are unstable
const fn closure2() {
    (|| {}) as fn();
//~^ ERROR function pointers in const fn are unstable
}
const fn reify(f: fn()) -> unsafe fn() { f }
//~^ ERROR function pointers in const fn are unstable
const fn reify2() { main as unsafe fn(); }
//~^ ERROR function pointers in const fn are unstable<commit_msg>Add trailing newline to satisfy tidy<commit_after>fn main() {}

const fn unsize(x: &[u8; 3]) -> &[u8] { x }
//~^ ERROR unsizing casts are not allowed in const fn
const fn closure() -> fn() { || {} }
//~^ ERROR function pointers in const fn are unstable
const fn closure2() {
    (|| {}) as fn();
//~^ ERROR function pointers in const fn are unstable
}
const fn reify(f: fn()) -> unsafe fn() { f }
//~^ ERROR function pointers in const fn are unstable
const fn reify2() { main as unsafe fn(); }
//~^ ERROR function pointers in const fn are unstable
<|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 dom::bindings::codegen::Bindings::FunctionBinding::Function;
use dom::bindings::codegen::Bindings::WorkerGlobalScopeBinding::WorkerGlobalScopeMethods;
use dom::bindings::codegen::InheritTypes::DedicatedWorkerGlobalScopeCast;
use dom::bindings::error::{ErrorResult, Fallible};
use dom::bindings::error::Error::{Syntax, Network, JSFailed};
use dom::bindings::global::GlobalRef;
use dom::bindings::js::{JS, Root, MutNullableHeap};
use dom::bindings::utils::Reflectable;
use dom::console::Console;
use dom::crypto::Crypto;
use dom::dedicatedworkerglobalscope::DedicatedWorkerGlobalScopeHelpers;
use dom::eventtarget::{EventTarget, EventTargetTypeId};
use dom::workerlocation::WorkerLocation;
use dom::workernavigator::WorkerNavigator;
use dom::window::{base64_atob, base64_btoa};
use script_task::{ScriptChan, TimerSource, ScriptPort, ScriptMsg};
use timers::{IsInterval, TimerId, TimerManager, TimerCallback};

use devtools_traits::{ScriptToDevtoolsControlMsg, DevtoolScriptControlMsg};

use msg::constellation_msg::{ConstellationChan, PipelineId, WorkerId};
use profile_traits::mem;
use net_traits::{load_whole_resource, ResourceTask};
use util::str::DOMString;

use ipc_channel::ipc::IpcSender;
use js::jsapi::{JSContext, HandleValue};
use js::rust::Runtime;
use url::{Url, UrlParser};

use std::default::Default;
use std::cell::Cell;
use std::rc::Rc;
use std::sync::mpsc::Receiver;

#[derive(JSTraceable, Copy, Clone, PartialEq, HeapSizeOf)]
pub enum WorkerGlobalScopeTypeId {
    DedicatedGlobalScope,
}

pub struct WorkerGlobalScopeInit {
    pub resource_task: ResourceTask,
    pub mem_profiler_chan: mem::ProfilerChan,
    pub devtools_chan: Option<IpcSender<ScriptToDevtoolsControlMsg>>,
    pub devtools_sender: Option<IpcSender<DevtoolScriptControlMsg>>,
    pub constellation_chan: ConstellationChan,
    pub worker_id: WorkerId,
}

// https://html.spec.whatwg.org/multipage/#the-workerglobalscope-common-interface
#[dom_struct]
pub struct WorkerGlobalScope {
    eventtarget: EventTarget,
    worker_id: WorkerId,
    worker_url: Url,
    runtime: Rc<Runtime>,
    next_worker_id: Cell<WorkerId>,
    resource_task: ResourceTask,
    location: MutNullableHeap<JS<WorkerLocation>>,
    navigator: MutNullableHeap<JS<WorkerNavigator>>,
    console: MutNullableHeap<JS<Console>>,
    crypto: MutNullableHeap<JS<Crypto>>,
    timers: TimerManager,
    mem_profiler_chan: mem::ProfilerChan,
    devtools_chan: Option<IpcSender<ScriptToDevtoolsControlMsg>>,

    /// Optional `IpcSender` for sending the `DevtoolScriptControlMsg`
    /// to the server from within the worker
    devtools_sender: Option<IpcSender<DevtoolScriptControlMsg>>,

    /// This `Receiver` will be ignored later if the corresponding
    /// `IpcSender` doesn't exist
    devtools_receiver: Receiver<DevtoolScriptControlMsg>,

    /// A flag to indicate whether the developer tools has requested live updates
    /// from the worker
    devtools_wants_updates: Cell<bool>,

    constellation_chan: ConstellationChan,
}

impl WorkerGlobalScope {
    pub fn new_inherited(type_id: WorkerGlobalScopeTypeId,
                         init: WorkerGlobalScopeInit,
                         worker_url: Url,
                         runtime: Rc<Runtime>,
                         devtools_receiver: Receiver<DevtoolScriptControlMsg>)
                         -> WorkerGlobalScope {
        WorkerGlobalScope {
            eventtarget: EventTarget::new_inherited(EventTargetTypeId::WorkerGlobalScope(type_id)),
            next_worker_id: Cell::new(WorkerId(0)),
            worker_id: init.worker_id,
            worker_url: worker_url,
            runtime: runtime,
            resource_task: init.resource_task,
            location: Default::default(),
            navigator: Default::default(),
            console: Default::default(),
            crypto: Default::default(),
            timers: TimerManager::new(),
            mem_profiler_chan: init.mem_profiler_chan,
            devtools_chan: init.devtools_chan,
            devtools_sender: init.devtools_sender,
            devtools_receiver: devtools_receiver,
            devtools_wants_updates: Cell::new(false),
            constellation_chan: init.constellation_chan,
        }
    }

    pub fn mem_profiler_chan(&self) -> mem::ProfilerChan {
        self.mem_profiler_chan.clone()
    }

    pub fn devtools_chan(&self) -> Option<IpcSender<ScriptToDevtoolsControlMsg>> {
        self.devtools_chan.clone()
    }

    pub fn devtools_sender(&self) -> Option<IpcSender<DevtoolScriptControlMsg>> {
        self.devtools_sender.clone()
    }

    pub fn devtools_port(&self) -> &Receiver<DevtoolScriptControlMsg> {
        &self.devtools_receiver
    }

    pub fn constellation_chan(&self) -> ConstellationChan {
        self.constellation_chan.clone()
    }

    #[inline]
    pub fn eventtarget<'a>(&'a self) -> &'a EventTarget {
        &self.eventtarget
    }

    pub fn get_cx(&self) -> *mut JSContext {
        self.runtime.cx()
    }

    pub fn resource_task<'a>(&'a self) -> &'a ResourceTask {
        &   self.resource_task
    }

    pub fn get_url<'a>(&'a self) -> &'a Url {
        &self.worker_url
    }

    pub fn get_worker_id(&self) -> WorkerId {
        self.worker_id.clone()
    }

    pub fn get_next_worker_id(&self) -> WorkerId {
        let worker_id = self.next_worker_id.get();
        let WorkerId(id_num) = worker_id;
        self.next_worker_id.set(WorkerId(id_num + 1));
        worker_id
    }
}

impl<'a> WorkerGlobalScopeMethods for &'a WorkerGlobalScope {
    // https://html.spec.whatwg.org/multipage/#dom-workerglobalscope-self
    fn Self_(self) -> Root<WorkerGlobalScope> {
        Root::from_ref(self)
    }

    // https://html.spec.whatwg.org/multipage/#dom-workerglobalscope-location
    fn Location(self) -> Root<WorkerLocation> {
        self.location.or_init(|| {
            WorkerLocation::new(self, self.worker_url.clone())
        })
    }

    // https://html.spec.whatwg.org/multipage/#dom-workerglobalscope-importscripts
    fn ImportScripts(self, url_strings: Vec<DOMString>) -> ErrorResult {
        let mut urls = Vec::with_capacity(url_strings.len());
        for url in url_strings.into_iter() {
            let url = UrlParser::new().base_url(&self.worker_url)
                                      .parse(&url);
            match url {
                Ok(url) => urls.push(url),
                Err(_) => return Err(Syntax),
            };
        }

        for url in urls.into_iter() {
            let (url, source) = match load_whole_resource(&self.resource_task, url) {
                Err(_) => return Err(Network),
                Ok((metadata, bytes)) => {
                    (metadata.final_url, String::from_utf8(bytes).unwrap())
                }
            };

            match self.runtime.evaluate_script(
                self.reflector().get_jsobject(), source, url.serialize(), 1) {
                Ok(_) => (),
                Err(_) => {
                    println!("evaluate_script failed");
                    return Err(JSFailed);
                }
            }
        }

        Ok(())
    }

    // https://html.spec.whatwg.org/multipage/#dom-worker-navigator
    fn Navigator(self) -> Root<WorkerNavigator> {
        self.navigator.or_init(|| WorkerNavigator::new(self))
    }

    // https://developer.mozilla.org/en-US/docs/Web/API/WorkerGlobalScope/console
    fn Console(self) -> Root<Console> {
        self.console.or_init(|| Console::new(GlobalRef::Worker(self)))
    }

    // https://html.spec.whatwg.org/multipage/#dfn-Crypto
    fn Crypto(self) -> Root<Crypto> {
        self.crypto.or_init(|| Crypto::new(GlobalRef::Worker(self)))
    }

    // https://html.spec.whatwg.org/multipage/#dom-windowbase64-btoa
    fn Btoa(self, btoa: DOMString) -> Fallible<DOMString> {
        base64_btoa(btoa)
    }

    // https://html.spec.whatwg.org/multipage/#dom-windowbase64-atob
    fn Atob(self, atob: DOMString) -> Fallible<DOMString> {
        base64_atob(atob)
    }

    // https://html.spec.whatwg.org/multipage/#dom-windowtimers-setinterval
    fn SetTimeout(self, _cx: *mut JSContext, callback: Rc<Function>, timeout: i32, args: Vec<HandleValue>) -> i32 {
        self.timers.set_timeout_or_interval(TimerCallback::FunctionTimerCallback(callback),
                                            args,
                                            timeout,
                                            IsInterval::NonInterval,
                                            TimerSource::FromWorker,
                                            self.script_chan())
    }

    // https://html.spec.whatwg.org/multipage/#dom-windowtimers-setinterval
    fn SetTimeout_(self, _cx: *mut JSContext, callback: DOMString, timeout: i32, args: Vec<HandleValue>) -> i32 {
        self.timers.set_timeout_or_interval(TimerCallback::StringTimerCallback(callback),
                                            args,
                                            timeout,
                                            IsInterval::NonInterval,
                                            TimerSource::FromWorker,
                                            self.script_chan())
    }

    // https://html.spec.whatwg.org/multipage/#dom-windowtimers-clearinterval
    fn ClearTimeout(self, handle: i32) {
        self.timers.clear_timeout_or_interval(handle);
    }

    // https://html.spec.whatwg.org/multipage/#dom-windowtimers-setinterval
    fn SetInterval(self, _cx: *mut JSContext, callback: Rc<Function>, timeout: i32, args: Vec<HandleValue>) -> i32 {
        self.timers.set_timeout_or_interval(TimerCallback::FunctionTimerCallback(callback),
                                            args,
                                            timeout,
                                            IsInterval::Interval,
                                            TimerSource::FromWorker,
                                            self.script_chan())
    }

    // https://html.spec.whatwg.org/multipage/#dom-windowtimers-setinterval
    fn SetInterval_(self, _cx: *mut JSContext, callback: DOMString, timeout: i32, args: Vec<HandleValue>) -> i32 {
        self.timers.set_timeout_or_interval(TimerCallback::StringTimerCallback(callback),
                                            args,
                                            timeout,
                                            IsInterval::Interval,
                                            TimerSource::FromWorker,
                                            self.script_chan())
    }

    // https://html.spec.whatwg.org/multipage/#dom-windowtimers-clearinterval
    fn ClearInterval(self, handle: i32) {
        self.ClearTimeout(handle);
    }
}

pub trait WorkerGlobalScopeHelpers {
    fn handle_fire_timer(self, timer_id: TimerId);
    fn script_chan(self) -> Box<ScriptChan+Send>;
    fn pipeline(self) -> PipelineId;
    fn new_script_pair(self) -> (Box<ScriptChan+Send>, Box<ScriptPort+Send>);
    fn process_event(self, msg: ScriptMsg);
    fn get_cx(self) -> *mut JSContext;
    fn set_devtools_wants_updates(self, value: bool);
}

impl<'a> WorkerGlobalScopeHelpers for &'a WorkerGlobalScope {
    fn script_chan(self) -> Box<ScriptChan+Send> {
        let dedicated =
            DedicatedWorkerGlobalScopeCast::to_ref(self);
        match dedicated {
            Some(dedicated) => dedicated.script_chan(),
            None => panic!("need to implement a sender for SharedWorker"),
        }
    }

    fn pipeline(self) -> PipelineId {
        let dedicated =
            DedicatedWorkerGlobalScopeCast::to_ref(self);
        match dedicated {
            Some(dedicated) => dedicated.pipeline(),
            None => panic!("need to add a pipeline for SharedWorker"),
        }
    }

    fn new_script_pair(self) -> (Box<ScriptChan+Send>, Box<ScriptPort+Send>) {
        let dedicated =
            DedicatedWorkerGlobalScopeCast::to_ref(self);
        match dedicated {
            Some(dedicated) => dedicated.new_script_pair(),
            None => panic!("need to implement creating isolated event loops for SharedWorker"),
        }
    }

    fn process_event(self, msg: ScriptMsg) {
        let dedicated =
            DedicatedWorkerGlobalScopeCast::to_ref(self);
        match dedicated {
            Some(dedicated) => dedicated.process_event(msg),
            None => panic!("need to implement processing single events for SharedWorker"),
        }
    }

    fn handle_fire_timer(self, timer_id: TimerId) {
        self.timers.fire_timer(timer_id, self);
    }

    fn get_cx(self) -> *mut JSContext {
        self.runtime.cx()
    }

    fn set_devtools_wants_updates(self, value: bool) {
        self.devtools_wants_updates.set(value);
    }
}
<commit_msg>Remove some stray whitespace.<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 dom::bindings::codegen::Bindings::FunctionBinding::Function;
use dom::bindings::codegen::Bindings::WorkerGlobalScopeBinding::WorkerGlobalScopeMethods;
use dom::bindings::codegen::InheritTypes::DedicatedWorkerGlobalScopeCast;
use dom::bindings::error::{ErrorResult, Fallible};
use dom::bindings::error::Error::{Syntax, Network, JSFailed};
use dom::bindings::global::GlobalRef;
use dom::bindings::js::{JS, Root, MutNullableHeap};
use dom::bindings::utils::Reflectable;
use dom::console::Console;
use dom::crypto::Crypto;
use dom::dedicatedworkerglobalscope::DedicatedWorkerGlobalScopeHelpers;
use dom::eventtarget::{EventTarget, EventTargetTypeId};
use dom::workerlocation::WorkerLocation;
use dom::workernavigator::WorkerNavigator;
use dom::window::{base64_atob, base64_btoa};
use script_task::{ScriptChan, TimerSource, ScriptPort, ScriptMsg};
use timers::{IsInterval, TimerId, TimerManager, TimerCallback};

use devtools_traits::{ScriptToDevtoolsControlMsg, DevtoolScriptControlMsg};

use msg::constellation_msg::{ConstellationChan, PipelineId, WorkerId};
use profile_traits::mem;
use net_traits::{load_whole_resource, ResourceTask};
use util::str::DOMString;

use ipc_channel::ipc::IpcSender;
use js::jsapi::{JSContext, HandleValue};
use js::rust::Runtime;
use url::{Url, UrlParser};

use std::default::Default;
use std::cell::Cell;
use std::rc::Rc;
use std::sync::mpsc::Receiver;

#[derive(JSTraceable, Copy, Clone, PartialEq, HeapSizeOf)]
pub enum WorkerGlobalScopeTypeId {
    DedicatedGlobalScope,
}

pub struct WorkerGlobalScopeInit {
    pub resource_task: ResourceTask,
    pub mem_profiler_chan: mem::ProfilerChan,
    pub devtools_chan: Option<IpcSender<ScriptToDevtoolsControlMsg>>,
    pub devtools_sender: Option<IpcSender<DevtoolScriptControlMsg>>,
    pub constellation_chan: ConstellationChan,
    pub worker_id: WorkerId,
}

// https://html.spec.whatwg.org/multipage/#the-workerglobalscope-common-interface
#[dom_struct]
pub struct WorkerGlobalScope {
    eventtarget: EventTarget,
    worker_id: WorkerId,
    worker_url: Url,
    runtime: Rc<Runtime>,
    next_worker_id: Cell<WorkerId>,
    resource_task: ResourceTask,
    location: MutNullableHeap<JS<WorkerLocation>>,
    navigator: MutNullableHeap<JS<WorkerNavigator>>,
    console: MutNullableHeap<JS<Console>>,
    crypto: MutNullableHeap<JS<Crypto>>,
    timers: TimerManager,
    mem_profiler_chan: mem::ProfilerChan,
    devtools_chan: Option<IpcSender<ScriptToDevtoolsControlMsg>>,

    /// Optional `IpcSender` for sending the `DevtoolScriptControlMsg`
    /// to the server from within the worker
    devtools_sender: Option<IpcSender<DevtoolScriptControlMsg>>,

    /// This `Receiver` will be ignored later if the corresponding
    /// `IpcSender` doesn't exist
    devtools_receiver: Receiver<DevtoolScriptControlMsg>,

    /// A flag to indicate whether the developer tools has requested live updates
    /// from the worker
    devtools_wants_updates: Cell<bool>,

    constellation_chan: ConstellationChan,
}

impl WorkerGlobalScope {
    pub fn new_inherited(type_id: WorkerGlobalScopeTypeId,
                         init: WorkerGlobalScopeInit,
                         worker_url: Url,
                         runtime: Rc<Runtime>,
                         devtools_receiver: Receiver<DevtoolScriptControlMsg>)
                         -> WorkerGlobalScope {
        WorkerGlobalScope {
            eventtarget: EventTarget::new_inherited(EventTargetTypeId::WorkerGlobalScope(type_id)),
            next_worker_id: Cell::new(WorkerId(0)),
            worker_id: init.worker_id,
            worker_url: worker_url,
            runtime: runtime,
            resource_task: init.resource_task,
            location: Default::default(),
            navigator: Default::default(),
            console: Default::default(),
            crypto: Default::default(),
            timers: TimerManager::new(),
            mem_profiler_chan: init.mem_profiler_chan,
            devtools_chan: init.devtools_chan,
            devtools_sender: init.devtools_sender,
            devtools_receiver: devtools_receiver,
            devtools_wants_updates: Cell::new(false),
            constellation_chan: init.constellation_chan,
        }
    }

    pub fn mem_profiler_chan(&self) -> mem::ProfilerChan {
        self.mem_profiler_chan.clone()
    }

    pub fn devtools_chan(&self) -> Option<IpcSender<ScriptToDevtoolsControlMsg>> {
        self.devtools_chan.clone()
    }

    pub fn devtools_sender(&self) -> Option<IpcSender<DevtoolScriptControlMsg>> {
        self.devtools_sender.clone()
    }

    pub fn devtools_port(&self) -> &Receiver<DevtoolScriptControlMsg> {
        &self.devtools_receiver
    }

    pub fn constellation_chan(&self) -> ConstellationChan {
        self.constellation_chan.clone()
    }

    #[inline]
    pub fn eventtarget<'a>(&'a self) -> &'a EventTarget {
        &self.eventtarget
    }

    pub fn get_cx(&self) -> *mut JSContext {
        self.runtime.cx()
    }

    pub fn resource_task<'a>(&'a self) -> &'a ResourceTask {
        &self.resource_task
    }

    pub fn get_url<'a>(&'a self) -> &'a Url {
        &self.worker_url
    }

    pub fn get_worker_id(&self) -> WorkerId {
        self.worker_id.clone()
    }

    pub fn get_next_worker_id(&self) -> WorkerId {
        let worker_id = self.next_worker_id.get();
        let WorkerId(id_num) = worker_id;
        self.next_worker_id.set(WorkerId(id_num + 1));
        worker_id
    }
}

impl<'a> WorkerGlobalScopeMethods for &'a WorkerGlobalScope {
    // https://html.spec.whatwg.org/multipage/#dom-workerglobalscope-self
    fn Self_(self) -> Root<WorkerGlobalScope> {
        Root::from_ref(self)
    }

    // https://html.spec.whatwg.org/multipage/#dom-workerglobalscope-location
    fn Location(self) -> Root<WorkerLocation> {
        self.location.or_init(|| {
            WorkerLocation::new(self, self.worker_url.clone())
        })
    }

    // https://html.spec.whatwg.org/multipage/#dom-workerglobalscope-importscripts
    fn ImportScripts(self, url_strings: Vec<DOMString>) -> ErrorResult {
        let mut urls = Vec::with_capacity(url_strings.len());
        for url in url_strings.into_iter() {
            let url = UrlParser::new().base_url(&self.worker_url)
                                      .parse(&url);
            match url {
                Ok(url) => urls.push(url),
                Err(_) => return Err(Syntax),
            };
        }

        for url in urls.into_iter() {
            let (url, source) = match load_whole_resource(&self.resource_task, url) {
                Err(_) => return Err(Network),
                Ok((metadata, bytes)) => {
                    (metadata.final_url, String::from_utf8(bytes).unwrap())
                }
            };

            match self.runtime.evaluate_script(
                self.reflector().get_jsobject(), source, url.serialize(), 1) {
                Ok(_) => (),
                Err(_) => {
                    println!("evaluate_script failed");
                    return Err(JSFailed);
                }
            }
        }

        Ok(())
    }

    // https://html.spec.whatwg.org/multipage/#dom-worker-navigator
    fn Navigator(self) -> Root<WorkerNavigator> {
        self.navigator.or_init(|| WorkerNavigator::new(self))
    }

    // https://developer.mozilla.org/en-US/docs/Web/API/WorkerGlobalScope/console
    fn Console(self) -> Root<Console> {
        self.console.or_init(|| Console::new(GlobalRef::Worker(self)))
    }

    // https://html.spec.whatwg.org/multipage/#dfn-Crypto
    fn Crypto(self) -> Root<Crypto> {
        self.crypto.or_init(|| Crypto::new(GlobalRef::Worker(self)))
    }

    // https://html.spec.whatwg.org/multipage/#dom-windowbase64-btoa
    fn Btoa(self, btoa: DOMString) -> Fallible<DOMString> {
        base64_btoa(btoa)
    }

    // https://html.spec.whatwg.org/multipage/#dom-windowbase64-atob
    fn Atob(self, atob: DOMString) -> Fallible<DOMString> {
        base64_atob(atob)
    }

    // https://html.spec.whatwg.org/multipage/#dom-windowtimers-setinterval
    fn SetTimeout(self, _cx: *mut JSContext, callback: Rc<Function>, timeout: i32, args: Vec<HandleValue>) -> i32 {
        self.timers.set_timeout_or_interval(TimerCallback::FunctionTimerCallback(callback),
                                            args,
                                            timeout,
                                            IsInterval::NonInterval,
                                            TimerSource::FromWorker,
                                            self.script_chan())
    }

    // https://html.spec.whatwg.org/multipage/#dom-windowtimers-setinterval
    fn SetTimeout_(self, _cx: *mut JSContext, callback: DOMString, timeout: i32, args: Vec<HandleValue>) -> i32 {
        self.timers.set_timeout_or_interval(TimerCallback::StringTimerCallback(callback),
                                            args,
                                            timeout,
                                            IsInterval::NonInterval,
                                            TimerSource::FromWorker,
                                            self.script_chan())
    }

    // https://html.spec.whatwg.org/multipage/#dom-windowtimers-clearinterval
    fn ClearTimeout(self, handle: i32) {
        self.timers.clear_timeout_or_interval(handle);
    }

    // https://html.spec.whatwg.org/multipage/#dom-windowtimers-setinterval
    fn SetInterval(self, _cx: *mut JSContext, callback: Rc<Function>, timeout: i32, args: Vec<HandleValue>) -> i32 {
        self.timers.set_timeout_or_interval(TimerCallback::FunctionTimerCallback(callback),
                                            args,
                                            timeout,
                                            IsInterval::Interval,
                                            TimerSource::FromWorker,
                                            self.script_chan())
    }

    // https://html.spec.whatwg.org/multipage/#dom-windowtimers-setinterval
    fn SetInterval_(self, _cx: *mut JSContext, callback: DOMString, timeout: i32, args: Vec<HandleValue>) -> i32 {
        self.timers.set_timeout_or_interval(TimerCallback::StringTimerCallback(callback),
                                            args,
                                            timeout,
                                            IsInterval::Interval,
                                            TimerSource::FromWorker,
                                            self.script_chan())
    }

    // https://html.spec.whatwg.org/multipage/#dom-windowtimers-clearinterval
    fn ClearInterval(self, handle: i32) {
        self.ClearTimeout(handle);
    }
}

pub trait WorkerGlobalScopeHelpers {
    fn handle_fire_timer(self, timer_id: TimerId);
    fn script_chan(self) -> Box<ScriptChan+Send>;
    fn pipeline(self) -> PipelineId;
    fn new_script_pair(self) -> (Box<ScriptChan+Send>, Box<ScriptPort+Send>);
    fn process_event(self, msg: ScriptMsg);
    fn get_cx(self) -> *mut JSContext;
    fn set_devtools_wants_updates(self, value: bool);
}

impl<'a> WorkerGlobalScopeHelpers for &'a WorkerGlobalScope {
    fn script_chan(self) -> Box<ScriptChan+Send> {
        let dedicated =
            DedicatedWorkerGlobalScopeCast::to_ref(self);
        match dedicated {
            Some(dedicated) => dedicated.script_chan(),
            None => panic!("need to implement a sender for SharedWorker"),
        }
    }

    fn pipeline(self) -> PipelineId {
        let dedicated =
            DedicatedWorkerGlobalScopeCast::to_ref(self);
        match dedicated {
            Some(dedicated) => dedicated.pipeline(),
            None => panic!("need to add a pipeline for SharedWorker"),
        }
    }

    fn new_script_pair(self) -> (Box<ScriptChan+Send>, Box<ScriptPort+Send>) {
        let dedicated =
            DedicatedWorkerGlobalScopeCast::to_ref(self);
        match dedicated {
            Some(dedicated) => dedicated.new_script_pair(),
            None => panic!("need to implement creating isolated event loops for SharedWorker"),
        }
    }

    fn process_event(self, msg: ScriptMsg) {
        let dedicated =
            DedicatedWorkerGlobalScopeCast::to_ref(self);
        match dedicated {
            Some(dedicated) => dedicated.process_event(msg),
            None => panic!("need to implement processing single events for SharedWorker"),
        }
    }

    fn handle_fire_timer(self, timer_id: TimerId) {
        self.timers.fire_timer(timer_id, self);
    }

    fn get_cx(self) -> *mut JSContext {
        self.runtime.cx()
    }

    fn set_devtools_wants_updates(self, value: bool) {
        self.devtools_wants_updates.set(value);
    }
}
<|endoftext|>