<commit_before>fn md4(msg: [u8]) -> {a: u32, b: u32, c: u32, d: u32} {
    // subtle: if orig_len is merely uint, then the code below
    // which performs shifts by 32 bits or more has undefined
    // results.
    let orig_len: u64 = (vec::len(msg) * 8u) as u64;

    // pad message
    let msg = msg + [0x80u8];
    let bitlen = orig_len + 8u;
    while (bitlen + 64u) % 512u > 0u {
        msg += [0u8];
        bitlen += 8u;
    }

    // append length
    let i = 0u;
    while i < 8u {
        msg += [(orig_len >> (i * 8u)) as u8];
        i += 1u;
    }

    let a = 0x67452301u32;
    let b = 0xefcdab89u32;
    let c = 0x98badcfeu32;
    let d = 0x10325476u32;

    fn rot(r: int, x: u32) -> u32 {
        let r = r as u32;
        (x << r) | (x >> (32u32 - r))
    }

    let i = 0u, e = vec::len(msg);
    let x = vec::init_elt_mut(16u, 0u32);
    while i < e {
        let aa = a, bb = b, cc = c, dd = d;

        let j = 0u, base = i;
        while j < 16u {
            x[j] = (msg[base] as u32) + (msg[base + 1u] as u32 << 8u32) +
                (msg[base + 2u] as u32 << 16u32) +
                (msg[base + 3u] as u32 << 24u32);
            j += 1u; base += 4u;
        }

        let j = 0u;
        while j < 16u {
            a = rot(3, a + ((b & c) | (!b & d)) + x[j]);
            j += 1u;
            d = rot(7, d + ((a & b) | (!a & c)) + x[j]);
            j += 1u;
            c = rot(11, c + ((d & a) | (!d & b)) + x[j]);
            j += 1u;
            b = rot(19, b + ((c & d) | (!c & a)) + x[j]);
            j += 1u;
        }

        let j = 0u, q = 0x5a827999u32;
        while j < 4u {
            a = rot(3, a + ((b & c) | ((b & d) | (c & d))) + x[j] + q);
            d = rot(5, d + ((a & b) | ((a & c) | (b & c))) + x[j + 4u] + q);
            c = rot(9, c + ((d & a) | ((d & b) | (a & b))) + x[j + 8u] + q);
            b = rot(13, b + ((c & d) | ((c & a) | (d & a))) + x[j + 12u] + q);
            j += 1u;
        }

        let j = 0u, q = 0x6ed9eba1u32;
        while j < 8u {
            let jj = j > 2u ? j - 3u : j;
            a = rot(3, a + (b ^ c ^ d) + x[jj] + q);
            d = rot(9, d + (a ^ b ^ c) + x[jj + 8u] + q);
            c = rot(11, c + (d ^ a ^ b) + x[jj + 4u] + q);
            b = rot(15, b + (c ^ d ^ a) + x[jj + 12u] + q);
            j += 2u;
        }

        a += aa; b += bb; c += cc; d += dd;
        i += 64u;
    }
    ret {a: a, b: b, c: c, d: d};
}

fn md4_str(msg: [u8]) -> str {
    let {a, b, c, d} = md4(msg);
    fn app(a: u32, b: u32, c: u32, d: u32, f: block(u32)) {
        f(a); f(b); f(c); f(d);
    }
    let result = "";
    app(a, b, c, d) {|u|
        let i = 0u32;
        while i < 4u32 {
            let byte = (u >> (i * 8u32)) as u8;
            if byte <= 16u8 { result += "0"; }
            result += uint::to_str(byte as uint, 16u);
            i += 1u32;
        }
    }
    result
}

fn md4_text(msg: str) -> str { md4_str(str::bytes(msg)) }

#[test]
fn test_md4() {
    assert md4_text("") == "31d6cfe0d16ae931b73c59d7e0c089c0";
    assert md4_text("a") == "bde52cb31de33e46245e05fbdbd6fb24";
    assert md4_text("abc") == "a448017aaf21d8525fc10ae87aa6729d";
    assert md4_text("message digest") == "d9130a8164549fe818874806e1c7014b";
    assert md4_text("abcdefghijklmnopqrstuvwxyz") ==
        "d79e1c308aa5bbcdeea8ed63df412da9";
    assert md4_text("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123\
                     456789") == "043f8582f241db351ce627e153e7f0e4";
    assert md4_text("12345678901234567890123456789012345678901234567890123456\
                     789012345678901234567890") ==
        "e33b4ddc9c38f2199c3e7b164fcc0536";
}
<commit_msg>use u64 and not uint; otherwise shift results are undef. in 32 bit<commit_after>fn md4(msg: [u8]) -> {a: u32, b: u32, c: u32, d: u32} {
    // subtle: if orig_len is merely uint, then the code below
    // which performs shifts by 32 bits or more has undefined
    // results.
    let orig_len: u64 = (vec::len(msg) * 8u) as u64;

    // pad message
    let msg = msg + [0x80u8];
    let bitlen = orig_len + 8u64;
    while (bitlen + 64u64) % 512u64 > 0u64 {
        msg += [0u8];
        bitlen += 8u64;
    }

    // append length
    let i = 0u64;
    while i < 8u64 {
        msg += [(orig_len >> (i * 8u64)) as u8];
        i += 1u64;
    }

    let a = 0x67452301u32;
    let b = 0xefcdab89u32;
    let c = 0x98badcfeu32;
    let d = 0x10325476u32;

    fn rot(r: int, x: u32) -> u32 {
        let r = r as u32;
        (x << r) | (x >> (32u32 - r))
    }

    let i = 0u, e = vec::len(msg);
    let x = vec::init_elt_mut(16u, 0u32);
    while i < e {
        let aa = a, bb = b, cc = c, dd = d;

        let j = 0u, base = i;
        while j < 16u {
            x[j] = (msg[base] as u32) + (msg[base + 1u] as u32 << 8u32) +
                (msg[base + 2u] as u32 << 16u32) +
                (msg[base + 3u] as u32 << 24u32);
            j += 1u; base += 4u;
        }

        let j = 0u;
        while j < 16u {
            a = rot(3, a + ((b & c) | (!b & d)) + x[j]);
            j += 1u;
            d = rot(7, d + ((a & b) | (!a & c)) + x[j]);
            j += 1u;
            c = rot(11, c + ((d & a) | (!d & b)) + x[j]);
            j += 1u;
            b = rot(19, b + ((c & d) | (!c & a)) + x[j]);
            j += 1u;
        }

        let j = 0u, q = 0x5a827999u32;
        while j < 4u {
            a = rot(3, a + ((b & c) | ((b & d) | (c & d))) + x[j] + q);
            d = rot(5, d + ((a & b) | ((a & c) | (b & c))) + x[j + 4u] + q);
            c = rot(9, c + ((d & a) | ((d & b) | (a & b))) + x[j + 8u] + q);
            b = rot(13, b + ((c & d) | ((c & a) | (d & a))) + x[j + 12u] + q);
            j += 1u;
        }

        let j = 0u, q = 0x6ed9eba1u32;
        while j < 8u {
            let jj = j > 2u ? j - 3u : j;
            a = rot(3, a + (b ^ c ^ d) + x[jj] + q);
            d = rot(9, d + (a ^ b ^ c) + x[jj + 8u] + q);
            c = rot(11, c + (d ^ a ^ b) + x[jj + 4u] + q);
            b = rot(15, b + (c ^ d ^ a) + x[jj + 12u] + q);
            j += 2u;
        }

        a += aa; b += bb; c += cc; d += dd;
        i += 64u;
    }
    ret {a: a, b: b, c: c, d: d};
}

fn md4_str(msg: [u8]) -> str {
    let {a, b, c, d} = md4(msg);
    fn app(a: u32, b: u32, c: u32, d: u32, f: block(u32)) {
        f(a); f(b); f(c); f(d);
    }
    let result = "";
    app(a, b, c, d) {|u|
        let i = 0u32;
        while i < 4u32 {
            let byte = (u >> (i * 8u32)) as u8;
            if byte <= 16u8 { result += "0"; }
            result += uint::to_str(byte as uint, 16u);
            i += 1u32;
        }
    }
    result
}

fn md4_text(msg: str) -> str { md4_str(str::bytes(msg)) }

#[test]
fn test_md4() {
    assert md4_text("") == "31d6cfe0d16ae931b73c59d7e0c089c0";
    assert md4_text("a") == "bde52cb31de33e46245e05fbdbd6fb24";
    assert md4_text("abc") == "a448017aaf21d8525fc10ae87aa6729d";
    assert md4_text("message digest") == "d9130a8164549fe818874806e1c7014b";
    assert md4_text("abcdefghijklmnopqrstuvwxyz") ==
        "d79e1c308aa5bbcdeea8ed63df412da9";
    assert md4_text("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123\
                     456789") == "043f8582f241db351ce627e153e7f0e4";
    assert md4_text("12345678901234567890123456789012345678901234567890123456\
                     789012345678901234567890") ==
        "e33b4ddc9c38f2199c3e7b164fcc0536";
}
<|endoftext|>


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

//! Basic functions for dealing with memory
//!
//! This module contains functions for querying the size and alignment of
//! types, initializing and manipulating memory.

#[allow(missing_doc)]; // FIXME

use cast;
use ptr;
use intrinsics;
use intrinsics::{bswap16, bswap32, bswap64};

/// Returns the size of a type in bytes.
#[inline]
pub fn size_of<T>() -> uint {
    unsafe { intrinsics::size_of::<T>() }
}

/// Returns the size of the type that `_val` points to in bytes.
#[inline]
pub fn size_of_val<T>(_val: &T) -> uint {
    size_of::<T>()
}

/// Returns the size of a type in bytes, or 1 if the actual size is zero.
///
/// Useful for building structures containing variable-length arrays.
#[inline]
pub fn nonzero_size_of<T>() -> uint {
    let s = size_of::<T>();
    if s == 0 { 1 } else { s }
}

/// Returns the size in bytes of the type of the value that `_val` points to.
#[inline]
pub fn nonzero_size_of_val<T>(_val: &T) -> uint {
    nonzero_size_of::<T>()
}

/// Returns the ABI-required minimum alignment of a type
///
/// This is the alignment used for struct fields. It may be smaller
/// than the preferred alignment.
#[inline]
pub fn min_align_of<T>() -> uint {
    unsafe { intrinsics::min_align_of::<T>() }
}

/// Returns the ABI-required minimum alignment of the type of the value that
/// `_val` points to
#[inline]
pub fn min_align_of_val<T>(_val: &T) -> uint {
    min_align_of::<T>()
}

/// Returns the preferred alignment of a type
#[inline]
pub fn pref_align_of<T>() -> uint {
    unsafe { intrinsics::pref_align_of::<T>() }
}

/// Returns the preferred alignment of the type of the value that
/// `_val` points to
#[inline]
pub fn pref_align_of_val<T>(_val: &T) -> uint {
    pref_align_of::<T>()
}

/// Create a value initialized to zero.
///
/// `init` is unsafe because it returns a zeroed-out datum,
/// which is unsafe unless T is Pod.
#[inline]
pub unsafe fn init<T>() -> T {
    intrinsics::init()
}

/// Create an uninitialized value.
#[inline]
pub unsafe fn uninit<T>() -> T {
    intrinsics::uninit()
}

/// Move a value to an uninitialized memory location.
///
/// Drop glue is not run on the destination.
#[inline]
pub unsafe fn move_val_init<T>(dst: &mut T, src: T) {
    intrinsics::move_val_init(dst, src)
}

#[cfg(target_endian = "little")] #[inline] pub fn to_le16(x: i16) -> i16 { x }
#[cfg(target_endian = "big")]    #[inline] pub fn to_le16(x: i16) -> i16 { unsafe { bswap16(x) } }
#[cfg(target_endian = "little")] #[inline] pub fn to_le32(x: i32) -> i32 { x }
#[cfg(target_endian = "big")]    #[inline] pub fn to_le32(x: i32) -> i32 { unsafe { bswap32(x) } }
#[cfg(target_endian = "little")] #[inline] pub fn to_le64(x: i64) -> i64 { x }
#[cfg(target_endian = "big")]    #[inline] pub fn to_le64(x: i64) -> i64 { unsafe { bswap64(x) } }

#[cfg(target_endian = "little")] #[inline] pub fn to_be16(x: i16) -> i16 { unsafe { bswap16(x) } }
#[cfg(target_endian = "big")]    #[inline] pub fn to_be16(x: i16) -> i16 { x }
#[cfg(target_endian = "little")] #[inline] pub fn to_be32(x: i32) -> i32 { unsafe { bswap32(x) } }
#[cfg(target_endian = "big")]    #[inline] pub fn to_be32(x: i32) -> i32 { x }
#[cfg(target_endian = "little")] #[inline] pub fn to_be64(x: i64) -> i64 { unsafe { bswap64(x) } }
#[cfg(target_endian = "big")]    #[inline] pub fn to_be64(x: i64) -> i64 { x }

#[cfg(target_endian = "little")] #[inline] pub fn from_le16(x: i16) -> i16 { x }
#[cfg(target_endian = "big")]    #[inline] pub fn from_le16(x: i16) -> i16 { unsafe { bswap16(x) } }
#[cfg(target_endian = "little")] #[inline] pub fn from_le32(x: i32) -> i32 { x }
#[cfg(target_endian = "big")]    #[inline] pub fn from_le32(x: i32) -> i32 { unsafe { bswap32(x) } }
#[cfg(target_endian = "little")] #[inline] pub fn from_le64(x: i64) -> i64 { x }
#[cfg(target_endian = "big")]    #[inline] pub fn from_le64(x: i64) -> i64 { unsafe { bswap64(x) } }

#[cfg(target_endian = "little")] #[inline] pub fn from_be16(x: i16) -> i16 { unsafe { bswap16(x) } }
#[cfg(target_endian = "big")]    #[inline] pub fn from_be16(x: i16) -> i16 { x }
#[cfg(target_endian = "little")] #[inline] pub fn from_be32(x: i32) -> i32 { unsafe { bswap32(x) } }
#[cfg(target_endian = "big")]    #[inline] pub fn from_be32(x: i32) -> i32 { x }
#[cfg(target_endian = "little")] #[inline] pub fn from_be64(x: i64) -> i64 { unsafe { bswap64(x) } }
#[cfg(target_endian = "big")]    #[inline] pub fn from_be64(x: i64) -> i64 { x }

/**
 * Swap the values at two mutable locations of the same type, without
 * deinitialising or copying either one.
 */
#[inline]
pub fn swap<T>(x: &mut T, y: &mut T) {
    unsafe {
        // Give ourselves some scratch space to work with
        let mut t: T = uninit();

        // Perform the swap, `&mut` pointers never alias
        ptr::copy_nonoverlapping_memory(&mut t, &*x, 1);
        ptr::copy_nonoverlapping_memory(x, &*y, 1);
        ptr::copy_nonoverlapping_memory(y, &t, 1);

        // y and t now point to the same thing, but we need to completely forget `tmp`
        // because it's no longer relevant.
        cast::forget(t);
    }
}

/**
 * Replace the value at a mutable location with a new one, returning the old
 * value, without deinitialising or copying either one.
 */
#[inline]
pub fn replace<T>(dest: &mut T, mut src: T) -> T {
    swap(dest, &mut src);
    src
}

/// Disposes of a value.
#[inline]
pub fn drop<T>(_x: T) { }

#[cfg(test)]
mod tests {
    use mem::*;
    use option::{Some,None};

    #[test]
    fn size_of_basic() {
        assert_eq!(size_of::<u8>(), 1u);
        assert_eq!(size_of::<u16>(), 2u);
        assert_eq!(size_of::<u32>(), 4u);
        assert_eq!(size_of::<u64>(), 8u);
    }

    #[test]
    #[cfg(target_arch = "x86")]
    #[cfg(target_arch = "arm")]
    #[cfg(target_arch = "mips")]
    fn size_of_32() {
        assert_eq!(size_of::<uint>(), 4u);
        assert_eq!(size_of::<*uint>(), 4u);
    }

    #[test]
    #[cfg(target_arch = "x86_64")]
    fn size_of_64() {
        assert_eq!(size_of::<uint>(), 8u);
        assert_eq!(size_of::<*uint>(), 8u);
    }

    #[test]
    fn size_of_val_basic() {
        assert_eq!(size_of_val(&1u8), 1);
        assert_eq!(size_of_val(&1u16), 2);
        assert_eq!(size_of_val(&1u32), 4);
        assert_eq!(size_of_val(&1u64), 8);
    }

    #[test]
    fn nonzero_size_of_basic() {
        type Z = [i8, ..0];
        assert_eq!(size_of::<Z>(), 0u);
        assert_eq!(nonzero_size_of::<Z>(), 1u);
        assert_eq!(nonzero_size_of::<uint>(), size_of::<uint>());
    }

    #[test]
    fn nonzero_size_of_val_basic() {
        let z = [0u8, ..0];
        assert_eq!(size_of_val(&z), 0u);
        assert_eq!(nonzero_size_of_val(&z), 1u);
        assert_eq!(nonzero_size_of_val(&1u), size_of_val(&1u));
    }

    #[test]
    fn align_of_basic() {
        assert_eq!(pref_align_of::<u8>(), 1u);
        assert_eq!(pref_align_of::<u16>(), 2u);
        assert_eq!(pref_align_of::<u32>(), 4u);
    }

    #[test]
    #[cfg(target_arch = "x86")]
    #[cfg(target_arch = "arm")]
    #[cfg(target_arch = "mips")]
    fn align_of_32() {
        assert_eq!(pref_align_of::<uint>(), 4u);
        assert_eq!(pref_align_of::<*uint>(), 4u);
    }

    #[test]
    #[cfg(target_arch = "x86_64")]
    fn align_of_64() {
        assert_eq!(pref_align_of::<uint>(), 8u);
        assert_eq!(pref_align_of::<*uint>(), 8u);
    }

    #[test]
    fn align_of_val_basic() {
        assert_eq!(pref_align_of_val(&1u8), 1u);
        assert_eq!(pref_align_of_val(&1u16), 2u);
        assert_eq!(pref_align_of_val(&1u32), 4u);
    }

    #[test]
    fn test_swap() {
        let mut x = 31337;
        let mut y = 42;
        swap(&mut x, &mut y);
        assert_eq!(x, 42);
        assert_eq!(y, 31337);
    }

    #[test]
    fn test_replace() {
        let mut x = Some(~"test");
        let y = replace(&mut x, None);
        assert!(x.is_none());
        assert!(y.is_some());
    }
}

/// Completely miscellaneous language-construct benchmarks.
#[cfg(test)]
mod bench {
    extern crate test;
    use self::test::BenchHarness;
    use option::{Some,None};

    // Static/dynamic method dispatch

    struct Struct {
        field: int
    }

    trait Trait {
        fn method(&self) -> int;
    }

    impl Trait for Struct {
        fn method(&self) -> int {
            self.field
        }
    }

    #[bench]
    fn trait_vtable_method_call(bh: &mut BenchHarness) {
        let s = Struct { field: 10 };
        let t = &s as &Trait;
        bh.iter(|| {
            t.method()
        });
    }

    #[bench]
    fn trait_static_method_call(bh: &mut BenchHarness) {
        let s = Struct { field: 10 };
        bh.iter(|| {
            s.method()
        });
    }

    // Overhead of various match forms

    #[bench]
    fn match_option_some(bh: &mut BenchHarness) {
        let x = Some(10);
        bh.iter(|| {
            match x {
                Some(y) => y,
                None => 11
            }
        });
    }

    #[bench]
    fn match_vec_pattern(bh: &mut BenchHarness) {
        let x = [1,2,3,4,5,6];
        bh.iter(|| {
            match x {
                [1,2,3,..] => 10,
                _ => 11
            }
        });
    }
}
<commit_msg>Doc-sprint: Document endian conversion functions<commit_after>// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Basic functions for dealing with memory
//!
//! This module contains functions for querying the size and alignment of
//! types, initializing and manipulating memory.

#[allow(missing_doc)]; // FIXME

use cast;
use ptr;
use intrinsics;
use intrinsics::{bswap16, bswap32, bswap64};

/// Returns the size of a type in bytes.
#[inline]
pub fn size_of<T>() -> uint {
    unsafe { intrinsics::size_of::<T>() }
}

/// Returns the size of the type that `_val` points to in bytes.
#[inline]
pub fn size_of_val<T>(_val: &T) -> uint {
    size_of::<T>()
}

/// Returns the size of a type in bytes, or 1 if the actual size is zero.
///
/// Useful for building structures containing variable-length arrays.
#[inline]
pub fn nonzero_size_of<T>() -> uint {
    let s = size_of::<T>();
    if s == 0 { 1 } else { s }
}

/// Returns the size in bytes of the type of the value that `_val` points to.
#[inline]
pub fn nonzero_size_of_val<T>(_val: &T) -> uint {
    nonzero_size_of::<T>()
}

/// Returns the ABI-required minimum alignment of a type
///
/// This is the alignment used for struct fields. It may be smaller
/// than the preferred alignment.
#[inline]
pub fn min_align_of<T>() -> uint {
    unsafe { intrinsics::min_align_of::<T>() }
}

/// Returns the ABI-required minimum alignment of the type of the value that
/// `_val` points to
#[inline]
pub fn min_align_of_val<T>(_val: &T) -> uint {
    min_align_of::<T>()
}

/// Returns the preferred alignment of a type
#[inline]
pub fn pref_align_of<T>() -> uint {
    unsafe { intrinsics::pref_align_of::<T>() }
}

/// Returns the preferred alignment of the type of the value that
/// `_val` points to
#[inline]
pub fn pref_align_of_val<T>(_val: &T) -> uint {
    pref_align_of::<T>()
}

/// Create a value initialized to zero.
///
/// `init` is unsafe because it returns a zeroed-out datum,
/// which is unsafe unless T is Pod.
#[inline]
pub unsafe fn init<T>() -> T {
    intrinsics::init()
}

/// Create an uninitialized value.
#[inline]
pub unsafe fn uninit<T>() -> T {
    intrinsics::uninit()
}

/// Move a value to an uninitialized memory location.
///
/// Drop glue is not run on the destination.
#[inline]
pub unsafe fn move_val_init<T>(dst: &mut T, src: T) {
    intrinsics::move_val_init(dst, src)
}

/// Convert an i16 to little endian from the target's endianness.
///
/// On little endian, this is a no-op.  On big endian, the bytes are swapped.
#[cfg(target_endian = "little")] #[inline] pub fn to_le16(x: i16) -> i16 { x }

/// Convert an i16 to little endian from the target's endianness.
///
/// On little endian, this is a no-op.  On big endian, the bytes are swapped.
#[cfg(target_endian = "big")]    #[inline] pub fn to_le16(x: i16) -> i16 { unsafe { bswap16(x) } }

/// Convert an i32 to little endian from the target's endianness.
///
/// On little endian, this is a no-op.  On big endian, the bytes are swapped.
#[cfg(target_endian = "little")] #[inline] pub fn to_le32(x: i32) -> i32 { x }

/// Convert an i32 to little endian from the target's endianness.
///
/// On little endian, this is a no-op.  On big endian, the bytes are swapped.
#[cfg(target_endian = "big")]    #[inline] pub fn to_le32(x: i32) -> i32 { unsafe { bswap32(x) } }

/// Convert an i64 to little endian from the target's endianness.
///
/// On little endian, this is a no-op.  On big endian, the bytes are swapped.
#[cfg(target_endian = "little")] #[inline] pub fn to_le64(x: i64) -> i64 { x }

/// Convert an i64 to little endian from the target's endianness.
///
/// On little endian, this is a no-op.  On big endian, the bytes are swapped.
#[cfg(target_endian = "big")]    #[inline] pub fn to_le64(x: i64) -> i64 { unsafe { bswap64(x) } }

/// Convert an i16 to big endian from the target's endianness.
///
/// On big endian, this is a no-op.  On little endian, the bytes are swapped.
#[cfg(target_endian = "little")] #[inline] pub fn to_be16(x: i16) -> i16 { unsafe { bswap16(x) } }

/// Convert an i16 to big endian from the target's endianness.
///
/// On big endian, this is a no-op.  On little endian, the bytes are swapped.
#[cfg(target_endian = "big")]    #[inline] pub fn to_be16(x: i16) -> i16 { x }

/// Convert an i32 to big endian from the target's endianness.
///
/// On big endian, this is a no-op.  On little endian, the bytes are swapped.
#[cfg(target_endian = "little")] #[inline] pub fn to_be32(x: i32) -> i32 { unsafe { bswap32(x) } }

/// Convert an i32 to big endian from the target's endianness.
///
/// On big endian, this is a no-op.  On little endian, the bytes are swapped.
#[cfg(target_endian = "big")]    #[inline] pub fn to_be32(x: i32) -> i32 { x }

/// Convert an i64 to big endian from the target's endianness.
///
/// On big endian, this is a no-op.  On little endian, the bytes are swapped.
#[cfg(target_endian = "little")] #[inline] pub fn to_be64(x: i64) -> i64 { unsafe { bswap64(x) } }

/// Convert an i64 to big endian from the target's endianness.
///
/// On big endian, this is a no-op.  On little endian, the bytes are swapped.
#[cfg(target_endian = "big")]    #[inline] pub fn to_be64(x: i64) -> i64 { x }

/// Convert an i16 from little endian to the target's endianness.
///
/// On little endian, this is a no-op.  On big endian, the bytes are swapped.
#[cfg(target_endian = "little")] #[inline] pub fn from_le16(x: i16) -> i16 { x }

/// Convert an i16 from little endian to the target's endianness.
///
/// On little endian, this is a no-op.  On big endian, the bytes are swapped.
#[cfg(target_endian = "big")]    #[inline] pub fn from_le16(x: i16) -> i16 { unsafe { bswap16(x) } }

/// Convert an i32 from little endian to the target's endianness.
///
/// On little endian, this is a no-op.  On big endian, the bytes are swapped.
#[cfg(target_endian = "little")] #[inline] pub fn from_le32(x: i32) -> i32 { x }

/// Convert an i32 from little endian to the target's endianness.
///
/// On little endian, this is a no-op.  On big endian, the bytes are swapped.
#[cfg(target_endian = "big")]    #[inline] pub fn from_le32(x: i32) -> i32 { unsafe { bswap32(x) } }

/// Convert an i64 from little endian to the target's endianness.
///
/// On little endian, this is a no-op.  On big endian, the bytes are swapped.
#[cfg(target_endian = "little")] #[inline] pub fn from_le64(x: i64) -> i64 { x }

/// Convert an i64 from little endian to the target's endianness.
///
/// On little endian, this is a no-op.  On big endian, the bytes are swapped.
#[cfg(target_endian = "big")]    #[inline] pub fn from_le64(x: i64) -> i64 { unsafe { bswap64(x) } }

/// Convert an i16 from big endian to the target's endianness.
///
/// On big endian, this is a no-op.  On little endian, the bytes are swapped.
#[cfg(target_endian = "little")] #[inline] pub fn from_be16(x: i16) -> i16 { unsafe { bswap16(x) } }

/// Convert an i16 from big endian to the target's endianness.
///
/// On big endian, this is a no-op.  On little endian, the bytes are swapped.
#[cfg(target_endian = "big")]    #[inline] pub fn from_be16(x: i16) -> i16 { x }

/// Convert an i32 from big endian to the target's endianness.
///
/// On big endian, this is a no-op.  On little endian, the bytes are swapped.
#[cfg(target_endian = "little")] #[inline] pub fn from_be32(x: i32) -> i32 { unsafe { bswap32(x) } }

/// Convert an i32 from big endian to the target's endianness.
///
/// On big endian, this is a no-op.  On little endian, the bytes are swapped.
#[cfg(target_endian = "big")]    #[inline] pub fn from_be32(x: i32) -> i32 { x }

/// Convert an i64 from big endian to the target's endianness.
///
/// On big endian, this is a no-op.  On little endian, the bytes are swapped.
#[cfg(target_endian = "little")] #[inline] pub fn from_be64(x: i64) -> i64 { unsafe { bswap64(x) } }

/// Convert an i64 from big endian to the target's endianness.
///
/// On big endian, this is a no-op.  On little endian, the bytes are swapped.
#[cfg(target_endian = "big")]    #[inline] pub fn from_be64(x: i64) -> i64 { x }

/**
 * Swap the values at two mutable locations of the same type, without
 * deinitialising or copying either one.
 */
#[inline]
pub fn swap<T>(x: &mut T, y: &mut T) {
    unsafe {
        // Give ourselves some scratch space to work with
        let mut t: T = uninit();

        // Perform the swap, `&mut` pointers never alias
        ptr::copy_nonoverlapping_memory(&mut t, &*x, 1);
        ptr::copy_nonoverlapping_memory(x, &*y, 1);
        ptr::copy_nonoverlapping_memory(y, &t, 1);

        // y and t now point to the same thing, but we need to completely forget `tmp`
        // because it's no longer relevant.
        cast::forget(t);
    }
}

/**
 * Replace the value at a mutable location with a new one, returning the old
 * value, without deinitialising or copying either one.
 */
#[inline]
pub fn replace<T>(dest: &mut T, mut src: T) -> T {
    swap(dest, &mut src);
    src
}

/// Disposes of a value.
#[inline]
pub fn drop<T>(_x: T) { }

#[cfg(test)]
mod tests {
    use mem::*;
    use option::{Some,None};

    #[test]
    fn size_of_basic() {
        assert_eq!(size_of::<u8>(), 1u);
        assert_eq!(size_of::<u16>(), 2u);
        assert_eq!(size_of::<u32>(), 4u);
        assert_eq!(size_of::<u64>(), 8u);
    }

    #[test]
    #[cfg(target_arch = "x86")]
    #[cfg(target_arch = "arm")]
    #[cfg(target_arch = "mips")]
    fn size_of_32() {
        assert_eq!(size_of::<uint>(), 4u);
        assert_eq!(size_of::<*uint>(), 4u);
    }

    #[test]
    #[cfg(target_arch = "x86_64")]
    fn size_of_64() {
        assert_eq!(size_of::<uint>(), 8u);
        assert_eq!(size_of::<*uint>(), 8u);
    }

    #[test]
    fn size_of_val_basic() {
        assert_eq!(size_of_val(&1u8), 1);
        assert_eq!(size_of_val(&1u16), 2);
        assert_eq!(size_of_val(&1u32), 4);
        assert_eq!(size_of_val(&1u64), 8);
    }

    #[test]
    fn nonzero_size_of_basic() {
        type Z = [i8, ..0];
        assert_eq!(size_of::<Z>(), 0u);
        assert_eq!(nonzero_size_of::<Z>(), 1u);
        assert_eq!(nonzero_size_of::<uint>(), size_of::<uint>());
    }

    #[test]
    fn nonzero_size_of_val_basic() {
        let z = [0u8, ..0];
        assert_eq!(size_of_val(&z), 0u);
        assert_eq!(nonzero_size_of_val(&z), 1u);
        assert_eq!(nonzero_size_of_val(&1u), size_of_val(&1u));
    }

    #[test]
    fn align_of_basic() {
        assert_eq!(pref_align_of::<u8>(), 1u);
        assert_eq!(pref_align_of::<u16>(), 2u);
        assert_eq!(pref_align_of::<u32>(), 4u);
    }

    #[test]
    #[cfg(target_arch = "x86")]
    #[cfg(target_arch = "arm")]
    #[cfg(target_arch = "mips")]
    fn align_of_32() {
        assert_eq!(pref_align_of::<uint>(), 4u);
        assert_eq!(pref_align_of::<*uint>(), 4u);
    }

    #[test]
    #[cfg(target_arch = "x86_64")]
    fn align_of_64() {
        assert_eq!(pref_align_of::<uint>(), 8u);
        assert_eq!(pref_align_of::<*uint>(), 8u);
    }

    #[test]
    fn align_of_val_basic() {
        assert_eq!(pref_align_of_val(&1u8), 1u);
        assert_eq!(pref_align_of_val(&1u16), 2u);
        assert_eq!(pref_align_of_val(&1u32), 4u);
    }

    #[test]
    fn test_swap() {
        let mut x = 31337;
        let mut y = 42;
        swap(&mut x, &mut y);
        assert_eq!(x, 42);
        assert_eq!(y, 31337);
    }

    #[test]
    fn test_replace() {
        let mut x = Some(~"test");
        let y = replace(&mut x, None);
        assert!(x.is_none());
        assert!(y.is_some());
    }
}

/// Completely miscellaneous language-construct benchmarks.
#[cfg(test)]
mod bench {
    extern crate test;
    use self::test::BenchHarness;
    use option::{Some,None};

    // Static/dynamic method dispatch

    struct Struct {
        field: int
    }

    trait Trait {
        fn method(&self) -> int;
    }

    impl Trait for Struct {
        fn method(&self) -> int {
            self.field
        }
    }

    #[bench]
    fn trait_vtable_method_call(bh: &mut BenchHarness) {
        let s = Struct { field: 10 };
        let t = &s as &Trait;
        bh.iter(|| {
            t.method()
        });
    }

    #[bench]
    fn trait_static_method_call(bh: &mut BenchHarness) {
        let s = Struct { field: 10 };
        bh.iter(|| {
            s.method()
        });
    }

    // Overhead of various match forms

    #[bench]
    fn match_option_some(bh: &mut BenchHarness) {
        let x = Some(10);
        bh.iter(|| {
            match x {
                Some(y) => y,
                None => 11
            }
        });
    }

    #[bench]
    fn match_vec_pattern(bh: &mut BenchHarness) {
        let x = [1,2,3,4,5,6];
        bh.iter(|| {
            match x {
                [1,2,3,..] => 10,
                _ => 11
            }
        });
    }
}
<|endoftext|>


<commit_before>use libimagstore::hook::error::HookError as HE;
use libimagstore::hook::error::HookErrorKind as HEK;
use libimagstore::hook::result::HookResult;

generate_error_module!(
    generate_error_types!(GitHookError, GitHookErrorKind,
        ConfigError => "Configuration Error",
        ConfigTypeError => "Configuration value type wrong",
        RuntimeInformationSetupError => "Couldn't setup runtime information for git hook",
        RepositoryError                   => "Error while interacting with git repository",
        RepositoryBranchError             => "Error while interacting with git branch(es)",
        RepositoryBranchNameFetchingError => "Error while fetching branch name",
        RepositorySignatureFetchingError  => "Error while fetching Authors/Committers signature",
        RepositoryIndexFetchingError      => "Error while fetching Repository Index",
        RepositoryPathAddingError         => "Error while adding Path to Index",
        RepositoryTreeWritingError        => "Error while writing repository tree",
        RepositoryTreeFindingError        => "Error while finding repository tree",
        RepositoryCommitFindingError      => "Error while finding commit",
        RepositoryCommittingError         => "Error while committing",
        HeadFetchError                    => "Error while getting HEAD",
        NotOnBranch                       => "No Branch is checked out",
        MkRepo => "Repository creation error",
        MkSignature => "Error while building Signature object"
    );
);

impl GitHookError {

    pub fn inside_of<T>(self, h: HEK) -> HookResult<T> {
        Err(HE::new(h, Some(Box::new(self))))
    }

}

pub use self::error::GitHookError;
pub use self::error::GitHookErrorKind;
pub use self::error::MapErrInto;

<commit_msg>Add error kind if config is not available<commit_after>use libimagstore::hook::error::HookError as HE;
use libimagstore::hook::error::HookErrorKind as HEK;
use libimagstore::hook::result::HookResult;

generate_error_module!(
    generate_error_types!(GitHookError, GitHookErrorKind,
        ConfigError => "Configuration Error",
        NoConfigError => "No Configuration",
        ConfigTypeError => "Configuration value type wrong",
        RuntimeInformationSetupError => "Couldn't setup runtime information for git hook",
        RepositoryError                   => "Error while interacting with git repository",
        RepositoryBranchError             => "Error while interacting with git branch(es)",
        RepositoryBranchNameFetchingError => "Error while fetching branch name",
        RepositorySignatureFetchingError  => "Error while fetching Authors/Committers signature",
        RepositoryIndexFetchingError      => "Error while fetching Repository Index",
        RepositoryPathAddingError         => "Error while adding Path to Index",
        RepositoryTreeWritingError        => "Error while writing repository tree",
        RepositoryTreeFindingError        => "Error while finding repository tree",
        RepositoryCommitFindingError      => "Error while finding commit",
        RepositoryCommittingError         => "Error while committing",
        HeadFetchError                    => "Error while getting HEAD",
        NotOnBranch                       => "No Branch is checked out",
        MkRepo => "Repository creation error",
        MkSignature => "Error while building Signature object"
    );
);

impl GitHookError {

    pub fn inside_of<T>(self, h: HEK) -> HookResult<T> {
        Err(HE::new(h, Some(Box::new(self))))
    }

}

pub use self::error::GitHookError;
pub use self::error::GitHookErrorKind;
pub use self::error::MapErrInto;

<|endoftext|>


<commit_before>pub use super::*;

use std::collections::{HashMap, HashSet};
use std::time::Duration;

use kafka;
use kafka::producer::{Producer, RequiredAcks};
use kafka::producer::Record;
use kafka::client::{FetchOffset, PartitionOffset};
use kafka::consumer::Consumer;

use rand;
use rand::Rng;

const RANDOM_MESSAGE_SIZE: usize = 32;

pub fn test_producer() -> Producer {
    let client = new_ready_kafka_client();

    Producer::from_client(client)
        .with_ack_timeout(Duration::from_secs(1))
        .with_required_acks(RequiredAcks::All)
        .create()
        .unwrap()
}

/// This is to avoid copy/pasting the consumer's config, whether
/// the consumer is built using `from_hosts` or `from_client`.
///
/// TODO: This can go away if we don't use the builder pattern.
macro_rules! test_consumer_config {
    ( $x:expr ) => {
        $x
            .with_topic_partitions(TEST_TOPIC_NAME.to_owned(), &TEST_TOPIC_PARTITIONS)
            .with_group(TEST_GROUP_NAME.to_owned())
            .with_fallback_offset(kafka::consumer::FetchOffset::Latest)
            .with_offset_storage(kafka::consumer::GroupOffsetStorage::Kafka)
    };
}

/// Return a Consumer builder with some defaults
pub fn test_consumer_builder() -> kafka::consumer::Builder {
    test_consumer_config!(Consumer::from_client(new_ready_kafka_client()))
}

pub fn test_consumer() -> Consumer {
    test_consumer_with_client(new_ready_kafka_client())
}

/// Return a ready Kafka consumer with all default settings
pub fn test_consumer_with_client(mut client: KafkaClient) -> Consumer {
    let topics = [TEST_TOPIC_NAME, TEST_TOPIC_NAME_2];

    // Fetch the latest offsets and commit those so that this consumer
    // is always at the latest offset before being used.
    let latest_offsets = client.fetch_offsets(&topics, FetchOffset::Latest).unwrap();

    debug!("latest_offsets: {:?}", latest_offsets);

    for (topic, partition_offsets) in latest_offsets {
        for po in partition_offsets {
            if po.offset == -1 {
                continue;
            }

            client
                .commit_offset(TEST_GROUP_NAME, &topic, po.partition, po.offset)
                .unwrap();
        }
    }

    client.load_metadata_all().unwrap();
    let partition_offsets: HashSet<PartitionOffset> = client
        .fetch_group_topic_offsets(TEST_GROUP_NAME, TEST_TOPIC_NAME)
        .unwrap()
        .into_iter()
        .collect();

    debug!("partition_offsets: {:?}", partition_offsets);

    test_consumer_config!(Consumer::from_client(client))
        .create()
        .unwrap()
}

/// Send `num_messages` randomly-generated messages to the given topic with
/// the given producer.
fn send_random_messages(producer: &mut Producer, topic: &str, num_messages: u32) {
    let mut random_message_buf = [0u8; RANDOM_MESSAGE_SIZE];
    let mut rng = rand::thread_rng();

    for _ in 0..num_messages {
        rng.fill_bytes(&mut random_message_buf);
        producer
            .send(&Record::from_value(topic, &random_message_buf[..]))
            .unwrap();
    }
}

/// Fetch the committed offsets for this group and topic on the given client.
/// If the offset is -1 (i.e., there isn't an offset committed for a partition),
/// use the given optional default value in place of -1. If the default value is
/// None, -1 is kept.
pub(crate) fn get_group_offsets(
    client: &mut KafkaClient,
    group: &str,
    topic: &str,
    default_offset: Option<i64>,
) -> HashMap<i32, i64> {
    client
        .fetch_group_topic_offsets(group, topic)
        .unwrap()
        .iter()
        .map(|po| {
            let offset = if default_offset.is_some() && po.offset == -1 {
                default_offset.unwrap()
            } else {
                po.offset
            };

            (po.partition, offset)
        })
        .collect()
}

/// Given two maps that represent committed offsets at some point in time, where
/// `older` represents some earlier point in time, and `newer` represents some
/// later point in time, compute the number of messages committed between
/// `earlier` and `later`—i.e., for each partition, compute the differences
/// `newer.partition.offset` - `older.partition.offset`, and sum them up.
pub(crate) fn diff_group_offsets(older: &HashMap<i32, i64>, newer: &HashMap<i32, i64>) -> i64 {
    newer
        .iter()
        .map(|(partition, new_offset)| {
            let old_offset = older.get(partition).unwrap();
            new_offset - old_offset
        })
        .sum()
}

mod producer;
mod consumer;
<commit_msg>Added use rand::RngCore;<commit_after>pub use super::*;

use std::collections::{HashMap, HashSet};
use std::time::Duration;

use kafka;
use kafka::client::{FetchOffset, PartitionOffset};
use kafka::consumer::Consumer;
use kafka::producer::Record;
use kafka::producer::{Producer, RequiredAcks};

use rand;
use rand::Rng;
use rand::RngCore;

const RANDOM_MESSAGE_SIZE: usize = 32;

pub fn test_producer() -> Producer {
    let client = new_ready_kafka_client();

    Producer::from_client(client)
        .with_ack_timeout(Duration::from_secs(1))
        .with_required_acks(RequiredAcks::All)
        .create()
        .unwrap()
}

/// This is to avoid copy/pasting the consumer's config, whether
/// the consumer is built using `from_hosts` or `from_client`.
///
/// TODO: This can go away if we don't use the builder pattern.
macro_rules! test_consumer_config {
    ( $x:expr ) => {
        $x.with_topic_partitions(TEST_TOPIC_NAME.to_owned(), &TEST_TOPIC_PARTITIONS)
            .with_group(TEST_GROUP_NAME.to_owned())
            .with_fallback_offset(kafka::consumer::FetchOffset::Latest)
            .with_offset_storage(kafka::consumer::GroupOffsetStorage::Kafka)
    };
}

/// Return a Consumer builder with some defaults
pub fn test_consumer_builder() -> kafka::consumer::Builder {
    test_consumer_config!(Consumer::from_client(new_ready_kafka_client()))
}

pub fn test_consumer() -> Consumer {
    test_consumer_with_client(new_ready_kafka_client())
}

/// Return a ready Kafka consumer with all default settings
pub fn test_consumer_with_client(mut client: KafkaClient) -> Consumer {
    let topics = [TEST_TOPIC_NAME, TEST_TOPIC_NAME_2];

    // Fetch the latest offsets and commit those so that this consumer
    // is always at the latest offset before being used.
    let latest_offsets = client.fetch_offsets(&topics, FetchOffset::Latest).unwrap();

    debug!("latest_offsets: {:?}", latest_offsets);

    for (topic, partition_offsets) in latest_offsets {
        for po in partition_offsets {
            if po.offset == -1 {
                continue;
            }

            client
                .commit_offset(TEST_GROUP_NAME, &topic, po.partition, po.offset)
                .unwrap();
        }
    }

    client.load_metadata_all().unwrap();
    let partition_offsets: HashSet<PartitionOffset> = client
        .fetch_group_topic_offsets(TEST_GROUP_NAME, TEST_TOPIC_NAME)
        .unwrap()
        .into_iter()
        .collect();

    debug!("partition_offsets: {:?}", partition_offsets);

    test_consumer_config!(Consumer::from_client(client))
        .create()
        .unwrap()
}

/// Send `num_messages` randomly-generated messages to the given topic with
/// the given producer.
fn send_random_messages(producer: &mut Producer, topic: &str, num_messages: u32) {
    let mut random_message_buf = [0u8; RANDOM_MESSAGE_SIZE];
    let mut rng = rand::thread_rng();

    for _ in 0..num_messages {
        rng.fill_bytes(&mut random_message_buf);
        producer
            .send(&Record::from_value(topic, &random_message_buf[..]))
            .unwrap();
    }
}

/// Fetch the committed offsets for this group and topic on the given client.
/// If the offset is -1 (i.e., there isn't an offset committed for a partition),
/// use the given optional default value in place of -1. If the default value is
/// None, -1 is kept.
pub(crate) fn get_group_offsets(
    client: &mut KafkaClient,
    group: &str,
    topic: &str,
    default_offset: Option<i64>,
) -> HashMap<i32, i64> {
    client
        .fetch_group_topic_offsets(group, topic)
        .unwrap()
        .iter()
        .map(|po| {
            let offset = if default_offset.is_some() && po.offset == -1 {
                default_offset.unwrap()
            } else {
                po.offset
            };

            (po.partition, offset)
        })
        .collect()
}

/// Given two maps that represent committed offsets at some point in time, where
/// `older` represents some earlier point in time, and `newer` represents some
/// later point in time, compute the number of messages committed between
/// `earlier` and `later`—i.e., for each partition, compute the differences
/// `newer.partition.offset` - `older.partition.offset`, and sum them up.
pub(crate) fn diff_group_offsets(older: &HashMap<i32, i64>, newer: &HashMap<i32, i64>) -> i64 {
    newer
        .iter()
        .map(|(partition, new_offset)| {
            let old_offset = older.get(partition).unwrap();
            new_offset - old_offset
        })
        .sum()
}

mod consumer;
mod producer;
<|endoftext|>


<commit_before>//! Standard library macros
//!
//! This module contains a set of macros which are exported from the standard
//! library. Each macro is available for use when linking against the standard
//! library.

#[doc = include_str!("../../core/src/macros/panic.md")]
#[macro_export]
#[rustc_builtin_macro = "std_panic"]
#[stable(feature = "rust1", since = "1.0.0")]
#[allow_internal_unstable(edition_panic)]
#[cfg_attr(not(test), rustc_diagnostic_item = "std_panic_macro")]
macro_rules! panic {
    // Expands to either `$crate::panic::panic_2015` or `$crate::panic::panic_2021`
    // depending on the edition of the caller.
    ($($arg:tt)*) => {
        /* compiler built-in */
    };
}

/// Prints to the standard output.
///
/// Equivalent to the [`println!`] macro except that a newline is not printed at
/// the end of the message.
///
/// Note that stdout is frequently line-buffered by default so it may be
/// necessary to use [`io::stdout().flush()`][flush] to ensure the output is emitted
/// immediately.
///
/// Use `print!` only for the primary output of your program. Use
/// [`eprint!`] instead to print error and progress messages.
///
/// [flush]: crate::io::Write::flush
///
/// # Panics
///
/// Panics if writing to `io::stdout()` fails.
///
/// # Examples
///
/// ```
/// use std::io::{self, Write};
///
/// print!("this ");
/// print!("will ");
/// print!("be ");
/// print!("on ");
/// print!("the ");
/// print!("same ");
/// print!("line ");
///
/// io::stdout().flush().unwrap();
///
/// print!("this string has a newline, why not choose println! instead?\n");
///
/// io::stdout().flush().unwrap();
/// ```
#[macro_export]
#[stable(feature = "rust1", since = "1.0.0")]
#[allow_internal_unstable(print_internals)]
macro_rules! print {
    ($($arg:tt)*) => ($crate::io::_print($crate::format_args!($($arg)*)));
}

/// Prints to the standard output, with a newline.
///
/// On all platforms, the newline is the LINE FEED character (`\n`/`U+000A`) alone
/// (no additional CARRIAGE RETURN (`\r`/`U+000D`)).
///
/// Use the [`format!`] syntax to write data to the standard output.
/// See [`std::fmt`] for more information.
///
/// Use `println!` only for the primary output of your program. Use
/// [`eprintln!`] instead to print error and progress messages.
///
/// [`std::fmt`]: crate::fmt
///
/// # Panics
///
/// Panics if writing to [`io::stdout`] fails.
///
/// [`io::stdout`]: crate::io::stdout
///
/// # Examples
///
/// ```
/// println!(); // prints just a newline
/// println!("hello there!");
/// println!("format {} arguments", "some");
/// ```
#[macro_export]
#[stable(feature = "rust1", since = "1.0.0")]
#[allow_internal_unstable(print_internals, format_args_nl)]
macro_rules! println {
    () => ($crate::print!("\n"));
    ($($arg:tt)*) => ({
        $crate::io::_print($crate::format_args_nl!($($arg)*));
    })
}

/// Prints to the standard error.
///
/// Equivalent to the [`print!`] macro, except that output goes to
/// [`io::stderr`] instead of [`io::stdout`]. See [`print!`] for
/// example usage.
///
/// Use `eprint!` only for error and progress messages. Use `print!`
/// instead for the primary output of your program.
///
/// [`io::stderr`]: crate::io::stderr
/// [`io::stdout`]: crate::io::stdout
///
/// # Panics
///
/// Panics if writing to `io::stderr` fails.
///
/// # Examples
///
/// ```
/// eprint!("Error: Could not complete task");
/// ```
#[macro_export]
#[stable(feature = "eprint", since = "1.19.0")]
#[allow_internal_unstable(print_internals)]
macro_rules! eprint {
    ($($arg:tt)*) => ($crate::io::_eprint($crate::format_args!($($arg)*)));
}

/// Prints to the standard error, with a newline.
///
/// Equivalent to the [`println!`] macro, except that output goes to
/// [`io::stderr`] instead of [`io::stdout`]. See [`println!`] for
/// example usage.
///
/// Use `eprintln!` only for error and progress messages. Use `println!`
/// instead for the primary output of your program.
///
/// [`io::stderr`]: crate::io::stderr
/// [`io::stdout`]: crate::io::stdout
///
/// # Panics
///
/// Panics if writing to `io::stderr` fails.
///
/// # Examples
///
/// ```
/// eprintln!("Error: Could not complete task");
/// ```
#[macro_export]
#[stable(feature = "eprint", since = "1.19.0")]
#[allow_internal_unstable(print_internals, format_args_nl)]
macro_rules! eprintln {
    () => ($crate::eprint!("\n"));
    ($($arg:tt)*) => ({
        $crate::io::_eprint($crate::format_args_nl!($($arg)*));
    })
}

/// Prints and returns the value of a given expression for quick and dirty
/// debugging.
///
/// An example:
///
/// ```rust
/// let a = 2;
/// let b = dbg!(a * 2) + 1;
/// //      ^-- prints: [src/main.rs:2] a * 2 = 4
/// assert_eq!(b, 5);
/// ```
///
/// The macro works by using the `Debug` implementation of the type of
/// the given expression to print the value to [stderr] along with the
/// source location of the macro invocation as well as the source code
/// of the expression.
///
/// Invoking the macro on an expression moves and takes ownership of it
/// before returning the evaluated expression unchanged. If the type
/// of the expression does not implement `Copy` and you don't want
/// to give up ownership, you can instead borrow with `dbg!(&expr)`
/// for some expression `expr`.
///
/// The `dbg!` macro works exactly the same in release builds.
/// This is useful when debugging issues that only occur in release
/// builds or when debugging in release mode is significantly faster.
///
/// Note that the macro is intended as a debugging tool and therefore you
/// should avoid having uses of it in version control for long periods.
/// Use cases involving debug output that should be added to version control
/// are better served by macros such as [`debug!`] from the [`log`] crate.
///
/// # Stability
///
/// The exact output printed by this macro should not be relied upon
/// and is subject to future changes.
///
/// # Panics
///
/// Panics if writing to `io::stderr` fails.
///
/// # Further examples
///
/// With a method call:
///
/// ```rust
/// fn foo(n: usize) {
///     if let Some(_) = dbg!(n.checked_sub(4)) {
///         // ...
///     }
/// }
///
/// foo(3)
/// ```
///
/// This prints to [stderr]:
///
/// ```text,ignore
/// [src/main.rs:4] n.checked_sub(4) = None
/// ```
///
/// Naive factorial implementation:
///
/// ```rust
/// fn factorial(n: u32) -> u32 {
///     if dbg!(n <= 1) {
///         dbg!(1)
///     } else {
///         dbg!(n * factorial(n - 1))
///     }
/// }
///
/// dbg!(factorial(4));
/// ```
///
/// This prints to [stderr]:
///
/// ```text,ignore
/// [src/main.rs:3] n <= 1 = false
/// [src/main.rs:3] n <= 1 = false
/// [src/main.rs:3] n <= 1 = false
/// [src/main.rs:3] n <= 1 = true
/// [src/main.rs:4] 1 = 1
/// [src/main.rs:5] n * factorial(n - 1) = 2
/// [src/main.rs:5] n * factorial(n - 1) = 6
/// [src/main.rs:5] n * factorial(n - 1) = 24
/// [src/main.rs:11] factorial(4) = 24
/// ```
///
/// The `dbg!(..)` macro moves the input:
///
/// ```compile_fail
/// /// A wrapper around `usize` which importantly is not Copyable.
/// #[derive(Debug)]
/// struct NoCopy(usize);
///
/// let a = NoCopy(42);
/// let _ = dbg!(a); // <-- `a` is moved here.
/// let _ = dbg!(a); // <-- `a` is moved again; error!
/// ```
///
/// You can also use `dbg!()` without a value to just print the
/// file and line whenever it's reached.
///
/// Finally, if you want to `dbg!(..)` multiple values, it will treat them as
/// a tuple (and return it, too):
///
/// ```
/// assert_eq!(dbg!(1usize, 2u32), (1, 2));
/// ```
///
/// However, a single argument with a trailing comma will still not be treated
/// as a tuple, following the convention of ignoring trailing commas in macro
/// invocations. You can use a 1-tuple directly if you need one:
///
/// ```
/// assert_eq!(1, dbg!(1u32,)); // trailing comma ignored
/// assert_eq!((1,), dbg!((1u32,))); // 1-tuple
/// ```
///
/// [stderr]: https://en.wikipedia.org/wiki/Standard_streams#Standard_error_(stderr)
/// [`debug!`]: https://docs.rs/log/*/log/macro.debug.html
/// [`log`]: https://crates.io/crates/log
#[macro_export]
#[stable(feature = "dbg_macro", since = "1.32.0")]
macro_rules! dbg {
    // NOTE: We cannot use `concat!` to make a static string as a format argument
    // of `eprintln!` because `file!` could contain a `{` or
    // `$val` expression could be a block (`{ .. }`), in which case the `eprintln!`
    // will be malformed.
    () => {
        $crate::eprintln!("[{}:{}]", $crate::file!(), $crate::line!());
    };
    ($val:expr $(,)?) => {
        // Use of `match` here is intentional because it affects the lifetimes
        // of temporaries - https://stackoverflow.com/a/48732525/1063961
        match $val {
            tmp => {
                $crate::eprintln!("[{}:{}] {} = {:#?}",
                    $crate::file!(), $crate::line!(), $crate::stringify!($val), &tmp);
                tmp
            }
        }
    };
    ($($val:expr),+ $(,)?) => {
        ($($crate::dbg!($val)),+,)
    };
}

#[cfg(test)]
macro_rules! assert_approx_eq {
    ($a:expr, $b:expr) => {{
        let (a, b) = (&$a, &$b);
        assert!((*a - *b).abs() < 1.0e-6, "{} is not approximately equal to {}", *a, *b);
    }};
}
<commit_msg>dbg macro: Discuss use in tests, and slightly clarify<commit_after>//! Standard library macros
//!
//! This module contains a set of macros which are exported from the standard
//! library. Each macro is available for use when linking against the standard
//! library.

#[doc = include_str!("../../core/src/macros/panic.md")]
#[macro_export]
#[rustc_builtin_macro = "std_panic"]
#[stable(feature = "rust1", since = "1.0.0")]
#[allow_internal_unstable(edition_panic)]
#[cfg_attr(not(test), rustc_diagnostic_item = "std_panic_macro")]
macro_rules! panic {
    // Expands to either `$crate::panic::panic_2015` or `$crate::panic::panic_2021`
    // depending on the edition of the caller.
    ($($arg:tt)*) => {
        /* compiler built-in */
    };
}

/// Prints to the standard output.
///
/// Equivalent to the [`println!`] macro except that a newline is not printed at
/// the end of the message.
///
/// Note that stdout is frequently line-buffered by default so it may be
/// necessary to use [`io::stdout().flush()`][flush] to ensure the output is emitted
/// immediately.
///
/// Use `print!` only for the primary output of your program. Use
/// [`eprint!`] instead to print error and progress messages.
///
/// [flush]: crate::io::Write::flush
///
/// # Panics
///
/// Panics if writing to `io::stdout()` fails.
///
/// # Examples
///
/// ```
/// use std::io::{self, Write};
///
/// print!("this ");
/// print!("will ");
/// print!("be ");
/// print!("on ");
/// print!("the ");
/// print!("same ");
/// print!("line ");
///
/// io::stdout().flush().unwrap();
///
/// print!("this string has a newline, why not choose println! instead?\n");
///
/// io::stdout().flush().unwrap();
/// ```
#[macro_export]
#[stable(feature = "rust1", since = "1.0.0")]
#[allow_internal_unstable(print_internals)]
macro_rules! print {
    ($($arg:tt)*) => ($crate::io::_print($crate::format_args!($($arg)*)));
}

/// Prints to the standard output, with a newline.
///
/// On all platforms, the newline is the LINE FEED character (`\n`/`U+000A`) alone
/// (no additional CARRIAGE RETURN (`\r`/`U+000D`)).
///
/// Use the [`format!`] syntax to write data to the standard output.
/// See [`std::fmt`] for more information.
///
/// Use `println!` only for the primary output of your program. Use
/// [`eprintln!`] instead to print error and progress messages.
///
/// [`std::fmt`]: crate::fmt
///
/// # Panics
///
/// Panics if writing to [`io::stdout`] fails.
///
/// [`io::stdout`]: crate::io::stdout
///
/// # Examples
///
/// ```
/// println!(); // prints just a newline
/// println!("hello there!");
/// println!("format {} arguments", "some");
/// ```
#[macro_export]
#[stable(feature = "rust1", since = "1.0.0")]
#[allow_internal_unstable(print_internals, format_args_nl)]
macro_rules! println {
    () => ($crate::print!("\n"));
    ($($arg:tt)*) => ({
        $crate::io::_print($crate::format_args_nl!($($arg)*));
    })
}

/// Prints to the standard error.
///
/// Equivalent to the [`print!`] macro, except that output goes to
/// [`io::stderr`] instead of [`io::stdout`]. See [`print!`] for
/// example usage.
///
/// Use `eprint!` only for error and progress messages. Use `print!`
/// instead for the primary output of your program.
///
/// [`io::stderr`]: crate::io::stderr
/// [`io::stdout`]: crate::io::stdout
///
/// # Panics
///
/// Panics if writing to `io::stderr` fails.
///
/// # Examples
///
/// ```
/// eprint!("Error: Could not complete task");
/// ```
#[macro_export]
#[stable(feature = "eprint", since = "1.19.0")]
#[allow_internal_unstable(print_internals)]
macro_rules! eprint {
    ($($arg:tt)*) => ($crate::io::_eprint($crate::format_args!($($arg)*)));
}

/// Prints to the standard error, with a newline.
///
/// Equivalent to the [`println!`] macro, except that output goes to
/// [`io::stderr`] instead of [`io::stdout`]. See [`println!`] for
/// example usage.
///
/// Use `eprintln!` only for error and progress messages. Use `println!`
/// instead for the primary output of your program.
///
/// [`io::stderr`]: crate::io::stderr
/// [`io::stdout`]: crate::io::stdout
///
/// # Panics
///
/// Panics if writing to `io::stderr` fails.
///
/// # Examples
///
/// ```
/// eprintln!("Error: Could not complete task");
/// ```
#[macro_export]
#[stable(feature = "eprint", since = "1.19.0")]
#[allow_internal_unstable(print_internals, format_args_nl)]
macro_rules! eprintln {
    () => ($crate::eprint!("\n"));
    ($($arg:tt)*) => ({
        $crate::io::_eprint($crate::format_args_nl!($($arg)*));
    })
}

/// Prints and returns the value of a given expression for quick and dirty
/// debugging.
///
/// An example:
///
/// ```rust
/// let a = 2;
/// let b = dbg!(a * 2) + 1;
/// //      ^-- prints: [src/main.rs:2] a * 2 = 4
/// assert_eq!(b, 5);
/// ```
///
/// The macro works by using the `Debug` implementation of the type of
/// the given expression to print the value to [stderr] along with the
/// source location of the macro invocation as well as the source code
/// of the expression.
///
/// Invoking the macro on an expression moves and takes ownership of it
/// before returning the evaluated expression unchanged. If the type
/// of the expression does not implement `Copy` and you don't want
/// to give up ownership, you can instead borrow with `dbg!(&expr)`
/// for some expression `expr`.
///
/// The `dbg!` macro works exactly the same in release builds.
/// This is useful when debugging issues that only occur in release
/// builds or when debugging in release mode is significantly faster.
///
/// Note that the macro is intended as a debugging tool and therefore you
/// should avoid having uses of it in version control for long periods
/// (other than in tests etc.)
/// Debug output from production code is better done with other facilities
/// such as the [`debug!`] macro from the [`log`] crate.
///
/// # Stability
///
/// The exact output printed by this macro should not be relied upon
/// and is subject to future changes.
///
/// # Panics
///
/// Panics if writing to `io::stderr` fails.
///
/// # Further examples
///
/// With a method call:
///
/// ```rust
/// fn foo(n: usize) {
///     if let Some(_) = dbg!(n.checked_sub(4)) {
///         // ...
///     }
/// }
///
/// foo(3)
/// ```
///
/// This prints to [stderr]:
///
/// ```text,ignore
/// [src/main.rs:4] n.checked_sub(4) = None
/// ```
///
/// Naive factorial implementation:
///
/// ```rust
/// fn factorial(n: u32) -> u32 {
///     if dbg!(n <= 1) {
///         dbg!(1)
///     } else {
///         dbg!(n * factorial(n - 1))
///     }
/// }
///
/// dbg!(factorial(4));
/// ```
///
/// This prints to [stderr]:
///
/// ```text,ignore
/// [src/main.rs:3] n <= 1 = false
/// [src/main.rs:3] n <= 1 = false
/// [src/main.rs:3] n <= 1 = false
/// [src/main.rs:3] n <= 1 = true
/// [src/main.rs:4] 1 = 1
/// [src/main.rs:5] n * factorial(n - 1) = 2
/// [src/main.rs:5] n * factorial(n - 1) = 6
/// [src/main.rs:5] n * factorial(n - 1) = 24
/// [src/main.rs:11] factorial(4) = 24
/// ```
///
/// The `dbg!(..)` macro moves the input:
///
/// ```compile_fail
/// /// A wrapper around `usize` which importantly is not Copyable.
/// #[derive(Debug)]
/// struct NoCopy(usize);
///
/// let a = NoCopy(42);
/// let _ = dbg!(a); // <-- `a` is moved here.
/// let _ = dbg!(a); // <-- `a` is moved again; error!
/// ```
///
/// You can also use `dbg!()` without a value to just print the
/// file and line whenever it's reached.
///
/// Finally, if you want to `dbg!(..)` multiple values, it will treat them as
/// a tuple (and return it, too):
///
/// ```
/// assert_eq!(dbg!(1usize, 2u32), (1, 2));
/// ```
///
/// However, a single argument with a trailing comma will still not be treated
/// as a tuple, following the convention of ignoring trailing commas in macro
/// invocations. You can use a 1-tuple directly if you need one:
///
/// ```
/// assert_eq!(1, dbg!(1u32,)); // trailing comma ignored
/// assert_eq!((1,), dbg!((1u32,))); // 1-tuple
/// ```
///
/// [stderr]: https://en.wikipedia.org/wiki/Standard_streams#Standard_error_(stderr)
/// [`debug!`]: https://docs.rs/log/*/log/macro.debug.html
/// [`log`]: https://crates.io/crates/log
#[macro_export]
#[stable(feature = "dbg_macro", since = "1.32.0")]
macro_rules! dbg {
    // NOTE: We cannot use `concat!` to make a static string as a format argument
    // of `eprintln!` because `file!` could contain a `{` or
    // `$val` expression could be a block (`{ .. }`), in which case the `eprintln!`
    // will be malformed.
    () => {
        $crate::eprintln!("[{}:{}]", $crate::file!(), $crate::line!());
    };
    ($val:expr $(,)?) => {
        // Use of `match` here is intentional because it affects the lifetimes
        // of temporaries - https://stackoverflow.com/a/48732525/1063961
        match $val {
            tmp => {
                $crate::eprintln!("[{}:{}] {} = {:#?}",
                    $crate::file!(), $crate::line!(), $crate::stringify!($val), &tmp);
                tmp
            }
        }
    };
    ($($val:expr),+ $(,)?) => {
        ($($crate::dbg!($val)),+,)
    };
}

#[cfg(test)]
macro_rules! assert_approx_eq {
    ($a:expr, $b:expr) => {{
        let (a, b) = (&$a, &$b);
        assert!((*a - *b).abs() < 1.0e-6, "{} is not approximately equal to {}", *a, *b);
    }};
}
<|endoftext|>


<commit_before>use std::fmt::Display;

use ide_db::{helpers::FamousDefs, RootDatabase};
use syntax::{
    ast::{self, NameOwner},
    AstNode, SyntaxNode,
};

use crate::{
    assist_context::{AssistBuilder, AssistContext, Assists},
    utils::generate_trait_impl_text,
    AssistId, AssistKind,
};

// Assist: generate_deref
//
// Generate `Deref` impl using the given struct field.
//
// ```
// struct A;
// struct B {
//    $0a: A
// }
// ```
// ->
// ```
// struct A;
// struct B {
//    a: A
// }
//
// impl std::ops::Deref for B {
//     type Target = A;
//
//     fn deref(&self) -> &Self::Target {
//         &self.a
//     }
// }
// ```
pub(crate) fn generate_deref(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
    generate_record_deref(acc, ctx).or_else(|| generate_tuple_deref(acc, ctx))
}

fn generate_record_deref(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
    let strukt = ctx.find_node_at_offset::<ast::Struct>()?;
    let field = ctx.find_node_at_offset::<ast::RecordField>()?;

    if existing_deref_impl(&ctx.sema, &strukt).is_some() {
        cov_mark::hit!(test_add_record_deref_impl_already_exists);
        return None;
    }

    let field_type = field.ty()?;
    let field_name = field.name()?;
    let target = field.syntax().text_range();
    acc.add(
        AssistId("generate_deref", AssistKind::Generate),
        format!("Generate `Deref` impl using `{}`", field_name),
        target,
        |edit| generate_edit(edit, strukt, field_type.syntax(), field_name.syntax()),
    )
}

fn generate_tuple_deref(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
    let strukt = ctx.find_node_at_offset::<ast::Struct>()?;
    let field = ctx.find_node_at_offset::<ast::TupleField>()?;
    let field_list = ctx.find_node_at_offset::<ast::TupleFieldList>()?;
    let field_list_index =
        field_list.syntax().children().into_iter().position(|s| &s == field.syntax())?;

    if existing_deref_impl(&ctx.sema, &strukt).is_some() {
        cov_mark::hit!(test_add_field_deref_impl_already_exists);
        return None;
    }

    let field_type = field.ty()?;
    let target = field.syntax().text_range();
    acc.add(
        AssistId("generate_deref", AssistKind::Generate),
        format!("Generate `Deref` impl using `{}`", field.syntax()),
        target,
        |edit| generate_edit(edit, strukt, field_type.syntax(), field_list_index),
    )
}

fn generate_edit(
    edit: &mut AssistBuilder,
    strukt: ast::Struct,
    field_type_syntax: &SyntaxNode,
    field_name: impl Display,
) {
    let start_offset = strukt.syntax().text_range().end();
    let impl_code = format!(
        r#"    type Target = {0};

    fn deref(&self) -> &Self::Target {{
        &self.{1}
    }}"#,
        field_type_syntax, field_name
    );
    let strukt_adt = ast::Adt::Struct(strukt);
    let deref_impl = generate_trait_impl_text(&strukt_adt, "std::ops::Deref", &impl_code);
    edit.insert(start_offset, deref_impl);
}

fn existing_deref_impl(
    sema: &'_ hir::Semantics<'_, RootDatabase>,
    strukt: &ast::Struct,
) -> Option<()> {
    let strukt = sema.to_def(strukt)?;
    let krate = strukt.module(sema.db).krate();

    let deref_trait = FamousDefs(sema, Some(krate)).core_ops_Deref()?;
    let strukt_type = strukt.ty(sema.db);

    if strukt_type.impls_trait(sema.db, deref_trait, &[]) {
        Some(())
    } else {
        None
    }
}

#[cfg(test)]
mod tests {
    use crate::tests::{check_assist, check_assist_not_applicable};

    use super::*;

    #[test]
    fn test_generate_record_deref() {
        check_assist(
            generate_deref,
            r#"struct A { }
struct B { $0a: A }"#,
            r#"struct A { }
struct B { a: A }

impl std::ops::Deref for B {
    type Target = A;

    fn deref(&self) -> &Self::Target {
        &self.a
    }
}"#,
        );
    }

    #[test]
    fn test_generate_field_deref_idx_0() {
        check_assist(
            generate_deref,
            r#"struct A { }
struct B($0A);"#,
            r#"struct A { }
struct B(A);

impl std::ops::Deref for B {
    type Target = A;

    fn deref(&self) -> &Self::Target {
        &self.0
    }
}"#,
        );
    }
    #[test]
    fn test_generate_field_deref_idx_1() {
        check_assist(
            generate_deref,
            r#"struct A { }
struct B(u8, $0A);"#,
            r#"struct A { }
struct B(u8, A);

impl std::ops::Deref for B {
    type Target = A;

    fn deref(&self) -> &Self::Target {
        &self.1
    }
}"#,
        );
    }

    fn check_not_applicable(ra_fixture: &str) {
        let fixture = format!(
            "//- /main.rs crate:main deps:core,std\n{}\n{}",
            ra_fixture,
            FamousDefs::FIXTURE
        );
        check_assist_not_applicable(generate_deref, &fixture)
    }

    #[test]
    fn test_generate_record_deref_not_applicable_if_already_impl() {
        cov_mark::check!(test_add_record_deref_impl_already_exists);
        check_not_applicable(
            r#"struct A { }
struct B { $0a: A }

impl std::ops::Deref for B {
    type Target = A;

    fn deref(&self) -> &Self::Target {
        &self.a
    }
}"#,
        )
    }

    #[test]
    fn test_generate_field_deref_not_applicable_if_already_impl() {
        cov_mark::check!(test_add_field_deref_impl_already_exists);
        check_not_applicable(
            r#"struct A { }
struct B($0A)

impl std::ops::Deref for B {
    type Target = A;

    fn deref(&self) -> &Self::Target {
        &self.0
    }
}"#,
        )
    }
}
<commit_msg>internal: switch some tests to minicore<commit_after>use std::fmt::Display;

use ide_db::{helpers::FamousDefs, RootDatabase};
use syntax::{
    ast::{self, NameOwner},
    AstNode, SyntaxNode,
};

use crate::{
    assist_context::{AssistBuilder, AssistContext, Assists},
    utils::generate_trait_impl_text,
    AssistId, AssistKind,
};

// Assist: generate_deref
//
// Generate `Deref` impl using the given struct field.
//
// ```
// struct A;
// struct B {
//    $0a: A
// }
// ```
// ->
// ```
// struct A;
// struct B {
//    a: A
// }
//
// impl std::ops::Deref for B {
//     type Target = A;
//
//     fn deref(&self) -> &Self::Target {
//         &self.a
//     }
// }
// ```
pub(crate) fn generate_deref(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
    generate_record_deref(acc, ctx).or_else(|| generate_tuple_deref(acc, ctx))
}

fn generate_record_deref(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
    let strukt = ctx.find_node_at_offset::<ast::Struct>()?;
    let field = ctx.find_node_at_offset::<ast::RecordField>()?;

    if existing_deref_impl(&ctx.sema, &strukt).is_some() {
        cov_mark::hit!(test_add_record_deref_impl_already_exists);
        return None;
    }

    let field_type = field.ty()?;
    let field_name = field.name()?;
    let target = field.syntax().text_range();
    acc.add(
        AssistId("generate_deref", AssistKind::Generate),
        format!("Generate `Deref` impl using `{}`", field_name),
        target,
        |edit| generate_edit(edit, strukt, field_type.syntax(), field_name.syntax()),
    )
}

fn generate_tuple_deref(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
    let strukt = ctx.find_node_at_offset::<ast::Struct>()?;
    let field = ctx.find_node_at_offset::<ast::TupleField>()?;
    let field_list = ctx.find_node_at_offset::<ast::TupleFieldList>()?;
    let field_list_index =
        field_list.syntax().children().into_iter().position(|s| &s == field.syntax())?;

    if existing_deref_impl(&ctx.sema, &strukt).is_some() {
        cov_mark::hit!(test_add_field_deref_impl_already_exists);
        return None;
    }

    let field_type = field.ty()?;
    let target = field.syntax().text_range();
    acc.add(
        AssistId("generate_deref", AssistKind::Generate),
        format!("Generate `Deref` impl using `{}`", field.syntax()),
        target,
        |edit| generate_edit(edit, strukt, field_type.syntax(), field_list_index),
    )
}

fn generate_edit(
    edit: &mut AssistBuilder,
    strukt: ast::Struct,
    field_type_syntax: &SyntaxNode,
    field_name: impl Display,
) {
    let start_offset = strukt.syntax().text_range().end();
    let impl_code = format!(
        r#"    type Target = {0};

    fn deref(&self) -> &Self::Target {{
        &self.{1}
    }}"#,
        field_type_syntax, field_name
    );
    let strukt_adt = ast::Adt::Struct(strukt);
    let deref_impl = generate_trait_impl_text(&strukt_adt, "std::ops::Deref", &impl_code);
    edit.insert(start_offset, deref_impl);
}

fn existing_deref_impl(
    sema: &'_ hir::Semantics<'_, RootDatabase>,
    strukt: &ast::Struct,
) -> Option<()> {
    let strukt = sema.to_def(strukt)?;
    let krate = strukt.module(sema.db).krate();

    let deref_trait = FamousDefs(sema, Some(krate)).core_ops_Deref()?;
    let strukt_type = strukt.ty(sema.db);

    if strukt_type.impls_trait(sema.db, deref_trait, &[]) {
        Some(())
    } else {
        None
    }
}

#[cfg(test)]
mod tests {
    use crate::tests::{check_assist, check_assist_not_applicable};

    use super::*;

    #[test]
    fn test_generate_record_deref() {
        check_assist(
            generate_deref,
            r#"struct A { }
struct B { $0a: A }"#,
            r#"struct A { }
struct B { a: A }

impl std::ops::Deref for B {
    type Target = A;

    fn deref(&self) -> &Self::Target {
        &self.a
    }
}"#,
        );
    }

    #[test]
    fn test_generate_field_deref_idx_0() {
        check_assist(
            generate_deref,
            r#"struct A { }
struct B($0A);"#,
            r#"struct A { }
struct B(A);

impl std::ops::Deref for B {
    type Target = A;

    fn deref(&self) -> &Self::Target {
        &self.0
    }
}"#,
        );
    }
    #[test]
    fn test_generate_field_deref_idx_1() {
        check_assist(
            generate_deref,
            r#"struct A { }
struct B(u8, $0A);"#,
            r#"struct A { }
struct B(u8, A);

impl std::ops::Deref for B {
    type Target = A;

    fn deref(&self) -> &Self::Target {
        &self.1
    }
}"#,
        );
    }

    #[test]
    fn test_generate_record_deref_not_applicable_if_already_impl() {
        cov_mark::check!(test_add_record_deref_impl_already_exists);
        check_assist_not_applicable(
            generate_deref,
            r#"
//- minicore: deref
struct A { }
struct B { $0a: A }

impl core::ops::Deref for B {
    type Target = A;

    fn deref(&self) -> &Self::Target {
        &self.a
    }
}"#,
        )
    }

    #[test]
    fn test_generate_field_deref_not_applicable_if_already_impl() {
        cov_mark::check!(test_add_field_deref_impl_already_exists);
        check_assist_not_applicable(
            generate_deref,
            r#"
//- minicore: deref
struct A { }
struct B($0A)

impl core::ops::Deref for B {
    type Target = A;

    fn deref(&self) -> &Self::Target {
        &self.0
    }
}"#,
        )
    }
}
<|endoftext|>


<commit_before>use clippy_utils::diagnostics::span_lint_and_help;
use rustc_ast::Attribute;
use rustc_hir::{Item, ItemKind};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::dep_graph::DepContext;
use rustc_middle::ty::Const;
use rustc_session::{declare_lint_pass, declare_tool_lint};

declare_clippy_lint! {
    /// ### What it does
    /// Displays a warning when a struct with a trailing zero-sized array is declared without a `repr` attribute.
    ///
    /// ### Why is this bad?
    /// Zero-sized arrays aren't very useful in Rust itself, so such a struct is likely being created to pass to C code or in some other situation where control over memory layout matters (for example, in conjuction with manual allocation to make it easy to compute the offset of the array). Either way, `#[repr(C)]` (or another `repr` attribute) is needed.
    ///
    /// ### Example
    /// ```rust
    /// struct RarelyUseful {
    ///     some_field: usize,
    ///     last: [SomeType; 0],
    /// }
    /// ```
    ///
    /// Use instead:
    /// ```rust
    /// #[repr(C)]
    /// struct MoreOftenUseful {
    ///     some_field: usize,
    ///     last: [SomeType; 0],
    /// }
    /// ```
    pub TRAILING_ZERO_SIZED_ARRAY_WITHOUT_REPR,
    nursery,
    "struct with a trailing zero-sized array but without `repr(C)` or another `repr` attribute"
}
declare_lint_pass!(TrailingZeroSizedArrayWithoutRepr => [TRAILING_ZERO_SIZED_ARRAY_WITHOUT_REPR]);

impl<'tcx> LateLintPass<'tcx> for TrailingZeroSizedArrayWithoutRepr {
    fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) {
        if is_struct_with_trailing_zero_sized_array(cx, item) {
            // NOTE: This is to include attributes on the definition when we print the lint. If the convention
            // is to not do that with struct definitions (I'm not sure), then this isn't necessary. (note: if
            // you don't get rid of this, change `has_repr_attr` to `includes_repr_attr`).
            let attrs = cx.tcx.get_attrs(item.def_id.to_def_id());
            let first_attr = attrs.iter().min_by_key(|attr| attr.span.lo());
            let lint_span = if let Some(first_attr) = first_attr {
                first_attr.span.to(item.span)
            } else {
                item.span
            };

            if !has_repr_attr(cx, attrs) {
                span_lint_and_help(
                    cx,
                    TRAILING_ZERO_SIZED_ARRAY_WITHOUT_REPR,
                    lint_span,
                    "trailing zero-sized array in a struct which is not marked `#[repr(C)]`",
                    None,
                    "consider annotating the struct definition with `#[repr(C)]` (or another `repr` attribute)",
                );
            }
        }
    }
}

fn is_struct_with_trailing_zero_sized_array(cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) -> bool {
    // TODO: when finalized, replace with an `if_chain`. I have it like this because my rust-analyzer
    // doesn't work when it's an `if_chain`.

    // First check if last field is an array
    if let ItemKind::Struct(data, _) = &item.kind {
        if let Some(last_field) = data.fields().last() {
            if let rustc_hir::TyKind::Array(_, length) = last_field.ty.kind {
                // Then check if that that array zero-sized
                let length_ldid = cx.tcx.hir().local_def_id(length.hir_id);
                let length = Const::from_anon_const(cx.tcx, length_ldid);
                let length = length.try_eval_usize(cx.tcx, cx.param_env);
                length == Some(0)
            } else {
                false
            }
        } else {
            false
        }
    } else {
        false
    }
}

fn has_repr_attr(cx: &LateContext<'tcx>, attrs: &[Attribute]) -> bool {
    // NOTE: there's at least four other ways to do this but I liked this one the best. (All five agreed
    // on all testcases (when i wrote this comment. I added a few since then).) Happy to use another;
    // they're in the commit history if you want to look (or I can go find them).
    attrs
        .iter()
        .any(|attr| !rustc_attr::find_repr_attrs(cx.tcx.sess(), attr).is_empty())
}
<commit_msg>Improve doc and span messages<commit_after>use clippy_utils::diagnostics::span_lint_and_help;
use rustc_ast::Attribute;
use rustc_hir::{Item, ItemKind};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::dep_graph::DepContext;
use rustc_middle::ty::Const;
use rustc_session::{declare_lint_pass, declare_tool_lint};

declare_clippy_lint! {
    /// ### What it does
    /// Displays a warning when a struct with a trailing zero-sized array is declared without a `repr` attribute.
    ///
    /// ### Why is this bad?
    /// Zero-sized arrays aren't very useful in Rust itself, so such a struct is likely being created to pass to C code or in some other situation where control over memory layout matters (for example, in conjuction with manual allocation to make it easy to compute the offset of the array). Either way, `#[repr(C)]` (or another `repr` attribute) is needed.
    ///
    /// ### Example
    /// ```rust
    /// struct RarelyUseful {
    ///     some_field: usize,
    ///     last: [SomeType; 0],
    /// }
    /// ```
    ///
    /// Use instead:
    /// ```rust
    /// #[repr(C)]
    /// struct MoreOftenUseful {
    ///     some_field: usize,
    ///     last: [SomeType; 0],
    /// }
    /// ```
    pub TRAILING_ZERO_SIZED_ARRAY_WITHOUT_REPR,
    nursery,
    "struct with a trailing zero-sized array but without `#[repr(C)]` or another `repr` attribute"
}
declare_lint_pass!(TrailingZeroSizedArrayWithoutRepr => [TRAILING_ZERO_SIZED_ARRAY_WITHOUT_REPR]);

impl<'tcx> LateLintPass<'tcx> for TrailingZeroSizedArrayWithoutRepr {
    fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) {
        if is_struct_with_trailing_zero_sized_array(cx, item) {
            // NOTE: This is to include attributes on the definition when we print the lint. If the convention
            // is to not do that with struct definitions (I'm not sure), then this isn't necessary. (note: if
            // you don't get rid of this, change `has_repr_attr` to `includes_repr_attr`).
            let attrs = cx.tcx.get_attrs(item.def_id.to_def_id());
            let first_attr = attrs.iter().min_by_key(|attr| attr.span.lo());
            let lint_span = if let Some(first_attr) = first_attr {
                first_attr.span.to(item.span)
            } else {
                item.span
            };

            if !has_repr_attr(cx, attrs) {
                span_lint_and_help(
                    cx,
                    TRAILING_ZERO_SIZED_ARRAY_WITHOUT_REPR,
                    lint_span,
                    "trailing zero-sized array in a struct which is not marked with a `repr` attribute",
                    None,
                    "consider annotating the struct definition with `#[repr(C)]` or another `repr` attribute",
                );
            }
        }
    }
}

fn is_struct_with_trailing_zero_sized_array(cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) -> bool {
    // TODO: when finalized, replace with an `if_chain`. I have it like this because my rust-analyzer
    // doesn't work when it's an `if_chain`.

    // First check if last field is an array
    if let ItemKind::Struct(data, _) = &item.kind {
        if let Some(last_field) = data.fields().last() {
            if let rustc_hir::TyKind::Array(_, length) = last_field.ty.kind {
                // Then check if that that array zero-sized
                let length_ldid = cx.tcx.hir().local_def_id(length.hir_id);
                let length = Const::from_anon_const(cx.tcx, length_ldid);
                let length = length.try_eval_usize(cx.tcx, cx.param_env);
                length == Some(0)
            } else {
                false
            }
        } else {
            false
        }
    } else {
        false
    }
}

fn has_repr_attr(cx: &LateContext<'tcx>, attrs: &[Attribute]) -> bool {
    // NOTE: there's at least four other ways to do this but I liked this one the best. (All five agreed
    // on all testcases (when i wrote this comment. I added a few since then).) Happy to use another;
    // they're in the commit history if you want to look (or I can go find them).
    attrs
        .iter()
        .any(|attr| !rustc_attr::find_repr_attrs(cx.tcx.sess(), attr).is_empty())
}
<|endoftext|>


<commit_before>use rustc::hir;
use rustc::lint::*;
use utils::{span_lint_and_then, span_lint, snippet_opt, SpanlessEq, get_trait_def_id, implements_trait};
use utils::{higher, sugg};

/// **What it does:** This lint checks for `+=` operations and similar.
///
/// **Why is this bad?** Projects with many developers from languages without those operations may
/// find them unreadable and not worth their weight.
///
/// **Known problems:** Types implementing `OpAssign` don't necessarily implement `Op`.
///
/// **Example:**
/// ```rust
/// a += 1;
/// ```
declare_restriction_lint! {
    pub ASSIGN_OPS,
    "any assignment operation"
}

/// **What it does:** Check for `a = a op b` or `a = b commutative_op a` patterns.
///
/// **Why is this bad?** These can be written as the shorter `a op= b`.
///
/// **Known problems:** While forbidden by the spec, `OpAssign` traits may have implementations that differ from the regular `Op` impl.
///
/// **Example:**
///
/// ```rust
/// let mut a = 5;
/// ...
/// a = a + b;
/// ```
declare_lint! {
    pub ASSIGN_OP_PATTERN,
    Warn,
    "assigning the result of an operation on a variable to that same variable"
}

#[derive(Copy, Clone, Default)]
pub struct AssignOps;

impl LintPass for AssignOps {
    fn get_lints(&self) -> LintArray {
        lint_array!(ASSIGN_OPS, ASSIGN_OP_PATTERN)
    }
}

impl LateLintPass for AssignOps {
    fn check_expr(&mut self, cx: &LateContext, expr: &hir::Expr) {
        match expr.node {
            hir::ExprAssignOp(op, ref lhs, ref rhs) => {
                span_lint_and_then(cx, ASSIGN_OPS, expr.span, "assign operation detected", |db| {
                    let lhs = &sugg::Sugg::hir(cx, lhs, "..");
                    let rhs = &sugg::Sugg::hir(cx, rhs, "..");

                    db.span_suggestion(expr.span,
                                       "replace it with",
                                       format!("{} = {}", lhs, sugg::make_binop(higher::binop(op.node), lhs, rhs)));
                });
            }
            hir::ExprAssign(ref assignee, ref e) => {
                if let hir::ExprBinary(op, ref l, ref r) = e.node {
                    let lint = |assignee: &hir::Expr, rhs: &hir::Expr| {
                        let ty = cx.tcx.expr_ty(assignee);
                        if ty.walk_shallow().next().is_some() {
                            return; // implements_trait does not work with generics
                        }
                        let rty = cx.tcx.expr_ty(rhs);
                        if rty.walk_shallow().next().is_some() {
                            return; // implements_trait does not work with generics
                        }
                        macro_rules! ops {
                            ($op:expr, $cx:expr, $ty:expr, $rty:expr, $($trait_name:ident:$full_trait_name:ident),+) => {
                                match $op {
                                    $(hir::$full_trait_name => {
                                        let [krate, module] = ::utils::paths::OPS_MODULE;
                                        let path = [krate, module, concat!(stringify!($trait_name), "Assign")];
                                        let trait_id = if let Some(trait_id) = get_trait_def_id($cx, &path) {
                                            trait_id
                                        } else {
                                            return; // useless if the trait doesn't exist
                                        };
                                        implements_trait($cx, $ty, trait_id, vec![$rty])
                                    },)*
                                    _ => false,
                                }
                            }
                        }
                        if ops!(op.node,
                                cx,
                                ty,
                                rty,
                                Add: BiAdd,
                                Sub: BiSub,
                                Mul: BiMul,
                                Div: BiDiv,
                                Rem: BiRem,
                                And: BiAnd,
                                Or: BiOr,
                                BitAnd: BiBitAnd,
                                BitOr: BiBitOr,
                                BitXor: BiBitXor,
                                Shr: BiShr,
                                Shl: BiShl) {
                            if let (Some(snip_a), Some(snip_r)) = (snippet_opt(cx, assignee.span),
                                                                   snippet_opt(cx, rhs.span)) {
                                span_lint_and_then(cx,
                                                   ASSIGN_OP_PATTERN,
                                                   expr.span,
                                                   "manual implementation of an assign operation",
                                                   |db| {
                                                       db.span_suggestion(expr.span,
                                                                          "replace it with",
                                                                          format!("{} {}= {}", snip_a, op.node.as_str(), snip_r));
                                                   });
                            } else {
                                span_lint(cx,
                                          ASSIGN_OP_PATTERN,
                                          expr.span,
                                          "manual implementation of an assign operation");
                            }
                        }
                    };
                    // a = a op b
                    if SpanlessEq::new(cx).ignore_fn().eq_expr(assignee, l) {
                        lint(assignee, r);
                    }
                    // a = b commutative_op a
                    if SpanlessEq::new(cx).ignore_fn().eq_expr(assignee, r) {
                        match op.node {
                            hir::BiAdd | hir::BiMul | hir::BiAnd | hir::BiOr | hir::BiBitXor | hir::BiBitAnd |
                            hir::BiBitOr => {
                                lint(assignee, l);
                            }
                            _ => {}
                        }
                    }
                }
            }
            _ => {}
        }
    }
}
<commit_msg>get snippets inside the suggestions-closure<commit_after>use rustc::hir;
use rustc::lint::*;
use utils::{span_lint_and_then, snippet_opt, SpanlessEq, get_trait_def_id, implements_trait};
use utils::{higher, sugg};

/// **What it does:** This lint checks for `+=` operations and similar.
///
/// **Why is this bad?** Projects with many developers from languages without those operations may
/// find them unreadable and not worth their weight.
///
/// **Known problems:** Types implementing `OpAssign` don't necessarily implement `Op`.
///
/// **Example:**
/// ```rust
/// a += 1;
/// ```
declare_restriction_lint! {
    pub ASSIGN_OPS,
    "any assignment operation"
}

/// **What it does:** Check for `a = a op b` or `a = b commutative_op a` patterns.
///
/// **Why is this bad?** These can be written as the shorter `a op= b`.
///
/// **Known problems:** While forbidden by the spec, `OpAssign` traits may have implementations that differ from the regular `Op` impl.
///
/// **Example:**
///
/// ```rust
/// let mut a = 5;
/// ...
/// a = a + b;
/// ```
declare_lint! {
    pub ASSIGN_OP_PATTERN,
    Warn,
    "assigning the result of an operation on a variable to that same variable"
}

#[derive(Copy, Clone, Default)]
pub struct AssignOps;

impl LintPass for AssignOps {
    fn get_lints(&self) -> LintArray {
        lint_array!(ASSIGN_OPS, ASSIGN_OP_PATTERN)
    }
}

impl LateLintPass for AssignOps {
    fn check_expr(&mut self, cx: &LateContext, expr: &hir::Expr) {
        match expr.node {
            hir::ExprAssignOp(op, ref lhs, ref rhs) => {
                span_lint_and_then(cx, ASSIGN_OPS, expr.span, "assign operation detected", |db| {
                    let lhs = &sugg::Sugg::hir(cx, lhs, "..");
                    let rhs = &sugg::Sugg::hir(cx, rhs, "..");

                    db.span_suggestion(expr.span,
                                       "replace it with",
                                       format!("{} = {}", lhs, sugg::make_binop(higher::binop(op.node), lhs, rhs)));
                });
            }
            hir::ExprAssign(ref assignee, ref e) => {
                if let hir::ExprBinary(op, ref l, ref r) = e.node {
                    let lint = |assignee: &hir::Expr, rhs: &hir::Expr| {
                        let ty = cx.tcx.expr_ty(assignee);
                        if ty.walk_shallow().next().is_some() {
                            return; // implements_trait does not work with generics
                        }
                        let rty = cx.tcx.expr_ty(rhs);
                        if rty.walk_shallow().next().is_some() {
                            return; // implements_trait does not work with generics
                        }
                        macro_rules! ops {
                            ($op:expr, $cx:expr, $ty:expr, $rty:expr, $($trait_name:ident:$full_trait_name:ident),+) => {
                                match $op {
                                    $(hir::$full_trait_name => {
                                        let [krate, module] = ::utils::paths::OPS_MODULE;
                                        let path = [krate, module, concat!(stringify!($trait_name), "Assign")];
                                        let trait_id = if let Some(trait_id) = get_trait_def_id($cx, &path) {
                                            trait_id
                                        } else {
                                            return; // useless if the trait doesn't exist
                                        };
                                        implements_trait($cx, $ty, trait_id, vec![$rty])
                                    },)*
                                    _ => false,
                                }
                            }
                        }
                        if ops!(op.node,
                                cx,
                                ty,
                                rty,
                                Add: BiAdd,
                                Sub: BiSub,
                                Mul: BiMul,
                                Div: BiDiv,
                                Rem: BiRem,
                                And: BiAnd,
                                Or: BiOr,
                                BitAnd: BiBitAnd,
                                BitOr: BiBitOr,
                                BitXor: BiBitXor,
                                Shr: BiShr,
                                Shl: BiShl) {
                            span_lint_and_then(cx,
                                               ASSIGN_OP_PATTERN,
                                               expr.span,
                                               "manual implementation of an assign operation",
                                               |db| {
                                                   if let (Some(snip_a), Some(snip_r)) = (snippet_opt(cx, assignee.span),
                                                                                snippet_opt(cx, rhs.span)) {
                                                       db.span_suggestion(expr.span,
                                                                          "replace it with",
                                                                          format!("{} {}= {}", snip_a, op.node.as_str(), snip_r));
                                                   }
                                               });
                        }
                    };
                    // a = a op b
                    if SpanlessEq::new(cx).ignore_fn().eq_expr(assignee, l) {
                        lint(assignee, r);
                    }
                    // a = b commutative_op a
                    if SpanlessEq::new(cx).ignore_fn().eq_expr(assignee, r) {
                        match op.node {
                            hir::BiAdd | hir::BiMul | hir::BiAnd | hir::BiOr | hir::BiBitXor | hir::BiBitAnd |
                            hir::BiBitOr => {
                                lint(assignee, l);
                            }
                            _ => {}
                        }
                    }
                }
            }
            _ => {}
        }
    }
}
<|endoftext|>