<commit_before>//! Disk header parsing.
//!
//! The disk header provides information on how to read a TFS disk. This module parses and
//! interprets the disk header so it is meaningful to the programmer.

/// The size of the disk header.
///
/// This should be a multiple of the cluster size.
const DISK_HEADER_SIZE: usize = 4096;
/// The default disk header.
const DEFAULT_DISK_HEADER: &'static [u8] = &[
    // The magic number (`TFS fmt `).
    b'T', b'F', b'S', b' ', b'f', b'm', b't', b' ',
    // The version number.
    0x00, 0x00, 0x00, 0x00,
    0xFF, 0xFF, 0xFF, 0xFF,
    // The implementation ID (`official`).
     b'o',  b'f',  b'f',  b'i',  b'c',  b'i',  b'a',  b'l',
    !b'o', !b'f', !b'f', !b'i', !b'c', !b'i', !b'a', !b'l',
    // Encryption algorithm.
    0x00, CompressionAlgorithm::Identity as u8,
    0xFF, !CompressionAlgorithm::Identity as u8,
    // Encryption parameters.
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
    // State block address (uninitialized).
    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    // Consistency flag.
    ConsistencyFlag::Uninitialized as u8, !ConsistencyFlag::Uninitialized as u8,
];

/// A disk header reading error.
enum Error {
    /// The consistency flag is corrupt.
    CorruptConsistencyFlag,
    /// The cipher field is corrupt.
    CorruptCipher,
    /// The encryption parameters is corrupt.
    CorruptEncryptionParameters,
    /// The implementation ID is corrupt.
    CorruptImplementationId,
    /// The state block address is corrupt.
    CorruptStateBlockAddress,
    /// The version number is corrupt.
    CorruptVersionNumber,
    /// The version is incompatible with this implementation.
    ///
    /// The version number is given by some integer. If the higher half of the integer does not
    /// match, the versions are incompatible and this error is returned.
    IncompatibleVersion,
    /// Unknown/unsupported (implementation-specific) cipher option.
    UnknownCipher,
    /// Invalid/nonexistent cipher option.
    ///
    /// Note that this is different from `UnknownCipher`, as it is necessarily invalid and not just
    /// implementation-specific.
    InvalidCipher,
    /// Unknown consistency flag value.
    UnknownConsistencyFlag,
    /// Unknown format (not TFS).
    UnknownFormat,
    /// A disk I/O error.
    Disk(disk::Error),
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), Error> {
        write!(f, )
    }
}

/// TFS magic number.
enum MagicNumber {
    /// The image is partially compatible with the official TFS specification.
    PartialCompatibility,
    /// The image is completely compatible with the official TFS specification.
    TotalCompatibility,
}

/// Cipher option.
enum Cipher {
    /// Disk encryption disabled.
    Identity = 0,
    /// Use the SPECK cipher.
    Speck128 = 1,
}

impl TryFrom<u16> for Cipher {
    type Err = Error;

    fn try_from(from: u16) -> Result<Cipher, Error> {
        match from {
            // Aye aye, encryption is disabled.
            0 => Ok(Cipher::Identity),
            // Wooh! Encryption on.
            1 => Ok(Cipher::Speck128),
            // These are implementation-specific ciphers which are unsupported in this (official)
            // implementation.
            1 << 15... => Err(Error::UnknownCipher),
            // This cipher is invalid by current revision.
            _ => Err(Error::InvalidCipher),
        }
    }
}

/// Consistency flag.
///
/// The consistency flag defines the state of the disk, telling the user if it is in a consistent
/// state or not. It is important for doing non-trivial things like garbage-collection, where the
/// disk needs to enter an inconsistent state for a small period of time.
enum ConsistencyFlag {
    /// The disk was properly closed and shut down.
    Closed,
    /// The disk is active/was forcibly shut down.
    StillActive,
    /// The disk is in an inconsistent state.
    ///
    /// Proceed with caution.
    Inconsistent,
    /// The disk is uninitialized.
    Uninitialized,
}

/// The disk header.
#[derive(Default)]
struct DiskHeader {
    /// The magic number.
    magic_number: MagicNumber,
    /// The version number.
    version_number: u32,
    /// The implementation ID.
    implementation_id: u32,
    /// The cipher.
    cipher: Cipher,
    /// The encryption paramters.
    ///
    /// These are used as defined by the choice of cipher. Some ciphers might use it for salt or
    /// settings, and others not use it at all.
    encryption_parameters: [u8; 16],
    /// The address of the state block.
    state_block_address: clusters::Pointer,
    /// The consistency flag.
    consistency_flag: ConsistencyFlag,
}

impl DiskHeader {
    /// Load the disk header from some disk.
    ///
    /// This will construct it into memory while performing error checks on the header to ensure
    /// correctness.
    fn load<D: Disk>(disk: &mut D) -> Result<DiskHeader, Error> {
        // Load the disk header into a buffer in memory.
        let mut buf = [0; DISK_HEADER_SIZE];
        // Fetch the sector size.
        let sector_size = disk.sector_size();
        // Load the first couple of sectors into `buf`.
        for sector in 0..DISK_HEADER_SIZE / sector_size {
            disk.read(sector, 0, &mut buf[sector * sector_size..])?;
        }

        // Start with some default value, which will be filled out later.
        let mut ret = DiskHeader::default();

        // # Introducer Section
        //
        // This section has the purpose of defining the implementation, version, and type of the
        // disk image. It is rarely changed unless updates or reformatting happens.

        // Load the magic number.
        ret.magic_number = match buf[..8] {
            // Total compatibility.
            b"TFS fmt " => MagicNumber::TotalCompatibility,
            // Partial compatibility.
            b"~TFS fmt" => MagicNumber::PartialCompatibility,
            // Unknown format; abort.
            _ => return Err(Error::UnknownFormat),
        };

        // Load the version number.
        ret.version_number = LittleEndian::read(buf[8..12]);
        // Right after the version number, the same number follows, but bitwise negated. Make sure
        // that these numbers match (if it is bitwise negated). The reason for using this form of
        // code rather than just repeating it as-is is that if one overwrites all bytes with a
        // constant value, like zero, it won't be detected.
        if ret.version_number == !LittleEndian::read(buf[12..16]) {
            // Check if the version is compatible.
            if ret.version_number >> 16 > 0 {
                // The version is not compatible; abort.
                return Err(Error::IncompatibleVersion);
            }
        } else {
            // The version number is corrupt; abort.
            return Err(Error::CorruptVersionNumber);
        }

        // Load the implementation ID.
        ret.implementation_id = LittleEndian::read(buf[16..24]);
        // Similarly to the version number, a bitwise negated repetition follows. Make sure it
        // matches.
        if ret.implementation_id != !LittleEndian::read(buf[24..32]) {
            // The implementation ID is corrupt; abort.
            return Err(Error::CorruptImplementationId);
        }

        //////////////// Encryption Section ////////////////

        // Load the encryption algorithm choice.
        ret.cipher = Cipher::try_from(LittleEndian::read(buf[64..66]))?;
        // Repeat the bitwise negation.
        if ret.cipher as u16 != !LittleEndian::read(buf[66..68]) {
            // The implementation ID is corrupt; abort.
            return Err(Error::CorruptCipher);
        }

        // Load the encryption parameters (e.g. salt).
        self.encryption_parameters.copy_from_slice(&buf[68..84]);
        // Repeat the bitwise negation.
        if self.encryption_parameters.iter().eq(buf[84..100].iter().map(|x| !x)) {
            // The encryption parameters are corrupt; abort.
            return Err(Error::CorruptEncryptionParameters);
        }

        //////////////// State ////////////////

        // Load the state block pointer.
        ret.state_block_address = clusters::Pointer::new(LittleEndian::read(buf[128..136]));
        // Repeat the bitwise negation.
        if ret.state_block_address as u64 != !LittleEndian::read(buf[136..144]) {
            // The state block address is corrupt; abort.
            return Err(Error::CorruptStateBlockAddress);
        }

        // Load the consistency flag.
        self.consistency_flag = ConsistencyFlag::from(buf[144])?;
        // Repeat the bitwise negation.
        if self.consistency_flag as u8 != !buf[145] {
            // The consistency flag is corrupt; abort.
            return Err(Error::CorruptConsistencyFlag);
        }
    }
}
<commit_msg>Separate parsing disk header from loading it.<commit_after>//! Disk header parsing.
//!
//! The disk header provides information on how to read a TFS disk. This module parses and
//! interprets the disk header so it is meaningful to the programmer.

/// The size of the disk header.
///
/// This should be a multiple of the cluster size.
const DISK_HEADER_SIZE: usize = 4096;
/// The default disk header.
const DEFAULT_DISK_HEADER: &'static [u8] = &[
    // The magic number (`TFS fmt `).
    b'T', b'F', b'S', b' ', b'f', b'm', b't', b' ',
    // The version number.
    0x00, 0x00, 0x00, 0x00,
    0xFF, 0xFF, 0xFF, 0xFF,
    // The implementation ID (`official`).
     b'o',  b'f',  b'f',  b'i',  b'c',  b'i',  b'a',  b'l',
    !b'o', !b'f', !b'f', !b'i', !b'c', !b'i', !b'a', !b'l',
    // Encryption algorithm.
    0x00, CompressionAlgorithm::Identity as u8,
    0xFF, !CompressionAlgorithm::Identity as u8,
    // Encryption parameters.
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
    // State block address (uninitialized).
    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    // Consistency flag.
    ConsistencyFlag::Uninitialized as u8, !ConsistencyFlag::Uninitialized as u8,
];

/// A disk header reading error.
enum Error {
    /// The consistency flag is corrupt.
    CorruptConsistencyFlag,
    /// The cipher field is corrupt.
    CorruptCipher,
    /// The encryption parameters is corrupt.
    CorruptEncryptionParameters,
    /// The implementation ID is corrupt.
    CorruptImplementationId,
    /// The state block address is corrupt.
    CorruptStateBlockAddress,
    /// The version number is corrupt.
    CorruptVersionNumber,
    /// The version is incompatible with this implementation.
    ///
    /// The version number is given by some integer. If the higher half of the integer does not
    /// match, the versions are incompatible and this error is returned.
    IncompatibleVersion,
    /// Unknown/unsupported (implementation-specific) cipher option.
    UnknownCipher,
    /// Invalid/nonexistent cipher option.
    ///
    /// Note that this is different from `UnknownCipher`, as it is necessarily invalid and not just
    /// implementation-specific.
    InvalidCipher,
    /// Unknown consistency flag value.
    UnknownConsistencyFlag,
    /// Unknown format (not TFS).
    UnknownFormat,
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), Error> {
        write!(f, )
    }
}

/// TFS magic number.
enum MagicNumber {
    /// The image is partially compatible with the official TFS specification.
    PartialCompatibility,
    /// The image is completely compatible with the official TFS specification.
    TotalCompatibility,
}

/// Cipher option.
enum Cipher {
    /// Disk encryption disabled.
    Identity = 0,
    /// Use the SPECK cipher.
    Speck128 = 1,
}

impl TryFrom<u16> for Cipher {
    type Err = Error;

    fn try_from(from: u16) -> Result<Cipher, Error> {
        match from {
            // Aye aye, encryption is disabled.
            0 => Ok(Cipher::Identity),
            // Wooh! Encryption on.
            1 => Ok(Cipher::Speck128),
            // These are implementation-specific ciphers which are unsupported in this (official)
            // implementation.
            1 << 15... => Err(Error::UnknownCipher),
            // This cipher is invalid by current revision.
            _ => Err(Error::InvalidCipher),
        }
    }
}

/// Consistency flag.
///
/// The consistency flag defines the state of the disk, telling the user if it is in a consistent
/// state or not. It is important for doing non-trivial things like garbage-collection, where the
/// disk needs to enter an inconsistent state for a small period of time.
enum ConsistencyFlag {
    /// The disk was properly closed and shut down.
    Closed,
    /// The disk is active/was forcibly shut down.
    StillActive,
    /// The disk is in an inconsistent state.
    ///
    /// Proceed with caution.
    Inconsistent,
    /// The disk is uninitialized.
    Uninitialized,
}

/// The disk header.
#[derive(Default)]
struct DiskHeader {
    /// The magic number.
    magic_number: MagicNumber,
    /// The version number.
    version_number: u32,
    /// The implementation ID.
    implementation_id: u32,
    /// The cipher.
    cipher: Cipher,
    /// The encryption paramters.
    ///
    /// These are used as defined by the choice of cipher. Some ciphers might use it for salt or
    /// settings, and others not use it at all.
    encryption_parameters: [u8; 16],
    /// The address of the state block.
    state_block_address: clusters::Pointer,
    /// The consistency flag.
    consistency_flag: ConsistencyFlag,
}

impl DiskHeader {
    /// Parse the disk header from some sequence of bytes.
    ///
    /// This will construct it into memory while performing error checks on the header to ensure
    /// correctness.
    fn parse(buf: &[u8]) -> Result<DiskHeader, Error> {
        // Start with some default value, which will be filled out later.
        let mut ret = DiskHeader::default();

        // # Introducer Section
        //
        // This section has the purpose of defining the implementation, version, and type of the
        // disk image. It is rarely changed unless updates or reformatting happens.

        // Load the magic number.
        ret.magic_number = match buf[..8] {
            // Total compatibility.
            b"TFS fmt " => MagicNumber::TotalCompatibility,
            // Partial compatibility.
            b"~TFS fmt" => MagicNumber::PartialCompatibility,
            // Unknown format; abort.
            _ => return Err(Error::UnknownFormat),
        };

        // Load the version number.
        ret.version_number = LittleEndian::read(buf[8..12]);
        // Right after the version number, the same number follows, but bitwise negated. Make sure
        // that these numbers match (if it is bitwise negated). The reason for using this form of
        // code rather than just repeating it as-is is that if one overwrites all bytes with a
        // constant value, like zero, it won't be detected.
        if ret.version_number == !LittleEndian::read(buf[12..16]) {
            // Check if the version is compatible.
            if ret.version_number >> 16 > 0 {
                // The version is not compatible; abort.
                return Err(Error::IncompatibleVersion);
            }
        } else {
            // The version number is corrupt; abort.
            return Err(Error::CorruptVersionNumber);
        }

        // Load the implementation ID.
        ret.implementation_id = LittleEndian::read(buf[16..24]);
        // Similarly to the version number, a bitwise negated repetition follows. Make sure it
        // matches.
        if ret.implementation_id != !LittleEndian::read(buf[24..32]) {
            // The implementation ID is corrupt; abort.
            return Err(Error::CorruptImplementationId);
        }

        //////////////// Encryption Section ////////////////

        // Load the encryption algorithm choice.
        ret.cipher = Cipher::try_from(LittleEndian::read(buf[64..66]))?;
        // Repeat the bitwise negation.
        if ret.cipher as u16 != !LittleEndian::read(buf[66..68]) {
            // The implementation ID is corrupt; abort.
            return Err(Error::CorruptCipher);
        }

        // Load the encryption parameters (e.g. salt).
        self.encryption_parameters.copy_from_slice(&buf[68..84]);
        // Repeat the bitwise negation.
        if self.encryption_parameters.iter().eq(buf[84..100].iter().map(|x| !x)) {
            // The encryption parameters are corrupt; abort.
            return Err(Error::CorruptEncryptionParameters);
        }

        //////////////// State ////////////////

        // Load the state block pointer.
        ret.state_block_address = clusters::Pointer::new(LittleEndian::read(buf[128..136]));
        // Repeat the bitwise negation.
        if ret.state_block_address as u64 != !LittleEndian::read(buf[136..144]) {
            // The state block address is corrupt; abort.
            return Err(Error::CorruptStateBlockAddress);
        }

        // Load the consistency flag.
        self.consistency_flag = ConsistencyFlag::from(buf[144])?;
        // Repeat the bitwise negation.
        if self.consistency_flag as u8 != !buf[145] {
            // The consistency flag is corrupt; abort.
            return Err(Error::CorruptConsistencyFlag);
        }
    }
}
<|endoftext|>


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

use bytes::{Buf, BufMut};
use futures::{future::Future, Async};
use tokio::io::{AsyncRead, AsyncWrite};

use std::{
    io::{self, Read, Write},
    path::Path,
};

/// Unix domain socket connection on unix, or named pipe connection on windows.
#[derive(Debug)]
pub struct Socket {
    #[cfg(unix)]
    inner: tokio_uds::UnixStream,
    #[cfg(windows)]
    inner: tokio_named_pipes::NamedPipe,
}

impl Socket {
    /// Connects a new socket.
    #[cfg(unix)]
    pub fn new<P: AsRef<Path>>(path: P) -> impl Future<Item = Socket, Error = io::Error> {
        tokio_uds::UnixStream::connect(path).map(|socket| Socket { inner: socket })
    }

    /// Connects a new socket.
    #[cfg(windows)]
    pub fn new<P: AsRef<Path>>(path: P) -> impl Future<Item = Socket, Error = io::Error> {
        use tokio_named_pipes::NamedPipe;

        let handle = tokio::reactor::Handle::default();
        NamedPipe::new(path.as_ref(), &handle)
            .and_then(|pipe| {
                pipe.connect()?;
                Ok(Socket { inner: pipe })
            })
            .into_future()
    }
}

impl Read for Socket {
    fn read(&mut self, buf: &mut [u8]) -> Result<usize, io::Error> {
        self.inner.read(buf)
    }
}

impl Write for Socket {
    fn write(&mut self, buf: &[u8]) -> Result<usize, io::Error> {
        self.inner.write(buf)
    }

    fn flush(&mut self) -> Result<(), io::Error> {
        self.inner.flush()
    }
}

impl AsyncRead for Socket {
    unsafe fn prepare_uninitialized_buffer(&self, buf: &mut [u8]) -> bool {
        self.inner.prepare_uninitialized_buffer(buf)
    }

    fn read_buf<B: BufMut>(&mut self, buf: &mut B) -> Result<Async<usize>, io::Error>
    where
        Self: Sized,
    {
        self.inner.read_buf(buf)
    }
}

impl AsyncWrite for Socket {
    fn shutdown(&mut self) -> Result<Async<()>, io::Error> {
        AsyncWrite::shutdown(&mut self.inner)
    }

    fn write_buf<B: Buf>(&mut self, buf: &mut B) -> Result<Async<usize>, io::Error>
    where
        Self: Sized,
    {
        self.inner.write_buf(buf)
    }
}
<commit_msg>Fix windows build<commit_after>// Copyright (c) 2019 Anatoly Ikorsky
//
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0> or the MIT
// license <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. All files in the project carrying such notice may not be copied,
// modified, or distributed except according to those terms.

use bytes::{Buf, BufMut};
use futures::{future::Future, Async};
use tokio::io::{AsyncRead, AsyncWrite};

use std::{
    io::{self, Read, Write},
    path::Path,
};

/// Unix domain socket connection on unix, or named pipe connection on windows.
#[derive(Debug)]
pub struct Socket {
    #[cfg(unix)]
    inner: tokio_uds::UnixStream,
    #[cfg(windows)]
    inner: tokio_named_pipes::NamedPipe,
}

impl Socket {
    /// Connects a new socket.
    #[cfg(unix)]
    pub fn new<P: AsRef<Path>>(path: P) -> impl Future<Item = Socket, Error = io::Error> {
        tokio_uds::UnixStream::connect(path).map(|socket| Socket { inner: socket })
    }

    /// Connects a new socket.
    #[cfg(windows)]
    pub fn new<P: AsRef<Path>>(path: P) -> impl Future<Item = Socket, Error = io::Error> {
        use futures::future::IntoFuture;
        use tokio_named_pipes::NamedPipe;

        let handle = tokio::reactor::Handle::default();
        NamedPipe::new(path.as_ref(), &handle)
            .and_then(|pipe| {
                pipe.connect()?;
                Ok(Socket { inner: pipe })
            })
            .into_future()
    }
}

impl Read for Socket {
    fn read(&mut self, buf: &mut [u8]) -> Result<usize, io::Error> {
        self.inner.read(buf)
    }
}

impl Write for Socket {
    fn write(&mut self, buf: &[u8]) -> Result<usize, io::Error> {
        self.inner.write(buf)
    }

    fn flush(&mut self) -> Result<(), io::Error> {
        self.inner.flush()
    }
}

impl AsyncRead for Socket {
    unsafe fn prepare_uninitialized_buffer(&self, buf: &mut [u8]) -> bool {
        self.inner.prepare_uninitialized_buffer(buf)
    }

    fn read_buf<B: BufMut>(&mut self, buf: &mut B) -> Result<Async<usize>, io::Error>
    where
        Self: Sized,
    {
        self.inner.read_buf(buf)
    }
}

impl AsyncWrite for Socket {
    fn shutdown(&mut self) -> Result<Async<()>, io::Error> {
        AsyncWrite::shutdown(&mut self.inner)
    }

    fn write_buf<B: Buf>(&mut self, buf: &mut B) -> Result<Async<usize>, io::Error>
    where
        Self: Sized,
    {
        self.inner.write_buf(buf)
    }
}
<|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 https://mozilla.org/MPL/2.0/. */

#[macro_use]
extern crate log;

use env_logger;
use simpleservo::{
    self, gl_glue, Coordinates, EventLoopWaker, HostTrait, InitOptions, ServoGlue, SERVO,
};
use std::ffi::{CStr, CString};
use std::mem;
use std::os::raw::{c_char, c_void};

fn call<F>(f: F)
where
    F: Fn(&mut ServoGlue) -> Result<(), &'static str>,
{
    SERVO.with(|s| {
        if let Err(error) = match s.borrow_mut().as_mut() {
            Some(ref mut s) => (f)(s),
            None => Err("Servo not available in this thread"),
        } {
            // FIXME: All C calls should have a have generic Result-like
            // return type. For now, we just panic instead of notifying
            // the embedder.
            panic!(error);
        }
    });
}

/// Callback used by Servo internals
#[repr(C)]
pub struct CHostCallbacks {
    pub flush: extern "C" fn(),
    pub make_current: extern "C" fn(),
    pub on_load_started: extern "C" fn(),
    pub on_load_ended: extern "C" fn(),
    pub on_title_changed: extern "C" fn(title: *const c_char),
    pub on_url_changed: extern "C" fn(url: *const c_char),
    pub on_history_changed: extern "C" fn(can_go_back: bool, can_go_forward: bool),
    pub on_animating_changed: extern "C" fn(animating: bool),
    pub on_shutdown_complete: extern "C" fn(),
    pub on_ime_state_changed: extern "C" fn(show: bool),
}

/// Servo options
#[repr(C)]
pub struct CInitOptions {
    pub args: *const c_char,
    pub url: *const c_char,
    pub width: i32,
    pub height: i32,
    pub density: f32,
    pub vr_pointer: *mut c_void,
    pub enable_subpixel_text_antialiasing: bool,
}

/// The returned string is not freed. This will leak.
#[no_mangle]
pub extern "C" fn servo_version() -> *const c_char {
    let v = simpleservo::servo_version();
    let text = CString::new(v).expect("Can't create string");
    let ptr = text.as_ptr();
    mem::forget(text);
    ptr
}

fn init(
    opts: CInitOptions,
    gl: gl_glue::ServoGl,
    wakeup: extern "C" fn(),
    callbacks: CHostCallbacks,
) {
    crate::env_logger::init();

    let args = unsafe { CStr::from_ptr(opts.args) };
    let args = args
        .to_str()
        .unwrap_or("")
        .split(' ')
        .map(|s| s.to_owned())
        .collect();

    let url = unsafe { CStr::from_ptr(opts.url) };
    let url = url.to_str().map(|s| s.to_string()).ok();

    let coordinates = Coordinates::new(0, 0, opts.width, opts.height, opts.width, opts.height);

    let opts = InitOptions {
        args,
        url,
        coordinates,
        density: opts.density,
        vr_pointer: if opts.vr_pointer.is_null() {
            None
        } else {
            Some(opts.vr_pointer)
        },
        enable_subpixel_text_antialiasing: opts.enable_subpixel_text_antialiasing,
    };

    let wakeup = Box::new(WakeupCallback::new(wakeup));
    let callbacks = Box::new(HostCallbacks::new(callbacks));

    simpleservo::init(opts, gl, wakeup, callbacks).unwrap();
}

#[cfg(target_os = "windows")]
#[no_mangle]
pub extern "C" fn init_with_egl(
    opts: CInitOptions,
    wakeup: extern "C" fn(),
    callbacks: CHostCallbacks,
) {
    let gl = gl_glue::egl::init().unwrap();
    init(opts, gl, wakeup, callbacks)
}

#[cfg(any(target_os = "linux", target_os = "windows", target_os = "macos"))]
#[no_mangle]
pub extern "C" fn init_with_gl(
    opts: CInitOptions,
    wakeup: extern "C" fn(),
    callbacks: CHostCallbacks,
) {
    let gl = gl_glue::gl::init().unwrap();
    init(opts, gl, wakeup, callbacks)
}

#[no_mangle]
pub extern "C" fn deinit() {
    debug!("deinit");
    simpleservo::deinit();
}

#[no_mangle]
pub extern "C" fn request_shutdown() {
    debug!("request_shutdown");
    call(|s| s.request_shutdown());
}

#[no_mangle]
pub extern "C" fn set_batch_mode(batch: bool) {
    debug!("set_batch_mode");
    call(|s| s.set_batch_mode(batch));
}

#[no_mangle]
pub extern "C" fn resize(width: i32, height: i32) {
    debug!("resize {}/{}", width, height);
    call(|s| {
        let coordinates = Coordinates::new(0, 0, width, height, width, height);
        s.resize(coordinates)
    });
}

#[no_mangle]
pub extern "C" fn perform_updates() {
    debug!("perform_updates");
    call(|s| s.perform_updates());
}

#[no_mangle]
pub extern "C" fn load_uri(url: *const c_char) {
    debug!("load_url");
    let url = unsafe { CStr::from_ptr(url) };
    let url = url.to_str().expect("Can't read string");
    call(|s| s.load_uri(url));
}

#[no_mangle]
pub extern "C" fn reload() {
    debug!("reload");
    call(|s| s.reload());
}

#[no_mangle]
pub extern "C" fn stop() {
    debug!("stop");
    call(|s| s.stop());
}

#[no_mangle]
pub extern "C" fn refresh() {
    debug!("refresh");
    call(|s| s.refresh());
}

#[no_mangle]
pub extern "C" fn go_back() {
    debug!("go_back");
    call(|s| s.go_back());
}

#[no_mangle]
pub extern "C" fn go_forward() {
    debug!("go_forward");
    call(|s| s.go_forward());
}

#[no_mangle]
pub extern "C" fn scroll_start(dx: i32, dy: i32, x: i32, y: i32) {
    debug!("scroll_start");
    call(|s| s.scroll_start(dx as f32, dy as f32, x, y));
}

#[no_mangle]
pub extern "C" fn scroll_end(dx: i32, dy: i32, x: i32, y: i32) {
    debug!("scroll_end");
    call(|s| s.scroll_end(dx as f32, dy as f32, x, y));
}

#[no_mangle]
pub extern "C" fn scroll(dx: i32, dy: i32, x: i32, y: i32) {
    debug!("scroll");
    call(|s| s.scroll(dx as f32, dy as f32, x, y));
}

#[no_mangle]
pub extern "C" fn touch_down(x: f32, y: f32, pointer_id: i32) {
    debug!("touch down");
    call(|s| s.touch_down(x, y, pointer_id));
}

#[no_mangle]
pub extern "C" fn touch_up(x: f32, y: f32, pointer_id: i32) {
    debug!("touch up");
    call(|s| s.touch_up(x, y, pointer_id));
}

#[no_mangle]
pub extern "C" fn touch_move(x: f32, y: f32, pointer_id: i32) {
    debug!("touch move");
    call(|s| s.touch_move(x, y, pointer_id));
}

#[no_mangle]
pub extern "C" fn touch_cancel(x: f32, y: f32, pointer_id: i32) {
    debug!("touch cancel");
    call(|s| s.touch_cancel(x, y, pointer_id));
}

#[no_mangle]
pub extern "C" fn pinchzoom_start(factor: f32, x: i32, y: i32) {
    debug!("pinchzoom_start");
    call(|s| s.pinchzoom_start(factor, x as u32, y as u32));
}

#[no_mangle]
pub extern "C" fn pinchzoom(factor: f32, x: i32, y: i32) {
    debug!("pinchzoom");
    call(|s| s.pinchzoom(factor, x as u32, y as u32));
}

#[no_mangle]
pub extern "C" fn pinchzoom_end(factor: f32, x: i32, y: i32) {
    debug!("pinchzoom_end");
    call(|s| s.pinchzoom_end(factor, x as u32, y as u32));
}

#[no_mangle]
pub extern "C" fn click(x: i32, y: i32) {
    debug!("click");
    call(|s| s.click(x as f32, y as f32));
}

pub struct WakeupCallback(extern "C" fn());

impl WakeupCallback {
    fn new(callback: extern "C" fn()) -> WakeupCallback {
        WakeupCallback(callback)
    }
}

impl EventLoopWaker for WakeupCallback {
    fn clone(&self) -> Box<dyn EventLoopWaker + Send> {
        Box::new(WakeupCallback(self.0))
    }
    fn wake(&self) {
        (self.0)();
    }
}

struct HostCallbacks(CHostCallbacks);

impl HostCallbacks {
    fn new(callback: CHostCallbacks) -> HostCallbacks {
        HostCallbacks(callback)
    }
}

impl HostTrait for HostCallbacks {
    fn flush(&self) {
        debug!("flush");
        (self.0.flush)();
    }

    fn make_current(&self) {
        debug!("make_current");
        (self.0.make_current)();
    }

    fn on_load_started(&self) {
        debug!("on_load_ended");
        (self.0.on_load_started)();
    }

    fn on_load_ended(&self) {
        debug!("on_load_ended");
        (self.0.on_load_ended)();
    }

    fn on_title_changed(&self, title: String) {
        debug!("on_title_changed");
        let title = CString::new(title).expect("Can't create string");
        let title_ptr = title.as_ptr();
        mem::forget(title);
        (self.0.on_title_changed)(title_ptr);
    }

    fn on_url_changed(&self, url: String) {
        debug!("on_url_changed");
        let url = CString::new(url).expect("Can't create string");
        let url_ptr = url.as_ptr();
        mem::forget(url);
        (self.0.on_url_changed)(url_ptr);
    }

    fn on_history_changed(&self, can_go_back: bool, can_go_forward: bool) {
        debug!("on_history_changed");
        (self.0.on_history_changed)(can_go_back, can_go_forward);
    }

    fn on_animating_changed(&self, animating: bool) {
        debug!("on_animating_changed");
        (self.0.on_animating_changed)(animating);
    }

    fn on_shutdown_complete(&self) {
        debug!("on_shutdown_complete");
        (self.0.on_shutdown_complete)();
    }

    fn on_ime_state_changed(&self, show: bool) {
        debug!("on_ime_state_changed");
        (self.0.on_ime_state_changed)(show);
    }
}
<commit_msg>Auto merge of #23501 - paulrouget:nullcheck, r=jdm<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 https://mozilla.org/MPL/2.0/. */

#[macro_use]
extern crate log;

use env_logger;
use simpleservo::{
    self, gl_glue, Coordinates, EventLoopWaker, HostTrait, InitOptions, ServoGlue, SERVO,
};
use std::ffi::{CStr, CString};
use std::mem;
use std::os::raw::{c_char, c_void};

fn call<F>(f: F)
where
    F: Fn(&mut ServoGlue) -> Result<(), &'static str>,
{
    SERVO.with(|s| {
        if let Err(error) = match s.borrow_mut().as_mut() {
            Some(ref mut s) => (f)(s),
            None => Err("Servo not available in this thread"),
        } {
            // FIXME: All C calls should have a have generic Result-like
            // return type. For now, we just panic instead of notifying
            // the embedder.
            panic!(error);
        }
    });
}

/// Callback used by Servo internals
#[repr(C)]
pub struct CHostCallbacks {
    pub flush: extern "C" fn(),
    pub make_current: extern "C" fn(),
    pub on_load_started: extern "C" fn(),
    pub on_load_ended: extern "C" fn(),
    pub on_title_changed: extern "C" fn(title: *const c_char),
    pub on_url_changed: extern "C" fn(url: *const c_char),
    pub on_history_changed: extern "C" fn(can_go_back: bool, can_go_forward: bool),
    pub on_animating_changed: extern "C" fn(animating: bool),
    pub on_shutdown_complete: extern "C" fn(),
    pub on_ime_state_changed: extern "C" fn(show: bool),
}

/// Servo options
#[repr(C)]
pub struct CInitOptions {
    pub args: *const c_char,
    pub url: *const c_char,
    pub width: i32,
    pub height: i32,
    pub density: f32,
    pub vr_pointer: *mut c_void,
    pub enable_subpixel_text_antialiasing: bool,
}

/// The returned string is not freed. This will leak.
#[no_mangle]
pub extern "C" fn servo_version() -> *const c_char {
    let v = simpleservo::servo_version();
    let text = CString::new(v).expect("Can't create string");
    let ptr = text.as_ptr();
    mem::forget(text);
    ptr
}

fn init(
    opts: CInitOptions,
    gl: gl_glue::ServoGl,
    wakeup: extern "C" fn(),
    callbacks: CHostCallbacks,
) {
    crate::env_logger::init();

    let args = if !opts.args.is_null() {
        let args = unsafe { CStr::from_ptr(opts.args) };
        args.to_str()
            .unwrap_or("")
            .split(' ')
            .map(|s| s.to_owned())
            .collect()
    } else {
        vec![]
    };

    let url = unsafe { CStr::from_ptr(opts.url) };
    let url = url.to_str().map(|s| s.to_string()).ok();

    let coordinates = Coordinates::new(0, 0, opts.width, opts.height, opts.width, opts.height);

    let opts = InitOptions {
        args,
        url,
        coordinates,
        density: opts.density,
        vr_pointer: if opts.vr_pointer.is_null() {
            None
        } else {
            Some(opts.vr_pointer)
        },
        enable_subpixel_text_antialiasing: opts.enable_subpixel_text_antialiasing,
    };

    let wakeup = Box::new(WakeupCallback::new(wakeup));
    let callbacks = Box::new(HostCallbacks::new(callbacks));

    simpleservo::init(opts, gl, wakeup, callbacks).unwrap();
}

#[cfg(target_os = "windows")]
#[no_mangle]
pub extern "C" fn init_with_egl(
    opts: CInitOptions,
    wakeup: extern "C" fn(),
    callbacks: CHostCallbacks,
) {
    let gl = gl_glue::egl::init().unwrap();
    init(opts, gl, wakeup, callbacks)
}

#[cfg(any(target_os = "linux", target_os = "windows", target_os = "macos"))]
#[no_mangle]
pub extern "C" fn init_with_gl(
    opts: CInitOptions,
    wakeup: extern "C" fn(),
    callbacks: CHostCallbacks,
) {
    let gl = gl_glue::gl::init().unwrap();
    init(opts, gl, wakeup, callbacks)
}

#[no_mangle]
pub extern "C" fn deinit() {
    debug!("deinit");
    simpleservo::deinit();
}

#[no_mangle]
pub extern "C" fn request_shutdown() {
    debug!("request_shutdown");
    call(|s| s.request_shutdown());
}

#[no_mangle]
pub extern "C" fn set_batch_mode(batch: bool) {
    debug!("set_batch_mode");
    call(|s| s.set_batch_mode(batch));
}

#[no_mangle]
pub extern "C" fn resize(width: i32, height: i32) {
    debug!("resize {}/{}", width, height);
    call(|s| {
        let coordinates = Coordinates::new(0, 0, width, height, width, height);
        s.resize(coordinates)
    });
}

#[no_mangle]
pub extern "C" fn perform_updates() {
    debug!("perform_updates");
    call(|s| s.perform_updates());
}

#[no_mangle]
pub extern "C" fn load_uri(url: *const c_char) {
    debug!("load_url");
    let url = unsafe { CStr::from_ptr(url) };
    let url = url.to_str().expect("Can't read string");
    call(|s| s.load_uri(url));
}

#[no_mangle]
pub extern "C" fn reload() {
    debug!("reload");
    call(|s| s.reload());
}

#[no_mangle]
pub extern "C" fn stop() {
    debug!("stop");
    call(|s| s.stop());
}

#[no_mangle]
pub extern "C" fn refresh() {
    debug!("refresh");
    call(|s| s.refresh());
}

#[no_mangle]
pub extern "C" fn go_back() {
    debug!("go_back");
    call(|s| s.go_back());
}

#[no_mangle]
pub extern "C" fn go_forward() {
    debug!("go_forward");
    call(|s| s.go_forward());
}

#[no_mangle]
pub extern "C" fn scroll_start(dx: i32, dy: i32, x: i32, y: i32) {
    debug!("scroll_start");
    call(|s| s.scroll_start(dx as f32, dy as f32, x, y));
}

#[no_mangle]
pub extern "C" fn scroll_end(dx: i32, dy: i32, x: i32, y: i32) {
    debug!("scroll_end");
    call(|s| s.scroll_end(dx as f32, dy as f32, x, y));
}

#[no_mangle]
pub extern "C" fn scroll(dx: i32, dy: i32, x: i32, y: i32) {
    debug!("scroll");
    call(|s| s.scroll(dx as f32, dy as f32, x, y));
}

#[no_mangle]
pub extern "C" fn touch_down(x: f32, y: f32, pointer_id: i32) {
    debug!("touch down");
    call(|s| s.touch_down(x, y, pointer_id));
}

#[no_mangle]
pub extern "C" fn touch_up(x: f32, y: f32, pointer_id: i32) {
    debug!("touch up");
    call(|s| s.touch_up(x, y, pointer_id));
}

#[no_mangle]
pub extern "C" fn touch_move(x: f32, y: f32, pointer_id: i32) {
    debug!("touch move");
    call(|s| s.touch_move(x, y, pointer_id));
}

#[no_mangle]
pub extern "C" fn touch_cancel(x: f32, y: f32, pointer_id: i32) {
    debug!("touch cancel");
    call(|s| s.touch_cancel(x, y, pointer_id));
}

#[no_mangle]
pub extern "C" fn pinchzoom_start(factor: f32, x: i32, y: i32) {
    debug!("pinchzoom_start");
    call(|s| s.pinchzoom_start(factor, x as u32, y as u32));
}

#[no_mangle]
pub extern "C" fn pinchzoom(factor: f32, x: i32, y: i32) {
    debug!("pinchzoom");
    call(|s| s.pinchzoom(factor, x as u32, y as u32));
}

#[no_mangle]
pub extern "C" fn pinchzoom_end(factor: f32, x: i32, y: i32) {
    debug!("pinchzoom_end");
    call(|s| s.pinchzoom_end(factor, x as u32, y as u32));
}

#[no_mangle]
pub extern "C" fn click(x: i32, y: i32) {
    debug!("click");
    call(|s| s.click(x as f32, y as f32));
}

pub struct WakeupCallback(extern "C" fn());

impl WakeupCallback {
    fn new(callback: extern "C" fn()) -> WakeupCallback {
        WakeupCallback(callback)
    }
}

impl EventLoopWaker for WakeupCallback {
    fn clone(&self) -> Box<dyn EventLoopWaker + Send> {
        Box::new(WakeupCallback(self.0))
    }
    fn wake(&self) {
        (self.0)();
    }
}

struct HostCallbacks(CHostCallbacks);

impl HostCallbacks {
    fn new(callback: CHostCallbacks) -> HostCallbacks {
        HostCallbacks(callback)
    }
}

impl HostTrait for HostCallbacks {
    fn flush(&self) {
        debug!("flush");
        (self.0.flush)();
    }

    fn make_current(&self) {
        debug!("make_current");
        (self.0.make_current)();
    }

    fn on_load_started(&self) {
        debug!("on_load_ended");
        (self.0.on_load_started)();
    }

    fn on_load_ended(&self) {
        debug!("on_load_ended");
        (self.0.on_load_ended)();
    }

    fn on_title_changed(&self, title: String) {
        debug!("on_title_changed");
        let title = CString::new(title).expect("Can't create string");
        let title_ptr = title.as_ptr();
        mem::forget(title);
        (self.0.on_title_changed)(title_ptr);
    }

    fn on_url_changed(&self, url: String) {
        debug!("on_url_changed");
        let url = CString::new(url).expect("Can't create string");
        let url_ptr = url.as_ptr();
        mem::forget(url);
        (self.0.on_url_changed)(url_ptr);
    }

    fn on_history_changed(&self, can_go_back: bool, can_go_forward: bool) {
        debug!("on_history_changed");
        (self.0.on_history_changed)(can_go_back, can_go_forward);
    }

    fn on_animating_changed(&self, animating: bool) {
        debug!("on_animating_changed");
        (self.0.on_animating_changed)(animating);
    }

    fn on_shutdown_complete(&self) {
        debug!("on_shutdown_complete");
        (self.0.on_shutdown_complete)();
    }

    fn on_ime_state_changed(&self, show: bool) {
        debug!("on_ime_state_changed");
        (self.0.on_ime_state_changed)(show);
    }
}
<|endoftext|>


<commit_before>extern crate image;
extern crate glium;
extern crate calx_window;
extern crate calx_cache;
extern crate calx_draw;

use std::char;
use glium::Surface;
use calx_cache::{AtlasBuilder, Atlas, AtlasItem, ImageStore, Font};
use calx_window::{WindowBuilder, Window, Event, Key};
use calx_draw::Buffer;

struct Context {
    pub window: Window,
    pub buffer: Buffer,
    pub tiles: Vec<AtlasItem>,
    pub font: Font<usize>,
}

impl Context {
    pub fn new() -> Context {
        let window = WindowBuilder::new().set_title("Calx demo").build();
        let mut atlas_builder = AtlasBuilder::new();

        // Solid color as the default element.
        assert!(atlas_builder.add_solid_image() == Default::default());

        // Load font into atlas.
        const DATA: &'static [u8] = include_bytes!("../assets/font.png");
        let font = Font::new(&mut image::load_from_memory(DATA).unwrap(),
                             &(32..128)
                                  .map(|i| char::from_u32(i).unwrap())
                                  .collect::<String>(),
                             &mut atlas_builder);

        let Atlas {
            image: img,
            items: tiles,
        } = atlas_builder.build();

        let buffer = Buffer::new(&window.display, img);

        Context {
            window: window,
            buffer: buffer,
            tiles: tiles,
            font: font,
        }
    }

    pub fn end_frame(&mut self) {
        let display = self.window.display.clone();
        let buffer = &mut self.buffer;

        self.window.draw(|target| {
            target.clear_color(0.4, 0.6, 0.9, 0.0);
            target.clear_depth(1.0);
            buffer.flush(&display, target);
        });

        self.window.end_frame();
    }
}

fn main() {
    let mut ctx = Context::new();

    'top: loop {
        for e in ctx.window.events().into_iter() {
            match e {
                Event::Quit => break 'top,
                Event::KeyPress(Key::Escape) => break 'top,
                _ => (),
            }
        }

        ctx.end_frame();
    }
}
<commit_msg>Demo uses context object<commit_after>extern crate image;
extern crate glium;
extern crate calx_color;
extern crate calx_layout;
extern crate calx_window;
extern crate calx_cache;
extern crate calx_draw;

use std::char;
use calx_color::{color};
use calx_layout::Rect;
use calx_cache::{AtlasBuilder, ImageStore, Font};
use calx_window::{WindowBuilder, Event, Key};
use calx_draw::{MeshContext, DrawUtil};

fn main() {
    let mut atlas_builder = AtlasBuilder::new();

    // Solid color as the default element.
    assert!(atlas_builder.add_solid_image() == Default::default());

    // Load font into atlas.
    const DATA: &'static [u8] = include_bytes!("../assets/font.png");
    let font = Font::new(&mut image::load_from_memory(DATA).unwrap(),
                         &(32..128)
                              .map(|i| char::from_u32(i).unwrap())
                              .collect::<String>(),
                         &mut atlas_builder);

    let mut ctx = MeshContext::new(WindowBuilder::new().set_title("Calx demo"),
                                   atlas_builder);

    'top: loop {
       ctx.draw_image(10, [10.0, 10.0], 0.4, color::BLACK, color::BLACK);

        for e in ctx.window.events().into_iter() {
            match e {
                Event::Quit => break 'top,
                Event::KeyPress(Key::Escape) => break 'top,
                _ => (),
            }
        }

        ctx.end_frame();
    }
}
<|endoftext|>


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

use std::cell::Cell;
use std::mem::swap;

// Just a grab bag of stuff that you wouldn't want to actually write.

fn strange() -> bool { let _x: bool = return true; }

fn funny() {
    fn f(_x: ()) { }
    f(return);
}

fn what() {
    fn the(x: &Cell<bool>) {
        return while !x.get() { x.set(true); };
    }
    let i = &Cell::new(false);
    let dont = {||the(i)};
    dont();
    assert!((i.get()));
}

fn zombiejesus() {
    loop {
        while (return) {
            if (return) {
                match (return) {
                    1 => {
                        if (return) {
                            return
                        } else {
                            return
                        }
                    }
                    _ => { return }
                };
            } else if (return) {
                return;
            }
        }
        if (return) { break; }
    }
}

fn notsure() {
    let mut _x: isize;
    let mut _y = (_x = 0) == (_x = 0);
    let mut _z = (_x = 0) < (_x = 0);
    let _a = (_x += 0) == (_x = 0);
    let _b = swap(&mut _y, &mut _z) == swap(&mut _y, &mut _z);
}

fn canttouchthis() -> usize {
    fn p() -> bool { true }
    let _a = (assert!((true)) == (assert!(p())));
    let _c = (assert!((p())) == ());
    let _b: bool = (println!("{}", 0) == (return 0));
}

fn angrydome() {
    loop { if break { } }
    let mut i = 0;
    loop { i += 1; if i == 1 { match (continue) { 1 => { }, _ => panic!("wat") } }
      break; }
}

fn evil_lincoln() { let _evil = println!("lincoln"); }

pub fn main() {
    strange();
    funny();
    what();
    zombiejesus();
    notsure();
    canttouchthis();
    angrydome();
    evil_lincoln();
}
<commit_msg>Auto merge of #42247 - durka:patch-41, r=arielb1<commit_after>// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use std::cell::Cell;
use std::mem::swap;

// Just a grab bag of stuff that you wouldn't want to actually write.

fn strange() -> bool { let _x: bool = return true; }

fn funny() {
    fn f(_x: ()) { }
    f(return);
}

fn what() {
    fn the(x: &Cell<bool>) {
        return while !x.get() { x.set(true); };
    }
    let i = &Cell::new(false);
    let dont = {||the(i)};
    dont();
    assert!((i.get()));
}

fn zombiejesus() {
    loop {
        while (return) {
            if (return) {
                match (return) {
                    1 => {
                        if (return) {
                            return
                        } else {
                            return
                        }
                    }
                    _ => { return }
                };
            } else if (return) {
                return;
            }
        }
        if (return) { break; }
    }
}

fn notsure() {
    let mut _x: isize;
    let mut _y = (_x = 0) == (_x = 0);
    let mut _z = (_x = 0) < (_x = 0);
    let _a = (_x += 0) == (_x = 0);
    let _b = swap(&mut _y, &mut _z) == swap(&mut _y, &mut _z);
}

fn canttouchthis() -> usize {
    fn p() -> bool { true }
    let _a = (assert!((true)) == (assert!(p())));
    let _c = (assert!((p())) == ());
    let _b: bool = (println!("{}", 0) == (return 0));
}

fn angrydome() {
    loop { if break { } }
    let mut i = 0;
    loop { i += 1; if i == 1 { match (continue) { 1 => { }, _ => panic!("wat") } }
      break; }
}

fn evil_lincoln() { let _evil = println!("lincoln"); }

fn dots() {
    assert_eq!(String::from(".................................................."),
               format!("{:?}", .. .. .. .. .. .. .. .. .. .. .. .. ..
                               .. .. .. .. .. .. .. .. .. .. .. ..));
}

fn you_eight() {
    assert_eq!(8, {
        macro_rules! u8 {
            (u8) => {
                mod u8 {
                    pub fn u8<'u8>(u8: &'u8 u8) -> &'u8 u8 {
                        "u8";
                        u8
                    }
                }
            };
        }

        u8!(u8);
        let &u8: &u8 = u8::u8(&8u8);
        u8
    });
}

fn fishy() {
    assert_eq!(String::from("><>"),
               String::<>::from::<>("><>").chars::<>().rev::<>().collect::<String>());
}

pub fn main() {
    strange();
    funny();
    what();
    zombiejesus();
    notsure();
    canttouchthis();
    angrydome();
    evil_lincoln();
    dots();
    you_eight();
    fishy();
}
<|endoftext|>


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

#[derive(Debug, Deserialize)]
pub struct Service {
    pub documentation: Option<String>,
    pub examples: Option<BTreeMap<String, String>>,
    pub metadata: Metadata,
    pub operations: BTreeMap<String, Operation>,
    pub shapes: BTreeMap<String, Shape>,
    pub version: String,
}

impl Service {
    pub fn client_type_name(&self) -> String {
        format!("{}Client", self.service_type_name())
    }

    pub fn service_type_name(&self) -> &str {
        match &self.metadata.service_full_name[..] {
            "AWS Certificate Manager" => "Acm",
            "AWS CloudFormation" => "CloudFormation",
            "AWS CloudTrail" => "CloudTrail",
            "AWS CodeCommit" => "CodeCommit",
            "AWS CodeDeploy" => "CodeDeploy",
            "AWS CodePipeline" => "CodePipeline",
            "AWS Config" => "ConfigService",
            "AWS Data Pipeline" => "DataPipeline",
            "AWS Device Farm" => "DeviceFarm",
            "AWS Direct Connect" => "DirectConnect",
            "AWS Directory Service" => "DirectoryService",
            "AWS Elastic Beanstalk" => "ElasticBeanstalk",
            "AWS Identity and Access Management" => "Iam",
            "AWS Import/Export" => "ImportExport",
            "AWS IoT Data Plane" => "IotDataPlane",
            "AWS IoT" => "Iot",
            "AWS Key Management Service" => "Kms",
            "AWS Lambda" => "Lambda",
            "AWS Marketplace Commerce Analytics" => "MarketplaceCommerceAnalytics",
            "AWS OpsWorks" => "OpsWorks",
            "AWS Security Token Service" => "Sts",
            "AWS Storage Gateway" => "StorageGateway",
            "AWS Support" => "Support",
            "AWS WAF" => "Waf",
            "Amazon API Gateway" => "ApiGateway",
            "Amazon CloudFront" => "CloudFront",
            "Amazon CloudHSM" => "CloudHsm",
            "Amazon CloudSearch Domain" => "CloudSearchDomain",
            "Amazon CloudSearch" => "CloudSearch",
            "Amazon CloudWatch Events" => "CloudWatchEvents",
            "Amazon CloudWatch Logs" => "CloudWatchLogs",
            "Amazon CloudWatch" => "CloudWatch",
            "Amazon Cognito Identity" => "CognitoIdentity",
            "Amazon Cognito Sync" => "CognitoSync",
            "Amazon DynamoDB Streams" => "DynamoDbStreams",
            "Amazon DynamoDB" => "DynamoDb",
            "Amazon EC2 Container Registry" => "Ecr",
            "Amazon EC2 Container Service" => "Ecs",
            "Amazon ElastiCache" => "ElastiCache",
            "Amazon Elastic Compute Cloud" => "Ec2",
            "Amazon Elastic File System" => "Efs",
            "Amazon Elastic MapReduce" => "Emr",
            "Amazon Elastic Transcoder" => "Ets",
            "Amazon Elasticsearch Service" => "ElasticsearchService",
            "Amazon GameLift" => "GameLift",
            "Amazon Glacier" => "Glacier",
            "Amazon Inspector" => "Inspector",
            "Amazon Kinesis Firehose" => "KinesisFirehose",
            "Amazon Kinesis" => "Kinesis",
            "Amazon Machine Learning" => "MachineLearning",
            "Amazon Redshift" => "Redshift",
            "Amazon Relational Database Service" => "Rds",
            "Amazon Route 53 Domains" => "Route53Domains",
            "Amazon Route 53" => "Route53",
            "Amazon Simple Email Service" => "Ses",
            "Amazon Simple Notification Service" => "Sns",
            "Amazon Simple Queue Service" => "Sqs",
            "Amazon Simple Storage Service" => "S3",
            "Amazon Simple Systems Management Service" => "Ssm",
            "Amazon Simple Workflow Service" => "Swf",
            "Amazon SimpleDB" => "SimpleDb",
            "Amazon WorkSpaces" => "Workspaces",
            "Auto Scaling" => "Autoscaling",
            "Elastic Load Balancing" => "Elb",
            name => panic!("Unknown service full name: {}", name),
        }
    }

    pub fn shape_for_member<'a>(&'a self, member: &Member) -> Option<&'a Shape> {
        self.shapes.get(&member.shape).map(|shape| shape)
    }

    pub fn shape_type_for_member<'a>(&'a self, member: &Member) -> Option<&'a str> {
        self.shapes.get(&member.shape).map(|ref shape| &shape.shape_type[..])
    }

    pub fn typed_errors(&self) -> bool {
        match self.service_type_name() {
            "Kinesis" | "KinesisFirehose" => true,
            _ => false
        }
    }
}

#[derive(Debug, Deserialize)]
pub struct HttpRequest {
    pub method: String,
    #[serde(rename="requestUri")]
    pub request_uri: String,
    #[serde(rename="responseCode")]
    pub response_code: Option<i32>,
}

#[derive(Debug, Deserialize)]
pub struct Input {
    pub documentation: Option<String>,
    pub shape: String,
}

#[derive(Debug, Deserialize)]
pub struct Output {
    pub documentation: Option<String>,
    #[serde(rename="resultWrapper")]
    pub result_wrapper: Option<String>,
    pub shape: String,
}

#[derive(Debug, Deserialize)]
pub struct Error {
    pub documentation: Option<String>,
    pub error: Option<HttpError>,
    pub exception: Option<bool>,
    pub fault: Option<bool>,
    pub shape: String,
}

impl Error {
    pub fn idiomatic_error_name(&self) -> String {
        self.shape.replace("Exception","")
    }
}

#[derive(Debug, Deserialize)]
pub struct HttpError {
    pub code: Option<String>,
    #[serde(rename="httpStatusCode")]
    pub http_status_code: i32,
    #[serde(rename="senderFault")]
    pub sender_fault: Option<bool>,
}

#[derive(Debug, Deserialize)]
pub struct Member {
    pub deprecated: Option<bool>,
    pub documentation: Option<String>,
    pub flattened: Option<bool>,
    pub location: Option<String>,
    #[serde(rename="locationName")]
    pub location_name: Option<String>,
    pub shape: String,
    pub streaming: Option<bool>,
    #[serde(rename="xmlAttribute")]
    pub xml_attribute: Option<bool>,
    #[serde(rename="xmlNamespace")]
    pub xml_namespace: Option<XmlNamespace>,
}

impl Member {
    pub fn tag_name(&self) -> String {
        self.location_name.clone().unwrap_or(self.shape.clone())
    }
}

#[derive(Debug, Deserialize)]
pub struct XmlNamespace {
    pub prefix: Option<String>,
    pub uri: String,
}

#[derive(Debug, Deserialize)]
pub struct Key {
    pub documentation: Option<String>,
    #[serde(rename="locationName")]
    pub location_name: Option<String>,
    pub required: Option<bool>,
    pub shape: String,
}

impl Key {
    pub fn tag_name(&self) -> String {
        self.location_name.clone().unwrap_or(self.shape.clone())
    }
}

#[derive(Debug, Deserialize)]
pub struct Value {
    pub documentation: Option<String>,
    #[serde(rename="locationName")]
    pub location_name: Option<String>,
    pub shape: String,
}

impl Value {
    pub fn tag_name(&self) -> String {
        self.location_name.clone().unwrap_or(self.shape.clone())
    }
}

#[derive(Debug, Deserialize)]
pub struct Shape {
    #[serde(rename="box")]
    pub aws_box: Option<bool>,
    pub documentation: Option<String>,
    pub error: Option<HttpError>,
    pub exception: Option<bool>,
    pub fault: Option<bool>,
    pub flattened: Option<bool>,
    pub key: Option<Key>,
    #[serde(rename="locationName")]
    pub location_name: Option<String>,
    pub max: Option<i32>,
    pub member: Option<Member>,
    pub members: Option<BTreeMap<String, Member>>,
    pub min: Option<i32>,
    pub pattern: Option<String>,
    pub payload: Option<String>,
    pub required: Option<Vec<String>>,
    #[serde(rename="enum")]
    pub shape_enum: Option<Vec<String>>,
    #[serde(rename="type")]
    pub shape_type: String,
    pub sensitive: Option<bool>,
    #[serde(rename="timestampFormat")]
    pub timestamp_format: Option<String>,
    pub value: Option<Value>,
    #[serde(rename="xmlNamespace")]
    pub xml_namespace: Option<XmlNamespace>,
}

impl<'a> Shape {
    pub fn key(&'a self) -> &'a str {
        &self.key.as_ref().expect("Key shape undefined").shape
    }

    pub fn value(&'a self) -> &'a str {
        &self.value.as_ref().expect("Value shape undefined").shape
    }

    pub fn member(&'a self) -> &'a str {
        &self.member.as_ref().expect("Member shape undefined").shape
    }

    pub fn required(&self, field: &'a str) -> bool {
        self.required.is_some() && self.required.as_ref().unwrap().contains(&String::from(field))
    }

    pub fn exception(&self) -> bool {
        self.exception.unwrap_or(false)
    }
}

#[derive(Debug, Deserialize)]
pub struct Operation {
    pub alias: Option<String>,
    pub deprecated: Option<bool>,
    pub documentation: Option<String>,
    #[serde(rename="documentationUrl")]
    pub documentation_url: Option<String>,
    pub errors: Option<Vec<Error>>,
    pub http: HttpRequest,
    pub input: Option<Input>,
    pub name: String,
    pub output: Option<Output>,
}

impl<'a> Operation {
    pub fn input_shape(&'a self) -> &'a str {
        &self.input.as_ref().expect("Operation input undefined").shape
    }

    pub fn output_shape_or(&'a self, default: &'a str) -> &'a str {
        match self.output.as_ref() {
            Some(output) => &output.shape,
            None => default
        }
    }
}

#[derive(Debug, Deserialize)]
pub struct Metadata {
    #[serde(rename="apiVersion")]
    pub api_version: String,
    #[serde(rename="checksumFormat")]
    pub checksum_format: Option<String>,
    #[serde(rename="endpointPrefix")]
    pub endpoint_prefix: String,
    #[serde(rename="globalEndpoint")]
    pub global_endpoint: Option<String>,
    #[serde(rename="jsonVersion")]
    pub json_version: Option<String>,
    pub protocol: String,
    #[serde(rename="serviceAbbreviation")]
    pub service_abbreviation: Option<String>,
    #[serde(rename="serviceFullName")]
    pub service_full_name: String,
    #[serde(rename="signatureVersion")]
    pub signature_version: String,
    #[serde(rename="targetPrefix")]
    pub target_prefix: Option<String>,
    #[serde(rename="timestampFormat")]
    pub timestamp_format: Option<String>,
    #[serde(rename="xmlNamespace")]
    pub xml_namespace: Option<String>
}
<commit_msg>use typed errors for all json protocol services<commit_after>use std::collections::BTreeMap;

#[derive(Debug, Deserialize)]
pub struct Service {
    pub documentation: Option<String>,
    pub examples: Option<BTreeMap<String, String>>,
    pub metadata: Metadata,
    pub operations: BTreeMap<String, Operation>,
    pub shapes: BTreeMap<String, Shape>,
    pub version: String,
}

impl Service {
    pub fn client_type_name(&self) -> String {
        format!("{}Client", self.service_type_name())
    }

    pub fn service_type_name(&self) -> &str {
        match &self.metadata.service_full_name[..] {
            "AWS Certificate Manager" => "Acm",
            "AWS CloudFormation" => "CloudFormation",
            "AWS CloudTrail" => "CloudTrail",
            "AWS CodeCommit" => "CodeCommit",
            "AWS CodeDeploy" => "CodeDeploy",
            "AWS CodePipeline" => "CodePipeline",
            "AWS Config" => "ConfigService",
            "AWS Data Pipeline" => "DataPipeline",
            "AWS Device Farm" => "DeviceFarm",
            "AWS Direct Connect" => "DirectConnect",
            "AWS Directory Service" => "DirectoryService",
            "AWS Elastic Beanstalk" => "ElasticBeanstalk",
            "AWS Identity and Access Management" => "Iam",
            "AWS Import/Export" => "ImportExport",
            "AWS IoT Data Plane" => "IotDataPlane",
            "AWS IoT" => "Iot",
            "AWS Key Management Service" => "Kms",
            "AWS Lambda" => "Lambda",
            "AWS Marketplace Commerce Analytics" => "MarketplaceCommerceAnalytics",
            "AWS OpsWorks" => "OpsWorks",
            "AWS Security Token Service" => "Sts",
            "AWS Storage Gateway" => "StorageGateway",
            "AWS Support" => "Support",
            "AWS WAF" => "Waf",
            "Amazon API Gateway" => "ApiGateway",
            "Amazon CloudFront" => "CloudFront",
            "Amazon CloudHSM" => "CloudHsm",
            "Amazon CloudSearch Domain" => "CloudSearchDomain",
            "Amazon CloudSearch" => "CloudSearch",
            "Amazon CloudWatch Events" => "CloudWatchEvents",
            "Amazon CloudWatch Logs" => "CloudWatchLogs",
            "Amazon CloudWatch" => "CloudWatch",
            "Amazon Cognito Identity" => "CognitoIdentity",
            "Amazon Cognito Sync" => "CognitoSync",
            "Amazon DynamoDB Streams" => "DynamoDbStreams",
            "Amazon DynamoDB" => "DynamoDb",
            "Amazon EC2 Container Registry" => "Ecr",
            "Amazon EC2 Container Service" => "Ecs",
            "Amazon ElastiCache" => "ElastiCache",
            "Amazon Elastic Compute Cloud" => "Ec2",
            "Amazon Elastic File System" => "Efs",
            "Amazon Elastic MapReduce" => "Emr",
            "Amazon Elastic Transcoder" => "Ets",
            "Amazon Elasticsearch Service" => "ElasticsearchService",
            "Amazon GameLift" => "GameLift",
            "Amazon Glacier" => "Glacier",
            "Amazon Inspector" => "Inspector",
            "Amazon Kinesis Firehose" => "KinesisFirehose",
            "Amazon Kinesis" => "Kinesis",
            "Amazon Machine Learning" => "MachineLearning",
            "Amazon Redshift" => "Redshift",
            "Amazon Relational Database Service" => "Rds",
            "Amazon Route 53 Domains" => "Route53Domains",
            "Amazon Route 53" => "Route53",
            "Amazon Simple Email Service" => "Ses",
            "Amazon Simple Notification Service" => "Sns",
            "Amazon Simple Queue Service" => "Sqs",
            "Amazon Simple Storage Service" => "S3",
            "Amazon Simple Systems Management Service" => "Ssm",
            "Amazon Simple Workflow Service" => "Swf",
            "Amazon SimpleDB" => "SimpleDb",
            "Amazon WorkSpaces" => "Workspaces",
            "Auto Scaling" => "Autoscaling",
            "Elastic Load Balancing" => "Elb",
            name => panic!("Unknown service full name: {}", name),
        }
    }

    pub fn shape_for_member<'a>(&'a self, member: &Member) -> Option<&'a Shape> {
        self.shapes.get(&member.shape).map(|shape| shape)
    }

    pub fn shape_type_for_member<'a>(&'a self, member: &Member) -> Option<&'a str> {
        self.shapes.get(&member.shape).map(|ref shape| &shape.shape_type[..])
    }

    pub fn typed_errors(&self) -> bool {
        match self.metadata.protocol.as_ref() {
            "json" => true,
            _ => false
        }
    }
}

#[derive(Debug, Deserialize)]
pub struct HttpRequest {
    pub method: String,
    #[serde(rename="requestUri")]
    pub request_uri: String,
    #[serde(rename="responseCode")]
    pub response_code: Option<i32>,
}

#[derive(Debug, Deserialize)]
pub struct Input {
    pub documentation: Option<String>,
    pub shape: String,
}

#[derive(Debug, Deserialize)]
pub struct Output {
    pub documentation: Option<String>,
    #[serde(rename="resultWrapper")]
    pub result_wrapper: Option<String>,
    pub shape: String,
}

#[derive(Debug, Deserialize)]
pub struct Error {
    pub documentation: Option<String>,
    pub error: Option<HttpError>,
    pub exception: Option<bool>,
    pub fault: Option<bool>,
    pub shape: String,
}

impl Error {
    pub fn idiomatic_error_name(&self) -> String {
        self.shape.replace("Exception","")
    }
}

#[derive(Debug, Deserialize)]
pub struct HttpError {
    pub code: Option<String>,
    #[serde(rename="httpStatusCode")]
    pub http_status_code: i32,
    #[serde(rename="senderFault")]
    pub sender_fault: Option<bool>,
}

#[derive(Debug, Deserialize)]
pub struct Member {
    pub deprecated: Option<bool>,
    pub documentation: Option<String>,
    pub flattened: Option<bool>,
    pub location: Option<String>,
    #[serde(rename="locationName")]
    pub location_name: Option<String>,
    pub shape: String,
    pub streaming: Option<bool>,
    #[serde(rename="xmlAttribute")]
    pub xml_attribute: Option<bool>,
    #[serde(rename="xmlNamespace")]
    pub xml_namespace: Option<XmlNamespace>,
}

impl Member {
    pub fn tag_name(&self) -> String {
        self.location_name.clone().unwrap_or(self.shape.clone())
    }
}

#[derive(Debug, Deserialize)]
pub struct XmlNamespace {
    pub prefix: Option<String>,
    pub uri: String,
}

#[derive(Debug, Deserialize)]
pub struct Key {
    pub documentation: Option<String>,
    #[serde(rename="locationName")]
    pub location_name: Option<String>,
    pub required: Option<bool>,
    pub shape: String,
}

impl Key {
    pub fn tag_name(&self) -> String {
        self.location_name.clone().unwrap_or(self.shape.clone())
    }
}

#[derive(Debug, Deserialize)]
pub struct Value {
    pub documentation: Option<String>,
    #[serde(rename="locationName")]
    pub location_name: Option<String>,
    pub shape: String,
}

impl Value {
    pub fn tag_name(&self) -> String {
        self.location_name.clone().unwrap_or(self.shape.clone())
    }
}

#[derive(Debug, Deserialize)]
pub struct Shape {
    #[serde(rename="box")]
    pub aws_box: Option<bool>,
    pub documentation: Option<String>,
    pub error: Option<HttpError>,
    pub exception: Option<bool>,
    pub fault: Option<bool>,
    pub flattened: Option<bool>,
    pub key: Option<Key>,
    #[serde(rename="locationName")]
    pub location_name: Option<String>,
    pub max: Option<i32>,
    pub member: Option<Member>,
    pub members: Option<BTreeMap<String, Member>>,
    pub min: Option<i32>,
    pub pattern: Option<String>,
    pub payload: Option<String>,
    pub required: Option<Vec<String>>,
    #[serde(rename="enum")]
    pub shape_enum: Option<Vec<String>>,
    #[serde(rename="type")]
    pub shape_type: String,
    pub sensitive: Option<bool>,
    #[serde(rename="timestampFormat")]
    pub timestamp_format: Option<String>,
    pub value: Option<Value>,
    #[serde(rename="xmlNamespace")]
    pub xml_namespace: Option<XmlNamespace>,
}

impl<'a> Shape {
    pub fn key(&'a self) -> &'a str {
        &self.key.as_ref().expect("Key shape undefined").shape
    }

    pub fn value(&'a self) -> &'a str {
        &self.value.as_ref().expect("Value shape undefined").shape
    }

    pub fn member(&'a self) -> &'a str {
        &self.member.as_ref().expect("Member shape undefined").shape
    }

    pub fn required(&self, field: &'a str) -> bool {
        self.required.is_some() && self.required.as_ref().unwrap().contains(&String::from(field))
    }

    pub fn exception(&self) -> bool {
        self.exception.unwrap_or(false)
    }
}

#[derive(Debug, Deserialize)]
pub struct Operation {
    pub alias: Option<String>,
    pub deprecated: Option<bool>,
    pub documentation: Option<String>,
    #[serde(rename="documentationUrl")]
    pub documentation_url: Option<String>,
    pub errors: Option<Vec<Error>>,
    pub http: HttpRequest,
    pub input: Option<Input>,
    pub name: String,
    pub output: Option<Output>,
}

impl<'a> Operation {
    pub fn input_shape(&'a self) -> &'a str {
        &self.input.as_ref().expect("Operation input undefined").shape
    }

    pub fn output_shape_or(&'a self, default: &'a str) -> &'a str {
        match self.output.as_ref() {
            Some(output) => &output.shape,
            None => default
        }
    }
}

#[derive(Debug, Deserialize)]
pub struct Metadata {
    #[serde(rename="apiVersion")]
    pub api_version: String,
    #[serde(rename="checksumFormat")]
    pub checksum_format: Option<String>,
    #[serde(rename="endpointPrefix")]
    pub endpoint_prefix: String,
    #[serde(rename="globalEndpoint")]
    pub global_endpoint: Option<String>,
    #[serde(rename="jsonVersion")]
    pub json_version: Option<String>,
    pub protocol: String,
    #[serde(rename="serviceAbbreviation")]
    pub service_abbreviation: Option<String>,
    #[serde(rename="serviceFullName")]
    pub service_full_name: String,
    #[serde(rename="signatureVersion")]
    pub signature_version: String,
    #[serde(rename="targetPrefix")]
    pub target_prefix: Option<String>,
    #[serde(rename="timestampFormat")]
    pub timestamp_format: Option<String>,
    #[serde(rename="xmlNamespace")]
    pub xml_namespace: Option<String>
}
<|endoftext|>


<commit_before>use rustc::ty;
use rustc::hir::def_id::DefId;
use rustc::lint::{LintContext, Lint, LateContext};
use rustc::hir::Expr_::*;
use rustc::hir::Expr;
use rustc::hir::def::Def;

use syntax::symbol;
use syntax_pos::Span;

const ROCKET_TYPE: &'static [&'static str] = &["rocket", "rocket", "Rocket"];

const ROCKET_IGNITE_FN: &'static [&'static str] = &["rocket", "ignite"];
const ROCKET_IGNITE_STATIC: &'static [&'static str] = &["rocket", "rocket",
                                                        "Rocket", "ignite"];

const ROCKET_CUSTOM_FN: &'static [&'static str] = &["rocket", "custom"];
const ROCKET_CUSTOM_STATIC: &'static [&'static str] = &["rocket", "rocket",
                                                        "Rocket", "custom"];

const ABSOLUTE: &'static ty::item_path::RootMode =
    &ty::item_path::RootMode::Absolute;

/// Check if a `DefId`'s path matches the given absolute type path usage.
pub fn match_def_path(tcx: ty::TyCtxt, def_id: DefId, path: &[&str]) -> bool {
    struct AbsolutePathBuffer {
        names: Vec<symbol::InternedString>,
    }

    impl ty::item_path::ItemPathBuffer for AbsolutePathBuffer {
        fn root_mode(&self) -> &ty::item_path::RootMode {
            ABSOLUTE
        }

        fn push(&mut self, text: &str) {
            self.names.push(symbol::Symbol::intern(text).as_str());
        }
    }

    let mut apb = AbsolutePathBuffer { names: vec![] };
    tcx.push_item_path(&mut apb, def_id);

    apb.names.len() == path.len() &&
    apb.names.iter().zip(path.iter()).all(|(a, &b)| &**a == b)
}

/// Check if the method call given in `expr` belongs to given type.
pub fn is_impl_method(cx: &LateContext, expr: &Expr, path: &[&str]) -> bool {
    let method_call = ty::MethodCall::expr(expr.id);

    let trt_id = cx.tables
        .method_map
        .get(&method_call)
        .and_then(|callee| cx.tcx.impl_of_method(callee.def_id));

    if let Some(trt_id) = trt_id {
        match_def_path(cx.tcx, trt_id, path)
    } else {
        false
    }
}

pub fn find_initial_receiver<'e>(cx: &LateContext,
                                 expr: &'e Expr)
                                 -> Option<&'e Expr> {
    match expr.node {
        ExprMethodCall(_, _, ref args) => find_initial_receiver(cx, &args[0]),
        ExprCall(..) if is_rocket_start_call(cx, expr) => Some(expr),
        ExprCall(ref call, _) => find_initial_receiver(cx, call),
        ExprPath(_) => Some(expr),
        _ => None,
    }
}

pub fn rocket_method_call<'e>(method: &str,
                              cx: &LateContext,
                              expr: &'e Expr)
                              -> (Option<(Option<&'e Expr>, &'e [Expr])>) {
    if let ExprMethodCall(ref name, _, ref exprs) = expr.node {
        if &*name.node.as_str() == method && is_impl_method(cx, expr, ROCKET_TYPE) {
            let receiver = find_initial_receiver(cx, &exprs[0]);
            return Some((receiver, &exprs[1..]));
        }
    }

    None
}

pub fn is_rocket_start_call(cx: &LateContext, expr: &Expr) -> bool {
    if let ExprCall(ref expr, ..) = expr.node {
        if let ExprPath(ref qpath) = expr.node {
            let def_id = cx.tables.qpath_def(qpath, expr.id).def_id();
            if match_def_path(cx.tcx, def_id, ROCKET_IGNITE_FN) {
                return true;
            } else if match_def_path(cx.tcx, def_id, ROCKET_IGNITE_STATIC) {
                return true;
            } else if match_def_path(cx.tcx, def_id, ROCKET_CUSTOM_FN) {
                return true;
            } else if is_impl_method(cx, expr, ROCKET_CUSTOM_STATIC) {
                return true;
            }
        }
    }

    false
}

pub fn extract_mount_fn_def_ids(cx: &LateContext, expr: &Expr) -> Vec<DefId> {
    let mut output = Vec::new();
    // Call to into_vec
    if let ExprCall(_, ref args) = expr.node {
        if let Some(&ExprBox(ref expr)) = args.iter().next().map(|e| &e.node) {
            // Array of routes.
            if let ExprArray(ref members) = expr.node {
                for expr in members.iter() {
                    // Route::From call
                    if let ExprCall(_, ref args) = expr.node {
                        if args.len() < 1 {
                            continue;
                        }

                        // address of info struct
                        if let ExprAddrOf(_, ref expr) = args[0].node {
                            // path to info_struct
                            if let ExprPath(ref qpath) = expr.node {
                                let def = cx.tables.qpath_def(qpath, expr.id);
                                output.push(def.def_id());
                            }
                        }
                    }
                }
            }
        }
    }

    output
}

pub fn returns_rocket_instance(cx: &LateContext, expr: &Expr) -> bool {
    if let Some(ref ty) = cx.tables.expr_ty_opt(expr) {
        if let Some(def_id) = ty.ty_to_def_id() {
            if match_def_path(cx.tcx, def_id, ROCKET_TYPE) {
                return true;
            }
        }
    }

    false
}

pub trait DefExt {
    fn def_id_opt(&self) -> Option<DefId>;
}

impl DefExt for Def {
    fn def_id_opt(&self) -> Option<DefId> {
        match *self {
            Def::Fn(id) |
            Def::Mod(id) |
            Def::Static(id, _) |
            Def::Variant(id) |
            Def::VariantCtor(id, ..) |
            Def::Enum(id) |
            Def::TyAlias(id) |
            Def::AssociatedTy(id) |
            Def::TyParam(id) |
            Def::Struct(id) |
            Def::StructCtor(id, ..) |
            Def::Union(id) |
            Def::Trait(id) |
            Def::Method(id) |
            Def::Const(id) |
            Def::AssociatedConst(id) |
            Def::Local(id) |
            Def::Upvar(id, ..) |
            Def::Macro(id) => Some(id),
            Def::Label(..) | Def::PrimTy(..) | Def::SelfTy(..) | Def::Err => None,
        }
    }
}

pub fn msg_and_help<'a, T: LintContext<'a>>(cx: &T,
                                            lint: &'static Lint,
                                            msg_sp: Span,
                                            msg: &str,
                                            note: &str,
                                            help_sp: Option<Span>,
                                            help: &str) {
    let mut b = cx.struct_span_lint(lint, msg_sp, msg);
    if let Some(span) = help_sp {
        b.span_help(span, help);
    }

    b.note(note);
    b.emit();
}
<commit_msg>Condense cases in 'def_id_opt'.<commit_after>use rustc::ty;
use rustc::hir::def_id::DefId;
use rustc::lint::{LintContext, Lint, LateContext};
use rustc::hir::Expr_::*;
use rustc::hir::Expr;
use rustc::hir::def::Def;

use syntax::symbol;
use syntax_pos::Span;

const ROCKET_TYPE: &'static [&'static str] = &["rocket", "rocket", "Rocket"];

const ROCKET_IGNITE_FN: &'static [&'static str] = &["rocket", "ignite"];
const ROCKET_IGNITE_STATIC: &'static [&'static str] = &["rocket", "rocket",
                                                        "Rocket", "ignite"];

const ROCKET_CUSTOM_FN: &'static [&'static str] = &["rocket", "custom"];
const ROCKET_CUSTOM_STATIC: &'static [&'static str] = &["rocket", "rocket",
                                                        "Rocket", "custom"];

const ABSOLUTE: &'static ty::item_path::RootMode =
    &ty::item_path::RootMode::Absolute;

/// Check if a `DefId`'s path matches the given absolute type path usage.
pub fn match_def_path(tcx: ty::TyCtxt, def_id: DefId, path: &[&str]) -> bool {
    struct AbsolutePathBuffer {
        names: Vec<symbol::InternedString>,
    }

    impl ty::item_path::ItemPathBuffer for AbsolutePathBuffer {
        fn root_mode(&self) -> &ty::item_path::RootMode {
            ABSOLUTE
        }

        fn push(&mut self, text: &str) {
            self.names.push(symbol::Symbol::intern(text).as_str());
        }
    }

    let mut apb = AbsolutePathBuffer { names: vec![] };
    tcx.push_item_path(&mut apb, def_id);

    apb.names.len() == path.len() &&
    apb.names.iter().zip(path.iter()).all(|(a, &b)| &**a == b)
}

/// Check if the method call given in `expr` belongs to given type.
pub fn is_impl_method(cx: &LateContext, expr: &Expr, path: &[&str]) -> bool {
    let method_call = ty::MethodCall::expr(expr.id);

    let trt_id = cx.tables
        .method_map
        .get(&method_call)
        .and_then(|callee| cx.tcx.impl_of_method(callee.def_id));

    if let Some(trt_id) = trt_id {
        match_def_path(cx.tcx, trt_id, path)
    } else {
        false
    }
}

pub fn find_initial_receiver<'e>(cx: &LateContext,
                                 expr: &'e Expr)
                                 -> Option<&'e Expr> {
    match expr.node {
        ExprMethodCall(_, _, ref args) => find_initial_receiver(cx, &args[0]),
        ExprCall(..) if is_rocket_start_call(cx, expr) => Some(expr),
        ExprCall(ref call, _) => find_initial_receiver(cx, call),
        ExprPath(_) => Some(expr),
        _ => None,
    }
}

pub fn rocket_method_call<'e>(method: &str,
                              cx: &LateContext,
                              expr: &'e Expr)
                              -> (Option<(Option<&'e Expr>, &'e [Expr])>) {
    if let ExprMethodCall(ref name, _, ref exprs) = expr.node {
        if &*name.node.as_str() == method && is_impl_method(cx, expr, ROCKET_TYPE) {
            let receiver = find_initial_receiver(cx, &exprs[0]);
            return Some((receiver, &exprs[1..]));
        }
    }

    None
}

pub fn is_rocket_start_call(cx: &LateContext, expr: &Expr) -> bool {
    if let ExprCall(ref expr, ..) = expr.node {
        if let ExprPath(ref qpath) = expr.node {
            let def_id = cx.tables.qpath_def(qpath, expr.id).def_id();
            if match_def_path(cx.tcx, def_id, ROCKET_IGNITE_FN) {
                return true;
            } else if match_def_path(cx.tcx, def_id, ROCKET_IGNITE_STATIC) {
                return true;
            } else if match_def_path(cx.tcx, def_id, ROCKET_CUSTOM_FN) {
                return true;
            } else if is_impl_method(cx, expr, ROCKET_CUSTOM_STATIC) {
                return true;
            }
        }
    }

    false
}

pub fn extract_mount_fn_def_ids(cx: &LateContext, expr: &Expr) -> Vec<DefId> {
    let mut output = Vec::new();
    // Call to into_vec
    if let ExprCall(_, ref args) = expr.node {
        if let Some(&ExprBox(ref expr)) = args.iter().next().map(|e| &e.node) {
            // Array of routes.
            if let ExprArray(ref members) = expr.node {
                for expr in members.iter() {
                    // Route::From call
                    if let ExprCall(_, ref args) = expr.node {
                        if args.len() < 1 {
                            continue;
                        }

                        // address of info struct
                        if let ExprAddrOf(_, ref expr) = args[0].node {
                            // path to info_struct
                            if let ExprPath(ref qpath) = expr.node {
                                let def = cx.tables.qpath_def(qpath, expr.id);
                                output.push(def.def_id());
                            }
                        }
                    }
                }
            }
        }
    }

    output
}

pub fn returns_rocket_instance(cx: &LateContext, expr: &Expr) -> bool {
    if let Some(ref ty) = cx.tables.expr_ty_opt(expr) {
        if let Some(def_id) = ty.ty_to_def_id() {
            if match_def_path(cx.tcx, def_id, ROCKET_TYPE) {
                return true;
            }
        }
    }

    false
}

pub trait DefExt {
    fn def_id_opt(&self) -> Option<DefId>;
}

impl DefExt for Def {
    fn def_id_opt(&self) -> Option<DefId> {
        match *self {
            Def::Fn(id) | Def::Mod(id) | Def::Static(id, _) | Def::Variant(id)
                | Def::VariantCtor(id, ..) | Def::Enum(id) | Def::TyAlias(id)
                | Def::AssociatedTy(id) | Def::TyParam(id) | Def::Struct(id)
                | Def::StructCtor(id, ..) | Def::Union(id) | Def::Trait(id)
                | Def::Method(id) | Def::Const(id) | Def::AssociatedConst(id)
                | Def::Local(id) | Def::Upvar(id, ..) | Def::Macro(id) => Some(id),
            Def::Label(..) | Def::PrimTy(..) | Def::SelfTy(..) | Def::Err => None,
        }
    }
}

pub fn msg_and_help<'a, T: LintContext<'a>>(cx: &T,
                                            lint: &'static Lint,
                                            msg_sp: Span,
                                            msg: &str,
                                            note: &str,
                                            help_sp: Option<Span>,
                                            help: &str) {
    let mut b = cx.struct_span_lint(lint, msg_sp, msg);
    if let Some(span) = help_sp {
        b.span_help(span, help);
    }

    b.note(note);
    b.emit();
}
<|endoftext|>