<commit_before>use collections::string::String;

use core::mem::size_of;
use core::num::Zero;
use core::ops::{BitOrAssign, ShlAssign};

const ZERO_OP: u8 = 0x00;
const ONE_OP: u8 = 0x01;
const NAME_OP: u8 = 0x08;
const BYTE_PREFIX: u8 = 0x0A;
const WORD_PREFIX: u8 = 0x0B;
const DWORD_PREFIX: u8 = 0x0C;
const STRING_PREFIX: u8 = 0x0D;
const QWORD_PREFIX: u8 = 0x0E;
const SCOPE_OP: u8 = 0x10;
const BUFFER_OP: u8 = 0x11;
const PACKAGE_OP: u8 = 0x12;
const METHOD_OP: u8 = 0x14;
const DUAL_NAME_PREFIX: u8 = 0x2E;
const MULTI_NAME_PREFIX: u8 = 0x2F;
const EXT_OP_PREFIX: u8 = 0x5B;
const ROOT_PREFIX: u8 = 0x5C;
const PARENT_PREFIX: u8 = 0x5E;

//EXT
const OP_REGION_OP: u8 = 0x80;
const FIELD_OP: u8 = 0x81;
const DEVICE_OP: u8 = 0x82;
const PROCESSOR_OP: u8 = 0x83;

pub fn parse_string(bytes: &[u8], i: &mut usize) -> String {
    let mut string = String::new();

    while *i < bytes.len() {
        let c = bytes[*i];
        if (c >= 0x30 && c <= 0x39) || (c >= 0x41 && c <= 0x5A) || c == 0x5F || c == ROOT_PREFIX || c == PARENT_PREFIX {
            string.push(c as char);
        } else {
            break;
        }

        *i += 1;
    }

    string
}

//This one function required three different unstable features and four trait requirements. Why is generic math so hard?
pub fn parse_num<T: BitOrAssign + From<u8> + ShlAssign<usize> + Zero>(bytes: &[u8], i: &mut usize) -> T {
    let mut num: T = T::zero();

    let mut shift = 0;
    while *i < bytes.len() && shift < size_of::<T>() * 8 {
        let mut b = T::from(bytes[*i]);
        b <<= shift;
        num |= b;

        shift += 8;
        *i += 1;
    }

    num
}

pub fn parse_length(bytes: &[u8], i: &mut usize) -> usize {
    let mut length = 0;

    if *i < bytes.len() {
        let b = bytes[*i] as usize;

        let mut follow = (b & 0b11000000) >> 6;
        if follow == 0 {
            length += b & 0b111111;
        } else {
            length += b & 0b1111;
        }

        *i += 1;

        let mut shift = 4;
        while *i < bytes.len() && follow > 0 {
            length += (bytes[*i] as usize) << shift;

            shift += 8;
            follow -= 1;
            *i += 1;
        }
    }

    length
}

pub fn parse_name(bytes: &[u8], i: &mut usize) -> String {
    let mut name = String::new();

    let mut count = 0;
    while *i < bytes.len() {
        match bytes[*i] {
            ZERO_OP => {
                *i += 1;

                count = 0;
                break;
            },
            DUAL_NAME_PREFIX  => {
                *i += 1;

                count = 2;
                break;
            },
            MULTI_NAME_PREFIX => {
                *i += 1;

                if *i < bytes.len() {
                    count = bytes[*i];
                    *i += 1;
                }

                break;
            },
            ROOT_PREFIX => {
                *i += 1;

                name.push('\\');
            },
            PARENT_PREFIX => {
                *i += 1;

                name.push('^');
            },
            _ => {
                count = 1;
                break;
            }
        };
    }

    while count > 0 {
        if ! name.is_empty() {
            name.push('.');
        }

        let end = *i + 4;

        let mut leading = true;
        while *i < bytes.len() && *i < end {
            let c = bytes[*i];
            if (c >= 0x30 && c <= 0x39) || (c >= 0x41 && c <= 0x5A) {
                leading = false;
                name.push(c as char);
            } else if c == 0x5F {
                if leading {
                    name.push('_');
                }
            }else {
                debugln!("parse_name: unknown: {:02X}", c);
                break;
            }

            *i += 1;
        }

        *i = end;

        count -= 1;
    }

    name
}

pub fn parse_int(bytes: &[u8], i: &mut usize) -> u64{
    if *i < bytes.len() {
        let b = bytes[*i];
        *i += 1;

        match b {
            ZERO_OP => return 0,
            ONE_OP => return 1,
            BYTE_PREFIX => return parse_num::<u8>(bytes, i) as u64,
            WORD_PREFIX => return parse_num::<u16>(bytes, i) as u64,
            DWORD_PREFIX => return parse_num::<u32>(bytes, i) as u64,
            QWORD_PREFIX => return parse_num::<u64>(bytes, i),
            _ => debugln!("parse_int: unknown: {:02X}", b),
        }
    }

    return 0;
}

pub fn parse_package(bytes: &[u8], i: &mut usize) {

        let end = *i + parse_length(bytes, i);
        let elements = parse_num::<u8>(bytes, i);

        debugln!("    Package ({})", elements);
        debugln!("    {{");
        while *i < bytes.len() && *i < end {
            let op = bytes[*i];
            *i += 1;

            match op {
                ZERO_OP => {
                    debugln!("        Zero");
                },
                ONE_OP => {
                    debugln!("        One");
                },
                BYTE_PREFIX => {
                    debugln!("        {:02X}", parse_num::<u8>(bytes, i));
                },
                WORD_PREFIX => {
                    debugln!("        {:04X}", parse_num::<u16>(bytes, i));
                },
                DWORD_PREFIX => {
                    debugln!("        {:08X}", parse_num::<u32>(bytes, i));
                },
                QWORD_PREFIX => {
                    debugln!("        {:016X}", parse_num::<u64>(bytes, i));
                },
                PACKAGE_OP => {
                    parse_package(bytes, i);
                },
                _ => {
                    *i -= 1;
                    debugln!("        {}", parse_name(bytes, i));
                    //debugln!("        parse_package: unknown: {:02X}", op);
                }
            }
        }
        debugln!("    }}");

        *i = end;
}

pub fn parse_device(bytes: &[u8], i: &mut usize) {
    let end = *i + parse_length(bytes, i);
    let name = parse_name(bytes, i);

    debugln!("    Device ({})", name);
    debugln!("    {{");
    while *i < bytes.len() && *i < end {
        let op = bytes[*i];
        *i += 1;

        match op {
            ZERO_OP => {
                debugln!("        Zero");
            },
            ONE_OP => {
                debugln!("        One");
            },
            BYTE_PREFIX => {
                debugln!("        {:02X}", parse_num::<u8>(bytes, i));
            },
            WORD_PREFIX => {
                debugln!("        {:04X}", parse_num::<u16>(bytes, i));
            },
            DWORD_PREFIX => {
                debugln!("        {:08X}", parse_num::<u32>(bytes, i));
            },
            STRING_PREFIX => {
                debugln!("        {}", parse_string(bytes, i));
            },
            QWORD_PREFIX => {
                debugln!("        {:016X}", parse_num::<u64>(bytes, i));
            },
            NAME_OP => {
                debugln!("        Name({})", parse_string(bytes, i));
            },
            METHOD_OP => {
                let end = *i + parse_length(bytes, i);
                let name = parse_name(bytes, i);
                let flags = parse_num::<u8>(bytes, i);

                debugln!("        Method ({}, {})", name, flags);
                debugln!("        {{");
                debugln!("        }}");

                *i = end;
            },
            BUFFER_OP => {
                let end = *i + parse_length(bytes, i);

                let count = parse_int(bytes, i);

                debugln!("        Buffer ({})", count);

                *i = end;
            },
            PACKAGE_OP => {
                parse_package(bytes, i);
            },
            EXT_OP_PREFIX => {
                if *i < bytes.len() {
                    let ext_op = bytes[*i];
                    *i += 1;

                    match ext_op {
                        OP_REGION_OP => {
                            let name = parse_name(bytes, i);
                            let space = parse_num::<u8>(bytes, i);
                            let offset = parse_int(bytes, i);
                            let size = parse_int(bytes, i);

                            debugln!("        OperationRegion ({}, {}, {}, {})", name, space, offset, size);
                        },
                        FIELD_OP => {
                            let end = *i + parse_length(bytes, i);

                            let name = parse_name(bytes, i);
                            let flags = parse_num::<u8>(bytes, i);

                            debugln!("        Field ({}, {})", name, flags);
                            debugln!("        {{");
                            while *i < bytes.len() && *i < end {
                                let name = parse_name(bytes, i);
                                let length = parse_length(bytes, i);

                                debugln!("            {}, {}", name, length);
                            }
                            debugln!("        }}");

                            *i = end;
                        },
                        _ => debugln!("        Unknown EXT: {:02X}", ext_op)
                    }
                }
            },
            _ => {
                debugln!("        parse_device: unknown: {:02X}", op);
                break;
            }
        }
    }
    debugln!("    }}");

    *i = end;
}

pub fn parse_scope(bytes: &[u8], i: &mut usize) {
    let end = *i + parse_length(bytes, i);
    let name = parse_name(bytes, i);

    debugln!("Scope ({})", name);
    debugln!("{{");
    while *i < bytes.len() && *i < end {
        let op = bytes[*i];
        *i += 1;

        match op {
            ZERO_OP => {
                debugln!("    Zero");
            },
            ONE_OP => {
                debugln!("    One");
            },
            BYTE_PREFIX => {
                debugln!("    {:02X}", parse_num::<u8>(bytes, i));
            },
            WORD_PREFIX => {
                debugln!("    {:04X}", parse_num::<u16>(bytes, i));
            },
            DWORD_PREFIX => {
                debugln!("    {:08X}", parse_num::<u32>(bytes, i));
            },
            STRING_PREFIX => {
                debugln!("    {}", parse_string(bytes, i));
            }
            QWORD_PREFIX => {
                debugln!("    {:016X}", parse_num::<u64>(bytes, i));
            },
            SCOPE_OP => {
                parse_scope(bytes, i);
            },
            NAME_OP => {
                debugln!("    Name({})", parse_string(bytes, i));
            },
            METHOD_OP => {
                let end = *i + parse_length(bytes, i);
                let name = parse_name(bytes, i);
                let flags = parse_num::<u8>(bytes, i);

                debugln!("    Method ({}, {})", name, flags);
                debugln!("    {{");
                debugln!("    }}");

                *i = end;
            },
            BUFFER_OP => {
                let end = *i + parse_length(bytes, i);

                let count = parse_int(bytes, i);

                debugln!("    Buffer ({})", count);

                *i = end;
            },
            PACKAGE_OP => {
                parse_package(bytes, i);
            },
            EXT_OP_PREFIX => {
                if *i < bytes.len() {
                    let ext_op = bytes[*i];
                    *i += 1;

                    match ext_op {
                        OP_REGION_OP => {
                            let name = parse_name(bytes, i);
                            let space = parse_num::<u8>(bytes, i);
                            let offset = parse_int(bytes, i);
                            let size = parse_int(bytes, i);

                            debugln!("    OperationRegion ({}, {}, {}, {})", name, space, offset, size);
                        },
                        FIELD_OP => {
                            let end = *i + parse_length(bytes, i);

                            let name = parse_name(bytes, i);
                            let flags = parse_num::<u8>(bytes, i);

                            debugln!("    Field ({}, {})", name, flags);
                            debugln!("    {{");
                            while *i < bytes.len() && *i < end {
                                let name = parse_name(bytes, i);
                                let length = parse_length(bytes, i);

                                debugln!("        {}, {}", name, length);
                            }
                            debugln!("    }}");

                            *i = end;
                        },
                        DEVICE_OP => {
                            parse_device(bytes, i);
                        },
                        PROCESSOR_OP => {
                            let end = *i + parse_length(bytes, i);

                            let name = parse_name(bytes, i);
                            let id = parse_num::<u8>(bytes, i);
                            let blk = parse_num::<u32>(bytes, i);
                            let blklen = parse_num::<u8>(bytes, i);

                            debugln!("    Processor ({})", name);

                            *i = end;
                        },
                        _ => debugln!("    Unknown EXT: {:02X}", ext_op)
                    }
                }
            },
            _ => {
                debugln!("    parse_scope: unknown: {:02X}", op);
                break;
            }
        }
    }
    debugln!("}}");

    *i = end;
}

pub fn parse(bytes: &[u8]) {
    let mut i = 0;
    while i < bytes.len() {
        let op = bytes[i];
        i += 1;

        match op {
            SCOPE_OP => {
                parse_scope(bytes, &mut i);
            },
            _ => {
                debugln!("parse: unknown: {:02X}", op);
                break;
            }
        }
    }
}
<commit_msg>No more unknowns in the Qemu DSDT<commit_after>use collections::string::String;

use core::mem::size_of;
use core::num::Zero;
use core::ops::{BitOrAssign, ShlAssign};

const ZERO_OP: u8 = 0x00;
const ONE_OP: u8 = 0x01;
const NAME_OP: u8 = 0x08;
const BYTE_PREFIX: u8 = 0x0A;
const WORD_PREFIX: u8 = 0x0B;
const DWORD_PREFIX: u8 = 0x0C;
const STRING_PREFIX: u8 = 0x0D;
const QWORD_PREFIX: u8 = 0x0E;
const SCOPE_OP: u8 = 0x10;
const BUFFER_OP: u8 = 0x11;
const PACKAGE_OP: u8 = 0x12;
const METHOD_OP: u8 = 0x14;
const DUAL_NAME_PREFIX: u8 = 0x2E;
const MULTI_NAME_PREFIX: u8 = 0x2F;
const EXT_OP_PREFIX: u8 = 0x5B;
const ROOT_PREFIX: u8 = 0x5C;
const PARENT_PREFIX: u8 = 0x5E;

//EXT
const MUTEX_OP: u8 = 0x01;
const OP_REGION_OP: u8 = 0x80;
const FIELD_OP: u8 = 0x81;
const DEVICE_OP: u8 = 0x82;
const PROCESSOR_OP: u8 = 0x83;

pub fn parse_string(bytes: &[u8], i: &mut usize) -> String {
    let mut string = String::new();

    while *i < bytes.len() {
        let c = bytes[*i];
        if (c >= 0x30 && c <= 0x39) || (c >= 0x41 && c <= 0x5A) || c == 0x5F || c == ROOT_PREFIX || c == PARENT_PREFIX {
            string.push(c as char);
        } else {
            break;
        }

        *i += 1;
    }

    string
}

//This one function required three different unstable features and four trait requirements. Why is generic math so hard?
pub fn parse_num<T: BitOrAssign + From<u8> + ShlAssign<usize> + Zero>(bytes: &[u8], i: &mut usize) -> T {
    let mut num: T = T::zero();

    let mut shift = 0;
    while *i < bytes.len() && shift < size_of::<T>() * 8 {
        let mut b = T::from(bytes[*i]);
        b <<= shift;
        num |= b;

        shift += 8;
        *i += 1;
    }

    num
}

pub fn parse_length(bytes: &[u8], i: &mut usize) -> usize {
    let mut length = 0;

    if *i < bytes.len() {
        let b = bytes[*i] as usize;

        let mut follow = (b & 0b11000000) >> 6;
        if follow == 0 {
            length += b & 0b111111;
        } else {
            length += b & 0b1111;
        }

        *i += 1;

        let mut shift = 4;
        while *i < bytes.len() && follow > 0 {
            length += (bytes[*i] as usize) << shift;

            shift += 8;
            follow -= 1;
            *i += 1;
        }
    }

    length
}

pub fn parse_name(bytes: &[u8], i: &mut usize) -> String {
    let mut name = String::new();

    let mut count = 0;
    while *i < bytes.len() {
        match bytes[*i] {
            ZERO_OP => {
                *i += 1;

                count = 0;
                break;
            },
            DUAL_NAME_PREFIX  => {
                *i += 1;

                count = 2;
                break;
            },
            MULTI_NAME_PREFIX => {
                *i += 1;

                if *i < bytes.len() {
                    count = bytes[*i];
                    *i += 1;
                }

                break;
            },
            ROOT_PREFIX => {
                *i += 1;

                name.push('\\');
            },
            PARENT_PREFIX => {
                *i += 1;

                name.push('^');
            },
            _ => {
                count = 1;
                break;
            }
        };
    }

    while count > 0 {
        if ! name.is_empty() {
            name.push('.');
        }

        let end = *i + 4;

        let mut leading = true;
        while *i < bytes.len() && *i < end {
            let c = bytes[*i];
            if (c >= 0x30 && c <= 0x39) || (c >= 0x41 && c <= 0x5A) {
                leading = false;
                name.push(c as char);
            } else if c == 0x5F {
                if leading {
                    name.push('_');
                }
            }else {
                debugln!("parse_name: unknown: {:02X}", c);
                break;
            }

            *i += 1;
        }

        *i = end;

        count -= 1;
    }

    name
}

pub fn parse_int(bytes: &[u8], i: &mut usize) -> u64{
    if *i < bytes.len() {
        let b = bytes[*i];
        *i += 1;

        match b {
            ZERO_OP => return 0,
            ONE_OP => return 1,
            BYTE_PREFIX => return parse_num::<u8>(bytes, i) as u64,
            WORD_PREFIX => return parse_num::<u16>(bytes, i) as u64,
            DWORD_PREFIX => return parse_num::<u32>(bytes, i) as u64,
            QWORD_PREFIX => return parse_num::<u64>(bytes, i),
            _ => debugln!("parse_int: unknown: {:02X}", b),
        }
    }

    return 0;
}

pub fn parse_package(bytes: &[u8], i: &mut usize) {

        let end = *i + parse_length(bytes, i);
        let elements = parse_num::<u8>(bytes, i);

        debugln!("    Package ({})", elements);
        debugln!("    {{");
        while *i < bytes.len() && *i < end {
            let op = bytes[*i];
            *i += 1;

            match op {
                ZERO_OP => {
                    debugln!("        Zero");
                },
                ONE_OP => {
                    debugln!("        One");
                },
                BYTE_PREFIX => {
                    debugln!("        {:02X}", parse_num::<u8>(bytes, i));
                },
                WORD_PREFIX => {
                    debugln!("        {:04X}", parse_num::<u16>(bytes, i));
                },
                DWORD_PREFIX => {
                    debugln!("        {:08X}", parse_num::<u32>(bytes, i));
                },
                QWORD_PREFIX => {
                    debugln!("        {:016X}", parse_num::<u64>(bytes, i));
                },
                PACKAGE_OP => {
                    parse_package(bytes, i);
                },
                _ => {
                    *i -= 1;
                    debugln!("        {}", parse_name(bytes, i));
                    //debugln!("        parse_package: unknown: {:02X}", op);
                }
            }
        }
        debugln!("    }}");

        *i = end;
}

pub fn parse_device(bytes: &[u8], i: &mut usize) {
    let end = *i + parse_length(bytes, i);
    let name = parse_name(bytes, i);

    debugln!("    Device ({})", name);
    debugln!("    {{");
    while *i < bytes.len() && *i < end {
        let op = bytes[*i];
        *i += 1;

        match op {
            ZERO_OP => {
                debugln!("        Zero");
            },
            ONE_OP => {
                debugln!("        One");
            },
            BYTE_PREFIX => {
                debugln!("        {:02X}", parse_num::<u8>(bytes, i));
            },
            WORD_PREFIX => {
                debugln!("        {:04X}", parse_num::<u16>(bytes, i));
            },
            DWORD_PREFIX => {
                debugln!("        {:08X}", parse_num::<u32>(bytes, i));
            },
            STRING_PREFIX => {
                debugln!("        {}", parse_string(bytes, i));
            },
            QWORD_PREFIX => {
                debugln!("        {:016X}", parse_num::<u64>(bytes, i));
            },
            NAME_OP => {
                debugln!("        Name({})", parse_string(bytes, i));
            },
            METHOD_OP => {
                let end = *i + parse_length(bytes, i);
                let name = parse_name(bytes, i);
                let flags = parse_num::<u8>(bytes, i);

                debugln!("        Method ({}, {})", name, flags);
                debugln!("        {{");
                debugln!("        }}");

                *i = end;
            },
            BUFFER_OP => {
                let end = *i + parse_length(bytes, i);

                let count = parse_int(bytes, i);

                debugln!("        Buffer ({})", count);

                *i = end;
            },
            PACKAGE_OP => {
                parse_package(bytes, i);
            },
            EXT_OP_PREFIX => {
                if *i < bytes.len() {
                    let ext_op = bytes[*i];
                    *i += 1;

                    match ext_op {
                        OP_REGION_OP => {
                            let name = parse_name(bytes, i);
                            let space = parse_num::<u8>(bytes, i);
                            let offset = parse_int(bytes, i);
                            let size = parse_int(bytes, i);

                            debugln!("        OperationRegion ({}, {}, {}, {})", name, space, offset, size);
                        },
                        FIELD_OP => {
                            let end = *i + parse_length(bytes, i);

                            let name = parse_name(bytes, i);
                            let flags = parse_num::<u8>(bytes, i);

                            debugln!("        Field ({}, {})", name, flags);
                            debugln!("        {{");
                            while *i < bytes.len() && *i < end {
                                let name = parse_name(bytes, i);
                                let length = parse_length(bytes, i);

                                debugln!("            {}, {}", name, length);
                            }
                            debugln!("        }}");

                            *i = end;
                        },
                        _ => debugln!("        Unknown EXT: {:02X}", ext_op)
                    }
                }
            },
            _ => {
                debugln!("        parse_device: unknown: {:02X}", op);
                break;
            }
        }
    }
    debugln!("    }}");

    *i = end;
}

pub fn parse_scope(bytes: &[u8], i: &mut usize) {
    let end = *i + parse_length(bytes, i);
    let name = parse_name(bytes, i);

    debugln!("Scope ({})", name);
    debugln!("{{");
    while *i < bytes.len() && *i < end {
        let op = bytes[*i];
        *i += 1;

        match op {
            ZERO_OP => {
                debugln!("    Zero");
            },
            ONE_OP => {
                debugln!("    One");
            },
            BYTE_PREFIX => {
                debugln!("    {:02X}", parse_num::<u8>(bytes, i));
            },
            WORD_PREFIX => {
                debugln!("    {:04X}", parse_num::<u16>(bytes, i));
            },
            DWORD_PREFIX => {
                debugln!("    {:08X}", parse_num::<u32>(bytes, i));
            },
            STRING_PREFIX => {
                debugln!("    {}", parse_string(bytes, i));
            }
            QWORD_PREFIX => {
                debugln!("    {:016X}", parse_num::<u64>(bytes, i));
            },
            SCOPE_OP => {
                parse_scope(bytes, i);
            },
            NAME_OP => {
                debugln!("    Name({})", parse_string(bytes, i));
            },
            METHOD_OP => {
                let end = *i + parse_length(bytes, i);
                let name = parse_name(bytes, i);
                let flags = parse_num::<u8>(bytes, i);

                debugln!("    Method ({}, {})", name, flags);
                debugln!("    {{");
                debugln!("    }}");

                *i = end;
            },
            BUFFER_OP => {
                let end = *i + parse_length(bytes, i);

                let count = parse_int(bytes, i);

                debugln!("    Buffer ({})", count);

                *i = end;
            },
            PACKAGE_OP => {
                parse_package(bytes, i);
            },
            EXT_OP_PREFIX => {
                if *i < bytes.len() {
                    let ext_op = bytes[*i];
                    *i += 1;

                    match ext_op {
                        MUTEX_OP => {
                            let name = parse_name(bytes, i);
                            let flags = parse_num::<u8>(bytes, i);

                            debugln!("    Mutex ({}, {})", name, flags);
                        },
                        OP_REGION_OP => {
                            let name = parse_name(bytes, i);
                            let space = parse_num::<u8>(bytes, i);
                            let offset = parse_int(bytes, i);
                            let size = parse_int(bytes, i);

                            debugln!("    OperationRegion ({}, {}, {}, {})", name, space, offset, size);
                        },
                        FIELD_OP => {
                            let end = *i + parse_length(bytes, i);

                            let name = parse_name(bytes, i);
                            let flags = parse_num::<u8>(bytes, i);

                            debugln!("    Field ({}, {})", name, flags);
                            debugln!("    {{");
                            while *i < bytes.len() && *i < end {
                                let name = parse_name(bytes, i);
                                let length = parse_length(bytes, i);

                                debugln!("        {}, {}", name, length);
                            }
                            debugln!("    }}");

                            *i = end;
                        },
                        DEVICE_OP => {
                            parse_device(bytes, i);
                        },
                        PROCESSOR_OP => {
                            let end = *i + parse_length(bytes, i);

                            let name = parse_name(bytes, i);
                            let id = parse_num::<u8>(bytes, i);
                            let blk = parse_num::<u32>(bytes, i);
                            let blklen = parse_num::<u8>(bytes, i);

                            debugln!("    Processor ({})", name);

                            *i = end;
                        },
                        _ => debugln!("    Unknown EXT: {:02X}", ext_op)
                    }
                }
            },
            _ => {
                debugln!("    parse_scope: unknown: {:02X}", op);
                break;
            }
        }
    }
    debugln!("}}");

    *i = end;
}

pub fn parse(bytes: &[u8]) {
    let mut i = 0;
    while i < bytes.len() {
        let op = bytes[i];
        i += 1;

        match op {
            SCOPE_OP => {
                parse_scope(bytes, &mut i);
            },
            _ => {
                debugln!("parse: unknown: {:02X}", op);
                break;
            }
        }
    }
}
<|endoftext|>


<commit_before><commit_msg>fetch/artifact: implement sha512 hash checking<commit_after><|endoftext|>


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

use std::ascii::AsciiExt;
use std::cmp;

#[derive(Debug, Clone)]
pub struct LogDirective {
    pub name: Option<String>,
    pub level: u32,
}

pub const LOG_LEVEL_NAMES: [&'static str; 4] = ["ERROR", "WARN", "INFO", "DEBUG"];

/// Parse an individual log level that is either a number or a symbolic log level
fn parse_log_level(level: &str) -> Option<u32> {
    level.parse::<u32>()
         .ok()
         .or_else(|| {
             let pos = LOG_LEVEL_NAMES.iter().position(|&name| name.eq_ignore_ascii_case(level));
             pos.map(|p| p as u32 + 1)
         })
         .map(|p| cmp::min(p, ::MAX_LOG_LEVEL))
}

/// Parse a logging specification string (e.g: "crate1,crate2::mod3,crate3::x=1/foo")
/// and return a vector with log directives.
///
/// Valid log levels are 0-255, with the most likely ones being 1-4 (defined in
/// std::).  Also supports string log levels of error, warn, info, and debug
pub fn parse_logging_spec(spec: &str) -> (Vec<LogDirective>, Option<String>) {
    let mut dirs = Vec::new();

    let mut parts = spec.split('/');
    let mods = parts.next();
    let filter = parts.next();
    if parts.next().is_some() {
        println!("warning: invalid logging spec '{}', ignoring it (too many '/'s)",
                 spec);
        return (dirs, None);
    }
    mods.map(|m| {
        for s in m.split(',') {
            if s.is_empty() {
                continue
            }
            let mut parts = s.split('=');
            let (log_level, name) = match (parts.next(),
                                           parts.next().map(|s| s.trim()),
                                           parts.next()) {
                (Some(part0), None, None) => {
                // if the single argument is a log-level string or number,
                // treat that as a global fallback
                    match parse_log_level(part0) {
                        Some(num) => (num, None),
                        None => (::MAX_LOG_LEVEL, Some(part0)),
                    }
                }
                (Some(part0), Some(""), None) => (::MAX_LOG_LEVEL, Some(part0)),
                (Some(part0), Some(part1), None) => {
                    match parse_log_level(part1) {
                        Some(num) => (num, Some(part0)),
                        _ => {
                            println!("warning: invalid logging spec '{}', ignoring it", part1);
                            continue
                        }
                    }
                }
                _ => {
                    println!("warning: invalid logging spec '{}', ignoring it", s);
                    continue
                }
            };
            dirs.push(LogDirective {
                name: name.map(str::to_owned),
                level: log_level,
            });
        }
    });

    (dirs, filter.map(str::to_owned))
}

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

    #[test]
    fn parse_logging_spec_valid() {
        let (dirs, filter) = parse_logging_spec("crate1::mod1=1,crate1::mod2,crate2=4");
        assert_eq!(dirs.len(), 3);
        assert_eq!(dirs[0].name, Some("crate1::mod1".to_owned()));
        assert_eq!(dirs[0].level, 1);

        assert_eq!(dirs[1].name, Some("crate1::mod2".to_owned()));
        assert_eq!(dirs[1].level, ::MAX_LOG_LEVEL);

        assert_eq!(dirs[2].name, Some("crate2".to_owned()));
        assert_eq!(dirs[2].level, 4);
        assert!(filter.is_none());
    }

    #[test]
    fn parse_logging_spec_invalid_crate() {
        // test parse_logging_spec with multiple = in specification
        let (dirs, filter) = parse_logging_spec("crate1::mod1=1=2,crate2=4");
        assert_eq!(dirs.len(), 1);
        assert_eq!(dirs[0].name, Some("crate2".to_owned()));
        assert_eq!(dirs[0].level, 4);
        assert!(filter.is_none());
    }

    #[test]
    fn parse_logging_spec_invalid_log_level() {
        // test parse_logging_spec with 'noNumber' as log level
        let (dirs, filter) = parse_logging_spec("crate1::mod1=noNumber,crate2=4");
        assert_eq!(dirs.len(), 1);
        assert_eq!(dirs[0].name, Some("crate2".to_owned()));
        assert_eq!(dirs[0].level, 4);
        assert!(filter.is_none());
    }

    #[test]
    fn parse_logging_spec_string_log_level() {
        // test parse_logging_spec with 'warn' as log level
        let (dirs, filter) = parse_logging_spec("crate1::mod1=wrong,crate2=warn");
        assert_eq!(dirs.len(), 1);
        assert_eq!(dirs[0].name, Some("crate2".to_owned()));
        assert_eq!(dirs[0].level, ::WARN);
        assert!(filter.is_none());
    }

    #[test]
    fn parse_logging_spec_empty_log_level() {
        // test parse_logging_spec with '' as log level
        let (dirs, filter) = parse_logging_spec("crate1::mod1=wrong,crate2=");
        assert_eq!(dirs.len(), 1);
        assert_eq!(dirs[0].name, Some("crate2".to_owned()));
        assert_eq!(dirs[0].level, ::MAX_LOG_LEVEL);
        assert!(filter.is_none());
    }

    #[test]
    fn parse_logging_spec_global() {
        // test parse_logging_spec with no crate
        let (dirs, filter) = parse_logging_spec("warn,crate2=4");
        assert_eq!(dirs.len(), 2);
        assert_eq!(dirs[0].name, None);
        assert_eq!(dirs[0].level, 2);
        assert_eq!(dirs[1].name, Some("crate2".to_owned()));
        assert_eq!(dirs[1].level, 4);
        assert!(filter.is_none());
    }

    #[test]
    fn parse_logging_spec_valid_filter() {
        let (dirs, filter) = parse_logging_spec("crate1::mod1=1,crate1::mod2,crate2=4/abc");
        assert_eq!(dirs.len(), 3);
        assert_eq!(dirs[0].name, Some("crate1::mod1".to_owned()));
        assert_eq!(dirs[0].level, 1);

        assert_eq!(dirs[1].name, Some("crate1::mod2".to_owned()));
        assert_eq!(dirs[1].level, ::MAX_LOG_LEVEL);

        assert_eq!(dirs[2].name, Some("crate2".to_owned()));
        assert_eq!(dirs[2].level, 4);
        assert!(filter.is_some() && filter.unwrap().to_owned() == "abc");
    }

    #[test]
    fn parse_logging_spec_invalid_crate_filter() {
        let (dirs, filter) = parse_logging_spec("crate1::mod1=1=2,crate2=4/a.c");
        assert_eq!(dirs.len(), 1);
        assert_eq!(dirs[0].name, Some("crate2".to_owned()));
        assert_eq!(dirs[0].level, 4);
        assert!(filter.is_some() && filter.unwrap().to_owned() == "a.c");
    }

    #[test]
    fn parse_logging_spec_empty_with_filter() {
        let (dirs, filter) = parse_logging_spec("crate1/a*c");
        assert_eq!(dirs.len(), 1);
        assert_eq!(dirs[0].name, Some("crate1".to_owned()));
        assert_eq!(dirs[0].level, ::MAX_LOG_LEVEL);
        assert!(filter.is_some() && filter.unwrap().to_owned() == "a*c");
    }
}
<commit_msg>Manually alligned comments.<commit_after>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use std::ascii::AsciiExt;
use std::cmp;

#[derive(Debug, Clone)]
pub struct LogDirective {
    pub name: Option<String>,
    pub level: u32,
}

pub const LOG_LEVEL_NAMES: [&'static str; 4] = ["ERROR", "WARN", "INFO", "DEBUG"];

/// Parse an individual log level that is either a number or a symbolic log level
fn parse_log_level(level: &str) -> Option<u32> {
    level.parse::<u32>()
         .ok()
         .or_else(|| {
             let pos = LOG_LEVEL_NAMES.iter().position(|&name| name.eq_ignore_ascii_case(level));
             pos.map(|p| p as u32 + 1)
         })
         .map(|p| cmp::min(p, ::MAX_LOG_LEVEL))
}

/// Parse a logging specification string (e.g: "crate1,crate2::mod3,crate3::x=1/foo")
/// and return a vector with log directives.
///
/// Valid log levels are 0-255, with the most likely ones being 1-4 (defined in
/// std::).  Also supports string log levels of error, warn, info, and debug
pub fn parse_logging_spec(spec: &str) -> (Vec<LogDirective>, Option<String>) {
    let mut dirs = Vec::new();

    let mut parts = spec.split('/');
    let mods = parts.next();
    let filter = parts.next();
    if parts.next().is_some() {
        println!("warning: invalid logging spec '{}', ignoring it (too many '/'s)",
                 spec);
        return (dirs, None);
    }
    mods.map(|m| {
        for s in m.split(',') {
            if s.is_empty() {
                continue
            }
            let mut parts = s.split('=');
            let (log_level, name) = match (parts.next(),
                                           parts.next().map(|s| s.trim()),
                                           parts.next()) {
                (Some(part0), None, None) => {
                    // if the single argument is a log-level string or number,
                    // treat that as a global fallback
                    match parse_log_level(part0) {
                        Some(num) => (num, None),
                        None => (::MAX_LOG_LEVEL, Some(part0)),
                    }
                }
                (Some(part0), Some(""), None) => (::MAX_LOG_LEVEL, Some(part0)),
                (Some(part0), Some(part1), None) => {
                    match parse_log_level(part1) {
                        Some(num) => (num, Some(part0)),
                        _ => {
                            println!("warning: invalid logging spec '{}', ignoring it", part1);
                            continue
                        }
                    }
                }
                _ => {
                    println!("warning: invalid logging spec '{}', ignoring it", s);
                    continue
                }
            };
            dirs.push(LogDirective {
                name: name.map(str::to_owned),
                level: log_level,
            });
        }
    });

    (dirs, filter.map(str::to_owned))
}

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

    #[test]
    fn parse_logging_spec_valid() {
        let (dirs, filter) = parse_logging_spec("crate1::mod1=1,crate1::mod2,crate2=4");
        assert_eq!(dirs.len(), 3);
        assert_eq!(dirs[0].name, Some("crate1::mod1".to_owned()));
        assert_eq!(dirs[0].level, 1);

        assert_eq!(dirs[1].name, Some("crate1::mod2".to_owned()));
        assert_eq!(dirs[1].level, ::MAX_LOG_LEVEL);

        assert_eq!(dirs[2].name, Some("crate2".to_owned()));
        assert_eq!(dirs[2].level, 4);
        assert!(filter.is_none());
    }

    #[test]
    fn parse_logging_spec_invalid_crate() {
        // test parse_logging_spec with multiple = in specification
        let (dirs, filter) = parse_logging_spec("crate1::mod1=1=2,crate2=4");
        assert_eq!(dirs.len(), 1);
        assert_eq!(dirs[0].name, Some("crate2".to_owned()));
        assert_eq!(dirs[0].level, 4);
        assert!(filter.is_none());
    }

    #[test]
    fn parse_logging_spec_invalid_log_level() {
        // test parse_logging_spec with 'noNumber' as log level
        let (dirs, filter) = parse_logging_spec("crate1::mod1=noNumber,crate2=4");
        assert_eq!(dirs.len(), 1);
        assert_eq!(dirs[0].name, Some("crate2".to_owned()));
        assert_eq!(dirs[0].level, 4);
        assert!(filter.is_none());
    }

    #[test]
    fn parse_logging_spec_string_log_level() {
        // test parse_logging_spec with 'warn' as log level
        let (dirs, filter) = parse_logging_spec("crate1::mod1=wrong,crate2=warn");
        assert_eq!(dirs.len(), 1);
        assert_eq!(dirs[0].name, Some("crate2".to_owned()));
        assert_eq!(dirs[0].level, ::WARN);
        assert!(filter.is_none());
    }

    #[test]
    fn parse_logging_spec_empty_log_level() {
        // test parse_logging_spec with '' as log level
        let (dirs, filter) = parse_logging_spec("crate1::mod1=wrong,crate2=");
        assert_eq!(dirs.len(), 1);
        assert_eq!(dirs[0].name, Some("crate2".to_owned()));
        assert_eq!(dirs[0].level, ::MAX_LOG_LEVEL);
        assert!(filter.is_none());
    }

    #[test]
    fn parse_logging_spec_global() {
        // test parse_logging_spec with no crate
        let (dirs, filter) = parse_logging_spec("warn,crate2=4");
        assert_eq!(dirs.len(), 2);
        assert_eq!(dirs[0].name, None);
        assert_eq!(dirs[0].level, 2);
        assert_eq!(dirs[1].name, Some("crate2".to_owned()));
        assert_eq!(dirs[1].level, 4);
        assert!(filter.is_none());
    }

    #[test]
    fn parse_logging_spec_valid_filter() {
        let (dirs, filter) = parse_logging_spec("crate1::mod1=1,crate1::mod2,crate2=4/abc");
        assert_eq!(dirs.len(), 3);
        assert_eq!(dirs[0].name, Some("crate1::mod1".to_owned()));
        assert_eq!(dirs[0].level, 1);

        assert_eq!(dirs[1].name, Some("crate1::mod2".to_owned()));
        assert_eq!(dirs[1].level, ::MAX_LOG_LEVEL);

        assert_eq!(dirs[2].name, Some("crate2".to_owned()));
        assert_eq!(dirs[2].level, 4);
        assert!(filter.is_some() && filter.unwrap().to_owned() == "abc");
    }

    #[test]
    fn parse_logging_spec_invalid_crate_filter() {
        let (dirs, filter) = parse_logging_spec("crate1::mod1=1=2,crate2=4/a.c");
        assert_eq!(dirs.len(), 1);
        assert_eq!(dirs[0].name, Some("crate2".to_owned()));
        assert_eq!(dirs[0].level, 4);
        assert!(filter.is_some() && filter.unwrap().to_owned() == "a.c");
    }

    #[test]
    fn parse_logging_spec_empty_with_filter() {
        let (dirs, filter) = parse_logging_spec("crate1/a*c");
        assert_eq!(dirs.len(), 1);
        assert_eq!(dirs[0].name, Some("crate1".to_owned()));
        assert_eq!(dirs[0].level, ::MAX_LOG_LEVEL);
        assert!(filter.is_some() && filter.unwrap().to_owned() == "a*c");
    }
}
<|endoftext|>


<commit_before>use std::fmt::{Debug, Formatter};
use std::fmt::Result as FMTResult;

mod header;

use module::Module;
use runtime::Runtime;

pub struct Notes<'a> {
    rt: &'a Runtime<'a>,
}

impl<'a> Notes<'a> {

    pub fn new(rt: &'a Runtime<'a>) -> Notes<'a> {
        Notes {
            rt: rt,
        }
    }

    fn command_add(&self, matches: &ArgMatches) -> bool {
        unimplemented!()
    }

    fn command_list(&self, matches: &ArgMatches) -> bool {
        unimplemented!()
    }

    fn command_remove(&self, matches: &ArgMatches) -> bool {
        unimplemented!()
    }

    fn command_add_tags(&self, matches: &ArgMatches) -> bool {
        unimplemented!()
    }

    fn command_rm_tags(&self, matches: &ArgMatches) -> bool {
        unimplemented!()
    }

    fn command_set_tags(&self, matches: &ArgMatches) -> bool {
        unimplemented!()
    }

}

impl<'a> Module<'a> for Notes<'a> {

    fn exec(&self, matches: &ArgMatches) -> bool {
        match matches.subcommand_name() {
            Some("add") => {
                self.command_add(matches.subcommand_matches("add").unwrap())
            },

            Some("list") => {
                self.command_list(matches.subcommand_matches("list").unwrap())
            },

            Some("remove") => {
                self.command_remove(matches.subcommand_matches("remove").unwrap())
            },

            Some("add_tags") => {
                self.command_add_tags(matches.subcommand_matches("add_tags").unwrap())
            },

            Some("rm_tags") => {
                self.command_rm_tags(matches.subcommand_matches("rm_tags").unwrap())
            },

            Some("set_tags") => {
                self.command_set_tags(matches.subcommand_matches("set_tags").unwrap())
            },

            Some(_) | None => {
                info!("No command given, doing nothing");
                false
            },
        }
    }

    fn name(&self) -> &'static str{
        "notes"
    }

}

impl<'a> Debug for Notes<'a> {

    fn fmt(&self, fmt: &mut Formatter) -> FMTResult {
        write!(fmt, "[Module][Notes]");
        Ok(())
    }

}
<commit_msg>Notes: Implement command_add()<commit_after>use std::fmt::{Debug, Formatter};
use std::fmt::Result as FMTResult;

use clap::ArgMatches;

mod header;

use module::Module;
use runtime::Runtime;
use storage::parser::Parser;
use storage::json::parser::JsonHeaderParser;

pub struct Notes<'a> {
    rt: &'a Runtime<'a>,
}

impl<'a> Notes<'a> {

    pub fn new(rt: &'a Runtime<'a>) -> Notes<'a> {
        Notes {
            rt: rt,
        }
    }

    fn command_add(&self, matches: &ArgMatches) -> bool {
        use std::process::exit;
        use self::header::build_header;

        let parser = Parser::new(JsonHeaderParser::new(None));
        let name   = matches.value_of("name")
                            .map(String::from)
                            .unwrap_or(String::from(""));
        let tags   = matches.value_of("tags")
                            .and_then(|s| Some(s.split(",").map(String::from).collect()))
                            .unwrap_or(vec![]);

        debug!("Building header with");
        debug!("    name = '{:?}'", name);
        debug!("    tags = '{:?}'", tags);
        let header = build_header(name, tags);

        let fileid = self.rt.store().new_file_with_header(self, header);
        self.rt
            .store()
            .load(self, &parser, &fileid)
            .and_then(|file| {
                info!("Created file in memory: {}", fileid);
                Some(self.rt.store().persist(&parser, file))
            })
            .unwrap_or(false)
    }

    fn command_list(&self, matches: &ArgMatches) -> bool {
        unimplemented!()
    }

    fn command_remove(&self, matches: &ArgMatches) -> bool {
        unimplemented!()
    }

    fn command_add_tags(&self, matches: &ArgMatches) -> bool {
        unimplemented!()
    }

    fn command_rm_tags(&self, matches: &ArgMatches) -> bool {
        unimplemented!()
    }

    fn command_set_tags(&self, matches: &ArgMatches) -> bool {
        unimplemented!()
    }

}

impl<'a> Module<'a> for Notes<'a> {

    fn exec(&self, matches: &ArgMatches) -> bool {
        match matches.subcommand_name() {
            Some("add") => {
                self.command_add(matches.subcommand_matches("add").unwrap())
            },

            Some("list") => {
                self.command_list(matches.subcommand_matches("list").unwrap())
            },

            Some("remove") => {
                self.command_remove(matches.subcommand_matches("remove").unwrap())
            },

            Some("add_tags") => {
                self.command_add_tags(matches.subcommand_matches("add_tags").unwrap())
            },

            Some("rm_tags") => {
                self.command_rm_tags(matches.subcommand_matches("rm_tags").unwrap())
            },

            Some("set_tags") => {
                self.command_set_tags(matches.subcommand_matches("set_tags").unwrap())
            },

            Some(_) | None => {
                info!("No command given, doing nothing");
                false
            },
        }
    }

    fn name(&self) -> &'static str{
        "notes"
    }

}

impl<'a> Debug for Notes<'a> {

    fn fmt(&self, fmt: &mut Formatter) -> FMTResult {
        write!(fmt, "[Module][Notes]");
        Ok(())
    }

}
<|endoftext|>


<commit_before>//! An echo server that just writes back everything that's written to it.

extern crate futures;
extern crate futures_io;
extern crate futures_mio;

use std::env;
use std::net::SocketAddr;

use futures::Future;
use futures::stream::Stream;
use futures_io::{copy, TaskIo};

fn main() {
    let addr = env::args().nth(1).unwrap_or("127.0.0.1:8080".to_string());
    let addr = addr.parse::<SocketAddr>().unwrap();

    // Create the event loop that will drive this server
    let mut l = futures_mio::Loop::new().unwrap();

    // Create a TCP listener which will listen for incoming connections
    let server = l.handle().tcp_listen(&addr);

    let done = server.and_then(move |socket| {
        // Once we've got the TCP listener, inform that we have it
        println!("Listening on: {}", addr);

        // Pull out the stream of incoming connections and then for each new
        // one spin up a new task copying data.
        //
        // We use the `io::copy` future to copy all data from the
        // reading half onto the writing half.
        socket.incoming().for_each(|(socket, addr)| {
            let (reader, writer) = TaskIo::new(socket).split();
            let amt = copy(reader, writer);

            // Once all that is done we print out how much we wrote, and then
            // critically we *forget* this future which allows it to run
            // concurrently with other connections.
            amt.map(move |amt| {
                println!("wrote {} bytes to {}", amt, addr)
            }).forget();

            Ok(())
        })
    });
    l.run(done).unwrap();
}
<commit_msg>Revert to using futures::lazy(), which is in fact needed.<commit_after>//! An echo server that just writes back everything that's written to it.

extern crate futures;
extern crate futures_io;
extern crate futures_mio;

use std::env;
use std::net::SocketAddr;

use futures::Future;
use futures::stream::Stream;
use futures_io::{copy, TaskIo};

fn main() {
    let addr = env::args().nth(1).unwrap_or("127.0.0.1:8080".to_string());
    let addr = addr.parse::<SocketAddr>().unwrap();

    // Create the event loop that will drive this server
    let mut l = futures_mio::Loop::new().unwrap();

    // Create a TCP listener which will listen for incoming connections
    let server = l.handle().tcp_listen(&addr);

    let done = server.and_then(move |socket| {
        // Once we've got the TCP listener, inform that we have it
        println!("Listening on: {}", addr);

        // Pull out the stream of incoming connections and then for each new
        // one spin up a new task copying data.
        //
        // We use the `io::copy` future to copy all data from the
        // reading half onto the writing half.
        socket.incoming().for_each(|(socket, addr)| {
            let socket = futures::lazy(|| futures::finished(TaskIo::new(socket)));
            let pair = socket.map(|s| s.split());
            let amt = pair.and_then(|(reader, writer)| copy(reader, writer));

            // Once all that is done we print out how much we wrote, and then
            // critically we *forget* this future which allows it to run
            // concurrently with other connections.
            amt.map(move |amt| {
                println!("wrote {} bytes to {}", amt, addr)
            }).forget();

            Ok(())
        })
    });
    l.run(done).unwrap();
}
<|endoftext|>


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

use libc;
use cell::UnsafeCell;
use sync::atomic::{AtomicUsize, Ordering};

pub struct RWLock {
    inner: UnsafeCell<libc::pthread_rwlock_t>,
    write_locked: UnsafeCell<bool>,
    num_readers: AtomicUsize,
}

unsafe impl Send for RWLock {}
unsafe impl Sync for RWLock {}

impl RWLock {
    pub const fn new() -> RWLock {
        RWLock {
            inner: UnsafeCell::new(libc::PTHREAD_RWLOCK_INITIALIZER),
            write_locked: UnsafeCell::new(false),
            num_readers: AtomicUsize::new(0),
        }
    }
    #[inline]
    pub unsafe fn read(&self) {
        let r = libc::pthread_rwlock_rdlock(self.inner.get());

        // According to the pthread_rwlock_rdlock spec, this function **may**
        // fail with EDEADLK if a deadlock is detected. On the other hand
        // pthread mutexes will *never* return EDEADLK if they are initialized
        // as the "fast" kind (which ours always are). As a result, a deadlock
        // situation may actually return from the call to pthread_rwlock_rdlock
        // instead of blocking forever (as mutexes and Windows rwlocks do). Note
        // that not all unix implementations, however, will return EDEADLK for
        // their rwlocks.
        //
        // We roughly maintain the deadlocking behavior by panicking to ensure
        // that this lock acquisition does not succeed.
        //
        // We also check whether this lock is already write locked. This
        // is only possible if it was write locked by the current thread and
        // the implementation allows recursive locking. The POSIX standard
        // doesn't require recursively locking a rwlock to deadlock, but we can't
        // allow that because it could lead to aliasing issues.
        if r == libc::EAGAIN {
            panic!("rwlock maximum reader count exceeded");
        } else if r == libc::EDEADLK || *self.write_locked.get() {
            if r == 0 {
                self.raw_unlock();
            }
            panic!("rwlock read lock would result in deadlock");
        } else {
            debug_assert_eq!(r, 0);
            self.num_readers.fetch_add(1, Ordering::Relaxed);
        }
    }
    #[inline]
    pub unsafe fn try_read(&self) -> bool {
        let r = libc::pthread_rwlock_tryrdlock(self.inner.get());
        if r == 0 {
            if *self.write_locked.get() {
                self.raw_unlock();
                false
            } else {
                self.num_readers.fetch_add(1, Ordering::Relaxed);
                true
            }
        } else {
            false
        }
    }
    #[inline]
    pub unsafe fn write(&self) {
        let r = libc::pthread_rwlock_wrlock(self.inner.get());
        // See comments above for why we check for EDEADLK and write_locked. We
        // also need to check that num_readers is 0.
        if r == libc::EDEADLK || *self.write_locked.get() ||
           self.num_readers.load(Ordering::Relaxed) != 0 {
            if r == 0 {
                self.raw_unlock();
            }
            panic!("rwlock write lock would result in deadlock");
        } else {
            debug_assert_eq!(r, 0);
        }
        *self.write_locked.get() = true;
    }
    #[inline]
    pub unsafe fn try_write(&self) -> bool {
        let r = libc::pthread_rwlock_trywrlock(self.inner.get());
        if r == 0 {
            if *self.write_locked.get() || self.num_readers.load(Ordering::Relaxed) != 0 {
                self.raw_unlock();
                false
            } else {
                *self.write_locked.get() = true;
                true
            }
        } else {
            false
        }
    }
    #[inline]
    unsafe fn raw_unlock(&self) {
        let r = libc::pthread_rwlock_unlock(self.inner.get());
        debug_assert_eq!(r, 0);
    }
    #[inline]
    pub unsafe fn read_unlock(&self) {
        debug_assert!(!*self.write_locked.get());
        self.num_readers.fetch_sub(1, Ordering::Relaxed);
        self.raw_unlock();
    }
    #[inline]
    pub unsafe fn write_unlock(&self) {
        debug_assert_eq!(self.num_readers.load(Ordering::Relaxed), 0);
        debug_assert!(*self.write_locked.get());
        *self.write_locked.get() = false;
        self.raw_unlock();
    }
    #[inline]
    pub unsafe fn destroy(&self) {
        let r = libc::pthread_rwlock_destroy(self.inner.get());
        // On DragonFly pthread_rwlock_destroy() returns EINVAL if called on a
        // rwlock that was just initialized with
        // libc::PTHREAD_RWLOCK_INITIALIZER. Once it is used (locked/unlocked)
        // or pthread_rwlock_init() is called, this behaviour no longer occurs.
        if cfg!(target_os = "dragonfly") {
            debug_assert!(r == 0 || r == libc::EINVAL);
        } else {
            debug_assert_eq!(r, 0);
        }
    }
}
<commit_msg>Unix RwLock: avoid racy access to write_locked<commit_after>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use libc;
use cell::UnsafeCell;
use sync::atomic::{AtomicUsize, Ordering};

pub struct RWLock {
    inner: UnsafeCell<libc::pthread_rwlock_t>,
    write_locked: UnsafeCell<bool>, // guarded by the `inner` RwLock
    num_readers: AtomicUsize,
}

unsafe impl Send for RWLock {}
unsafe impl Sync for RWLock {}

impl RWLock {
    pub const fn new() -> RWLock {
        RWLock {
            inner: UnsafeCell::new(libc::PTHREAD_RWLOCK_INITIALIZER),
            write_locked: UnsafeCell::new(false),
            num_readers: AtomicUsize::new(0),
        }
    }
    #[inline]
    pub unsafe fn read(&self) {
        let r = libc::pthread_rwlock_rdlock(self.inner.get());

        // According to the pthread_rwlock_rdlock spec, this function **may**
        // fail with EDEADLK if a deadlock is detected. On the other hand
        // pthread mutexes will *never* return EDEADLK if they are initialized
        // as the "fast" kind (which ours always are). As a result, a deadlock
        // situation may actually return from the call to pthread_rwlock_rdlock
        // instead of blocking forever (as mutexes and Windows rwlocks do). Note
        // that not all unix implementations, however, will return EDEADLK for
        // their rwlocks.
        //
        // We roughly maintain the deadlocking behavior by panicking to ensure
        // that this lock acquisition does not succeed.
        //
        // We also check whether this lock is already write locked. This
        // is only possible if it was write locked by the current thread and
        // the implementation allows recursive locking. The POSIX standard
        // doesn't require recursively locking a rwlock to deadlock, but we can't
        // allow that because it could lead to aliasing issues.
        if r == libc::EAGAIN {
            panic!("rwlock maximum reader count exceeded");
        } else if r == libc::EDEADLK || (r == 0 && *self.write_locked.get()) {
            if r == 0 {
                self.raw_unlock();
            }
            panic!("rwlock read lock would result in deadlock");
        } else {
            debug_assert_eq!(r, 0);
            self.num_readers.fetch_add(1, Ordering::Relaxed);
        }
    }
    #[inline]
    pub unsafe fn try_read(&self) -> bool {
        let r = libc::pthread_rwlock_tryrdlock(self.inner.get());
        if r == 0 {
            if *self.write_locked.get() {
                self.raw_unlock();
                false
            } else {
                self.num_readers.fetch_add(1, Ordering::Relaxed);
                true
            }
        } else {
            false
        }
    }
    #[inline]
    pub unsafe fn write(&self) {
        let r = libc::pthread_rwlock_wrlock(self.inner.get());
        // See comments above for why we check for EDEADLK and write_locked. We
        // also need to check that num_readers is 0.
        if r == libc::EDEADLK || *self.write_locked.get() ||
           self.num_readers.load(Ordering::Relaxed) != 0 {
            if r == 0 {
                self.raw_unlock();
            }
            panic!("rwlock write lock would result in deadlock");
        } else {
            debug_assert_eq!(r, 0);
        }
        *self.write_locked.get() = true;
    }
    #[inline]
    pub unsafe fn try_write(&self) -> bool {
        let r = libc::pthread_rwlock_trywrlock(self.inner.get());
        if r == 0 {
            if *self.write_locked.get() || self.num_readers.load(Ordering::Relaxed) != 0 {
                self.raw_unlock();
                false
            } else {
                *self.write_locked.get() = true;
                true
            }
        } else {
            false
        }
    }
    #[inline]
    unsafe fn raw_unlock(&self) {
        let r = libc::pthread_rwlock_unlock(self.inner.get());
        debug_assert_eq!(r, 0);
    }
    #[inline]
    pub unsafe fn read_unlock(&self) {
        debug_assert!(!*self.write_locked.get());
        self.num_readers.fetch_sub(1, Ordering::Relaxed);
        self.raw_unlock();
    }
    #[inline]
    pub unsafe fn write_unlock(&self) {
        debug_assert_eq!(self.num_readers.load(Ordering::Relaxed), 0);
        debug_assert!(*self.write_locked.get());
        *self.write_locked.get() = false;
        self.raw_unlock();
    }
    #[inline]
    pub unsafe fn destroy(&self) {
        let r = libc::pthread_rwlock_destroy(self.inner.get());
        // On DragonFly pthread_rwlock_destroy() returns EINVAL if called on a
        // rwlock that was just initialized with
        // libc::PTHREAD_RWLOCK_INITIALIZER. Once it is used (locked/unlocked)
        // or pthread_rwlock_init() is called, this behaviour no longer occurs.
        if cfg!(target_os = "dragonfly") {
            debug_assert!(r == 0 || r == libc::EINVAL);
        } else {
            debug_assert_eq!(r, 0);
        }
    }
}
<|endoftext|>


<commit_before>#![feature(phase)]
extern crate regex;
#[phase(plugin)] extern crate regex_macros;

use std::os;

use file::File;
use dir::Dir;
use options::Options;
use unix::Unix;
use colours::Plain;

pub mod colours;
pub mod column;
pub mod dir;
pub mod format;
pub mod file;
pub mod filetype;
pub mod unix;
pub mod options;
pub mod sort;

fn main() {
    let args = os::args();

    match Options::getopts(args) {
        Err(err) => println!("Invalid options:\n{}", err),
        Ok(opts) => {
            if opts.dirs.is_empty() {
                exa(&opts, false, ".".to_string())
            }
            else {
                let mut first = true;
                let print_header = opts.dirs.len() > 1;
                for dir in opts.dirs.clone().move_iter() {
                    if first {
                        first = false;
                    }
                    else {
                        print!("\n");
                    }
                    exa(&opts, print_header, dir)
                }
            }
        }
    };
}

fn exa(options: &Options, print_header: bool, string: String) {
    let path = Path::new(string.clone());

    let dir = match Dir::readdir(path) {
        Ok(dir) => dir,
        Err(e) => {
            println!("{}: {}", string, e);
            return;
        }
    };

    // Print header *after* readdir must have succeeded
    if print_header {
        println!("{}:", string);
    }

    let unsorted_files = dir.files();
    let files: Vec<&File> = options.transform_files(&unsorted_files);

    // The output gets formatted into columns, which looks nicer. To
    // do this, we have to write the results into a table, instead of
    // displaying each file immediately, then calculating the maximum
    // width of each column based on the length of the results and
    // padding the fields during output.

    let mut cache = Unix::empty_cache();

    let mut table: Vec<Vec<String>> = files.iter()
        .map(|f| options.columns.iter().map(|c| f.display(c, &mut cache)).collect())
        .collect();

    if options.header {
        table.unshift(options.columns.iter().map(|c| Plain.underline().paint(c.header())).collect());
    }

    // Each column needs to have its invisible colour-formatting
    // characters stripped before it has its width calculated, or the
    // width will be incorrect and the columns won't line up properly.
    // This is fairly expensive to do (it uses a regex), so the
    // results are cached.

    let lengths: Vec<Vec<uint>> = table.iter()
        .map(|row| row.iter().map(|col| colours::strip_formatting(col).len()).collect())
        .collect();

    let column_widths: Vec<uint> = range(0, options.columns.len())
        .map(|n| lengths.iter().map(|row| *row.get(n)).max().unwrap())
        .collect();

    for (field_lengths, row) in lengths.iter().zip(table.iter()) {
        for (((column_length, cell), field_length), (num, column)) in column_widths.iter().zip(row.iter()).zip(field_lengths.iter()).zip(options.columns.iter().enumerate()) {  // this is getting messy
            if num != 0 {
                print!(" ");
            }

            if num == options.columns.len() - 1 {
                print!("{}", cell);
            }
            else {
                print!("{}", column.alignment().pad_string(cell, *field_length, *column_length));
            }
        }
        print!("\n");
    }
}
<commit_msg>Replace messy line with calls to get<commit_after>#![feature(phase)]
extern crate regex;
#[phase(plugin)] extern crate regex_macros;

use std::os;

use file::File;
use dir::Dir;
use options::Options;
use unix::Unix;
use colours::Plain;

pub mod colours;
pub mod column;
pub mod dir;
pub mod format;
pub mod file;
pub mod filetype;
pub mod unix;
pub mod options;
pub mod sort;

fn main() {
    let args = os::args();

    match Options::getopts(args) {
        Err(err) => println!("Invalid options:\n{}", err),
        Ok(opts) => {
            if opts.dirs.is_empty() {
                exa(&opts, false, ".".to_string())
            }
            else {
                let mut first = true;
                let print_header = opts.dirs.len() > 1;
                for dir in opts.dirs.clone().move_iter() {
                    if first {
                        first = false;
                    }
                    else {
                        print!("\n");
                    }
                    exa(&opts, print_header, dir)
                }
            }
        }
    };
}

fn exa(options: &Options, print_header: bool, string: String) {
    let path = Path::new(string.clone());

    let dir = match Dir::readdir(path) {
        Ok(dir) => dir,
        Err(e) => {
            println!("{}: {}", string, e);
            return;
        }
    };

    // Print header *after* readdir must have succeeded
    if print_header {
        println!("{}:", string);
    }

    let unsorted_files = dir.files();
    let files: Vec<&File> = options.transform_files(&unsorted_files);

    // The output gets formatted into columns, which looks nicer. To
    // do this, we have to write the results into a table, instead of
    // displaying each file immediately, then calculating the maximum
    // width of each column based on the length of the results and
    // padding the fields during output.

    let mut cache = Unix::empty_cache();

    let mut table: Vec<Vec<String>> = files.iter()
        .map(|f| options.columns.iter().map(|c| f.display(c, &mut cache)).collect())
        .collect();

    if options.header {
        table.unshift(options.columns.iter().map(|c| Plain.underline().paint(c.header())).collect());
    }

    // Each column needs to have its invisible colour-formatting
    // characters stripped before it has its width calculated, or the
    // width will be incorrect and the columns won't line up properly.
    // This is fairly expensive to do (it uses a regex), so the
    // results are cached.

    let lengths: Vec<Vec<uint>> = table.iter()
        .map(|row| row.iter().map(|col| colours::strip_formatting(col).len()).collect())
        .collect();

    let column_widths: Vec<uint> = range(0, options.columns.len())
        .map(|n| lengths.iter().map(|row| *row.get(n)).max().unwrap())
        .collect();

    for (field_lengths, row) in lengths.iter().zip(table.iter()) {
        for (num, column) in options.columns.iter().enumerate() {
            if num != 0 {
                print!(" ");
            }

            if num == options.columns.len() - 1 {
                print!("{}", row.get(num));
            }
            else {
                print!("{}", column.alignment().pad_string(row.get(num), *field_lengths.get(num), *column_widths.get(num)));
            }
        }
        print!("\n");
    }
}
<|endoftext|>


<commit_before><commit_msg>Auto merge of #10340 - hi-rustin:rustin-patch-clippy, r=ehuss<commit_after><|endoftext|>


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

use std::collections::BitVec;
use std::u32;

#[test]
fn test_to_str() {
    let zerolen = BitVec::new();
    assert_eq!(format!("{:?}", zerolen), "");

    let eightbits = BitVec::from_elem(8, false);
    assert_eq!(format!("{:?}", eightbits), "00000000")
}

#[test]
fn test_0_elements() {
    let act = BitVec::new();
    let exp = Vec::new();
    assert!(act.eq_vec(&exp));
    assert!(act.none() && act.all());
}

#[test]
fn test_1_element() {
    let mut act = BitVec::from_elem(1, false);
    assert!(act.eq_vec(&[false]));
    assert!(act.none() && !act.all());
    act = BitVec::from_elem(1, true);
    assert!(act.eq_vec(&[true]));
    assert!(!act.none() && act.all());
}

#[test]
fn test_2_elements() {
    let mut b = BitVec::from_elem(2, false);
    b.set(0, true);
    b.set(1, false);
    assert_eq!(format!("{:?}", b), "10");
    assert!(!b.none() && !b.all());
}

#[test]
fn test_10_elements() {
    let mut act;
    // all 0

    act = BitVec::from_elem(10, false);
    assert!((act.eq_vec(
                &[false, false, false, false, false, false, false, false, false, false])));
    assert!(act.none() && !act.all());
    // all 1

    act = BitVec::from_elem(10, true);
    assert!((act.eq_vec(&[true, true, true, true, true, true, true, true, true, true])));
    assert!(!act.none() && act.all());
    // mixed

    act = BitVec::from_elem(10, false);
    act.set(0, true);
    act.set(1, true);
    act.set(2, true);
    act.set(3, true);
    act.set(4, true);
    assert!((act.eq_vec(&[true, true, true, true, true, false, false, false, false, false])));
    assert!(!act.none() && !act.all());
    // mixed

    act = BitVec::from_elem(10, false);
    act.set(5, true);
    act.set(6, true);
    act.set(7, true);
    act.set(8, true);
    act.set(9, true);
    assert!((act.eq_vec(&[false, false, false, false, false, true, true, true, true, true])));
    assert!(!act.none() && !act.all());
    // mixed

    act = BitVec::from_elem(10, false);
    act.set(0, true);
    act.set(3, true);
    act.set(6, true);
    act.set(9, true);
    assert!((act.eq_vec(&[true, false, false, true, false, false, true, false, false, true])));
    assert!(!act.none() && !act.all());
}

#[test]
fn test_31_elements() {
    let mut act;
    // all 0

    act = BitVec::from_elem(31, false);
    assert!(act.eq_vec(
            &[false, false, false, false, false, false, false, false, false, false, false,
              false, false, false, false, false, false, false, false, false, false, false,
              false, false, false, false, false, false, false, false, false]));
    assert!(act.none() && !act.all());
    // all 1

    act = BitVec::from_elem(31, true);
    assert!(act.eq_vec(
            &[true, true, true, true, true, true, true, true, true, true, true, true, true,
              true, true, true, true, true, true, true, true, true, true, true, true, true,
              true, true, true, true, true]));
    assert!(!act.none() && act.all());
    // mixed

    act = BitVec::from_elem(31, false);
    act.set(0, true);
    act.set(1, true);
    act.set(2, true);
    act.set(3, true);
    act.set(4, true);
    act.set(5, true);
    act.set(6, true);
    act.set(7, true);
    assert!(act.eq_vec(
            &[true, true, true, true, true, true, true, true, false, false, false, false, false,
              false, false, false, false, false, false, false, false, false, false, false,
              false, false, false, false, false, false, false]));
    assert!(!act.none() && !act.all());
    // mixed

    act = BitVec::from_elem(31, false);
    act.set(16, true);
    act.set(17, true);
    act.set(18, true);
    act.set(19, true);
    act.set(20, true);
    act.set(21, true);
    act.set(22, true);
    act.set(23, true);
    assert!(act.eq_vec(
            &[false, false, false, false, false, false, false, false, false, false, false,
              false, false, false, false, false, true, true, true, true, true, true, true, true,
              false, false, false, false, false, false, false]));
    assert!(!act.none() && !act.all());
    // mixed

    act = BitVec::from_elem(31, false);
    act.set(24, true);
    act.set(25, true);
    act.set(26, true);
    act.set(27, true);
    act.set(28, true);
    act.set(29, true);
    act.set(30, true);
    assert!(act.eq_vec(
            &[false, false, false, false, false, false, false, false, false, false, false,
              false, false, false, false, false, false, false, false, false, false, false,
              false, false, true, true, true, true, true, true, true]));
    assert!(!act.none() && !act.all());
    // mixed

    act = BitVec::from_elem(31, false);
    act.set(3, true);
    act.set(17, true);
    act.set(30, true);
    assert!(act.eq_vec(
            &[false, false, false, true, false, false, false, false, false, false, false, false,
              false, false, false, false, false, true, false, false, false, false, false, false,
              false, false, false, false, false, false, true]));
    assert!(!act.none() && !act.all());
}

#[test]
fn test_32_elements() {
    let mut act;
    // all 0

    act = BitVec::from_elem(32, false);
    assert!(act.eq_vec(
            &[false, false, false, false, false, false, false, false, false, false, false,
              false, false, false, false, false, false, false, false, false, false, false,
              false, false, false, false, false, false, false, false, false, false]));
    assert!(act.none() && !act.all());
    // all 1

    act = BitVec::from_elem(32, true);
    assert!(act.eq_vec(
            &[true, true, true, true, true, true, true, true, true, true, true, true, true,
              true, true, true, true, true, true, true, true, true, true, true, true, true,
              true, true, true, true, true, true]));
    assert!(!act.none() && act.all());
    // mixed

    act = BitVec::from_elem(32, false);
    act.set(0, true);
    act.set(1, true);
    act.set(2, true);
    act.set(3, true);
    act.set(4, true);
    act.set(5, true);
    act.set(6, true);
    act.set(7, true);
    assert!(act.eq_vec(
            &[true, true, true, true, true, true, true, true, false, false, false, false, false,
              false, false, false, false, false, false, false, false, false, false, false,
              false, false, false, false, false, false, false, false]));
    assert!(!act.none() && !act.all());
    // mixed

    act = BitVec::from_elem(32, false);
    act.set(16, true);
    act.set(17, true);
    act.set(18, true);
    act.set(19, true);
    act.set(20, true);
    act.set(21, true);
    act.set(22, true);
    act.set(23, true);
    assert!(act.eq_vec(
            &[false, false, false, false, false, false, false, false, false, false, false,
              false, false, false, false, false, true, true, true, true, true, true, true, true,
              false, false, false, false, false, false, false, false]));
    assert!(!act.none() && !act.all());
    // mixed

    act = BitVec::from_elem(32, false);
    act.set(24, true);
    act.set(25, true);
    act.set(26, true);
    act.set(27, true);
    act.set(28, true);
    act.set(29, true);
    act.set(30, true);
    act.set(31, true);
    assert!(act.eq_vec(
            &[false, false, false, false, false, false, false, false, false, false, false,
              false, false, false, false, false, false, false, false, false, false, false,
              false, false, true, true, true, true, true, true, true, true]));
    assert!(!act.none() && !act.all());
    // mixed

    act = BitVec::from_elem(32, false);
    act.set(3, true);
    act.set(17, true);
    act.set(30, true);
    act.set(31, true);
    assert!(act.eq_vec(
            &[false, false, false, true, false, false, false, false, false, false, false, false,
              false, false, false, false, false, true, false, false, false, false, false, false,
              false, false, false, false, false, false, true, true]));
    assert!(!act.none() && !act.all());
}

#[test]
fn test_33_elements() {
    let mut act;
    // all 0

    act = BitVec::from_elem(33, false);
    assert!(act.eq_vec(
            &[false, false, false, false, false, false, false, false, false, false, false,
              false, false, false, false, false, false, false, false, false, false, false,
              false, false, false, false, false, false, false, false, false, false, false]));
    assert!(act.none() && !act.all());
    // all 1

    act = BitVec::from_elem(33, true);
    assert!(act.eq_vec(
            &[true, true, true, true, true, true, true, true, true, true, true, true, true,
              true, true, true, true, true, true, true, true, true, true, true, true, true,
              true, true, true, true, true, true, true]));
    assert!(!act.none() && act.all());
    // mixed

    act = BitVec::from_elem(33, false);
    act.set(0, true);
    act.set(1, true);
    act.set(2, true);
    act.set(3, true);
    act.set(4, true);
    act.set(5, true);
    act.set(6, true);
    act.set(7, true);
    assert!(act.eq_vec(
            &[true, true, true, true, true, true, true, true, false, false, false, false, false,
              false, false, false, false, false, false, false, false, false, false, false,
              false, false, false, false, false, false, false, false, false]));
    assert!(!act.none() && !act.all());
    // mixed

    act = BitVec::from_elem(33, false);
    act.set(16, true);
    act.set(17, true);
    act.set(18, true);
    act.set(19, true);
    act.set(20, true);
    act.set(21, true);
    act.set(22, true);
    act.set(23, true);
    assert!(act.eq_vec(
            &[false, false, false, false, false, false, false, false, false, false, false,
              false, false, false, false, false, true, true, true, true, true, true, true, true,
              false, false, false, false, false, false, false, false, false]));
    assert!(!act.none() && !act.all());
    // mixed

    act = BitVec::from_elem(33, false);
    act.set(24, true);
    act.set(25, true);
    act.set(26, true);
    act.set(27, true);
    act.set(28, true);
    act.set(29, true);
    act.set(30, true);
    act.set(31, true);
    assert!(act.eq_vec(
            &[false, false, false, false, false, false, false, false, false, false, false,
              false, false, false, false, false, false, false, false, false, false, false,
              false, false, true, true, true, true, true, true, true, true, false]));
    assert!(!act.none() && !act.all());
    // mixed

    act = BitVec::from_elem(33, false);
    act.set(3, true);
    act.set(17, true);
    act.set(30, true);
    act.set(31, true);
    act.set(32, true);
    assert!(act.eq_vec(
            &[false, false, false, true, false, false, false, false, false, false, false, false,
              false, false, false, false, false, true, false, false, false, false, false, false,
              false, false, false, false, false, false, true, true, true]));
    assert!(!act.none() && !act.all());
}

#[test]
fn test_equal_differing_sizes() {
    let v0 = BitVec::from_elem(10, false);
    let v1 = BitVec::from_elem(11, false);
    assert!(v0 != v1);
}

#[test]
fn test_equal_greatly_differing_sizes() {
    let v0 = BitVec::from_elem(10, false);
    let v1 = BitVec::from_elem(110, false);
    assert!(v0 != v1);
}

#[test]
fn test_equal_sneaky_small() {
    let mut a = BitVec::from_elem(1, false);
    a.set(0, true);

    let mut b = BitVec::from_elem(1, true);
    b.set(0, true);

    assert_eq!(a, b);
}

#[test]
fn test_equal_sneaky_big() {
    let mut a = BitVec::from_elem(100, false);
    for i in 0..100 {
        a.set(i, true);
    }

    let mut b = BitVec::from_elem(100, true);
    for i in 0..100 {
        b.set(i, true);
    }

    assert_eq!(a, b);
}

#[test]
fn test_from_bytes() {
    let bit_vec = BitVec::from_bytes(&[0b10110110, 0b00000000, 0b11111111]);
    let str = concat!("10110110", "00000000", "11111111");
    assert_eq!(format!("{:?}", bit_vec), str);
}

#[test]
fn test_to_bytes() {
    let mut bv = BitVec::from_elem(3, true);
    bv.set(1, false);
    assert_eq!(bv.to_bytes(), [0b10100000]);

    let mut bv = BitVec::from_elem(9, false);
    bv.set(2, true);
    bv.set(8, true);
    assert_eq!(bv.to_bytes(), [0b00100000, 0b10000000]);
}

#[test]
fn test_from_bools() {
    let bools = vec![true, false, true, true];
    let bit_vec: BitVec = bools.iter().map(|n| *n).collect();
    assert_eq!(format!("{:?}", bit_vec), "1011");
}

#[test]
fn test_to_bools() {
    let bools = vec![false, false, true, false, false, true, true, false];
    assert_eq!(BitVec::from_bytes(&[0b00100110]).iter().collect::<Vec<bool>>(), bools);
}

#[test]
fn test_bit_vec_iterator() {
    let bools = vec![true, false, true, true];
    let bit_vec: BitVec = bools.iter().map(|n| *n).collect();

    assert_eq!(bit_vec.iter().collect::<Vec<bool>>(), bools);

    let long: Vec<_> = (0..10000).map(|i| i % 2 == 0).collect();
    let bit_vec: BitVec = long.iter().map(|n| *n).collect();
    assert_eq!(bit_vec.iter().collect::<Vec<bool>>(), long)
}

#[test]
fn test_small_difference() {
    let mut b1 = BitVec::from_elem(3, false);
    let mut b2 = BitVec::from_elem(3, false);
    b1.set(0, true);
    b1.set(1, true);
    b2.set(1, true);
    b2.set(2, true);
    assert!(b1.difference(&b2));
    assert!(b1[0]);
    assert!(!b1[1]);
    assert!(!b1[2]);
}

#[test]
fn test_big_difference() {
    let mut b1 = BitVec::from_elem(100, false);
    let mut b2 = BitVec::from_elem(100, false);
    b1.set(0, true);
    b1.set(40, true);
    b2.set(40, true);
    b2.set(80, true);
    assert!(b1.difference(&b2));
    assert!(b1[0]);
    assert!(!b1[40]);
    assert!(!b1[80]);
}

#[test]
fn test_small_clear() {
    let mut b = BitVec::from_elem(14, true);
    assert!(!b.none() && b.all());
    b.clear();
    assert!(b.none() && !b.all());
}

#[test]
fn test_big_clear() {
    let mut b = BitVec::from_elem(140, true);
    assert!(!b.none() && b.all());
    b.clear();
    assert!(b.none() && !b.all());
}

#[test]
fn test_bit_vec_lt() {
    let mut a = BitVec::from_elem(5, false);
    let mut b = BitVec::from_elem(5, false);

    assert!(!(a < b) && !(b < a));
    b.set(2, true);
    assert!(a < b);
    a.set(3, true);
    assert!(a < b);
    a.set(2, true);
    assert!(!(a < b) && b < a);
    b.set(0, true);
    assert!(a < b);
}

#[test]
fn test_ord() {
    let mut a = BitVec::from_elem(5, false);
    let mut b = BitVec::from_elem(5, false);

    assert!(a <= b && a >= b);
    a.set(1, true);
    assert!(a > b && a >= b);
    assert!(b < a && b <= a);
    b.set(1, true);
    b.set(2, true);
    assert!(b > a && b >= a);
    assert!(a < b && a <= b);
}

#[test]
fn test_small_bit_vec_tests() {
    let v = BitVec::from_bytes(&[0]);
    assert!(!v.all());
    assert!(!v.any());
    assert!(v.none());

    let v = BitVec::from_bytes(&[0b00010100]);
    assert!(!v.all());
    assert!(v.any());
    assert!(!v.none());

    let v = BitVec::from_bytes(&[0xFF]);
    assert!(v.all());
    assert!(v.any());
    assert!(!v.none());
}

#[test]
fn test_big_bit_vec_tests() {
    let v = BitVec::from_bytes(&[ // 88 bits
        0, 0, 0, 0,
        0, 0, 0, 0,
        0, 0, 0]);
    assert!(!v.all());
    assert!(!v.any());
    assert!(v.none());

    let v = BitVec::from_bytes(&[ // 88 bits
        0, 0, 0b00010100, 0,
        0, 0, 0, 0b00110100,
        0, 0, 0]);
    assert!(!v.all());
    assert!(v.any());
    assert!(!v.none());

    let v = BitVec::from_bytes(&[ // 88 bits
        0xFF, 0xFF, 0xFF, 0xFF,
        0xFF, 0xFF, 0xFF, 0xFF,
        0xFF, 0xFF, 0xFF]);
    assert!(v.all());
    assert!(v.any());
    assert!(!v.none());
}

#[test]
fn test_bit_vec_push_pop() {
    let mut s = BitVec::from_elem(5 * u32::BITS - 2, false);
    assert_eq!(s.len(), 5 * u32::BITS - 2);
    assert_eq!(s[5 * u32::BITS - 3], false);
    s.push(true);
    s.push(true);
    assert_eq!(s[5 * u32::BITS - 2], true);
    assert_eq!(s[5 * u32::BITS - 1], true);
    // Here the internal vector will need to be extended
    s.push(false);
    assert_eq!(s[5 * u32::BITS], false);
    s.push(false);
    assert_eq!(s[5 * u32::BITS + 1], false);
    assert_eq!(s.len(), 5 * u32::BITS + 2);
    // Pop it all off
    assert_eq!(s.pop(), Some(false));
    assert_eq!(s.pop(), Some(false));
    assert_eq!(s.pop(), Some(true));
    assert_eq!(s.pop(), Some(true));
    assert_eq!(s.len(), 5 * u32::BITS - 2);
}

#[test]
fn test_bit_vec_truncate() {
    let mut s = BitVec::from_elem(5 * u32::BITS, true);

    assert_eq!(s, BitVec::from_elem(5 * u32::BITS, true));
    assert_eq!(s.len(), 5 * u32::BITS);
    s.truncate(4 * u32::BITS);
    assert_eq!(s, BitVec::from_elem(4 * u32::BITS, true));
    assert_eq!(s.len(), 4 * u32::BITS);
    // Truncating to a size > s.len() should be a noop
    s.truncate(5 * u32::BITS);
    assert_eq!(s, BitVec::from_elem(4 * u32::BITS, true));
    assert_eq!(s.len(), 4 * u32::BITS);
    s.truncate(3 * u32::BITS - 10);
    assert_eq!(s, BitVec::from_elem(3 * u32::BITS - 10, true));
    assert_eq!(s.len(), 3 * u32::BITS - 10);
    s.truncate(0);
    assert_eq!(s, BitVec::from_elem(0, true));
    assert_eq!(s.len(), 0);
}

#[test]
fn test_bit_vec_reserve() {
    let mut s = BitVec::from_elem(5 * u32::BITS, true);
    // Check capacity
    assert!(s.capacity() >= 5 * u32::BITS);
    s.reserve(2 * u32::BITS);
    assert!(s.capacity() >= 7 * u32::BITS);
    s.reserve(7 * u32::BITS);
    assert!(s.capacity() >= 12 * u32::BITS);
    s.reserve_exact(7 * u32::BITS);
    assert!(s.capacity() >= 12 * u32::BITS);
    s.reserve(7 * u32::BITS + 1);
    assert!(s.capacity() >= 12 * u32::BITS + 1);
    // Check that length hasn't changed
    assert_eq!(s.len(), 5 * u32::BITS);
    s.push(true);
    s.push(false);
    s.push(true);
    assert_eq!(s[5 * u32::BITS - 1], true);
    assert_eq!(s[5 * u32::BITS - 0], true);
    assert_eq!(s[5 * u32::BITS + 1], false);
    assert_eq!(s[5 * u32::BITS + 2], true);
}

#[test]
fn test_bit_vec_grow() {
    let mut bit_vec = BitVec::from_bytes(&[0b10110110, 0b00000000, 0b10101010]);
    bit_vec.grow(32, true);
    assert_eq!(bit_vec, BitVec::from_bytes(&[0b10110110, 0b00000000, 0b10101010,
                                 0xFF, 0xFF, 0xFF, 0xFF]));
    bit_vec.grow(64, false);
    assert_eq!(bit_vec, BitVec::from_bytes(&[0b10110110, 0b00000000, 0b10101010,
                                 0xFF, 0xFF, 0xFF, 0xFF, 0, 0, 0, 0, 0, 0, 0, 0]));
    bit_vec.grow(16, true);
    assert_eq!(bit_vec, BitVec::from_bytes(&[0b10110110, 0b00000000, 0b10101010,
                                 0xFF, 0xFF, 0xFF, 0xFF, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF]));
}

#[test]
fn test_bit_vec_extend() {
    let mut bit_vec = BitVec::from_bytes(&[0b10110110, 0b00000000, 0b11111111]);
    let ext = BitVec::from_bytes(&[0b01001001, 0b10010010, 0b10111101]);
    bit_vec.extend(ext.iter());
    assert_eq!(bit_vec, BitVec::from_bytes(&[0b10110110, 0b00000000, 0b11111111,
                                 0b01001001, 0b10010010, 0b10111101]));
}

mod bench {
    use std::collections::BitVec;
    use std::u32;
    use std::__rand::{Rng, thread_rng, ThreadRng};

    use test::{Bencher, black_box};

    const BENCH_BITS : usize = 1 << 14;

    fn rng() -> ThreadRng {
        thread_rng()
    }

    #[bench]
    fn bench_usize_small(b: &mut Bencher) {
        let mut r = rng();
        let mut bit_vec = 0 as usize;
        b.iter(|| {
            for _ in 0..100 {
                bit_vec |= 1 << ((r.next_u32() as usize) % u32::BITS);
            }
            black_box(&bit_vec);
        });
    }

    #[bench]
    fn bench_bit_set_big_fixed(b: &mut Bencher) {
        let mut r = rng();
        let mut bit_vec = BitVec::from_elem(BENCH_BITS, false);
        b.iter(|| {
            for _ in 0..100 {
                bit_vec.set((r.next_u32() as usize) % BENCH_BITS, true);
            }
            black_box(&bit_vec);
        });
    }

    #[bench]
    fn bench_bit_set_big_variable(b: &mut Bencher) {
        let mut r = rng();
        let mut bit_vec = BitVec::from_elem(BENCH_BITS, false);
        b.iter(|| {
            for _ in 0..100 {
                bit_vec.set((r.next_u32() as usize) % BENCH_BITS, r.gen());
            }
            black_box(&bit_vec);
        });
    }

    #[bench]
    fn bench_bit_set_small(b: &mut Bencher) {
        let mut r = rng();
        let mut bit_vec = BitVec::from_elem(u32::BITS, false);
        b.iter(|| {
            for _ in 0..100 {
                bit_vec.set((r.next_u32() as usize) % u32::BITS, true);
            }
            black_box(&bit_vec);
        });
    }

    #[bench]
    fn bench_bit_vec_big_union(b: &mut Bencher) {
        let mut b1 = BitVec::from_elem(BENCH_BITS, false);
        let b2 = BitVec::from_elem(BENCH_BITS, false);
        b.iter(|| {
            b1.union(&b2)
        })
    }

    #[bench]
    fn bench_bit_vec_small_iter(b: &mut Bencher) {
        let bit_vec = BitVec::from_elem(u32::BITS, false);
        b.iter(|| {
            let mut sum = 0;
            for _ in 0..10 {
                for pres in &bit_vec {
                    sum += pres as usize;
                }
            }
            sum
        })
    }

    #[bench]
    fn bench_bit_vec_big_iter(b: &mut Bencher) {
        let bit_vec = BitVec::from_elem(BENCH_BITS, false);
        b.iter(|| {
            let mut sum = 0;
            for pres in &bit_vec {
                sum += pres as usize;
            }
            sum
        })
    }
}
<|endoftext|>