<commit_before>use std::mem;
use std::result;

use byteorder::{ByteOrder, BigEndian};

use serde;

use defs::*;
use error::*;

pub type Result = result::Result<(), Error>;

pub struct Serializer<F: FnMut(&[u8]) -> Result> {
    output: F
}

impl<F: FnMut(&[u8]) -> Result> Serializer<F> {
    pub const fn new(output: F) -> Serializer<F> {
        Serializer {
            output: output
        }
    }

    fn output(&mut self, buf: &[u8]) -> Result {
        self.output.call_mut((buf,))
    }
}

impl<F: FnMut(&[u8]) -> Result> serde::Serializer for Serializer<F> {
    type Error = Error;

    fn serialize_bool(&mut self, v: bool) -> Result {
        if v {
            self.output(&[TRUE])
        } else {
            self.output(&[FALSE])
        }
    }

    fn serialize_i64(&mut self, value: i64) -> Result {
        if value >= FIXINT_MIN as i64 && value <= FIXINT_MAX as i64 {
            self.output(&[unsafe {mem::transmute(value as i8)}])
        } else if value >= i8::min_value() as i64 && value <= i8::max_value() as i64 {
            self.output(&[INT8, unsafe {mem::transmute(value as i8)}])
        } else if value >= 0 && value <= u8::max_value() as i64 {
            self.output(&[UINT8, unsafe {mem::transmute(value as i8)}])
        } else if value >= i16::min_value() as i64 && value <= i16::max_value() as i64 {
            let mut buf = [INT16; U16_BYTES + 1];
            BigEndian::write_i16(&mut buf[1..], value as i16);
            self.output(&buf)
        } else if value >= 0 && value <= u16::max_value() as i64 {
            let mut buf = [UINT16; U16_BYTES + 1];
            BigEndian::write_u16(&mut buf[1..], value as u16);
            self.output(&buf)
        } else if value >= i32::min_value() as i64 && value <= i32::max_value() as i64 {
            let mut buf = [INT32; U32_BYTES + 1];
            BigEndian::write_i32(&mut buf[1..], value as i32);
            self.output(&buf)
        } else if value >= 0 && value <= u32::max_value() as i64 {
            let mut buf = [UINT32; U16_BYTES + 1];
            BigEndian::write_u32(&mut buf[1..], value as u32);
            self.output(&buf)
        } else {
            let mut buf = [INT64; U64_BYTES + 1];
            BigEndian::write_i64(&mut buf[1..], value);
            self.output(&buf)
        }
    }

    fn serialize_u64(&mut self, value: u64) -> Result {
        if value <= FIXINT_MAX as u64 {
            self.output(&[value as u8])
        } else if value <= u8::max_value() as u64 {
            self.output(&[UINT8, value as u8])
        } else if value <= u16::max_value() as u64 {
            let mut buf = [UINT16; U16_BYTES + 1];
            BigEndian::write_u16(&mut buf[1..], value as u16);
            self.output(&buf)
        } else if value <= u32::max_value() as u64 {
            let mut buf = [UINT32; U32_BYTES + 1];
            BigEndian::write_u32(&mut buf[1..], value as u32);
            self.output(&buf)
        } else {
            let mut buf = [UINT64; U64_BYTES + 1];
            BigEndian::write_u64(&mut buf[1..], value);
            self.output(&buf)
        }
    }

    fn serialize_f32(&mut self, value: f32) -> Result {
        let mut buf = [FLOAT32; U32_BYTES + 1];
        BigEndian::write_f32(&mut buf[1..], value);
        self.output(&buf)
    }

    fn serialize_f64(&mut self, value: f64) -> Result {
        let mut buf = [FLOAT64; U64_BYTES + 1];
        BigEndian::write_f64(&mut buf[1..], value);
        self.output(&buf)
    }

    fn serialize_str(&mut self, value: &str) -> Result {
        if value.len() <= MAX_FIXSTR {
            try!(self.output(&[value.len() as u8 | FIXSTR_MASK]));
        } else if value.len() <= MAX_STR8 {
            try!(self.output(&[STR8, value.len() as u8]));
        } else if value.len() <= MAX_STR16 {
            let mut buf = [STR16; U16_BYTES + 1];
            BigEndian::write_u16(&mut buf[1..], value.len() as u16);
            try!(self.output(&buf));
        } else if value.len() <= MAX_STR32 {
            let mut buf = [STR32; U32_BYTES + 1];
            BigEndian::write_u32(&mut buf[1..], value.len() as u32);
            try!(self.output(&buf));
        } else {
            return Err(Error::simple(Reason::TooBig));
        }

        self.output(value.as_bytes())
    }

    fn serialize_unit(&mut self) -> Result {
        self.output(&[NIL])
    }

    fn serialize_none(&mut self) -> Result {
        self.serialize_unit()
    }

    fn serialize_some<V>(&mut self, value: V) -> Result
        where V: serde::Serialize {
        value.serialize(self)
    }

    fn serialize_seq<V>(&mut self, mut visitor: V) -> Result
        where V: serde::ser::SeqVisitor {

        if let Some(size) = visitor.len() {
            if size <= MAX_FIXARRAY {
                try!(self.output(&[size as u8 | FIXARRAY_MASK]));
            } else if size <= MAX_ARRAY16 {
                let mut buf = [ARRAY16; U16_BYTES + 1];
                BigEndian::write_u16(&mut buf[1..], size as u16);
                try!(self.output(&buf));
            } else if size <= MAX_ARRAY32 {
                let mut buf = [ARRAY32; U32_BYTES + 1];
                BigEndian::write_u32(&mut buf[1..], size as u32);
                try!(self.output(&buf));
            } else {
                return Err(Error::simple(Reason::TooBig));
            }
        } else {
            return Err(Error::simple(Reason::Unsized));
        }

        loop {
            match visitor.visit(self) {
                Ok(Some(())) => {},
                Ok(None) => {
                    break;
                },
                Err(e) => {
                    return Err(e);
                }
            }
        }

        Ok(())
    }

    fn serialize_seq_elt<T>(&mut self, value: T) -> Result
        where T: serde::Serialize {
        value.serialize(self)
    }

    fn serialize_map<V>(&mut self, mut visitor: V) -> Result
        where V: serde::ser::MapVisitor {
        if let Some(size) = visitor.len() {
            if size <= MAX_FIXMAP {
                try!(self.output(&[size as u8 | FIXMAP_MASK]));
            } else if size <= MAX_MAP16 {
                let mut buf = [MAP16; U16_BYTES + 1];
                BigEndian::write_u16(&mut buf[1..], size as u16);
                try!(self.output(&buf));
            } else if size <= MAX_MAP32 {
                let mut buf = [MAP32; U32_BYTES + 1];
                BigEndian::write_u32(&mut buf[1..], size as u32);
                try!(self.output(&buf));
            } else {
                return Err(Error::simple(Reason::TooBig));
            }
        } else {
            return Err(Error::simple(Reason::Unsized));
        }

        loop {
            match visitor.visit(self) {
                Ok(Some(())) => {},
                Ok(None) => {
                    break;
                },
                Err(e) => {
                    return Err(e);
                }
            }
        }

        Ok(())
    }

    fn serialize_map_elt<K, V>(&mut self, key: K, value: V) -> Result
        where K: serde::Serialize, V: serde::Serialize {
        try!(key.serialize(self));
        value.serialize(self)
    }

    fn serialize_bytes(&mut self, value: &[u8]) -> Result {
        if value.len() <= MAX_BIN8 {
            try!(self.output(&[BIN8, value.len() as u8]));
        } else if value.len() <= MAX_BIN16 {
            let mut buf = [BIN16; U16_BYTES + 1];
            BigEndian::write_u16(&mut buf[1..], value.len() as u16);
            try!(self.output(&buf));
        } else if value.len() <= MAX_BIN32 {
            let mut buf = [BIN32; U32_BYTES + 1];
            BigEndian::write_u32(&mut buf[1..], value.len() as u32);
            try!(self.output(&buf));
        } else {
            return Err(Error::simple(Reason::TooBig));
        }

        self.output(value)
    }
}

#[cfg(test)]
mod test {
    use collections::Vec;

    #[test]
    fn positive_fixint_test() {
        let v: u8 = 23;
        assert_eq!(::to_bytes(v).unwrap(), &[0x17]);
    }

    #[test]
    fn negative_fixint_test() {
        let v: i8 = -5;
        assert_eq!(::to_bytes(v).unwrap(), &[0xfb]);
    }

    #[test]
    fn uint8_test() {
        let v: u8 = 154;
        assert_eq!(::to_bytes(v).unwrap(), &[0xcc, 0x9a]);
    }

    #[test]
    fn fixstr_test() {
        let s: &str = "Hello World!";
        assert_eq!(::to_bytes(s).unwrap(), &[0xac, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20,
                                             0x57, 0x6f, 0x72, 0x6c, 0x64, 0x21]);
    }

    #[test]
    fn str8_test() {
        let s: &str = "The quick brown fox jumps over the lazy dog";
        let mut fixture: Vec<u8> = vec![];
        fixture.push(0xd9);
        fixture.push(s.len() as u8);
        fixture.extend_from_slice(s.as_bytes());
        assert_eq!(::to_bytes(s).unwrap(), fixture);
    }

    #[test]
    fn fixarr_test() {
        let v: Vec<u8> = vec![5, 8, 20, 231];
        assert_eq!(::to_bytes(v).unwrap(), &[0x94, 0x05, 0x08, 0x14, 0xcc, 0xe7]);
    }

    #[test]
    fn array16_test() {
        let v: Vec<isize> = vec![-5, 16, 101, -45, 184,
                                 89, 62, -233, -33, 304,
                                 76, 90, 23, 108, 45,
                                 -3, 2];
        assert_eq!(::to_bytes(v).unwrap(), &[0xdc,
                                             0x00, 0x11,
                                             0xfb,  0x10,  0x65,  0xd0, 0xd3,  0xcc, 0xb8,
                                             0x59,  0x3e,  0xd1, 0xff, 0x17,  0xd0, 0xdf,  0xd1, 0x01, 0x30,
                                             0x4c, 0x5a, 0x17, 0x6c, 0x2d,
                                             0xfd, 0x02]);
    }
}
<commit_msg>Fix small typo<commit_after>use std::mem;
use std::result;

use byteorder::{ByteOrder, BigEndian};

use serde;

use defs::*;
use error::*;

pub type Result = result::Result<(), Error>;

pub struct Serializer<F: FnMut(&[u8]) -> Result> {
    output: F
}

impl<F: FnMut(&[u8]) -> Result> Serializer<F> {
    pub const fn new(output: F) -> Serializer<F> {
        Serializer {
            output: output
        }
    }

    fn output(&mut self, buf: &[u8]) -> Result {
        self.output.call_mut((buf,))
    }
}

impl<F: FnMut(&[u8]) -> Result> serde::Serializer for Serializer<F> {
    type Error = Error;

    fn serialize_bool(&mut self, v: bool) -> Result {
        if v {
            self.output(&[TRUE])
        } else {
            self.output(&[FALSE])
        }
    }

    fn serialize_i64(&mut self, value: i64) -> Result {
        if value >= FIXINT_MIN as i64 && value <= FIXINT_MAX as i64 {
            self.output(&[unsafe {mem::transmute(value as i8)}])
        } else if value >= i8::min_value() as i64 && value <= i8::max_value() as i64 {
            self.output(&[INT8, unsafe {mem::transmute(value as i8)}])
        } else if value >= 0 && value <= u8::max_value() as i64 {
            self.output(&[UINT8, unsafe {mem::transmute(value as u8)}])
        } else if value >= i16::min_value() as i64 && value <= i16::max_value() as i64 {
            let mut buf = [INT16; U16_BYTES + 1];
            BigEndian::write_i16(&mut buf[1..], value as i16);
            self.output(&buf)
        } else if value >= 0 && value <= u16::max_value() as i64 {
            let mut buf = [UINT16; U16_BYTES + 1];
            BigEndian::write_u16(&mut buf[1..], value as u16);
            self.output(&buf)
        } else if value >= i32::min_value() as i64 && value <= i32::max_value() as i64 {
            let mut buf = [INT32; U32_BYTES + 1];
            BigEndian::write_i32(&mut buf[1..], value as i32);
            self.output(&buf)
        } else if value >= 0 && value <= u32::max_value() as i64 {
            let mut buf = [UINT32; U16_BYTES + 1];
            BigEndian::write_u32(&mut buf[1..], value as u32);
            self.output(&buf)
        } else {
            let mut buf = [INT64; U64_BYTES + 1];
            BigEndian::write_i64(&mut buf[1..], value);
            self.output(&buf)
        }
    }

    fn serialize_u64(&mut self, value: u64) -> Result {
        if value <= FIXINT_MAX as u64 {
            self.output(&[value as u8])
        } else if value <= u8::max_value() as u64 {
            self.output(&[UINT8, value as u8])
        } else if value <= u16::max_value() as u64 {
            let mut buf = [UINT16; U16_BYTES + 1];
            BigEndian::write_u16(&mut buf[1..], value as u16);
            self.output(&buf)
        } else if value <= u32::max_value() as u64 {
            let mut buf = [UINT32; U32_BYTES + 1];
            BigEndian::write_u32(&mut buf[1..], value as u32);
            self.output(&buf)
        } else {
            let mut buf = [UINT64; U64_BYTES + 1];
            BigEndian::write_u64(&mut buf[1..], value);
            self.output(&buf)
        }
    }

    fn serialize_f32(&mut self, value: f32) -> Result {
        let mut buf = [FLOAT32; U32_BYTES + 1];
        BigEndian::write_f32(&mut buf[1..], value);
        self.output(&buf)
    }

    fn serialize_f64(&mut self, value: f64) -> Result {
        let mut buf = [FLOAT64; U64_BYTES + 1];
        BigEndian::write_f64(&mut buf[1..], value);
        self.output(&buf)
    }

    fn serialize_str(&mut self, value: &str) -> Result {
        if value.len() <= MAX_FIXSTR {
            try!(self.output(&[value.len() as u8 | FIXSTR_MASK]));
        } else if value.len() <= MAX_STR8 {
            try!(self.output(&[STR8, value.len() as u8]));
        } else if value.len() <= MAX_STR16 {
            let mut buf = [STR16; U16_BYTES + 1];
            BigEndian::write_u16(&mut buf[1..], value.len() as u16);
            try!(self.output(&buf));
        } else if value.len() <= MAX_STR32 {
            let mut buf = [STR32; U32_BYTES + 1];
            BigEndian::write_u32(&mut buf[1..], value.len() as u32);
            try!(self.output(&buf));
        } else {
            return Err(Error::simple(Reason::TooBig));
        }

        self.output(value.as_bytes())
    }

    fn serialize_unit(&mut self) -> Result {
        self.output(&[NIL])
    }

    fn serialize_none(&mut self) -> Result {
        self.serialize_unit()
    }

    fn serialize_some<V>(&mut self, value: V) -> Result
        where V: serde::Serialize {
        value.serialize(self)
    }

    fn serialize_seq<V>(&mut self, mut visitor: V) -> Result
        where V: serde::ser::SeqVisitor {

        if let Some(size) = visitor.len() {
            if size <= MAX_FIXARRAY {
                try!(self.output(&[size as u8 | FIXARRAY_MASK]));
            } else if size <= MAX_ARRAY16 {
                let mut buf = [ARRAY16; U16_BYTES + 1];
                BigEndian::write_u16(&mut buf[1..], size as u16);
                try!(self.output(&buf));
            } else if size <= MAX_ARRAY32 {
                let mut buf = [ARRAY32; U32_BYTES + 1];
                BigEndian::write_u32(&mut buf[1..], size as u32);
                try!(self.output(&buf));
            } else {
                return Err(Error::simple(Reason::TooBig));
            }
        } else {
            return Err(Error::simple(Reason::Unsized));
        }

        loop {
            match visitor.visit(self) {
                Ok(Some(())) => {},
                Ok(None) => {
                    break;
                },
                Err(e) => {
                    return Err(e);
                }
            }
        }

        Ok(())
    }

    fn serialize_seq_elt<T>(&mut self, value: T) -> Result
        where T: serde::Serialize {
        value.serialize(self)
    }

    fn serialize_map<V>(&mut self, mut visitor: V) -> Result
        where V: serde::ser::MapVisitor {
        if let Some(size) = visitor.len() {
            if size <= MAX_FIXMAP {
                try!(self.output(&[size as u8 | FIXMAP_MASK]));
            } else if size <= MAX_MAP16 {
                let mut buf = [MAP16; U16_BYTES + 1];
                BigEndian::write_u16(&mut buf[1..], size as u16);
                try!(self.output(&buf));
            } else if size <= MAX_MAP32 {
                let mut buf = [MAP32; U32_BYTES + 1];
                BigEndian::write_u32(&mut buf[1..], size as u32);
                try!(self.output(&buf));
            } else {
                return Err(Error::simple(Reason::TooBig));
            }
        } else {
            return Err(Error::simple(Reason::Unsized));
        }

        loop {
            match visitor.visit(self) {
                Ok(Some(())) => {},
                Ok(None) => {
                    break;
                },
                Err(e) => {
                    return Err(e);
                }
            }
        }

        Ok(())
    }

    fn serialize_map_elt<K, V>(&mut self, key: K, value: V) -> Result
        where K: serde::Serialize, V: serde::Serialize {
        try!(key.serialize(self));
        value.serialize(self)
    }

    fn serialize_bytes(&mut self, value: &[u8]) -> Result {
        if value.len() <= MAX_BIN8 {
            try!(self.output(&[BIN8, value.len() as u8]));
        } else if value.len() <= MAX_BIN16 {
            let mut buf = [BIN16; U16_BYTES + 1];
            BigEndian::write_u16(&mut buf[1..], value.len() as u16);
            try!(self.output(&buf));
        } else if value.len() <= MAX_BIN32 {
            let mut buf = [BIN32; U32_BYTES + 1];
            BigEndian::write_u32(&mut buf[1..], value.len() as u32);
            try!(self.output(&buf));
        } else {
            return Err(Error::simple(Reason::TooBig));
        }

        self.output(value)
    }
}

#[cfg(test)]
mod test {
    use collections::Vec;

    #[test]
    fn positive_fixint_test() {
        let v: u8 = 23;
        assert_eq!(::to_bytes(v).unwrap(), &[0x17]);
    }

    #[test]
    fn negative_fixint_test() {
        let v: i8 = -5;
        assert_eq!(::to_bytes(v).unwrap(), &[0xfb]);
    }

    #[test]
    fn uint8_test() {
        let v: u8 = 154;
        assert_eq!(::to_bytes(v).unwrap(), &[0xcc, 0x9a]);
    }

    #[test]
    fn fixstr_test() {
        let s: &str = "Hello World!";
        assert_eq!(::to_bytes(s).unwrap(), &[0xac, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20,
                                             0x57, 0x6f, 0x72, 0x6c, 0x64, 0x21]);
    }

    #[test]
    fn str8_test() {
        let s: &str = "The quick brown fox jumps over the lazy dog";
        let mut fixture: Vec<u8> = vec![];
        fixture.push(0xd9);
        fixture.push(s.len() as u8);
        fixture.extend_from_slice(s.as_bytes());
        assert_eq!(::to_bytes(s).unwrap(), fixture);
    }

    #[test]
    fn fixarr_test() {
        let v: Vec<u8> = vec![5, 8, 20, 231];
        assert_eq!(::to_bytes(v).unwrap(), &[0x94, 0x05, 0x08, 0x14, 0xcc, 0xe7]);
    }

    #[test]
    fn array16_test() {
        let v: Vec<isize> = vec![-5, 16, 101, -45, 184,
                                 89, 62, -233, -33, 304,
                                 76, 90, 23, 108, 45,
                                 -3, 2];
        assert_eq!(::to_bytes(v).unwrap(), &[0xdc,
                                             0x00, 0x11,
                                             0xfb,  0x10,  0x65,  0xd0, 0xd3,  0xcc, 0xb8,
                                             0x59,  0x3e,  0xd1, 0xff, 0x17,  0xd0, 0xdf,  0xd1, 0x01, 0x30,
                                             0x4c, 0x5a, 0x17, 0x6c, 0x2d,
                                             0xfd, 0x02]);
    }
}
<|endoftext|>


<commit_before>use std::{
    sync::{
        atomic::{AtomicBool, AtomicUsize, Ordering},
        Arc,
    },
    thread,
};

use docopt::Docopt;
use rand::{thread_rng, Rng};
use serde::Deserialize;

#[cfg_attr(
    // only enable jemalloc on linux and macos by default
    all(
        any(target_os = "linux", target_os = "macos"),
        not(feature = "no_jemalloc"),
    ),
    global_allocator
)]
static ALLOC: jemallocator::Jemalloc = jemallocator::Jemalloc;

static TOTAL: AtomicUsize = AtomicUsize::new(0);
static SEQ: AtomicUsize = AtomicUsize::new(0);

const USAGE: &'static str = "
Usage: stress [--threads=<#>] [--burn-in] [--duration=<s>] \
    [--key-len=<l>] [--val-len=<l>] \
    [--get-prop=<p>] \
    [--set-prop=<p>] \
    [--del-prop=<p>] \
    [--cas-prop=<p>] \
    [--scan-prop=<p>] \
    [--merge-prop=<p>] \
    [--entries=<n>] \
    [--sequential] \
    [--total-ops=<n>] \
    [--async]

Options:
    --threads=<#>      Number of threads [default: 4].
    --burn-in          Don't halt until we receive a signal.
    --duration=<s>     Seconds to run for [default: 10].
    --key-len=<l>      The length of keys [default: 10].
    --val-len=<l>      The length of values [default: 100].
    --get-prop=<p>     The relative proportion of get requests [default: 94].
    --set-prop=<p>     The relative proportion of set requests [default: 2].
    --del-prop=<p>     The relative proportion of del requests [default: 1].
    --cas-prop=<p>     The relative proportion of cas requests [default: 1].
    --scan-prop=<p>    The relative proportion of scan requests [default: 1].
    --merge-prop=<p>   The relative proportion of merge requests [default: 1].
    --entries=<n>      The total keyspace [default: 100000].
    --sequential       Run the test in sequential mode instead of random.
    --total-ops=<n>    Stop test after executing a total number of operations.
    --async            Use a threadpool to perform disk IO in the background.
";

#[derive(Deserialize, Clone)]
struct Args {
    flag_threads: usize,
    flag_burn_in: bool,
    flag_duration: u64,
    flag_key_len: usize,
    flag_val_len: usize,
    flag_get_prop: usize,
    flag_set_prop: usize,
    flag_del_prop: usize,
    flag_cas_prop: usize,
    flag_scan_prop: usize,
    flag_merge_prop: usize,
    flag_entries: usize,
    flag_sequential: bool,
    flag_total_ops: Option<usize>,
    flag_async: bool,
}

// defaults will be applied later based on USAGE above
static mut ARGS: Args = Args {
    flag_threads: 0,
    flag_burn_in: false,
    flag_duration: 0,
    flag_key_len: 0,
    flag_val_len: 0,
    flag_get_prop: 0,
    flag_set_prop: 0,
    flag_del_prop: 0,
    flag_cas_prop: 0,
    flag_scan_prop: 0,
    flag_merge_prop: 0,
    flag_entries: 0,
    flag_sequential: false,
    flag_total_ops: None,
    flag_async: false,
};

fn report(shutdown: Arc<AtomicBool>) {
    let mut last = 0;
    while !shutdown.load(Ordering::Relaxed) {
        thread::sleep(std::time::Duration::from_secs(1));
        let total = TOTAL.load(Ordering::Acquire);

        println!("did {} ops", total - last);

        last = total;
    }
}

fn concatenate_merge(
    _key: &[u8],              // the key being merged
    old_value: Option<&[u8]>, // the previous value, if one existed
    merged_bytes: &[u8],      // the new bytes being merged in
) -> Option<Vec<u8>> {
    // set the new value, return None to delete
    let mut ret = old_value.map(|ov| ov.to_vec()).unwrap_or_else(|| vec![]);

    ret.extend_from_slice(merged_bytes);

    Some(ret)
}

fn run(tree: Arc<sled::Db>, shutdown: Arc<AtomicBool>) {
    let args = unsafe { ARGS.clone() };

    let get_max = args.flag_get_prop;
    let set_max = get_max + args.flag_set_prop;
    let del_max = set_max + args.flag_del_prop;
    let cas_max = del_max + args.flag_cas_prop;
    let scan_max = cas_max + args.flag_scan_prop;
    let merge_max = scan_max + args.flag_merge_prop;

    let bytes = |len| -> Vec<u8> {
        let i = if args.flag_sequential {
            SEQ.fetch_add(1, Ordering::Relaxed)
        } else {
            thread_rng().gen::<usize>()
        } % args.flag_entries;

        let i_bytes: [u8; std::mem::size_of::<usize>()] =
            unsafe { std::mem::transmute(i) };

        i_bytes.into_iter().cycle().take(len).cloned().collect()
    };
    let mut rng = thread_rng();

    while !shutdown.load(Ordering::Relaxed) {
        TOTAL.fetch_add(1, Ordering::Release);
        let key = bytes(args.flag_key_len);
        let choice = rng.gen_range(0, merge_max + 1);

        match choice {
            v if v <= get_max => {
                tree.get(&key).unwrap();
            }
            v if v > get_max && v <= set_max => {
                tree.insert(&key, bytes(args.flag_val_len)).unwrap();
            }
            v if v > set_max && v <= del_max => {
                tree.remove(&key).unwrap();
            }
            v if v > del_max && v <= cas_max => {
                let old_k = bytes(args.flag_val_len);

                let old = if rng.gen::<bool>() {
                    Some(old_k.as_slice())
                } else {
                    None
                };

                let new = if rng.gen::<bool>() {
                    Some(bytes(args.flag_val_len))
                } else {
                    None
                };

                if let Err(e) = tree.cas(&key, old, new) {
                    panic!("operational error: {:?}", e);
                }
            }
            v if v > cas_max && v <= scan_max => {
                let iter = tree.range(key..).map(|res| res.unwrap());

                if v % 2 == 0 {
                    let _ = iter.take(rng.gen_range(0, 15)).collect::<Vec<_>>();
                } else {
                    let _ = iter
                        .rev()
                        .take(rng.gen_range(0, 15))
                        .collect::<Vec<_>>();
                }
            }
            _ => {
                tree.merge(&key, bytes(args.flag_val_len)).unwrap();
            }
        }
    }
}

fn main() {
    setup_logger();

    let args = unsafe {
        ARGS = Docopt::new(USAGE)
            .and_then(|d| d.argv(std::env::args().into_iter()).deserialize())
            .unwrap_or_else(|e| e.exit());
        ARGS.clone()
    };

    let shutdown = Arc::new(AtomicBool::new(false));

    let config = sled::ConfigBuilder::new()
        .io_bufs(16)
        .io_buf_size(8_000_000)
        .async_io(args.flag_async)
        .blink_node_split_size(4096)
        .page_consolidation_threshold(10)
        .cache_bits(8)
        .cache_capacity(1_000_000_000)
        .flush_every_ms(Some(200))
        .snapshot_after_ops(100_000_000_000)
        .print_profile_on_drop(true)
        .merge_operator(concatenate_merge)
        .build();

    let tree = Arc::new(sled::Db::start(config).unwrap());

    let mut threads = vec![];

    let now = std::time::Instant::now();

    let n_threads = args.flag_threads;

    for i in 0..n_threads + 1 {
        let tree = tree.clone();
        let shutdown = shutdown.clone();

        let t = if i == 0 {
            thread::Builder::new()
                .name("reporter".into())
                .spawn(move || report(shutdown))
                .unwrap()
        } else {
            thread::Builder::new()
                .name(format!("t({})", i))
                .spawn(move || run(tree, shutdown))
                .unwrap()
        };

        threads.push(t);
    }

    if let Some(ops) = args.flag_total_ops {
        assert!(
            !args.flag_burn_in,
            "don't set both --burn-in and --total-ops"
        );
        while TOTAL.load(Ordering::Relaxed) < ops {
            thread::sleep(std::time::Duration::from_millis(50));
        }
        shutdown.store(true, Ordering::SeqCst);
    } else if !args.flag_burn_in {
        thread::sleep(std::time::Duration::from_secs(unsafe {
            ARGS.flag_duration
        }));
        shutdown.store(true, Ordering::SeqCst);
    }

    for t in threads.into_iter() {
        t.join().unwrap();
    }

    let ops = TOTAL.load(Ordering::SeqCst);
    let time = now.elapsed().as_secs() as usize;

    println!(
        "did {} total ops in {} seconds. {} ops/s",
        ops,
        time,
        (ops * 1_000) / (time * 1_000)
    );
}

pub fn setup_logger() {
    use std::io::Write;

    color_backtrace::install();

    fn tn() -> String {
        std::thread::current()
            .name()
            .unwrap_or("unknown")
            .to_owned()
    }

    let mut builder = env_logger::Builder::new();
    builder
        .format(|buf, record| {
            writeln!(
                buf,
                "{:05} {:25} {:10} {}",
                record.level(),
                tn(),
                record.module_path().unwrap().split("::").last().unwrap(),
                record.args()
            )
        })
        .filter(None, log::LevelFilter::Info);

    if std::env::var("RUST_LOG").is_ok() {
        builder.parse(&std::env::var("RUST_LOG").unwrap());
    }

    let _r = builder.try_init();
}
<commit_msg>keep stress2 threads named the same to keep flamegraphs nicer to read<commit_after>use std::{
    sync::{
        atomic::{AtomicBool, AtomicUsize, Ordering},
        Arc,
    },
    thread,
};

use docopt::Docopt;
use rand::{thread_rng, Rng};
use serde::Deserialize;

#[cfg_attr(
    // only enable jemalloc on linux and macos by default
    all(
        any(target_os = "linux", target_os = "macos"),
        not(feature = "no_jemalloc"),
    ),
    global_allocator
)]
static ALLOC: jemallocator::Jemalloc = jemallocator::Jemalloc;

static TOTAL: AtomicUsize = AtomicUsize::new(0);
static SEQ: AtomicUsize = AtomicUsize::new(0);

const USAGE: &'static str = "
Usage: stress [--threads=<#>] [--burn-in] [--duration=<s>] \
    [--key-len=<l>] [--val-len=<l>] \
    [--get-prop=<p>] \
    [--set-prop=<p>] \
    [--del-prop=<p>] \
    [--cas-prop=<p>] \
    [--scan-prop=<p>] \
    [--merge-prop=<p>] \
    [--entries=<n>] \
    [--sequential] \
    [--total-ops=<n>] \
    [--async]

Options:
    --threads=<#>      Number of threads [default: 4].
    --burn-in          Don't halt until we receive a signal.
    --duration=<s>     Seconds to run for [default: 10].
    --key-len=<l>      The length of keys [default: 10].
    --val-len=<l>      The length of values [default: 100].
    --get-prop=<p>     The relative proportion of get requests [default: 94].
    --set-prop=<p>     The relative proportion of set requests [default: 2].
    --del-prop=<p>     The relative proportion of del requests [default: 1].
    --cas-prop=<p>     The relative proportion of cas requests [default: 1].
    --scan-prop=<p>    The relative proportion of scan requests [default: 1].
    --merge-prop=<p>   The relative proportion of merge requests [default: 1].
    --entries=<n>      The total keyspace [default: 100000].
    --sequential       Run the test in sequential mode instead of random.
    --total-ops=<n>    Stop test after executing a total number of operations.
    --async            Use a threadpool to perform disk IO in the background.
";

#[derive(Deserialize, Clone)]
struct Args {
    flag_threads: usize,
    flag_burn_in: bool,
    flag_duration: u64,
    flag_key_len: usize,
    flag_val_len: usize,
    flag_get_prop: usize,
    flag_set_prop: usize,
    flag_del_prop: usize,
    flag_cas_prop: usize,
    flag_scan_prop: usize,
    flag_merge_prop: usize,
    flag_entries: usize,
    flag_sequential: bool,
    flag_total_ops: Option<usize>,
    flag_async: bool,
}

// defaults will be applied later based on USAGE above
static mut ARGS: Args = Args {
    flag_threads: 0,
    flag_burn_in: false,
    flag_duration: 0,
    flag_key_len: 0,
    flag_val_len: 0,
    flag_get_prop: 0,
    flag_set_prop: 0,
    flag_del_prop: 0,
    flag_cas_prop: 0,
    flag_scan_prop: 0,
    flag_merge_prop: 0,
    flag_entries: 0,
    flag_sequential: false,
    flag_total_ops: None,
    flag_async: false,
};

fn report(shutdown: Arc<AtomicBool>) {
    let mut last = 0;
    while !shutdown.load(Ordering::Relaxed) {
        thread::sleep(std::time::Duration::from_secs(1));
        let total = TOTAL.load(Ordering::Acquire);

        println!("did {} ops", total - last);

        last = total;
    }
}

fn concatenate_merge(
    _key: &[u8],              // the key being merged
    old_value: Option<&[u8]>, // the previous value, if one existed
    merged_bytes: &[u8],      // the new bytes being merged in
) -> Option<Vec<u8>> {
    // set the new value, return None to delete
    let mut ret = old_value.map(|ov| ov.to_vec()).unwrap_or_else(|| vec![]);

    ret.extend_from_slice(merged_bytes);

    Some(ret)
}

fn run(tree: Arc<sled::Db>, shutdown: Arc<AtomicBool>) {
    let args = unsafe { ARGS.clone() };

    let get_max = args.flag_get_prop;
    let set_max = get_max + args.flag_set_prop;
    let del_max = set_max + args.flag_del_prop;
    let cas_max = del_max + args.flag_cas_prop;
    let scan_max = cas_max + args.flag_scan_prop;
    let merge_max = scan_max + args.flag_merge_prop;

    let bytes = |len| -> Vec<u8> {
        let i = if args.flag_sequential {
            SEQ.fetch_add(1, Ordering::Relaxed)
        } else {
            thread_rng().gen::<usize>()
        } % args.flag_entries;

        let i_bytes: [u8; std::mem::size_of::<usize>()] =
            unsafe { std::mem::transmute(i) };

        i_bytes.into_iter().cycle().take(len).cloned().collect()
    };
    let mut rng = thread_rng();

    while !shutdown.load(Ordering::Relaxed) {
        TOTAL.fetch_add(1, Ordering::Release);
        let key = bytes(args.flag_key_len);
        let choice = rng.gen_range(0, merge_max + 1);

        match choice {
            v if v <= get_max => {
                tree.get(&key).unwrap();
            }
            v if v > get_max && v <= set_max => {
                tree.insert(&key, bytes(args.flag_val_len)).unwrap();
            }
            v if v > set_max && v <= del_max => {
                tree.remove(&key).unwrap();
            }
            v if v > del_max && v <= cas_max => {
                let old_k = bytes(args.flag_val_len);

                let old = if rng.gen::<bool>() {
                    Some(old_k.as_slice())
                } else {
                    None
                };

                let new = if rng.gen::<bool>() {
                    Some(bytes(args.flag_val_len))
                } else {
                    None
                };

                if let Err(e) = tree.cas(&key, old, new) {
                    panic!("operational error: {:?}", e);
                }
            }
            v if v > cas_max && v <= scan_max => {
                let iter = tree.range(key..).map(|res| res.unwrap());

                if v % 2 == 0 {
                    let _ = iter.take(rng.gen_range(0, 15)).collect::<Vec<_>>();
                } else {
                    let _ = iter
                        .rev()
                        .take(rng.gen_range(0, 15))
                        .collect::<Vec<_>>();
                }
            }
            _ => {
                tree.merge(&key, bytes(args.flag_val_len)).unwrap();
            }
        }
    }
}

fn main() {
    setup_logger();

    let args = unsafe {
        ARGS = Docopt::new(USAGE)
            .and_then(|d| d.argv(std::env::args().into_iter()).deserialize())
            .unwrap_or_else(|e| e.exit());
        ARGS.clone()
    };

    let shutdown = Arc::new(AtomicBool::new(false));

    let config = sled::ConfigBuilder::new()
        .io_bufs(16)
        .io_buf_size(8_000_000)
        .async_io(args.flag_async)
        .blink_node_split_size(4096)
        .page_consolidation_threshold(10)
        .cache_bits(8)
        .cache_capacity(1_000_000_000)
        .flush_every_ms(Some(200))
        .snapshot_after_ops(100_000_000_000)
        .print_profile_on_drop(true)
        .merge_operator(concatenate_merge)
        .build();

    let tree = Arc::new(sled::Db::start(config).unwrap());

    let mut threads = vec![];

    let now = std::time::Instant::now();

    let n_threads = args.flag_threads;

    for i in 0..n_threads + 1 {
        let tree = tree.clone();
        let shutdown = shutdown.clone();

        let t = if i == 0 {
            thread::Builder::new()
                .name("reporter".into())
                .spawn(move || report(shutdown))
                .unwrap()
        } else {
            thread::spawn(move || run(tree, shutdown))
        };

        threads.push(t);
    }

    if let Some(ops) = args.flag_total_ops {
        assert!(
            !args.flag_burn_in,
            "don't set both --burn-in and --total-ops"
        );
        while TOTAL.load(Ordering::Relaxed) < ops {
            thread::sleep(std::time::Duration::from_millis(50));
        }
        shutdown.store(true, Ordering::SeqCst);
    } else if !args.flag_burn_in {
        thread::sleep(std::time::Duration::from_secs(unsafe {
            ARGS.flag_duration
        }));
        shutdown.store(true, Ordering::SeqCst);
    }

    for t in threads.into_iter() {
        t.join().unwrap();
    }

    let ops = TOTAL.load(Ordering::SeqCst);
    let time = now.elapsed().as_secs() as usize;

    println!(
        "did {} total ops in {} seconds. {} ops/s",
        ops,
        time,
        (ops * 1_000) / (time * 1_000)
    );
}

pub fn setup_logger() {
    use std::io::Write;

    color_backtrace::install();

    fn tn() -> String {
        std::thread::current()
            .name()
            .unwrap_or("unknown")
            .to_owned()
    }

    let mut builder = env_logger::Builder::new();
    builder
        .format(|buf, record| {
            writeln!(
                buf,
                "{:05} {:25} {:10} {}",
                record.level(),
                tn(),
                record.module_path().unwrap().split("::").last().unwrap(),
                record.args()
            )
        })
        .filter(None, log::LevelFilter::Info);

    if std::env::var("RUST_LOG").is_ok() {
        builder.parse(&std::env::var("RUST_LOG").unwrap());
    }

    let _r = builder.try_init();
}
<|endoftext|>


<commit_before>extern crate rustyline;
extern crate easy_ll;
extern crate weld;

use rustyline::error::ReadlineError;
use rustyline::Editor;
use std::env;
use std::path::PathBuf;
use weld::ast::ExprKind::*;
use weld::llvm::LlvmGenerator;
use weld::macro_processor;
use weld::parser::*;
use weld::pretty_print::*;
use weld::transforms;
use weld::type_inference::*;
use weld::sir::ast_to_sir;

fn main() {
    let home_path = env::home_dir().unwrap_or(PathBuf::new());
    let history_file_path = home_path.join(".weld_history");
    let history_file_path = history_file_path.to_str().unwrap_or(".weld_history");

    let mut rl = Editor::<()>::new();
    rl.load_history(&history_file_path).unwrap();

    loop {
        let raw_readline = rl.readline(">> ");
        let readline;
        match raw_readline {
            Ok(raw_readline) => {
                rl.add_history_entry(&raw_readline);
                readline = raw_readline;
            }
            Err(ReadlineError::Interrupted) => {
                println!("Exiting!");
                break;
            }
            Err(ReadlineError::Eof) => {
                println!("Exiting!");
                break;
            }
            Err(err) => {
                println!("Error: {:?}", err);
                break;
            }
        }

        let trimmed = readline.trim();
        if trimmed == "" {
            continue;
        }

        let program = parse_program(trimmed);
        if let Err(ref e) = program {
            println!("Error during parsing: {:?}", e);
            continue;
        }
        let program = program.unwrap();
        println!("Raw structure:\n{:?}\n", program);

        let expr = macro_processor::process_program(&program);
        if let Err(ref e) = expr {
            println!("Error during macro substitution: {}", e);
            continue;
        }
        let mut expr = expr.unwrap();
        println!("After macro substitution:\n{}\n", print_expr(&expr));

        transforms::inline_apply(&mut expr);
        println!("After inlining applies:\n{}\n", print_expr(&expr));

        if let Err(ref e) = infer_types(&mut expr) {
            println!("Error during type inference: {}\n", e);
            println!("Partially inferred types:\n{}\n", print_typed_expr(&expr));
            continue;
        }
        println!("After type inference:\n{}\n", print_typed_expr(&expr));
        println!("Expression type: {}\n", print_type(&expr.ty));

        let mut expr = expr.to_typed().unwrap();

        transforms::fuse_loops_horizontal(&mut expr);
        println!("After horizontal loop fusion:\n{}\n",
                 print_typed_expr(&expr));

        transforms::fuse_loops_vertical(&mut expr);
        println!("After vertical loop fusion:\n{}\n", print_typed_expr(&expr));

        if let Lambda { ref params, ref body } = expr.kind {
            let mut generator = LlvmGenerator::new();
            if let Err(ref e) = generator.add_function_on_pointers("run", params, body) {
                println!("Error during LLVM code gen:\n{}\n", e);
                continue;
            }
            let llvm_code = generator.result();
            println!("LLVM code:\n{}\n", llvm_code);

            if let Err(ref e) = easy_ll::compile_module(&llvm_code) {
                println!("Error during LLVM compilation:\n{}\n", e);
                continue;
            }
            println!("LLVM module compiled successfully\n");

            match ast_to_sir(&expr) {
                Ok(sir) => println!("SIR representation:\n{}\n", sir),
                Err(ref e) => println!("Error during SIR code gen:\n{}\n", e)
            };
        } else {
            println!("Expression is not a function, so not compiling to LLVM.\n")
        }
    }
    rl.save_history(&history_file_path).unwrap();
}
<commit_msg>stuff<commit_after>extern crate rustyline;
extern crate easy_ll;
extern crate weld;

use rustyline::error::ReadlineError;
use rustyline::Editor;
use std::env;
use std::path::PathBuf;
use weld::ast::ExprKind::*;
use weld::llvm::LlvmGenerator;
use weld::macro_processor;
use weld::parser::*;
use weld::pretty_print::*;
use weld::transforms;
use weld::type_inference::*;
use weld::sir::ast_to_sir;

fn main() {
    let home_path = env::home_dir().unwrap_or(PathBuf::new());
    let history_file_path = home_path.join(".weld_history");
    let history_file_path = history_file_path.to_str().unwrap_or(".weld_history");

    let mut rl = Editor::<()>::new();
    rl.load_history(&history_file_path).unwrap();

    loop {
        let raw_readline = rl.readline(">> ");
        let readline;
        match raw_readline {
            Ok(raw_readline) => {
                rl.add_history_entry(&raw_readline);
                readline = raw_readline;
            }
            Err(ReadlineError::Interrupted) => {
                println!("Exiting!");
                break;
            }
            Err(ReadlineError::Eof) => {
                println!("Exiting!");
                break;
            }
            Err(err) => {
                println!("Error: {:?}", err);
                break;
            }
        }

        let trimmed = readline.trim();
        if trimmed == "" {
            continue;
        }

        let program = parse_program(trimmed);
        if let Err(ref e) = program {
            println!("Error during parsing: {:?}", e);
            continue;
        }
        let program = program.unwrap();
        println!("Raw structure:\n{:?}\n", program);

        let expr = macro_processor::process_program(&program);
        if let Err(ref e) = expr {
            println!("Error during macro substitution: {}", e);
            continue;
        }
        let mut expr = expr.unwrap();
        println!("After macro substitution:\n{}\n", print_expr(&expr));

        transforms::inline_apply(&mut expr);
        println!("After inlining applies:\n{}\n", print_expr(&expr));

        if let Err(ref e) = infer_types(&mut expr) {
            println!("Error during type inference: {}\n", e);
            println!("Partially inferred types:\n{}\n", print_typed_expr(&expr));
            continue;
        }
        println!("After type inference:\n{}\n", print_typed_expr(&expr));
        println!("Expression type: {}\n", print_type(&expr.ty));

        let mut expr = expr.to_typed().unwrap();

        transforms::fuse_loops_horizontal(&mut expr);
        println!("After horizontal loop fusion:\n{}\n",
                 print_typed_expr(&expr));

        transforms::fuse_loops_vertical(&mut expr);
        println!("After vertical loop fusion:\n{}\n", print_typed_expr(&expr));

        if let Lambda { ref params, ref body } = expr.kind {
            let mut generator = LlvmGenerator::new();
            if let Err(ref e) = generator.add_function_on_pointers("run", params, body) {
                println!("Error during LLVM code gen:\n{}\n", e);
                continue;
            }
            let llvm_code = generator.result();
            println!("LLVM code:\n{}\n", llvm_code);

            if let Err(ref e) = easy_ll::compile_module(&llvm_code) {
                println!("Error during LLVM compilation:\n{}\n", e);
            } else {
                println!("LLVM module compiled successfully\n");
            }

            match ast_to_sir(&expr) {
                Ok(sir) => println!("SIR representation:\n{}\n", sir),
                Err(ref e) => println!("Error during SIR code gen:\n{}\n", e)
            }
        } else {
            println!("Expression is not a function, so not compiling to LLVM.\n");
        }
    }
    rl.save_history(&history_file_path).unwrap();
}
<|endoftext|>


<commit_before>mod bindings {
    include!(concat!(env!("OUT_DIR"), "/test.rs"));
}

use std::ffi::CStr;

#[test]
fn test_static_method() {
    let c_str = unsafe { bindings::Test::name() };
    let name = unsafe {
        CStr::from_ptr(c_str).to_string_lossy().into_owned()
    };
    assert_eq!(name, "Test", "Calling a static C++ method works!");
}

#[test]
fn test_constructor() {
    let test = unsafe { bindings::Test::new(5) };
    assert_eq!(test.m_int, 5);
    assert_eq!(test.m_double, 0.0);
}

#[test]
fn test_overload() {
    let test = unsafe { bindings::Test::new1(5.0) };
    assert_eq!(test.m_int, 0);
    assert_eq!(test.m_double, 5.0);
}
<commit_msg>bindgen-integration: run `cargo fmt`<commit_after>mod bindings {
    include!(concat!(env!("OUT_DIR"), "/test.rs"));
}

use std::ffi::CStr;

#[test]
fn test_static_method() {
    let c_str = unsafe { bindings::Test::name() };
    let name = unsafe { CStr::from_ptr(c_str).to_string_lossy().into_owned() };
    assert_eq!(name, "Test", "Calling a static C++ method works!");
}

#[test]
fn test_constructor() {
    let test = unsafe { bindings::Test::new(5) };
    assert_eq!(test.m_int, 5);
    assert_eq!(test.m_double, 0.0);
}

#[test]
fn test_overload() {
    let test = unsafe { bindings::Test::new1(5.0) };
    assert_eq!(test.m_int, 0);
    assert_eq!(test.m_double, 5.0);
}
<|endoftext|>


<commit_before>use ffi;

use Push;
use PushGuard;
use AsMutLua;

use std::collections::{HashMap, HashSet};
use std::hash::Hash;
use std::iter;
use std::mem;

fn push_iter<L, V, I>(mut lua: L, iterator: I) -> PushGuard<L>
                      where L: AsMutLua, V: for<'b> Push<&'b mut L>, I: Iterator<Item=V>
{
    // creating empty table
    unsafe { ffi::lua_newtable(lua.as_mut_lua().0) };

    for (elem, index) in iterator.zip(iter::count(1u, 1u)) {
        let size = {
            let pushed_cnt = elem.push_to_lua(&mut lua);

            let size = pushed_cnt.size;
            unsafe { mem::forget(pushed_cnt) };
            size
        };

        match size {
            0 => continue,
            1 => {
                let index = index as u32;
                index.push_to_lua(&mut lua);
                unsafe { ffi::lua_insert(lua.as_mut_lua().0, -2) }
                unsafe { ffi::lua_settable(lua.as_mut_lua().0, -3) }
            },
            2 => unsafe { ffi::lua_settable(lua.as_mut_lua().0, -3) },
            _ => panic!()
        }
    }

    PushGuard { lua: lua, size: 1 }
}

/*fn push_rec_iter<L: AsLua, V: Push<L>, I: Iterator<V>>(lua: &mut L, mut iterator: I)
                                                                   -> uint
{
    let (nrec, _) = iterator.size_hint();

    // creating empty table with pre-allocated non-array elements
    unsafe { ffi::lua_createtable(lua.as_lua(), 0, nrec as i32) };

    for elem in iterator {
        let pushed_cnt = elem.push_to_lua(lua);

        match pushed_cnt {
            0 => continue,
            2 => unsafe { ffi::lua_settable(lua.as_lua(), -3) },
            _ => panic!()
        }
    }

    1
}*/

impl<L, T> Push<L> for Vec<T> where L: AsMutLua, T: for<'a> Push<&'a mut L> {
    fn push_to_lua(self, lua: L) -> PushGuard<L> {
        push_iter(lua, self.into_iter())
    }
}

impl<'a, L, T> Push<L> for &'a [T] where L: AsMutLua, T: Clone + for<'a> Push<&'a mut L> {
    fn push_to_lua(self, lua: L) -> PushGuard<L> {
        push_iter(lua, self.iter().map(|e| e.clone()))
    }
}

/*impl<L: AsLua, K: Push<L> + Eq + Hash, V: Push<L>> Push<L> for HashMap<K, V> {
    fn push_to_lua(self, lua: &mut L) -> uint {
        push_rec_iter(lua, self.into_iter())
    }
}

impl<L: AsLua, K: Push<L> + Eq + Hash> Push<L> for HashSet<K> {
    fn push_to_lua(self, lua: &mut L) -> uint {
        use std::iter;
        push_rec_iter(lua, self.into_iter().zip(iter::repeat(true)))
    }
}*/
<commit_msg>Restore pushing hashmaps and hashsets<commit_after>use ffi;

use Push;
use PushGuard;
use AsMutLua;

use std::collections::{HashMap, HashSet};
use std::hash::Hash;
use std::iter;
use std::mem;

fn push_iter<L, V, I>(mut lua: L, iterator: I) -> PushGuard<L>
                      where L: AsMutLua, V: for<'b> Push<&'b mut L>, I: Iterator<Item=V>
{
    // creating empty table
    unsafe { ffi::lua_newtable(lua.as_mut_lua().0) };

    for (elem, index) in iterator.zip(iter::count(1u, 1u)) {
        let size = {
            let pushed_cnt = elem.push_to_lua(&mut lua);

            let size = pushed_cnt.size;
            unsafe { mem::forget(pushed_cnt) };
            size
        };

        match size {
            0 => continue,
            1 => {
                let index = index as u32;
                index.push_to_lua(&mut lua);
                unsafe { ffi::lua_insert(lua.as_mut_lua().0, -2) }
                unsafe { ffi::lua_settable(lua.as_mut_lua().0, -3) }
            },
            2 => unsafe { ffi::lua_settable(lua.as_mut_lua().0, -3) },
            _ => unreachable!()
        }
    }

    PushGuard { lua: lua, size: 1 }
}

fn push_rec_iter<L, V, I>(mut lua: L, mut iterator: I) -> PushGuard<L>
                          where L: AsMutLua, V: for<'a> Push<&'a mut L>, I: Iterator<Item=V>
{
    let (nrec, _) = iterator.size_hint();

    // creating empty table with pre-allocated non-array elements
    unsafe { ffi::lua_createtable(lua.as_mut_lua().0, 0, nrec as i32) };

    for elem in iterator {
        let size = {
            let pushed_cnt = elem.push_to_lua(&mut lua);
            let size = pushed_cnt.size;
            unsafe { mem::forget(pushed_cnt) };
            size
        };

        match size {
            0 => continue,
            2 => unsafe { ffi::lua_settable(lua.as_mut_lua().0, -3) },
            _ => unreachable!()
        }
    }

    PushGuard { lua: lua, size: 1 }
}

impl<L, T> Push<L> for Vec<T> where L: AsMutLua, T: for<'a> Push<&'a mut L> {
    fn push_to_lua(self, lua: L) -> PushGuard<L> {
        push_iter(lua, self.into_iter())
    }
}

impl<'a, L, T> Push<L> for &'a [T] where L: AsMutLua, T: Clone + for<'a> Push<&'a mut L> {
    fn push_to_lua(self, lua: L) -> PushGuard<L> {
        push_iter(lua, self.iter().map(|e| e.clone()))
    }
}

impl<L, K, V> Push<L> for HashMap<K, V> where L: AsMutLua, K: for<'a, 'b> Push<&'a mut &'b mut L> + Eq + Hash, V: for<'a, 'b> Push<&'a mut &'b mut L> {
    fn push_to_lua(self, lua: L) -> PushGuard<L> {
        push_rec_iter(lua, self.into_iter())
    }
}

impl<L, K> Push<L> for HashSet<K> where L: AsMutLua, K: for<'a, 'b> Push<&'a mut &'b mut L> + Eq + Hash {
    fn push_to_lua(self, lua: L) -> PushGuard<L> {
        use std::iter;
        push_rec_iter(lua, self.into_iter().zip(iter::repeat(true)))
    }
}
<|endoftext|>


<commit_before>extern crate rand;

use std::io;
use std::cmp::Ordering;
use rand::Rng;

fn main() {
    println!("Guess the number!");

    let secret_number = rand::thread_rng().gen_range(1, 101);

    println!("The secret number is: {}", secret_number);

    loop
    {
        println!("Please input your guess.");

	let mut guess = String::new();

	io::stdin().read_line(&mut guess)
            .expect("Failed to read line");

	let guess: u32 = match guess.trim().parse() {
	    Ok(num) => num,
	    Err(_) => continue,
	};

	println!("You guessed: {}", guess);

	match guess.cmp(&secret_number) {
              Ordering::Less    => println!("Too small!"),
	      Ordering::Greater => println!("Too big!"),
	      Ordering::Equal   => {
	      			println!("You win!");
				break;
	      }
	}
    }
}
<commit_msg>Hide the number!<commit_after>extern crate rand;

use std::io;
use std::cmp::Ordering;
use rand::Rng;

fn main() {
    println!("Guess the number!");

    let secret_number = rand::thread_rng().gen_range(1, 101);

//    println!("The secret number is: {}", secret_number);

    loop
    {
        println!("Please input your guess.");

	let mut guess = String::new();

	io::stdin().read_line(&mut guess)
            .expect("Failed to read line");

	let guess: u32 = match guess.trim().parse() {
	    Ok(num) => num,
	    Err(_) => continue,
	};

	println!("You guessed: {}", guess);

	match guess.cmp(&secret_number) {
              Ordering::Less    => println!("Too small!"),
	      Ordering::Greater => println!("Too big!"),
	      Ordering::Equal   => {
	      			println!("You win!");
				break;
	      }
	}
    }
}
<|endoftext|>


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

//! A bare-metal library supplying functions rustc may lower code to
//!
//! This library is not intended for general use, and is superseded by a system
//! libc if one is available. In a freestanding context, however, common
//! functions such as memset, memcpy, etc are not implemented. This library
//! provides an implementation of these functions which are either required by
//! libcore or called by rustc implicitly.
//!
//! This library is never included by default, and must be manually included if
//! necessary. It is an error to include this library when also linking with
//! the system libc library.

#![crate_name = "rlibc"]
#![crate_type = "rlib"]

#![no_std]

// This library defines the builtin functions, so it would be a shame for
// LLVM to optimize these function calls to themselves!
#![no_builtins]

extern crate core;

#[phase(plugin, link)]
#[cfg(test)] extern crate std;
#[cfg(test)] extern crate native;

use core::ptr::PtrExt;

#[no_mangle]
pub unsafe extern fn memcpy(dest: *mut u8, src: *const u8,
                            n: uint) -> *mut u8 {
    let mut i = 0;
    while i < n {
        *dest.offset(i as int) = *src.offset(i as int);
        i += 1;
    }
    return dest;
}

#[no_mangle]
pub unsafe extern fn memmove(dest: *mut u8, src: *const u8,
                             n: uint) -> *mut u8 {
    if src < dest as *const u8 { // copy from end
        let mut i = n;
        while i != 0 {
            i -= 1;
            *dest.offset(i as int) = *src.offset(i as int);
        }
    } else { // copy from beginning
        let mut i = 0;
        while i < n {
            *dest.offset(i as int) = *src.offset(i as int);
            i += 1;
        }
    }
    return dest;
}

#[no_mangle]
pub unsafe extern fn memset(s: *mut u8, c: i32, n: uint) -> *mut u8 {
    let mut i = 0;
    while i < n {
        *s.offset(i as int) = c as u8;
        i += 1;
    }
    return s;
}

#[no_mangle]
pub unsafe extern fn memcmp(s1: *const u8, s2: *const u8, n: uint) -> i32 {
    let mut i = 0;
    while i < n {
        let a = *s1.offset(i as int);
        let b = *s2.offset(i as int);
        if a != b {
            return a as i32 - b as i32
        }
        i += 1;
    }
    return 0;
}

#[cfg(test)]
mod test {
    use core::str::StrSlice;
    use core::slice::{MutableSlice, ImmutableSlice};

    use super::{memcmp, memset, memcpy, memmove};

    #[test]
    fn memcmp_single_byte_pointers() {
        unsafe {
            assert_eq!(memcmp(&0xFAu8, &0xFAu8, 1), 0x00);
            assert!(memcmp(&0xEFu8, &0xFEu8, 1) < 0x00);
        }
    }

    #[test]
    fn memcmp_strings() {
        {
            let (x, z) = ("Hello!", "Good Bye.");
            let l = x.len();
            unsafe {
                assert_eq!(memcmp(x.as_ptr(), x.as_ptr(), l), 0);
                assert!(memcmp(x.as_ptr(), z.as_ptr(), l) > 0);
                assert!(memcmp(z.as_ptr(), x.as_ptr(), l) < 0);
            }
        }
        {
            let (x, z) = ("hey!", "hey.");
            let l = x.len();
            unsafe {
                assert!(memcmp(x.as_ptr(), z.as_ptr(), l) < 0);
            }
        }
    }

    #[test]
    fn memset_single_byte_pointers() {
        let mut x: u8 = 0xFF;
        unsafe {
            memset(&mut x, 0xAA, 1);
            assert_eq!(x, 0xAA);
            memset(&mut x, 0x00, 1);
            assert_eq!(x, 0x00);
            x = 0x01;
            memset(&mut x, 0x12, 0);
            assert_eq!(x, 0x01);
        }
    }

    #[test]
    fn memset_array() {
        let mut buffer = [b'X', .. 100];
        unsafe {
            memset(buffer.as_mut_ptr(), b'#' as i32, buffer.len());
        }
        for byte in buffer.iter() { assert_eq!(*byte, b'#'); }
    }

    #[test]
    fn memcpy_and_memcmp_arrays() {
        let (src, mut dst) = ([b'X', .. 100], [b'Y', .. 100]);
        unsafe {
            assert!(memcmp(src.as_ptr(), dst.as_ptr(), 100) != 0);
            let _ = memcpy(dst.as_mut_ptr(), src.as_ptr(), 100);
            assert_eq!(memcmp(src.as_ptr(), dst.as_ptr(), 100), 0);
        }
    }

    #[test]
    fn memmove_overlapping() {
        {
            let mut buffer = [ b'0', b'1', b'2', b'3', b'4', b'5', b'6', b'7', b'8', b'9' ];
            unsafe {
                memmove(&mut buffer[4], &buffer[0], 6);
                let mut i = 0;
                for byte in b"0123012345".iter() {
                    assert_eq!(buffer[i], *byte);
                    i += 1;
                }
            }
        }
        {
            let mut buffer = [ b'0', b'1', b'2', b'3', b'4', b'5', b'6', b'7', b'8', b'9' ];
            unsafe {
                memmove(&mut buffer[0], &buffer[4], 6);
                let mut i = 0;
                for byte in b"4567896789".iter() {
                    assert_eq!(buffer[i], *byte);
                    i += 1;
                }
            }
        }
    }
}
<commit_msg>no std requires create attribute<commit_after>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! A bare-metal library supplying functions rustc may lower code to
//!
//! This library is not intended for general use, and is superseded by a system
//! libc if one is available. In a freestanding context, however, common
//! functions such as memset, memcpy, etc are not implemented. This library
//! provides an implementation of these functions which are either required by
//! libcore or called by rustc implicitly.
//!
//! This library is never included by default, and must be manually included if
//! necessary. It is an error to include this library when also linking with
//! the system libc library.

#![crate_name = "rlibc"]
#![crate_type = "rlib"]

#![feature(no_std)]
#![no_std]

// This library defines the builtin functions, so it would be a shame for
// LLVM to optimize these function calls to themselves!
#![no_builtins]

extern crate core;

#[phase(plugin, link)]
#[cfg(test)] extern crate std;
#[cfg(test)] extern crate native;

use core::ptr::PtrExt;

#[no_mangle]
pub unsafe extern fn memcpy(dest: *mut u8, src: *const u8,
                            n: uint) -> *mut u8 {
    let mut i = 0;
    while i < n {
        *dest.offset(i as int) = *src.offset(i as int);
        i += 1;
    }
    return dest;
}

#[no_mangle]
pub unsafe extern fn memmove(dest: *mut u8, src: *const u8,
                             n: uint) -> *mut u8 {
    if src < dest as *const u8 { // copy from end
        let mut i = n;
        while i != 0 {
            i -= 1;
            *dest.offset(i as int) = *src.offset(i as int);
        }
    } else { // copy from beginning
        let mut i = 0;
        while i < n {
            *dest.offset(i as int) = *src.offset(i as int);
            i += 1;
        }
    }
    return dest;
}

#[no_mangle]
pub unsafe extern fn memset(s: *mut u8, c: i32, n: uint) -> *mut u8 {
    let mut i = 0;
    while i < n {
        *s.offset(i as int) = c as u8;
        i += 1;
    }
    return s;
}

#[no_mangle]
pub unsafe extern fn memcmp(s1: *const u8, s2: *const u8, n: uint) -> i32 {
    let mut i = 0;
    while i < n {
        let a = *s1.offset(i as int);
        let b = *s2.offset(i as int);
        if a != b {
            return a as i32 - b as i32
        }
        i += 1;
    }
    return 0;
}

#[cfg(test)]
mod test {
    use core::str::StrSlice;
    use core::slice::{MutableSlice, ImmutableSlice};

    use super::{memcmp, memset, memcpy, memmove};

    #[test]
    fn memcmp_single_byte_pointers() {
        unsafe {
            assert_eq!(memcmp(&0xFAu8, &0xFAu8, 1), 0x00);
            assert!(memcmp(&0xEFu8, &0xFEu8, 1) < 0x00);
        }
    }

    #[test]
    fn memcmp_strings() {
        {
            let (x, z) = ("Hello!", "Good Bye.");
            let l = x.len();
            unsafe {
                assert_eq!(memcmp(x.as_ptr(), x.as_ptr(), l), 0);
                assert!(memcmp(x.as_ptr(), z.as_ptr(), l) > 0);
                assert!(memcmp(z.as_ptr(), x.as_ptr(), l) < 0);
            }
        }
        {
            let (x, z) = ("hey!", "hey.");
            let l = x.len();
            unsafe {
                assert!(memcmp(x.as_ptr(), z.as_ptr(), l) < 0);
            }
        }
    }

    #[test]
    fn memset_single_byte_pointers() {
        let mut x: u8 = 0xFF;
        unsafe {
            memset(&mut x, 0xAA, 1);
            assert_eq!(x, 0xAA);
            memset(&mut x, 0x00, 1);
            assert_eq!(x, 0x00);
            x = 0x01;
            memset(&mut x, 0x12, 0);
            assert_eq!(x, 0x01);
        }
    }

    #[test]
    fn memset_array() {
        let mut buffer = [b'X', .. 100];
        unsafe {
            memset(buffer.as_mut_ptr(), b'#' as i32, buffer.len());
        }
        for byte in buffer.iter() { assert_eq!(*byte, b'#'); }
    }

    #[test]
    fn memcpy_and_memcmp_arrays() {
        let (src, mut dst) = ([b'X', .. 100], [b'Y', .. 100]);
        unsafe {
            assert!(memcmp(src.as_ptr(), dst.as_ptr(), 100) != 0);
            let _ = memcpy(dst.as_mut_ptr(), src.as_ptr(), 100);
            assert_eq!(memcmp(src.as_ptr(), dst.as_ptr(), 100), 0);
        }
    }

    #[test]
    fn memmove_overlapping() {
        {
            let mut buffer = [ b'0', b'1', b'2', b'3', b'4', b'5', b'6', b'7', b'8', b'9' ];
            unsafe {
                memmove(&mut buffer[4], &buffer[0], 6);
                let mut i = 0;
                for byte in b"0123012345".iter() {
                    assert_eq!(buffer[i], *byte);
                    i += 1;
                }
            }
        }
        {
            let mut buffer = [ b'0', b'1', b'2', b'3', b'4', b'5', b'6', b'7', b'8', b'9' ];
            unsafe {
                memmove(&mut buffer[0], &buffer[4], 6);
                let mut i = 0;
                for byte in b"4567896789".iter() {
                    assert_eq!(buffer[i], *byte);
                    i += 1;
                }
            }
        }
    }
}
<|endoftext|>


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

///! [CSS cascade origins](https://drafts.csswg.org/css-cascade/#cascading-origins).

use std::marker::PhantomData;
use std::mem::transmute;

/// Each style rule has an origin, which determines where it enters the cascade.
///
/// https://drafts.csswg.org/css-cascade/#cascading-origins
#[derive(Clone, PartialEq, Eq, Copy, Debug)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub enum Origin {
    /// https://drafts.csswg.org/css-cascade/#cascade-origin-us
    UserAgent,

    /// https://drafts.csswg.org/css-cascade/#cascade-origin-author
    Author,

    /// https://drafts.csswg.org/css-cascade/#cascade-origin-user
    User,
}

/// An object that stores a `T` for each origin of the CSS cascade.
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
#[derive(Debug, Default)]
pub struct PerOrigin<T> {
    /// Data for `Origin::UserAgent`.
    pub user_agent: T,

    /// Data for `Origin::Author`.
    pub author: T,

    /// Data for `Origin::User`.
    pub user: T,
}

impl<T> PerOrigin<T> {
    /// Returns a reference to the per-origin data for the specified origin.
    #[inline]
    pub fn borrow_for_origin(&self, origin: &Origin) -> &T {
        match *origin {
            Origin::UserAgent => &self.user_agent,
            Origin::Author => &self.author,
            Origin::User => &self.user,
        }
    }

    /// Returns a mutable reference to the per-origin data for the specified
    /// origin.
    #[inline]
    pub fn borrow_mut_for_origin(&mut self, origin: &Origin) -> &mut T {
        match *origin {
            Origin::UserAgent => &mut self.user_agent,
            Origin::Author => &mut self.author,
            Origin::User => &mut self.user,
        }
    }

    /// Iterates over references to per-origin extra style data, from highest
    /// level (user) to lowest (user agent).
    pub fn iter_origins(&self) -> PerOriginIter<T> {
        PerOriginIter {
            data: &self,
            cur: 0,
        }
    }

    /// Iterates over mutable references to per-origin extra style data, from
    /// highest level (user) to lowest (user agent).
    pub fn iter_mut_origins(&mut self) -> PerOriginIterMut<T> {
        PerOriginIterMut {
            data: self,
            cur: 0,
            _marker: PhantomData,
        }
    }
}

/// An object that can be cleared.
pub trait PerOriginClear {
    /// Clears the object.
    fn clear(&mut self);
}

impl<T> PerOriginClear for PerOrigin<T> where T: PerOriginClear {
    fn clear(&mut self) {
        self.user_agent.clear();
        self.author.clear();
        self.user.clear();
    }
}

/// Iterator over `PerOrigin<T>`, from highest level (user) to lowest
/// (user agent).
///
/// We rely on this specific order for correctly looking up @font-face,
/// @counter-style and @keyframes rules.
pub struct PerOriginIter<'a, T: 'a> {
    data: &'a PerOrigin<T>,
    cur: usize,
}

impl<'a, T> Iterator for PerOriginIter<'a, T> where T: 'a {
    type Item = (&'a T, Origin);

    fn next(&mut self) -> Option<Self::Item> {
        let result = match self.cur {
            0 => (&self.data.user, Origin::User),
            1 => (&self.data.author, Origin::Author),
            2 => (&self.data.user_agent, Origin::UserAgent),
            _ => return None,
        };
        self.cur += 1;
        Some(result)
    }
}

/// Like `PerOriginIter<T>`, but iterates over mutable references to the
/// per-origin data.
///
/// We must use unsafe code here since it's not possible for the borrow
/// checker to know that we are safely returning a different reference
/// each time from `next()`.
pub struct PerOriginIterMut<'a, T: 'a> {
    data: *mut PerOrigin<T>,
    cur: usize,
    _marker: PhantomData<&'a mut PerOrigin<T>>,
}

impl<'a, T> Iterator for PerOriginIterMut<'a, T> where T: 'a {
    type Item = (&'a mut T, Origin);

    fn next(&mut self) -> Option<Self::Item> {
        let result = match self.cur {
            0 => (unsafe { transmute(&mut (*self.data).user) }, Origin::User),
            1 => (unsafe { transmute(&mut (*self.data).author) }, Origin::Author),
            2 => (unsafe { transmute(&mut (*self.data).user_agent) }, Origin::UserAgent),
            _ => return None,
        };
        self.cur += 1;
        Some(result)
    }
}
<commit_msg>style: Fix origin iteration order.<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

///! [CSS cascade origins](https://drafts.csswg.org/css-cascade/#cascading-origins).

use std::marker::PhantomData;
use std::mem::transmute;

/// Each style rule has an origin, which determines where it enters the cascade.
///
/// https://drafts.csswg.org/css-cascade/#cascading-origins
#[derive(Clone, PartialEq, Eq, Copy, Debug)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub enum Origin {
    /// https://drafts.csswg.org/css-cascade/#cascade-origin-us
    UserAgent,

    /// https://drafts.csswg.org/css-cascade/#cascade-origin-user
    User,

    /// https://drafts.csswg.org/css-cascade/#cascade-origin-author
    Author,
}

/// An object that stores a `T` for each origin of the CSS cascade.
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
#[derive(Debug, Default)]
pub struct PerOrigin<T> {
    /// Data for `Origin::UserAgent`.
    pub user_agent: T,

    /// Data for `Origin::User`.
    pub user: T,

    /// Data for `Origin::Author`.
    pub author: T,
}

impl<T> PerOrigin<T> {
    /// Returns a reference to the per-origin data for the specified origin.
    #[inline]
    pub fn borrow_for_origin(&self, origin: &Origin) -> &T {
        match *origin {
            Origin::UserAgent => &self.user_agent,
            Origin::User => &self.user,
            Origin::Author => &self.author,
        }
    }

    /// Returns a mutable reference to the per-origin data for the specified
    /// origin.
    #[inline]
    pub fn borrow_mut_for_origin(&mut self, origin: &Origin) -> &mut T {
        match *origin {
            Origin::UserAgent => &mut self.user_agent,
            Origin::User => &mut self.user,
            Origin::Author => &mut self.author,
        }
    }

    /// Iterates over references to per-origin extra style data, from highest
    /// level (author) to lowest (user agent).
    pub fn iter_origins(&self) -> PerOriginIter<T> {
        PerOriginIter {
            data: &self,
            cur: 0,
        }
    }

    /// Iterates over mutable references to per-origin extra style data, from
    /// highest level (author) to lowest (user agent).
    pub fn iter_mut_origins(&mut self) -> PerOriginIterMut<T> {
        PerOriginIterMut {
            data: self,
            cur: 0,
            _marker: PhantomData,
        }
    }
}

/// An object that can be cleared.
pub trait PerOriginClear {
    /// Clears the object.
    fn clear(&mut self);
}

impl<T> PerOriginClear for PerOrigin<T> where T: PerOriginClear {
    fn clear(&mut self) {
        self.user_agent.clear();
        self.user.clear();
        self.author.clear();
    }
}

/// Iterator over `PerOrigin<T>`, from highest level (author) to lowest
/// (user agent).
///
/// We rely on this specific order for correctly looking up @font-face,
/// @counter-style and @keyframes rules.
pub struct PerOriginIter<'a, T: 'a> {
    data: &'a PerOrigin<T>,
    cur: usize,
}

impl<'a, T> Iterator for PerOriginIter<'a, T> where T: 'a {
    type Item = (&'a T, Origin);

    fn next(&mut self) -> Option<Self::Item> {
        let result = match self.cur {
            0 => (&self.data.author, Origin::Author),
            1 => (&self.data.user, Origin::User),
            2 => (&self.data.user_agent, Origin::UserAgent),
            _ => return None,
        };
        self.cur += 1;
        Some(result)
    }
}

/// Like `PerOriginIter<T>`, but iterates over mutable references to the
/// per-origin data.
///
/// We must use unsafe code here since it's not possible for the borrow
/// checker to know that we are safely returning a different reference
/// each time from `next()`.
pub struct PerOriginIterMut<'a, T: 'a> {
    data: *mut PerOrigin<T>,
    cur: usize,
    _marker: PhantomData<&'a mut PerOrigin<T>>,
}

impl<'a, T> Iterator for PerOriginIterMut<'a, T> where T: 'a {
    type Item = (&'a mut T, Origin);

    fn next(&mut self) -> Option<Self::Item> {
        let result = match self.cur {
            0 => (unsafe { transmute(&mut (*self.data).author) }, Origin::Author),
            1 => (unsafe { transmute(&mut (*self.data).user) }, Origin::User),
            2 => (unsafe { transmute(&mut (*self.data).user_agent) }, Origin::UserAgent),
            _ => return None,
        };
        self.cur += 1;
        Some(result)
    }
}
<|endoftext|>


<commit_before>
use protos::{LogFileEntry, StudyQuestion, StudyQuestions, StudyQuestionAnswer};
use std::error::Error;

pub struct UserStudyQuestions {
    pub replay_filename: String,
    pub answer_lines: Vec<String>,
}
impl UserStudyQuestions {
    #[allow(unused_assignments)]
    pub fn get_questions(&mut self) -> Result<Option<StudyQuestions>, Box<Error>> {
        use scaii_core;
        use std::fs::File;
        use std::io::prelude::*;
        use std::io::BufReader;
        println!("Looking for question file for replay {}", self.replay_filename);
        let mut questionfile_path = scaii_core::get_default_replay_dir()?;
        let question_filename_root = get_question_filename_root_for_replay(&self.replay_filename);
        println!("question_filename root is {}", question_filename_root);
        let question_filename = get_filename_for_root(question_filename_root)?;
        let mut user_id = "".to_string();
        let mut treatment_id = "".to_string();
        let mut answer_filename = "".to_string();
        match question_filename  {
            None => { return Ok(None); },
            Some(ref filename)  => {
                user_id = get_field_from_filename(filename, 2 as u32);
                treatment_id = get_field_from_filename(filename, 3 as u32);
                answer_filename = filename.replace("question", "answer");
                let result = str::replace("Hello World!", "!", "?");
println!("{}", result); // => "Hello World!"
                println!("user_id {} ", user_id);
                println!("treatment_id {}", treatment_id);
            },
        }
        questionfile_path.push(question_filename.unwrap().as_str());
        println!("path is {:?}", questionfile_path);
        let f = File::open(questionfile_path)?;
        let reader = BufReader::new(f);

        let mut questions_vec: Vec<StudyQuestion> = Vec::new();
        for line in reader.lines() {
            let question_string = line.unwrap();
            println!("STUDY QUESTION: {}", question_string);
            let question: StudyQuestion = self.get_study_question(&question_string)?;
            questions_vec.push(question);
        }
        let study_questions = StudyQuestions {
            user_id: user_id,
            treatment_id: treatment_id,
            study_questions: questions_vec,
            answer_filename: answer_filename,
        };
        Ok(Some(study_questions))
    }

    fn get_study_question(&mut self, line : &String) -> Result<StudyQuestion, Box<Error>> {
        use super::ReplayError;
        let line_parts_iterator = line.split(";");
        let vec: Vec<&str> = line_parts_iterator.collect();
        if vec.len() < 3 {
            return Err(Box::new(ReplayError::new(&format!("study question line needs at least three fields: <step>;<questionIndex>;<question>;<answer1>..."))));
        }
        let step: String = vec[0].to_string();
        let question_index: String = vec[1].to_string();
        let question_type: String = vec[2].to_string();
        let question : String = vec[3].to_string();
        let mut answer_vec : Vec<String> = Vec::new();
        for x in 4..vec.len() {
            answer_vec.push(vec[x].to_string());
        }
        Ok(StudyQuestion {
            step: step,
            question: question,
            answers: answer_vec,
            question_id_for_step: question_index,
            question_type: question_type,
        })
    }

    pub fn persist_log_entry_incremental(&mut self, lfe: LogFileEntry) -> Result<(), Box<Error>> {
        use std::fs::{File, OpenOptions,remove_file};
        use std::io::Write;
        use scaii_core;
        println!("{:?}", &lfe);
        let output_line = lfe.entry;

        let mut answerfile_path = scaii_core::get_default_replay_dir()?;
        let filename = lfe.filename;
        answerfile_path.push(filename);

        let mut file = OpenOptions::new().append(true).open(answerfile_path).unwrap();
        file.write_all(output_line.as_bytes())?;
        file.write_all("\n".to_string().as_bytes())?;
        Ok(())
    }
    pub fn persist_log_entry(&mut self, lfe: LogFileEntry) -> Result<(), Box<Error>> {
        use std::fs::{File, OpenOptions,remove_file};
        use std::io::Write;
        use scaii_core;
        println!("{:?}", &lfe);
        let output_line = lfe.entry;
        self.answer_lines.push(output_line);

        if lfe.is_last_line {
            let mut answerfile_path = scaii_core::get_default_replay_dir()?;
            // append to file called replayX_answers_userID_treatmentID.txt
            // or ??? replayX_answers_userID_sessionID_treatmentID.txt
            let filename = lfe.filename;
            answerfile_path.push(filename);
            if answerfile_path.exists(){
                remove_file(&answerfile_path)?;
            }
            println!("answerfile_path is {:?}", answerfile_path);
            File::create(&answerfile_path)?;
            let mut file = OpenOptions::new().append(true).open(answerfile_path).unwrap();
            for line in &self.answer_lines {
                file.write_all(line.as_bytes())?;
                file.write_all("\n".to_string().as_bytes())?;
                //writeln!(file, format!("{}",line))?;
            }
        }

        Ok(())
    }

    pub fn persist_study_question_answer(&mut self, sqa: StudyQuestionAnswer) -> Result<(), Box<Error>> {
        use std::fs::{File, OpenOptions,remove_file};
        use std::io::Write;
        use scaii_core;
        println!("{:?}", &sqa);
        let user_id = sqa.user_id;
        let treatment_id = sqa.treatment_id;
        let answer = sqa.answer;
        let question = sqa.question;
        let question_number = sqa.question_number;
        let step = sqa.step;
        let output_line = format!("{};{};{};{}", question_number, step, question, answer);
        self.answer_lines.push(output_line);

        if step == "summary".to_string() {
            let mut answerfile_path = scaii_core::get_default_replay_dir()?;
            // append to file called replayX_answers_userID_treatmentID.txt
            // or ??? replayX_answers_userID_sessionID_treatmentID.txt
            let filename = get_answer_filename(&self.replay_filename, &user_id, &treatment_id);
            answerfile_path.push(filename);
            if answerfile_path.exists(){
                remove_file(&answerfile_path)?;
            }
            println!("answerfile_path is {:?}", answerfile_path);
            File::create(&answerfile_path)?;
            let mut file = OpenOptions::new().append(true).open(answerfile_path).unwrap();
            for line in &self.answer_lines {
                file.write_all(line.as_bytes())?;
                file.write_all("\n".to_string().as_bytes())?;
                //writeln!(file, format!("{}",line))?;
            }
        }

        Ok(())
    }
}

fn get_field_from_filename(filename : &String, index : u32) -> String {
    let filename_parts_iterator = filename.split(".");
    let vec: Vec<&str> = filename_parts_iterator.collect();
    let root = vec[0];
    let root_parts_iterator = root.split("_");
    let vec:Vec<&str> = root_parts_iterator.collect();
    vec[index as usize].to_string()
}

fn get_filename_for_root(root: String) -> Result<Option<String>, Box<Error>>  {
    use scaii_core;
    use std::fs;
    let questionfile_path = scaii_core::get_default_replay_dir()?;
    for entry in fs::read_dir(questionfile_path)? {
        let entry = entry?;
        let path = entry.path();
        if !path.is_dir() {
            let filename = path.file_name().unwrap().to_str().unwrap().to_string();
            if filename.starts_with(root.as_str()) {
                println!("filename found was {}", filename);
                return Ok(Some(filename));
            }
        }
    }
    Ok(None)
}

fn get_question_filename_root_for_replay(filename : &String) -> String {
    let filename_parts_iterator = filename.split(".");
    let vec: Vec<&str> = filename_parts_iterator.collect();
    format!("{}_questions", vec[0])
}

// replayX_answers_userID_treatmentID.txt
fn get_answer_filename(filename : &String, user_id: &String, treatment_id: &String) -> String {
    let filename_parts_iterator = filename.split(".");
    let vec: Vec<&str> = filename_parts_iterator.collect();
    format!("{}_answers_{}_{}.txt", vec[0], user_id, treatment_id)
}

<commit_msg>need to create file first before can append<commit_after>
use protos::{LogFileEntry, StudyQuestion, StudyQuestions, StudyQuestionAnswer};
use std::error::Error;

pub struct UserStudyQuestions {
    pub replay_filename: String,
    pub answer_lines: Vec<String>,
}
impl UserStudyQuestions {
    #[allow(unused_assignments)]
    pub fn get_questions(&mut self) -> Result<Option<StudyQuestions>, Box<Error>> {
        use scaii_core;
        use std::fs::File;
        use std::io::prelude::*;
        use std::io::BufReader;
        println!("Looking for question file for replay {}", self.replay_filename);
        let mut questionfile_path = scaii_core::get_default_replay_dir()?;
        let question_filename_root = get_question_filename_root_for_replay(&self.replay_filename);
        println!("question_filename root is {}", question_filename_root);
        let question_filename = get_filename_for_root(question_filename_root)?;
        let mut user_id = "".to_string();
        let mut treatment_id = "".to_string();
        let mut answer_filename = "".to_string();
        match question_filename  {
            None => { return Ok(None); },
            Some(ref filename)  => {
                user_id = get_field_from_filename(filename, 2 as u32);
                treatment_id = get_field_from_filename(filename, 3 as u32);
                answer_filename = filename.replace("question", "answer");
                let result = str::replace("Hello World!", "!", "?");
println!("{}", result); // => "Hello World!"
                println!("user_id {} ", user_id);
                println!("treatment_id {}", treatment_id);
            },
        }
        questionfile_path.push(question_filename.unwrap().as_str());
        println!("path is {:?}", questionfile_path);
        let f = File::open(questionfile_path)?;
        let reader = BufReader::new(f);

        let mut questions_vec: Vec<StudyQuestion> = Vec::new();
        for line in reader.lines() {
            let question_string = line.unwrap();
            println!("STUDY QUESTION: {}", question_string);
            let question: StudyQuestion = self.get_study_question(&question_string)?;
            questions_vec.push(question);
        }
        let study_questions = StudyQuestions {
            user_id: user_id,
            treatment_id: treatment_id,
            study_questions: questions_vec,
            answer_filename: answer_filename,
        };
        Ok(Some(study_questions))
    }

    fn get_study_question(&mut self, line : &String) -> Result<StudyQuestion, Box<Error>> {
        use super::ReplayError;
        let line_parts_iterator = line.split(";");
        let vec: Vec<&str> = line_parts_iterator.collect();
        if vec.len() < 3 {
            return Err(Box::new(ReplayError::new(&format!("study question line needs at least three fields: <step>;<questionIndex>;<question>;<answer1>..."))));
        }
        let step: String = vec[0].to_string();
        let question_index: String = vec[1].to_string();
        let question_type: String = vec[2].to_string();
        let question : String = vec[3].to_string();
        let mut answer_vec : Vec<String> = Vec::new();
        for x in 4..vec.len() {
            answer_vec.push(vec[x].to_string());
        }
        Ok(StudyQuestion {
            step: step,
            question: question,
            answers: answer_vec,
            question_id_for_step: question_index,
            question_type: question_type,
        })
    }

    pub fn persist_log_entry_incremental(&mut self, lfe: LogFileEntry) -> Result<(), Box<Error>> {
        use std::fs::{File, OpenOptions,remove_file};
        use std::io::Write;
        use scaii_core;
        println!("{:?}", &lfe);
        let output_line = lfe.entry;

        let mut answerfile_path = scaii_core::get_default_replay_dir()?;
        let filename = lfe.filename;
        answerfile_path.push(filename);

        if !answerfile_path.exists(){
            File::create(&answerfile_path)?;
        }
        let mut file = OpenOptions::new().append(true).open(answerfile_path).unwrap();
        file.write_all(output_line.as_bytes())?;
        file.write_all("\n".to_string().as_bytes())?;
        Ok(())
    }
    pub fn persist_log_entry(&mut self, lfe: LogFileEntry) -> Result<(), Box<Error>> {
        use std::fs::{File, OpenOptions,remove_file};
        use std::io::Write;
        use scaii_core;
        println!("{:?}", &lfe);
        let output_line = lfe.entry;
        self.answer_lines.push(output_line);

        if lfe.is_last_line {
            let mut answerfile_path = scaii_core::get_default_replay_dir()?;
            // append to file called replayX_answers_userID_treatmentID.txt
            // or ??? replayX_answers_userID_sessionID_treatmentID.txt
            let filename = lfe.filename;
            answerfile_path.push(filename);
            if answerfile_path.exists(){
                remove_file(&answerfile_path)?;
            }
            println!("answerfile_path is {:?}", answerfile_path);
            File::create(&answerfile_path)?;
            let mut file = OpenOptions::new().append(true).open(answerfile_path).unwrap();
            for line in &self.answer_lines {
                file.write_all(line.as_bytes())?;
                file.write_all("\n".to_string().as_bytes())?;
                //writeln!(file, format!("{}",line))?;
            }
        }

        Ok(())
    }

    pub fn persist_study_question_answer(&mut self, sqa: StudyQuestionAnswer) -> Result<(), Box<Error>> {
        use std::fs::{File, OpenOptions,remove_file};
        use std::io::Write;
        use scaii_core;
        println!("{:?}", &sqa);
        let user_id = sqa.user_id;
        let treatment_id = sqa.treatment_id;
        let answer = sqa.answer;
        let question = sqa.question;
        let question_number = sqa.question_number;
        let step = sqa.step;
        let output_line = format!("{};{};{};{}", question_number, step, question, answer);
        self.answer_lines.push(output_line);

        if step == "summary".to_string() {
            let mut answerfile_path = scaii_core::get_default_replay_dir()?;
            // append to file called replayX_answers_userID_treatmentID.txt
            // or ??? replayX_answers_userID_sessionID_treatmentID.txt
            let filename = get_answer_filename(&self.replay_filename, &user_id, &treatment_id);
            answerfile_path.push(filename);
            if answerfile_path.exists(){
                remove_file(&answerfile_path)?;
            }
            println!("answerfile_path is {:?}", answerfile_path);
            File::create(&answerfile_path)?;
            let mut file = OpenOptions::new().append(true).open(answerfile_path).unwrap();
            for line in &self.answer_lines {
                file.write_all(line.as_bytes())?;
                file.write_all("\n".to_string().as_bytes())?;
                //writeln!(file, format!("{}",line))?;
            }
        }

        Ok(())
    }
}

fn get_field_from_filename(filename : &String, index : u32) -> String {
    let filename_parts_iterator = filename.split(".");
    let vec: Vec<&str> = filename_parts_iterator.collect();
    let root = vec[0];
    let root_parts_iterator = root.split("_");
    let vec:Vec<&str> = root_parts_iterator.collect();
    vec[index as usize].to_string()
}

fn get_filename_for_root(root: String) -> Result<Option<String>, Box<Error>>  {
    use scaii_core;
    use std::fs;
    let questionfile_path = scaii_core::get_default_replay_dir()?;
    for entry in fs::read_dir(questionfile_path)? {
        let entry = entry?;
        let path = entry.path();
        if !path.is_dir() {
            let filename = path.file_name().unwrap().to_str().unwrap().to_string();
            if filename.starts_with(root.as_str()) {
                println!("filename found was {}", filename);
                return Ok(Some(filename));
            }
        }
    }
    Ok(None)
}

fn get_question_filename_root_for_replay(filename : &String) -> String {
    let filename_parts_iterator = filename.split(".");
    let vec: Vec<&str> = filename_parts_iterator.collect();
    format!("{}_questions", vec[0])
}

// replayX_answers_userID_treatmentID.txt
fn get_answer_filename(filename : &String, user_id: &String, treatment_id: &String) -> String {
    let filename_parts_iterator = filename.split(".");
    let vec: Vec<&str> = filename_parts_iterator.collect();
    format!("{}_answers_{}_{}.txt", vec[0], user_id, treatment_id)
}

<|endoftext|>