<commit_before>use winapi::shared::ws2def::{AF_INET, AF_INET6, AF_UNSPEC, SOCKADDR};
use winapi::shared::winerror::{ERROR_BUFFER_OVERFLOW, ERROR_SUCCESS};
use winapi::shared::ws2ipdef::SOCKADDR_IN6_LH;
use winapi::shared::minwindef::*;
use winapi::ctypes::*;
use libc::{c_void, uint8_t, size_t, malloc, free};

use data::*;

use std::collections::BTreeMap;
use std::io::{Write, Error};
use std::slice::from_raw_parts;
use std::{io, ptr, mem};
use std::ffi::CStr;

// unions with non-`Copy` fields are unstable (see issue #32836)
// #[repr(C)]
// union AlimentOrLengthIfIndex {
//     aliment: c_ulonglong,
//     length_ifindex: LengthIfIndex,
// }

#[repr(C)]
struct LengthIfIndex{
    length: ULONG,
    ifindex: DWORD,
}

#[repr(C)]
struct LengthFlags{
    length: ULONG,
    flags: DWORD,
}

#[repr(C)]
struct SoketAddress{
    lp_sockaddr: *mut SOCKADDR,
    i_sockaddr_length: c_int
}

#[repr(C)]
struct IpAdapterPrefix{
    aol: LengthIfIndex,
    next: *mut IpAdapterPrefix,
    address: SoketAddress,
    prefix_length: ULONG,
}

#[repr(C)]
struct IpAdapterUnicastAddress {
    aol: LengthFlags,
    next: *mut IpAdapterUnicastAddress,
    address: SoketAddress,
    prefix_origin: c_int,
    suffix_origin: c_int,
    dad_state: c_int,
    valid_lifetime: ULONG,
    preferred_lifetime: ULONG,
    lease_lifetime: ULONG,
    on_link_prefix_length: uint8_t
}

const MAX_ADAPTER_ADDRESS_LENGTH: usize = 8;

#[repr(C)]
struct IpAdapterAddresses{
    aol: LengthIfIndex,
    next: *mut IpAdapterAddresses,
    adapter_name:  *mut c_char,
    first_unicass_address: *mut IpAdapterUnicastAddress,
    first_anycass_address: *const c_void,
    first_multicass_address: *const c_void,
    first_dns_server_address: *const c_void,
    dns_suffix: *mut wchar_t,
    description: *mut wchar_t,
    friendly_name:  *mut wchar_t,
    physical_address: [u8; MAX_ADAPTER_ADDRESS_LENGTH],
    physical_address_length: DWORD,
    flags: DWORD,
    mtu: DWORD,
    if_type: DWORD,
    oper_status: c_int,
    ipv6_if_index: DWORD,
    zone_indices:  [DWORD;16],
    first_prefix: *mut IpAdapterPrefix,
}

// https://msdn.microsoft.com/en-us/library/aa365915(v=vs.85).aspx
// https://msdn.microsoft.com/zh-cn/library/windows/desktop/aa366066(d=printer,v=vs.85).aspx
// C:\Program Files (x86)\Windows Kits\8.1\Include\um\IPHlpApi.h
#[link(name = "Iphlpapi")]
extern "system" {
    fn GetAdaptersAddresses(
        family: ULONG,
        flags: ULONG,
        reserved: *const c_void,
        addresses: *mut IpAdapterAddresses,
        size: *mut ULONG,
    ) -> ULONG;
}

const WORKING_BUFFER_SIZEL: size_t = 15000;

pub fn interfaces() -> io::Result<BTreeMap<String, Network>> {
    let mut new_size:ULONG = WORKING_BUFFER_SIZEL as ULONG;
    let mut p_adapter: *mut IpAdapterAddresses;
    loop {
        unsafe {
            p_adapter = malloc( WORKING_BUFFER_SIZEL) as *mut IpAdapterAddresses;
            if p_adapter.is_null() {
                panic!("Failed: malloc!");
            }
            let res_code = GetAdaptersAddresses (
                0,
                AF_UNSPEC as ULONG, // ipv4 & ipv6
                ptr::null(),
                p_adapter,
                &mut new_size as *mut ULONG
            );
            match res_code {
                // 0
                ERROR_SUCCESS => break,
                // 111, retry
                ERROR_BUFFER_OVERFLOW => {
                    new_size*=2;
                    free(p_adapter as *mut c_void);
                    continue;
                }
                _=> {
                    return Err( Error::last_os_error());
                }
            }
        }
    }

    let mut map = BTreeMap::new();
    // key->adapter_name, name-> friendly_name, maybe should use the adapter_name all.
    unsafe {
        let mut cur_p_adapter = p_adapter;
        while !cur_p_adapter.is_null() {
            // name, mac, etc
            let adapter_name = c_char_array_to_string( (*cur_p_adapter).adapter_name);
            // println!("adapter_name : {}", adapter_name);

            // let dns_suffix = u16_array_to_string((*cur_p_adapter).dns_suffix);
            // println!("dns_suffix   : {}", dns_suffix);

            let friendly_name =  u16_array_to_string((*cur_p_adapter).friendly_name);
            // println!("friendly_name: {}", friendly_name);

            // let description = u16_array_to_string((*cur_p_adapter).description);
            // println!("description  : {}", description);

            // let mac = physical_address_to_string(&(*cur_p_adapter).physical_address, (*cur_p_adapter).physical_address_length);
            // println!("mac          : {}", mac);

            let mut addrs = Vec::new();
            // ip
            let mut cur_p_addr = (*cur_p_adapter).first_unicass_address;
            while !cur_p_addr.is_null() {
                let addr = parse_addr_and_netmask((*cur_p_addr).address.lp_sockaddr, (*cur_p_addr).on_link_prefix_length);
                addrs.push(addr);
               // println!("{:?}", addr);
               // next addr
               cur_p_addr =(*cur_p_addr).next;
            }
            let network = Network {
                name: friendly_name,
                addrs: addrs
            };
            map.insert(adapter_name,network);

            // next adapter
            cur_p_adapter = (*cur_p_adapter).next;
        }
    }

    unsafe { free(p_adapter as *mut c_void); }
    Ok(map)
}

fn u16_array_to_string(p: *const u16) ->String {
    use std::char::{decode_utf16, REPLACEMENT_CHARACTER};
    unsafe {
        if p.is_null() {
            return String::new();
        }
        let mut amt = 0usize;
        while !p.offset(amt as isize).is_null() &&  *p.offset(amt as isize) != 0u16 {
            amt+=1;
        }
        let u16s = from_raw_parts(p, amt);
        decode_utf16(u16s.iter().cloned())
        .map(|r| r.unwrap_or(REPLACEMENT_CHARACTER))
        .collect::<String>()
    }
}

fn c_char_array_to_string(p: *const c_char) -> String {
    unsafe {
        CStr::from_ptr(p).to_string_lossy().into_owned()
    }
}

fn physical_address_to_string(array: &[u8;8], length: DWORD) -> String {
    let mut bytes = Vec::with_capacity(length as usize);
    for idx in 0..length as usize {
        if idx == 0  {
            write!(&mut bytes, "{:02X}", array[idx]).unwrap();
        } else {
            write!(&mut bytes, "-{:02X}", array[idx]).unwrap();
        }
    }
    String::from_utf8_lossy(&bytes[..]).into_owned()
}

// Thanks , copy from unix.rs and some modify
fn parse_addr_and_netmask(aptr: *const SOCKADDR, mut net_bits: uint8_t) -> NetworkAddrs {
    if aptr == ptr::null() {
        return NetworkAddrs {addr: IpAddr::Empty, netmask: IpAddr::Empty};
    }
    let addr = unsafe { *aptr };
    match addr.sa_family as i32 {
        AF_INET => {
           let addr = IpAddr::V4(Ipv4Addr::new(addr.sa_data[2] as u8, addr.sa_data[3] as u8,
                                            addr.sa_data[4] as u8, addr.sa_data[5] as u8));
            let netmask = if net_bits <= 32 {
                        let v = netmask_v4(net_bits);
                        IpAddr::V4(Ipv4Addr::new(v[0], v[1], v[2], v[3]))
                    } else {
                        IpAddr::Empty
                    };
            NetworkAddrs { addr, netmask }
        },
        AF_INET6 => {
            // This is horrible.
            let addr6: *const SOCKADDR_IN6_LH = unsafe { mem::transmute(aptr) };
            let mut a: [u8; 16] = unsafe { *(*addr6).sin6_addr.u.Byte() };
            &mut a[..].reverse();
            let a: [u16; 8] = unsafe { mem::transmute(a) };
            let addr = IpAddr::V6(Ipv6Addr::new(a[7], a[6], a[5], a[4], a[3], a[2], a[1], a[0]));
            let netmask = if net_bits <= 128 {
                    let v = netmask_v6(net_bits);
                    IpAddr::V6( Ipv6Addr::new(v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7]))
                } else {
                    IpAddr::Empty
                };
            NetworkAddrs { addr, netmask }
        },
        _ => NetworkAddrs { addr: IpAddr::Empty, netmask: IpAddr::Empty }
    }
}

fn netmask_v4(bits: u8) -> [u8;4] {
    let mut tmp = [0u8;4];
    (0..4).for_each(|idx|
        {
            match (bits as usize> idx*8, bits as usize> idx*8 +8) {
                (true, true) => {
                    tmp[idx] = 255;
                },
                (true, false) => {
                    tmp[idx] = 255 << 8 - (bits as usize- idx*8)  as usize;
                },
                _=> {}
            }
        }
    );
    tmp
}

fn netmask_v6(bits: u8) -> [u16;8] {
    let mut tmp = [0u16;8];
    (0..8).for_each(|idx|
        {
            match (bits as usize> idx*16, bits as usize> idx*16 +16) {
                (true, true) => {
                    tmp[idx] = 0xffff;
                },
                (true, false) => {
                    tmp[idx] = 0xffff << 16 - (bits as usize- idx*16)  as usize;
                },
                _=> {}
            }
        }
    );
    tmp
}<commit_msg>Rewrite netmask_vx function.<commit_after>use winapi::shared::ws2def::{AF_INET, AF_INET6, AF_UNSPEC, SOCKADDR};
use winapi::shared::winerror::{ERROR_BUFFER_OVERFLOW, ERROR_SUCCESS};
use winapi::shared::ws2ipdef::SOCKADDR_IN6_LH;
use winapi::shared::minwindef::*;
use winapi::ctypes::*;
use libc::{c_void, uint8_t, size_t, malloc, free};

use data::*;

use std::collections::BTreeMap;
use std::io::{Write, Error};
use std::slice::from_raw_parts;
use std::{io, ptr, mem};
use std::ffi::CStr;

// unions with non-`Copy` fields are unstable (see issue #32836)
// #[repr(C)]
// union AlimentOrLengthIfIndex {
//     aliment: c_ulonglong,
//     length_ifindex: LengthIfIndex,
// }

#[repr(C)]
struct LengthIfIndex{
    length: ULONG,
    ifindex: DWORD,
}

#[repr(C)]
struct LengthFlags{
    length: ULONG,
    flags: DWORD,
}

#[repr(C)]
struct SoketAddress{
    lp_sockaddr: *mut SOCKADDR,
    i_sockaddr_length: c_int
}

#[repr(C)]
struct IpAdapterPrefix{
    aol: LengthIfIndex,
    next: *mut IpAdapterPrefix,
    address: SoketAddress,
    prefix_length: ULONG,
}

#[repr(C)]
struct IpAdapterUnicastAddress {
    aol: LengthFlags,
    next: *mut IpAdapterUnicastAddress,
    address: SoketAddress,
    prefix_origin: c_int,
    suffix_origin: c_int,
    dad_state: c_int,
    valid_lifetime: ULONG,
    preferred_lifetime: ULONG,
    lease_lifetime: ULONG,
    on_link_prefix_length: uint8_t
}

const MAX_ADAPTER_ADDRESS_LENGTH: usize = 8;

#[repr(C)]
struct IpAdapterAddresses{
    aol: LengthIfIndex,
    next: *mut IpAdapterAddresses,
    adapter_name:  *mut c_char,
    first_unicass_address: *mut IpAdapterUnicastAddress,
    first_anycass_address: *const c_void,
    first_multicass_address: *const c_void,
    first_dns_server_address: *const c_void,
    dns_suffix: *mut wchar_t,
    description: *mut wchar_t,
    friendly_name:  *mut wchar_t,
    physical_address: [u8; MAX_ADAPTER_ADDRESS_LENGTH],
    physical_address_length: DWORD,
    flags: DWORD,
    mtu: DWORD,
    if_type: DWORD,
    oper_status: c_int,
    ipv6_if_index: DWORD,
    zone_indices:  [DWORD;16],
    first_prefix: *mut IpAdapterPrefix,
}

// https://msdn.microsoft.com/en-us/library/aa365915(v=vs.85).aspx
// https://msdn.microsoft.com/zh-cn/library/windows/desktop/aa366066(d=printer,v=vs.85).aspx
// C:\Program Files (x86)\Windows Kits\8.1\Include\um\IPHlpApi.h
#[link(name = "Iphlpapi")]
extern "system" {
    fn GetAdaptersAddresses(
        family: ULONG,
        flags: ULONG,
        reserved: *const c_void,
        addresses: *mut IpAdapterAddresses,
        size: *mut ULONG,
    ) -> ULONG;
}

const WORKING_BUFFER_SIZEL: size_t = 15000;

pub fn interfaces() -> io::Result<BTreeMap<String, Network>> {
    let mut new_size:ULONG = WORKING_BUFFER_SIZEL as ULONG;
    let mut p_adapter: *mut IpAdapterAddresses;
    loop {
        unsafe {
            p_adapter = malloc( WORKING_BUFFER_SIZEL) as *mut IpAdapterAddresses;
            if p_adapter.is_null() {
                panic!("Failed: malloc!");
            }
            let res_code = GetAdaptersAddresses (
                0,
                AF_UNSPEC as ULONG, // ipv4 & ipv6
                ptr::null(),
                p_adapter,
                &mut new_size as *mut ULONG
            );
            match res_code {
                // 0
                ERROR_SUCCESS => break,
                // 111, retry
                ERROR_BUFFER_OVERFLOW => {
                    new_size*=2;
                    free(p_adapter as *mut c_void);
                    continue;
                }
                _=> {
                    return Err( Error::last_os_error());
                }
            }
        }
    }

    let mut map = BTreeMap::new();
    // key->adapter_name, name-> friendly_name, maybe should use the adapter_name all.
    unsafe {
        let mut cur_p_adapter = p_adapter;
        while !cur_p_adapter.is_null() {
            // name, mac, etc
            let adapter_name = c_char_array_to_string( (*cur_p_adapter).adapter_name);
            // println!("adapter_name : {}", adapter_name);

            // let dns_suffix = u16_array_to_string((*cur_p_adapter).dns_suffix);
            // println!("dns_suffix   : {}", dns_suffix);

            let friendly_name =  u16_array_to_string((*cur_p_adapter).friendly_name);
            // println!("friendly_name: {}", friendly_name);

            // let description = u16_array_to_string((*cur_p_adapter).description);
            // println!("description  : {}", description);

            // let mac = physical_address_to_string(&(*cur_p_adapter).physical_address, (*cur_p_adapter).physical_address_length);
            // println!("mac          : {}", mac);

            let mut addrs = Vec::new();
            // ip
            let mut cur_p_addr = (*cur_p_adapter).first_unicass_address;
            while !cur_p_addr.is_null() {
                let addr = parse_addr_and_netmask((*cur_p_addr).address.lp_sockaddr, (*cur_p_addr).on_link_prefix_length);
                addrs.push(addr);
               // println!("{:?}", addr);
               // next addr
               cur_p_addr =(*cur_p_addr).next;
            }
            let network = Network {
                name: friendly_name,
                addrs: addrs
            };
            map.insert(adapter_name,network);

            // next adapter
            cur_p_adapter = (*cur_p_adapter).next;
        }
    }

    unsafe { free(p_adapter as *mut c_void); }
    Ok(map)
}

fn u16_array_to_string(p: *const u16) ->String {
    use std::char::{decode_utf16, REPLACEMENT_CHARACTER};
    unsafe {
        if p.is_null() {
            return String::new();
        }
        let mut amt = 0usize;
        while !p.offset(amt as isize).is_null() &&  *p.offset(amt as isize) != 0u16 {
            amt+=1;
        }
        let u16s = from_raw_parts(p, amt);
        decode_utf16(u16s.iter().cloned())
        .map(|r| r.unwrap_or(REPLACEMENT_CHARACTER))
        .collect::<String>()
    }
}

fn c_char_array_to_string(p: *const c_char) -> String {
    unsafe {
        CStr::from_ptr(p).to_string_lossy().into_owned()
    }
}

fn physical_address_to_string(array: &[u8;8], length: DWORD) -> String {
    let mut bytes = Vec::with_capacity(length as usize);
    for idx in 0..length as usize {
        if idx == 0  {
            write!(&mut bytes, "{:02X}", array[idx]).unwrap();
        } else {
            write!(&mut bytes, "-{:02X}", array[idx]).unwrap();
        }
    }
    String::from_utf8_lossy(&bytes[..]).into_owned()
}

// Thanks , copy from unix.rs and some modify
fn parse_addr_and_netmask(aptr: *const SOCKADDR, net_bits: uint8_t) -> NetworkAddrs {
    if aptr == ptr::null() {
        return NetworkAddrs {addr: IpAddr::Empty, netmask: IpAddr::Empty};
    }
    let addr = unsafe { *aptr };
    match addr.sa_family as i32 {
        AF_INET => {
           let addr = IpAddr::V4(Ipv4Addr::new(addr.sa_data[2] as u8, addr.sa_data[3] as u8,
                                            addr.sa_data[4] as u8, addr.sa_data[5] as u8));
            let netmask = if net_bits <= 32 {
                        IpAddr::V4(netmask_v4(net_bits))
                    } else {
                        IpAddr::Empty
                    };
            NetworkAddrs { addr, netmask }
        },
        AF_INET6 => {
            // This is horrible.
            let addr6: *const SOCKADDR_IN6_LH = unsafe { mem::transmute(aptr) };
            let mut a: [u8; 16] = unsafe { *(*addr6).sin6_addr.u.Byte() };
            &mut a[..].reverse();
            let a: [u16; 8] = unsafe { mem::transmute(a) };
            let addr = IpAddr::V6(Ipv6Addr::new(a[7], a[6], a[5], a[4], a[3], a[2], a[1], a[0]));
            let netmask = if net_bits <= 128 {
                    IpAddr::V6(netmask_v6(net_bits))
                } else {
                    IpAddr::Empty
                };
            NetworkAddrs { addr, netmask }
        },
        _ => NetworkAddrs { addr: IpAddr::Empty, netmask: IpAddr::Empty }
    }
}

// This faster than [u8;4], but v6 is slower if use this..
// And the scan() method is slower also.
fn netmask_v4(bits: u8) -> Ipv4Addr {
    let mut i = (0..4).map(|idx| {
        let idx8 = idx << 3;
        match (bits as usize > idx8, bits as usize > idx8 + 8) {
            (true, true) => 255,
            (true, false) => 255 << 8 - bits % 8,
            _ => 0,
        }
    });
    Ipv4Addr::new(
        i.next().unwrap(),
        i.next().unwrap(),
        i.next().unwrap(),
        i.next().unwrap(),
    )
}

fn netmask_v6(bits: u8) -> Ipv6Addr {
    let mut tmp = [0u16; 8];
    (0..8).for_each(|idx| {
        let idx16 = idx << 4;
        match (bits as usize > idx16, bits as usize > idx16 + 16) {
            (true, true) => {
                tmp[idx] = 0xffff;
            }
            (true, false) => {
                tmp[idx] = 0xffff << 16 - bits % 16;
            }
            _ => {}
        }
    });
    Ipv6Addr::new(
        tmp[0],
        tmp[1],
        tmp[2],
        tmp[3],
        tmp[4],
        tmp[5],
        tmp[6],
        tmp[7],
    )
}<|endoftext|>


<commit_before>use ra_syntax::{
    algo::visit::{visitor, Visitor},
    AstNode,
    ast::{self, LoopBodyOwner},
    SyntaxKind::*, SyntaxNodeRef,
};

use crate::completion::{CompletionContext, CompletionItem, Completions, CompletionKind, CompletionItemKind};

fn keyword(kw: &str, snippet: &str) -> CompletionItem {
    CompletionItem::new(CompletionKind::Keyword, kw)
        .kind(CompletionItemKind::Keyword)
        .snippet(snippet)
        .build()
}

pub(super) fn complete_expr_keyword(acc: &mut Completions, ctx: &CompletionContext) {
    if !ctx.is_trivial_path {
        return;
    }
    let fn_def = match ctx.function_syntax {
        Some(it) => it,
        None => return,
    };
    acc.add(keyword("if", "if $0 {}"));
    acc.add(keyword("match", "match $0 {}"));
    acc.add(keyword("while", "while $0 {}"));
    acc.add(keyword("loop", "loop {$0}"));

    if ctx.after_if {
        acc.add(keyword("else", "else {$0}"));
        acc.add(keyword("else if", "else if $0 {}"));
    }
    if is_in_loop_body(ctx.leaf) {
        acc.add(keyword("continue", "continue"));
        acc.add(keyword("break", "break"));
    }
    acc.add_all(complete_return(fn_def, ctx.can_be_stmt));
}

fn is_in_loop_body(leaf: SyntaxNodeRef) -> bool {
    for node in leaf.ancestors() {
        if node.kind() == FN_DEF || node.kind() == LAMBDA_EXPR {
            break;
        }
        let loop_body = visitor()
            .visit::<ast::ForExpr, _>(LoopBodyOwner::loop_body)
            .visit::<ast::WhileExpr, _>(LoopBodyOwner::loop_body)
            .visit::<ast::LoopExpr, _>(LoopBodyOwner::loop_body)
            .accept(node);
        if let Some(Some(body)) = loop_body {
            if leaf.range().is_subrange(&body.syntax().range()) {
                return true;
            }
        }
    }
    false
}

fn complete_return(fn_def: ast::FnDef, can_be_stmt: bool) -> Option<CompletionItem> {
    let snip = match (can_be_stmt, fn_def.ret_type().is_some()) {
        (true, true) => "return $0;",
        (true, false) => "return;",
        (false, true) => "return $0",
        (false, false) => "return",
    };
    Some(keyword("return", snip))
}

#[cfg(test)]
mod tests {
    use crate::completion::{CompletionKind, check_completion};
    fn check_keyword_completion(code: &str, expected_completions: &str) {
        check_completion(code, expected_completions, CompletionKind::Keyword);
    }

    #[test]
    fn completes_various_keywords_in_function() {
        check_keyword_completion(
            r"
            fn quux() {
                <|>
            }
            ",
            r#"
            if "if $0 {}"
            match "match $0 {}"
            while "while $0 {}"
            loop "loop {$0}"
            return "return;"
            "#,
        );
    }

    #[test]
    fn completes_else_after_if() {
        check_keyword_completion(
            r"
            fn quux() {
                if true {
                    ()
                } <|>
            }
            ",
            r#"
            if "if $0 {}"
            match "match $0 {}"
            while "while $0 {}"
            loop "loop {$0}"
            else "else {$0}"
            else if "else if $0 {}"
            return "return;"
            "#,
        );
    }

    #[test]
    fn test_completion_return_value() {
        check_keyword_completion(
            r"
            fn quux() -> i32 {
                <|>
                92
            }
            ",
            r#"
            if "if $0 {}"
            match "match $0 {}"
            while "while $0 {}"
            loop "loop {$0}"
            return "return $0;"
            "#,
        );
        check_keyword_completion(
            r"
            fn quux() {
                <|>
                92
            }
            ",
            r#"
            if "if $0 {}"
            match "match $0 {}"
            while "while $0 {}"
            loop "loop {$0}"
            return "return;"
            "#,
        );
    }

    #[test]
    fn dont_add_semi_after_return_if_not_a_statement() {
        check_keyword_completion(
            r"
            fn quux() -> i32 {
                match () {
                    () => <|>
                }
            }
            ",
            r#"
            if "if $0 {}"
            match "match $0 {}"
            while "while $0 {}"
            loop "loop {$0}"
            return "return $0"
            "#,
        );
    }

    #[test]
    fn last_return_in_block_has_semi() {
        check_keyword_completion(
            r"
            fn quux() -> i32 {
                if condition {
                    <|>
                }
            }
            ",
            r#"
            if "if $0 {}"
            match "match $0 {}"
            while "while $0 {}"
            loop "loop {$0}"
            return "return $0;"
            "#,
        );
    }

    #[test]
    fn completes_break_and_continue_in_loops() {
        check_keyword_completion(
            r"
            fn quux() -> i32 {
                loop { <|> }
            }
            ",
            r#"
            if "if $0 {}"
            match "match $0 {}"
            while "while $0 {}"
            loop "loop {$0}"
            continue "continue"
            break "break"
            return "return $0;"
            "#,
        );
        // No completion: lambda isolates control flow
        check_keyword_completion(
            r"
            fn quux() -> i32 {
                loop { || { <|> } }
            }
            ",
            r#"
            if "if $0 {}"
            match "match $0 {}"
            while "while $0 {}"
            loop "loop {$0}"
            return "return $0;"
            "#,
        );
    }
}
<commit_msg>semies after break&continue<commit_after>use ra_syntax::{
    algo::visit::{visitor, Visitor},
    AstNode,
    ast::{self, LoopBodyOwner},
    SyntaxKind::*, SyntaxNodeRef,
};

use crate::completion::{CompletionContext, CompletionItem, Completions, CompletionKind, CompletionItemKind};

fn keyword(kw: &str, snippet: &str) -> CompletionItem {
    CompletionItem::new(CompletionKind::Keyword, kw)
        .kind(CompletionItemKind::Keyword)
        .snippet(snippet)
        .build()
}

pub(super) fn complete_expr_keyword(acc: &mut Completions, ctx: &CompletionContext) {
    if !ctx.is_trivial_path {
        return;
    }
    let fn_def = match ctx.function_syntax {
        Some(it) => it,
        None => return,
    };
    acc.add(keyword("if", "if $0 {}"));
    acc.add(keyword("match", "match $0 {}"));
    acc.add(keyword("while", "while $0 {}"));
    acc.add(keyword("loop", "loop {$0}"));

    if ctx.after_if {
        acc.add(keyword("else", "else {$0}"));
        acc.add(keyword("else if", "else if $0 {}"));
    }
    if is_in_loop_body(ctx.leaf) {
        if ctx.can_be_stmt {
            acc.add(keyword("continue", "continue;"));
            acc.add(keyword("break", "break;"));
        } else {
            acc.add(keyword("continue", "continue"));
            acc.add(keyword("break", "break"));
        }
    }
    acc.add_all(complete_return(fn_def, ctx.can_be_stmt));
}

fn is_in_loop_body(leaf: SyntaxNodeRef) -> bool {
    for node in leaf.ancestors() {
        if node.kind() == FN_DEF || node.kind() == LAMBDA_EXPR {
            break;
        }
        let loop_body = visitor()
            .visit::<ast::ForExpr, _>(LoopBodyOwner::loop_body)
            .visit::<ast::WhileExpr, _>(LoopBodyOwner::loop_body)
            .visit::<ast::LoopExpr, _>(LoopBodyOwner::loop_body)
            .accept(node);
        if let Some(Some(body)) = loop_body {
            if leaf.range().is_subrange(&body.syntax().range()) {
                return true;
            }
        }
    }
    false
}

fn complete_return(fn_def: ast::FnDef, can_be_stmt: bool) -> Option<CompletionItem> {
    let snip = match (can_be_stmt, fn_def.ret_type().is_some()) {
        (true, true) => "return $0;",
        (true, false) => "return;",
        (false, true) => "return $0",
        (false, false) => "return",
    };
    Some(keyword("return", snip))
}

#[cfg(test)]
mod tests {
    use crate::completion::{CompletionKind, check_completion};
    fn check_keyword_completion(code: &str, expected_completions: &str) {
        check_completion(code, expected_completions, CompletionKind::Keyword);
    }

    #[test]
    fn completes_various_keywords_in_function() {
        check_keyword_completion(
            r"
            fn quux() {
                <|>
            }
            ",
            r#"
            if "if $0 {}"
            match "match $0 {}"
            while "while $0 {}"
            loop "loop {$0}"
            return "return;"
            "#,
        );
    }

    #[test]
    fn completes_else_after_if() {
        check_keyword_completion(
            r"
            fn quux() {
                if true {
                    ()
                } <|>
            }
            ",
            r#"
            if "if $0 {}"
            match "match $0 {}"
            while "while $0 {}"
            loop "loop {$0}"
            else "else {$0}"
            else if "else if $0 {}"
            return "return;"
            "#,
        );
    }

    #[test]
    fn test_completion_return_value() {
        check_keyword_completion(
            r"
            fn quux() -> i32 {
                <|>
                92
            }
            ",
            r#"
            if "if $0 {}"
            match "match $0 {}"
            while "while $0 {}"
            loop "loop {$0}"
            return "return $0;"
            "#,
        );
        check_keyword_completion(
            r"
            fn quux() {
                <|>
                92
            }
            ",
            r#"
            if "if $0 {}"
            match "match $0 {}"
            while "while $0 {}"
            loop "loop {$0}"
            return "return;"
            "#,
        );
    }

    #[test]
    fn dont_add_semi_after_return_if_not_a_statement() {
        check_keyword_completion(
            r"
            fn quux() -> i32 {
                match () {
                    () => <|>
                }
            }
            ",
            r#"
            if "if $0 {}"
            match "match $0 {}"
            while "while $0 {}"
            loop "loop {$0}"
            return "return $0"
            "#,
        );
    }

    #[test]
    fn last_return_in_block_has_semi() {
        check_keyword_completion(
            r"
            fn quux() -> i32 {
                if condition {
                    <|>
                }
            }
            ",
            r#"
            if "if $0 {}"
            match "match $0 {}"
            while "while $0 {}"
            loop "loop {$0}"
            return "return $0;"
            "#,
        );
    }

    #[test]
    fn completes_break_and_continue_in_loops() {
        check_keyword_completion(
            r"
            fn quux() -> i32 {
                loop { <|> }
            }
            ",
            r#"
            if "if $0 {}"
            match "match $0 {}"
            while "while $0 {}"
            loop "loop {$0}"
            continue "continue;"
            break "break;"
            return "return $0;"
            "#,
        );
        // No completion: lambda isolates control flow
        check_keyword_completion(
            r"
            fn quux() -> i32 {
                loop { || { <|> } }
            }
            ",
            r#"
            if "if $0 {}"
            match "match $0 {}"
            while "while $0 {}"
            loop "loop {$0}"
            return "return $0;"
            "#,
        );
    }

    #[test]
    fn no_semi_after_break_continue_in_expr() {
        check_keyword_completion(
            r"
            fn f() {
                loop {
                    match () {
                        () => br<|>
                    }
                }
            }
            ",
            r#"
            if "if $0 {}"
            match "match $0 {}"
            while "while $0 {}"
            loop "loop {$0}"
            continue "continue"
            break "break"
            return "return"
            "#,
        )
    }
}
<|endoftext|>


<commit_before>use std::num::abs;

struct Point {
    x: f64,
    y: f64,
}

// implementation block, all Point methods go in here
impl Point {
    // static method, generally used for constructors
    fn origin() -> Point {
        Point { x: 0.0, y: 0.0 }
    }

    // another static method, that takes two arguments
    fn new(x: f64, y: f64) -> Point {
        Point { x: x, y: y }
    }
}

struct Rectangle {
    p1: Point,
    p2: Point,
}

impl Rectangle {
    // instance method, self refers to the caller object
    fn area(&self) -> f64 {
        // `self` gives access to the struct fields via the dot operator
        let Point { x: x1, y: y1 } = self.p1;
        let Point { x: x2, y: y2 } = self.p2;

        abs((x1 - x2) * (y1 - y2))
    }

    fn perimeter(&self) -> f64 {
        let Point { x: x1, y: y1 } = self.p1;
        let Point { x: x2, y: y2 } = self.p2;

        2.0 * abs(x1 - x2) + 2.0 * abs(y1 - y2)
    }

    // this method requires the caller object to be mutable
    fn move(&mut self, x: f64, y: f64) {
        self.p1.x += x;
        self.p2.x += x;

        self.p1.y += y;
        self.p2.y += y;
    }
}

struct Bomb {
    name: ~str,
}

impl Bomb {
    // this method consumes the caller object
    fn boom(self) {
        println!("{} goes boom!", self.name);
        // self goes out of scope and its destroyed
    }
}

fn main() {
    let rectangle = Rectangle {
        // static methods are called using double semicolons
        p1: Point::origin(),
        p2: Point::new(3.0, 4.0),
    };

    // instance method are called using the dot operator
    // note that the first argument &self is implicitly passed
    println!("Rectangle perimeter: {}", rectangle.perimeter());
    println!("Rectangle area: {}", rectangle.area());

    let mut square = Rectangle {
        p1: Point::origin(),
        p2: Point::new(1.0, 1.0),
    };

    // Error: object is immutable, but method requires a mutable object
    //rectangle.move(1.0, 0.0);

    // Ok: mutable object can call mutable methods
    square.move(1.0, 1.0);

    let bomb = Bomb { name: ~"C4" };

    bomb.boom();

    // Error: previous boom() call moved the bomb out of scope
    //bomb.boom();
}
<commit_msg>Fixed some typos<commit_after>use std::num::abs;

struct Point {
    x: f64,
    y: f64,
}

// implementation block, all Point methods go in here
impl Point {
    // static method, generally used for constructors
    fn origin() -> Point {
        Point { x: 0.0, y: 0.0 }
    }

    // another static method, that takes two arguments
    fn new(x: f64, y: f64) -> Point {
        Point { x: x, y: y }
    }
}

struct Rectangle {
    p1: Point,
    p2: Point,
}

impl Rectangle {
    // instance method, self refers to the caller object
    fn area(&self) -> f64 {
        // `self` gives access to the struct fields via the dot operator
        let Point { x: x1, y: y1 } = self.p1;
        let Point { x: x2, y: y2 } = self.p2;

        abs((x1 - x2) * (y1 - y2))
    }

    fn perimeter(&self) -> f64 {
        let Point { x: x1, y: y1 } = self.p1;
        let Point { x: x2, y: y2 } = self.p2;

        2.0 * abs(x1 - x2) + 2.0 * abs(y1 - y2)
    }

    // this method requires the caller object to be mutable
    fn move(&mut self, x: f64, y: f64) {
        self.p1.x += x;
        self.p2.x += x;

        self.p1.y += y;
        self.p2.y += y;
    }
}

struct Bomb {
    name: ~str,
}

impl Bomb {
    // this method consumes the caller object
    fn boom(self) {
        println!("{} goes boom!", self.name);
        // self goes out of scope and it's destroyed
    }
}

fn main() {
    let rectangle = Rectangle {
        // static methods are called using double colons
        p1: Point::origin(),
        p2: Point::new(3.0, 4.0),
    };

    // instance method are called using the dot operator
    // note that the first argument &self is implicitly passed
    println!("Rectangle perimeter: {}", rectangle.perimeter());
    println!("Rectangle area: {}", rectangle.area());

    let mut square = Rectangle {
        p1: Point::origin(),
        p2: Point::new(1.0, 1.0),
    };

    // Error: object is immutable, but method requires a mutable object
    //rectangle.move(1.0, 0.0);

    // Ok: mutable object can call mutable methods
    square.move(1.0, 1.0);

    let bomb = Bomb { name: ~"C4" };

    bomb.boom();

    // Error: previous boom() call moved the bomb out of scope
    //bomb.boom();
}
<|endoftext|>


<commit_before>use imageops::*;
use imageops::ops::*;

extern crate multicache;
use self::multicache::MultiCache;
use std::sync::Arc;
use std::io::Write;

extern crate time;
extern crate serde;
extern crate serde_yaml;
use self::serde::{Serialize,Deserialize};

fn do_timing<O, F: FnMut() -> O>(name: &str, mut closure: F) -> O {
  let from_time = time::precise_time_ns();
  let ret = closure();
  let to_time = time::precise_time_ns();
  println!("{} ms for '{}'", (to_time - from_time)/1000000, name);

  ret
}

pub trait ImageOp<'a>: Debug+Serialize+Deserialize<'a> {
  fn name(&self) -> &str;
  fn run(&self, pipeline: &mut PipelineGlobals, inid: BufHash, outid: BufHash);
  fn to_settings(&self) -> String {
    serde_yaml::to_string(self).unwrap()
  }
  fn hash(&self, hasher: &mut BufHasher) {
    // Hash the name first as a zero sized struct doesn't actually do any hashing
    hasher.write(self.name().as_bytes()).unwrap();
    hasher.from_serialize(self);
  }
}

#[derive(Debug, Copy, Clone, Serialize)]
pub struct PipelineSettings {
  pub maxwidth: usize,
  pub maxheight: usize,
  pub linear: bool,
}

impl PipelineSettings{
  fn hash(&self, hasher: &mut BufHasher) {
    hasher.from_serialize(self);
  }
}

#[derive(Debug)]
pub struct PipelineGlobals<'a> {
  pub cache: MultiCache<BufHash, OpBuffer>,
  pub image: &'a RawImage,
  pub settings: PipelineSettings,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PipelineOps {
  gofloat: gofloat::OpGoFloat,
  demosaic: demosaic::OpDemosaic,
  level: level::OpLevel,
  tolab: colorspaces::OpToLab,
  basecurve: curves::OpBaseCurve,
  fromlab: colorspaces::OpFromLab,
  gamma: gamma::OpGamma,
  transform: transform::OpTransform,
}

macro_rules! for_vals {
  ([$($val:expr),*] |$x:pat, $i:ident| $body:expr) => {
    let mut pos = 0;
    $({
      let $x = $val;
      pos += 1;
      let $i = pos-1;
      $body
    })*
  }
}

macro_rules! all_ops {
  ($ops:expr, |$x:pat, $i:ident| $body:expr) => {
    for_vals!([
      $ops.gofloat,
      $ops.demosaic,
      $ops.level,
      $ops.tolab,
      $ops.basecurve,
      $ops.fromlab,
      $ops.gamma,
      $ops.transform
    ] |$x, $i| {
      $body
    });
  }
}

#[derive(Debug)]
pub struct Pipeline<'a> {
  globals: PipelineGlobals<'a>,
  ops: PipelineOps,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct PipelineSerialization {
  version: u32,
  filehash: String,
}

impl<'a> Pipeline<'a> {
  pub fn new(img: &RawImage, maxwidth: usize, maxheight: usize, linear: bool) -> Pipeline {
    // Check if the image's orientation results in a rotation that
    // swaps the maximum width with the maximum height
    let (transpose, ..) = img.orientation.to_flips();
    let (maxwidth, maxheight) = if transpose {
      (maxheight, maxwidth)
    } else {
      (maxwidth, maxheight)
    };

    Pipeline {
      globals: PipelineGlobals {
        cache: MultiCache::new(1),
        image: img,
        settings: PipelineSettings {maxwidth, maxheight, linear},
      },
      ops: PipelineOps {
        gofloat: gofloat::OpGoFloat::new(img),
        demosaic: demosaic::OpDemosaic::new(img),
        level: level::OpLevel::new(img),
        tolab: colorspaces::OpToLab::new(img),
        basecurve: curves::OpBaseCurve::new(img),
        fromlab: colorspaces::OpFromLab::new(img),
        gamma: gamma::OpGamma::new(img),
        transform: transform::OpTransform::new(img),
      },
    }
  }

  pub fn to_serial(&self) -> String {
    let serial = (PipelineSerialization {
      version: 0,
      filehash: "0".to_string(),
    }, &self.ops);

    serde_yaml::to_string(&serial).unwrap()
  }

  pub fn new_from_serial(img: &RawImage, maxwidth: usize, maxheight: usize, linear: bool, serial: String) -> Pipeline {
    let serial: (PipelineSerialization, PipelineOps) = serde_yaml::from_str(&serial).unwrap();

    Pipeline {
      globals: PipelineGlobals {
        cache: MultiCache::new(1),
        image: img,
        settings: PipelineSettings {maxwidth, maxheight, linear},
      },
      ops: serial.1,
    }
  }

  pub fn run(&mut self) -> Arc<OpBuffer> {
    // Generate all the hashes for the operations
    let mut hasher = BufHasher::new();
    let mut ophashes = Vec::new();
    let mut startpos = 0;
    // Hash the base settings that are potentially used by all operations
    self.globals.settings.hash(&mut hasher);
    // Now hash op by op
    all_ops!(self.ops, |ref op, i| {
      op.hash(&mut hasher);
      let result = hasher.result();
      ophashes.push(result);

      // Set the latest op for which we already have the calculated buffer
      if self.globals.cache.contains_key(&result) {
        startpos = i+1;
      }
    });

    // Do the operations, starting with a dummy buffer id as gofloat doesn't use it
    let mut bufin = BufHash::default();
    all_ops!(self.ops, |ref op, i| {
      let hash = ophashes[i];
      if i >= startpos { // We're at the point where we need to start calculating ops
        let globals = &mut self.globals;
        do_timing(op.name(), ||op.run(globals, bufin, hash));
      }
      bufin = hash;
    });
    self.globals.cache.get(&bufin).unwrap()
  }
}
<commit_msg>imageops: shut up the timing by default<commit_after>use imageops::*;
use imageops::ops::*;

extern crate multicache;
use self::multicache::MultiCache;
use std::sync::Arc;
use std::io::Write;

extern crate time;
extern crate serde;
extern crate serde_yaml;
use self::serde::{Serialize,Deserialize};

fn do_timing<O, F: FnMut() -> O>(_name: &str, mut closure: F) -> O {
  //let from_time = time::precise_time_ns();
  let ret = closure();
  //let to_time = time::precise_time_ns();
  //println!("{} ms for '{}'", (to_time - from_time)/1000000, name);

  ret
}

pub trait ImageOp<'a>: Debug+Serialize+Deserialize<'a> {
  fn name(&self) -> &str;
  fn run(&self, pipeline: &mut PipelineGlobals, inid: BufHash, outid: BufHash);
  fn to_settings(&self) -> String {
    serde_yaml::to_string(self).unwrap()
  }
  fn hash(&self, hasher: &mut BufHasher) {
    // Hash the name first as a zero sized struct doesn't actually do any hashing
    hasher.write(self.name().as_bytes()).unwrap();
    hasher.from_serialize(self);
  }
}

#[derive(Debug, Copy, Clone, Serialize)]
pub struct PipelineSettings {
  pub maxwidth: usize,
  pub maxheight: usize,
  pub linear: bool,
}

impl PipelineSettings{
  fn hash(&self, hasher: &mut BufHasher) {
    hasher.from_serialize(self);
  }
}

#[derive(Debug)]
pub struct PipelineGlobals<'a> {
  pub cache: MultiCache<BufHash, OpBuffer>,
  pub image: &'a RawImage,
  pub settings: PipelineSettings,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PipelineOps {
  gofloat: gofloat::OpGoFloat,
  demosaic: demosaic::OpDemosaic,
  level: level::OpLevel,
  tolab: colorspaces::OpToLab,
  basecurve: curves::OpBaseCurve,
  fromlab: colorspaces::OpFromLab,
  gamma: gamma::OpGamma,
  transform: transform::OpTransform,
}

macro_rules! for_vals {
  ([$($val:expr),*] |$x:pat, $i:ident| $body:expr) => {
    let mut pos = 0;
    $({
      let $x = $val;
      pos += 1;
      let $i = pos-1;
      $body
    })*
  }
}

macro_rules! all_ops {
  ($ops:expr, |$x:pat, $i:ident| $body:expr) => {
    for_vals!([
      $ops.gofloat,
      $ops.demosaic,
      $ops.level,
      $ops.tolab,
      $ops.basecurve,
      $ops.fromlab,
      $ops.gamma,
      $ops.transform
    ] |$x, $i| {
      $body
    });
  }
}

#[derive(Debug)]
pub struct Pipeline<'a> {
  globals: PipelineGlobals<'a>,
  ops: PipelineOps,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct PipelineSerialization {
  version: u32,
  filehash: String,
}

impl<'a> Pipeline<'a> {
  pub fn new(img: &RawImage, maxwidth: usize, maxheight: usize, linear: bool) -> Pipeline {
    // Check if the image's orientation results in a rotation that
    // swaps the maximum width with the maximum height
    let (transpose, ..) = img.orientation.to_flips();
    let (maxwidth, maxheight) = if transpose {
      (maxheight, maxwidth)
    } else {
      (maxwidth, maxheight)
    };

    Pipeline {
      globals: PipelineGlobals {
        cache: MultiCache::new(1),
        image: img,
        settings: PipelineSettings {maxwidth, maxheight, linear},
      },
      ops: PipelineOps {
        gofloat: gofloat::OpGoFloat::new(img),
        demosaic: demosaic::OpDemosaic::new(img),
        level: level::OpLevel::new(img),
        tolab: colorspaces::OpToLab::new(img),
        basecurve: curves::OpBaseCurve::new(img),
        fromlab: colorspaces::OpFromLab::new(img),
        gamma: gamma::OpGamma::new(img),
        transform: transform::OpTransform::new(img),
      },
    }
  }

  pub fn to_serial(&self) -> String {
    let serial = (PipelineSerialization {
      version: 0,
      filehash: "0".to_string(),
    }, &self.ops);

    serde_yaml::to_string(&serial).unwrap()
  }

  pub fn new_from_serial(img: &RawImage, maxwidth: usize, maxheight: usize, linear: bool, serial: String) -> Pipeline {
    let serial: (PipelineSerialization, PipelineOps) = serde_yaml::from_str(&serial).unwrap();

    Pipeline {
      globals: PipelineGlobals {
        cache: MultiCache::new(1),
        image: img,
        settings: PipelineSettings {maxwidth, maxheight, linear},
      },
      ops: serial.1,
    }
  }

  pub fn run(&mut self) -> Arc<OpBuffer> {
    // Generate all the hashes for the operations
    let mut hasher = BufHasher::new();
    let mut ophashes = Vec::new();
    let mut startpos = 0;
    // Hash the base settings that are potentially used by all operations
    self.globals.settings.hash(&mut hasher);
    // Now hash op by op
    all_ops!(self.ops, |ref op, i| {
      op.hash(&mut hasher);
      let result = hasher.result();
      ophashes.push(result);

      // Set the latest op for which we already have the calculated buffer
      if self.globals.cache.contains_key(&result) {
        startpos = i+1;
      }
    });

    // Do the operations, starting with a dummy buffer id as gofloat doesn't use it
    let mut bufin = BufHash::default();
    all_ops!(self.ops, |ref op, i| {
      let hash = ophashes[i];
      if i >= startpos { // We're at the point where we need to start calculating ops
        let globals = &mut self.globals;
        do_timing(op.name(), ||op.run(globals, bufin, hash));
      }
      bufin = hash;
    });
    self.globals.cache.get(&bufin).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.

//! Constructor methods for ndarray
//!
//!

use libnum::{Zero, One, Float};

use imp_prelude::*;
use {Shape, StrideShape};
use dimension;
use linspace;
use error::{self, ShapeError, ErrorKind};
use Indexes;
use iterators::{to_vec, to_vec_mapped};

/// Constructor methods for one-dimensional arrays.
///
/// Note that the constructor methods apply to `Array` and `RcArray`,
/// the two array types that have owned storage.
impl<S> ArrayBase<S, Ix1>
    where S: DataOwned
{
    /// Create a one-dimensional array from a vector (no copying needed).
    ///
    /// ```rust
    /// use ndarray::Array;
    ///
    /// let array = Array::from_vec(vec![1., 2., 3., 4.]);
    /// ```
    pub fn from_vec(v: Vec<S::Elem>) -> Self {
        unsafe { Self::from_shape_vec_unchecked(v.len() as Ix, v) }
    }

    /// Create a one-dimensional array from an iterable.
    ///
    /// ```rust
    /// use ndarray::{Array, arr1};
    ///
    /// let array = Array::from_iter((0..5).map(|x| x * x));
    /// assert!(array == arr1(&[0, 1, 4, 9, 16]))
    /// ```
    pub fn from_iter(iterable: I) -> Self
        where I: IntoIterator<Item=S::Elem>
    {
        Self::from_vec(iterable.into_iter().collect())
    }

    /// Create a one-dimensional array from the inclusive interval
    /// `[start, end]` with `n` elements. `F` must be a floating point type.
    ///
    /// ```rust
    /// use ndarray::{Array, arr1};
    ///
    /// let array = Array::linspace(0., 1., 5);
    /// assert!(array == arr1(&[0.0, 0.25, 0.5, 0.75, 1.0]))
    /// ```
    pub fn linspace<F>(start: F, end: F, n: usize) -> Self
        where S: Data<Elem=F>,
              F: Float,
    {
        Self::from_vec(to_vec(linspace::linspace(start, end, n)))
    }

    /// Create a one-dimensional array from the half-open interval
    /// `[start, end)` with elements spaced by `step`. `F` must be a floating point type.
    ///
    /// ```rust
    /// use ndarray::{Array, arr1};
    ///
    /// let array = Array::range(0., 5., 1.);
    /// assert!(array == arr1(&[0., 1., 2., 3., 4.]))
    /// ```
    pub fn range<F>(start: F, end: F, step: F) -> Self
        where S: Data<Elem=F>,
              F: Float,
    {
        Self::from_vec(to_vec(linspace::range(start, end, step)))
    }
}

/// Constructor methods for two-dimensional arrays.
impl<S, A> ArrayBase<S, Ix2>
    where S: DataOwned<Elem=A>,
{
    /// Create an identity matrix of size `n` (square 2D array).
    ///
    /// **Panics** if `n * n` would overflow usize.
    pub fn eye(n: Ix) -> Self
        where S: DataMut,
              A: Clone + Zero + One,
    {
        let mut eye = Self::zeros((n, n));
        for a_ii in eye.diag_mut() {
            *a_ii = A::one();
        }
        eye
    }
}

macro_rules! size_checked_unwrap {
    ($dim:expr) => {
        match $dim.size_checked() {
            Some(sz) => sz,
            None => panic!("ndarray: Shape too large, number of elements overflows usize"),
        }
    }
}

/// Constructor methods for n-dimensional arrays.
impl<S, A, D> ArrayBase<S, D>
    where S: DataOwned<Elem=A>,
          D: Dimension,
{
    /// Create an array with copies of `elem`, shape `shape`.
    ///
    /// **Panics** if the number of elements in `shape` would overflow usize.
    ///
    /// ```
    /// use ndarray::{Array, arr3, ShapeBuilder};
    ///
    /// let a = Array::from_elem((2, 2, 2), 1.);
    ///
    /// assert!(
    ///     a == arr3(&[[[1., 1.],
    ///                  [1., 1.]],
    ///                 [[1., 1.],
    ///                  [1., 1.]]])
    /// );
    /// assert!(a.strides() == &[4, 2, 1]);
    ///
    /// let b = Array::from_elem((2, 2, 2).f(), 1.);
    /// assert!(b.strides() == &[1, 2, 4]);
    /// ```
    pub fn from_elem<Sh>(shape: Sh, elem: A) -> Self
        where A: Clone,
              Sh: ShapeBuilder<Dim=D>,
    {
        // Note: We don't need to check the case of a size between
        // isize::MAX -> usize::MAX; in this case, the vec constructor itself
        // panics.
        let shape = shape.into_shape();
        let size = size_checked_unwrap!(shape.dim);
        let v = vec![elem; size];
        unsafe { Self::from_shape_vec_unchecked(shape, v) }
    }

    /// Create an array with zeros, shape `shape`.
    ///
    /// **Panics** if the number of elements in `shape` would overflow usize.
    pub fn zeros<Sh>(shape: Sh) -> Self
        where A: Clone + Zero,
              Sh: ShapeBuilder<Dim=D>,
    {
        Self::from_elem(shape, A::zero())
    }

    /// Create an array with default values, shape `shape`
    ///
    /// **Panics** if the number of elements in `shape` would overflow usize.
    pub fn default<Sh>(shape: Sh) -> Self
        where A: Default,
              Sh: ShapeBuilder<Dim=D>,
    {
        let shape = shape.into_shape();
        let v = to_vec((0..shape.dim.size()).map(|_| A::default()));
        unsafe { Self::from_shape_vec_unchecked(shape, v) }
    }

    /// Create an array with values created by the function `f`.
    ///
    /// The elements are visited in arbitirary order.
    ///
    /// **Panics** if the number of elements in `shape` would overflow usize.
    pub fn from_shape_fn<Sh, F>(shape: Sh, f: F) -> Self
        where Sh: ShapeBuilder<Dim=D>,
              F: FnMut(D::Pattern) -> A,
    {
        let shape = shape.into_shape();
        let v = to_vec_mapped(Indexes::new(shape.dim.clone()), f);
        unsafe { Self::from_shape_vec_unchecked(shape, v) }
    }

    /// Create an array with the given shape from a vector. (No cloning of
    /// elements needed.)
    ///
    /// ----
    ///
    /// For a contiguous c- or f-order shape, the following applies:
    ///
    /// **Errors** if `shape` does not correspond to the number of elements in `v`.
    ///
    /// ----
    ///
    /// For custom strides, the following applies:
    ///
    /// **Errors** if strides and dimensions can point out of bounds of `v`.

    /// **Errors** if strides allow multiple indices to point to the same element.
    ///
    /// ```
    /// use ndarray::prelude::*;
    ///
    /// let a = Array::from_shape_vec((2, 2), vec![1., 2., 3., 4.]);
    /// assert!(a.is_ok());
    ///
    /// let b = Array::from_shape_vec((2, 2).strides((1, 2)),
    ///                                    vec![1., 2., 3., 4.]).unwrap();
    /// assert!(
    ///     b == arr2(&[[1., 3.],
    ///                 [2., 4.]])
    /// );
    /// ```
    pub fn from_shape_vec<Sh>(shape: Sh, v: Vec) -> Result<Self, ShapeError>
        where Sh: Into<StrideShape<D>>,
    {
        // eliminate the type parameter Sh as soon as possible
        Self::from_shape_vec_impl(shape.into(), v)
    }

    fn from_shape_vec_impl(shape: StrideShape<D>, v: Vec) -> Result<Self, ShapeError>
    {
        if shape.custom {
            Self::from_vec_dim_stride(shape.dim, shape.strides, v)
        } else {
            let dim = shape.dim;
            let strides = shape.strides;
            if dim.size_checked() != Some(v.len()) {
                return Err(error::incompatible_shapes(&Ix1(v.len()), &dim));
            }
            unsafe { Ok(Self::from_vec_dim_stride_unchecked(dim, strides, v)) }
        }
    }

    /// Create an array from a vector and interpret it according to the
    /// provided dimensions and strides. (No cloning of elements needed.)
    ///
    /// Unsafe because dimension and strides are unchecked.
    pub unsafe fn from_shape_vec_unchecked<Sh>(shape: Sh, v: Vec) -> Self
        where Sh: Into<StrideShape<D>>,
    {
        let shape = shape.into();
        Self::from_vec_dim_stride_unchecked(shape.dim, shape.strides, v)
    }

    fn from_vec_dim_stride(dim: D, strides: D, v: Vec)
        -> Result<Self, ShapeError>
    {
        dimension::can_index_slice(&v, &dim, &strides).map(|_| {
            unsafe {
                Self::from_vec_dim_stride_unchecked(dim, strides, v)
            }
        })
    }

    unsafe fn from_vec_dim_stride_unchecked(dim: D, strides: D, mut v: Vec)
        -> Self
    {
        // debug check for issues that indicates wrong use of this constructor
        debug_assert!(match dimension::can_index_slice(&v, &dim, &strides) {
            Ok(_) => true,
            Err(ref e) => match e.kind() {
                ErrorKind::OutOfBounds => false,
                ErrorKind::RangeLimited => false,
                _ => true,
            }
        });
        ArrayBase {
            ptr: v.as_mut_ptr(),
            data: DataOwned::new(v),
            strides: strides,
            dim: dim
        }
    }

}
<commit_msg>Remove unused imports in constructors<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.

//! Constructor methods for ndarray
//!
//!

use libnum::{Zero, One, Float};

use imp_prelude::*;
use StrideShape;
use dimension;
use linspace;
use error::{self, ShapeError, ErrorKind};
use Indexes;
use iterators::{to_vec, to_vec_mapped};

/// Constructor methods for one-dimensional arrays.
///
/// Note that the constructor methods apply to `Array` and `RcArray`,
/// the two array types that have owned storage.
impl<S> ArrayBase<S, Ix1>
    where S: DataOwned
{
    /// Create a one-dimensional array from a vector (no copying needed).
    ///
    /// ```rust
    /// use ndarray::Array;
    ///
    /// let array = Array::from_vec(vec![1., 2., 3., 4.]);
    /// ```
    pub fn from_vec(v: Vec<S::Elem>) -> Self {
        unsafe { Self::from_shape_vec_unchecked(v.len() as Ix, v) }
    }

    /// Create a one-dimensional array from an iterable.
    ///
    /// ```rust
    /// use ndarray::{Array, arr1};
    ///
    /// let array = Array::from_iter((0..5).map(|x| x * x));
    /// assert!(array == arr1(&[0, 1, 4, 9, 16]))
    /// ```
    pub fn from_iter(iterable: I) -> Self
        where I: IntoIterator<Item=S::Elem>
    {
        Self::from_vec(iterable.into_iter().collect())
    }

    /// Create a one-dimensional array from the inclusive interval
    /// `[start, end]` with `n` elements. `F` must be a floating point type.
    ///
    /// ```rust
    /// use ndarray::{Array, arr1};
    ///
    /// let array = Array::linspace(0., 1., 5);
    /// assert!(array == arr1(&[0.0, 0.25, 0.5, 0.75, 1.0]))
    /// ```
    pub fn linspace<F>(start: F, end: F, n: usize) -> Self
        where S: Data<Elem=F>,
              F: Float,
    {
        Self::from_vec(to_vec(linspace::linspace(start, end, n)))
    }

    /// Create a one-dimensional array from the half-open interval
    /// `[start, end)` with elements spaced by `step`. `F` must be a floating point type.
    ///
    /// ```rust
    /// use ndarray::{Array, arr1};
    ///
    /// let array = Array::range(0., 5., 1.);
    /// assert!(array == arr1(&[0., 1., 2., 3., 4.]))
    /// ```
    pub fn range<F>(start: F, end: F, step: F) -> Self
        where S: Data<Elem=F>,
              F: Float,
    {
        Self::from_vec(to_vec(linspace::range(start, end, step)))
    }
}

/// Constructor methods for two-dimensional arrays.
impl<S, A> ArrayBase<S, Ix2>
    where S: DataOwned<Elem=A>,
{
    /// Create an identity matrix of size `n` (square 2D array).
    ///
    /// **Panics** if `n * n` would overflow usize.
    pub fn eye(n: Ix) -> Self
        where S: DataMut,
              A: Clone + Zero + One,
    {
        let mut eye = Self::zeros((n, n));
        for a_ii in eye.diag_mut() {
            *a_ii = A::one();
        }
        eye
    }
}

macro_rules! size_checked_unwrap {
    ($dim:expr) => {
        match $dim.size_checked() {
            Some(sz) => sz,
            None => panic!("ndarray: Shape too large, number of elements overflows usize"),
        }
    }
}

/// Constructor methods for n-dimensional arrays.
impl<S, A, D> ArrayBase<S, D>
    where S: DataOwned<Elem=A>,
          D: Dimension,
{
    /// Create an array with copies of `elem`, shape `shape`.
    ///
    /// **Panics** if the number of elements in `shape` would overflow usize.
    ///
    /// ```
    /// use ndarray::{Array, arr3, ShapeBuilder};
    ///
    /// let a = Array::from_elem((2, 2, 2), 1.);
    ///
    /// assert!(
    ///     a == arr3(&[[[1., 1.],
    ///                  [1., 1.]],
    ///                 [[1., 1.],
    ///                  [1., 1.]]])
    /// );
    /// assert!(a.strides() == &[4, 2, 1]);
    ///
    /// let b = Array::from_elem((2, 2, 2).f(), 1.);
    /// assert!(b.strides() == &[1, 2, 4]);
    /// ```
    pub fn from_elem<Sh>(shape: Sh, elem: A) -> Self
        where A: Clone,
              Sh: ShapeBuilder<Dim=D>,
    {
        // Note: We don't need to check the case of a size between
        // isize::MAX -> usize::MAX; in this case, the vec constructor itself
        // panics.
        let shape = shape.into_shape();
        let size = size_checked_unwrap!(shape.dim);
        let v = vec![elem; size];
        unsafe { Self::from_shape_vec_unchecked(shape, v) }
    }

    /// Create an array with zeros, shape `shape`.
    ///
    /// **Panics** if the number of elements in `shape` would overflow usize.
    pub fn zeros<Sh>(shape: Sh) -> Self
        where A: Clone + Zero,
              Sh: ShapeBuilder<Dim=D>,
    {
        Self::from_elem(shape, A::zero())
    }

    /// Create an array with default values, shape `shape`
    ///
    /// **Panics** if the number of elements in `shape` would overflow usize.
    pub fn default<Sh>(shape: Sh) -> Self
        where A: Default,
              Sh: ShapeBuilder<Dim=D>,
    {
        let shape = shape.into_shape();
        let v = to_vec((0..shape.dim.size()).map(|_| A::default()));
        unsafe { Self::from_shape_vec_unchecked(shape, v) }
    }

    /// Create an array with values created by the function `f`.
    ///
    /// The elements are visited in arbitirary order.
    ///
    /// **Panics** if the number of elements in `shape` would overflow usize.
    pub fn from_shape_fn<Sh, F>(shape: Sh, f: F) -> Self
        where Sh: ShapeBuilder<Dim=D>,
              F: FnMut(D::Pattern) -> A,
    {
        let shape = shape.into_shape();
        let v = to_vec_mapped(Indexes::new(shape.dim.clone()), f);
        unsafe { Self::from_shape_vec_unchecked(shape, v) }
    }

    /// Create an array with the given shape from a vector. (No cloning of
    /// elements needed.)
    ///
    /// ----
    ///
    /// For a contiguous c- or f-order shape, the following applies:
    ///
    /// **Errors** if `shape` does not correspond to the number of elements in `v`.
    ///
    /// ----
    ///
    /// For custom strides, the following applies:
    ///
    /// **Errors** if strides and dimensions can point out of bounds of `v`.

    /// **Errors** if strides allow multiple indices to point to the same element.
    ///
    /// ```
    /// use ndarray::prelude::*;
    ///
    /// let a = Array::from_shape_vec((2, 2), vec![1., 2., 3., 4.]);
    /// assert!(a.is_ok());
    ///
    /// let b = Array::from_shape_vec((2, 2).strides((1, 2)),
    ///                                    vec![1., 2., 3., 4.]).unwrap();
    /// assert!(
    ///     b == arr2(&[[1., 3.],
    ///                 [2., 4.]])
    /// );
    /// ```
    pub fn from_shape_vec<Sh>(shape: Sh, v: Vec) -> Result<Self, ShapeError>
        where Sh: Into<StrideShape<D>>,
    {
        // eliminate the type parameter Sh as soon as possible
        Self::from_shape_vec_impl(shape.into(), v)
    }

    fn from_shape_vec_impl(shape: StrideShape<D>, v: Vec) -> Result<Self, ShapeError>
    {
        if shape.custom {
            Self::from_vec_dim_stride(shape.dim, shape.strides, v)
        } else {
            let dim = shape.dim;
            let strides = shape.strides;
            if dim.size_checked() != Some(v.len()) {
                return Err(error::incompatible_shapes(&Ix1(v.len()), &dim));
            }
            unsafe { Ok(Self::from_vec_dim_stride_unchecked(dim, strides, v)) }
        }
    }

    /// Create an array from a vector and interpret it according to the
    /// provided dimensions and strides. (No cloning of elements needed.)
    ///
    /// Unsafe because dimension and strides are unchecked.
    pub unsafe fn from_shape_vec_unchecked<Sh>(shape: Sh, v: Vec) -> Self
        where Sh: Into<StrideShape<D>>,
    {
        let shape = shape.into();
        Self::from_vec_dim_stride_unchecked(shape.dim, shape.strides, v)
    }

    fn from_vec_dim_stride(dim: D, strides: D, v: Vec)
        -> Result<Self, ShapeError>
    {
        dimension::can_index_slice(&v, &dim, &strides).map(|_| {
            unsafe {
                Self::from_vec_dim_stride_unchecked(dim, strides, v)
            }
        })
    }

    unsafe fn from_vec_dim_stride_unchecked(dim: D, strides: D, mut v: Vec)
        -> Self
    {
        // debug check for issues that indicates wrong use of this constructor
        debug_assert!(match dimension::can_index_slice(&v, &dim, &strides) {
            Ok(_) => true,
            Err(ref e) => match e.kind() {
                ErrorKind::OutOfBounds => false,
                ErrorKind::RangeLimited => false,
                _ => true,
            }
        });
        ArrayBase {
            ptr: v.as_mut_ptr(),
            data: DataOwned::new(v),
            strides: strides,
            dim: dim
        }
    }

}
<|endoftext|>


<commit_before>use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
use internal::{self, Version};
use internal::consts::{self, MAX_REGULAR_STREAM_ID, NO_STREAM};
use std::io::{self, Read, Write};
use uuid::Uuid;

// ========================================================================= //

macro_rules! malformed {
    ($e:expr) => { invalid_data!("Malformed directory entry ({})", $e) };
    ($fmt:expr, $($arg:tt)+) => {
        invalid_data!("Malformed directory entry ({})",
                      format!($fmt, $($arg)+))
    };
}

// ========================================================================= //

#[derive(Clone)]
pub struct DirEntry {
    pub name: String,
    pub obj_type: u8,
    pub color: u8,
    pub left_sibling: u32,
    pub right_sibling: u32,
    pub child: u32,
    pub clsid: Uuid,
    pub state_bits: u32,
    pub creation_time: u64,
    pub modified_time: u64,
    pub start_sector: u32,
    pub stream_len: u64,
}

impl DirEntry {
    pub fn unallocated() -> DirEntry {
        DirEntry {
            name: String::new(),
            obj_type: consts::OBJ_TYPE_UNALLOCATED,
            color: 0,
            left_sibling: NO_STREAM,
            right_sibling: NO_STREAM,
            child: NO_STREAM,
            clsid: Uuid::nil(),
            state_bits: 0,
            creation_time: 0,
            modified_time: 0,
            start_sector: 0,
            stream_len: 0,
        }
    }

    pub fn read_clsid<R: Read>(reader: &mut R) -> io::Result<Uuid> {
        let d1 = reader.read_u32::<LittleEndian>()?;
        let d2 = reader.read_u16::<LittleEndian>()?;
        let d3 = reader.read_u16::<LittleEndian>()?;
        let mut d4 = [0u8; 8];
        reader.read_exact(&mut d4)?;
        Ok(Uuid::from_fields(d1, d2, d3, &d4).unwrap())
    }

    pub fn write_clsid<W: Write>(writer: &mut W, clsid: &Uuid)
                                 -> io::Result<()> {
        let (d1, d2, d3, d4) = clsid.as_fields();
        writer.write_u32::<LittleEndian>(d1)?;
        writer.write_u16::<LittleEndian>(d2)?;
        writer.write_u16::<LittleEndian>(d3)?;
        writer.write_all(d4)?;
        Ok(())
    }

    pub fn read_from<R: Read>(reader: &mut R, version: Version)
                              -> io::Result<DirEntry> {
        let name: String = {
            let mut name_chars: Vec<u16> = Vec::with_capacity(32);
            for _ in 0..32 {
                name_chars.push(reader.read_u16::<LittleEndian>()?);
            }
            let name_len_bytes = reader.read_u16::<LittleEndian>()?;
            if name_len_bytes > 64 {
                malformed!("name length too large: {}", name_len_bytes);
            } else if name_len_bytes % 2 != 0 {
                malformed!("odd name length: {}", name_len_bytes);
            }
            let name_len_chars = if name_len_bytes > 0 {
                (name_len_bytes / 2 - 1) as usize
            } else {
                0
            };
            debug_assert!(name_len_chars < name_chars.len());
            if name_chars[name_len_chars] != 0 {
                malformed!("name not null-terminated");
            }
            match String::from_utf16(&name_chars[0..name_len_chars]) {
                Ok(name) => name,
                Err(_) => malformed!("name not valid UTF-16"),
            }
        };
        internal::path::validate_name(&name)?;
        let obj_type = reader.read_u8()?;
        if obj_type != consts::OBJ_TYPE_UNALLOCATED &&
            obj_type != consts::OBJ_TYPE_STORAGE &&
            obj_type != consts::OBJ_TYPE_STREAM &&
            obj_type != consts::OBJ_TYPE_ROOT
        {
            malformed!("invalid object type: {}", obj_type);
        }
        let color = reader.read_u8()?;
        if color != consts::COLOR_RED && color != consts::COLOR_BLACK {
            malformed!("invalid color: {}", color);
        }
        let left_sibling = reader.read_u32::<LittleEndian>()?;
        if left_sibling != NO_STREAM && left_sibling > MAX_REGULAR_STREAM_ID {
            malformed!("invalid left sibling: {}", left_sibling);
        }
        let right_sibling = reader.read_u32::<LittleEndian>()?;
        if right_sibling != NO_STREAM &&
            right_sibling > MAX_REGULAR_STREAM_ID
        {
            malformed!("invalid right sibling: {}", right_sibling);
        }
        let child = reader.read_u32::<LittleEndian>()?;
        if child != NO_STREAM {
            if obj_type == consts::OBJ_TYPE_STREAM {
                malformed!("non-empty stream child: {}", child);
            } else if child > MAX_REGULAR_STREAM_ID {
                malformed!("invalid child: {}", child);
            }
        }
        let clsid = DirEntry::read_clsid(reader)?;
        if obj_type == consts::OBJ_TYPE_STREAM && !clsid.is_nil() {
            malformed!("non-null stream CLSID: {:?}", clsid);
        }
        let state_bits = reader.read_u32::<LittleEndian>()?;
        let creation_time = reader.read_u64::<LittleEndian>()?;
        let modified_time = reader.read_u64::<LittleEndian>()?;
        let start_sector = reader.read_u32::<LittleEndian>()?;
        if obj_type == consts::OBJ_TYPE_STORAGE && start_sector != 0 {
            malformed!("non-zero storage start sector: {}", start_sector);
        }
        let stream_len = reader.read_u64::<LittleEndian>()? &
            version.stream_len_mask();
        if obj_type == consts::OBJ_TYPE_STORAGE && stream_len != 0 {
            malformed!("non-zero storage stream length: {}", stream_len);
        }
        Ok(DirEntry {
               name: name,
               obj_type: obj_type,
               color: color,
               left_sibling: left_sibling,
               right_sibling: right_sibling,
               child: child,
               clsid: clsid,
               state_bits: state_bits,
               creation_time: creation_time,
               modified_time: modified_time,
               start_sector: start_sector,
               stream_len: stream_len,
           })
    }

    pub fn write_to<W: Write>(&self, writer: &mut W) -> io::Result<()> {
        debug_assert!(internal::path::validate_name(&self.name).is_ok());
        let name_utf16: Vec<u16> = self.name.encode_utf16().collect();
        debug_assert!(name_utf16.len() < 32);
        for &chr in name_utf16.iter() {
            writer.write_u16::<LittleEndian>(chr)?;
        }
        for _ in name_utf16.len()..32 {
            writer.write_u16::<LittleEndian>(0)?;
        }
        writer.write_u16::<LittleEndian>((name_utf16.len() as u16 + 1) * 2)?;
        writer.write_u8(self.obj_type)?;
        writer.write_u8(self.color)?;
        writer.write_u32::<LittleEndian>(self.left_sibling)?;
        writer.write_u32::<LittleEndian>(self.right_sibling)?;
        writer.write_u32::<LittleEndian>(self.child)?;
        DirEntry::write_clsid(writer, &self.clsid)?;
        writer.write_u32::<LittleEndian>(self.state_bits)?;
        writer.write_u64::<LittleEndian>(self.creation_time)?;
        writer.write_u64::<LittleEndian>(self.modified_time)?;
        writer.write_u32::<LittleEndian>(self.start_sector)?;
        writer.write_u64::<LittleEndian>(self.stream_len)?;
        Ok(())
    }
}

// ========================================================================= //

#[cfg(test)]
mod tests {
    use super::DirEntry;
    use internal::Version;
    use internal::consts;
    use uuid::Uuid;

    #[test]
    fn parse_valid_storage_entry() {
        let input: [u8; consts::DIR_ENTRY_LEN] = [
            // Name:
            70, 0, 111, 0, 111, 0, 98, 0, 97, 0, 114, 0, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
            14, 0, // name length
            1, // obj type
            1, // color,
            12, 0, 0, 0, // left sibling
            34, 0, 0, 0, // right sibling
            56, 0, 0, 0, // child
            0xe0, 0x85, 0x9f, 0xf2, 0xf9, 0x4f, 0x68, 0x10, // CLSID
            0xab, 0x91, 0x08, 0x00, 0x2b, 0x27, 0xb3, 0xd9, // CLSID
            239, 190, 173, 222, // state bits
            0, 0, 0, 0, 0, 0, 0, 0, // created
            0, 0, 0, 0, 0, 0, 0, 0, // modified
            0, 0, 0, 0, // start sector
            0, 0, 0, 0, 0, 0, 0, 0, // stream length
        ];
        let dir_entry =
            DirEntry::read_from(&mut (&input as &[u8]), Version::V4).unwrap();
        assert_eq!(&dir_entry.name, "Foobar");
        assert_eq!(dir_entry.obj_type, consts::OBJ_TYPE_STORAGE);
        assert_eq!(dir_entry.color, consts::COLOR_BLACK);
        assert_eq!(dir_entry.left_sibling, 12);
        assert_eq!(dir_entry.right_sibling, 34);
        assert_eq!(dir_entry.child, 56);
        assert_eq!(dir_entry.clsid,
                   Uuid::parse_str("F29F85E0-4FF9-1068-AB91-08002B27B3D9")
                       .unwrap());
        assert_eq!(dir_entry.state_bits, 0xdeadbeef);
        assert_eq!(dir_entry.creation_time, 0);
        assert_eq!(dir_entry.modified_time, 0);
        assert_eq!(dir_entry.start_sector, 0);
        assert_eq!(dir_entry.stream_len, 0);
    }

    #[test]
    #[should_panic(expected = "Malformed directory entry \
                               (invalid object type: 3)")]
    fn invalid_object_type() {
        let input: [u8; consts::DIR_ENTRY_LEN] = [
            // Name:
            70, 0, 111, 0, 111, 0, 98, 0, 97, 0, 114, 0, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
            14, 0, // name length
            3, // obj type
            1, // color,
            12, 0, 0, 0, // left sibling
            34, 0, 0, 0, // right sibling
            56, 0, 0, 0, // child
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // CLSID
            239, 190, 173, 222, // state bits
            0, 0, 0, 0, 0, 0, 0, 0, // created
            0, 0, 0, 0, 0, 0, 0, 0, // modified
            0, 0, 0, 0, // start sector
            0, 0, 0, 0, 0, 0, 0, 0, // stream length
        ];
        DirEntry::read_from(&mut (&input as &[u8]), Version::V4).unwrap();
    }

    #[test]
    #[should_panic(expected = "Malformed directory entry (invalid color: 2)")]
    fn invalid_color() {
        let input: [u8; consts::DIR_ENTRY_LEN] = [
            // Name:
            70, 0, 111, 0, 111, 0, 98, 0, 97, 0, 114, 0, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
            14, 0, // name length
            1, // obj type
            2, // color,
            12, 0, 0, 0, // left sibling
            34, 0, 0, 0, // right sibling
            56, 0, 0, 0, // child
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // CLSID
            239, 190, 173, 222, // state bits
            0, 0, 0, 0, 0, 0, 0, 0, // created
            0, 0, 0, 0, 0, 0, 0, 0, // modified
            0, 0, 0, 0, // start sector
            0, 0, 0, 0, 0, 0, 0, 0, // stream length
        ];
        DirEntry::read_from(&mut (&input as &[u8]), Version::V4).unwrap();
    }
}

// ========================================================================= //
<commit_msg>fix for start_sector set to FREE_SECTOR<commit_after>use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
use internal::{self, Version};
use internal::consts::{self, MAX_REGULAR_STREAM_ID, NO_STREAM};
use std::io::{self, Read, Write};
use uuid::Uuid;

// ========================================================================= //

macro_rules! malformed {
    ($e:expr) => { invalid_data!("Malformed directory entry ({})", $e) };
    ($fmt:expr, $($arg:tt)+) => {
        invalid_data!("Malformed directory entry ({})",
                      format!($fmt, $($arg)+))
    };
}

// ========================================================================= //

#[derive(Clone)]
pub struct DirEntry {
    pub name: String,
    pub obj_type: u8,
    pub color: u8,
    pub left_sibling: u32,
    pub right_sibling: u32,
    pub child: u32,
    pub clsid: Uuid,
    pub state_bits: u32,
    pub creation_time: u64,
    pub modified_time: u64,
    pub start_sector: u32,
    pub stream_len: u64,
}

impl DirEntry {
    pub fn unallocated() -> DirEntry {
        DirEntry {
            name: String::new(),
            obj_type: consts::OBJ_TYPE_UNALLOCATED,
            color: 0,
            left_sibling: NO_STREAM,
            right_sibling: NO_STREAM,
            child: NO_STREAM,
            clsid: Uuid::nil(),
            state_bits: 0,
            creation_time: 0,
            modified_time: 0,
            start_sector: 0,
            stream_len: 0,
        }
    }

    pub fn read_clsid<R: Read>(reader: &mut R) -> io::Result<Uuid> {
        let d1 = reader.read_u32::<LittleEndian>()?;
        let d2 = reader.read_u16::<LittleEndian>()?;
        let d3 = reader.read_u16::<LittleEndian>()?;
        let mut d4 = [0u8; 8];
        reader.read_exact(&mut d4)?;
        Ok(Uuid::from_fields(d1, d2, d3, &d4).unwrap())
    }

    pub fn write_clsid<W: Write>(writer: &mut W, clsid: &Uuid)
                                 -> io::Result<()> {
        let (d1, d2, d3, d4) = clsid.as_fields();
        writer.write_u32::<LittleEndian>(d1)?;
        writer.write_u16::<LittleEndian>(d2)?;
        writer.write_u16::<LittleEndian>(d3)?;
        writer.write_all(d4)?;
        Ok(())
    }

    pub fn read_from<R: Read>(reader: &mut R, version: Version)
                              -> io::Result<DirEntry> {
        let name: String = {
            let mut name_chars: Vec<u16> = Vec::with_capacity(32);
            for _ in 0..32 {
                name_chars.push(reader.read_u16::<LittleEndian>()?);
            }
            let name_len_bytes = reader.read_u16::<LittleEndian>()?;
            if name_len_bytes > 64 {
                malformed!("name length too large: {}", name_len_bytes);
            } else if name_len_bytes % 2 != 0 {
                malformed!("odd name length: {}", name_len_bytes);
            }
            let name_len_chars = if name_len_bytes > 0 {
                (name_len_bytes / 2 - 1) as usize
            } else {
                0
            };
            debug_assert!(name_len_chars < name_chars.len());
            if name_chars[name_len_chars] != 0 {
                malformed!("name not null-terminated");
            }
            match String::from_utf16(&name_chars[0..name_len_chars]) {
                Ok(name) => name,
                Err(_) => malformed!("name not valid UTF-16"),
            }
        };
        internal::path::validate_name(&name)?;
        let obj_type = reader.read_u8()?;
        if obj_type != consts::OBJ_TYPE_UNALLOCATED &&
            obj_type != consts::OBJ_TYPE_STORAGE &&
            obj_type != consts::OBJ_TYPE_STREAM &&
            obj_type != consts::OBJ_TYPE_ROOT
        {
            malformed!("invalid object type: {}", obj_type);
        }
        let color = reader.read_u8()?;
        if color != consts::COLOR_RED && color != consts::COLOR_BLACK {
            malformed!("invalid color: {}", color);
        }
        let left_sibling = reader.read_u32::<LittleEndian>()?;
        if left_sibling != NO_STREAM && left_sibling > MAX_REGULAR_STREAM_ID {
            malformed!("invalid left sibling: {}", left_sibling);
        }
        let right_sibling = reader.read_u32::<LittleEndian>()?;
        if right_sibling != NO_STREAM &&
            right_sibling > MAX_REGULAR_STREAM_ID
        {
            malformed!("invalid right sibling: {}", right_sibling);
        }
        let child = reader.read_u32::<LittleEndian>()?;
        if child != NO_STREAM {
            if obj_type == consts::OBJ_TYPE_STREAM {
                malformed!("non-empty stream child: {}", child);
            } else if child > MAX_REGULAR_STREAM_ID {
                malformed!("invalid child: {}", child);
            }
        }
        let clsid = DirEntry::read_clsid(reader)?;
        if obj_type == consts::OBJ_TYPE_STREAM && !clsid.is_nil() {
            malformed!("non-null stream CLSID: {:?}", clsid);
        }
        let state_bits = reader.read_u32::<LittleEndian>()?;
        let creation_time = reader.read_u64::<LittleEndian>()?;
        let modified_time = reader.read_u64::<LittleEndian>()?;
        let start_sector = reader.read_u32::<LittleEndian>()?;

        // Spec say this is suppose to be zero for DirEntries
        // but some cfb implementations set start_sector to FREE_SECTOR instead
        if obj_type == consts::OBJ_TYPE_STORAGE && !(start_sector == 0 || start_sector == consts::FREE_SECTOR) {
            malformed!("non-zero storage start sector: {}", start_sector);
        }
        let stream_len = reader.read_u64::<LittleEndian>()? &
            version.stream_len_mask();
        if obj_type == consts::OBJ_TYPE_STORAGE && stream_len != 0 {
            malformed!("non-zero storage stream length: {}", stream_len);
        }
        Ok(DirEntry {
               name: name,
               obj_type: obj_type,
               color: color,
               left_sibling: left_sibling,
               right_sibling: right_sibling,
               child: child,
               clsid: clsid,
               state_bits: state_bits,
               creation_time: creation_time,
               modified_time: modified_time,
               start_sector: start_sector,
               stream_len: stream_len,
           })
    }

    pub fn write_to<W: Write>(&self, writer: &mut W) -> io::Result<()> {
        debug_assert!(internal::path::validate_name(&self.name).is_ok());
        let name_utf16: Vec<u16> = self.name.encode_utf16().collect();
        debug_assert!(name_utf16.len() < 32);
        for &chr in name_utf16.iter() {
            writer.write_u16::<LittleEndian>(chr)?;
        }
        for _ in name_utf16.len()..32 {
            writer.write_u16::<LittleEndian>(0)?;
        }
        writer.write_u16::<LittleEndian>((name_utf16.len() as u16 + 1) * 2)?;
        writer.write_u8(self.obj_type)?;
        writer.write_u8(self.color)?;
        writer.write_u32::<LittleEndian>(self.left_sibling)?;
        writer.write_u32::<LittleEndian>(self.right_sibling)?;
        writer.write_u32::<LittleEndian>(self.child)?;
        DirEntry::write_clsid(writer, &self.clsid)?;
        writer.write_u32::<LittleEndian>(self.state_bits)?;
        writer.write_u64::<LittleEndian>(self.creation_time)?;
        writer.write_u64::<LittleEndian>(self.modified_time)?;
        writer.write_u32::<LittleEndian>(self.start_sector)?;
        writer.write_u64::<LittleEndian>(self.stream_len)?;
        Ok(())
    }
}

// ========================================================================= //

#[cfg(test)]
mod tests {
    use super::DirEntry;
    use internal::Version;
    use internal::consts;
    use uuid::Uuid;

    #[test]
    fn parse_valid_storage_entry() {
        let input: [u8; consts::DIR_ENTRY_LEN] = [
            // Name:
            70, 0, 111, 0, 111, 0, 98, 0, 97, 0, 114, 0, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
            14, 0, // name length
            1, // obj type
            1, // color,
            12, 0, 0, 0, // left sibling
            34, 0, 0, 0, // right sibling
            56, 0, 0, 0, // child
            0xe0, 0x85, 0x9f, 0xf2, 0xf9, 0x4f, 0x68, 0x10, // CLSID
            0xab, 0x91, 0x08, 0x00, 0x2b, 0x27, 0xb3, 0xd9, // CLSID
            239, 190, 173, 222, // state bits
            0, 0, 0, 0, 0, 0, 0, 0, // created
            0, 0, 0, 0, 0, 0, 0, 0, // modified
            0, 0, 0, 0, // start sector
            0, 0, 0, 0, 0, 0, 0, 0, // stream length
        ];
        let dir_entry =
            DirEntry::read_from(&mut (&input as &[u8]), Version::V4).unwrap();
        assert_eq!(&dir_entry.name, "Foobar");
        assert_eq!(dir_entry.obj_type, consts::OBJ_TYPE_STORAGE);
        assert_eq!(dir_entry.color, consts::COLOR_BLACK);
        assert_eq!(dir_entry.left_sibling, 12);
        assert_eq!(dir_entry.right_sibling, 34);
        assert_eq!(dir_entry.child, 56);
        assert_eq!(dir_entry.clsid,
                   Uuid::parse_str("F29F85E0-4FF9-1068-AB91-08002B27B3D9")
                       .unwrap());
        assert_eq!(dir_entry.state_bits, 0xdeadbeef);
        assert_eq!(dir_entry.creation_time, 0);
        assert_eq!(dir_entry.modified_time, 0);
        assert_eq!(dir_entry.start_sector, 0);
        assert_eq!(dir_entry.stream_len, 0);
    }

    #[test]
    #[should_panic(expected = "Malformed directory entry \
                               (invalid object type: 3)")]
    fn invalid_object_type() {
        let input: [u8; consts::DIR_ENTRY_LEN] = [
            // Name:
            70, 0, 111, 0, 111, 0, 98, 0, 97, 0, 114, 0, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
            14, 0, // name length
            3, // obj type
            1, // color,
            12, 0, 0, 0, // left sibling
            34, 0, 0, 0, // right sibling
            56, 0, 0, 0, // child
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // CLSID
            239, 190, 173, 222, // state bits
            0, 0, 0, 0, 0, 0, 0, 0, // created
            0, 0, 0, 0, 0, 0, 0, 0, // modified
            0, 0, 0, 0, // start sector
            0, 0, 0, 0, 0, 0, 0, 0, // stream length
        ];
        DirEntry::read_from(&mut (&input as &[u8]), Version::V4).unwrap();
    }

    #[test]
    #[should_panic(expected = "Malformed directory entry (invalid color: 2)")]
    fn invalid_color() {
        let input: [u8; consts::DIR_ENTRY_LEN] = [
            // Name:
            70, 0, 111, 0, 111, 0, 98, 0, 97, 0, 114, 0, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
            14, 0, // name length
            1, // obj type
            2, // color,
            12, 0, 0, 0, // left sibling
            34, 0, 0, 0, // right sibling
            56, 0, 0, 0, // child
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // CLSID
            239, 190, 173, 222, // state bits
            0, 0, 0, 0, 0, 0, 0, 0, // created
            0, 0, 0, 0, 0, 0, 0, 0, // modified
            0, 0, 0, 0, // start sector
            0, 0, 0, 0, 0, 0, 0, 0, // stream length
        ];
        DirEntry::read_from(&mut (&input as &[u8]), Version::V4).unwrap();
    }
}

// ========================================================================= //
<|endoftext|>


<commit_before>use super::ident::Identifier;

use std::collections::{HashMap, VecMap};

/// Represents a single scope, translates to source code locations.
pub type ScopeId = usize;

/// Holds an exact location within a ScopedTable.
#[derive(Clone, Debug)]
pub struct ScopePos {
    pub scope: Vec<ScopeId>,
    pub scope_lengths: Vec<usize>,
}

#[derive(Clone, Debug)]
pub struct Symbol<T> where T: Clone {
    pub scope: ScopePos,
    pub val: T,
}

pub struct ScopedTable<T> where T: Clone {
    symbols: HashMap<ScopeId, VecMap<Symbol<T>>>,
    pub scope: Vec<ScopeId>,
    pub scope_lengths: Vec<usize>,
}

impl<T> ScopedTable<T> where T: Clone {
    pub fn new() -> ScopedTable<T> {
        let mut symbols = HashMap::new();
        symbols.insert(0, VecMap::new());
        ScopedTable {
            symbols: symbols,
            scope: vec![0],
            scope_lengths: vec![0],
        }
    }

    /// Push a list of scopes which will all be popped off at once when pop() is called.
    pub fn push_scope(&mut self, scopes: &[ScopeId]) {
        self.scope.push_all(scopes);
        self.scope_lengths.push(scopes.len());
    }

    /// Push a single scope, which will be popped off when pop() is called.
    pub fn push(&mut self, scope: ScopeId) {
        self.scope.push(scope);
        self.scope_lengths.push(1);
        self.symbols.entry(scope).or_insert(VecMap::new());
    }

    /// Push a single scope onto the end of the current group.
    /// It will be popped off along with the rest of the group when pop() is called.
    pub fn push_to_scope(&mut self, scope: ScopeId) {
        self.scope.push(scope);
        *self.scope_lengths.last_mut().unwrap() += 1;
        self.symbols.entry(scope).or_insert(VecMap::new());
    }

    /// Pops the topmost group of scopes from the stack.
    pub fn pop(&mut self) {
        assert!(self.scope_lengths.len() > 1, "tried to leave the outermost scope!");
        for _ in 0..self.scope_lengths.pop().unwrap() {
            self.scope.pop().unwrap();
        }
    }

    /// Returns the current stack of scopes.
    pub fn get_scope_pos(&self) -> ScopePos {
        ScopePos {
            scope: self.scope.clone(),
            scope_lengths: self.scope_lengths.clone(),
        }
    }

    /// Sets a source identifer with the given scope identifier to a value.
    pub fn set_val(&mut self, id: Identifier, scope: ScopeId, val: T) {
        self.push_to_scope(scope);
        let scope_pos = self.get_scope_pos();
        let id_map = self.symbols.get_mut(&scope).unwrap();
        id_map.insert(id, Symbol {
                scope: scope_pos,
                val: val,
            });
    }

    /// Searches backwards through the scope stack until a symbol with the given identifier is
    /// found, and returns the symbol.
    pub fn get_symbol(&self, id: Identifier) -> Option<&Symbol<T>> {
        for block_pos in self.scope.iter().rev() {
            let id_map = self.symbols.get(&block_pos).unwrap();
            if let Some(symbol) = id_map.get(&id) {
                return Some(symbol)
            }
        }
        None
    }

    /// Searches backwards through the scope stack until a symbol with the given identifier is
    /// found, and returns the depth down the stack it was found at.
    pub fn get_symbol_depth(&self, id: Identifier) -> Option<usize> {
        for (idx, block_pos) in self.scope.iter().rev().enumerate() {
            let id_map = self.symbols.get(&block_pos).unwrap();
            if let Some(_) = id_map.get(&id) {
                return Some(idx)
            }
        }
        None
    }
}

<commit_msg>Remove unnecessary public fields<commit_after>use super::ident::Identifier;

use std::collections::{HashMap, VecMap};

/// Represents a single scope, translates to source code locations.
pub type ScopeId = usize;

/// Holds an exact location within a ScopedTable.
#[derive(Clone, Debug)]
pub struct ScopePos {
    pub scope: Vec<ScopeId>,
    pub scope_lengths: Vec<usize>,
}

#[derive(Clone, Debug)]
pub struct Symbol<T> where T: Clone {
    pub scope: ScopePos,
    pub val: T,
}

pub struct ScopedTable<T> where T: Clone {
    symbols: HashMap<ScopeId, VecMap<Symbol<T>>>,
    scope: Vec<ScopeId>,
    scope_lengths: Vec<usize>,
}

impl<T> ScopedTable<T> where T: Clone {
    pub fn new() -> ScopedTable<T> {
        let mut symbols = HashMap::new();
        symbols.insert(0, VecMap::new());
        ScopedTable {
            symbols: symbols,
            scope: vec![0],
            scope_lengths: vec![0],
        }
    }

    /// Push a list of scopes which will all be popped off at once when pop() is called.
    pub fn push_scope(&mut self, scopes: &[ScopeId]) {
        self.scope.push_all(scopes);
        self.scope_lengths.push(scopes.len());
    }

    /// Push a single scope, which will be popped off when pop() is called.
    pub fn push(&mut self, scope: ScopeId) {
        self.scope.push(scope);
        self.scope_lengths.push(1);
        self.symbols.entry(scope).or_insert(VecMap::new());
    }

    /// Push a single scope onto the end of the current group.
    /// It will be popped off along with the rest of the group when pop() is called.
    pub fn push_to_scope(&mut self, scope: ScopeId) {
        self.scope.push(scope);
        *self.scope_lengths.last_mut().unwrap() += 1;
        self.symbols.entry(scope).or_insert(VecMap::new());
    }

    /// Pops the topmost group of scopes from the stack.
    pub fn pop(&mut self) {
        assert!(self.scope_lengths.len() > 1, "tried to leave the outermost scope!");
        for _ in 0..self.scope_lengths.pop().unwrap() {
            self.scope.pop().unwrap();
        }
    }

    /// Returns the current stack of scopes.
    pub fn get_scope_pos(&self) -> ScopePos {
        ScopePos {
            scope: self.scope.clone(),
            scope_lengths: self.scope_lengths.clone(),
        }
    }

    /// Sets a source identifer with the given scope identifier to a value.
    pub fn set_val(&mut self, id: Identifier, scope: ScopeId, val: T) {
        self.push_to_scope(scope);
        let scope_pos = self.get_scope_pos();
        let id_map = self.symbols.get_mut(&scope).unwrap();
        id_map.insert(id, Symbol {
                scope: scope_pos,
                val: val,
            });
    }

    /// Searches backwards through the scope stack until a symbol with the given identifier is
    /// found, and returns the symbol.
    pub fn get_symbol(&self, id: Identifier) -> Option<&Symbol<T>> {
        for block_pos in self.scope.iter().rev() {
            let id_map = self.symbols.get(&block_pos).unwrap();
            if let Some(symbol) = id_map.get(&id) {
                return Some(symbol)
            }
        }
        None
    }

    /// Searches backwards through the scope stack until a symbol with the given identifier is
    /// found, and returns the depth down the stack it was found at.
    pub fn get_symbol_depth(&self, id: Identifier) -> Option<usize> {
        for (idx, block_pos) in self.scope.iter().rev().enumerate() {
            let id_map = self.symbols.get(&block_pos).unwrap();
            if let Some(_) = id_map.get(&id) {
                return Some(idx)
            }
        }
        None
    }
}
<|endoftext|>


<commit_before>use super::*;

impl Editor {
    /// Get pos of next char
    pub fn next_pos(&self) -> (usize, usize) {
        // TODO: Add numerals
        if self.x() == self.text[self.y()].len() {
            if self.y() < self.text.len() - 1 {
                (0, self.y() + 1)
            } else {
                (self.x(), self.y())
            }
        } else {
            (self.x() + 1, self.y())
        }
    }

    /// Get pos of previous char
    pub fn previous_pos(&self) -> (usize, usize) {
        if self.x() == 0 {
            if self.y() > 0 {
                (self.text[self.y()].len(), self.y() - 1)
            } else {
                (self.x(), self.y())
            }
        } else {
            (self.x() - 1, self.y())
        }
    }

    pub fn next(&mut self) {
        let (x, y) = self.next_pos();
        self.cursor_mut().x = x;
        self.cursor_mut().y = y;
    }
    pub fn previous(&mut self) {
        let (x, y) = self.previous_pos();
        self.cursor_mut().x = x;
        self.cursor_mut().y = y;
    }

    /// Get right pos
    pub fn right_pos(&self, n: usize) -> (usize, usize) {
        let x = self.x() + n;

        if x > self.text[self.y()].len() {
            (self.text[self.y()].len(), self.y())
        } else {
            (x, self.y())
        }
    }
    pub fn right(&mut self, n: usize) {
        self.cursor_mut().x = self.right_pos(n).0;
    }

    /// Get left pos
    pub fn left_pos(&self, n: usize) -> (usize, usize) {
        if n <= self.x() {
            (self.x() - n, self.y())
        } else {
            (0, self.y())
        }

    }
    pub fn left(&mut self, n: usize) {
        self.cursor_mut().x = self.left_pos(n).0;
    }

    /// Get up pos
    pub fn up_pos(&self, n: usize) -> (usize, usize) {
        if n <= self.y() {
            (self.cursor().x, self.y() - n)
        } else {
            (self.cursor().x, 0)
        }
    }
    pub fn up(&mut self, n: usize) {
        let (x, y) = self.up_pos(n);
        self.cursor_mut().x = x;
        self.cursor_mut().y = y;
    }

    /// Get down pos
    pub fn down_pos(&self, n: usize) -> (usize, usize) {
        let y = self.y() + n;

        if y >= self.text.len() {
            (self.cursor().x, self.text.len() - 1)
        } else {
            (self.cursor().x, y)
        }
    }

    pub fn down(&mut self, n: usize) {
        let (x, y) = self.down_pos(n);
        self.cursor_mut().x = x;
        self.cursor_mut().y = y;
    }

}
<commit_msg>Fix bug in previous function<commit_after>use super::*;

impl Editor {
    /// Get pos of next char
    pub fn next_pos(&self) -> (usize, usize) {
        // TODO: Add numerals
        if self.x() == self.text[self.y()].len() {
            if self.y() < self.text.len() - 1 {
                (0, self.y() + 1)
            } else {
                (self.x(), self.y())
            }
        } else {
            (self.x() + 1, self.y())
        }
    }

    /// Get pos of previous char
    pub fn previous_pos(&self) -> (usize, usize) {
        if self.x() == 0 {
            if self.y() > 0 {
                (self.text[self.y() - 1].len(), self.y() - 1)
            } else {
                (self.x(), self.y())
            }
        } else {
            (self.x() - 1, self.y())
        }
    }

    pub fn next(&mut self) {
        let (x, y) = self.next_pos();
        self.cursor_mut().x = x;
        self.cursor_mut().y = y;
    }
    pub fn previous(&mut self) {
        let (x, y) = self.previous_pos();
        self.cursor_mut().x = x;
        self.cursor_mut().y = y;
    }

    /// Get right pos
    pub fn right_pos(&self, n: usize) -> (usize, usize) {
        let x = self.x() + n;

        if x > self.text[self.y()].len() {
            (self.text[self.y()].len(), self.y())
        } else {
            (x, self.y())
        }
    }
    pub fn right(&mut self, n: usize) {
        self.cursor_mut().x = self.right_pos(n).0;
    }

    /// Get left pos
    pub fn left_pos(&self, n: usize) -> (usize, usize) {
        if n <= self.x() {
            (self.x() - n, self.y())
        } else {
            (0, self.y())
        }

    }
    pub fn left(&mut self, n: usize) {
        self.cursor_mut().x = self.left_pos(n).0;
    }

    /// Get up pos
    pub fn up_pos(&self, n: usize) -> (usize, usize) {
        if n <= self.y() {
            (self.cursor().x, self.y() - n)
        } else {
            (self.cursor().x, 0)
        }
    }
    pub fn up(&mut self, n: usize) {
        let (x, y) = self.up_pos(n);
        self.cursor_mut().x = x;
        self.cursor_mut().y = y;
    }

    /// Get down pos
    pub fn down_pos(&self, n: usize) -> (usize, usize) {
        let y = self.y() + n;

        if y >= self.text.len() {
            (self.cursor().x, self.text.len() - 1)
        } else {
            (self.cursor().x, y)
        }
    }

    pub fn down(&mut self, n: usize) {
        let (x, y) = self.down_pos(n);
        self.cursor_mut().x = x;
        self.cursor_mut().y = y;
    }

}
<|endoftext|>