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

//! Composable iterator objects

use prelude::*;

pub trait Iterator<A> {
    /// Advance the iterator and return the next value. Return `None` when the end is reached.
    fn next(&mut self) -> Option<A>;
}

pub trait IteratorUtil<A> {
    fn zip<B, U: Iterator<B>>(self, other: U) -> ZipIterator<Self, U>;
    // FIXME: #5898: should be called map
    fn transform<'r, B>(self, f: &'r fn(A) -> B) -> MapIterator<'r, A, B, Self>;
    fn filter<'r>(self, predicate: &'r fn(&A) -> bool) -> FilterIterator<'r, A, Self>;
    fn enumerate(self) -> EnumerateIterator<Self>;
    fn skip_while<'r>(self, predicate: &'r fn(&A) -> bool) -> SkipWhileIterator<'r, A, Self>;
    fn take_while<'r>(self, predicate: &'r fn(&A) -> bool) -> TakeWhileIterator<'r, A, Self>;
    fn skip(self, n: uint) -> SkipIterator<Self>;
    fn take(self, n: uint) -> TakeIterator<Self>;
    fn advance(&mut self, f: &fn(A) -> bool);
}

impl<A, T: Iterator<A>> IteratorUtil<A> for T {
    #[inline(always)]
    fn zip<B, U: Iterator<B>>(self, other: U) -> ZipIterator<T, U> {
        ZipIterator{a: self, b: other}
    }

    // FIXME: #5898: should be called map
    #[inline(always)]
    fn transform<'r, B>(self, f: &'r fn(A) -> B) -> MapIterator<'r, A, B, T> {
        MapIterator{iter: self, f: f}
    }

    #[inline(always)]
    fn filter<'r>(self, predicate: &'r fn(&A) -> bool) -> FilterIterator<'r, A, T> {
        FilterIterator{iter: self, predicate: predicate}
    }

    #[inline(always)]
    fn enumerate(self) -> EnumerateIterator<T> {
        EnumerateIterator{iter: self, count: 0}
    }

    #[inline(always)]
    fn skip_while<'r>(self, predicate: &'r fn(&A) -> bool) -> SkipWhileIterator<'r, A, T> {
        SkipWhileIterator{iter: self, flag: false, predicate: predicate}
    }

    #[inline(always)]
    fn take_while<'r>(self, predicate: &'r fn(&A) -> bool) -> TakeWhileIterator<'r, A, T> {
        TakeWhileIterator{iter: self, flag: false, predicate: predicate}
    }

    #[inline(always)]
    fn skip(self, n: uint) -> SkipIterator<T> {
        SkipIterator{iter: self, n: n}
    }

    #[inline(always)]
    fn take(self, n: uint) -> TakeIterator<T> {
        TakeIterator{iter: self, n: n}
    }

    /// A shim implementing the `for` loop iteration protocol for iterator objects
    #[inline]
    fn advance(&mut self, f: &fn(A) -> bool) {
        loop {
            match self.next() {
                Some(x) => {
                    if !f(x) { return }
                }
                None => return
            }
        }
    }
}

pub struct ZipIterator<T, U> {
    priv a: T,
    priv b: U
}

impl<A, B, T: Iterator<A>, U: Iterator<B>> Iterator<(A, B)> for ZipIterator<T, U> {
    #[inline]
    fn next(&mut self) -> Option<(A, B)> {
        match (self.a.next(), self.b.next()) {
            (Some(x), Some(y)) => Some((x, y)),
            _ => None
        }
    }
}

pub struct MapIterator<'self, A, B, T> {
    priv iter: T,
    priv f: &'self fn(A) -> B
}

impl<'self, A, B, T: Iterator<A>> Iterator<B> for MapIterator<'self, A, B, T> {
    #[inline]
    fn next(&mut self) -> Option<B> {
        match self.iter.next() {
            Some(a) => Some((self.f)(a)),
            _ => None
        }
    }
}

pub struct FilterIterator<'self, A, T> {
    priv iter: T,
    priv predicate: &'self fn(&A) -> bool
}

impl<'self, A, T: Iterator<A>> Iterator<A> for FilterIterator<'self, A, T> {
    #[inline]
    fn next(&mut self) -> Option<A> {
        for self.iter.advance |x| {
            if (self.predicate)(&x) {
                return Some(x);
            } else {
                loop
            }
        }
        None
    }
}

pub struct EnumerateIterator<T> {
    priv iter: T,
    priv count: uint
}

impl<A, T: Iterator<A>> Iterator<(uint, A)> for EnumerateIterator<T> {
    #[inline]
    fn next(&mut self) -> Option<(uint, A)> {
        match self.iter.next() {
            Some(a) => {
                let ret = Some((self.count, a));
                self.count += 1;
                ret
            }
            _ => None
        }
    }
}

pub struct SkipWhileIterator<'self, A, T> {
    priv iter: T,
    priv flag: bool,
    priv predicate: &'self fn(&A) -> bool
}

impl<'self, A, T: Iterator<A>> Iterator<A> for SkipWhileIterator<'self, A, T> {
    #[inline]
    fn next(&mut self) -> Option<A> {
        let mut next = self.iter.next();
        if self.flag {
            next
        } else {
            loop {
                match next {
                    Some(x) => {
                        if (self.predicate)(&x) {
                            next = self.iter.next();
                            loop
                        } else {
                            self.flag = true;
                            return Some(x)
                        }
                    }
                    None => return None
                }
            }
        }
    }
}

pub struct TakeWhileIterator<'self, A, T> {
    priv iter: T,
    priv flag: bool,
    priv predicate: &'self fn(&A) -> bool
}

impl<'self, A, T: Iterator<A>> Iterator<A> for TakeWhileIterator<'self, A, T> {
    #[inline]
    fn next(&mut self) -> Option<A> {
        if self.flag {
            None
        } else {
            match self.iter.next() {
                Some(x) => {
                    if (self.predicate)(&x) {
                        Some(x)
                    } else {
                        self.flag = true;
                        None
                    }
                }
                None => None
            }
        }
    }
}

pub struct SkipIterator<T> {
    priv iter: T,
    priv n: uint
}

impl<A, T: Iterator<A>> Iterator<A> for SkipIterator<T> {
    #[inline]
    fn next(&mut self) -> Option<A> {
        let mut next = self.iter.next();
        if self.n == 0 {
            next
        } else {
            let n = self.n;
            for n.times {
                match next {
                    Some(_) => {
                        next = self.iter.next();
                        loop
                    }
                    None => {
                        self.n = 0;
                        return None
                    }
                }
            }
            self.n = 0;
            next
        }
    }
}

pub struct TakeIterator<T> {
    priv iter: T,
    priv n: uint
}

impl<A, T: Iterator<A>> Iterator<A> for TakeIterator<T> {
    #[inline]
    fn next(&mut self) -> Option<A> {
        let next = self.iter.next();
        if self.n != 0 {
            self.n -= 1;
            next
        } else {
            None
        }
    }
}

pub struct UnfoldrIterator<'self, A, St> {
    priv f: &'self fn(&mut St) -> Option<A>,
    priv state: St
}

pub impl<'self, A, St> UnfoldrIterator<'self, A, St> {
    #[inline]
    fn new(f: &'self fn(&mut St) -> Option<A>, initial_state: St) -> UnfoldrIterator<'self, A, St> {
        UnfoldrIterator {
            f: f,
            state: initial_state
        }
    }
}

impl<'self, A, St> Iterator<A> for UnfoldrIterator<'self, A, St> {
    #[inline]
    fn next(&mut self) -> Option<A> {
        (self.f)(&mut self.state)
    }
}

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

    #[test]
    fn test_iterator_enumerate() {
        let xs = [0u, 1, 2, 3, 4, 5];
        let mut it = xs.iter().enumerate();
        for it.advance |(i, &x): (uint, &uint)| {
            assert_eq!(i, x);
        }
    }

    #[test]
    fn test_iterator_take_while() {
        let xs = [0u, 1, 2, 3, 5, 13, 15, 16, 17, 19];
        let ys = [0u, 1, 2, 3, 5, 13];
        let mut it = xs.iter().take_while(|&x| *x < 15u);
        let mut i = 0;
        for it.advance |&x: &uint| {
            assert_eq!(x, ys[i]);
            i += 1;
        }
        assert_eq!(i, ys.len());
    }

    #[test]
    fn test_iterator_skip_while() {
        let xs = [0u, 1, 2, 3, 5, 13, 15, 16, 17, 19];
        let ys = [15, 16, 17, 19];
        let mut it = xs.iter().skip_while(|&x| *x < 15u);
        let mut i = 0;
        for it.advance |&x: &uint| {
            assert_eq!(x, ys[i]);
            i += 1;
        }
        assert_eq!(i, ys.len());
    }

    #[test]
    fn test_iterator_skip() {
        let xs = [0u, 1, 2, 3, 5, 13, 15, 16, 17, 19, 20, 30];
        let ys = [13, 15, 16, 17, 19, 20, 30];
        let mut it = xs.iter().skip(5);
        let mut i = 0;
        for it.advance |&x: &uint| {
            assert_eq!(x, ys[i]);
            i += 1;
        }
        assert_eq!(i, ys.len());
    }

    #[test]
    fn test_iterator_take() {
        let xs = [0u, 1, 2, 3, 5, 13, 15, 16, 17, 19];
        let ys = [0u, 1, 2, 3, 5];
        let mut it = xs.iter().take(5);
        let mut i = 0;
        for it.advance |&x: &uint| {
            assert_eq!(x, ys[i]);
            i += 1;
        }
        assert_eq!(i, ys.len());
    }

    #[test]
    fn test_unfoldr() {
        fn count(st: &mut uint) -> Option<uint> {
            if *st < 10 {
                let ret = Some(*st);
                *st += 1;
                ret
            } else {
                None
            }
        }

        let mut it = UnfoldrIterator::new(count, 0);
        let mut i = 0;
        for it.advance |counted| {
            assert_eq!(counted, i);
            i += 1;
        }
        assert_eq!(i, 10);
    }
}
<commit_msg>iterator: add a chain adaptor<commit_after>// Copyright 2013 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.

//! Composable iterator objects

use prelude::*;

pub trait Iterator<A> {
    /// Advance the iterator and return the next value. Return `None` when the end is reached.
    fn next(&mut self) -> Option<A>;
}

pub trait IteratorUtil<A> {
    fn chain(self, other: Self) -> ChainIterator<Self>;
    fn zip<B, U: Iterator<B>>(self, other: U) -> ZipIterator<Self, U>;
    // FIXME: #5898: should be called map
    fn transform<'r, B>(self, f: &'r fn(A) -> B) -> MapIterator<'r, A, B, Self>;
    fn filter<'r>(self, predicate: &'r fn(&A) -> bool) -> FilterIterator<'r, A, Self>;
    fn enumerate(self) -> EnumerateIterator<Self>;
    fn skip_while<'r>(self, predicate: &'r fn(&A) -> bool) -> SkipWhileIterator<'r, A, Self>;
    fn take_while<'r>(self, predicate: &'r fn(&A) -> bool) -> TakeWhileIterator<'r, A, Self>;
    fn skip(self, n: uint) -> SkipIterator<Self>;
    fn take(self, n: uint) -> TakeIterator<Self>;
    fn advance(&mut self, f: &fn(A) -> bool);
}

impl<A, T: Iterator<A>> IteratorUtil<A> for T {
    #[inline(always)]
    fn chain(self, other: T) -> ChainIterator<T> {
        ChainIterator{a: self, b: other, flag: false}
    }

    #[inline(always)]
    fn zip<B, U: Iterator<B>>(self, other: U) -> ZipIterator<T, U> {
        ZipIterator{a: self, b: other}
    }

    // FIXME: #5898: should be called map
    #[inline(always)]
    fn transform<'r, B>(self, f: &'r fn(A) -> B) -> MapIterator<'r, A, B, T> {
        MapIterator{iter: self, f: f}
    }

    #[inline(always)]
    fn filter<'r>(self, predicate: &'r fn(&A) -> bool) -> FilterIterator<'r, A, T> {
        FilterIterator{iter: self, predicate: predicate}
    }

    #[inline(always)]
    fn enumerate(self) -> EnumerateIterator<T> {
        EnumerateIterator{iter: self, count: 0}
    }

    #[inline(always)]
    fn skip_while<'r>(self, predicate: &'r fn(&A) -> bool) -> SkipWhileIterator<'r, A, T> {
        SkipWhileIterator{iter: self, flag: false, predicate: predicate}
    }

    #[inline(always)]
    fn take_while<'r>(self, predicate: &'r fn(&A) -> bool) -> TakeWhileIterator<'r, A, T> {
        TakeWhileIterator{iter: self, flag: false, predicate: predicate}
    }

    #[inline(always)]
    fn skip(self, n: uint) -> SkipIterator<T> {
        SkipIterator{iter: self, n: n}
    }

    #[inline(always)]
    fn take(self, n: uint) -> TakeIterator<T> {
        TakeIterator{iter: self, n: n}
    }

    /// A shim implementing the `for` loop iteration protocol for iterator objects
    #[inline]
    fn advance(&mut self, f: &fn(A) -> bool) {
        loop {
            match self.next() {
                Some(x) => {
                    if !f(x) { return }
                }
                None => return
            }
        }
    }
}

pub struct ChainIterator<T> {
    priv a: T,
    priv b: T,
    priv flag: bool
}

impl<A, T: Iterator<A>> Iterator<A> for ChainIterator<T> {
    #[inline]
    fn next(&mut self) -> Option<A> {
        if self.flag {
            self.b.next()
        } else {
            match self.a.next() {
                Some(x) => return Some(x),
                _ => ()
            }
            self.flag = true;
            self.b.next()
        }
    }
}

pub struct ZipIterator<T, U> {
    priv a: T,
    priv b: U
}

impl<A, B, T: Iterator<A>, U: Iterator<B>> Iterator<(A, B)> for ZipIterator<T, U> {
    #[inline]
    fn next(&mut self) -> Option<(A, B)> {
        match (self.a.next(), self.b.next()) {
            (Some(x), Some(y)) => Some((x, y)),
            _ => None
        }
    }
}

pub struct MapIterator<'self, A, B, T> {
    priv iter: T,
    priv f: &'self fn(A) -> B
}

impl<'self, A, B, T: Iterator<A>> Iterator<B> for MapIterator<'self, A, B, T> {
    #[inline]
    fn next(&mut self) -> Option<B> {
        match self.iter.next() {
            Some(a) => Some((self.f)(a)),
            _ => None
        }
    }
}

pub struct FilterIterator<'self, A, T> {
    priv iter: T,
    priv predicate: &'self fn(&A) -> bool
}

impl<'self, A, T: Iterator<A>> Iterator<A> for FilterIterator<'self, A, T> {
    #[inline]
    fn next(&mut self) -> Option<A> {
        for self.iter.advance |x| {
            if (self.predicate)(&x) {
                return Some(x);
            } else {
                loop
            }
        }
        None
    }
}

pub struct EnumerateIterator<T> {
    priv iter: T,
    priv count: uint
}

impl<A, T: Iterator<A>> Iterator<(uint, A)> for EnumerateIterator<T> {
    #[inline]
    fn next(&mut self) -> Option<(uint, A)> {
        match self.iter.next() {
            Some(a) => {
                let ret = Some((self.count, a));
                self.count += 1;
                ret
            }
            _ => None
        }
    }
}

pub struct SkipWhileIterator<'self, A, T> {
    priv iter: T,
    priv flag: bool,
    priv predicate: &'self fn(&A) -> bool
}

impl<'self, A, T: Iterator<A>> Iterator<A> for SkipWhileIterator<'self, A, T> {
    #[inline]
    fn next(&mut self) -> Option<A> {
        let mut next = self.iter.next();
        if self.flag {
            next
        } else {
            loop {
                match next {
                    Some(x) => {
                        if (self.predicate)(&x) {
                            next = self.iter.next();
                            loop
                        } else {
                            self.flag = true;
                            return Some(x)
                        }
                    }
                    None => return None
                }
            }
        }
    }
}

pub struct TakeWhileIterator<'self, A, T> {
    priv iter: T,
    priv flag: bool,
    priv predicate: &'self fn(&A) -> bool
}

impl<'self, A, T: Iterator<A>> Iterator<A> for TakeWhileIterator<'self, A, T> {
    #[inline]
    fn next(&mut self) -> Option<A> {
        if self.flag {
            None
        } else {
            match self.iter.next() {
                Some(x) => {
                    if (self.predicate)(&x) {
                        Some(x)
                    } else {
                        self.flag = true;
                        None
                    }
                }
                None => None
            }
        }
    }
}

pub struct SkipIterator<T> {
    priv iter: T,
    priv n: uint
}

impl<A, T: Iterator<A>> Iterator<A> for SkipIterator<T> {
    #[inline]
    fn next(&mut self) -> Option<A> {
        let mut next = self.iter.next();
        if self.n == 0 {
            next
        } else {
            let n = self.n;
            for n.times {
                match next {
                    Some(_) => {
                        next = self.iter.next();
                        loop
                    }
                    None => {
                        self.n = 0;
                        return None
                    }
                }
            }
            self.n = 0;
            next
        }
    }
}

pub struct TakeIterator<T> {
    priv iter: T,
    priv n: uint
}

impl<A, T: Iterator<A>> Iterator<A> for TakeIterator<T> {
    #[inline]
    fn next(&mut self) -> Option<A> {
        let next = self.iter.next();
        if self.n != 0 {
            self.n -= 1;
            next
        } else {
            None
        }
    }
}

pub struct UnfoldrIterator<'self, A, St> {
    priv f: &'self fn(&mut St) -> Option<A>,
    priv state: St
}

pub impl<'self, A, St> UnfoldrIterator<'self, A, St> {
    #[inline]
    fn new(f: &'self fn(&mut St) -> Option<A>, initial_state: St) -> UnfoldrIterator<'self, A, St> {
        UnfoldrIterator {
            f: f,
            state: initial_state
        }
    }
}

impl<'self, A, St> Iterator<A> for UnfoldrIterator<'self, A, St> {
    #[inline]
    fn next(&mut self) -> Option<A> {
        (self.f)(&mut self.state)
    }
}

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

    #[test]
    fn test_iterator_chain() {
        let xs = [0u, 1, 2, 3, 4, 5];
        let ys = [30, 40, 50, 60];
        let expected = [0, 1, 2, 3, 4, 5, 30, 40, 50, 60];
        let mut it = xs.iter().chain(ys.iter());
        let mut i = 0;
        for it.advance |&x: &uint| {
            assert_eq!(x, expected[i]);
            i += 1;
        }
        assert_eq!(i, expected.len());
    }

    #[test]
    fn test_iterator_enumerate() {
        let xs = [0u, 1, 2, 3, 4, 5];
        let mut it = xs.iter().enumerate();
        for it.advance |(i, &x): (uint, &uint)| {
            assert_eq!(i, x);
        }
    }

    #[test]
    fn test_iterator_take_while() {
        let xs = [0u, 1, 2, 3, 5, 13, 15, 16, 17, 19];
        let ys = [0u, 1, 2, 3, 5, 13];
        let mut it = xs.iter().take_while(|&x| *x < 15u);
        let mut i = 0;
        for it.advance |&x: &uint| {
            assert_eq!(x, ys[i]);
            i += 1;
        }
        assert_eq!(i, ys.len());
    }

    #[test]
    fn test_iterator_skip_while() {
        let xs = [0u, 1, 2, 3, 5, 13, 15, 16, 17, 19];
        let ys = [15, 16, 17, 19];
        let mut it = xs.iter().skip_while(|&x| *x < 15u);
        let mut i = 0;
        for it.advance |&x: &uint| {
            assert_eq!(x, ys[i]);
            i += 1;
        }
        assert_eq!(i, ys.len());
    }

    #[test]
    fn test_iterator_skip() {
        let xs = [0u, 1, 2, 3, 5, 13, 15, 16, 17, 19, 20, 30];
        let ys = [13, 15, 16, 17, 19, 20, 30];
        let mut it = xs.iter().skip(5);
        let mut i = 0;
        for it.advance |&x: &uint| {
            assert_eq!(x, ys[i]);
            i += 1;
        }
        assert_eq!(i, ys.len());
    }

    #[test]
    fn test_iterator_take() {
        let xs = [0u, 1, 2, 3, 5, 13, 15, 16, 17, 19];
        let ys = [0u, 1, 2, 3, 5];
        let mut it = xs.iter().take(5);
        let mut i = 0;
        for it.advance |&x: &uint| {
            assert_eq!(x, ys[i]);
            i += 1;
        }
        assert_eq!(i, ys.len());
    }

    #[test]
    fn test_unfoldr() {
        fn count(st: &mut uint) -> Option<uint> {
            if *st < 10 {
                let ret = Some(*st);
                *st += 1;
                ret
            } else {
                None
            }
        }

        let mut it = UnfoldrIterator::new(count, 0);
        let mut i = 0;
        for it.advance |counted| {
            assert_eq!(counted, i);
            i += 1;
        }
        assert_eq!(i, 10);
    }
}
<|endoftext|>


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

#![unstable(feature = "std_misc")]

use convert::{Into, From};
use cmp::{PartialEq, Eq, PartialOrd, Ord, Ordering};
use error::Error;
use fmt;
use io;
use iter::Iterator;
use libc;
use mem;
use ops::Deref;
use option::Option::{self, Some, None};
use result::Result::{self, Ok, Err};
use slice;
use string::String;
use vec::Vec;

/// A type representing an owned C-compatible string
///
/// This type serves the primary purpose of being able to safely generate a
/// C-compatible string from a Rust byte slice or vector. An instance of this
/// type is a static guarantee that the underlying bytes contain no interior 0
/// bytes and the final byte is 0.
///
/// A `CString` is created from either a byte slice or a byte vector. After
/// being created, a `CString` predominately inherits all of its methods from
/// the `Deref` implementation to `[libc::c_char]`. Note that the underlying
/// array is represented as an array of `libc::c_char` as opposed to `u8`. A
/// `u8` slice can be obtained with the `as_bytes` method.  Slices produced from
/// a `CString` do *not* contain the trailing nul terminator unless otherwise
/// specified.
///
/// # Examples
///
/// ```no_run
/// # #![feature(libc)]
/// # extern crate libc;
/// # fn main() {
/// use std::ffi::CString;
/// use libc;
///
/// extern {
///     fn my_printer(s: *const libc::c_char);
/// }
///
/// let to_print = &b"Hello, world!"[..];
/// let c_to_print = CString::new(to_print).unwrap();
/// unsafe {
///     my_printer(c_to_print.as_ptr());
/// }
/// # }
/// ```
#[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct CString {
    inner: Vec<u8>,
}

/// Representation of a borrowed C string.
///
/// This dynamically sized type is only safely constructed via a borrowed
/// version of an instance of `CString`. This type can be constructed from a raw
/// C string as well and represents a C string borrowed from another location.
///
/// Note that this structure is **not** `repr(C)` and is not recommended to be
/// placed in the signatures of FFI functions. Instead safe wrappers of FFI
/// functions may leverage the unsafe `from_ptr` constructor to provide a safe
/// interface to other consumers.
///
/// # Examples
///
/// Inspecting a foreign C string
///
/// ```no_run
/// # #![feature(libc)]
/// extern crate libc;
/// use std::ffi::CStr;
///
/// extern { fn my_string() -> *const libc::c_char; }
///
/// fn main() {
///     unsafe {
///         let slice = CStr::from_ptr(my_string());
///         println!("string length: {}", slice.to_bytes().len());
///     }
/// }
/// ```
///
/// Passing a Rust-originating C string
///
/// ```no_run
/// # #![feature(libc)]
/// extern crate libc;
/// use std::ffi::{CString, CStr};
///
/// fn work(data: &CStr) {
///     extern { fn work_with(data: *const libc::c_char); }
///
///     unsafe { work_with(data.as_ptr()) }
/// }
///
/// fn main() {
///     let s = CString::new("data data data data").unwrap();
///     work(&s);
/// }
/// ```
#[derive(Hash)]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct CStr {
    // FIXME: this should not be represented with a DST slice but rather with
    //        just a raw `libc::c_char` along with some form of marker to make
    //        this an unsized type. Essentially `sizeof(&CStr)` should be the
    //        same as `sizeof(&c_char)` but `CStr` should be an unsized type.
    inner: [libc::c_char]
}

/// An error returned from `CString::new` to indicate that a nul byte was found
/// in the vector provided.
#[derive(Clone, PartialEq, Debug)]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct NulError(usize, Vec<u8>);

impl CString {
    /// Creates a new C-compatible string from a container of bytes.
    ///
    /// This method will consume the provided data and use the underlying bytes
    /// to construct a new string, ensuring that there is a trailing 0 byte.
    ///
    /// # Examples
    ///
    /// ```no_run
    /// # #![feature(libc)]
    /// extern crate libc;
    /// use std::ffi::CString;
    ///
    /// extern { fn puts(s: *const libc::c_char); }
    ///
    /// fn main() {
    ///     let to_print = CString::new("Hello!").unwrap();
    ///     unsafe {
    ///         puts(to_print.as_ptr());
    ///     }
    /// }
    /// ```
    ///
    /// # Errors
    ///
    /// This function will return an error if the bytes yielded contain an
    /// internal 0 byte. The error returned will contain the bytes as well as
    /// the position of the nul byte.
    #[stable(feature = "rust1", since = "1.0.0")]
    pub fn new<T: Into<Vec<u8>>>(t: T) -> Result<CString, NulError> {
        let bytes = t.into();
        match bytes.iter().position(|x| *x == 0) {
            Some(i) => Err(NulError(i, bytes)),
            None => Ok(unsafe { CString::from_vec_unchecked(bytes) }),
        }
    }

    /// Creates a C-compatible string from a byte vector without checking for
    /// interior 0 bytes.
    ///
    /// This method is equivalent to `new` except that no runtime assertion
    /// is made that `v` contains no 0 bytes, and it requires an actual
    /// byte vector, not anything that can be converted to one with Into.
    #[stable(feature = "rust1", since = "1.0.0")]
    pub unsafe fn from_vec_unchecked(mut v: Vec<u8>) -> CString {
        v.push(0);
        CString { inner: v }
    }

    /// Returns the contents of this `CString` as a slice of bytes.
    ///
    /// The returned slice does **not** contain the trailing nul separator and
    /// it is guaranteed to not have any interior nul bytes.
    #[stable(feature = "rust1", since = "1.0.0")]
    pub fn as_bytes(&self) -> &[u8] {
        &self.inner[..self.inner.len() - 1]
    }

    /// Equivalent to the `as_bytes` function except that the returned slice
    /// includes the trailing nul byte.
    #[stable(feature = "rust1", since = "1.0.0")]
    pub fn as_bytes_with_nul(&self) -> &[u8] {
        &self.inner
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl Deref for CString {
    type Target = CStr;

    fn deref(&self) -> &CStr {
        unsafe { mem::transmute(self.as_bytes_with_nul()) }
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl fmt::Debug for CString {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Debug::fmt(&String::from_utf8_lossy(self.as_bytes()), f)
    }
}

impl NulError {
    /// Returns the position of the nul byte in the slice that was provided to
    /// `CString::new`.
    #[stable(feature = "rust1", since = "1.0.0")]
    pub fn nul_position(&self) -> usize { self.0 }

    /// Consumes this error, returning the underlying vector of bytes which
    /// generated the error in the first place.
    #[stable(feature = "rust1", since = "1.0.0")]
    pub fn into_vec(self) -> Vec<u8> { self.1 }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl Error for NulError {
    fn description(&self) -> &str { "nul byte found in data" }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl fmt::Display for NulError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "nul byte found in provided data at position: {}", self.0)
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl From<NulError> for io::Error {
    fn from(_: NulError) -> io::Error {
        io::Error::new(io::ErrorKind::InvalidInput,
                       "data provided contains a nul byte")
    }
}

impl CStr {
    /// Casts a raw C string to a safe C string wrapper.
    ///
    /// This function will cast the provided `ptr` to the `CStr` wrapper which
    /// allows inspection and interoperation of non-owned C strings. This method
    /// is unsafe for a number of reasons:
    ///
    /// * There is no guarantee to the validity of `ptr`
    /// * The returned lifetime is not guaranteed to be the actual lifetime of
    ///   `ptr`
    /// * There is no guarantee that the memory pointed to by `ptr` contains a
    ///   valid nul terminator byte at the end of the string.
    ///
    /// > **Note**: This operation is intended to be a 0-cost cast but it is
    /// > currently implemented with an up-front calculation of the length of
    /// > the string. This is not guaranteed to always be the case.
    ///
    /// # Examples
    ///
    /// ```no_run
    /// # #![feature(libc)]
    /// # extern crate libc;
    /// # fn main() {
    /// use std::ffi::CStr;
    /// use std::str;
    /// use libc;
    ///
    /// extern {
    ///     fn my_string() -> *const libc::c_char;
    /// }
    ///
    /// unsafe {
    ///     let slice = CStr::from_ptr(my_string());
    ///     println!("string returned: {}",
    ///              str::from_utf8(slice.to_bytes()).unwrap());
    /// }
    /// # }
    /// ```
    #[stable(feature = "rust1", since = "1.0.0")]
    pub unsafe fn from_ptr<'a>(ptr: *const libc::c_char) -> &'a CStr {
        let len = libc::strlen(ptr);
        mem::transmute(slice::from_raw_parts(ptr, len as usize + 1))
    }

    /// Returns the inner pointer to this C string.
    ///
    /// The returned pointer will be valid for as long as `self` is and points
    /// to a contiguous region of memory terminated with a 0 byte to represent
    /// the end of the string.
    #[stable(feature = "rust1", since = "1.0.0")]
    pub fn as_ptr(&self) -> *const libc::c_char {
        self.inner.as_ptr()
    }

    /// Converts this C string to a byte slice.
    ///
    /// This function will calculate the length of this string (which normally
    /// requires a linear amount of work to be done) and then return the
    /// resulting slice of `u8` elements.
    ///
    /// The returned slice will **not** contain the trailing nul that this C
    /// string has.
    ///
    /// > **Note**: This method is currently implemented as a 0-cost cast, but
    /// > it is planned to alter its definition in the future to perform the
    /// > length calculation whenever this method is called.
    #[stable(feature = "rust1", since = "1.0.0")]
    pub fn to_bytes(&self) -> &[u8] {
        let bytes = self.to_bytes_with_nul();
        &bytes[..bytes.len() - 1]
    }

    /// Converts this C string to a byte slice containing the trailing 0 byte.
    ///
    /// This function is the equivalent of `to_bytes` except that it will retain
    /// the trailing nul instead of chopping it off.
    ///
    /// > **Note**: This method is currently implemented as a 0-cost cast, but
    /// > it is planned to alter its definition in the future to perform the
    /// > length calculation whenever this method is called.
    #[stable(feature = "rust1", since = "1.0.0")]
    pub fn to_bytes_with_nul(&self) -> &[u8] {
        unsafe { mem::transmute::<&[libc::c_char], &[u8]>(&self.inner) }
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl PartialEq for CStr {
    fn eq(&self, other: &CStr) -> bool {
        self.to_bytes().eq(other.to_bytes())
    }
}
#[stable(feature = "rust1", since = "1.0.0")]
impl Eq for CStr {}
#[stable(feature = "rust1", since = "1.0.0")]
impl PartialOrd for CStr {
    fn partial_cmp(&self, other: &CStr) -> Option<Ordering> {
        self.to_bytes().partial_cmp(&other.to_bytes())
    }
}
#[stable(feature = "rust1", since = "1.0.0")]
impl Ord for CStr {
    fn cmp(&self, other: &CStr) -> Ordering {
        self.to_bytes().cmp(&other.to_bytes())
    }
}

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

    #[test]
    fn c_to_rust() {
        let data = b"123\0";
        let ptr = data.as_ptr() as *const libc::c_char;
        unsafe {
            assert_eq!(CStr::from_ptr(ptr).to_bytes(), b"123");
            assert_eq!(CStr::from_ptr(ptr).to_bytes_with_nul(), b"123\0");
        }
    }

    #[test]
    fn simple() {
        let s = CString::new("1234").unwrap();
        assert_eq!(s.as_bytes(), b"1234");
        assert_eq!(s.as_bytes_with_nul(), b"1234\0");
    }

    #[test]
    fn build_with_zero1() {
        assert!(CString::new(&b"\0"[..]).is_err());
    }
    #[test]
    fn build_with_zero2() {
        assert!(CString::new(vec![0]).is_err());
    }

    #[test]
    fn build_with_zero3() {
        unsafe {
            let s = CString::from_vec_unchecked(vec![0]);
            assert_eq!(s.as_bytes(), b"\0");
        }
    }

    #[test]
    fn formatted() {
        let s = CString::new(&b"12"[..]).unwrap();
        assert_eq!(format!("{:?}", s), "\"12\"");
    }

    #[test]
    fn borrowed() {
        unsafe {
            let s = CStr::from_ptr(b"12\0".as_ptr() as *const _);
            assert_eq!(s.to_bytes(), b"12");
            assert_eq!(s.to_bytes_with_nul(), b"12\0");
        }
    }
}
<commit_msg>Rollup merge of #25516 - bstrie:cstrdoc, r=alexcrichton<commit_after>// Copyright 2012 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.

#![unstable(feature = "std_misc")]

use convert::{Into, From};
use cmp::{PartialEq, Eq, PartialOrd, Ord, Ordering};
use error::Error;
use fmt;
use io;
use iter::Iterator;
use libc;
use mem;
use ops::Deref;
use option::Option::{self, Some, None};
use result::Result::{self, Ok, Err};
use slice;
use string::String;
use vec::Vec;

/// A type representing an owned C-compatible string
///
/// This type serves the primary purpose of being able to safely generate a
/// C-compatible string from a Rust byte slice or vector. An instance of this
/// type is a static guarantee that the underlying bytes contain no interior 0
/// bytes and the final byte is 0.
///
/// A `CString` is created from either a byte slice or a byte vector. After
/// being created, a `CString` predominately inherits all of its methods from
/// the `Deref` implementation to `[libc::c_char]`. Note that the underlying
/// array is represented as an array of `libc::c_char` as opposed to `u8`. A
/// `u8` slice can be obtained with the `as_bytes` method.  Slices produced from
/// a `CString` do *not* contain the trailing nul terminator unless otherwise
/// specified.
///
/// # Examples
///
/// ```no_run
/// # #![feature(libc)]
/// # extern crate libc;
/// # fn main() {
/// use std::ffi::CString;
/// use libc;
///
/// extern {
///     fn my_printer(s: *const libc::c_char);
/// }
///
/// let c_to_print = CString::new("Hello, world!").unwrap();
/// unsafe {
///     my_printer(c_to_print.as_ptr());
/// }
/// # }
/// ```
#[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct CString {
    inner: Vec<u8>,
}

/// Representation of a borrowed C string.
///
/// This dynamically sized type is only safely constructed via a borrowed
/// version of an instance of `CString`. This type can be constructed from a raw
/// C string as well and represents a C string borrowed from another location.
///
/// Note that this structure is **not** `repr(C)` and is not recommended to be
/// placed in the signatures of FFI functions. Instead safe wrappers of FFI
/// functions may leverage the unsafe `from_ptr` constructor to provide a safe
/// interface to other consumers.
///
/// # Examples
///
/// Inspecting a foreign C string
///
/// ```no_run
/// # #![feature(libc)]
/// extern crate libc;
/// use std::ffi::CStr;
///
/// extern { fn my_string() -> *const libc::c_char; }
///
/// fn main() {
///     unsafe {
///         let slice = CStr::from_ptr(my_string());
///         println!("string length: {}", slice.to_bytes().len());
///     }
/// }
/// ```
///
/// Passing a Rust-originating C string
///
/// ```no_run
/// # #![feature(libc)]
/// extern crate libc;
/// use std::ffi::{CString, CStr};
///
/// fn work(data: &CStr) {
///     extern { fn work_with(data: *const libc::c_char); }
///
///     unsafe { work_with(data.as_ptr()) }
/// }
///
/// fn main() {
///     let s = CString::new("data data data data").unwrap();
///     work(&s);
/// }
/// ```
#[derive(Hash)]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct CStr {
    // FIXME: this should not be represented with a DST slice but rather with
    //        just a raw `libc::c_char` along with some form of marker to make
    //        this an unsized type. Essentially `sizeof(&CStr)` should be the
    //        same as `sizeof(&c_char)` but `CStr` should be an unsized type.
    inner: [libc::c_char]
}

/// An error returned from `CString::new` to indicate that a nul byte was found
/// in the vector provided.
#[derive(Clone, PartialEq, Debug)]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct NulError(usize, Vec<u8>);

impl CString {
    /// Creates a new C-compatible string from a container of bytes.
    ///
    /// This method will consume the provided data and use the underlying bytes
    /// to construct a new string, ensuring that there is a trailing 0 byte.
    ///
    /// # Examples
    ///
    /// ```no_run
    /// # #![feature(libc)]
    /// extern crate libc;
    /// use std::ffi::CString;
    ///
    /// extern { fn puts(s: *const libc::c_char); }
    ///
    /// fn main() {
    ///     let to_print = CString::new("Hello!").unwrap();
    ///     unsafe {
    ///         puts(to_print.as_ptr());
    ///     }
    /// }
    /// ```
    ///
    /// # Errors
    ///
    /// This function will return an error if the bytes yielded contain an
    /// internal 0 byte. The error returned will contain the bytes as well as
    /// the position of the nul byte.
    #[stable(feature = "rust1", since = "1.0.0")]
    pub fn new<T: Into<Vec<u8>>>(t: T) -> Result<CString, NulError> {
        let bytes = t.into();
        match bytes.iter().position(|x| *x == 0) {
            Some(i) => Err(NulError(i, bytes)),
            None => Ok(unsafe { CString::from_vec_unchecked(bytes) }),
        }
    }

    /// Creates a C-compatible string from a byte vector without checking for
    /// interior 0 bytes.
    ///
    /// This method is equivalent to `new` except that no runtime assertion
    /// is made that `v` contains no 0 bytes, and it requires an actual
    /// byte vector, not anything that can be converted to one with Into.
    #[stable(feature = "rust1", since = "1.0.0")]
    pub unsafe fn from_vec_unchecked(mut v: Vec<u8>) -> CString {
        v.push(0);
        CString { inner: v }
    }

    /// Returns the contents of this `CString` as a slice of bytes.
    ///
    /// The returned slice does **not** contain the trailing nul separator and
    /// it is guaranteed to not have any interior nul bytes.
    #[stable(feature = "rust1", since = "1.0.0")]
    pub fn as_bytes(&self) -> &[u8] {
        &self.inner[..self.inner.len() - 1]
    }

    /// Equivalent to the `as_bytes` function except that the returned slice
    /// includes the trailing nul byte.
    #[stable(feature = "rust1", since = "1.0.0")]
    pub fn as_bytes_with_nul(&self) -> &[u8] {
        &self.inner
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl Deref for CString {
    type Target = CStr;

    fn deref(&self) -> &CStr {
        unsafe { mem::transmute(self.as_bytes_with_nul()) }
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl fmt::Debug for CString {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Debug::fmt(&String::from_utf8_lossy(self.as_bytes()), f)
    }
}

impl NulError {
    /// Returns the position of the nul byte in the slice that was provided to
    /// `CString::new`.
    #[stable(feature = "rust1", since = "1.0.0")]
    pub fn nul_position(&self) -> usize { self.0 }

    /// Consumes this error, returning the underlying vector of bytes which
    /// generated the error in the first place.
    #[stable(feature = "rust1", since = "1.0.0")]
    pub fn into_vec(self) -> Vec<u8> { self.1 }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl Error for NulError {
    fn description(&self) -> &str { "nul byte found in data" }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl fmt::Display for NulError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "nul byte found in provided data at position: {}", self.0)
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl From<NulError> for io::Error {
    fn from(_: NulError) -> io::Error {
        io::Error::new(io::ErrorKind::InvalidInput,
                       "data provided contains a nul byte")
    }
}

impl CStr {
    /// Casts a raw C string to a safe C string wrapper.
    ///
    /// This function will cast the provided `ptr` to the `CStr` wrapper which
    /// allows inspection and interoperation of non-owned C strings. This method
    /// is unsafe for a number of reasons:
    ///
    /// * There is no guarantee to the validity of `ptr`
    /// * The returned lifetime is not guaranteed to be the actual lifetime of
    ///   `ptr`
    /// * There is no guarantee that the memory pointed to by `ptr` contains a
    ///   valid nul terminator byte at the end of the string.
    ///
    /// > **Note**: This operation is intended to be a 0-cost cast but it is
    /// > currently implemented with an up-front calculation of the length of
    /// > the string. This is not guaranteed to always be the case.
    ///
    /// # Examples
    ///
    /// ```no_run
    /// # #![feature(libc)]
    /// # extern crate libc;
    /// # fn main() {
    /// use std::ffi::CStr;
    /// use std::str;
    /// use libc;
    ///
    /// extern {
    ///     fn my_string() -> *const libc::c_char;
    /// }
    ///
    /// unsafe {
    ///     let slice = CStr::from_ptr(my_string());
    ///     println!("string returned: {}",
    ///              str::from_utf8(slice.to_bytes()).unwrap());
    /// }
    /// # }
    /// ```
    #[stable(feature = "rust1", since = "1.0.0")]
    pub unsafe fn from_ptr<'a>(ptr: *const libc::c_char) -> &'a CStr {
        let len = libc::strlen(ptr);
        mem::transmute(slice::from_raw_parts(ptr, len as usize + 1))
    }

    /// Returns the inner pointer to this C string.
    ///
    /// The returned pointer will be valid for as long as `self` is and points
    /// to a contiguous region of memory terminated with a 0 byte to represent
    /// the end of the string.
    #[stable(feature = "rust1", since = "1.0.0")]
    pub fn as_ptr(&self) -> *const libc::c_char {
        self.inner.as_ptr()
    }

    /// Converts this C string to a byte slice.
    ///
    /// This function will calculate the length of this string (which normally
    /// requires a linear amount of work to be done) and then return the
    /// resulting slice of `u8` elements.
    ///
    /// The returned slice will **not** contain the trailing nul that this C
    /// string has.
    ///
    /// > **Note**: This method is currently implemented as a 0-cost cast, but
    /// > it is planned to alter its definition in the future to perform the
    /// > length calculation whenever this method is called.
    #[stable(feature = "rust1", since = "1.0.0")]
    pub fn to_bytes(&self) -> &[u8] {
        let bytes = self.to_bytes_with_nul();
        &bytes[..bytes.len() - 1]
    }

    /// Converts this C string to a byte slice containing the trailing 0 byte.
    ///
    /// This function is the equivalent of `to_bytes` except that it will retain
    /// the trailing nul instead of chopping it off.
    ///
    /// > **Note**: This method is currently implemented as a 0-cost cast, but
    /// > it is planned to alter its definition in the future to perform the
    /// > length calculation whenever this method is called.
    #[stable(feature = "rust1", since = "1.0.0")]
    pub fn to_bytes_with_nul(&self) -> &[u8] {
        unsafe { mem::transmute::<&[libc::c_char], &[u8]>(&self.inner) }
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl PartialEq for CStr {
    fn eq(&self, other: &CStr) -> bool {
        self.to_bytes().eq(other.to_bytes())
    }
}
#[stable(feature = "rust1", since = "1.0.0")]
impl Eq for CStr {}
#[stable(feature = "rust1", since = "1.0.0")]
impl PartialOrd for CStr {
    fn partial_cmp(&self, other: &CStr) -> Option<Ordering> {
        self.to_bytes().partial_cmp(&other.to_bytes())
    }
}
#[stable(feature = "rust1", since = "1.0.0")]
impl Ord for CStr {
    fn cmp(&self, other: &CStr) -> Ordering {
        self.to_bytes().cmp(&other.to_bytes())
    }
}

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

    #[test]
    fn c_to_rust() {
        let data = b"123\0";
        let ptr = data.as_ptr() as *const libc::c_char;
        unsafe {
            assert_eq!(CStr::from_ptr(ptr).to_bytes(), b"123");
            assert_eq!(CStr::from_ptr(ptr).to_bytes_with_nul(), b"123\0");
        }
    }

    #[test]
    fn simple() {
        let s = CString::new("1234").unwrap();
        assert_eq!(s.as_bytes(), b"1234");
        assert_eq!(s.as_bytes_with_nul(), b"1234\0");
    }

    #[test]
    fn build_with_zero1() {
        assert!(CString::new(&b"\0"[..]).is_err());
    }
    #[test]
    fn build_with_zero2() {
        assert!(CString::new(vec![0]).is_err());
    }

    #[test]
    fn build_with_zero3() {
        unsafe {
            let s = CString::from_vec_unchecked(vec![0]);
            assert_eq!(s.as_bytes(), b"\0");
        }
    }

    #[test]
    fn formatted() {
        let s = CString::new(&b"12"[..]).unwrap();
        assert_eq!(format!("{:?}", s), "\"12\"");
    }

    #[test]
    fn borrowed() {
        unsafe {
            let s = CStr::from_ptr(b"12\0".as_ptr() as *const _);
            assert_eq!(s.to_bytes(), b"12");
            assert_eq!(s.to_bytes_with_nul(), b"12\0");
        }
    }
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use command_line::command_line_init;
use interfaces::cef_app_t;
use types::{cef_main_args_t, cef_settings_t};
use window::init_window;

use browser;
use libc::{c_char, c_int, c_void};
use std::ffi;
use std::str;
use util::opts;

const MAX_RENDERING_THREADS: usize = 128;

//static HOME_URL: &'static str = "http://s27.postimg.org/vqbtrolyr/servo.jpg";

static CEF_API_HASH_UNIVERSAL: &'static [u8] = b"8efd129f4afc344bd04b2feb7f73a149b6c4e27f\0";
#[cfg(target_os="windows")]
static CEF_API_HASH_PLATFORM: &'static [u8] = b"5c7f3e50ff5265985d11dc1a466513e25748bedd\0";
#[cfg(target_os="macos")]
static CEF_API_HASH_PLATFORM: &'static [u8] = b"6813214accbf2ebfb6bdcf8d00654650b251bf3d\0";
#[cfg(target_os="linux")]
static CEF_API_HASH_PLATFORM: &'static [u8] = b"2bc564c3871965ef3a2531b528bda3e17fa17a6d\0";

pub static mut CEF_APP: *mut cef_app_t = 0 as *mut cef_app_t;

#[no_mangle]
pub extern "C" fn cef_initialize(args: *const cef_main_args_t,
                                 settings: *mut cef_settings_t,
                                 application: *mut cef_app_t,
                                 _windows_sandbox_info: *const c_void)
                                 -> c_int {
    if args.is_null() {
        return 0;
    }
    unsafe {
        if !CEF_APP.is_null() {
            panic!("Attempting to call cef_initialize() multiple times!");
        }
    }

    unsafe {
        command_line_init((*args).argc, (*args).argv);

        if !application.is_null() {
            (*application).get_browser_process_handler.map(|cb| {
                    let handler = cb(application);
                    if !handler.is_null() {
                        (*handler).on_context_initialized.map(|hcb| hcb(handler));
                    }
            });
            CEF_APP = application;
        }
    }

    let rendering_threads = unsafe {
        if ((*settings).rendering_threads as usize) < 1 {
            1
        } else if (*settings).rendering_threads as usize > MAX_RENDERING_THREADS {
            MAX_RENDERING_THREADS
        } else {
            (*settings).rendering_threads as usize
        }
    };

    let mut temp_opts = opts::default_opts();
    temp_opts.paint_threads = rendering_threads;
    temp_opts.layout_threads = rendering_threads;
    temp_opts.headless = false;
    temp_opts.hard_fail = false;
    temp_opts.enable_text_antialiasing = true;
    temp_opts.enable_canvas_antialiasing = true;
    temp_opts.url = None;
    opts::set_defaults(temp_opts);

    if unsafe { (*settings).windowless_rendering_enabled != 0 } {
        init_window();
    }

    return 1
}

#[no_mangle]
pub extern "C" fn cef_shutdown() {
}

#[no_mangle]
pub extern "C" fn cef_run_message_loop() {
    // GWTODO: Support blocking message loop
    // again. Although, will it ever actually
    // be used or will everything use the
    // cef_do_message_loop_work function below
    // as our current miniservo apps do?
    unimplemented!()
}

#[no_mangle]
pub extern "C" fn cef_do_message_loop_work() {
    browser::update();
}

#[no_mangle]
pub extern "C" fn cef_quit_message_loop() {
}

#[no_mangle]
pub extern "C" fn cef_execute_process(_args: *const cef_main_args_t,
                                      _app: *mut cef_app_t,
                                      _windows_sandbox_info: *mut c_void)
                                      -> c_int {
    -1
}

#[no_mangle]
pub extern "C" fn cef_api_hash(entry: c_int) -> *const c_char {
    if entry == 0 {
        &CEF_API_HASH_PLATFORM[0] as *const u8 as *const c_char
    } else {
        &CEF_API_HASH_UNIVERSAL[0] as *const u8 as *const c_char
    }
}

#[no_mangle]
pub extern "C" fn cef_log(_file: *const c_char,
                          _line: c_int,
                          _severity: c_int,
                          message: *const c_char) {
    unsafe {
        let slice = ffi::CStr::from_ptr(message);
        println!("{}", str::from_utf8(slice.to_bytes()).unwrap())
    }
}

#[no_mangle]
pub extern "C" fn cef_get_min_log_level() -> c_int {
    0
}
<commit_msg>Remove `layout_threads` assignment from CEF<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use command_line::command_line_init;
use interfaces::cef_app_t;
use types::{cef_main_args_t, cef_settings_t};
use window::init_window;

use browser;
use libc::{c_char, c_int, c_void};
use std::ffi;
use std::str;
use util::opts;

const MAX_RENDERING_THREADS: usize = 128;

//static HOME_URL: &'static str = "http://s27.postimg.org/vqbtrolyr/servo.jpg";

static CEF_API_HASH_UNIVERSAL: &'static [u8] = b"8efd129f4afc344bd04b2feb7f73a149b6c4e27f\0";
#[cfg(target_os="windows")]
static CEF_API_HASH_PLATFORM: &'static [u8] = b"5c7f3e50ff5265985d11dc1a466513e25748bedd\0";
#[cfg(target_os="macos")]
static CEF_API_HASH_PLATFORM: &'static [u8] = b"6813214accbf2ebfb6bdcf8d00654650b251bf3d\0";
#[cfg(target_os="linux")]
static CEF_API_HASH_PLATFORM: &'static [u8] = b"2bc564c3871965ef3a2531b528bda3e17fa17a6d\0";

pub static mut CEF_APP: *mut cef_app_t = 0 as *mut cef_app_t;

#[no_mangle]
pub extern "C" fn cef_initialize(args: *const cef_main_args_t,
                                 settings: *mut cef_settings_t,
                                 application: *mut cef_app_t,
                                 _windows_sandbox_info: *const c_void)
                                 -> c_int {
    if args.is_null() {
        return 0;
    }
    unsafe {
        if !CEF_APP.is_null() {
            panic!("Attempting to call cef_initialize() multiple times!");
        }
    }

    unsafe {
        command_line_init((*args).argc, (*args).argv);

        if !application.is_null() {
            (*application).get_browser_process_handler.map(|cb| {
                    let handler = cb(application);
                    if !handler.is_null() {
                        (*handler).on_context_initialized.map(|hcb| hcb(handler));
                    }
            });
            CEF_APP = application;
        }
    }

    let rendering_threads = unsafe {
        if ((*settings).rendering_threads as usize) < 1 {
            1
        } else if (*settings).rendering_threads as usize > MAX_RENDERING_THREADS {
            MAX_RENDERING_THREADS
        } else {
            (*settings).rendering_threads as usize
        }
    };

    let mut temp_opts = opts::default_opts();
    temp_opts.paint_threads = rendering_threads;
    temp_opts.headless = false;
    temp_opts.hard_fail = false;
    temp_opts.enable_text_antialiasing = true;
    temp_opts.enable_canvas_antialiasing = true;
    temp_opts.url = None;
    opts::set_defaults(temp_opts);

    if unsafe { (*settings).windowless_rendering_enabled != 0 } {
        init_window();
    }

    return 1
}

#[no_mangle]
pub extern "C" fn cef_shutdown() {
}

#[no_mangle]
pub extern "C" fn cef_run_message_loop() {
    // GWTODO: Support blocking message loop
    // again. Although, will it ever actually
    // be used or will everything use the
    // cef_do_message_loop_work function below
    // as our current miniservo apps do?
    unimplemented!()
}

#[no_mangle]
pub extern "C" fn cef_do_message_loop_work() {
    browser::update();
}

#[no_mangle]
pub extern "C" fn cef_quit_message_loop() {
}

#[no_mangle]
pub extern "C" fn cef_execute_process(_args: *const cef_main_args_t,
                                      _app: *mut cef_app_t,
                                      _windows_sandbox_info: *mut c_void)
                                      -> c_int {
    -1
}

#[no_mangle]
pub extern "C" fn cef_api_hash(entry: c_int) -> *const c_char {
    if entry == 0 {
        &CEF_API_HASH_PLATFORM[0] as *const u8 as *const c_char
    } else {
        &CEF_API_HASH_UNIVERSAL[0] as *const u8 as *const c_char
    }
}

#[no_mangle]
pub extern "C" fn cef_log(_file: *const c_char,
                          _line: c_int,
                          _severity: c_int,
                          message: *const c_char) {
    unsafe {
        let slice = ffi::CStr::from_ptr(message);
        println!("{}", str::from_utf8(slice.to_bytes()).unwrap())
    }
}

#[no_mangle]
pub extern "C" fn cef_get_min_log_level() -> c_int {
    0
}
<|endoftext|>


<commit_before>use crate::future::poll_fn;
use crate::sync::semaphore_ll::{AcquireError, Permit, Semaphore};
use std::cell::UnsafeCell;
use std::ops;
use std::task::{Context, Poll};

#[cfg(not(loom))]
const MAX_READS: usize = 32;

#[cfg(loom)]
const MAX_READS: usize = 10;

/// An asynchronous reader-writer lock
///
/// This type of lock allows a number of readers or at most one writer at any
/// point in time. The write portion of this lock typically allows modification
/// of the underlying data (exclusive access) and the read portion of this lock
/// typically allows for read-only access (shared access).
///
/// In comparison, a [`Mutex`] does not distinguish between readers or writers
/// that acquire the lock, therefore blocking any tasks waiting for the lock to
/// become available. An `RwLock` will allow any number of readers to acquire the
/// lock as long as a writer is not holding the lock.
///
/// The priority policy of the lock is dependent on the underlying operating
/// system's implementation, and this type does not guarantee that any
/// particular policy will be used.
///
/// The type parameter `T` represents the data that this lock protects. It is
/// required that `T` satisfies [`Send`] to be shared across threads. The RAII guards
/// returned from the locking methods implement [`Deref`](https://doc.rust-lang.org/std/ops/trait.Deref.html)
/// (and [`DerefMut`](https://doc.rust-lang.org/std/ops/trait.DerefMut.html)
/// for the `write` methods) to allow access to the content of the lock.
///
/// # Examples
///
/// ```
/// use tokio::sync::RwLock;
///
/// #[tokio::main]
/// async fn main() {
///     let lock = RwLock::new(5);
///
/// // many reader locks can be held at once
///     {
///         let r1 = lock.read().await;
///         let r2 = lock.read().await;
///         assert_eq!(*r1, 5);
///         assert_eq!(*r2, 5);
///     } // read locks are dropped at this point
///
/// // only one write lock may be held, however
///     {
///         let mut w = lock.write().await;
///         *w += 1;
///         assert_eq!(*w, 6);
///     } // write lock is dropped here
/// }
/// ```
///
/// [`Mutex`]: struct.Mutex.html
/// [`RwLock`]: struct.RwLock.html
/// [`RwLockReadGuard`]: struct.RwLockReadGuard.html
/// [`RwLockWriteGuard`]: struct.RwLockWriteGuard.html
/// [`Send`]: https://doc.rust-lang.org/std/marker/trait.Send.html
#[derive(Debug)]
pub struct RwLock<T> {
    //semaphore to coordinate read and write access to T
    s: Semaphore,

    //inner data T
    c: UnsafeCell<T>,
}

/// RAII structure used to release the shared read access of a lock when
/// dropped.
///
/// This structure is created by the [`read`] method on
/// [`RwLock`].
///
/// [`read`]: struct.RwLock.html#method.read
#[derive(Debug)]
pub struct RwLockReadGuard<'a, T> {
    permit: ReleasingPermit<'a, T>,
    lock: &'a RwLock<T>,
}

/// RAII structure used to release the exclusive write access of a lock when
/// dropped.
///
/// This structure is created by the [`write`] and method
/// on [`RwLock`].
///
/// [`write`]: struct.RwLock.html#method.write
/// [`RwLock`]: struct.RwLock.html
#[derive(Debug)]
pub struct RwLockWriteGuard<'a, T> {
    permit: ReleasingPermit<'a, T>,
    lock: &'a RwLock<T>,
}

// Wrapper arround Permit that releases on Drop
#[derive(Debug)]
struct ReleasingPermit<'a, T> {
    num_permits: u16,
    permit: Permit,
    lock: &'a RwLock<T>,
}

impl<'a, T> ReleasingPermit<'a, T> {
    fn poll_acquire(
        &mut self,
        cx: &mut Context<'_>,
        s: &Semaphore,
    ) -> Poll<Result<(), AcquireError>> {
        self.permit.poll_acquire(cx, self.num_permits, s)
    }
}

impl<'a, T> Drop for ReleasingPermit<'a, T> {
    fn drop(&mut self) {
        self.permit.release(self.num_permits, &self.lock.s);
    }
}

// As long as T: Send + Sync, it's fine to send and share RwLock<T> between threads.
// If T were not Send, sending and sharing a RwLock<T> would be bad, since you can access T through
// RwLock<T>.
unsafe impl<T> Send for RwLock<T> where T: Send {}
unsafe impl<T> Sync for RwLock<T> where T: Send + Sync {}
unsafe impl<'a, T> Sync for RwLockReadGuard<'a, T> where T: Send + Sync {}
unsafe impl<'a, T> Sync for RwLockWriteGuard<'a, T> where T: Send + Sync {}

impl<T> RwLock<T> {
    /// Creates a new instance of an `RwLock<T>` which is unlocked.
    ///
    /// # Examples
    ///
    /// ```
    /// use tokio::sync::RwLock;
    ///
    /// let lock = RwLock::new(5);
    /// ```
    pub fn new(value: T) -> RwLock<T> {
        RwLock {
            c: UnsafeCell::new(value),
            s: Semaphore::new(MAX_READS),
        }
    }

    /// Locks this rwlock with shared read access, blocking the current task
    /// until it can be acquired.
    ///
    /// The calling task will be blocked until there are no more writers which
    /// hold the lock. There may be other readers currently inside the lock when
    /// this method returns.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::sync::Arc;
    /// use tokio::sync::RwLock;
    ///
    /// #[tokio::main]
    /// async fn main() {
    ///     let lock = Arc::new(RwLock::new(1));
    ///     let c_lock = lock.clone();
    ///
    ///     let n = lock.read().await;
    ///     assert_eq!(*n, 1);
    ///
    ///     tokio::spawn(async move {
    ///         let r = c_lock.read().await;
    ///         assert_eq!(*r, 1);
    ///     });
    ///}
    /// ```
    pub async fn read(&self) -> RwLockReadGuard<'_, T> {
        let mut permit = ReleasingPermit {
            num_permits: 1,
            permit: Permit::new(),
            lock: self,
        };

        poll_fn(|cx| permit.poll_acquire(cx, &self.s))
            .await
            .unwrap_or_else(|_| {
                // The semaphore was closed. but, we never explicitly close it, and we have a
                // handle to it through the Arc, which means that this can never happen.
                unreachable!()
            });
        RwLockReadGuard { lock: self, permit }
    }

    /// Locks this rwlock with exclusive write access, blocking the current
    /// task until it can be acquired.
    ///
    /// This function will not return while other writers or other readers
    /// currently have access to the lock.
    ///
    /// Returns an RAII guard which will drop the write access of this rwlock
    /// when dropped.
    ///
    /// # Examples
    ///
    /// ```
    /// use tokio::sync::RwLock;
    ///
    /// #[tokio::main]
    /// async fn main() {
    ///   let lock = RwLock::new(1);
    ///
    ///   let mut n = lock.write().await;
    ///   *n = 2;
    ///}
    /// ```
    pub async fn write(&self) -> RwLockWriteGuard<'_, T> {
        let mut permit = ReleasingPermit {
            num_permits: MAX_READS as u16,
            permit: Permit::new(),
            lock: self,
        };

        poll_fn(|cx| permit.poll_acquire(cx, &self.s))
            .await
            .unwrap_or_else(|_| {
                // The semaphore was closed. but, we never explicitly close it, and we have a
                // handle to it through the Arc, which means that this can never happen.
                unreachable!()
            });

        RwLockWriteGuard { lock: self, permit }
    }
}

impl<T> ops::Deref for RwLockReadGuard<'_, T> {
    type Target = T;

    fn deref(&self) -> &T {
        unsafe { &*self.lock.c.get() }
    }
}

impl<T> ops::Deref for RwLockWriteGuard<'_, T> {
    type Target = T;

    fn deref(&self) -> &T {
        unsafe { &*self.lock.c.get() }
    }
}

impl<T> ops::DerefMut for RwLockWriteGuard<'_, T> {
    fn deref_mut(&mut self) -> &mut T {
        unsafe { &mut *self.lock.c.get() }
    }
}
<commit_msg>sync: impl From<T> and Default for RwLock (#2089)<commit_after>use crate::future::poll_fn;
use crate::sync::semaphore_ll::{AcquireError, Permit, Semaphore};
use std::cell::UnsafeCell;
use std::ops;
use std::task::{Context, Poll};

#[cfg(not(loom))]
const MAX_READS: usize = 32;

#[cfg(loom)]
const MAX_READS: usize = 10;

/// An asynchronous reader-writer lock
///
/// This type of lock allows a number of readers or at most one writer at any
/// point in time. The write portion of this lock typically allows modification
/// of the underlying data (exclusive access) and the read portion of this lock
/// typically allows for read-only access (shared access).
///
/// In comparison, a [`Mutex`] does not distinguish between readers or writers
/// that acquire the lock, therefore blocking any tasks waiting for the lock to
/// become available. An `RwLock` will allow any number of readers to acquire the
/// lock as long as a writer is not holding the lock.
///
/// The priority policy of the lock is dependent on the underlying operating
/// system's implementation, and this type does not guarantee that any
/// particular policy will be used.
///
/// The type parameter `T` represents the data that this lock protects. It is
/// required that `T` satisfies [`Send`] to be shared across threads. The RAII guards
/// returned from the locking methods implement [`Deref`](https://doc.rust-lang.org/std/ops/trait.Deref.html)
/// (and [`DerefMut`](https://doc.rust-lang.org/std/ops/trait.DerefMut.html)
/// for the `write` methods) to allow access to the content of the lock.
///
/// # Examples
///
/// ```
/// use tokio::sync::RwLock;
///
/// #[tokio::main]
/// async fn main() {
///     let lock = RwLock::new(5);
///
/// // many reader locks can be held at once
///     {
///         let r1 = lock.read().await;
///         let r2 = lock.read().await;
///         assert_eq!(*r1, 5);
///         assert_eq!(*r2, 5);
///     } // read locks are dropped at this point
///
/// // only one write lock may be held, however
///     {
///         let mut w = lock.write().await;
///         *w += 1;
///         assert_eq!(*w, 6);
///     } // write lock is dropped here
/// }
/// ```
///
/// [`Mutex`]: struct.Mutex.html
/// [`RwLock`]: struct.RwLock.html
/// [`RwLockReadGuard`]: struct.RwLockReadGuard.html
/// [`RwLockWriteGuard`]: struct.RwLockWriteGuard.html
/// [`Send`]: https://doc.rust-lang.org/std/marker/trait.Send.html
#[derive(Debug)]
pub struct RwLock<T> {
    //semaphore to coordinate read and write access to T
    s: Semaphore,

    //inner data T
    c: UnsafeCell<T>,
}

/// RAII structure used to release the shared read access of a lock when
/// dropped.
///
/// This structure is created by the [`read`] method on
/// [`RwLock`].
///
/// [`read`]: struct.RwLock.html#method.read
#[derive(Debug)]
pub struct RwLockReadGuard<'a, T> {
    permit: ReleasingPermit<'a, T>,
    lock: &'a RwLock<T>,
}

/// RAII structure used to release the exclusive write access of a lock when
/// dropped.
///
/// This structure is created by the [`write`] and method
/// on [`RwLock`].
///
/// [`write`]: struct.RwLock.html#method.write
/// [`RwLock`]: struct.RwLock.html
#[derive(Debug)]
pub struct RwLockWriteGuard<'a, T> {
    permit: ReleasingPermit<'a, T>,
    lock: &'a RwLock<T>,
}

// Wrapper arround Permit that releases on Drop
#[derive(Debug)]
struct ReleasingPermit<'a, T> {
    num_permits: u16,
    permit: Permit,
    lock: &'a RwLock<T>,
}

impl<'a, T> ReleasingPermit<'a, T> {
    fn poll_acquire(
        &mut self,
        cx: &mut Context<'_>,
        s: &Semaphore,
    ) -> Poll<Result<(), AcquireError>> {
        self.permit.poll_acquire(cx, self.num_permits, s)
    }
}

impl<'a, T> Drop for ReleasingPermit<'a, T> {
    fn drop(&mut self) {
        self.permit.release(self.num_permits, &self.lock.s);
    }
}

// As long as T: Send + Sync, it's fine to send and share RwLock<T> between threads.
// If T were not Send, sending and sharing a RwLock<T> would be bad, since you can access T through
// RwLock<T>.
unsafe impl<T> Send for RwLock<T> where T: Send {}
unsafe impl<T> Sync for RwLock<T> where T: Send + Sync {}
unsafe impl<'a, T> Sync for RwLockReadGuard<'a, T> where T: Send + Sync {}
unsafe impl<'a, T> Sync for RwLockWriteGuard<'a, T> where T: Send + Sync {}

impl<T> RwLock<T> {
    /// Creates a new instance of an `RwLock<T>` which is unlocked.
    ///
    /// # Examples
    ///
    /// ```
    /// use tokio::sync::RwLock;
    ///
    /// let lock = RwLock::new(5);
    /// ```
    pub fn new(value: T) -> RwLock<T> {
        RwLock {
            c: UnsafeCell::new(value),
            s: Semaphore::new(MAX_READS),
        }
    }

    /// Locks this rwlock with shared read access, blocking the current task
    /// until it can be acquired.
    ///
    /// The calling task will be blocked until there are no more writers which
    /// hold the lock. There may be other readers currently inside the lock when
    /// this method returns.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::sync::Arc;
    /// use tokio::sync::RwLock;
    ///
    /// #[tokio::main]
    /// async fn main() {
    ///     let lock = Arc::new(RwLock::new(1));
    ///     let c_lock = lock.clone();
    ///
    ///     let n = lock.read().await;
    ///     assert_eq!(*n, 1);
    ///
    ///     tokio::spawn(async move {
    ///         let r = c_lock.read().await;
    ///         assert_eq!(*r, 1);
    ///     });
    ///}
    /// ```
    pub async fn read(&self) -> RwLockReadGuard<'_, T> {
        let mut permit = ReleasingPermit {
            num_permits: 1,
            permit: Permit::new(),
            lock: self,
        };

        poll_fn(|cx| permit.poll_acquire(cx, &self.s))
            .await
            .unwrap_or_else(|_| {
                // The semaphore was closed. but, we never explicitly close it, and we have a
                // handle to it through the Arc, which means that this can never happen.
                unreachable!()
            });
        RwLockReadGuard { lock: self, permit }
    }

    /// Locks this rwlock with exclusive write access, blocking the current
    /// task until it can be acquired.
    ///
    /// This function will not return while other writers or other readers
    /// currently have access to the lock.
    ///
    /// Returns an RAII guard which will drop the write access of this rwlock
    /// when dropped.
    ///
    /// # Examples
    ///
    /// ```
    /// use tokio::sync::RwLock;
    ///
    /// #[tokio::main]
    /// async fn main() {
    ///   let lock = RwLock::new(1);
    ///
    ///   let mut n = lock.write().await;
    ///   *n = 2;
    ///}
    /// ```
    pub async fn write(&self) -> RwLockWriteGuard<'_, T> {
        let mut permit = ReleasingPermit {
            num_permits: MAX_READS as u16,
            permit: Permit::new(),
            lock: self,
        };

        poll_fn(|cx| permit.poll_acquire(cx, &self.s))
            .await
            .unwrap_or_else(|_| {
                // The semaphore was closed. but, we never explicitly close it, and we have a
                // handle to it through the Arc, which means that this can never happen.
                unreachable!()
            });

        RwLockWriteGuard { lock: self, permit }
    }
}

impl<T> ops::Deref for RwLockReadGuard<'_, T> {
    type Target = T;

    fn deref(&self) -> &T {
        unsafe { &*self.lock.c.get() }
    }
}

impl<T> ops::Deref for RwLockWriteGuard<'_, T> {
    type Target = T;

    fn deref(&self) -> &T {
        unsafe { &*self.lock.c.get() }
    }
}

impl<T> ops::DerefMut for RwLockWriteGuard<'_, T> {
    fn deref_mut(&mut self) -> &mut T {
        unsafe { &mut *self.lock.c.get() }
    }
}

impl<T> From<T> for RwLock<T> {
    fn from(s: T) -> Self {
        Self::new(s)
    }
}

impl<T> Default for RwLock<T>
where
    T: Default,
{
    fn default() -> Self {
        Self::new(T::default())
    }
}
<|endoftext|>


<commit_before>use std::collections::HashMap;

pub struct Translator {
	rules: HashMap<(char, char), char>,
}

impl Translator {
	pub fn new() -> Translator {
		Translator{ rules: get_default_rules(), }
	}

	// Returns translated characted and boolean value indicating that previous character should be erased.
	fn translate_char(&self, current : char, previous : char) -> (char, bool) {
		match self.rules.get(&(current, previous)) {
			Some(result) => (*result, previous != ' '),
			None => match self.rules.get(&(current, ' ')) {
				Some(result) => (*result, false),
				None => (current, false),
			}
		}
	}

	pub fn translate(&self, text : &str) -> String {
		let mut result = String::with_capacity(text.len());

		let mut previous = ' ';
		for c in text.chars() {
			let (translated, erase_previous) = self.translate_char(c, previous);
			if erase_previous {
				result.pop();
			}

			result.push(translated);
			previous = translated;
		}

		result
	}
}

fn get_default_rules() -> HashMap<(char, char), char> {
	let mut result = HashMap::with_capacity(50);

	result.insert(('a', ' '), 'а');
	result.insert(('b', ' '), 'б');
	result.insert(('v', ' '), 'в');
	result.insert(('g', ' '), 'г');
	result.insert(('d', ' '), 'д');
	result.insert(('e', ' '), 'е');
	result.insert(('o', 'j'), 'ё');
	result.insert(('o', 'й'), 'ё');
	result.insert(('h', 'z'), 'ж');
	result.insert(('h', 'з'), 'ж');
	result.insert(('z', ' '), 'з');
	result.insert(('i', ' '), 'и');
	result.insert(('j', ' '), 'й');
	result.insert(('k', ' '), 'к');
	result.insert(('l', ' '), 'л');
	result.insert(('m', ' '), 'м');
	result.insert(('n', ' '), 'н');
	result.insert(('o', ' '), 'о');
	result.insert(('p', ' '), 'п');
	result.insert(('r', ' '), 'р');
	result.insert(('s', ' '), 'с');
	result.insert(('t', ' '), 'т');
	result.insert(('u', ' '), 'у');
	result.insert(('f', ' '), 'ф');
	result.insert(('h', ' '), 'х');
	result.insert(('x', ' '), 'х');
	result.insert(('c', ' '), 'ц');
	result.insert(('h', 'c'), 'ч');
	result.insert(('h', 'ц'), 'ч');
	result.insert(('h', 'h'), 'ш');
	result.insert(('h', 'с'), 'ш');
	result.insert(('h', 'ш'), 'щ');
	result.insert(('w', ' '), 'щ');
	result.insert(('#', ' '), 'ъ');
	result.insert(('y', ' '), 'ы');
	result.insert(('\'', ' '), 'ь');
	result.insert(('e', 'j'), 'э');
	result.insert(('e', 'й'), 'э');
	result.insert(('u', 'j'), 'ю');
	result.insert(('u', 'й'), 'ю');
	result.insert(('a', 'j'), 'я');
	result.insert(('a', 'й'), 'я');

	result.insert(('A', ' '), 'А');
	result.insert(('B', ' '), 'Б');
	result.insert(('V', ' '), 'В');
	result.insert(('G', ' '), 'Г');
	result.insert(('D', ' '), 'Д');
	result.insert(('E', ' '), 'Е');
	result.insert(('O', 'J'), 'Ё');
	result.insert(('O', 'Й'), 'Ё');
	result.insert(('H', 'Z'), 'Ж');
	result.insert(('H', 'З'), 'Ж');
	result.insert(('Z', ' '), 'З');
	result.insert(('I', ' '), 'И');
	result.insert(('J', ' '), 'Й');
	result.insert(('K', ' '), 'К');
	result.insert(('L', ' '), 'Л');
	result.insert(('M', ' '), 'М');
	result.insert(('N', ' '), 'Н');
	result.insert(('O', ' '), 'О');
	result.insert(('P', ' '), 'П');
	result.insert(('R', ' '), 'Р');
	result.insert(('S', ' '), 'С');
	result.insert(('T', ' '), 'Т');
	result.insert(('U', ' '), 'У');
	result.insert(('F', ' '), 'Ф');
	result.insert(('H', ' '), 'Х');
	result.insert(('X', ' '), 'Х');
	result.insert(('C', ' '), 'Ц');
	result.insert(('H', 'C'), 'Ч');
	result.insert(('H', 'Ц'), 'Ч');
	result.insert(('H', 'H'), 'Ш');
	result.insert(('H', 'С'), 'Ш');
	result.insert(('H', 'Ш'), 'Щ');
	result.insert(('W', ' '), 'Щ');
	result.insert(('#', 'ъ'), 'Ъ');
	result.insert(('Y', ' '), 'Ы');
	result.insert(('\'', 'ь'), 'Ь');
	result.insert(('E', 'J'), 'Э');
	result.insert(('E', 'Й'), 'Э');
	result.insert(('U', 'J'), 'Ю');
	result.insert(('U', 'Й'), 'Ю');
	result.insert(('A', 'J'), 'Я');
	result.insert(('A', 'Й'), 'Я');

	result
}

#[test]
fn translator_new() {
    let translator = Translator::new();
    assert_eq(Translator.rules, get_default_rules());
}
<commit_msg>translate_char refactoring<commit_after>use std::collections::HashMap;

pub struct Translator {
	rules: HashMap<(char, char), char>,
}

impl Translator {
	pub fn new() -> Translator {
		Translator{ rules: get_default_rules(), }
	}

	// Returns translated characted and boolean value indicating that previous character should be erased.
	fn translate_char(&self, current : char, previous : char) -> (char, bool) {
        if let Some(result) = self.rules.get(&(current, previous)) {
            return (*result, previous != ' ');
        }
        match self.rules.get(&(current, ' ')) {
            Some(result) => (*result, false),
            None => (current, false),
        }
	}

	pub fn translate(&self, text : &str) -> String {
		let mut result = String::with_capacity(text.len());

		let mut previous = ' ';
		for c in text.chars() {
			let (translated, erase_previous) = self.translate_char(c, previous);
			if erase_previous {
				result.pop();
			}

			result.push(translated);
			previous = translated;
		}

		result
	}
}

fn get_default_rules() -> HashMap<(char, char), char> {
	let mut result = HashMap::with_capacity(50);

	result.insert(('a', ' '), 'а');
	result.insert(('b', ' '), 'б');
	result.insert(('v', ' '), 'в');
	result.insert(('g', ' '), 'г');
	result.insert(('d', ' '), 'д');
	result.insert(('e', ' '), 'е');
	result.insert(('o', 'j'), 'ё');
	result.insert(('o', 'й'), 'ё');
	result.insert(('h', 'z'), 'ж');
	result.insert(('h', 'з'), 'ж');
	result.insert(('z', ' '), 'з');
	result.insert(('i', ' '), 'и');
	result.insert(('j', ' '), 'й');
	result.insert(('k', ' '), 'к');
	result.insert(('l', ' '), 'л');
	result.insert(('m', ' '), 'м');
	result.insert(('n', ' '), 'н');
	result.insert(('o', ' '), 'о');
	result.insert(('p', ' '), 'п');
	result.insert(('r', ' '), 'р');
	result.insert(('s', ' '), 'с');
	result.insert(('t', ' '), 'т');
	result.insert(('u', ' '), 'у');
	result.insert(('f', ' '), 'ф');
	result.insert(('h', ' '), 'х');
	result.insert(('x', ' '), 'х');
	result.insert(('c', ' '), 'ц');
	result.insert(('h', 'c'), 'ч');
	result.insert(('h', 'ц'), 'ч');
	result.insert(('h', 'h'), 'ш');
	result.insert(('h', 'с'), 'ш');
	result.insert(('h', 'ш'), 'щ');
	result.insert(('w', ' '), 'щ');
	result.insert(('#', ' '), 'ъ');
	result.insert(('y', ' '), 'ы');
	result.insert(('\'', ' '), 'ь');
	result.insert(('e', 'j'), 'э');
	result.insert(('e', 'й'), 'э');
	result.insert(('u', 'j'), 'ю');
	result.insert(('u', 'й'), 'ю');
	result.insert(('a', 'j'), 'я');
	result.insert(('a', 'й'), 'я');

	result.insert(('A', ' '), 'А');
	result.insert(('B', ' '), 'Б');
	result.insert(('V', ' '), 'В');
	result.insert(('G', ' '), 'Г');
	result.insert(('D', ' '), 'Д');
	result.insert(('E', ' '), 'Е');
	result.insert(('O', 'J'), 'Ё');
	result.insert(('O', 'Й'), 'Ё');
	result.insert(('H', 'Z'), 'Ж');
	result.insert(('H', 'З'), 'Ж');
	result.insert(('Z', ' '), 'З');
	result.insert(('I', ' '), 'И');
	result.insert(('J', ' '), 'Й');
	result.insert(('K', ' '), 'К');
	result.insert(('L', ' '), 'Л');
	result.insert(('M', ' '), 'М');
	result.insert(('N', ' '), 'Н');
	result.insert(('O', ' '), 'О');
	result.insert(('P', ' '), 'П');
	result.insert(('R', ' '), 'Р');
	result.insert(('S', ' '), 'С');
	result.insert(('T', ' '), 'Т');
	result.insert(('U', ' '), 'У');
	result.insert(('F', ' '), 'Ф');
	result.insert(('H', ' '), 'Х');
	result.insert(('X', ' '), 'Х');
	result.insert(('C', ' '), 'Ц');
	result.insert(('H', 'C'), 'Ч');
	result.insert(('H', 'Ц'), 'Ч');
	result.insert(('H', 'H'), 'Ш');
	result.insert(('H', 'С'), 'Ш');
	result.insert(('H', 'Ш'), 'Щ');
	result.insert(('W', ' '), 'Щ');
	result.insert(('#', 'ъ'), 'Ъ');
	result.insert(('Y', ' '), 'Ы');
	result.insert(('\'', 'ь'), 'Ь');
	result.insert(('E', 'J'), 'Э');
	result.insert(('E', 'Й'), 'Э');
	result.insert(('U', 'J'), 'Ю');
	result.insert(('U', 'Й'), 'Ю');
	result.insert(('A', 'J'), 'Я');
	result.insert(('A', 'Й'), 'Я');

	result
}

#[test]
fn translator_new() {
    let translator = Translator::new();
    assert_eq(Translator.rules, get_default_rules());
}
<|endoftext|>


<commit_before>use failure::ResultExt;
use org_varlink_resolver::{VarlinkClient, VarlinkClientInterface};
use serde_json::{from_slice, from_value, to_string};
use std::io::{self, copy, BufRead, Write};
use std::thread;
use varlink::{
    Call, Connection, ErrorKind, GetInterfaceDescriptionArgs, Reply, Request, Result, VarlinkStream,
};

pub fn handle<R, W>(mut client_reader: R, mut client_writer: W) -> Result<bool>
where
    R: BufRead + Send + Sync + 'static,
    W: Write + Send + Sync + 'static,
{
    let conn = Connection::new("unix:/run/org.varlink.resolver")?;
    let mut resolver = VarlinkClient::new(conn);

    let mut upgraded = false;
    let mut last_iface = String::new();
    let mut last_service_stream: Option<VarlinkStream> = None;
    let mut address = String::new();

    loop {
        if !upgraded {
            let mut buf = Vec::new();
            match client_reader.read_until(b'\0', &mut buf) {
                Ok(0) => break,
                Err(_e) => break,
                _ => {}
            }

            // pop the last zero byte
            buf.pop();

            let mut req: Request = from_slice(&buf).context(ErrorKind::SerdeJsonDe(
                String::from_utf8_lossy(&buf).to_string(),
            ))?;

            if req.method == "org.varlink.service.GetInfo" {
                req.method = "org.varlink.resolver.GetInfo".into();
            }

            let n: usize = match req.method.rfind('.') {
                None => {
                    let method: String = String::from(req.method.as_ref());
                    let mut call = Call::new(&mut client_writer, &req);
                    call.reply_interface_not_found(Some(method))?;
                    return Ok(false);
                }
                Some(x) => x,
            };

            let iface = {
                if req.method == "org.varlink.service.GetInterfaceDescription" {
                    let val = req.parameters.clone().unwrap_or_default();
                    let args: GetInterfaceDescriptionArgs = from_value(val)?;
                    args.interface.into()
                } else {
                    String::from(&req.method[..n])
                }
            };

            if iface != last_iface {
                if iface.eq("org.varlink.resolver") {
                    address = String::from("unix:/run/org.varlink.resolver");
                } else {
                    address = match resolver.resolve(iface.clone()).call() {
                        Ok(r) => r.address,
                        _ => {
                            let mut call = Call::new(&mut client_writer, &req);
                            call.reply_interface_not_found(Some(iface))?;
                            return Ok(false);
                        }
                    };
                }
                last_iface = iface.clone();
            }

            let mut stream = match VarlinkStream::connect(&address) {
                Ok((a, _)) => a,
                _ => {
                    let mut call = Call::new(&mut client_writer, &req);
                    call.reply_interface_not_found(Some(iface))?;
                    return Ok(false);
                }
            };

            let (service_reader, mut service_writer) = stream.split()?;
            last_service_stream = Some(stream);
            let mut service_bufreader = ::std::io::BufReader::new(service_reader);

            {
                let b = to_string(&req)? + "\0";

                service_writer.write_all(b.as_bytes())?;
                service_writer.flush()?;
            }

            loop {
                let mut buf = Vec::new();

                if service_bufreader.read_until(0, &mut buf)? == 0 {
                    break;
                }
                if buf.is_empty() {
                    return Err(ErrorKind::ConnectionClosed)?;
                }

                client_writer.write_all(&buf)?;
                client_writer.flush()?;

                buf.pop();

                let reply: Reply = from_slice(&buf).context(ErrorKind::SerdeJsonDe(
                    String::from_utf8_lossy(&buf).to_string(),
                ))?;

                upgraded = reply.upgraded.unwrap_or(false);

                if upgraded || !reply.continues.unwrap_or(false) {
                    break;
                }
            }
        } else {
            if let Some(ref mut service_stream) = last_service_stream {
                // Should copy back and forth, until someone disconnects.
                let (mut service_reader, mut service_writer) = service_stream.split()?;
                {
                    let copy1 =
                        thread::spawn(move || copy(&mut client_reader, &mut service_writer));
                    let copy2 =
                        thread::spawn(move || copy(&mut service_reader, &mut client_writer));
                    let r = copy1.join();
                    r.unwrap_or(Err(io::Error::from(io::ErrorKind::ConnectionAborted)))?;
                    let r = copy2.join();
                    r.unwrap_or(Err(io::Error::from(io::ErrorKind::ConnectionAborted)))?;
                }
                return Ok(true);
            }
        }
    }
    Ok(upgraded)
}

pub fn handle_connect<R, W>(
    address: &str,
    mut client_reader: R,
    mut client_writer: W,
) -> Result<bool>
where
    R: BufRead + Send + Sync + 'static,
    W: Write + Send + Sync + 'static,
{
    let mut upgraded = false;
    let mut last_iface = String::new();
    let (mut stream, _) = VarlinkStream::connect(&address)?;

    loop {
        if !upgraded {
            let (service_reader, mut service_writer) = stream.split()?;

            let mut buf = Vec::new();
            match client_reader.read_until(b'\0', &mut buf) {
                Ok(0) => break,
                Err(_e) => break,
                _ => {}
            }

            // pop the last zero byte
            buf.pop();

            let req: Request = from_slice(&buf).context(ErrorKind::SerdeJsonDe(
                String::from_utf8_lossy(&buf).to_string(),
            ))?;

            if req.oneway.unwrap_or(false) {
                continue;
            }
            let n: usize = match req.method.rfind('.') {
                None => {
                    let method: String = String::from(req.method.as_ref());
                    let mut call = Call::new(&mut client_writer, &req);
                    call.reply_interface_not_found(Some(method))?;
                    return Ok(false);
                }
                Some(x) => x,
            };

            let iface = String::from(&req.method[..n]);

            if iface != last_iface {
                last_iface = iface.clone();
            }

            {
                let b = to_string(&req)? + "\0";

                service_writer.write_all(b.as_bytes())?;
                service_writer.flush()?;
            }

            let mut service_bufreader = ::std::io::BufReader::new(service_reader);

            loop {
                let mut buf = Vec::new();

                if service_bufreader.read_until(0, &mut buf)? == 0 {
                    break;
                }
                if buf.is_empty() {
                    return Err(ErrorKind::ConnectionClosed)?;
                }

                client_writer.write_all(&buf)?;
                client_writer.flush()?;

                buf.pop();

                let reply: Reply = from_slice(&buf).context(ErrorKind::SerdeJsonDe(
                    String::from_utf8_lossy(&buf).to_string(),
                ))?;

                upgraded = reply.upgraded.unwrap_or(false);

                if upgraded || !reply.continues.unwrap_or(false) {
                    break;
                }
            }
        } else {
            let (mut service_reader, mut service_writer) = stream.split()?;

            // Should copy back and forth, until someone disconnects.
            {
                let copy1 = thread::spawn(move || copy(&mut client_reader, &mut service_writer));
                let copy2 = thread::spawn(move || copy(&mut service_reader, &mut client_writer));
                let r = copy1.join();
                r.unwrap_or(Err(io::Error::from(io::ErrorKind::ConnectionAborted)))?;
                let r = copy2.join();
                r.unwrap_or(Err(io::Error::from(io::ErrorKind::ConnectionAborted)))?;
            }
            return Ok(true);
        }
    }
    Ok(upgraded)
}
<commit_msg>varlink-cli: bridge: fixed oneway<commit_after>use failure::ResultExt;
use org_varlink_resolver::{VarlinkClient, VarlinkClientInterface};
use serde_json::{from_slice, from_value, to_string};
use std::io::{self, copy, BufRead, Write};
use std::thread;
use varlink::{
    Call, Connection, ErrorKind, GetInterfaceDescriptionArgs, Reply, Request, Result, VarlinkStream,
};

pub fn handle<R, W>(mut client_reader: R, mut client_writer: W) -> Result<bool>
where
    R: BufRead + Send + Sync + 'static,
    W: Write + Send + Sync + 'static,
{
    let conn = Connection::new("unix:/run/org.varlink.resolver")?;
    let mut resolver = VarlinkClient::new(conn);

    let mut upgraded = false;
    let mut last_iface = String::new();
    let mut last_service_stream: Option<VarlinkStream> = None;
    let mut address = String::new();

    loop {
        if !upgraded {
            let mut buf = Vec::new();
            match client_reader.read_until(b'\0', &mut buf) {
                Ok(0) => break,
                Err(_e) => break,
                _ => {}
            }

            // pop the last zero byte
            buf.pop();

            let mut req: Request = from_slice(&buf).context(ErrorKind::SerdeJsonDe(
                String::from_utf8_lossy(&buf).to_string(),
            ))?;

            if req.method == "org.varlink.service.GetInfo" {
                req.method = "org.varlink.resolver.GetInfo".into();
            }

            let n: usize = match req.method.rfind('.') {
                None => {
                    let method: String = String::from(req.method.as_ref());
                    let mut call = Call::new(&mut client_writer, &req);
                    call.reply_interface_not_found(Some(method))?;
                    return Ok(false);
                }
                Some(x) => x,
            };

            let iface = {
                if req.method == "org.varlink.service.GetInterfaceDescription" {
                    let val = req.parameters.clone().unwrap_or_default();
                    let args: GetInterfaceDescriptionArgs = from_value(val)?;
                    args.interface.into()
                } else {
                    String::from(&req.method[..n])
                }
            };

            if iface != last_iface {
                if iface.eq("org.varlink.resolver") {
                    address = String::from("unix:/run/org.varlink.resolver");
                } else {
                    address = match resolver.resolve(iface.clone()).call() {
                        Ok(r) => r.address,
                        _ => {
                            let mut call = Call::new(&mut client_writer, &req);
                            call.reply_interface_not_found(Some(iface))?;
                            return Ok(false);
                        }
                    };
                }
                last_iface = iface.clone();
            }

            let mut stream = match VarlinkStream::connect(&address) {
                Ok((a, _)) => a,
                _ => {
                    let mut call = Call::new(&mut client_writer, &req);
                    call.reply_interface_not_found(Some(iface))?;
                    return Ok(false);
                }
            };

            let (service_reader, mut service_writer) = stream.split()?;
            last_service_stream = Some(stream);
            let mut service_bufreader = ::std::io::BufReader::new(service_reader);

            {
                let b = to_string(&req)? + "\0";

                service_writer.write_all(b.as_bytes())?;
                service_writer.flush()?;
            }

            if req.oneway.unwrap_or(false) {
                continue;
            }

            loop {
                let mut buf = Vec::new();

                if service_bufreader.read_until(0, &mut buf)? == 0 {
                    break;
                }
                if buf.is_empty() {
                    return Err(ErrorKind::ConnectionClosed)?;
                }

                client_writer.write_all(&buf)?;
                client_writer.flush()?;

                buf.pop();

                let reply: Reply = from_slice(&buf).context(ErrorKind::SerdeJsonDe(
                    String::from_utf8_lossy(&buf).to_string(),
                ))?;

                upgraded = reply.upgraded.unwrap_or(false);

                if upgraded || (!reply.continues.unwrap_or(false)) {
                    break;
                }
            }
        } else {
            if let Some(ref mut service_stream) = last_service_stream {
                // Should copy back and forth, until someone disconnects.
                let (mut service_reader, mut service_writer) = service_stream.split()?;
                {
                    let copy1 =
                        thread::spawn(move || copy(&mut client_reader, &mut service_writer));
                    let copy2 =
                        thread::spawn(move || copy(&mut service_reader, &mut client_writer));
                    let r = copy1.join();
                    r.unwrap_or(Err(io::Error::from(io::ErrorKind::ConnectionAborted)))?;
                    let r = copy2.join();
                    r.unwrap_or(Err(io::Error::from(io::ErrorKind::ConnectionAborted)))?;
                }
                return Ok(true);
            }
        }
    }
    Ok(upgraded)
}

pub fn handle_connect<R, W>(
    address: &str,
    mut client_reader: R,
    mut client_writer: W,
) -> Result<bool>
where
    R: BufRead + Send + Sync + 'static,
    W: Write + Send + Sync + 'static,
{
    let mut upgraded = false;
    let mut last_iface = String::new();
    let (mut stream, _) = VarlinkStream::connect(&address)?;

    loop {
        if !upgraded {
            let (service_reader, mut service_writer) = stream.split()?;

            let mut buf = Vec::new();
            match client_reader.read_until(b'\0', &mut buf) {
                Ok(0) => break,
                Err(_e) => break,
                _ => {}
            }

            // pop the last zero byte
            buf.pop();

            let req: Request = from_slice(&buf).context(ErrorKind::SerdeJsonDe(
                String::from_utf8_lossy(&buf).to_string(),
            ))?;

            let n: usize = match req.method.rfind('.') {
                None => {
                    let method: String = String::from(req.method.as_ref());
                    let mut call = Call::new(&mut client_writer, &req);
                    call.reply_interface_not_found(Some(method))?;
                    return Ok(false);
                }
                Some(x) => x,
            };

            let iface = String::from(&req.method[..n]);

            if iface != last_iface {
                last_iface = iface.clone();
            }

            {
                let b = to_string(&req)? + "\0";

                service_writer.write_all(b.as_bytes())?;
                service_writer.flush()?;
            }

            if req.oneway.unwrap_or(false) {
                continue;
            }

            let mut service_bufreader = ::std::io::BufReader::new(service_reader);

            loop {
                let mut buf = Vec::new();

                if service_bufreader.read_until(0, &mut buf)? == 0 {
                    break;
                }
                if buf.is_empty() {
                    return Err(ErrorKind::ConnectionClosed)?;
                }

                client_writer.write_all(&buf)?;
                client_writer.flush()?;

                buf.pop();

                let reply: Reply = from_slice(&buf).context(ErrorKind::SerdeJsonDe(
                    String::from_utf8_lossy(&buf).to_string(),
                ))?;

                upgraded = reply.upgraded.unwrap_or(false);

                if upgraded || !reply.continues.unwrap_or(false) {
                    break;
                }
            }
        } else {
            let (mut service_reader, mut service_writer) = stream.split()?;

            // Should copy back and forth, until someone disconnects.
            {
                let copy1 = thread::spawn(move || copy(&mut client_reader, &mut service_writer));
                let copy2 = thread::spawn(move || copy(&mut service_reader, &mut client_writer));
                let r = copy1.join();
                r.unwrap_or(Err(io::Error::from(io::ErrorKind::ConnectionAborted)))?;
                let r = copy2.join();
                r.unwrap_or(Err(io::Error::from(io::ErrorKind::ConnectionAborted)))?;
            }
            return Ok(true);
        }
    }
    Ok(upgraded)
}
<|endoftext|>