<commit_before>//#![feature(convert)]
#![crate_type="lib"]
extern crate byteorder;
pub mod xdr;

#[test]
fn u16_writer_test() {
	let mut x = xdr::XdrWriter::new();
	let wtr = vec![0,0,2,5];

	x.pack(517u16);
	assert_eq!(x.into_buffer(),wtr);
}

#[test]
fn u16_reader_test() {
	let wtr = vec![0,0,2,5];
	let mut x = xdr::XdrReader::new(&wtr);

	let v = x.unpack::<u16>().unwrap();
	assert_eq!(v,517u16);
}

#[test]
fn r_w_primitive_test() {
	let mut wr = xdr::XdrWriter::new();
	wr.pack(0xCCu8);
	wr.pack(0xAAAAu16);
	wr.pack(0xDEADBEEFu32);
	wr.pack(-1i8);
	wr.pack(-256i16);
	wr.pack(-20i32);
	wr.pack(100.500f32);
	wr.pack(-100.500e10f64);

	let buf = &wr.into_buffer();
	let mut rdr = xdr::XdrReader::new(buf);

	assert_eq!(0xCCu8,rdr.unpack::<u8>().unwrap());
	assert_eq!(0xAAAAu16,rdr.unpack::<u16>().unwrap());
	assert_eq!(0xDEADBEEFu32,rdr.unpack::<u32>().unwrap());
	assert_eq!(-1i8,rdr.unpack::<i8>().unwrap());
	assert_eq!(-256i16,rdr.unpack::<i16>().unwrap());
	assert_eq!(-20i32,rdr.unpack::<i32>().unwrap());
	assert_eq!(100.500f32,rdr.unpack::<f32>().unwrap());
	assert_eq!(-100.500e10f64,rdr.unpack::<f64>().unwrap());
}

#[test]
fn variable_length_array_test() {
	let mut wr = xdr::XdrWriter::new();
	let vec = vec![0u32,1,2,3,4,5];

	wr.pack(vec);
	let buf = &wr.into_buffer();
	let mut rdr = xdr::XdrReader::new(buf);

	let res = rdr.unpack::<Vec<u32>>().unwrap();

	assert_eq!(vec![0u32,1,2,3,4,5], res)
}

#[test]
fn fixed_length_array_test() {
	let mut wr = xdr::XdrWriter::new();
	let vec = vec![0u32,1,2,3,4,5];

	wr.pack_array(vec);
	let buf = &wr.into_buffer();
	let mut rdr = xdr::XdrReader::new(buf);

	let res = rdr.unpack_array::<u32>(6).unwrap();

	assert_eq!(vec![0u32,1,2,3,4,5], res)
}

#[test]
fn ascii_string_test() {
	let mut wr = xdr::XdrWriter::new();
	let str = "abcdefABCDEFGH".to_string();

	wr.pack(str);
	let buf = &wr.into_buffer();
	let mut rdr = xdr::XdrReader::new(buf);

	let res = rdr.unpack::<String>().unwrap();

	assert_eq!("abcdefABCDEFGH", res)
}

#[test]
fn utf_8_string_test() {
	let mut wr = xdr::XdrWriter::new();
	let str = "abcdefABCDEFGHАБВГДЕЁ".to_string();

	wr.pack(str);
	let buf = &wr.into_buffer();
	let mut rdr = xdr::XdrReader::new(buf);

	let res = rdr.unpack::<String>().unwrap();

	assert_eq!("abcdefABCDEFGHАБВГДЕЁ", res)
}
<commit_msg>change to_string to to_owned<commit_after>//#![feature(convert)]
#![crate_type="lib"]
extern crate byteorder;
pub mod xdr;

#[test]
fn u16_writer_test() {
	let mut x = xdr::XdrWriter::new();
	let wtr = vec![0,0,2,5];

	x.pack(517u16);
	assert_eq!(x.into_buffer(),wtr);
}

#[test]
fn u16_reader_test() {
	let wtr = vec![0,0,2,5];
	let mut x = xdr::XdrReader::new(&wtr);

	let v = x.unpack::<u16>().unwrap();
	assert_eq!(v,517u16);
}

#[test]
fn r_w_primitive_test() {
	let mut wr = xdr::XdrWriter::new();
	wr.pack(0xCCu8);
	wr.pack(0xAAAAu16);
	wr.pack(0xDEADBEEFu32);
	wr.pack(-1i8);
	wr.pack(-256i16);
	wr.pack(-20i32);
	wr.pack(100.500f32);
	wr.pack(-100.500e10f64);

	let buf = &wr.into_buffer();
	let mut rdr = xdr::XdrReader::new(buf);

	assert_eq!(0xCCu8,rdr.unpack::<u8>().unwrap());
	assert_eq!(0xAAAAu16,rdr.unpack::<u16>().unwrap());
	assert_eq!(0xDEADBEEFu32,rdr.unpack::<u32>().unwrap());
	assert_eq!(-1i8,rdr.unpack::<i8>().unwrap());
	assert_eq!(-256i16,rdr.unpack::<i16>().unwrap());
	assert_eq!(-20i32,rdr.unpack::<i32>().unwrap());
	assert_eq!(100.500f32,rdr.unpack::<f32>().unwrap());
	assert_eq!(-100.500e10f64,rdr.unpack::<f64>().unwrap());
}

#[test]
fn variable_length_array_test() {
	let mut wr = xdr::XdrWriter::new();
	let vec = vec![0u32,1,2,3,4,5];

	wr.pack(vec);
	let buf = &wr.into_buffer();
	let mut rdr = xdr::XdrReader::new(buf);

	let res = rdr.unpack::<Vec<u32>>().unwrap();

	assert_eq!(vec![0u32,1,2,3,4,5], res)
}

#[test]
fn fixed_length_array_test() {
	let mut wr = xdr::XdrWriter::new();
	let vec = vec![0u32,1,2,3,4,5];

	wr.pack_array(vec);
	let buf = &wr.into_buffer();
	let mut rdr = xdr::XdrReader::new(buf);

	let res = rdr.unpack_array::<u32>(6).unwrap();

	assert_eq!(vec![0u32,1,2,3,4,5], res)
}

#[test]
fn ascii_string_test() {
	let mut wr = xdr::XdrWriter::new();
	let str = "abcdefABCDEFGH".to_owned();

	wr.pack(str);
	let buf = &wr.into_buffer();
	let mut rdr = xdr::XdrReader::new(buf);

	let res = rdr.unpack::<String>().unwrap();

	assert_eq!("abcdefABCDEFGH", res)
}

#[test]
fn utf_8_string_test() {
	let mut wr = xdr::XdrWriter::new();
	let str = "abcdefABCDEFGHАБВГДЕЁ".to_owned();

	wr.pack(str);
	let buf = &wr.into_buffer();
	let mut rdr = xdr::XdrReader::new(buf);

	let res = rdr.unpack::<String>().unwrap();

	assert_eq!("abcdefABCDEFGHАБВГДЕЁ", res)
}
<|endoftext|>


<commit_before>/* Copyright 2017 Christopher Bacher
 *
 * 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.
 */

//! Galvanic-assert: Matcher-based assertions for easier testing
//! ============================================================
//! This crate provides a new assertion macro `assert_that!` based on **matching predicates** (matchers) to
//!
//!  * make **writing** asserts easier
//!  * make **reading** asserts comprehendable
//!  * easily **extend** the assertion framework
//!  * provide a large list **common matchers**
//!  * integrate with **galvanic-test** and **galvanic-mock** (both still in development ... stay tuned!)
//!  * be used with your favourite test framework
//!
//! The crate will be part of **galvanic**---a complete test framework for **Rust**.
//!
//! **galvanic-assert** currently requires *nightly* until *impl trait* returns have been stabilized.

#![feature(conservative_impl_trait)]
#![feature(discriminant_value)]

use std::fmt::{Display, Debug, Formatter, Result as FormatResult};

/// States that the asserted values satisfies the required properties of the supplied `Matcher`.
///
/// The macro comes in three different forms:
///
///  1. Assert that some expression is true, supplied with an optional error message.
///
///     ```rust,ignore
///     assert_that!(EXPRESSION);
///     assert_that!(EXPRESSION, otherwise "some error message");
///     ```
///  2. Assert that some expression satifies the properties of some `Matcher`.
///     The `Matcher` is either predefined, a user defined type with a `Matcher` implementation, or a closure returning a `MatchResult`
///
///     ```rust,ignore
///     assert_that!(1, eq(1));
///     assert_that!(1, |x| {
///         let builder = MatchResultBuilder::for_("my_matcher");
///         if x == 1 { builder.matched } else { builder.failed_because("some reason") }
///     })
///     ```
///  3. Assert that some expression is expected to panic/not panic.
///
///     ```rust,ignore
///     assert_that!(panic!("panic"), panics);
///     assert_that!(1+1, does not panic);
///     ```
#[macro_export]
macro_rules! assert_that {
    ( $actual: expr, panics ) => {
        let result = std::panic::catch_unwind(|| { $actual; });
        if result.is_ok() {
            panic!("\nFailed assertion; expected expression to panic")
        }
    };
    ( $actual: expr, does not panic ) => {
        let result = std::panic::catch_unwind(|| { $actual; });
        if result.is_err() {
            panic!("\nFailed assertion; expression panicked unexpectantly")
        }
    };
    ( $actual: expr) => {
        if !$actual {
            panic!("\nFailed assertion; '{}' is not true", stringify!($actual));
        }
    };
    ( $actual: expr , otherwise $reason: expr ) => {
        if !$actual {
            panic!("\nFailed assertion; expression '{}' is not true,\n    Because: {}",
                   stringify!($actual), $reason
            );
        }
    };
    ( $actual: expr, $matcher: expr ) => {
        match $matcher.check($actual) {
            MatchResult::Matched { .. } => { },
            MatchResult::Failed { name, reason } => {
                panic!("\nFailed assertion of matcher: {}\n{}", name, reason)
            }
        }
    };
}

/// The trait which has to be implemented by all matchers.
pub trait Matcher<T> {
    /// Checks the passed value if it satisfies the `Matcher`.
    fn check(&self, actual: T) -> MatchResult;
}

/// A closures can be used as a `Matcher`.
///
/// The closure must be repeatably callable in case that the matcher is combined with another matcher.
impl<T, F> Matcher<T> for F
where F: Fn(T) -> MatchResult {
    fn check(&self, actual: T) -> MatchResult {
        self(actual)
    }
}

/// The return type of any `Machter`
pub enum MatchResult {
    /// Indicates that the `Matcher` matched the value under inspection.
    Matched {
        /// The `name` of the `Matcher`
        name: String
    },
    /// Indicates that the `Matcher` failed to match the value under inspection.
    Failed {
        /// The `name` of the `Matcher`
        name: String,
        /// The `reason` why the `Matcher` failed
        reason: String
    }
}

/// A builder for creating `MatchResult`s.
///
/// Create a new builder with `new()` or `for_()`
/// and finalize it either with `matched()`, `failed_because()`, or `failed_comparison()`.
pub struct MatchResultBuilder {
    matcher_name: String
}

impl MatchResultBuilder {
    /// Creates a `MatchResultBuilder` for an anonymous `Matcher`.
    pub fn new() -> MatchResultBuilder {
        MatchResultBuilder {
            matcher_name: "_unknown_".to_owned()
        }
    }

    /// Creates `MatchResultBuilder` for a `Matcher` with the given `name`
    pub fn for_(name: &str) -> MatchResultBuilder {
        MatchResultBuilder {
            matcher_name: name.to_owned()
        }
    }

    /// Finalzes the builder indicating that the `Matcher` matched the inspected value.
    pub fn matched(self) -> MatchResult {
        MatchResult::Matched { name: self.matcher_name }
    }

    /// Finalzes the builder indicating that the `Matcher` failed to the inspected value.
    ///
    /// The `reason` should give a short indication why the matcher failed.
    pub fn failed_because(self, reason: &str) -> MatchResult {
        MatchResult::Failed {
            name: self.matcher_name,
            reason: format!("  Because: {}", reason)
        }
    }

    /// Finalzes the builder indicating that the `Matcher` failed to the inspected value.
    ///
    /// The `actual` and `expected` value are used the generate a useful error message.
    pub fn failed_comparison<T: Debug>(self, actual: &T, expected: &T) -> MatchResult {
        MatchResult::Failed {
            name: self.matcher_name,
            reason: format!("  Expected: {:?}\n  Got: {:?}", expected, actual)
        }
    }
}

pub mod matchers;
<commit_msg>fix warnings for unused imports<commit_after>/* Copyright 2017 Christopher Bacher
 *
 * 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.
 */

//! Galvanic-assert: Matcher-based assertions for easier testing
//! ============================================================
//! This crate provides a new assertion macro `assert_that!` based on **matching predicates** (matchers) to
//!
//!  * make **writing** asserts easier
//!  * make **reading** asserts comprehendable
//!  * easily **extend** the assertion framework
//!  * provide a large list **common matchers**
//!  * integrate with **galvanic-test** and **galvanic-mock** (both still in development ... stay tuned!)
//!  * be used with your favourite test framework
//!
//! The crate will be part of **galvanic**---a complete test framework for **Rust**.
//!
//! **galvanic-assert** currently requires *nightly* until *impl trait* returns have been stabilized.

#![feature(conservative_impl_trait)]
#![feature(discriminant_value)]

use std::fmt::{Debug};

/// States that the asserted values satisfies the required properties of the supplied `Matcher`.
///
/// The macro comes in three different forms:
///
///  1. Assert that some expression is true, supplied with an optional error message.
///
///     ```rust,ignore
///     assert_that!(EXPRESSION);
///     assert_that!(EXPRESSION, otherwise "some error message");
///     ```
///  2. Assert that some expression satifies the properties of some `Matcher`.
///     The `Matcher` is either predefined, a user defined type with a `Matcher` implementation, or a closure returning a `MatchResult`
///
///     ```rust,ignore
///     assert_that!(1, eq(1));
///     assert_that!(1, |x| {
///         let builder = MatchResultBuilder::for_("my_matcher");
///         if x == 1 { builder.matched } else { builder.failed_because("some reason") }
///     })
///     ```
///  3. Assert that some expression is expected to panic/not panic.
///
///     ```rust,ignore
///     assert_that!(panic!("panic"), panics);
///     assert_that!(1+1, does not panic);
///     ```
#[macro_export]
macro_rules! assert_that {
    ( $actual: expr, panics ) => {
        let result = std::panic::catch_unwind(|| { $actual; });
        if result.is_ok() {
            panic!("\nFailed assertion; expected expression to panic")
        }
    };
    ( $actual: expr, does not panic ) => {
        let result = std::panic::catch_unwind(|| { $actual; });
        if result.is_err() {
            panic!("\nFailed assertion; expression panicked unexpectantly")
        }
    };
    ( $actual: expr) => {
        if !$actual {
            panic!("\nFailed assertion; '{}' is not true", stringify!($actual));
        }
    };
    ( $actual: expr , otherwise $reason: expr ) => {
        if !$actual {
            panic!("\nFailed assertion; expression '{}' is not true,\n    Because: {}",
                   stringify!($actual), $reason
            );
        }
    };
    ( $actual: expr, $matcher: expr ) => {
        match $matcher.check($actual) {
            MatchResult::Matched { .. } => { },
            MatchResult::Failed { name, reason } => {
                panic!("\nFailed assertion of matcher: {}\n{}", name, reason)
            }
        }
    };
}

/// The trait which has to be implemented by all matchers.
pub trait Matcher<T> {
    /// Checks the passed value if it satisfies the `Matcher`.
    fn check(&self, actual: T) -> MatchResult;
}

/// A closures can be used as a `Matcher`.
///
/// The closure must be repeatably callable in case that the matcher is combined with another matcher.
impl<T, F> Matcher<T> for F
where F: Fn(T) -> MatchResult {
    fn check(&self, actual: T) -> MatchResult {
        self(actual)
    }
}

/// The return type of any `Machter`
pub enum MatchResult {
    /// Indicates that the `Matcher` matched the value under inspection.
    Matched {
        /// The `name` of the `Matcher`
        name: String
    },
    /// Indicates that the `Matcher` failed to match the value under inspection.
    Failed {
        /// The `name` of the `Matcher`
        name: String,
        /// The `reason` why the `Matcher` failed
        reason: String
    }
}

/// A builder for creating `MatchResult`s.
///
/// Create a new builder with `new()` or `for_()`
/// and finalize it either with `matched()`, `failed_because()`, or `failed_comparison()`.
pub struct MatchResultBuilder {
    matcher_name: String
}

impl MatchResultBuilder {
    /// Creates a `MatchResultBuilder` for an anonymous `Matcher`.
    pub fn new() -> MatchResultBuilder {
        MatchResultBuilder {
            matcher_name: "_unknown_".to_owned()
        }
    }

    /// Creates `MatchResultBuilder` for a `Matcher` with the given `name`
    pub fn for_(name: &str) -> MatchResultBuilder {
        MatchResultBuilder {
            matcher_name: name.to_owned()
        }
    }

    /// Finalzes the builder indicating that the `Matcher` matched the inspected value.
    pub fn matched(self) -> MatchResult {
        MatchResult::Matched { name: self.matcher_name }
    }

    /// Finalzes the builder indicating that the `Matcher` failed to the inspected value.
    ///
    /// The `reason` should give a short indication why the matcher failed.
    pub fn failed_because(self, reason: &str) -> MatchResult {
        MatchResult::Failed {
            name: self.matcher_name,
            reason: format!("  Because: {}", reason)
        }
    }

    /// Finalzes the builder indicating that the `Matcher` failed to the inspected value.
    ///
    /// The `actual` and `expected` value are used the generate a useful error message.
    pub fn failed_comparison<T: Debug>(self, actual: &T, expected: &T) -> MatchResult {
        MatchResult::Failed {
            name: self.matcher_name,
            reason: format!("  Expected: {:?}\n  Got: {:?}", expected, actual)
        }
    }
}

pub mod matchers;
<|endoftext|>


<commit_before>/*!
Simple persistent generic HashMap/Key-value store, using file locking to limit
writing between threads.

This is in a beta state at the moment.

Basic usage:

```
use typedb::{ KV, Value };

fn main() {
    let mut test_store = KV::<String, Value>::new("./basic.cab").unwrap();

    let _ = test_store.insert("key".to_string(), Value::String("value".to_string()));
    println!("{:?}", test_store.get(&"key".to_string()));
    let _ = test_store.remove(&"key".to_string());
}
```

Usage with user defined Key and Value types:

```
use typedb::{KV, key, value};
use serde_derive::{ Serialize, Deserialize };

key!(
enum MyKey {
    String(String),
    Int(i32),
});

value!(
enum MyValue {
    String(String),
    Int(i32),
});

fn main() {
    let mut test_store = KV::<MyKey, MyValue>::new("./types.cab").unwrap();

    let _ = test_store.insert(MyKey::Int(1i32), MyValue::String("value".to_string()));
    println!("{:?}", test_store.get(&MyKey::Int(1i32)));
    let _ = test_store.remove(&MyKey::Int(1i32));
}
```

*/

#![deny(missing_docs)]

extern crate bincode;
#[macro_use]
extern crate log;
extern crate persy;
extern crate serde;
#[macro_use]
extern crate serde_derive;

/// Macros for simplifying custom key and value types definition
pub mod macros;

use std::collections::HashMap;
use std::hash::Hash;

use bincode::{deserialize, serialize};
use serde::de::Deserialize;
use serde::ser::Serialize;

use persy::{Config, PRes, Persy, PersyError};

/// A default value type to use with KV
#[derive(Clone, Serialize, Deserialize, PartialEq, Debug)]
pub enum Value {
    /// Cab default Value type for strings
    String(String),
    /// Cab default Value type for intergers
    Int(i32),
    /// Cab default Value type for floats
    Float(f32),
    /// Cab default Value type for a sub map
    Map(HashMap<String, Value>),
    /// Cab default Value type for list
    List(Vec<Value>),
}

/// Type alias for results from KV
type KVResult = PRes<bool>;

/// Type alias for PersyError
type KVError = PersyError;

const SEGMENT_NAME: &str = "tdb";

/// The type that represents the key-value store
pub struct KV<K, V> {
    cab: HashMap<K, V>,
    persy: Persy,
    id: Option<persy::PersyId>,
}

impl<K, V> KV<K, V>
where
    K: Clone + Serialize + for<'kde> Deserialize<'kde> + Eq + Hash,
    V: Clone + Serialize + for<'vde> Deserialize<'vde>,
{
    /// Creates a new instance of the KV store
    pub fn new(p: &'static str) -> Result<KV<K, V>, PersyError> {
        // create the KV instance
        match Persy::create(p) {
            Ok(o) => o,
            Err(PersyError::IO(ref e)) if e == "File exists (os error 17)" => (),
            Err(e) => return Err(e),
        }
        let persy = Persy::open(p, Config::new())?;

        // if the segment doesn't exist create
        if !persy.exists_segment(SEGMENT_NAME)? {
            let mut tx = persy.begin()?;
            persy.create_segment(&mut tx, SEGMENT_NAME)?;
            let prepared = persy.prepare_commit(tx)?;
            persy.commit(prepared)?;
        }

        let mut store = KV {
            cab: HashMap::new(),
            persy,
            id: None,
        };

        store.load_from_persist()?;

        Ok(store)
    }

    /// Inserta a key, value pair into the key-value store
    pub fn insert(&mut self, key: K, value: V) -> KVResult {
        // make sure mem version up to date
        self.load_from_persist()?;
        // insert into the HashMap
        self.cab.insert(key, value);
        // persist
        self.write_to_persist()
    }

    /// Get the value from a key
    pub fn get(&mut self, key: &K) -> Result<Option<V>, KVError> {
        // make sure mem version up to date
        self.load_from_persist()?;
        // get the value from the cab
        Ok(self.cab.get(&key).map(|v| (*v).clone()))
    }

    /// Removes a key and associated value from the key-value Store
    pub fn remove(&mut self, key: &K) -> KVResult {
        // make sure mem version up to date
        self.load_from_persist()?;
        // remove from the HashMap
        self.cab.remove(&key);
        // persist
        self.write_to_persist()
    }

    /// get all the keys contained in the KV Store
    pub fn keys(&mut self) -> Result<Vec<K>, KVError> {
        // make sure mem version up to date
        self.load_from_persist()?;
        // create a vec from the cabs keys
        Ok(self.cab.keys().cloned().collect())
    }

    /// Writes the key-value Store to file
    fn write_to_persist(&mut self) -> KVResult {
        // attempt to write to the cab
        let mut tx = self.persy.begin()?;

        // serialize the cab as a u8 vec
        let byte_vec: Vec<u8> = match serialize(&self.cab) {
            Ok(bv) => bv,
            Err(e) => {
                error!("serialize: {}", e);
                return Err(PersyError::Err("Couldn't encode".to_string()));
            }
        };

        match &self.id {
            Some(ref x) => self.persy.update_record(&mut tx, SEGMENT_NAME, x, &byte_vec)?,
            None => self.id = Some(self.persy.insert_record(&mut tx, SEGMENT_NAME, &byte_vec)?),
        }

        let prepared = self.persy.prepare_commit(tx)?;
        self.persy.commit(prepared)?;

        Ok(true)
    }

    /// Loads key-value store from file
    fn load_from_persist(&mut self) -> KVResult {
        if self.persy.exists_segment(SEGMENT_NAME)? {
            let deserbv = |byte_vec: &Vec<u8>| {
                // deserialize u8 vec back into HashMap
                match deserialize(byte_vec.as_slice()) {
                    Ok(f) => {
                        // assign read HashMap back to self
                        Ok(f)
                    }
                    Err(e) => {
                        error!("{}", e);
                        Err(PersyError::Err("Couldn't decode cab".to_string()))
                    }
                }
            };
            if let Some(ref x) = &self.id {
                if let Some(byte_vec) = self.persy.read_record(SEGMENT_NAME, x)? {
                    self.cab = deserbv(&byte_vec)?;
                    return Ok(true);
                }
            }
            for (id, byte_vec) in self.persy.scan(SEGMENT_NAME)? {
                self.cab = deserbv(&byte_vec)?;
                self.id = Some(id);
            }
        }

        Ok(true)
    }
}
<commit_msg>only load once<commit_after>/*!
Simple persistent generic HashMap/Key-value store, using file locking to limit
writing between threads.

This is in a beta state at the moment.

Basic usage:

```
use typedb::{ KV, Value };

fn main() {
    let mut test_store = KV::<String, Value>::new("./basic.cab").unwrap();

    let _ = test_store.insert("key".to_string(), Value::String("value".to_string()));
    println!("{:?}", test_store.get(&"key".to_string()));
    let _ = test_store.remove(&"key".to_string());
}
```

Usage with user defined Key and Value types:

```
use typedb::{KV, key, value};
use serde_derive::{ Serialize, Deserialize };

key!(
enum MyKey {
    String(String),
    Int(i32),
});

value!(
enum MyValue {
    String(String),
    Int(i32),
});

fn main() {
    let mut test_store = KV::<MyKey, MyValue>::new("./types.cab").unwrap();

    let _ = test_store.insert(MyKey::Int(1i32), MyValue::String("value".to_string()));
    println!("{:?}", test_store.get(&MyKey::Int(1i32)));
    let _ = test_store.remove(&MyKey::Int(1i32));
}
```

*/

#![deny(missing_docs)]

extern crate bincode;
#[macro_use]
extern crate log;
extern crate persy;
extern crate serde;
#[macro_use]
extern crate serde_derive;

/// Macros for simplifying custom key and value types definition
pub mod macros;

use std::collections::HashMap;
use std::hash::Hash;

use bincode::{deserialize, serialize};
use serde::de::Deserialize;
use serde::ser::Serialize;

use persy::{Config, PRes, Persy, PersyError};

/// A default value type to use with KV
#[derive(Clone, Serialize, Deserialize, PartialEq, Debug)]
pub enum Value {
    /// Cab default Value type for strings
    String(String),
    /// Cab default Value type for intergers
    Int(i32),
    /// Cab default Value type for floats
    Float(f32),
    /// Cab default Value type for a sub map
    Map(HashMap<String, Value>),
    /// Cab default Value type for list
    List(Vec<Value>),
}

/// Type alias for results from KV
type KVResult = PRes<bool>;

/// Type alias for PersyError
type KVError = PersyError;

const SEGMENT_NAME: &str = "tdb";

/// The type that represents the key-value store
pub struct KV<K, V> {
    cab: HashMap<K, V>,
    persy: Persy,
    id: Option<persy::PersyId>,
}

impl<K, V> KV<K, V>
where
    K: Clone + Serialize + for<'kde> Deserialize<'kde> + Eq + Hash,
    V: Clone + Serialize + for<'vde> Deserialize<'vde>,
{
    /// Creates a new instance of the KV store
    pub fn new(p: &'static str) -> Result<KV<K, V>, PersyError> {
        // create the KV instance
        match Persy::create(p) {
            Ok(o) => o,
            Err(PersyError::IO(ref e)) if e == "File exists (os error 17)" => (),
            Err(e) => return Err(e),
        }
        let persy = Persy::open(p, Config::new())?;

        // if the segment doesn't exist create
        if !persy.exists_segment(SEGMENT_NAME)? {
            let mut tx = persy.begin()?;
            persy.create_segment(&mut tx, SEGMENT_NAME)?;
            let prepared = persy.prepare_commit(tx)?;
            persy.commit(prepared)?;
        }

        let mut store = KV {
            cab: HashMap::new(),
            persy,
            id: None,
        };

        store.load_from_persist()?;

        Ok(store)
    }

    /// Inserta a key, value pair into the key-value store
    pub fn insert(&mut self, key: K, value: V) -> KVResult {
        // insert into the HashMap
        self.cab.insert(key, value);
        // persist
        self.write_to_persist()
    }

    /// Get the value from a key
    pub fn get(&mut self, key: &K) -> Result<Option<V>, KVError> {
        // get the value from the cab
        Ok(self.cab.get(&key).map(|v| (*v).clone()))
    }

    /// Removes a key and associated value from the key-value Store
    pub fn remove(&mut self, key: &K) -> KVResult {
        // remove from the HashMap
        self.cab.remove(&key);
        // persist
        self.write_to_persist()
    }

    /// get all the keys contained in the KV Store
    pub fn keys(&mut self) -> Result<Vec<K>, KVError> {
        // create a vec from the cabs keys
        Ok(self.cab.keys().cloned().collect())
    }

    /// Writes the key-value Store to file
    fn write_to_persist(&mut self) -> KVResult {
        // attempt to write to the cab
        let mut tx = self.persy.begin()?;

        // serialize the cab as a u8 vec
        let byte_vec: Vec<u8> = match serialize(&self.cab) {
            Ok(bv) => bv,
            Err(e) => {
                error!("serialize: {}", e);
                return Err(PersyError::Err("Couldn't encode".to_string()));
            }
        };

        match &self.id {
            Some(ref x) => self.persy.update_record(&mut tx, SEGMENT_NAME, x, &byte_vec)?,
            None => self.id = Some(self.persy.insert_record(&mut tx, SEGMENT_NAME, &byte_vec)?),
        }

        let prepared = self.persy.prepare_commit(tx)?;
        self.persy.commit(prepared)?;

        Ok(true)
    }

    /// Loads key-value store from file
    fn load_from_persist(&mut self) -> KVResult {
        if self.persy.exists_segment(SEGMENT_NAME)? {
            let deserbv = |byte_vec: &Vec<u8>| {
                // deserialize u8 vec back into HashMap
                match deserialize(byte_vec.as_slice()) {
                    Ok(f) => {
                        // assign read HashMap back to self
                        Ok(f)
                    }
                    Err(e) => {
                        error!("{}", e);
                        Err(PersyError::Err("Couldn't decode cab".to_string()))
                    }
                }
            };
            if let Some(ref x) = &self.id {
                if let Some(byte_vec) = self.persy.read_record(SEGMENT_NAME, x)? {
                    self.cab = deserbv(&byte_vec)?;
                    return Ok(true);
                }
            }
            for (id, byte_vec) in self.persy.scan(SEGMENT_NAME)? {
                self.cab = deserbv(&byte_vec)?;
                self.id = Some(id);
            }
        }

        Ok(true)
    }
}
<|endoftext|>


<commit_before>extern crate bytes;
#[macro_use]
extern crate futures;
extern crate native_tls;
extern crate tokio_core;
extern crate tokio_io;
extern crate tokio_tls;
extern crate tokio_proto;

mod client;
mod proto;

pub use client::Client;
<commit_msg>Make proto module public<commit_after>extern crate bytes;
#[macro_use]
extern crate futures;
extern crate native_tls;
extern crate tokio_core;
extern crate tokio_io;
extern crate tokio_tls;
extern crate tokio_proto;

mod client;
pub mod proto;

pub use client::Client;
<|endoftext|>


<commit_before>#![deny(missing_docs,
       missing_debug_implementations, missing_copy_implementations,
       trivial_casts, trivial_numeric_casts,
       unsafe_code,
       unstable_features,
       unused_import_braces, unused_qualifications)]

//! Contains functions and structs for sending and receiving SNMP messages.
use std::net::UdpSocket;
use std::{io, time};

/// Various errors that can occur.
#[derive(Debug)]
pub enum SnmpError {
    /// The packet is too short to parse.
    PacketTooShort,
    /// The type specified in the packet is invalid.
    InvalidType,
    /// The packet could not be parsed in the wanted manner.
    ParsingError,
    /// An IO error occured when sending or receiving the packets.
    Io(io::Error),
}

impl From<io::Error> for SnmpError {
    fn from(error: io::Error) -> Self {
        SnmpError::Io(error)
    }
}

/// Contains functions and structs for sending and receiving SNMPv1 messages.
pub mod snmpv1 {
    use super::*;

    /// Contains a SNMP response and some extracted metadata from it.
    #[derive(Debug)]
    pub struct Message {
        packet: Vec<u8>,
        datatype: MessageDataType,
        datalength: usize,
        datastart: usize,
    }

    /// Enum describing the various SNMP datatypes.
    #[derive(Debug, Clone, Copy)]
    pub enum MessageDataType {
        /// An integer.
        SnmpInteger,
        /// An octet string.
        SnmpString,
        /// Null.
        SnmpNull,
        /// Another object ID.
        SnmpObjectID,
        /// A sequence of some sort
        SnmpSequence,
    }

    /// Holds a SNMPv1 packet, and has some handy functions for parsing the contents.
    impl Message {
        fn from_packet(packet: &[u8]) -> Result<Self, SnmpError> {
            if packet.len() < 26 {
                return Err(SnmpError::PacketTooShort);
            };

            let commlength = packet[6] as usize;
            if packet.len() < 25 + commlength {
                return Err(SnmpError::PacketTooShort);
            };

            let miblength = packet[23 + commlength] as usize;
            if packet.len() < 25 + commlength + miblength {
                return Err(SnmpError::PacketTooShort);
            };

            let datatype = packet[24 + commlength + miblength];
            let datalength = packet[25 + commlength + miblength] as usize;
            let datastart = 26 + commlength + miblength;
            if packet.len() < 26 + commlength + miblength + datalength {
                return Err(SnmpError::PacketTooShort);
            };

            let datatype = match datatype {
                0x02 => MessageDataType::SnmpInteger,
                0x04 => MessageDataType::SnmpString,
                0x05 => MessageDataType::SnmpNull,
                0x06 => MessageDataType::SnmpObjectID,
                0x30 => MessageDataType::SnmpSequence,
                _ => return Err(SnmpError::InvalidType),
            };

            Ok(Message {
                packet: packet.to_vec(),
                datatype: datatype,
                datalength: datalength,
                datastart: datastart,
            })
        }

        /// Returns the full packet received.
        pub fn packet(&self) -> &[u8] {
            &self.packet
        }

        /// Returns the data part of the packet.
        pub fn data(&self) -> &[u8] {
            &self.packet[self.datastart..self.datalength]
        }

        /// Parses the data of the packet as a utf8 string.
        pub fn as_string(&self) -> Result<String, SnmpError> {
            match String::from_utf8(self.packet[self.datastart..(self.datastart +
                                                                    self.datalength)]
                .to_vec()) {
                Ok(s) => Ok(s),
                Err(_) => Err(SnmpError::ParsingError),
            }
        }

        /// If the message is a SnmpInteger, parses it and returns the number.
        pub fn as_int(&self) -> Result<i32, SnmpError> {
            match self.datatype {
                MessageDataType::SnmpInteger => {
                    // The value may by a multi-byte integer, so each byte
                    // may have to be shifted to the higher byte order.
                    let mut value: i32 = 0;
                    for i in self.datalength..0 {
                        value = (value * 128) +
                                self.packet[self.datastart + self.datalength - i] as i32;
                    }
                    Ok(value)
                }
                _ => Err(SnmpError::InvalidType),
            }
        }
    }

    /// Sends a SMTPv1 message end returns the reply or an error specifiying what went wrong.
    ///
    /// #Examples
    /// ```
    /// let answer = rust_snmp::snmpv1::smtpv1_send("demo.snmplabs.com:161",
    ///                                           "public",
    ///                                           &[1, 3, 6, 1, 2, 1, 1, 5, 0])
    ///     .unwrap();
    /// let answer = answer.as_string().unwrap();
    /// assert_eq!("monkey5000", answer);
    /// ```
    pub fn smtpv1_send(addr: &str,
                        community: &str,
                        mibvals: &[u16])
                        -> Result<Message, SnmpError> {
        let socket = UdpSocket::bind("0.0.0.0:0")?;
        socket.set_read_timeout(Some(time::Duration::from_millis(1000)))?;
        send(addr, mibvals, community, &socket)?;
        let mut packet: [u8; 1024] = [0; 1024];
        let length = receive(&socket, &mut packet)?;
        let packet = Message::from_packet(&packet[0..length])?;
        Ok(packet)
    }

    fn receive(socket: &UdpSocket, mut buffer: &mut [u8]) -> Result<usize, SnmpError> {
        let (amount, _) = socket.recv_from(&mut buffer)?;
        Ok(amount)
    }

    fn send(addr: &str,
            mibvals: &[u16],
            community: &str,
            socket: &UdpSocket)
            -> Result<usize, io::Error> {
        let mut buf: [u8; 1024] = [0; 1024];
        let mut mib: [u8; 1024] = [0; 1024];
        let orgmiblen = mibvals.len();
        let mut miblen = orgmiblen;

        let mut counter = 0;
        for mibval in mibvals.iter() {
            if mibval > &127u16 {
                mib[counter] = (128 + (mibval / 128)) as u8;
                mib[counter + 1] = (mibval - (mibval - ((mibval / 128) * 128))) as u8;
                counter += 2;
                miblen += 1;
            } else {
                mib[counter] = *mibval as u8;
                counter += 1;
            }
        }
        let mib = &mib[0..miblen];
        let miblen = miblen;
        let snmplen = 29 + community.len() + miblen - 1;

        // SNMP sequence start
        buf[0] = 0x30;
        buf[1] = (snmplen - 2) as u8;

        buf[2] = 0x02; // Integer
        buf[3] = 0x01; // Length
        buf[4] = 0x00; // SNMP version

        // Community
        buf[5] = 0x04;
        buf[6] = community.len() as u8;
        let mut offset = 7;
        for byte in community.as_bytes() {
            buf[offset] = *byte;
            offset += 1;
        }

        buf[offset] = 0xA0; // GET
        buf[offset + 1] = 19 + miblen as u8; // MIB size

        buf[offset + 2] = 0x02; // Integer type
        buf[offset + 3] = 0x04; // Length
        buf[offset + 4] = 0x00; // SNMP Request ID
        buf[offset + 5] = 0x00;
        buf[offset + 6] = 0x00;
        buf[offset + 7] = 0x01;

        buf[offset + 8] = 0x02; // Integer
        buf[offset + 9] = 0x01; // Length
        buf[offset + 10] = 0x00; // SNMP error status

        buf[offset + 11] = 0x02; // Integer
        buf[offset + 12] = 0x01; // Length
        buf[offset + 13] = 0x00; // SNMP error index

        // Variable binding
        buf[offset + 14] = 0x30;               // Start of sequence
        buf[offset + 15] = (5 + miblen) as u8; // Size
        buf[offset + 16] = 0x30;               // Start of sequence
        buf[offset + 17] = (3 + miblen) as u8; // Size
        buf[offset + 18] = 0x06;               // Object type
        buf[offset + 19] = (miblen - 1) as u8; // Size

        // MIB
        buf[offset + 20] = 0x2b;
        offset += 21;
        for index in mib.iter().skip(2) {
            buf[offset] = *index;
            offset += 1;
        }

        buf[offset] = 0x05; // Null object
        buf[offset + 1] = 0x00; // Null

        socket.send_to(&buf[0..offset + 2], addr)
    }
}
<commit_msg>Start work on snmpv3 module<commit_after>#![deny(missing_docs,
       missing_debug_implementations, missing_copy_implementations,
       trivial_casts, trivial_numeric_casts,
       unsafe_code,
       unstable_features,
       unused_import_braces, unused_qualifications)]

//! Contains functions and structs for sending and receiving SNMP messages.
use std::net::UdpSocket;
use std::{io, time};

/// Various errors that can occur.
#[derive(Debug)]
pub enum SnmpError {
    /// The packet is too short to parse.
    PacketTooShort,
    /// The type specified in the packet is invalid.
    InvalidType,
    /// The packet could not be parsed in the wanted manner.
    ParsingError,
    /// An IO error occured when sending or receiving the packets.
    Io(io::Error),
}

impl From<io::Error> for SnmpError {
    fn from(error: io::Error) -> Self {
        SnmpError::Io(error)
    }
}

/// Contains functions and structs for sending and receiving SNMPv3 messages.
pub mod snmpv3 {
    use super::*;

    /// Sends a SMTPv3 message and returns the reply or an error specifiying what went wrong.
    ///
    /// #Examples
    /// ```
    /// rust_snmp::snmpv3::smtpv3_send("demo.snmplabs.com:161",
    ///                                           "public",
    ///                                           &[1, 3, 6, 1, 2, 1, 1, 5, 0]);
    /// ```
    pub fn smtpv3_send(addr: &str,
                       community: &str,
                       mibvals: &[u16]) {
        let mut buf: [u8; 1024] = [0; 1024];
        let mut mib: [u8; 1024] = [0; 1024];
        let orgmiblen = mibvals.len();
        let mut miblen = orgmiblen;

        let mut counter = 0;
        for mibval in mibvals.iter() {
            if mibval > &127u16 {
                mib[counter] = (128 + (mibval / 128)) as u8;
                mib[counter + 1] = (mibval - (mibval - ((mibval / 128) * 128))) as u8;
                counter += 2;
                miblen += 1;
            } else {
                mib[counter] = *mibval as u8;
                counter += 1;
            }
        }
        let mib = &mib[0..miblen];
        let miblen = miblen;
        let snmplen = 29 + community.len() + miblen - 1;

        // SNMP sequence start
        buf[0] = 0x30;
        buf[1] = (snmplen - 2) as u8;

        buf[2] = 0x02; // Integer
        buf[3] = 0x01; // Length
        buf[4] = 0x03; // SNMP version

        buf[5] = 0x02; // Integer type
        buf[6] = 0x04; // Length
        buf[7] = 0x00; // SNMP Request ID

        buf[5] = 0x02; // Integer type
        buf[6] = 0x08; // Length
        buf[7] = 0x04; // Message Max Size
        buf[8] = 0x00;
    }
}

/// Contains functions and structs for sending and receiving SNMPv1 messages.
pub mod snmpv1 {
    use super::*;

    /// Contains a SNMP response and some extracted metadata from it.
    #[derive(Debug)]
    pub struct Message {
        packet: Vec<u8>,
        datatype: MessageDataType,
        datalength: usize,
        datastart: usize,
    }

    /// Enum describing the various SNMP datatypes.
    #[derive(Debug, Clone, Copy)]
    pub enum MessageDataType {
        /// An integer.
        SnmpInteger,
        /// An octet string.
        SnmpString,
        /// Null.
        SnmpNull,
        /// Another object ID.
        SnmpObjectID,
        /// A sequence of some sort
        SnmpSequence,
    }

    /// Holds a SNMPv1 packet, and has some handy functions for parsing the contents.
    impl Message {
        fn from_packet(packet: &[u8]) -> Result<Self, SnmpError> {
            if packet.len() < 26 {
                return Err(SnmpError::PacketTooShort);
            };

            let commlength = packet[6] as usize;
            if packet.len() < 25 + commlength {
                return Err(SnmpError::PacketTooShort);
            };

            let miblength = packet[23 + commlength] as usize;
            if packet.len() < 25 + commlength + miblength {
                return Err(SnmpError::PacketTooShort);
            };

            let datatype = packet[24 + commlength + miblength];
            let datalength = packet[25 + commlength + miblength] as usize;
            let datastart = 26 + commlength + miblength;
            if packet.len() < 26 + commlength + miblength + datalength {
                return Err(SnmpError::PacketTooShort);
            };

            let datatype = match datatype {
                0x02 => MessageDataType::SnmpInteger,
                0x04 => MessageDataType::SnmpString,
                0x05 => MessageDataType::SnmpNull,
                0x06 => MessageDataType::SnmpObjectID,
                0x30 => MessageDataType::SnmpSequence,
                _ => return Err(SnmpError::InvalidType),
            };

            Ok(Message {
                packet: packet.to_vec(),
                datatype: datatype,
                datalength: datalength,
                datastart: datastart,
            })
        }

        /// Returns the full packet received.
        pub fn packet(&self) -> &[u8] {
            &self.packet
        }

        /// Returns the data part of the packet.
        pub fn data(&self) -> &[u8] {
            &self.packet[self.datastart..self.datalength]
        }

        /// Parses the data of the packet as a utf8 string.
        pub fn as_string(&self) -> Result<String, SnmpError> {
            match String::from_utf8(self.packet[self.datastart..(self.datastart +
                                                                    self.datalength)]
                .to_vec()) {
                Ok(s) => Ok(s),
                Err(_) => Err(SnmpError::ParsingError),
            }
        }

        /// If the message is a SnmpInteger, parses it and returns the number.
        pub fn as_int(&self) -> Result<i32, SnmpError> {
            match self.datatype {
                MessageDataType::SnmpInteger => {
                    // The value may by a multi-byte integer, so each byte
                    // may have to be shifted to the higher byte order.
                    let mut value: i32 = 0;
                    for i in self.datalength..0 {
                        value = (value * 128) +
                                self.packet[self.datastart + self.datalength - i] as i32;
                    }
                    Ok(value)
                }
                _ => Err(SnmpError::InvalidType),
            }
        }
    }

    /// Sends a SMTPv1 message and returns the reply or an error specifiying what went wrong.
    ///
    /// #Examples
    /// ```
    /// let answer = rust_snmp::snmpv1::smtpv1_send("demo.snmplabs.com:161",
    ///                                           "public",
    ///                                           &[1, 3, 6, 1, 2, 1, 1, 5, 0])
    ///     .unwrap();
    /// let answer = answer.as_string().unwrap();
    /// assert_eq!("monkey5000", answer);
    /// ```
    pub fn smtpv1_send(addr: &str,
                        community: &str,
                        mibvals: &[u16])
                        -> Result<Message, SnmpError> {
        let socket = UdpSocket::bind("0.0.0.0:0")?;
        socket.set_read_timeout(Some(time::Duration::from_millis(1000)))?;
        send(addr, mibvals, community, &socket)?;
        let mut packet: [u8; 1024] = [0; 1024];
        let length = receive(&socket, &mut packet)?;
        let packet = Message::from_packet(&packet[0..length])?;
        Ok(packet)
    }

    fn receive(socket: &UdpSocket, mut buffer: &mut [u8]) -> Result<usize, SnmpError> {
        let (amount, _) = socket.recv_from(&mut buffer)?;
        Ok(amount)
    }

    fn send(addr: &str,
            mibvals: &[u16],
            community: &str,
            socket: &UdpSocket)
            -> Result<usize, io::Error> {
        let mut buf: [u8; 1024] = [0; 1024];
        let mut mib: [u8; 1024] = [0; 1024];
        let orgmiblen = mibvals.len();
        let mut miblen = orgmiblen;

        let mut counter = 0;
        for mibval in mibvals.iter() {
            if mibval > &127u16 {
                mib[counter] = (128 + (mibval / 128)) as u8;
                mib[counter + 1] = (mibval - (mibval - ((mibval / 128) * 128))) as u8;
                counter += 2;
                miblen += 1;
            } else {
                mib[counter] = *mibval as u8;
                counter += 1;
            }
        }
        let mib = &mib[0..miblen];
        let miblen = miblen;
        let snmplen = 29 + community.len() + miblen - 1;

        // SNMP sequence start
        buf[0] = 0x30;
        buf[1] = (snmplen - 2) as u8;

        buf[2] = 0x02; // Integer
        buf[3] = 0x01; // Length
        buf[4] = 0x00; // SNMP version

        // Community
        buf[5] = 0x04;
        buf[6] = community.len() as u8;
        let mut offset = 7;
        for byte in community.as_bytes() {
            buf[offset] = *byte;
            offset += 1;
        }

        buf[offset] = 0xA0; // GET
        buf[offset + 1] = 19 + miblen as u8; // MIB size

        buf[offset + 2] = 0x02; // Integer type
        buf[offset + 3] = 0x04; // Length
        buf[offset + 4] = 0x00; // SNMP Request ID
        buf[offset + 5] = 0x00;
        buf[offset + 6] = 0x00;
        buf[offset + 7] = 0x01;

        buf[offset + 8] = 0x02; // Integer
        buf[offset + 9] = 0x01; // Length
        buf[offset + 10] = 0x00; // SNMP error status

        buf[offset + 11] = 0x02; // Integer
        buf[offset + 12] = 0x01; // Length
        buf[offset + 13] = 0x00; // SNMP error index

        // Variable binding
        buf[offset + 14] = 0x30;               // Start of sequence
        buf[offset + 15] = (5 + miblen) as u8; // Size
        buf[offset + 16] = 0x30;               // Start of sequence
        buf[offset + 17] = (3 + miblen) as u8; // Size
        buf[offset + 18] = 0x06;               // Object type
        buf[offset + 19] = (miblen - 1) as u8; // Size

        // MIB
        buf[offset + 20] = 0x2b;
        offset += 21;
        for index in mib.iter().skip(2) {
            buf[offset] = *index;
            offset += 1;
        }

        buf[offset] = 0x05; // Null object
        buf[offset + 1] = 0x00; // Null

        socket.send_to(&buf[0..offset + 2], addr)
    }
}
<|endoftext|>


<commit_before>// Copyright 2016 lazy-static.rs Developers
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
// http://opensource.org/licenses/MIT>, at your option. This file may not be
// copied, modified, or distributed except according to those terms.

/*!
A macro for declaring lazily evaluated statics.

Using this macro, it is possible to have `static`s that require code to be
executed at runtime in order to be initialized.
This includes anything requiring heap allocations, like vectors or hash maps,
as well as anything that requires function calls to be computed.

# Syntax

```ignore
lazy_static! {
    [pub] static ref NAME_1: TYPE_1 = EXPR_1;
    [pub] static ref NAME_2: TYPE_2 = EXPR_2;
    ...
    [pub] static ref NAME_N: TYPE_N = EXPR_N;
}
```

Attributes (including doc comments) are supported as well:

```rust
use lazy_static::lazy_static;

# fn main() {
lazy_static! {
    /// This is an example for using doc comment attributes
    static ref EXAMPLE: u8 = 42;
}
# }
```

# Semantics

For a given `static ref NAME: TYPE = EXPR;`, the macro generates a unique type that
implements `Deref<TYPE>` and stores it in a static with name `NAME`. (Attributes end up
attaching to this type.)

On first deref, `EXPR` gets evaluated and stored internally, such that all further derefs
can return a reference to the same object. Note that this can lead to deadlocks
if you have multiple lazy statics that depend on each other in their initialization.

Apart from the lazy initialization, the resulting "static ref" variables
have generally the same properties as regular "static" variables:

- Any type in them needs to fulfill the `Sync` trait.
- If the type has a destructor, then it will not run when the process exits.

# Example

Using the macro:

```rust
use lazy_static::lazy_static;
use std::collections::HashMap;

lazy_static! {
    static ref HASHMAP: HashMap<u32, &'static str> = {
        let mut m = HashMap::new();
        m.insert(0, "foo");
        m.insert(1, "bar");
        m.insert(2, "baz");
        m
    };
    static ref COUNT: usize = HASHMAP.len();
    static ref NUMBER: u32 = times_two(21);
}

fn times_two(n: u32) -> u32 { n * 2 }

fn main() {
    println!("The map has {} entries.", *COUNT);
    println!("The entry for `0` is \"{}\".", HASHMAP.get(&0).unwrap());
    println!("A expensive calculation on a static results in: {}.", *NUMBER);
}
```

# Implementation details

The `Deref` implementation uses a hidden static variable that is guarded by an atomic check on each access.

# Cargo features

This crate provides one cargo feature:

- `spin_no_std`: This allows using this crate in a no-std environment, by depending on the standalone `spin` crate.

*/

#![doc(html_root_url = "https://docs.rs/lazy_static/1.4.0")]
#![no_std]

#[cfg(not(feature = "spin_no_std"))]
#[path="inline_lazy.rs"]
#[doc(hidden)]
pub mod lazy;

#[cfg(test)]
#[macro_use]
extern crate doc_comment;

#[cfg(test)]
doctest!("../README.md");

#[cfg(feature = "spin_no_std")]
#[path="core_lazy.rs"]
#[doc(hidden)]
pub mod lazy;

#[doc(hidden)]
pub use core::ops::Deref as __Deref;

#[macro_export(local_inner_macros)]
#[doc(hidden)]
macro_rules! __lazy_static_internal {
    // optional visibility restrictions are wrapped in `()` to allow for
    // explicitly passing otherwise implicit information about private items
    ($(#[$attr:meta])* ($($vis:tt)*) static ref $N:ident : $T:ty = $e:expr; $($t:tt)*) => {
        __lazy_static_internal!(@MAKE TY, $(#[$attr])*, ($($vis)*), $N);
        __lazy_static_internal!(@TAIL, $N : $T = $e);
        lazy_static!($($t)*);
    };
    (@TAIL, $N:ident : $T:ty = $e:expr) => {
        impl $crate::__Deref for $N {
            type Target = $T;
            fn deref(&self) -> &$T {
                #[inline(always)]
                fn __static_ref_initialize() -> $T { $e }

                #[inline(always)]
                fn __stability() -> &'static $T {
                    __lazy_static_create!(LAZY, $T);
                    LAZY.get(__static_ref_initialize)
                }
                __stability()
            }
        }
        impl $crate::LazyStatic for $N {
            fn initialize(lazy: &Self) {
                let _ = &**lazy;
            }
        }
    };
    // `vis` is wrapped in `()` to prevent parsing ambiguity
    (@MAKE TY, $(#[$attr:meta])*, ($($vis:tt)*), $N:ident) => {
        #[allow(missing_copy_implementations)]
        #[allow(non_camel_case_types)]
        #[allow(dead_code)]
        $(#[$attr])*
        $($vis)* struct $N {__private_field: ()}
        #[doc(hidden)]
        $($vis)* static $N: $N = $N {__private_field: ()};
    };
    () => ()
}

#[macro_export(local_inner_macros)]
macro_rules! lazy_static {
    ($(#[$attr:meta])* static ref $N:ident : $T:ty = $e:expr; $($t:tt)*) => {
        // use `()` to explicitly forward the information about private items
        __lazy_static_internal!($(#[$attr])* () static ref $N : $T = $e; $($t)*);
    };
    ($(#[$attr:meta])* pub static ref $N:ident : $T:ty = $e:expr; $($t:tt)*) => {
        __lazy_static_internal!($(#[$attr])* (pub) static ref $N : $T = $e; $($t)*);
    };
    ($(#[$attr:meta])* pub ($($vis:tt)+) static ref $N:ident : $T:ty = $e:expr; $($t:tt)*) => {
        __lazy_static_internal!($(#[$attr])* (pub ($($vis)+)) static ref $N : $T = $e; $($t)*);
    };
    () => ()
}

/// Support trait for enabling a few common operation on lazy static values.
///
/// This is implemented by each defined lazy static, and
/// used by the free functions in this crate.
pub trait LazyStatic {
    #[doc(hidden)]
    fn initialize(lazy: &Self);
}

/// Takes a shared reference to a lazy static and initializes
/// it if it has not been already.
///
/// This can be used to control the initialization point of a lazy static.
///
/// Example:
///
/// ```rust
/// use lazy_static::lazy_static;
///
/// lazy_static! {
///     static ref BUFFER: Vec<u8> = (0..255).collect();
/// }
///
/// fn main() {
///     lazy_static::initialize(&BUFFER);
///
///     // ...
///     work_with_initialized_data(&BUFFER);
/// }
/// # fn work_with_initialized_data(_: &[u8]) {}
/// ```
pub fn initialize<T: LazyStatic>(lazy: &T) {
    LazyStatic::initialize(lazy);
}
<commit_msg>Rustdoc is now passing "doctest" cfg and not "test" anymore<commit_after>// Copyright 2016 lazy-static.rs Developers
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
// http://opensource.org/licenses/MIT>, at your option. This file may not be
// copied, modified, or distributed except according to those terms.

/*!
A macro for declaring lazily evaluated statics.

Using this macro, it is possible to have `static`s that require code to be
executed at runtime in order to be initialized.
This includes anything requiring heap allocations, like vectors or hash maps,
as well as anything that requires function calls to be computed.

# Syntax

```ignore
lazy_static! {
    [pub] static ref NAME_1: TYPE_1 = EXPR_1;
    [pub] static ref NAME_2: TYPE_2 = EXPR_2;
    ...
    [pub] static ref NAME_N: TYPE_N = EXPR_N;
}
```

Attributes (including doc comments) are supported as well:

```rust
use lazy_static::lazy_static;

# fn main() {
lazy_static! {
    /// This is an example for using doc comment attributes
    static ref EXAMPLE: u8 = 42;
}
# }
```

# Semantics

For a given `static ref NAME: TYPE = EXPR;`, the macro generates a unique type that
implements `Deref<TYPE>` and stores it in a static with name `NAME`. (Attributes end up
attaching to this type.)

On first deref, `EXPR` gets evaluated and stored internally, such that all further derefs
can return a reference to the same object. Note that this can lead to deadlocks
if you have multiple lazy statics that depend on each other in their initialization.

Apart from the lazy initialization, the resulting "static ref" variables
have generally the same properties as regular "static" variables:

- Any type in them needs to fulfill the `Sync` trait.
- If the type has a destructor, then it will not run when the process exits.

# Example

Using the macro:

```rust
use lazy_static::lazy_static;
use std::collections::HashMap;

lazy_static! {
    static ref HASHMAP: HashMap<u32, &'static str> = {
        let mut m = HashMap::new();
        m.insert(0, "foo");
        m.insert(1, "bar");
        m.insert(2, "baz");
        m
    };
    static ref COUNT: usize = HASHMAP.len();
    static ref NUMBER: u32 = times_two(21);
}

fn times_two(n: u32) -> u32 { n * 2 }

fn main() {
    println!("The map has {} entries.", *COUNT);
    println!("The entry for `0` is \"{}\".", HASHMAP.get(&0).unwrap());
    println!("A expensive calculation on a static results in: {}.", *NUMBER);
}
```

# Implementation details

The `Deref` implementation uses a hidden static variable that is guarded by an atomic check on each access.

# Cargo features

This crate provides one cargo feature:

- `spin_no_std`: This allows using this crate in a no-std environment, by depending on the standalone `spin` crate.

*/

#![doc(html_root_url = "https://docs.rs/lazy_static/1.4.0")]
#![no_std]

#[cfg(not(feature = "spin_no_std"))]
#[path="inline_lazy.rs"]
#[doc(hidden)]
pub mod lazy;

#[cfg(doctest)]
#[macro_use]
extern crate doc_comment;

#[cfg(doctest)]
doctest!("../README.md");

#[cfg(feature = "spin_no_std")]
#[path="core_lazy.rs"]
#[doc(hidden)]
pub mod lazy;

#[doc(hidden)]
pub use core::ops::Deref as __Deref;

#[macro_export(local_inner_macros)]
#[doc(hidden)]
macro_rules! __lazy_static_internal {
    // optional visibility restrictions are wrapped in `()` to allow for
    // explicitly passing otherwise implicit information about private items
    ($(#[$attr:meta])* ($($vis:tt)*) static ref $N:ident : $T:ty = $e:expr; $($t:tt)*) => {
        __lazy_static_internal!(@MAKE TY, $(#[$attr])*, ($($vis)*), $N);
        __lazy_static_internal!(@TAIL, $N : $T = $e);
        lazy_static!($($t)*);
    };
    (@TAIL, $N:ident : $T:ty = $e:expr) => {
        impl $crate::__Deref for $N {
            type Target = $T;
            fn deref(&self) -> &$T {
                #[inline(always)]
                fn __static_ref_initialize() -> $T { $e }

                #[inline(always)]
                fn __stability() -> &'static $T {
                    __lazy_static_create!(LAZY, $T);
                    LAZY.get(__static_ref_initialize)
                }
                __stability()
            }
        }
        impl $crate::LazyStatic for $N {
            fn initialize(lazy: &Self) {
                let _ = &**lazy;
            }
        }
    };
    // `vis` is wrapped in `()` to prevent parsing ambiguity
    (@MAKE TY, $(#[$attr:meta])*, ($($vis:tt)*), $N:ident) => {
        #[allow(missing_copy_implementations)]
        #[allow(non_camel_case_types)]
        #[allow(dead_code)]
        $(#[$attr])*
        $($vis)* struct $N {__private_field: ()}
        #[doc(hidden)]
        $($vis)* static $N: $N = $N {__private_field: ()};
    };
    () => ()
}

#[macro_export(local_inner_macros)]
macro_rules! lazy_static {
    ($(#[$attr:meta])* static ref $N:ident : $T:ty = $e:expr; $($t:tt)*) => {
        // use `()` to explicitly forward the information about private items
        __lazy_static_internal!($(#[$attr])* () static ref $N : $T = $e; $($t)*);
    };
    ($(#[$attr:meta])* pub static ref $N:ident : $T:ty = $e:expr; $($t:tt)*) => {
        __lazy_static_internal!($(#[$attr])* (pub) static ref $N : $T = $e; $($t)*);
    };
    ($(#[$attr:meta])* pub ($($vis:tt)+) static ref $N:ident : $T:ty = $e:expr; $($t:tt)*) => {
        __lazy_static_internal!($(#[$attr])* (pub ($($vis)+)) static ref $N : $T = $e; $($t)*);
    };
    () => ()
}

/// Support trait for enabling a few common operation on lazy static values.
///
/// This is implemented by each defined lazy static, and
/// used by the free functions in this crate.
pub trait LazyStatic {
    #[doc(hidden)]
    fn initialize(lazy: &Self);
}

/// Takes a shared reference to a lazy static and initializes
/// it if it has not been already.
///
/// This can be used to control the initialization point of a lazy static.
///
/// Example:
///
/// ```rust
/// use lazy_static::lazy_static;
///
/// lazy_static! {
///     static ref BUFFER: Vec<u8> = (0..255).collect();
/// }
///
/// fn main() {
///     lazy_static::initialize(&BUFFER);
///
///     // ...
///     work_with_initialized_data(&BUFFER);
/// }
/// # fn work_with_initialized_data(_: &[u8]) {}
/// ```
pub fn initialize<T: LazyStatic>(lazy: &T) {
    LazyStatic::initialize(lazy);
}
<|endoftext|>


<commit_before>//! # FFI bindings to **libpmem**
//!
//! Rust bindings for the NVM Library [http://pmem.io](http://pmem.io)
//!
//! The **pmem** library provides low level persistent memory support.
//! The libraries above are implemented using **pmem**.
//! Developers wishing to roll their own persistent memory algorithms will find this library useful,
//! but most developers will likely use **pmem-obj** and let that library call **pmem** for them.
//!
//! > This is **not** an official port of the NVM Library.
//! >
//! > The official **libpmem** documentation can be found at: [http://pmem.io/nvml/libpmem/](http://pmem.io/nvml/libpmem/)

#[macro_use]
extern crate bitflags;
extern crate pmem_sys;
extern crate libc;

// Modules

pub mod persistentmap;
pub mod ptr;
pub mod nodrain;

// lib module

use ::std::mem;
use ::std::io;
use ::std::ffi::CStr;

use ::libc::c_void;
use ::libc::size_t;
use ::pmem_sys as ffi;

/// Description of the last error
///
/// The error message is thread-local; errors encountered in one thread do not affect its value in other threads.
/// Its content is significant only when the return value of the immediately preceding
/// call to a function indicated an error.
pub fn errormsg() -> Option<String> {
    unsafe {
        let reason_p = ffi::pmem_errormsg();
        if !reason_p.is_null() {
            CStr::from_ptr(reason_p).to_owned().into_string().ok()
        } else {
            None
        }
    }
}

/// Checks if an entire object consists of persistent memory
/// If `true` then it is safe to use `persist(1)` and other related functions to make changes durable for that memory range.
///
/// The implementation of `is_pmem(1)` requires a non-trivial amount of work to determine if the given range is
/// entirely persistent memory. For this reason, it is better to call `is_pmem(1)` once when a range of memory is first encountered,
/// save the result, and use the saved result to determine whether `persist()` or `msync(1)` is appropriate for flushing changes to persistence.
/// Calling `is_pmem(1)` each time changes are flushed to persistence will not perform well.
///
/// > **Warning:** Using `persist(1)` on a range where `is_pmem(1)` returns `false` may not do anything useful -- use `msync(1)` instead.
pub fn is_pmem<T>(x: &T) -> bool {
    let len = mem::size_of_val(x);
    let r = unsafe { ffi::pmem_is_pmem(x as *const _ as *const c_void, len as size_t) };
    r > 0
}

/// Force an object to be stored durably in persistent memory.
///
/// This is equivalent to calling `msync(1)` but may be more optimal
/// and will avoid calling into the kernel if possible.
/// There are no alignment restrictions on the range the object is in,
/// but `persist(1)` may expand the range as necessary to meet platform alignment requirements.
///
/// > **Warning:** Like `msync()`, there is nothing atomic or transactional about this call.
/// > Any unwritten stores in the given range will be written, but some stores may have already been written
/// > by virtue of normal cache eviction/replacement policies. Correctly written code must not depend on stores
/// > waiting until `persist(1)` is called to become persistent -- they can become persistent at
/// > any time before `persist(1)` is called.
///
/// To create your own variations of `persist(1)`, see `flush(1)` and `drain()`. One can think of `persist(1)` as:
///
/// ```no_run
/// fn persist<T>(x: &T) {
///     // flush the processor caches
///     pmem::flush(x);
///
///     // wait for any pmem stores to drain from HW buffers
///     pmem::drain();
/// }
/// ```
pub fn persist<T>(x: &T) {
    let len = mem::size_of_val(x);
    unsafe { ffi::pmem_persist(x as *const _ as *const c_void, len as size_t) };
}

/// Forces any changes in an object to be stored durably.
///
/// This function works on either persistent memory or a memory mapped file on traditional storage.
/// `msync()` takes steps to ensure the alignment of addresses and lengths passed down meet the requirements of that system call.
/// It calls msync() with the MS_SYNC flag as described in msync(2).
/// Typically the application only checks for the existence of persistent memory once,
/// and then uses that result throughout the program, for example:
///
/// # Example
///
/// ```no_run
/// fn some_method<T>(x: &T) {
///     // do this call once, after the pmem is memory mapped
///     let is_pmem = pmem::is_pmem(x);
///
///     // ...make some changes to x
///
///     // make the changes durable
///     if is_pmem {
///         pmem::persist(&x);
///     } else{
///         pmem::msync(&x).unwrap();
///     }
/// }
/// ```
pub fn msync<T>(x: &T) -> Result<(), io::Error> {
    let len = mem::size_of_val(x);
    let r = unsafe { ffi::pmem_msync(x as *const _ as *const c_void, len as size_t) };
    if r == -1 {
        Err(io::Error::last_os_error())
    } else {
        Ok(())
    }
}

/// Flushes the processor caches
///
/// This is the first of two steps in flushing to persistence,
/// the second stpe is `drain()`.
///
/// These steps are performed together when `persist()` is called.
///
/// > Note that either of these steps may be unnecessary on a given platform, and
/// > the library knows how to check for that and do the right thing.
/// > For example, on Intel platforms, pmem_drain() is an empty function.
pub fn flush<T>(x: &T) {
    let len = mem::size_of_val(x);
    unsafe { ffi::pmem_flush(x as *const _ as *const c_void, len as size_t) };
}

/// Waits for any pmem stores to drain from HW buffers
///
/// This is the second of two steps in flushing to persistence,
/// the first step is `flush(1)`.
///
/// These steps are performed together when `persist(1)` is called.
///
/// > Note that either of these steps may be unnecessary on a given platform, and
/// > the library knows how to check for that and do the right thing.
/// > For example, on Intel platforms, pmem_drain() is an empty function.
pub fn drain() { unsafe { ffi::pmem_drain() }; }

/// Wether or not the machine supports an explicit hardware drain instruction for persistent memory.
///
/// On Intel processors with persistent memory, stores to persistent memory are considered persistent
/// once they are flushed from the CPU caches, so this function always returns false.
///
/// Despite that, programs using `flush(1)` to flush ranges of memory should still follow up by calling `drain()`
// once to ensure the flushes are complete. As mentioned above, `persist(1)` handles calling both `flush(1)` and `drain()`.
pub fn has_hw_drain() -> bool {
    let r = unsafe { ffi::pmem_has_hw_drain() };
    r > 0
}
<commit_msg>misc: doc<commit_after>//! # FFI bindings to **libpmem**
//!
//! Rust bindings for the NVM Library [http://pmem.io](http://pmem.io)
//!
//! The **pmem** library provides low level persistent memory support.
//! Developers wishing to roll their own persistent memory algorithms will find this library useful,
//! but most developers will likely use **pmem-obj** and let that library call **pmem** for them.
//!
//! The interfaces in `pmem` are **non-transactional**. Crates like `pmem-obj` provide transactional
//! interfaces by building on these `pmem` functions.
//!
//! > This is **not** an official port of the NVM Library.
//! >
//! > The official **libpmem** documentation can be found at: [http://pmem.io/nvml/libpmem/](http://pmem.io/nvml/libpmem/)

#[macro_use]
extern crate bitflags;
extern crate pmem_sys;
extern crate libc;

// Modules

pub mod persistentmap;
pub mod ptr;
pub mod nodrain;

// lib module

use ::std::mem;
use ::std::io;
use ::std::ffi::CStr;

use ::libc::c_void;
use ::libc::size_t;
use ::pmem_sys as ffi;

/// Description of the last error
///
/// The error message is thread-local; errors encountered in one thread do not affect its value in other threads.
/// Its content is significant only when the return value of the immediately preceding
/// call to a function indicated an error.
pub fn errormsg() -> Option<String> {
    unsafe {
        let reason_p = ffi::pmem_errormsg();
        if !reason_p.is_null() {
            CStr::from_ptr(reason_p).to_owned().into_string().ok()
        } else {
            None
        }
    }
}

/// Checks if an entire object consists of persistent memory
/// If `true` then it is safe to use `persist(1)` and other related functions to make changes durable for that memory range.
///
/// The implementation of `is_pmem(1)` requires a non-trivial amount of work to determine if the given range is
/// entirely persistent memory. For this reason, it is better to call `is_pmem(1)` once when a range of memory is first encountered,
/// save the result, and use the saved result to determine whether `persist()` or `msync(1)` is appropriate for flushing changes to persistence.
/// Calling `is_pmem(1)` each time changes are flushed to persistence will not perform well.
///
/// > **Warning:** Using `persist(1)` on a range where `is_pmem(1)` returns `false` may not do anything useful -- use `msync(1)` instead.
pub fn is_pmem<T>(x: &T) -> bool {
    let len = mem::size_of_val(x);
    let r = unsafe { ffi::pmem_is_pmem(x as *const _ as *const c_void, len as size_t) };
    r > 0
}

/// Force an object to be stored durably in persistent memory.
///
/// This is equivalent to calling `msync(1)` but may be more optimal
/// and will avoid calling into the kernel if possible.
/// There are no alignment restrictions on the range the object is in,
/// but `persist(1)` may expand the range as necessary to meet platform alignment requirements.
///
/// > **Warning:** Like `msync()`, there is nothing atomic or transactional about this call.
/// > Any unwritten stores in the given range will be written, but some stores may have already been written
/// > by virtue of normal cache eviction/replacement policies. Correctly written code must not depend on stores
/// > waiting until `persist(1)` is called to become persistent -- they can become persistent at
/// > any time before `persist(1)` is called.
///
/// To create your own variations of `persist(1)`, see `flush(1)` and `drain()`. One can think of `persist(1)` as:
///
/// ```no_run
/// fn persist<T>(x: &T) {
///     // flush the processor caches
///     pmem::flush(x);
///
///     // wait for any pmem stores to drain from HW buffers
///     pmem::drain();
/// }
/// ```
pub fn persist<T>(x: &T) {
    let len = mem::size_of_val(x);
    unsafe { ffi::pmem_persist(x as *const _ as *const c_void, len as size_t) };
}

/// Forces any changes in an object to be stored durably.
///
/// This function works on either persistent memory or a memory mapped file on traditional storage.
/// `msync()` takes steps to ensure the alignment of addresses and lengths passed down meet the requirements of that system call.
/// It calls msync() with the MS_SYNC flag as described in msync(2).
/// Typically the application only checks for the existence of persistent memory once,
/// and then uses that result throughout the program, for example:
///
/// # Example
///
/// ```no_run
/// fn some_method<T>(x: &T) {
///     // do this call once, after the pmem is memory mapped
///     let is_pmem = pmem::is_pmem(x);
///
///     // ...make some changes to x
///
///     // make the changes durable
///     if is_pmem {
///         pmem::persist(&x);
///     } else{
///         pmem::msync(&x).unwrap();
///     }
/// }
/// ```
pub fn msync<T>(x: &T) -> Result<(), io::Error> {
    let len = mem::size_of_val(x);
    let r = unsafe { ffi::pmem_msync(x as *const _ as *const c_void, len as size_t) };
    if r == -1 {
        Err(io::Error::last_os_error())
    } else {
        Ok(())
    }
}

/// Flushes the processor caches
///
/// This is the first of two steps in flushing to persistence,
/// the second stpe is `drain()`.
///
/// These steps are performed together when `persist()` is called.
///
/// > Note that either of these steps may be unnecessary on a given platform, and
/// > the library knows how to check for that and do the right thing.
/// > For example, on Intel platforms, pmem_drain() is an empty function.
pub fn flush<T>(x: &T) {
    let len = mem::size_of_val(x);
    unsafe { ffi::pmem_flush(x as *const _ as *const c_void, len as size_t) };
}

/// Waits for any pmem stores to drain from HW buffers
///
/// This is the second of two steps in flushing to persistence,
/// the first step is `flush(1)`.
///
/// These steps are performed together when `persist(1)` is called.
///
/// > Note that either of these steps may be unnecessary on a given platform, and
/// > the library knows how to check for that and do the right thing.
/// > For example, on Intel platforms, pmem_drain() is an empty function.
pub fn drain() { unsafe { ffi::pmem_drain() }; }

/// Wether or not the machine supports an explicit hardware drain instruction for persistent memory.
///
/// On Intel processors with persistent memory, stores to persistent memory are considered persistent
/// once they are flushed from the CPU caches, so this function always returns false.
///
/// Despite that, programs using `flush(1)` to flush ranges of memory should still follow up by calling `drain()`
// once to ensure the flushes are complete. As mentioned above, `persist(1)` handles calling both `flush(1)` and `drain()`.
pub fn has_hw_drain() -> bool {
    let r = unsafe { ffi::pmem_has_hw_drain() };
    r > 0
}
<|endoftext|>


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

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

#![feature(plugin, unsafe_no_drop_flag)]
#![feature(core, collections, alloc, hash)]
#![deny(warnings)]
#![cfg_attr(test, feature(test, std_misc))]
#![cfg_attr(bench, feature(rand))]
#![plugin(phf_macros, string_cache_macros)]

#[cfg(test)]
extern crate test;

#[no_link]
extern crate phf_macros;
extern crate phf;

#[macro_use]
extern crate lazy_static;

extern crate rand;
extern crate xxhash;

#[no_link] #[macro_use]
extern crate string_cache_macros;

#[cfg(feature = "log-events")]
extern crate serialize;

pub use atom::Atom;
pub use namespace::{Namespace, QualName};

#[cfg(feature = "log-events")]
pub mod event;

pub mod atom;
pub mod namespace;

// A private module so that macro-expanded idents like
// `::string_cache::atom::Atom` will also work in this crate.
//
// `libstd` uses the same trick.
#[doc(hidden)]
mod string_cache {
    pub use atom;
    pub use namespace;
}
<commit_msg>Remove unneeded `extern crate`<commit_after>// Copyright 2014 The Servo Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

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

#![feature(plugin, unsafe_no_drop_flag)]
#![feature(core, collections, alloc, hash)]
#![deny(warnings)]
#![cfg_attr(test, feature(test, std_misc))]
#![cfg_attr(bench, feature(rand))]
#![plugin(phf_macros, string_cache_macros)]

#[cfg(test)]
extern crate test;

extern crate phf;

#[macro_use]
extern crate lazy_static;

extern crate rand;
extern crate xxhash;

#[no_link] #[macro_use]
extern crate string_cache_macros;

#[cfg(feature = "log-events")]
extern crate serialize;

pub use atom::Atom;
pub use namespace::{Namespace, QualName};

#[cfg(feature = "log-events")]
pub mod event;

pub mod atom;
pub mod namespace;

// A private module so that macro-expanded idents like
// `::string_cache::atom::Atom` will also work in this crate.
//
// `libstd` uses the same trick.
#[doc(hidden)]
mod string_cache {
    pub use atom;
    pub use namespace;
}
<|endoftext|>


<commit_before>#![allow(dead_code)]

#[macro_use]
extern crate log;
#[macro_use]
mod macros;
#[cfg(test)]
mod tests;
use std::fmt;

pub trait Name {
    fn name(&self) -> &'static str;
}

pub trait Initializer {
    fn new() -> Self;
}

pub enum Action<UsrStEnum: fmt::Debug> {
    Ignore,
    Parent,
    Transition(UsrStEnum),
    ClosureTransition(Box<Fn() -> UsrStEnum>)
}
impl<UsrStEnum: fmt::Debug> fmt::Debug for Action<UsrStEnum> {
    fn fmt(&self, f:&mut fmt::Formatter) -> Result<(), fmt::Error> {
        match self {
            &Action::Ignore               => try!(fmt::Debug::fmt("Ignore", f)),
            &Action::Parent               => try!(fmt::Debug::fmt("Parent", f)),
            &Action::Transition(ref x)    => try!(fmt::Debug::fmt(&format!("Transition({:?})", x), f)),
            &Action::ClosureTransition(_) => try!(fmt::Debug::fmt("ClosureTransition", f)),
        };
        Ok(())
    }
}

#[derive(Debug, Clone)]
pub enum Event<UsrEvtEnum: Clone> {
    Enter,
    User(UsrEvtEnum),
    Exit
}

pub trait Parent<UsrStEnum> {
    fn get_parent(&self) -> Option<UsrStEnum>;
    fn set_parent(&mut self, newparent: UsrStEnum);
}

pub trait State<UsrEvtEnum, UsrStEnum>
    where Self: Name+Parent<UsrStEnum> {
    fn handle_event(&mut self, evt: Event<UsrEvtEnum>) -> Action<UsrStEnum>;
}
impl<'a, UsrEvtEnum, UsrStEnum> fmt::Debug for &'a State<UsrEvtEnum, UsrStEnum> {
    fn fmt(&self, f:&mut fmt::Formatter) -> Result<(), fmt::Error> {
        try!(fmt::Debug::fmt(self.name(), f));
        Ok(())
    }
}

pub trait StateLookup<UsrStEnum, UsrEvtEnum> {
    fn lookup(&mut self, typ: &UsrStEnum) -> &mut State<UsrEvtEnum, UsrStEnum>;
}

#[derive(Clone)]
struct Task<UsrStEnum, UsrEvtEnum: Clone> {
    state:  UsrStEnum,
    event: Event<UsrEvtEnum>
}
impl<UsrStEnum, UsrEvtEnum: Clone> Task<UsrStEnum, UsrEvtEnum> {
    fn new(state:  UsrStEnum, event: Event<UsrEvtEnum>) -> Self {
        Task { state:  state, event: event }
    }
}

pub struct StateMachine<UsrStStr, UsrStEnum, UsrEvtEnum: Clone> {
    current  : UsrStEnum,
    states   : UsrStStr,
    tasklist : Vec<Task<UsrStEnum, UsrEvtEnum>>,
    _phantom : ::std::marker::PhantomData<UsrEvtEnum>
}
impl<UsrStStr, UsrStEnum, UsrEvtEnum> StateMachine<UsrStStr, UsrStEnum, UsrEvtEnum>
    where UsrStStr   : Initializer + StateLookup<UsrStEnum, UsrEvtEnum>,
          UsrStEnum  : fmt::Debug+Eq+Clone,
          UsrEvtEnum : fmt::Debug+Clone {

    pub fn new(initial: UsrStEnum) -> Self {
        StateMachine {
            current  : initial,
            states   : UsrStStr::new(),
            tasklist : Vec::new(),
            _phantom : ::std::marker::PhantomData
        }
    }

    fn process_tasklist(&mut self) {
        for task in self.tasklist.iter() {
            debug!("send {:?} to {:?}", task.event, task.state);
            self.states.lookup(&task.state).handle_event(task.event.clone());
        }
        self.tasklist.clear();
    }

    fn transition(&mut self, from_state: UsrStEnum, to_state: UsrStEnum) {
        let mut parent = Some(from_state);
        while let Some(state) = parent {
            parent = self.states.lookup(&state).get_parent();
            self.tasklist.push(Task::new(state, Event::Exit));
        }
        let mut same_idx: Option<usize> = None;
        let mut enter_list = Vec::new();
        parent = Some(to_state);
        'outer: while let Some(state) = parent {
            for (i, task) in self.tasklist.iter().enumerate() {
                if task.state == state {
                    same_idx = Some(i);
                    break 'outer;
                }
            }
            parent = self.states.lookup(&state).get_parent();
            enter_list.push(Task::new(state, Event::Enter));
        }
        if let Some(i) = same_idx {
            let drop_num = self.tasklist.len() - i;
            for _ in 0..drop_num {
                self.tasklist.pop();
            }
        }
        self.process_tasklist();
        enter_list.reverse();
        for task in enter_list.iter() {
            debug!("send {:?} to {:?}", task.event, task.state);
            self.states.lookup(&task.state).handle_event(task.event.clone());
        }
    }

    pub fn input(&mut self, evt: Event<UsrEvtEnum>) {
        debug!("state:  {:?}", self.current);
        debug!("input:  {:?}", evt);
        let mut action;
        let mut state = self.current.clone();
        loop {
            action = self.states.lookup(&state).handle_event(evt.clone());
            match action {
                Action::Ignore               => {
                    self.tasklist.clear();
                    break
                },
                Action::Parent               => {
                    if let Some(parent) = self.states.lookup(&state).get_parent() {
                        self.tasklist.push(Task::new(state.clone(), Event::Exit));
                        state = parent;
                    } else {
                        error!("State {:?} responded with Action::Parent to event {:?}, but the state has no parent", state, evt);
                    }
                },
                Action::Transition(x)        => {
                    debug!("send {:?} to {:?}", evt, state);
                    self.process_tasklist();  // exit until in the parent that handles the signal
                    self.current = x.clone(); // signal allready handled
                    self.transition(state.clone(), x);
                    break;
                },
                Action::ClosureTransition(x) => {
                    self.process_tasklist(); // exit until in the parent that handles the signal
                    debug!("send {:?} to {:?}", evt, state);
                    self.current = x();      // handle the signal
                    let current_state = self.current.clone();
                    self.transition(state.clone(), current_state);
                    break;
                },
            }
        }
    }
}
<commit_msg>refactor tasklists<commit_after>#![allow(dead_code)]

#[macro_use]
extern crate log;
#[macro_use]
mod macros;
#[cfg(test)]
mod tests;
use std::fmt;

pub trait Name {
    fn name(&self) -> &'static str;
}

pub trait Initializer {
    fn new() -> Self;
}

pub enum Action<UsrStEnum: fmt::Debug> {
    Ignore,
    Parent,
    Transition(UsrStEnum),
    ClosureTransition(Box<Fn() -> UsrStEnum>)
}
impl<UsrStEnum: fmt::Debug> fmt::Debug for Action<UsrStEnum> {
    fn fmt(&self, f:&mut fmt::Formatter) -> Result<(), fmt::Error> {
        match self {
            &Action::Ignore               => try!(fmt::Debug::fmt("Ignore", f)),
            &Action::Parent               => try!(fmt::Debug::fmt("Parent", f)),
            &Action::Transition(ref x)    => try!(fmt::Debug::fmt(&format!("Transition({:?})", x), f)),
            &Action::ClosureTransition(_) => try!(fmt::Debug::fmt("ClosureTransition", f)),
        };
        Ok(())
    }
}

#[derive(Debug, Clone)]
pub enum Event<UsrEvtEnum: Clone> {
    Enter,
    User(UsrEvtEnum),
    Exit
}

pub trait Parent<UsrStEnum> {
    fn get_parent(&self) -> Option<UsrStEnum>;
    fn set_parent(&mut self, newparent: UsrStEnum);
}

pub trait State<UsrEvtEnum, UsrStEnum>
    where Self: Name+Parent<UsrStEnum> {
    fn handle_event(&mut self, evt: Event<UsrEvtEnum>) -> Action<UsrStEnum>;
}
impl<'a, UsrEvtEnum, UsrStEnum> fmt::Debug for &'a State<UsrEvtEnum, UsrStEnum> {
    fn fmt(&self, f:&mut fmt::Formatter) -> Result<(), fmt::Error> {
        try!(fmt::Debug::fmt(self.name(), f));
        Ok(())
    }
}

pub trait StateLookup<UsrStEnum, UsrEvtEnum> {
    fn lookup(&mut self, typ: &UsrStEnum) -> &mut State<UsrEvtEnum, UsrStEnum>;
}

#[derive(Clone)]
struct Task<UsrStEnum, UsrEvtEnum: Clone> {
    state:  UsrStEnum,
    event: Event<UsrEvtEnum>
}
impl<UsrStEnum, UsrEvtEnum: Clone> Task<UsrStEnum, UsrEvtEnum> {
    fn new(state:  UsrStEnum, event: Event<UsrEvtEnum>) -> Self {
        Task { state:  state, event: event }
    }
}

pub struct StateMachine<UsrStStr, UsrStEnum, UsrEvtEnum: Clone> {
    current     : UsrStEnum,
    states      : UsrStStr,
    exit_tasks  : Vec<Task<UsrStEnum, UsrEvtEnum>>,
    enter_tasks : Vec<Task<UsrStEnum, UsrEvtEnum>>,
    _phantom    : ::std::marker::PhantomData<UsrEvtEnum>
}
impl<UsrStStr, UsrStEnum, UsrEvtEnum> StateMachine<UsrStStr, UsrStEnum, UsrEvtEnum>
    where UsrStStr   : Initializer + StateLookup<UsrStEnum, UsrEvtEnum>,
          UsrStEnum  : fmt::Debug+Eq+Clone,
          UsrEvtEnum : fmt::Debug+Clone {

    pub fn new(initial: UsrStEnum) -> Self {
        StateMachine {
            current     : initial,
            states      : UsrStStr::new(),
            exit_tasks  : Vec::new(),
            enter_tasks : Vec::new(),
            _phantom    : ::std::marker::PhantomData
        }
    }

    fn process_exit_tasks(&mut self) {
        for task in self.exit_tasks.iter() {
            debug!("send {:?} to {:?}", task.event, task.state);
            self.states.lookup(&task.state).handle_event(task.event.clone());
        }
        self.exit_tasks.clear();
    }

    fn process_enter_tasks(&mut self) {
        self.enter_tasks.reverse();
        for task in self.enter_tasks.iter() {
            debug!("send {:?} to {:?}", task.event, task.state);
            self.states.lookup(&task.state).handle_event(task.event.clone());
        }
        self.enter_tasks.clear();
    }

    fn transition(&mut self, from_state: UsrStEnum, to_state: UsrStEnum) {
        let mut parent = Some(from_state);
        while let Some(state) = parent {
            parent = self.states.lookup(&state).get_parent();
            self.exit_tasks.push(Task::new(state, Event::Exit));
        }
        let mut same_idx: Option<usize> = None;
        parent = Some(to_state);
        'outer: while let Some(state) = parent {
            for (i, task) in self.exit_tasks.iter().enumerate() {
                if task.state == state {
                    same_idx = Some(i);
                    break 'outer;
                }
            }
            parent = self.states.lookup(&state).get_parent();
            self.enter_tasks.push(Task::new(state, Event::Enter));
        }
        if let Some(i) = same_idx {
            let drop_num = self.exit_tasks.len() - i;
            for _ in 0..drop_num {
                self.exit_tasks.pop();
            }
        }
        self.process_exit_tasks();
        self.process_enter_tasks();
    }

    pub fn input(&mut self, evt: Event<UsrEvtEnum>) {
        debug!("state:  {:?}", self.current);
        debug!("input:  {:?}", evt);
        let mut action;
        let mut state = self.current.clone();
        loop {
            action = self.states.lookup(&state).handle_event(evt.clone());
            match action {
                Action::Ignore               => {
                    self.exit_tasks.clear();
                    break
                },
                Action::Parent               => {
                    if let Some(parent) = self.states.lookup(&state).get_parent() {
                        self.exit_tasks.push(Task::new(state.clone(), Event::Exit));
                        state = parent;
                    } else {
                        error!("State {:?} responded with Action::Parent to event {:?}, but the state has no parent", state, evt);
                    }
                },
                Action::Transition(x)        => {
                    debug!("send {:?} to {:?}", evt, state);
                    self.process_exit_tasks();  // exit until in the parent that handles the signal
                    self.current = x.clone(); // signal allready handled
                    self.transition(state.clone(), x);
                    break;
                },
                Action::ClosureTransition(x) => {
                    self.process_exit_tasks(); // exit until in the parent that handles the signal
                    debug!("send {:?} to {:?}", evt, state);
                    self.current = x();      // handle the signal
                    let current_state = self.current.clone();
                    self.transition(state.clone(), current_state);
                    break;
                },
            }
        }
    }
}
<|endoftext|>