<commit_before>#![allow(non_upper_case_globals, non_camel_case_types)]

extern crate libc;

use std::ffi::CString;
use std::ptr;
use std::str;

pub type Boolean = ::std::os::raw::c_uchar;

pub type CFRef = *mut ::std::os::raw::c_void;

pub type CFIndex = ::std::os::raw::c_long;
pub type CFTimeInterval = f64;

#[doc(hidden)]
pub enum CFError {}

pub type CFAllocatorRef = CFRef;
pub type CFMutableArrayRef = CFRef;
pub type CFURLRef = CFRef;
pub type CFErrorRef = *mut CFError;
pub type CFStringRef = CFRef;
pub type CFRunLoopRef = CFRef;

pub const NULL: CFRef = 0 as CFRef;
pub const NULL_REF_PTR: *mut CFRef = 0 as *mut CFRef;

pub type CFAllocatorRetainCallBack =
    extern "C" fn(*const ::std::os::raw::c_void) -> *const ::std::os::raw::c_void;
pub type CFAllocatorReleaseCallBack = extern "C" fn(*const ::std::os::raw::c_void);
pub type CFAllocatorCopyDescriptionCallBack =
    extern "C" fn(*const ::std::os::raw::c_void) -> *const CFStringRef;

pub type CFURLPathStyle = CFIndex;

pub const kCFAllocatorDefault: CFAllocatorRef = NULL;
pub const kCFURLPOSIXPathStyle: CFURLPathStyle = 0;
pub const kCFURLHFSPathStyle: CFURLPathStyle = 1;
pub const kCFURLWindowsPathStyle: CFURLPathStyle = 2;

pub const kCFStringEncodingUTF8: CFStringEncoding = 0x08000100;
pub type CFStringEncoding = u32;

pub const kCFCompareEqualTo: CFIndex = 0;
pub type CFComparisonResult = CFIndex;

// MacOS uses Case Insensitive path
pub const kCFCompareCaseInsensitive: CFStringCompareFlags = 1;
pub type CFStringCompareFlags = ::std::os::raw::c_ulong;

pub type CFArrayRetainCallBack =
    extern "C" fn(CFAllocatorRef, *const ::std::os::raw::c_void) -> *const ::std::os::raw::c_void;
pub type CFArrayReleaseCallBack = extern "C" fn(CFAllocatorRef, *const ::std::os::raw::c_void);
pub type CFArrayCopyDescriptionCallBack = extern "C" fn(*const ::std::os::raw::c_void) -> CFStringRef;
pub type CFArrayEqualCallBack =
    extern "C" fn(*const ::std::os::raw::c_void, *const ::std::os::raw::c_void) -> Boolean;

#[repr(C)]
pub struct CFArrayCallBacks {
    version: CFIndex,
    retain: Option<CFArrayRetainCallBack>,
    release: Option<CFArrayReleaseCallBack>,
    cp: Option<CFArrayCopyDescriptionCallBack>,
    equal: Option<CFArrayEqualCallBack>,
}
//impl Clone for CFArrayCallBacks { }

#[link(name = "CoreServices", kind = "framework")]
extern "C" {
    pub static kCFTypeArrayCallBacks: CFArrayCallBacks;
    pub static kCFRunLoopDefaultMode: CFStringRef;

    pub fn CFRelease(res: CFRef);
    pub fn CFShow(res: CFRef);
    pub fn CFCopyDescription(cf: CFRef) -> CFStringRef;

    pub fn CFRunLoopRun();
    pub fn CFRunLoopStop(run_loop: CFRunLoopRef);
    pub fn CFRunLoopGetCurrent() -> CFRunLoopRef;

    pub fn CFArrayCreateMutable(
        allocator: CFRef,
        capacity: CFIndex,
        callbacks: *const CFArrayCallBacks,
    ) -> CFMutableArrayRef;
    pub fn CFArrayInsertValueAtIndex(arr: CFMutableArrayRef, position: CFIndex, element: CFRef);
    pub fn CFArrayAppendValue(aff: CFMutableArrayRef, element: CFRef);
    pub fn CFArrayGetCount(arr: CFMutableArrayRef) -> CFIndex;
    pub fn CFArrayGetValueAtIndex(arr: CFMutableArrayRef, index: CFIndex) -> CFRef;

    pub fn CFURLCreateFileReferenceURL(
        allocator: CFRef,
        url: CFURLRef,
        err: *mut CFErrorRef,
    ) -> CFURLRef;
    pub fn CFURLCreateFilePathURL(
        allocator: CFRef,
        url: CFURLRef,
        err: *mut CFErrorRef,
    ) -> CFURLRef;
    pub fn CFURLCreateFromFileSystemRepresentation(
        allocator: CFRef,
        path: *const ::std::os::raw::c_char,
        len: CFIndex,
        is_directory: bool,
    ) -> CFURLRef;
    pub fn CFURLCopyAbsoluteURL(res: CFURLRef) -> CFURLRef;
    pub fn CFURLCopyLastPathComponent(res: CFURLRef) -> CFStringRef;
    pub fn CFURLCreateCopyDeletingLastPathComponent(allocator: CFRef, url: CFURLRef) -> CFURLRef;
    pub fn CFURLCreateCopyAppendingPathComponent(
        allocation: CFRef,
        url: CFURLRef,
        path: CFStringRef,
        is_directory: bool,
    ) -> CFURLRef;
    pub fn CFURLCopyFileSystemPath(anUrl: CFURLRef, path_style: CFURLPathStyle) -> CFStringRef;

    pub fn CFURLResourceIsReachable(res: CFURLRef, err: *mut CFErrorRef) -> bool;

    pub fn CFShowStr(str: CFStringRef);
    pub fn CFStringGetCString(
        theString: CFStringRef,
        buffer: *mut ::std::os::raw::c_char,
        buffer_size: CFIndex,
        encoding: CFStringEncoding,
    ) -> bool;
    pub fn CFStringGetCStringPtr(
        theString: CFStringRef,
        encoding: CFStringEncoding,
    ) -> *const ::std::os::raw::c_char;
    pub fn CFStringCreateWithCString(
        alloc: CFRef,
        source: *const ::std::os::raw::c_char,
        encoding: CFStringEncoding,
    ) -> CFStringRef;

    pub fn CFStringCompare(
        theString1: CFStringRef,
        theString2: CFStringRef,
        compareOptions: CFStringCompareFlags,
    ) -> CFComparisonResult;
    pub fn CFArrayRemoveValueAtIndex(theArray: CFMutableArrayRef, idx: CFIndex);

}

pub unsafe fn str_path_to_cfstring_ref(source: &str, err: &mut CFErrorRef) -> CFStringRef {
    let c_path = CString::new(source).unwrap();
    let c_len = libc::strlen(c_path.as_ptr());
    let mut url = CFURLCreateFromFileSystemRepresentation(
        kCFAllocatorDefault,
        c_path.as_ptr(),
        c_len as CFIndex,
        false,
    );
    let mut placeholder = CFURLCopyAbsoluteURL(url);
    CFRelease(url);

    let imaginary: CFRef = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);

    while !CFURLResourceIsReachable(placeholder, ptr::null_mut()) {
        let child = CFURLCopyLastPathComponent(placeholder);
        CFArrayInsertValueAtIndex(imaginary, 0, child);
        CFRelease(child);

        url = CFURLCreateCopyDeletingLastPathComponent(kCFAllocatorDefault, placeholder);
        CFRelease(placeholder);
        placeholder = url;
    }

    url = CFURLCreateFileReferenceURL(kCFAllocatorDefault, placeholder, err);
    if !err.is_null() {
        return ptr::null_mut();
    }

    CFRelease(placeholder);
    placeholder = CFURLCreateFilePathURL(kCFAllocatorDefault, url, err);
    if !err.is_null() {
        return ptr::null_mut();
    }

    CFRelease(url);

    if imaginary != kCFAllocatorDefault {
        let mut count = 0;
        while count < CFArrayGetCount(imaginary) {
            let component = CFArrayGetValueAtIndex(imaginary, count);
            url = CFURLCreateCopyAppendingPathComponent(
                kCFAllocatorDefault,
                placeholder,
                component,
                false,
            );
            CFRelease(placeholder);
            placeholder = url;
            count += 1;
        }
        CFRelease(imaginary);
    }

    let cf_path = CFURLCopyFileSystemPath(placeholder, kCFURLPOSIXPathStyle);
    CFRelease(placeholder);
    cf_path
}
<commit_msg>Fix leaking resources upon errors<commit_after>#![allow(non_upper_case_globals, non_camel_case_types)]

extern crate libc;

use std::ffi::CString;
use std::ptr;
use std::str;

pub type Boolean = ::std::os::raw::c_uchar;

pub type CFRef = *mut ::std::os::raw::c_void;

pub type CFIndex = ::std::os::raw::c_long;
pub type CFTimeInterval = f64;

#[doc(hidden)]
pub enum CFError {}

pub type CFAllocatorRef = CFRef;
pub type CFMutableArrayRef = CFRef;
pub type CFURLRef = CFRef;
pub type CFErrorRef = *mut CFError;
pub type CFStringRef = CFRef;
pub type CFRunLoopRef = CFRef;

pub const NULL: CFRef = 0 as CFRef;
pub const NULL_REF_PTR: *mut CFRef = 0 as *mut CFRef;

pub type CFAllocatorRetainCallBack =
    extern "C" fn(*const ::std::os::raw::c_void) -> *const ::std::os::raw::c_void;
pub type CFAllocatorReleaseCallBack = extern "C" fn(*const ::std::os::raw::c_void);
pub type CFAllocatorCopyDescriptionCallBack =
    extern "C" fn(*const ::std::os::raw::c_void) -> *const CFStringRef;

pub type CFURLPathStyle = CFIndex;

pub const kCFAllocatorDefault: CFAllocatorRef = NULL;
pub const kCFURLPOSIXPathStyle: CFURLPathStyle = 0;
pub const kCFURLHFSPathStyle: CFURLPathStyle = 1;
pub const kCFURLWindowsPathStyle: CFURLPathStyle = 2;

pub const kCFStringEncodingUTF8: CFStringEncoding = 0x08000100;
pub type CFStringEncoding = u32;

pub const kCFCompareEqualTo: CFIndex = 0;
pub type CFComparisonResult = CFIndex;

// MacOS uses Case Insensitive path
pub const kCFCompareCaseInsensitive: CFStringCompareFlags = 1;
pub type CFStringCompareFlags = ::std::os::raw::c_ulong;

pub type CFArrayRetainCallBack =
    extern "C" fn(CFAllocatorRef, *const ::std::os::raw::c_void) -> *const ::std::os::raw::c_void;
pub type CFArrayReleaseCallBack = extern "C" fn(CFAllocatorRef, *const ::std::os::raw::c_void);
pub type CFArrayCopyDescriptionCallBack = extern "C" fn(*const ::std::os::raw::c_void) -> CFStringRef;
pub type CFArrayEqualCallBack =
    extern "C" fn(*const ::std::os::raw::c_void, *const ::std::os::raw::c_void) -> Boolean;

#[repr(C)]
pub struct CFArrayCallBacks {
    version: CFIndex,
    retain: Option<CFArrayRetainCallBack>,
    release: Option<CFArrayReleaseCallBack>,
    cp: Option<CFArrayCopyDescriptionCallBack>,
    equal: Option<CFArrayEqualCallBack>,
}
//impl Clone for CFArrayCallBacks { }

#[link(name = "CoreServices", kind = "framework")]
extern "C" {
    pub static kCFTypeArrayCallBacks: CFArrayCallBacks;
    pub static kCFRunLoopDefaultMode: CFStringRef;

    pub fn CFRelease(res: CFRef);
    pub fn CFShow(res: CFRef);
    pub fn CFCopyDescription(cf: CFRef) -> CFStringRef;

    pub fn CFRunLoopRun();
    pub fn CFRunLoopStop(run_loop: CFRunLoopRef);
    pub fn CFRunLoopGetCurrent() -> CFRunLoopRef;

    pub fn CFArrayCreateMutable(
        allocator: CFRef,
        capacity: CFIndex,
        callbacks: *const CFArrayCallBacks,
    ) -> CFMutableArrayRef;
    pub fn CFArrayInsertValueAtIndex(arr: CFMutableArrayRef, position: CFIndex, element: CFRef);
    pub fn CFArrayAppendValue(aff: CFMutableArrayRef, element: CFRef);
    pub fn CFArrayGetCount(arr: CFMutableArrayRef) -> CFIndex;
    pub fn CFArrayGetValueAtIndex(arr: CFMutableArrayRef, index: CFIndex) -> CFRef;

    pub fn CFURLCreateFileReferenceURL(
        allocator: CFRef,
        url: CFURLRef,
        err: *mut CFErrorRef,
    ) -> CFURLRef;
    pub fn CFURLCreateFilePathURL(
        allocator: CFRef,
        url: CFURLRef,
        err: *mut CFErrorRef,
    ) -> CFURLRef;
    pub fn CFURLCreateFromFileSystemRepresentation(
        allocator: CFRef,
        path: *const ::std::os::raw::c_char,
        len: CFIndex,
        is_directory: bool,
    ) -> CFURLRef;
    pub fn CFURLCopyAbsoluteURL(res: CFURLRef) -> CFURLRef;
    pub fn CFURLCopyLastPathComponent(res: CFURLRef) -> CFStringRef;
    pub fn CFURLCreateCopyDeletingLastPathComponent(allocator: CFRef, url: CFURLRef) -> CFURLRef;
    pub fn CFURLCreateCopyAppendingPathComponent(
        allocation: CFRef,
        url: CFURLRef,
        path: CFStringRef,
        is_directory: bool,
    ) -> CFURLRef;
    pub fn CFURLCopyFileSystemPath(anUrl: CFURLRef, path_style: CFURLPathStyle) -> CFStringRef;

    pub fn CFURLResourceIsReachable(res: CFURLRef, err: *mut CFErrorRef) -> bool;

    pub fn CFShowStr(str: CFStringRef);
    pub fn CFStringGetCString(
        theString: CFStringRef,
        buffer: *mut ::std::os::raw::c_char,
        buffer_size: CFIndex,
        encoding: CFStringEncoding,
    ) -> bool;
    pub fn CFStringGetCStringPtr(
        theString: CFStringRef,
        encoding: CFStringEncoding,
    ) -> *const ::std::os::raw::c_char;
    pub fn CFStringCreateWithCString(
        alloc: CFRef,
        source: *const ::std::os::raw::c_char,
        encoding: CFStringEncoding,
    ) -> CFStringRef;

    pub fn CFStringCompare(
        theString1: CFStringRef,
        theString2: CFStringRef,
        compareOptions: CFStringCompareFlags,
    ) -> CFComparisonResult;
    pub fn CFArrayRemoveValueAtIndex(theArray: CFMutableArrayRef, idx: CFIndex);
}

pub unsafe fn str_path_to_cfstring_ref(source: &str, err: &mut CFErrorRef) -> CFStringRef {
    let c_path = CString::new(source).unwrap();
    let c_len = libc::strlen(c_path.as_ptr());
    let mut url = CFURLCreateFromFileSystemRepresentation(
        kCFAllocatorDefault,
        c_path.as_ptr(),
        c_len as CFIndex,
        false,
    );
    if url.is_null() {
        return ptr::null_mut();
    }
    let mut placeholder = CFURLCopyAbsoluteURL(url);
    CFRelease(url);

    let mut imaginary = ptr::null_mut();

    while !CFURLResourceIsReachable(placeholder.0, ptr::null_mut()) {
        if imaginary.is_null() {
            imaginary = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);
            if imaginary.is_null() {
                CFRelease(placeholder);
                return ptr::null_mut();
            }
        }

        let child = CFURLCopyLastPathComponent(placeholder);
        CFArrayInsertValueAtIndex(imaginary, 0, child);
        CFRelease(child);

        url = CFURLCreateCopyDeletingLastPathComponent(kCFAllocatorDefault, placeholder);
        CFRelease(placeholder);
        placeholder = url;
    }

    url = CFURLCreateFileReferenceURL(kCFAllocatorDefault, placeholder, err);
    CFRelease(placeholder);
    if url.is_null() {
        if !imaginary.is_null() {
            CFRelease(imaginary);
        }
        return ptr::null_mut();
    }

    placeholder = CFURLCreateFilePathURL(kCFAllocatorDefault, url, err);
    CFRelease(url);
    if placeholder.is_null() {
        if !imaginary.is_null() {
            CFRelease(imaginary);
        }
        return ptr::null_mut();
    }

    if !imaginary.is_null() {
        let mut count = 0;
        while count < CFArrayGetCount(imaginary) {
            let component = CFArrayGetValueAtIndex(imaginary, count);
            url = CFURLCreateCopyAppendingPathComponent(
                kCFAllocatorDefault,
                placeholder,
                component,
                false,
            );
            CFRelease(placeholder);
            if url.is_null() {
                CFRelease(imaginary);
                return ptr::null_mut();
            }
            placeholder = url;
            count += 1;
        }
        CFRelease(imaginary);
    }

    let cf_path = CFURLCopyFileSystemPath(placeholder, kCFURLPOSIXPathStyle);
    CFRelease(placeholder);
    cf_path
}
<|endoftext|>


<commit_before>//! Functions and types used by generated protobuf code.
//!
//! Should rarely be used by programs written by hands.
use std::default::Default;

pub use crate::cached_size::CachedSize;
use crate::coded_input_stream::CodedInputStream;
use crate::coded_output_stream::CodedOutputStream;
use crate::enums::Enum;
use crate::error::Result;
pub use crate::lazy::Lazy;
use crate::varint::encoded_varint64_len;
pub use crate::wire_format::WireType;
use crate::zigzag::*;
use crate::EnumOrUnknown;
use crate::Message;
use crate::MessageField;

pub(crate) mod map;
pub(crate) mod repeated;
pub(crate) mod unsorted;
pub use map::compute_map_size;
pub use map::read_map_into;
pub use map::write_map_with_cached_sizes;
pub use repeated::read_repeated_packed_enum_or_unknown_into;
pub use unsorted::read_unknown_or_skip_group;
pub use unsorted::unknown_fields_size;

/// Given `u64` value compute varint encoded length.
pub fn compute_raw_varint64_size(value: u64) -> u64 {
    encoded_varint64_len(value) as u64
}

/// Given `u32` value compute varint encoded length.
pub fn compute_raw_varint32_size(value: u32) -> u64 {
    compute_raw_varint64_size(value as u64)
}

/// Given `usize` value compute varint encoded length.
pub fn compute_raw_varint_usize_size(value: usize) -> u64 {
    compute_raw_varint64_size(value as u64)
}

/// Fixed size integers.
pub trait ProtobufFixed {
    /// Size of this fixed type in bytes.
    const LEN: u32;
}

/// Helper trait implemented by integer types which could be encoded as varint.
pub trait ProtobufVarint {
    /// Size of self when encoded as varint.
    fn len_varint(&self) -> u64;
}

/// Helper trait implemented by integer types which could be encoded as zigzag varint.
pub trait ProtobufVarintZigzag {
    /// Size of self when encoded as zigzag varint.
    fn len_varint_zigzag(&self) -> u64;
}

impl ProtobufVarint for u64 {
    fn len_varint(&self) -> u64 {
        compute_raw_varint64_size(*self)
    }
}

impl ProtobufVarint for u32 {
    fn len_varint(&self) -> u64 {
        (*self as u64).len_varint()
    }
}

impl ProtobufVarint for i64 {
    fn len_varint(&self) -> u64 {
        // same as length of u64
        (*self as u64).len_varint()
    }
}

impl ProtobufVarintZigzag for i64 {
    fn len_varint_zigzag(&self) -> u64 {
        compute_raw_varint64_size(encode_zig_zag_64(*self))
    }
}

impl ProtobufVarint for i32 {
    fn len_varint(&self) -> u64 {
        // sign-extend and then compute
        (*self as i64).len_varint()
    }
}

impl ProtobufVarintZigzag for i32 {
    fn len_varint_zigzag(&self) -> u64 {
        compute_raw_varint32_size(encode_zig_zag_32(*self))
    }
}

impl ProtobufVarint for bool {
    fn len_varint(&self) -> u64 {
        1
    }
}

impl ProtobufFixed for u32 {
    const LEN: u32 = 4;
}

impl ProtobufFixed for i32 {
    const LEN: u32 = 4;
}

impl ProtobufFixed for u64 {
    const LEN: u32 = 8;
}

impl ProtobufFixed for i64 {
    const LEN: u32 = 8;
}

impl ProtobufFixed for f32 {
    const LEN: u32 = 4;
}

impl ProtobufFixed for f64 {
    const LEN: u32 = 8;
}

/// Technically `bool` is not fixed, but it can be considered as fixed
/// for the purpose of encoding.
impl ProtobufFixed for bool {
    const LEN: u32 = 1;
}

/// Size of serialized repeated packed field, excluding length and tag.
pub fn vec_packed_varint_data_size<T: ProtobufVarint>(vec: &[T]) -> u64 {
    vec.iter()
        .map(|v| v.len_varint() as u64)
        .fold(0, |a, i| a + i)
}

/// Size of serialized repeated packed field, excluding length and tag.
pub fn vec_packed_varint_zigzag_data_size<T: ProtobufVarintZigzag>(vec: &[T]) -> u64 {
    vec.iter()
        .map(|v| v.len_varint_zigzag())
        .fold(0, |a, i| a + i)
}

/// Size of serialized repeated packed enum field, excluding length and tag.
pub fn vec_packed_enum_or_unknown_data_size<E: Enum>(vec: &[EnumOrUnknown<E>]) -> u64 {
    vec.iter()
        .map(|e| compute_raw_varint32_size(e.value() as u32))
        .fold(0, |a, i| a + i)
}

/// Size of serialized data with length prefix and tag
pub fn vec_packed_varint_size<T: ProtobufVarint>(field_number: u32, vec: &[T]) -> u64 {
    if vec.is_empty() {
        0
    } else {
        let data_size = vec_packed_varint_data_size(vec);
        tag_size(field_number) + data_size.len_varint() + data_size
    }
}

/// Size of serialized data with length prefix and tag
pub fn vec_packed_varint_zigzag_size<T: ProtobufVarintZigzag>(field_number: u32, vec: &[T]) -> u64 {
    if vec.is_empty() {
        0
    } else {
        let data_size = vec_packed_varint_zigzag_data_size(vec);
        tag_size(field_number) + data_size.len_varint() + data_size
    }
}

/// Size of serialized data with length prefix and tag
pub fn vec_packed_enum_or_unknown_size<E: Enum>(
    field_number: u32,
    vec: &[EnumOrUnknown<E>],
) -> u64 {
    if vec.is_empty() {
        0
    } else {
        let data_size = vec_packed_enum_or_unknown_data_size(vec);
        tag_size(field_number) + data_size.len_varint() + data_size
    }
}

/// Compute data size of fixed encoding of repeated field data.
pub(crate) fn vec_packed_fixed_data_size<V: ProtobufFixed>(vec: &[V]) -> u64 {
    (vec.len() as u64) * (V::LEN as u64)
}

/// Compute field size (data plus header) of fixed encoding of repeated field.
pub fn vec_packed_fixed_size<V: ProtobufFixed>(field_number: u32, vec: &[V]) -> u64 {
    if vec.is_empty() {
        0
    } else {
        let data_size = vec_packed_fixed_data_size::<V>(vec);
        tag_size(field_number) + data_size.len_varint() + data_size
    }
}

/// Compute tag size. Size of tag does not depend on wire type.
pub fn tag_size(field_number: u32) -> u64 {
    encoded_varint64_len((field_number as u64) << 3) as u64
}

fn value_size_no_tag<T: ProtobufVarint>(value: T, wt: WireType) -> u64 {
    match wt {
        WireType::Fixed64 => 8,
        WireType::Fixed32 => 4,
        WireType::Varint => value.len_varint(),
        _ => panic!(),
    }
}

/// Integer value size when encoded as specified wire type.
pub fn value_size<T: ProtobufVarint>(field_number: u32, value: T, wt: WireType) -> u64 {
    tag_size(field_number) + value_size_no_tag(value, wt)
}

/// Integer value size when encoded as specified wire type.
pub(crate) fn value_varint_zigzag_size_no_tag<T: ProtobufVarintZigzag>(value: T) -> u64 {
    value.len_varint_zigzag()
}

/// Length of value when encoding with zigzag encoding with tag
pub fn value_varint_zigzag_size<T: ProtobufVarintZigzag>(field_number: u32, value: T) -> u64 {
    tag_size(field_number) + value_varint_zigzag_size_no_tag(value)
}

fn enum_or_unknown_size_no_tag<E: Enum>(value: EnumOrUnknown<E>) -> u64 {
    value.value().len_varint() as u64
}

/// Size of encoded enum field value.
pub fn enum_or_unknown_size<E: Enum>(field_number: u32, value: EnumOrUnknown<E>) -> u64 {
    tag_size(field_number) + enum_or_unknown_size_no_tag(value)
}

/// Size of encoded bytes field.
pub(crate) fn bytes_size_no_tag(bytes: &[u8]) -> u64 {
    compute_raw_varint64_size(bytes.len() as u64) + bytes.len() as u64
}

/// Size of encoded bytes field.
pub fn bytes_size(field_number: u32, bytes: &[u8]) -> u64 {
    tag_size(field_number) + bytes_size_no_tag(bytes)
}

/// Size of encoded string field.
pub(crate) fn string_size_no_tag(s: &str) -> u64 {
    bytes_size_no_tag(s.as_bytes())
}

/// Size of encoded string field.
pub fn string_size(field_number: u32, s: &str) -> u64 {
    tag_size(field_number) + string_size_no_tag(s)
}

/// Read singular `message` field.
pub fn read_singular_message_into_field<M>(
    is: &mut CodedInputStream,
    target: &mut MessageField<M>,
) -> Result<()>
where
    M: Message + Default,
{
    let mut m = M::new();
    is.merge_message(&mut m)?;
    *target = MessageField::some(m);
    Ok(())
}

/// Write message with field number and length to the stream.
pub fn write_message_field_with_cached_size<M>(
    field_number: u32,
    message: &M,
    os: &mut CodedOutputStream,
) -> Result<()>
where
    M: Message,
{
    os.write_tag(field_number, WireType::LengthDelimited)?;
    os.write_raw_varint32(message.cached_size())?;
    message.write_to_with_cached_sizes(os)
}
<commit_msg>`mod rt` is not public API<commit_after>//! # Functions and types used by generated protobuf code
//!
//! These are not considered to be public API of rust-protobuf,
//! so they can be changed any time (provided compatibility with
//! previously generated code is preserved).
use std::default::Default;

pub use crate::cached_size::CachedSize;
use crate::coded_input_stream::CodedInputStream;
use crate::coded_output_stream::CodedOutputStream;
use crate::enums::Enum;
use crate::error::Result;
pub use crate::lazy::Lazy;
use crate::varint::encoded_varint64_len;
pub use crate::wire_format::WireType;
use crate::zigzag::*;
use crate::EnumOrUnknown;
use crate::Message;
use crate::MessageField;

pub(crate) mod map;
pub(crate) mod repeated;
pub(crate) mod unsorted;
pub use map::compute_map_size;
pub use map::read_map_into;
pub use map::write_map_with_cached_sizes;
pub use repeated::read_repeated_packed_enum_or_unknown_into;
pub use unsorted::read_unknown_or_skip_group;
pub use unsorted::unknown_fields_size;

/// Given `u64` value compute varint encoded length.
pub fn compute_raw_varint64_size(value: u64) -> u64 {
    encoded_varint64_len(value) as u64
}

/// Given `u32` value compute varint encoded length.
pub fn compute_raw_varint32_size(value: u32) -> u64 {
    compute_raw_varint64_size(value as u64)
}

/// Given `usize` value compute varint encoded length.
pub fn compute_raw_varint_usize_size(value: usize) -> u64 {
    compute_raw_varint64_size(value as u64)
}

/// Fixed size integers.
pub trait ProtobufFixed {
    /// Size of this fixed type in bytes.
    const LEN: u32;
}

/// Helper trait implemented by integer types which could be encoded as varint.
pub trait ProtobufVarint {
    /// Size of self when encoded as varint.
    fn len_varint(&self) -> u64;
}

/// Helper trait implemented by integer types which could be encoded as zigzag varint.
pub trait ProtobufVarintZigzag {
    /// Size of self when encoded as zigzag varint.
    fn len_varint_zigzag(&self) -> u64;
}

impl ProtobufVarint for u64 {
    fn len_varint(&self) -> u64 {
        compute_raw_varint64_size(*self)
    }
}

impl ProtobufVarint for u32 {
    fn len_varint(&self) -> u64 {
        (*self as u64).len_varint()
    }
}

impl ProtobufVarint for i64 {
    fn len_varint(&self) -> u64 {
        // same as length of u64
        (*self as u64).len_varint()
    }
}

impl ProtobufVarintZigzag for i64 {
    fn len_varint_zigzag(&self) -> u64 {
        compute_raw_varint64_size(encode_zig_zag_64(*self))
    }
}

impl ProtobufVarint for i32 {
    fn len_varint(&self) -> u64 {
        // sign-extend and then compute
        (*self as i64).len_varint()
    }
}

impl ProtobufVarintZigzag for i32 {
    fn len_varint_zigzag(&self) -> u64 {
        compute_raw_varint32_size(encode_zig_zag_32(*self))
    }
}

impl ProtobufVarint for bool {
    fn len_varint(&self) -> u64 {
        1
    }
}

impl ProtobufFixed for u32 {
    const LEN: u32 = 4;
}

impl ProtobufFixed for i32 {
    const LEN: u32 = 4;
}

impl ProtobufFixed for u64 {
    const LEN: u32 = 8;
}

impl ProtobufFixed for i64 {
    const LEN: u32 = 8;
}

impl ProtobufFixed for f32 {
    const LEN: u32 = 4;
}

impl ProtobufFixed for f64 {
    const LEN: u32 = 8;
}

/// Technically `bool` is not fixed, but it can be considered as fixed
/// for the purpose of encoding.
impl ProtobufFixed for bool {
    const LEN: u32 = 1;
}

/// Size of serialized repeated packed field, excluding length and tag.
pub fn vec_packed_varint_data_size<T: ProtobufVarint>(vec: &[T]) -> u64 {
    vec.iter()
        .map(|v| v.len_varint() as u64)
        .fold(0, |a, i| a + i)
}

/// Size of serialized repeated packed field, excluding length and tag.
pub fn vec_packed_varint_zigzag_data_size<T: ProtobufVarintZigzag>(vec: &[T]) -> u64 {
    vec.iter()
        .map(|v| v.len_varint_zigzag())
        .fold(0, |a, i| a + i)
}

/// Size of serialized repeated packed enum field, excluding length and tag.
pub fn vec_packed_enum_or_unknown_data_size<E: Enum>(vec: &[EnumOrUnknown<E>]) -> u64 {
    vec.iter()
        .map(|e| compute_raw_varint32_size(e.value() as u32))
        .fold(0, |a, i| a + i)
}

/// Size of serialized data with length prefix and tag
pub fn vec_packed_varint_size<T: ProtobufVarint>(field_number: u32, vec: &[T]) -> u64 {
    if vec.is_empty() {
        0
    } else {
        let data_size = vec_packed_varint_data_size(vec);
        tag_size(field_number) + data_size.len_varint() + data_size
    }
}

/// Size of serialized data with length prefix and tag
pub fn vec_packed_varint_zigzag_size<T: ProtobufVarintZigzag>(field_number: u32, vec: &[T]) -> u64 {
    if vec.is_empty() {
        0
    } else {
        let data_size = vec_packed_varint_zigzag_data_size(vec);
        tag_size(field_number) + data_size.len_varint() + data_size
    }
}

/// Size of serialized data with length prefix and tag
pub fn vec_packed_enum_or_unknown_size<E: Enum>(
    field_number: u32,
    vec: &[EnumOrUnknown<E>],
) -> u64 {
    if vec.is_empty() {
        0
    } else {
        let data_size = vec_packed_enum_or_unknown_data_size(vec);
        tag_size(field_number) + data_size.len_varint() + data_size
    }
}

/// Compute data size of fixed encoding of repeated field data.
pub(crate) fn vec_packed_fixed_data_size<V: ProtobufFixed>(vec: &[V]) -> u64 {
    (vec.len() as u64) * (V::LEN as u64)
}

/// Compute field size (data plus header) of fixed encoding of repeated field.
pub fn vec_packed_fixed_size<V: ProtobufFixed>(field_number: u32, vec: &[V]) -> u64 {
    if vec.is_empty() {
        0
    } else {
        let data_size = vec_packed_fixed_data_size::<V>(vec);
        tag_size(field_number) + data_size.len_varint() + data_size
    }
}

/// Compute tag size. Size of tag does not depend on wire type.
pub fn tag_size(field_number: u32) -> u64 {
    encoded_varint64_len((field_number as u64) << 3) as u64
}

fn value_size_no_tag<T: ProtobufVarint>(value: T, wt: WireType) -> u64 {
    match wt {
        WireType::Fixed64 => 8,
        WireType::Fixed32 => 4,
        WireType::Varint => value.len_varint(),
        _ => panic!(),
    }
}

/// Integer value size when encoded as specified wire type.
pub fn value_size<T: ProtobufVarint>(field_number: u32, value: T, wt: WireType) -> u64 {
    tag_size(field_number) + value_size_no_tag(value, wt)
}

/// Integer value size when encoded as specified wire type.
pub(crate) fn value_varint_zigzag_size_no_tag<T: ProtobufVarintZigzag>(value: T) -> u64 {
    value.len_varint_zigzag()
}

/// Length of value when encoding with zigzag encoding with tag
pub fn value_varint_zigzag_size<T: ProtobufVarintZigzag>(field_number: u32, value: T) -> u64 {
    tag_size(field_number) + value_varint_zigzag_size_no_tag(value)
}

fn enum_or_unknown_size_no_tag<E: Enum>(value: EnumOrUnknown<E>) -> u64 {
    value.value().len_varint() as u64
}

/// Size of encoded enum field value.
pub fn enum_or_unknown_size<E: Enum>(field_number: u32, value: EnumOrUnknown<E>) -> u64 {
    tag_size(field_number) + enum_or_unknown_size_no_tag(value)
}

/// Size of encoded bytes field.
pub(crate) fn bytes_size_no_tag(bytes: &[u8]) -> u64 {
    compute_raw_varint64_size(bytes.len() as u64) + bytes.len() as u64
}

/// Size of encoded bytes field.
pub fn bytes_size(field_number: u32, bytes: &[u8]) -> u64 {
    tag_size(field_number) + bytes_size_no_tag(bytes)
}

/// Size of encoded string field.
pub(crate) fn string_size_no_tag(s: &str) -> u64 {
    bytes_size_no_tag(s.as_bytes())
}

/// Size of encoded string field.
pub fn string_size(field_number: u32, s: &str) -> u64 {
    tag_size(field_number) + string_size_no_tag(s)
}

/// Read singular `message` field.
pub fn read_singular_message_into_field<M>(
    is: &mut CodedInputStream,
    target: &mut MessageField<M>,
) -> Result<()>
where
    M: Message + Default,
{
    let mut m = M::new();
    is.merge_message(&mut m)?;
    *target = MessageField::some(m);
    Ok(())
}

/// Write message with field number and length to the stream.
pub fn write_message_field_with_cached_size<M>(
    field_number: u32,
    message: &M,
    os: &mut CodedOutputStream,
) -> Result<()>
where
    M: Message,
{
    os.write_tag(field_number, WireType::LengthDelimited)?;
    os.write_raw_varint32(message.cached_size())?;
    message.write_to_with_cached_sizes(os)
}
<|endoftext|>


<commit_before>// check-pass

#![feature(array_value_iter)]
#![feature(trusted_len)]

use std::{
    array::IntoIter,
    fmt::Debug,
    iter::{ExactSizeIterator, FusedIterator, TrustedLen},
};

pub fn yes_iterator() -> impl Iterator<Item = i32> {
    IntoIter::new([0i32; 32])
}

pub fn yes_double_ended_iterator() -> impl DoubleEndedIterator {
    IntoIter::new([0i32; 32])
}

pub fn yes_exact_size_iterator() -> impl ExactSizeIterator {
    IntoIter::new([0i32; 32])
}

pub fn yes_fused_iterator() -> impl FusedIterator {
    IntoIter::new([0i32; 32])
}

pub fn yes_trusted_len() -> impl TrustedLen {
    IntoIter::new([0i32; 32])
}

pub fn yes_clone() -> impl Clone {
    IntoIter::new([0i32; 32])
}

pub fn yes_debug() -> impl Debug {
    IntoIter::new([0i32; 32])
}

fn main() {}
<commit_msg>Fix copypaste in test into-iter-impls-length-33 (const generic 32 -> 33)<commit_after>// check-pass

#![feature(array_value_iter)]
#![feature(trusted_len)]

use std::{
    array::IntoIter,
    fmt::Debug,
    iter::{ExactSizeIterator, FusedIterator, TrustedLen},
};

pub fn yes_iterator() -> impl Iterator<Item = i32> {
    IntoIter::new([0i32; 33])
}

pub fn yes_double_ended_iterator() -> impl DoubleEndedIterator {
    IntoIter::new([0i32; 33])
}

pub fn yes_exact_size_iterator() -> impl ExactSizeIterator {
    IntoIter::new([0i32; 33])
}

pub fn yes_fused_iterator() -> impl FusedIterator {
    IntoIter::new([0i32; 33])
}

pub fn yes_trusted_len() -> impl TrustedLen {
    IntoIter::new([0i32; 33])
}

pub fn yes_clone() -> impl Clone {
    IntoIter::new([0i32; 33])
}

pub fn yes_debug() -> impl Debug {
    IntoIter::new([0i32; 33])
}

fn main() {}
<|endoftext|>


<commit_before>use std::rc::Rc;

use Message;
use state::State;
use TimerEvent;

#[derive(Clone, Debug)]
pub struct Conditions {
    pub timeout: u32,
    pub renew_timeout: Option<u32>,
    pub first_opens: Option<bool>,
    pub last_closes: Option<bool>,
    pub max_size: Option<usize>,
    pub patterns: Vec<String>
}

impl Conditions {
    fn new(timeout: u32) -> Conditions {
        Conditions {
            timeout: timeout,
            renew_timeout: None,
            first_opens: None,
            last_closes: None,
            max_size: None,
            patterns: Vec::new()
        }
    }

    pub fn on_message(&mut self, message: Rc<Message>, state: &mut State) {
        if !self.patterns.contains(message.get("uuid").unwrap()) && self.patterns.len() > 0 {
            println!("ignoring");
            return;
        }

        if state.is_open() {
            state.add_message(message);
            if self.is_closing(state) {
                state.close()
            }
        } else if self.is_opening(&message) {
            state.add_message(message);
            state.open();
        }
    }

    fn is_max_size_reached(&self, state: &State) -> bool {
        self.max_size.map_or(false, |max_size| state.messages().len() >= max_size)
    }

    fn is_closing_message(&self, state: &State) -> bool {
        self.last_closes.map_or(false, |closes| {
            if closes {
                self.patterns.last().map_or(false, |pattern| {
                    pattern == state.messages().last().unwrap().get("uuid").unwrap()
                })
            } else {
                false
            }
        })
    }

    fn is_opening(&self, message: &Message) -> bool {
        let found = self.patterns.contains(message.get("uuid").unwrap());
        println!("found: {}", found);
        self.first_opens.map_or(found, |first| {
            if first {
                self.patterns.first().map_or(false, |pattern| {
                    pattern == message.get("uuid").unwrap()
                })
            } else {
                found
            }
        })
    }

    fn is_closing(&self, state: &State) -> bool {
        println!("checking close");
        self.is_max_size_reached(state) || self.is_closing_message(state)
    }

    pub fn on_timer(&mut self, event: &TimerEvent, state: &mut State) {
        state.on_timer(event);
        if self.is_any_timer_expired(state) {
            println!("closing state");
            state.close()
        }
    }

    fn is_timeout_expired(&self, state: &State) -> bool {
        state.elapsed_time() >= self.timeout
    }

    fn is_renew_timeout_expired(&self, state: &State) -> bool {
        self.renew_timeout.map_or(false, |renew_timeout| {
            state.elapsed_time_since_last_message() >= renew_timeout
        })
    }

    fn is_any_timer_expired(&self, state: &State) -> bool {
        self.is_timeout_expired(state) || self.is_renew_timeout_expired(state)
    }
}

pub struct Builder {
    conditions: Conditions
}

impl Builder {
    pub fn new(timeout: u32) -> Builder {
        Builder{
            conditions: Conditions::new(timeout)
        }
    }

    pub fn renew_timeout(&mut self, timeout: u32) -> &mut Builder {
        self.conditions.renew_timeout = Some(timeout);
        self
    }

    pub fn first_opens(&mut self, first_opens: bool) -> &mut Builder {
        self.conditions.first_opens = Some(first_opens);
        self
    }

    pub fn last_closes(&mut self, last_closes: bool) -> &mut Builder {
        self.conditions.last_closes = Some(last_closes);
        self
    }
    pub fn max_size(&mut self, max_size: usize) -> &mut Builder {
        self.conditions.max_size = Some(max_size);
        self
    }

    pub fn patterns(&mut self, patterns: Vec<String>) -> &mut Builder {
        self.conditions.patterns = patterns;
        self
    }

    pub fn build(&mut self) -> Conditions {
        self.conditions.clone()
    }
}
<commit_msg>small refactors<commit_after>use std::rc::Rc;

use Message;
use MiliSec;
use state::State;
use TimerEvent;

#[derive(Clone, Debug)]
pub struct Conditions {
    pub timeout: u32,
    pub renew_timeout: Option<u32>,
    pub first_opens: Option<bool>,
    pub last_closes: Option<bool>,
    pub max_size: Option<usize>,
    pub patterns: Vec<String>
}

impl Conditions {
    fn new(timeout: u32) -> Conditions {
        Conditions {
            timeout: timeout,
            renew_timeout: None,
            first_opens: None,
            last_closes: None,
            max_size: None,
            patterns: Vec::new()
        }
    }

    pub fn on_message(&mut self, message: Rc<Message>, state: &mut State) {
        if self.ignore_message(&message) {
            println!("ignoring");
            return;
        }

        if state.is_open() {
            state.add_message(message);
            if self.is_closing(state) {
                state.close()
            }
        } else if self.is_opening(&message) {
            state.add_message(message);
            state.open();
        }
    }

    fn ignore_message(&self, message: &Message) -> bool {
        !self.patterns.contains(message.get("uuid").unwrap()) && self.patterns.len() > 0
    }

    fn is_opening(&self, message: &Message) -> bool {
        self.first_opens.map_or(true, |first| {
            if first {
                self.patterns.first().unwrap() == message.get("uuid").unwrap()
            } else {
                true
            }
        })
    }

    fn is_max_size_reached(&self, state: &State) -> bool {
        self.max_size.map_or(false, |max_size| state.messages().len() >= max_size)
    }

    fn is_closing_message(&self, state: &State) -> bool {
        self.last_closes.map_or(false, |closes| {
            if closes {
                self.patterns.last().map_or(false, |pattern| {
                    pattern == state.messages().last().unwrap().get("uuid").unwrap()
                })
            } else {
                false
            }
        })
    }

    fn is_closing(&self, state: &State) -> bool {
        println!("checking close");
        self.is_max_size_reached(state) || self.is_closing_message(state)
    }

    pub fn on_timer(&mut self, event: &TimerEvent, state: &mut State) {
        state.on_timer(event);
        if self.is_any_timer_expired(state) {
            println!("closing state");
            state.close()
        }
    }

    fn is_timeout_expired(&self, state: &State) -> bool {
        state.elapsed_time() >= self.timeout
    }

    fn is_renew_timeout_expired(&self, state: &State) -> bool {
        self.renew_timeout.map_or(false, |renew_timeout| {
            state.elapsed_time_since_last_message() >= renew_timeout
        })
    }

    fn is_any_timer_expired(&self, state: &State) -> bool {
        self.is_timeout_expired(state) || self.is_renew_timeout_expired(state)
    }
}

pub struct Builder {
    conditions: Conditions
}

impl Builder {
    pub fn new(timeout: u32) -> Builder {
        Builder{
            conditions: Conditions::new(timeout)
        }
    }

    pub fn renew_timeout(&mut self, timeout: u32) -> &mut Builder {
        self.conditions.renew_timeout = Some(timeout);
        self
    }

    pub fn first_opens(&mut self, first_opens: bool) -> &mut Builder {
        self.conditions.first_opens = Some(first_opens);
        self
    }

    pub fn last_closes(&mut self, last_closes: bool) -> &mut Builder {
        self.conditions.last_closes = Some(last_closes);
        self
    }
    pub fn max_size(&mut self, max_size: usize) -> &mut Builder {
        self.conditions.max_size = Some(max_size);
        self
    }

    pub fn patterns(&mut self, patterns: Vec<String>) -> &mut Builder {
        self.conditions.patterns = patterns;
        self
    }

    pub fn build(&mut self) -> Conditions {
        self.conditions.clone()
    }
}
<|endoftext|>


<commit_before>use std::io;
use std::io::{Read, Write};
use std::net::TcpStream;
#[cfg(unix)]
use std::os::unix::net::UnixStream;
use url::Url;
#[cfg(unix)]
use url::Host;
use error::MemcacheError;

enum Stream {
    TcpStream(TcpStream),
    #[cfg(unix)]
    UnixStream(UnixStream),
}

/// The connection acts as a TCP connection to the memcached server
pub struct Connection {
    stream: Stream,
    pub url: String,
}

impl Connection {
    pub fn connect(addr: &str) -> Result<Self, MemcacheError> {
        let addr = match Url::parse(addr) {
            Ok(v) => v,
            Err(_) => return Err(MemcacheError::ClientError("Invalid memcache URL".into())),
        };
        if addr.scheme() != "memcache" {
            return Err(MemcacheError::ClientError(
                "memcache URL should start with 'memcache://'".into(),
            ));
        }
        #[cfg(unix)]
        {
            if addr.host() == Some(Host::Domain("")) && addr.port() == None {
                let stream = UnixStream::connect(addr.path())?;
                return Ok(Connection {
                    url: addr.into_string(),
                    stream: Stream::UnixStream(stream),
                });
            }
        }
        let stream = TcpStream::connect(addr.clone())?;
        return Ok(Connection {
            url: addr.into_string(),
            stream: Stream::TcpStream(stream),
        });
    }
}

impl Read for Connection {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        match self.stream {
            Stream::TcpStream(ref mut stream) => stream.read(buf),
            #[cfg(unix)]
            Stream::UnixStream(ref mut stream) => stream.read(buf),
        }
    }
}

impl Write for Connection {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        match self.stream {
            Stream::TcpStream(ref mut stream) => stream.write(buf),
            #[cfg(unix)]
            Stream::UnixStream(ref mut stream) => stream.write(buf),
        }
    }

    fn flush(&mut self) -> io::Result<()> {
        match self.stream {
            Stream::TcpStream(ref mut stream) => stream.flush(),
            #[cfg(unix)]
            Stream::UnixStream(ref mut stream) => stream.flush(),
        }
    }
}
<commit_msg>:zap: Support TCP_NODELAY (#18)<commit_after>use std::io;
use std::io::{Read, Write};
use std::net::TcpStream;
#[cfg(unix)]
use std::os::unix::net::UnixStream;
use url::Url;
#[cfg(unix)]
use url::Host;
use error::MemcacheError;

enum Stream {
    TcpStream(TcpStream),
    #[cfg(unix)] UnixStream(UnixStream),
}

/// The connection acts as a TCP connection to the memcached server
pub struct Connection {
    stream: Stream,
    pub url: String,
}

impl Connection {
    pub fn connect(addr: &str) -> Result<Self, MemcacheError> {
        let addr = match Url::parse(addr) {
            Ok(v) => v,
            Err(_) => return Err(MemcacheError::ClientError("Invalid memcache URL".into())),
        };
        if addr.scheme() != "memcache" {
            return Err(MemcacheError::ClientError(
                "memcache URL should start with 'memcache://'".into(),
            ));
        }
        #[cfg(unix)]
        {
            if addr.host() == Some(Host::Domain("")) && addr.port() == None {
                let stream = UnixStream::connect(addr.path())?;
                return Ok(Connection {
                    url: addr.into_string(),
                    stream: Stream::UnixStream(stream),
                });
            }
        }
        let stream = TcpStream::connect(addr.clone())?;
        let tcp_nodelay = addr.query_pairs()
            .find(|&(ref k, ref v)| k == "tcp_nodelay" && v == "true")
            .is_some();
        stream.set_nodelay(tcp_nodelay)?;
        return Ok(Connection {
            url: addr.into_string(),
            stream: Stream::TcpStream(stream),
        });
    }
}

impl Read for Connection {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        match self.stream {
            Stream::TcpStream(ref mut stream) => stream.read(buf),
            #[cfg(unix)]
            Stream::UnixStream(ref mut stream) => stream.read(buf),
        }
    }
}

impl Write for Connection {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        match self.stream {
            Stream::TcpStream(ref mut stream) => stream.write(buf),
            #[cfg(unix)]
            Stream::UnixStream(ref mut stream) => stream.write(buf),
        }
    }

    fn flush(&mut self) -> io::Result<()> {
        match self.stream {
            Stream::TcpStream(ref mut stream) => stream.flush(),
            #[cfg(unix)]
            Stream::UnixStream(ref mut stream) => stream.flush(),
        }
    }
}

#[cfg(test)]
mod tests {
    #[test]
    fn tcp_nodelay() {
        super::Connection::connect("memcache://localhost:12345?tcp_nodelay=true").unwrap();
    }
}
<|endoftext|>


<commit_before>// Copyright 2014-2016 bluss and ndarray developers.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! The data (inner representation) traits for ndarray

use std::mem;
use std::rc::Rc;

use {
    ArrayBase,
    Dimension,
    ViewRepr,
};

/// Array representation trait.
///
/// ***Note:*** `Data` is not an extension interface at this point.
/// Traits in Rust can serve many different roles. This trait is public because
/// it is used as a bound on public methods.
pub unsafe trait Data {
    /// The array element type.
    type Elem;
    #[doc(hidden)]
    // This method is only used for debugging
    fn _data_slice(&self) -> &[Self::Elem];
}

/// Array representation trait.
///
/// For an array with writable elements.
///
/// ***Internal trait, see `Data`.***
pub unsafe trait DataMut : Data {
    #[doc(hidden)]
    #[inline]
    fn ensure_unique<D>(&mut ArrayBase<Self, D>)
        where Self: Sized,
              D: Dimension
    { }

    #[doc(hidden)]
    #[inline]
    fn is_unique(&mut self) -> bool {
        true
    }
}

/// Array representation trait.
///
/// An array representation that can be cloned.
///
/// ***Internal trait, see `Data`.***
pub unsafe trait DataClone : Data {
    #[doc(hidden)]
    /// Unsafe because, `ptr` must point inside the current storage.
    unsafe fn clone_with_ptr(&self, ptr: *mut Self::Elem) -> (Self, *mut Self::Elem);
}

unsafe impl Data for Rc<Vec> {
    type Elem = A;
    fn _data_slice(&self) -> &[A] {
        self
    }
}

// NOTE: Copy on write
unsafe impl DataMut for Rc<Vec>
    where A: Clone
{
    fn ensure_unique<D>(self_: &mut ArrayBase<Self, D>)
        where Self: Sized,
              D: Dimension
    {
        if Rc::get_mut(&mut self_.data).is_some() {
            return;
        }
        if self_.dim.size() <= self_.data.len() / 2 {
            // Create a new vec if the current view is less than half of
            // backing data.
            unsafe {
                *self_ = ArrayBase::from_shape_vec_unchecked(self_.dim.clone(),
                                                             self_.iter()
                                                            .cloned()
                                                            .collect());
            }
            return;
        }
        let our_off = (self_.ptr as isize - self_.data.as_ptr() as isize) /
                      mem::size_of::() as isize;
        let rvec = Rc::make_mut(&mut self_.data);
        unsafe {
            self_.ptr = rvec.as_mut_ptr().offset(our_off);
        }
    }

    fn is_unique(&mut self) -> bool {
        Rc::get_mut(self).is_some()
    }
}

unsafe impl DataClone for Rc<Vec> {
    unsafe fn clone_with_ptr(&self, ptr: *mut Self::Elem) -> (Self, *mut Self::Elem) {
        // pointer is preserved
        (self.clone(), ptr)
    }
}

unsafe impl Data for Vec {
    type Elem = A;
    fn _data_slice(&self) -> &[A] {
        self
    }
}

unsafe impl DataMut for Vec { }

unsafe impl DataClone for Vec
    where A: Clone
{
    unsafe fn clone_with_ptr(&self, ptr: *mut Self::Elem) -> (Self, *mut Self::Elem) {
        let mut u = self.clone();
        let our_off = (self.as_ptr() as isize - ptr as isize) /
                      mem::size_of::() as isize;
        let new_ptr = u.as_mut_ptr().offset(our_off);
        (u, new_ptr)
    }
}

unsafe impl<'a, A> Data for ViewRepr<&'a A> {
    type Elem = A;
    fn _data_slice(&self) -> &[A] {
        &[]
    }
}

unsafe impl<'a, A> DataClone for ViewRepr<&'a A> {
    unsafe fn clone_with_ptr(&self, ptr: *mut Self::Elem) -> (Self, *mut Self::Elem) {
        (*self, ptr)
    }
}

unsafe impl<'a, A> Data for ViewRepr<&'a mut A> {
    type Elem = A;
    fn _data_slice(&self) -> &[A] {
        &[]
    }
}

unsafe impl<'a, A> DataMut for ViewRepr<&'a mut A> { }

/// Array representation trait.
///
/// A representation that is a unique or shared owner of its data.
///
/// ***Internal trait, see `Data`.***
pub unsafe trait DataOwned : Data {
    #[doc(hidden)]
    fn new(elements: Vec<Self::Elem>) -> Self;
    #[doc(hidden)]
    fn into_shared(self) -> Rc<Vec<Self::Elem>>;
}

/// Array representation trait.
///
/// A representation that is a lightweight view.
///
/// ***Internal trait, see `Data`.***
pub unsafe trait DataShared : Clone + DataClone { }

unsafe impl DataShared for Rc<Vec> {}
unsafe impl<'a, A> DataShared for ViewRepr<&'a A> {}

unsafe impl DataOwned for Vec {
    fn new(elements: Vec) -> Self {
        elements
    }
    fn into_shared(self) -> Rc<Vec> {
        Rc::new(self)
    }
}

unsafe impl DataOwned for Rc<Vec> {
    fn new(elements: Vec) -> Self {
        Rc::new(elements)
    }
    fn into_shared(self) -> Rc<Vec> {
        self
    }
}

<commit_msg>Fix a well-formedness issue, Data requires Sized<commit_after>// Copyright 2014-2016 bluss and ndarray developers.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! The data (inner representation) traits for ndarray

use std::mem;
use std::rc::Rc;

use {
    ArrayBase,
    Dimension,
    ViewRepr,
};

/// Array representation trait.
///
/// ***Note:*** `Data` is not an extension interface at this point.
/// Traits in Rust can serve many different roles. This trait is public because
/// it is used as a bound on public methods.
pub unsafe trait Data : Sized {
    /// The array element type.
    type Elem;
    #[doc(hidden)]
    // This method is only used for debugging
    fn _data_slice(&self) -> &[Self::Elem];
}

/// Array representation trait.
///
/// For an array with writable elements.
///
/// ***Internal trait, see `Data`.***
pub unsafe trait DataMut : Data {
    #[doc(hidden)]
    #[inline]
    fn ensure_unique<D>(&mut ArrayBase<Self, D>)
        where Self: Sized,
              D: Dimension
    { }

    #[doc(hidden)]
    #[inline]
    fn is_unique(&mut self) -> bool {
        true
    }
}

/// Array representation trait.
///
/// An array representation that can be cloned.
///
/// ***Internal trait, see `Data`.***
pub unsafe trait DataClone : Data {
    #[doc(hidden)]
    /// Unsafe because, `ptr` must point inside the current storage.
    unsafe fn clone_with_ptr(&self, ptr: *mut Self::Elem) -> (Self, *mut Self::Elem);
}

unsafe impl Data for Rc<Vec> {
    type Elem = A;
    fn _data_slice(&self) -> &[A] {
        self
    }
}

// NOTE: Copy on write
unsafe impl DataMut for Rc<Vec>
    where A: Clone
{
    fn ensure_unique<D>(self_: &mut ArrayBase<Self, D>)
        where Self: Sized,
              D: Dimension
    {
        if Rc::get_mut(&mut self_.data).is_some() {
            return;
        }
        if self_.dim.size() <= self_.data.len() / 2 {
            // Create a new vec if the current view is less than half of
            // backing data.
            unsafe {
                *self_ = ArrayBase::from_shape_vec_unchecked(self_.dim.clone(),
                                                             self_.iter()
                                                            .cloned()
                                                            .collect());
            }
            return;
        }
        let our_off = (self_.ptr as isize - self_.data.as_ptr() as isize) /
                      mem::size_of::() as isize;
        let rvec = Rc::make_mut(&mut self_.data);
        unsafe {
            self_.ptr = rvec.as_mut_ptr().offset(our_off);
        }
    }

    fn is_unique(&mut self) -> bool {
        Rc::get_mut(self).is_some()
    }
}

unsafe impl DataClone for Rc<Vec> {
    unsafe fn clone_with_ptr(&self, ptr: *mut Self::Elem) -> (Self, *mut Self::Elem) {
        // pointer is preserved
        (self.clone(), ptr)
    }
}

unsafe impl Data for Vec {
    type Elem = A;
    fn _data_slice(&self) -> &[A] {
        self
    }
}

unsafe impl DataMut for Vec { }

unsafe impl DataClone for Vec
    where A: Clone
{
    unsafe fn clone_with_ptr(&self, ptr: *mut Self::Elem) -> (Self, *mut Self::Elem) {
        let mut u = self.clone();
        let our_off = (self.as_ptr() as isize - ptr as isize) /
                      mem::size_of::() as isize;
        let new_ptr = u.as_mut_ptr().offset(our_off);
        (u, new_ptr)
    }
}

unsafe impl<'a, A> Data for ViewRepr<&'a A> {
    type Elem = A;
    fn _data_slice(&self) -> &[A] {
        &[]
    }
}

unsafe impl<'a, A> DataClone for ViewRepr<&'a A> {
    unsafe fn clone_with_ptr(&self, ptr: *mut Self::Elem) -> (Self, *mut Self::Elem) {
        (*self, ptr)
    }
}

unsafe impl<'a, A> Data for ViewRepr<&'a mut A> {
    type Elem = A;
    fn _data_slice(&self) -> &[A] {
        &[]
    }
}

unsafe impl<'a, A> DataMut for ViewRepr<&'a mut A> { }

/// Array representation trait.
///
/// A representation that is a unique or shared owner of its data.
///
/// ***Internal trait, see `Data`.***
pub unsafe trait DataOwned : Data {
    #[doc(hidden)]
    fn new(elements: Vec<Self::Elem>) -> Self;
    #[doc(hidden)]
    fn into_shared(self) -> Rc<Vec<Self::Elem>>;
}

/// Array representation trait.
///
/// A representation that is a lightweight view.
///
/// ***Internal trait, see `Data`.***
pub unsafe trait DataShared : Clone + DataClone { }

unsafe impl DataShared for Rc<Vec> {}
unsafe impl<'a, A> DataShared for ViewRepr<&'a A> {}

unsafe impl DataOwned for Vec {
    fn new(elements: Vec) -> Self {
        elements
    }
    fn into_shared(self) -> Rc<Vec> {
        Rc::new(self)
    }
}

unsafe impl DataOwned for Rc<Vec> {
    fn new(elements: Vec) -> Self {
        Rc::new(elements)
    }
    fn into_shared(self) -> Rc<Vec> {
        self
    }
}

<|endoftext|>


<commit_before>#![feature(test)]

extern crate bio;
extern crate genomic_fx;
extern crate linked_hash_map;
extern crate test;

use test::Bencher;

use bio::utils::{Interval, Strand};
use linked_hash_map::LinkedHashMap;

use genomic_fx::{ExonFeature, ExonFeatureKind, EBuilder, TBuilder, GBuilder, RefFlatReader};
use ExonFeatureKind::*;

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

    #[bench]
    fn ebuilder_no_features(b: &mut Bencher) {
        b.iter(|| {
            EBuilder::new("chrT", 100, 500)
                .strand(Strand::Forward)
                .build()
        });
    }

    #[bench]
    fn ebuiler_5_features(b: &mut Bencher) {
        b.iter(|| {
            EBuilder::new("chrT", 100, 300)
                .strand(Strand::Forward)
                .features(vec![
                    ExonFeature {
                        interval: Interval::new(100..150).unwrap(),
                        kind: UTR5,
                    },
                    ExonFeature {
                        interval: Interval::new(150..153).unwrap(),
                        kind: StartCodon { frame: Some(0) },
                    },
                    ExonFeature {
                        interval: Interval::new(150..300).unwrap(),
                        kind: CDS { frame: Some(0) },
                    },
                    ExonFeature {
                        interval: Interval::new(300..303).unwrap(),
                        kind: StopCodon { frame: Some(0) },
                    },
                    ExonFeature {
                        interval: Interval::new(300..500).unwrap(),
                        kind: UTR3,
                    },
                ])
                .build()
        });
    }

    #[bench]
    fn tbuilder_1_exon_no_cds(b: &mut Bencher) {
        b.iter(|| {
            TBuilder::new("chrT", 100, 10000)
                .strand(Strand::Forward)
                .id("trx01")
                .coords(vec![(100, 10000)], None)
                .build()
        });
    }

    #[bench]
    fn tbuilder_1_exon_1_cds(b: &mut Bencher) {
        b.iter(|| {
            TBuilder::new("chrT", 100, 10000)
                .strand(Strand::Forward)
                .id("trx01")
                .coords(vec![(100, 10000)], Some((200, 9500)))
                .build()
        });
    }

    #[bench]
    fn tbuilder_12_exons_no_cds(b: &mut Bencher) {
        b.iter(|| {
            TBuilder::new("chrT", 100, 10000)
                .strand(Strand::Forward)
                .id("trx01")
                .coords(
                    vec![
                        (100, 300), (400, 500), (700, 1000),
                        (1100, 1300), (1400, 1500), (1700, 2000),
                        (2100, 2300), (2400, 2500), (2700, 3000),
                        (3000, 6000), (7000, 8000), (9000, 10000),
                    ], None)
                .build()
        });
    }

    #[bench]
    fn tbuilder_12_exons_with_cds(b: &mut Bencher) {
        b.iter(|| {
            TBuilder::new("chrT", 100, 10000)
                .strand(Strand::Forward)
                .id("trx01")
                .coords(
                    vec![
                        (100, 300), (400, 500), (700, 1000),
                        (1100, 1300), (1400, 1500), (1700, 2000),
                        (2100, 2300), (2400, 2500), (2700, 3000),
                        (3000, 6000), (7000, 8000), (9000, 10000),
                    ], Some((200, 9500)))
                .build()
        });
    }

    #[bench]
    fn gbuilder_no_transcripts(b: &mut Bencher) {
        b.iter(|| {
            GBuilder::new("chrT", 100, 20000)
                .strand(Strand::Forward)
                .id("gx01")
                .build()
        });
    }

    #[bench]
    fn gbuilder_3_transcripts_with_cds(b: &mut Bencher) {
        b.iter(|| {
            let mut coords = LinkedHashMap::new();
            coords.insert(
                "trx01".to_owned(),
                ((100, 10000),
                vec![
                    (100, 300), (400, 500), (700, 1000),
                    (1100, 1300), (1400, 1500), (1700, 2000),
                    (2100, 2300), (2400, 2500), (2700, 3000),
                    (3000, 6000), (7000, 8000), (9000, 10000)],
                Some((200, 9500))));
            coords.insert(
                "trx02".to_owned(),
                ((100, 10000),
                vec![
                    (100, 300), (400, 500), (700, 1000),
                    (1100, 1300), (1400, 1500), (1700, 2000),
                    (2100, 2300), (2400, 2500), (2700, 3000),
                    (3000, 6000), (7000, 8000), (9000, 10000)],
                Some((200, 9500))));
            coords.insert(
                "trx03".to_owned(),
                ((100, 10000),
                vec![
                    (100, 300), (400, 500), (700, 1000),
                    (1100, 1300), (1400, 1500), (1700, 2000),
                    (2100, 2300), (2400, 2500), (2700, 3000),
                    (3000, 6000), (7000, 8000), (9000, 10000)],
                Some((200, 9500))));
            GBuilder::new("chrT", 100, 20000)
                .strand(Strand::Forward)
                .id("gx01")
                .transcript_coords(coords)
                .build()
        });
    }

    const REFFLAT_MULT_ROWS: &'static [u8] = b"TNFRSF14\tNM_001297605\tchr1\t+\t2556364\t2565622\t2556664\t2562868\t7\t2556364,2557725,2558342,2559822,2560623,2562864,2563147,\t2556733,2557834,2558468,2559978,2560714,2562896,2565622,
TNFRSF14\tNM_003820\tchr1\t+\t2556364\t2565622\t2556664\t2563273\t8\t2556364,2557725,2558342,2559822,2560623,2561672,2562864,2563147,\t2556733,2557834,2558468,2559978,2560714,2561815,2562896,2565622,
SMIM12\tNM_001164824\tchr1\t-\t34850361\t34859045\t34855698\t34855977\t3\t34850361,34856555,34858839,\t34855982,34856739,34859045,
SMIM12\tNM_001164825\tchr1\t-\t34850361\t34859737\t34855698\t34855977\t2\t34850361,34859454,\t34855982,34859737,
SMIM12\tNM_138428\tchr1\t-\t34850361\t34859816\t34855698\t34855977\t2\t34850361,34859676,\t34855982,34859816,";

    #[bench]
    fn refflat_reader_mult_rows_records(b: &mut Bencher) {
        b.iter(|| {
            let mut count = 0;
            let mut reader = RefFlatReader::from_reader(REFFLAT_MULT_ROWS);
            for rec in reader.records() {
                if let Ok(_) = rec {
                    count += 1;
                }
            }
            assert_eq!(count, 5);
        });
    }

    #[bench]
    fn refflat_reader_mult_rows_transcripts(b: &mut Bencher) {
        b.iter(|| {
            let mut count = 0;
            let mut reader = RefFlatReader::from_reader(REFFLAT_MULT_ROWS);
            for trx in reader.transcripts() {
                if let Ok(_) = trx {
                    count += 1;
                }
            }
            assert_eq!(count, 5);
        });
    }

    #[bench]
    fn refflat_reader_mult_rows_genes(b: &mut Bencher) {
        b.iter(|| {
            let mut count = 0;
            let mut reader = RefFlatReader::from_reader(REFFLAT_MULT_ROWS);
            for gx in reader.genes() {
                if let Ok(_) = gx {
                    count += 1;
                }
            }
            assert_eq!(count, 2);
        });
    }
}
<commit_msg>Fix ExonFeature creation in benches<commit_after>#![feature(test)]

extern crate bio;
extern crate genomic_fx;
extern crate linked_hash_map;
extern crate test;

use test::Bencher;

use bio::utils::{Interval, Strand};
use linked_hash_map::LinkedHashMap;

use genomic_fx::{ExonFeature, ExonFeatureKind, EBuilder, TBuilder, GBuilder, RefFlatReader};
use ExonFeatureKind::*;

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

    #[bench]
    fn ebuilder_no_features(b: &mut Bencher) {
        b.iter(|| {
            EBuilder::new("chrT", 100, 500)
                .strand(Strand::Forward)
                .build()
        });
    }

    #[bench]
    fn ebuiler_5_features(b: &mut Bencher) {
        b.iter(|| {
            EBuilder::new("chrT", 100, 300)
                .strand(Strand::Forward)
                .features(vec![
                    ExonFeature::new(Interval::new(100..150).unwrap(), UTR5),
                    ExonFeature::new(Interval::new(150..153).unwrap(),
                                     StartCodon { frame: Some(0) }),
                    ExonFeature::new(Interval::new(150..300).unwrap(),
                                     CDS { frame: Some(0) }),
                    ExonFeature::new(Interval::new(300..303).unwrap(),
                                     StopCodon { frame: Some(0) }),
                    ExonFeature::new(Interval::new(303..500).unwrap(),
                                     UTR3),
                ])
                .build()
        });
    }

    #[bench]
    fn tbuilder_1_exon_no_cds(b: &mut Bencher) {
        b.iter(|| {
            TBuilder::new("chrT", 100, 10000)
                .strand(Strand::Forward)
                .id("trx01")
                .coords(vec![(100, 10000)], None)
                .build()
        });
    }

    #[bench]
    fn tbuilder_1_exon_1_cds(b: &mut Bencher) {
        b.iter(|| {
            TBuilder::new("chrT", 100, 10000)
                .strand(Strand::Forward)
                .id("trx01")
                .coords(vec![(100, 10000)], Some((200, 9500)))
                .build()
        });
    }

    #[bench]
    fn tbuilder_12_exons_no_cds(b: &mut Bencher) {
        b.iter(|| {
            TBuilder::new("chrT", 100, 10000)
                .strand(Strand::Forward)
                .id("trx01")
                .coords(
                    vec![
                        (100, 300), (400, 500), (700, 1000),
                        (1100, 1300), (1400, 1500), (1700, 2000),
                        (2100, 2300), (2400, 2500), (2700, 3000),
                        (3000, 6000), (7000, 8000), (9000, 10000),
                    ], None)
                .build()
        });
    }

    #[bench]
    fn tbuilder_12_exons_with_cds(b: &mut Bencher) {
        b.iter(|| {
            TBuilder::new("chrT", 100, 10000)
                .strand(Strand::Forward)
                .id("trx01")
                .coords(
                    vec![
                        (100, 300), (400, 500), (700, 1000),
                        (1100, 1300), (1400, 1500), (1700, 2000),
                        (2100, 2300), (2400, 2500), (2700, 3000),
                        (3000, 6000), (7000, 8000), (9000, 10000),
                    ], Some((200, 9500)))
                .build()
        });
    }

    #[bench]
    fn gbuilder_no_transcripts(b: &mut Bencher) {
        b.iter(|| {
            GBuilder::new("chrT", 100, 20000)
                .strand(Strand::Forward)
                .id("gx01")
                .build()
        });
    }

    #[bench]
    fn gbuilder_3_transcripts_with_cds(b: &mut Bencher) {
        b.iter(|| {
            let mut coords = LinkedHashMap::new();
            coords.insert(
                "trx01".to_owned(),
                ((100, 10000),
                vec![
                    (100, 300), (400, 500), (700, 1000),
                    (1100, 1300), (1400, 1500), (1700, 2000),
                    (2100, 2300), (2400, 2500), (2700, 3000),
                    (3000, 6000), (7000, 8000), (9000, 10000)],
                Some((200, 9500))));
            coords.insert(
                "trx02".to_owned(),
                ((100, 10000),
                vec![
                    (100, 300), (400, 500), (700, 1000),
                    (1100, 1300), (1400, 1500), (1700, 2000),
                    (2100, 2300), (2400, 2500), (2700, 3000),
                    (3000, 6000), (7000, 8000), (9000, 10000)],
                Some((200, 9500))));
            coords.insert(
                "trx03".to_owned(),
                ((100, 10000),
                vec![
                    (100, 300), (400, 500), (700, 1000),
                    (1100, 1300), (1400, 1500), (1700, 2000),
                    (2100, 2300), (2400, 2500), (2700, 3000),
                    (3000, 6000), (7000, 8000), (9000, 10000)],
                Some((200, 9500))));
            GBuilder::new("chrT", 100, 20000)
                .strand(Strand::Forward)
                .id("gx01")
                .transcript_coords(coords)
                .build()
        });
    }

    const REFFLAT_MULT_ROWS: &'static [u8] = b"TNFRSF14\tNM_001297605\tchr1\t+\t2556364\t2565622\t2556664\t2562868\t7\t2556364,2557725,2558342,2559822,2560623,2562864,2563147,\t2556733,2557834,2558468,2559978,2560714,2562896,2565622,
TNFRSF14\tNM_003820\tchr1\t+\t2556364\t2565622\t2556664\t2563273\t8\t2556364,2557725,2558342,2559822,2560623,2561672,2562864,2563147,\t2556733,2557834,2558468,2559978,2560714,2561815,2562896,2565622,
SMIM12\tNM_001164824\tchr1\t-\t34850361\t34859045\t34855698\t34855977\t3\t34850361,34856555,34858839,\t34855982,34856739,34859045,
SMIM12\tNM_001164825\tchr1\t-\t34850361\t34859737\t34855698\t34855977\t2\t34850361,34859454,\t34855982,34859737,
SMIM12\tNM_138428\tchr1\t-\t34850361\t34859816\t34855698\t34855977\t2\t34850361,34859676,\t34855982,34859816,";

    #[bench]
    fn refflat_reader_mult_rows_records(b: &mut Bencher) {
        b.iter(|| {
            let mut count = 0;
            let mut reader = RefFlatReader::from_reader(REFFLAT_MULT_ROWS);
            for rec in reader.records() {
                if let Ok(_) = rec {
                    count += 1;
                }
            }
            assert_eq!(count, 5);
        });
    }

    #[bench]
    fn refflat_reader_mult_rows_transcripts(b: &mut Bencher) {
        b.iter(|| {
            let mut count = 0;
            let mut reader = RefFlatReader::from_reader(REFFLAT_MULT_ROWS);
            for trx in reader.transcripts() {
                if let Ok(_) = trx {
                    count += 1;
                }
            }
            assert_eq!(count, 5);
        });
    }

    #[bench]
    fn refflat_reader_mult_rows_genes(b: &mut Bencher) {
        b.iter(|| {
            let mut count = 0;
            let mut reader = RefFlatReader::from_reader(REFFLAT_MULT_ROWS);
            for gx in reader.genes() {
                if let Ok(_) = gx {
                    count += 1;
                }
            }
            assert_eq!(count, 2);
        });
    }
}
<|endoftext|>


<commit_before>#![recursion_limit="512"]

extern crate proc_macro;
extern crate syn;
#[macro_use]
extern crate quote;
extern crate proc_macro2;

use proc_macro::TokenStream;
use syn::DeriveInput;

fn get_meta_items( attr: &syn::Attribute ) -> Option< Vec< syn::NestedMeta > > {
    if attr.path.segments.len() == 1 && attr.path.segments[0].ident == "reference" {
        match attr.interpret_meta() {
            Some( syn::Meta::List( meta ) ) => Some( meta.nested.into_iter().collect() ),
            _ => {
                panic!( "Unrecognized meta item type!" );
            }
        }
    } else {
        None
    }
}

/// A derive macro for defining custom reference types.
///
/// For example:
///
/// ```rust
/// #[derive(Clone, Debug, PartialEq, Eq, ReferenceType)]
/// #[reference(instance_of = "Error")]
/// pub struct Error( Reference );
///
/// #[derive(Clone, Debug, PartialEq, Eq, ReferenceType)]
/// #[reference(instance_of = "TypeError")]
/// #[reference(subclass_of(Error))]
/// pub struct TypeError( Reference );
/// ```
///
/// And then you can do:
///
/// ```rust
/// // You can use `try_into` to cast a `Value` to your type.
/// let error: TypeError = js!( return new TypeError(); ).try_into().unwrap();
///
/// // You can also pass your type freely into the `js!` macro:
/// js!( console.log( @{error} ); );
/// ```
#[proc_macro_derive(ReferenceType, attributes(reference))]
pub fn derive_reference_type( input: TokenStream ) -> TokenStream {
    let input: proc_macro2::TokenStream = input.into();
    let input: DeriveInput = syn::parse2( input ).unwrap();

    let name = input.ident;
    let generics_params = &input.generics.params;

    let mut instance_of = None;
    let mut subclass_of = Vec::new();

    for meta_items in input.attrs.iter().filter_map( get_meta_items ) {
        for meta in meta_items {
            match meta {
                syn::NestedMeta::Meta( syn::Meta::NameValue( ref meta ) ) if meta.ident == "instance_of" => {
                    if instance_of.is_some() {
                        panic!( "Duplicate '#[reference(instance_of)]'!" );
                    }

                    if let syn::Lit::Str( ref str ) = meta.lit {
                        instance_of = Some( str.value() );
                    } else {
                        panic!( "The value of '#[reference(instance_of = ...)]' is not a string!" );
                    }
                },
                syn::NestedMeta::Meta( syn::Meta::List( ref meta ) ) if meta.ident == "subclass_of" => {
                    for nested in &meta.nested {
                        match *nested {
                            syn::NestedMeta::Meta( ref nested ) => {
                                match *nested {
                                    syn::Meta::Word( ref ident ) => {
                                        subclass_of.push( ident.clone() );
                                    },
                                    _ => panic!( "The value of '#[reference(subclass_of(...))]' is invalid!" )
                                }
                            },
                            _ => panic!( "The value of '#[reference(subclass_of(...))]' is invalid!" )
                        }
                    }
                },
                syn::NestedMeta::Meta( ref meta ) => {
                    panic!( "Unrecognized attribute: '#[reference({})]'", meta.name() );
                },
                _ => panic!( "Unrecognized attribute!" )
            }
        }
    }

    let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();

    match input.data {
        syn::Data::Struct( ref data ) => {
            match data.fields {
                syn::Fields::Unnamed( ref fields ) => {
                    fn invalid_structure() {
                        panic!( "The structure can only have either (Reference) or (Reference, PhantomData)!" );
                    }

                    let fields = &fields.unnamed;
                    if fields.len() != 1 && fields.len() != 2 {
                        invalid_structure();
                    }

                    let mut fields_iter = fields.iter();
                    match fields_iter.next().unwrap().ty {
                        syn::Type::Path( ref ty_path ) => {
                            if ty_path.qself.is_some() {
                                invalid_structure();
                            }

                            let segs: Vec< _ > = ty_path.path.segments.iter().collect();
                            if segs.last().unwrap().ident != "Reference" || !segs.last().unwrap().arguments.is_empty() {
                                invalid_structure();
                            }

                            match segs.len() {
                                1 => {},
                                2 => {
                                    if segs.first().unwrap().ident != "stdweb" {
                                        invalid_structure();
                                    }
                                },
                                _ => invalid_structure()
                            }
                        },
                        _ => invalid_structure()
                    }

                    match fields_iter.next().map( |field| &field.ty ) {
                        Some( &syn::Type::Path( ref ty_path ) ) => {
                            if ty_path.qself.is_some() {
                                invalid_structure();
                            }

                            let segs: Vec< _ > = ty_path.path.segments.iter().collect();
                            if segs.last().unwrap().ident != "PhantomData" {
                                invalid_structure();
                            }
                        },
                        Some( _ ) => invalid_structure(),
                        None => {}
                    }
                },
                _ => panic!( "Only tuple structures are supported!" )
            }
        },
        _ => panic!( "Only tuple structures are supported!" )
    }

    let mut default_args = Vec::new();
    for param in input.generics.params.iter() {
        match *param {
            syn::GenericParam::Type( _ ) => {
                default_args.push( quote! {
                    ::std::default::Default::default()
                });
            },
            _ => {}
        }
    }
    let default_args = quote! { #(#default_args),* };
    let instance_of_impl = match instance_of {
        Some( js_name ) => {
            quote! {
                impl #impl_generics ::stdweb::InstanceOf for #name #ty_generics {
                    #[inline]
                    fn instance_of( reference: &::stdweb::Reference ) -> bool {
                        __js_raw_asm!(
                            concat!( "return (Module.STDWEB_PRIVATE.acquire_js_reference( $0 ) instanceof ", #js_name, ") | 0;" ),
                            reference.as_raw()
                        ) == 1
                    }
                }
            }
        },
        None => quote! {}
    };

    let subclass_of_impl: Vec< _ > = subclass_of.into_iter().map( |target| {
        let target: syn::Ident = target.into();
        quote! {
            impl #impl_generics From< #name #ty_generics > for #target #where_clause {
                #[inline]
                fn from( value: #name #ty_generics ) -> Self {
                    let reference: ::stdweb::Reference = value.into();
                    unsafe {
                        <#target as ::stdweb::ReferenceType>::from_reference_unchecked( reference )
                    }
                }
            }

            impl #impl_generics ::stdweb::unstable::TryFrom< #target > for #name #ty_generics #where_clause {
                type Error = ::stdweb::private::ConversionError;

                #[inline]
                fn try_from( value: #target ) -> Result< Self, Self::Error > {
                    use ::stdweb::unstable::TryInto;
                    let reference: ::stdweb::Reference = value.into();
                    reference.try_into()
                }
            }
        }
    }).collect();

    let expanded = quote! {
        #(#subclass_of_impl)*
        #instance_of_impl

        impl #impl_generics AsRef< ::stdweb::Reference > for #name #ty_generics #where_clause {
            #[inline]
            fn as_ref( &self ) -> &::stdweb::Reference {
                &self.0
            }
        }

        impl #impl_generics ::stdweb::ReferenceType for #name #ty_generics #where_clause {
            #[inline]
            unsafe fn from_reference_unchecked( reference: ::stdweb::Reference ) -> Self {
                #name( reference, #default_args )
            }
        }

        impl #impl_generics From< #name #ty_generics > for ::stdweb::Reference #where_clause {
            #[inline]
            fn from( value: #name #ty_generics ) -> Self {
                value.0
            }
        }

        impl #impl_generics ::stdweb::unstable::TryFrom< #name #ty_generics > for ::stdweb::Reference #where_clause {
            type Error = ::stdweb::unstable::Void;

            #[inline]
            fn try_from( value: #name #ty_generics ) -> Result< Self, Self::Error > {
                Ok( value.0 )
            }
        }

        impl #impl_generics ::stdweb::unstable::TryFrom< ::stdweb::Reference > for #name #ty_generics #where_clause {
            type Error = ::stdweb::private::ConversionError;

            #[inline]
            fn try_from( reference: ::stdweb::Reference ) -> Result< Self, Self::Error > {
                reference.downcast()
                    .ok_or_else( || ::stdweb::private::ConversionError::Custom( "reference is of a different type".into() ) )
            }
        }

        impl< '_r, #generics_params > ::stdweb::unstable::TryFrom< &'_r ::stdweb::Reference > for #name #ty_generics #where_clause {
            type Error = ::stdweb::private::ConversionError;

            #[inline]
            fn try_from( reference: &::stdweb::Reference ) -> Result< Self, Self::Error > {
                use ::stdweb::unstable::TryInto;
                reference.clone().try_into()
            }
        }

        impl #impl_generics ::stdweb::unstable::TryFrom< ::stdweb::Value > for #name #ty_generics #where_clause {
            type Error = ::stdweb::private::ConversionError;

            #[inline]
            fn try_from( value: ::stdweb::Value ) -> Result< Self, Self::Error > {
                use ::stdweb::unstable::TryInto;
                let reference: ::stdweb::Reference = value.try_into()?;
                reference.downcast()
                    .ok_or_else( || ::stdweb::private::ConversionError::Custom( "reference is of a different type".into() ) )
            }
        }

        impl< '_r, #generics_params > ::stdweb::unstable::TryFrom< &'_r ::stdweb::Value > for #name #ty_generics #where_clause {
            type Error = ::stdweb::private::ConversionError;

            #[inline]
            fn try_from( value: &::stdweb::Value ) -> Result< Self, Self::Error > {
                use ::stdweb::unstable::TryInto;
                let reference: &::stdweb::Reference =
                    value.as_reference()
                    .ok_or_else( || ::stdweb::private::ConversionError::Custom( "not a reference".into() ) )?;

                reference.try_into()
            }
        }

        impl #impl_generics ::stdweb::private::JsSerialize for #name #ty_generics #where_clause {
            #[doc(hidden)]
            #[inline]
            fn _into_js< 'a >( &'a self ) -> ::stdweb::private::SerializedValue< 'a > {
                self.0._into_js()
            }
        }

        impl #impl_generics ::stdweb::private::JsSerializeOwned for #name #ty_generics #where_clause {
            #[inline]
            fn into_js_owned< '_a >( value: &'_a mut Option< Self > ) -> ::stdweb::private::SerializedValue< '_a > {
                ::stdweb::private::JsSerialize::_into_js( value.as_ref().unwrap() )
            }
        }

        impl< '_r, #generics_params > ::stdweb::private::JsSerializeOwned for &'_r #name #ty_generics #where_clause {
            #[inline]
            fn into_js_owned< '_a >( value: &'_a mut Option< Self > ) -> ::stdweb::private::SerializedValue< '_a > {
                ::stdweb::private::JsSerialize::_into_js( value.unwrap() )
            }
        }
    };

    expanded.into()
}
<commit_msg>Support `#[reference(event = ...)]` in `stdweb-derive`<commit_after>#![recursion_limit="512"]

extern crate proc_macro;
extern crate syn;
#[macro_use]
extern crate quote;
extern crate proc_macro2;

use proc_macro::TokenStream;
use syn::DeriveInput;

fn get_meta_items( attr: &syn::Attribute ) -> Option< Vec< syn::NestedMeta > > {
    if attr.path.segments.len() == 1 && attr.path.segments[0].ident == "reference" {
        match attr.interpret_meta() {
            Some( syn::Meta::List( meta ) ) => Some( meta.nested.into_iter().collect() ),
            _ => {
                panic!( "Unrecognized meta item type!" );
            }
        }
    } else {
        None
    }
}

/// A derive macro for defining custom reference types.
///
/// For example:
///
/// ```rust
/// #[derive(Clone, Debug, PartialEq, Eq, ReferenceType)]
/// #[reference(instance_of = "Error")]
/// pub struct Error( Reference );
///
/// #[derive(Clone, Debug, PartialEq, Eq, ReferenceType)]
/// #[reference(instance_of = "TypeError")]
/// #[reference(subclass_of(Error))]
/// pub struct TypeError( Reference );
/// ```
///
/// And then you can do:
///
/// ```rust
/// // You can use `try_into` to cast a `Value` to your type.
/// let error: TypeError = js!( return new TypeError(); ).try_into().unwrap();
///
/// // You can also pass your type freely into the `js!` macro:
/// js!( console.log( @{error} ); );
/// ```
#[proc_macro_derive(ReferenceType, attributes(reference))]
pub fn derive_reference_type( input: TokenStream ) -> TokenStream {
    let input: proc_macro2::TokenStream = input.into();
    let input: DeriveInput = syn::parse2( input ).unwrap();

    let name = input.ident;
    let generics_params = &input.generics.params;

    let mut instance_of = None;
    let mut event = None;
    let mut subclass_of = Vec::new();

    for meta_items in input.attrs.iter().filter_map( get_meta_items ) {
        for meta in meta_items {
            match meta {
                syn::NestedMeta::Meta( syn::Meta::NameValue( ref meta ) ) if meta.ident == "instance_of" => {
                    if instance_of.is_some() {
                        panic!( "Duplicate '#[reference(instance_of)]'!" );
                    }

                    if let syn::Lit::Str( ref str ) = meta.lit {
                        instance_of = Some( str.value() );
                    } else {
                        panic!( "The value of '#[reference(instance_of = ...)]' is not a string!" );
                    }
                },
                syn::NestedMeta::Meta( syn::Meta::NameValue( ref meta ) ) if meta.ident == "event" => {
                    if event.is_some() {
                        panic!( "Duplicate '#[reference(event)]'!" );
                    }

                    if let syn::Lit::Str( ref str ) = meta.lit {
                        event = Some( str.value() );
                    } else {
                        panic!( "The value of '#[reference(event = ...)]' is not a string!" );
                    }
                },
                syn::NestedMeta::Meta( syn::Meta::List( ref meta ) ) if meta.ident == "subclass_of" => {
                    for nested in &meta.nested {
                        match *nested {
                            syn::NestedMeta::Meta( ref nested ) => {
                                match *nested {
                                    syn::Meta::Word( ref ident ) => {
                                        subclass_of.push( ident.clone() );
                                    },
                                    _ => panic!( "The value of '#[reference(subclass_of(...))]' is invalid!" )
                                }
                            },
                            _ => panic!( "The value of '#[reference(subclass_of(...))]' is invalid!" )
                        }
                    }
                },
                syn::NestedMeta::Meta( ref meta ) => {
                    panic!( "Unrecognized attribute: '#[reference({})]'", meta.name() );
                },
                _ => panic!( "Unrecognized attribute!" )
            }
        }
    }

    let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();

    match input.data {
        syn::Data::Struct( ref data ) => {
            match data.fields {
                syn::Fields::Unnamed( ref fields ) => {
                    fn invalid_structure() {
                        panic!( "The structure can only have either (Reference) or (Reference, PhantomData)!" );
                    }

                    let fields = &fields.unnamed;
                    if fields.len() != 1 && fields.len() != 2 {
                        invalid_structure();
                    }

                    let mut fields_iter = fields.iter();
                    match fields_iter.next().unwrap().ty {
                        syn::Type::Path( ref ty_path ) => {
                            if ty_path.qself.is_some() {
                                invalid_structure();
                            }

                            let segs: Vec< _ > = ty_path.path.segments.iter().collect();
                            if segs.last().unwrap().ident != "Reference" || !segs.last().unwrap().arguments.is_empty() {
                                invalid_structure();
                            }

                            match segs.len() {
                                1 => {},
                                2 => {
                                    if segs.first().unwrap().ident != "stdweb" {
                                        invalid_structure();
                                    }
                                },
                                _ => invalid_structure()
                            }
                        },
                        _ => invalid_structure()
                    }

                    match fields_iter.next().map( |field| &field.ty ) {
                        Some( &syn::Type::Path( ref ty_path ) ) => {
                            if ty_path.qself.is_some() {
                                invalid_structure();
                            }

                            let segs: Vec< _ > = ty_path.path.segments.iter().collect();
                            if segs.last().unwrap().ident != "PhantomData" {
                                invalid_structure();
                            }
                        },
                        Some( _ ) => invalid_structure(),
                        None => {}
                    }
                },
                _ => panic!( "Only tuple structures are supported!" )
            }
        },
        _ => panic!( "Only tuple structures are supported!" )
    }

    let mut default_args = Vec::new();
    for param in input.generics.params.iter() {
        match *param {
            syn::GenericParam::Type( _ ) => {
                default_args.push( quote! {
                    ::std::default::Default::default()
                });
            },
            _ => {}
        }
    }

    let default_args = quote! { #(#default_args),* };

    let mut instance_of_code = Vec::new();
    if let Some( js_name ) = instance_of {
        let code = format!( "o instanceof {}", js_name );
        instance_of_code.push( code );
    }

    if let Some( ref event_name ) = event {
        let code = format!( "o.type === \"{}\"", event_name );
        instance_of_code.push( code );
    }

    let instance_of_impl = if !instance_of_code.is_empty() {
        let mut code = String::new();
        code.push_str( "var o = Module.STDWEB_PRIVATE.acquire_js_reference( $0 );" );
        code.push_str( "return (" );
        code.push_str( &instance_of_code.join( " && " ) );
        code.push_str( ") | 0;" );

        quote! {
            impl #impl_generics ::stdweb::InstanceOf for #name #ty_generics {
                #[inline]
                fn instance_of( reference: &::stdweb::Reference ) -> bool {
                    __js_raw_asm!(
                        #code,
                        reference.as_raw()
                    ) == 1
                }
            }
        }
    } else {
        quote! {}
    };

    let concrete_event_impl = if let Some( event_name ) = event {
        quote! {
            impl #impl_generics ::stdweb::web::event::ConcreteEvent for #name #ty_generics {
                const EVENT_TYPE: &'static str = #event_name;
            }
        }
    } else {
        quote! {}
    };

    let subclass_of_impl: Vec< _ > = subclass_of.into_iter().map( |target| {
        let target: syn::Ident = target.into();
        quote! {
            impl #impl_generics From< #name #ty_generics > for #target #where_clause {
                #[inline]
                fn from( value: #name #ty_generics ) -> Self {
                    let reference: ::stdweb::Reference = value.into();
                    unsafe {
                        <#target as ::stdweb::ReferenceType>::from_reference_unchecked( reference )
                    }
                }
            }

            impl #impl_generics ::stdweb::unstable::TryFrom< #target > for #name #ty_generics #where_clause {
                type Error = ::stdweb::private::ConversionError;

                #[inline]
                fn try_from( value: #target ) -> Result< Self, Self::Error > {
                    use ::stdweb::unstable::TryInto;
                    let reference: ::stdweb::Reference = value.into();
                    reference.try_into()
                }
            }
        }
    }).collect();

    let expanded = quote! {
        #(#subclass_of_impl)*
        #instance_of_impl
        #concrete_event_impl

        impl #impl_generics AsRef< ::stdweb::Reference > for #name #ty_generics #where_clause {
            #[inline]
            fn as_ref( &self ) -> &::stdweb::Reference {
                &self.0
            }
        }

        impl #impl_generics ::stdweb::ReferenceType for #name #ty_generics #where_clause {
            #[inline]
            unsafe fn from_reference_unchecked( reference: ::stdweb::Reference ) -> Self {
                #name( reference, #default_args )
            }
        }

        impl #impl_generics From< #name #ty_generics > for ::stdweb::Reference #where_clause {
            #[inline]
            fn from( value: #name #ty_generics ) -> Self {
                value.0
            }
        }

        impl #impl_generics ::stdweb::unstable::TryFrom< #name #ty_generics > for ::stdweb::Reference #where_clause {
            type Error = ::stdweb::unstable::Void;

            #[inline]
            fn try_from( value: #name #ty_generics ) -> Result< Self, Self::Error > {
                Ok( value.0 )
            }
        }

        impl #impl_generics ::stdweb::unstable::TryFrom< ::stdweb::Reference > for #name #ty_generics #where_clause {
            type Error = ::stdweb::private::ConversionError;

            #[inline]
            fn try_from( reference: ::stdweb::Reference ) -> Result< Self, Self::Error > {
                reference.downcast()
                    .ok_or_else( || ::stdweb::private::ConversionError::Custom( "reference is of a different type".into() ) )
            }
        }

        impl< '_r, #generics_params > ::stdweb::unstable::TryFrom< &'_r ::stdweb::Reference > for #name #ty_generics #where_clause {
            type Error = ::stdweb::private::ConversionError;

            #[inline]
            fn try_from( reference: &::stdweb::Reference ) -> Result< Self, Self::Error > {
                use ::stdweb::unstable::TryInto;
                reference.clone().try_into()
            }
        }

        impl #impl_generics ::stdweb::unstable::TryFrom< ::stdweb::Value > for #name #ty_generics #where_clause {
            type Error = ::stdweb::private::ConversionError;

            #[inline]
            fn try_from( value: ::stdweb::Value ) -> Result< Self, Self::Error > {
                use ::stdweb::unstable::TryInto;
                let reference: ::stdweb::Reference = value.try_into()?;
                reference.downcast()
                    .ok_or_else( || ::stdweb::private::ConversionError::Custom( "reference is of a different type".into() ) )
            }
        }

        impl< '_r, #generics_params > ::stdweb::unstable::TryFrom< &'_r ::stdweb::Value > for #name #ty_generics #where_clause {
            type Error = ::stdweb::private::ConversionError;

            #[inline]
            fn try_from( value: &::stdweb::Value ) -> Result< Self, Self::Error > {
                use ::stdweb::unstable::TryInto;
                let reference: &::stdweb::Reference =
                    value.as_reference()
                    .ok_or_else( || ::stdweb::private::ConversionError::Custom( "not a reference".into() ) )?;

                reference.try_into()
            }
        }

        impl #impl_generics ::stdweb::private::JsSerialize for #name #ty_generics #where_clause {
            #[doc(hidden)]
            #[inline]
            fn _into_js< 'a >( &'a self ) -> ::stdweb::private::SerializedValue< 'a > {
                self.0._into_js()
            }
        }

        impl #impl_generics ::stdweb::private::JsSerializeOwned for #name #ty_generics #where_clause {
            #[inline]
            fn into_js_owned< '_a >( value: &'_a mut Option< Self > ) -> ::stdweb::private::SerializedValue< '_a > {
                ::stdweb::private::JsSerialize::_into_js( value.as_ref().unwrap() )
            }
        }

        impl< '_r, #generics_params > ::stdweb::private::JsSerializeOwned for &'_r #name #ty_generics #where_clause {
            #[inline]
            fn into_js_owned< '_a >( value: &'_a mut Option< Self > ) -> ::stdweb::private::SerializedValue< '_a > {
                ::stdweb::private::JsSerialize::_into_js( value.unwrap() )
            }
        }
    };

    expanded.into()
}
<|endoftext|>