<commit_before>// why use a library? Clap lets us quickly build a CLI and
// lets us focus the below code on password generation
// not the intricacies building a CLI in rust.
// Read more about clap here: https://clap.rs/
// declare our external dependency for parsing command line arguments
extern crate clap;
// bring the App structure into scope so we can use it
use clap::App;

fn main() {
    App::new("password-generator")
        .version("0.1")
        .about("generate a password according to the rosetta code rules: http://rosettacode.org/wiki/Password_generator")
        .get_matches();
}
<commit_msg>add defaults for positional arguments<commit_after>// why use a library? Clap lets us quickly build a CLI and
// lets us focus the below code on password generation
// not the intricacies building a CLI in rust.
// Read more about clap here: https://clap.rs/
// declare our external dependency for parsing command line arguments
extern crate clap;
// bring the needed structures into scope so we
// invoke them later in the program
use clap::{App,Arg};

fn main() {
    // create our new CLI
    // clap provides powerful defaults so we don't have to
    // write all the logic here
    // For example, clap takes care of the help and version flags by default
    App::new("password-generator")
        .version("0.1")
        .about("generate a password according to the rosetta code rules: http://rosettacode.org/wiki/Password_generator")
        // configure our first required argument
        .arg(Arg::with_name("LENGTH")
             .help("password length")
             // make it SECURE by default
             // https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html
             .default_value("160")
             .required(true)
             .index(1)
            )
        // configure our second required argument
        .arg(Arg::with_name("COUNT")
             .help("how many passwords to generate")
             .default_value("1")
             .required(true)
             .index(2)
            )
        .get_matches();
}
<|endoftext|>


<commit_before>// Copyright 2017 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

use std::cmp::min;
use std::num::Wrapping;
use std::sync::atomic::{fence, Ordering};

use sys_util::{GuestAddress, GuestMemory};

const VIRTQ_DESC_F_NEXT: u16 = 0x1;
const VIRTQ_DESC_F_WRITE: u16 = 0x2;
#[allow(dead_code)]
const VIRTQ_DESC_F_INDIRECT: u16 = 0x4;

/// A virtio descriptor chain.
#[derive(Clone)]
pub struct DescriptorChain<'a> {
    mem: &'a GuestMemory,
    desc_table: GuestAddress,
    queue_size: u16,
    ttl: u16, // used to prevent infinite chain cycles

    /// Index into the descriptor table
    pub index: u16,

    /// Guest physical address of device specific data
    pub addr: GuestAddress,

    /// Length of device specific data
    pub len: u32,

    /// Includes next, write, and indirect bits
    pub flags: u16,

    /// Index into the descriptor table of the next descriptor if flags has
    /// the next bit set
    pub next: u16,
}

impl<'a> DescriptorChain<'a> {
    fn checked_new(mem: &GuestMemory,
                   desc_table: GuestAddress,
                   queue_size: u16,
                   index: u16)
                   -> Option<DescriptorChain> {
        if index >= queue_size {
            return None;
        }

        let desc_head = match mem.checked_offset(desc_table, (index as u64) * 16) {
            Some(a) => a,
            None => return None,
        };
        // These reads can't fail unless Guest memory is hopelessly broken.
        let addr = GuestAddress(mem.read_obj_from_addr::<u64>(desc_head).unwrap() as u64);
        if mem.checked_offset(desc_head, 16).is_none() {
            return None;
        }
        let len: u32 = mem.read_obj_from_addr(desc_head.unchecked_add(8))
            .unwrap();
        let flags: u16 = mem.read_obj_from_addr(desc_head.unchecked_add(12))
            .unwrap();
        let next: u16 = mem.read_obj_from_addr(desc_head.unchecked_add(14))
            .unwrap();
        let chain = DescriptorChain {
            mem: mem,
            desc_table: desc_table,
            queue_size: queue_size,
            ttl: queue_size,
            index: index,
            addr: addr,
            len: len,
            flags: flags,
            next: next,
        };

        if chain.is_valid() { Some(chain) } else { None }
    }

    fn is_valid(&self) -> bool {
        if self.mem
               .checked_offset(self.addr, self.len as u64)
               .is_none() {
            false
        } else if self.has_next() && self.next >= self.queue_size {
            false
        } else {
            true
        }
    }

    /// Gets if this descriptor chain has another descriptor chain linked after it.
    pub fn has_next(&self) -> bool {
        self.flags & VIRTQ_DESC_F_NEXT != 0 && self.ttl > 1
    }

    /// If the driver designated this as a write only descriptor.
    ///
    /// If this is false, this descriptor is read only.
    /// Write only means the the emulated device can write and the driver can read.
    pub fn is_write_only(&self) -> bool {
        self.flags & VIRTQ_DESC_F_WRITE != 0
    }

    /// Gets the next descriptor in this descriptor chain, if there is one.
    ///
    /// Note that this is distinct from the next descriptor chain returned by `AvailIter`, which is
    /// the head of the next _available_ descriptor chain.
    pub fn next_descriptor(&self) -> Option<DescriptorChain<'a>> {
        if self.has_next() {
            DescriptorChain::checked_new(self.mem, self.desc_table, self.queue_size, self.next)
                .map(|mut c| {
                         c.ttl = self.ttl - 1;
                         c
                     })
        } else {
            None
        }
    }
}

/// Consuming iterator over all available descriptor chain heads in the queue.
pub struct AvailIter<'a, 'b> {
    mem: &'a GuestMemory,
    desc_table: GuestAddress,
    avail_ring: GuestAddress,
    next_index: Wrapping<u16>,
    last_index: Wrapping<u16>,
    queue_size: u16,
    next_avail: &'b mut Wrapping<u16>,
}

impl<'a, 'b> Iterator for AvailIter<'a, 'b> {
    type Item = DescriptorChain<'a>;

    fn next(&mut self) -> Option<Self::Item> {
        if self.next_index == self.last_index {
            return None;
        }

        let offset = (4 + (self.next_index.0 % self.queue_size) * 2) as usize;
        let avail_addr = match self.mem.checked_offset(self.avail_ring, offset as u64) {
            Some(a) => a,
            None => return None,
        };
        // This index is checked below in checked_new
        let desc_index: u16 = self.mem.read_obj_from_addr(avail_addr).unwrap();

        self.next_index += Wrapping(1);

        let ret =
            DescriptorChain::checked_new(self.mem, self.desc_table, self.queue_size, desc_index);
        if ret.is_some() {
            *self.next_avail += Wrapping(1);
        }
        ret
    }
}

#[derive(Clone)]
/// A virtio queue's parameters.
pub struct Queue {
    /// The maximal size in elements offered by the device
    pub max_size: u16,

    /// The queue size in elements the driver selected
    pub size: u16,

    /// Inidcates if the queue is finished with configuration
    pub ready: bool,

    /// Guest physical address of the descriptor table
    pub desc_table: GuestAddress,

    /// Guest physical address of the available ring
    pub avail_ring: GuestAddress,

    /// Guest physical address of the used ring
    pub used_ring: GuestAddress,

    next_avail: Wrapping<u16>,
    next_used: Wrapping<u16>,
}

impl Queue {
    /// Constructs an empty virtio queue with the given `max_size`.
    pub fn new(max_size: u16) -> Queue {
        Queue {
            max_size: max_size,
            size: 0,
            ready: false,
            desc_table: GuestAddress(0),
            avail_ring: GuestAddress(0),
            used_ring: GuestAddress(0),
            next_avail: Wrapping(0),
            next_used: Wrapping(0),
        }
    }

    /// Return the actual size of the queue, as the driver may not set up a
    /// queue as big as the device allows.
    pub fn actual_size(&self) -> u16 {
        min(self.size, self.max_size)
    }

    pub fn is_valid(&self, mem: &GuestMemory) -> bool {
        let queue_size = self.actual_size() as usize;
        let desc_table = self.desc_table;
        let desc_table_size = 16 * queue_size;
        let avail_ring = self.avail_ring;
        let avail_ring_size = 6 + 2 * queue_size;
        let used_ring = self.used_ring;
        let used_ring_size = 6 + 8 * queue_size;
        if !self.ready {
            error!("attempt to use virtio queue that is not marked ready");
            false
        } else if self.size > self.max_size || self.size == 0 ||
                  (self.size & (self.size - 1)) != 0 {
            error!("virtio queue with invalid size: {}", self.size);
            false
        } else if desc_table
                      .checked_add(desc_table_size as u64)
                      .map_or(true, |v| !mem.address_in_range(v)) {
            error!("virtio queue descriptor table goes out of bounds: start:0x{:08x} size:0x{:08x}",
                   desc_table.offset(),
                   desc_table_size);
            false
        } else if avail_ring
                      .checked_add(avail_ring_size as u64)
                      .map_or(true, |v| !mem.address_in_range(v)) {
            error!("virtio queue available ring goes out of bounds: start:0x{:08x} size:0x{:08x}",
                   avail_ring.offset(),
                   avail_ring_size);
            false
        } else if used_ring
                      .checked_add(used_ring_size as u64)
                      .map_or(true, |v| !mem.address_in_range(v)) {
            error!("virtio queue used ring goes out of bounds: start:0x{:08x} size:0x{:08x}",
                   used_ring.offset(),
                   used_ring_size);
            false
        } else {
            true
        }

    }

    /// A consuming iterator over all available descriptor chain heads offered by the driver.
    pub fn iter<'a, 'b>(&'b mut self, mem: &'a GuestMemory) -> AvailIter<'a, 'b> {
        if !self.is_valid(mem) {
            return AvailIter {
                       mem: mem,
                       desc_table: GuestAddress(0),
                       avail_ring: GuestAddress(0),
                       next_index: Wrapping(0),
                       last_index: Wrapping(0),
                       queue_size: 0,
                       next_avail: &mut self.next_avail,
                   };
        }
        let queue_size = self.actual_size();
        let avail_ring = self.avail_ring;

        let index_addr = mem.checked_offset(avail_ring, 2).unwrap();
        // Note that last_index has no invalid values
        let last_index: u16 = mem.read_obj_from_addr::<u16>(index_addr).unwrap();
        let queue_len = Wrapping(last_index) - self.next_avail;

        if queue_len.0 > queue_size {
            return AvailIter {
                mem: mem,
                desc_table: GuestAddress(0),
                avail_ring: GuestAddress(0),
                next_index: Wrapping(0),
                last_index: Wrapping(0),
                queue_size: 0,
                next_avail: &mut self.next_avail,
            };
        }

        AvailIter {
            mem: mem,
            desc_table: self.desc_table,
            avail_ring: avail_ring,
            next_index: self.next_avail,
            last_index: Wrapping(last_index),
            queue_size: queue_size,
            next_avail: &mut self.next_avail,
        }
    }

    /// Puts an available descriptor head into the used ring for use by the guest.
    pub fn add_used(&mut self, mem: &GuestMemory, desc_index: u16, len: u32) {
        if desc_index >= self.actual_size() {
            error!("attempted to add out of bounds descriptor to used ring: {}",
                   desc_index);
            return;
        }

        let used_ring = self.used_ring;
        let next_used = (self.next_used.0 % self.actual_size()) as usize;
        let used_elem = used_ring.unchecked_add((4 + next_used * 8) as u64);

        // These writes can't fail as we are guaranteed to be within the descriptor ring.
        mem.write_obj_at_addr(desc_index as u32, used_elem)
            .unwrap();
        mem.write_obj_at_addr(len as u32, used_elem.unchecked_add(4))
            .unwrap();

        self.next_used += Wrapping(1);

        // This fence ensures all descriptor writes are visible before the index update is.
        fence(Ordering::Release);

        mem.write_obj_at_addr(self.next_used.0 as u16, used_ring.unchecked_add(2))
            .unwrap();
    }
}
<commit_msg>virtio-queue: Add an is_read_only() method for DescriptorChain<commit_after>// Copyright 2017 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

use std::cmp::min;
use std::num::Wrapping;
use std::sync::atomic::{fence, Ordering};

use sys_util::{GuestAddress, GuestMemory};

const VIRTQ_DESC_F_NEXT: u16 = 0x1;
const VIRTQ_DESC_F_WRITE: u16 = 0x2;
#[allow(dead_code)]
const VIRTQ_DESC_F_INDIRECT: u16 = 0x4;

/// A virtio descriptor chain.
#[derive(Clone)]
pub struct DescriptorChain<'a> {
    mem: &'a GuestMemory,
    desc_table: GuestAddress,
    queue_size: u16,
    ttl: u16, // used to prevent infinite chain cycles

    /// Index into the descriptor table
    pub index: u16,

    /// Guest physical address of device specific data
    pub addr: GuestAddress,

    /// Length of device specific data
    pub len: u32,

    /// Includes next, write, and indirect bits
    pub flags: u16,

    /// Index into the descriptor table of the next descriptor if flags has
    /// the next bit set
    pub next: u16,
}

impl<'a> DescriptorChain<'a> {
    fn checked_new(mem: &GuestMemory,
                   desc_table: GuestAddress,
                   queue_size: u16,
                   index: u16)
                   -> Option<DescriptorChain> {
        if index >= queue_size {
            return None;
        }

        let desc_head = match mem.checked_offset(desc_table, (index as u64) * 16) {
            Some(a) => a,
            None => return None,
        };
        // These reads can't fail unless Guest memory is hopelessly broken.
        let addr = GuestAddress(mem.read_obj_from_addr::<u64>(desc_head).unwrap() as u64);
        if mem.checked_offset(desc_head, 16).is_none() {
            return None;
        }
        let len: u32 = mem.read_obj_from_addr(desc_head.unchecked_add(8))
            .unwrap();
        let flags: u16 = mem.read_obj_from_addr(desc_head.unchecked_add(12))
            .unwrap();
        let next: u16 = mem.read_obj_from_addr(desc_head.unchecked_add(14))
            .unwrap();
        let chain = DescriptorChain {
            mem: mem,
            desc_table: desc_table,
            queue_size: queue_size,
            ttl: queue_size,
            index: index,
            addr: addr,
            len: len,
            flags: flags,
            next: next,
        };

        if chain.is_valid() { Some(chain) } else { None }
    }

    fn is_valid(&self) -> bool {
        if self.mem
               .checked_offset(self.addr, self.len as u64)
               .is_none() {
            false
        } else if self.has_next() && self.next >= self.queue_size {
            false
        } else {
            true
        }
    }

    /// Gets if this descriptor chain has another descriptor chain linked after it.
    pub fn has_next(&self) -> bool {
        self.flags & VIRTQ_DESC_F_NEXT != 0 && self.ttl > 1
    }

    /// If the driver designated this as a write only descriptor.
    ///
    /// If this is false, this descriptor is read only.
    /// Write only means the the emulated device can write and the driver can read.
    pub fn is_write_only(&self) -> bool {
        self.flags & VIRTQ_DESC_F_WRITE != 0
    }

    /// If the driver designated this as a read only descriptor.
    ///
    /// If this is false, this descriptor is write only.
    /// Read only means the emulated device can read and the driver can write.
    pub fn is_read_only(&self) -> bool {
        self.flags & VIRTQ_DESC_F_WRITE == 0
    }

    /// Gets the next descriptor in this descriptor chain, if there is one.
    ///
    /// Note that this is distinct from the next descriptor chain returned by `AvailIter`, which is
    /// the head of the next _available_ descriptor chain.
    pub fn next_descriptor(&self) -> Option<DescriptorChain<'a>> {
        if self.has_next() {
            DescriptorChain::checked_new(self.mem, self.desc_table, self.queue_size, self.next)
                .map(|mut c| {
                         c.ttl = self.ttl - 1;
                         c
                     })
        } else {
            None
        }
    }
}

/// Consuming iterator over all available descriptor chain heads in the queue.
pub struct AvailIter<'a, 'b> {
    mem: &'a GuestMemory,
    desc_table: GuestAddress,
    avail_ring: GuestAddress,
    next_index: Wrapping<u16>,
    last_index: Wrapping<u16>,
    queue_size: u16,
    next_avail: &'b mut Wrapping<u16>,
}

impl<'a, 'b> Iterator for AvailIter<'a, 'b> {
    type Item = DescriptorChain<'a>;

    fn next(&mut self) -> Option<Self::Item> {
        if self.next_index == self.last_index {
            return None;
        }

        let offset = (4 + (self.next_index.0 % self.queue_size) * 2) as usize;
        let avail_addr = match self.mem.checked_offset(self.avail_ring, offset as u64) {
            Some(a) => a,
            None => return None,
        };
        // This index is checked below in checked_new
        let desc_index: u16 = self.mem.read_obj_from_addr(avail_addr).unwrap();

        self.next_index += Wrapping(1);

        let ret =
            DescriptorChain::checked_new(self.mem, self.desc_table, self.queue_size, desc_index);
        if ret.is_some() {
            *self.next_avail += Wrapping(1);
        }
        ret
    }
}

#[derive(Clone)]
/// A virtio queue's parameters.
pub struct Queue {
    /// The maximal size in elements offered by the device
    pub max_size: u16,

    /// The queue size in elements the driver selected
    pub size: u16,

    /// Inidcates if the queue is finished with configuration
    pub ready: bool,

    /// Guest physical address of the descriptor table
    pub desc_table: GuestAddress,

    /// Guest physical address of the available ring
    pub avail_ring: GuestAddress,

    /// Guest physical address of the used ring
    pub used_ring: GuestAddress,

    next_avail: Wrapping<u16>,
    next_used: Wrapping<u16>,
}

impl Queue {
    /// Constructs an empty virtio queue with the given `max_size`.
    pub fn new(max_size: u16) -> Queue {
        Queue {
            max_size: max_size,
            size: 0,
            ready: false,
            desc_table: GuestAddress(0),
            avail_ring: GuestAddress(0),
            used_ring: GuestAddress(0),
            next_avail: Wrapping(0),
            next_used: Wrapping(0),
        }
    }

    /// Return the actual size of the queue, as the driver may not set up a
    /// queue as big as the device allows.
    pub fn actual_size(&self) -> u16 {
        min(self.size, self.max_size)
    }

    pub fn is_valid(&self, mem: &GuestMemory) -> bool {
        let queue_size = self.actual_size() as usize;
        let desc_table = self.desc_table;
        let desc_table_size = 16 * queue_size;
        let avail_ring = self.avail_ring;
        let avail_ring_size = 6 + 2 * queue_size;
        let used_ring = self.used_ring;
        let used_ring_size = 6 + 8 * queue_size;
        if !self.ready {
            error!("attempt to use virtio queue that is not marked ready");
            false
        } else if self.size > self.max_size || self.size == 0 ||
                  (self.size & (self.size - 1)) != 0 {
            error!("virtio queue with invalid size: {}", self.size);
            false
        } else if desc_table
                      .checked_add(desc_table_size as u64)
                      .map_or(true, |v| !mem.address_in_range(v)) {
            error!("virtio queue descriptor table goes out of bounds: start:0x{:08x} size:0x{:08x}",
                   desc_table.offset(),
                   desc_table_size);
            false
        } else if avail_ring
                      .checked_add(avail_ring_size as u64)
                      .map_or(true, |v| !mem.address_in_range(v)) {
            error!("virtio queue available ring goes out of bounds: start:0x{:08x} size:0x{:08x}",
                   avail_ring.offset(),
                   avail_ring_size);
            false
        } else if used_ring
                      .checked_add(used_ring_size as u64)
                      .map_or(true, |v| !mem.address_in_range(v)) {
            error!("virtio queue used ring goes out of bounds: start:0x{:08x} size:0x{:08x}",
                   used_ring.offset(),
                   used_ring_size);
            false
        } else {
            true
        }

    }

    /// A consuming iterator over all available descriptor chain heads offered by the driver.
    pub fn iter<'a, 'b>(&'b mut self, mem: &'a GuestMemory) -> AvailIter<'a, 'b> {
        if !self.is_valid(mem) {
            return AvailIter {
                       mem: mem,
                       desc_table: GuestAddress(0),
                       avail_ring: GuestAddress(0),
                       next_index: Wrapping(0),
                       last_index: Wrapping(0),
                       queue_size: 0,
                       next_avail: &mut self.next_avail,
                   };
        }
        let queue_size = self.actual_size();
        let avail_ring = self.avail_ring;

        let index_addr = mem.checked_offset(avail_ring, 2).unwrap();
        // Note that last_index has no invalid values
        let last_index: u16 = mem.read_obj_from_addr::<u16>(index_addr).unwrap();
        let queue_len = Wrapping(last_index) - self.next_avail;

        if queue_len.0 > queue_size {
            return AvailIter {
                mem: mem,
                desc_table: GuestAddress(0),
                avail_ring: GuestAddress(0),
                next_index: Wrapping(0),
                last_index: Wrapping(0),
                queue_size: 0,
                next_avail: &mut self.next_avail,
            };
        }

        AvailIter {
            mem: mem,
            desc_table: self.desc_table,
            avail_ring: avail_ring,
            next_index: self.next_avail,
            last_index: Wrapping(last_index),
            queue_size: queue_size,
            next_avail: &mut self.next_avail,
        }
    }

    /// Puts an available descriptor head into the used ring for use by the guest.
    pub fn add_used(&mut self, mem: &GuestMemory, desc_index: u16, len: u32) {
        if desc_index >= self.actual_size() {
            error!("attempted to add out of bounds descriptor to used ring: {}",
                   desc_index);
            return;
        }

        let used_ring = self.used_ring;
        let next_used = (self.next_used.0 % self.actual_size()) as usize;
        let used_elem = used_ring.unchecked_add((4 + next_used * 8) as u64);

        // These writes can't fail as we are guaranteed to be within the descriptor ring.
        mem.write_obj_at_addr(desc_index as u32, used_elem)
            .unwrap();
        mem.write_obj_at_addr(len as u32, used_elem.unchecked_add(4))
            .unwrap();

        self.next_used += Wrapping(1);

        // This fence ensures all descriptor writes are visible before the index update is.
        fence(Ordering::Release);

        mem.write_obj_at_addr(self.next_used.0 as u16, used_ring.unchecked_add(2))
            .unwrap();
    }
}
<|endoftext|>


<commit_before>mod float;
mod int;
mod uint;

pub use float::*;
pub use int::*;
pub use uint::*;

// Vectors of pointers are not for public use at the current time.
pub(crate) mod ptr;

mod sealed {
    pub trait Sealed {}
}

/// A representation of a vector as an "array" with indices, implementing
/// operations applicable to any vector type based solely on "having lanes",
/// and describing relationships between vector and scalar types.
pub trait Vector: sealed::Sealed {
    /// The scalar type in every lane of this vector type.
    type Scalar: Copy + Sized;

    /// The number of lanes for this vector.
    const LANES: usize;

    // Implementation detail until the compiler can support bitmasks of any integer width
    #[doc(hidden)]
    type BitMask: Into<u64>;

    /// Generates a SIMD vector with the same value in every lane.
    #[must_use]
    fn splat(val: Self::Scalar) -> Self;

}

macro_rules! impl_vector_for {
    ($simd:ident {type Scalar = $scalar:ident;}) => {
        impl_vector_for! { $simd<1> { type Scalar = $scalar; type BitMask = u8; } }
        impl_vector_for! { $simd<2> { type Scalar = $scalar; type BitMask = u8; } }
        impl_vector_for! { $simd<4> { type Scalar = $scalar; type BitMask = u8; } }
        impl_vector_for! { $simd<8> { type Scalar = $scalar; type BitMask = u8; } }
        impl_vector_for! { $simd<16> { type Scalar = $scalar; type BitMask = u16; } }
        impl_vector_for! { $simd<32> { type Scalar = $scalar; type BitMask = u32; } }
    };
    ($simd:ident<$lanes:literal> {type Scalar = $scalar:ident; type BitMask = $bitmask:ident; }) => {
        impl sealed::Sealed for $simd<$lanes> {}

        impl Vector for $simd<$lanes> {
            type Scalar = $scalar;
            const LANES: usize = $lanes;

            type BitMask = $bitmask;

            #[inline]
            fn splat(val: Self::Scalar) -> Self {
                [val; $lanes].into()
            }
        }
    };
}

impl_vector_for! {
    SimdUsize {
        type Scalar = usize;
    }
}

impl_vector_for! {
    SimdIsize {
        type Scalar = isize;
    }
}

impl_vector_for! {
    SimdI8 {
        type Scalar = i8;
    }
}

impl_vector_for! {
    SimdI16 {
        type Scalar = i16;
    }
}

impl_vector_for! {
    SimdI32 {
        type Scalar = i32;
    }
}

impl_vector_for! {
    SimdI64 {
        type Scalar = i64;
    }
}

impl_vector_for! {
    SimdU8 {
        type Scalar = u8;
    }
}

impl_vector_for! {
    SimdU16 {
        type Scalar = u16;
    }
}

impl_vector_for! {
    SimdU32 {
        type Scalar = u32;
    }
}

impl_vector_for! {
    SimdU64 {
        type Scalar = u64;
    }
}

impl_vector_for! {
    SimdF32 {
        type Scalar = f32;
    }
}

impl_vector_for! {
    SimdF64 {
        type Scalar = f64;
    }
}
<commit_msg>Add as_slice/as_mut_slice to Vector<commit_after>mod float;
mod int;
mod uint;

pub use float::*;
pub use int::*;
pub use uint::*;

// Vectors of pointers are not for public use at the current time.
pub(crate) mod ptr;

mod sealed {
    pub trait Sealed {}
}

/// A representation of a vector as an "array" with indices, implementing
/// operations applicable to any vector type based solely on "having lanes",
/// and describing relationships between vector and scalar types.
pub trait Vector: sealed::Sealed {
    /// The scalar type in every lane of this vector type.
    type Scalar: Copy + Sized;

    /// The number of lanes for this vector.
    const LANES: usize;

    // Implementation detail until the compiler can support bitmasks of any integer width
    #[doc(hidden)]
    type BitMask: Into<u64>;

    /// Generates a SIMD vector with the same value in every lane.
    #[must_use]
    fn splat(val: Self::Scalar) -> Self;

    /// Returns a slice containing the entire SIMD vector.
    fn as_slice(&self) -> &[Self::Scalar];

    /// Returns a mutable slice containing the entire SIMD vector.
    fn as_mut_slice(&mut self) -> &mut [Self::Scalar];
}

macro_rules! impl_vector_for {
    ($simd:ident {type Scalar = $scalar:ident;}) => {
        impl_vector_for! { $simd<1> { type Scalar = $scalar; type BitMask = u8; } }
        impl_vector_for! { $simd<2> { type Scalar = $scalar; type BitMask = u8; } }
        impl_vector_for! { $simd<4> { type Scalar = $scalar; type BitMask = u8; } }
        impl_vector_for! { $simd<8> { type Scalar = $scalar; type BitMask = u8; } }
        impl_vector_for! { $simd<16> { type Scalar = $scalar; type BitMask = u16; } }
        impl_vector_for! { $simd<32> { type Scalar = $scalar; type BitMask = u32; } }
    };
    ($simd:ident<$lanes:literal> {type Scalar = $scalar:ident; type BitMask = $bitmask:ident; }) => {
        impl sealed::Sealed for $simd<$lanes> {}

        impl Vector for $simd<$lanes> {
            type Scalar = $scalar;
            const LANES: usize = $lanes;

            type BitMask = $bitmask;

            #[inline]
            fn splat(val: Self::Scalar) -> Self {
                Self::splat(val)
            }

            #[inline]
            fn as_slice(&self) -> &[Self::Scalar] {
                self.as_slice()
            }

            #[inline]
            fn as_mut_slice(&mut self) -> &mut [Self::Scalar] {
                self.as_mut_slice()
            }
        }
    };
}

impl_vector_for! {
    SimdUsize {
        type Scalar = usize;
    }
}

impl_vector_for! {
    SimdIsize {
        type Scalar = isize;
    }
}

impl_vector_for! {
    SimdI8 {
        type Scalar = i8;
    }
}

impl_vector_for! {
    SimdI16 {
        type Scalar = i16;
    }
}

impl_vector_for! {
    SimdI32 {
        type Scalar = i32;
    }
}

impl_vector_for! {
    SimdI64 {
        type Scalar = i64;
    }
}

impl_vector_for! {
    SimdU8 {
        type Scalar = u8;
    }
}

impl_vector_for! {
    SimdU16 {
        type Scalar = u16;
    }
}

impl_vector_for! {
    SimdU32 {
        type Scalar = u32;
    }
}

impl_vector_for! {
    SimdU64 {
        type Scalar = u64;
    }
}

impl_vector_for! {
    SimdF32 {
        type Scalar = f32;
    }
}

impl_vector_for! {
    SimdF64 {
        type Scalar = f64;
    }
}
<|endoftext|>


<commit_before>use rustc::lint::*;
use rustc::ty::{self, Ty};
use rustc::hir::*;
use std::borrow::Cow;
use syntax::ast;
use utils::{last_path_segment, match_def_path, paths, snippet, span_lint, span_lint_and_then};
use utils::{sugg, opt_def_id};

/// **What it does:** Checks for transmutes that can't ever be correct on any
/// architecture.
///
/// **Why is this bad?** It's basically guaranteed to be undefined behaviour.
///
/// **Known problems:** When accessing C, users might want to store pointer
/// sized objects in `extradata` arguments to save an allocation.
///
/// **Example:**
/// ```rust
/// let ptr: *const T = core::intrinsics::transmute('x')`
/// ```
declare_lint! {
    pub WRONG_TRANSMUTE,
    Warn,
    "transmutes that are confusing at best, undefined behaviour at worst and always useless"
}

/// **What it does:** Checks for transmutes to the original type of the object
/// and transmutes that could be a cast.
///
/// **Why is this bad?** Readability. The code tricks people into thinking that
/// something complex is going on.
///
/// **Known problems:** None.
///
/// **Example:**
/// ```rust
/// core::intrinsics::transmute(t) // where the result type is the same as `t`'s
/// ```
declare_lint! {
    pub USELESS_TRANSMUTE,
    Warn,
    "transmutes that have the same to and from types or could be a cast/coercion"
}

/// **What it does:** Checks for transmutes between a type `T` and `*T`.
///
/// **Why is this bad?** It's easy to mistakenly transmute between a type and a
/// pointer to that type.
///
/// **Known problems:** None.
///
/// **Example:**
/// ```rust
/// core::intrinsics::transmute(t)` // where the result type is the same as
/// `*t` or `&t`'s
/// ```
declare_lint! {
    pub CROSSPOINTER_TRANSMUTE,
    Warn,
    "transmutes that have to or from types that are a pointer to the other"
}

/// **What it does:** Checks for transmutes from a pointer to a reference.
///
/// **Why is this bad?** This can always be rewritten with `&` and `*`.
///
/// **Known problems:** None.
///
/// **Example:**
/// ```rust
/// let _: &T = std::mem::transmute(p); // where p: *const T
/// // can be written:
/// let _: &T = &*p;
/// ```
declare_lint! {
    pub TRANSMUTE_PTR_TO_REF,
    Warn,
    "transmutes from a pointer to a reference type"
}

/// **What it does:** Checks for transmutes from an integer to a `char`.
///
/// **Why is this bad?** Not every integer is a unicode scalar value.
///
/// **Known problems:** None.
///
/// **Example:**
/// ```rust
/// let _: char = std::mem::transmute(x); // where x: u32
/// // should be:
/// let _ = std::char::from_u32(x).unwrap();
/// ```
declare_lint! {
    pub TRANSMUTE_INT_TO_CHAR,
    Warn,
    "transmutes from an integer to a `char`"
}

/// **What it does:** Checks for transmutes from a `&[u8]` to a `&str`.
///
/// **Why is this bad?** Not every byte slice is a valid UTF-8 string.
///
/// **Known problems:**
/// - [`from_utf8`] which this lint suggests using is slower than `transmute`
/// as it needs to validate the input.
/// If you are certain that the input is always a valid UTF-8,
/// use [`from_utf8_unchecked`] which is as fast as `transmute`
/// but has a semantically meaningful name.
/// - You might want to handle errors returned from [`from_utf8`] instead of calling `unwrap`.
///
/// [`from_utf8`]: https://doc.rust-lang.org/std/str/fn.from_utf8.html
/// [`from_utf8_unchecked`]: https://doc.rust-lang.org/std/str/fn.from_utf8_unchecked.html
///
/// **Example:**
/// ```rust
/// let _: &str = std::mem::transmute(b); // where b: &[u8]
/// // should be:
/// let _ = std::str::from_utf8(b).unwrap();
/// ```
declare_lint! {
    pub TRANSMUTE_BYTES_TO_STR,
    Warn,
    "transmutes from a `&[u8]` to a `&str`"
}

/// **What it does:** Checks for transmutes from an integer to a `bool`.
///
/// **Why is this bad?** This might result in an invalid in-memory representation of a `bool`.
///
/// **Known problems:** None.
///
/// **Example:**
/// ```rust
/// let _: bool = std::mem::transmute(x); // where x: u8
/// // should be:
/// let _: bool = x != 0;
/// ```
declare_lint! {
    pub TRANSMUTE_INT_TO_BOOL,
    Warn,
    "transmutes from an integer to a `bool`"
}

/// **What it does:** Checks for transmutes from an integer to a float.
///
/// **Why is this bad?** This might result in an invalid in-memory representation of a float.
///
/// **Known problems:** None.
///
/// **Example:**
/// ```rust
/// let _: f32 = std::mem::transmute(x); // where x: u32
/// // should be:
/// let _: f32 = f32::from_bits(x);
/// ```
declare_lint! {
    pub TRANSMUTE_INT_TO_FLOAT,
    Warn,
    "transmutes from an integer to a float"
}

pub struct Transmute;

impl LintPass for Transmute {
    fn get_lints(&self) -> LintArray {
        lint_array!(
            CROSSPOINTER_TRANSMUTE,
            TRANSMUTE_PTR_TO_REF,
            USELESS_TRANSMUTE,
            WRONG_TRANSMUTE,
            TRANSMUTE_INT_TO_CHAR,
            TRANSMUTE_BYTES_TO_STR,
            TRANSMUTE_INT_TO_BOOL,
            TRANSMUTE_INT_TO_FLOAT
        )
    }
}

impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Transmute {
    fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) {
        if let ExprCall(ref path_expr, ref args) = e.node {
            if let ExprPath(ref qpath) = path_expr.node {
                if let Some(def_id) = opt_def_id(cx.tables.qpath_def(qpath, path_expr.hir_id)) {

                    if match_def_path(cx.tcx, def_id, &paths::TRANSMUTE) {
                        let from_ty = cx.tables.expr_ty(&args[0]);
                        let to_ty = cx.tables.expr_ty(e);

                        match (&from_ty.sty, &to_ty.sty) {
                            _ if from_ty == to_ty => span_lint(
                                cx,
                                USELESS_TRANSMUTE,
                                e.span,
                                &format!("transmute from a type (`{}`) to itself", from_ty),
                            ),
                            (&ty::TyRef(_, rty), &ty::TyRawPtr(ptr_ty)) => span_lint_and_then(
                                cx,
                                USELESS_TRANSMUTE,
                                e.span,
                                "transmute from a reference to a pointer",
                                |db| if let Some(arg) = sugg::Sugg::hir_opt(cx, &args[0]) {
                                    let sugg = if ptr_ty == rty {
                                        arg.as_ty(to_ty)
                                    } else {
                                        arg.as_ty(cx.tcx.mk_ptr(rty)).as_ty(to_ty)
                                    };

                                    db.span_suggestion(e.span, "try", sugg.to_string());
                                },
                            ),
                            (&ty::TyInt(_), &ty::TyRawPtr(_)) | (&ty::TyUint(_), &ty::TyRawPtr(_)) => span_lint_and_then(
                                cx,
                                USELESS_TRANSMUTE,
                                e.span,
                                "transmute from an integer to a pointer",
                                |db| if let Some(arg) = sugg::Sugg::hir_opt(cx, &args[0]) {
                                    db.span_suggestion(e.span, "try", arg.as_ty(&to_ty.to_string()).to_string());
                                },
                            ),
                            (&ty::TyFloat(_), &ty::TyRef(..)) |
                            (&ty::TyFloat(_), &ty::TyRawPtr(_)) |
                            (&ty::TyChar, &ty::TyRef(..)) |
                            (&ty::TyChar, &ty::TyRawPtr(_)) => span_lint(
                                cx,
                                WRONG_TRANSMUTE,
                                e.span,
                                &format!("transmute from a `{}` to a pointer", from_ty),
                            ),
                            (&ty::TyRawPtr(from_ptr), _) if from_ptr.ty == to_ty => span_lint(
                                cx,
                                CROSSPOINTER_TRANSMUTE,
                                e.span,
                                &format!(
                                    "transmute from a type (`{}`) to the type that it points to (`{}`)",
                                    from_ty,
                                    to_ty
                                ),
                            ),
                            (_, &ty::TyRawPtr(to_ptr)) if to_ptr.ty == from_ty => span_lint(
                                cx,
                                CROSSPOINTER_TRANSMUTE,
                                e.span,
                                &format!("transmute from a type (`{}`) to a pointer to that type (`{}`)", from_ty, to_ty),
                            ),
                            (&ty::TyRawPtr(from_pty), &ty::TyRef(_, to_ref_ty)) => span_lint_and_then(
                                cx,
                                TRANSMUTE_PTR_TO_REF,
                                e.span,
                                &format!(
                                    "transmute from a pointer type (`{}`) to a reference type \
                                    (`{}`)",
                                    from_ty,
                                    to_ty
                                ),
                                |db| {
                                    let arg = sugg::Sugg::hir(cx, &args[0], "..");
                                    let (deref, cast) = if to_ref_ty.mutbl == Mutability::MutMutable {
                                        ("&mut *", "*mut")
                                    } else {
                                        ("&*", "*const")
                                    };

                                    let arg = if from_pty.ty == to_ref_ty.ty {
                                        arg
                                    } else {
                                        arg.as_ty(&format!("{} {}", cast, get_type_snippet(cx, qpath, to_ref_ty.ty)))
                                    };

                                    db.span_suggestion(e.span, "try", sugg::make_unop(deref, arg).to_string());
                                },
                            ),
                            (&ty::TyInt(ast::IntTy::I32), &ty::TyChar) |
                            (&ty::TyUint(ast::UintTy::U32), &ty::TyChar) => span_lint_and_then(
                                cx,
                                TRANSMUTE_INT_TO_CHAR,
                                e.span,
                                &format!("transmute from a `{}` to a `char`", from_ty),
                                |db| {
                                    let arg = sugg::Sugg::hir(cx, &args[0], "..");
                                    let arg = if let ty::TyInt(_) = from_ty.sty {
                                        arg.as_ty(ty::TyUint(ast::UintTy::U32))
                                    } else {
                                        arg
                                    };
                                    db.span_suggestion(e.span, "consider using", format!("std::char::from_u32({}).unwrap()", arg.to_string()));
                                }
                            ),
                            (&ty::TyRef(_, ref ref_from), &ty::TyRef(_, ref ref_to)) => {
                                if_chain! {
                                    if let (&ty::TySlice(slice_ty), &ty::TyStr) = (&ref_from.ty.sty, &ref_to.ty.sty);
                                    if let ty::TyUint(ast::UintTy::U8) = slice_ty.sty;
                                    if ref_from.mutbl == ref_to.mutbl;
                                    then {
                                        let postfix = if ref_from.mutbl == Mutability::MutMutable {
                                            "_mut"
                                        } else {
                                            ""
                                        };

                                        span_lint_and_then(
                                            cx,
                                            TRANSMUTE_BYTES_TO_STR,
                                            e.span,
                                            &format!("transmute from a `{}` to a `{}`", from_ty, to_ty),
                                            |db| {
                                                db.span_suggestion(
                                                    e.span,
                                                    "consider using",
                                                    format!(
                                                        "std::str::from_utf8{}({}).unwrap()",
                                                        postfix,
                                                        snippet(cx, args[0].span, ".."),
                                                    ),
                                                );
                                            }
                                        )
                                    }
                                }
                            },
                            (&ty::TyInt(ast::IntTy::I8), &ty::TyBool) |
                            (&ty::TyUint(ast::UintTy::U8), &ty::TyBool) => span_lint_and_then(
                                cx,
                                TRANSMUTE_INT_TO_BOOL,
                                e.span,
                                &format!("transmute from a `{}` to a `bool`", from_ty),
                                |db| {
                                    let arg = sugg::Sugg::hir(cx, &args[0], "..");
                                    let zero = sugg::Sugg::NonParen(Cow::from("0"));
                                    db.span_suggestion(e.span, "consider using", sugg::make_binop(ast::BinOpKind::Ne, &arg, &zero).to_string());
                                }
                            ),
                            (&ty::TyInt(_), &ty::TyFloat(_)) |
                            (&ty::TyUint(_), &ty::TyFloat(_)) => span_lint_and_then(
                                cx,
                                TRANSMUTE_INT_TO_FLOAT,
                                e.span,
                                &format!("transmute from a `{}` to a `{}`", from_ty, to_ty),
                                |db| {
                                    let arg = sugg::Sugg::hir(cx, &args[0], "..");
                                    let arg = if let ty::TyInt(int_ty) = from_ty.sty {
                                        arg.as_ty(format!("u{}", int_ty.bit_width().map_or_else(|| "size".to_string(), |v| v.to_string())))
                                    } else {
                                        arg
                                    };
                                    db.span_suggestion(e.span, "consider using", format!("{}::from_bits({})", to_ty, arg.to_string()));
                                }
                            ),
                            _ => return,
                        };
                    }
                }
            }
        }
    }
}

/// Get the snippet of `Bar` in `…::transmute<Foo, &Bar>`. If that snippet is
/// not available , use
/// the type's `ToString` implementation. In weird cases it could lead to types
/// with invalid `'_`
/// lifetime, but it should be rare.
fn get_type_snippet(cx: &LateContext, path: &QPath, to_ref_ty: Ty) -> String {
    let seg = last_path_segment(path);
    if_chain! {
        if let Some(ref params) = seg.parameters;
        if !params.parenthesized;
        if let Some(to_ty) = params.types.get(1);
        if let TyRptr(_, ref to_ty) = to_ty.node;
        then {
            return snippet(cx, to_ty.ty.span, &to_ref_ty.to_string()).to_string();
        }
    }

    to_ref_ty.to_string()
}
<commit_msg>Known problems<commit_after>use rustc::lint::*;
use rustc::ty::{self, Ty};
use rustc::hir::*;
use std::borrow::Cow;
use syntax::ast;
use utils::{last_path_segment, match_def_path, paths, snippet, span_lint, span_lint_and_then};
use utils::{sugg, opt_def_id};

/// **What it does:** Checks for transmutes that can't ever be correct on any
/// architecture.
///
/// **Why is this bad?** It's basically guaranteed to be undefined behaviour.
///
/// **Known problems:** When accessing C, users might want to store pointer
/// sized objects in `extradata` arguments to save an allocation.
///
/// **Example:**
/// ```rust
/// let ptr: *const T = core::intrinsics::transmute('x')`
/// ```
declare_lint! {
    pub WRONG_TRANSMUTE,
    Warn,
    "transmutes that are confusing at best, undefined behaviour at worst and always useless"
}

/// **What it does:** Checks for transmutes to the original type of the object
/// and transmutes that could be a cast.
///
/// **Why is this bad?** Readability. The code tricks people into thinking that
/// something complex is going on.
///
/// **Known problems:** None.
///
/// **Example:**
/// ```rust
/// core::intrinsics::transmute(t) // where the result type is the same as `t`'s
/// ```
declare_lint! {
    pub USELESS_TRANSMUTE,
    Warn,
    "transmutes that have the same to and from types or could be a cast/coercion"
}

/// **What it does:** Checks for transmutes between a type `T` and `*T`.
///
/// **Why is this bad?** It's easy to mistakenly transmute between a type and a
/// pointer to that type.
///
/// **Known problems:** None.
///
/// **Example:**
/// ```rust
/// core::intrinsics::transmute(t)` // where the result type is the same as
/// `*t` or `&t`'s
/// ```
declare_lint! {
    pub CROSSPOINTER_TRANSMUTE,
    Warn,
    "transmutes that have to or from types that are a pointer to the other"
}

/// **What it does:** Checks for transmutes from a pointer to a reference.
///
/// **Why is this bad?** This can always be rewritten with `&` and `*`.
///
/// **Known problems:** None.
///
/// **Example:**
/// ```rust
/// let _: &T = std::mem::transmute(p); // where p: *const T
/// // can be written:
/// let _: &T = &*p;
/// ```
declare_lint! {
    pub TRANSMUTE_PTR_TO_REF,
    Warn,
    "transmutes from a pointer to a reference type"
}

/// **What it does:** Checks for transmutes from an integer to a `char`.
///
/// **Why is this bad?** Not every integer is a Unicode scalar value.
///
/// **Known problems:**
/// - [`from_u32`] which this lint suggests using is slower than `transmute`
/// as it needs to validate the input.
/// If you are certain that the input is always a valid Unicode scalar value,
/// use [`from_u32_unchecked`] which is as fast as `transmute`
/// but has a semantically meaningful name.
/// - You might want to handle `None` returned from [`from_u32`] instead of calling `unwrap`.
///
/// [`from_u32`]: https://doc.rust-lang.org/std/char/fn.from_u32.html
/// [`from_u32_unchecked`]: https://doc.rust-lang.org/std/char/fn.from_u32_unchecked.html
///
/// **Example:**
/// ```rust
/// let _: char = std::mem::transmute(x); // where x: u32
/// // should be:
/// let _ = std::char::from_u32(x).unwrap();
/// ```
declare_lint! {
    pub TRANSMUTE_INT_TO_CHAR,
    Warn,
    "transmutes from an integer to a `char`"
}

/// **What it does:** Checks for transmutes from a `&[u8]` to a `&str`.
///
/// **Why is this bad?** Not every byte slice is a valid UTF-8 string.
///
/// **Known problems:**
/// - [`from_utf8`] which this lint suggests using is slower than `transmute`
/// as it needs to validate the input.
/// If you are certain that the input is always a valid UTF-8,
/// use [`from_utf8_unchecked`] which is as fast as `transmute`
/// but has a semantically meaningful name.
/// - You might want to handle errors returned from [`from_utf8`] instead of calling `unwrap`.
///
/// [`from_utf8`]: https://doc.rust-lang.org/std/str/fn.from_utf8.html
/// [`from_utf8_unchecked`]: https://doc.rust-lang.org/std/str/fn.from_utf8_unchecked.html
///
/// **Example:**
/// ```rust
/// let _: &str = std::mem::transmute(b); // where b: &[u8]
/// // should be:
/// let _ = std::str::from_utf8(b).unwrap();
/// ```
declare_lint! {
    pub TRANSMUTE_BYTES_TO_STR,
    Warn,
    "transmutes from a `&[u8]` to a `&str`"
}

/// **What it does:** Checks for transmutes from an integer to a `bool`.
///
/// **Why is this bad?** This might result in an invalid in-memory representation of a `bool`.
///
/// **Known problems:** None.
///
/// **Example:**
/// ```rust
/// let _: bool = std::mem::transmute(x); // where x: u8
/// // should be:
/// let _: bool = x != 0;
/// ```
declare_lint! {
    pub TRANSMUTE_INT_TO_BOOL,
    Warn,
    "transmutes from an integer to a `bool`"
}

/// **What it does:** Checks for transmutes from an integer to a float.
///
/// **Why is this bad?** This might result in an invalid in-memory representation of a float.
///
/// **Known problems:** None.
///
/// **Example:**
/// ```rust
/// let _: f32 = std::mem::transmute(x); // where x: u32
/// // should be:
/// let _: f32 = f32::from_bits(x);
/// ```
declare_lint! {
    pub TRANSMUTE_INT_TO_FLOAT,
    Warn,
    "transmutes from an integer to a float"
}

pub struct Transmute;

impl LintPass for Transmute {
    fn get_lints(&self) -> LintArray {
        lint_array!(
            CROSSPOINTER_TRANSMUTE,
            TRANSMUTE_PTR_TO_REF,
            USELESS_TRANSMUTE,
            WRONG_TRANSMUTE,
            TRANSMUTE_INT_TO_CHAR,
            TRANSMUTE_BYTES_TO_STR,
            TRANSMUTE_INT_TO_BOOL,
            TRANSMUTE_INT_TO_FLOAT
        )
    }
}

impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Transmute {
    fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) {
        if let ExprCall(ref path_expr, ref args) = e.node {
            if let ExprPath(ref qpath) = path_expr.node {
                if let Some(def_id) = opt_def_id(cx.tables.qpath_def(qpath, path_expr.hir_id)) {

                    if match_def_path(cx.tcx, def_id, &paths::TRANSMUTE) {
                        let from_ty = cx.tables.expr_ty(&args[0]);
                        let to_ty = cx.tables.expr_ty(e);

                        match (&from_ty.sty, &to_ty.sty) {
                            _ if from_ty == to_ty => span_lint(
                                cx,
                                USELESS_TRANSMUTE,
                                e.span,
                                &format!("transmute from a type (`{}`) to itself", from_ty),
                            ),
                            (&ty::TyRef(_, rty), &ty::TyRawPtr(ptr_ty)) => span_lint_and_then(
                                cx,
                                USELESS_TRANSMUTE,
                                e.span,
                                "transmute from a reference to a pointer",
                                |db| if let Some(arg) = sugg::Sugg::hir_opt(cx, &args[0]) {
                                    let sugg = if ptr_ty == rty {
                                        arg.as_ty(to_ty)
                                    } else {
                                        arg.as_ty(cx.tcx.mk_ptr(rty)).as_ty(to_ty)
                                    };

                                    db.span_suggestion(e.span, "try", sugg.to_string());
                                },
                            ),
                            (&ty::TyInt(_), &ty::TyRawPtr(_)) | (&ty::TyUint(_), &ty::TyRawPtr(_)) => span_lint_and_then(
                                cx,
                                USELESS_TRANSMUTE,
                                e.span,
                                "transmute from an integer to a pointer",
                                |db| if let Some(arg) = sugg::Sugg::hir_opt(cx, &args[0]) {
                                    db.span_suggestion(e.span, "try", arg.as_ty(&to_ty.to_string()).to_string());
                                },
                            ),
                            (&ty::TyFloat(_), &ty::TyRef(..)) |
                            (&ty::TyFloat(_), &ty::TyRawPtr(_)) |
                            (&ty::TyChar, &ty::TyRef(..)) |
                            (&ty::TyChar, &ty::TyRawPtr(_)) => span_lint(
                                cx,
                                WRONG_TRANSMUTE,
                                e.span,
                                &format!("transmute from a `{}` to a pointer", from_ty),
                            ),
                            (&ty::TyRawPtr(from_ptr), _) if from_ptr.ty == to_ty => span_lint(
                                cx,
                                CROSSPOINTER_TRANSMUTE,
                                e.span,
                                &format!(
                                    "transmute from a type (`{}`) to the type that it points to (`{}`)",
                                    from_ty,
                                    to_ty
                                ),
                            ),
                            (_, &ty::TyRawPtr(to_ptr)) if to_ptr.ty == from_ty => span_lint(
                                cx,
                                CROSSPOINTER_TRANSMUTE,
                                e.span,
                                &format!("transmute from a type (`{}`) to a pointer to that type (`{}`)", from_ty, to_ty),
                            ),
                            (&ty::TyRawPtr(from_pty), &ty::TyRef(_, to_ref_ty)) => span_lint_and_then(
                                cx,
                                TRANSMUTE_PTR_TO_REF,
                                e.span,
                                &format!(
                                    "transmute from a pointer type (`{}`) to a reference type \
                                    (`{}`)",
                                    from_ty,
                                    to_ty
                                ),
                                |db| {
                                    let arg = sugg::Sugg::hir(cx, &args[0], "..");
                                    let (deref, cast) = if to_ref_ty.mutbl == Mutability::MutMutable {
                                        ("&mut *", "*mut")
                                    } else {
                                        ("&*", "*const")
                                    };

                                    let arg = if from_pty.ty == to_ref_ty.ty {
                                        arg
                                    } else {
                                        arg.as_ty(&format!("{} {}", cast, get_type_snippet(cx, qpath, to_ref_ty.ty)))
                                    };

                                    db.span_suggestion(e.span, "try", sugg::make_unop(deref, arg).to_string());
                                },
                            ),
                            (&ty::TyInt(ast::IntTy::I32), &ty::TyChar) |
                            (&ty::TyUint(ast::UintTy::U32), &ty::TyChar) => span_lint_and_then(
                                cx,
                                TRANSMUTE_INT_TO_CHAR,
                                e.span,
                                &format!("transmute from a `{}` to a `char`", from_ty),
                                |db| {
                                    let arg = sugg::Sugg::hir(cx, &args[0], "..");
                                    let arg = if let ty::TyInt(_) = from_ty.sty {
                                        arg.as_ty(ty::TyUint(ast::UintTy::U32))
                                    } else {
                                        arg
                                    };
                                    db.span_suggestion(e.span, "consider using", format!("std::char::from_u32({}).unwrap()", arg.to_string()));
                                }
                            ),
                            (&ty::TyRef(_, ref ref_from), &ty::TyRef(_, ref ref_to)) => {
                                if_chain! {
                                    if let (&ty::TySlice(slice_ty), &ty::TyStr) = (&ref_from.ty.sty, &ref_to.ty.sty);
                                    if let ty::TyUint(ast::UintTy::U8) = slice_ty.sty;
                                    if ref_from.mutbl == ref_to.mutbl;
                                    then {
                                        let postfix = if ref_from.mutbl == Mutability::MutMutable {
                                            "_mut"
                                        } else {
                                            ""
                                        };

                                        span_lint_and_then(
                                            cx,
                                            TRANSMUTE_BYTES_TO_STR,
                                            e.span,
                                            &format!("transmute from a `{}` to a `{}`", from_ty, to_ty),
                                            |db| {
                                                db.span_suggestion(
                                                    e.span,
                                                    "consider using",
                                                    format!(
                                                        "std::str::from_utf8{}({}).unwrap()",
                                                        postfix,
                                                        snippet(cx, args[0].span, ".."),
                                                    ),
                                                );
                                            }
                                        )
                                    }
                                }
                            },
                            (&ty::TyInt(ast::IntTy::I8), &ty::TyBool) |
                            (&ty::TyUint(ast::UintTy::U8), &ty::TyBool) => span_lint_and_then(
                                cx,
                                TRANSMUTE_INT_TO_BOOL,
                                e.span,
                                &format!("transmute from a `{}` to a `bool`", from_ty),
                                |db| {
                                    let arg = sugg::Sugg::hir(cx, &args[0], "..");
                                    let zero = sugg::Sugg::NonParen(Cow::from("0"));
                                    db.span_suggestion(e.span, "consider using", sugg::make_binop(ast::BinOpKind::Ne, &arg, &zero).to_string());
                                }
                            ),
                            (&ty::TyInt(_), &ty::TyFloat(_)) |
                            (&ty::TyUint(_), &ty::TyFloat(_)) => span_lint_and_then(
                                cx,
                                TRANSMUTE_INT_TO_FLOAT,
                                e.span,
                                &format!("transmute from a `{}` to a `{}`", from_ty, to_ty),
                                |db| {
                                    let arg = sugg::Sugg::hir(cx, &args[0], "..");
                                    let arg = if let ty::TyInt(int_ty) = from_ty.sty {
                                        arg.as_ty(format!("u{}", int_ty.bit_width().map_or_else(|| "size".to_string(), |v| v.to_string())))
                                    } else {
                                        arg
                                    };
                                    db.span_suggestion(e.span, "consider using", format!("{}::from_bits({})", to_ty, arg.to_string()));
                                }
                            ),
                            _ => return,
                        };
                    }
                }
            }
        }
    }
}

/// Get the snippet of `Bar` in `…::transmute<Foo, &Bar>`. If that snippet is
/// not available , use
/// the type's `ToString` implementation. In weird cases it could lead to types
/// with invalid `'_`
/// lifetime, but it should be rare.
fn get_type_snippet(cx: &LateContext, path: &QPath, to_ref_ty: Ty) -> String {
    let seg = last_path_segment(path);
    if_chain! {
        if let Some(ref params) = seg.parameters;
        if !params.parenthesized;
        if let Some(to_ty) = params.types.get(1);
        if let TyRptr(_, ref to_ty) = to_ty.node;
        then {
            return snippet(cx, to_ty.ty.span, &to_ref_ty.to_string()).to_string();
        }
    }

    to_ref_ty.to_string()
}
<|endoftext|>


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

use vertex::{RawVertex,Vertex};
use traversal::GraphQuery;
use path::Element;
use treepath::TreePath;
use edge::Edge;
use parser::{parse, Arg};

#[derive(Debug)]
pub struct Graph {
    elements: i64,
    // we transmute our Boxed vertex into a pointer later
    vertices: HashMap<i64, *mut RawVertex>,
    queue: Vec<String>,
    treepath: Option<TreePath>,
}

// graph is not thread safe - needs to be wrapped in an Arc<Mutex> when running as server
impl Graph {
    pub fn new() -> Box<Graph> {
        let vertices: HashMap<i64, *mut RawVertex> = HashMap::new();
        Box::new(Graph{elements:0,
                        vertices:vertices,
                        queue:Vec::with_capacity(100),
                        treepath: None })
    }

    // todo actually return a result DERP DERP DERP
    pub fn execute(&self, query: &str) {
        // parse the graph query

        // let mut steps_table : HashMap<&'static str, FnMut() -> Result<&'static str, &'static str> > = HashMap::new();
        // steps_table.insert("outV", traverse_out);
        // steps_table.insert("inV", traverse_in);

        // todo - validate query is using legit steps

        match parse(query) {
            Ok(query) => {
                // execute each of the steps sequentially
                for step in query.steps.iter() {
                    // lookup step in hash table
                    println!("{}", step);

                    let name : &str = &step.name;

                    // there has to be a better way of doing this?
                    let step_result = match name {
                        "outV" => self.traverse_out_vertex(&step.args),
                        "inV" => self.traverse_in_vertex(&step.args),
                        "outE" => self.traverse_out_edge(&step.args),
                        "inE" => self.traverse_in_edge(&step.args),
                        "v" => self.vertex_query(&step.args),
                        "V" => self.global_query(&step.args),
                        _ => Err("no thingy found")
                    };
                    // execute function, passing step args
                }
            },
            Err(x) => {
                println!("SUCH FAIL!!!!")
            }
                // Result::Err("meh")
        }
        println!("query finished");
        ()
    }

    fn vertex_query(&self, args: &Vec<Arg>) -> Result<&'static str, &'static str>  {
        println!("vertex query");
        // gather the requested vertices
        unimplemented!();
        Ok("cool")
    }

    fn global_query(&self, args: &Vec<Arg>) -> Result<&'static str, &'static str>  {
        println!("global query");
        unimplemented!();
        Ok("cool")
    }

    fn traverse_out_vertex(&self, args: &Vec<Arg>) -> Result<&'static str, &'static str>  {
        println!("outV traversal");

        Ok("cool")
    }

    fn traverse_in_vertex(&self, args: &Vec<Arg>) -> Result<&'static str, &'static str>  {
        println!("inV traversal");

        unimplemented!();
        Ok("cool")
    }

    fn traverse_out_edge(&self, args: &Vec<Arg>) -> Result<&'static str, &'static str>  {
        println!("outE traversal");
        unimplemented!();
        Ok("cool")
    }

    fn traverse_in_edge(&self, args: &Vec<Arg>) -> Result<&'static str, &'static str>  {
        println!("inE traversal");
        unimplemented!();
        Ok("cool")
    }
    pub fn add_vertex(&mut self) -> Vertex {
        let new_id = self.elements + 1;
        self.elements += 1;
        let v = RawVertex::new(new_id);
        let ptr: *mut RawVertex = unsafe { mem::transmute(v) };

        self.vertices.insert(new_id, ptr);

        // return the proxy which knows it's own id
        Vertex{id:new_id, v: ptr}
    }

    pub fn get(&self, vertex_id:i64) -> Option<Vertex>  {
        let vertex_pointer = self.vertices.get(&vertex_id);
        // return a proxy
        match vertex_pointer {
            Some(ptr) =>
                Some(Vertex{id:vertex_id, v:*ptr}),
            None =>
                None
        }
    }

    // this will be used to start a graph query
    pub fn v(&self, vertex_id:i64) -> GraphQuery {
        // grab the original vertex
        let vertex = self.get(vertex_id);
        let mut v = Vec::new();
        match vertex {
            Some(result) => {
                v.push(result);
                GraphQuery::new(v)
            }
            None => GraphQuery::empty()
        }
    }
}

pub trait TraversableToVertex {
	fn inV(&self) -> Vec<Vertex>;
	fn outV(&self, &[&str]) -> Vec<Vertex>;
//	fn inE(&self) -> Vec<Edge>;

}

struct GraphQueryResult {
    results: TreePath
}
<commit_msg>passing graph result through<commit_after>use std::collections::HashMap;
use std::mem;

use vertex::{RawVertex,Vertex};
use traversal::GraphQuery;
use path::Element;
use treepath::TreePath;
use edge::Edge;
use parser::{parse, Arg};

#[derive(Debug)]
pub struct Graph {
    elements: i64,
    // we transmute our Boxed vertex into a pointer later
    vertices: HashMap<i64, *mut RawVertex>,
    queue: Vec<String>,
    treepath: Option<TreePath>,
}

// graph is not thread safe - needs to be wrapped in an Arc<Mutex> when running as server
impl Graph {
    pub fn new() -> Box<Graph> {
        let vertices: HashMap<i64, *mut RawVertex> = HashMap::new();
        Box::new(Graph{elements:0,
                        vertices:vertices,
                        queue:Vec::with_capacity(100),
                        treepath: None })
    }

    // todo actually return a result DERP DERP DERP
    pub fn execute(&self, query: &str) {
        // parse the graph query

        // let mut steps_table : HashMap<&'static str, FnMut() -> Result<&'static str, &'static str> > = HashMap::new();
        // steps_table.insert("outV", traverse_out);
        // steps_table.insert("inV", traverse_in);

        // todo - validate query is using legit steps
        let result = GraphQueryResult::new();

        match parse(query) {
            Ok(query) => {
                // execute each of the steps sequentially
                for step in query.steps.iter() {
                    // lookup step in hash table
                    println!("{}", step);

                    let name : &str = &step.name;

                    // there has to be a better way of doing this?
                    let step_result = match name {
                        "outV" => self.traverse_out_vertex(&step.args),
                        "inV" => self.traverse_in_vertex(&step.args),
                        "outE" => self.traverse_out_edge(&step.args),
                        "inE" => self.traverse_in_edge(&step.args),
                        "v" => self.vertex_query(&result, &step.args),
                        "V" => self.global_query(&step.args),
                        _ => Err("no thingy found")
                    };
                    // execute function, passing step args
                }
            },
            Err(x) => {
                println!("SUCH FAIL!!!!")
            }
                // Result::Err("meh")
        }
        println!("query finished");
        ()
    }

    fn vertex_query(&self, result: &GraphQueryResult, args: &Vec<Arg>) -> Result<&'static str, &'static str>  {
        println!("vertex query");
        // gather the requested vertices
        unimplemented!();
        Ok("cool")
    }

    fn global_query(&self, args: &Vec<Arg>) -> Result<&'static str, &'static str>  {
        println!("global query");
        unimplemented!();
        Ok("cool")
    }

    fn traverse_out_vertex(&self, args: &Vec<Arg>) -> Result<&'static str, &'static str>  {
        println!("outV traversal");

        Ok("cool")
    }

    fn traverse_in_vertex(&self, args: &Vec<Arg>) -> Result<&'static str, &'static str>  {
        println!("inV traversal");

        unimplemented!();
        Ok("cool")
    }

    fn traverse_out_edge(&self, args: &Vec<Arg>) -> Result<&'static str, &'static str>  {
        println!("outE traversal");
        unimplemented!();
        Ok("cool")
    }

    fn traverse_in_edge(&self, args: &Vec<Arg>) -> Result<&'static str, &'static str>  {
        println!("inE traversal");
        unimplemented!();
        Ok("cool")
    }
    pub fn add_vertex(&mut self) -> Vertex {
        let new_id = self.elements + 1;
        self.elements += 1;
        let v = RawVertex::new(new_id);
        let ptr: *mut RawVertex = unsafe { mem::transmute(v) };

        self.vertices.insert(new_id, ptr);

        // return the proxy which knows it's own id
        Vertex{id:new_id, v: ptr}
    }

    pub fn get(&self, vertex_id:i64) -> Option<Vertex>  {
        let vertex_pointer = self.vertices.get(&vertex_id);
        // return a proxy
        match vertex_pointer {
            Some(ptr) =>
                Some(Vertex{id:vertex_id, v:*ptr}),
            None =>
                None
        }
    }

    // this will be used to start a graph query
    pub fn v(&self, vertex_id:i64) -> GraphQuery {
        // grab the original vertex
        let vertex = self.get(vertex_id);
        let mut v = Vec::new();
        match vertex {
            Some(result) => {
                v.push(result);
                GraphQuery::new(v)
            }
            None => GraphQuery::empty()
        }
    }
}

pub trait TraversableToVertex {
	fn inV(&self) -> Vec<Vertex>;
	fn outV(&self, &[&str]) -> Vec<Vertex>;
//	fn inE(&self) -> Vec<Edge>;

}

struct GraphQueryResult {
    results: Option<TreePath>
}

impl GraphQueryResult {
    pub fn new() -> GraphQueryResult {
        GraphQueryResult{ results: None }
    }
}
<|endoftext|>


<commit_before>use sql_types::{self, NotNull};

/// Marker trait for types which can be used with `MAX` and `MIN`
pub trait SqlOrd {}

impl SqlOrd for sql_types::SmallInt {}
impl SqlOrd for sql_types::Integer {}
impl SqlOrd for sql_types::BigInt {}
impl SqlOrd for sql_types::Float {}
impl SqlOrd for sql_types::Double {}
impl SqlOrd for sql_types::Text {}
impl SqlOrd for sql_types::Date {}
impl SqlOrd for sql_types::Interval {}
impl SqlOrd for sql_types::Time {}
impl SqlOrd for sql_types::Timestamp {}
impl<T: SqlOrd + NotNull> SqlOrd for sql_types::Nullable<T> {}

#[cfg(feature = "postgres")]
impl<T: SqlOrd> SqlOrd for sql_types::Array<T> {}

#[cfg(feature = "mysql")]
impl SqlOrd for sql_types::Unsigned<sql_types::SmallInt> {}
#[cfg(feature = "mysql")]
impl SqlOrd for sql_types::Unsigned<sql_types::Integer> {}
#[cfg(feature = "mysql")]
impl SqlOrd for sql_types::Unsigned<sql_types::BigInt> {}
<commit_msg>impl SqlOrd for Timestamptz<commit_after>use sql_types::{self, NotNull};

/// Marker trait for types which can be used with `MAX` and `MIN`
pub trait SqlOrd {}

impl SqlOrd for sql_types::SmallInt {}
impl SqlOrd for sql_types::Integer {}
impl SqlOrd for sql_types::BigInt {}
impl SqlOrd for sql_types::Float {}
impl SqlOrd for sql_types::Double {}
impl SqlOrd for sql_types::Text {}
impl SqlOrd for sql_types::Date {}
impl SqlOrd for sql_types::Interval {}
impl SqlOrd for sql_types::Time {}
impl SqlOrd for sql_types::Timestamp {}
impl<T: SqlOrd + NotNull> SqlOrd for sql_types::Nullable<T> {}

#[cfg(feature = "postgres")]
impl SqlOrd for sql_types::Timestamptz {}
#[cfg(feature = "postgres")]
impl<T: SqlOrd> SqlOrd for sql_types::Array<T> {}

#[cfg(feature = "mysql")]
impl SqlOrd for sql_types::Unsigned<sql_types::SmallInt> {}
#[cfg(feature = "mysql")]
impl SqlOrd for sql_types::Unsigned<sql_types::Integer> {}
#[cfg(feature = "mysql")]
impl SqlOrd for sql_types::Unsigned<sql_types::BigInt> {}
<|endoftext|>


<commit_before>#![feature(custom_derive, plugin, custom_attribute, test)]
#![plugin(diesel_codegen, dotenv_macros)]
#[macro_use]
extern crate diesel;
extern crate test;

mod schema;

use self::test::Bencher;
use self::schema::*;
use diesel::*;

#[bench]
fn bench_selecting_0_rows_with_trivial_query(b: &mut Bencher) {
    let conn = connection();

    b.iter(|| {
        users::table.load(&conn).unwrap().collect::<Vec<User>>();
    })
}

#[bench]
fn bench_selecting_10k_rows_with_trivial_query(b: &mut Bencher) {
    let conn = connection();
    let data: Vec<_> = (0..10_000).map(|i| {
        NewUser::new(&format!("User {}", i), None)
    }).collect();
    batch_insert(&data, users::table, &conn);

    b.iter(|| {
        users::table.load(&conn).unwrap().collect::<Vec<User>>()
    })
}

#[bench]
fn bench_selecting_0_rows_with_medium_complex_query(b: &mut Bencher) {
    let conn = connection();

    b.iter(|| {
        use schema::users::dsl::*;
        let target = users.left_outer_join(posts::table)
            .filter(hair_color.eq("black"))
            .order(name.desc());
        target.load(&conn).unwrap().collect::<Vec<(User, Option<Post>)>>()
    })
}

#[bench]
fn bench_selecting_10k_rows_with_medium_complex_query(b: &mut Bencher) {
    let conn = connection();

    let data: Vec<_> = (0..10_000).map(|i| {
        let hair_color = if i % 2 == 0 { "black" } else { "brown" };
        NewUser::new(&format!("User {}", i), Some(hair_color))
    }).collect();
    batch_insert(&data, users::table, &conn);

    b.iter(|| {
        use schema::users::dsl::*;
        let target = users.left_outer_join(posts::table)
            .filter(hair_color.eq("black"))
            .order(name.desc());
        target.load(&conn).unwrap().collect::<Vec<(User, Option<Post>)>>()
    })
}
<commit_msg>Update benchmarks to account for recent changes<commit_after>#![feature(custom_derive, plugin, custom_attribute, test)]
#![plugin(diesel_codegen, dotenv_macros)]
#[macro_use]
extern crate diesel;
extern crate test;

mod schema;

use self::test::Bencher;
use self::schema::*;
use diesel::*;

#[bench]
fn bench_selecting_0_rows_with_trivial_query(b: &mut Bencher) {
    let conn = connection();

    b.iter(|| {
        users::table.load::<User>(&conn).unwrap();
    })
}

#[bench]
fn bench_selecting_10k_rows_with_trivial_query(b: &mut Bencher) {
    let conn = connection();
    let data: Vec<_> = (0..10_000).map(|i| {
        NewUser::new(&format!("User {}", i), None)
    }).collect();
    batch_insert(&data, users::table, &conn);

    b.iter(|| {
        users::table.load::<User>(&conn).unwrap()
    })
}

#[bench]
fn bench_selecting_10k_rows_with_trivial_query_boxed(b: &mut Bencher) {
    let conn = connection();
    let data: Vec<_> = (0..10_000).map(|i| {
        NewUser::new(&format!("User {}", i), None)
    }).collect();
    batch_insert(&data, users::table, &conn);

    b.iter(|| {
        users::table.into_boxed().load::<User>(&conn).unwrap()
    })
}

#[bench]
fn bench_selecting_0_rows_with_medium_complex_query(b: &mut Bencher) {
    let conn = connection();

    b.iter(|| {
        use schema::users::dsl::*;
        let target = users.left_outer_join(posts::table)
            .filter(hair_color.eq("black"))
            .order(name.desc());
        target.load::<(User, Option<Post>)>(&conn).unwrap()
    })
}

#[bench]
fn bench_selecting_10k_rows_with_medium_complex_query(b: &mut Bencher) {
    let conn = connection();

    let data: Vec<_> = (0..10_000).map(|i| {
        let hair_color = if i % 2 == 0 { "black" } else { "brown" };
        NewUser::new(&format!("User {}", i), Some(hair_color))
    }).collect();
    batch_insert(&data, users::table, &conn);

    b.iter(|| {
        use schema::users::dsl::*;
        let target = users.left_outer_join(posts::table)
            .filter(hair_color.eq("black"))
            .order(name.desc());
        target.load::<(User, Option<Post>)>(&conn).unwrap()
    })
}

#[bench]
fn bench_selecting_10k_rows_with_medium_complex_query_boxed(b: &mut Bencher) {
    let conn = connection();

    let data: Vec<_> = (0..10_000).map(|i| {
        let hair_color = if i % 2 == 0 { "black" } else { "brown" };
        NewUser::new(&format!("User {}", i), Some(hair_color))
    }).collect();
    batch_insert(&data, users::table, &conn);

    b.iter(|| {
        use schema::users::dsl::*;
        let target = users.left_outer_join(posts::table)
            .filter(hair_color.eq("black"))
            .order(name.desc())
            .into_boxed();
        target.load::<(User, Option<Post>)>(&conn).unwrap()
    })
}
<|endoftext|>


<commit_before>use super::super::request::Request;
use super::super::response::Response;
use super::super::ingot::{Ingot, Continue, Unwind};
use super::super::anymap::AnyMap;
use super::super::alloy::Alloy;

use super::Furnace;

struct IronFurnace<Rq, Rs> {
    stack: Vec<Box<Ingot<Rq, Rs>: Send>>
}

impl<Rq: Request, Rs: Response> Clone for IronFurnace<Rq, Rs> {
    fn clone(&self) -> IronFurnace<Rq, Rs> { IronFurnace { stack: self.stack.clone() } }
}

impl<Rq: Request, Rs: Response> Clone for Box<Ingot<Rq, Rs>> {
    fn clone(&self) -> Box<Ingot<Rq, Rs>> { self.clone_box() }
}

<commit_msg>(feat) Added skeleton of forge for IronFurnace<commit_after>use super::super::request::Request;
use super::super::response::Response;
use super::super::ingot::{Ingot, Continue, Unwind};
use super::super::anymap::AnyMap;
use super::super::alloy::Alloy;

use super::Furnace;

struct IronFurnace<Rq, Rs> {
    stack: Vec<Box<Ingot<Rq, Rs>: Send>>
}

impl<Rq: Request, Rs: Response> Clone for IronFurnace<Rq, Rs> {
    fn clone(&self) -> IronFurnace<Rq, Rs> { IronFurnace { stack: self.stack.clone() } }
}

impl<Rq: Request, Rs: Response> Clone for Box<Ingot<Rq, Rs>> {
    fn clone(&self) -> Box<Ingot<Rq, Rs>> { self.clone_box() }
}

impl<Rq: Request, Rs: Response> Furnace<Rq, Rs> for IronFurnace<Rq, Rs> {
    fn forge(&mut self, request: &mut Rq, response: &mut Rs, malloy: Option<&mut Alloy>) {
        let mut alloy = &mut AnyMap::new();

        match malloy {
            Some(a) => alloy = a,
            None => ()
        };

        'enter: for ingot in self.stack.mut_iter() {
            match ingot.enter(request, response, alloy) {
                Unwind   => break 'enter,
                Continue => ()
            }
        }
    }
    fn smelt<I: Ingot<Rq, Rs>>(&mut self, ingot: I) {
        self.stack.push(box ingot);
    }
}

<|endoftext|>


<commit_before>mod macaddr;
pub use self::macaddr::*;

packet!(EthernetPacket, MutEthernetPacket, 14);

getters!(EthernetPacket
    pub fn destination(&self) -> MacAddr {
        MacAddr::from_slice(&self.0[0..6])
    }

    pub fn source(&self) -> MacAddr {
        MacAddr::from_slice(&self.0[6..12])
    }

    pub fn ether_type(&self) -> EtherType {
        EtherType(read_offset!(self.0, 12, u16, from_be))
    }
);

setters!(MutEthernetPacket
    pub fn set_destination(&mut self, destination: MacAddr) {
        self.0[0..6].copy_from_slice(destination.as_ref());
    }

    pub fn set_source(&mut self, source: MacAddr) {
        self.0[6..12].copy_from_slice(source.as_ref());
    }

    pub fn set_ether_type(&mut self, ether_type: EtherType) {
        write_offset!(self.0, 12, ether_type.value(), u16, to_be)
    }
);

/// A representation of the 16 bit EtherType header field of an Ethernet packet.
///
/// A few select, commonly used, values are attached as associated constants. Their values are
/// defined at https://www.iana.org/assignments/ieee-802-numbers/ieee-802-numbers.xhtml
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
pub struct EtherType(pub u16);

impl EtherType {
    pub const IPV4: EtherType = EtherType(0x0800);
    pub const ARP: EtherType = EtherType(0x0806);
    pub const IPV6: EtherType = EtherType(0x86DD);

    #[inline]
    pub fn value(&self) -> u16 {
        self.0
    }
}

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

    static MAC: [u8; 6] = [0xff; 6];

    macro_rules! eth_setget_test {
        ($name:ident, $set_name:ident, $value:expr, $offset:expr, $expected:expr) => {
            setget_test!(MutEthernetPacket, $name, $set_name, $value, $offset, $expected);
        }
    }

    eth_setget_test!(destination, set_destination, MacAddr(MAC), 0, MAC);
    eth_setget_test!(source, set_source, MacAddr(MAC), 6, MAC);
    eth_setget_test!(ether_type, set_ether_type, EtherType(0xffff), 12, [0xff; 2]);

    #[test]
    fn set_payload() {
        let mut backing_data = [0; 15];
        {
            let mut testee = MutEthernetPacket::new(&mut backing_data).unwrap();
            testee.payload()[0] = 99;
        }
        assert_eq!(99, backing_data[14]);
    }
}
<commit_msg>Fix doc markdown warning<commit_after>mod macaddr;
pub use self::macaddr::*;

packet!(EthernetPacket, MutEthernetPacket, 14);

getters!(EthernetPacket
    pub fn destination(&self) -> MacAddr {
        MacAddr::from_slice(&self.0[0..6])
    }

    pub fn source(&self) -> MacAddr {
        MacAddr::from_slice(&self.0[6..12])
    }

    pub fn ether_type(&self) -> EtherType {
        EtherType(read_offset!(self.0, 12, u16, from_be))
    }
);

setters!(MutEthernetPacket
    pub fn set_destination(&mut self, destination: MacAddr) {
        self.0[0..6].copy_from_slice(destination.as_ref());
    }

    pub fn set_source(&mut self, source: MacAddr) {
        self.0[6..12].copy_from_slice(source.as_ref());
    }

    pub fn set_ether_type(&mut self, ether_type: EtherType) {
        write_offset!(self.0, 12, ether_type.value(), u16, to_be)
    }
);

/// A representation of the 16 bit EtherType header field of an Ethernet packet.
///
/// A few select, commonly used, values are attached as associated constants. Their values are
/// defined on [IANA's website].
///
/// [IANA's website]: https://www.iana.org/assignments/ieee-802-numbers/ieee-802-numbers.xhtml
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
pub struct EtherType(pub u16);

impl EtherType {
    pub const IPV4: EtherType = EtherType(0x0800);
    pub const ARP: EtherType = EtherType(0x0806);
    pub const IPV6: EtherType = EtherType(0x86DD);

    #[inline]
    pub fn value(&self) -> u16 {
        self.0
    }
}

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

    static MAC: [u8; 6] = [0xff; 6];

    macro_rules! eth_setget_test {
        ($name:ident, $set_name:ident, $value:expr, $offset:expr, $expected:expr) => {
            setget_test!(MutEthernetPacket, $name, $set_name, $value, $offset, $expected);
        }
    }

    eth_setget_test!(destination, set_destination, MacAddr(MAC), 0, MAC);
    eth_setget_test!(source, set_source, MacAddr(MAC), 6, MAC);
    eth_setget_test!(ether_type, set_ether_type, EtherType(0xffff), 12, [0xff; 2]);

    #[test]
    fn set_payload() {
        let mut backing_data = [0; 15];
        {
            let mut testee = MutEthernetPacket::new(&mut backing_data).unwrap();
            testee.payload()[0] = 99;
        }
        assert_eq!(99, backing_data[14]);
    }
}
<|endoftext|>