<commit_before>use unix_socket::UnixStream;

use std::io::{Result, Read, Write};
use std::io::Error;
use std::io::ErrorKind::Other;

use parser::{LvmTextMap, TextMapOps, into_textmap};
use vg;
use parser;

const LVMETAD_PATH: &'static str = "/run/lvm/lvmetad.socket";

fn collect_response(stream: &mut UnixStream) -> Result<Vec<u8>> {
    let mut response = [0; 32];
    let mut v = Vec::new();

    loop {
        let bytes_read = try!(stream.read(&mut response));

        v.extend(&response[..bytes_read]);

        if v.ends_with(b"\n##\n") {
            // drop the end marker
            let len = v.len() - 4;
            v.truncate(len);
            return Ok(v);
        }
    }
}

pub fn _request(s: &[u8],
                token: Option<&[u8]>,
                stream: &mut UnixStream,
                args: Option<&[&[u8]]>) -> Result<Vec<u8>> {
    try!(stream.write_all(b"request = \""));
    try!(stream.write_all(s));
    try!(stream.write_all(b"\"\n"));

    if let Some(token) = token {
        try!(stream.write_all(b"token = \""));
        try!(stream.write_all(token));
        try!(stream.write_all(b"\"\n"));
        try!(stream.write_all(b"\n"));
    }

    if let Some(args) = args {
        for arg in args {
            try!(stream.write_all(arg));
            try!(stream.write_all(b"\n"));
        }
    }

    try!(stream.write_all(b"\n##\n"));

    collect_response(stream)
}

pub fn request(s: &[u8], args: Option<&[&[u8]]>) -> Result<LvmTextMap> {
    let err = || Error::new(Other, "response parsing error");
    let token = b"0";

    let mut stream = try!(UnixStream::connect(LVMETAD_PATH));

    let txt = try!(_request(s, Some(token), &mut stream, args));
    let mut response = try!(into_textmap(&txt));

    if try!(response.string_from_textmap("response").ok_or(err())) == "token_mismatch" {
        try!(_request(b"token_update", Some(token), &mut stream, None));
        response = try!(_request(s, Some(token), &mut stream, args)
            .and_then(|r| into_textmap(&r)));
    }

    if response.get("global_invalid").is_some() || response.get("vg_invalid").is_some() {
        return Err(Error::new(Other, "cached metadata flagged as invalid"));
    }

    if try!(response.string_from_textmap("response").ok_or(err())) != "OK" {
        let reason = match response.string_from_textmap("reason") {
            Some(x) => x,
            None => "no reason given",
        };
        return Err(Error::new(Other, reason));
    }

    response.remove("response");

    Ok(response)
}

pub fn vgs_from_lvmetad() -> Result<Vec<vg::VG>> {
    let err = || Error::new(Other, "response parsing error");
    let mut v = Vec::new();

    let vg_list = try!(request(b"vg_list", None));
    let vgs = try!(vg_list.textmap_from_textmap("volume_groups").ok_or(err()));

    for id in vgs.keys() {
        let name = try!(vgs.textmap_from_textmap(id)
                        .and_then(|val| val.string_from_textmap("name"))
                        .ok_or(err()));

        let mut option: Vec<u8> = Vec::new();
        option.extend(b"uuid = \"");
        option.extend(id.as_bytes());
        option.extend(b"\"");
        let options = vec!(&option[..]);

        let vg_info = try!(request(b"vg_lookup", Some(&options[..])));
        let md = try!(vg_info.textmap_from_textmap("metadata").ok_or(err()));

        let vg = parser::vg_from_textmap(&name, md).expect("didn't get vg!");

        v.push(vg);
    }

    Ok(v)
}

pub fn vg_update_lvmetad(map: &LvmTextMap) -> Result<()> {

    assert_eq!(map.len(), 1);

    let k = map.keys().next().unwrap();
    let v = map.textmap_from_textmap(k).unwrap();

    let mut option = Vec::new();
    option.extend(b"vgname = \"");
    option.extend(k.as_bytes());
    option.extend(b"\"");

    let mut option2 = Vec::new();
    option2.extend(b"metadata {");
    option2.extend(textmap_to_buf(v));
    option2.extend(b"}");

    let mut options: Vec<&[u8]> = Vec::new();

    options.push(&option);
    options.push(&option2);

    try!(request(b"vg_update", Some(options)));

    Ok(())
}
<commit_msg>lvmetad.rs cleanups<commit_after>use unix_socket::UnixStream;

use std::io::{Result, Read, Write};
use std::io::Error;
use std::io::ErrorKind::Other;

use std::collections::btree_map::BTreeMap;

use parser::{
    LvmTextMap,
    TextMapOps,
    buf_to_textmap,
    vg_from_textmap,
    textmap_to_buf,
    Entry,
};
use vg;

const LVMETAD_PATH: &'static str = "/run/lvm/lvmetad.socket";

fn collect_response(stream: &mut UnixStream) -> Result<Vec<u8>> {
    let mut response = [0; 32];
    let mut v = Vec::new();

    loop {
        let bytes_read = try!(stream.read(&mut response));

        v.extend(&response[..bytes_read]);

        if v.ends_with(b"\n##\n") {
            // drop the end marker
            let len = v.len() - 4;
            v.truncate(len);
            return Ok(v);
        }
    }
}

pub fn _request(s: &[u8],
                token: Option<&[u8]>,
                stream: &mut UnixStream,
                args: &Option<Vec<&[u8]>>) -> Result<Vec<u8>> {

    let mut v = Vec::new();
    v.extend(b"request = \"");
    v.extend(s);
    v.extend(b"\"\n");

    if let Some(token) = token {
        v.extend(b"token = \"filter:");
        v.extend(token);
        v.extend(b"\"\n");
    }

    if let &Some(ref args) = args {
        for arg in args {
            v.extend(arg.clone());
            v.extend(b"\n");
        }
    }

    try!(stream.write_all(&v));
    try!(stream.write_all(b"\n##\n"));

    collect_response(stream)
}

pub fn request(s: &[u8], args: Option<Vec<&[u8]>>) -> Result<LvmTextMap> {
    let err = || Error::new(Other, "response parsing error");
    let token = b"0";

    let mut stream = try!(UnixStream::connect(LVMETAD_PATH));

    let txt = try!(_request(s, Some(token), &mut stream, &args));
    let mut response = try!(buf_to_textmap(&txt));

    if try!(response.string_from_textmap("response").ok_or(err())) == "token_mismatch" {
        try!(_request(b"token_update", Some(token), &mut stream, &None));
        response = try!(_request(s, Some(token), &mut stream, &args)
            .and_then(|r| buf_to_textmap(&r)));
    }

    if response.get("global_invalid").is_some() || response.get("vg_invalid").is_some() {
        return Err(Error::new(Other, "cached metadata flagged as invalid"));
    }

    if try!(response.string_from_textmap("response").ok_or(err())) != "OK" {
        let reason = match response.string_from_textmap("reason") {
            Some(x) => x,
            None => "no reason given",
        };
        return Err(Error::new(Other, reason));
    }

    response.remove("response");

    Ok(response)
}

pub fn vgs_from_lvmetad() -> Result<Vec<vg::VG>> {
    let err = || Error::new(Other, "response parsing error");
    let mut v = Vec::new();

    let vg_list = try!(request(b"vg_list", None));
    let vgs = try!(vg_list.textmap_from_textmap("volume_groups").ok_or(err()));

    for id in vgs.keys() {
        let name = try!(vgs.textmap_from_textmap(id)
                        .and_then(|val| val.string_from_textmap("name"))
                        .ok_or(err()));

        let mut option: Vec<u8> = Vec::new();
        option.extend(b"uuid = \"");
        option.extend(id.as_bytes());
        option.extend(b"\"");
        let options = vec!(&option[..]);

        let vg_info = try!(request(b"vg_lookup", Some(options)));
        let md = try!(vg_info.textmap_from_textmap("metadata").ok_or(err()));

        let vg = vg_from_textmap(&name, md).expect("didn't get vg!");

        v.push(vg);
    }

    Ok(v)
}

pub fn vg_update_lvmetad(map: &LvmTextMap) -> Result<()> {

    assert_eq!(map.len(), 1);

    let k = map.keys().next().unwrap();
    let v = map.textmap_from_textmap(k).unwrap();

    let mut option = Vec::new();
    option.extend(b"vgname = \"");
    option.extend(k.as_bytes());
    option.extend(b"\"");

    let mut option2 = Vec::new();
    option2.extend(b"metadata {");
    option2.extend(textmap_to_buf(v));
    option2.extend(b"}");

    let mut options: Vec<&[u8]> = Vec::new();

    options.push(&option);
    options.push(&option2);

    try!(request(b"vg_update", Some(options)));

    Ok(())
}
<|endoftext|>


<commit_before>#[cfg(not(test))]
use crate::alloc::{self, Layout};
use crate::num::NonZeroUsize;
#[cfg(not(test))]
use crate::slice;
#[cfg(not(test))]
use crate::str;

use super::waitqueue::{
    try_lock_or_false, NotifiedTcs, SpinMutex, SpinMutexGuard, WaitQueue, WaitVariable,
};
use crate::mem;

pub struct RWLock {
    readers: SpinMutex<WaitVariable<Option<NonZeroUsize>>>,
    writer: SpinMutex<WaitVariable<bool>>,
}

// Below is to check at compile time, that RWLock has size of 128 bytes.
#[allow(dead_code)]
unsafe fn rw_lock_size_assert(r: RWLock) {
    mem::transmute::<RWLock, [u8; 128]>(r);
}

impl RWLock {
    pub const fn new() -> RWLock {
        RWLock {
            readers: SpinMutex::new(WaitVariable::new(None)),
            writer: SpinMutex::new(WaitVariable::new(false)),
        }
    }

    #[inline]
    pub unsafe fn read(&self) {
        let mut rguard = self.readers.lock();
        let wguard = self.writer.lock();
        if *wguard.lock_var() || !wguard.queue_empty() {
            // Another thread has or is waiting for the write lock, wait
            drop(wguard);
            WaitQueue::wait(rguard);
            // Another thread has passed the lock to us
        } else {
            // No waiting writers, acquire the read lock
            *rguard.lock_var_mut() =
                NonZeroUsize::new(rguard.lock_var().map_or(0, |n| n.get()) + 1);
        }
    }

    #[inline]
    pub unsafe fn try_read(&self) -> bool {
        let mut rguard = try_lock_or_false!(self.readers);
        let wguard = try_lock_or_false!(self.writer);
        if *wguard.lock_var() || !wguard.queue_empty() {
            // Another thread has or is waiting for the write lock
            false
        } else {
            // No waiting writers, acquire the read lock
            *rguard.lock_var_mut() =
                NonZeroUsize::new(rguard.lock_var().map_or(0, |n| n.get()) + 1);
            true
        }
    }

    #[inline]
    pub unsafe fn write(&self) {
        let rguard = self.readers.lock();
        let mut wguard = self.writer.lock();
        if *wguard.lock_var() || rguard.lock_var().is_some() {
            // Another thread has the lock, wait
            drop(rguard);
            WaitQueue::wait(wguard);
            // Another thread has passed the lock to us
        } else {
            // We are just now obtaining the lock
            *wguard.lock_var_mut() = true;
        }
    }

    #[inline]
    pub unsafe fn try_write(&self) -> bool {
        let rguard = try_lock_or_false!(self.readers);
        let mut wguard = try_lock_or_false!(self.writer);
        if *wguard.lock_var() || rguard.lock_var().is_some() {
            // Another thread has the lock
            false
        } else {
            // We are just now obtaining the lock
            *wguard.lock_var_mut() = true;
            true
        }
    }

    #[inline]
    unsafe fn __read_unlock(
        &self,
        mut rguard: SpinMutexGuard<WaitVariable<Option<NonZeroUsize>>>,
        wguard: SpinMutexGuard<WaitVariable<bool>>,
    ) {
        *rguard.lock_var_mut() = NonZeroUsize::new(rguard.lock_var().unwrap().get() - 1);
        if rguard.lock_var().is_some() {
            // There are other active readers
        } else {
            if let Ok(mut wguard) = WaitQueue::notify_one(wguard) {
                // A writer was waiting, pass the lock
                *wguard.lock_var_mut() = true;
            } else {
                // No writers were waiting, the lock is released
                assert!(rguard.queue_empty());
            }
        }
    }

    #[inline]
    pub unsafe fn read_unlock(&self) {
        let rguard = self.readers.lock();
        let wguard = self.writer.lock();
        self.__read_unlock(rguard, wguard);
    }

    #[inline]
    unsafe fn __write_unlock(
        &self,
        rguard: SpinMutexGuard<WaitVariable<Option<NonZeroUsize>>>,
        wguard: SpinMutexGuard<WaitVariable<bool>>,
    ) {
        if let Err(mut wguard) = WaitQueue::notify_one(wguard) {
            // No writers waiting, release the write lock
            *wguard.lock_var_mut() = false;
            if let Ok(mut rguard) = WaitQueue::notify_all(rguard) {
                // One or more readers were waiting, pass the lock to them
                if let NotifiedTcs::All { count } = rguard.notified_tcs() {
                    *rguard.lock_var_mut() = Some(count)
                } else {
                    unreachable!() // called notify_all
                }
            } else {
                // No readers waiting, the lock is released
            }
        } else {
            // There was a thread waiting for write, just pass the lock
        }
    }

    #[inline]
    pub unsafe fn write_unlock(&self) {
        let rguard = self.readers.lock();
        let wguard = self.writer.lock();
        self.__write_unlock(rguard, wguard);
    }

    // only used by __rust_rwlock_unlock below
    #[inline]
    #[cfg_attr(test, allow(dead_code))]
    unsafe fn unlock(&self) {
        let rguard = self.readers.lock();
        let wguard = self.writer.lock();
        if *wguard.lock_var() == true {
            self.__write_unlock(rguard, wguard);
        } else {
            self.__read_unlock(rguard, wguard);
        }
    }

    #[inline]
    pub unsafe fn destroy(&self) {}
}

#[cfg(not(test))]
const EINVAL: i32 = 22;

// used by libunwind port
#[cfg(not(test))]
#[no_mangle]
pub unsafe extern "C" fn __rust_rwlock_rdlock(p: *mut RWLock) -> i32 {
    if p.is_null() {
        return EINVAL;
    }
    (*p).read();
    return 0;
}

#[cfg(not(test))]
#[no_mangle]
pub unsafe extern "C" fn __rust_rwlock_wrlock(p: *mut RWLock) -> i32 {
    if p.is_null() {
        return EINVAL;
    }
    (*p).write();
    return 0;
}
#[cfg(not(test))]
#[no_mangle]
pub unsafe extern "C" fn __rust_rwlock_unlock(p: *mut RWLock) -> i32 {
    if p.is_null() {
        return EINVAL;
    }
    (*p).unlock();
    return 0;
}

// the following functions are also used by the libunwind port. They're
// included here to make sure parallel codegen and LTO don't mess things up.
#[cfg(not(test))]
#[no_mangle]
pub unsafe extern "C" fn __rust_print_err(m: *mut u8, s: i32) {
    if s < 0 {
        return;
    }
    let buf = slice::from_raw_parts(m as *const u8, s as _);
    if let Ok(s) = str::from_utf8(&buf[..buf.iter().position(|&b| b == 0).unwrap_or(buf.len())]) {
        eprint!("{}", s);
    }
}

#[cfg(not(test))]
#[no_mangle]
// NB. used by both libunwind and libpanic_abort
pub unsafe extern "C" fn __rust_abort() {
    crate::sys::abort_internal();
}

#[cfg(not(test))]
#[no_mangle]
pub unsafe extern "C" fn __rust_c_alloc(size: usize, align: usize) -> *mut u8 {
    alloc::alloc(Layout::from_size_align_unchecked(size, align))
}

#[cfg(not(test))]
#[no_mangle]
pub unsafe extern "C" fn __rust_c_dealloc(ptr: *mut u8, size: usize, align: usize) {
    alloc::dealloc(ptr, Layout::from_size_align_unchecked(size, align))
}

#[cfg(test)]
mod tests {
    use super::*;
    use core::array::FixedSizeArray;
    use crate::mem::{self, MaybeUninit};

    // Verify that the bytes of initialized RWLock are the same as in
    // libunwind. If they change, `src/UnwindRustSgx.h` in libunwind needs to
    // be changed too.
    #[test]
    fn test_c_rwlock_initializer() {
        const RWLOCK_INIT: &[u8] = &[
            0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
            0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
            0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
            0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
            0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
            0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
            0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
            0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
            0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
            0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
            0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
            0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
            0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
            0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
            0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
            0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
        ];

        #[inline(never)]
        fn zero_stack() {
            test::black_box(MaybeUninit::<[RWLock; 16]>::zeroed());
        }

        #[inline(never)]
        unsafe fn rwlock_new(init: &mut MaybeUninit<RWLock>) {
            init.set(RWLock::new());
        }

        unsafe {
            // try hard to make sure that the padding/unused bytes in RWLock
            // get initialized as 0. If the assertion below fails, that might
            // just be an issue with the test code and not with the value of
            // RWLOCK_INIT.
            zero_stack();
            let mut init = MaybeUninit::<RWLock>::zeroed();
            rwlock_new(&mut init);
            assert_eq!(
                mem::transmute::<_, [u8; 128]>(init.assume_init()).as_slice(),
                RWLOCK_INIT
            )
        };
    }
}
<commit_msg>Rollup merge of #59511 - jethrogb:jb/maybeinit-deprecated, r=Centril<commit_after>#[cfg(not(test))]
use crate::alloc::{self, Layout};
use crate::num::NonZeroUsize;
#[cfg(not(test))]
use crate::slice;
#[cfg(not(test))]
use crate::str;

use super::waitqueue::{
    try_lock_or_false, NotifiedTcs, SpinMutex, SpinMutexGuard, WaitQueue, WaitVariable,
};
use crate::mem;

pub struct RWLock {
    readers: SpinMutex<WaitVariable<Option<NonZeroUsize>>>,
    writer: SpinMutex<WaitVariable<bool>>,
}

// Below is to check at compile time, that RWLock has size of 128 bytes.
#[allow(dead_code)]
unsafe fn rw_lock_size_assert(r: RWLock) {
    mem::transmute::<RWLock, [u8; 128]>(r);
}

impl RWLock {
    pub const fn new() -> RWLock {
        RWLock {
            readers: SpinMutex::new(WaitVariable::new(None)),
            writer: SpinMutex::new(WaitVariable::new(false)),
        }
    }

    #[inline]
    pub unsafe fn read(&self) {
        let mut rguard = self.readers.lock();
        let wguard = self.writer.lock();
        if *wguard.lock_var() || !wguard.queue_empty() {
            // Another thread has or is waiting for the write lock, wait
            drop(wguard);
            WaitQueue::wait(rguard);
            // Another thread has passed the lock to us
        } else {
            // No waiting writers, acquire the read lock
            *rguard.lock_var_mut() =
                NonZeroUsize::new(rguard.lock_var().map_or(0, |n| n.get()) + 1);
        }
    }

    #[inline]
    pub unsafe fn try_read(&self) -> bool {
        let mut rguard = try_lock_or_false!(self.readers);
        let wguard = try_lock_or_false!(self.writer);
        if *wguard.lock_var() || !wguard.queue_empty() {
            // Another thread has or is waiting for the write lock
            false
        } else {
            // No waiting writers, acquire the read lock
            *rguard.lock_var_mut() =
                NonZeroUsize::new(rguard.lock_var().map_or(0, |n| n.get()) + 1);
            true
        }
    }

    #[inline]
    pub unsafe fn write(&self) {
        let rguard = self.readers.lock();
        let mut wguard = self.writer.lock();
        if *wguard.lock_var() || rguard.lock_var().is_some() {
            // Another thread has the lock, wait
            drop(rguard);
            WaitQueue::wait(wguard);
            // Another thread has passed the lock to us
        } else {
            // We are just now obtaining the lock
            *wguard.lock_var_mut() = true;
        }
    }

    #[inline]
    pub unsafe fn try_write(&self) -> bool {
        let rguard = try_lock_or_false!(self.readers);
        let mut wguard = try_lock_or_false!(self.writer);
        if *wguard.lock_var() || rguard.lock_var().is_some() {
            // Another thread has the lock
            false
        } else {
            // We are just now obtaining the lock
            *wguard.lock_var_mut() = true;
            true
        }
    }

    #[inline]
    unsafe fn __read_unlock(
        &self,
        mut rguard: SpinMutexGuard<WaitVariable<Option<NonZeroUsize>>>,
        wguard: SpinMutexGuard<WaitVariable<bool>>,
    ) {
        *rguard.lock_var_mut() = NonZeroUsize::new(rguard.lock_var().unwrap().get() - 1);
        if rguard.lock_var().is_some() {
            // There are other active readers
        } else {
            if let Ok(mut wguard) = WaitQueue::notify_one(wguard) {
                // A writer was waiting, pass the lock
                *wguard.lock_var_mut() = true;
            } else {
                // No writers were waiting, the lock is released
                assert!(rguard.queue_empty());
            }
        }
    }

    #[inline]
    pub unsafe fn read_unlock(&self) {
        let rguard = self.readers.lock();
        let wguard = self.writer.lock();
        self.__read_unlock(rguard, wguard);
    }

    #[inline]
    unsafe fn __write_unlock(
        &self,
        rguard: SpinMutexGuard<WaitVariable<Option<NonZeroUsize>>>,
        wguard: SpinMutexGuard<WaitVariable<bool>>,
    ) {
        if let Err(mut wguard) = WaitQueue::notify_one(wguard) {
            // No writers waiting, release the write lock
            *wguard.lock_var_mut() = false;
            if let Ok(mut rguard) = WaitQueue::notify_all(rguard) {
                // One or more readers were waiting, pass the lock to them
                if let NotifiedTcs::All { count } = rguard.notified_tcs() {
                    *rguard.lock_var_mut() = Some(count)
                } else {
                    unreachable!() // called notify_all
                }
            } else {
                // No readers waiting, the lock is released
            }
        } else {
            // There was a thread waiting for write, just pass the lock
        }
    }

    #[inline]
    pub unsafe fn write_unlock(&self) {
        let rguard = self.readers.lock();
        let wguard = self.writer.lock();
        self.__write_unlock(rguard, wguard);
    }

    // only used by __rust_rwlock_unlock below
    #[inline]
    #[cfg_attr(test, allow(dead_code))]
    unsafe fn unlock(&self) {
        let rguard = self.readers.lock();
        let wguard = self.writer.lock();
        if *wguard.lock_var() == true {
            self.__write_unlock(rguard, wguard);
        } else {
            self.__read_unlock(rguard, wguard);
        }
    }

    #[inline]
    pub unsafe fn destroy(&self) {}
}

#[cfg(not(test))]
const EINVAL: i32 = 22;

// used by libunwind port
#[cfg(not(test))]
#[no_mangle]
pub unsafe extern "C" fn __rust_rwlock_rdlock(p: *mut RWLock) -> i32 {
    if p.is_null() {
        return EINVAL;
    }
    (*p).read();
    return 0;
}

#[cfg(not(test))]
#[no_mangle]
pub unsafe extern "C" fn __rust_rwlock_wrlock(p: *mut RWLock) -> i32 {
    if p.is_null() {
        return EINVAL;
    }
    (*p).write();
    return 0;
}
#[cfg(not(test))]
#[no_mangle]
pub unsafe extern "C" fn __rust_rwlock_unlock(p: *mut RWLock) -> i32 {
    if p.is_null() {
        return EINVAL;
    }
    (*p).unlock();
    return 0;
}

// the following functions are also used by the libunwind port. They're
// included here to make sure parallel codegen and LTO don't mess things up.
#[cfg(not(test))]
#[no_mangle]
pub unsafe extern "C" fn __rust_print_err(m: *mut u8, s: i32) {
    if s < 0 {
        return;
    }
    let buf = slice::from_raw_parts(m as *const u8, s as _);
    if let Ok(s) = str::from_utf8(&buf[..buf.iter().position(|&b| b == 0).unwrap_or(buf.len())]) {
        eprint!("{}", s);
    }
}

#[cfg(not(test))]
#[no_mangle]
// NB. used by both libunwind and libpanic_abort
pub unsafe extern "C" fn __rust_abort() {
    crate::sys::abort_internal();
}

#[cfg(not(test))]
#[no_mangle]
pub unsafe extern "C" fn __rust_c_alloc(size: usize, align: usize) -> *mut u8 {
    alloc::alloc(Layout::from_size_align_unchecked(size, align))
}

#[cfg(not(test))]
#[no_mangle]
pub unsafe extern "C" fn __rust_c_dealloc(ptr: *mut u8, size: usize, align: usize) {
    alloc::dealloc(ptr, Layout::from_size_align_unchecked(size, align))
}

#[cfg(test)]
mod tests {
    use super::*;
    use core::array::FixedSizeArray;
    use crate::mem::{self, MaybeUninit};

    // Verify that the bytes of initialized RWLock are the same as in
    // libunwind. If they change, `src/UnwindRustSgx.h` in libunwind needs to
    // be changed too.
    #[test]
    fn test_c_rwlock_initializer() {
        const RWLOCK_INIT: &[u8] = &[
            0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
            0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
            0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
            0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
            0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
            0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
            0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
            0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
            0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
            0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
            0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
            0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
            0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
            0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
            0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
            0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
        ];

        #[inline(never)]
        fn zero_stack() {
            test::black_box(MaybeUninit::<[RWLock; 16]>::zeroed());
        }

        #[inline(never)]
        unsafe fn rwlock_new(init: &mut MaybeUninit<RWLock>) {
            init.write(RWLock::new());
        }

        unsafe {
            // try hard to make sure that the padding/unused bytes in RWLock
            // get initialized as 0. If the assertion below fails, that might
            // just be an issue with the test code and not with the value of
            // RWLOCK_INIT.
            zero_stack();
            let mut init = MaybeUninit::<RWLock>::zeroed();
            rwlock_new(&mut init);
            assert_eq!(
                mem::transmute::<_, [u8; 128]>(init.assume_init()).as_slice(),
                RWLOCK_INIT
            )
        };
    }
}
<|endoftext|>


<commit_before>use crate::io;
use crate::libc;
use crate::sys::cvt;

pub struct Stdin;
pub struct Stdout;
pub struct Stderr;

impl Stdin {
    pub fn new() -> io::Result<Stdin> {
        Ok(Stdin)
    }

    pub fn read(&self, data: &mut [u8]) -> io::Result<usize> {
        let amt = cvt(unsafe {
            libc::read(libc::STDIN_FILENO, data.as_mut_ptr() as *mut _, data.len())
        })?;
        Ok(amt as usize)
    }
}

impl Stdout {
    pub fn new() -> io::Result<Stdout> {
        Ok(Stdout)
    }

    pub fn write(&self, data: &[u8]) -> io::Result<usize> {
        let amt = cvt(unsafe {
            libc::write(libc::STDOUT_FILENO, data.as_ptr() as *const _, data.len())
        })?;
        Ok(amt as usize)
    }

    pub fn flush(&self) -> io::Result<()> {
        Ok(())
    }
}

impl Stderr {
    pub fn new() -> io::Result<Stderr> {
        Ok(Stderr)
    }

    pub fn write(&self, data: &[u8]) -> io::Result<usize> {
        let amt = cvt(unsafe {
            libc::write(libc::STDERR_FILENO, data.as_ptr() as *const _, data.len())
        })?;
        Ok(amt as usize)
    }

    pub fn flush(&self) -> io::Result<()> {
        Ok(())
    }
}

impl io::Write for Stderr {
    fn write(&mut self, data: &[u8]) -> io::Result<usize> {
        (&*self).write(data)
    }

    fn flush(&mut self) -> io::Result<()> {
        (&*self).flush()
    }
}

pub const STDIN_BUF_SIZE: usize = crate::sys_common::io::DEFAULT_BUF_SIZE;

pub fn is_ebadf(err: &io::Error) -> bool {
    err.raw_os_error() == Some(libc::__WASI_EBADF as i32)
}

pub fn panic_output() -> Option<impl io::Write> {
    Stderr::new().ok()
}
<commit_msg>wasi: Use raw syscalls for stdio<commit_after>use crate::io::{self, IoVec, IoVecMut};
use crate::libc;
use crate::mem::ManuallyDrop;
use crate::sys::fd::WasiFd;

pub struct Stdin;
pub struct Stdout;
pub struct Stderr;

impl Stdin {
    pub fn new() -> io::Result<Stdin> {
        Ok(Stdin)
    }

    pub fn read(&self, data: &mut [u8]) -> io::Result<usize> {
        ManuallyDrop::new(unsafe { WasiFd::from_raw(libc::STDIN_FILENO as u32) })
            .read(&mut [IoVecMut::new(data)])
    }
}

impl Stdout {
    pub fn new() -> io::Result<Stdout> {
        Ok(Stdout)
    }

    pub fn write(&self, data: &[u8]) -> io::Result<usize> {
        ManuallyDrop::new(unsafe { WasiFd::from_raw(libc::STDOUT_FILENO as u32) })
            .write(&[IoVec::new(data)])
    }

    pub fn flush(&self) -> io::Result<()> {
        Ok(())
    }
}

impl Stderr {
    pub fn new() -> io::Result<Stderr> {
        Ok(Stderr)
    }

    pub fn write(&self, data: &[u8]) -> io::Result<usize> {
        ManuallyDrop::new(unsafe { WasiFd::from_raw(libc::STDERR_FILENO as u32) })
            .write(&[IoVec::new(data)])
    }

    pub fn flush(&self) -> io::Result<()> {
        Ok(())
    }
}

impl io::Write for Stderr {
    fn write(&mut self, data: &[u8]) -> io::Result<usize> {
        (&*self).write(data)
    }

    fn flush(&mut self) -> io::Result<()> {
        (&*self).flush()
    }
}

pub const STDIN_BUF_SIZE: usize = crate::sys_common::io::DEFAULT_BUF_SIZE;

pub fn is_ebadf(err: &io::Error) -> bool {
    err.raw_os_error() == Some(libc::__WASI_EBADF as i32)
}

pub fn panic_output() -> Option<impl io::Write> {
    Stderr::new().ok()
}
<|endoftext|>


<commit_before>use std::iter::repeat;

fn sierpinski(order: usize) {
    let mut triangle = vec!["*".to_string()];
    for i in 0..order {
        let space = repeat(' ').take(2_usize.pow(i as u32)).collect::<String>();

        // save original state
        let mut d = triangle.clone();

        // extend existing lines
        d.iter_mut().for_each(|r| {
            let new_row = format!("{}{}{}", space, r, space);
            *r = new_row;
        });

        // add new lines
        triangle.iter().for_each(|r| {
            let new_row = format!("{}{}{}", r, " ", r);
            d.push(new_row);
        });

        triangle = d;
    }

    triangle.iter().for_each(|r| println!("{}", r));
}
fn main() {
    let order = std::env::args()
        .nth(1)
        .unwrap_or_else(|| "4".to_string())
        .parse::<usize>()
        .unwrap();

    sierpinski(order);
}

#[cfg(test)]
#[rustfmt::skip]
mod tests {
    use assert_cmd::Command;
    use indoc::indoc;

    #[test]
    fn test_outputs() {
        let mut cmd = Command::cargo_bin("sierpinski-triangle").unwrap();
        cmd.arg("2").assert().success().stdout(indoc! {"
            *
           * *
          *   *
         * * * *
        "});

        let mut cmd = Command::cargo_bin("sierpinski-triangle").unwrap();
        cmd.arg("3").assert().success().stdout(indoc! {"
                     *
                    * *
                   *   *
                  * * * *
                 *       *
                * *     * *
               *   *   *   *
              * * * * * * * *
        "});
    }
}
<commit_msg>Update tasks/sierpinski-triangle/src/main.rs<commit_after>use std::iter::repeat;

fn sierpinski(order: usize) {
    let mut triangle = vec!["*".to_string()];
    for i in 0..order {
        let space = repeat(' ').take(2_usize.pow(i as u32)).collect::<String>();

        // save original state
        let mut d = triangle.clone();

        // extend existing lines
        d.iter_mut().for_each(|r| {
            let new_row = format!("{}{}{}", space, r, space);
            *r = new_row;
        });

        // add new lines
        triangle.iter().for_each(|r| {
            let new_row = format!("{}{}{}", r, " ", r);
            d.push(new_row);
        });

        triangle = d;
    }

    triangle.iter().for_each(|r| println!("{}", r));
}
fn main() {
    let order = std::env::args()
        .nth(1)
        .unwrap_or_else(|| "4".to_string())
        .parse::<usize>()
        .unwrap();

    sierpinski(order);
}

#[cfg(test)]
#[rustfmt::skip]
mod tests {
    use assert_cmd::Command;
    use indoc::indoc;

    #[test]
    fn test_outputs() {
        let mut cmd = Command::cargo_bin("sierpinski-triangle").unwrap();
        cmd.arg("2").assert().success().stdout(indoc! {"
               *
              * *
             *   *
            * * * *
        "});

        let mut cmd = Command::cargo_bin("sierpinski-triangle").unwrap();
        cmd.arg("3").assert().success().stdout(indoc! {"
                     *
                    * *
                   *   *
                  * * * *
                 *       *
                * *     * *
               *   *   *   *
              * * * * * * * *
        "});
    }
}
<|endoftext|>


<commit_before>mod helpers;

use helpers::{ways, TestClient};

use std::cell::Cell;
use std::ffi::OsStr;
use std::rc::Rc;
use std::sync::{Arc, Mutex};
use std::time::Duration;

#[test]
fn client_sync_roundtrip() {
    let socket_name = "wayland-client-sync-roundtrip";

    let kill_switch = Arc::new(Mutex::new(false));
    let server_kill_switch = kill_switch.clone();

    let server_thread = ::std::thread::spawn(move || {
        let mut display = ways::Display::new();
        display.add_socket(Some(socket_name)).unwrap();

        loop {
            display.dispatch(Duration::from_millis(10), &mut ()).unwrap();
            display.flush_clients(&mut ());
            if *(server_kill_switch.lock().unwrap()) {
                break;
            }
        }
    });

    // let the server boot up
    ::std::thread::sleep(::std::time::Duration::from_millis(100));

    let mut client = TestClient::new(OsStr::new(socket_name));

    client
        .event_queue
        .sync_roundtrip(&mut (), |_, _, _| unreachable!())
        .unwrap();

    *(kill_switch.lock().unwrap()) = true;

    server_thread.join().unwrap();
}

#[test]
fn client_dispatch() {
    let socket_name = "wayland-client-dispatch";

    let kill_switch = Arc::new(Mutex::new(false));
    let server_kill_switch = kill_switch.clone();

    let server_thread = ::std::thread::spawn(move || {
        let mut display = ways::Display::new();
        display.add_socket(Some(socket_name)).unwrap();

        loop {
            display.dispatch(Duration::from_millis(10), &mut ()).unwrap();
            display.flush_clients(&mut ());
            if *(server_kill_switch.lock().unwrap()) {
                break;
            }
        }
    });

    // let the server boot up
    ::std::thread::sleep(::std::time::Duration::from_millis(100));

    let mut client = TestClient::new(OsStr::new(socket_name));

    // do a manual roundtrip
    let done = Rc::new(Cell::new(false));
    let done2 = done.clone();
    client
        .display_proxy
        .sync()
        .quick_assign(move |_, _, _| done2.set(true));
    while !done.get() {
        client
            .event_queue
            .dispatch(&mut (), |_, _, _| unreachable!())
            .unwrap();
    }

    *(kill_switch.lock().unwrap()) = true;

    server_thread.join().unwrap();
}
<commit_msg>Stabilize client_dispatch tests<commit_after>mod helpers;

use helpers::{ways, TestClient};

use std::cell::Cell;
use std::ffi::OsStr;
use std::rc::Rc;
use std::sync::{Arc, Mutex};
use std::time::Duration;

#[test]
fn client_sync_roundtrip() {
    let socket_name = "wayland-client-sync-roundtrip";

    let kill_switch = Arc::new(Mutex::new(false));
    let server_kill_switch = kill_switch.clone();

    let server_thread = ::std::thread::spawn(move || {
        let mut display = ways::Display::new();
        display.add_socket(Some(socket_name)).unwrap();

        loop {
            display.dispatch(Duration::from_millis(100), &mut ()).unwrap();
            display.flush_clients(&mut ());
            if *(server_kill_switch.lock().unwrap()) {
                break;
            }
        }
    });

    // let the server boot up
    ::std::thread::sleep(::std::time::Duration::from_millis(500));

    let mut client = TestClient::new(OsStr::new(socket_name));

    client
        .event_queue
        .sync_roundtrip(&mut (), |_, _, _| unreachable!())
        .unwrap();

    *(kill_switch.lock().unwrap()) = true;

    server_thread.join().unwrap();
}

#[test]
fn client_dispatch() {
    let socket_name = "wayland-client-dispatch";

    let kill_switch = Arc::new(Mutex::new(false));
    let server_kill_switch = kill_switch.clone();

    let server_thread = ::std::thread::spawn(move || {
        let mut display = ways::Display::new();
        display.add_socket(Some(socket_name)).unwrap();

        loop {
            display.dispatch(Duration::from_millis(100), &mut ()).unwrap();
            display.flush_clients(&mut ());
            if *(server_kill_switch.lock().unwrap()) {
                break;
            }
        }
    });

    // let the server boot up
    ::std::thread::sleep(::std::time::Duration::from_millis(500));

    let mut client = TestClient::new(OsStr::new(socket_name));

    // do a manual roundtrip
    let done = Rc::new(Cell::new(false));
    let done2 = done.clone();
    client
        .display_proxy
        .sync()
        .quick_assign(move |_, _, _| done2.set(true));
    while !done.get() {
        client
            .event_queue
            .dispatch(&mut (), |_, _, _| unreachable!())
            .unwrap();
    }

    *(kill_switch.lock().unwrap()) = true;

    server_thread.join().unwrap();
}
<|endoftext|>


<commit_before>//
//   Copyright 2016 Andrew Hunter
//
//   Licensed under the Apache License, Version 2.0 (the "License");
//   you may not use this file except in compliance with the License.
//   You may obtain a copy of the License at
//
//       http://www.apache.org/licenses/LICENSE-2.0
//
//   Unless required by applicable law or agreed to in writing, software
//   distributed under the License is distributed on an "AS IS" BASIS,
//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//   See the License for the specific language governing permissions and
//   limitations under the License.
//

//!
//! These functions deal with establishing how much of a particular stream (or string) matches a particular pattern. The
//! most important function is `matches`, which takes a stream and a pattern and returns the number of characters from the
//! stream that matches the pattern. Use it like this:
//!
//! ```
//! # use concordance::*;
//! # assert!(matches("abcabc", "abc".repeat_forever(1)) == Some(6));
//! # assert!(matches("abcabcabc", "abc".repeat_forever(1)).is_some());
//! # assert!(matches("abc", "abc").is_some());
//! # assert!(matches("def", "abc".repeat_forever(1)).is_none());
//! if matches("abcabc", "abc".repeat_forever(1)).is_some() { /* ... */ }
//! ```
//!
//! To determine if a string exactly matches a pattern, compare to the string length like this:
//!
//! ```
//! # use concordance::*;
//! let input_string = "abcabc";
//! let pattern      = "abc".repeat_forever(1);
//!
//! if matches(input_string, pattern) == Some(input_string.len()) { }
//! # assert!(matches(input_string, "abc".repeat_forever(1)) == Some(input_string.len()));
//! ```
//!

use super::symbol_range_dfa::*;
use super::symbol_reader::*;
use super::pattern_matcher::*;
use super::prepare::*;

///
/// Runs a DFA against a symbol stream and returns its final state
///
/// This takes a DFA match action as an initial state (such as that returned by `SymbolRangeDfa::start()`) and runs it until it accepts
/// or rejects the pattern passed to it.
///
/// This call is useful for cases where there is more than one output symbol (as the output symbol that was matched can be retrieved)
/// or for working with pattern matchers other than the default one.
///
/// ```
/// # use concordance::*;
/// let input_string = "abcabc";
/// let pattern      = "abc".repeat_forever(1);
/// let matcher      = pattern.prepare_to_match();
///
/// let match_result = match_pattern(matcher.start(), &mut input_string.read_symbols()); // == Accept(6, &true)
/// # assert!(match match_result { Accept(count, val) => count == 6 && val == &true, _ => false });
/// ```
///
pub fn match_pattern<'a, InputSymbol: Ord, OutputSymbol, State>(start_state: MatchAction<'a, OutputSymbol, State>, symbol_reader: &mut SymbolReader<InputSymbol>) -> MatchAction<'a, OutputSymbol, State>
where State: MatchingState<'a, InputSymbol, OutputSymbol> {
    let mut current_state = start_state;

    while let More(this_state) = current_state {
        let next_state =
            if let Some(next_char) = symbol_reader.next_symbol() {
                this_state.next(next_char)
            } else {
                this_state.finish()
            };

        current_state = next_state;
    }

    current_state
}

///
/// Runs a pattern matcher against a stream, and returns the number of characters matching if it accepted the stream
///
fn matches_symbol_range<InputSymbol: Ord, OutputSymbol: 'static>(dfa: &SymbolRangeDfa<InputSymbol, OutputSymbol>, symbol_reader: &mut SymbolReader<InputSymbol>) -> Option<usize> {
    // Run the DFA
    let final_state = match_pattern(dfa.start(), symbol_reader);

    if let Accept(count, _) = final_state {
        Some(count)
    } else {
        None
    }
}

///
/// Matches a source stream against a pattern
///
/// This is the basic pattern matcher. It matches against the left-hand side of the source, and if there is a string of any
/// length that can match the passed in pattern it will return the length of that string. Pattern matchers should be greedy,
/// so this will return the length of the longest string that can match the given pattern.
///
/// ```
/// # use concordance::*;
/// matches("abc", "abc");                      // Returns Some(3)
/// matches("abcabc", "abc");                   // Also returns Some(3) as 'abc' matches the pattern
/// matches("abcabc", "abc".repeat_forever(0)); // Returns Some(6)
/// matches("ab", "abc");                       // Doesn't match: returns None
/// ```
///
/// It's worth noting that this is not just limited to strings and characters. For example, vectors will work too:
///
/// ```
/// # use concordance::*;
/// matches(&vec![1,2,3,1,2,3], vec![1,2,3].repeat_forever(1)); // == Some(6)
/// # assert!(matches(&vec![1,2,3,1,2,3], vec![1,2,3].repeat_forever(1)) == Some(6));
/// ```
///
pub fn matches<'a, Symbol, OutputSymbol, Prepare, Reader, Source>(source: Source, pattern: Prepare) -> Option<usize>
where   Prepare: PrepareToMatch<SymbolRangeDfa<Symbol, OutputSymbol>>
,       Reader: SymbolReader<Symbol>+'a
,       Source: SymbolSource<'a, Symbol, SymbolReader=Reader>
,       Symbol: Ord
,       OutputSymbol: 'static {
    let matcher    = pattern.prepare_to_match();
    let mut reader = source.read_symbols();

    matches_symbol_range(&matcher, &mut reader)
}

///
/// Matches a source stream against a prepared pattern
///
/// If it's necessary to match a pattern against a lot of different things, then preparing it by calling `pattern.prepare_to_match()`
/// will increase the performance of the matcher for every match after the first one. This call is otherwise identical to `matches`.
///
/// ```
/// # use concordance::*;
/// let prepared = "abc".repeat_forever(1).prepare_to_match();
///
/// matches_prepared("abcabc", &prepared);      // == Some(6)
/// matches_prepared("abc", &prepared);         // == Some(3)
/// matches_prepared("abcabcabc", &prepared);   // == Some(9)
/// ```
///
pub fn matches_prepared<'a, Symbol, OutputSymbol, Reader, Source>(source: Source, matcher: &SymbolRangeDfa<Symbol, OutputSymbol>) -> Option<usize>
where   Reader: SymbolReader<Symbol>+'a
,       Source: SymbolSource<'a, Symbol, SymbolReader=Reader>
,       Symbol: Ord
,       OutputSymbol: 'static {
    let mut reader = source.read_symbols();

    matches_symbol_range(&matcher, &mut reader)
}

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

    #[test]
    fn match_multiple_repeats() {
        assert!(matches("abcabc", "abc".repeat_forever(1)).is_some());
    }

    #[test]
    fn match_prepared() {
        let prepared = "abc".repeat_forever(1).prepare_to_match();

        assert!(matches_prepared("abcabc", &prepared) == Some(6));
        assert!(matches_prepared("abc", &prepared) == Some(3));
        assert!(matches_prepared("abcabcabc", &prepared) == Some(9));
    }

    #[test]
    fn match_single_repeat() {
        assert!(matches("abc", "abc".repeat_forever(1)).is_some());
    }

    #[test]
    fn match_with_zero_or_more() {
        assert!(matches("abc", "abc".repeat_forever(0)) == Some(3));
        assert!(matches("abcabc", "abc".repeat_forever(0)) == Some(6));
        assert!(matches("abcabcabc", "abc".repeat_forever(0)) == Some(9));
    }

    #[test]
    fn match_with_zero_or_more_following() {
        assert!(matches("abc", "abc".repeat_forever(0).append("def")).is_none());
        assert!(matches("abcabc", "abc".repeat_forever(0).append("def")).is_none());

        assert!(matches("abcdef", "abc".repeat_forever(0).append("def")).is_some());
        assert!(matches("abcabcdef", "abc".repeat_forever(0).append("def")).is_some());
    }

    #[test]
    fn match_limited_range() {
        assert!(matches("abc", "abc".repeat(2..4)).is_none());
        assert!(matches("abcabc", "abc".repeat(2..4)).is_some());
        assert!(matches("abcabcabc", "abc".repeat(2..4)) == Some(3*3));
        assert!(matches("abcabcabcabc", "abc".repeat(2..4)) == Some(3*3));
    }

    #[test]
    fn match_zero_repeats() {
        assert!(matches("", "abc".repeat_forever(0)).is_some());
    }
}
<commit_msg>Add tests for zero-or-more and ‘or’ when combined<commit_after>//
//   Copyright 2016 Andrew Hunter
//
//   Licensed under the Apache License, Version 2.0 (the "License");
//   you may not use this file except in compliance with the License.
//   You may obtain a copy of the License at
//
//       http://www.apache.org/licenses/LICENSE-2.0
//
//   Unless required by applicable law or agreed to in writing, software
//   distributed under the License is distributed on an "AS IS" BASIS,
//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//   See the License for the specific language governing permissions and
//   limitations under the License.
//

//!
//! These functions deal with establishing how much of a particular stream (or string) matches a particular pattern. The
//! most important function is `matches`, which takes a stream and a pattern and returns the number of characters from the
//! stream that matches the pattern. Use it like this:
//!
//! ```
//! # use concordance::*;
//! # assert!(matches("abcabc", "abc".repeat_forever(1)) == Some(6));
//! # assert!(matches("abcabcabc", "abc".repeat_forever(1)).is_some());
//! # assert!(matches("abc", "abc").is_some());
//! # assert!(matches("def", "abc".repeat_forever(1)).is_none());
//! if matches("abcabc", "abc".repeat_forever(1)).is_some() { /* ... */ }
//! ```
//!
//! To determine if a string exactly matches a pattern, compare to the string length like this:
//!
//! ```
//! # use concordance::*;
//! let input_string = "abcabc";
//! let pattern      = "abc".repeat_forever(1);
//!
//! if matches(input_string, pattern) == Some(input_string.len()) { }
//! # assert!(matches(input_string, "abc".repeat_forever(1)) == Some(input_string.len()));
//! ```
//!

use super::symbol_range_dfa::*;
use super::symbol_reader::*;
use super::pattern_matcher::*;
use super::prepare::*;

///
/// Runs a DFA against a symbol stream and returns its final state
///
/// This takes a DFA match action as an initial state (such as that returned by `SymbolRangeDfa::start()`) and runs it until it accepts
/// or rejects the pattern passed to it.
///
/// This call is useful for cases where there is more than one output symbol (as the output symbol that was matched can be retrieved)
/// or for working with pattern matchers other than the default one.
///
/// ```
/// # use concordance::*;
/// let input_string = "abcabc";
/// let pattern      = "abc".repeat_forever(1);
/// let matcher      = pattern.prepare_to_match();
///
/// let match_result = match_pattern(matcher.start(), &mut input_string.read_symbols()); // == Accept(6, &true)
/// # assert!(match match_result { Accept(count, val) => count == 6 && val == &true, _ => false });
/// ```
///
pub fn match_pattern<'a, InputSymbol: Ord, OutputSymbol, State>(start_state: MatchAction<'a, OutputSymbol, State>, symbol_reader: &mut SymbolReader<InputSymbol>) -> MatchAction<'a, OutputSymbol, State>
where State: MatchingState<'a, InputSymbol, OutputSymbol> {
    let mut current_state = start_state;

    while let More(this_state) = current_state {
        let next_state =
            if let Some(next_char) = symbol_reader.next_symbol() {
                this_state.next(next_char)
            } else {
                this_state.finish()
            };

        current_state = next_state;
    }

    current_state
}

///
/// Runs a pattern matcher against a stream, and returns the number of characters matching if it accepted the stream
///
fn matches_symbol_range<InputSymbol: Ord, OutputSymbol: 'static>(dfa: &SymbolRangeDfa<InputSymbol, OutputSymbol>, symbol_reader: &mut SymbolReader<InputSymbol>) -> Option<usize> {
    // Run the DFA
    let final_state = match_pattern(dfa.start(), symbol_reader);

    if let Accept(count, _) = final_state {
        Some(count)
    } else {
        None
    }
}

///
/// Matches a source stream against a pattern
///
/// This is the basic pattern matcher. It matches against the left-hand side of the source, and if there is a string of any
/// length that can match the passed in pattern it will return the length of that string. Pattern matchers should be greedy,
/// so this will return the length of the longest string that can match the given pattern.
///
/// ```
/// # use concordance::*;
/// matches("abc", "abc");                      // Returns Some(3)
/// matches("abcabc", "abc");                   // Also returns Some(3) as 'abc' matches the pattern
/// matches("abcabc", "abc".repeat_forever(0)); // Returns Some(6)
/// matches("ab", "abc");                       // Doesn't match: returns None
/// ```
///
/// It's worth noting that this is not just limited to strings and characters. For example, vectors will work too:
///
/// ```
/// # use concordance::*;
/// matches(&vec![1,2,3,1,2,3], vec![1,2,3].repeat_forever(1)); // == Some(6)
/// # assert!(matches(&vec![1,2,3,1,2,3], vec![1,2,3].repeat_forever(1)) == Some(6));
/// ```
///
pub fn matches<'a, Symbol, OutputSymbol, Prepare, Reader, Source>(source: Source, pattern: Prepare) -> Option<usize>
where   Prepare: PrepareToMatch<SymbolRangeDfa<Symbol, OutputSymbol>>
,       Reader: SymbolReader<Symbol>+'a
,       Source: SymbolSource<'a, Symbol, SymbolReader=Reader>
,       Symbol: Ord
,       OutputSymbol: 'static {
    let matcher    = pattern.prepare_to_match();
    let mut reader = source.read_symbols();

    matches_symbol_range(&matcher, &mut reader)
}

///
/// Matches a source stream against a prepared pattern
///
/// If it's necessary to match a pattern against a lot of different things, then preparing it by calling `pattern.prepare_to_match()`
/// will increase the performance of the matcher for every match after the first one. This call is otherwise identical to `matches`.
///
/// ```
/// # use concordance::*;
/// let prepared = "abc".repeat_forever(1).prepare_to_match();
///
/// matches_prepared("abcabc", &prepared);      // == Some(6)
/// matches_prepared("abc", &prepared);         // == Some(3)
/// matches_prepared("abcabcabc", &prepared);   // == Some(9)
/// ```
///
pub fn matches_prepared<'a, Symbol, OutputSymbol, Reader, Source>(source: Source, matcher: &SymbolRangeDfa<Symbol, OutputSymbol>) -> Option<usize>
where   Reader: SymbolReader<Symbol>+'a
,       Source: SymbolSource<'a, Symbol, SymbolReader=Reader>
,       Symbol: Ord
,       OutputSymbol: 'static {
    let mut reader = source.read_symbols();

    matches_symbol_range(&matcher, &mut reader)
}

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

    #[test]
    fn match_multiple_repeats() {
        assert!(matches("abcabc", "abc".repeat_forever(1)).is_some());
    }

    #[test]
    fn match_prepared() {
        let prepared = "abc".repeat_forever(1).prepare_to_match();

        assert!(matches_prepared("abcabc", &prepared) == Some(6));
        assert!(matches_prepared("abc", &prepared) == Some(3));
        assert!(matches_prepared("abcabcabc", &prepared) == Some(9));
    }

    #[test]
    fn match_single_repeat() {
        assert!(matches("abc", "abc".repeat_forever(1)).is_some());
    }

    #[test]
    fn match_with_zero_or_more() {
        assert!(matches("abc", "abc".repeat_forever(0)) == Some(3));
        assert!(matches("abcabc", "abc".repeat_forever(0)) == Some(6));
        assert!(matches("abcabcabc", "abc".repeat_forever(0)) == Some(9));
    }

    #[test]
    fn match_with_zero_or_more_following() {
        assert!(matches("abc", "abc".repeat_forever(0).append("def")).is_none());
        assert!(matches("abcabc", "abc".repeat_forever(0).append("def")).is_none());

        assert!(matches("abcdef", "abc".repeat_forever(0).append("def")).is_some());
        assert!(matches("abcabcdef", "abc".repeat_forever(0).append("def")).is_some());
    }

    #[test]
    fn match_with_zero_or_more_alternatives() {
        assert!(matches("", ("abc".repeat_forever(0)).or("def".repeat_forever(0))) == Some(0));
        assert!(matches("abc", ("abc".repeat_forever(0)).or("def".repeat_forever(0))) == Some(3));
        assert!(matches("def", ("abc".repeat_forever(0)).or("def".repeat_forever(0))) == Some(3));
        assert!(matches("abcabc", ("abc".repeat_forever(0)).or("def".repeat_forever(0))) == Some(6));
        assert!(matches("defdef", ("abc".repeat_forever(0)).or("def".repeat_forever(0))) == Some(6));
    }

    #[test]
    fn match_with_one_or_more_alternatives() {
        assert!(matches("", ("abc".repeat_forever(1)).or("def".repeat_forever(1))) == None);
        assert!(matches("abc", ("abc".repeat_forever(1)).or("def".repeat_forever(1))) == Some(3));
        assert!(matches("def", ("abc".repeat_forever(1)).or("def".repeat_forever(1))) == Some(3));
        assert!(matches("abcabc", ("abc".repeat_forever(1)).or("def".repeat_forever(1))) == Some(6));
        assert!(matches("defdef", ("abc".repeat_forever(1)).or("def".repeat_forever(1))) == Some(6));
    }

    #[test]
    fn match_limited_range() {
        assert!(matches("abc", "abc".repeat(2..4)).is_none());
        assert!(matches("abcabc", "abc".repeat(2..4)).is_some());
        assert!(matches("abcabcabc", "abc".repeat(2..4)) == Some(3*3));
        assert!(matches("abcabcabcabc", "abc".repeat(2..4)) == Some(3*3));
    }

    #[test]
    fn match_zero_repeats() {
        assert!(matches("", "abc".repeat_forever(0)).is_some());
    }
}
<|endoftext|>


<commit_before>//
// Copyright (c) 2016, Boris Popov <popov@whitekefir.ru>
//
// 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/.
//

extern crate regex;

use logger;
use env;
use std::process::exit;
use self::regex::Regex;
use blkid;
use mount;
use mount::MountInfo;

//////////////////////////////////////////////////////////////////
pub struct Mounter {
    part_label: String,
    part_type:  String,
    target:     String
}

impl Mounter {
    pub fn new() -> Mounter {
        Mounter{
            part_label: "".to_string(),
            part_type:  "".to_string(),
            target:     "".to_string()
        }
    }

    pub fn mount(&mut self, l: &logger::Logger, e: &env::Env) {
        self.load_part_info(e.getDevice(), l);
        if !self.verify_label(e.getLabel()) {
            let i = format!("Label does not match {}.", e.getLabel());
            l.info(&i);
            exit(0);
        }
        self.process(l, e);
    }

    fn process(&mut self, l: &logger::Logger, e: &env::Env) {
        let source = e.getDevice().to_string();
        self.target = e.getDir().to_string();
        let mi = MountInfo{source: &source,
                           target: &self.target,
                           filesystem: &self.part_type};
        let res = mount::mount(&mi);
        match res {
            Err(e) => {
                l.info(&e);
                exit(0);
            },
            _ => {
                return;
            }
        }
    }

    fn verify_label(&self, templ: &str) -> bool {
        if self.part_label.len() == 0 {
            return false;
        }

        let res = Regex::new(templ);
        match res {
            Ok(re) => re.is_match(&self.part_label),
            _      => false
        }
    }

    fn load_part_info(&mut self, dev: &str, l: &logger::Logger) {
        let prober = blkid::Prober::new(dev);
        let res = prober.probe();
        if let Err(e) = res {
            l.error(&e);
            exit(1);
        }
        self.loadLabel(&prober, l);
        self.loadType(&prober, l);
    }

    fn loadLabel(&mut self, prober: &blkid::Prober,
                 l: &logger::Logger) {
        let lr = prober.getLabel();
        match lr {
            Ok(o) => {
                self.part_label = o;
                let mess = "LABEL=".to_string() + &self.part_label;
                l.info(&mess);
            },
            Err(e) => {
                l.error(&e);
            }
        }
    }

    fn loadType(&mut self, prober: &blkid::Prober,
                l: &logger::Logger) {
        let lr = prober.getType();
        match lr {
            Ok(o) => {
                self.part_type = o;
                let mess = "TYPE=".to_string() + &self.part_label;
                l.info(&mess);
            },
            Err(e) => {
                l.error(&e);
            }
        }
    }
}

impl Drop for Mounter {
    fn drop(&mut self) {
        if self.target.len() != 0 {
            mount::umount(&self.target);
        }
    }
}
//////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////
#[test]
fn test_verify_label_01() {
    let i = Mounter{part_label: "BNC-124".to_string(),
                    target: "/mnt/temp".to_string(),
                    part_type: "".to_string()};
    assert_eq!(false, i.verify_label(".*ANC.*"));
}

#[test]
fn test_verify_label_02() {
    let i = Mounter{part_label: "XANC-124".to_string(),
                    target: "/mnt/temp".to_string(),
                    part_type: "".to_string()};
    assert_eq!(true, i.verify_label(".*ANC.*"));
}

#[test]
fn test_verify_label_04() {
    let i = Mounter{part_label: "ANC".to_string(),
                    target: "/mnt/temp".to_string(),
                    part_type: "".to_string()};
    assert_eq!(true, i.verify_label(".*ANC.*"));
}

#[test]
fn test_verify_label_05() {
    let i = Mounter{part_label: "01234_ ANC".to_string(),
                    target: "/mnt/temp".to_string(),
                    part_type: "".to_string()};
    assert_eq!(true, i.verify_label(".*ANC.*"));
}

#[test]
fn test_verify_label_06() {
    let i = Mounter{part_label: "01234_ ANC 782883 ".to_string(),
                    target: "/mnt/temp".to_string(),
                    part_type: "".to_string()};
    assert_eq!(true, i.verify_label(".*ANC.*"));
}

#[test]
fn test_verify_label_07() {
    let i = Mounter{part_label: " ANC 782883 ".to_string(),
                    target: "/mnt/temp".to_string(),
                    part_type: "".to_string()};
    assert_eq!(true, i.verify_label(".*ANC.*"));
}

#[test]
fn test_verify_label_08() {
    let i = Mounter{part_label: "ANC---!782883 ".to_string(),
                    target: "/mnt/temp".to_string(),
                    part_type: "".to_string()};
    assert_eq!(true, i.verify_label(".*ANC.*"));
}

#[test]
fn test_verify_label_09() {
    let i = Mounter{part_label: "01234_ NC 782883 ".to_string(),
                    target: "/mnt/temp".to_string(),
                    part_type: "".to_string()};
    assert_eq!(false, i.verify_label(".*ANC.*"));
}

#[test]
fn test_verify_label_10() {
    let i = Mounter{part_label: "".to_string(),
                    target: "/mnt/temp".to_string(),
                    part_type: "".to_string()};
    assert_eq!(false, i.verify_label(".*ANC.*"));
}
//////////////////////////////////////////////////////////////////
<commit_msg>fixed Mounter<commit_after>//
// Copyright (c) 2016, Boris Popov <popov@whitekefir.ru>
//
// 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 logger;
use env;
use std::process::exit;
use blkid;
use mount;

//////////////////////////////////////////////////////////////////
pub struct Mounter {
    part_label: String,
    part_type:  String,
    target:     String
}

impl Mounter {
    pub fn new() -> Mounter {
        Mounter{
            part_label: "".to_string(),
            part_type:  "".to_string(),
            target:     "".to_string()
        }
    }

    pub fn mount(&mut self, l: &logger::Logger, e: &env::Env) {
        self.load_part_info(e.getDevice(), l);
        let result = self.verify_label(e.getLabel(), l);
        if ! result {
            let i = format!("Label does not match {}.", e.getLabel());
            l.info(&i);
            exit(0);
        }
        self.process(l, e);
    }

    fn process(&mut self, l: &logger::Logger, e: &env::Env) {
        let source = e.getDevice().to_string();
        self.target = e.getDir().to_string();
        let res = mount::mount(source.as_str(),
                               self.target.as_str(),
                               self.part_type.as_str());
        match res {
            Err(e) => {
                l.info(e.as_str());
                exit(0);
            },
            _ => {
                let i = format!("Mount {} to {} OK!",
                                source.as_str(),
                                self.target.as_str());
                l.info(i.as_str());
                return;
            }
        }
    }

    fn verify_label(&self, templ: &str, l: &logger::Logger) -> bool {
        if self.part_label.len() == 0 {
            return false;
        }
        return self.part_label.contains(templ);
    }

    fn load_part_info(&mut self, dev: &str, l: &logger::Logger) {
        let prober = blkid::Prober::new(dev);
        let res = prober.probe();
        if let Err(e) = res {
            l.error(&e);
            exit(1);
        }
        self.loadLabel(&prober, l);
        self.loadType(&prober, l);
    }

    fn loadLabel(&mut self, prober: &blkid::Prober,
                 l: &logger::Logger) {
        let lr = prober.getLabel();
        match lr {
            Ok(o) => {
                self.part_label = o;
            },
            Err(e) => {
                l.error(&e);
            }
        }
    }

    fn loadType(&mut self, prober: &blkid::Prober,
                l: &logger::Logger) {
        let lr = prober.getType();
        match lr {
            Ok(o) => {
                self.part_type = o;
            },
            Err(e) => {
                l.error(&e);
            }
        }
    }
}

impl Drop for Mounter {
    fn drop(&mut self) {
        if self.target.len() != 0 {
            //
            //TODO
            //
            //mount::umount(&self.target);
        }
    }
}
//////////////////////////////////////////////////////////////////
<|endoftext|>


<commit_before>pub mod vector_tile; // protoc --rust_out . vector_tile.proto
mod geom_to_proto;

#[test]
fn test_protobuf_structs() {
    let mut value = vector_tile::Tile_Value::new();
    assert_eq!(value, Default::default());
    assert!(!value.has_string_value());
    value.set_string_value(String::from("Hello, world!"));
    println!("{:?}", value);
    assert!(value.has_string_value());
    assert_eq!(value.get_string_value(), String::from("Hello, world!"));
}

#[test]
fn test_read_pbf_file() {
    use std::fs::File;
    use std::io::BufReader;
    use protobuf::parse_from_reader;

    let f = File::open("src/test/tile.pbf").unwrap();
    // Command line decoding:
    // protoc --decode=vector_tile.Tile src/mvt/vector_tile.proto <src/test/tile.pbf
    let mut reader = BufReader::new(f);
    let tile = parse_from_reader::<vector_tile::Tile>(&mut reader).unwrap();
    println!("{:#?}", tile);
    let ref layer = tile.get_layers()[0];
    assert_eq!(layer.get_name(), "roads");
    let ref feature = layer.get_features()[1];
    assert_eq!(feature.get_field_type(), vector_tile::Tile_GeomType::POLYGON);
    let ref geometry = feature.get_geometry();
    assert_eq!(geometry, &[9,8236,4926,34,9,24,37,21,10,7,4,19,15]);
}

struct FeatureAttribute {
    key: String,
    values: Vec<String>
}

struct FeatureAttributes {
    vec: Vec<FeatureAttribute>
}

impl FeatureAttributes {
    fn new() -> FeatureAttributes {
        FeatureAttributes { vec: Vec::<FeatureAttribute>::new() }
    }
    fn add_attribute(&mut self, key: String, value: String) -> (u32, u32) {
        let entry = self.vec.iter().position(|ref kv| kv.key == key);
        match entry {
            None => {
                self.vec.push(FeatureAttribute {
                        key: key,
                        values : [value].to_vec()
                    });
                (self.vec.len() as u32 - 1, 0)
            },
            Some(idx) => {
                let mut kv = self.vec.get_mut(idx).unwrap();
                let valentry = kv.values.iter().position(|v| *v == value);
                let validx = match valentry {
                    None => {
                        kv.values.push(value);
                        kv.values.len()-1
                    },
                    Some(idx) => idx
                };
                (idx as u32, validx as u32)
            }
        }
    }
}
#[test]
fn test_create_pbf() {
    // https://github.com/mapbox/vector-tile-spec/tree/master/2.1#45-example
    let mut tile = vector_tile::Tile::new();

    let mut layer = vector_tile::Tile_Layer::new();
    layer.set_version(2);
    layer.set_name(String::from("points"));
    layer.set_extent(4096);

    let mut feature_id = 1;
    let mut feature = vector_tile::Tile_Feature::new();
    feature.set_id(feature_id);
    feature.set_field_type(vector_tile::Tile_GeomType::POINT);
    feature.set_geometry([9, 2410, 3080].to_vec());

    let mut attrs = FeatureAttributes::new();
    let (keyidx, validx) = attrs.add_attribute(
        String::from("hello"), String::from("world"));
    feature.mut_tags().push(keyidx);
    feature.mut_tags().push(validx);
    let (keyidx, validx) = attrs.add_attribute(
        String::from("h"), String::from("world"));
    feature.mut_tags().push(keyidx);
    feature.mut_tags().push(validx);

    layer.mut_features().push(feature);

    feature_id += 1;
    feature = vector_tile::Tile_Feature::new();
    feature.set_id(feature_id);
    feature.set_field_type(vector_tile::Tile_GeomType::POINT);
    feature.set_geometry([9, 2410, 3080].to_vec());
    layer.mut_features().push(feature);

    for keyval in attrs.vec.iter() {
        layer.mut_keys().push(keyval.key.clone());
        for val in keyval.values.iter() {
            let mut value = vector_tile::Tile_Value::new();
            value.set_string_value(val.clone());
            layer.mut_values().push(value);
        }
    }

    tile.mut_layers().push(layer);
    println!("{:#?}", tile);
}<commit_msg>Unit test for MVT tile creation<commit_after>pub mod vector_tile; // protoc --rust_out . vector_tile.proto
mod geom_to_proto;

#[test]
fn test_protobuf_structs() {
    let mut value = vector_tile::Tile_Value::new();
    assert_eq!(value, Default::default());
    assert!(!value.has_string_value());
    value.set_string_value(String::from("Hello, world!"));
    println!("{:?}", value);
    assert!(value.has_string_value());
    assert_eq!(value.get_string_value(), String::from("Hello, world!"));
}

#[test]
fn test_read_pbf_file() {
    use std::fs::File;
    use std::io::BufReader;
    use protobuf::parse_from_reader;

    let f = File::open("src/test/tile.pbf").unwrap();
    // Command line decoding:
    // protoc --decode=vector_tile.Tile src/mvt/vector_tile.proto <src/test/tile.pbf
    let mut reader = BufReader::new(f);
    let tile = parse_from_reader::<vector_tile::Tile>(&mut reader).unwrap();
    println!("{:#?}", tile);
    let ref layer = tile.get_layers()[0];
    assert_eq!(layer.get_name(), "roads");
    let ref feature = layer.get_features()[1];
    assert_eq!(feature.get_field_type(), vector_tile::Tile_GeomType::POLYGON);
    let ref geometry = feature.get_geometry();
    assert_eq!(geometry, &[9,8236,4926,34,9,24,37,21,10,7,4,19,15]);
}

struct FeatureAttributes {
    keys: Vec<String>,
    values: Vec<String>,
}

impl FeatureAttributes {
    fn new() -> FeatureAttributes {
        FeatureAttributes { keys: Vec::<String>::new(), values: Vec::<String>::new() }
    }
    fn add_attribute(&mut self, key: String, value: String) -> (u32, u32) {
        let keyentry = self.keys.iter().position(|k| *k == key);
        let keyidx = match keyentry {
            None => {
                self.keys.push(key);
                self.keys.len()-1
            },
            Some(idx) => idx
        };
        let valentry = self.values.iter().position(|v| *v == value);
        let validx = match valentry {
            None => {
                self.values.push(value);
                self.values.len()-1
            },
            Some(idx) => idx
        };
        (keyidx as u32, validx as u32)
    }
}
#[test]
fn test_create_pbf() {
    // https://github.com/mapbox/vector-tile-spec/tree/master/2.1#45-example
    let mut tile = vector_tile::Tile::new();

    let mut layer = vector_tile::Tile_Layer::new();
    layer.set_version(2);
    layer.set_name(String::from("points"));
    layer.set_extent(4096);

    let mut feature_id = 1;
    let mut feature = vector_tile::Tile_Feature::new();
    feature.set_id(feature_id);
    feature.set_field_type(vector_tile::Tile_GeomType::POINT);
    feature.set_geometry([9, 2410, 3080].to_vec());

    let mut attrs = FeatureAttributes::new();
    let (keyidx, validx) = attrs.add_attribute(
        String::from("hello"), String::from("world"));
    feature.mut_tags().push(keyidx);
    feature.mut_tags().push(validx);
    let (keyidx, validx) = attrs.add_attribute(
        String::from("h"), String::from("world"));
    feature.mut_tags().push(keyidx);
    feature.mut_tags().push(validx);
    let (keyidx, validx) = attrs.add_attribute(
        String::from("count"), String::from("1.23")); // FIXME: double_value
    feature.mut_tags().push(keyidx);
    feature.mut_tags().push(validx);

    layer.mut_features().push(feature);

    feature_id += 1;
    feature = vector_tile::Tile_Feature::new();
    feature.set_id(feature_id);
    feature.set_field_type(vector_tile::Tile_GeomType::POINT);
    feature.set_geometry([9, 2410, 3080].to_vec());

    let (keyidx, validx) = attrs.add_attribute(
        String::from("hello"), String::from("again"));
    feature.mut_tags().push(keyidx);
    feature.mut_tags().push(validx);
    let (keyidx, validx) = attrs.add_attribute(
        String::from("count"), String::from("2")); // FIXME: int_value
    feature.mut_tags().push(keyidx);
    feature.mut_tags().push(validx);

    layer.mut_features().push(feature);

    for key in attrs.keys.iter() {
        layer.mut_keys().push(key.clone());
    }
    for val in attrs.values.iter() {
        let mut value = vector_tile::Tile_Value::new();
        value.set_string_value(val.clone());
        layer.mut_values().push(value);
    }

    tile.mut_layers().push(layer);
    println!("{:#?}", tile);
    let expected = "Tile {
    layers: [
        Tile_Layer {
            version: Some(
                2
            ),
            name: Some(\"points\"),
            features: [
                Tile_Feature {
                    id: Some(
                        1
                    ),
                    tags: [
                        0,
                        0,
                        1,
                        0,
                        2,
                        1
                    ],
                    field_type: Some(
                        POINT
                    ),
                    geometry: [
                        9,
                        2410,
                        3080
                    ],
                    unknown_fields: UnknownFields {
                        fields: None
                    },
                    cached_size: Cell { value: 0 }
                },
                Tile_Feature {
                    id: Some(
                        2
                    ),
                    tags: [
                        0,
                        2,
                        2,
                        3
                    ],
                    field_type: Some(
                        POINT
                    ),
                    geometry: [
                        9,
                        2410,
                        3080
                    ],
                    unknown_fields: UnknownFields {
                        fields: None
                    },
                    cached_size: Cell { value: 0 }
                }
            ],
            keys: [
                \"hello\",
                \"h\",
                \"count\"
            ],
            values: [
                Tile_Value {
                    string_value: Some(\"world\"),
                    float_value: None,
                    double_value: None,
                    int_value: None,
                    uint_value: None,
                    sint_value: None,
                    bool_value: None,
                    unknown_fields: UnknownFields {
                        fields: None
                    },
                    cached_size: Cell { value: 0 }
                },
                Tile_Value {
                    string_value: Some(\"1.23\"),
                    float_value: None,
                    double_value: None,
                    int_value: None,
                    uint_value: None,
                    sint_value: None,
                    bool_value: None,
                    unknown_fields: UnknownFields {
                        fields: None
                    },
                    cached_size: Cell { value: 0 }
                },
                Tile_Value {
                    string_value: Some(\"again\"),
                    float_value: None,
                    double_value: None,
                    int_value: None,
                    uint_value: None,
                    sint_value: None,
                    bool_value: None,
                    unknown_fields: UnknownFields {
                        fields: None
                    },
                    cached_size: Cell { value: 0 }
                },
                Tile_Value {
                    string_value: Some(\"2\"),
                    float_value: None,
                    double_value: None,
                    int_value: None,
                    uint_value: None,
                    sint_value: None,
                    bool_value: None,
                    unknown_fields: UnknownFields {
                        fields: None
                    },
                    cached_size: Cell { value: 0 }
                }
            ],
            extent: Some(
                4096
            ),
            unknown_fields: UnknownFields {
                fields: None
            },
            cached_size: Cell { value: 0 }
        }
    ],
    unknown_fields: UnknownFields {
        fields: None
    },
    cached_size: Cell { value: 0 }
}";
    assert_eq!(expected, &*format!("{:#?}", tile));
}
<|endoftext|>


<commit_before>// Manages a single participant in the epoch scheme. This is where all
// of the actual epoch management logic happens!

use std::{fmt, mem};
use std::cell::UnsafeCell;
use std::sync::atomic::{self, AtomicUsize, AtomicBool};

use mem::epoch::{Atomic, Guard, garbage, global};
use mem::epoch::participants::ParticipantNode;

/// The garbage collection threshold (in garbage items).
const GC_THRESHOLD: usize = 32;

/// Thread-local data for epoch participation.
pub struct Participant {
    /// The local epoch.
    ///
    /// This is incremented on new epochs.
    epoch: AtomicUsize,
    /// Number of pending uses of `epoch::pin()`.
    ///
    /// Keeping a count allows for reentrant use of epoch management.
    in_critical: AtomicUsize,
    /// The thread-local garbage tracking.
    garbage: UnsafeCell<garbage::Local>,
    /// Is the thread still active?
    ///
    /// This becomes `false` when the thread exits. This is ultimately used to free `Participant`
    /// records.
    pub active: AtomicBool,
    /// The next participant node.
    ///
    /// The participant list is coded intrusively; here's the pointer to the next node.
    pub next: Atomic<ParticipantNode>,
}

impl Participant {
    /// Enter a critical section.
    ///
    /// This method is reentrant, allowing for nested critical sections.
    ///
    /// It returns `true` is this is the first entry on the stack (as opposed to a re-entrant
    /// call).
    pub fn enter(&self) -> bool {
        // Increment the counter.
        if self.in_critical.fetch_add(1, atomic::Ordering::Relaxed) > 0 {
            // Since it was above zero, we return false.
            false
        } else {
            // This fence is critical to avoid reordering with the increment.
            atomic::fence(atomic::Ordering::SeqCst);

            // Load the global epoch counter and test if this epoch matches the global.
            let global_epoch = global::EPOCH.epoch.load(atomic::Ordering::Relaxed);
            if global_epoch != self.epoch.load(atomic::Ordering::Relaxed) {
                // As it isn't already at the global epoch count, set it.
                self.epoch.store(global_epoch, atomic::Ordering::Relaxed);

                // Then collect the garbage.
                unsafe {
                    (*self.garbage.get()).collect();
                }
            }

            true
        }
    }

    /// Exit the current (nested) critical section.
    pub fn exit(&self) {
        // Decrement the counter.
        self.in_critical.fetch_sub(1, atomic::Ordering::SeqCst);
    }

    /// Begin the reclamation process for a piece of data.
    pub unsafe fn reclaim<T>(&self, data: *mut T) {
        // Insert it into the garbage list.
        (*self.garbage.get()).insert(data);
    }

    /// Attempt to collect garbage by moving the global epoch forward.
    ///
    /// If it failed, it returns `Err(())`.
    pub fn try_collect(&self, guard: &Guard) -> Result<(), ()> {
        // Load the global epoch counter.
        let cur_epoch = global::EPOCH.epoch.load(atomic::Ordering::SeqCst);

        // Go over the participants to ensure that none are critical.
        for p in global::EPOCH.participants.iter(guard) {
            if p.is_critical() && p.epoch.load(atomic::Ordering::Relaxed) != cur_epoch {
                // A participant was in critical state, and can thus not be GC'd at this moment.
                return Err(());
            }
        }

        let new_epoch = cur_epoch.wrapping_add(1);

        // This fence is important to avoid reordering of the CAS with any of the previous loads.
        // TODO: Is this really necessary?
        atomic::fence(atomic::Ordering::Acquire);
        // CAS with the new epoch. The reason we do CAS and not a simple store is that we want to
        // solve the ABA problem, as another thread could have updated the counter, causing us to
        // reverting its changes. Hence, we must ensure that this is NOT the case.
        if global::EPOCH.epoch.compare_and_swap(cur_epoch, new_epoch, atomic::Ordering::SeqCst) != cur_epoch {
            // Another thread touched it, so the collection failed.
            return Err(());
        }

        // If you've come so far, everything is right for collecting the garbage, so let's do it.
        unsafe {
            (*self.garbage.get()).collect();
            global::EPOCH.garbage.collect(new_epoch.wrapping_add(1))
        }

        // Update the epoch counter. As the epoch was collected, the ABA problem shouldn't be an
        // issue here.
        // TODO: Is this really correct?
        self.epoch.store(new_epoch, atomic::Ordering::Release);

        Ok(())
    }

    /// Move the current thread-local garbage into the global garbage bags.
    pub fn migrate_garbage(&self) {
        // Load the current epoch counter.
        let cur_epoch = self.epoch.load(atomic::Ordering::Relaxed);
        // Replace the local garbage set with an empty set.
        let local = unsafe { mem::replace(&mut *self.garbage.get(), garbage::Local::default()) };
        // Insert each epoch-kind into the global set.
        global::EPOCH.garbage.insert(cur_epoch.wrapping_sub(1), local.old);
        global::EPOCH.garbage.insert(cur_epoch, local.cur);
        global::EPOCH.garbage.insert(cur_epoch.wrapping_add(1), local.new);

        // TODO
        // global::EPOCH.garbage[global::EPOCH.epoch.load(atomic::Ordering::Relaxed) % 3].insert(local.new);
    }

    /// How many garbage items is this participant currently storing?
    pub fn garbage_len(&self) -> usize {
        unsafe { (*self.garbage.get()).len() }
    }

    /// Is this participant past its local GC threshold?
    pub fn should_gc(&self) -> bool {
        // We only GC when the garbage length is above some threshold.
        self.garbage_len() >= GC_THRESHOLD
    }

    /// Is this participant in a critical state?
    ///
    /// "Critical state" means that an `epoch::pin()` is pending, and thus it cannot be modified
    /// ATM.
    fn is_critical(&self) -> bool {
        self.in_critical.load(atomic::Ordering::Relaxed) > 0
    }
}

unsafe impl Sync for Participant {}

impl fmt::Debug for Participant {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "Participant {{ ... }}")
    }
}

impl Default for Participant {
    fn default() -> Participant {
        Participant {
            epoch: AtomicUsize::new(0),
            in_critical: AtomicUsize::new(0),
            active: AtomicBool::new(true),
            garbage: UnsafeCell::new(garbage::Local::default()),
            next: Atomic::null(),
        }
    }
}
<commit_msg>Quad-double the GC threshold to improve performance.<commit_after>// Manages a single participant in the epoch scheme. This is where all
// of the actual epoch management logic happens!

use std::{fmt, mem};
use std::cell::UnsafeCell;
use std::sync::atomic::{self, AtomicUsize, AtomicBool};

use mem::epoch::{Atomic, Guard, garbage, global};
use mem::epoch::participants::ParticipantNode;

/// The garbage collection threshold (in garbage items).
const GC_THRESHOLD: usize = 128;

/// Thread-local data for epoch participation.
pub struct Participant {
    /// The local epoch.
    ///
    /// This is incremented on new epochs.
    epoch: AtomicUsize,
    /// Number of pending uses of `epoch::pin()`.
    ///
    /// Keeping a count allows for reentrant use of epoch management.
    in_critical: AtomicUsize,
    /// The thread-local garbage tracking.
    garbage: UnsafeCell<garbage::Local>,
    /// Is the thread still active?
    ///
    /// This becomes `false` when the thread exits. This is ultimately used to free `Participant`
    /// records.
    pub active: AtomicBool,
    /// The next participant node.
    ///
    /// The participant list is coded intrusively; here's the pointer to the next node.
    pub next: Atomic<ParticipantNode>,
}

impl Participant {
    /// Enter a critical section.
    ///
    /// This method is reentrant, allowing for nested critical sections.
    ///
    /// It returns `true` is this is the first entry on the stack (as opposed to a re-entrant
    /// call).
    pub fn enter(&self) -> bool {
        // Increment the counter.
        if self.in_critical.fetch_add(1, atomic::Ordering::Relaxed) > 0 {
            // Since it was above zero, we return false.
            false
        } else {
            // This fence is critical to avoid reordering with the increment.
            atomic::fence(atomic::Ordering::SeqCst);

            // Load the global epoch counter and test if this epoch matches the global.
            let global_epoch = global::EPOCH.epoch.load(atomic::Ordering::Relaxed);
            if global_epoch != self.epoch.load(atomic::Ordering::Relaxed) {
                // As it isn't already at the global epoch count, set it.
                self.epoch.store(global_epoch, atomic::Ordering::Relaxed);

                // Then collect the garbage.
                unsafe {
                    (*self.garbage.get()).collect();
                }
            }

            true
        }
    }

    /// Exit the current (nested) critical section.
    pub fn exit(&self) {
        // Decrement the counter.
        self.in_critical.fetch_sub(1, atomic::Ordering::SeqCst);
    }

    /// Begin the reclamation process for a piece of data.
    pub unsafe fn reclaim<T>(&self, data: *mut T) {
        // Insert it into the garbage list.
        (*self.garbage.get()).insert(data);
    }

    /// Attempt to collect garbage by moving the global epoch forward.
    ///
    /// If it failed, it returns `Err(())`.
    pub fn try_collect(&self, guard: &Guard) -> Result<(), ()> {
        // Load the global epoch counter.
        let cur_epoch = global::EPOCH.epoch.load(atomic::Ordering::SeqCst);

        // Go over the participants to ensure that none are critical.
        for p in global::EPOCH.participants.iter(guard) {
            if p.is_critical() && p.epoch.load(atomic::Ordering::Relaxed) != cur_epoch {
                // A participant was in critical state, and can thus not be GC'd at this moment.
                return Err(());
            }
        }

        let new_epoch = cur_epoch.wrapping_add(1);

        // This fence is important to avoid reordering of the CAS with any of the previous loads.
        // TODO: Is this really necessary?
        atomic::fence(atomic::Ordering::Acquire);
        // CAS with the new epoch. The reason we do CAS and not a simple store is that we want to
        // solve the ABA problem, as another thread could have updated the counter, causing us to
        // reverting its changes. Hence, we must ensure that this is NOT the case.
        if global::EPOCH.epoch.compare_and_swap(cur_epoch, new_epoch, atomic::Ordering::SeqCst) != cur_epoch {
            // Another thread touched it, so the collection failed.
            return Err(());
        }

        // If you've come so far, everything is right for collecting the garbage, so let's do it.
        unsafe {
            (*self.garbage.get()).collect();
            global::EPOCH.garbage.collect(new_epoch.wrapping_add(1))
        }

        // Update the epoch counter. As the epoch was collected, the ABA problem shouldn't be an
        // issue here.
        // TODO: Is this really correct?
        self.epoch.store(new_epoch, atomic::Ordering::Release);

        Ok(())
    }

    /// Move the current thread-local garbage into the global garbage bags.
    pub fn migrate_garbage(&self) {
        // Load the current epoch counter.
        let cur_epoch = self.epoch.load(atomic::Ordering::Relaxed);
        // Replace the local garbage set with an empty set.
        let local = unsafe { mem::replace(&mut *self.garbage.get(), garbage::Local::default()) };
        // Insert each epoch-kind into the global set.
        global::EPOCH.garbage.insert(cur_epoch.wrapping_sub(1), local.old);
        global::EPOCH.garbage.insert(cur_epoch, local.cur);
        global::EPOCH.garbage.insert(cur_epoch.wrapping_add(1), local.new);

        // TODO
        // global::EPOCH.garbage[global::EPOCH.epoch.load(atomic::Ordering::Relaxed) % 3].insert(local.new);
    }

    /// How many garbage items is this participant currently storing?
    pub fn garbage_len(&self) -> usize {
        unsafe { (*self.garbage.get()).len() }
    }

    /// Is this participant past its local GC threshold?
    pub fn should_gc(&self) -> bool {
        // We only GC when the garbage length is above some threshold.
        self.garbage_len() >= GC_THRESHOLD
    }

    /// Is this participant in a critical state?
    ///
    /// "Critical state" means that an `epoch::pin()` is pending, and thus it cannot be modified
    /// ATM.
    fn is_critical(&self) -> bool {
        self.in_critical.load(atomic::Ordering::Relaxed) > 0
    }
}

unsafe impl Sync for Participant {}

impl fmt::Debug for Participant {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "Participant {{ ... }}")
    }
}

impl Default for Participant {
    fn default() -> Participant {
        Participant {
            epoch: AtomicUsize::new(0),
            in_critical: AtomicUsize::new(0),
            active: AtomicBool::new(true),
            garbage: UnsafeCell::new(garbage::Local::default()),
            next: Atomic::null(),
        }
    }
}
<|endoftext|>


<commit_before>extern crate memcache;
extern crate r2d2;
extern crate r2d2_memcache;

use r2d2_memcache::MemcacheConnectionManager;
use std::thread;

#[test]
fn get_thousand_data_parallel() {
    let config = r2d2::Config::default();
    let manager = MemcacheConnectionManager::new("memcache://localhost:11211");

    let pool = r2d2::Pool::new(config, manager).unwrap();
    {
        let pool = pool.clone();
        let mut conn = pool.get().unwrap();
        conn.flush().unwrap();
    }
    for i in 0..1000 {
        let pool = pool.clone();
        thread::spawn(move || {
            let mut conn = pool.get().unwrap();
            conn.flush().unwrap();
            let value = format!{"{}{}","bar_thousand",i};
            conn.set(&format!("{}{}", "foo_thousand", i), value, 0)
                .unwrap();
        });
    }
    for i in 0..1000 {
        let pool = pool.clone();
        thread::spawn(move || {
            let value = format!{"{}{}","bar_thousand",i};
            let mut conn = pool.get().unwrap();
            let result: String = conn.get(&format!("{}{}", "foo_thousand", i))
                .unwrap()
                .unwrap();
            assert!(result == value);
        });
    }
}
<commit_msg>fix get_thousand_data_parallel test<commit_after>extern crate memcache;
extern crate r2d2;
extern crate r2d2_memcache;

use r2d2_memcache::MemcacheConnectionManager;
use std::thread;

#[test]
fn get_thousand_data_parallel() {
    let config = r2d2::Config::default();
    let manager = MemcacheConnectionManager::new("memcache://localhost:11211");

    let pool = r2d2::Pool::new(config, manager).unwrap();
    {
        let pool = pool.clone();
        let mut conn = pool.get().unwrap();
        conn.flush().unwrap();
    }

    pool.get().unwrap().flush().unwrap();

    let mut threads = vec![];
    for i in 0..1000 {
        let pool = pool.clone();
        let t = thread::spawn(move || {
            let mut conn = pool.get().unwrap();
            let value = format!{"{}{}","bar_thousand_",i};
            conn.set(&format!("{}{}", "foo_thousand_", i), value, 0)
                .unwrap();
        });
        threads.push(t);
    }
    for thread in threads {
        thread.join().unwrap();
    }

    let mut threads = vec![];
    for i in 0..1000 {
        let pool = pool.clone();
        let t = thread::spawn(move || {
            let value = format! {"{}{}","bar_thousand_",i};
            let mut conn = pool.get().unwrap();
            let result: String = conn
                .get(&format!("{}{}", "foo_thousand_", i))
                .unwrap()
                .unwrap();
            assert!(result == value);
        });
        threads.push(t);
    }
    for thread in threads {
        thread.join().unwrap();
    }
}
<|endoftext|>


<commit_before>#[cfg(unix)]
pub use self::unix::*;
#[cfg(target_os = "linux")]
pub use self::linux::*;
#[cfg(windows)]
pub use self::windows::*;

// Add any operating systems we support here
#[cfg(not(any(target_os = "linux")))]
pub use self::default::*;

#[cfg(unix)]
mod unix;
#[cfg(target_os = "linux")]
mod linux;
#[cfg(windows)]
mod windows;

// Add any operating systems we support here
#[cfg(not(any(target_os = "linux")))]
mod default;
<commit_msg>uucore: allow the Linux zero-copy setup on Android<commit_after>#[cfg(unix)]
pub use self::unix::*;
#[cfg(any(target_os = "linux", target_os = "android"))]
pub use self::linux::*;
#[cfg(windows)]
pub use self::windows::*;

// Add any operating systems we support here
#[cfg(not(any(target_os = "linux", target_os = "android")))]
pub use self::default::*;

#[cfg(unix)]
mod unix;
#[cfg(any(target_os = "linux", target_os = "android"))]
mod linux;
#[cfg(windows)]
mod windows;

// Add any operating systems we support here
#[cfg(not(any(target_os = "linux", target_os = "android")))]
mod default;
<|endoftext|>


<commit_before>// mod prelude

pub use client::{Client, ClientList};
pub use channel::{Channel, ChannelList};
pub use connection::Connection;
pub use command::Command;

pub use error::{Result, Error, SQError};
<commit_msg>exporting types and functions from map<commit_after>//! The prelude exports all important structs and functions of sqlib.

pub use client::{Client, ClientList};
pub use channel::{Channel, ChannelList};
pub use connection::Connection;
pub use command::Command;
pub use map::{StringMap, to_map, update_from_map};

pub use error::{Result, Error, SQError};
<|endoftext|>