<commit_before>use super::{
    LENGTH_BYTES,
};

#[derive(Debug, PartialEq)]
pub enum DecodeError {
    OutOfBounds,
    TooShort,
    TooLong,
}

pub trait Decodable: Sized {
    fn ssz_decode(bytes: &[u8], index: usize) -> Result<(Self, usize), DecodeError>;
}

/// Decode the given bytes for the given type
///
/// The single ssz encoded value will be decoded as the given type at the
/// given index.
pub fn decode_ssz<T>(ssz_bytes: &[u8], index: usize)
    -> Result<(T, usize), DecodeError>
    where T: Decodable
{
    if index >= ssz_bytes.len() {
        return Err(DecodeError::OutOfBounds)
    }
    T::ssz_decode(ssz_bytes, index)
}

/// Return the nth value in some ssz encoded list.
///
/// The four-byte length prefix is not included in the return.
///
/// A single ssz encoded value can be considered a list of
/// one element, so this function will work on it too.
fn nth_value(ssz_bytes: &[u8], n: usize)
    -> Result<&[u8], DecodeError>
{
    let mut c: usize = 0;
    for i in 0..(n + 1) {
        let length = decode_length(&ssz_bytes[c..], LENGTH_BYTES)?;
        let next = c + LENGTH_BYTES + length;

        if i == n {
            return Ok(&ssz_bytes[c + LENGTH_BYTES..next]);
        } else {
            if next >= ssz_bytes.len() {
                return Err(DecodeError::OutOfBounds);
            } else {
                c = next;
            }
        }
    }
    Err(DecodeError::OutOfBounds)
}

/// Given some number of bytes, interpret the first four
/// bytes as a 32-bit big-endian integer and return the
/// result.
fn decode_length(bytes: &[u8], length_bytes: usize)
    -> Result<usize, DecodeError>
{
    if bytes.len() < length_bytes {
        return Err(DecodeError::TooShort);
    };
    let mut len: usize = 0;
    for i in 0..length_bytes {
        let offset = (length_bytes - i - 1) * 8;
        len = ((bytes[i] as usize) << offset) | len;
    };
    Ok(len)
}

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

    #[test]
    fn test_ssz_decode_length() {
        let decoded = decode_length(
            &vec![0, 0, 0, 1],
            LENGTH_BYTES);
        assert_eq!(decoded.unwrap(), 1);

        let decoded = decode_length(
            &vec![0, 0, 1, 0],
            LENGTH_BYTES);
        assert_eq!(decoded.unwrap(), 256);

        let decoded = decode_length(
            &vec![0, 0, 1, 255],
            LENGTH_BYTES);
        assert_eq!(decoded.unwrap(), 511);

        let decoded = decode_length(
            &vec![255, 255, 255, 255],
            LENGTH_BYTES);
        assert_eq!(decoded.unwrap(), 4294967295);
    }

    #[test]
    fn test_encode_decode_length() {
        let params: Vec<usize> = vec![
            0, 1, 2, 3, 7, 8, 16,
            2^8,  2^8  + 1,
            2^16, 2^16 + 1,
            2^24, 2^24 + 1,
            2^32,
        ];
        for i in params {
            let decoded = decode_length(
                &encode_length(i, LENGTH_BYTES),
                LENGTH_BYTES).unwrap();
            assert_eq!(i, decoded);
        }
    }
}
<commit_msg>Begin `decode_ssz_list` for serialized lists of elements<commit_after>use super::{
    LENGTH_BYTES,
};

#[derive(Debug, PartialEq)]
pub enum DecodeError {
    OutOfBounds,
    TooShort,
    TooLong,
}

pub trait Decodable: Sized {
    fn ssz_decode(bytes: &[u8], index: usize) -> Result<(Self, usize), DecodeError>;
}

/// Decode the given bytes for the given type
///
/// The single ssz encoded value will be decoded as the given type at the
/// given index.
pub fn decode_ssz<T>(ssz_bytes: &[u8], index: usize)
    -> Result<(T, usize), DecodeError>
    where T: Decodable
{
    if index >= ssz_bytes.len() {
        return Err(DecodeError::OutOfBounds)
    }
    T::ssz_decode(ssz_bytes, index)
}

/// Decode a vector (list) of encoded bytes.
///
/// Each element in the list will be decoded and placed into the vector.
pub fn decode_ssz_list<T>(ssz_bytes: &[u8], index: usize)
    -> Result<(Vec<T>, usize), DecodeError>
    where T: Decodable
{

    if index + LENGTH_BYTES > ssz_bytes.len() {
        return Err(DecodeError::OutOfBounds);
    };

    // get the length
    let mut serialized_length = match decode_length(ssz_bytes, LENGTH_BYTES) {
        Err(v) => return Err(v),
        Ok(v) => v,
    };

    let final_len: usize = index + LENGTH_BYTES + serialized_length;

    if final_len > ssz_bytes.len() {
        return Err(DecodeError::OutOfBounds);
    };

    let mut tmp_index = index + LENGTH_BYTES;
    let mut res_vec: Vec<T> = Vec::new();

    while tmp_index < final_len {
        match T::ssz_decode(ssz_bytes, tmp_index) {
            Err(v) => return Err(v),
            Ok(v) => {
                tmp_index = v.1;
                res_vec.push(v.0);
            },
        };

    };

    Ok((res_vec, final_len))
}

/// Given some number of bytes, interpret the first four
/// bytes as a 32-bit big-endian integer and return the
/// result.
fn decode_length(bytes: &[u8], length_bytes: usize)
    -> Result<usize, DecodeError>
{
    if bytes.len() < length_bytes {
        return Err(DecodeError::TooShort);
    };
    let mut len: usize = 0;
    for i in 0..length_bytes {
        let offset = (length_bytes - i - 1) * 8;
        len = ((bytes[i] as usize) << offset) | len;
    };
    Ok(len)
}

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

    #[test]
    fn test_ssz_decode_length() {
        let decoded = decode_length(
            &vec![0, 0, 0, 1],
            LENGTH_BYTES);
        assert_eq!(decoded.unwrap(), 1);

        let decoded = decode_length(
            &vec![0, 0, 1, 0],
            LENGTH_BYTES);
        assert_eq!(decoded.unwrap(), 256);

        let decoded = decode_length(
            &vec![0, 0, 1, 255],
            LENGTH_BYTES);
        assert_eq!(decoded.unwrap(), 511);

        let decoded = decode_length(
            &vec![255, 255, 255, 255],
            LENGTH_BYTES);
        assert_eq!(decoded.unwrap(), 4294967295);
    }

    #[test]
    fn test_encode_decode_length() {
        let params: Vec<usize> = vec![
            0, 1, 2, 3, 7, 8, 16,
            2^8,  2^8  + 1,
            2^16, 2^16 + 1,
            2^24, 2^24 + 1,
            2^32,
        ];
        for i in params {
            let decoded = decode_length(
                &encode_length(i, LENGTH_BYTES),
                LENGTH_BYTES).unwrap();
            assert_eq!(i, decoded);
        }
    }
}
<|endoftext|>


<commit_before>use core::marker::PhantomData;

use std::alloc;
use std::mem;
use std::ptr;
use std::ops::RangeFrom;
use std::slice;
use std::str;

pub struct PartialString {
    buf: *const u8,
    len: usize,
    _marker: PhantomData<[u8]>,
}

impl Drop for PartialString {
    fn drop(&mut self) {
        unsafe {
            let layout = alloc::Layout::from_size_align_unchecked(self.len, mem::align_of::<u8>());
            alloc::dealloc(self.buf as *mut u8, layout);

            self.buf = ptr::null();
            self.len = 0;
        }
    }
}

impl Clone for PartialString {
    #[inline]
    fn clone(&self) -> Self {
        self.clone_from_offset(0)
    }
}

fn scan_for_terminator<Iter: Iterator<Item = char>>(iter: Iter) -> usize {
    let mut terminator_idx = 0;

    for c in iter {
        if c == '\u{0}' {
            break;
        }

        terminator_idx += c.len_utf8();
    }

    terminator_idx
}

pub struct PStrIter {
    buf: *const u8,
}

impl PStrIter {
    #[inline]
    fn from(buf: *const u8, idx: usize) -> Self {
        PStrIter {
            buf: (buf as usize + idx) as *const _
        }
    }
}

impl Iterator for PStrIter {
    type Item = char;

    fn next(&mut self) -> Option<Self::Item> {
        unsafe {
            let mut byte_count = 0;

            for n in 0 .. mem::size_of::<char>() {
                let b = ptr::read((self.buf as usize + n) as *const u8);

                if b == 0u8 {
                    break;
                } else {
                    byte_count += 1;
                }
            }

            if byte_count == 0 {
                return None;
            }

            let slice = slice::from_raw_parts(self.buf, byte_count);
            let s = str::from_utf8(slice).unwrap();

            if let Some(c) = s.chars().next() {
                self.buf = self.buf.offset(c.len_utf8() as isize);
                Some(c)
            } else {
                None
            }
        }
    }
}

impl PartialString {
    #[inline]
    pub(super)
    fn new(src: &str) -> Option<(Self, &str)> {
        let pstr = PartialString {
            buf: ptr::null_mut(),
            len: 0,
            _marker: PhantomData,
        };

        unsafe {
            pstr.append_chars(src)
        }
    }

    #[inline]
    pub(super)
    fn empty() -> Self {
        let mut pstr = PartialString {
            buf: ptr::null(),
            len: 0,
            _marker: PhantomData,
        };

        unsafe {
            let layout = alloc::Layout::from_size_align_unchecked(
                '\u{0}'.len_utf8(),
                mem::align_of::<u8>(),
            );

            pstr.buf = alloc::alloc(layout) as *const _;
            pstr.len = '\u{0}'.len_utf8();

            pstr.write_terminator_at(0);
        }

        pstr
    }

    unsafe fn append_chars(mut self, src: &str) -> Option<(Self, &str)> {
        let terminator_idx = scan_for_terminator(src.chars());

        if terminator_idx == 0 {
            return None;
        }

        let layout = alloc::Layout::from_size_align_unchecked(
            terminator_idx + '\u{0}'.len_utf8(),
            mem::align_of::<u8>(),
        );

        self.buf = alloc::alloc(layout) as *const _;
        self.len = terminator_idx + '\u{0}'.len_utf8();

        ptr::copy(
            src.as_ptr(),
            self.buf as *mut _,
            terminator_idx,
        );

        self.write_terminator_at(terminator_idx);

        Some(if terminator_idx != src.len() {
            (self, &src[terminator_idx + '\u{0}'.len_utf8() ..])
        } else {
            (self, "")
        })
    }

    pub(super)
    fn clone_from_offset(&self, n: usize) -> Self {
        let len =
            if self.len - '\u{0}'.len_utf8() > n {
                self.len - n - '\u{0}'.len_utf8()
            } else {
                0
            };

        let mut pstr = PartialString {
            buf: ptr::null_mut(),
            len: len + '\u{0}'.len_utf8(),
            _marker: PhantomData,
        };

        unsafe {
            let layout = alloc::Layout::from_size_align_unchecked(
                len + '\u{0}'.len_utf8(),
                mem::align_of::<u8>(),
            );

            pstr.buf = alloc::alloc(layout);

            if len > 0 {
                ptr::copy(
                    (self.buf as usize + n) as *const u8,
                    pstr.buf as *mut _,
                    len,
                );
            }

            pstr.write_terminator_at(len);
        }

        pstr
    }

    #[inline]
    pub(super)
    fn write_terminator_at(&mut self, index: usize) {
        unsafe {
            ptr::write(
                (self.buf as usize + index) as *mut u8,
                0u8,
            );
        }
    }

    #[inline]
    pub fn range_from(&self, index: RangeFrom<usize>) -> PStrIter {
        PStrIter::from(self.buf, index.start)
    }

    #[inline]
    pub fn at_end(&self, end_n: usize) -> bool {
        unsafe {
            ptr::read((self.buf as usize + end_n) as *const u8) == 0u8
        }
    }

    #[inline]
    pub fn as_str_from(&self, n: usize) -> &str {
        unsafe {
            let slice = slice::from_raw_parts(
                self.buf,
                self.len - '\u{0}'.len_utf8(),
            );

            let s = str::from_utf8(slice).unwrap();

            &s[n ..]
        }
    }
}
<commit_msg>properly iterate through UTF-8 strings (#350)<commit_after>use core::marker::PhantomData;

use std::alloc;
use std::mem;
use std::ptr;
use std::ops::RangeFrom;
use std::slice;
use std::str;

pub struct PartialString {
    buf: *const u8,
    len: usize,
    _marker: PhantomData<[u8]>,
}

impl Drop for PartialString {
    fn drop(&mut self) {
        unsafe {
            let layout = alloc::Layout::from_size_align_unchecked(self.len, mem::align_of::<u8>());
            alloc::dealloc(self.buf as *mut u8, layout);

            self.buf = ptr::null();
            self.len = 0;
        }
    }
}

impl Clone for PartialString {
    #[inline]
    fn clone(&self) -> Self {
        self.clone_from_offset(0)
    }
}

fn scan_for_terminator<Iter: Iterator<Item = char>>(iter: Iter) -> usize {
    let mut terminator_idx = 0;

    for c in iter {
        if c == '\u{0}' {
            break;
        }

        terminator_idx += c.len_utf8();
    }

    terminator_idx
}

pub struct PStrIter {
    buf: *const u8,
    len: usize,
}

impl PStrIter {
    #[inline]
    fn from(buf: *const u8, len: usize, idx: usize) -> Self {
        PStrIter {
            buf: (buf as usize + idx) as *const _,
            len: len - idx,
        }
    }
}

impl Iterator for PStrIter {
    type Item = char;

    fn next(&mut self) -> Option<Self::Item> {
        unsafe {
            let slice = slice::from_raw_parts(self.buf, self.len);
            let s = str::from_utf8(slice).unwrap();

            if let Some(c) = s.chars().next() {
                self.buf = self.buf.offset(c.len_utf8() as isize);
                self.len -= c.len_utf8();

                Some(c)
            } else {
                None
            }
        }
    }
}

impl PartialString {
    #[inline]
    pub(super)
    fn new(src: &str) -> Option<(Self, &str)> {
        let pstr = PartialString {
            buf: ptr::null_mut(),
            len: 0,
            _marker: PhantomData,
        };

        unsafe {
            pstr.append_chars(src)
        }
    }

    #[inline]
    pub(super)
    fn empty() -> Self {
        let mut pstr = PartialString {
            buf: ptr::null(),
            len: 0,
            _marker: PhantomData,
        };

        unsafe {
            let layout = alloc::Layout::from_size_align_unchecked(
                '\u{0}'.len_utf8(),
                mem::align_of::<u8>(),
            );

            pstr.buf = alloc::alloc(layout) as *const _;
            pstr.len = '\u{0}'.len_utf8();

            pstr.write_terminator_at(0);
        }

        pstr
    }

    unsafe fn append_chars(mut self, src: &str) -> Option<(Self, &str)> {
        let terminator_idx = scan_for_terminator(src.chars());

        if terminator_idx == 0 {
            return None;
        }

        let layout = alloc::Layout::from_size_align_unchecked(
            terminator_idx + '\u{0}'.len_utf8(),
            mem::align_of::<u8>(),
        );

        self.buf = alloc::alloc(layout) as *const _;
        self.len = terminator_idx + '\u{0}'.len_utf8();

        ptr::copy(
            src.as_ptr(),
            self.buf as *mut _,
            terminator_idx,
        );

        self.write_terminator_at(terminator_idx);

        Some(if terminator_idx != src.len() {
            (self, &src[terminator_idx + '\u{0}'.len_utf8() ..])
        } else {
            (self, "")
        })
    }

    pub(super)
    fn clone_from_offset(&self, n: usize) -> Self {
        let len =
            if self.len - '\u{0}'.len_utf8() > n {
                self.len - n - '\u{0}'.len_utf8()
            } else {
                0
            };

        let mut pstr = PartialString {
            buf: ptr::null_mut(),
            len: len + '\u{0}'.len_utf8(),
            _marker: PhantomData,
        };

        unsafe {
            let layout = alloc::Layout::from_size_align_unchecked(
                len + '\u{0}'.len_utf8(),
                mem::align_of::<u8>(),
            );

            pstr.buf = alloc::alloc(layout);

            if len > 0 {
                ptr::copy(
                    (self.buf as usize + n) as *const u8,
                    pstr.buf as *mut _,
                    len,
                );
            }

            pstr.write_terminator_at(len);
        }

        pstr
    }

    #[inline]
    pub(super)
    fn write_terminator_at(&mut self, index: usize) {
        unsafe {
            ptr::write(
                (self.buf as usize + index) as *mut u8,
                0u8,
            );
        }
    }

    #[inline]
    pub fn range_from(&self, index: RangeFrom<usize>) -> PStrIter {
        PStrIter::from(self.buf, self.len, index.start)
    }

    #[inline]
    pub fn at_end(&self, end_n: usize) -> bool {
        unsafe {
            ptr::read((self.buf as usize + end_n) as *const u8) == 0u8
        }
    }

    #[inline]
    pub fn as_str_from(&self, n: usize) -> &str {
        unsafe {
            let slice = slice::from_raw_parts(
                self.buf,
                self.len - '\u{0}'.len_utf8(),
            );

            let s = str::from_utf8(slice).unwrap();

            &s[n ..]
        }
    }
}
<|endoftext|>


<commit_before>#![feature(test)]

#[macro_use]
extern crate lazy_static;
extern crate test;

use std::fs::File;
use std::io::{BufRead, BufReader};
use std::path::{Path, PathBuf};
use test::Bencher;

extern crate hyphenation;
use hyphenation::{load, Corpus, Hyphenation, Language};
use hyphenation::exception::{Exceptions};
use hyphenation::pattern::{Patterns};

fn fiat_io(lang: Language) -> Corpus {
    let mut path = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
    path.push("patterns");

    hyphenation::set_pattern_folder(path.as_path());
    load::language(lang).unwrap()
}

lazy_static! {
    static ref DATAPATH: PathBuf = {
        let mut path = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
        path.push("patterns");

        path
    };

    static ref EN_US: Corpus = fiat_io(Language::English_US);

    static ref WORDS: Vec<String> = {
        let file = File::open(Path::new("/usr/share/dict/words")).unwrap();
        let words: Vec<_> = BufReader::new(file).lines().map(|l| l.unwrap()).collect();

        words
    };
}

#[bench]
fn parse_patterns_en_us(b: &mut Bencher) {
    hyphenation::set_pattern_folder(DATAPATH.as_path());

    let by_line = load::patterns(Language::English_US).unwrap();
    let v: Vec<_> = by_line.collect();

    let mut ps = Patterns::empty();
    b.iter(|| {
        for p in &v {
            for val in p { ps.insert(&*val) };
        }
    });
}

#[bench]
fn parse_exceptions_en_us(b: &mut Bencher) {
    hyphenation::set_pattern_folder(DATAPATH.as_path());

    let by_line = load::exceptions(Language::English_US).unwrap();
    let v: Vec<_> = by_line.collect();

    let mut exs = Exceptions::empty();
    b.iter(|| {
        for ex in &v {
            for val in ex { exs.insert(&*val) };
        }
    });
}

#[bench]
fn opportunities_words(b: &mut Bencher) {
    hyphenation::set_pattern_folder(DATAPATH.as_path());

    let mut ws = WORDS.iter();

    b.iter(|| {
        for w in ws.by_ref() {
            w.opportunities(&EN_US);
        }
    })
}
<commit_msg>Code layout inconsequentialities<commit_after>#![feature(test)]

#[macro_use]
extern crate lazy_static;
extern crate test;

use std::fs::File;
use std::io::{BufRead, BufReader};
use std::path::{Path, PathBuf};
use test::Bencher;

extern crate hyphenation;
use hyphenation::{load, Corpus, Hyphenation, Language};
use hyphenation::exception::{Exceptions};
use hyphenation::pattern::{Patterns};

fn fiat_io(lang: Language) -> Corpus {
    let mut path = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
    path.push("patterns");

    hyphenation::set_pattern_folder(path.as_path());
    load::language(lang).unwrap()
}

lazy_static! {
    static ref DATAPATH: PathBuf = {
        let mut path = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
        path.push("patterns");

        path
    };

    static ref EN_US: Corpus = fiat_io(Language::English_US);

    static ref WORDS: Vec<String> = {
        let file = File::open(Path::new("/usr/share/dict/words")).unwrap();
        let words: Vec<_> = BufReader::new(file).lines().map(|l| l.unwrap()).collect();

        words
    };
}

#[bench]
fn parse_patterns_en_us(b: &mut Bencher) {
    hyphenation::set_pattern_folder(DATAPATH.as_path());
    let by_line = load::patterns(Language::English_US).unwrap();
    let v: Vec<_> = by_line.collect();

    let mut ps = Patterns::empty();
    b.iter(|| {
        for p in &v {
            for val in p { ps.insert(&*val) };
        }
    });
}

#[bench]
fn parse_exceptions_en_us(b: &mut Bencher) {
    hyphenation::set_pattern_folder(DATAPATH.as_path());
    let by_line = load::exceptions(Language::English_US).unwrap();
    let v: Vec<_> = by_line.collect();

    let mut exs = Exceptions::empty();
    b.iter(|| {
        for ex in &v {
            for val in ex { exs.insert(&*val) };
        }
    });
}

#[bench]
fn opportunities_words(b: &mut Bencher) {
    hyphenation::set_pattern_folder(DATAPATH.as_path());
    let mut ws = WORDS.iter();

    b.iter(|| {
        for w in ws.by_ref() {
            w.opportunities(&EN_US);
        }
    })
}
<|endoftext|>


<commit_before>// Copyright 2017 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.

// Matching against float literals should result in a linter error

#![feature(slice_patterns)]
#![feature(exclusive_range_pattern)]
#![allow(unused)]
#![forbid(illegal_floating_point_literal_pattern)]

fn main() {
    let x = 42.0;
    match x {
        5.0 => {}, //~ ERROR floating-point literals cannot be used
                   //~| WARNING hard error
        5.0f32 => {}, //~ ERROR floating-point literals cannot be used
                      //~| WARNING hard error
        -5.0 => {}, //~ ERROR floating-point literals cannot be used
                    //~| WARNING hard error
        1.0 .. 33.0 => {}, //~ ERROR floating-point literals cannot be used
                           //~| WARNING hard error
                           //~| ERROR floating-point literals cannot be used
                           //~| WARNING hard error
        39.0 ... 70.0 => {}, //~ ERROR floating-point literals cannot be used
                             //~| WARNING hard error
                             //~| ERROR floating-point literals cannot be used
                             //~| WARNING hard error
        _ => {},
    };
    let y = 5.0;
    // Same for tuples
    match (x, 5) {
        (3.14, 1) => {}, //~ ERROR floating-point literals cannot be used
                         //~| WARNING hard error
        _ => {},
    }
    // Or structs
    struct Foo { x: f32 };
    match (Foo { x }) {
        Foo { x: 2.0 } => {}, //~ ERROR floating-point literals cannot be used
                              //~| WARNING hard error
        _ => {},
    }
}
<commit_msg>Fix test<commit_after>// Copyright 2017 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.

// Matching against float literals should result in a linter error

#![feature(slice_patterns)]
#![feature(exclusive_range_pattern)]
#![allow(unused)]
#![forbid(illegal_floating_point_literal_pattern)]

fn main() {
    let x = 42.0;
    match x {
        5.0 => {}, //~ ERROR floating-point literals cannot be used
                   //~| WARNING hard error
        5.0f32 => {}, //~ ERROR floating-point literals cannot be used
                      //~| WARNING hard error
        -5.0 => {}, //~ ERROR floating-point literals cannot be used
                    //~| WARNING hard error
        1.0 .. 33.0 => {}, //~ ERROR floating-point literals cannot be used
                           //~| WARNING hard error
                           //~| ERROR floating-point literals cannot be used
                           //~| WARNING hard error
        39.0 ... 70.0 => {}, //~ ERROR floating-point literals cannot be used
                             //~| WARNING hard error
                             //~| ERROR floating-point literals cannot be used
                             //~| WARNING hard error
        _ => {},
    };
    let y = 5.0;
    // Same for tuples
    match (x, 5) {
        (3.14, 1) => {}, //~ ERROR floating-point literals cannot be used
                         //~| WARNING hard error
                         //~| ERROR floating-point literals cannot be used
                         //~| WARNING hard error
        _ => {},
    }
    // Or structs
    struct Foo { x: f32 };
    match (Foo { x }) {
        Foo { x: 2.0 } => {}, //~ ERROR floating-point literals cannot be used
                              //~| WARNING hard error
                              //~| ERROR floating-point literals cannot be used
                              //~| WARNING hard error
        _ => {},
    }
}
<|endoftext|>


<commit_before>// Copyright 2017 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.

// this tests move up progration, which is not yet implemented
// Copyright 2017 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.

// Check codegen for assignments (`a = b`) where the left-hand-side is
// not yet initialized. Assignments tend to be absent in simple code,
// so subtle breakage in them can leave a quite hard-to-find trail of
// destruction.

// ignore-tidy-linelength

fn main() {
    let nodrop_x = false;
    let nodrop_y;

    // Since boolean does not require drop, this can be a simple
    // assignment:
    nodrop_y = nodrop_x;

    let drop_x : Option<Box<u32>> = None;
    let drop_y;

    // Since the type of `drop_y` has drop, we generate a `replace`
    // terminator:
    drop_y = drop_x;
}

// END RUST SOURCE
// START rustc.main.SimplifyCfg-initial.after.mir
//    bb0: {
//        StorageLive(_1);
//        _1 = const false;
//        FakeRead(ForLet, _1);
//        StorageLive(_2);
//        StorageLive(_3);
//        _3 = _1;
//        _2 = move _3;
//        StorageDead(_3);
//        StorageLive(_4);
//        _4 = std::option::Option<std::boxed::Box<u32>>::None;
//        FakeRead(ForLet, _4);
//        AscribeUserType(_4, o, Canonical { variables: [], value: std::option::Option<std::boxed::Box<u32>> });
//        StorageLive(_5);
//        StorageLive(_6);
//        _6 = move _4;
//        replace(_5 <- move _6) -> [return: bb2, unwind: bb5];
//    }
//    ...
//    bb2: {
//        drop(_6) -> [return: bb6, unwind: bb4];
//    }
//    ...
//    bb5: {
//        drop(_6) -> bb4;
//    }
// END rustc.main.SimplifyCfg-initial.after.mir
<commit_msg>fix mir-opt test<commit_after>// Copyright 2017 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.

// this tests move up progration, which is not yet implemented
// Copyright 2017 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.

// Check codegen for assignments (`a = b`) where the left-hand-side is
// not yet initialized. Assignments tend to be absent in simple code,
// so subtle breakage in them can leave a quite hard-to-find trail of
// destruction.

// ignore-tidy-linelength

fn main() {
    let nodrop_x = false;
    let nodrop_y;

    // Since boolean does not require drop, this can be a simple
    // assignment:
    nodrop_y = nodrop_x;

    let drop_x : Option<Box<u32>> = None;
    let drop_y;

    // Since the type of `drop_y` has drop, we generate a `replace`
    // terminator:
    drop_y = drop_x;
}

// END RUST SOURCE
// START rustc.main.SimplifyCfg-initial.after.mir
//    bb0: {
//        StorageLive(_1);
//        _1 = const false;
//        FakeRead(ForLet, _1);
//        StorageLive(_2);
//        StorageLive(_3);
//        _3 = _1;
//        _2 = move _3;
//        StorageDead(_3);
//        StorageLive(_4);
//        _4 = std::option::Option<std::boxed::Box<u32>>::None;
//        FakeRead(ForLet, _4);
//        AscribeUserType(_4, o, Ty(Canonical { variables: [], value: std::option::Option<std::boxed::Box<u32>> }));
//        StorageLive(_5);
//        StorageLive(_6);
//        _6 = move _4;
//        replace(_5 <- move _6) -> [return: bb2, unwind: bb5];
//    }
//    ...
//    bb2: {
//        drop(_6) -> [return: bb6, unwind: bb4];
//    }
//    ...
//    bb5: {
//        drop(_6) -> bb4;
//    }
// END rustc.main.SimplifyCfg-initial.after.mir
<|endoftext|>


<commit_before>// This file is part of the uutils coreutils package.
//
// (c) Jian Zeng <anonymousknight96@gmail.com>
//
// For the full copyright and license information, please view the LICENSE
// file that was distributed with this source code.
//
//! Aims to provide platform-independent methods to obtain login records
//!
//! **ONLY** support linux, macos and freebsd for the time being
//!
//! # Examples:
//!
//! ```
//! use uucore::utmpx::Utmpx;
//! for ut in Utmpx::iter_all_records() {
//!     if ut.is_user_process() {
//!         println!("{}: {}", ut.host(), ut.user())
//!     }
//! }
//! ```
//!
//! Specifying the path to login record:
//!
//! ```
//! use uucore::utmpx::Utmpx;
//! for ut in Utmpx::iter_all_records_from("/some/where/else") {
//!     if ut.is_user_process() {
//!         println!("{}: {}", ut.host(), ut.user())
//!     }
//! }
//! ```

pub extern crate time;
use self::time::{Timespec, Tm};

use std::ffi::CString;
use std::io::Result as IOResult;
use std::marker::PhantomData;
use std::os::unix::ffi::OsStrExt;
use std::path::Path;
use std::ptr;
use std::sync::{Mutex, MutexGuard};

pub use self::ut::*;
use libc::utmpx;
// pub use libc::getutxid;
// pub use libc::getutxline;
// pub use libc::pututxline;
pub use libc::endutxent;
pub use libc::getutxent;
pub use libc::setutxent;
#[cfg(any(target_vendor = "apple", target_os = "linux", target_os = "netbsd"))]
pub use libc::utmpxname;
#[cfg(target_os = "freebsd")]
pub unsafe extern "C" fn utmpxname(_file: *const libc::c_char) -> libc::c_int {
    0
}

use once_cell::sync::Lazy;

use crate::*; // import macros from `../../macros.rs`

// In case the c_char array doesn't end with NULL
macro_rules! chars2string {
    ($arr:expr) => {
        $arr.iter()
            .take_while(|i| **i > 0)
            .map(|&i| i as u8 as char)
            .collect::<String>()
    };
}

#[cfg(target_os = "linux")]
mod ut {
    pub static DEFAULT_FILE: &str = "/var/run/utmp";

    pub use libc::__UT_HOSTSIZE as UT_HOSTSIZE;
    pub use libc::__UT_LINESIZE as UT_LINESIZE;
    pub use libc::__UT_NAMESIZE as UT_NAMESIZE;
    pub const UT_IDSIZE: usize = 4;

    pub use libc::ACCOUNTING;
    pub use libc::BOOT_TIME;
    pub use libc::DEAD_PROCESS;
    pub use libc::EMPTY;
    pub use libc::INIT_PROCESS;
    pub use libc::LOGIN_PROCESS;
    pub use libc::NEW_TIME;
    pub use libc::OLD_TIME;
    pub use libc::RUN_LVL;
    pub use libc::USER_PROCESS;
}

#[cfg(target_vendor = "apple")]
mod ut {
    pub static DEFAULT_FILE: &str = "/var/run/utmpx";

    pub use libc::_UTX_HOSTSIZE as UT_HOSTSIZE;
    pub use libc::_UTX_IDSIZE as UT_IDSIZE;
    pub use libc::_UTX_LINESIZE as UT_LINESIZE;
    pub use libc::_UTX_USERSIZE as UT_NAMESIZE;

    pub use libc::ACCOUNTING;
    pub use libc::BOOT_TIME;
    pub use libc::DEAD_PROCESS;
    pub use libc::EMPTY;
    pub use libc::INIT_PROCESS;
    pub use libc::LOGIN_PROCESS;
    pub use libc::NEW_TIME;
    pub use libc::OLD_TIME;
    pub use libc::RUN_LVL;
    pub use libc::SHUTDOWN_TIME;
    pub use libc::SIGNATURE;
    pub use libc::USER_PROCESS;
}

#[cfg(target_os = "freebsd")]
mod ut {
    pub static DEFAULT_FILE: &str = "";

    pub const UT_LINESIZE: usize = 16;
    pub const UT_NAMESIZE: usize = 32;
    pub const UT_IDSIZE: usize = 8;
    pub const UT_HOSTSIZE: usize = 128;

    pub use libc::BOOT_TIME;
    pub use libc::DEAD_PROCESS;
    pub use libc::EMPTY;
    pub use libc::INIT_PROCESS;
    pub use libc::LOGIN_PROCESS;
    pub use libc::NEW_TIME;
    pub use libc::OLD_TIME;
    pub use libc::SHUTDOWN_TIME;
    pub use libc::USER_PROCESS;
}

#[cfg(target_os = "netbsd")]
mod ut {
    pub static DEFAULT_FILE: &str = "/var/run/utmpx";

    pub const ACCOUNTING: usize = 9;
    pub const SHUTDOWN_TIME: usize = 11;

    pub use libc::_UTX_HOSTSIZE as UT_HOSTSIZE;
    pub use libc::_UTX_IDSIZE as UT_IDSIZE;
    pub use libc::_UTX_LINESIZE as UT_LINESIZE;
    pub use libc::_UTX_USERSIZE as UT_NAMESIZE;

    pub use libc::ACCOUNTING;
    pub use libc::DEAD_PROCESS;
    pub use libc::EMPTY;
    pub use libc::INIT_PROCESS;
    pub use libc::LOGIN_PROCESS;
    pub use libc::NEW_TIME;
    pub use libc::OLD_TIME;
    pub use libc::RUN_LVL;
    pub use libc::SIGNATURE;
    pub use libc::USER_PROCESS;
}

pub struct Utmpx {
    inner: utmpx,
}

impl Utmpx {
    /// A.K.A. ut.ut_type
    pub fn record_type(&self) -> i16 {
        self.inner.ut_type as i16
    }
    /// A.K.A. ut.ut_pid
    pub fn pid(&self) -> i32 {
        self.inner.ut_pid as i32
    }
    /// A.K.A. ut.ut_id
    pub fn terminal_suffix(&self) -> String {
        chars2string!(self.inner.ut_id)
    }
    /// A.K.A. ut.ut_user
    pub fn user(&self) -> String {
        chars2string!(self.inner.ut_user)
    }
    /// A.K.A. ut.ut_host
    pub fn host(&self) -> String {
        chars2string!(self.inner.ut_host)
    }
    /// A.K.A. ut.ut_line
    pub fn tty_device(&self) -> String {
        chars2string!(self.inner.ut_line)
    }
    /// A.K.A. ut.ut_tv
    pub fn login_time(&self) -> Tm {
        time::at(Timespec::new(
            self.inner.ut_tv.tv_sec as i64,
            self.inner.ut_tv.tv_usec as i32,
        ))
    }
    /// A.K.A. ut.ut_exit
    ///
    /// Return (e_termination, e_exit)
    #[cfg(any(target_os = "linux", target_os = "android"))]
    pub fn exit_status(&self) -> (i16, i16) {
        (self.inner.ut_exit.e_termination, self.inner.ut_exit.e_exit)
    }
    /// A.K.A. ut.ut_exit
    ///
    /// Return (0, 0) on Non-Linux platform
    #[cfg(not(any(target_os = "linux", target_os = "android")))]
    pub fn exit_status(&self) -> (i16, i16) {
        (0, 0)
    }
    /// Consumes the `Utmpx`, returning the underlying C struct utmpx
    pub fn into_inner(self) -> utmpx {
        self.inner
    }
    pub fn is_user_process(&self) -> bool {
        !self.user().is_empty() && self.record_type() == USER_PROCESS
    }

    /// Canonicalize host name using DNS
    pub fn canon_host(&self) -> IOResult<String> {
        let host = self.host();

        // TODO: change to use `split_once` when MSRV hits 1.52.0
        // let (hostname, display) = host.split_once(':').unwrap_or((&host, ""));
        let mut h = host.split(':');
        let hostname = h.next().unwrap_or(&host);
        let display = h.next().unwrap_or("");

        if !hostname.is_empty() {
            extern crate dns_lookup;
            use dns_lookup::{getaddrinfo, AddrInfoHints};

            const AI_CANONNAME: i32 = 0x2;
            let hints = AddrInfoHints {
                flags: AI_CANONNAME,
                ..AddrInfoHints::default()
            };
            if let Ok(sockets) = getaddrinfo(Some(hostname), None, Some(hints)) {
                let sockets = sockets.collect::<IOResult<Vec<_>>>()?;
                for socket in sockets {
                    if let Some(ai_canonname) = socket.canonname {
                        return Ok(if display.is_empty() {
                            ai_canonname
                        } else {
                            format!("{}:{}", ai_canonname, display)
                        });
                    }
                }
            } else {
                // GNU coreutils has this behavior
                return Ok(hostname.to_string());
            }
        }

        Ok(host.to_string())
    }

    /// Iterate through all the utmp records.
    ///
    /// This will use the default location, or the path [`Utmpx::iter_all_records_from`]
    /// was most recently called with.
    ///
    /// Only one instance of [`UtmpxIter`] may be active at a time. This
    /// function will block as long as one is still active. Beware!
    pub fn iter_all_records() -> UtmpxIter {
        let iter = UtmpxIter::new();
        unsafe {
            // This can technically fail, and it would be nice to detect that,
            // but it doesn't return anything so we'd have to do nasty things
            // with errno.
            setutxent();
        }
        iter
    }

    /// Iterate through all the utmp records from a specific file.
    ///
    /// No failure is reported or detected.
    ///
    /// This function affects subsequent calls to [`Utmpx::iter_all_records`].
    ///
    /// The same caveats as for [`Utmpx::iter_all_records`] apply.
    pub fn iter_all_records_from<P: AsRef<Path>>(path: P) -> UtmpxIter {
        let iter = UtmpxIter::new();
        let path = CString::new(path.as_ref().as_os_str().as_bytes()).unwrap();
        unsafe {
            // In glibc, utmpxname() only fails if there's not enough memory
            // to copy the string.
            // Solaris returns 1 on success instead of 0. Supposedly there also
            // exist systems where it returns void.
            // GNU who on Debian seems to output nothing if an invalid filename
            // is specified, no warning or anything.
            // So this function is pretty crazy and we don't try to detect errors.
            // Not much we can do besides pray.
            utmpxname(path.as_ptr());
            setutxent();
        }
        iter
    }
}

// On some systems these functions are not thread-safe. On others they're
// thread-local. Therefore we use a mutex to allow only one guard to exist at
// a time, and make sure UtmpxIter cannot be sent across threads.
//
// I believe the only technical memory unsafety that could happen is a data
// race while copying the data out of the pointer returned by getutxent(), but
// ordinary race conditions are also very much possible.
static LOCK: Lazy<Mutex<()>> = Lazy::new(|| Mutex::new(()));

/// Iterator of login records
pub struct UtmpxIter {
    #[allow(dead_code)]
    guard: MutexGuard<'static, ()>,
    /// Ensure UtmpxIter is !Send. Technically redundant because MutexGuard
    /// is also !Send.
    phantom: PhantomData<std::rc::Rc<()>>,
}

impl UtmpxIter {
    fn new() -> Self {
        // PoisonErrors can safely be ignored
        let guard = LOCK.lock().unwrap_or_else(|err| err.into_inner());
        Self {
            guard,
            phantom: PhantomData,
        }
    }
}

impl Iterator for UtmpxIter {
    type Item = Utmpx;
    fn next(&mut self) -> Option<Self::Item> {
        unsafe {
            let res = getutxent();
            if !res.is_null() {
                // The data behind this pointer will be replaced by the next
                // call to getutxent(), so we have to read it now.
                // All the strings live inline in the struct as arrays, which
                // makes things easier.
                Some(Utmpx {
                    inner: ptr::read(res as *const _),
                })
            } else {
                None
            }
        }
    }
}

impl Drop for UtmpxIter {
    fn drop(&mut self) {
        unsafe {
            endutxent();
        }
    }
}
<commit_msg>uucore: use split_once in canon_host<commit_after>// This file is part of the uutils coreutils package.
//
// (c) Jian Zeng <anonymousknight96@gmail.com>
//
// For the full copyright and license information, please view the LICENSE
// file that was distributed with this source code.
//
//! Aims to provide platform-independent methods to obtain login records
//!
//! **ONLY** support linux, macos and freebsd for the time being
//!
//! # Examples:
//!
//! ```
//! use uucore::utmpx::Utmpx;
//! for ut in Utmpx::iter_all_records() {
//!     if ut.is_user_process() {
//!         println!("{}: {}", ut.host(), ut.user())
//!     }
//! }
//! ```
//!
//! Specifying the path to login record:
//!
//! ```
//! use uucore::utmpx::Utmpx;
//! for ut in Utmpx::iter_all_records_from("/some/where/else") {
//!     if ut.is_user_process() {
//!         println!("{}: {}", ut.host(), ut.user())
//!     }
//! }
//! ```

pub extern crate time;
use self::time::{Timespec, Tm};

use std::ffi::CString;
use std::io::Result as IOResult;
use std::marker::PhantomData;
use std::os::unix::ffi::OsStrExt;
use std::path::Path;
use std::ptr;
use std::sync::{Mutex, MutexGuard};

pub use self::ut::*;
use libc::utmpx;
// pub use libc::getutxid;
// pub use libc::getutxline;
// pub use libc::pututxline;
pub use libc::endutxent;
pub use libc::getutxent;
pub use libc::setutxent;
#[cfg(any(target_vendor = "apple", target_os = "linux", target_os = "netbsd"))]
pub use libc::utmpxname;
#[cfg(target_os = "freebsd")]
pub unsafe extern "C" fn utmpxname(_file: *const libc::c_char) -> libc::c_int {
    0
}

use once_cell::sync::Lazy;

use crate::*; // import macros from `../../macros.rs`

// In case the c_char array doesn't end with NULL
macro_rules! chars2string {
    ($arr:expr) => {
        $arr.iter()
            .take_while(|i| **i > 0)
            .map(|&i| i as u8 as char)
            .collect::<String>()
    };
}

#[cfg(target_os = "linux")]
mod ut {
    pub static DEFAULT_FILE: &str = "/var/run/utmp";

    pub use libc::__UT_HOSTSIZE as UT_HOSTSIZE;
    pub use libc::__UT_LINESIZE as UT_LINESIZE;
    pub use libc::__UT_NAMESIZE as UT_NAMESIZE;
    pub const UT_IDSIZE: usize = 4;

    pub use libc::ACCOUNTING;
    pub use libc::BOOT_TIME;
    pub use libc::DEAD_PROCESS;
    pub use libc::EMPTY;
    pub use libc::INIT_PROCESS;
    pub use libc::LOGIN_PROCESS;
    pub use libc::NEW_TIME;
    pub use libc::OLD_TIME;
    pub use libc::RUN_LVL;
    pub use libc::USER_PROCESS;
}

#[cfg(target_vendor = "apple")]
mod ut {
    pub static DEFAULT_FILE: &str = "/var/run/utmpx";

    pub use libc::_UTX_HOSTSIZE as UT_HOSTSIZE;
    pub use libc::_UTX_IDSIZE as UT_IDSIZE;
    pub use libc::_UTX_LINESIZE as UT_LINESIZE;
    pub use libc::_UTX_USERSIZE as UT_NAMESIZE;

    pub use libc::ACCOUNTING;
    pub use libc::BOOT_TIME;
    pub use libc::DEAD_PROCESS;
    pub use libc::EMPTY;
    pub use libc::INIT_PROCESS;
    pub use libc::LOGIN_PROCESS;
    pub use libc::NEW_TIME;
    pub use libc::OLD_TIME;
    pub use libc::RUN_LVL;
    pub use libc::SHUTDOWN_TIME;
    pub use libc::SIGNATURE;
    pub use libc::USER_PROCESS;
}

#[cfg(target_os = "freebsd")]
mod ut {
    pub static DEFAULT_FILE: &str = "";

    pub const UT_LINESIZE: usize = 16;
    pub const UT_NAMESIZE: usize = 32;
    pub const UT_IDSIZE: usize = 8;
    pub const UT_HOSTSIZE: usize = 128;

    pub use libc::BOOT_TIME;
    pub use libc::DEAD_PROCESS;
    pub use libc::EMPTY;
    pub use libc::INIT_PROCESS;
    pub use libc::LOGIN_PROCESS;
    pub use libc::NEW_TIME;
    pub use libc::OLD_TIME;
    pub use libc::SHUTDOWN_TIME;
    pub use libc::USER_PROCESS;
}

#[cfg(target_os = "netbsd")]
mod ut {
    pub static DEFAULT_FILE: &str = "/var/run/utmpx";

    pub const ACCOUNTING: usize = 9;
    pub const SHUTDOWN_TIME: usize = 11;

    pub use libc::_UTX_HOSTSIZE as UT_HOSTSIZE;
    pub use libc::_UTX_IDSIZE as UT_IDSIZE;
    pub use libc::_UTX_LINESIZE as UT_LINESIZE;
    pub use libc::_UTX_USERSIZE as UT_NAMESIZE;

    pub use libc::ACCOUNTING;
    pub use libc::DEAD_PROCESS;
    pub use libc::EMPTY;
    pub use libc::INIT_PROCESS;
    pub use libc::LOGIN_PROCESS;
    pub use libc::NEW_TIME;
    pub use libc::OLD_TIME;
    pub use libc::RUN_LVL;
    pub use libc::SIGNATURE;
    pub use libc::USER_PROCESS;
}

pub struct Utmpx {
    inner: utmpx,
}

impl Utmpx {
    /// A.K.A. ut.ut_type
    pub fn record_type(&self) -> i16 {
        self.inner.ut_type as i16
    }
    /// A.K.A. ut.ut_pid
    pub fn pid(&self) -> i32 {
        self.inner.ut_pid as i32
    }
    /// A.K.A. ut.ut_id
    pub fn terminal_suffix(&self) -> String {
        chars2string!(self.inner.ut_id)
    }
    /// A.K.A. ut.ut_user
    pub fn user(&self) -> String {
        chars2string!(self.inner.ut_user)
    }
    /// A.K.A. ut.ut_host
    pub fn host(&self) -> String {
        chars2string!(self.inner.ut_host)
    }
    /// A.K.A. ut.ut_line
    pub fn tty_device(&self) -> String {
        chars2string!(self.inner.ut_line)
    }
    /// A.K.A. ut.ut_tv
    pub fn login_time(&self) -> Tm {
        time::at(Timespec::new(
            self.inner.ut_tv.tv_sec as i64,
            self.inner.ut_tv.tv_usec as i32,
        ))
    }
    /// A.K.A. ut.ut_exit
    ///
    /// Return (e_termination, e_exit)
    #[cfg(any(target_os = "linux", target_os = "android"))]
    pub fn exit_status(&self) -> (i16, i16) {
        (self.inner.ut_exit.e_termination, self.inner.ut_exit.e_exit)
    }
    /// A.K.A. ut.ut_exit
    ///
    /// Return (0, 0) on Non-Linux platform
    #[cfg(not(any(target_os = "linux", target_os = "android")))]
    pub fn exit_status(&self) -> (i16, i16) {
        (0, 0)
    }
    /// Consumes the `Utmpx`, returning the underlying C struct utmpx
    pub fn into_inner(self) -> utmpx {
        self.inner
    }
    pub fn is_user_process(&self) -> bool {
        !self.user().is_empty() && self.record_type() == USER_PROCESS
    }

    /// Canonicalize host name using DNS
    pub fn canon_host(&self) -> IOResult<String> {
        let host = self.host();

        let (hostname, display) = host.split_once(':').unwrap_or((&host, ""));

        if !hostname.is_empty() {
            extern crate dns_lookup;
            use dns_lookup::{getaddrinfo, AddrInfoHints};

            const AI_CANONNAME: i32 = 0x2;
            let hints = AddrInfoHints {
                flags: AI_CANONNAME,
                ..AddrInfoHints::default()
            };
            if let Ok(sockets) = getaddrinfo(Some(hostname), None, Some(hints)) {
                let sockets = sockets.collect::<IOResult<Vec<_>>>()?;
                for socket in sockets {
                    if let Some(ai_canonname) = socket.canonname {
                        return Ok(if display.is_empty() {
                            ai_canonname
                        } else {
                            format!("{}:{}", ai_canonname, display)
                        });
                    }
                }
            } else {
                // GNU coreutils has this behavior
                return Ok(hostname.to_string());
            }
        }

        Ok(host.to_string())
    }

    /// Iterate through all the utmp records.
    ///
    /// This will use the default location, or the path [`Utmpx::iter_all_records_from`]
    /// was most recently called with.
    ///
    /// Only one instance of [`UtmpxIter`] may be active at a time. This
    /// function will block as long as one is still active. Beware!
    pub fn iter_all_records() -> UtmpxIter {
        let iter = UtmpxIter::new();
        unsafe {
            // This can technically fail, and it would be nice to detect that,
            // but it doesn't return anything so we'd have to do nasty things
            // with errno.
            setutxent();
        }
        iter
    }

    /// Iterate through all the utmp records from a specific file.
    ///
    /// No failure is reported or detected.
    ///
    /// This function affects subsequent calls to [`Utmpx::iter_all_records`].
    ///
    /// The same caveats as for [`Utmpx::iter_all_records`] apply.
    pub fn iter_all_records_from<P: AsRef<Path>>(path: P) -> UtmpxIter {
        let iter = UtmpxIter::new();
        let path = CString::new(path.as_ref().as_os_str().as_bytes()).unwrap();
        unsafe {
            // In glibc, utmpxname() only fails if there's not enough memory
            // to copy the string.
            // Solaris returns 1 on success instead of 0. Supposedly there also
            // exist systems where it returns void.
            // GNU who on Debian seems to output nothing if an invalid filename
            // is specified, no warning or anything.
            // So this function is pretty crazy and we don't try to detect errors.
            // Not much we can do besides pray.
            utmpxname(path.as_ptr());
            setutxent();
        }
        iter
    }
}

// On some systems these functions are not thread-safe. On others they're
// thread-local. Therefore we use a mutex to allow only one guard to exist at
// a time, and make sure UtmpxIter cannot be sent across threads.
//
// I believe the only technical memory unsafety that could happen is a data
// race while copying the data out of the pointer returned by getutxent(), but
// ordinary race conditions are also very much possible.
static LOCK: Lazy<Mutex<()>> = Lazy::new(|| Mutex::new(()));

/// Iterator of login records
pub struct UtmpxIter {
    #[allow(dead_code)]
    guard: MutexGuard<'static, ()>,
    /// Ensure UtmpxIter is !Send. Technically redundant because MutexGuard
    /// is also !Send.
    phantom: PhantomData<std::rc::Rc<()>>,
}

impl UtmpxIter {
    fn new() -> Self {
        // PoisonErrors can safely be ignored
        let guard = LOCK.lock().unwrap_or_else(|err| err.into_inner());
        Self {
            guard,
            phantom: PhantomData,
        }
    }
}

impl Iterator for UtmpxIter {
    type Item = Utmpx;
    fn next(&mut self) -> Option<Self::Item> {
        unsafe {
            let res = getutxent();
            if !res.is_null() {
                // The data behind this pointer will be replaced by the next
                // call to getutxent(), so we have to read it now.
                // All the strings live inline in the struct as arrays, which
                // makes things easier.
                Some(Utmpx {
                    inner: ptr::read(res as *const _),
                })
            } else {
                None
            }
        }
    }
}

impl Drop for UtmpxIter {
    fn drop(&mut self) {
        unsafe {
            endutxent();
        }
    }
}
<|endoftext|>


<commit_before>// Copyright (C) 2017 Sebastian Dröge <sebastian@centricular.com>
//
// 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::ptr;
use std::mem;

use glib_ffi;
use gobject_ffi;
use gst_ffi;

use glib;
use glib::translate::*;
use gst;
use gst::prelude::*;

use object::*;
use element::*;
use anyimpl::*;

pub trait BinImpl<T: BinBase>
    : AnyImpl + ObjectImpl<T> + ElementImpl<T> + Send + Sync + 'static {
    fn add_element(&self, bin: &T, element: &gst::Element) -> bool {
        bin.parent_add_element(element)
    }

    fn remove_element(&self, bin: &T, element: &gst::Element) -> bool {
        bin.parent_remove_element(element)
    }

    fn handle_message(&self, bin: &T, message: gst::Message) {
        bin.parent_handle_message(message)
    }
}

any_impl!(BinBase, BinImpl);

pub unsafe trait BinBase: IsA<gst::Element> + IsA<gst::Bin> + ObjectType {
    fn parent_add_element(&self, element: &gst::Element) -> bool {
        unsafe {
            let klass = self.get_class();
            let parent_klass = (*klass).get_parent_class() as *const gst_ffi::GstBinClass;
            (*parent_klass)
                .add_element
                .map(|f| {
                    from_glib(f(self.to_glib_none().0, element.to_glib_none().0))
                })
                .unwrap_or(false)
        }
    }

    fn parent_remove_element(&self, element: &gst::Element) -> bool {
        unsafe {
            let klass = self.get_class();
            let parent_klass = (*klass).get_parent_class() as *const gst_ffi::GstBinClass;
            (*parent_klass)
                .remove_element
                .map(|f| {
                    from_glib(f(self.to_glib_none().0, element.to_glib_none().0))
                })
                .unwrap_or(false)
        }
    }

    fn parent_handle_message(&self, message: gst::Message) {
        unsafe {
            let klass = self.get_class();
            let parent_klass = (*klass).get_parent_class() as *const gst_ffi::GstBinClass;
            (*parent_klass)
                .handle_message
                .map(move |f| f(self.to_glib_none().0, message.into_ptr()));
        }
    }
}

pub unsafe trait BinClassExt<T: BinBase>
where
    T::ImplType: BinImpl<T>,
{
    fn override_vfuncs(&mut self, _: &ClassInitToken) {
        unsafe {
            let klass = &mut *(self as *const Self as *mut gst_ffi::GstBinClass);
            klass.add_element = Some(bin_add_element::<T>);
            klass.remove_element = Some(bin_remove_element::<T>);
            klass.handle_message = Some(bin_handle_message::<T>);
        }
    }
}

glib_wrapper! {
    pub struct Bin(Object<InstanceStruct<Bin>>): [gst::Bin => gst_ffi::GstBin,
                                                  gst::Element => gst_ffi::GstElement,
                                                  gst::Object => gst_ffi::GstObject,
                                                  gst::ChildProxy => gst_ffi::GstChildProxy];

    match fn {
        get_type => || get_type::<Bin>(),
    }
}

unsafe impl<T: IsA<gst::Element> + IsA<gst::Bin> + ObjectType> BinBase for T {}
pub type BinClass = ClassStruct<Bin>;

// FIXME: Boilerplate
unsafe impl BinClassExt<Bin> for BinClass {}
unsafe impl ElementClassExt<Bin> for BinClass {}

#[macro_export]
macro_rules! box_bin_impl(
    ($name:ident) => {
        box_element_impl!($name);

        impl<T: BinBase> BinImpl<T> for Box<$name<T>> {
            fn add_element(&self, bin: &T, element: &gst::Element) -> bool {
                let imp: &$name<T> = self.as_ref();
                imp.add_element(bin, element)
            }

            fn remove_element(&self, bin: &T, element: &gst::Element) -> bool {
                let imp: &$name<T> = self.as_ref();
                imp.remove_element(bin, element)
            }

            fn handle_message(&self, bin: &T, message: gst::Message) {
                let imp: &$name<T> = self.as_ref();
                imp.handle_message(bin, message)
            }
        }
    };
);
box_bin_impl!(BinImpl);

impl ObjectType for Bin {
    const NAME: &'static str = "RsBin";
    type GlibType = gst_ffi::GstBin;
    type GlibClassType = gst_ffi::GstBinClass;
    type ImplType = Box<BinImpl<Self>>;

    fn glib_type() -> glib::Type {
        unsafe { from_glib(gst_ffi::gst_bin_get_type()) }
    }

    fn class_init(token: &ClassInitToken, klass: &mut BinClass) {
        ElementClassExt::override_vfuncs(klass, token);
        BinClassExt::override_vfuncs(klass, token);
    }

    object_type_fns!();
}

unsafe extern "C" fn bin_add_element<T: BinBase>(
    ptr: *mut gst_ffi::GstBin,
    element: *mut gst_ffi::GstElement,
) -> glib_ffi::gboolean
where
    T::ImplType: BinImpl<T>,
{
    callback_guard!();
    floating_reference_guard!(ptr);
    floating_reference_guard!(element);
    let bin = &*(ptr as *mut InstanceStruct<T>);
    let wrap: T = from_glib_borrow(ptr as *mut InstanceStruct<T>);
    let imp = &*bin.imp;

    panic_to_error!(&wrap, &bin.panicked, false, {
        imp.add_element(&wrap, &from_glib_borrow(element))
    }).to_glib()
}

unsafe extern "C" fn bin_remove_element<T: BinBase>(
    ptr: *mut gst_ffi::GstBin,
    element: *mut gst_ffi::GstElement,
) -> glib_ffi::gboolean
where
    T::ImplType: BinImpl<T>,
{
    callback_guard!();
    floating_reference_guard!(ptr);
    floating_reference_guard!(element);
    let bin = &*(ptr as *mut InstanceStruct<T>);
    let wrap: T = from_glib_borrow(ptr as *mut InstanceStruct<T>);
    let imp = &*bin.imp;

    panic_to_error!(&wrap, &bin.panicked, false, {
        imp.remove_element(&wrap, &from_glib_borrow(element))
    }).to_glib()
}

unsafe extern "C" fn bin_handle_message<T: BinBase>(
    ptr: *mut gst_ffi::GstBin,
    message: *mut gst_ffi::GstMessage,
) where
    T::ImplType: BinImpl<T>,
{
    callback_guard!();
    floating_reference_guard!(ptr);
    let bin = &*(ptr as *mut InstanceStruct<T>);
    let wrap: T = from_glib_borrow(ptr as *mut InstanceStruct<T>);
    let imp = &*bin.imp;

    panic_to_error!(&wrap, &bin.panicked, (), {
        imp.handle_message(&wrap, from_glib_full(message))
    });
}
<commit_msg>Take ownership of any floating references in Bin::add/remove_element()<commit_after>// Copyright (C) 2017 Sebastian Dröge <sebastian@centricular.com>
//
// 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::ptr;
use std::mem;

use glib_ffi;
use gobject_ffi;
use gst_ffi;

use glib;
use glib::translate::*;
use gst;
use gst::prelude::*;

use object::*;
use element::*;
use anyimpl::*;

pub trait BinImpl<T: BinBase>
    : AnyImpl + ObjectImpl<T> + ElementImpl<T> + Send + Sync + 'static {
    fn add_element(&self, bin: &T, element: &gst::Element) -> bool {
        bin.parent_add_element(element)
    }

    fn remove_element(&self, bin: &T, element: &gst::Element) -> bool {
        bin.parent_remove_element(element)
    }

    fn handle_message(&self, bin: &T, message: gst::Message) {
        bin.parent_handle_message(message)
    }
}

any_impl!(BinBase, BinImpl);

pub unsafe trait BinBase: IsA<gst::Element> + IsA<gst::Bin> + ObjectType {
    fn parent_add_element(&self, element: &gst::Element) -> bool {
        unsafe {
            let klass = self.get_class();
            let parent_klass = (*klass).get_parent_class() as *const gst_ffi::GstBinClass;
            (*parent_klass)
                .add_element
                .map(|f| {
                    from_glib(f(self.to_glib_none().0, element.to_glib_none().0))
                })
                .unwrap_or(false)
        }
    }

    fn parent_remove_element(&self, element: &gst::Element) -> bool {
        unsafe {
            let klass = self.get_class();
            let parent_klass = (*klass).get_parent_class() as *const gst_ffi::GstBinClass;
            (*parent_klass)
                .remove_element
                .map(|f| {
                    from_glib(f(self.to_glib_none().0, element.to_glib_none().0))
                })
                .unwrap_or(false)
        }
    }

    fn parent_handle_message(&self, message: gst::Message) {
        unsafe {
            let klass = self.get_class();
            let parent_klass = (*klass).get_parent_class() as *const gst_ffi::GstBinClass;
            (*parent_klass)
                .handle_message
                .map(move |f| f(self.to_glib_none().0, message.into_ptr()));
        }
    }
}

pub unsafe trait BinClassExt<T: BinBase>
where
    T::ImplType: BinImpl<T>,
{
    fn override_vfuncs(&mut self, _: &ClassInitToken) {
        unsafe {
            let klass = &mut *(self as *const Self as *mut gst_ffi::GstBinClass);
            klass.add_element = Some(bin_add_element::<T>);
            klass.remove_element = Some(bin_remove_element::<T>);
            klass.handle_message = Some(bin_handle_message::<T>);
        }
    }
}

glib_wrapper! {
    pub struct Bin(Object<InstanceStruct<Bin>>): [gst::Bin => gst_ffi::GstBin,
                                                  gst::Element => gst_ffi::GstElement,
                                                  gst::Object => gst_ffi::GstObject,
                                                  gst::ChildProxy => gst_ffi::GstChildProxy];

    match fn {
        get_type => || get_type::<Bin>(),
    }
}

unsafe impl<T: IsA<gst::Element> + IsA<gst::Bin> + ObjectType> BinBase for T {}
pub type BinClass = ClassStruct<Bin>;

// FIXME: Boilerplate
unsafe impl BinClassExt<Bin> for BinClass {}
unsafe impl ElementClassExt<Bin> for BinClass {}

#[macro_export]
macro_rules! box_bin_impl(
    ($name:ident) => {
        box_element_impl!($name);

        impl<T: BinBase> BinImpl<T> for Box<$name<T>> {
            fn add_element(&self, bin: &T, element: &gst::Element) -> bool {
                let imp: &$name<T> = self.as_ref();
                imp.add_element(bin, element)
            }

            fn remove_element(&self, bin: &T, element: &gst::Element) -> bool {
                let imp: &$name<T> = self.as_ref();
                imp.remove_element(bin, element)
            }

            fn handle_message(&self, bin: &T, message: gst::Message) {
                let imp: &$name<T> = self.as_ref();
                imp.handle_message(bin, message)
            }
        }
    };
);
box_bin_impl!(BinImpl);

impl ObjectType for Bin {
    const NAME: &'static str = "RsBin";
    type GlibType = gst_ffi::GstBin;
    type GlibClassType = gst_ffi::GstBinClass;
    type ImplType = Box<BinImpl<Self>>;

    fn glib_type() -> glib::Type {
        unsafe { from_glib(gst_ffi::gst_bin_get_type()) }
    }

    fn class_init(token: &ClassInitToken, klass: &mut BinClass) {
        ElementClassExt::override_vfuncs(klass, token);
        BinClassExt::override_vfuncs(klass, token);
    }

    object_type_fns!();
}

unsafe extern "C" fn bin_add_element<T: BinBase>(
    ptr: *mut gst_ffi::GstBin,
    element: *mut gst_ffi::GstElement,
) -> glib_ffi::gboolean
where
    T::ImplType: BinImpl<T>,
{
    callback_guard!();
    floating_reference_guard!(ptr);
    let bin = &*(ptr as *mut InstanceStruct<T>);
    let wrap: T = from_glib_borrow(ptr as *mut InstanceStruct<T>);
    let imp = &*bin.imp;

    panic_to_error!(&wrap, &bin.panicked, false, {
        imp.add_element(&wrap, &from_glib_none(element))
    }).to_glib()
}

unsafe extern "C" fn bin_remove_element<T: BinBase>(
    ptr: *mut gst_ffi::GstBin,
    element: *mut gst_ffi::GstElement,
) -> glib_ffi::gboolean
where
    T::ImplType: BinImpl<T>,
{
    callback_guard!();
    floating_reference_guard!(ptr);
    let bin = &*(ptr as *mut InstanceStruct<T>);
    let wrap: T = from_glib_borrow(ptr as *mut InstanceStruct<T>);
    let imp = &*bin.imp;

    panic_to_error!(&wrap, &bin.panicked, false, {
        imp.remove_element(&wrap, &from_glib_none(element))
    }).to_glib()
}

unsafe extern "C" fn bin_handle_message<T: BinBase>(
    ptr: *mut gst_ffi::GstBin,
    message: *mut gst_ffi::GstMessage,
) where
    T::ImplType: BinImpl<T>,
{
    callback_guard!();
    floating_reference_guard!(ptr);
    let bin = &*(ptr as *mut InstanceStruct<T>);
    let wrap: T = from_glib_borrow(ptr as *mut InstanceStruct<T>);
    let imp = &*bin.imp;

    panic_to_error!(&wrap, &bin.panicked, (), {
        imp.handle_message(&wrap, from_glib_full(message))
    });
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate bencher;

extern crate gluon;

extern crate bincode;
extern crate serde_state;

use std::fs::File;
use std::io::Read;

use bencher::{black_box, Bencher};

use serde_state::ser::SerializeState;

use gluon::{new_vm, Compiler, Future};
use gluon::vm::thread::ThreadInternal;
use gluon::vm::serialization::SeSeed;

fn precompiled_prelude(b: &mut Bencher) {
    let thread = new_vm();
    Compiler::new()
        .implicit_prelude(false)
        .load_file(&thread, "std/prelude.glu")
        .unwrap();
    let mut serialized_prelude = Vec::new();
    {
        let env = thread.global_env().get_env();
        let prelude = env.globals.get("std.prelude").unwrap();
        prelude
            .serialize_state(
                &mut bincode::Serializer::new(&mut serialized_prelude),
                &SeSeed::new(),
            )
            .unwrap();
    }
    b.iter(|| {
        use gluon::compiler_pipeline::{Executable, Precompiled};

        let mut deserializer = bincode::Deserializer::new(
            bincode::read_types::SliceReader::new(&serialized_prelude),
            bincode::Infinite,
        );
        let result = Precompiled(&mut deserializer)
            .run_expr(&mut Compiler::new(), &thread, "std.prelude", "", ())
            .wait()
            .unwrap();
        black_box(result)
    })
}

fn source_prelude(b: &mut Bencher) {
    let mut prelude_source = String::new();
    File::open("std/prelude.glu")
        .and_then(|mut f| f.read_to_string(&mut prelude_source))
        .unwrap();
    let thread = new_vm();

    b.iter(|| {
        use gluon::compiler_pipeline::Executable;

        let result = prelude_source
            .run_expr(
                &mut Compiler::new(),
                &thread,
                "std.prelude",
                &prelude_source,
                None,
            )
            .wait()
            .unwrap();
        black_box(result)
    })
}

benchmark_group!(precompiled, precompiled_prelude, source_prelude);
benchmark_main!(precompiled);
<commit_msg>Fix benchmarks<commit_after>#[macro_use]
extern crate bencher;

extern crate gluon;

extern crate bincode;
extern crate serde_state;

use std::fs::File;
use std::io::Read;

use bencher::{black_box, Bencher};

use serde_state::ser::SerializeState;

use gluon::{new_vm, Compiler, Future};
use gluon::vm::thread::ThreadInternal;
use gluon::vm::serialization::SeSeed;

fn precompiled_prelude(b: &mut Bencher) {
    let thread = new_vm();
    Compiler::new()
        .implicit_prelude(false)
        .load_file(&thread, "std/prelude.glu")
        .unwrap();
    let mut serialized_prelude = Vec::new();
    {
        let env = thread.global_env().get_env();
        let prelude = env.globals.get("std.prelude").unwrap();
        prelude
            .serialize_state(
                &mut bincode::Serializer::new(&mut serialized_prelude),
                &SeSeed::new(),
            )
            .unwrap();
    }
    b.iter(|| {
        use gluon::compiler_pipeline::{Executable, Precompiled};

        let mut deserializer = bincode::Deserializer::new(
            bincode::read_types::SliceReader::new(&serialized_prelude),
            bincode::Infinite,
        );
        let result = Precompiled(&mut deserializer)
            .run_expr(&mut Compiler::new(), &*thread, "std.prelude", "", ())
            .wait()
            .unwrap();
        black_box(result)
    })
}

fn source_prelude(b: &mut Bencher) {
    let mut prelude_source = String::new();
    File::open("std/prelude.glu")
        .and_then(|mut f| f.read_to_string(&mut prelude_source))
        .unwrap();
    let thread = new_vm();

    b.iter(|| {
        use gluon::compiler_pipeline::Executable;

        let result = prelude_source
            .run_expr(
                &mut Compiler::new(),
                &*thread,
                "std.prelude",
                &prelude_source,
                None,
            )
            .wait()
            .unwrap();
        black_box(result)
    })
}

benchmark_group!(precompiled, precompiled_prelude, source_prelude);
benchmark_main!(precompiled);
<|endoftext|>


<commit_before>#[derive(Debug, Clone)]
struct Tree {
    enter: Node,
    left: Option<Box<Tree>>,
    right: Option<Box<Tree>>,
}

//for red-black tree
#[derive(Debug, Clone)]
enum Color {
    Black,
    Red,
    White,
}

#[derive(Debug, Clone)]
struct Node {
    val: i32,
    color: Color,
}

impl Node {
    fn new(v: &i32) -> Node {
        Node {
            val: *v,
            color: Color::White,
        }
    }
}

type ReTr<'a> = Result<&'a mut Tree, String>;

impl Tree {
    fn new(v: &i32) -> Tree {
        Tree {
            enter: Node::new(v),
            left: None,
            right: None,
        }
    }

    fn insert(&mut self, v: &i32) {
        let target = if *v > self.enter.val {
            &mut self.right
        } else {
            &mut self.left
        };
        //println!("target is -> {:?}", target);
        match target {
            Some(next) => {
                //println!("next is -> {:?}", &next);
                next.insert(v)
            }
            None => {
                let new_node = Node::new(v);
                let new_tree = Tree {
                    enter: new_node,
                    left: None,
                    right: None,
                };
                *target = Some(Box::new(new_tree));
            }
        }
    }

    fn look_up_recursive(&mut self, v: &i32) -> Result<&mut Self, String> {
        if *v == self.enter.val {
            return Ok(self);
        } else if *v > self.enter.val {
            if let Some(_) = self.right {
                let next = self.right.as_mut().unwrap();
                return next.look_up(v);
            } else {
                Err("not find".to_string())
            }
        } else {
            if let Some(_) = self.left {
                let next = self.left.as_mut().unwrap();
                return next.look_up(v);
            } else {
                Err("not find".to_string())
            }
        }
    }

    fn look_up(&mut self, v: &i32) -> ReTr {
        let mut this: &mut Self = self;
        loop {
            if *v == this.enter.val {
                return Ok(this);
            } else if *v > this.enter.val {
                if let None = this.right {
                    return Err("not find".to_string());
                }
                this = { this }.right.as_mut().unwrap();
            } else {
                if let None = this.left {
                    return Err("not find".to_string());
                }
                this = { this }.left.as_mut().unwrap();
            }
        }
    }

    fn look_up_father(&mut self, v: &i32) -> (ReTr, String) {
        let mut this: &mut Self = self;
        loop {
            if *v == this.right.as_ref().unwrap().enter.val {
                return (Ok(this), "right".to_string());
            } else if *v == this.left.as_ref().unwrap().enter.val {
                return (Ok(this), "left".to_string());
            } else if *v > this.enter.val {
                if let None = this.right {
                    return (Err("not find".to_string()), "Error".to_string());
                }
                this = { this }.right.as_mut().unwrap();
            } else {
                if let None = this.left {
                    return (Err("not find".to_string()), "Error".to_string());
                }
                this = { this }.left.as_mut().unwrap();
            }
        }
    }

    fn cut_left_tree(&mut self) -> Option<Box<Self>> {
        self.left.clone()
    }

    fn cut_right_tree(&mut self) -> Option<Box<Self>> {
        self.right.clone()
    }

    fn left_shift(&mut self, v: &i32) {
        let father = self.look_up_father(v).0.unwrap();
        let mut this = father.cut_left_tree().unwrap();
        let mut son = this.cut_right_tree().unwrap();
        let grand_son = son.cut_left_tree().unwrap();

        this.right = Some(grand_son);
        son.left = Some(this);
        father.left = Some(son);
    }

    fn right_shift(&mut self, v: &i32) {
        let father = self.look_up_father(v).0.unwrap();
        let mut this = father.cut_right_tree().unwrap();
        let mut son = this.cut_left_tree().unwrap();
        let grand_son = son.cut_right_tree().unwrap();

        this.left = Some(grand_son);
        son.right = Some(this);
        father.right = Some(son);
    }
}

fn main() {
    //let mut a = Tree::new(&3);
    //a.insert(&2);
    //a.insert(&1);
    //a.insert(&4);
    //a.insert(&5);

    //println!("{:?}", a);
    //println!("{:?}", a.look_up(&1));
    //println!("{:?}", a.look_up_father(&4));
    //println!("{:?}", a);

    //let mut b = Tree::new(&10);
    //b.insert(&2);
    //b.insert(&1);
    //b.insert(&5);
    //b.insert(&3);
    //b.insert(&6);
    //b.insert(&11);

    //println!("{:?}", b);
    //println!("{:?}", b.look_up_father(&2));
    //b.left_shift(&2);
    //println!("{:?}", b);

    let mut c = Tree::new(&2);
    c.insert(&8);
    c.insert(&1);
    c.insert(&5);
    c.insert(&4);
    c.insert(&7);
    c.insert(&9);
    //println!("{:?}", c.look_up_father(&8));
    c.right_shift(&8);
    println!("{:?}", c);
}
<commit_msg>add color<commit_after>#[derive(Debug, Clone)]
struct Tree {
    enter: Node,
    left: Option<Box<Tree>>,
    right: Option<Box<Tree>>,
}

//for red-black tree
#[derive(Debug, Clone)]
enum Color {
    Black,
    Red,
    White,
}

#[derive(Debug, Clone)]
struct Node {
    val: i32,
    color: Color,
}

impl Node {
    fn new(v: &i32) -> Node {
        Node {
            val: *v,
            color: Color::White,
        }
    }

    fn make_black(&mut self) {
        self.color = Color::Black;
    }

    fn make_red(&mut self) {
        self.color = Color::Red;
    }
}

type ReTr<'a> = Result<&'a mut Tree, String>;

impl Tree {
    fn new(v: &i32) -> Tree {
        let mut root = Node::new(v);
        root.make_black();
        Tree {
            enter: root,
            left: None,
            right: None,
        }
    }

    fn insert(&mut self, v: &i32) {
        let target = if *v > self.enter.val {
            &mut self.right
        } else {
            &mut self.left
        };

        match target {
            Some(next) => next.insert(v),
            None => {
                let mut new_node = Node::new(v);
                new_node.make_red();
                let new_tree = Tree {
                    enter: new_node,
                    left: None,
                    right: None,
                };
                *target = Some(Box::new(new_tree));
            }
        }
    }

    fn look_up_recursive(&mut self, v: &i32) -> ReTr {
        if *v == self.enter.val {
            return Ok(self);
        } else if *v > self.enter.val {
            if let Some(_) = self.right {
                let next = self.right.as_mut().unwrap();
                return next.look_up(v);
            } else {
                Err("not find".to_string())
            }
        } else {
            if let Some(_) = self.left {
                let next = self.left.as_mut().unwrap();
                return next.look_up(v);
            } else {
                Err("not find".to_string())
            }
        }
    }

    fn look_up(&mut self, v: &i32) -> ReTr {
        let mut this: &mut Self = self;
        loop {
            if *v == this.enter.val {
                return Ok(this);
            } else if *v > this.enter.val {
                if let None = this.right {
                    return Err("not find".to_string());
                }
                this = { this }.right.as_mut().unwrap();
            } else {
                if let None = this.left {
                    return Err("not find".to_string());
                }
                this = { this }.left.as_mut().unwrap();
            }
        }
    }

    fn look_up_father(&mut self, v: &i32) -> (ReTr, String) {
        let mut this: &mut Self = self;
        loop {
            if *v == this.right.as_ref().unwrap().enter.val {
                return (Ok(this), "right".to_string());
            } else if *v == this.left.as_ref().unwrap().enter.val {
                return (Ok(this), "left".to_string());
            } else if *v > this.enter.val {
                if let None = this.right {
                    return (Err("not find".to_string()), "Error".to_string());
                }
                this = { this }.right.as_mut().unwrap();
            } else {
                if let None = this.left {
                    return (Err("not find".to_string()), "Error".to_string());
                }
                this = { this }.left.as_mut().unwrap();
            }
        }
    }

    fn cut_left_tree(&mut self) -> Option<Box<Self>> {
        self.left.clone()
    }

    fn cut_right_tree(&mut self) -> Option<Box<Self>> {
        self.right.clone()
    }

    fn left_shift(&mut self, v: &i32) {
        let father = self.look_up_father(v).0.unwrap();
        let mut this = father.cut_left_tree().unwrap();
        let mut son = this.cut_right_tree().unwrap();
        let grand_son = son.cut_left_tree().unwrap();

        this.right = Some(grand_son);
        son.left = Some(this);
        father.left = Some(son);
    }

    fn right_shift(&mut self, v: &i32) {
        let father = self.look_up_father(v).0.unwrap();
        let mut this = father.cut_right_tree().unwrap();
        let mut son = this.cut_left_tree().unwrap();
        let grand_son = son.cut_right_tree().unwrap();

        this.left = Some(grand_son);
        son.right = Some(this);
        father.right = Some(son);
    }
}

fn main() {
    //let mut a = Tree::new(&3);
    //a.insert(&2);
    //a.insert(&1);
    //a.insert(&4);
    //a.insert(&5);

    //println!("{:?}", a);
    //println!("{:?}", a.look_up(&1));
    //println!("{:?}", a.look_up_father(&4));
    //println!("{:?}", a);

    //let mut b = Tree::new(&10);
    //b.insert(&2);
    //b.insert(&1);
    //b.insert(&5);
    //b.insert(&3);
    //b.insert(&6);
    //b.insert(&11);

    //println!("{:?}", b);
    //println!("{:?}", b.look_up_father(&2));
    //b.left_shift(&2);
    //println!("{:?}", b);

    let mut c = Tree::new(&2);
    c.insert(&8);
    c.insert(&1);
    c.insert(&5);
    c.insert(&4);
    c.insert(&7);
    c.insert(&9);
    //println!("{:?}", c.look_up_father(&8));
    c.right_shift(&8);
    println!("{:?}", c);
}
<|endoftext|>