<commit_before>//! `cpuid` intrinsics

#![cfg_attr(feature = "cargo-clippy", allow(stutter))]

use mem;

#[cfg(test)]
use stdsimd_test::assert_instr;

/// Result of the `cpuid` instruction.
#[derive(Copy, Clone, Eq, Ord, PartialEq, PartialOrd)]
#[cfg_attr(feature = "cargo-clippy", allow(stutter))]
#[stable(feature = "simd_x86", since = "1.27.0")]
pub struct CpuidResult {
    /// EAX register.
    #[stable(feature = "simd_x86", since = "1.27.0")]
    pub eax: u32,
    /// EBX register.
    #[stable(feature = "simd_x86", since = "1.27.0")]
    pub ebx: u32,
    /// ECX register.
    #[stable(feature = "simd_x86", since = "1.27.0")]
    pub ecx: u32,
    /// EDX register.
    #[stable(feature = "simd_x86", since = "1.27.0")]
    pub edx: u32,
}

/// Returns the result of the `cpuid` instruction for a given `leaf` (`EAX`)
/// and
/// `sub_leaf` (`ECX`).
///
/// The highest-supported leaf value is returned by the first tuple argument of
/// [`__get_cpuid_max(0)`](fn.__get_cpuid_max.html). For leaves containung
/// sub-leaves, the second tuple argument returns the highest-supported
/// sub-leaf
/// value.
///
/// The [CPUID Wikipedia page][wiki_cpuid] contains how to query which
/// information using the `EAX` and `ECX` registers, and the interpretation of
/// the results returned in `EAX`, `EBX`, `ECX`, and `EDX`.
///
/// The references are:
/// - [Intel 64 and IA-32 Architectures Software Developer's Manual Volume 2:
///   Instruction Set Reference, A-Z][intel64_ref].
/// - [AMD64 Architecture Programmer's Manual, Volume 3: General-Purpose and
///   System Instructions][amd64_ref].
///
/// [wiki_cpuid]: https://en.wikipedia.org/wiki/CPUID
/// [intel64_ref]: http://www.intel.de/content/dam/www/public/us/en/documents/manuals/64-ia-32-architectures-software-developer-instruction-set-reference-manual-325383.pdf
/// [amd64_ref]: http://support.amd.com/TechDocs/24594.pdf
#[inline]
#[cfg_attr(test, assert_instr(cpuid))]
#[stable(feature = "simd_x86", since = "1.27.0")]
pub unsafe fn __cpuid_count(leaf: u32, sub_leaf: u32) -> CpuidResult {
    let mut r = mem::uninitialized::<CpuidResult>();
    if cfg!(target_arch = "x86") {
        asm!("cpuid"
             : "={eax}"(r.eax), "={ebx}"(r.ebx), "={ecx}"(r.ecx), "={edx}"(r.edx)
             : "{eax}"(leaf), "{ecx}"(sub_leaf)
             : :);
    } else {
        // x86-64 uses %rbx as the base register, so preserve it.
        asm!("cpuid\n"
             : "={eax}"(r.eax), "={ebx}"(r.ebx), "={ecx}"(r.ecx), "={edx}"(r.edx)
             : "{eax}"(leaf), "{ecx}"(sub_leaf)
             : "rbx" :);
    }
    r
}

/// See [`__cpuid_count`](fn.__cpuid_count.html).
#[inline]
#[cfg_attr(test, assert_instr(cpuid))]
#[stable(feature = "simd_x86", since = "1.27.0")]
pub unsafe fn __cpuid(leaf: u32) -> CpuidResult {
    __cpuid_count(leaf, 0)
}

/// Does the host support the `cpuid` instruction?
#[inline]
pub fn has_cpuid() -> bool {
    #[cfg(target_arch = "x86_64")]
    {
        true
    }
    #[cfg(target_arch = "x86")]
    {
        unsafe {
            // On `x86` the `cpuid` instruction is not always available.
            // This follows the approach indicated in:
            // http://wiki.osdev.org/CPUID#Checking_CPUID_availability
            // https://software.intel.com/en-us/articles/using-cpuid-to-detect-the-presence-of-sse-41-and-sse-42-instruction-sets/
            // which detects whether `cpuid` is available by checking whether the 21st bit of the EFLAGS register is modifiable or not.
            // If it is, then `cpuid` is available.
            let result: u32;
            let _temp: u32;
            asm!(r#"
                 # Read eflags into $0 and copy it into $1:
                 pushfd
                 pop     $0
                 mov     $1, $0
                 # Flip 21st bit of $0.
                 xor     $0, 0x200000
                 # Set eflags to the value of $0
                 #
                 # Bit 21st can only be modified if cpuid is available
                 push    $0
                 popfd          # A
                 # Read eflags into $0:
                 pushfd         # B
                 pop     $0
                 # xor with the original eflags sets the bits that
                 # have been modified:
                 xor     $0, $1
                 "#
                 : "=r"(result), "=r"(_temp)
                 :
                 : "cc", "memory"
                 : "intel");
            // There is a race between popfd (A) and pushfd (B)
            // where other bits beyond 21st may have been modified due to
            // interrupts, a debugger stepping through the asm, etc.
            //
            // Therefore, explicitly check whether the 21st bit
            // was modified or not.
            //
            // If the result is zero, the cpuid bit was not modified.
            // If the result is 0x200000 (non-zero), then the cpuid
            // was correctly modified and the CPU supports the cpuid
            // instruction:
            (result & 0x200000) != 0
        }
    }
}

/// Returns the highest-supported `leaf` (`EAX`) and sub-leaf (`ECX`) `cpuid`
/// values.
///
/// If `cpuid` is supported, and `leaf` is zero, then the first tuple argument
/// contains the highest `leaf` value that `cpuid` supports. For `leaf`s
/// containing sub-leafs, the second tuple argument contains the
/// highest-supported sub-leaf value.
///
/// See also [`__cpuid`](fn.__cpuid.html) and
/// [`__cpuid_count`](fn.__cpuid_count.html).
#[inline]
#[stable(feature = "simd_x86", since = "1.27.0")]
pub unsafe fn __get_cpuid_max(leaf: u32) -> (u32, u32) {
    let CpuidResult { eax, ebx, .. } = __cpuid(leaf);
    (eax, ebx)
}

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

    #[test]
    fn test_always_has_cpuid() {
        // all currently-tested targets have the instruction
        // FIXME: add targets without `cpuid` to CI
        assert!(cpuid::has_cpuid());
    }

    #[test]
    fn test_has_cpuid_idempotent() {
        assert_eq!(cpuid::has_cpuid(), cpuid::has_cpuid());
    }
}
<commit_msg>Optimize has_cpuid for x86 Rust targets that have cpuid<commit_after>//! `cpuid` intrinsics

#![cfg_attr(feature = "cargo-clippy", allow(stutter))]

use mem;

#[cfg(test)]
use stdsimd_test::assert_instr;

/// Result of the `cpuid` instruction.
#[derive(Copy, Clone, Eq, Ord, PartialEq, PartialOrd)]
#[cfg_attr(feature = "cargo-clippy", allow(stutter))]
#[stable(feature = "simd_x86", since = "1.27.0")]
pub struct CpuidResult {
    /// EAX register.
    #[stable(feature = "simd_x86", since = "1.27.0")]
    pub eax: u32,
    /// EBX register.
    #[stable(feature = "simd_x86", since = "1.27.0")]
    pub ebx: u32,
    /// ECX register.
    #[stable(feature = "simd_x86", since = "1.27.0")]
    pub ecx: u32,
    /// EDX register.
    #[stable(feature = "simd_x86", since = "1.27.0")]
    pub edx: u32,
}

/// Returns the result of the `cpuid` instruction for a given `leaf` (`EAX`)
/// and
/// `sub_leaf` (`ECX`).
///
/// The highest-supported leaf value is returned by the first tuple argument of
/// [`__get_cpuid_max(0)`](fn.__get_cpuid_max.html). For leaves containung
/// sub-leaves, the second tuple argument returns the highest-supported
/// sub-leaf
/// value.
///
/// The [CPUID Wikipedia page][wiki_cpuid] contains how to query which
/// information using the `EAX` and `ECX` registers, and the interpretation of
/// the results returned in `EAX`, `EBX`, `ECX`, and `EDX`.
///
/// The references are:
/// - [Intel 64 and IA-32 Architectures Software Developer's Manual Volume 2:
///   Instruction Set Reference, A-Z][intel64_ref].
/// - [AMD64 Architecture Programmer's Manual, Volume 3: General-Purpose and
///   System Instructions][amd64_ref].
///
/// [wiki_cpuid]: https://en.wikipedia.org/wiki/CPUID
/// [intel64_ref]: http://www.intel.de/content/dam/www/public/us/en/documents/manuals/64-ia-32-architectures-software-developer-instruction-set-reference-manual-325383.pdf
/// [amd64_ref]: http://support.amd.com/TechDocs/24594.pdf
#[inline]
#[cfg_attr(test, assert_instr(cpuid))]
#[stable(feature = "simd_x86", since = "1.27.0")]
pub unsafe fn __cpuid_count(leaf: u32, sub_leaf: u32) -> CpuidResult {
    let mut r = mem::uninitialized::<CpuidResult>();
    if cfg!(target_arch = "x86") {
        asm!("cpuid"
             : "={eax}"(r.eax), "={ebx}"(r.ebx), "={ecx}"(r.ecx), "={edx}"(r.edx)
             : "{eax}"(leaf), "{ecx}"(sub_leaf)
             : :);
    } else {
        // x86-64 uses %rbx as the base register, so preserve it.
        asm!("cpuid\n"
             : "={eax}"(r.eax), "={ebx}"(r.ebx), "={ecx}"(r.ecx), "={edx}"(r.edx)
             : "{eax}"(leaf), "{ecx}"(sub_leaf)
             : "rbx" :);
    }
    r
}

/// See [`__cpuid_count`](fn.__cpuid_count.html).
#[inline]
#[cfg_attr(test, assert_instr(cpuid))]
#[stable(feature = "simd_x86", since = "1.27.0")]
pub unsafe fn __cpuid(leaf: u32) -> CpuidResult {
    __cpuid_count(leaf, 0)
}

/// Does the host support the `cpuid` instruction?
#[inline]
pub fn has_cpuid() -> bool {
    #[cfg(target_arch = "x86_64")]
    {
        true
    }
    #[cfg(target_arch = "x86")]
    {
        // Optimization for i586 and i686 Rust targets which SSE enabled
        // and support cpuid:
        #[cfg(target_feature = "sse")] {
            true
        }

        // If SSE is not enabled, detect whether cpuid is available:
        #[cfg(not(target_feature = "sse"))]
        unsafe {
            // On `x86` the `cpuid` instruction is not always available.
            // This follows the approach indicated in:
            // http://wiki.osdev.org/CPUID#Checking_CPUID_availability
            // https://software.intel.com/en-us/articles/using-cpuid-to-detect-the-presence-of-sse-41-and-sse-42-instruction-sets/
            // which detects whether `cpuid` is available by checking whether the 21st bit of the EFLAGS register is modifiable or not.
            // If it is, then `cpuid` is available.
            let result: u32;
            let _temp: u32;
            asm!(r#"
                 # Read eflags into $0 and copy it into $1:
                 pushfd
                 pop     $0
                 mov     $1, $0
                 # Flip 21st bit of $0.
                 xor     $0, 0x200000
                 # Set eflags to the value of $0
                 #
                 # Bit 21st can only be modified if cpuid is available
                 push    $0
                 popfd          # A
                 # Read eflags into $0:
                 pushfd         # B
                 pop     $0
                 # xor with the original eflags sets the bits that
                 # have been modified:
                 xor     $0, $1
                 "#
                 : "=r"(result), "=r"(_temp)
                 :
                 : "cc", "memory"
                 : "intel");
            // There is a race between popfd (A) and pushfd (B)
            // where other bits beyond 21st may have been modified due to
            // interrupts, a debugger stepping through the asm, etc.
            //
            // Therefore, explicitly check whether the 21st bit
            // was modified or not.
            //
            // If the result is zero, the cpuid bit was not modified.
            // If the result is 0x200000 (non-zero), then the cpuid
            // was correctly modified and the CPU supports the cpuid
            // instruction:
            (result & 0x200000) != 0
        }
    }
}

/// Returns the highest-supported `leaf` (`EAX`) and sub-leaf (`ECX`) `cpuid`
/// values.
///
/// If `cpuid` is supported, and `leaf` is zero, then the first tuple argument
/// contains the highest `leaf` value that `cpuid` supports. For `leaf`s
/// containing sub-leafs, the second tuple argument contains the
/// highest-supported sub-leaf value.
///
/// See also [`__cpuid`](fn.__cpuid.html) and
/// [`__cpuid_count`](fn.__cpuid_count.html).
#[inline]
#[stable(feature = "simd_x86", since = "1.27.0")]
pub unsafe fn __get_cpuid_max(leaf: u32) -> (u32, u32) {
    let CpuidResult { eax, ebx, .. } = __cpuid(leaf);
    (eax, ebx)
}

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

    #[test]
    fn test_always_has_cpuid() {
        // all currently-tested targets have the instruction
        // FIXME: add targets without `cpuid` to CI
        assert!(cpuid::has_cpuid());
    }

    #[test]
    fn test_has_cpuid_idempotent() {
        assert_eq!(cpuid::has_cpuid(), cpuid::has_cpuid());
    }
}
<|endoftext|>


<commit_before>use core::cmp::Ordering;
use core::fmt::{self, Debug};
use core::hash::{Hash, Hasher};
use core::ops::{Deref, DerefMut};

#[cfg(feature = "alloc")]
use alloc::borrow::ToOwned;

#[cfg(feature = "alloc")]
use alloc::boxed::Box;

#[cfg(any(feature = "std", feature = "alloc"))]
use crate::ByteBuf;

use serde::de::{Deserialize, Deserializer, Error, Visitor};
use serde::ser::{Serialize, Serializer};

/// Wrapper around `&[u8]` to serialize and deserialize efficiently.
///
/// ```
/// use std::collections::HashMap;
/// use std::io;
///
/// use serde_bytes::Bytes;
///
/// fn print_encoded_cache() -> bincode::Result<()> {
///     let mut cache = HashMap::new();
///     cache.insert(3, Bytes::new(b"three"));
///     cache.insert(2, Bytes::new(b"two"));
///     cache.insert(1, Bytes::new(b"one"));
///
///     bincode::serialize_into(&mut io::stdout(), &cache)
/// }
/// #
/// # fn main() {
/// #     print_encoded_cache().unwrap();
/// # }
/// ```
#[derive(Eq, Ord)]
#[repr(C)]
pub struct Bytes {
    bytes: [u8],
}

impl Bytes {
    /// Wrap an existing `&[u8]`.
    pub fn new(bytes: &[u8]) -> &Self {
        unsafe { &*(bytes as *const [u8] as *const Bytes) }
    }
}

impl Debug for Bytes {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        Debug::fmt(&self.bytes, f)
    }
}

impl AsRef<[u8]> for Bytes {
    fn as_ref(&self) -> &[u8] {
        &self.bytes
    }
}

impl AsMut<[u8]> for Bytes {
    fn as_mut(&mut self) -> &mut [u8] {
        &mut self.bytes
    }
}

impl Deref for Bytes {
    type Target = [u8];

    fn deref(&self) -> &Self::Target {
        &self.bytes
    }
}

impl DerefMut for Bytes {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.bytes
    }
}

#[cfg(any(feature = "std", feature = "alloc"))]
impl ToOwned for Bytes {
    type Owned = ByteBuf;

    fn to_owned(&self) -> Self::Owned {
        ByteBuf::from(&self.bytes)
    }
}

#[cfg(any(feature = "std", feature = "alloc"))]
impl From<Box<[u8]>> for Box<Bytes> {
    fn from(bytes: Box<[u8]>) -> Self {
        unsafe { Box::from_raw(Box::into_raw(bytes) as *mut Bytes) }
    }
}

impl<Rhs> PartialEq<Rhs> for Bytes
where
    Rhs: ?Sized + AsRef<[u8]>,
{
    fn eq(&self, other: &Rhs) -> bool {
        self.as_ref().eq(other.as_ref())
    }
}

impl<Rhs> PartialOrd<Rhs> for Bytes
where
    Rhs: ?Sized + AsRef<[u8]>,
{
    fn partial_cmp(&self, other: &Rhs) -> Option<Ordering> {
        self.as_ref().partial_cmp(other.as_ref())
    }
}

impl Hash for Bytes {
    fn hash<H: Hasher>(&self, state: &mut H) {
        self.bytes.hash(state);
    }
}

impl Serialize for Bytes {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        serializer.serialize_bytes(&self.bytes)
    }
}

struct BytesVisitor;

impl<'de> Visitor<'de> for BytesVisitor {
    type Value = &'de Bytes;

    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        formatter.write_str("a borrowed byte array")
    }

    fn visit_borrowed_bytes<E>(self, v: &'de [u8]) -> Result<Self::Value, E>
    where
        E: Error,
    {
        Ok(Bytes::new(v))
    }

    fn visit_borrowed_str<E>(self, v: &'de str) -> Result<Self::Value, E>
    where
        E: Error,
    {
        Ok(Bytes::new(v.as_bytes()))
    }
}

impl<'a, 'de: 'a> Deserialize<'de> for &'a Bytes {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        deserializer.deserialize_bytes(BytesVisitor)
    }
}
<commit_msg>Add Default impls for Bytes<commit_after>use core::cmp::Ordering;
use core::fmt::{self, Debug};
use core::hash::{Hash, Hasher};
use core::ops::{Deref, DerefMut};

#[cfg(feature = "alloc")]
use alloc::borrow::ToOwned;

#[cfg(feature = "alloc")]
use alloc::boxed::Box;

#[cfg(feature = "alloc")]
use alloc::vec::Vec;

#[cfg(any(feature = "std", feature = "alloc"))]
use crate::ByteBuf;

use serde::de::{Deserialize, Deserializer, Error, Visitor};
use serde::ser::{Serialize, Serializer};

/// Wrapper around `&[u8]` to serialize and deserialize efficiently.
///
/// ```
/// use std::collections::HashMap;
/// use std::io;
///
/// use serde_bytes::Bytes;
///
/// fn print_encoded_cache() -> bincode::Result<()> {
///     let mut cache = HashMap::new();
///     cache.insert(3, Bytes::new(b"three"));
///     cache.insert(2, Bytes::new(b"two"));
///     cache.insert(1, Bytes::new(b"one"));
///
///     bincode::serialize_into(&mut io::stdout(), &cache)
/// }
/// #
/// # fn main() {
/// #     print_encoded_cache().unwrap();
/// # }
/// ```
#[derive(Eq, Ord)]
#[repr(C)]
pub struct Bytes {
    bytes: [u8],
}

impl Bytes {
    /// Wrap an existing `&[u8]`.
    pub fn new(bytes: &[u8]) -> &Self {
        unsafe { &*(bytes as *const [u8] as *const Bytes) }
    }
}

impl Debug for Bytes {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        Debug::fmt(&self.bytes, f)
    }
}

impl AsRef<[u8]> for Bytes {
    fn as_ref(&self) -> &[u8] {
        &self.bytes
    }
}

impl AsMut<[u8]> for Bytes {
    fn as_mut(&mut self) -> &mut [u8] {
        &mut self.bytes
    }
}

impl Deref for Bytes {
    type Target = [u8];

    fn deref(&self) -> &Self::Target {
        &self.bytes
    }
}

impl DerefMut for Bytes {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.bytes
    }
}

#[cfg(any(feature = "std", feature = "alloc"))]
impl ToOwned for Bytes {
    type Owned = ByteBuf;

    fn to_owned(&self) -> Self::Owned {
        ByteBuf::from(&self.bytes)
    }
}

#[cfg(any(feature = "std", feature = "alloc"))]
impl From<Box<[u8]>> for Box<Bytes> {
    fn from(bytes: Box<[u8]>) -> Self {
        unsafe { Box::from_raw(Box::into_raw(bytes) as *mut Bytes) }
    }
}

impl<'a> Default for &'a Bytes {
    fn default() -> Self {
        Bytes::new(&[])
    }
}

#[cfg(any(feature = "std", feature = "alloc"))]
impl Default for Box<Bytes> {
    fn default() -> Self {
        Vec::new().into_boxed_slice().into()
    }
}

impl<Rhs> PartialEq<Rhs> for Bytes
where
    Rhs: ?Sized + AsRef<[u8]>,
{
    fn eq(&self, other: &Rhs) -> bool {
        self.as_ref().eq(other.as_ref())
    }
}

impl<Rhs> PartialOrd<Rhs> for Bytes
where
    Rhs: ?Sized + AsRef<[u8]>,
{
    fn partial_cmp(&self, other: &Rhs) -> Option<Ordering> {
        self.as_ref().partial_cmp(other.as_ref())
    }
}

impl Hash for Bytes {
    fn hash<H: Hasher>(&self, state: &mut H) {
        self.bytes.hash(state);
    }
}

impl Serialize for Bytes {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        serializer.serialize_bytes(&self.bytes)
    }
}

struct BytesVisitor;

impl<'de> Visitor<'de> for BytesVisitor {
    type Value = &'de Bytes;

    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        formatter.write_str("a borrowed byte array")
    }

    fn visit_borrowed_bytes<E>(self, v: &'de [u8]) -> Result<Self::Value, E>
    where
        E: Error,
    {
        Ok(Bytes::new(v))
    }

    fn visit_borrowed_str<E>(self, v: &'de str) -> Result<Self::Value, E>
    where
        E: Error,
    {
        Ok(Bytes::new(v.as_bytes()))
    }
}

impl<'a, 'de: 'a> Deserialize<'de> for &'a Bytes {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        deserializer.deserialize_bytes(BytesVisitor)
    }
}
<|endoftext|>


<commit_before>use {ByteBuf, SmallByteStr};
use traits::{Buf, ByteStr, ToBytes};
use std::{fmt, mem, ops, ptr};
use std::any::{Any, TypeId};

const INLINE: usize = 1;

/// A specialized `ByteStr` box.
pub struct Bytes {
    vtable: usize,
    data: *mut (),
}

impl Bytes {
    pub fn from_slice(bytes: &[u8]) -> Bytes {
        SmallByteStr::from_slice(bytes)
            .map(|small| Bytes::of(small))
            .unwrap_or_else(|| ByteBuf::from_slice(bytes).to_bytes())
    }

    pub fn of<B: ByteStr>(bytes: B) -> Bytes {
        unsafe {
            if inline::<B>() {
                let mut vtable;
                let mut data;

                {
                    let obj: &ByteStrPriv = &bytes;
                    let obj: TraitObject = mem::transmute(obj);
                    let ptr: *const *mut () = mem::transmute(obj.data);

                    data = *ptr;
                    vtable = obj.vtable;
                }

                // Prevent drop from being called
                mem::forget(bytes);

                Bytes {
                    vtable: vtable as usize | INLINE,
                    data: data,
                }
            } else {
                let obj: Box<ByteStrPriv> = Box::new(bytes);
                let obj: TraitObject = mem::transmute(obj);

                Bytes {
                    vtable: obj.vtable as usize,
                    data: obj.data,
                }
            }
        }
    }

    pub fn empty() -> Bytes {
        Bytes::of(SmallByteStr::zero())
    }

    /// If the underlying `ByteStr` is of type `B`, returns a reference to it
    /// otherwise None.
    pub fn downcast_ref<'a, B: ByteStr>(&'a self) -> Option<&'a B> {
        if TypeId::of::<B>() == self.obj().get_type_id() {
            unsafe {
                if inline::<B>() {
                    return Some(mem::transmute(&self.data));
                } else {
                    return Some(mem::transmute(self.data));
                }
            }
        }

        None
    }

    /// If the underlying `ByteStr` is of type `B`, returns the unwraped value,
    /// otherwise, returns the original `Bytes` as `Err`.
    pub fn try_unwrap<B: ByteStr>(self) -> Result<B, Bytes> {
        if TypeId::of::<B>() == self.obj().get_type_id() {
            unsafe {
                // Underlying ByteStr value is of the correct type. Unwrap it
                let mut ret;

                if inline::<B>() {
                    // The value is inline, read directly from the pointer
                    ret = ptr::read(mem::transmute(&self.data));
                } else {
                    ret = ptr::read(mem::transmute(self.data));
                }

                mem::forget(self);
                Ok(ret)
            }
        } else {
            Err(self)
        }
    }

    fn obj(&self) -> &ByteStrPriv {
        unsafe {
            let obj = if self.is_inline() {
                TraitObject {
                    data: mem::transmute(&self.data),
                    vtable: mem::transmute(self.vtable - 1),
                }
            } else {
                TraitObject {
                    data: self.data,
                    vtable: mem::transmute(self.vtable),
                }
            };

            mem::transmute(obj)
        }
    }

    fn obj_mut(&mut self) -> &mut ByteStrPriv {
        unsafe { mem::transmute(self.obj()) }
    }

    fn is_inline(&self) -> bool {
        (self.vtable & INLINE) == INLINE
    }
}

fn inline<B: ByteStr>() -> bool {
    mem::size_of::<B>() <= 2 * mem::size_of::<usize>()
}

impl ByteStr for Bytes {

    type Buf = Box<Buf+'static>;

    fn buf(&self) -> Box<Buf+'static> {
        self.obj().buf()
    }

    fn concat<B: ByteStr>(&self, other: &B) -> Bytes {
        self.obj().concat(&Bytes::of(other.clone()))
    }

    fn len(&self) -> usize {
        self.obj().len()
    }

    fn slice(&self, begin: usize, end: usize) -> Bytes {
        self.obj().slice(begin, end)
    }

    fn split_at(&self, mid: usize) -> (Bytes, Bytes) {
        self.obj().split_at(mid)
    }
}

impl ToBytes for Bytes {
    fn to_bytes(self) -> Bytes {
        self
    }
}

impl ops::Index<usize> for Bytes {
    type Output = u8;

    fn index(&self, index: usize) -> &u8 {
        self.obj().index(index)
    }
}

impl fmt::Debug for Bytes {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        super::debug(self, "Bytes", fmt)
    }
}

impl Clone for Bytes {
    fn clone(&self) -> Bytes {
        self.obj().clone()
    }
}

impl Drop for Bytes {
    fn drop(&mut self) {
        unsafe {
            if self.is_inline() {
                let obj = self.obj_mut();
                obj.drop();
            } else {
                let _: Box<ByteStrPriv> =
                    mem::transmute(self.obj());
            }
        }
    }
}

unsafe impl Send for Bytes { }
unsafe impl Sync for Bytes { }

trait ByteStrPriv {

    fn buf(&self) -> Box<Buf+'static>;

    fn clone(&self) -> Bytes;

    fn concat(&self, other: &Bytes) -> Bytes;

    fn drop(&mut self);

    fn get_type_id(&self) -> TypeId;

    fn index(&self, index: usize) -> &u8;

    fn len(&self) -> usize;

    fn slice(&self, begin: usize, end: usize) -> Bytes;

    fn split_at(&self, mid: usize) -> (Bytes, Bytes);
}

impl<B: ByteStr> ByteStrPriv for B {

    fn buf(&self) -> Box<Buf+'static> {
        Box::new(self.buf())
    }

    fn clone(&self) -> Bytes {
        Bytes::of(self.clone())
    }

    fn concat(&self, other: &Bytes) -> Bytes {
        self.concat(other)
    }

    fn drop(&mut self) {
        unsafe {
            ptr::read(mem::transmute(self))
        }
    }

    fn get_type_id(&self) -> TypeId {
        TypeId::of::<B>()
    }

    fn index(&self, index: usize) -> &u8 {
        ops::Index::index(self, index)
    }

    fn len(&self) -> usize {
        self.len()
    }

    fn slice(&self, begin: usize, end: usize) -> Bytes {
        self.slice(begin, end)
    }

    fn split_at(&self, mid: usize) -> (Bytes, Bytes) {
        self.split_at(mid)
    }
}

// TODO: Figure out how to not depend on the memory layout of trait objects
// Blocked: rust-lang/rust#24050
struct TraitObject {
    data: *mut (),
    vtable: *mut (),
}

#[test]
pub fn test_size_of() {
    // TODO: One day, there shouldn't be a drop flag
    let ptr_size = mem::size_of::<usize>();
    let expect = ptr_size * 3;

    assert_eq!(expect, mem::size_of::<Bytes>());
    assert_eq!(expect + ptr_size, mem::size_of::<Option<Bytes>>());
}
<commit_msg>Fix TraitObject<commit_after>use {ByteBuf, SmallByteStr};
use traits::{Buf, ByteStr, ToBytes};
use std::{fmt, mem, ops, ptr};
use std::any::{Any, TypeId};

const INLINE: usize = 1;

/// A specialized `ByteStr` box.
pub struct Bytes {
    vtable: usize,
    data: *mut (),
}

impl Bytes {
    pub fn from_slice(bytes: &[u8]) -> Bytes {
        SmallByteStr::from_slice(bytes)
            .map(|small| Bytes::of(small))
            .unwrap_or_else(|| ByteBuf::from_slice(bytes).to_bytes())
    }

    pub fn of<B: ByteStr>(bytes: B) -> Bytes {
        unsafe {
            if inline::<B>() {
                let mut vtable;
                let mut data;

                {
                    let obj: &ByteStrPriv = &bytes;
                    let obj: TraitObject = mem::transmute(obj);
                    let ptr: *const *mut () = mem::transmute(obj.data);

                    data = *ptr;
                    vtable = obj.vtable;
                }

                // Prevent drop from being called
                mem::forget(bytes);

                Bytes {
                    vtable: vtable as usize | INLINE,
                    data: data,
                }
            } else {
                let obj: Box<ByteStrPriv> = Box::new(bytes);
                let obj: TraitObject = mem::transmute(obj);

                Bytes {
                    vtable: obj.vtable as usize,
                    data: obj.data,
                }
            }
        }
    }

    pub fn empty() -> Bytes {
        Bytes::of(SmallByteStr::zero())
    }

    /// If the underlying `ByteStr` is of type `B`, returns a reference to it
    /// otherwise None.
    pub fn downcast_ref<'a, B: ByteStr>(&'a self) -> Option<&'a B> {
        if TypeId::of::<B>() == self.obj().get_type_id() {
            unsafe {
                if inline::<B>() {
                    return Some(mem::transmute(&self.data));
                } else {
                    return Some(mem::transmute(self.data));
                }
            }
        }

        None
    }

    /// If the underlying `ByteStr` is of type `B`, returns the unwraped value,
    /// otherwise, returns the original `Bytes` as `Err`.
    pub fn try_unwrap<B: ByteStr>(self) -> Result<B, Bytes> {
        if TypeId::of::<B>() == self.obj().get_type_id() {
            unsafe {
                // Underlying ByteStr value is of the correct type. Unwrap it
                let mut ret;

                if inline::<B>() {
                    // The value is inline, read directly from the pointer
                    ret = ptr::read(mem::transmute(&self.data));
                } else {
                    ret = ptr::read(mem::transmute(self.data));
                }

                mem::forget(self);
                Ok(ret)
            }
        } else {
            Err(self)
        }
    }

    fn obj(&self) -> &ByteStrPriv {
        unsafe {
            let obj = if self.is_inline() {
                TraitObject {
                    data: mem::transmute(&self.data),
                    vtable: mem::transmute(self.vtable - 1),
                }
            } else {
                TraitObject {
                    data: self.data,
                    vtable: mem::transmute(self.vtable),
                }
            };

            mem::transmute(obj)
        }
    }

    fn obj_mut(&mut self) -> &mut ByteStrPriv {
        unsafe { mem::transmute(self.obj()) }
    }

    fn is_inline(&self) -> bool {
        (self.vtable & INLINE) == INLINE
    }
}

fn inline<B: ByteStr>() -> bool {
    mem::size_of::<B>() <= 2 * mem::size_of::<usize>()
}

impl ByteStr for Bytes {

    type Buf = Box<Buf+'static>;

    fn buf(&self) -> Box<Buf+'static> {
        self.obj().buf()
    }

    fn concat<B: ByteStr>(&self, other: &B) -> Bytes {
        self.obj().concat(&Bytes::of(other.clone()))
    }

    fn len(&self) -> usize {
        self.obj().len()
    }

    fn slice(&self, begin: usize, end: usize) -> Bytes {
        self.obj().slice(begin, end)
    }

    fn split_at(&self, mid: usize) -> (Bytes, Bytes) {
        self.obj().split_at(mid)
    }
}

impl ToBytes for Bytes {
    fn to_bytes(self) -> Bytes {
        self
    }
}

impl ops::Index<usize> for Bytes {
    type Output = u8;

    fn index(&self, index: usize) -> &u8 {
        self.obj().index(index)
    }
}

impl fmt::Debug for Bytes {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        super::debug(self, "Bytes", fmt)
    }
}

impl Clone for Bytes {
    fn clone(&self) -> Bytes {
        self.obj().clone()
    }
}

impl Drop for Bytes {
    fn drop(&mut self) {
        unsafe {
            if self.is_inline() {
                let obj = self.obj_mut();
                obj.drop();
            } else {
                let _: Box<ByteStrPriv> =
                    mem::transmute(self.obj());
            }
        }
    }
}

unsafe impl Send for Bytes { }
unsafe impl Sync for Bytes { }

trait ByteStrPriv {

    fn buf(&self) -> Box<Buf+'static>;

    fn clone(&self) -> Bytes;

    fn concat(&self, other: &Bytes) -> Bytes;

    fn drop(&mut self);

    fn get_type_id(&self) -> TypeId;

    fn index(&self, index: usize) -> &u8;

    fn len(&self) -> usize;

    fn slice(&self, begin: usize, end: usize) -> Bytes;

    fn split_at(&self, mid: usize) -> (Bytes, Bytes);
}

impl<B: ByteStr> ByteStrPriv for B {

    fn buf(&self) -> Box<Buf+'static> {
        Box::new(self.buf())
    }

    fn clone(&self) -> Bytes {
        Bytes::of(self.clone())
    }

    fn concat(&self, other: &Bytes) -> Bytes {
        self.concat(other)
    }

    fn drop(&mut self) {
        unsafe {
            ptr::read(mem::transmute(self))
        }
    }

    fn get_type_id(&self) -> TypeId {
        TypeId::of::<B>()
    }

    fn index(&self, index: usize) -> &u8 {
        ops::Index::index(self, index)
    }

    fn len(&self) -> usize {
        self.len()
    }

    fn slice(&self, begin: usize, end: usize) -> Bytes {
        self.slice(begin, end)
    }

    fn split_at(&self, mid: usize) -> (Bytes, Bytes) {
        self.split_at(mid)
    }
}

// TODO: Figure out how to not depend on the memory layout of trait objects
// Blocked: rust-lang/rust#24050
#[repr(C)]
struct TraitObject {
    data: *mut (),
    vtable: *mut (),
}

#[test]
pub fn test_size_of() {
    // TODO: One day, there shouldn't be a drop flag
    let ptr_size = mem::size_of::<usize>();
    let expect = ptr_size * 3;

    assert_eq!(expect, mem::size_of::<Bytes>());
    assert_eq!(expect + ptr_size, mem::size_of::<Option<Bytes>>());
}
<|endoftext|>


<commit_before>use std::io;
use std::result;
use std::error::Error;
use std::fmt;
use std::string;

#[derive(Debug)]
pub enum QuicError {
    Io(io::Error),
    ParseError,
    SerializeError,
    FromUtf8Error(string::FromUtf8Error),
    PacketTooLarge,
}

pub type Result<T> = result::Result<T, QuicError>;

impl Error for QuicError {
    fn description(&self) -> &str {
        match *self {
            QuicError::Io(ref err) => err.description(),
            QuicError::FromUtf8Error(ref err) => err.description(),
            QuicError::ParseError => "Error parsing packet",
            QuicError::SerializeError => "Error serializing packet",
            QuicError::PacketTooLarge => "Packet too large",
        }
    }

    fn cause(&self) -> Option<&Error> {
        match *self {
            QuicError::Io(ref err) => Some(err),
            QuicError::FromUtf8Error(ref err) => Some(err),
            QuicError::ParseError | QuicError::SerializeError | QuicError::PacketTooLarge => None,
        }
    }
}

impl From<io::Error> for QuicError {
    fn from(err: io::Error) -> QuicError {
        QuicError::Io(err)
    }
}

impl From<string::FromUtf8Error> for QuicError {
    fn from(err: string::FromUtf8Error) -> QuicError {
        QuicError::FromUtf8Error(err)
    }
}

impl fmt::Display for QuicError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            QuicError::Io(ref err) => err.fmt(f),
            QuicError::FromUtf8Error(ref err) => err.fmt(f),
            QuicError::ParseError => write!(f, "Error parsing packet"),
            QuicError::SerializeError => write!(f, "Error serializing packet"),
            QuicError::PacketTooLarge => write!(f, "Packet too large"),
        }
    }
}<commit_msg>add transport error codes<commit_after>use std::io;
use std::result;
use std::error::Error;
use std::fmt;
use std::string;

bitflags! {
    pub flags TransportErrorFlag: u32 {
        const QUIC_INTERNAL_ERROR                        = 0x80000001,
        const QUIC_STREAM_DATA_AFTER_TERMINATION         = 0x80000002,
        const QUIC_INVALID_PACKET_HEADER                 = 0x80000003,
        const QUIC_INVALID_FRAME_DATA                    = 0x80000004,
        const QUIC_MULTIPLE_TERMINATION_OFFSETS          = 0x80000005,
        const QUIC_STREAM_CANCELLED                      = 0x80000006,
        const QUIC_CLOSED_CRITICAL_STREAM                = 0x80000007,
        const QUIC_MISSING_PAYLOAD                       = 0x80000030,
        const QUIC_INVALID_STREAM_DATA                   = 0x8000002E,
        const QUIC_UNENCRYPTED_STREAM_DATA               = 0x8000003D,
        const QUIC_MAYBE_CORRUPTED_MEMORY                = 0x80000059,
        const QUIC_INVALID_RST_STREAM_DATA               = 0x80000006,
        const QUIC_INVALID_CONNECTION_CLOSE_DATA         = 0x80000007,
        const QUIC_INVALID_GOAWAY_DATA                   = 0x80000008,
        const QUIC_INVALID_WINDOW_UPDATE_DATA            = 0x80000039,
        const QUIC_INVALID_BLOCKED_DATA                  = 0x8000003A,
        const QUIC_INVALID_PATH_CLOSE_DATA               = 0x8000004E,
        const QUIC_INVALID_ACK_DATA                      = 0x80000009,
        const QUIC_INVALID_VERSION_NEGOTIATION_PACKET    = 0x8000000A,
        const QUIC_INVALID_PUBLIC_RST_PACKET             = 0x8000000B,
        const QUIC_DECRYPTION_FAILURE                    = 0x8000000C,
        const QUIC_ENCRYPTION_FAILURE                    = 0x8000000D,
        const QUIC_PACKET_TOO_LARGE                      = 0x8000000E,
        const QUIC_PEER_GOING_AWAY                       = 0x80000010,
        const QUIC_INVALID_STREAM_ID                     = 0x80000011,
        const QUIC_INVALID_PRIORITY                      = 0x80000031,
        const QUIC_TOO_MANY_OPEN_STREAMS                 = 0x80000012,
        const QUIC_TOO_MANY_AVAILABLE_STREAMS            = 0x8000004c,
        const QUIC_PUBLIC_RESET                          = 0x80000013,
        const QUIC_INVALID_VERSION                       = 0x80000014,
        const QUIC_INVALID_HEADER_ID                     = 0x80000016,
        const QUIC_INVALID_NEGOTIATED_VALUE              = 0x80000017,
        const QUIC_DECOMPRESSION_FAILURE                 = 0x80000018,
        const QUIC_NETWORK_IDLE_TIMEOUT                  = 0x80000019,
        const QUIC_HANDSHAKE_TIMEOUT                     = 0x80000043,
        const QUIC_ERROR_MIGRATING_ADDRESS               = 0x8000001a,
        const QUIC_ERROR_MIGRATING_PORT                  = 0x80000056,
        const QUIC_EMPTY_STREAM_FRAME_NO_FIN             = 0x80000032,
        const QUIC_FLOW_CONTROL_RECEIVED_TOO_MUCH_DATA   = 0x8000003B,
        const QUIC_FLOW_CONTROL_SENT_TOO_MUCH_DATA       = 0x8000003F,
        const QUIC_FLOW_CONTROL_INVALID_WINDOW           = 0x80000040,
        const QUIC_CONNECTION_IP_POOLED                  = 0x8000003E,
        const QUIC_TOO_MANY_OUTSTANDING_SENT_PACKETS     = 0x80000044,
        const QUIC_TOO_MANY_OUTSTANDING_RECEIVED_PACKETS = 0x80000045,
        const QUIC_CONNECTION_CANCELLED                  = 0x80000046,
        const QUIC_BAD_PACKET_LOSS_RATE                  = 0x80000047,
        const QUIC_PUBLIC_RESETS_POST_HANDSHAKE          = 0x80000049,
        const QUIC_TIMEOUTS_WITH_OPEN_STREAMS            = 0x8000004a,
        const QUIC_TOO_MANY_RTOS                         = 0x80000055,
        const QUIC_ENCRYPTION_LEVEL_INCORRECT            = 0x8000002c,
        const QUIC_VERSION_NEGOTIATION_MISMATCH          = 0x80000037,
        const QUIC_IP_ADDRESS_CHANGED                    = 0x80000050,
        const QUIC_ADDRESS_VALIDATION_FAILURE            = 0x80000051,
        const QUIC_TOO_MANY_FRAME_GAPS                   = 0x8000005d,
        const QUIC_TOO_MANY_SESSIONS_ON_SERVER           = 0x80000060,
    }
}

#[derive(Debug)]
pub enum QuicError {
    Io(io::Error),
    ParseError,
    SerializeError,
    FromUtf8Error(string::FromUtf8Error),
    PacketTooLarge,
    TransportError(TransportErrorFlag)
}

pub type Result<T> = result::Result<T, QuicError>;

impl Error for QuicError {
    fn description(&self) -> &str {
        match *self {
            QuicError::Io(ref err) => err.description(),
            QuicError::FromUtf8Error(ref err) => err.description(),
            QuicError::ParseError => "Error parsing packet",
            QuicError::SerializeError => "Error serializing packet",
            QuicError::PacketTooLarge => "Packet too large",
            QuicError::TransportError(_) => "Transport error",
        }
    }

    fn cause(&self) -> Option<&Error> {
        match *self {
            QuicError::Io(ref err) => Some(err),
            QuicError::FromUtf8Error(ref err) => Some(err),
            QuicError::ParseError | QuicError::SerializeError | QuicError::PacketTooLarge | QuicError::TransportError(_) => None,
        }
    }
}

impl From<io::Error> for QuicError {
    fn from(err: io::Error) -> QuicError {
        QuicError::Io(err)
    }
}

impl From<string::FromUtf8Error> for QuicError {
    fn from(err: string::FromUtf8Error) -> QuicError {
        QuicError::FromUtf8Error(err)
    }
}

impl fmt::Display for QuicError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            QuicError::Io(ref err) => err.fmt(f),
            QuicError::FromUtf8Error(ref err) => err.fmt(f),
            QuicError::ParseError => write!(f, "Error parsing packet"),
            QuicError::SerializeError => write!(f, "Error serializing packet"),
            QuicError::PacketTooLarge => write!(f, "Packet too large"),
            QuicError::TransportError(ref err) => write!(f, "Transport Error: 0x{:X}", err.bits()),
        }
    }
}<|endoftext|>


<commit_before>#[cfg(feature = "use_failure")]
use failure::{Backtrace, Context, Fail};
use std;
use std::fmt::{self, Display};

#[derive(Debug)]
pub struct Error {
    #[cfg(feature = "use_failure")]
    inner: Context<ErrorKind>,
    #[cfg(not(feature = "use_failure"))]
    inner: ErrorKind,
}

// To suppress false positives from cargo-clippy
#[cfg_attr(feature = "cargo-clippy", allow(empty_line_after_outer_attr))]
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
pub enum ErrorKind {
    BadAbsolutePath,
    BadRelativePath,
    CannotFindBinaryPath,
    CannotGetCurrentDir,
    CannotCanonicalize,
}

#[cfg(feature = "use_failure")]
impl Fail for ErrorKind {}

impl Display for ErrorKind {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let display = match *self {
            ErrorKind::BadAbsolutePath => "Bad absolute path",
            ErrorKind::BadRelativePath => "Bad relative path",
            ErrorKind::CannotFindBinaryPath => "Cannot find binary path",
            ErrorKind::CannotGetCurrentDir => "Cannot get current directory",
            ErrorKind::CannotCanonicalize => "Cannot canonicalize path",
        };
        f.write_str(display)
    }
}

#[cfg(feature = "use_failure")]
impl Fail for Error {
    fn cause(&self) -> Option<&dyn Fail> {
        self.inner.cause()
    }

    fn backtrace(&self) -> Option<&Backtrace> {
        self.inner.backtrace()
    }
}

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

impl Error {
    pub fn kind(&self) -> ErrorKind {
        #[cfg(feature = "use_failure")]
        {
            *self.inner.get_context()
        }
        #[cfg(not(feature = "use_failure"))]
        {
            self.inner
        }
    }
}

impl From<ErrorKind> for Error {
    fn from(kind: ErrorKind) -> Error {
        Error {
            #[cfg(feature = "use_failure")]
            inner: Context::new(kind),
            #[cfg(not(feature = "use_failure"))]
            inner: kind,
        }
    }
}

#[cfg(feature = "use_failure")]
impl From<Context<ErrorKind>> for Error {
    fn from(inner: Context<ErrorKind>) -> Error {
        Error { inner }
    }
}

pub type Result<T> = std::result::Result<T, Error>;
<commit_msg>Implement std::error::Error when not using failure<commit_after>#[cfg(feature = "use_failure")]
use failure::{Backtrace, Context, Fail};
use std;
use std::fmt::{self, Display};

#[derive(Debug)]
pub struct Error {
    #[cfg(feature = "use_failure")]
    inner: Context<ErrorKind>,
    #[cfg(not(feature = "use_failure"))]
    inner: ErrorKind,
}

// To suppress false positives from cargo-clippy
#[cfg_attr(feature = "cargo-clippy", allow(empty_line_after_outer_attr))]
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
pub enum ErrorKind {
    BadAbsolutePath,
    BadRelativePath,
    CannotFindBinaryPath,
    CannotGetCurrentDir,
    CannotCanonicalize,
}

#[cfg(feature = "use_failure")]
impl Fail for ErrorKind {}

impl Display for ErrorKind {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let display = match *self {
            ErrorKind::BadAbsolutePath => "Bad absolute path",
            ErrorKind::BadRelativePath => "Bad relative path",
            ErrorKind::CannotFindBinaryPath => "Cannot find binary path",
            ErrorKind::CannotGetCurrentDir => "Cannot get current directory",
            ErrorKind::CannotCanonicalize => "Cannot canonicalize path",
        };
        f.write_str(display)
    }
}

#[cfg(feature = "use_failure")]
impl Fail for Error {
    fn cause(&self) -> Option<&dyn Fail> {
        self.inner.cause()
    }

    fn backtrace(&self) -> Option<&Backtrace> {
        self.inner.backtrace()
    }
}

#[cfg(not(feature = "failure"))]
impl std::error::Error for Error {}

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

impl Error {
    pub fn kind(&self) -> ErrorKind {
        #[cfg(feature = "use_failure")]
        {
            *self.inner.get_context()
        }
        #[cfg(not(feature = "use_failure"))]
        {
            self.inner
        }
    }
}

impl From<ErrorKind> for Error {
    fn from(kind: ErrorKind) -> Error {
        Error {
            #[cfg(feature = "use_failure")]
            inner: Context::new(kind),
            #[cfg(not(feature = "use_failure"))]
            inner: kind,
        }
    }
}

#[cfg(feature = "use_failure")]
impl From<Context<ErrorKind>> for Error {
    fn from(inner: Context<ErrorKind>) -> Error {
        Error { inner }
    }
}

pub type Result<T> = std::result::Result<T, Error>;
<|endoftext|>


<commit_before>use crate::context::ContextError;
use std::any::TypeId;
use std::error::Error as StdError;
use std::fmt::{self, Debug, Display};
use std::mem;
use std::ops::{Deref, DerefMut};
use std::ptr;

#[cfg(backtrace)]
use std::backtrace::{Backtrace, BacktraceStatus};

/// The `Error` type, a wrapper around a dynamic error type.
///
/// `Error` works a lot like `Box<dyn std::error::Error>`, but with these
/// differences:
///
/// - `Error` requires that the error is `Send`, `Sync`, and `'static`.
/// - `Error` guarantees that a backtrace is available, even if the underlying
///   error type does not provide one.
/// - `Error` is represented as a narrow pointer — exactly one word in
///   size instead of two.
pub struct Error {
    inner: Box<ErrorImpl<()>>,
}

impl Error {
    /// Create a new error object from any error type.
    ///
    /// The error type must be threadsafe and `'static`, so that the `Error`
    /// will be as well.
    ///
    /// If the error type does not provide a backtrace, a backtrace will be
    /// created here to ensure that a backtrace exists.
    pub fn new<E>(error: E) -> Self
    where
        E: StdError + Send + Sync + 'static,
    {
        // Captured here instead of in Error::construct to have one fewer layer
        // of wrapping visible in the backtrace.
        #[cfg(backtrace)]
        let backtrace = match error.backtrace() {
            Some(_) => None,
            None => Some(Backtrace::capture()),
        };

        #[cfg(not(backtrace))]
        let backtrace = None;

        Error::construct(error, TypeId::of::<E>(), backtrace)
    }

    pub(crate) fn new_adhoc<M>(message: M, backtrace: Option<Backtrace>) -> Self
    where
        M: Display + Debug + Send + Sync + 'static,
    {
        Error::construct(MessageError(message), TypeId::of::<M>(), backtrace)
    }

    fn construct<E>(error: E, type_id: TypeId, backtrace: Option<Backtrace>) -> Self
    where
        E: StdError + Send + Sync + 'static,
    {
        unsafe {
            let obj = mem::transmute::<&dyn StdError, TraitObject>(&error);
            let inner = Box::new(ErrorImpl {
                vtable: obj.vtable,
                type_id,
                backtrace,
                error,
            });
            Error {
                inner: mem::transmute::<Box<ErrorImpl<E>>, Box<ErrorImpl<()>>>(inner),
            }
        }
    }

    /// Wrap the error value with additional context.
    ///
    /// For attaching context to a `Result` as it is propagated, the
    /// [`Context`][crate::Context] extension trait may be more convenient than
    /// this function.
    ///
    /// The primary reason to use `error.context(...)` instead of
    /// `result.context(...)` via the `Context` trait would be if the context
    /// needs to depend on some data held by the underlying error:
    ///
    /// ```
    /// # use std::fmt::{self, Debug, Display};
    /// #
    /// # type T = ();
    /// #
    /// # impl std::error::Error for ParseError {}
    /// # impl Debug for ParseError {
    /// #     fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
    /// #         unimplemented!()
    /// #     }
    /// # }
    /// # impl Display for ParseError {
    /// #     fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
    /// #         unimplemented!()
    /// #     }
    /// # }
    /// #
    /// use std::fs::File;
    /// use std::path::Path;
    ///
    /// struct ParseError {
    ///     line: usize,
    ///     column: usize,
    /// }
    ///
    /// fn parse_impl(file: File) -> Result<T, ParseError> {
    ///     # const IGNORE: &str = stringify! {
    ///     ...
    ///     # };
    ///     # unimplemented!()
    /// }
    ///
    /// pub fn parse(path: impl AsRef<Path>) -> anyhow::Result<T> {
    ///     let file = File::open(&path)?;
    ///     parse_impl(file).map_err(|error| {
    ///         let context = format!(
    ///             "only the first {} lines of {} are valid",
    ///             error.line, path.as_ref().display(),
    ///         );
    ///         anyhow::Error::new(error).context(context)
    ///     })
    /// }
    /// ```
    pub fn context<C>(self, context: C) -> Self
    where
        C: Display + Send + Sync + 'static,
    {
        Error::from(ContextError {
            error: self,
            context,
        })
    }

    /// Get the backtrace for this Error.
    ///
    /// Backtraces are only available on the nightly channel. Tracking issue:
    /// [rust-lang/rust#53487][tracking].
    ///
    /// In order for the backtrace to be meaningful, the environment variable
    /// `RUST_LIB_BACKTRACE=1` must be defined. Backtraces are somewhat
    /// expensive to capture in Rust, so we don't necessarily want to be
    /// capturing them all over the place all the time.
    ///
    /// [tracking]: https://github.com/rust-lang/rust/issues/53487
    #[cfg(backtrace)]
    pub fn backtrace(&self) -> &Backtrace {
        // NB: this unwrap can only fail if the underlying error's backtrace
        // method is nondeterministic, which would only happen in maliciously
        // constructed code
        self.inner
            .backtrace
            .as_ref()
            .or_else(|| self.inner.error().backtrace())
            .expect("backtrace capture failed")
    }

    /// An iterator of the chain of source errors contained by this Error.
    ///
    /// This iterator will visit every error in the cause chain of this error
    /// object, beginning with the error that this error object was created
    /// from.
    ///
    /// # Example
    ///
    /// ```
    /// use anyhow::Error;
    /// use std::io;
    ///
    /// pub fn underlying_io_error_kind(error: &Error) -> Option<io::ErrorKind> {
    ///     for cause in error.chain() {
    ///         if let Some(io_error) = cause.downcast_ref::<io::Error>() {
    ///             return Some(io_error.kind());
    ///         }
    ///     }
    ///     None
    /// }
    /// ```
    pub fn chain(&self) -> Chain {
        Chain {
            next: Some(self.inner.error()),
        }
    }

    /// The lowest level cause of this error — this error's cause's
    /// cause's cause etc.
    ///
    /// The root cause is the last error in the iterator produced by
    /// [`chain()`][Error::chain].
    pub fn root_cause(&self) -> &(dyn StdError + 'static) {
        let mut chain = self.chain();
        let mut root_cause = chain.next().unwrap();
        for cause in chain {
            root_cause = cause;
        }
        root_cause
    }

    /// Returns `true` if `E` is the type wrapped by this error object.
    pub fn is<E>(&self) -> bool
    where
        E: Display + Debug + Send + Sync + 'static,
    {
        TypeId::of::<E>() == self.inner.type_id
    }

    /// Attempt to downcast the error object to a concrete type.
    pub fn downcast<E>(self) -> Result<E, Self>
    where
        E: Display + Debug + Send + Sync + 'static,
    {
        if let Some(error) = self.downcast_ref::<E>() {
            unsafe {
                let error = ptr::read(error);
                drop(ptr::read(&self.inner));
                mem::forget(self);
                Ok(error)
            }
        } else {
            Err(self)
        }
    }

    /// Downcast this error object by reference.
    ///
    /// # Example
    ///
    /// ```
    /// # use anyhow::anyhow;
    /// # use std::fmt::{self, Display};
    /// # use std::task::Poll;
    /// #
    /// # #[derive(Debug)]
    /// # enum DataStoreError {
    /// #     Censored(()),
    /// # }
    /// #
    /// # impl Display for DataStoreError {
    /// #     fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
    /// #         unimplemented!()
    /// #     }
    /// # }
    /// #
    /// # impl std::error::Error for DataStoreError {}
    /// #
    /// # const REDACTED_CONTENT: () = ();
    /// #
    /// # let error = anyhow!("...");
    /// # let root_cause = &error;
    /// #
    /// # let ret =
    /// // If the error was caused by redaction, then return a tombstone instead
    /// // of the content.
    /// match root_cause.downcast_ref::<DataStoreError>() {
    ///     Some(DataStoreError::Censored(_)) => Ok(Poll::Ready(REDACTED_CONTENT)),
    ///     None => Err(error),
    /// }
    /// # ;
    /// ```
    pub fn downcast_ref<E>(&self) -> Option<&E>
    where
        E: Display + Debug + Send + Sync + 'static,
    {
        if self.is::<E>() {
            unsafe { Some(&*(self.inner.error() as *const dyn StdError as *const E)) }
        } else {
            None
        }
    }

    /// Downcast this error object by mutable reference.
    pub fn downcast_mut<E>(&mut self) -> Option<&mut E>
    where
        E: Display + Debug + Send + Sync + 'static,
    {
        if self.is::<E>() {
            unsafe { Some(&mut *(self.inner.error_mut() as *mut dyn StdError as *mut E)) }
        } else {
            None
        }
    }
}

#[cfg(not(backtrace))]
pub(crate) enum Backtrace {}

impl<E> From<E> for Error
where
    E: StdError + Send + Sync + 'static,
{
    fn from(error: E) -> Self {
        Error::new(error)
    }
}

impl Deref for Error {
    type Target = dyn StdError + Send + Sync + 'static;

    fn deref(&self) -> &Self::Target {
        self.inner.error()
    }
}

impl DerefMut for Error {
    fn deref_mut(&mut self) -> &mut Self::Target {
        self.inner.error_mut()
    }
}

impl Debug for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        writeln!(f, "{}", self.inner.error())?;

        let mut chain = self.chain().skip(1).enumerate();
        if let Some((n, error)) = chain.next() {
            writeln!(f, "\nCaused by:")?;
            writeln!(f, "\t{}: {}", n, error)?;
            for (n, error) in chain {
                writeln!(f, "\t{}: {}", n, error)?;
            }
        }

        #[cfg(backtrace)]
        {
            let backtrace = self.backtrace();
            match backtrace.status() {
                BacktraceStatus::Captured => {
                    writeln!(f, "\n{}", backtrace)?;
                }
                BacktraceStatus::Disabled => {
                    writeln!(
                        f,
                        "\nBacktrace disabled; run with RUST_LIB_BACKTRACE=1 environment variable to display a backtrace"
                    )?;
                }
                _ => {}
            }
        }

        Ok(())
    }
}

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

unsafe impl Send for Error {}
unsafe impl Sync for Error {}

impl Drop for Error {
    fn drop(&mut self) {
        unsafe { ptr::drop_in_place(self.inner.error_mut()) }
    }
}

// repr C to ensure that `E` remains in the final position
#[repr(C)]
struct ErrorImpl<E> {
    vtable: *const (),
    type_id: TypeId,
    backtrace: Option<Backtrace>,
    error: E,
}

// repr C to ensure that transmuting from trait objects is safe
#[repr(C)]
struct TraitObject {
    data: *const (),
    vtable: *const (),
}

#[repr(transparent)]
struct MessageError<M>(M);

impl<M> Debug for MessageError<M>
where
    M: Display + Debug,
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        Debug::fmt(&self.0, f)
    }
}

impl<M> Display for MessageError<M>
where
    M: Display + Debug,
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        Display::fmt(&self.0, f)
    }
}

impl<M> StdError for MessageError<M> where M: Display + Debug + 'static {}

impl ErrorImpl<()> {
    fn error(&self) -> &(dyn StdError + Send + Sync + 'static) {
        let object = TraitObject {
            data: &self.error,
            vtable: self.vtable,
        };

        unsafe { mem::transmute::<TraitObject, &(dyn StdError + Send + Sync + 'static)>(object) }
    }

    fn error_mut(&mut self) -> &mut (dyn StdError + Send + Sync + 'static) {
        let object = TraitObject {
            data: &mut self.error,
            vtable: self.vtable,
        };

        unsafe {
            mem::transmute::<TraitObject, &mut (dyn StdError + Send + Sync + 'static)>(object)
        }
    }
}

/// Iterator of a chain of source errors.
///
/// This type is the iterator returned by [`Error::chain`].
///
/// # Example
///
/// ```
/// use anyhow::Error;
/// use std::io;
///
/// pub fn underlying_io_error_kind(error: &Error) -> Option<io::ErrorKind> {
///     for cause in error.chain() {
///         if let Some(io_error) = cause.downcast_ref::<io::Error>() {
///             return Some(io_error.kind());
///         }
///     }
///     None
/// }
/// ```
pub struct Chain<'a> {
    next: Option<&'a (dyn StdError + 'static)>,
}

impl<'a> Iterator for Chain<'a> {
    type Item = &'a (dyn StdError + 'static);

    fn next(&mut self) -> Option<Self::Item> {
        let next = self.next.take()?;
        self.next = next.source();
        Some(next)
    }
}

#[cfg(test)]
mod repr_correctness {
    use super::*;
    use std::marker::Unpin;
    use std::mem;
    use std::sync::atomic::AtomicBool;
    use std::sync::atomic::Ordering::SeqCst;
    use std::sync::Arc;

    #[test]
    fn size_of_error() {
        assert_eq!(mem::size_of::<Error>(), mem::size_of::<usize>());
    }

    #[test]
    fn error_autotraits() {
        fn assert<E: Unpin + Send + Sync + 'static>() {}
        assert::<Error>();
    }

    #[test]
    fn drop_works() {
        #[derive(Debug)]
        struct DetectDrop {
            has_dropped: Arc<AtomicBool>,
        }

        impl StdError for DetectDrop {}

        impl Display for DetectDrop {
            fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                write!(f, "does something")
            }
        }

        impl Drop for DetectDrop {
            fn drop(&mut self) {
                let already_dropped = self.has_dropped.swap(true, SeqCst);
                assert!(!already_dropped);
            }
        }

        let has_dropped = Arc::new(AtomicBool::new(false));

        drop(Error::from(DetectDrop {
            has_dropped: has_dropped.clone(),
        }));

        assert!(has_dropped.load(SeqCst));
    }
}
<commit_msg>Indent causes in Debug representation with spaces<commit_after>use crate::context::ContextError;
use std::any::TypeId;
use std::error::Error as StdError;
use std::fmt::{self, Debug, Display};
use std::mem;
use std::ops::{Deref, DerefMut};
use std::ptr;

#[cfg(backtrace)]
use std::backtrace::{Backtrace, BacktraceStatus};

/// The `Error` type, a wrapper around a dynamic error type.
///
/// `Error` works a lot like `Box<dyn std::error::Error>`, but with these
/// differences:
///
/// - `Error` requires that the error is `Send`, `Sync`, and `'static`.
/// - `Error` guarantees that a backtrace is available, even if the underlying
///   error type does not provide one.
/// - `Error` is represented as a narrow pointer — exactly one word in
///   size instead of two.
pub struct Error {
    inner: Box<ErrorImpl<()>>,
}

impl Error {
    /// Create a new error object from any error type.
    ///
    /// The error type must be threadsafe and `'static`, so that the `Error`
    /// will be as well.
    ///
    /// If the error type does not provide a backtrace, a backtrace will be
    /// created here to ensure that a backtrace exists.
    pub fn new<E>(error: E) -> Self
    where
        E: StdError + Send + Sync + 'static,
    {
        // Captured here instead of in Error::construct to have one fewer layer
        // of wrapping visible in the backtrace.
        #[cfg(backtrace)]
        let backtrace = match error.backtrace() {
            Some(_) => None,
            None => Some(Backtrace::capture()),
        };

        #[cfg(not(backtrace))]
        let backtrace = None;

        Error::construct(error, TypeId::of::<E>(), backtrace)
    }

    pub(crate) fn new_adhoc<M>(message: M, backtrace: Option<Backtrace>) -> Self
    where
        M: Display + Debug + Send + Sync + 'static,
    {
        Error::construct(MessageError(message), TypeId::of::<M>(), backtrace)
    }

    fn construct<E>(error: E, type_id: TypeId, backtrace: Option<Backtrace>) -> Self
    where
        E: StdError + Send + Sync + 'static,
    {
        unsafe {
            let obj = mem::transmute::<&dyn StdError, TraitObject>(&error);
            let inner = Box::new(ErrorImpl {
                vtable: obj.vtable,
                type_id,
                backtrace,
                error,
            });
            Error {
                inner: mem::transmute::<Box<ErrorImpl<E>>, Box<ErrorImpl<()>>>(inner),
            }
        }
    }

    /// Wrap the error value with additional context.
    ///
    /// For attaching context to a `Result` as it is propagated, the
    /// [`Context`][crate::Context] extension trait may be more convenient than
    /// this function.
    ///
    /// The primary reason to use `error.context(...)` instead of
    /// `result.context(...)` via the `Context` trait would be if the context
    /// needs to depend on some data held by the underlying error:
    ///
    /// ```
    /// # use std::fmt::{self, Debug, Display};
    /// #
    /// # type T = ();
    /// #
    /// # impl std::error::Error for ParseError {}
    /// # impl Debug for ParseError {
    /// #     fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
    /// #         unimplemented!()
    /// #     }
    /// # }
    /// # impl Display for ParseError {
    /// #     fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
    /// #         unimplemented!()
    /// #     }
    /// # }
    /// #
    /// use std::fs::File;
    /// use std::path::Path;
    ///
    /// struct ParseError {
    ///     line: usize,
    ///     column: usize,
    /// }
    ///
    /// fn parse_impl(file: File) -> Result<T, ParseError> {
    ///     # const IGNORE: &str = stringify! {
    ///     ...
    ///     # };
    ///     # unimplemented!()
    /// }
    ///
    /// pub fn parse(path: impl AsRef<Path>) -> anyhow::Result<T> {
    ///     let file = File::open(&path)?;
    ///     parse_impl(file).map_err(|error| {
    ///         let context = format!(
    ///             "only the first {} lines of {} are valid",
    ///             error.line, path.as_ref().display(),
    ///         );
    ///         anyhow::Error::new(error).context(context)
    ///     })
    /// }
    /// ```
    pub fn context<C>(self, context: C) -> Self
    where
        C: Display + Send + Sync + 'static,
    {
        Error::from(ContextError {
            error: self,
            context,
        })
    }

    /// Get the backtrace for this Error.
    ///
    /// Backtraces are only available on the nightly channel. Tracking issue:
    /// [rust-lang/rust#53487][tracking].
    ///
    /// In order for the backtrace to be meaningful, the environment variable
    /// `RUST_LIB_BACKTRACE=1` must be defined. Backtraces are somewhat
    /// expensive to capture in Rust, so we don't necessarily want to be
    /// capturing them all over the place all the time.
    ///
    /// [tracking]: https://github.com/rust-lang/rust/issues/53487
    #[cfg(backtrace)]
    pub fn backtrace(&self) -> &Backtrace {
        // NB: this unwrap can only fail if the underlying error's backtrace
        // method is nondeterministic, which would only happen in maliciously
        // constructed code
        self.inner
            .backtrace
            .as_ref()
            .or_else(|| self.inner.error().backtrace())
            .expect("backtrace capture failed")
    }

    /// An iterator of the chain of source errors contained by this Error.
    ///
    /// This iterator will visit every error in the cause chain of this error
    /// object, beginning with the error that this error object was created
    /// from.
    ///
    /// # Example
    ///
    /// ```
    /// use anyhow::Error;
    /// use std::io;
    ///
    /// pub fn underlying_io_error_kind(error: &Error) -> Option<io::ErrorKind> {
    ///     for cause in error.chain() {
    ///         if let Some(io_error) = cause.downcast_ref::<io::Error>() {
    ///             return Some(io_error.kind());
    ///         }
    ///     }
    ///     None
    /// }
    /// ```
    pub fn chain(&self) -> Chain {
        Chain {
            next: Some(self.inner.error()),
        }
    }

    /// The lowest level cause of this error — this error's cause's
    /// cause's cause etc.
    ///
    /// The root cause is the last error in the iterator produced by
    /// [`chain()`][Error::chain].
    pub fn root_cause(&self) -> &(dyn StdError + 'static) {
        let mut chain = self.chain();
        let mut root_cause = chain.next().unwrap();
        for cause in chain {
            root_cause = cause;
        }
        root_cause
    }

    /// Returns `true` if `E` is the type wrapped by this error object.
    pub fn is<E>(&self) -> bool
    where
        E: Display + Debug + Send + Sync + 'static,
    {
        TypeId::of::<E>() == self.inner.type_id
    }

    /// Attempt to downcast the error object to a concrete type.
    pub fn downcast<E>(self) -> Result<E, Self>
    where
        E: Display + Debug + Send + Sync + 'static,
    {
        if let Some(error) = self.downcast_ref::<E>() {
            unsafe {
                let error = ptr::read(error);
                drop(ptr::read(&self.inner));
                mem::forget(self);
                Ok(error)
            }
        } else {
            Err(self)
        }
    }

    /// Downcast this error object by reference.
    ///
    /// # Example
    ///
    /// ```
    /// # use anyhow::anyhow;
    /// # use std::fmt::{self, Display};
    /// # use std::task::Poll;
    /// #
    /// # #[derive(Debug)]
    /// # enum DataStoreError {
    /// #     Censored(()),
    /// # }
    /// #
    /// # impl Display for DataStoreError {
    /// #     fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
    /// #         unimplemented!()
    /// #     }
    /// # }
    /// #
    /// # impl std::error::Error for DataStoreError {}
    /// #
    /// # const REDACTED_CONTENT: () = ();
    /// #
    /// # let error = anyhow!("...");
    /// # let root_cause = &error;
    /// #
    /// # let ret =
    /// // If the error was caused by redaction, then return a tombstone instead
    /// // of the content.
    /// match root_cause.downcast_ref::<DataStoreError>() {
    ///     Some(DataStoreError::Censored(_)) => Ok(Poll::Ready(REDACTED_CONTENT)),
    ///     None => Err(error),
    /// }
    /// # ;
    /// ```
    pub fn downcast_ref<E>(&self) -> Option<&E>
    where
        E: Display + Debug + Send + Sync + 'static,
    {
        if self.is::<E>() {
            unsafe { Some(&*(self.inner.error() as *const dyn StdError as *const E)) }
        } else {
            None
        }
    }

    /// Downcast this error object by mutable reference.
    pub fn downcast_mut<E>(&mut self) -> Option<&mut E>
    where
        E: Display + Debug + Send + Sync + 'static,
    {
        if self.is::<E>() {
            unsafe { Some(&mut *(self.inner.error_mut() as *mut dyn StdError as *mut E)) }
        } else {
            None
        }
    }
}

#[cfg(not(backtrace))]
pub(crate) enum Backtrace {}

impl<E> From<E> for Error
where
    E: StdError + Send + Sync + 'static,
{
    fn from(error: E) -> Self {
        Error::new(error)
    }
}

impl Deref for Error {
    type Target = dyn StdError + Send + Sync + 'static;

    fn deref(&self) -> &Self::Target {
        self.inner.error()
    }
}

impl DerefMut for Error {
    fn deref_mut(&mut self) -> &mut Self::Target {
        self.inner.error_mut()
    }
}

impl Debug for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        writeln!(f, "{}", self.inner.error())?;

        let mut chain = self.chain().skip(1).enumerate();
        if let Some((n, error)) = chain.next() {
            writeln!(f, "\nCaused by:")?;
            writeln!(f, "    {}: {}", n, error)?;
            for (n, error) in chain {
                writeln!(f, "    {}: {}", n, error)?;
            }
        }

        #[cfg(backtrace)]
        {
            let backtrace = self.backtrace();
            match backtrace.status() {
                BacktraceStatus::Captured => {
                    writeln!(f, "\n{}", backtrace)?;
                }
                BacktraceStatus::Disabled => {
                    writeln!(
                        f,
                        "\nBacktrace disabled; run with RUST_LIB_BACKTRACE=1 environment variable to display a backtrace"
                    )?;
                }
                _ => {}
            }
        }

        Ok(())
    }
}

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

unsafe impl Send for Error {}
unsafe impl Sync for Error {}

impl Drop for Error {
    fn drop(&mut self) {
        unsafe { ptr::drop_in_place(self.inner.error_mut()) }
    }
}

// repr C to ensure that `E` remains in the final position
#[repr(C)]
struct ErrorImpl<E> {
    vtable: *const (),
    type_id: TypeId,
    backtrace: Option<Backtrace>,
    error: E,
}

// repr C to ensure that transmuting from trait objects is safe
#[repr(C)]
struct TraitObject {
    data: *const (),
    vtable: *const (),
}

#[repr(transparent)]
struct MessageError<M>(M);

impl<M> Debug for MessageError<M>
where
    M: Display + Debug,
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        Debug::fmt(&self.0, f)
    }
}

impl<M> Display for MessageError<M>
where
    M: Display + Debug,
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        Display::fmt(&self.0, f)
    }
}

impl<M> StdError for MessageError<M> where M: Display + Debug + 'static {}

impl ErrorImpl<()> {
    fn error(&self) -> &(dyn StdError + Send + Sync + 'static) {
        let object = TraitObject {
            data: &self.error,
            vtable: self.vtable,
        };

        unsafe { mem::transmute::<TraitObject, &(dyn StdError + Send + Sync + 'static)>(object) }
    }

    fn error_mut(&mut self) -> &mut (dyn StdError + Send + Sync + 'static) {
        let object = TraitObject {
            data: &mut self.error,
            vtable: self.vtable,
        };

        unsafe {
            mem::transmute::<TraitObject, &mut (dyn StdError + Send + Sync + 'static)>(object)
        }
    }
}

/// Iterator of a chain of source errors.
///
/// This type is the iterator returned by [`Error::chain`].
///
/// # Example
///
/// ```
/// use anyhow::Error;
/// use std::io;
///
/// pub fn underlying_io_error_kind(error: &Error) -> Option<io::ErrorKind> {
///     for cause in error.chain() {
///         if let Some(io_error) = cause.downcast_ref::<io::Error>() {
///             return Some(io_error.kind());
///         }
///     }
///     None
/// }
/// ```
pub struct Chain<'a> {
    next: Option<&'a (dyn StdError + 'static)>,
}

impl<'a> Iterator for Chain<'a> {
    type Item = &'a (dyn StdError + 'static);

    fn next(&mut self) -> Option<Self::Item> {
        let next = self.next.take()?;
        self.next = next.source();
        Some(next)
    }
}

#[cfg(test)]
mod repr_correctness {
    use super::*;
    use std::marker::Unpin;
    use std::mem;
    use std::sync::atomic::AtomicBool;
    use std::sync::atomic::Ordering::SeqCst;
    use std::sync::Arc;

    #[test]
    fn size_of_error() {
        assert_eq!(mem::size_of::<Error>(), mem::size_of::<usize>());
    }

    #[test]
    fn error_autotraits() {
        fn assert<E: Unpin + Send + Sync + 'static>() {}
        assert::<Error>();
    }

    #[test]
    fn drop_works() {
        #[derive(Debug)]
        struct DetectDrop {
            has_dropped: Arc<AtomicBool>,
        }

        impl StdError for DetectDrop {}

        impl Display for DetectDrop {
            fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                write!(f, "does something")
            }
        }

        impl Drop for DetectDrop {
            fn drop(&mut self) {
                let already_dropped = self.has_dropped.swap(true, SeqCst);
                assert!(!already_dropped);
            }
        }

        let has_dropped = Arc::new(AtomicBool::new(false));

        drop(Error::from(DetectDrop {
            has_dropped: has_dropped.clone(),
        }));

        assert!(has_dropped.load(SeqCst));
    }
}
<|endoftext|>


<commit_before>// This file is part of Grust, GObject introspection bindings for Rust
//
// Copyright (C) 2014, 2015  Mikhail Zabaluev <mikhail.zabaluev@gmail.com>
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

use boxed::BoxedType;
use gstr::GStr;
use gtype::GType;
use quark::Quark;
use types::{gint, gpointer};
use util::escape_bytestring;

use glib as ffi;
use gobject;

use std::error::Error as ErrorTrait;
use std::error::FromError;
use std::fmt;
use std::mem;
use std::num;

pub struct Error {
    ptr: *mut ffi::GError
}

pub struct DomainError<T> {
    inner: Error
}

#[derive(Copy, Debug)]
pub enum Code<T> {
    Known(T),
    Unknown(gint)
}

pub trait Domain : num::FromPrimitive {
    fn domain() -> Quark;
    fn name(&self) -> &'static str;
}

pub fn domain<T>() -> Quark where T: Domain {
    <T as Domain>::domain()
}

unsafe impl Send for Error { }

unsafe impl<T> Send for DomainError<T> { }

impl Drop for Error {
    fn drop(&mut self) {
        unsafe { ffi::g_error_free(self.ptr); }
    }
}

impl Clone for Error {
    fn clone(&self) -> Error {
        Error {
            ptr: unsafe { ffi::g_error_copy(self.ptr) }
        }
    }
}

impl<T> Clone for DomainError<T> {
    fn clone(&self) -> DomainError<T> {
        DomainError { inner: self.inner.clone() }
    }
}

impl BoxedType for Error {

    fn get_type() -> GType {
        unsafe { GType::from_raw(gobject::g_error_get_type()) }
    }

    unsafe fn from_ptr(ptr: gpointer) -> Error {
        Error { ptr: ptr as *mut ffi::GError }
    }

    unsafe fn into_ptr(self) -> gpointer {
        let ptr = self.ptr;
        mem::forget(self);
        ptr as gpointer
    }
}

impl Error {

    pub unsafe fn from_raw(ptr: *mut ffi::GError) -> Error {
        assert!(!ptr.is_null(), "GError pointer is not set");
        Error { ptr: ptr }
    }

    pub fn domain(&self) -> Quark {
        unsafe { Quark::from_raw((*self.ptr).domain) }
    }

    pub fn matches<T>(&self, code: T) -> bool where T: Domain + PartialEq {
        if self.domain() == domain::<T>() {
            let own_code_raw = unsafe { (*self.ptr).code };
            if let Some(own_code) = num::from_i32::<T>(own_code_raw as i32) {
                return own_code == code;
            }
        }
        false
    }

    pub fn key(&self) -> (Quark, gint) {
        unsafe {
            let raw = &*self.ptr;
            (Quark::from_raw(raw.domain), raw.code)
        }
    }

    pub fn in_domain<T>(&self) -> bool where T: Domain {
        self.domain() == domain::<T>()
    }

    pub fn into_domain<T>(self) -> Result<DomainError<T>, Error>
        where T: Domain
    {
        if self.in_domain::<T>() {
            Ok(DomainError { inner: self })
        } else {
            Err(self)
        }
    }

    fn message(&self) -> Option<&str> {
        let message = unsafe { GStr::from_ptr((*self.ptr).message) };
        message.to_utf8().ok()
    }

    fn message_bytes(&self) -> &[u8] {
        let message = unsafe { GStr::from_ptr((*self.ptr).message) };
        message.to_bytes()
    }
}

impl<T> DomainError<T> where T: num::FromPrimitive {
    pub fn code(&self) -> Code<T> {
        let code = unsafe { (*self.inner.ptr).code };
        match num::from_i32(code as i32) {
            Some(domain_code) => Code::Known(domain_code),
            None              => Code::Unknown(code)
        }
    }
}

impl ErrorTrait for Error {
    fn description(&self) -> &str {
        if let Some(s) = self.message() {
            return s;
        }
        match self.domain().to_g_str().to_utf8() {
            Ok(s)  => s,
            Err(_) => "GError (message and domain are not represented)"
        }
    }
}

impl<T> ErrorTrait for DomainError<T> where T: Domain {
    fn description(&self) -> &str {
        if let Some(s) = self.inner.message() {
            return s;
        }
        if let Code::Known(code) = self.code() {
            return code.name();
        }
        match self.inner.domain().to_g_str().to_utf8() {
            Ok(s)  => s,
            Err(_) => "GError (message and domain are not represented; unknown code)"
        }
    }
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let bytes = self.message_bytes();
        write!(f, "{}", String::from_utf8_lossy(bytes))
    }
}

impl<T> fmt::Display for DomainError<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let bytes = self.inner.message_bytes();
        write!(f, "{}", String::from_utf8_lossy(bytes))
    }
}

impl fmt::Debug for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let (domain, code) = self.key();
        let message = escape_bytestring(self.message_bytes());
        write!(f,
               r#"GError {{ domain: {:?}, code: {}, message: "{}" }}"#,
               domain, code, message)
    }
}

impl<T> fmt::Debug for DomainError<T> where T: Domain {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let domain = self.inner.domain();
        let message = escape_bytestring(self.inner.message_bytes());
        match self.code() {
            Code::Known(code) => {
                write!(f,
                       r#"GError {{ domain: {:?}, code: {:?}, message: "{}" }}"#,
                       domain, code.name(), message)
            }
            Code::Unknown(int_code) => {
                write!(f,
                       r#"GError {{ domain: {:?}, code: {}, message: "{}" }}"#,
                       domain, int_code, message)
            }
        }
    }
}

impl<T> FromError<DomainError<T>> for Error {
    fn from_error(err: DomainError<T>) -> Error {
        err.inner
    }
}

impl<T> Code<T> {

    pub fn known(self) -> Option<T> {
        match self {
            Code::Known(code) => Some(code),
            Code::Unknown(_) => None
        }
    }
}

impl<T> PartialEq for Code<T> where T: PartialEq {
    fn eq(&self, other: &Code<T>) -> bool {
        match (self, other) {
            (&Code::Known(ref a), &Code::Known(ref b)) => *a == *b,
            (&Code::Unknown(a), &Code::Unknown(b)) => a == b,
            _ => false
        }
    }
}

#[cfg(test)]
mod test {
    use super::*;
    use glib as ffi;
    use gstr::GStrBuf;
    use quark::Quark;
    use types::gint;

    fn new_error(domain: Quark, code: gint, message: &[u8]) -> Error {
        let msg_buf = GStrBuf::from_bytes(message).unwrap();
        unsafe {
            let raw = ffi::g_error_new_literal(
                domain.to_raw(), code, msg_buf.as_ptr());
            Error::from_raw(raw)
        }
    }

    #[test]
    fn message() {
        let domain = Quark::from_static_str("foo\0");
        let message = "test message";
        let err = new_error(domain, 1, message.as_bytes());
        assert_eq!(err.message().unwrap(), message);
        let err = new_error(domain, 1, b"U can't parse this.\x9C Hammer time!");
        assert!(err.message().is_none());
    }
}
<commit_msg>error: Unit test for internal method message_bytes()<commit_after>// This file is part of Grust, GObject introspection bindings for Rust
//
// Copyright (C) 2014, 2015  Mikhail Zabaluev <mikhail.zabaluev@gmail.com>
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

use boxed::BoxedType;
use gstr::GStr;
use gtype::GType;
use quark::Quark;
use types::{gint, gpointer};
use util::escape_bytestring;

use glib as ffi;
use gobject;

use std::error::Error as ErrorTrait;
use std::error::FromError;
use std::fmt;
use std::mem;
use std::num;

pub struct Error {
    ptr: *mut ffi::GError
}

pub struct DomainError<T> {
    inner: Error
}

#[derive(Copy, Debug)]
pub enum Code<T> {
    Known(T),
    Unknown(gint)
}

pub trait Domain : num::FromPrimitive {
    fn domain() -> Quark;
    fn name(&self) -> &'static str;
}

pub fn domain<T>() -> Quark where T: Domain {
    <T as Domain>::domain()
}

unsafe impl Send for Error { }

unsafe impl<T> Send for DomainError<T> { }

impl Drop for Error {
    fn drop(&mut self) {
        unsafe { ffi::g_error_free(self.ptr); }
    }
}

impl Clone for Error {
    fn clone(&self) -> Error {
        Error {
            ptr: unsafe { ffi::g_error_copy(self.ptr) }
        }
    }
}

impl<T> Clone for DomainError<T> {
    fn clone(&self) -> DomainError<T> {
        DomainError { inner: self.inner.clone() }
    }
}

impl BoxedType for Error {

    fn get_type() -> GType {
        unsafe { GType::from_raw(gobject::g_error_get_type()) }
    }

    unsafe fn from_ptr(ptr: gpointer) -> Error {
        Error { ptr: ptr as *mut ffi::GError }
    }

    unsafe fn into_ptr(self) -> gpointer {
        let ptr = self.ptr;
        mem::forget(self);
        ptr as gpointer
    }
}

impl Error {

    pub unsafe fn from_raw(ptr: *mut ffi::GError) -> Error {
        assert!(!ptr.is_null(), "GError pointer is not set");
        Error { ptr: ptr }
    }

    pub fn domain(&self) -> Quark {
        unsafe { Quark::from_raw((*self.ptr).domain) }
    }

    pub fn matches<T>(&self, code: T) -> bool where T: Domain + PartialEq {
        if self.domain() == domain::<T>() {
            let own_code_raw = unsafe { (*self.ptr).code };
            if let Some(own_code) = num::from_i32::<T>(own_code_raw as i32) {
                return own_code == code;
            }
        }
        false
    }

    pub fn key(&self) -> (Quark, gint) {
        unsafe {
            let raw = &*self.ptr;
            (Quark::from_raw(raw.domain), raw.code)
        }
    }

    pub fn in_domain<T>(&self) -> bool where T: Domain {
        self.domain() == domain::<T>()
    }

    pub fn into_domain<T>(self) -> Result<DomainError<T>, Error>
        where T: Domain
    {
        if self.in_domain::<T>() {
            Ok(DomainError { inner: self })
        } else {
            Err(self)
        }
    }

    fn message(&self) -> Option<&str> {
        let message = unsafe { GStr::from_ptr((*self.ptr).message) };
        message.to_utf8().ok()
    }

    fn message_bytes(&self) -> &[u8] {
        let message = unsafe { GStr::from_ptr((*self.ptr).message) };
        message.to_bytes()
    }
}

impl<T> DomainError<T> where T: num::FromPrimitive {
    pub fn code(&self) -> Code<T> {
        let code = unsafe { (*self.inner.ptr).code };
        match num::from_i32(code as i32) {
            Some(domain_code) => Code::Known(domain_code),
            None              => Code::Unknown(code)
        }
    }
}

impl ErrorTrait for Error {
    fn description(&self) -> &str {
        if let Some(s) = self.message() {
            return s;
        }
        match self.domain().to_g_str().to_utf8() {
            Ok(s)  => s,
            Err(_) => "GError (message and domain are not represented)"
        }
    }
}

impl<T> ErrorTrait for DomainError<T> where T: Domain {
    fn description(&self) -> &str {
        if let Some(s) = self.inner.message() {
            return s;
        }
        if let Code::Known(code) = self.code() {
            return code.name();
        }
        match self.inner.domain().to_g_str().to_utf8() {
            Ok(s)  => s,
            Err(_) => "GError (message and domain are not represented; unknown code)"
        }
    }
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let bytes = self.message_bytes();
        write!(f, "{}", String::from_utf8_lossy(bytes))
    }
}

impl<T> fmt::Display for DomainError<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let bytes = self.inner.message_bytes();
        write!(f, "{}", String::from_utf8_lossy(bytes))
    }
}

impl fmt::Debug for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let (domain, code) = self.key();
        let message = escape_bytestring(self.message_bytes());
        write!(f,
               r#"GError {{ domain: {:?}, code: {}, message: "{}" }}"#,
               domain, code, message)
    }
}

impl<T> fmt::Debug for DomainError<T> where T: Domain {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let domain = self.inner.domain();
        let message = escape_bytestring(self.inner.message_bytes());
        match self.code() {
            Code::Known(code) => {
                write!(f,
                       r#"GError {{ domain: {:?}, code: {:?}, message: "{}" }}"#,
                       domain, code.name(), message)
            }
            Code::Unknown(int_code) => {
                write!(f,
                       r#"GError {{ domain: {:?}, code: {}, message: "{}" }}"#,
                       domain, int_code, message)
            }
        }
    }
}

impl<T> FromError<DomainError<T>> for Error {
    fn from_error(err: DomainError<T>) -> Error {
        err.inner
    }
}

impl<T> Code<T> {

    pub fn known(self) -> Option<T> {
        match self {
            Code::Known(code) => Some(code),
            Code::Unknown(_) => None
        }
    }
}

impl<T> PartialEq for Code<T> where T: PartialEq {
    fn eq(&self, other: &Code<T>) -> bool {
        match (self, other) {
            (&Code::Known(ref a), &Code::Known(ref b)) => *a == *b,
            (&Code::Unknown(a), &Code::Unknown(b)) => a == b,
            _ => false
        }
    }
}

#[cfg(test)]
mod test {
    use super::*;
    use glib as ffi;
    use gstr::GStrBuf;
    use quark::Quark;
    use types::gint;

    fn new_error(domain: Quark, code: gint, message: &[u8]) -> Error {
        let msg_buf = GStrBuf::from_bytes(message).unwrap();
        unsafe {
            let raw = ffi::g_error_new_literal(
                domain.to_raw(), code, msg_buf.as_ptr());
            Error::from_raw(raw)
        }
    }

    #[test]
    fn message() {
        let domain = Quark::from_static_str("foo\0");
        let message = "test message";
        let err = new_error(domain, 1, message.as_bytes());
        assert_eq!(err.message().unwrap(), message);
        let err = new_error(domain, 1, b"U can't parse this.\x9C Hammer time!");
        assert!(err.message().is_none());
    }

    #[test]
    fn message_bytes() {
        let domain = Quark::from_static_str("foo\0");
        let message = b"U can't parse this.\x9C Hammer time!";
        let err = new_error(domain, 1, message);
        assert_eq!(err.message_bytes(), message);
    }
}
<|endoftext|>


<commit_before>use std::fmt;

pub enum GitError {
    CorruptRepository(&'static str),
    CorruptCommit(&'static str),
}

impl fmt::Show for GitError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            CorruptCommit(s) => write!(f, "CorruptCommit: {}", s),
            CorruptRepository(s) => write!(f, "CorruptRepository: {}", s),
        }
    }
}<commit_msg>Add new error type<commit_after>use std::fmt;

pub enum GitError {
    CorruptRepository(&'static str),
    CorruptCommit(&'static str),
    NotFound,
}

impl fmt::Show for GitError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            CorruptCommit(s) => write!(f, "CorruptCommit: {}", s),
            CorruptRepository(s) => write!(f, "CorruptRepository: {}", s),
            NotFound => write!(f, "NotFound"),
        }
    }
}<|endoftext|>


<commit_before>use std::error::Error;
use std::fmt;

#[derive(Debug)]
pub enum ParseError {
    /// Wraps any errors that might arise from the input
    InputError(Box<Error>),
}

impl ParseError {
    pub(crate) fn from_error<E>(err: E) -> Self
    where
        E: Error + 'static,
    {
        ParseError::InputError(Box::new(err))
    }
}

impl fmt::Display for ParseError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            &ParseError::InputError(ref err) => write!(f, "{}", err),
        }
    }
}

impl Error for ParseError {
    fn description(&self) -> &str {
        match self {
            &ParseError::InputError(ref err) => err.description(),
        }
    }

    fn cause(&self) -> Option<&Error> {
        match self {
            &ParseError::InputError(ref err) => Some(err.as_ref()),
        }
    }
}<commit_msg>Add tests for `ParseError`<commit_after>use std::error::Error;
use std::fmt;

#[derive(Debug)]
pub enum ParseError {
    /// Wraps any errors that might arise from the input
    InputError(Box<Error>),
}

impl ParseError {
    pub(crate) fn from_error<E>(err: E) -> Self
    where
        E: Error + 'static,
    {
        ParseError::InputError(Box::new(err))
    }
}

impl fmt::Display for ParseError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            &ParseError::InputError(ref err) => write!(f, "{}", err),
        }
    }
}

impl Error for ParseError {
    fn description(&self) -> &str {
        match self {
            &ParseError::InputError(ref err) => err.description(),
        }
    }

    fn cause(&self) -> Option<&Error> {
        match self {
            &ParseError::InputError(ref err) => Some(err.as_ref()),
        }
    }
}

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

    #[test]
    fn description_works() {
        let err = ParseError::from_error(io::Error::from(io::ErrorKind::BrokenPipe));
        let io_err = io::Error::from(io::ErrorKind::BrokenPipe);

        assert_eq!(err.description(), io_err.description());
    }

    #[test]
    fn display_works() {
        let err = ParseError::from_error(io::Error::from(io::ErrorKind::BrokenPipe));
        let io_err = io::Error::from(io::ErrorKind::BrokenPipe);

        assert_eq!(format!("{}", io_err), format!("{}", err));
    }
}<|endoftext|>


<commit_before>extern crate walkdir;
extern crate unicode_segmentation;

use std::cmp;
use self::unicode_segmentation::UnicodeSegmentation;
use self::walkdir::WalkDir;

pub fn find_duplicates(dir: &str, expected_dist: i32) {
    let paths = get_paths(dir);
    for i in 0..paths.len() {
        let mut duplicates: Vec<&NamePath> = vec![];
        let ref path1 = paths[i];
        for j in (i + 1)..paths.len() {
            let ref path2 = paths[j];
            let dist = edit_distance(&path1.name, &path2.name);
            if dist <= expected_dist {
                duplicates.push(path2);
            }
        }
        if duplicates.len() > 0 {
            println!("-----------------------------------------------------------------------");
            println!("* {} --> {} *", path1.name, path1.path);
            println!("-----------------------------------------------------------------------");
            for dupe in duplicates {
                println!("- Possible duplicate: {} --> {}", dupe.name, dupe.path);
            }
        }
    }
}

fn edit_distance(str1: &str, str2: &str) -> i32 {
    let str1_vec = UnicodeSegmentation::graphemes(str1, true).collect::<Vec<&str>>();
    let str2_vec = UnicodeSegmentation::graphemes(str2, true).collect::<Vec<&str>>();
    let str1_size = str1_vec.len() + 1;
    let str2_size = str2_vec.len() + 1;
    let mut dp = vec![vec![0; str2_size]; str1_size];
    for i in 0..str1_size {
        for j in 0..str2_size {
            if i == 0 {
                dp[i][j] = j;
            } else if j == 0 {
                dp[i][j] = i;
            } else if str1_vec[i - 1] == str2_vec[j - 1] {
                dp[i][j] = dp[i - 1][j - 1];
            } else {
                dp[i][j] = 1 + cmp::min(
                    dp[i][j - 1],
                    cmp::min(dp[i - 1][j],
                        dp[i - 1][j - 1]));
            }
        }
    }
    dp[str1_size - 1 as usize][str2_size - 1 as usize] as i32
}

#[derive(Debug)]
struct NamePath {
    name: String,
    path: String,
}

fn get_paths<'a>(dir: &str) -> Vec<NamePath> {
    let mut name_paths: Vec<NamePath> = vec![];
    let walker = WalkDir::new(dir).into_iter();
    for entry in walker.filter_map(|e| e.ok()) {
        let path = entry.path();
        if path.is_file() {
            let name_path = NamePath{
                name: path.file_name().unwrap().to_str().unwrap().to_string(),
                path: path.to_str().unwrap().to_string(),
            };
            name_paths.push(name_path);
        }
    }
    name_paths
}

#[cfg(test)]
mod test {
    use fdupe;
    use std::path::Path;

    #[test]
    fn test_edit_distance() {
        assert_eq!(2, fdupe::edit_distance("hello", "holla"));
        assert_eq!(2, fdupe::edit_distance("hell", "holla"));
        assert_eq!(3, fdupe::edit_distance("abc", "def"));
        assert_eq!(1, fdupe::edit_distance("忠犬ハチ公", "忠犬ハチ"));
        assert_eq!(2, fdupe::edit_distance("犬ハチ公", "忠犬ハチ"));
    }

    #[test]
    fn test_get_paths() {
        assert_eq!(5, fdupe::get_paths(Path::new("src").join("testdata").to_str().unwrap()).len());
    }

    #[test]
    fn test_find_duplicates() {
        fdupe::find_duplicates(Path::new("src").join("testdata").to_str().unwrap(), 3);
    }
}<commit_msg>Update unit test<commit_after>extern crate walkdir;
extern crate unicode_segmentation;

use std::cmp;
use self::unicode_segmentation::UnicodeSegmentation;
use self::walkdir::WalkDir;

pub fn find_duplicates(dir: &str, expected_dist: i32) {
    let paths = get_paths(dir);
    for i in 0..paths.len() {
        let mut duplicates: Vec<&NamePath> = vec![];
        let ref path1 = paths[i];
        for j in (i + 1)..paths.len() {
            let ref path2 = paths[j];
            let dist = edit_distance(&path1.name, &path2.name);
            if dist <= expected_dist {
                duplicates.push(path2);
            }
        }
        if duplicates.len() > 0 {
            println!("-----------------------------------------------------------------------");
            println!("* {} --> {} *", path1.name, path1.path);
            println!("-----------------------------------------------------------------------");
            for dupe in duplicates {
                println!("- Possible duplicate: {} --> {}", dupe.name, dupe.path);
            }
        }
    }
}

fn edit_distance(str1: &str, str2: &str) -> i32 {
    let str1_vec = UnicodeSegmentation::graphemes(str1, true).collect::<Vec<&str>>();
    let str2_vec = UnicodeSegmentation::graphemes(str2, true).collect::<Vec<&str>>();
    let str1_size = str1_vec.len() + 1;
    let str2_size = str2_vec.len() + 1;
    let mut dp = vec![vec![0; str2_size]; str1_size];
    for i in 0..str1_size {
        for j in 0..str2_size {
            if i == 0 {
                dp[i][j] = j;
            } else if j == 0 {
                dp[i][j] = i;
            } else if str1_vec[i - 1] == str2_vec[j - 1] {
                dp[i][j] = dp[i - 1][j - 1];
            } else {
                dp[i][j] = 1 + cmp::min(
                    dp[i][j - 1],
                    cmp::min(dp[i - 1][j],
                        dp[i - 1][j - 1]));
            }
        }
    }
    dp[str1_size - 1 as usize][str2_size - 1 as usize] as i32
}

#[derive(Debug)]
struct NamePath {
    name: String,
    path: String,
}

fn get_paths<'a>(dir: &str) -> Vec<NamePath> {
    let mut name_paths: Vec<NamePath> = vec![];
    let walker = WalkDir::new(dir).into_iter();
    for entry in walker.filter_map(|e| e.ok()) {
        let path = entry.path();
        if path.is_file() {
            let name_path = NamePath{
                name: path.file_name().unwrap().to_str().unwrap().to_string(),
                path: path.to_str().unwrap().to_string(),
            };
            name_paths.push(name_path);
        }
    }
    name_paths
}

#[cfg(test)]
mod test {
    use fdupe;
    use std::path::Path;

    #[test]
    fn test_edit_distance() {
        assert_eq!(2, fdupe::edit_distance("hello", "holla"));
        assert_eq!(2, fdupe::edit_distance("hell", "holla"));
        assert_eq!(3, fdupe::edit_distance("abc", "def"));
        assert_eq!(1, fdupe::edit_distance("忠犬ハチ公", "忠犬ハチ"));
        assert_eq!(2, fdupe::edit_distance("犬ハチ公", "忠犬ハチ"));
    }

    #[test]
    fn test_get_paths() {
        assert_eq!(8, fdupe::get_paths(Path::new("src").join("testdata").to_str().unwrap()).len());
    }

    #[test]
    fn test_find_duplicates() {
        fdupe::find_duplicates(Path::new("src").join("testdata").to_str().unwrap(), 3);
    }
}<|endoftext|>