<commit_before>use std::path::PathBuf;
use std::path::Path;
use std::borrow::Borrow;
use std::ops::Deref;

use semver::Version;
use std::fmt::{Debug, Formatter};
use std::fmt::Error as FmtError;
use std::result::Result as RResult;

use error::StoreErrorKind as SEK;
use store::Result;
use store::Store;

/// The Index into the Store
#[derive(Debug, Clone, PartialEq, Hash, Eq, PartialOrd, Ord)]
pub struct StoreId(PathBuf);

impl StoreId {

    pub fn storified(self, store: &Store) -> StoreId {
        debug!("Create new store id out of: {:?} and {:?}", store.path(), self);
        let mut new_id = store.path().clone();
        new_id.push(self);
        debug!("Created: '{:?}'", new_id);
        StoreId::from(new_id)
    }

}

impl Into<PathBuf> for StoreId {

    fn into(self) -> PathBuf {
        self.0
    }

}

impl Deref for StoreId {
    type Target = PathBuf;

    fn deref(&self) -> &PathBuf {
        &self.0
    }

}

impl From<PathBuf> for StoreId {

    fn from(pb: PathBuf) -> StoreId {
        StoreId(pb)
    }

}

impl From<String> for StoreId {

    fn from(string: String) -> StoreId {
        StoreId(string.into())
    }

}

impl AsRef<Path> for StoreId {

    fn as_ref(&self) -> &Path {
        self.0.as_ref()
    }

}

impl Borrow<Path> for StoreId {

    fn borrow(&self) -> &Path {
        self.0.borrow()
    }

}

/// This Trait allows you to convert various representations to a single one
/// suitable for usage in the Store
pub trait IntoStoreId {
    fn into_storeid(self) -> StoreId;
}

impl IntoStoreId for PathBuf {
    fn into_storeid(self) -> StoreId {
        StoreId(self)
    }
}

impl IntoStoreId for StoreId {
    fn into_storeid(self) -> StoreId {
        self
    }
}

pub fn build_entry_path(store: &Store, path_elem: &str) -> Result<PathBuf> {
    debug!("Checking path element for version");
    if path_elem.split('~').last().map_or(false, |v| Version::parse(v).is_err()) {
        debug!("Version cannot be parsed from {:?}", path_elem);
        debug!("Path does not contain version!");
        return Err(SEK::StorePathLacksVersion.into());
    }
    debug!("Version checking succeeded");

    debug!("Building path from {:?}", path_elem);
    let mut path = store.path().clone();

    if path_elem.starts_with('/') {
        path.push(&path_elem[1..]);
    } else {
        path.push(path_elem);
    }

    Ok(path)
}

#[macro_export]
macro_rules! module_entry_path_mod {
    ($name:expr, $version:expr) => (
        #[deny(missing_docs,
                missing_copy_implementations,
                trivial_casts, trivial_numeric_casts,
                unsafe_code,
                unstable_features,
                unused_import_braces, unused_qualifications,
                unused_imports)]
        /// A helper module to create valid module entry paths
        pub mod module_path {
            use semver::Version;
            use std::convert::AsRef;
            use std::path::Path;
            use std::path::PathBuf;

            use $crate::storeid::StoreId;

            /// A Struct giving you the ability to choose store entries assigned
            /// to it.
            ///
            /// It is created through a call to `new`.
            pub struct ModuleEntryPath(PathBuf);

            impl ModuleEntryPath {
                /// Path has to be a valid UTF-8 string or this will panic!
                pub fn new<P: AsRef<Path>>(pa: P) -> ModuleEntryPath {
                    let mut path = PathBuf::new();
                    path.push(format!("{}", $name));
                    path.push(pa.as_ref().clone());
                    let version = Version::parse($version).unwrap();
                    let name = pa.as_ref().file_name().unwrap()
                        .to_str().unwrap();
                    path.set_file_name(format!("{}~{}",
                                               name,
                                               version));
                    ModuleEntryPath(path)
                }
            }

            impl $crate::storeid::IntoStoreId for ModuleEntryPath {
                fn into_storeid(self) -> $crate::storeid::StoreId {
                    StoreId::from(self.0)
                }
            }
        }
    )
}

pub struct StoreIdIterator {
    iter: Box<Iterator<Item = StoreId>>,
}

impl Debug for StoreIdIterator {

    fn fmt(&self, fmt: &mut Formatter) -> RResult<(), FmtError> {
        write!(fmt, "StoreIdIterator")
    }

}

impl StoreIdIterator {

    pub fn new(iter: Box<Iterator<Item = StoreId>>) -> StoreIdIterator {
        StoreIdIterator {
            iter: iter,
        }
    }

}

impl Iterator for StoreIdIterator {
    type Item = StoreId;

    fn next(&mut self) -> Option<StoreId> {
        self.iter.next()
    }

}

#[cfg(test)]
mod test {

    use storeid::IntoStoreId;

    module_entry_path_mod!("test", "0.2.0-alpha+leet1337");

    #[test]
    fn correct_path() {
        let p = module_path::ModuleEntryPath::new("test");

        assert_eq!(p.into_storeid().to_str().unwrap(), "test/test~0.2.0-alpha+leet1337");
    }

}
<commit_msg>Add StoreId::unstorified()<commit_after>use std::path::PathBuf;
use std::path::Path;
use std::borrow::Borrow;
use std::ops::Deref;

use semver::Version;
use std::fmt::{Debug, Formatter};
use std::fmt::Error as FmtError;
use std::result::Result as RResult;

use error::StoreErrorKind as SEK;
use error::MapErrInto;
use store::Result;
use store::Store;

/// The Index into the Store
#[derive(Debug, Clone, PartialEq, Hash, Eq, PartialOrd, Ord)]
pub struct StoreId(PathBuf);

impl StoreId {

    pub fn storified(self, store: &Store) -> StoreId {
        debug!("Create new store id out of: {:?} and {:?}", store.path(), self);
        let mut new_id = store.path().clone();
        new_id.push(self);
        debug!("Created: '{:?}'", new_id);
        StoreId::from(new_id)
    }

    pub fn unstorified(self, store: &Store) -> Result<StoreId> {
        self.strip_prefix(store.path())
            .map(PathBuf::from)
            .map(StoreId::from)
            .map_err_into(SEK::StoreIdHandlingError)
    }

}

impl Into<PathBuf> for StoreId {

    fn into(self) -> PathBuf {
        self.0
    }

}

impl Deref for StoreId {
    type Target = PathBuf;

    fn deref(&self) -> &PathBuf {
        &self.0
    }

}

impl From<PathBuf> for StoreId {

    fn from(pb: PathBuf) -> StoreId {
        StoreId(pb)
    }

}

impl From<String> for StoreId {

    fn from(string: String) -> StoreId {
        StoreId(string.into())
    }

}

impl AsRef<Path> for StoreId {

    fn as_ref(&self) -> &Path {
        self.0.as_ref()
    }

}

impl Borrow<Path> for StoreId {

    fn borrow(&self) -> &Path {
        self.0.borrow()
    }

}

/// This Trait allows you to convert various representations to a single one
/// suitable for usage in the Store
pub trait IntoStoreId {
    fn into_storeid(self) -> StoreId;
}

impl IntoStoreId for PathBuf {
    fn into_storeid(self) -> StoreId {
        StoreId(self)
    }
}

impl IntoStoreId for StoreId {
    fn into_storeid(self) -> StoreId {
        self
    }
}

pub fn build_entry_path(store: &Store, path_elem: &str) -> Result<PathBuf> {
    debug!("Checking path element for version");
    if path_elem.split('~').last().map_or(false, |v| Version::parse(v).is_err()) {
        debug!("Version cannot be parsed from {:?}", path_elem);
        debug!("Path does not contain version!");
        return Err(SEK::StorePathLacksVersion.into());
    }
    debug!("Version checking succeeded");

    debug!("Building path from {:?}", path_elem);
    let mut path = store.path().clone();

    if path_elem.starts_with('/') {
        path.push(&path_elem[1..]);
    } else {
        path.push(path_elem);
    }

    Ok(path)
}

#[macro_export]
macro_rules! module_entry_path_mod {
    ($name:expr, $version:expr) => (
        #[deny(missing_docs,
                missing_copy_implementations,
                trivial_casts, trivial_numeric_casts,
                unsafe_code,
                unstable_features,
                unused_import_braces, unused_qualifications,
                unused_imports)]
        /// A helper module to create valid module entry paths
        pub mod module_path {
            use semver::Version;
            use std::convert::AsRef;
            use std::path::Path;
            use std::path::PathBuf;

            use $crate::storeid::StoreId;

            /// A Struct giving you the ability to choose store entries assigned
            /// to it.
            ///
            /// It is created through a call to `new`.
            pub struct ModuleEntryPath(PathBuf);

            impl ModuleEntryPath {
                /// Path has to be a valid UTF-8 string or this will panic!
                pub fn new<P: AsRef<Path>>(pa: P) -> ModuleEntryPath {
                    let mut path = PathBuf::new();
                    path.push(format!("{}", $name));
                    path.push(pa.as_ref().clone());
                    let version = Version::parse($version).unwrap();
                    let name = pa.as_ref().file_name().unwrap()
                        .to_str().unwrap();
                    path.set_file_name(format!("{}~{}",
                                               name,
                                               version));
                    ModuleEntryPath(path)
                }
            }

            impl $crate::storeid::IntoStoreId for ModuleEntryPath {
                fn into_storeid(self) -> $crate::storeid::StoreId {
                    StoreId::from(self.0)
                }
            }
        }
    )
}

pub struct StoreIdIterator {
    iter: Box<Iterator<Item = StoreId>>,
}

impl Debug for StoreIdIterator {

    fn fmt(&self, fmt: &mut Formatter) -> RResult<(), FmtError> {
        write!(fmt, "StoreIdIterator")
    }

}

impl StoreIdIterator {

    pub fn new(iter: Box<Iterator<Item = StoreId>>) -> StoreIdIterator {
        StoreIdIterator {
            iter: iter,
        }
    }

}

impl Iterator for StoreIdIterator {
    type Item = StoreId;

    fn next(&mut self) -> Option<StoreId> {
        self.iter.next()
    }

}

#[cfg(test)]
mod test {

    use storeid::IntoStoreId;

    module_entry_path_mod!("test", "0.2.0-alpha+leet1337");

    #[test]
    fn correct_path() {
        let p = module_path::ModuleEntryPath::new("test");

        assert_eq!(p.into_storeid().to_str().unwrap(), "test/test~0.2.0-alpha+leet1337");
    }

}
<|endoftext|>


<commit_before>use std::path::PathBuf;
use glob::Paths;

/// The Index into the Store
pub type StoreId = PathBuf;

/// This Trait allows you to convert various representations to a single one
/// suitable for usage in the Store
trait IntoStoreId {
    fn into_storeid(self) -> StoreId;
}

impl IntoStoreId for PathBuf {
    fn into_storeid(self) -> StoreId {
        self
    }
}

#[macro_export]
macro_rules! module_entry_path_mod {
    ($name:expr, $version:expr) => (
        #[deny(missing_docs,
                missing_copy_implementations,
                trivial_casts, trivial_numeric_casts,
                unsafe_code,
                unstable_features,
                unused_import_braces, unused_qualifications,
                unused_imports)]
        pub mod module_path {
            use semver::Version;
            use std::convert::AsRef;
            use std::path::Path;
            use std::path::PathBuf;

            /// A Struct giving you the ability to choose store entries assigned
            /// to it.
            ///
            /// It is created through a call to `new`.
            pub struct ModuleEntryPath(PathBuf);

            impl ModuleEntryPath {
                /// Path has to be a valid UTF-8 string or this will panic!
                pub fn new<P: AsRef<Path>>(pa: P) -> ModuleEntryPath {
                    let mut path = PathBuf::new();
                    path.push(format!("/{}", $name));
                    path.push(pa.as_ref().clone());
                    let version = Version::parse($version).unwrap();
                    let name = pa.as_ref().file_name().unwrap()
                        .to_str().unwrap();
                    path.set_file_name(format!("{}~{}",
                                               name,
                                               version));
                    ModuleEntryPath(path)
                }
            }

            impl $crate::storeid::IntoStoreId for ModuleEntryPath {
                fn into_storeid(mut self) -> $crate::storeid::StoreId {
                    self.0
                }
            }
        }
    )
}

pub struct StoreIdIterator {
    paths: Paths,
}

impl StoreIdIterator {

    pub fn new(paths: Paths) -> StoreIdIterator {
        StoreIdIterator {
            paths: paths,
        }
    }

}

impl Iterator for StoreIdIterator {
    type Item = StoreId;

    fn next(&mut self) -> Option<StoreId> {
        self.paths.next().and_then(|o| o.ok())
    }

}

#[cfg(test)]
mod test {

    use storeid::IntoStoreId;

    module_entry_path_mod!("test", "0.2.0-alpha+leet1337");

    #[test]
    fn correct_path() {
        let p = module_path::ModuleEntryPath::new("test");

        assert_eq!(p.into_storeid().to_str().unwrap(),
        "/test/test~0.2.0-alpha+leet1337");
    }

}
<commit_msg>Fix: Make IntoStoreId public<commit_after>use std::path::PathBuf;
use glob::Paths;

/// The Index into the Store
pub type StoreId = PathBuf;

/// This Trait allows you to convert various representations to a single one
/// suitable for usage in the Store
pub trait IntoStoreId {
    fn into_storeid(self) -> StoreId;
}

impl IntoStoreId for PathBuf {
    fn into_storeid(self) -> StoreId {
        self
    }
}

#[macro_export]
macro_rules! module_entry_path_mod {
    ($name:expr, $version:expr) => (
        #[deny(missing_docs,
                missing_copy_implementations,
                trivial_casts, trivial_numeric_casts,
                unsafe_code,
                unstable_features,
                unused_import_braces, unused_qualifications,
                unused_imports)]
        pub mod module_path {
            use semver::Version;
            use std::convert::AsRef;
            use std::path::Path;
            use std::path::PathBuf;

            /// A Struct giving you the ability to choose store entries assigned
            /// to it.
            ///
            /// It is created through a call to `new`.
            pub struct ModuleEntryPath(PathBuf);

            impl ModuleEntryPath {
                /// Path has to be a valid UTF-8 string or this will panic!
                pub fn new<P: AsRef<Path>>(pa: P) -> ModuleEntryPath {
                    let mut path = PathBuf::new();
                    path.push(format!("/{}", $name));
                    path.push(pa.as_ref().clone());
                    let version = Version::parse($version).unwrap();
                    let name = pa.as_ref().file_name().unwrap()
                        .to_str().unwrap();
                    path.set_file_name(format!("{}~{}",
                                               name,
                                               version));
                    ModuleEntryPath(path)
                }
            }

            impl $crate::storeid::IntoStoreId for ModuleEntryPath {
                fn into_storeid(mut self) -> $crate::storeid::StoreId {
                    self.0
                }
            }
        }
    )
}

pub struct StoreIdIterator {
    paths: Paths,
}

impl StoreIdIterator {

    pub fn new(paths: Paths) -> StoreIdIterator {
        StoreIdIterator {
            paths: paths,
        }
    }

}

impl Iterator for StoreIdIterator {
    type Item = StoreId;

    fn next(&mut self) -> Option<StoreId> {
        self.paths.next().and_then(|o| o.ok())
    }

}

#[cfg(test)]
mod test {

    use storeid::IntoStoreId;

    module_entry_path_mod!("test", "0.2.0-alpha+leet1337");

    #[test]
    fn correct_path() {
        let p = module_path::ModuleEntryPath::new("test");

        assert_eq!(p.into_storeid().to_str().unwrap(),
        "/test/test~0.2.0-alpha+leet1337");
    }

}
<|endoftext|>


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

#![feature(test)]

extern crate test;
extern crate xi_rope;

use test::Bencher;
use xi_rope::compare;
use xi_rope::diff::{Diff, LineHashDiff};
use xi_rope::rope::RopeDelta;

static EDITOR_STR: &str = include_str!("../../core-lib/src/editor.rs");
static VIEW_STR: &str = include_str!("../../core-lib/src/view.rs");

static INTERVAL_STR: &str = include_str!("../src/interval.rs");
static BREAKS_STR: &str = include_str!("../src/breaks.rs");

static BASE_STR: &str = "This adds FixedSizeAdler32, that has a size set at construction, and keeps bytes in a cyclic buffer of that size to be removed when it fills up.

Current logic (and implementing Write) might be too much, since bytes will probably always be fed one by one anyway. Otherwise a faster way of removing a sequence might be needed (one by one is inefficient).";

static TARG_STR: &str = "This adds some function, I guess?, that has a size set at construction, and keeps bytes in a cyclic buffer of that size to be ground up and injested when it fills up.

Currently my sense of smell (and the pain of implementing Write) might be too much, since bytes will probably always be fed one by one anyway. Otherwise crying might be needed (one by one is inefficient).";

fn make_test_data() -> (Vec<u8>, Vec<u8>) {
    let one = [EDITOR_STR, VIEW_STR, INTERVAL_STR, BREAKS_STR].concat().into_bytes();
    let mut two = one.clone();
    let idx = one.len() / 2;
    two[idx] = 0x02;
    (one, two)
}

#[bench]
fn ne_idx_sw(b: &mut Bencher) {
    let (one, two) = make_test_data();

    b.iter(|| {
        compare::ne_idx_fallback(&one, &one);
        compare::ne_idx_fallback(&one, &two);
    })
}

#[bench]
fn ne_idx_sse(b: &mut Bencher) {
    let (one, two) = make_test_data();

    let mut x = 0;
    b.iter(|| {
        x += unsafe { compare::ne_idx_sse(&one, &one).unwrap_or_default() };
        x += unsafe { compare::ne_idx_sse(&one, &two).unwrap_or_default() };
    })
}

#[bench]
fn ne_idx_avx(b: &mut Bencher) {
    let (one, two) = make_test_data();

    let mut dont_opt_me = 0;
    b.iter(|| {
        dont_opt_me += unsafe { compare::ne_idx_avx(&one, &two).unwrap_or_default() };
        dont_opt_me += unsafe { compare::ne_idx_avx(&one, &one).unwrap_or_default() };
    })
}

#[bench]
fn ne_idx_detect(b: &mut Bencher) {
    let (one, two) = make_test_data();

    let mut dont_opt_me = 0;
    b.iter(|| {
        dont_opt_me += compare::ne_idx(&one, &two).unwrap_or_default();
        dont_opt_me += compare::ne_idx(&one, &one).unwrap_or_default();
    })
}

#[bench]
fn ne_idx_rev_sw(b: &mut Bencher) {
    let (one, two) = make_test_data();

    let mut x = 0;
    b.iter(|| {
        x += compare::ne_idx_rev_fallback(&one, &one).unwrap_or_default();
        x += compare::ne_idx_rev_fallback(&one, &two).unwrap_or_default();
    })
}

#[bench]
fn ne_idx_rev_sse(b: &mut Bencher) {
    let (one, two) = make_test_data();

    b.iter(|| {
        compare::ne_idx_rev_sse(&one, &one);
        compare::ne_idx_rev_sse(&one, &two);
    })
}

#[bench]
fn hash_diff(b: &mut Bencher) {
    let one = BASE_STR.into();
    let two = TARG_STR.into();
    let mut delta: Option<RopeDelta> = None;
    b.iter(|| {
        delta = Some(LineHashDiff::compute_delta(&one, &two));
    });

    let _result = delta.unwrap().apply(&one);
    assert_eq!(String::from(_result), String::from(&two));
}

#[bench]
fn hash_diff_med(b: &mut Bencher) {
    let one = INTERVAL_STR.into();
    let two = BREAKS_STR.into();
    let mut delta: Option<RopeDelta> = None;
    b.iter(|| {
        delta = Some(LineHashDiff::compute_delta(&one, &two));
    });

    let _result = delta.unwrap().apply(&one);
    assert_eq!(String::from(_result), String::from(&two));
}

#[bench]
fn hash_diff_big(b: &mut Bencher) {
    let one = EDITOR_STR.into();
    let two = VIEW_STR.into();
    let mut delta: Option<RopeDelta> = None;
    b.iter(|| {
        delta = Some(LineHashDiff::compute_delta(&one, &two));
    });

    let _result = delta.unwrap().apply(&one);
    assert_eq!(String::from(_result), String::from(&two));
}
<commit_msg>Add a RopeScanner benchmark<commit_after>// Copyright 2018 The xi-editor Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#![feature(test)]

extern crate test;
extern crate xi_rope;

use test::Bencher;
use xi_rope::compare;
use xi_rope::diff::{Diff, LineHashDiff};
use xi_rope::rope::{Rope, RopeDelta};

static EDITOR_STR: &str = include_str!("../../core-lib/src/editor.rs");
static VIEW_STR: &str = include_str!("../../core-lib/src/view.rs");

static INTERVAL_STR: &str = include_str!("../src/interval.rs");
static BREAKS_STR: &str = include_str!("../src/breaks.rs");

static BASE_STR: &str = "This adds FixedSizeAdler32, that has a size set at construction, and keeps bytes in a cyclic buffer of that size to be removed when it fills up.

Current logic (and implementing Write) might be too much, since bytes will probably always be fed one by one anyway. Otherwise a faster way of removing a sequence might be needed (one by one is inefficient).";

static TARG_STR: &str = "This adds some function, I guess?, that has a size set at construction, and keeps bytes in a cyclic buffer of that size to be ground up and injested when it fills up.

Currently my sense of smell (and the pain of implementing Write) might be too much, since bytes will probably always be fed one by one anyway. Otherwise crying might be needed (one by one is inefficient).";

fn make_test_data() -> (Vec<u8>, Vec<u8>) {
    let one = [EDITOR_STR, VIEW_STR, INTERVAL_STR, BREAKS_STR].concat().into_bytes();
    let mut two = one.clone();
    let idx = one.len() / 2;
    two[idx] = 0x02;
    (one, two)
}

#[bench]
fn ne_idx_sw(b: &mut Bencher) {
    let (one, two) = make_test_data();

    b.iter(|| {
        compare::ne_idx_fallback(&one, &one);
        compare::ne_idx_fallback(&one, &two);
    })
}

#[bench]
fn ne_idx_sse(b: &mut Bencher) {
    let (one, two) = make_test_data();

    let mut x = 0;
    b.iter(|| {
        x += unsafe { compare::ne_idx_sse(&one, &one).unwrap_or_default() };
        x += unsafe { compare::ne_idx_sse(&one, &two).unwrap_or_default() };
    })
}

#[bench]
fn ne_idx_avx(b: &mut Bencher) {
    let (one, two) = make_test_data();

    let mut dont_opt_me = 0;
    b.iter(|| {
        dont_opt_me += unsafe { compare::ne_idx_avx(&one, &two).unwrap_or_default() };
        dont_opt_me += unsafe { compare::ne_idx_avx(&one, &one).unwrap_or_default() };
    })
}

#[bench]
fn ne_idx_detect(b: &mut Bencher) {
    let (one, two) = make_test_data();

    let mut dont_opt_me = 0;
    b.iter(|| {
        dont_opt_me += compare::ne_idx(&one, &two).unwrap_or_default();
        dont_opt_me += compare::ne_idx(&one, &one).unwrap_or_default();
    })
}

#[bench]
fn ne_idx_rev_sw(b: &mut Bencher) {
    let (one, two) = make_test_data();

    let mut x = 0;
    b.iter(|| {
        x += compare::ne_idx_rev_fallback(&one, &one).unwrap_or_default();
        x += compare::ne_idx_rev_fallback(&one, &two).unwrap_or_default();
    })
}

#[bench]
fn ne_idx_rev_sse(b: &mut Bencher) {
    let (one, two) = make_test_data();

    b.iter(|| {
        compare::ne_idx_rev_sse(&one, &one);
        compare::ne_idx_rev_sse(&one, &two);
    })
}

#[bench]
fn scanner(b: &mut Bencher) {
    let (one, two) = make_test_data();
    let one = Rope::from(String::from_utf8(one).unwrap());
    let two = Rope::from(String::from_utf8(two).unwrap());

    let mut scanner = compare::RopeScanner::new(&one, &two);
    b.iter(|| {
        scanner.find_ne_char_right(0, 0, None);
        scanner.find_ne_char_left(one.len(), two.len(), None);
    })
}

#[bench]
fn hash_diff(b: &mut Bencher) {
    let one = BASE_STR.into();
    let two = TARG_STR.into();
    let mut delta: Option<RopeDelta> = None;
    b.iter(|| {
        delta = Some(LineHashDiff::compute_delta(&one, &two));
    });

    let _result = delta.unwrap().apply(&one);
    assert_eq!(String::from(_result), String::from(&two));
}

#[bench]
fn hash_diff_med(b: &mut Bencher) {
    let one = INTERVAL_STR.into();
    let two = BREAKS_STR.into();
    let mut delta: Option<RopeDelta> = None;
    b.iter(|| {
        delta = Some(LineHashDiff::compute_delta(&one, &two));
    });

    let _result = delta.unwrap().apply(&one);
    assert_eq!(String::from(_result), String::from(&two));
}

#[bench]
fn hash_diff_big(b: &mut Bencher) {
    let one = EDITOR_STR.into();
    let two = VIEW_STR.into();
    let mut delta: Option<RopeDelta> = None;
    b.iter(|| {
        delta = Some(LineHashDiff::compute_delta(&one, &two));
    });

    let _result = delta.unwrap().apply(&one);
    assert_eq!(String::from(_result), String::from(&two));
}
<|endoftext|>


<commit_before>use std;
use std::fmt::{Debug, Display, Formatter};
use std::ops::*;

const P: i64 = 1_000_000_007;

/// Calculates `x^n`. O(log n) time.
/// By Fermat's little theorem, `x^(-1) = pow(x, P - 2)`.
pub fn pow(x: i64, n: i64) -> i64 {
    let (mut x, mut y, mut n) = (x % P, 1_i64, n);
    while n > 0 {
        if n % 2 != 0 {
            y = (y * x) % P;
            n -= 1;
        }

        x = (x * x) % P;
        n /= 2;
    }
    y
}

/// Calculates `1/a` for each `a` in `1..n`.
/// Use `P = floor(P / k) * k + P % k` for proof.
pub fn inv_dp(n: usize) -> Vec<i64> {
    let mut dp = vec![0; n];
    if n >= 2 {
        dp[1] = 1;
        for i in 2..n {
            let mut z = P - dp[(P % i as i64) as usize];
            z %= P;
            z *= P / i as i64;
            z %= P;
            dp[i] = z;
        }
    }
    dp
}

/// Represents an element of finite field.
#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Default)]
struct Finite(i64);

impl Finite {
    fn pow(self, e: i64) -> Self {
        pow(self.0, e).into()
    }

    fn normalize(&mut self) {
        self.0 %= P;
        self.0 += P;
        self.0 %= P;
    }
}

impl Debug for Finite {
    fn fmt(&self, formatter: &mut Formatter) -> std::fmt::Result {
        formatter.write_fmt(format_args!("{:?}", self.0))
    }
}

impl Display for Finite {
    fn fmt(&self, formatter: &mut Formatter) -> std::fmt::Result {
        formatter.write_fmt(format_args!("{}", self.0))
    }
}

impl From<i64> for Finite {
    fn from(value: i64) -> Self {
        let mut it = Finite(value);
        it.normalize();
        it
    }
}

// Generate binary operation traits.
macro_rules! impl_binary_op_for_finite {
    ($op_trait:ident, $op:ident, $assign_trait:ident, $assign:ident $(, $f:ident)*) => {
        impl $op_trait<i64> for Finite {
            type Output = Self;

            fn $op(self, other: i64) -> Self {
                let mut it = self.clone();
                it.$assign(other);
                it
            }
        }

        impl $op_trait<Finite> for Finite {
            type Output = Self;

            fn $op(self, other: Self) -> Self {
                self.$op(other.0)
            }
        }

        impl $assign_trait<Finite> for Finite {
            fn $assign(&mut self, other: Self) {
                self.$assign(other.0);
            }
        }

        $(impl $assign_trait<i64> for Finite {
            fn $assign(&mut self, other: i64) {
                (self.0).$f(Finite::from(other).0);
                self.normalize();
            }
        })*
    };
}

impl_binary_op_for_finite! {Add, add, AddAssign, add_assign, add_assign}
impl_binary_op_for_finite! {Sub, sub, SubAssign, sub_assign, sub_assign}
impl_binary_op_for_finite! {Mul, mul, MulAssign, mul_assign, mul_assign}
impl_binary_op_for_finite! {Div, div, DivAssign, div_assign}

impl DivAssign<i64> for Finite {
    fn div_assign(&mut self, other: i64) {
        *self *= Self::from(other).pow(P - 2);
    }
}

#[cfg(test)]
mod tests {
    use super::{inv_dp, pow, Finite, P};
    use std;

    #[test]
    fn test_pow_edges() {
        assert_eq!(pow(0, 0), 1);
        assert_eq!(pow(2, 0), 1);
        assert_eq!(pow(3, 1), 3);
        assert_eq!(pow(5, 6), (5 * 5 * 5) * (5 * 5 * 5));
        assert_eq!(pow(std::i64::MAX % P, std::i64::MAX), 856225998);
    }

    #[test]
    fn test_pow_small() {
        for x in 0..100_i64 {
            for n in 0..100_i64 {
                let actual = pow(x, n);
                let expected = (0..n).fold(1_i64, |acc, _| (acc * x) % P);
                assert_eq!(actual, expected, "{}^{}", x, n);
            }
        }
    }

    #[test]
    fn test_inv_dp() {
        let n = 10000;
        let dp = inv_dp(n);
        for i in 1..n {
            let mut z = dp[i] * i as i64;
            z %= P;
            z += P;
            z %= P;
            assert_eq!(z, 1);
        }
    }

    #[test]
    fn test_finite() {
        let x = Finite::from(P + 2);

        // `from` should normalize the value.
        assert_eq!(x.0, 2);

        // Operations.
        assert_eq!(x + 7, (2 + 7).into());
        assert_eq!(x - 7, (P + (2 - 7)).into());
        assert_eq!(x * 3, (2 * 3).into());
        assert_eq!((x / 11) * 11, 2.into());

        assert_eq!(x + Finite::from(7), (2 + 7).into());
        assert_eq!(x - Finite::from(7), (P + (2 - 7)).into());
        assert_eq!(x * Finite::from(3), (2 * 3).into());
        assert_eq!((x / Finite::from(11)) * 11, 2.into());

        let mut x = x;
        x += 7;
        assert_eq!(x, 9.into());
        x -= 5;
        assert_eq!(x, 4.into());
        x *= 6;
        assert_eq!(x, 24.into());
        x /= 3;
        assert_eq!(x, 8.into());
    }
}
<commit_msg>refactor: Test `Finite::fmt`<commit_after>use std;
use std::fmt::{Debug, Display, Formatter};
use std::ops::*;

const P: i64 = 1_000_000_007;

/// Calculates `x^n`. O(log n) time.
/// By Fermat's little theorem, `x^(-1) = pow(x, P - 2)`.
pub fn pow(x: i64, n: i64) -> i64 {
    let (mut x, mut y, mut n) = (x % P, 1_i64, n);
    while n > 0 {
        if n % 2 != 0 {
            y = (y * x) % P;
            n -= 1;
        }

        x = (x * x) % P;
        n /= 2;
    }
    y
}

/// Calculates `1/a` for each `a` in `1..n`.
/// Use `P = floor(P / k) * k + P % k` for proof.
pub fn inv_dp(n: usize) -> Vec<i64> {
    let mut dp = vec![0; n];
    if n >= 2 {
        dp[1] = 1;
        for i in 2..n {
            let mut z = P - dp[(P % i as i64) as usize];
            z %= P;
            z *= P / i as i64;
            z %= P;
            dp[i] = z;
        }
    }
    dp
}

/// Represents an element of finite field.
#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Default)]
struct Finite(i64);

impl Finite {
    fn pow(self, e: i64) -> Self {
        pow(self.0, e).into()
    }

    fn normalize(&mut self) {
        self.0 %= P;
        self.0 += P;
        self.0 %= P;
    }
}

impl Debug for Finite {
    fn fmt(&self, formatter: &mut Formatter) -> std::fmt::Result {
        formatter.write_fmt(format_args!("{:?}", self.0))
    }
}

impl Display for Finite {
    fn fmt(&self, formatter: &mut Formatter) -> std::fmt::Result {
        formatter.write_fmt(format_args!("{}", self.0))
    }
}

impl From<i64> for Finite {
    fn from(value: i64) -> Self {
        let mut it = Finite(value);
        it.normalize();
        it
    }
}

// Generate binary operation traits.
macro_rules! impl_binary_op_for_finite {
    ($op_trait:ident, $op:ident, $assign_trait:ident, $assign:ident $(, $f:ident)*) => {
        impl $op_trait<i64> for Finite {
            type Output = Self;

            fn $op(self, other: i64) -> Self {
                let mut it = self.clone();
                it.$assign(other);
                it
            }
        }

        impl $op_trait<Finite> for Finite {
            type Output = Self;

            fn $op(self, other: Self) -> Self {
                self.$op(other.0)
            }
        }

        impl $assign_trait<Finite> for Finite {
            fn $assign(&mut self, other: Self) {
                self.$assign(other.0);
            }
        }

        $(impl $assign_trait<i64> for Finite {
            fn $assign(&mut self, other: i64) {
                (self.0).$f(Finite::from(other).0);
                self.normalize();
            }
        })*
    };
}

impl_binary_op_for_finite! {Add, add, AddAssign, add_assign, add_assign}
impl_binary_op_for_finite! {Sub, sub, SubAssign, sub_assign, sub_assign}
impl_binary_op_for_finite! {Mul, mul, MulAssign, mul_assign, mul_assign}
impl_binary_op_for_finite! {Div, div, DivAssign, div_assign}

impl DivAssign<i64> for Finite {
    fn div_assign(&mut self, other: i64) {
        *self *= Self::from(other).pow(P - 2);
    }
}

#[cfg(test)]
mod tests {
    use super::{inv_dp, pow, Finite, P};
    use std;

    #[test]
    fn test_pow_edges() {
        assert_eq!(pow(0, 0), 1);
        assert_eq!(pow(2, 0), 1);
        assert_eq!(pow(3, 1), 3);
        assert_eq!(pow(5, 6), (5 * 5 * 5) * (5 * 5 * 5));
        assert_eq!(pow(std::i64::MAX % P, std::i64::MAX), 856225998);
    }

    #[test]
    fn test_pow_small() {
        for x in 0..100_i64 {
            for n in 0..100_i64 {
                let actual = pow(x, n);
                let expected = (0..n).fold(1_i64, |acc, _| (acc * x) % P);
                assert_eq!(actual, expected, "{}^{}", x, n);
            }
        }
    }

    #[test]
    fn test_inv_dp() {
        let n = 10000;
        let dp = inv_dp(n);
        for i in 1..n {
            let mut z = dp[i] * i as i64;
            z %= P;
            z += P;
            z %= P;
            assert_eq!(z, 1);
        }
    }

    #[test]
    fn test_finite() {
        let x = Finite::from(P + 2);

        // `from` should normalize the value.
        assert_eq!(x.0, 2);

        // Operations.
        assert_eq!(x + 7, (2 + 7).into());
        assert_eq!(x - 7, (P + (2 - 7)).into());
        assert_eq!(x * 3, (2 * 3).into());
        assert_eq!((x / 11) * 11, 2.into());

        assert_eq!(x + Finite::from(7), (2 + 7).into());
        assert_eq!(x - Finite::from(7), (P + (2 - 7)).into());
        assert_eq!(x * Finite::from(3), (2 * 3).into());
        assert_eq!((x / Finite::from(11)) * 11, 2.into());

        let mut x = x;
        x += 7;
        assert_eq!(x, 9.into());
        x -= 5;
        assert_eq!(x, 4.into());
        x *= 6;
        assert_eq!(x, 24.into());
        x /= 3;
        assert_eq!(x, 8.into());
    }

    #[test]
    fn test_finite_fmt() {
        assert_eq!(format!("{:?}", Finite::from(2)), "2");
        assert_eq!(format!("{}", Finite::from(2)), "2");
    }
}
<|endoftext|>


<commit_before>#![feature(test)]

#[cfg(feature = "comparitive")]
extern crate decimal;
extern crate rust_decimal;
extern crate test;

use rust_decimal::Decimal;
use std::str::FromStr;

macro_rules! bench_decimal_op {
    ($name:ident, $op:tt, $y:expr) => {
        #[bench]
        fn $name(b: &mut ::test::Bencher) {
            let x = Decimal::from_str("2.01").unwrap();
            let y = Decimal::from_str($y).unwrap();
            b.iter(|| {
                let result = x $op y;
                ::test::black_box(result);
            });
        }
    }
}

macro_rules! bench_fold_op {
    ($name:ident, $op:tt, $init:expr) => {
        #[bench]
        fn $name(b: &mut ::test::Bencher) {
            fn fold(values: &[Decimal]) -> Decimal {
                let mut acc: Decimal = $init.into();
                for value in values {
                    acc = acc $op value;
                }
                acc
            }

            let values: Vec<Decimal> = test::black_box((0..10_000).map(|i| i.into()).collect());
            b.iter(|| {
                let result = fold(&values);
                ::test::black_box(result);
            });
        }
    }
}

/* Add */
bench_decimal_op!(add_one, +, "1");
bench_decimal_op!(add_two, +, "2");
bench_decimal_op!(add_one_hundred, +, "100");
bench_decimal_op!(add_point_zero_one, +, "0.01");
bench_decimal_op!(add_negative_point_five, +, "-0.5");
bench_decimal_op!(add_pi, +, "3.1415926535897932384626433832");
bench_decimal_op!(add_negative_pi, +, "-3.1415926535897932384626433832");

bench_fold_op!(sum_10k, +, 0);

/* Sub */
bench_decimal_op!(sub_one, -, "1");
bench_decimal_op!(sub_two, -, "2");
bench_decimal_op!(sub_one_hundred, -, "100");
bench_decimal_op!(sub_point_zero_one, -, "0.01");
bench_decimal_op!(sub_negative_point_five, -, "-0.5");
bench_decimal_op!(sub_pi, -, "3.1415926535897932384626433832");
bench_decimal_op!(sub_negative_pi, -, "-3.1415926535897932384626433832");

bench_fold_op!(dec_10k, -, 5_000_000);

/* Mul */
bench_decimal_op!(mul_one, *, "1");
bench_decimal_op!(mul_two, *, "2");
bench_decimal_op!(mul_one_hundred, *, "100");
bench_decimal_op!(mul_point_zero_one, *, "0.01");
bench_decimal_op!(mul_negative_point_five, *, "-0.5");
bench_decimal_op!(mul_pi, *, "3.1415926535897932384626433832");
bench_decimal_op!(mul_negative_pi, *, "-3.1415926535897932384626433832");

/* Div */
bench_decimal_op!(div_one, /, "1");
bench_decimal_op!(div_two, /, "2");
bench_decimal_op!(div_one_hundred, /, "100");
bench_decimal_op!(div_point_zero_one, /, "0.01");
bench_decimal_op!(div_negative_point_five, /, "-0.5");
bench_decimal_op!(div_pi, /, "3.1415926535897932384626433832");
bench_decimal_op!(div_negative_pi, /, "-3.1415926535897932384626433832");

#[cfg(feature = "comparitive")]
mod comparitive {
    use decimal::d128;
    use rust_decimal::Decimal;
    use std::str::FromStr;

    macro_rules! bench_dec_op {
        ($name:ident, $op:tt) => {
            #[bench]
            fn $name(b: &mut ::test::Bencher) {
                let x = Decimal::from_str("2.01").unwrap();
                let y = Decimal::from_str("3.1415926535897932384626433832").unwrap();
                b.iter(|| {
                    let result = x $op y;
                    ::test::black_box(result);
                });
            }
        }
    }

    macro_rules! bench_d128_op {
        ($name:ident, $op:tt) => {
            #[bench]
            fn $name(b: &mut ::test::Bencher) {
                let x = d128::from_str("2.01").unwrap();
                let y = d128::from_str("3.1415926535897932384626433832").unwrap();
                b.iter(|| {
                    let result = x $op y;
                    ::test::black_box(result);
                });
            }
        }
    }

    bench_dec_op!(add_dec, +);
    bench_d128_op!(add_d128, +);
    bench_dec_op!(sub_dec, -);
    bench_d128_op!(sub_d128, -);
    bench_dec_op!(mul_dec, *);
    bench_d128_op!(mul_d128, *);
    bench_dec_op!(div_dec, /);
    bench_d128_op!(div_d128, /);
}
#[cfg(not(feature = "comparitive"))]
mod comparitive {

}
<commit_msg>added frac_10k bench<commit_after>#![feature(test)]

#[cfg(feature = "comparitive")]
extern crate decimal;
extern crate rust_decimal;
extern crate test;

use rust_decimal::Decimal;
use std::str::FromStr;

macro_rules! bench_decimal_op {
    ($name:ident, $op:tt, $y:expr) => {
        #[bench]
        fn $name(b: &mut ::test::Bencher) {
            let x = Decimal::from_str("2.01").unwrap();
            let y = Decimal::from_str($y).unwrap();
            b.iter(|| {
                let result = x $op y;
                ::test::black_box(result);
            });
        }
    }
}

macro_rules! bench_fold_op {
    ($name:ident, $op:tt, $init:expr, $count:expr) => {
        #[bench]
        fn $name(b: &mut ::test::Bencher) {
            fn fold(values: &[Decimal]) -> Decimal {
                let mut acc: Decimal = $init.into();
                for value in values {
                    acc = acc $op value;
                }
                acc
            }

            let values: Vec<Decimal> = test::black_box((1..$count).map(|i| i.into()).collect());
            b.iter(|| {
                let result = fold(&values);
                ::test::black_box(result);
            });
        }
    }
}

/* Add */
bench_decimal_op!(add_one, +, "1");
bench_decimal_op!(add_two, +, "2");
bench_decimal_op!(add_one_hundred, +, "100");
bench_decimal_op!(add_point_zero_one, +, "0.01");
bench_decimal_op!(add_negative_point_five, +, "-0.5");
bench_decimal_op!(add_pi, +, "3.1415926535897932384626433832");
bench_decimal_op!(add_negative_pi, +, "-3.1415926535897932384626433832");

bench_fold_op!(sum_10k, +, 0, 10_000);

/* Sub */
bench_decimal_op!(sub_one, -, "1");
bench_decimal_op!(sub_two, -, "2");
bench_decimal_op!(sub_one_hundred, -, "100");
bench_decimal_op!(sub_point_zero_one, -, "0.01");
bench_decimal_op!(sub_negative_point_five, -, "-0.5");
bench_decimal_op!(sub_pi, -, "3.1415926535897932384626433832");
bench_decimal_op!(sub_negative_pi, -, "-3.1415926535897932384626433832");

bench_fold_op!(dec_10k, -, 5_000_000, 10_000);

/* Mul */
bench_decimal_op!(mul_one, *, "1");
bench_decimal_op!(mul_two, *, "2");
bench_decimal_op!(mul_one_hundred, *, "100");
bench_decimal_op!(mul_point_zero_one, *, "0.01");
bench_decimal_op!(mul_negative_point_five, *, "-0.5");
bench_decimal_op!(mul_pi, *, "3.1415926535897932384626433832");
bench_decimal_op!(mul_negative_pi, *, "-3.1415926535897932384626433832");

/* Div */
bench_decimal_op!(div_one, /, "1");
bench_decimal_op!(div_two, /, "2");
bench_decimal_op!(div_one_hundred, /, "100");
bench_decimal_op!(div_point_zero_one, /, "0.01");
bench_decimal_op!(div_negative_point_five, /, "-0.5");
bench_decimal_op!(div_pi, /, "3.1415926535897932384626433832");
bench_decimal_op!(div_negative_pi, /, "-3.1415926535897932384626433832");

bench_fold_op!(frac_10k, /, Decimal::max_value(), 10_000);

#[cfg(feature = "comparitive")]
mod comparitive {
    use decimal::d128;
    use rust_decimal::Decimal;
    use std::str::FromStr;

    macro_rules! bench_dec_op {
        ($name:ident, $op:tt) => {
            #[bench]
            fn $name(b: &mut ::test::Bencher) {
                let x = Decimal::from_str("2.01").unwrap();
                let y = Decimal::from_str("3.1415926535897932384626433832").unwrap();
                b.iter(|| {
                    let result = x $op y;
                    ::test::black_box(result);
                });
            }
        }
    }

    macro_rules! bench_d128_op {
        ($name:ident, $op:tt) => {
            #[bench]
            fn $name(b: &mut ::test::Bencher) {
                let x = d128::from_str("2.01").unwrap();
                let y = d128::from_str("3.1415926535897932384626433832").unwrap();
                b.iter(|| {
                    let result = x $op y;
                    ::test::black_box(result);
                });
            }
        }
    }

    bench_dec_op!(add_dec, +);
    bench_d128_op!(add_d128, +);
    bench_dec_op!(sub_dec, -);
    bench_d128_op!(sub_d128, -);
    bench_dec_op!(mul_dec, *);
    bench_d128_op!(mul_d128, *);
    bench_dec_op!(div_dec, /);
    bench_d128_op!(div_d128, /);
}
#[cfg(not(feature = "comparitive"))]
mod comparitive {

}
<|endoftext|>


<commit_before>extern crate bincode;
extern crate proto;
extern crate mio;
extern crate rusqlite;

mod db;

use std::io::Read;
use std::collections::HashMap;

use mio::net::{TcpListener, TcpStream};
use mio::{Poll, Token, Ready, PollOpt, Events};

const LISTENER: Token = Token(0);

struct ClientSock {
    stream: TcpStream,
    data_buf: Vec<u8>,
}

impl ClientSock {
    fn new(stream: TcpStream) -> Self {
        Self {
            stream,
            data_buf: Vec::with_capacity(1024),
        }
    }

    fn read_socket(&mut self) {
        let _ = self.stream.read_to_end(&mut self.data_buf);
    }

    fn try_deserialize(&mut self) -> Option<proto::Command> {
        let (cmd, bytes_read) = {
            let mut bytes = self.data_buf.as_slice();
            let cmd = bincode::deserialize_from(&mut bytes);
            let bytes_read = bytes.as_ptr() as usize - self.data_buf.as_slice().as_ptr() as usize;
            (cmd, bytes_read)
        };
        println!("try_deserialize: {} bytes", bytes_read);

        // Catch disconnects
        let cmd = if cmd.is_err() && bytes_read == 0 {
            Ok(proto::Command::Disconnect)
        } else {
            cmd
        };

        match cmd {
            Ok(cmd) => {
                self.data_buf.drain(0..bytes_read);
                Some(cmd)
            }
            Err(e) => {
                match *e {
                    bincode::ErrorKind::Io(..) => {} // Not enough data received yet
                    _ => { self.data_buf.drain(0..bytes_read); },
                };
                None
            }
        }
    }
}

fn main() {
    let mut clients: HashMap<usize, ClientSock> = HashMap::new();
    let mut user_list: HashMap<usize, String> = HashMap::new();

    let addr = "0.0.0.0:4450".parse().unwrap();
    let listener = TcpListener::bind(&addr).expect("TCP listen");
    let poll = Poll::new().expect("Poll");
    poll.register(&listener, LISTENER, Ready::readable(), PollOpt::edge()).expect("Listener register");

    let mut cur_client_id = 1usize;
    let mut events = Events::with_capacity(1024);

    let database = db::Database::new().expect("Database");
    for u in database.all_users().expect("Query").into_iter() {
        println!("User: {}", u.user_name);
    }

    loop {
        poll.poll(&mut events, None).unwrap();
        for e in events.iter() {
            match e.token() {
                LISTENER => {
                    let (client_stream, client_addr) = listener.accept().expect("Client accept");
                    println!("New client: {:?}", client_addr);
                    let client = ClientSock::new(client_stream);
                    clients.insert(cur_client_id, client);
                    poll.register(&clients[&cur_client_id].stream, Token(cur_client_id), Ready::readable(), PollOpt::edge()).expect("Client register");
                    cur_client_id += 1;
                },
                Token(client_id) => {
                    let cmd = {
                        let client = &mut clients.get_mut(&client_id).unwrap();
                        client.read_socket();
                        client.try_deserialize()
                    };
                    if let Some(cmd) = cmd {
                        if let Some(resp) = build_response(&database, cmd, client_id, &mut user_list, &mut clients) {
                            let client = &mut clients.get_mut(&client_id).unwrap();
                            if bincode::serialize_into(&client.stream, &resp).is_err() {
                                println!("Failed to write response!");
                            }
                        }
                    }
                }
            }
        }
    }
}

fn fetch_users(db: &db::Database, user_list: &HashMap<usize, String>) -> Vec<proto::User> {
    if let Ok(users) = db.users_from_user_name_iter(user_list.values().map(|s| s.as_ref())) {
        users
    } else {
        Vec::new()
    }
}

fn build_response(db: &db::Database, cmd: proto::Command, client_id: usize, user_list: &mut HashMap<usize, String>, clients: &mut HashMap<usize, ClientSock>) -> Option<proto::Response> {
    use proto::Command::*;
    match cmd {
        ListUsers => Some(proto::Response::UserList(fetch_users(db, user_list))),
        Login { email, password, } => {
            let password_hex = {
                use std::fmt::Write;
                let mut buf = String::with_capacity(password.len() * 2);
                for b in password.iter() {
                    let _ = write!(&mut buf, "{:X}", b);
                }
                buf
            };
            println!("Login with email '{}' and password '{}'", email, password_hex);
            if let Ok(Some(user)) = db.user_with_credentials(&email, &password) {
                // We insert the user name instead of the email address, because I want
                // to avoid moving around and possibly leaking user sensitive data.
                user_list.insert(client_id, user.user_name);

                // Notify other clients about the newly joined guy
                let msg = proto::Response::UserList(fetch_users(db, user_list));
                for c in clients.values() {
                    let _ = bincode::serialize_into(&c.stream, &msg);
                }

                Some(proto::Response::LoginOk)
            } else {
                Some(proto::Response::LoginInvalid)
            }
        },
        Disconnect => {
            clients.remove(&client_id);
            user_list.remove(&client_id);
            let msg = proto::Response::UserList(fetch_users(db, user_list));
            for c in clients.values() {
                let _ = bincode::serialize_into(&c.stream, &msg);
            }
            None
        }
    }
}
<commit_msg>server: Quit command for clean shutdown<commit_after>extern crate bincode;
extern crate proto;
extern crate mio;
extern crate rusqlite;

mod db;

use std::io;
use std::io::Read;
use std::time::Duration;
use std::thread;
use std::sync::mpsc;
use std::collections::HashMap;

use mio::net::{TcpListener, TcpStream};
use mio::{Poll, Token, Ready, PollOpt, Events};

const LISTENER: Token = Token(0);

struct ClientSock {
    stream: TcpStream,
    data_buf: Vec<u8>,
}

impl ClientSock {
    fn new(stream: TcpStream) -> Self {
        Self {
            stream,
            data_buf: Vec::with_capacity(1024),
        }
    }

    fn read_socket(&mut self) {
        let _ = self.stream.read_to_end(&mut self.data_buf);
    }

    fn try_deserialize(&mut self) -> Option<proto::Command> {
        let (cmd, bytes_read) = {
            let mut bytes = self.data_buf.as_slice();
            let cmd = bincode::deserialize_from(&mut bytes);
            let bytes_read = bytes.as_ptr() as usize - self.data_buf.as_slice().as_ptr() as usize;
            (cmd, bytes_read)
        };
        println!("try_deserialize: {} bytes", bytes_read);

        // Catch disconnects
        let cmd = if cmd.is_err() && bytes_read == 0 {
            Ok(proto::Command::Disconnect)
        } else {
            cmd
        };

        match cmd {
            Ok(cmd) => {
                self.data_buf.drain(0..bytes_read);
                Some(cmd)
            }
            Err(e) => {
                match *e {
                    bincode::ErrorKind::Io(..) => {} // Not enough data received yet
                    _ => { self.data_buf.drain(0..bytes_read); },
                };
                None
            }
        }
    }
}

fn ignore_timeout(err: io::Error) -> Option<io::Error> {
    if err.kind() == io::ErrorKind::WouldBlock {
        None
    } else {
        Some(err)
    }
}

fn main() {
    let mut clients: HashMap<usize, ClientSock> = HashMap::new();
    let mut user_list: HashMap<usize, String> = HashMap::new();

    let addr = "0.0.0.0:4450".parse().unwrap();
    let listener = TcpListener::bind(&addr).expect("TCP listen");
    let poll = Poll::new().expect("Poll");
    poll.register(&listener, LISTENER, Ready::readable(), PollOpt::edge()).expect("Listener register");

    let mut cur_client_id = 1usize;
    let mut events = Events::with_capacity(1024);

    let database = db::Database::new().expect("Database");
    for u in database.all_users().expect("Query").into_iter() {
        println!("User: {}", u.user_name);
    }

    println!("Enter \"quit\" to quit the server.");

    let (quit_tx, quit_rx) = mpsc::channel();
    let quit_thread = thread::spawn(move || {
        let mut dummy = String::new();
        let _ = io::stdin().read_line(&mut dummy);
        let _ = quit_tx.send(());
    });

    loop {
        if let Ok(()) = quit_rx.try_recv() {
            break;
        }

        if let Err(e) = poll.poll(&mut events, Some(Duration::from_secs(1))) {
            if let Some(e) = ignore_timeout(e) {
                println!("poll ERR: {}", e);
            }
        }

        for e in events.iter() {
            match e.token() {
                LISTENER => {
                    let (client_stream, client_addr) = listener.accept().expect("Client accept");
                    println!("New client: {:?}", client_addr);
                    let client = ClientSock::new(client_stream);
                    clients.insert(cur_client_id, client);
                    poll.register(&clients[&cur_client_id].stream, Token(cur_client_id), Ready::readable(), PollOpt::edge()).expect("Client register");
                    cur_client_id += 1;
                },
                Token(client_id) => {
                    let cmd = {
                        let client = &mut clients.get_mut(&client_id).unwrap();
                        client.read_socket();
                        client.try_deserialize()
                    };
                    if let Some(cmd) = cmd {
                        if let Some(resp) = build_response(&database, cmd, client_id, &mut user_list, &mut clients) {
                            let client = &mut clients.get_mut(&client_id).unwrap();
                            if bincode::serialize_into(&client.stream, &resp).is_err() {
                                println!("Failed to write response!");
                            }
                        }
                    }
                }
            }
        }
    }

    quit_thread.join().unwrap();
}

fn fetch_users(db: &db::Database, user_list: &HashMap<usize, String>) -> Vec<proto::User> {
    if let Ok(users) = db.users_from_user_name_iter(user_list.values().map(|s| s.as_ref())) {
        users
    } else {
        Vec::new()
    }
}

fn build_response(db: &db::Database, cmd: proto::Command, client_id: usize, user_list: &mut HashMap<usize, String>, clients: &mut HashMap<usize, ClientSock>) -> Option<proto::Response> {
    use proto::Command::*;
    match cmd {
        ListUsers => Some(proto::Response::UserList(fetch_users(db, user_list))),
        Login { email, password, } => {
            let password_hex = {
                use std::fmt::Write;
                let mut buf = String::with_capacity(password.len() * 2);
                for b in password.iter() {
                    let _ = write!(&mut buf, "{:X}", b);
                }
                buf
            };
            println!("Login with email '{}' and password '{}'", email, password_hex);
            if let Ok(Some(user)) = db.user_with_credentials(&email, &password) {
                // We insert the user name instead of the email address, because I want
                // to avoid moving around and possibly leaking user sensitive data.
                user_list.insert(client_id, user.user_name);

                // Notify other clients about the newly joined guy
                let msg = proto::Response::UserList(fetch_users(db, user_list));
                for c in clients.values() {
                    let _ = bincode::serialize_into(&c.stream, &msg);
                }

                Some(proto::Response::LoginOk)
            } else {
                Some(proto::Response::LoginInvalid)
            }
        }
        Disconnect => {
            clients.remove(&client_id);
            user_list.remove(&client_id);
            let msg = proto::Response::UserList(fetch_users(db, user_list));
            for c in clients.values() {
                let _ = bincode::serialize_into(&c.stream, &msg);
            }
            None
        }
    }
}
<|endoftext|>


<commit_before>use gmp::mpq::Mpq;
use std::borrow::Borrow;
use std::collections::VecDeque;
use std::vec::Vec;

struct BallotState {
    visited: bool,
    prev: usize,
    edge_flow: Box<[Mpq]>,
    sink_flow: Mpq,
    count: i32,
}

#[derive(Clone)]
struct CandidateState {
    prev: usize,
    count: i32,
}

pub fn strength<Ballot>(num_seats: usize, ballots: &[(Ballot, Mpq)]) -> Mpq
    where Ballot: Borrow<[usize]>
{
    let candidate_ballots = &mut vec![Vec::new(); num_seats][..];
    for (b, &(ref cs, _)) in ballots.iter().enumerate() {
        for &c in cs.borrow() {
            candidate_ballots[c].push(b);
        }
    }
    let ballot_states = &mut ballots.iter()
        .map(|&(_, ref w)| {
            BallotState {
                visited: false,
                prev: !0,
                edge_flow: vec![Mpq::zero(); num_seats].into_boxed_slice(),
                sink_flow: w.clone(),
                count: 0,
            }
        })
        .collect::<Vec<_>>()[..];
    let candidate_states = &mut vec![CandidateState {
        prev: !0,
        count: 0,
    }; num_seats][..];

    let mut total_flow = Mpq::zero();
    let mut queue = VecDeque::new();

    loop {
        for (b, bs) in ballot_states.iter_mut().enumerate() {
            if !bs.sink_flow.is_zero() {
                bs.visited = true;
                queue.push_back(b);
            }
        }

        let mut found = Vec::new();
        'search: loop {
            match queue.pop_front() {
                None => {
                    return total_flow;
                }
                Some(b) => {
                    let (ref cs, _) = ballots[b];
                    for &c in cs.borrow() {
                        if candidate_states[c].prev != !0 {
                            continue;
                        }
                        candidate_states[c].prev = b;
                        found.push(c);
                        if found.len() == num_seats {
                            break 'search;
                        }
                        for &b1 in &candidate_ballots[c] {
                            if ballot_states[b1].edge_flow[c].is_zero() ||
                               ballot_states[b1].visited {
                                continue;
                            }
                            ballot_states[b1].visited = true;
                            ballot_states[b1].prev = c;
                            queue.push_back(b1);
                        }
                    }
                }
            }
        }

        let mut sunk = 0;
        for &c in found.iter().rev() {
            let b = candidate_states[c].prev;
            let count = candidate_states[c].count + 1;
            ballot_states[b].count += count;
            let c1 = ballot_states[b].prev;
            if c1 == !0 {
                sunk += count;
            } else {
                candidate_states[c1].count += count;
            }
        }
        debug_assert_eq!(sunk, num_seats as i32);

        let flow = found.iter()
            .map(|&c| {
                let b = candidate_states[c].prev;
                let c1 = ballot_states[b].prev;
                (if c1 == !0 {
                    &ballot_states[b].sink_flow
                } else {
                    &ballot_states[b].edge_flow[c1]
                } / Mpq::from(ballot_states[b].count as i64))
            })
            .min()
            .unwrap();
        debug_assert!(!flow.is_zero());
        total_flow = total_flow + &flow;

        for c in found {
            let b = candidate_states[c].prev;
            let c1 = ballot_states[b].prev;
            ballot_states[b].edge_flow[c] = &ballot_states[b].edge_flow[c] +
                                            &flow * Mpq::from(candidate_states[c].count as i64 + 1);
            if ballot_states[b].count != 0 {
                let edge_flow = if c1 == !0 {
                    &mut ballot_states[b].sink_flow
                } else {
                    &mut ballot_states[b].edge_flow[c1]
                };
                *edge_flow = &*edge_flow - &flow * Mpq::from(ballot_states[b].count as i64);
                ballot_states[b].count = 0;
            }

            candidate_states[c].prev = !0;
            candidate_states[c].count = 0;
        }

        for bs in &mut *ballot_states {
            bs.visited = false;
            bs.prev = !0;
            debug_assert_eq!(bs.count, 0);
        }
        queue.clear();
    }
}

#[cfg(test)]
mod tests {
    use super::strength;
    use gmp::mpq::Mpq;

    const Q: fn(i64) -> Mpq = Mpq::from;

    #[test]
    fn test_strength_1() {
        // Wikipedia
        let ballots: &[(&[usize], Mpq)] =
            &[(&[0], Q(12)), (&[1], Q(0)), (&[0, 1], Q(51)), (&[], Q(27))];
        assert_eq!(strength(2, ballots), Q(63) / Q(2));
    }

    #[test]
    fn test_strength_2() {
        // Wikipedia
        let ballots: &[(&[usize], Mpq)] = &[(&[0], Q(38)), (&[1], Q(27)), (&[0, 1], Q(12))];
        assert_eq!(strength(2, ballots), Q(77) / Q(2));
    }

    #[test]
    fn test_strength_3() {
        // Schulze’s calcul02.pdf
        let ballots: &[(&[usize], Mpq)] = &[(&[0, 1, 2, 3], Q(36_597383) / Q(1_000000)),
                                            (&[0, 1, 2], Q(5_481150) / Q(1_000000)),
                                            (&[0, 1, 3], Q(13_279131) / Q(1_000000)),
                                            (&[0, 1], Q(4_859413) / Q(1_000000)),
                                            (&[0, 2, 3], Q(35_425375) / Q(1_000000)),
                                            (&[0, 2], Q(5_490934) / Q(1_000000)),
                                            (&[0, 3], Q(22_855333) / Q(1_000000)),
                                            (&[0], Q(19_835570) / Q(1_000000)),
                                            (&[1, 2, 3], Q(22_928716) / Q(1_000000)),
                                            (&[1, 2], Q(5_538309) / Q(1_000000)),
                                            (&[1, 3], Q(13_130227) / Q(1_000000)),
                                            (&[1], Q(6_056291) / Q(1_000000)),
                                            (&[2, 3], Q(23_992772) / Q(1_000000)),
                                            (&[2], Q(16_699207) / Q(1_000000)),
                                            (&[3], Q(98_165759) / Q(1_000000)),
                                            (&[], Q(129_664430) / Q(1_000000))];
        assert_eq!(strength(4, ballots), Q(77_389937) / Q(1_000000));
    }
}
<commit_msg>vote_management: Change indexing strategy to avoid special cases<commit_after>use gmp::mpq::Mpq;
use std::borrow::Borrow;
use std::collections::VecDeque;
use std::vec::Vec;

struct BallotState {
    visited: bool,
    prev: usize,
    edge_flow: Box<[Mpq]>,
    count: i32,
}

#[derive(Clone)]
struct CandidateState {
    prev: (usize, usize),
    count: i32,
}

pub fn strength<Ballot>(num_seats: usize, ballots: &[(Ballot, Mpq)]) -> Mpq
    where Ballot: Borrow<[usize]>
{
    let candidate_ballots = &mut vec![Vec::new(); num_seats][..];
    for (b, &(ref cs, _)) in ballots.iter().enumerate() {
        for (i, &c) in cs.borrow().iter().enumerate() {
            candidate_ballots[c].push((b, i));
        }
    }
    let ballot_states = &mut ballots.iter()
        .map(|&(ref cs, ref w)| {
            let mut edge_flow = vec![Mpq::zero(); 1 + cs.borrow().len()].into_boxed_slice();
            edge_flow[0] = w.clone();
            BallotState {
                visited: false,
                prev: !0,
                edge_flow: edge_flow,
                count: 0,
            }
        })
        .collect::<Vec<_>>()[..];
    let candidate_states = &mut vec![CandidateState {
        prev: (!0, !0),
        count: 0,
    }; num_seats][..];

    let mut total_flow = Mpq::zero();
    let mut queue = VecDeque::new();

    loop {
        for (b, bs) in ballot_states.iter_mut().enumerate() {
            if !bs.edge_flow[0].is_zero() {
                bs.visited = true;
                bs.prev = 0;
                queue.push_back(b);
            }
        }

        let mut found = Vec::new();
        'search: loop {
            match queue.pop_front() {
                None => {
                    return total_flow;
                }
                Some(b) => {
                    let (ref cs, _) = ballots[b];
                    for (i, &c) in cs.borrow().iter().enumerate() {
                        if candidate_states[c].prev != (!0, !0) {
                            continue;
                        }
                        candidate_states[c].prev = (b, i);
                        found.push(c);
                        if found.len() == num_seats {
                            break 'search;
                        }
                        for &(b1, i1) in &candidate_ballots[c] {
                            if ballot_states[b1].edge_flow[i1 + 1].is_zero() ||
                               ballot_states[b1].visited {
                                continue;
                            }
                            ballot_states[b1].visited = true;
                            ballot_states[b1].prev = i1 + 1;
                            queue.push_back(b1);
                        }
                    }
                }
            }
        }

        let mut sunk = 0;
        for &c in found.iter().rev() {
            let (b, _) = candidate_states[c].prev;
            let count = candidate_states[c].count + 1;
            ballot_states[b].count += count;
            let i1 = ballot_states[b].prev;
            if i1 == 0 {
                sunk += count;
            } else {
                let (ref cs, _) = ballots[b];
                candidate_states[cs.borrow()[i1 - 1]].count += count;
            }
        }
        debug_assert_eq!(sunk, num_seats as i32);

        let flow = found.iter()
            .map(|&c| {
                let (b, _) = candidate_states[c].prev;
                &ballot_states[b].edge_flow[ballot_states[b].prev] /
                Mpq::from(ballot_states[b].count as i64)
            })
            .min()
            .unwrap();
        debug_assert!(!flow.is_zero());
        total_flow = total_flow + &flow;

        for c in found {
            let (b, i) = candidate_states[c].prev;
            {
                let edge_flow = &mut ballot_states[b].edge_flow[i + 1];
                *edge_flow = &*edge_flow + &flow * Mpq::from(candidate_states[c].count as i64 + 1);
            }
            if ballot_states[b].count != 0 {
                let edge_flow = &mut ballot_states[b].edge_flow[ballot_states[b].prev];
                *edge_flow = &*edge_flow - &flow * Mpq::from(ballot_states[b].count as i64);
                ballot_states[b].count = 0;
            }

            candidate_states[c].prev = (!0, !0);
            candidate_states[c].count = 0;
        }

        for bs in &mut *ballot_states {
            bs.visited = false;
            bs.prev = !0;
            debug_assert_eq!(bs.count, 0);
        }
        queue.clear();
    }
}

#[cfg(test)]
mod tests {
    use super::strength;
    use gmp::mpq::Mpq;

    const Q: fn(i64) -> Mpq = Mpq::from;

    #[test]
    fn test_strength_1() {
        // Wikipedia
        let ballots: &[(&[usize], Mpq)] =
            &[(&[0], Q(12)), (&[1], Q(0)), (&[0, 1], Q(51)), (&[], Q(27))];
        assert_eq!(strength(2, ballots), Q(63) / Q(2));
    }

    #[test]
    fn test_strength_2() {
        // Wikipedia
        let ballots: &[(&[usize], Mpq)] = &[(&[0], Q(38)), (&[1], Q(27)), (&[0, 1], Q(12))];
        assert_eq!(strength(2, ballots), Q(77) / Q(2));
    }

    #[test]
    fn test_strength_3() {
        // Schulze’s calcul02.pdf
        let ballots: &[(&[usize], Mpq)] = &[(&[0, 1, 2, 3], Q(36_597383) / Q(1_000000)),
                                            (&[0, 1, 2], Q(5_481150) / Q(1_000000)),
                                            (&[0, 1, 3], Q(13_279131) / Q(1_000000)),
                                            (&[0, 1], Q(4_859413) / Q(1_000000)),
                                            (&[0, 2, 3], Q(35_425375) / Q(1_000000)),
                                            (&[0, 2], Q(5_490934) / Q(1_000000)),
                                            (&[0, 3], Q(22_855333) / Q(1_000000)),
                                            (&[0], Q(19_835570) / Q(1_000000)),
                                            (&[1, 2, 3], Q(22_928716) / Q(1_000000)),
                                            (&[1, 2], Q(5_538309) / Q(1_000000)),
                                            (&[1, 3], Q(13_130227) / Q(1_000000)),
                                            (&[1], Q(6_056291) / Q(1_000000)),
                                            (&[2, 3], Q(23_992772) / Q(1_000000)),
                                            (&[2], Q(16_699207) / Q(1_000000)),
                                            (&[3], Q(98_165759) / Q(1_000000)),
                                            (&[], Q(129_664430) / Q(1_000000))];
        assert_eq!(strength(4, ballots), Q(77_389937) / Q(1_000000));
    }
}
<|endoftext|>


<commit_before>//! Asynchronous DNS resolver

use std::{
    io::{self, Error, ErrorKind},
    net::SocketAddr,
};

use log::{debug, error, trace};
use tokio::{self, runtime::Handle};
use trust_dns_resolver::{config::ResolverConfig, TokioAsyncResolver};

use super::tokio_dns_resolver::resolve as tokio_resolve;
use crate::context::Context;

/// Create a `trust-dns` asynchronous DNS resolver
pub async fn create_resolver(dns: Option<ResolverConfig>, rt: Handle) -> io::Result<TokioAsyncResolver> {
    {
        // To make this independent, if targeting macOS, BSD, Linux, or Windows, we can use the system's configuration:
        #[cfg(any(unix, windows))]
        {
            if let Some(conf) = dns {
                use trust_dns_resolver::config::ResolverOpts;
                trace!(
                    "Initializing DNS resolver with config {:?} opts {:?}",
                    conf,
                    ResolverOpts::default()
                );
                TokioAsyncResolver::new(conf, ResolverOpts::default(), rt)
            } else {
                use trust_dns_resolver::system_conf::read_system_conf;
                // use the system resolver configuration
                let (config, opts) = match read_system_conf() {
                    Ok(o) => o,
                    Err(err) => {
                        error!("Failed to initialize DNS resolver with system-config, error: {}", err);
                        return Err(err);
                    }
                };

                trace!(
                    "Initializing DNS resolver with system-config {:?} opts {:?}",
                    config,
                    opts
                );

                TokioAsyncResolver::new(config, opts, rt)
            }
        }

        // For other operating systems, we can use one of the preconfigured definitions
        #[cfg(not(any(unix, windows)))]
        {
            // Directly reference the config types
            use trust_dns_resolver::config::{ResolverConfig, ResolverOpts};

            if let Some(conf) = dns {
                trace!(
                    "Initializing DNS resolver with config {:?} opts {:?}",
                    conf,
                    ResolverOpts::default()
                );
                TokioAsyncResolver::new(conf, ResolverOpts::default(), rt)
            } else {
                // Get a new resolver with the google nameservers as the upstream recursive resolvers
                trace!(
                    "Initializing DNS resolver with google-config {:?} opts {:?}",
                    ResolverConfig::google(),
                    ResolverOpts::default()
                );
                TokioAsyncResolver::new(ResolverConfig::google(), ResolverOpts::default(), rt)
            }
        }
    }
    .await
    .map_err(|err| {
        error!("Failed to create trust-dns DNS Resolver, {}", err);
        Error::new(ErrorKind::Other, "failed to create trust-dns DNS resolver")
    })
}

/// Perform a DNS resolution
pub async fn resolve(context: &Context, addr: &str, port: u16, check_forbidden: bool) -> io::Result<Vec<SocketAddr>> {
    match context.dns_resolver() {
        Some(resolver) => match resolver.lookup_ip(addr).await {
            Ok(lookup_result) => {
                let mut vaddr = Vec::new();
                for ip in lookup_result.iter() {
                    if check_forbidden && context.check_forbidden_ip(&ip) {
                        debug!("Resolved {} => {}, which is skipped by forbidden_ip", addr, ip);
                        continue;
                    }

                    vaddr.push(SocketAddr::new(ip, port));
                }

                if vaddr.is_empty() {
                    let err = Error::new(
                        ErrorKind::Other,
                        format!("resolved {}:{}, but all IPs are filtered", addr, port),
                    );
                    Err(err)
                } else {
                    debug!("Resolved {}:{} => {:?}", addr, port, vaddr);
                    Ok(vaddr)
                }
            }
            Err(err) => {
                let err = Error::new(ErrorKind::Other, format!("dns resolve {}:{}, {}", addr, port, err));
                Err(err)
            }
        },
        // Fallback to tokio's DNS resolver
        None => tokio_resolve(context, addr, port, check_forbidden).await,
    }
}
<commit_msg>read_system_conf returns ResolverResult on Windows<commit_after>//! Asynchronous DNS resolver

use std::{
    io::{self, Error, ErrorKind},
    net::SocketAddr,
};

use log::{debug, error, trace};
use tokio::{self, runtime::Handle};
use trust_dns_resolver::{config::ResolverConfig, TokioAsyncResolver};

use super::tokio_dns_resolver::resolve as tokio_resolve;
use crate::context::Context;

/// Create a `trust-dns` asynchronous DNS resolver
pub async fn create_resolver(dns: Option<ResolverConfig>, rt: Handle) -> io::Result<TokioAsyncResolver> {
    {
        // To make this independent, if targeting macOS, BSD, Linux, or Windows, we can use the system's configuration:
        #[cfg(any(unix, windows))]
        {
            if let Some(conf) = dns {
                use trust_dns_resolver::config::ResolverOpts;
                trace!(
                    "Initializing DNS resolver with config {:?} opts {:?}",
                    conf,
                    ResolverOpts::default()
                );
                TokioAsyncResolver::new(conf, ResolverOpts::default(), rt)
            } else {
                use trust_dns_resolver::system_conf::read_system_conf;
                // use the system resolver configuration
                let (config, opts) = match read_system_conf() {
                    Ok(o) => o,
                    Err(err) => {
                        error!("Failed to initialize DNS resolver with system-config, error: {}", err);
                        return Err(From::from(err));
                    }
                };

                trace!(
                    "Initializing DNS resolver with system-config {:?} opts {:?}",
                    config,
                    opts
                );

                TokioAsyncResolver::new(config, opts, rt)
            }
        }

        // For other operating systems, we can use one of the preconfigured definitions
        #[cfg(not(any(unix, windows)))]
        {
            // Directly reference the config types
            use trust_dns_resolver::config::{ResolverConfig, ResolverOpts};

            if let Some(conf) = dns {
                trace!(
                    "Initializing DNS resolver with config {:?} opts {:?}",
                    conf,
                    ResolverOpts::default()
                );
                TokioAsyncResolver::new(conf, ResolverOpts::default(), rt)
            } else {
                // Get a new resolver with the google nameservers as the upstream recursive resolvers
                trace!(
                    "Initializing DNS resolver with google-config {:?} opts {:?}",
                    ResolverConfig::google(),
                    ResolverOpts::default()
                );
                TokioAsyncResolver::new(ResolverConfig::google(), ResolverOpts::default(), rt)
            }
        }
    }
    .await
    .map_err(|err| {
        error!("Failed to create trust-dns DNS Resolver, {}", err);
        Error::new(ErrorKind::Other, "failed to create trust-dns DNS resolver")
    })
}

/// Perform a DNS resolution
pub async fn resolve(context: &Context, addr: &str, port: u16, check_forbidden: bool) -> io::Result<Vec<SocketAddr>> {
    match context.dns_resolver() {
        Some(resolver) => match resolver.lookup_ip(addr).await {
            Ok(lookup_result) => {
                let mut vaddr = Vec::new();
                for ip in lookup_result.iter() {
                    if check_forbidden && context.check_forbidden_ip(&ip) {
                        debug!("Resolved {} => {}, which is skipped by forbidden_ip", addr, ip);
                        continue;
                    }

                    vaddr.push(SocketAddr::new(ip, port));
                }

                if vaddr.is_empty() {
                    let err = Error::new(
                        ErrorKind::Other,
                        format!("resolved {}:{}, but all IPs are filtered", addr, port),
                    );
                    Err(err)
                } else {
                    debug!("Resolved {}:{} => {:?}", addr, port, vaddr);
                    Ok(vaddr)
                }
            }
            Err(err) => {
                let err = Error::new(ErrorKind::Other, format!("dns resolve {}:{}, {}", addr, port, err));
                Err(err)
            }
        },
        // Fallback to tokio's DNS resolver
        None => tokio_resolve(context, addr, port, check_forbidden).await,
    }
}
<|endoftext|>


<commit_before>use std;
use meow;

fn BM(haystack: str, needle: str) -> [uint] {
   str::boyer_moore_search(haystack, needle,
                           str::len(haystack),
                           0u, str::len(haystack))
}

fn simple(haystack: str, needle: str) -> [uint] {
   str::simple_search(haystack, needle,
                      str::len(haystack),
                      0u, str::len(haystack))
}

fn compareHN(hlen: uint, nlen: uint) -> float {
   // some strings to test
   let generator = rand::rng();
   let needle   = generator.gen_str(nlen);
   let haystack = generator.gen_str(hlen);

   // run each
   let (sim_val, sim_time)
      = meow::measure_time_and_value({|| simple(haystack, needle)});
   let (bm_val, bm_time)
      = meow::measure_time_and_value({|| BM(haystack, needle)});

   assert sim_val == bm_val;

   // return the ratio
   ret bm_time as float / sim_time as float;
}

fn main() {
/*
   let bible = meow::bible();
   //let phrase = "And leik, dont think ur all hot soup cuz you just read the FAQ.";
   let phrase = "And leik, dont think ur all hot soup cuz you just read the BANANAS.";
   let phrase2 = "x-ray-banana";

   meow::time("c simple", {|| simple(bible, phrase)});
   meow::time("c BM", {||    BM(bible, phrase)});

   let yy = "superxpalidocious exxpeealidocioussuperxpalidocious exxpeealidocioussuperxpalidocious exxpeealidocious";
   meow::time("c1 simple", {|| simple(bible, yy)});
   meow::time("c1 BM", {||    BM(bible, yy)});

   let mut ii = 0u;
   let N = 40u;
   let mut bibleN = "";
   str::reserve(bibleN, N * str::len(bibleN) + 1u);
   while ii < N {
      bibleN += bible;
      ii += 1u;
   }

   meow::time("d simple", {|| simple(bibleN, phrase2)});
   meow::time("d BM", {||    BM(bibleN, phrase2)});
*/

/*
   let loremipsum = "
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris laoreet consequat fringilla. Quisque venenatis lacinia ipsum non rhoncus. Donec adipiscing fringilla erat, a pretium purus rhoncus quis. Nunc rhoncus dui at ipsum bibendum tincidunt. Etiam eu lorem nulla. Nulla id est id augue blandit vestibulum. Nullam eleifend gravida feugiat. Aliquam vitae urna arcu. Ut sed enim dui, a suscipit sapien.

Ut sollicitudin, metus id malesuada dapibus, quam velit ultrices nibh, at feugiat diam tellus eget risus. Vestibulum in ultrices enim. Nulla at est molestie augue hendrerit tempor sed in purus. Mauris non lorem libero, id faucibus odio. Proin feugiat magna id diam laoreet eu dapibus sapien eleifend. Nunc imperdiet auctor hendrerit. Curabitur porta tempus quam, vel scelerisque elit feugiat ac. Vestibulum feugiat bibendum massa in dapibus. Quisque lacinia porttitor turpis et auctor. Ut quis tortor vitae ligula faucibus euismod nec eu risus. Nullam blandit, risus at consectetur dapibus, velit nisl tincidunt tortor, sed varius risus neque sit amet purus. In diam nisl, facilisis tristique convallis sit amet, posuere congue augue. Vestibulum malesuada, tellus vitae mattis laoreet, nulla felis posuere libero, et blandit eros erat at lacus. Morbi id placerat magna. Nulla lacus magna, gravida sit amet elementum et, posuere nec sapien. Maecenas vitae felis magna, fringilla facilisis massa.

Ut porta, ligula id blandit volutpat, felis sapien ornare sapien, a auctor felis nunc in risus. Etiam in erat at tellus rutrum euismod quis at quam. Proin massa mauris, auctor in tempor eu, cursus quis metus. Suspendisse et dolor quam. Nam id neque eget lorem interdum ultricies. Phasellus aliquet facilisis tortor ac pellentesque. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Suspendisse sed porta purus. Donec consectetur imperdiet tortor et sagittis. Ut pretium vulputate tortor eget ullamcorper. Nullam a urna sollicitudin quam mollis fermentum eu id enim. Mauris pharetra blandit ultricies. In ligula justo, rhoncus et tempus vitae, rutrum non neque.

In accumsan pulvinar lorem sed sollicitudin. Donec justo sem, aliquet at posuere ut, tempus at est. Quisque mattis scelerisque felis ac semper. Quisque nec tristique orci. Donec id diam ut ipsum auctor hendrerit non non sem. Vivamus non erat eros, at vulputate dolor. Duis vehicula, neque sed rhoncus ornare, ante est placerat erat, non luctus justo libero quis mauris. Pellentesque sollicitudin dignissim faucibus. Nunc arcu urna, hendrerit at sagittis nec, dapibus eu leo. Sed eget libero nec risus aliquet hendrerit ullamcorper vel sem. Vestibulum eleifend elit sed tellus tempor elementum. Maecenas eu nibh quis tortor pretium ullamcorper id vel nibh. Pellentesque viverra, nulla vitae condimentum pretium, enim nisl euismod odio, eget vulputate velit justo in lorem.

Nunc eget leo ipsum. Nulla facilisi. Nam adipiscing justo id nisl aliquam at posuere nulla pharetra. Pellentesque fringilla fringilla placerat. Nam pulvinar vehicula augue, a vestibulum turpis rutrum eu. Curabitur semper viverra elit id ultricies. Nunc nibh lacus, congue at imperdiet eget, lacinia at lorem. Aliquam erat volutpat. Pellentesque malesuada ultrices arcu, eu dignissim nisi consectetur at. Nam tristique justo molestie lorem pellentesque vel consectetur augue hendrerit.
";

   meow::time("lorem ipsum (400) in bible (simple)",
              {|| simple(bible, str::slice(loremipsum, 0u, 400u))});
   meow::time("lorem ipsum (400) in bible (BM)   ",
              {||    BM(bible, str::slice(loremipsum, 0u, 400u))});

   let mut ii = 0u;
   let N = 40u;
   let mut bibleN = "";
   str::reserve(bibleN, N * str::len(bibleN) + 1u);
   while ii < N {
      bibleN += bible;
      ii += 1u;
   }

   meow::time("lorem ipsum (100) in bible x40 (simple)",
              {|| simple(bibleN, str::slice(loremipsum, 0u, 100u))});
   meow::time("lorem ipsum (100) in bible x40 (BM)   ",
              {||    BM(bibleN, str::slice(loremipsum, 0u, 100u))});

   meow::time("lorem ipsum (400) in bible x40 (simple)",
              {|| simple(bibleN, str::slice(loremipsum, 0u, 400u))});
   meow::time("lorem ipsum (400) in bible x40 (BM)   ",
              {||    BM(bibleN, str::slice(loremipsum, 0u, 400u))});

   let mut ii = 0u;
   let N = 160u;
   let mut bibleN = "";
   str::reserve(bibleN, N * str::len(bibleN) + 1u);
   while ii < N {
      bibleN += bible;
      ii += 1u;
   }

   meow::time("lorem ipsum (100) in bible x160 (simple)",
              {|| simple(bibleN, str::slice(loremipsum, 0u, 100u))});
   meow::time("lorem ipsum (100) in bible x160 (BM)   ",
              {||    BM(bibleN, str::slice(loremipsum, 0u, 100u))});

   meow::time("lorem ipsum (400) in bible x160 (simple)",
              {|| simple(bibleN, str::slice(loremipsum, 0u, 400u))});
   meow::time("lorem ipsum (400) in bible x160 (BM)   ",
              {||    BM(bibleN, str::slice(loremipsum, 0u, 400u))});

   let mut ii = 0u;
   let N = 260u;
   let mut bibleN = "";
   str::reserve(bibleN, N * str::len(bibleN) + 1u);
   while ii < N {
      bibleN += bible;
      ii += 1u;
   }

   meow::time("lorem ipsum (100) in bible x260 (simple)",
              {|| simple(bibleN, str::slice(loremipsum, 0u, 100u))});
   meow::time("lorem ipsum (100) in bible x260 (BM)   ",
              {||    BM(bibleN, str::slice(loremipsum, 0u, 100u))});

   meow::time("lorem ipsum (400) in bible x260 (simple)",
              {|| simple(bibleN, str::slice(loremipsum, 0u, 400u))});
   meow::time("lorem ipsum (400) in bible x260 (BM)   ",
              {||    BM(bibleN, str::slice(loremipsum, 0u, 400u))});

*/

//   meow::time("lorem ipsum ^2 (simple)", {|| BM(loremipsum, loremipsum)} );
//   meow::time("lorem ipsum ^2 (BM)", {|| BM(loremipsum, loremipsum)} );

   // 2D range
   let (num_n, num_h) = (200u, 400u);
   let (mult_n, mult_h) = (10u, 100u);
   let row1 = vec::to_mut(vec::from_elem(num_h, 1.0f));
   let result = vec::to_mut(vec::from_elem(num_n, row1));
   let mut nn = 0u;
   while nn < num_n {
      let mut hh = 0u;
      while hh < num_h {
         // save a grid of ratio of time for BM / simple search
         result[nn][hh] = compareHN(1u+hh*mult_h, 1u+nn*mult_n);

         hh += 1u;
      }
      nn += 1u;
   }

   let matlab_data_2d = fn@(data: [mut [mut float]]) -> (str,str,str) {
      // captured:
      //let mult_h, mult_n;

      let xxlim = vec::len(data);
      let yylim = vec::len(data[0]);

      let mut res = "";
      let mut xs = "";
      let mut ys = "";

      // Y
      let mut yy = 0u;
      while yy < yylim {
         if yy != 0u {
            res += "; ";
            xs += ", ";
         }

         // X
         let mut xx = 0u;
         while xx < xxlim {
            if xx != 0u {
               res += ", ";
               if yy == 0u {
                  ys += ", ";
               }
            }

            // data
            res += #fmt("%f", data[xx][yy]);

            if yy == 0u {
               ys += #fmt("%u", 1u + mult_n * xx);
            }
            xx += 1u;
         }

         xs += #fmt("%u", 1u + mult_h * yy);
         yy += 1u;
      }

      ret (xs, ys, res);
   };

   io::println("######################################################");
   io::println("### paste into Octave or Matlab... ###################");

   // output to octave/matlab
   let (xs, ys, ratio) = matlab_data_2d(result);
   io::println("ratio     = [" + ratio + "];");
   io::println("haystacks = [" + ys + "];");
   io::println("needles   = [" + xs + "];");

   io::println("contourf(haystacks, needles, ratio, [0.1 : 0.1 : 10.0]);");
   io::println("xlabel('needle size');");
   io::println("ylabel('haystack size');");
   io::println("title('Boyer-Moore time / basic search time');");
   io::println("xlim([min(needles) max(needles)]);");
   io::println("ylim([min(haystacks) max(haystacks)]);");
   io::println("colormap('cool');");
   io::println("colorbar;");
   io::println("");
   io::println("print('comparison.svg', '-dSVG');");

   io::println("######################################################");
}

<commit_msg>a decent resolution and range...<commit_after>use std;
use meow;

fn BM(haystack: str, needle: str) -> [uint] {
   str::boyer_moore_search(haystack, needle,
                           str::len(haystack),
                           0u, str::len(haystack))
}

fn simple(haystack: str, needle: str) -> [uint] {
   str::simple_search(haystack, needle,
                      str::len(haystack),
                      0u, str::len(haystack))
}

fn compareHN(hlen: uint, nlen: uint) -> float {
   // some strings to test
   let generator = rand::rng();
   let needle   = generator.gen_str(nlen);
   let haystack = generator.gen_str(hlen);

   // run each
   let (sim_val, sim_time)
      = meow::measure_time_and_value({|| simple(haystack, needle)});
   let (bm_val, bm_time)
      = meow::measure_time_and_value({|| BM(haystack, needle)});

   assert sim_val == bm_val;

   // return the ratio
   ret sim_time as float / bm_time as float;
}

fn main() {
/*
   let bible = meow::bible();
   //let phrase = "And leik, dont think ur all hot soup cuz you just read the FAQ.";
   let phrase = "And leik, dont think ur all hot soup cuz you just read the BANANAS.";
   let phrase2 = "x-ray-banana";

   meow::time("c simple", {|| simple(bible, phrase)});
   meow::time("c BM", {||    BM(bible, phrase)});

   let yy = "superxpalidocious exxpeealidocioussuperxpalidocious exxpeealidocioussuperxpalidocious exxpeealidocious";
   meow::time("c1 simple", {|| simple(bible, yy)});
   meow::time("c1 BM", {||    BM(bible, yy)});

   let mut ii = 0u;
   let N = 40u;
   let mut bibleN = "";
   str::reserve(bibleN, N * str::len(bibleN) + 1u);
   while ii < N {
      bibleN += bible;
      ii += 1u;
   }

   meow::time("d simple", {|| simple(bibleN, phrase2)});
   meow::time("d BM", {||    BM(bibleN, phrase2)});
*/

/*
   let loremipsum = "
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris laoreet consequat fringilla. Quisque venenatis lacinia ipsum non rhoncus. Donec adipiscing fringilla erat, a pretium purus rhoncus quis. Nunc rhoncus dui at ipsum bibendum tincidunt. Etiam eu lorem nulla. Nulla id est id augue blandit vestibulum. Nullam eleifend gravida feugiat. Aliquam vitae urna arcu. Ut sed enim dui, a suscipit sapien.

Ut sollicitudin, metus id malesuada dapibus, quam velit ultrices nibh, at feugiat diam tellus eget risus. Vestibulum in ultrices enim. Nulla at est molestie augue hendrerit tempor sed in purus. Mauris non lorem libero, id faucibus odio. Proin feugiat magna id diam laoreet eu dapibus sapien eleifend. Nunc imperdiet auctor hendrerit. Curabitur porta tempus quam, vel scelerisque elit feugiat ac. Vestibulum feugiat bibendum massa in dapibus. Quisque lacinia porttitor turpis et auctor. Ut quis tortor vitae ligula faucibus euismod nec eu risus. Nullam blandit, risus at consectetur dapibus, velit nisl tincidunt tortor, sed varius risus neque sit amet purus. In diam nisl, facilisis tristique convallis sit amet, posuere congue augue. Vestibulum malesuada, tellus vitae mattis laoreet, nulla felis posuere libero, et blandit eros erat at lacus. Morbi id placerat magna. Nulla lacus magna, gravida sit amet elementum et, posuere nec sapien. Maecenas vitae felis magna, fringilla facilisis massa.

Ut porta, ligula id blandit volutpat, felis sapien ornare sapien, a auctor felis nunc in risus. Etiam in erat at tellus rutrum euismod quis at quam. Proin massa mauris, auctor in tempor eu, cursus quis metus. Suspendisse et dolor quam. Nam id neque eget lorem interdum ultricies. Phasellus aliquet facilisis tortor ac pellentesque. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Suspendisse sed porta purus. Donec consectetur imperdiet tortor et sagittis. Ut pretium vulputate tortor eget ullamcorper. Nullam a urna sollicitudin quam mollis fermentum eu id enim. Mauris pharetra blandit ultricies. In ligula justo, rhoncus et tempus vitae, rutrum non neque.

In accumsan pulvinar lorem sed sollicitudin. Donec justo sem, aliquet at posuere ut, tempus at est. Quisque mattis scelerisque felis ac semper. Quisque nec tristique orci. Donec id diam ut ipsum auctor hendrerit non non sem. Vivamus non erat eros, at vulputate dolor. Duis vehicula, neque sed rhoncus ornare, ante est placerat erat, non luctus justo libero quis mauris. Pellentesque sollicitudin dignissim faucibus. Nunc arcu urna, hendrerit at sagittis nec, dapibus eu leo. Sed eget libero nec risus aliquet hendrerit ullamcorper vel sem. Vestibulum eleifend elit sed tellus tempor elementum. Maecenas eu nibh quis tortor pretium ullamcorper id vel nibh. Pellentesque viverra, nulla vitae condimentum pretium, enim nisl euismod odio, eget vulputate velit justo in lorem.

Nunc eget leo ipsum. Nulla facilisi. Nam adipiscing justo id nisl aliquam at posuere nulla pharetra. Pellentesque fringilla fringilla placerat. Nam pulvinar vehicula augue, a vestibulum turpis rutrum eu. Curabitur semper viverra elit id ultricies. Nunc nibh lacus, congue at imperdiet eget, lacinia at lorem. Aliquam erat volutpat. Pellentesque malesuada ultrices arcu, eu dignissim nisi consectetur at. Nam tristique justo molestie lorem pellentesque vel consectetur augue hendrerit.
";

   meow::time("lorem ipsum (400) in bible (simple)",
              {|| simple(bible, str::slice(loremipsum, 0u, 400u))});
   meow::time("lorem ipsum (400) in bible (BM)   ",
              {||    BM(bible, str::slice(loremipsum, 0u, 400u))});

   let mut ii = 0u;
   let N = 40u;
   let mut bibleN = "";
   str::reserve(bibleN, N * str::len(bibleN) + 1u);
   while ii < N {
      bibleN += bible;
      ii += 1u;
   }

   meow::time("lorem ipsum (100) in bible x40 (simple)",
              {|| simple(bibleN, str::slice(loremipsum, 0u, 100u))});
   meow::time("lorem ipsum (100) in bible x40 (BM)   ",
              {||    BM(bibleN, str::slice(loremipsum, 0u, 100u))});

   meow::time("lorem ipsum (400) in bible x40 (simple)",
              {|| simple(bibleN, str::slice(loremipsum, 0u, 400u))});
   meow::time("lorem ipsum (400) in bible x40 (BM)   ",
              {||    BM(bibleN, str::slice(loremipsum, 0u, 400u))});

   let mut ii = 0u;
   let N = 160u;
   let mut bibleN = "";
   str::reserve(bibleN, N * str::len(bibleN) + 1u);
   while ii < N {
      bibleN += bible;
      ii += 1u;
   }

   meow::time("lorem ipsum (100) in bible x160 (simple)",
              {|| simple(bibleN, str::slice(loremipsum, 0u, 100u))});
   meow::time("lorem ipsum (100) in bible x160 (BM)   ",
              {||    BM(bibleN, str::slice(loremipsum, 0u, 100u))});

   meow::time("lorem ipsum (400) in bible x160 (simple)",
              {|| simple(bibleN, str::slice(loremipsum, 0u, 400u))});
   meow::time("lorem ipsum (400) in bible x160 (BM)   ",
              {||    BM(bibleN, str::slice(loremipsum, 0u, 400u))});

   let mut ii = 0u;
   let N = 260u;
   let mut bibleN = "";
   str::reserve(bibleN, N * str::len(bibleN) + 1u);
   while ii < N {
      bibleN += bible;
      ii += 1u;
   }

   meow::time("lorem ipsum (100) in bible x260 (simple)",
              {|| simple(bibleN, str::slice(loremipsum, 0u, 100u))});
   meow::time("lorem ipsum (100) in bible x260 (BM)   ",
              {||    BM(bibleN, str::slice(loremipsum, 0u, 100u))});

   meow::time("lorem ipsum (400) in bible x260 (simple)",
              {|| simple(bibleN, str::slice(loremipsum, 0u, 400u))});
   meow::time("lorem ipsum (400) in bible x260 (BM)   ",
              {||    BM(bibleN, str::slice(loremipsum, 0u, 400u))});

*/

//   meow::time("lorem ipsum ^2 (simple)", {|| BM(loremipsum, loremipsum)} );
//   meow::time("lorem ipsum ^2 (BM)", {|| BM(loremipsum, loremipsum)} );

   // 2D range
   let (num_n, num_h) = (100u, 90u);
   let (mult_n, mult_h) = (4u, 100u);
   let row1 = vec::to_mut(vec::from_elem(num_n, 1.0f));
   let result = vec::to_mut(vec::from_elem(num_h, row1));
   let mut nn = 0u;
   while nn < num_n {
      let mut hh = 0u;
      while hh < num_h {
         // save a grid of ratio of time
         result[hh][nn] = compareHN(1u+hh*mult_h, 1u+nn*mult_n);

         hh += 1u;
      }
      nn += 1u;
   }

   // data [row\y] [col\x]
   let matlab_data_2d = fn@(data: [mut [mut float]]) -> (str,str,str) {
      // captured:
      //let mult_h, mult_n;

      let xxlim = vec::len(data[0]);
      let yylim = vec::len(data);

      let mut res = "";
      let mut xs = "";
      let mut ys = "";

      // Y
      let mut yy = 0u;
      while yy < yylim {
         if yy != 0u {
            res += "; ";
            ys += ", ";
         }

         // X
         let mut xx = 0u;
         while xx < xxlim {
            if xx != 0u {
               res += ", ";
               if yy == 0u {
                  xs += ", ";
               }
            }

            // data
            res += #fmt("%f", data[yy][xx]);

            if yy == 0u {
               xs += #fmt("%u", 1u + mult_n * xx);
            }
            xx += 1u;
         }

         ys += #fmt("%u", 1u + mult_h * yy);
         yy += 1u;
      }

      ret (xs, ys, res);
   };

   io::println("######################################################");
   io::println("### paste into Octave or Matlab... ###################");

   // output to octave/matlab
   let (xs, ys, ratio) = matlab_data_2d(result);
   io::println("ratio     = [" + ratio + "];");
   io::println("needles   = [" + xs + "];");
   io::println("haystacks = [" + ys + "];");

   io::println("contourf(needles, haystacks, ratio, [0.0 : 0.5 : 10.0]);");
   io::println("%contourf(needles, haystacks, ratio, [0.1 1.0 2.0]);");
   io::println("xlabel('needle size');");
   io::println("ylabel('haystack size');");
   io::println("title('basic search time / Boyer-Moore time');");
   io::println("xlim([min(needles) max(needles)]);");
   io::println("ylim([min(haystacks) max(haystacks)]);");
   io::println("colormap('cool');");
   io::println("colorbar;");
   io::println("");
   io::println("print('comparison.svg', '-dSVG');");

   io::println("######################################################");
}

<|endoftext|>