<commit_before>extern crate lazy_bencoding;

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

use lazy_bencoding::*;

fn pretty_print<'a>(bencoded: BEncoded<'a>, padding: &str) {
    if let Some(s) = bencoded.get_utf8_string() {
        println!("{}{}", padding, s);
    } else if let Some(bs) = bencoded.get_byte_string() {
        // Hexdump
        let mut line = String::new();
        for (i, b) in bs.iter().enumerate() {
            line.push_str(&format!("{:02X}", b));
            if i & 15 == 0 {
                println!("{}{}", padding, line);
                line.clear();
            } else if i & 7 == 0 {
                line.push_str("   ");
            } else if i & 3 == 0 {
                line.push_str("  ");
            } else {
                line.push_str(" ");
            }
        }
        if line.len() > 0 {
            println!("{}{}", padding, line);
        }
    } else if let Some(i) = bencoded.get_integer() {
        println!("{}{}", padding, i);
    } else if bencoded.is_dict() {
        for (key, value) in bencoded.dict() {
            if let Some(key) = key.get_utf8_string() {
                println!("{}{}:", padding, key);
            } else {
                pretty_print(key, padding);
            }
            pretty_print(value, &format!("{}    ", padding));
        }
    } else if bencoded.is_list() {
        for (i, elem) in bencoded.list().enumerate() {
            let padding = if i == 0 {
                format!("{}  - ", padding)
            } else {
                let space_padding: String = padding.chars()
                    .map(|c| ' ').collect();
                format!("{}  - ", space_padding)
            };
            pretty_print(elem, &padding);
        }
    } else {
        println!("{}Weird tokens: {:?}", padding, bencoded.collect::<Vec<Token<'a>>>());
    }
}

fn main() {
    for filename in env::args().skip(1) {
        let mut f = match File::open(&filename) {
            Ok(f) => f,
            Err(e) => {
                println!("{}: {:?}", filename, e);
                continue;
            }
        };
        let mut contents = Vec::new();
        f.read_to_end(&mut contents).unwrap();

        let bencoded = BEncoded::new(&contents[..]);
        pretty_print(bencoded, "");
    }
}
<commit_msg>print_torrent examples: delint<commit_after>extern crate lazy_bencoding;

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

use lazy_bencoding::*;

fn pretty_print<'a>(bencoded: BEncoded<'a>, padding: &str) {
    if let Some(s) = bencoded.get_utf8_string() {
        println!("{}{}", padding, s);
    } else if let Some(bs) = bencoded.get_byte_string() {
        // Hexdump
        let mut line = String::new();
        for (i, b) in bs.iter().enumerate() {
            line.push_str(&format!("{:02X}", b));
            if i & 15 == 0 {
                println!("{}{}", padding, line);
                line.clear();
            } else if i & 7 == 0 {
                line.push_str("   ");
            } else if i & 3 == 0 {
                line.push_str("  ");
            } else {
                line.push_str(" ");
            }
        }
        if line.len() > 0 {
            println!("{}{}", padding, line);
        }
    } else if let Some(i) = bencoded.get_integer() {
        println!("{}{}", padding, i);
    } else if bencoded.is_dict() {
        for (key, value) in bencoded.dict() {
            if let Some(key) = key.get_utf8_string() {
                println!("{}{}:", padding, key);
            } else {
                pretty_print(key, padding);
            }
            pretty_print(value, &format!("{}    ", padding));
        }
    } else if bencoded.is_list() {
        for (i, elem) in bencoded.list().enumerate() {
            let padding = if i == 0 {
                format!("{}  - ", padding)
            } else {
                let space_padding: String = padding.chars()
                    .map(|_| ' ').collect();
                format!("{}  - ", space_padding)
            };
            pretty_print(elem, &padding);
        }
    } else {
        println!("{}Weird tokens: {:?}", padding, bencoded.collect::<Vec<Token<'a>>>());
    }
}

fn main() {
    for filename in env::args().skip(1) {
        let mut f = match File::open(&filename) {
            Ok(f) => f,
            Err(e) => {
                println!("{}: {:?}", filename, e);
                continue;
            }
        };
        let mut contents = Vec::new();
        f.read_to_end(&mut contents).unwrap();

        let bencoded = BEncoded::new(&contents[..]);
        pretty_print(bencoded, "");
    }
}
<|endoftext|>


<commit_before>use std::collections::HashMap;
use std::error::Error;
use std::fmt::{Debug, Display, Formatter};
use std::fmt;

use serde_json::{Value, from_str};
use serde_json::error::Result as R;
use serde_json::Serializer;
use serde::ser::Serialize;
use serde::ser::Serializer as Ser;

use storage::parser::{FileHeaderParser, ParserError};
use storage::file::header::spec::FileHeaderSpec;
use storage::file::header::data::FileHeaderData;

pub struct JsonHeaderParser {
    spec: Option<FileHeaderSpec>,
}

impl JsonHeaderParser {

    pub fn new(spec: Option<FileHeaderSpec>) -> JsonHeaderParser {
        JsonHeaderParser {
            spec: spec
        }
    }

}

impl Display for JsonHeaderParser {

    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
        try!(write!(fmt, "JsonHeaderParser"));
        Ok(())
    }

}

impl Debug for JsonHeaderParser {

    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
        try!(write!(fmt, "JsonHeaderParser, Spec: {:?}", self.spec));
        Ok(())
    }

}

impl FileHeaderParser for JsonHeaderParser {

    fn read(&self, string: Option<String>)
        -> Result<FileHeaderData, ParserError>
    {
        if string.is_some() {
            let s = string.unwrap();
            debug!("Deserializing: {}", s);
            let fromstr : R<Value> = from_str(&s[..]);
            if let Ok(ref content) = fromstr {
                return Ok(visit_json(&content))
            }
            let oe = fromstr.err().unwrap();
            let s = format!("JSON parser error: {}", oe.description());
            let e = ParserError::short(&s[..], s.clone(), 0);
            Err(e)
        } else {
            Ok(FileHeaderData::Null)
        }
    }

    fn write(&self, data: &FileHeaderData) -> Result<String, ParserError> {
        let mut s = Vec::<u8>::new();
        {
            let mut ser = Serializer::pretty(&mut s);
            data.serialize(&mut ser).map_err(|e| {
                debug!("Serializer error: {:?}", e);
            }).ok();
        }

        String::from_utf8(s).or(
            Err(ParserError::short("Cannot parse utf8 bytes",
                                   String::from("<not printable>"),
                                   0)))
    }

}

// TODO: This function must be able to return a parser error
fn visit_json(v: &Value) -> FileHeaderData {
    match v {
        &Value::Null             => FileHeaderData::Null,
        &Value::Bool(b)          => FileHeaderData::Bool(b),
        &Value::I64(i)           => FileHeaderData::Integer(i),
        &Value::U64(u)           => FileHeaderData::UInteger(u),
        &Value::F64(f)           => FileHeaderData::Float(f),
        &Value::String(ref s)        => FileHeaderData::Text(s.clone()),
        &Value::Array(ref vec)       => {
            FileHeaderData::Array {
                values: Box::new(vec.clone().into_iter().map(|i| visit_json(&i)).collect())
            }
        },
        &Value::Object(ref btree)    => {
            let btree = btree.clone();
            FileHeaderData::Map{
                keys: btree.into_iter().map(|(k, v)|
                    FileHeaderData::Key {
                        name: k,
                        value: Box::new(visit_json(&v)),
                    }
                ).collect()
            }
        }
    }
}

impl Serialize for FileHeaderData {

    fn serialize<S>(&self, ser: &mut S) -> Result<(), S::Error>
        where S: Ser
    {
        match self {
            &FileHeaderData::Null               => {
                let o : Option<bool> = None;
                o.serialize(ser)
            },
            &FileHeaderData::Bool(ref b)            => b.serialize(ser),
            &FileHeaderData::Integer(ref i)         => i.serialize(ser),
            &FileHeaderData::UInteger(ref u)        => u.serialize(ser),
            &FileHeaderData::Float(ref f)           => f.serialize(ser),
            &FileHeaderData::Text(ref s)            => (&s[..]).serialize(ser),
            &FileHeaderData::Array{values: ref vs}  => vs.serialize(ser),
            &FileHeaderData::Map{keys: ref ks}      => {
                let mut hm = HashMap::new();

                for key in ks {
                    if let &FileHeaderData::Key{name: ref n, value: ref v} = key {
                        hm.insert(n, v);
                    } else {
                        panic!("Not a key: {:?}", key);
                    }
                }

                hm.serialize(ser)
            },
            &FileHeaderData::Key{name: _, value: _} => unreachable!(),

        }
    }

}

#[cfg(test)]
mod test {

    use std::ops::Deref;

    use super::JsonHeaderParser;
    use storage::parser::FileHeaderParser;
    use storage::file::header::data::FileHeaderData as FHD;
    use storage::file::header::spec::FileHeaderSpec as FHS;

    #[test]
    fn test_deserialization() {
        let text = String::from("{\"a\": 1, \"b\": -2}");
        let spec = FHS::Map {
            keys: vec![
                FHS::Key {
                    name: String::from("a"),
                    value_type: Box::new(FHS::UInteger)
                },
                FHS::Key {
                    name: String::from("b"),
                    value_type: Box::new(FHS::Integer)
                }
            ]
        };

        let parser = JsonHeaderParser::new(Some(spec));
        let parsed = parser.read(Some(text));
        assert!(parsed.is_ok(), "Parsed is not ok: {:?}", parsed);

        match parsed.ok() {
            Some(FHD::Map{keys}) => {
                for k in keys {
                    match k {
                        FHD::Key{name, value} => {
                            assert!(name == "a" || name == "b", "Key unknown");
                            match value.deref() {
                                &FHD::UInteger(u) => assert_eq!(u, 1),
                                &FHD::Integer(i) => assert_eq!(i, -2),
                                _ => assert!(false, "Integers are not here"),
                            }
                        },
                        _ => assert!(false, "Key is not a Key"),
                    }
                }
            },

            _ => assert!(false, "Parsed is not a map"),
        }
    }

    #[test]
    fn test_deserialization_without_spec() {
        let text    = String::from("{\"a\": [1], \"b\": {\"c\": -2}}");
        let parser  = JsonHeaderParser::new(None);
        let parsed  = parser.read(Some(text));

        assert!(parsed.is_ok(), "Parsed is not ok: {:?}", parsed);

        match parsed.ok() {
            Some(FHD::Map{keys}) => {
                for k in keys {
                    match_key(&k);
                }
            },

            _ => assert!(false, "Parsed is not a map"),
        }
    }

    fn match_key(k: &FHD) {
        use std::ops::Deref;

        match k {
            &FHD::Key{ref name, ref value} => {
                assert!(name == "a" || name == "b", "Key unknown");
                match value.deref() {
                    &FHD::Array{values: ref vs} => {
                        for value in vs.iter() {
                            match value {
                                &FHD::UInteger(u) => assert_eq!(u, 1),
                                _ => assert!(false, "UInt is not an UInt"),
                            }
                        }
                    }

                    &FHD::Map{keys: ref ks} => {
                        for key in ks.iter() {
                            match key {
                                &FHD::Key{ref name, ref value} => {
                                    match value.deref() {
                                        &FHD::Integer(i) => {
                                            assert_eq!(i, -2);
                                            assert_eq!(name, "c");
                                        },
                                        _ => assert!(false, "Int is not an Int"),
                                    };
                                },
                                _ => assert!(false, "Key is not a Key"),
                            }
                        }
                    }
                    _ => assert!(false, "Integers are not here"),
                }
            },
            _ => assert!(false, "Key in main Map is not a Key"),
        }
    }

    #[test]
    fn test_desser() {
        use serde_json::error::Result as R;
        use serde_json::{Value, from_str};

        let text    = String::from("{\"a\": [1], \"b\": {\"c\": -2}}");
        let parser  = JsonHeaderParser::new(None);

        let des = parser.read(Some(text.clone()));
        assert!(des.is_ok(), "Deserializing failed");

        let ser = parser.write(&des.unwrap());
        assert!(ser.is_ok(), "Parser error when serializing deserialized text");

        let json_text : R<Value> = from_str(&text[..]);
        let json_ser  : R<Value> = from_str(&ser.unwrap()[..]);

        assert!(json_text.is_ok(), "Could not use serde to serialize text for comparison");
        assert!(json_ser.is_ok(),  "Could not use serde to serialize serialized-deserialized text for comparison");
        assert_eq!(json_text.unwrap(), json_ser.unwrap());
    }

}
<commit_msg>Rename some variables, so we can remove unneeded shorthand field patterns<commit_after>use std::collections::HashMap;
use std::error::Error;
use std::fmt::{Debug, Display, Formatter};
use std::fmt;

use serde_json::{Value, from_str};
use serde_json::error::Result as R;
use serde_json::Serializer;
use serde::ser::Serialize;
use serde::ser::Serializer as Ser;

use storage::parser::{FileHeaderParser, ParserError};
use storage::file::header::spec::FileHeaderSpec;
use storage::file::header::data::FileHeaderData;

pub struct JsonHeaderParser {
    spec: Option<FileHeaderSpec>,
}

impl JsonHeaderParser {

    pub fn new(spec: Option<FileHeaderSpec>) -> JsonHeaderParser {
        JsonHeaderParser {
            spec: spec
        }
    }

}

impl Display for JsonHeaderParser {

    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
        try!(write!(fmt, "JsonHeaderParser"));
        Ok(())
    }

}

impl Debug for JsonHeaderParser {

    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
        try!(write!(fmt, "JsonHeaderParser, Spec: {:?}", self.spec));
        Ok(())
    }

}

impl FileHeaderParser for JsonHeaderParser {

    fn read(&self, string: Option<String>)
        -> Result<FileHeaderData, ParserError>
    {
        if string.is_some() {
            let s = string.unwrap();
            debug!("Deserializing: {}", s);
            let fromstr : R<Value> = from_str(&s[..]);
            if let Ok(ref content) = fromstr {
                return Ok(visit_json(&content))
            }
            let oe = fromstr.err().unwrap();
            let s = format!("JSON parser error: {}", oe.description());
            let e = ParserError::short(&s[..], s.clone(), 0);
            Err(e)
        } else {
            Ok(FileHeaderData::Null)
        }
    }

    fn write(&self, data: &FileHeaderData) -> Result<String, ParserError> {
        let mut s = Vec::<u8>::new();
        {
            let mut ser = Serializer::pretty(&mut s);
            data.serialize(&mut ser).map_err(|e| {
                debug!("Serializer error: {:?}", e);
            }).ok();
        }

        String::from_utf8(s).or(
            Err(ParserError::short("Cannot parse utf8 bytes",
                                   String::from("<not printable>"),
                                   0)))
    }

}

// TODO: This function must be able to return a parser error
fn visit_json(v: &Value) -> FileHeaderData {
    match v {
        &Value::Null             => FileHeaderData::Null,
        &Value::Bool(b)          => FileHeaderData::Bool(b),
        &Value::I64(i)           => FileHeaderData::Integer(i),
        &Value::U64(u)           => FileHeaderData::UInteger(u),
        &Value::F64(f)           => FileHeaderData::Float(f),
        &Value::String(ref s)        => FileHeaderData::Text(s.clone()),
        &Value::Array(ref vec)       => {
            FileHeaderData::Array {
                values: Box::new(vec.clone().into_iter().map(|i| visit_json(&i)).collect())
            }
        },
        &Value::Object(ref btree)    => {
            let btree = btree.clone();
            FileHeaderData::Map{
                keys: btree.into_iter().map(|(k, v)|
                    FileHeaderData::Key {
                        name: k,
                        value: Box::new(visit_json(&v)),
                    }
                ).collect()
            }
        }
    }
}

impl Serialize for FileHeaderData {

    fn serialize<S>(&self, ser: &mut S) -> Result<(), S::Error>
        where S: Ser
    {
        match self {
            &FileHeaderData::Null               => {
                let o : Option<bool> = None;
                o.serialize(ser)
            },
            &FileHeaderData::Bool(ref b)            => b.serialize(ser),
            &FileHeaderData::Integer(ref i)         => i.serialize(ser),
            &FileHeaderData::UInteger(ref u)        => u.serialize(ser),
            &FileHeaderData::Float(ref f)           => f.serialize(ser),
            &FileHeaderData::Text(ref s)            => (&s[..]).serialize(ser),
            &FileHeaderData::Array{values: ref vs}  => vs.serialize(ser),
            &FileHeaderData::Map{keys: ref ks}      => {
                let mut hm = HashMap::new();

                for key in ks {
                    if let &FileHeaderData::Key{name: ref n, value: ref v} = key {
                        hm.insert(n, v);
                    } else {
                        panic!("Not a key: {:?}", key);
                    }
                }

                hm.serialize(ser)
            },
            &FileHeaderData::Key{name: _, value: _} => unreachable!(),

        }
    }

}

#[cfg(test)]
mod test {

    use std::ops::Deref;

    use super::JsonHeaderParser;
    use storage::parser::FileHeaderParser;
    use storage::file::header::data::FileHeaderData as FHD;
    use storage::file::header::spec::FileHeaderSpec as FHS;

    #[test]
    fn test_deserialization() {
        let text = String::from("{\"a\": 1, \"b\": -2}");
        let spec = FHS::Map {
            keys: vec![
                FHS::Key {
                    name: String::from("a"),
                    value_type: Box::new(FHS::UInteger)
                },
                FHS::Key {
                    name: String::from("b"),
                    value_type: Box::new(FHS::Integer)
                }
            ]
        };

        let parser = JsonHeaderParser::new(Some(spec));
        let parsed = parser.read(Some(text));
        assert!(parsed.is_ok(), "Parsed is not ok: {:?}", parsed);

        match parsed.ok() {
            Some(FHD::Map{keys}) => {
                for k in keys {
                    match k {
                        FHD::Key{name, value} => {
                            assert!(name == "a" || name == "b", "Key unknown");
                            match value.deref() {
                                &FHD::UInteger(u) => assert_eq!(u, 1),
                                &FHD::Integer(i) => assert_eq!(i, -2),
                                _ => assert!(false, "Integers are not here"),
                            }
                        },
                        _ => assert!(false, "Key is not a Key"),
                    }
                }
            },

            _ => assert!(false, "Parsed is not a map"),
        }
    }

    #[test]
    fn test_deserialization_without_spec() {
        let text    = String::from("{\"a\": [1], \"b\": {\"c\": -2}}");
        let parser  = JsonHeaderParser::new(None);
        let parsed  = parser.read(Some(text));

        assert!(parsed.is_ok(), "Parsed is not ok: {:?}", parsed);

        match parsed.ok() {
            Some(FHD::Map{keys}) => {
                for k in keys {
                    match_key(&k);
                }
            },

            _ => assert!(false, "Parsed is not a map"),
        }
    }

    fn match_key(k: &FHD) {
        use std::ops::Deref;

        match k {
            &FHD::Key{ref name, ref value} => {
                assert!(name == "a" || name == "b", "Key unknown");
                match value.deref() {
                    &FHD::Array{ref values} => {
                        for value in values.iter() {
                            match value {
                                &FHD::UInteger(u) => assert_eq!(u, 1),
                                _ => assert!(false, "UInt is not an UInt"),
                            }
                        }
                    }

                    &FHD::Map{ref keys} => {
                        for key in keys.iter() {
                            match key {
                                &FHD::Key{ref name, ref value} => {
                                    match value.deref() {
                                        &FHD::Integer(i) => {
                                            assert_eq!(i, -2);
                                            assert_eq!(name, "c");
                                        },
                                        _ => assert!(false, "Int is not an Int"),
                                    };
                                },
                                _ => assert!(false, "Key is not a Key"),
                            }
                        }
                    }
                    _ => assert!(false, "Integers are not here"),
                }
            },
            _ => assert!(false, "Key in main Map is not a Key"),
        }
    }

    #[test]
    fn test_desser() {
        use serde_json::error::Result as R;
        use serde_json::{Value, from_str};

        let text    = String::from("{\"a\": [1], \"b\": {\"c\": -2}}");
        let parser  = JsonHeaderParser::new(None);

        let des = parser.read(Some(text.clone()));
        assert!(des.is_ok(), "Deserializing failed");

        let ser = parser.write(&des.unwrap());
        assert!(ser.is_ok(), "Parser error when serializing deserialized text");

        let json_text : R<Value> = from_str(&text[..]);
        let json_ser  : R<Value> = from_str(&ser.unwrap()[..]);

        assert!(json_text.is_ok(), "Could not use serde to serialize text for comparison");
        assert!(json_ser.is_ok(),  "Could not use serde to serialize serialized-deserialized text for comparison");
        assert_eq!(json_text.unwrap(), json_ser.unwrap());
    }

}
<|endoftext|>


<commit_before>// Parallel mergesort: regular sorting with a parallel merge step.
// O(n log n) time; O(n) extra space; critical path is O(log^3 n)
//
// Algorithm described in: https://software.intel.com/en-us/articles/a-parallel-stable-sort-using-c11-for-tbb-cilk-plus-and-openmp
extern crate rayon;

use std::cmp::max;
use std::env::args;
use std::time::Instant;

pub fn merge_sort<T: Ord + Send + Copy>(v: &mut [T]) {
    let n = v.len();
    let mut buf = Vec::with_capacity(n);
    // We always overwrite the buffer before reading to it, and letting rust
    // initialize it would increase the critical path to O(n).
    unsafe {
        buf.set_len(n);
    }
    rsort(v, &mut buf[..]);
}

// Values from manual tuning gigasort on one machine.
const SORT_CHUNK: usize = 32 * 1024;
const MERGE_CHUNK: usize = 64 * 1024;

// Sort src, possibly making use of identically sized buf.
fn rsort<T: Ord + Send + Copy>(src: &mut [T], buf: &mut [T]) {
    if src.len() <= SORT_CHUNK {
        src.sort();
        return;
    }

    // Sort each half into half of the buffer.
    let mid = src.len() / 2;
    let (bufa, bufb) = buf.split_at_mut(mid);
    {
        let (sa, sb) = src.split_at_mut(mid);
        rayon::join(|| rsort_into(sa, bufa), || rsort_into(sb, bufb));
    }

    // Merge the buffer halves back into the original.
    rmerge(bufa, bufb, src);
}

// Sort src, putting the result into dest.
fn rsort_into<T: Ord + Send + Copy>(src: &mut [T], dest: &mut [T]) {
    let mid = src.len() / 2;
    let (s1, s2) = src.split_at_mut(mid);
    {
        // Sort each half.
        let (d1, d2) = dest.split_at_mut(mid);
        rayon::join(|| rsort(s1, d1), || rsort(s2, d2));
    }

    // Merge the halves into dest.
    rmerge(s1, s2, dest);
}

// Merge sorted inputs a and b, putting result in dest.
// TODO: Figure out how to get a and b immutable with enough template magic.
fn rmerge<T: Ord + Send + Copy>(a: &mut [T], b: &mut [T], dest: &mut [T]) {
    // Swap so a is always longer.
    let (a, b) = if a.len() > b.len() {
        (a, b)
    } else {
        (b, a)
    };
    if dest.len() <= MERGE_CHUNK {
        seq_merge(a, b, dest);
        return;
    }

    // Find the middle element of the longer list, and
    // use binary search to find its location in the shorter list.
    let ma = a.len() / 2;
    let mb = match b.binary_search(&a[ma]) {
        Ok(i) => i,
        Err(i) => i,
    };

    let (a1, a2) = a.split_at_mut(ma);
    let (b1, b2) = b.split_at_mut(mb);
    let (d1, d2) = dest.split_at_mut(ma + mb);
    rayon::join(|| rmerge(a1, b1, d1), || rmerge(a2, b2, d2));
}

// Merges sorted a and b into sorted dest.
#[inline(never)]
fn seq_merge<T: Ord + Copy>(a: &[T], b: &[T], dest: &mut [T]) {
    if b.is_empty() {
        dest.copy_from_slice(a);
        return;
    }
    let biggest = max(*a.last().unwrap(), *b.last().unwrap());
    let mut ai = a.iter();
    let mut an = *ai.next().unwrap();
    let mut bi = b.iter();
    let mut bn = *bi.next().unwrap();
    for d in dest.iter_mut() {
        if an < bn {
            *d = an;
            an = match ai.next() {
                Some(x) => *x,
                None => biggest,
            }
        } else {
            *d = bn;
            bn = match bi.next() {
                Some(x) => *x,
                None => biggest,
            }
        }
    }
}

#[test]
fn test_merge_sort() {
    let mut v = vec![1; 200_000];
    merge_sort(&mut v[..]);

    let sorted: Vec<u32> = (1..1_000_000).collect();
    let mut v = sorted.clone();
    merge_sort(&mut v[..]);
    assert_eq!(sorted, v);

    v.reverse();
    merge_sort(&mut v[..]);
    assert_eq!(sorted, v);
}

pub fn seq_merge_sort<T: Ord + Copy>(v: &mut [T]) {
    let n = v.len();
    let mut buf = Vec::with_capacity(n);
    // We always overwrite the buffer before reading to it, and we want to
    // duplicate the behavior of parallel sort.
    unsafe {
        buf.set_len(n);
    }
    seq_sort(v, &mut buf[..]);
}

// Sort src, possibly making use of identically sized buf.
fn seq_sort<T: Ord + Copy>(src: &mut [T], buf: &mut [T]) {
    if src.len() <= SORT_CHUNK {
        src.sort();
        return;
    }

    // Sort each half into half of the buffer.
    let mid = src.len() / 2;
    let (bufa, bufb) = buf.split_at_mut(mid);
    {
        let (sa, sb) = src.split_at_mut(mid);
        seq_sort_into(sa, bufa);
        seq_sort_into(sb, bufb);
    }

    // Merge the buffer halves back into the original.
    seq_merge(bufa, bufb, src);
}

// Sort src, putting the result into dest.
fn seq_sort_into<T: Ord + Copy>(src: &mut [T], dest: &mut [T]) {
    let mid = src.len() / 2;
    let (s1, s2) = src.split_at_mut(mid);
    {
        // Sort each half.
        let (d1, d2) = dest.split_at_mut(mid);
        seq_sort(s1, d1);
        seq_sort(s2, d2);
    }

    // Merge the halves into dest.
    seq_merge(s1, s2, dest);
}

pub fn is_sorted<T: Send + Ord>(v: &mut [T]) -> bool {
    let n = v.len();
    if n <= SORT_CHUNK {
        for i in 1..n {
            if v[i - 1] >= v[i] {
                return false;
            }
        }
        return true;
    }

    let mid = n / 2;
    if v[mid - 1] >= v[mid] {
        return false;
    }
    let (a, b) = v.split_at_mut(mid);
    let (left, right) = rayon::join(|| is_sorted(a), || is_sorted(b));
    return left && right;
}

fn timed_sort<F: FnOnce(&mut [u32])>(n: usize, f: F, name: &str) -> u64 {
    let mut v = Vec::<u32>::with_capacity(n);
    // Populate with unique, pseudorandom values.
    let mut m = 1;
    for _ in 0..n {
        v.push(m);
        m = m.wrapping_mul(101);
    }

    let start = Instant::now();
    f(&mut v[..]);
    let dur = Instant::now() - start;
    let nanos = dur.subsec_nanos() as u64 + dur.as_secs() * 1_000_000_000u64;
    println!("{}: sorted {} ints: {} s", name, n, nanos as f32 / 1e9f32);

    // Check correctness
    assert!(is_sorted(&mut v[..]));

    return nanos
}

pub fn main() {
    // Default to gigasort: sort one gigabyte of 32-bit ints.
    let giga: usize = 250_000_000;
    let n: usize = args().nth(1).unwrap_or("".to_string()).parse().unwrap_or(giga);
    let seq = timed_sort(n, seq_merge_sort, "seq");
    let par = timed_sort(n, merge_sort, "par");
    let speedup = seq as f64 / par as f64;
    println!("speedup: {:.2}x", speedup);
}
<commit_msg>adjust comment<commit_after>// Parallel mergesort: regular sorting with a parallel merge step.
// O(n log n) time; O(n) extra space; critical path is O(log^3 n)
//
// Algorithm described in: https://software.intel.com/en-us/articles/a-parallel-stable-sort-using-c11-for-tbb-cilk-plus-and-openmp
extern crate rayon;

use std::cmp::max;
use std::env::args;
use std::time::Instant;

pub fn merge_sort<T: Ord + Send + Copy>(v: &mut [T]) {
    let n = v.len();
    let mut buf = Vec::with_capacity(n);
    // We always overwrite the buffer before reading to it, and letting rust
    // initialize it would increase the critical path to O(n).
    unsafe {
        buf.set_len(n);
    }
    rsort(v, &mut buf[..]);
}

// Values from manual tuning gigasort on one machine.
const SORT_CHUNK: usize = 32 * 1024;
const MERGE_CHUNK: usize = 64 * 1024;

// Sort src, possibly making use of identically sized buf.
fn rsort<T: Ord + Send + Copy>(src: &mut [T], buf: &mut [T]) {
    if src.len() <= SORT_CHUNK {
        src.sort();
        return;
    }

    // Sort each half into half of the buffer.
    let mid = src.len() / 2;
    let (bufa, bufb) = buf.split_at_mut(mid);
    {
        let (sa, sb) = src.split_at_mut(mid);
        rayon::join(|| rsort_into(sa, bufa), || rsort_into(sb, bufb));
    }

    // Merge the buffer halves back into the original.
    rmerge(bufa, bufb, src);
}

// Sort src, putting the result into dest.
fn rsort_into<T: Ord + Send + Copy>(src: &mut [T], dest: &mut [T]) {
    let mid = src.len() / 2;
    let (s1, s2) = src.split_at_mut(mid);
    {
        // Sort each half.
        let (d1, d2) = dest.split_at_mut(mid);
        rayon::join(|| rsort(s1, d1), || rsort(s2, d2));
    }

    // Merge the halves into dest.
    rmerge(s1, s2, dest);
}

// Merge sorted inputs a and b, putting result in dest.
//
// Note: `a` and `b` have type `&mut [T]` and not `&[T]` because we do
// not want to require a `T: Sync` bound. Using `&mut` references
// proves to the compiler that we are not sharing `a` and `b` across
// threads and thus we only need a `T: Send` bound.
fn rmerge<T: Ord + Send + Copy>(a: &mut [T], b: &mut [T], dest: &mut [T]) {
    // Swap so a is always longer.
    let (a, b) = if a.len() > b.len() {
        (a, b)
    } else {
        (b, a)
    };
    if dest.len() <= MERGE_CHUNK {
        seq_merge(a, b, dest);
        return;
    }

    // Find the middle element of the longer list, and
    // use binary search to find its location in the shorter list.
    let ma = a.len() / 2;
    let mb = match b.binary_search(&a[ma]) {
        Ok(i) => i,
        Err(i) => i,
    };

    let (a1, a2) = a.split_at_mut(ma);
    let (b1, b2) = b.split_at_mut(mb);
    let (d1, d2) = dest.split_at_mut(ma + mb);
    rayon::join(|| rmerge(a1, b1, d1), || rmerge(a2, b2, d2));
}

// Merges sorted a and b into sorted dest.
#[inline(never)]
fn seq_merge<T: Ord + Copy>(a: &[T], b: &[T], dest: &mut [T]) {
    if b.is_empty() {
        dest.copy_from_slice(a);
        return;
    }
    let biggest = max(*a.last().unwrap(), *b.last().unwrap());
    let mut ai = a.iter();
    let mut an = *ai.next().unwrap();
    let mut bi = b.iter();
    let mut bn = *bi.next().unwrap();
    for d in dest.iter_mut() {
        if an < bn {
            *d = an;
            an = match ai.next() {
                Some(x) => *x,
                None => biggest,
            }
        } else {
            *d = bn;
            bn = match bi.next() {
                Some(x) => *x,
                None => biggest,
            }
        }
    }
}

#[test]
fn test_merge_sort() {
    let mut v = vec![1; 200_000];
    merge_sort(&mut v[..]);

    let sorted: Vec<u32> = (1..1_000_000).collect();
    let mut v = sorted.clone();
    merge_sort(&mut v[..]);
    assert_eq!(sorted, v);

    v.reverse();
    merge_sort(&mut v[..]);
    assert_eq!(sorted, v);
}

pub fn seq_merge_sort<T: Ord + Copy>(v: &mut [T]) {
    let n = v.len();
    let mut buf = Vec::with_capacity(n);
    // We always overwrite the buffer before reading to it, and we want to
    // duplicate the behavior of parallel sort.
    unsafe {
        buf.set_len(n);
    }
    seq_sort(v, &mut buf[..]);
}

// Sort src, possibly making use of identically sized buf.
fn seq_sort<T: Ord + Copy>(src: &mut [T], buf: &mut [T]) {
    if src.len() <= SORT_CHUNK {
        src.sort();
        return;
    }

    // Sort each half into half of the buffer.
    let mid = src.len() / 2;
    let (bufa, bufb) = buf.split_at_mut(mid);
    {
        let (sa, sb) = src.split_at_mut(mid);
        seq_sort_into(sa, bufa);
        seq_sort_into(sb, bufb);
    }

    // Merge the buffer halves back into the original.
    seq_merge(bufa, bufb, src);
}

// Sort src, putting the result into dest.
fn seq_sort_into<T: Ord + Copy>(src: &mut [T], dest: &mut [T]) {
    let mid = src.len() / 2;
    let (s1, s2) = src.split_at_mut(mid);
    {
        // Sort each half.
        let (d1, d2) = dest.split_at_mut(mid);
        seq_sort(s1, d1);
        seq_sort(s2, d2);
    }

    // Merge the halves into dest.
    seq_merge(s1, s2, dest);
}

pub fn is_sorted<T: Send + Ord>(v: &mut [T]) -> bool {
    let n = v.len();
    if n <= SORT_CHUNK {
        for i in 1..n {
            if v[i - 1] >= v[i] {
                return false;
            }
        }
        return true;
    }

    let mid = n / 2;
    if v[mid - 1] >= v[mid] {
        return false;
    }
    let (a, b) = v.split_at_mut(mid);
    let (left, right) = rayon::join(|| is_sorted(a), || is_sorted(b));
    return left && right;
}

fn timed_sort<F: FnOnce(&mut [u32])>(n: usize, f: F, name: &str) -> u64 {
    let mut v = Vec::<u32>::with_capacity(n);
    // Populate with unique, pseudorandom values.
    let mut m = 1;
    for _ in 0..n {
        v.push(m);
        m = m.wrapping_mul(101);
    }

    let start = Instant::now();
    f(&mut v[..]);
    let dur = Instant::now() - start;
    let nanos = dur.subsec_nanos() as u64 + dur.as_secs() * 1_000_000_000u64;
    println!("{}: sorted {} ints: {} s", name, n, nanos as f32 / 1e9f32);

    // Check correctness
    assert!(is_sorted(&mut v[..]));

    return nanos
}

pub fn main() {
    // Default to gigasort: sort one gigabyte of 32-bit ints.
    let giga: usize = 250_000_000;
    let n: usize = args().nth(1).unwrap_or("".to_string()).parse().unwrap_or(giga);
    let seq = timed_sort(n, seq_merge_sort, "seq");
    let par = timed_sort(n, merge_sort, "par");
    let speedup = seq as f64 / par as f64;
    println!("speedup: {:.2}x", speedup);
}
<|endoftext|>


<commit_before>use std::ops::Not;
use std::borrow::Cow;

use types::*;
use requests::*;

/// Use this method to send an audio
#[derive(Debug, Clone, PartialEq, PartialOrd, Serialize)]
#[must_use = "requests do nothing unless sent"]
pub struct SendAudio<'s, 'c, 'p, 't> {
    chat_id: ChatRef,
    audio: Cow<'s, str>,
    #[serde(skip_serializing_if = "Option::is_none")]
    caption: Option<Cow<'c, str>>,
    #[serde(skip_serializing_if = "Option::is_none")]
    parse_mode: Option<ParseMode>,
    #[serde(skip_serializing_if = "Option::is_none")]
    duration: Option<i64>,
    #[serde(skip_serializing_if = "Option::is_none")]
    performer: Option<Cow<'p, str>>,
    #[serde(skip_serializing_if = "Option::is_none")]
    title: Option<Cow<'t, str>>,
    #[serde(skip_serializing_if = "Option::is_none")]
    reply_to_message_id: Option<MessageId>,
    #[serde(skip_serializing_if = "Not::not")]
    disable_notification: bool,
    #[serde(skip_serializing_if = "Option::is_none")]
    reply_markup: Option<ReplyMarkup>,
}

impl<'s, 'c, 'p, 't> Request for SendAudio<'s, 'c, 'p, 't> {
    type Type = JsonRequestType<Self>;
    type Response = JsonTrueToUnitResponse;

    fn serialize(&self) -> Result<HttpRequest, Error> {
        Self::Type::serialize(RequestUrl::method("sendAudio"), self)
    }
}

impl<'s, 'c, 'p, 't> SendAudio<'s, 'c, 'p, 't> {
    pub fn with_url<C, T>(chat: C, url: T) -> Self
    where
        C: ToChatRef,
        T: Into<Cow<'s, str>>,
    {
        Self {
            chat_id: chat.to_chat_ref(),
            audio: url.into(),
            caption: None,
            parse_mode: None,
            duration: None,
            performer: None,
            title: None,
            reply_to_message_id: None,
            reply_markup: None,
            disable_notification: false,
        }
    }

    pub fn caption<T>(&mut self, caption: T) -> &mut Self
    where
        T: Into<Cow<'c, str>>,
    {
        self.caption = Some(caption.into());
        self
    }

    pub fn parse_mode(&mut self, parse_mode: ParseMode) -> &mut Self {
        self.parse_mode = Some(parse_mode);
        self
    }

    pub fn duration(&mut self, duration: i64) -> &mut Self {
        self.duration = Some(duration);
        self
    }

    pub fn performer<T>(&mut self, performer: T) -> &mut Self
    where
        T: Into<Cow<'p, str>>,
    {
        self.performer = Some(performer.into());
        self
    }

    pub fn title<T>(&mut self, title: T) -> &mut Self
    where
        T: Into<Cow<'t, str>>,
    {
        self.title = Some(title.into());
        self
    }

    pub fn reply_to<R>(&mut self, to: R) -> &mut Self
    where
        R: ToMessageId,
    {
        self.reply_to_message_id = Some(to.to_message_id());
        self
    }

    pub fn reply_markup<R>(&mut self, reply_markup: R) -> &mut Self
    where
        R: Into<ReplyMarkup>,
    {
        self.reply_markup = Some(reply_markup.into());
        self
    }
}

/// Can reply with an audio
pub trait CanReplySendAudio {
    fn reply_audio_url<'s, 'c, 'p, 't, T>(&self, url: T) -> SendAudio<'s, 'c, 'p, 't>
    where
        T: Into<Cow<'s, str>>;
}

impl<M> CanReplySendAudio for M
where
    M: ToMessageId + ToSourceChat,
{
    fn reply_audio_url<'s, 'c, 'p, 't, T>(&self, url: T) -> SendAudio<'s, 'c, 'p, 't>
    where
        T: Into<Cow<'s, str>>,
    {
        let mut req = SendAudio::with_url(self.to_source_chat(), url);
        req.reply_to(self);
        req
    }
}

/// Send an audio
pub trait CanSendAudio {
    fn send_audio_url<'s, 'c, 'p, 't, T>(&self, url: T) -> SendAudio<'s, 'c, 'p, 't>
    where
        T: Into<Cow<'s, str>>;
}

impl<M> CanSendAudio for M
where
    M: ToChatRef,
{
    fn send_audio_url<'s, 'c, 'p, 't, T>(&self, url: T) -> SendAudio<'s, 'c, 'p, 't>
    where
        T: Into<Cow<'s, str>>,
    {
        SendAudio::with_url(self.to_chat_ref(), url)
    }
}
<commit_msg>refactor: consistent methods names<commit_after>use std::ops::Not;
use std::borrow::Cow;

use types::*;
use requests::*;

/// Use this method to send an audio
#[derive(Debug, Clone, PartialEq, PartialOrd, Serialize)]
#[must_use = "requests do nothing unless sent"]
pub struct SendAudio<'s, 'c, 'p, 't> {
    chat_id: ChatRef,
    audio: Cow<'s, str>,
    #[serde(skip_serializing_if = "Option::is_none")]
    caption: Option<Cow<'c, str>>,
    #[serde(skip_serializing_if = "Option::is_none")]
    parse_mode: Option<ParseMode>,
    #[serde(skip_serializing_if = "Option::is_none")]
    duration: Option<i64>,
    #[serde(skip_serializing_if = "Option::is_none")]
    performer: Option<Cow<'p, str>>,
    #[serde(skip_serializing_if = "Option::is_none")]
    title: Option<Cow<'t, str>>,
    #[serde(skip_serializing_if = "Option::is_none")]
    reply_to_message_id: Option<MessageId>,
    #[serde(skip_serializing_if = "Not::not")]
    disable_notification: bool,
    #[serde(skip_serializing_if = "Option::is_none")]
    reply_markup: Option<ReplyMarkup>,
}

impl<'s, 'c, 'p, 't> Request for SendAudio<'s, 'c, 'p, 't> {
    type Type = JsonRequestType<Self>;
    type Response = JsonTrueToUnitResponse;

    fn serialize(&self) -> Result<HttpRequest, Error> {
        Self::Type::serialize(RequestUrl::method("sendAudio"), self)
    }
}

impl<'s, 'c, 'p, 't> SendAudio<'s, 'c, 'p, 't> {
    pub fn with_url<C, T>(chat: C, url: T) -> Self
    where
        C: ToChatRef,
        T: Into<Cow<'s, str>>,
    {
        Self {
            chat_id: chat.to_chat_ref(),
            audio: url.into(),
            caption: None,
            parse_mode: None,
            duration: None,
            performer: None,
            title: None,
            reply_to_message_id: None,
            reply_markup: None,
            disable_notification: false,
        }
    }

    pub fn caption<T>(&mut self, caption: T) -> &mut Self
    where
        T: Into<Cow<'c, str>>,
    {
        self.caption = Some(caption.into());
        self
    }

    pub fn parse_mode(&mut self, parse_mode: ParseMode) -> &mut Self {
        self.parse_mode = Some(parse_mode);
        self
    }

    pub fn duration(&mut self, duration: i64) -> &mut Self {
        self.duration = Some(duration);
        self
    }

    pub fn performer<T>(&mut self, performer: T) -> &mut Self
    where
        T: Into<Cow<'p, str>>,
    {
        self.performer = Some(performer.into());
        self
    }

    pub fn title<T>(&mut self, title: T) -> &mut Self
    where
        T: Into<Cow<'t, str>>,
    {
        self.title = Some(title.into());
        self
    }

    pub fn reply_to<R>(&mut self, to: R) -> &mut Self
    where
        R: ToMessageId,
    {
        self.reply_to_message_id = Some(to.to_message_id());
        self
    }

    pub fn reply_markup<R>(&mut self, reply_markup: R) -> &mut Self
    where
        R: Into<ReplyMarkup>,
    {
        self.reply_markup = Some(reply_markup.into());
        self
    }
}

/// Can reply with an audio
pub trait CanReplySendAudio {
    fn audio_url_reply<'s, 'c, 'p, 't, T>(&self, url: T) -> SendAudio<'s, 'c, 'p, 't>
    where
        T: Into<Cow<'s, str>>;
}

impl<M> CanReplySendAudio for M
where
    M: ToMessageId + ToSourceChat,
{
    fn audio_url_reply<'s, 'c, 'p, 't, T>(&self, url: T) -> SendAudio<'s, 'c, 'p, 't>
    where
        T: Into<Cow<'s, str>>,
    {
        let mut req = SendAudio::with_url(self.to_source_chat(), url);
        req.reply_to(self);
        req
    }
}

/// Send an audio
pub trait CanSendAudio {
    fn audio_url<'s, 'c, 'p, 't, T>(&self, url: T) -> SendAudio<'s, 'c, 'p, 't>
    where
        T: Into<Cow<'s, str>>;
}

impl<M> CanSendAudio for M
where
    M: ToChatRef,
{
    fn audio_url<'s, 'c, 'p, 't, T>(&self, url: T) -> SendAudio<'s, 'c, 'p, 't>
    where
        T: Into<Cow<'s, str>>,
    {
        SendAudio::with_url(self.to_chat_ref(), url)
    }
}
<|endoftext|>


<commit_before>// ignore-windows: File handling is not implemented yet
// compile-flags: -Zmiri-disable-isolation

use std::fs::{File, create_dir, read_dir, remove_dir, remove_dir_all, remove_file, rename};
use std::io::{Read, Write, ErrorKind, Result, Seek, SeekFrom};
use std::path::{PathBuf, Path};

fn main() {
    test_file();
    test_file_clone();
    test_seek();
    test_metadata();
    test_symlink();
    test_errors();
    test_rename();
    test_directory();
}

/// Prepare: compute filename and make sure the file does not exist.
fn prepare(filename: &str) -> PathBuf {
    let tmp = std::env::temp_dir();
    let path = tmp.join(filename);
    // Clean the paths for robustness.
    remove_file(&path).ok();
    path
}

/// Prepare directory: compute directory name and make sure it does not exist.
fn prepare_dir(dirname: &str) -> PathBuf {
    let tmp = std::env::temp_dir();
    let path = tmp.join(&dirname);
    // Clean the directory for robustness.
    remove_dir_all(&path).ok();
    path
}

/// Prepare like above, and also write some initial content to the file.
fn prepare_with_content(filename: &str, content: &[u8]) -> PathBuf {
    let path = prepare(filename);
    let mut file = File::create(&path).unwrap();
    file.write(content).unwrap();
    path
}

fn test_file() {
    let bytes = b"Hello, World!\n";
    let path = prepare("miri_test_fs_file.txt");

    // Test creating, writing and closing a file (closing is tested when `file` is dropped).
    let mut file = File::create(&path).unwrap();
    // Writing 0 bytes should not change the file contents.
    file.write(&mut []).unwrap();
    assert_eq!(file.metadata().unwrap().len(), 0);

    file.write(bytes).unwrap();
    assert_eq!(file.metadata().unwrap().len(), bytes.len() as u64);
    // Test opening, reading and closing a file.
    let mut file = File::open(&path).unwrap();
    let mut contents = Vec::new();
    // Reading 0 bytes should not move the file pointer.
    file.read(&mut []).unwrap();
    // Reading until EOF should get the whole text.
    file.read_to_end(&mut contents).unwrap();
    assert_eq!(bytes, contents.as_slice());

    // Removing file should succeed.
    remove_file(&path).unwrap();
}

fn test_file_clone() {
    let bytes = b"Hello, World!\n";
    let path = prepare_with_content("miri_test_fs_file_clone.txt", bytes);

    // Cloning a file should be successful.
    let file = File::open(&path).unwrap();
    let mut cloned = file.try_clone().unwrap();
    // Reading from a cloned file should get the same text.
    let mut contents = Vec::new();
    cloned.read_to_end(&mut contents).unwrap();
    assert_eq!(bytes, contents.as_slice());

    // Removing file should succeed.
    remove_file(&path).unwrap();
}

fn test_seek() {
    let bytes = b"Hello, entire World!\n";
    let path = prepare_with_content("miri_test_fs_seek.txt", bytes);

    let mut file = File::open(&path).unwrap();
    let mut contents = Vec::new();
    file.read_to_end(&mut contents).unwrap();
    assert_eq!(bytes, contents.as_slice());
    // Test that seeking to the beginning and reading until EOF gets the text again.
    file.seek(SeekFrom::Start(0)).unwrap();
    let mut contents = Vec::new();
    file.read_to_end(&mut contents).unwrap();
    assert_eq!(bytes, contents.as_slice());
    // Test seeking relative to the end of the file.
    file.seek(SeekFrom::End(-1)).unwrap();
    let mut contents = Vec::new();
    file.read_to_end(&mut contents).unwrap();
    assert_eq!(&bytes[bytes.len() - 1..], contents.as_slice());
    // Test seeking relative to the current position.
    file.seek(SeekFrom::Start(5)).unwrap();
    file.seek(SeekFrom::Current(-3)).unwrap();
    let mut contents = Vec::new();
    file.read_to_end(&mut contents).unwrap();
    assert_eq!(&bytes[2..], contents.as_slice());

    // Removing file should succeed.
    remove_file(&path).unwrap();
}

fn check_metadata(bytes: &[u8], path: &Path) -> Result<()> {
    // Test that the file metadata is correct.
    let metadata = path.metadata()?;
    // `path` should point to a file.
    assert!(metadata.is_file());
    // The size of the file must be equal to the number of written bytes.
    assert_eq!(bytes.len() as u64, metadata.len());
    Ok(())
}

fn test_metadata() {
    let bytes = b"Hello, meta-World!\n";
    let path = prepare_with_content("miri_test_fs_metadata.txt", bytes);

    // Test that metadata of an absolute path is correct.
    check_metadata(bytes, &path).unwrap();
    // Test that metadata of a relative path is correct.
    std::env::set_current_dir(path.parent().unwrap()).unwrap();
    check_metadata(bytes, Path::new(path.file_name().unwrap())).unwrap();

    // Removing file should succeed.
    remove_file(&path).unwrap();
}

fn test_symlink() {
    let bytes = b"Hello, World!\n";
    let path = prepare_with_content("miri_test_fs_link_target.txt", bytes);
    let symlink_path = prepare("miri_test_fs_symlink.txt");

    // Creating a symbolic link should succeed.
    std::os::unix::fs::symlink(&path, &symlink_path).unwrap();
    // Test that the symbolic link has the same contents as the file.
    let mut symlink_file = File::open(&symlink_path).unwrap();
    let mut contents = Vec::new();
    symlink_file.read_to_end(&mut contents).unwrap();
    assert_eq!(bytes, contents.as_slice());
    // Test that metadata of a symbolic link is correct.
    check_metadata(bytes, &symlink_path).unwrap();
    // Test that the metadata of a symbolic link is correct when not following it.
    assert!(symlink_path.symlink_metadata().unwrap().file_type().is_symlink());
    // Removing symbolic link should succeed.
    remove_file(&symlink_path).unwrap();

    // Removing file should succeed.
    remove_file(&path).unwrap();
}

fn test_errors() {
    let bytes = b"Hello, World!\n";
    let path = prepare("miri_test_fs_errors.txt");

    // The following tests also check that the `__errno_location()` shim is working properly.
    // Opening a non-existing file should fail with a "not found" error.
    assert_eq!(ErrorKind::NotFound, File::open(&path).unwrap_err().kind());
    // Removing a non-existing file should fail with a "not found" error.
    assert_eq!(ErrorKind::NotFound, remove_file(&path).unwrap_err().kind());
    // Reading the metadata of a non-existing file should fail with a "not found" error.
    assert_eq!(ErrorKind::NotFound, check_metadata(bytes, &path).unwrap_err().kind());
}

fn test_rename() {
    // Renaming a file should succeed.
    let path1 = prepare("miri_test_fs_rename_source.txt");
    let path2 = prepare("miri_test_fs_rename_destination.txt");

    let file = File::create(&path1).unwrap();
    drop(file);

    // Renaming should succeed
    rename(&path1, &path2).unwrap();
    // Check that the old file path isn't present
    assert_eq!(ErrorKind::NotFound, path1.metadata().unwrap_err().kind());
    // Check that the file has moved successfully
    assert!(path2.metadata().unwrap().is_file());

    // Renaming a nonexistent file should fail
    assert_eq!(ErrorKind::NotFound, rename(&path1, &path2).unwrap_err().kind());

    remove_file(&path2).unwrap();
}

fn test_directory() {
    let dir_path = prepare_dir("miri_test_fs_dir");
    // Creating a directory should succeed.
    create_dir(&dir_path).unwrap();
    // Test that the metadata of a directory is correct.
    assert!(dir_path.metadata().unwrap().is_dir());
    // Creating a directory when it already exists should fail.
    assert_eq!(ErrorKind::AlreadyExists, create_dir(&dir_path).unwrap_err().kind());

    // Create some files inside the directory
    let path_1 = dir_path.join("test_file_1");
    drop(File::create(&path_1).unwrap());
    let path_2 = dir_path.join("test_file_2");
    drop(File::create(&path_2).unwrap());
    // Test that the files are present inside the directory
    let dir_iter = read_dir(&dir_path).unwrap();
    let mut file_names = dir_iter.map(|e| e.unwrap().file_name()).collect::<Vec<_>>();
    file_names.sort_unstable();
    assert_eq!(file_names, vec!["test_file_1", "test_file_2"]);
    // Clean up the files in the directory
    remove_file(&path_1).unwrap();
    remove_file(&path_2).unwrap();
    // Now there should be nothing left in the directory.
    let dir_iter = read_dir(&dir_path).unwrap();
    let file_names = dir_iter.map(|e| e.unwrap().file_name()).collect::<Vec<_>>();
    assert!(file_names.is_empty());

    // Deleting the directory should succeed.
    remove_dir(&dir_path).unwrap();
    // Reading the metadata of a non-existent directory should fail with a "not found" error.
    assert_eq!(ErrorKind::NotFound, check_metadata(&[], &dir_path).unwrap_err().kind());
}
<commit_msg>make fs.rs at least build under Windows<commit_after>// ignore-windows: File handling is not implemented yet
// compile-flags: -Zmiri-disable-isolation

use std::fs::{File, create_dir, read_dir, remove_dir, remove_dir_all, remove_file, rename};
use std::io::{Read, Write, ErrorKind, Result, Seek, SeekFrom};
use std::path::{PathBuf, Path};

fn main() {
    test_file();
    test_file_clone();
    test_seek();
    test_metadata();
    test_symlink();
    test_errors();
    test_rename();
    test_directory();
}

/// Prepare: compute filename and make sure the file does not exist.
fn prepare(filename: &str) -> PathBuf {
    let tmp = std::env::temp_dir();
    let path = tmp.join(filename);
    // Clean the paths for robustness.
    remove_file(&path).ok();
    path
}

/// Prepare directory: compute directory name and make sure it does not exist.
fn prepare_dir(dirname: &str) -> PathBuf {
    let tmp = std::env::temp_dir();
    let path = tmp.join(&dirname);
    // Clean the directory for robustness.
    remove_dir_all(&path).ok();
    path
}

/// Prepare like above, and also write some initial content to the file.
fn prepare_with_content(filename: &str, content: &[u8]) -> PathBuf {
    let path = prepare(filename);
    let mut file = File::create(&path).unwrap();
    file.write(content).unwrap();
    path
}

fn test_file() {
    let bytes = b"Hello, World!\n";
    let path = prepare("miri_test_fs_file.txt");

    // Test creating, writing and closing a file (closing is tested when `file` is dropped).
    let mut file = File::create(&path).unwrap();
    // Writing 0 bytes should not change the file contents.
    file.write(&mut []).unwrap();
    assert_eq!(file.metadata().unwrap().len(), 0);

    file.write(bytes).unwrap();
    assert_eq!(file.metadata().unwrap().len(), bytes.len() as u64);
    // Test opening, reading and closing a file.
    let mut file = File::open(&path).unwrap();
    let mut contents = Vec::new();
    // Reading 0 bytes should not move the file pointer.
    file.read(&mut []).unwrap();
    // Reading until EOF should get the whole text.
    file.read_to_end(&mut contents).unwrap();
    assert_eq!(bytes, contents.as_slice());

    // Removing file should succeed.
    remove_file(&path).unwrap();
}

fn test_file_clone() {
    let bytes = b"Hello, World!\n";
    let path = prepare_with_content("miri_test_fs_file_clone.txt", bytes);

    // Cloning a file should be successful.
    let file = File::open(&path).unwrap();
    let mut cloned = file.try_clone().unwrap();
    // Reading from a cloned file should get the same text.
    let mut contents = Vec::new();
    cloned.read_to_end(&mut contents).unwrap();
    assert_eq!(bytes, contents.as_slice());

    // Removing file should succeed.
    remove_file(&path).unwrap();
}

fn test_seek() {
    let bytes = b"Hello, entire World!\n";
    let path = prepare_with_content("miri_test_fs_seek.txt", bytes);

    let mut file = File::open(&path).unwrap();
    let mut contents = Vec::new();
    file.read_to_end(&mut contents).unwrap();
    assert_eq!(bytes, contents.as_slice());
    // Test that seeking to the beginning and reading until EOF gets the text again.
    file.seek(SeekFrom::Start(0)).unwrap();
    let mut contents = Vec::new();
    file.read_to_end(&mut contents).unwrap();
    assert_eq!(bytes, contents.as_slice());
    // Test seeking relative to the end of the file.
    file.seek(SeekFrom::End(-1)).unwrap();
    let mut contents = Vec::new();
    file.read_to_end(&mut contents).unwrap();
    assert_eq!(&bytes[bytes.len() - 1..], contents.as_slice());
    // Test seeking relative to the current position.
    file.seek(SeekFrom::Start(5)).unwrap();
    file.seek(SeekFrom::Current(-3)).unwrap();
    let mut contents = Vec::new();
    file.read_to_end(&mut contents).unwrap();
    assert_eq!(&bytes[2..], contents.as_slice());

    // Removing file should succeed.
    remove_file(&path).unwrap();
}

fn check_metadata(bytes: &[u8], path: &Path) -> Result<()> {
    // Test that the file metadata is correct.
    let metadata = path.metadata()?;
    // `path` should point to a file.
    assert!(metadata.is_file());
    // The size of the file must be equal to the number of written bytes.
    assert_eq!(bytes.len() as u64, metadata.len());
    Ok(())
}

fn test_metadata() {
    let bytes = b"Hello, meta-World!\n";
    let path = prepare_with_content("miri_test_fs_metadata.txt", bytes);

    // Test that metadata of an absolute path is correct.
    check_metadata(bytes, &path).unwrap();
    // Test that metadata of a relative path is correct.
    std::env::set_current_dir(path.parent().unwrap()).unwrap();
    check_metadata(bytes, Path::new(path.file_name().unwrap())).unwrap();

    // Removing file should succeed.
    remove_file(&path).unwrap();
}

fn test_symlink() {
    let bytes = b"Hello, World!\n";
    let path = prepare_with_content("miri_test_fs_link_target.txt", bytes);
    let symlink_path = prepare("miri_test_fs_symlink.txt");

    // Creating a symbolic link should succeed.
    #[cfg(unix)]
    std::os::unix::fs::symlink(&path, &symlink_path).unwrap();
    #[cfg(windows)]
    std::os::windows::fs::symlink_file(&path, &symlink_path).unwrap();
    // Test that the symbolic link has the same contents as the file.
    let mut symlink_file = File::open(&symlink_path).unwrap();
    let mut contents = Vec::new();
    symlink_file.read_to_end(&mut contents).unwrap();
    assert_eq!(bytes, contents.as_slice());
    // Test that metadata of a symbolic link is correct.
    check_metadata(bytes, &symlink_path).unwrap();
    // Test that the metadata of a symbolic link is correct when not following it.
    assert!(symlink_path.symlink_metadata().unwrap().file_type().is_symlink());
    // Removing symbolic link should succeed.
    remove_file(&symlink_path).unwrap();

    // Removing file should succeed.
    remove_file(&path).unwrap();
}

fn test_errors() {
    let bytes = b"Hello, World!\n";
    let path = prepare("miri_test_fs_errors.txt");

    // The following tests also check that the `__errno_location()` shim is working properly.
    // Opening a non-existing file should fail with a "not found" error.
    assert_eq!(ErrorKind::NotFound, File::open(&path).unwrap_err().kind());
    // Removing a non-existing file should fail with a "not found" error.
    assert_eq!(ErrorKind::NotFound, remove_file(&path).unwrap_err().kind());
    // Reading the metadata of a non-existing file should fail with a "not found" error.
    assert_eq!(ErrorKind::NotFound, check_metadata(bytes, &path).unwrap_err().kind());
}

fn test_rename() {
    // Renaming a file should succeed.
    let path1 = prepare("miri_test_fs_rename_source.txt");
    let path2 = prepare("miri_test_fs_rename_destination.txt");

    let file = File::create(&path1).unwrap();
    drop(file);

    // Renaming should succeed
    rename(&path1, &path2).unwrap();
    // Check that the old file path isn't present
    assert_eq!(ErrorKind::NotFound, path1.metadata().unwrap_err().kind());
    // Check that the file has moved successfully
    assert!(path2.metadata().unwrap().is_file());

    // Renaming a nonexistent file should fail
    assert_eq!(ErrorKind::NotFound, rename(&path1, &path2).unwrap_err().kind());

    remove_file(&path2).unwrap();
}

fn test_directory() {
    let dir_path = prepare_dir("miri_test_fs_dir");
    // Creating a directory should succeed.
    create_dir(&dir_path).unwrap();
    // Test that the metadata of a directory is correct.
    assert!(dir_path.metadata().unwrap().is_dir());
    // Creating a directory when it already exists should fail.
    assert_eq!(ErrorKind::AlreadyExists, create_dir(&dir_path).unwrap_err().kind());

    // Create some files inside the directory
    let path_1 = dir_path.join("test_file_1");
    drop(File::create(&path_1).unwrap());
    let path_2 = dir_path.join("test_file_2");
    drop(File::create(&path_2).unwrap());
    // Test that the files are present inside the directory
    let dir_iter = read_dir(&dir_path).unwrap();
    let mut file_names = dir_iter.map(|e| e.unwrap().file_name()).collect::<Vec<_>>();
    file_names.sort_unstable();
    assert_eq!(file_names, vec!["test_file_1", "test_file_2"]);
    // Clean up the files in the directory
    remove_file(&path_1).unwrap();
    remove_file(&path_2).unwrap();
    // Now there should be nothing left in the directory.
    let dir_iter = read_dir(&dir_path).unwrap();
    let file_names = dir_iter.map(|e| e.unwrap().file_name()).collect::<Vec<_>>();
    assert!(file_names.is_empty());

    // Deleting the directory should succeed.
    remove_dir(&dir_path).unwrap();
    // Reading the metadata of a non-existent directory should fail with a "not found" error.
    assert_eq!(ErrorKind::NotFound, check_metadata(&[], &dir_path).unwrap_err().kind());
}
<|endoftext|>


<commit_before>#![feature(nll)]

use std::borrow::Cow;

#[derive(Clone, Debug)]
struct S<'a> {
    name: Cow<'a, str>
}

#[derive(Clone, Debug)]
struct T<'a> {
    s: Cow<'a, [S<'a>]>
}

fn main() {
    let s1 = [S { name: Cow::Borrowed("Test1") }, S { name: Cow::Borrowed("Test2") }];
    let b1 = T { s: Cow::Borrowed(&s1) };
    let s2 = [S { name: Cow::Borrowed("Test3") }, S { name: Cow::Borrowed("Test4") }];
    let b2 = T { s: Cow::Borrowed(&s2) };

    let mut v = Vec::new();
    v.push(b1);
    v.push(b2);

    println!("{:?}", v);
}<commit_msg>Formatting<commit_after>// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// must-compile-successfully

#![feature(nll)]

use std::borrow::Cow;

#[derive(Clone, Debug)]
struct S<'a> {
    name: Cow<'a, str>
}

#[derive(Clone, Debug)]
struct T<'a> {
    s: Cow<'a, [S<'a>]>
}

fn main() {
    let s1 = [S { name: Cow::Borrowed("Test1") }, S { name: Cow::Borrowed("Test2") }];
    let b1 = T { s: Cow::Borrowed(&s1) };
    let s2 = [S { name: Cow::Borrowed("Test3") }, S { name: Cow::Borrowed("Test4") }];
    let b2 = T { s: Cow::Borrowed(&s2) };

    let mut v = Vec::new();
    v.push(b1);
    v.push(b2);

    println!("{:?}", v);
}
<|endoftext|>


<commit_before>use crate::Factors;
use std::num::Wrapping;

include!(concat!(env!("OUT_DIR"), "/prime_table.rs"));

pub(crate) fn factor(mut num: u64) -> (Factors, u64) {
    let mut factors = Factors::new();
    for &(prime, inv, ceil) in P_INVS_U64 {
        if num == 1 {
            break;
        }

        // inv = prime^-1 mod 2^64
        // ceil = floor((2^64-1) / prime)
        // if (num * inv) mod 2^64 <= ceil, then prime divides num
        // See https://math.stackexchange.com/questions/1251327/
        // for a nice explanation.
        loop {
            let Wrapping(x) = Wrapping(num) * Wrapping(inv);

            // While prime divides num
            if x <= ceil {
                num = x;
                factors.push(prime);
            } else {
                break;
            }
        }
    }

    // do we still have more factoring to do?
    // Decide whether to use Pollard Rho or slow divisibility based on
    // number's size:
    //if num >= 1 << 63 {
    // number is too big to use rho pollard without overflowing
    //trial_division_slow(num, factors);
    //} else if num > 1 {
    // number is still greater than 1, but not so big that we have to worry
    (factors, num)
    //}
}
<commit_msg>factor::table: Remove obsolete, commented code<commit_after>use crate::Factors;
use std::num::Wrapping;

include!(concat!(env!("OUT_DIR"), "/prime_table.rs"));

pub(crate) fn factor(mut num: u64) -> (Factors, u64) {
    let mut factors = Factors::new();
    for &(prime, inv, ceil) in P_INVS_U64 {
        if num == 1 {
            break;
        }

        // inv = prime^-1 mod 2^64
        // ceil = floor((2^64-1) / prime)
        // if (num * inv) mod 2^64 <= ceil, then prime divides num
        // See https://math.stackexchange.com/questions/1251327/
        // for a nice explanation.
        loop {
            let Wrapping(x) = Wrapping(num) * Wrapping(inv);

            // While prime divides num
            if x <= ceil {
                num = x;
                factors.push(prime);
            } else {
                break;
            }
        }
    }

    (factors, num)
}
<|endoftext|>


<commit_before>extern crate tokio_core;
extern crate futures;
extern crate reqwest;
extern crate serde;

extern crate influxdb;

use std::error::Error;
use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering};

use futures::Future;

use influxdb::{AsyncDb, QueryResponse, InfluxServerError};

const HOSTNAME: &'static str = "http://localhost:8086/";

#[test]
fn query_asynchronously() {
    let db = fresh_db();

    db.add_data("cpu_load_short,host=server01,region=us-west value=0.64 1434055562000000000")
        .unwrap();

    let response = with_core(|core| {
        let async_db = AsyncDb::new(core.handle(), HOSTNAME, &db.name).unwrap();

        async_db.query(r#"SELECT "value","host" FROM "cpu_load_short" WHERE "region"='us-west'"#)
    });

    assert_eq!(response.results[0].series[0].name, "cpu_load_short");
    assert_eq!(response.results[0].series[0].values[0][1].as_f64(), Some(0.64));
    assert_eq!(response.results[0].series[0].values[0][2].as_str(), Some("server01"));
}

#[test]
fn add_data_asynchronously() {
    let db = fresh_db();

    with_core(|core| {
        let async_db = AsyncDb::new(core.handle(), HOSTNAME, &db.name).unwrap();

        async_db.add_data("cpu_load_short,host=server01,region=us-west value=0.64 1434055562000000000")
    });

    let response: QueryResponse = db.query(r#"SELECT "value","host" FROM "cpu_load_short" WHERE "region"='us-west'"#).unwrap();

    assert_eq!(response.results[0].error, None);
    assert_eq!(response.results[0].series[0].name, "cpu_load_short");
    assert_eq!(response.results[0].series[0].values[0][1].as_f64(), Some(0.64));
    assert_eq!(response.results[0].series[0].values[0][2].as_str(), Some("server01"));
}

#[test]
fn query_nonexistent_db() {
    let response = with_core(|core| {
        let async_db = AsyncDb::new(core.handle(), HOSTNAME, "does_not_exist").unwrap();

        async_db.query(r#"SELECT "value","host" FROM "cpu_load_short" WHERE "region"='us-west'"#)
    });

    assert_eq!(response.results[0].error, Some(String::from("database not found: does_not_exist")));
}

#[test]
fn multiple_queries() {
    let db = fresh_db();

    db.add_data("cpu_load_short,host=server01,region=us-west value=0.64 1434055562000000000")
        .unwrap();
    db.add_data("cpu_load_short,host=server02,region=us-west value=0.8")
        .unwrap();
    db.add_data("cpu_load_short,host=server01,region=us-west value=0.4")
        .unwrap();

    let mut response = with_core(|core| {
        let async_db = AsyncDb::new(core.handle(), HOSTNAME, &db.name).unwrap();

        async_db.query(r#"SELECT "value","host" FROM "cpu_load_short" WHERE "region"='us-west'; SELECT "value" FROM "cpu_load_short" WHERE "host"='server01'"#)
    });

    response.results.sort_by_key(|k| k.statement_id);

    assert_eq!(response.results[0].statement_id, 0);
    assert_eq!(response.results[0].series[0].name, "cpu_load_short");
    assert_eq!(response.results[0].series[0].values[0][1].as_f64(), Some(0.64));
    assert_eq!(response.results[0].series[0].values[0][2].as_str(), Some("server01"));

    assert_eq!(response.results[1].statement_id, 1);
    assert_eq!(response.results[1].series[0].name, "cpu_load_short");
    assert_eq!(response.results[1].series[0].values[0][1].as_f64(), Some(0.64));
    assert_eq!(response.results[1].series[0].values[1][1].as_f64(), Some(0.4));
}

#[test]
fn test_infrastructure() {
    let db = fresh_db();

    db.add_data("cpu_load_short,host=server01,region=us-west value=0.64 1434055562000000000")
        .unwrap();

    let response: QueryResponse =
        db.query(r#"SELECT "value","host" FROM "cpu_load_short" WHERE "region"='us-west'"#)
        .unwrap();

    assert_eq!(response.results[0].series[0].name, "cpu_load_short");
    assert_eq!(response.results[0].series[0].values[0][1].as_f64(), Some(0.64));
    assert_eq!(response.results[0].series[0].values[0][2].as_str(), Some("server01"));
}

fn fresh_db() -> TestingDb {
    static DB_COUNTER: AtomicUsize = ATOMIC_USIZE_INIT;

    let id = DB_COUNTER.fetch_add(1, Ordering::SeqCst);
    let name = format!("influxdb_rs_{}", id);
    let db = TestingDb::new(HOSTNAME, name)
        .expect("Unable to create test database");
    db.create_db()
        .expect("Unable to create test database");

    // The InfluxDB created isn't ready immediately; this prevents
    // intermittent failures.
    std::thread::sleep(std::time::Duration::from_millis(5));
    db
}

fn with_core<F, T>(f: F) -> T::Item
    where F: FnOnce(&mut tokio_core::reactor::Core) -> T,
          T: Future,
          T::Error: std::fmt::Debug,
{
    let mut core = tokio_core::reactor::Core::new()
        .expect("Unable to create reactor core for testing");

    let future = f(&mut core);

    core.run(future).expect("Unable to run future to completion")
}

struct TestingDb {
    name: String,
    client: reqwest::Client,
    query_endpoint: reqwest::Url,
    write_endpoint: reqwest::Url,
}

impl TestingDb {
    /// `base_url` should include the protocol, host, and port (`http://localhost:8086`)
    fn new<S>(base_url: &str, name: S) -> Result<Self, Box<Error>>
        where S: Into<String>,
    {
        let name = name.into();

        let base_url = reqwest::Url::parse(base_url)?;
        let query_endpoint = base_url.join("/query")?;
        let mut write_endpoint = base_url.join("/write")?;
        write_endpoint.query_pairs_mut()
            .append_pair("db", &name);

        let client = reqwest::Client::new()?;

        Ok(TestingDb {
            name: name,
            client: client,
            query_endpoint: query_endpoint,
            write_endpoint: write_endpoint,
        })
    }

    fn create_db(&self) -> Result<(), Box<Error>> {
        let mut u = self.query_endpoint.clone();
        u.query_pairs_mut()
            .append_pair("q", &format!("CREATE DATABASE {}", self.name));
        let mut res = self.client.post(u).send()?;

        check_result(&mut res)?;
        Ok(())
    }

    fn drop_db(&self) -> Result<(), Box<Error>> {
        let mut u = self.query_endpoint.clone();
        u.query_pairs_mut()
            .append_pair("q", &format!("DROP DATABASE {}", self.name));
        let mut res = self.client.post(u).send()?;

        check_result(&mut res)?;
        Ok(())
    }

    fn add_data(&self, data: &str) -> Result<(), Box<Error>> {
        let mut res = self.client.post(self.write_endpoint.clone())
            .body(data)
            .send()?;

        check_result(&mut res)?;
        Ok(())
    }

    fn query<T>(&self, query: &str) -> Result<T, Box<Error>>
        where T: serde::Deserialize,
    {
        let mut u = self.query_endpoint.clone();
        u.query_pairs_mut()
            .append_pair("db", &self.name)
            .append_pair("q", query);
        let mut res = self.client.get(u).send()?;

        check_result(&mut res)?;
        let val = res.json()?;
        Ok(val)
    }
}

impl Drop for TestingDb {
    fn drop(&mut self) {
        // TODO: What happens if we drop twice?
        self.drop_db().unwrap_or_else(|e| panic!("Unable to drop database {}: {}", self.name, e));
    }
}

fn check_result(res: &mut reqwest::Response) -> Result<(), Box<Error>> {
    let status = *res.status();

    if status.is_success() {
        Ok(())
    } else if status.is_client_error() {
        Err(parse_influx_server_error(res, "Client error").into())
    } else if status.is_server_error() {
        Err(parse_influx_server_error(res, "Server error").into())
    } else {
        Err(parse_influx_server_error(res, "Unknown error").into())
    }
}

fn parse_influx_server_error(res: &mut reqwest::Response, kind: &str) -> String {
    match res.json::<InfluxServerError>() {
        Ok(e) => format!("{}: {}", kind, e.error),
        Err(_) => format!("{}: (unable to parse error message)", kind),
    }
}
<commit_msg>Add a test for multiple queries to a nonexistent database<commit_after>extern crate tokio_core;
extern crate futures;
extern crate reqwest;
extern crate serde;

extern crate influxdb;

use std::error::Error;
use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering};

use futures::Future;

use influxdb::{AsyncDb, QueryResponse, InfluxServerError};

const HOSTNAME: &'static str = "http://localhost:8086/";

#[test]
fn query_asynchronously() {
    let db = fresh_db();

    db.add_data("cpu_load_short,host=server01,region=us-west value=0.64 1434055562000000000")
        .unwrap();

    let response = with_core(|core| {
        let async_db = AsyncDb::new(core.handle(), HOSTNAME, &db.name).unwrap();

        async_db.query(r#"SELECT "value","host" FROM "cpu_load_short" WHERE "region"='us-west'"#)
    });

    assert_eq!(response.results[0].series[0].name, "cpu_load_short");
    assert_eq!(response.results[0].series[0].values[0][1].as_f64(), Some(0.64));
    assert_eq!(response.results[0].series[0].values[0][2].as_str(), Some("server01"));
}

#[test]
fn add_data_asynchronously() {
    let db = fresh_db();

    with_core(|core| {
        let async_db = AsyncDb::new(core.handle(), HOSTNAME, &db.name).unwrap();

        async_db.add_data("cpu_load_short,host=server01,region=us-west value=0.64 1434055562000000000")
    });

    let response: QueryResponse = db.query(r#"SELECT "value","host" FROM "cpu_load_short" WHERE "region"='us-west'"#).unwrap();

    assert_eq!(response.results[0].error, None);
    assert_eq!(response.results[0].series[0].name, "cpu_load_short");
    assert_eq!(response.results[0].series[0].values[0][1].as_f64(), Some(0.64));
    assert_eq!(response.results[0].series[0].values[0][2].as_str(), Some("server01"));
}

#[test]
fn query_nonexistent_db() {
    let response = with_core(|core| {
        let async_db = AsyncDb::new(core.handle(), HOSTNAME, "does_not_exist").unwrap();

        async_db.query(r#"SELECT "value","host" FROM "cpu_load_short" WHERE "region"='us-west'"#)
    });

    assert_eq!(response.results[0].error, Some(String::from("database not found: does_not_exist")));
}

#[test]
fn multiple_queries() {
    let db = fresh_db();

    db.add_data("cpu_load_short,host=server01,region=us-west value=0.64 1434055562000000000")
        .unwrap();
    db.add_data("cpu_load_short,host=server02,region=us-west value=0.8")
        .unwrap();
    db.add_data("cpu_load_short,host=server01,region=us-west value=0.4")
        .unwrap();

    let mut response = with_core(|core| {
        let async_db = AsyncDb::new(core.handle(), HOSTNAME, &db.name).unwrap();

        async_db.query(r#"SELECT "value","host" FROM "cpu_load_short" WHERE "region"='us-west'; SELECT "value" FROM "cpu_load_short" WHERE "host"='server01'"#)
    });

    response.results.sort_by_key(|k| k.statement_id);

    assert_eq!(response.results[0].statement_id, 0);
    assert_eq!(response.results[0].series[0].name, "cpu_load_short");
    assert_eq!(response.results[0].series[0].values[0][1].as_f64(), Some(0.64));
    assert_eq!(response.results[0].series[0].values[0][2].as_str(), Some("server01"));

    assert_eq!(response.results[1].statement_id, 1);
    assert_eq!(response.results[1].series[0].name, "cpu_load_short");
    assert_eq!(response.results[1].series[0].values[0][1].as_f64(), Some(0.64));
    assert_eq!(response.results[1].series[0].values[1][1].as_f64(), Some(0.4));
}

#[test]
fn multiple_queries_to_nonexistent_database() {
    let response = with_core(|core| {
        let async_db = AsyncDb::new(core.handle(), HOSTNAME, "does_not_exist").unwrap();

        async_db.query(r#"SELECT "value","host" FROM "cpu_load_short" WHERE "region"='us-west'; SELECT "value" FROM "cpu_load_short" WHERE "host"='server01'"#)
    });

    assert_eq!(response.results.len(), 1);
    assert_eq!(response.results[0].statement_id, 0);
    assert_eq!(response.results[0].series.len(), 0);
    assert_eq!(response.results[0].error, Some(String::from("not executed")));
}

#[test]
fn test_infrastructure() {
    let db = fresh_db();

    db.add_data("cpu_load_short,host=server01,region=us-west value=0.64 1434055562000000000")
        .unwrap();

    let response: QueryResponse =
        db.query(r#"SELECT "value","host" FROM "cpu_load_short" WHERE "region"='us-west'"#)
        .unwrap();

    assert_eq!(response.results[0].series[0].name, "cpu_load_short");
    assert_eq!(response.results[0].series[0].values[0][1].as_f64(), Some(0.64));
    assert_eq!(response.results[0].series[0].values[0][2].as_str(), Some("server01"));
}

fn fresh_db() -> TestingDb {
    static DB_COUNTER: AtomicUsize = ATOMIC_USIZE_INIT;

    let id = DB_COUNTER.fetch_add(1, Ordering::SeqCst);
    let name = format!("influxdb_rs_{}", id);
    let db = TestingDb::new(HOSTNAME, name)
        .expect("Unable to create test database");
    db.create_db()
        .expect("Unable to create test database");

    // The InfluxDB created isn't ready immediately; this prevents
    // intermittent failures.
    std::thread::sleep(std::time::Duration::from_millis(5));
    db
}

fn with_core<F, T>(f: F) -> T::Item
    where F: FnOnce(&mut tokio_core::reactor::Core) -> T,
          T: Future,
          T::Error: std::fmt::Debug,
{
    let mut core = tokio_core::reactor::Core::new()
        .expect("Unable to create reactor core for testing");

    let future = f(&mut core);

    core.run(future).expect("Unable to run future to completion")
}

struct TestingDb {
    name: String,
    client: reqwest::Client,
    query_endpoint: reqwest::Url,
    write_endpoint: reqwest::Url,
}

impl TestingDb {
    /// `base_url` should include the protocol, host, and port (`http://localhost:8086`)
    fn new<S>(base_url: &str, name: S) -> Result<Self, Box<Error>>
        where S: Into<String>,
    {
        let name = name.into();

        let base_url = reqwest::Url::parse(base_url)?;
        let query_endpoint = base_url.join("/query")?;
        let mut write_endpoint = base_url.join("/write")?;
        write_endpoint.query_pairs_mut()
            .append_pair("db", &name);

        let client = reqwest::Client::new()?;

        Ok(TestingDb {
            name: name,
            client: client,
            query_endpoint: query_endpoint,
            write_endpoint: write_endpoint,
        })
    }

    fn create_db(&self) -> Result<(), Box<Error>> {
        let mut u = self.query_endpoint.clone();
        u.query_pairs_mut()
            .append_pair("q", &format!("CREATE DATABASE {}", self.name));
        let mut res = self.client.post(u).send()?;

        check_result(&mut res)?;
        Ok(())
    }

    fn drop_db(&self) -> Result<(), Box<Error>> {
        let mut u = self.query_endpoint.clone();
        u.query_pairs_mut()
            .append_pair("q", &format!("DROP DATABASE {}", self.name));
        let mut res = self.client.post(u).send()?;

        check_result(&mut res)?;
        Ok(())
    }

    fn add_data(&self, data: &str) -> Result<(), Box<Error>> {
        let mut res = self.client.post(self.write_endpoint.clone())
            .body(data)
            .send()?;

        check_result(&mut res)?;
        Ok(())
    }

    fn query<T>(&self, query: &str) -> Result<T, Box<Error>>
        where T: serde::Deserialize,
    {
        let mut u = self.query_endpoint.clone();
        u.query_pairs_mut()
            .append_pair("db", &self.name)
            .append_pair("q", query);
        let mut res = self.client.get(u).send()?;

        check_result(&mut res)?;
        let val = res.json()?;
        Ok(val)
    }
}

impl Drop for TestingDb {
    fn drop(&mut self) {
        // TODO: What happens if we drop twice?
        self.drop_db().unwrap_or_else(|e| panic!("Unable to drop database {}: {}", self.name, e));
    }
}

fn check_result(res: &mut reqwest::Response) -> Result<(), Box<Error>> {
    let status = *res.status();

    if status.is_success() {
        Ok(())
    } else if status.is_client_error() {
        Err(parse_influx_server_error(res, "Client error").into())
    } else if status.is_server_error() {
        Err(parse_influx_server_error(res, "Server error").into())
    } else {
        Err(parse_influx_server_error(res, "Unknown error").into())
    }
}

fn parse_influx_server_error(res: &mut reqwest::Response, kind: &str) -> String {
    match res.json::<InfluxServerError>() {
        Ok(e) => format!("{}: {}", kind, e.error),
        Err(_) => format!("{}: (unable to parse error message)", kind),
    }
}
<|endoftext|>