<commit_before>//! The most basic Amethyst example.

extern crate amethyst;

use amethyst::{Application, Duration, State, Trans};

struct Example;

impl State for Example {
    fn on_start(&mut self) {
        println!("Begin!");
    }

    fn update(&mut self, _delta: Duration) -> Trans {
        println!("Hello from Amethyst!");
        Trans::Quit
    }

    fn on_stop(&mut self) {
        println!("End!");
    }
}

fn main() {
    let mut game = Application::new(GameState::new());
    game.run();
}
<commit_msg>remove state_experiments.rs, update hello_world.rs<commit_after>//! The most basic Amethyst example.

extern crate amethyst;

use amethyst::{Application, Duration, State, Trans};

struct Example;

impl State for Example {
    fn on_start(&mut self) {
        println!("Begin!");
    }

    fn update(&mut self, _delta: Duration) -> Trans {
        println!("Hello from Amethyst!");
        Trans::Quit
    }

    fn on_stop(&mut self) {
        println!("End!");
    }
}

fn main() {
    let mut game = Application::new(Example);
    game.run();
}
<|endoftext|>


<commit_before>//! Mock request dispatcher and credentials for unit testing rusoto AWS service clients
//!
//! All rusoto generated service clients come with a constuctor function named `new_with` which
//! accepts three arguments
//!
//! * A `rusoto_core::DispatchSignedRequest` implementation
//! * A `rusoto_core::credential::ProvideAwsCredentials` implementation
//! * A `rusoto_core::Region`
//!
//! This crate provides mock implementations to satisfy the first two.
//!
//! # Example
//!
//! The following is an example for the `rusoto_s3` crate but should
//! work for all service crates just the same. The code is commented
//! out for illustration but also to avoid a cyclic dependency in this crate.
//!
//! ```rust
//! extern crate rusoto_mock;
//! // extern crate rusoto_s3;
//!
//! use rusoto_mock::{MockCredentialsProvider, MockRequestDispatcher, MockResponseReader};
//!
//! fn main() {
//!    // let s3 = rusoto_s3::S3Client::new_with(
//!    //   MockRequestDispatcher::default().with_body(
//!    //      MockResponseReader::read_response("test-data", "s3-response.json")
//!    //   ),
//!    //   MockCredentialsProvider,
//!    //   Default::default()
//!    // );
//! }
//! ```
#![deny(missing_docs)]
use std::fs::File;
use std::io::Read;
use std::time::Duration;

use async_trait::async_trait;
use futures::FutureExt;
use http::{header::HeaderName, HeaderMap, StatusCode};
use rusoto_core::credential::{AwsCredentials, ProvideAwsCredentials};
use rusoto_core::request::HttpResponse;
use rusoto_core::signature::SignedRequest;
use rusoto_core::{ByteStream, DispatchSignedRequest, HttpDispatchError};
use serde::Serialize;

/// Provides a set of credentials that always resolve
/// successfully
pub struct MockCredentialsProvider;

#[async_trait]
impl ProvideAwsCredentials for MockCredentialsProvider {
    async fn credentials(
        &self,
    ) -> Result<rusoto_core::credential::AwsCredentials, rusoto_core::credential::CredentialsError>
    {
        Ok(AwsCredentials::new("mock_key", "mock_secret", None, None))
    }
}

/// Composes mock API responses
///
/// A Default is provided which returns an successful response with an empty body
///
/// These can be constructed using either a Default implementation or
///  with the [with_status](method.with_status) function.
///
#[derive(Default)]
pub struct MockRequestDispatcher {
    outcome: RequestOutcome,
    body: Vec<u8>,
    headers: HeaderMap<String>,
    request_checker: Option<Box<dyn Fn(&SignedRequest) + Send + Sync>>,
}

enum RequestOutcome {
    Performed(StatusCode),
    Failed(HttpDispatchError),
}

impl Default for RequestOutcome {
    fn default() -> RequestOutcome {
        RequestOutcome::Performed(StatusCode::default())
    }
}

impl MockRequestDispatcher {
    /// Returns a instance that mocks the status code that would
    /// be returned from AWS
    pub fn with_status(status: u16) -> MockRequestDispatcher {
        MockRequestDispatcher {
            outcome: RequestOutcome::Performed(StatusCode::from_u16(status).unwrap()),
            ..MockRequestDispatcher::default()
        }
    }

    /// Mocks the service request failing with a communications error
    pub fn with_dispatch_error(error: HttpDispatchError) -> MockRequestDispatcher {
        MockRequestDispatcher {
            outcome: RequestOutcome::Failed(error),
            ..MockRequestDispatcher::default()
        }
    }

    /// Mocks the service response body what would be
    /// returned from AWS
    pub fn with_body(mut self, body: &str) -> MockRequestDispatcher {
        self.body = body.as_bytes().to_vec();
        self
    }

    /// Mocks the json serialized response body what would be
    /// returned from AWS
    pub fn with_json_body<B>(mut self, body: B) -> MockRequestDispatcher
    where
        B: Serialize,
    {
        self.body = serde_json::to_vec(&body).expect("failed to deserialize into json");
        self
    }

    /// Mocks the signed request checking applied to a request before sending
    /// to AWS
    pub fn with_request_checker<F>(mut self, checker: F) -> MockRequestDispatcher
    where
        F: Fn(&SignedRequest) + Send + Sync + 'static,
    {
        self.request_checker = Some(Box::new(checker));
        self
    }

    /// Mocks a single service header that would be returned from AWS
    pub fn with_header(mut self, key: &str, value: &str) -> MockRequestDispatcher {
        self.headers
            .insert(key.parse::<HeaderName>().unwrap(), value.into());
        self
    }
}

impl DispatchSignedRequest for MockRequestDispatcher {
    fn dispatch(
        &self,
        request: SignedRequest,
        _timeout: Option<Duration>,
    ) -> rusoto_core::request::DispatchSignedRequestFuture {
        if self.request_checker.is_some() {
            self.request_checker.as_ref().unwrap()(&request);
        }
        match self.outcome {
            RequestOutcome::Performed(ref status) => futures::future::ready(Ok(HttpResponse {
                status: *status,
                body: ByteStream::from(self.body.clone()),
                headers: self.headers.clone(),
            }))
            .boxed(),
            RequestOutcome::Failed(ref error) => futures::future::ready(Err(error.clone())).boxed(),
        }
    }
}

/// An interface for producing response body content
pub trait ReadMockResponse {
    /// Return a response body string for a given directory and file name
    fn read_response(dir_name: &str, file_name: &str) -> String;
}

/// Reads response body content from disk
pub struct MockResponseReader;

impl ReadMockResponse for MockResponseReader {
    fn read_response(dir_name: &str, response_name: &str) -> String {
        let file_name = format!("{}/{}", dir_name, response_name);

        let mut input_file = File::open(&file_name).expect("couldn't find file");

        let mut mock_response = String::new();

        input_file
            .read_to_string(&mut mock_response)
            .unwrap_or_else(|_| panic!("Failed to read {:?}", file_name));

        mock_response
    }
}

/// Returns sequential mock API responses consuming a collection of MockRequestDispatch
pub struct MultipleMockRequestDispatcher<I>
where
    I: Iterator<Item = MockRequestDispatcher>,
{
    iterator: I,
}

impl<I> MultipleMockRequestDispatcher<I>
where
    I: Iterator<Item = MockRequestDispatcher>,
{
    /// Constructs a new MultipleMockRequestDispatcher with a collection of MockRequestDispatch as input
    pub fn new<C>(collection: C) -> MultipleMockRequestDispatcher<I>
    where
        C: IntoIterator<Item = MockRequestDispatcher>,
        C: IntoIterator<IntoIter = I>,
    {
        MultipleMockRequestDispatcher {
            iterator: collection.into_iter(),
        }
    }
}

impl<I> DispatchSignedRequest for MultipleMockRequestDispatcher<I>
where
    I: Iterator<Item = MockRequestDispatcher>,
{
    //type Future = FutureResult<HttpResponse, HttpDispatchError>;

    fn dispatch(
        &self,
        request: SignedRequest,
        _timeout: Option<Duration>,
    ) -> rusoto_core::request::DispatchSignedRequestFuture {
        unsafe {
            (*(self as *const Self as *mut Self))
                .iterator
                .next()
                .unwrap()
                .dispatch(request, _timeout)
        }
    }
}
<commit_msg>Improve comments<commit_after>//! Mock request dispatcher and credentials for unit testing rusoto AWS service clients
//!
//! All rusoto generated service clients come with a constuctor function named `new_with` which
//! accepts three arguments
//!
//! * A `rusoto_core::DispatchSignedRequest` implementation
//! * A `rusoto_core::credential::ProvideAwsCredentials` implementation
//! * A `rusoto_core::Region`
//!
//! This crate provides mock implementations to satisfy the first two.
//!
//! # Example
//!
//! The following is an example for the `rusoto_s3` crate but should
//! work for all service crates just the same. The code is commented
//! out for illustration but also to avoid a cyclic dependency in this crate.
//!
//! ```rust
//! extern crate rusoto_mock;
//! // extern crate rusoto_s3;
//!
//! use rusoto_mock::{MockCredentialsProvider, MockRequestDispatcher, MockResponseReader};
//!
//! fn main() {
//!    // let s3 = rusoto_s3::S3Client::new_with(
//!    //   MockRequestDispatcher::default().with_body(
//!    //      MockResponseReader::read_response("test-data", "s3-response.json")
//!    //   ),
//!    //   MockCredentialsProvider,
//!    //   Default::default()
//!    // );
//! }
//! ```
#![deny(missing_docs)]
use std::fs::File;
use std::io::Read;
use std::time::Duration;

use async_trait::async_trait;
use futures::FutureExt;
use http::{header::HeaderName, HeaderMap, StatusCode};
use rusoto_core::credential::{AwsCredentials, ProvideAwsCredentials};
use rusoto_core::request::HttpResponse;
use rusoto_core::signature::SignedRequest;
use rusoto_core::{ByteStream, DispatchSignedRequest, HttpDispatchError};
use serde::Serialize;

/// Provides a set of credentials that always resolve
/// successfully
pub struct MockCredentialsProvider;

#[async_trait]
impl ProvideAwsCredentials for MockCredentialsProvider {
    async fn credentials(
        &self,
    ) -> Result<rusoto_core::credential::AwsCredentials, rusoto_core::credential::CredentialsError>
    {
        Ok(AwsCredentials::new("mock_key", "mock_secret", None, None))
    }
}

/// Composes mock API responses
///
/// A Default is provided which returns an successful response with an empty body
///
/// These can be constructed using either a Default implementation or
///  with the [with_status](method.with_status) function.
///
#[derive(Default)]
pub struct MockRequestDispatcher {
    outcome: RequestOutcome,
    body: Vec<u8>,
    headers: HeaderMap<String>,
    request_checker: Option<Box<dyn Fn(&SignedRequest) + Send + Sync>>,
}

enum RequestOutcome {
    Performed(StatusCode),
    Failed(HttpDispatchError),
}

impl Default for RequestOutcome {
    fn default() -> RequestOutcome {
        RequestOutcome::Performed(StatusCode::default())
    }
}

impl MockRequestDispatcher {
    /// Returns a instance that mocks the status code that would
    /// be returned from AWS
    pub fn with_status(status: u16) -> MockRequestDispatcher {
        MockRequestDispatcher {
            outcome: RequestOutcome::Performed(StatusCode::from_u16(status).unwrap()),
            ..MockRequestDispatcher::default()
        }
    }

    /// Mocks the service request failing with a communications error
    pub fn with_dispatch_error(error: HttpDispatchError) -> MockRequestDispatcher {
        MockRequestDispatcher {
            outcome: RequestOutcome::Failed(error),
            ..MockRequestDispatcher::default()
        }
    }

    /// Mocks the service response body what would be
    /// returned from AWS
    pub fn with_body(mut self, body: &str) -> MockRequestDispatcher {
        self.body = body.as_bytes().to_vec();
        self
    }

    /// Mocks the json serialized response body what would be
    /// returned from AWS
    pub fn with_json_body<B>(mut self, body: B) -> MockRequestDispatcher
    where
        B: Serialize,
    {
        self.body = serde_json::to_vec(&body).expect("failed to deserialize into json");
        self
    }

    /// Mocks the signed request checking applied to a request before sending
    /// to AWS
    pub fn with_request_checker<F>(mut self, checker: F) -> MockRequestDispatcher
    where
        F: Fn(&SignedRequest) + Send + Sync + 'static,
    {
        self.request_checker = Some(Box::new(checker));
        self
    }

    /// Mocks a single service header that would be returned from AWS
    pub fn with_header(mut self, key: &str, value: &str) -> MockRequestDispatcher {
        self.headers
            .insert(key.parse::<HeaderName>().unwrap(), value.into());
        self
    }
}

impl DispatchSignedRequest for MockRequestDispatcher {
    fn dispatch(
        &self,
        request: SignedRequest,
        _timeout: Option<Duration>,
    ) -> rusoto_core::request::DispatchSignedRequestFuture {
        if self.request_checker.is_some() {
            self.request_checker.as_ref().unwrap()(&request);
        }
        match self.outcome {
            RequestOutcome::Performed(ref status) => futures::future::ready(Ok(HttpResponse {
                status: *status,
                body: ByteStream::from(self.body.clone()),
                headers: self.headers.clone(),
            }))
            .boxed(),
            RequestOutcome::Failed(ref error) => futures::future::ready(Err(error.clone())).boxed(),
        }
    }
}

/// An interface for producing response body content
pub trait ReadMockResponse {
    /// Return a response body string for a given directory and file name
    fn read_response(dir_name: &str, file_name: &str) -> String;
}

/// Reads response body content from disk
pub struct MockResponseReader;

impl ReadMockResponse for MockResponseReader {
    fn read_response(dir_name: &str, response_name: &str) -> String {
        let file_name = format!("{}/{}", dir_name, response_name);

        let mut input_file = File::open(&file_name).expect("couldn't find file");

        let mut mock_response = String::new();

        input_file
            .read_to_string(&mut mock_response)
            .unwrap_or_else(|_| panic!("Failed to read {:?}", file_name));

        mock_response
    }
}

/// Returns sequential mock API responses consuming a collection of MockRequestDispatch
pub struct MultipleMockRequestDispatcher<I>
where
    I: Iterator<Item = MockRequestDispatcher>,
{
    iterator: I,
}

impl<I> MultipleMockRequestDispatcher<I>
where
    I: Iterator<Item = MockRequestDispatcher>,
{
    /// Constructs a new MultipleMockRequestDispatcher with a collection of MockRequestDispatch as input
    pub fn new<C>(collection: C) -> MultipleMockRequestDispatcher<I>
    where
        C: IntoIterator<Item = MockRequestDispatcher>,
        C: IntoIterator<IntoIter = I>,
    {
        MultipleMockRequestDispatcher {
            iterator: collection.into_iter(),
        }
    }
}

impl<I> DispatchSignedRequest for MultipleMockRequestDispatcher<I>
where
    I: Iterator<Item = MockRequestDispatcher>,
{
    fn dispatch(
        &self,
        request: SignedRequest,
        _timeout: Option<Duration>,
    ) -> rusoto_core::request::DispatchSignedRequestFuture {
        // Unsafe code required to increment iterator due to non-mutable &self
        unsafe {
            (*(self as *const Self as *mut Self))
                .iterator
                .next()
                .unwrap()
                .dispatch(request, _timeout)
        }
    }
}
<|endoftext|>


<commit_before>// Copyright 2018 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 depends on a patch that was committed to upstream LLVM
// before 7.0, then backported to the Rust LLVM fork.  It tests that
// optimized enum debug info accurately reflects the enum layout.

// ignore-tidy-linelength
// ignore-windows
// min-system-llvm-version 7.0

// compile-flags: -g -C no-prepopulate-passes

// CHECK-LABEL: @main
// CHECK: {{.*}}DICompositeType{{.*}}tag: DW_TAG_variant_part,{{.*}}discriminator:{{.*}}
// CHECK: {{.*}}DIDerivedType{{.*}}tag: DW_TAG_member,{{.*}}name: "A",{{.*}}extraData:{{.*}}
// CHECK: {{.*}}DICompositeType{{.*}}tag: DW_TAG_structure_type,{{.*}}name: "A",{{.*}}
// CHECK: {{.*}}DIDerivedType{{.*}}tag: DW_TAG_member,{{.*}}name: "B",{{.*}}extraData:{{.*}}
// CHECK: {{.*}}DICompositeType{{.*}}tag: DW_TAG_structure_type,{{.*}}name: "B",{{.*}}
// CHECK: {{.*}}DIDerivedType{{.*}}tag: DW_TAG_member,{{.*}}name: "C",{{.*}}extraData:{{.*}}
// CHECK: {{.*}}DICompositeType{{.*}}tag: DW_TAG_structure_type,{{.*}}name: "C",{{.*}}
// CHECK: {{.*}}DIDerivedType{{.*}}tag: DW_TAG_member,{{.*}}name: "D",{{.*}}
// CHECK: {{.*}}DICompositeType{{.*}}tag: DW_TAG_structure_type,{{.*}}name: "D",{{.*}}

#![allow(dead_code)]
#![allow(unused_variables)]
#![allow(unused_assignments)]

enum E { A, B, C, D(bool) }

pub fn main() {
    let e = E::D(true);
}
<commit_msg>Tighten enum-debug test<commit_after>// Copyright 2018 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 depends on a patch that was committed to upstream LLVM
// before 7.0, then backported to the Rust LLVM fork.  It tests that
// optimized enum debug info accurately reflects the enum layout.

// ignore-tidy-linelength
// ignore-windows
// min-system-llvm-version 7.0

// compile-flags: -g -C no-prepopulate-passes

// CHECK-LABEL: @main
// CHECK: {{.*}}DICompositeType{{.*}}tag: DW_TAG_variant_part,{{.*}}discriminator:{{.*}}
// CHECK: {{.*}}DIDerivedType{{.*}}tag: DW_TAG_member,{{.*}}name: "A",{{.*}}extraData:{{.*}}
// CHECK: {{.*}}DICompositeType{{.*}}tag: DW_TAG_structure_type,{{.*}}name: "A",{{.*}}
// CHECK: {{.*}}DIDerivedType{{.*}}tag: DW_TAG_member,{{.*}}name: "B",{{.*}}extraData:{{.*}}
// CHECK: {{.*}}DICompositeType{{.*}}tag: DW_TAG_structure_type,{{.*}}name: "B",{{.*}}
// CHECK: {{.*}}DIDerivedType{{.*}}tag: DW_TAG_member,{{.*}}name: "C",{{.*}}extraData:{{.*}}
// CHECK: {{.*}}DICompositeType{{.*}}tag: DW_TAG_structure_type,{{.*}}name: "C",{{.*}}
// CHECK-NOT: {{.*}}DIDerivedType{{.*}}name: "D",{{.*}}extraData:{{.*}}
// CHECK: {{.*}}DIDerivedType{{.*}}tag: DW_TAG_member,{{.*}}name: "D",{{.*}}
// CHECK: {{.*}}DICompositeType{{.*}}tag: DW_TAG_structure_type,{{.*}}name: "D",{{.*}}
// CHECK: {{.*}}DIDerivedType{{.*}}tag: DW_TAG_member,{{.*}}flags: DIFlagArtificial{{.*}}

#![allow(dead_code)]
#![allow(unused_variables)]
#![allow(unused_assignments)]

enum E { A, B, C, D(bool) }

pub fn main() {
    let e = E::D(true);
}
<|endoftext|>


<commit_before>/* PKCS#7 validation
 *
 * Dmitry Vasiliev <dima@hlabs.org>
 */

static AES_BLOCK_SIZE: u8 = 16;

fn remove_pkcs7_padding(data: &[u8]) -> Option<&[u8]> {
    let len = data.len();
    if (len == 0) || (len % AES_BLOCK_SIZE as uint != 0) {
        return None;
    }
    match data.last() {
        Some(&last) if last > 0 && last < AES_BLOCK_SIZE => {
            let data_len = len - last as uint;
            if data.slice_from(data_len).iter().all(|&c| c == last) {
                Some(data.slice_to(data_len))
            } else {
                None
            }
        }
        _ => None
    }
}

fn main() {
    let strings = [
        b"ICE ICE BABY\x04\x04\x04\x04",
        b"ICE ICE BABY\x05\x05\x05\x05",
        b"ICE ICE BABY\x01\x02\x03\x04",
    ];
    for &string in strings.iter() {
        print!("Input: {}, ", string);
        match remove_pkcs7_padding(string) {
            Some(stripped) => println!("Stripped: \"{}\"",
                String::from_utf8(stripped.to_vec()).unwrap()),
            None => println!("Invalid PKCS#7 padding")
        }
    }
}
<commit_msg>Optimize code<commit_after>/* PKCS#7 validation
 *
 * Dmitry Vasiliev <dima@hlabs.org>
 */

static AES_BLOCK_SIZE: u8 = 16;

fn remove_pkcs7_padding(data: &[u8]) -> Option<&[u8]> {
    let len = data.len();
    if (len == 0) || (len % AES_BLOCK_SIZE as uint != 0) {
        return None;
    }
    match data.last() {
        Some(&last) if last > 0 && last < AES_BLOCK_SIZE => {
            let data_len = len - last as uint;
            match data.slice_from(data_len).iter().all(|&c| c == last) {
                true => Some(data.slice_to(data_len)),
                false => None
            }
        }
        _ => None
    }
}

fn main() {
    let strings = [
        b"ICE ICE BABY\x04\x04\x04\x04",
        b"ICE ICE BABY\x05\x05\x05\x05",
        b"ICE ICE BABY\x01\x02\x03\x04",
    ];
    for &string in strings.iter() {
        print!("Input: {}, ", string);
        match remove_pkcs7_padding(string) {
            Some(stripped) => println!("Stripped: \"{}\"",
                String::from_utf8(stripped.to_vec()).unwrap()),
            None => println!("Invalid PKCS#7 padding")
        }
    }
}
<|endoftext|>


<commit_before>use crate::mir::interpret::{sign_extend, truncate, InterpErrorInfo, InterpResult};
use crate::throw_ub;
use rustc_apfloat::ieee::{Double, Single};
use rustc_apfloat::Float;
use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
use rustc_target::abi::{Size, TargetDataLayout};
use std::convert::{TryFrom, TryInto};
use std::fmt;

#[derive(Copy, Clone)]
/// A type for representing any integer. Only used for printing.
pub struct ConstInt {
    /// The "untyped" variant of `ConstInt`.
    int: ScalarInt,
    /// Whether the value is of a signed integer type.
    signed: bool,
    /// Whether the value is a `usize` or `isize` type.
    is_ptr_sized_integral: bool,
}

impl ConstInt {
    pub fn new(int: ScalarInt, signed: bool, is_ptr_sized_integral: bool) -> Self {
        Self { int, signed, is_ptr_sized_integral }
    }
}

impl std::fmt::Debug for ConstInt {
    fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        let Self { int, signed, is_ptr_sized_integral } = *self;
        let size = int.size().bytes();
        let raw = int.data;
        if signed {
            let bit_size = size * 8;
            let min = 1u128 << (bit_size - 1);
            let max = min - 1;
            if raw == min {
                match (size, is_ptr_sized_integral) {
                    (_, true) => write!(fmt, "isize::MIN"),
                    (1, _) => write!(fmt, "i8::MIN"),
                    (2, _) => write!(fmt, "i16::MIN"),
                    (4, _) => write!(fmt, "i32::MIN"),
                    (8, _) => write!(fmt, "i64::MIN"),
                    (16, _) => write!(fmt, "i128::MIN"),
                    _ => bug!("ConstInt 0x{:x} with size = {} and signed = {}", raw, size, signed),
                }
            } else if raw == max {
                match (size, is_ptr_sized_integral) {
                    (_, true) => write!(fmt, "isize::MAX"),
                    (1, _) => write!(fmt, "i8::MAX"),
                    (2, _) => write!(fmt, "i16::MAX"),
                    (4, _) => write!(fmt, "i32::MAX"),
                    (8, _) => write!(fmt, "i64::MAX"),
                    (16, _) => write!(fmt, "i128::MAX"),
                    _ => bug!("ConstInt 0x{:x} with size = {} and signed = {}", raw, size, signed),
                }
            } else {
                match size {
                    1 => write!(fmt, "{}", raw as i8)?,
                    2 => write!(fmt, "{}", raw as i16)?,
                    4 => write!(fmt, "{}", raw as i32)?,
                    8 => write!(fmt, "{}", raw as i64)?,
                    16 => write!(fmt, "{}", raw as i128)?,
                    _ => bug!("ConstInt 0x{:x} with size = {} and signed = {}", raw, size, signed),
                }
                if fmt.alternate() {
                    match (size, is_ptr_sized_integral) {
                        (_, true) => write!(fmt, "_isize")?,
                        (1, _) => write!(fmt, "_i8")?,
                        (2, _) => write!(fmt, "_i16")?,
                        (4, _) => write!(fmt, "_i32")?,
                        (8, _) => write!(fmt, "_i64")?,
                        (16, _) => write!(fmt, "_i128")?,
                        _ => bug!(),
                    }
                }
                Ok(())
            }
        } else {
            let max = truncate(u128::MAX, Size::from_bytes(size));
            if raw == max {
                match (size, is_ptr_sized_integral) {
                    (_, true) => write!(fmt, "usize::MAX"),
                    (1, _) => write!(fmt, "u8::MAX"),
                    (2, _) => write!(fmt, "u16::MAX"),
                    (4, _) => write!(fmt, "u32::MAX"),
                    (8, _) => write!(fmt, "u64::MAX"),
                    (16, _) => write!(fmt, "u128::MAX"),
                    _ => bug!("ConstInt 0x{:x} with size = {} and signed = {}", raw, size, signed),
                }
            } else {
                match size {
                    1 => write!(fmt, "{}", raw as u8)?,
                    2 => write!(fmt, "{}", raw as u16)?,
                    4 => write!(fmt, "{}", raw as u32)?,
                    8 => write!(fmt, "{}", raw as u64)?,
                    16 => write!(fmt, "{}", raw as u128)?,
                    _ => bug!("ConstInt 0x{:x} with size = {} and signed = {}", raw, size, signed),
                }
                if fmt.alternate() {
                    match (size, is_ptr_sized_integral) {
                        (_, true) => write!(fmt, "_usize")?,
                        (1, _) => write!(fmt, "_u8")?,
                        (2, _) => write!(fmt, "_u16")?,
                        (4, _) => write!(fmt, "_u32")?,
                        (8, _) => write!(fmt, "_u64")?,
                        (16, _) => write!(fmt, "_u128")?,
                        _ => bug!(),
                    }
                }
                Ok(())
            }
        }
    }
}

/// The raw bytes of a simple value.
///
/// This is a packed struct in order to allow this type to be optimally embedded in enums
/// (like Scalar).
#[derive(Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash)]
#[repr(packed)]
pub struct ScalarInt {
    /// The first `size` bytes of `data` are the value.
    /// Do not try to read less or more bytes than that. The remaining bytes must be 0.
    data: u128,
    size: u8,
}

// Cannot derive these, as the derives take references to the fields, and we
// can't take references to fields of packed structs.
impl<CTX> crate::ty::HashStable<CTX> for ScalarInt {
    fn hash_stable(&self, hcx: &mut CTX, hasher: &mut crate::ty::StableHasher) {
        // Using a block `{self.data}` here to force a copy instead of using `self.data`
        // directly, because `hash_stable` takes `&self` and would thus borrow `self.data`.
        // Since `Self` is a packed struct, that would create a possibly unaligned reference,
        // which is UB.
        { self.data }.hash_stable(hcx, hasher);
        self.size.hash_stable(hcx, hasher);
    }
}

impl<S: Encoder> Encodable<S> for ScalarInt {
    fn encode(&self, s: &mut S) -> Result<(), S::Error> {
        s.emit_u128(self.data)?;
        s.emit_u8(self.size)
    }
}

impl<D: Decoder> Decodable<D> for ScalarInt {
    fn decode(d: &mut D) -> Result<ScalarInt, D::Error> {
        Ok(ScalarInt { data: d.read_u128()?, size: d.read_u8()? })
    }
}

impl ScalarInt {
    pub const TRUE: ScalarInt = ScalarInt { data: 1_u128, size: 1 };

    pub const FALSE: ScalarInt = ScalarInt { data: 0_u128, size: 1 };

    pub const ZST: ScalarInt = ScalarInt { data: 0_u128, size: 0 };

    #[inline]
    pub fn size(self) -> Size {
        Size::from_bytes(self.size)
    }

    /// Make sure the `data` fits in `size`.
    /// This is guaranteed by all constructors here, but since the enum variants are public,
    /// it could still be violated (even though no code outside this file should
    /// construct `Scalar`s).
    #[inline(always)]
    fn check_data(self) {
        // Using a block `{self.data}` here to force a copy instead of using `self.data`
        // directly, because `assert_eq` takes references to its arguments and formatting
        // arguments and would thus borrow `self.data`. Since `Self`
        // is a packed struct, that would create a possibly unaligned reference, which
        // is UB.
        debug_assert_eq!(
            truncate(self.data, self.size()),
            { self.data },
            "Scalar value {:#x} exceeds size of {} bytes",
            { self.data },
            self.size
        );
    }

    #[inline]
    pub fn zst() -> Self {
        Self::null(Size::ZERO)
    }

    #[inline]
    pub fn null(size: Size) -> Self {
        Self { data: 0, size: size.bytes() as u8 }
    }

    pub(crate) fn ptr_sized_op<'tcx>(
        self,
        dl: &TargetDataLayout,
        f_int: impl FnOnce(u64) -> InterpResult<'tcx, u64>,
    ) -> InterpResult<'tcx, Self> {
        assert_eq!(u64::from(self.size), dl.pointer_size.bytes());
        Ok(Self { data: u128::from(f_int(u64::try_from(self.data).unwrap())?), size: self.size })
    }

    #[inline]
    pub fn try_from_uint(i: impl Into<u128>, size: Size) -> Option<Self> {
        let data = i.into();
        if truncate(data, size) == data {
            Some(Self { data, size: size.bytes() as u8 })
        } else {
            None
        }
    }

    #[inline]
    pub fn try_from_int(i: impl Into<i128>, size: Size) -> Option<Self> {
        let i = i.into();
        // `into` performed sign extension, we have to truncate
        let truncated = truncate(i as u128, size);
        if sign_extend(truncated, size) as i128 == i {
            Some(Self { data: truncated, size: size.bytes() as u8 })
        } else {
            None
        }
    }

    #[inline]
    pub fn assert_bits(self, target_size: Size) -> u128 {
        assert_ne!(target_size.bytes(), 0, "you should never look at the bits of a ZST");
        assert_eq!(target_size.bytes(), u64::from(self.size));
        self.check_data();
        self.data
    }

    #[inline]
    pub fn to_bits(self, target_size: Size) -> InterpResult<'static, u128> {
        assert_ne!(target_size.bytes(), 0, "you should never look at the bits of a ZST");
        if target_size.bytes() != u64::from(self.size) {
            throw_ub!(ScalarSizeMismatch {
                target_size: target_size.bytes(),
                data_size: u64::from(self.size),
            });
        }
        self.check_data();
        Ok(self.data)
    }
}

macro_rules! from {
    ($($ty:ty),*) => {
        $(
            impl From<$ty> for ScalarInt {
                #[inline]
                fn from(u: $ty) -> Self {
                    Self {
                        data: u128::from(u),
                        size: std::mem::size_of::<$ty>() as u8,
                    }
                }
            }
        )*
    }
}

macro_rules! try_from {
    ($($ty:ty),*) => {
        $(
            impl TryFrom<ScalarInt> for $ty {
                type Error = InterpErrorInfo<'static>;
                #[inline]
                fn try_from(int: ScalarInt) -> InterpResult<'static, Self> {
                    int.to_bits(Size::from_bytes(std::mem::size_of::<$ty>())).map(|u| u.try_into().unwrap())
                }
            }
        )*
    }
}

from!(u8, u16, u32, u64, u128, bool);
try_from!(u8, u16, u32, u64, u128);

impl From<char> for ScalarInt {
    #[inline]
    fn from(c: char) -> Self {
        Self { data: c as u128, size: std::mem::size_of::<char>() as u8 }
    }
}

impl TryFrom<ScalarInt> for char {
    type Error = InterpErrorInfo<'static>;
    #[inline]
    fn try_from(int: ScalarInt) -> InterpResult<'static, Self> {
        int.to_bits(Size::from_bytes(std::mem::size_of::<char>()))
            .map(|u| char::from_u32(u.try_into().unwrap()).unwrap())
    }
}

impl From<Single> for ScalarInt {
    #[inline]
    fn from(f: Single) -> Self {
        // We trust apfloat to give us properly truncated data.
        Self { data: f.to_bits(), size: 4 }
    }
}

impl TryFrom<ScalarInt> for Single {
    type Error = InterpErrorInfo<'static>;
    #[inline]
    fn try_from(int: ScalarInt) -> InterpResult<'static, Self> {
        int.to_bits(Size::from_bytes(4)).map(Self::from_bits)
    }
}

impl From<Double> for ScalarInt {
    #[inline]
    fn from(f: Double) -> Self {
        // We trust apfloat to give us properly truncated data.
        Self { data: f.to_bits(), size: 8 }
    }
}

impl TryFrom<ScalarInt> for Double {
    type Error = InterpErrorInfo<'static>;
    #[inline]
    fn try_from(int: ScalarInt) -> InterpResult<'static, Self> {
        int.to_bits(Size::from_bytes(8)).map(Self::from_bits)
    }
}

impl fmt::Debug for ScalarInt {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        if self.size == 0 {
            self.check_data();
            write!(f, "<ZST>")
        } else {
            write!(f, "0x{:x}", self)
        }
    }
}

impl fmt::LowerHex for ScalarInt {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        self.check_data();
        // Format as hex number wide enough to fit any value of the given `size`.
        // So data=20, size=1 will be "0x14", but with size=4 it'll be "0x00000014".
        // Using a block `{self.data}` here to force a copy instead of using `self.data`
        // directly, because `write!` takes references to its formatting arguments and
        // would thus borrow `self.data`. Since `Self`
        // is a packed struct, that would create a possibly unaligned reference, which
        // is UB.
        write!(f, "{:01$x}", { self.data }, self.size as usize * 2)
    }
}

impl fmt::UpperHex for ScalarInt {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        self.check_data();
        // Format as hex number wide enough to fit any value of the given `size`.
        // So data=20, size=1 will be "0x14", but with size=4 it'll be "0x00000014".
        // Using a block `{self.data}` here to force a copy instead of using `self.data`
        // directly, because `write!` takes references to its formatting arguments and
        // would thus borrow `self.data`. Since `Self`
        // is a packed struct, that would create a possibly unaligned reference, which
        // is UB.
        write!(f, "{:01$X}", { self.data }, self.size as usize * 2)
    }
}
<commit_msg>Update comment<commit_after>use crate::mir::interpret::{sign_extend, truncate, InterpErrorInfo, InterpResult};
use crate::throw_ub;
use rustc_apfloat::ieee::{Double, Single};
use rustc_apfloat::Float;
use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
use rustc_target::abi::{Size, TargetDataLayout};
use std::convert::{TryFrom, TryInto};
use std::fmt;

#[derive(Copy, Clone)]
/// A type for representing any integer. Only used for printing.
pub struct ConstInt {
    /// The "untyped" variant of `ConstInt`.
    int: ScalarInt,
    /// Whether the value is of a signed integer type.
    signed: bool,
    /// Whether the value is a `usize` or `isize` type.
    is_ptr_sized_integral: bool,
}

impl ConstInt {
    pub fn new(int: ScalarInt, signed: bool, is_ptr_sized_integral: bool) -> Self {
        Self { int, signed, is_ptr_sized_integral }
    }
}

impl std::fmt::Debug for ConstInt {
    fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        let Self { int, signed, is_ptr_sized_integral } = *self;
        let size = int.size().bytes();
        let raw = int.data;
        if signed {
            let bit_size = size * 8;
            let min = 1u128 << (bit_size - 1);
            let max = min - 1;
            if raw == min {
                match (size, is_ptr_sized_integral) {
                    (_, true) => write!(fmt, "isize::MIN"),
                    (1, _) => write!(fmt, "i8::MIN"),
                    (2, _) => write!(fmt, "i16::MIN"),
                    (4, _) => write!(fmt, "i32::MIN"),
                    (8, _) => write!(fmt, "i64::MIN"),
                    (16, _) => write!(fmt, "i128::MIN"),
                    _ => bug!("ConstInt 0x{:x} with size = {} and signed = {}", raw, size, signed),
                }
            } else if raw == max {
                match (size, is_ptr_sized_integral) {
                    (_, true) => write!(fmt, "isize::MAX"),
                    (1, _) => write!(fmt, "i8::MAX"),
                    (2, _) => write!(fmt, "i16::MAX"),
                    (4, _) => write!(fmt, "i32::MAX"),
                    (8, _) => write!(fmt, "i64::MAX"),
                    (16, _) => write!(fmt, "i128::MAX"),
                    _ => bug!("ConstInt 0x{:x} with size = {} and signed = {}", raw, size, signed),
                }
            } else {
                match size {
                    1 => write!(fmt, "{}", raw as i8)?,
                    2 => write!(fmt, "{}", raw as i16)?,
                    4 => write!(fmt, "{}", raw as i32)?,
                    8 => write!(fmt, "{}", raw as i64)?,
                    16 => write!(fmt, "{}", raw as i128)?,
                    _ => bug!("ConstInt 0x{:x} with size = {} and signed = {}", raw, size, signed),
                }
                if fmt.alternate() {
                    match (size, is_ptr_sized_integral) {
                        (_, true) => write!(fmt, "_isize")?,
                        (1, _) => write!(fmt, "_i8")?,
                        (2, _) => write!(fmt, "_i16")?,
                        (4, _) => write!(fmt, "_i32")?,
                        (8, _) => write!(fmt, "_i64")?,
                        (16, _) => write!(fmt, "_i128")?,
                        _ => bug!(),
                    }
                }
                Ok(())
            }
        } else {
            let max = truncate(u128::MAX, Size::from_bytes(size));
            if raw == max {
                match (size, is_ptr_sized_integral) {
                    (_, true) => write!(fmt, "usize::MAX"),
                    (1, _) => write!(fmt, "u8::MAX"),
                    (2, _) => write!(fmt, "u16::MAX"),
                    (4, _) => write!(fmt, "u32::MAX"),
                    (8, _) => write!(fmt, "u64::MAX"),
                    (16, _) => write!(fmt, "u128::MAX"),
                    _ => bug!("ConstInt 0x{:x} with size = {} and signed = {}", raw, size, signed),
                }
            } else {
                match size {
                    1 => write!(fmt, "{}", raw as u8)?,
                    2 => write!(fmt, "{}", raw as u16)?,
                    4 => write!(fmt, "{}", raw as u32)?,
                    8 => write!(fmt, "{}", raw as u64)?,
                    16 => write!(fmt, "{}", raw as u128)?,
                    _ => bug!("ConstInt 0x{:x} with size = {} and signed = {}", raw, size, signed),
                }
                if fmt.alternate() {
                    match (size, is_ptr_sized_integral) {
                        (_, true) => write!(fmt, "_usize")?,
                        (1, _) => write!(fmt, "_u8")?,
                        (2, _) => write!(fmt, "_u16")?,
                        (4, _) => write!(fmt, "_u32")?,
                        (8, _) => write!(fmt, "_u64")?,
                        (16, _) => write!(fmt, "_u128")?,
                        _ => bug!(),
                    }
                }
                Ok(())
            }
        }
    }
}

/// The raw bytes of a simple value.
///
/// This is a packed struct in order to allow this type to be optimally embedded in enums
/// (like Scalar).
#[derive(Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash)]
#[repr(packed)]
pub struct ScalarInt {
    /// The first `size` bytes of `data` are the value.
    /// Do not try to read less or more bytes than that. The remaining bytes must be 0.
    data: u128,
    size: u8,
}

// Cannot derive these, as the derives take references to the fields, and we
// can't take references to fields of packed structs.
impl<CTX> crate::ty::HashStable<CTX> for ScalarInt {
    fn hash_stable(&self, hcx: &mut CTX, hasher: &mut crate::ty::StableHasher) {
        // Using a block `{self.data}` here to force a copy instead of using `self.data`
        // directly, because `hash_stable` takes `&self` and would thus borrow `self.data`.
        // Since `Self` is a packed struct, that would create a possibly unaligned reference,
        // which is UB.
        { self.data }.hash_stable(hcx, hasher);
        self.size.hash_stable(hcx, hasher);
    }
}

impl<S: Encoder> Encodable<S> for ScalarInt {
    fn encode(&self, s: &mut S) -> Result<(), S::Error> {
        s.emit_u128(self.data)?;
        s.emit_u8(self.size)
    }
}

impl<D: Decoder> Decodable<D> for ScalarInt {
    fn decode(d: &mut D) -> Result<ScalarInt, D::Error> {
        Ok(ScalarInt { data: d.read_u128()?, size: d.read_u8()? })
    }
}

impl ScalarInt {
    pub const TRUE: ScalarInt = ScalarInt { data: 1_u128, size: 1 };

    pub const FALSE: ScalarInt = ScalarInt { data: 0_u128, size: 1 };

    pub const ZST: ScalarInt = ScalarInt { data: 0_u128, size: 0 };

    #[inline]
    pub fn size(self) -> Size {
        Size::from_bytes(self.size)
    }

    /// Make sure the `data` fits in `size`.
    /// This is guaranteed by all constructors here, but having had this check saved us from
    /// bugs many times in the past, so keeping it around is definitely worth it.
    #[inline(always)]
    fn check_data(self) {
        // Using a block `{self.data}` here to force a copy instead of using `self.data`
        // directly, because `assert_eq` takes references to its arguments and formatting
        // arguments and would thus borrow `self.data`. Since `Self`
        // is a packed struct, that would create a possibly unaligned reference, which
        // is UB.
        debug_assert_eq!(
            truncate(self.data, self.size()),
            { self.data },
            "Scalar value {:#x} exceeds size of {} bytes",
            { self.data },
            self.size
        );
    }

    #[inline]
    pub fn zst() -> Self {
        Self::null(Size::ZERO)
    }

    #[inline]
    pub fn null(size: Size) -> Self {
        Self { data: 0, size: size.bytes() as u8 }
    }

    pub(crate) fn ptr_sized_op<'tcx>(
        self,
        dl: &TargetDataLayout,
        f_int: impl FnOnce(u64) -> InterpResult<'tcx, u64>,
    ) -> InterpResult<'tcx, Self> {
        assert_eq!(u64::from(self.size), dl.pointer_size.bytes());
        Ok(Self { data: u128::from(f_int(u64::try_from(self.data).unwrap())?), size: self.size })
    }

    #[inline]
    pub fn try_from_uint(i: impl Into<u128>, size: Size) -> Option<Self> {
        let data = i.into();
        if truncate(data, size) == data {
            Some(Self { data, size: size.bytes() as u8 })
        } else {
            None
        }
    }

    #[inline]
    pub fn try_from_int(i: impl Into<i128>, size: Size) -> Option<Self> {
        let i = i.into();
        // `into` performed sign extension, we have to truncate
        let truncated = truncate(i as u128, size);
        if sign_extend(truncated, size) as i128 == i {
            Some(Self { data: truncated, size: size.bytes() as u8 })
        } else {
            None
        }
    }

    #[inline]
    pub fn assert_bits(self, target_size: Size) -> u128 {
        assert_ne!(target_size.bytes(), 0, "you should never look at the bits of a ZST");
        assert_eq!(target_size.bytes(), u64::from(self.size));
        self.check_data();
        self.data
    }

    #[inline]
    pub fn to_bits(self, target_size: Size) -> InterpResult<'static, u128> {
        assert_ne!(target_size.bytes(), 0, "you should never look at the bits of a ZST");
        if target_size.bytes() != u64::from(self.size) {
            throw_ub!(ScalarSizeMismatch {
                target_size: target_size.bytes(),
                data_size: u64::from(self.size),
            });
        }
        self.check_data();
        Ok(self.data)
    }
}

macro_rules! from {
    ($($ty:ty),*) => {
        $(
            impl From<$ty> for ScalarInt {
                #[inline]
                fn from(u: $ty) -> Self {
                    Self {
                        data: u128::from(u),
                        size: std::mem::size_of::<$ty>() as u8,
                    }
                }
            }
        )*
    }
}

macro_rules! try_from {
    ($($ty:ty),*) => {
        $(
            impl TryFrom<ScalarInt> for $ty {
                type Error = InterpErrorInfo<'static>;
                #[inline]
                fn try_from(int: ScalarInt) -> InterpResult<'static, Self> {
                    int.to_bits(Size::from_bytes(std::mem::size_of::<$ty>())).map(|u| u.try_into().unwrap())
                }
            }
        )*
    }
}

from!(u8, u16, u32, u64, u128, bool);
try_from!(u8, u16, u32, u64, u128);

impl From<char> for ScalarInt {
    #[inline]
    fn from(c: char) -> Self {
        Self { data: c as u128, size: std::mem::size_of::<char>() as u8 }
    }
}

impl TryFrom<ScalarInt> for char {
    type Error = InterpErrorInfo<'static>;
    #[inline]
    fn try_from(int: ScalarInt) -> InterpResult<'static, Self> {
        int.to_bits(Size::from_bytes(std::mem::size_of::<char>()))
            .map(|u| char::from_u32(u.try_into().unwrap()).unwrap())
    }
}

impl From<Single> for ScalarInt {
    #[inline]
    fn from(f: Single) -> Self {
        // We trust apfloat to give us properly truncated data.
        Self { data: f.to_bits(), size: 4 }
    }
}

impl TryFrom<ScalarInt> for Single {
    type Error = InterpErrorInfo<'static>;
    #[inline]
    fn try_from(int: ScalarInt) -> InterpResult<'static, Self> {
        int.to_bits(Size::from_bytes(4)).map(Self::from_bits)
    }
}

impl From<Double> for ScalarInt {
    #[inline]
    fn from(f: Double) -> Self {
        // We trust apfloat to give us properly truncated data.
        Self { data: f.to_bits(), size: 8 }
    }
}

impl TryFrom<ScalarInt> for Double {
    type Error = InterpErrorInfo<'static>;
    #[inline]
    fn try_from(int: ScalarInt) -> InterpResult<'static, Self> {
        int.to_bits(Size::from_bytes(8)).map(Self::from_bits)
    }
}

impl fmt::Debug for ScalarInt {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        if self.size == 0 {
            self.check_data();
            write!(f, "<ZST>")
        } else {
            write!(f, "0x{:x}", self)
        }
    }
}

impl fmt::LowerHex for ScalarInt {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        self.check_data();
        // Format as hex number wide enough to fit any value of the given `size`.
        // So data=20, size=1 will be "0x14", but with size=4 it'll be "0x00000014".
        // Using a block `{self.data}` here to force a copy instead of using `self.data`
        // directly, because `write!` takes references to its formatting arguments and
        // would thus borrow `self.data`. Since `Self`
        // is a packed struct, that would create a possibly unaligned reference, which
        // is UB.
        write!(f, "{:01$x}", { self.data }, self.size as usize * 2)
    }
}

impl fmt::UpperHex for ScalarInt {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        self.check_data();
        // Format as hex number wide enough to fit any value of the given `size`.
        // So data=20, size=1 will be "0x14", but with size=4 it'll be "0x00000014".
        // Using a block `{self.data}` here to force a copy instead of using `self.data`
        // directly, because `write!` takes references to its formatting arguments and
        // would thus borrow `self.data`. Since `Self`
        // is a packed struct, that would create a possibly unaligned reference, which
        // is UB.
        write!(f, "{:01$X}", { self.data }, self.size as usize * 2)
    }
}
<|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::EventBinding::EventMethods;
use dom::bindings::codegen::Bindings::ExtendableEventBinding;
use dom::bindings::error::{Error, ErrorResult, Fallible};
use dom::bindings::global::GlobalRef;
use dom::bindings::inheritance::Castable;
use dom::bindings::js::Root;
use dom::bindings::reflector::reflect_dom_object;
use dom::bindings::str::DOMString;
use dom::event::Event;
use js::jsapi::{HandleValue, JSContext};
use string_cache::Atom;

// https://w3c.github.io/ServiceWorker/#extendable-event
#[dom_struct]
pub struct ExtendableEvent {
    event: Event,
    extensions_allowed: bool
}

impl ExtendableEvent {
    pub fn new_inherited() -> ExtendableEvent {
        ExtendableEvent {
            event: Event::new_inherited(),
            extensions_allowed: true
        }
    }
    pub fn new(global: GlobalRef,
               type_: Atom,
               bubbles: bool,
               cancelable: bool)
               -> Root<ExtendableEvent> {
        let ev = reflect_dom_object(box ExtendableEvent::new_inherited(), global, ExtendableEventBinding::Wrap);
        {
            let event = ev.upcast::<Event>();
            event.init_event(type_, bubbles, cancelable);
        }
        ev
    }

    pub fn Constructor(global: GlobalRef,
                       type_: DOMString,
                       init: &ExtendableEventBinding::ExtendableEventInit) -> Fallible<Root<ExtendableEvent>> {
        Ok(ExtendableEvent::new(global,
                                Atom::from(type_),
                                init.parent.bubbles,
                                init.parent.cancelable))
    }

    // https://w3c.github.io/ServiceWorker/#wait-until-method
    pub fn WaitUntil(&self, _cx: *mut JSContext, val: HandleValue) -> ErrorResult {
        // Step 1
        if !self.extensions_allowed {
            return Err(Error::InvalidState);
        }
        // Step 2
        // TODO add a extended_promises array to enqueue the `val`
        Ok(())
    }

    // https://dom.spec.whatwg.org/#dom-event-istrusted
    pub fn IsTrusted(&self) -> bool {
        self.event.IsTrusted()
    }
}
<commit_msg>Silence a warning in ExtendableEvent::WaitUntil<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::EventBinding::EventMethods;
use dom::bindings::codegen::Bindings::ExtendableEventBinding;
use dom::bindings::error::{Error, ErrorResult, Fallible};
use dom::bindings::global::GlobalRef;
use dom::bindings::inheritance::Castable;
use dom::bindings::js::Root;
use dom::bindings::reflector::reflect_dom_object;
use dom::bindings::str::DOMString;
use dom::event::Event;
use js::jsapi::{HandleValue, JSContext};
use string_cache::Atom;

// https://w3c.github.io/ServiceWorker/#extendable-event
#[dom_struct]
pub struct ExtendableEvent {
    event: Event,
    extensions_allowed: bool
}

impl ExtendableEvent {
    pub fn new_inherited() -> ExtendableEvent {
        ExtendableEvent {
            event: Event::new_inherited(),
            extensions_allowed: true
        }
    }
    pub fn new(global: GlobalRef,
               type_: Atom,
               bubbles: bool,
               cancelable: bool)
               -> Root<ExtendableEvent> {
        let ev = reflect_dom_object(box ExtendableEvent::new_inherited(), global, ExtendableEventBinding::Wrap);
        {
            let event = ev.upcast::<Event>();
            event.init_event(type_, bubbles, cancelable);
        }
        ev
    }

    pub fn Constructor(global: GlobalRef,
                       type_: DOMString,
                       init: &ExtendableEventBinding::ExtendableEventInit) -> Fallible<Root<ExtendableEvent>> {
        Ok(ExtendableEvent::new(global,
                                Atom::from(type_),
                                init.parent.bubbles,
                                init.parent.cancelable))
    }

    // https://w3c.github.io/ServiceWorker/#wait-until-method
    pub fn WaitUntil(&self, _cx: *mut JSContext, _val: HandleValue) -> ErrorResult {
        // Step 1
        if !self.extensions_allowed {
            return Err(Error::InvalidState);
        }
        // Step 2
        // TODO add a extended_promises array to enqueue the `val`
        Ok(())
    }

    // https://dom.spec.whatwg.org/#dom-event-istrusted
    pub fn IsTrusted(&self) -> bool {
        self.event.IsTrusted()
    }
}
<|endoftext|>


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

use llvm::{AvailableExternallyLinkage, InternalLinkage, SetLinkage};
use middle::cstore::{CrateStore, FoundAst, InlinedItem};
use middle::def_id::DefId;
use middle::subst::Substs;
use trans::base::{push_ctxt, trans_item, trans_fn};
use trans::callee::Callee;
use trans::common::*;

use rustc::dep_graph::DepNode;
use rustc_front::hir;

fn instantiate_inline(ccx: &CrateContext, fn_id: DefId) -> Option<DefId> {
    debug!("instantiate_inline({:?})", fn_id);
    let _icx = push_ctxt("instantiate_inline");
    let tcx = ccx.tcx();
    let _task = tcx.dep_graph.in_task(DepNode::TransInlinedItem(fn_id));

    match ccx.external().borrow().get(&fn_id) {
        Some(&Some(node_id)) => {
            // Already inline
            debug!("instantiate_inline({}): already inline as node id {}",
                   tcx.item_path_str(fn_id), node_id);
            let node_def_id = tcx.map.local_def_id(node_id);
            return Some(node_def_id);
        }
        Some(&None) => {
            return None; // Not inlinable
        }
        None => {
            // Not seen yet
        }
    }

    let inlined = tcx.sess.cstore.maybe_get_item_ast(tcx, fn_id);
    let inline_id = match inlined {
        FoundAst::NotFound => {
            ccx.external().borrow_mut().insert(fn_id, None);
            return None;
        }
        FoundAst::Found(&InlinedItem::Item(ref item)) => {
            ccx.external().borrow_mut().insert(fn_id, Some(item.id));
            ccx.external_srcs().borrow_mut().insert(item.id, fn_id);

            ccx.stats().n_inlines.set(ccx.stats().n_inlines.get() + 1);
            trans_item(ccx, item);

            if let hir::ItemFn(_, _, _, _, ref generics, _) = item.node {
                // Generics have no symbol, so they can't be given any linkage.
                if !generics.is_type_parameterized() {
                    let linkage = if ccx.sess().opts.cg.codegen_units == 1 {
                        // We could use AvailableExternallyLinkage here,
                        // but InternalLinkage allows LLVM to optimize more
                        // aggressively (at the cost of sometimes
                        // duplicating code).
                        InternalLinkage
                    } else {
                        // With multiple compilation units, duplicated code
                        // is more of a problem.  Also, `codegen_units > 1`
                        // means the user is okay with losing some
                        // performance.
                        AvailableExternallyLinkage
                    };
                    let empty_substs = tcx.mk_substs(Substs::empty());
                    let def_id = tcx.map.local_def_id(item.id);
                    let llfn = Callee::def(ccx, def_id, empty_substs).reify(ccx).val;
                    SetLinkage(llfn, linkage);
                }
            }

            item.id
        }
        FoundAst::Found(&InlinedItem::Foreign(ref item)) => {
            ccx.external().borrow_mut().insert(fn_id, Some(item.id));
            ccx.external_srcs().borrow_mut().insert(item.id, fn_id);
            item.id
        }
        FoundAst::FoundParent(parent_id, item) => {
            ccx.external().borrow_mut().insert(parent_id, Some(item.id));
            ccx.external_srcs().borrow_mut().insert(item.id, parent_id);

            let mut my_id = 0;
            match item.node {
                hir::ItemEnum(ref ast_def, _) => {
                    let ast_vs = &ast_def.variants;
                    let ty_vs = &tcx.lookup_adt_def(parent_id).variants;
                    assert_eq!(ast_vs.len(), ty_vs.len());
                    for (ast_v, ty_v) in ast_vs.iter().zip(ty_vs.iter()) {
                        if ty_v.did == fn_id { my_id = ast_v.node.data.id(); }
                        ccx.external().borrow_mut().insert(ty_v.did, Some(ast_v.node.data.id()));
                    }
                }
                hir::ItemStruct(ref struct_def, _) => {
                    if struct_def.is_struct() {
                        ccx.sess().bug("instantiate_inline: called on a \
                                                                 non-tuple struct")
                    } else {
                        ccx.external().borrow_mut().insert(fn_id, Some(struct_def.id()));
                        my_id = struct_def.id();
                    }
                }
                _ => ccx.sess().bug("instantiate_inline: item has a \
                                 non-enum, non-struct parent")
            }
            my_id
        }
        FoundAst::Found(&InlinedItem::TraitItem(_, ref trait_item)) => {
            ccx.external().borrow_mut().insert(fn_id, Some(trait_item.id));
            ccx.external_srcs().borrow_mut().insert(trait_item.id, fn_id);

            ccx.stats().n_inlines.set(ccx.stats().n_inlines.get() + 1);

            // Associated consts already have to be evaluated in `typeck`, so
            // the logic to do that already exists in `middle`. In order to
            // reuse that code, it needs to be able to look up the traits for
            // inlined items.
            let ty_trait_item = tcx.impl_or_trait_item(fn_id).clone();
            let trait_item_def_id = tcx.map.local_def_id(trait_item.id);
            tcx.impl_or_trait_items.borrow_mut()
               .insert(trait_item_def_id, ty_trait_item);

            // If this is a default method, we can't look up the
            // impl type. But we aren't going to translate anyways, so
            // don't.
            trait_item.id
        }
        FoundAst::Found(&InlinedItem::ImplItem(impl_did, ref impl_item)) => {
            ccx.external().borrow_mut().insert(fn_id, Some(impl_item.id));
            ccx.external_srcs().borrow_mut().insert(impl_item.id, fn_id);

            ccx.stats().n_inlines.set(ccx.stats().n_inlines.get() + 1);

            // Translate monomorphic impl methods immediately.
            if let hir::ImplItemKind::Method(ref sig, ref body) = impl_item.node {
                let impl_tpt = tcx.lookup_item_type(impl_did);
                if impl_tpt.generics.types.is_empty() &&
                        sig.generics.ty_params.is_empty() {
                    let def_id = tcx.map.local_def_id(impl_item.id);
                    let empty_substs = ccx.empty_substs_for_def_id(def_id);
                    let llfn = Callee::def(ccx, def_id, empty_substs).reify(ccx).val;
                    trans_fn(ccx,
                             &sig.decl,
                             body,
                             llfn,
                             empty_substs,
                             impl_item.id);
                    // See linkage comments on items.
                    if ccx.sess().opts.cg.codegen_units == 1 {
                        SetLinkage(llfn, InternalLinkage);
                    } else {
                        SetLinkage(llfn, AvailableExternallyLinkage);
                    }
                }
            }

            impl_item.id
        }
    };

    let inline_def_id = tcx.map.local_def_id(inline_id);
    Some(inline_def_id)
}

pub fn get_local_instance(ccx: &CrateContext, fn_id: DefId)
    -> Option<DefId> {
    if let Some(_) = ccx.tcx().map.as_local_node_id(fn_id) {
        Some(fn_id)
    } else {
        instantiate_inline(ccx, fn_id)
    }
}

pub fn maybe_instantiate_inline(ccx: &CrateContext, fn_id: DefId) -> DefId {
    get_local_instance(ccx, fn_id).unwrap_or(fn_id)
}
<commit_msg>Add missing entries for enum variants in trans::CrateContext::external_srcs.<commit_after>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use llvm::{AvailableExternallyLinkage, InternalLinkage, SetLinkage};
use middle::cstore::{CrateStore, FoundAst, InlinedItem};
use middle::def_id::DefId;
use middle::subst::Substs;
use trans::base::{push_ctxt, trans_item, trans_fn};
use trans::callee::Callee;
use trans::common::*;

use rustc::dep_graph::DepNode;
use rustc_front::hir;

fn instantiate_inline(ccx: &CrateContext, fn_id: DefId) -> Option<DefId> {
    debug!("instantiate_inline({:?})", fn_id);
    let _icx = push_ctxt("instantiate_inline");
    let tcx = ccx.tcx();
    let _task = tcx.dep_graph.in_task(DepNode::TransInlinedItem(fn_id));

    match ccx.external().borrow().get(&fn_id) {
        Some(&Some(node_id)) => {
            // Already inline
            debug!("instantiate_inline({}): already inline as node id {}",
                   tcx.item_path_str(fn_id), node_id);
            let node_def_id = tcx.map.local_def_id(node_id);
            return Some(node_def_id);
        }
        Some(&None) => {
            return None; // Not inlinable
        }
        None => {
            // Not seen yet
        }
    }

    let inlined = tcx.sess.cstore.maybe_get_item_ast(tcx, fn_id);
    let inline_id = match inlined {
        FoundAst::NotFound => {
            ccx.external().borrow_mut().insert(fn_id, None);
            return None;
        }
        FoundAst::Found(&InlinedItem::Item(ref item)) => {
            ccx.external().borrow_mut().insert(fn_id, Some(item.id));
            ccx.external_srcs().borrow_mut().insert(item.id, fn_id);

            ccx.stats().n_inlines.set(ccx.stats().n_inlines.get() + 1);
            trans_item(ccx, item);

            if let hir::ItemFn(_, _, _, _, ref generics, _) = item.node {
                // Generics have no symbol, so they can't be given any linkage.
                if !generics.is_type_parameterized() {
                    let linkage = if ccx.sess().opts.cg.codegen_units == 1 {
                        // We could use AvailableExternallyLinkage here,
                        // but InternalLinkage allows LLVM to optimize more
                        // aggressively (at the cost of sometimes
                        // duplicating code).
                        InternalLinkage
                    } else {
                        // With multiple compilation units, duplicated code
                        // is more of a problem.  Also, `codegen_units > 1`
                        // means the user is okay with losing some
                        // performance.
                        AvailableExternallyLinkage
                    };
                    let empty_substs = tcx.mk_substs(Substs::empty());
                    let def_id = tcx.map.local_def_id(item.id);
                    let llfn = Callee::def(ccx, def_id, empty_substs).reify(ccx).val;
                    SetLinkage(llfn, linkage);
                }
            }

            item.id
        }
        FoundAst::Found(&InlinedItem::Foreign(ref item)) => {
            ccx.external().borrow_mut().insert(fn_id, Some(item.id));
            ccx.external_srcs().borrow_mut().insert(item.id, fn_id);
            item.id
        }
        FoundAst::FoundParent(parent_id, item) => {
            ccx.external().borrow_mut().insert(parent_id, Some(item.id));
            ccx.external_srcs().borrow_mut().insert(item.id, parent_id);

            let mut my_id = 0;
            match item.node {
                hir::ItemEnum(ref ast_def, _) => {
                    let ast_vs = &ast_def.variants;
                    let ty_vs = &tcx.lookup_adt_def(parent_id).variants;
                    assert_eq!(ast_vs.len(), ty_vs.len());
                    for (ast_v, ty_v) in ast_vs.iter().zip(ty_vs.iter()) {
                        if ty_v.did == fn_id { my_id = ast_v.node.data.id(); }
                        ccx.external().borrow_mut().insert(ty_v.did, Some(ast_v.node.data.id()));
                        ccx.external_srcs().borrow_mut().insert(ast_v.node.data.id(), ty_v.did);
                    }
                }
                hir::ItemStruct(ref struct_def, _) => {
                    if struct_def.is_struct() {
                        ccx.sess().bug("instantiate_inline: called on a \
                                                                 non-tuple struct")
                    } else {
                        ccx.external().borrow_mut().insert(fn_id, Some(struct_def.id()));
                        ccx.external_srcs().borrow_mut().insert(struct_def.id(), fn_id);
                        my_id = struct_def.id();
                    }
                }
                _ => ccx.sess().bug("instantiate_inline: item has a \
                                 non-enum, non-struct parent")
            }
            my_id
        }
        FoundAst::Found(&InlinedItem::TraitItem(_, ref trait_item)) => {
            ccx.external().borrow_mut().insert(fn_id, Some(trait_item.id));
            ccx.external_srcs().borrow_mut().insert(trait_item.id, fn_id);

            ccx.stats().n_inlines.set(ccx.stats().n_inlines.get() + 1);

            // Associated consts already have to be evaluated in `typeck`, so
            // the logic to do that already exists in `middle`. In order to
            // reuse that code, it needs to be able to look up the traits for
            // inlined items.
            let ty_trait_item = tcx.impl_or_trait_item(fn_id).clone();
            let trait_item_def_id = tcx.map.local_def_id(trait_item.id);
            tcx.impl_or_trait_items.borrow_mut()
               .insert(trait_item_def_id, ty_trait_item);

            // If this is a default method, we can't look up the
            // impl type. But we aren't going to translate anyways, so
            // don't.
            trait_item.id
        }
        FoundAst::Found(&InlinedItem::ImplItem(impl_did, ref impl_item)) => {
            ccx.external().borrow_mut().insert(fn_id, Some(impl_item.id));
            ccx.external_srcs().borrow_mut().insert(impl_item.id, fn_id);

            ccx.stats().n_inlines.set(ccx.stats().n_inlines.get() + 1);

            // Translate monomorphic impl methods immediately.
            if let hir::ImplItemKind::Method(ref sig, ref body) = impl_item.node {
                let impl_tpt = tcx.lookup_item_type(impl_did);
                if impl_tpt.generics.types.is_empty() &&
                        sig.generics.ty_params.is_empty() {
                    let def_id = tcx.map.local_def_id(impl_item.id);
                    let empty_substs = ccx.empty_substs_for_def_id(def_id);
                    let llfn = Callee::def(ccx, def_id, empty_substs).reify(ccx).val;
                    trans_fn(ccx,
                             &sig.decl,
                             body,
                             llfn,
                             empty_substs,
                             impl_item.id);
                    // See linkage comments on items.
                    if ccx.sess().opts.cg.codegen_units == 1 {
                        SetLinkage(llfn, InternalLinkage);
                    } else {
                        SetLinkage(llfn, AvailableExternallyLinkage);
                    }
                }
            }

            impl_item.id
        }
    };

    let inline_def_id = tcx.map.local_def_id(inline_id);
    Some(inline_def_id)
}

pub fn get_local_instance(ccx: &CrateContext, fn_id: DefId)
    -> Option<DefId> {
    if let Some(_) = ccx.tcx().map.as_local_node_id(fn_id) {
        Some(fn_id)
    } else {
        instantiate_inline(ccx, fn_id)
    }
}

pub fn maybe_instantiate_inline(ccx: &CrateContext, fn_id: DefId) -> DefId {
    get_local_instance(ccx, fn_id).unwrap_or(fn_id)
}
<|endoftext|>


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

pub struct AnimationSet {
    animations: HashMap<String, Animation>,
}

impl AnimationSet {
    pub fn new() -> AnimationSet {
        AnimationSet {
            animations: HashMap::new()
        }
    }

    pub fn add<T: Into<String>>(&mut self, name: T, animation: Animation) {
        self.animations.insert(name.into(), animation);
    }
}

pub struct Animation {
}

struct AnimationFrame {
}
<commit_msg>Basic animation frames structure<commit_after>use sdl2::rect::Rect;
use std::collections::HashMap;

pub struct AnimationSet {
    animations: HashMap<String, Animation>,
}

impl AnimationSet {
    pub fn new() -> AnimationSet {
        AnimationSet {
            animations: HashMap::new()
        }
    }

    pub fn add<T: Into<String>>(&mut self, name: T, animation: Animation) {
        self.animations.insert(name.into(), animation);
    }
}

pub struct Animation {
    frames: Vec<AnimationFrame>
}

impl Animation {
    pub fn new() -> Animation {
        Animation {
            frames: vec![]
        }
    }

    pub fn add(&mut self, frame: AnimationFrame) {
        self.frames.push(frame);
    }
}

pub struct AnimationFrame {
    source_bounds: Rect
}

impl AnimationFrame {
    pub fn new(source: &Rect) -> AnimationFrame {
        AnimationFrame {
            source_bounds: source.clone()
        }
    }
}
<|endoftext|>


<commit_before>use std::cell::RefCell;

use smithay::{
    reexports::wayland_server::protocol::wl_surface,
    utils::Rectangle,
    wayland::{
        compositor::{roles::Role, CompositorToken, SubsurfaceRole, SurfaceAttributes, TraversalAction},
        shell::{
            legacy::{ShellSurface, ShellSurfaceRole},
            xdg::{ToplevelSurface, XdgSurfaceRole},
        },
    },
};

pub enum Kind<R> {
    Xdg(ToplevelSurface<R>),
    Wl(ShellSurface<R>),
}

impl<R> Kind<R>
where
    R: Role<SubsurfaceRole> + Role<XdgSurfaceRole> + Role<ShellSurfaceRole> + 'static,
{
    pub fn alive(&self) -> bool {
        match *self {
            Kind::Xdg(ref t) => t.alive(),
            Kind::Wl(ref t) => t.alive(),
        }
    }
    pub fn get_surface(&self) -> Option<&wl_surface::WlSurface> {
        match *self {
            Kind::Xdg(ref t) => t.get_surface(),
            Kind::Wl(ref t) => t.get_surface(),
        }
    }

    /// Do this handle and the other one actually refer to the same toplevel surface?
    pub fn equals(&self, other: &Self) -> bool {
        match (self, other) {
            (Kind::Xdg(a), Kind::Xdg(b)) => a.equals(b),
            (Kind::Wl(a), Kind::Wl(b)) => a.equals(b),
            _ => false,
        }
    }
}

struct Window<R> {
    location: (i32, i32),
    /// A bounding box over the input areas of this window and its children.
    ///
    /// Used for the fast path of the check in `matching`.
    input_bbox: Rectangle,
    toplevel: Kind<R>,
}

impl<R> Window<R>
where
    R: Role<SubsurfaceRole> + Role<XdgSurfaceRole> + Role<ShellSurfaceRole> + 'static,
{
    /// Finds the topmost surface under this point if any and returns it together with the location of this
    /// surface.
    ///
    /// You need to provide a `contains_point` function which checks if the point (in surface-local
    /// coordinates) is within the input region of the given `SurfaceAttributes`.
    fn matching<F>(
        &self,
        point: (f64, f64),
        ctoken: CompositorToken<R>,
        contains_point: F,
    ) -> Option<(wl_surface::WlSurface, (f64, f64))>
    where
        F: Fn(&SurfaceAttributes, (f64, f64)) -> bool,
    {
        if !self.input_bbox.contains((point.0 as i32, point.1 as i32)) {
            return None;
        }
        // need to check more carefully
        let found = RefCell::new(None);
        if let Some(wl_surface) = self.toplevel.get_surface() {
            ctoken.with_surface_tree_downward(
                wl_surface,
                self.location,
                |wl_surface, attributes, role, &(mut x, mut y)| {
                    if let Ok(subdata) = Role::<SubsurfaceRole>::data(role) {
                        x += subdata.location.0;
                        y += subdata.location.1;
                    }

                    let surface_local_point = (point.0 - x as f64, point.1 - y as f64);
                    if contains_point(attributes, surface_local_point) {
                        *found.borrow_mut() = Some((wl_surface.clone(), (x as f64, y as f64)));
                    }

                    TraversalAction::DoChildren((x, y))
                },
                |_, _, _, _| {},
                |_, _, _, _| {
                    // only continue if the point is not found
                    found.borrow().is_none()
                },
            );
        }
        found.into_inner()
    }

    fn self_update<F>(&mut self, ctoken: CompositorToken<R>, get_size: F)
    where
        F: Fn(&SurfaceAttributes) -> Option<(i32, i32)>,
    {
        let (base_x, base_y) = self.location;
        let (mut min_x, mut min_y, mut max_x, mut max_y) = (base_x, base_y, base_x, base_y);
        if let Some(wl_surface) = self.toplevel.get_surface() {
            ctoken.with_surface_tree_downward(
                wl_surface,
                (base_x, base_y),
                |_, attributes, role, &(mut x, mut y)| {
                    // The input region is intersected with the surface size, so the surface size
                    // can serve as an approximation for the input bounding box.
                    if let Some((w, h)) = get_size(attributes) {
                        if let Ok(subdata) = Role::<SubsurfaceRole>::data(role) {
                            x += subdata.location.0;
                            y += subdata.location.1;
                        }
                        // update the bounding box
                        if x < min_x {
                            min_x = x;
                        }
                        if y < min_y {
                            min_y = y;
                        }
                        if x + w > max_x {
                            max_x = x + w;
                        }
                        if y + h > max_y {
                            max_y = y + w;
                        }
                        TraversalAction::DoChildren((x, y))
                    } else {
                        TraversalAction::SkipChildren
                    }
                },
                |_, _, _, _| {},
                |_, _, _, _| true,
            );
        }
        self.input_bbox = Rectangle {
            x: min_x,
            y: min_y,
            width: max_x - min_x,
            height: max_y - min_y,
        };
    }
}

pub struct WindowMap<R, F, G> {
    ctoken: CompositorToken<R>,
    windows: Vec<Window<R>>,
    /// A function returning the surface size.
    get_size: F,
    /// A function that checks if the point is in the surface's input region.
    contains_point: G,
}

impl<R, F, G> WindowMap<R, F, G>
where
    F: Fn(&SurfaceAttributes) -> Option<(i32, i32)>,
    G: Fn(&SurfaceAttributes, (f64, f64)) -> bool,
    R: Role<SubsurfaceRole> + Role<XdgSurfaceRole> + Role<ShellSurfaceRole> + 'static,
{
    pub fn new(ctoken: CompositorToken<R>, get_size: F, contains_point: G) -> Self {
        WindowMap {
            ctoken,
            windows: Vec::new(),
            get_size,
            contains_point,
        }
    }

    pub fn insert(&mut self, toplevel: Kind<R>, location: (i32, i32)) {
        let mut window = Window {
            location,
            input_bbox: Rectangle::default(),
            toplevel,
        };
        window.self_update(self.ctoken, &self.get_size);
        self.windows.insert(0, window);
    }

    pub fn get_surface_under(&self, point: (f64, f64)) -> Option<(wl_surface::WlSurface, (f64, f64))> {
        for w in &self.windows {
            if let Some(surface) = w.matching(point, self.ctoken, &self.contains_point) {
                return Some(surface);
            }
        }
        None
    }

    pub fn get_surface_and_bring_to_top(
        &mut self,
        point: (f64, f64),
    ) -> Option<(wl_surface::WlSurface, (f64, f64))> {
        let mut found = None;
        for (i, w) in self.windows.iter().enumerate() {
            if let Some(surface) = w.matching(point, self.ctoken, &self.contains_point) {
                found = Some((i, surface));
                break;
            }
        }
        if let Some((i, surface)) = found {
            let winner = self.windows.remove(i);
            self.windows.insert(0, winner);
            Some(surface)
        } else {
            None
        }
    }

    pub fn with_windows_from_bottom_to_top<Func>(&self, mut f: Func)
    where
        Func: FnMut(&Kind<R>, (i32, i32)),
    {
        for w in self.windows.iter().rev() {
            f(&w.toplevel, w.location)
        }
    }

    pub fn refresh(&mut self) {
        self.windows.retain(|w| w.toplevel.alive());
        for w in &mut self.windows {
            w.self_update(self.ctoken, &self.get_size);
        }
    }

    pub fn clear(&mut self) {
        self.windows.clear();
    }
}
<commit_msg>anvil.window_map: add WindowMap::location<commit_after>use std::cell::RefCell;

use smithay::{
    reexports::wayland_server::protocol::wl_surface,
    utils::Rectangle,
    wayland::{
        compositor::{roles::Role, CompositorToken, SubsurfaceRole, SurfaceAttributes, TraversalAction},
        shell::{
            legacy::{ShellSurface, ShellSurfaceRole},
            xdg::{ToplevelSurface, XdgSurfaceRole},
        },
    },
};

pub enum Kind<R> {
    Xdg(ToplevelSurface<R>),
    Wl(ShellSurface<R>),
}

impl<R> Kind<R>
where
    R: Role<SubsurfaceRole> + Role<XdgSurfaceRole> + Role<ShellSurfaceRole> + 'static,
{
    pub fn alive(&self) -> bool {
        match *self {
            Kind::Xdg(ref t) => t.alive(),
            Kind::Wl(ref t) => t.alive(),
        }
    }
    pub fn get_surface(&self) -> Option<&wl_surface::WlSurface> {
        match *self {
            Kind::Xdg(ref t) => t.get_surface(),
            Kind::Wl(ref t) => t.get_surface(),
        }
    }

    /// Do this handle and the other one actually refer to the same toplevel surface?
    pub fn equals(&self, other: &Self) -> bool {
        match (self, other) {
            (Kind::Xdg(a), Kind::Xdg(b)) => a.equals(b),
            (Kind::Wl(a), Kind::Wl(b)) => a.equals(b),
            _ => false,
        }
    }
}

struct Window<R> {
    location: (i32, i32),
    /// A bounding box over the input areas of this window and its children.
    ///
    /// Used for the fast path of the check in `matching`.
    input_bbox: Rectangle,
    toplevel: Kind<R>,
}

impl<R> Window<R>
where
    R: Role<SubsurfaceRole> + Role<XdgSurfaceRole> + Role<ShellSurfaceRole> + 'static,
{
    /// Finds the topmost surface under this point if any and returns it together with the location of this
    /// surface.
    ///
    /// You need to provide a `contains_point` function which checks if the point (in surface-local
    /// coordinates) is within the input region of the given `SurfaceAttributes`.
    fn matching<F>(
        &self,
        point: (f64, f64),
        ctoken: CompositorToken<R>,
        contains_point: F,
    ) -> Option<(wl_surface::WlSurface, (f64, f64))>
    where
        F: Fn(&SurfaceAttributes, (f64, f64)) -> bool,
    {
        if !self.input_bbox.contains((point.0 as i32, point.1 as i32)) {
            return None;
        }
        // need to check more carefully
        let found = RefCell::new(None);
        if let Some(wl_surface) = self.toplevel.get_surface() {
            ctoken.with_surface_tree_downward(
                wl_surface,
                self.location,
                |wl_surface, attributes, role, &(mut x, mut y)| {
                    if let Ok(subdata) = Role::<SubsurfaceRole>::data(role) {
                        x += subdata.location.0;
                        y += subdata.location.1;
                    }

                    let surface_local_point = (point.0 - x as f64, point.1 - y as f64);
                    if contains_point(attributes, surface_local_point) {
                        *found.borrow_mut() = Some((wl_surface.clone(), (x as f64, y as f64)));
                    }

                    TraversalAction::DoChildren((x, y))
                },
                |_, _, _, _| {},
                |_, _, _, _| {
                    // only continue if the point is not found
                    found.borrow().is_none()
                },
            );
        }
        found.into_inner()
    }

    fn self_update<F>(&mut self, ctoken: CompositorToken<R>, get_size: F)
    where
        F: Fn(&SurfaceAttributes) -> Option<(i32, i32)>,
    {
        let (base_x, base_y) = self.location;
        let (mut min_x, mut min_y, mut max_x, mut max_y) = (base_x, base_y, base_x, base_y);
        if let Some(wl_surface) = self.toplevel.get_surface() {
            ctoken.with_surface_tree_downward(
                wl_surface,
                (base_x, base_y),
                |_, attributes, role, &(mut x, mut y)| {
                    // The input region is intersected with the surface size, so the surface size
                    // can serve as an approximation for the input bounding box.
                    if let Some((w, h)) = get_size(attributes) {
                        if let Ok(subdata) = Role::<SubsurfaceRole>::data(role) {
                            x += subdata.location.0;
                            y += subdata.location.1;
                        }
                        // update the bounding box
                        if x < min_x {
                            min_x = x;
                        }
                        if y < min_y {
                            min_y = y;
                        }
                        if x + w > max_x {
                            max_x = x + w;
                        }
                        if y + h > max_y {
                            max_y = y + w;
                        }
                        TraversalAction::DoChildren((x, y))
                    } else {
                        TraversalAction::SkipChildren
                    }
                },
                |_, _, _, _| {},
                |_, _, _, _| true,
            );
        }
        self.input_bbox = Rectangle {
            x: min_x,
            y: min_y,
            width: max_x - min_x,
            height: max_y - min_y,
        };
    }
}

pub struct WindowMap<R, F, G> {
    ctoken: CompositorToken<R>,
    windows: Vec<Window<R>>,
    /// A function returning the surface size.
    get_size: F,
    /// A function that checks if the point is in the surface's input region.
    contains_point: G,
}

impl<R, F, G> WindowMap<R, F, G>
where
    F: Fn(&SurfaceAttributes) -> Option<(i32, i32)>,
    G: Fn(&SurfaceAttributes, (f64, f64)) -> bool,
    R: Role<SubsurfaceRole> + Role<XdgSurfaceRole> + Role<ShellSurfaceRole> + 'static,
{
    pub fn new(ctoken: CompositorToken<R>, get_size: F, contains_point: G) -> Self {
        WindowMap {
            ctoken,
            windows: Vec::new(),
            get_size,
            contains_point,
        }
    }

    pub fn insert(&mut self, toplevel: Kind<R>, location: (i32, i32)) {
        let mut window = Window {
            location,
            input_bbox: Rectangle::default(),
            toplevel,
        };
        window.self_update(self.ctoken, &self.get_size);
        self.windows.insert(0, window);
    }

    pub fn get_surface_under(&self, point: (f64, f64)) -> Option<(wl_surface::WlSurface, (f64, f64))> {
        for w in &self.windows {
            if let Some(surface) = w.matching(point, self.ctoken, &self.contains_point) {
                return Some(surface);
            }
        }
        None
    }

    pub fn get_surface_and_bring_to_top(
        &mut self,
        point: (f64, f64),
    ) -> Option<(wl_surface::WlSurface, (f64, f64))> {
        let mut found = None;
        for (i, w) in self.windows.iter().enumerate() {
            if let Some(surface) = w.matching(point, self.ctoken, &self.contains_point) {
                found = Some((i, surface));
                break;
            }
        }
        if let Some((i, surface)) = found {
            let winner = self.windows.remove(i);
            self.windows.insert(0, winner);
            Some(surface)
        } else {
            None
        }
    }

    pub fn with_windows_from_bottom_to_top<Func>(&self, mut f: Func)
    where
        Func: FnMut(&Kind<R>, (i32, i32)),
    {
        for w in self.windows.iter().rev() {
            f(&w.toplevel, w.location)
        }
    }

    pub fn refresh(&mut self) {
        self.windows.retain(|w| w.toplevel.alive());
        for w in &mut self.windows {
            w.self_update(self.ctoken, &self.get_size);
        }
    }

    pub fn clear(&mut self) {
        self.windows.clear();
    }

    /// Returns the location of the toplevel, if it exists.
    pub fn location(&self, toplevel: &Kind<R>) -> Option<(i32, i32)> {
        self.windows
            .iter()
            .find(|w| w.toplevel.equals(toplevel))
            .map(|w| w.location)
    }
}
<|endoftext|>