<commit_before>use std::ops::Bound;

use pagecache::{Measure, M};

use super::*;

#[cfg(feature = "lock_free_delays")]
const MAX_LOOPS: usize = usize::max_value();

#[cfg(not(feature = "lock_free_delays"))]
const MAX_LOOPS: usize = 1_000_000;

fn possible_predecessor(s: &[u8]) -> Option<Vec<u8>> {
    let mut ret = s.to_vec();
    match ret.pop() {
        None => None,
        Some(i) if i == 0 => Some(ret),
        Some(i) => {
            ret.push(i - 1);
            for _ in 0..4 {
                ret.push(255);
            }
            Some(ret)
        }
    }
}

macro_rules! iter_try {
    ($e:expr) => {
        match $e {
            Ok(item) => item,
            Err(e) => return Some(Err(e)),
        }
    };
}

/// An iterator over keys and values in a `Tree`.
pub struct Iter<'a> {
    pub(super) tree: &'a Tree,
    pub(super) hi: Bound<IVec>,
    pub(super) lo: Bound<IVec>,
    pub(super) cached_view: Option<View<'a>>,
    pub(super) tx: Result<Tx<'a, BLinkMaterializer, Frag>>,
    pub(super) going_forward: bool,
}

impl<'a> Iter<'a> {
    /// Iterate over the keys of this Tree
    pub fn keys(self) -> impl 'a + DoubleEndedIterator<Item = Result<IVec>> {
        self.map(|r| r.map(|(k, _v)| k))
    }

    /// Iterate over the values of this Tree
    pub fn values(self) -> impl 'a + DoubleEndedIterator<Item = Result<IVec>> {
        self.map(|r| r.map(|(_k, v)| v))
    }

    fn bounds_collapsed(&self) -> bool {
        match (&self.lo, &self.hi) {
            (Bound::Included(ref start), Bound::Included(ref end))
            | (Bound::Included(ref start), Bound::Excluded(ref end))
            | (Bound::Excluded(ref start), Bound::Included(ref end))
            | (Bound::Excluded(ref start), Bound::Excluded(ref end)) => {
                start > end
            }
            _ => false,
        }
    }

    fn low_key(&self) -> &[u8] {
        match self.lo {
            Bound::Unbounded => &[],
            Bound::Excluded(ref lo) | Bound::Included(ref lo) => lo.as_ref(),
        }
    }

    fn high_key(&self) -> &[u8] {
        const MAX_KEY: &[u8] = &[255; 1024 * 1024];
        match self.hi {
            Bound::Unbounded => MAX_KEY,
            Bound::Excluded(ref hi) | Bound::Included(ref hi) => hi.as_ref(),
        }
    }
}

impl<'a> Iterator for Iter<'a> {
    type Item = Result<(IVec, IVec)>;

    fn next(&mut self) -> Option<Self::Item> {
        let _measure = Measure::new(&M.tree_scan);
        let _ = self.tree.concurrency_control.read().unwrap();

        let tx: &'a Tx<'a, _, _> = match self.tx {
            Ok(ref tx) => {
                let tx_ref = tx as *const Tx<'a, _, _>;
                unsafe { &*tx_ref as &'a Tx<'a, _, _> }
            }
            Err(ref e) => return Some(Err(e.clone())),
        };

        let mut view = match (self.going_forward, self.cached_view.take()) {
            (true, Some(view)) => view,
            _ => iter_try!(self.tree.view_for_key(self.low_key(), &tx)),
        };

        for _ in 0..MAX_LOOPS {
            if self.bounds_collapsed() {
                return None;
            }

            if !view.contains_upper_bound(&self.lo) {
                // view too low (maybe merged, maybe exhausted?)
                let next_pid = view.next?;
                assert_ne!(view.pid, next_pid);
                if let Some(v) =
                    iter_try!(self.tree.view_for_pid(next_pid, &tx))
                {
                    view = v;
                } else {
                    view =
                        iter_try!(self.tree.view_for_key(self.low_key(), &tx));
                }
                continue;
            } else if !view.contains_lower_bound(&self.lo, true) {
                // view too high (maybe split, maybe exhausted?)
                let seek_key = possible_predecessor(view.lo)?;
                view = iter_try!(self.tree.view_for_key(seek_key, &tx));
                continue;
            }

            if let Some((key, value)) =
                view.successor(&self.lo, &self.tree.context)
            {
                self.lo = Bound::Excluded(key.clone());
                self.cached_view = Some(view);
                self.going_forward = true;

                match self.hi {
                    Bound::Unbounded => return Some(Ok((key, value))),
                    Bound::Included(ref h) if *h >= key => {
                        return Some(Ok((key, value)));
                    }
                    Bound::Excluded(ref h) if *h > key => {
                        return Some(Ok((key, value)));
                    }
                    _ => return None,
                }
            } else {
                if view.hi.is_empty() {
                    return None;
                }
                self.lo = Bound::Included(view.hi.clone());
                continue;
            }
        }
        panic!(
            "fucked up tree traversal next({:?}) on {:?}",
            self.lo, self.tree
        );
    }
}

impl<'a> DoubleEndedIterator for Iter<'a> {
    fn next_back(&mut self) -> Option<Self::Item> {
        let _measure = Measure::new(&M.tree_reverse_scan);
        let _ = self.tree.concurrency_control.read().unwrap();

        let tx: &'a Tx<'a, _, _> = match self.tx {
            Ok(ref tx) => {
                let tx_ref = tx as *const Tx<'a, _, _>;
                unsafe { &*tx_ref as &'a Tx<'a, _, _> }
            }
            Err(ref e) => return Some(Err(e.clone())),
        };

        let mut view = match (self.going_forward, self.cached_view.take()) {
            (false, Some(view)) => view,
            _ => iter_try!(self.tree.view_for_key(self.high_key(), &tx)),
        };

        for _ in 0..MAX_LOOPS {
            if self.bounds_collapsed() {
                return None;
            }

            if !view.contains_upper_bound(&self.hi) {
                // view too low (maybe merged, maybe exhausted?)
                let next_pid = view.next?;
                assert_ne!(view.pid, next_pid);
                if let Some(v) =
                    iter_try!(self.tree.view_for_pid(next_pid, &tx))
                {
                    view = v;
                } else {
                    view =
                        iter_try!(self.tree.view_for_key(self.high_key(), &tx));
                }
                continue;
            } else if !view.contains_lower_bound(&self.hi, false) {
                // view too high (maybe split, maybe exhausted?)
                let seek_key = possible_predecessor(view.lo)?;
                view = iter_try!(self.tree.view_for_key(seek_key, &tx));
                continue;
            }

            if let Some((key, value)) =
                view.predecessor(&self.hi, &self.tree.context)
            {
                self.hi = Bound::Excluded(key.clone());
                self.cached_view = Some(view);
                self.going_forward = false;

                match self.lo {
                    Bound::Unbounded => return Some(Ok((key, value))),
                    Bound::Included(ref l) if *l <= key => {
                        return Some(Ok((key, value)));
                    }
                    Bound::Excluded(ref l) if *l < key => {
                        return Some(Ok((key, value)));
                    }
                    _ => {
                        return None;
                    }
                }
            } else {
                if view.lo.is_empty() {
                    return None;
                }
                self.hi = Bound::Excluded(view.lo.clone());
                continue;
            }
        }
        panic!(
            "fucked up tree traversal next_back({:?}) on {:?}",
            self.hi, self.tree
        );
    }
}

#[test]
fn test_possible_predecessor() {
    assert_eq!(possible_predecessor(b""), None);
    assert_eq!(possible_predecessor(&[0]), Some(vec![]));
    assert_eq!(possible_predecessor(&[0, 0]), Some(vec![0]));
    assert_eq!(
        possible_predecessor(&[0, 1]),
        Some(vec![0, 0, 255, 255, 255, 255])
    );
    assert_eq!(
        possible_predecessor(&[0, 2]),
        Some(vec![0, 1, 255, 255, 255, 255])
    );
    assert_eq!(possible_predecessor(&[1, 0]), Some(vec![1]));
    assert_eq!(
        possible_predecessor(&[1, 1]),
        Some(vec![1, 0, 255, 255, 255, 255])
    );
    assert_eq!(
        possible_predecessor(&[155]),
        Some(vec![154, 255, 255, 255, 255])
    );
}
<commit_msg>feat: Use next_back in the Iterator last method<commit_after>use std::ops::Bound;

use pagecache::{Measure, M};

use super::*;

#[cfg(feature = "lock_free_delays")]
const MAX_LOOPS: usize = usize::max_value();

#[cfg(not(feature = "lock_free_delays"))]
const MAX_LOOPS: usize = 1_000_000;

fn possible_predecessor(s: &[u8]) -> Option<Vec<u8>> {
    let mut ret = s.to_vec();
    match ret.pop() {
        None => None,
        Some(i) if i == 0 => Some(ret),
        Some(i) => {
            ret.push(i - 1);
            for _ in 0..4 {
                ret.push(255);
            }
            Some(ret)
        }
    }
}

macro_rules! iter_try {
    ($e:expr) => {
        match $e {
            Ok(item) => item,
            Err(e) => return Some(Err(e)),
        }
    };
}

/// An iterator over keys and values in a `Tree`.
pub struct Iter<'a> {
    pub(super) tree: &'a Tree,
    pub(super) hi: Bound<IVec>,
    pub(super) lo: Bound<IVec>,
    pub(super) cached_view: Option<View<'a>>,
    pub(super) tx: Result<Tx<'a, BLinkMaterializer, Frag>>,
    pub(super) going_forward: bool,
}

impl<'a> Iter<'a> {
    /// Iterate over the keys of this Tree
    pub fn keys(self) -> impl 'a + DoubleEndedIterator<Item = Result<IVec>> {
        self.map(|r| r.map(|(k, _v)| k))
    }

    /// Iterate over the values of this Tree
    pub fn values(self) -> impl 'a + DoubleEndedIterator<Item = Result<IVec>> {
        self.map(|r| r.map(|(_k, v)| v))
    }

    fn bounds_collapsed(&self) -> bool {
        match (&self.lo, &self.hi) {
            (Bound::Included(ref start), Bound::Included(ref end))
            | (Bound::Included(ref start), Bound::Excluded(ref end))
            | (Bound::Excluded(ref start), Bound::Included(ref end))
            | (Bound::Excluded(ref start), Bound::Excluded(ref end)) => {
                start > end
            }
            _ => false,
        }
    }

    fn low_key(&self) -> &[u8] {
        match self.lo {
            Bound::Unbounded => &[],
            Bound::Excluded(ref lo) | Bound::Included(ref lo) => lo.as_ref(),
        }
    }

    fn high_key(&self) -> &[u8] {
        const MAX_KEY: &[u8] = &[255; 1024 * 1024];
        match self.hi {
            Bound::Unbounded => MAX_KEY,
            Bound::Excluded(ref hi) | Bound::Included(ref hi) => hi.as_ref(),
        }
    }
}

impl<'a> Iterator for Iter<'a> {
    type Item = Result<(IVec, IVec)>;

    fn next(&mut self) -> Option<Self::Item> {
        let _measure = Measure::new(&M.tree_scan);
        let _ = self.tree.concurrency_control.read().unwrap();

        let tx: &'a Tx<'a, _, _> = match self.tx {
            Ok(ref tx) => {
                let tx_ref = tx as *const Tx<'a, _, _>;
                unsafe { &*tx_ref as &'a Tx<'a, _, _> }
            }
            Err(ref e) => return Some(Err(e.clone())),
        };

        let mut view = match (self.going_forward, self.cached_view.take()) {
            (true, Some(view)) => view,
            _ => iter_try!(self.tree.view_for_key(self.low_key(), &tx)),
        };

        for _ in 0..MAX_LOOPS {
            if self.bounds_collapsed() {
                return None;
            }

            if !view.contains_upper_bound(&self.lo) {
                // view too low (maybe merged, maybe exhausted?)
                let next_pid = view.next?;
                assert_ne!(view.pid, next_pid);
                if let Some(v) =
                    iter_try!(self.tree.view_for_pid(next_pid, &tx))
                {
                    view = v;
                } else {
                    view =
                        iter_try!(self.tree.view_for_key(self.low_key(), &tx));
                }
                continue;
            } else if !view.contains_lower_bound(&self.lo, true) {
                // view too high (maybe split, maybe exhausted?)
                let seek_key = possible_predecessor(view.lo)?;
                view = iter_try!(self.tree.view_for_key(seek_key, &tx));
                continue;
            }

            if let Some((key, value)) =
                view.successor(&self.lo, &self.tree.context)
            {
                self.lo = Bound::Excluded(key.clone());
                self.cached_view = Some(view);
                self.going_forward = true;

                match self.hi {
                    Bound::Unbounded => return Some(Ok((key, value))),
                    Bound::Included(ref h) if *h >= key => {
                        return Some(Ok((key, value)));
                    }
                    Bound::Excluded(ref h) if *h > key => {
                        return Some(Ok((key, value)));
                    }
                    _ => return None,
                }
            } else {
                if view.hi.is_empty() {
                    return None;
                }
                self.lo = Bound::Included(view.hi.clone());
                continue;
            }
        }
        panic!(
            "fucked up tree traversal next({:?}) on {:?}",
            self.lo, self.tree
        );
    }

    fn last(mut self) -> Option<Self::Item> {
        self.next_back()
    }
}

impl<'a> DoubleEndedIterator for Iter<'a> {
    fn next_back(&mut self) -> Option<Self::Item> {
        let _measure = Measure::new(&M.tree_reverse_scan);
        let _ = self.tree.concurrency_control.read().unwrap();

        let tx: &'a Tx<'a, _, _> = match self.tx {
            Ok(ref tx) => {
                let tx_ref = tx as *const Tx<'a, _, _>;
                unsafe { &*tx_ref as &'a Tx<'a, _, _> }
            }
            Err(ref e) => return Some(Err(e.clone())),
        };

        let mut view = match (self.going_forward, self.cached_view.take()) {
            (false, Some(view)) => view,
            _ => iter_try!(self.tree.view_for_key(self.high_key(), &tx)),
        };

        for _ in 0..MAX_LOOPS {
            if self.bounds_collapsed() {
                return None;
            }

            if !view.contains_upper_bound(&self.hi) {
                // view too low (maybe merged, maybe exhausted?)
                let next_pid = view.next?;
                assert_ne!(view.pid, next_pid);
                if let Some(v) =
                    iter_try!(self.tree.view_for_pid(next_pid, &tx))
                {
                    view = v;
                } else {
                    view =
                        iter_try!(self.tree.view_for_key(self.high_key(), &tx));
                }
                continue;
            } else if !view.contains_lower_bound(&self.hi, false) {
                // view too high (maybe split, maybe exhausted?)
                let seek_key = possible_predecessor(view.lo)?;
                view = iter_try!(self.tree.view_for_key(seek_key, &tx));
                continue;
            }

            if let Some((key, value)) =
                view.predecessor(&self.hi, &self.tree.context)
            {
                self.hi = Bound::Excluded(key.clone());
                self.cached_view = Some(view);
                self.going_forward = false;

                match self.lo {
                    Bound::Unbounded => return Some(Ok((key, value))),
                    Bound::Included(ref l) if *l <= key => {
                        return Some(Ok((key, value)));
                    }
                    Bound::Excluded(ref l) if *l < key => {
                        return Some(Ok((key, value)));
                    }
                    _ => {
                        return None;
                    }
                }
            } else {
                if view.lo.is_empty() {
                    return None;
                }
                self.hi = Bound::Excluded(view.lo.clone());
                continue;
            }
        }
        panic!(
            "fucked up tree traversal next_back({:?}) on {:?}",
            self.hi, self.tree
        );
    }
}

#[test]
fn test_possible_predecessor() {
    assert_eq!(possible_predecessor(b""), None);
    assert_eq!(possible_predecessor(&[0]), Some(vec![]));
    assert_eq!(possible_predecessor(&[0, 0]), Some(vec![0]));
    assert_eq!(
        possible_predecessor(&[0, 1]),
        Some(vec![0, 0, 255, 255, 255, 255])
    );
    assert_eq!(
        possible_predecessor(&[0, 2]),
        Some(vec![0, 1, 255, 255, 255, 255])
    );
    assert_eq!(possible_predecessor(&[1, 0]), Some(vec![1]));
    assert_eq!(
        possible_predecessor(&[1, 1]),
        Some(vec![1, 0, 255, 255, 255, 255])
    );
    assert_eq!(
        possible_predecessor(&[155]),
        Some(vec![154, 255, 255, 255, 255])
    );
}
<|endoftext|>


<commit_before>//! File holding the FormHashMap type and associated tests
//!
//! Author: [Boris](mailto:boris@humanenginuity.com)
//! Version: 1.1

// =======================================================================
// ATTRIBUTES
// =======================================================================
#![allow(dead_code)]

// =======================================================================
// LIBRARY IMPORTS
// =======================================================================
use std::collections::HashMap;
use std::error::Error;
use std::fmt::Debug;
use std::io::Read;
use std::marker::PhantomData;

use rocket;
use rocket::{ Request, Data };
use rocket::data::FromData;
use rocket::http::Status;
use rocket::outcome::IntoOutcome;
use rocket::request::{ FromForm, FromFormValue, FormItems };

use types::OneOrMany;

// =======================================================================
// FORMVALUES INNER STRUCT DEFINITION
// =======================================================================
/// Private structure to hold a random number of values
/// providing utility methods to `push()`or `get()` the underlying data
struct FormValues<'v, T: 'v> {
    value: Option<OneOrMany<T>>,
    _phantom: PhantomData<&'v T>,
}

/// Generic structure to hold the value in a key/value pair
/// since we can have an arbitrary number of values associated to a key
impl<'v, T: 'v> FormValues<'v, T> {
    fn new() -> FormValues<'v, T> {
        FormValues {
            value: None,
            _phantom: PhantomData
        }
    }

    /// Set/add a new value
    fn push(&mut self, new_value: T) {
        let old_value = ::std::mem::replace(&mut self.value, None);
        self._phantom = PhantomData;
        self.value = match old_value {
            None => {
                Some(OneOrMany::One(new_value))
            }
            Some(OneOrMany::One(existing_value)) => {
                Some(OneOrMany::Many(vec![existing_value, new_value]))
            }
            Some(OneOrMany::Many(mut vec)) => {
                vec.push(new_value);
                Some(OneOrMany::Many(vec))
            }
        }
    }

    /// Get a reference to this object's value
    fn get(&self) -> Option<&OneOrMany<T>> {
        self.value.as_ref()
    }

    /// Consume this object (since it takes `self`) and move out its content
    fn into_inner(self) -> Option<OneOrMany<T>> {
        self.value
    }
}

impl<'v, T: Debug + 'v> Debug for FormValues<'v, T> {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        write!(f, "FormValues {{ values: {:?} }}", self.value)
    }
}

// =======================================================================
// FORMHASHMAP (implement FormData and FromForm)
// =======================================================================

/// A `FromData` type that creates a map of the key/value pairs from a
/// `x-www-form-urlencoded` form `string`.
pub struct FormHashMap<'f> {
    form_string: String,
    form_hash: HashMap<&'f str, FormValues<'f, String>>,
    _phantom: PhantomData<&'f String>,
}

impl<'f> FormHashMap<'f> {
    /// Get a reference for the value (or values) associated with `key`.
    pub fn get(&'f self, key: &str) -> Option<&OneOrMany<String>> {
        // Note: The map method takes the self argument by value, consuming the original
        // `HashMap::get()` returns a reference to the value corresponding to the key
        // so we then consume *that* reference with `map`
        self.form_hash
            .get(key) // Option<&FormValues<String>> corresponding to the key
            .map(|form_value| form_value.get())
            .unwrap() // converted to an Option<&OneOrMany<String>> to 'hide' FormValues
    }

    /// Returns the raw form string that was used to parse the encapsulated
    /// object.
    pub fn raw_form_string(&self) -> &str {
        &self.form_string
    }

    // We'd like to have form objects have pointers directly to the form string.
    // This means that the form string has to live at least as long as the form object. So,
    // to enforce this, we store the form_string along with the form object.
    //
    // So far so good. Now, this means that the form_string can never be
    // deallocated while the object is alive. That implies that the
    // `form_string` value should never be moved away. We can enforce that
    // easily by 1) not making `form_string` public, and 2) not exposing any
    // `&mut self` methods that could modify `form_string`.
    fn new(form_string: String) -> Result<Self, String> {
        let long_lived_string: &'f str = unsafe {
            ::std::mem::transmute(form_string.as_str())
        };

        let mut items = FormItems::from(long_lived_string);

        // Handle parsing or decode errors
        let parsing_errors: Vec<_> = items.by_ref()
            .map(|(key, value)| (key, String::from_form_value(value)))
            .filter(|&(_, ref decoded_value)| decoded_value.is_err())
            .collect();

        if !parsing_errors.is_empty() {
            // Parsing errors => fail with invalid result
            return Err(format!("::MODEL::ROCKET::FORM_HASMAP::NEW::WARNING Unable to parse form string {}", form_string));
        }
        if !items.completed() {
            warn!("::MODEL::ROCKET::FORM_HASMAP::NEW::WARNING Form string {} couldn't be completely parsed", form_string);
        }

        Ok(FormHashMap {
            form_string: form_string,
            form_hash: FormItems::from(long_lived_string).by_ref()
                            .map(|(key, value)| (key, String::from_form_value(value)))
                            .filter(|&(_, ref decoded_value)| decoded_value.is_ok())
                            .fold(
                                HashMap::<&'f str, FormValues<String>>::new(),
                                |mut map, (key, decoded_value)| {
                                    map.entry(key).or_insert(FormValues::new()).push(decoded_value.unwrap());
                                    map
                                }
                            ),
            _phantom: PhantomData,
        })
    }
}

/// Parses a `FormHashMap` from incoming POST/... form data.
///
/// - If the content type of the request data is not
/// `application/x-www-form-urlencoded`, `Forward`s the request.
/// - If the form string is malformed, a `Failure` with status code
/// `BadRequest` is returned.
/// - Finally, if reading the incoming stream fails, returns a `Failure` with status code
/// `InternalServerError`.
/// In all failure cases, the raw form string is returned if it was able to be retrieved from the incoming stream.
///
/// All relevant warnings and errors are written to the console
impl<'f> FromData for FormHashMap<'f> {
    type Error = String;

    fn from_data(request: &Request, data: Data) -> rocket::data::Outcome<Self, Self::Error> {
        // TODO add support for application/json
        if !request.content_type().map_or(false, |ct| ct.is_form()) {
            error!("::MODEL::ROCKET::FORM_HASMAP::FROM_DATA::WARNING Form data does not have form content type.");
            return rocket::Outcome::Forward(data);
        }

        let size_limit = rocket::config::active()
            .and_then(|c| c.extras.get("limits.application")) // TODO: remove placeholder when upgrading to rocket version > 0.2.6
            // .and_then(|c| c.limits.get("application") // In next version
            .and_then(|limit| limit.as_integer())
            .unwrap_or(32768) as u64;

        let mut buffer = String::new();
        data.open()
            .take(size_limit)
            .read_to_string(&mut buffer)
            .or_else(|err| Err(format!("::MODEL::ROCKET::FORM_HASMAP::FROM_DATA::ERROR IO Error: {}", err.description())) )
            .and_then(|_| FormHashMap::new(buffer)) // Note: if ok, read_to_string() returns how many bytes where read
            .or_else(|error_message| {
                error!("{}", error_message);
                Err(error_message)
            }).into_outcome() // Note: trait implemented by Rocket FromData for Result<S,E> `fn into_outcome(self, status: Status) -> Outcome<S, E>`
    }
}

/// Parses a `FormHashMap` from incoming GET query strings.
///
/// - If the form string is malformed, a `Failure` with status code
/// `BadRequest` is returned.
/// - Finally, if reading the incoming stream fails, returns a `Failure` with status code
/// `InternalServerError`.
/// In all failure cases, the raw form string is returned if it was able to be retrieved from the incoming stream.
///
/// All relevant warnings and errors are written to the console
impl<'f> FromForm<'f> for FormHashMap<'f> {
    /// The raw form string, if it was able to be retrieved from the request.
    type Error = (Status, Option<String>);

    fn from_form_items(items: &mut FormItems<'f>) -> Result<Self, Self::Error> {
        FormHashMap::new(items.inner_str().to_string())
            .map(|map| {
                info!("::MODEL::ROCKET::FORM_HASMAP::FROM_FORM_ITEMS::INFO Successfully parsed input data => {:?}", map);
                map
            }).map_err(|invalid_string| {
                error!("::MODEL::ROCKET::FORM_HASMAP::FROM_FORM_ITEMS::ERROR The request's form string '{}' was malformed.", invalid_string);
                (Status::BadRequest, Some(invalid_string))
            })
    }
}

/// Implement Debug displaying '<internal data holding structure>' from string: <parsed string>'
impl<'f> Debug for FormHashMap<'f> {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        write!(f, "{:?} from string: {:?}", self.form_hash, self.form_string)
    }
}

// =======================================================================
// TESTS
// =======================================================================
#[cfg(test)]
mod tests {
    #![allow(unmounted_route)]

    use super::FormHashMap;
    use types::OneOrMany;

    use rocket;
    use rocket::testing::MockRequest;
    use rocket::http::{ ContentType, Method, Status };

    #[test]
    fn test_new() {
        let form_string = "a=b1&a=b2&b=c";

        match FormHashMap::new(form_string.to_string()) {
            Ok(map) => {
                assert_eq!(map.get("a"), Some(&OneOrMany::Many(vec!["b1".to_string(), "b2".to_string()])));
                assert_eq!(map.get("b"), Some(&OneOrMany::One("c".to_string())));
            },
            Err(invalid_string) => {
                panic!("Unable to parse {}", invalid_string);
            }
        }
    }

    #[test]
    fn test_post_route() {
        #[post("/test", data= "<params>")]
        fn test_route(params: FormHashMap) -> &'static str {
            assert_eq!(params.get("a"), Some(&OneOrMany::Many(vec!["b1".to_string(), "b2".to_string()])));
            assert_eq!(params.get("b"), Some(&OneOrMany::One("c".to_string())));
            "It's working !"
        }

        let rocket = rocket::ignite()
            .mount("/post", routes![test_route]);

        let mut req = MockRequest::new(Method::Post, "/post/test")
            .header(ContentType::Form)
            .body("a=b1&a=b2&b=c");

        let mut response = req.dispatch_with(&rocket);
        let body_str = response.body().and_then(|b| b.into_string());

        assert_eq!(response.status(), Status::Ok);
        assert_eq!(body_str, Some("It's working !".to_string()));
    }

    #[test]
    fn test_get_route() {
        #[get("/test?<params>")]
        fn test_route(params: FormHashMap) -> &'static str {
            assert_eq!(params.get("a"), Some(&OneOrMany::Many(vec!["b1".to_string(), "b2".to_string()])));
            assert_eq!(params.get("b"), Some(&OneOrMany::One("c".to_string())));
            "It's working !"
        }

        let rocket = rocket::ignite()
            .mount("/get", routes![test_route]);

        let mut req = MockRequest::new(Method::Get, "/get/test?a=b1&a=b2&b=c");

        let mut response = req.dispatch_with(&rocket);
        let body_str = response.body().and_then(|b| b.into_string());

        assert_eq!(response.status(), Status::Ok);
        assert_eq!(body_str, Some("It's working !".to_string()));
    }

    #[test]
    fn test_get_qs_with_dot() {
        #[get("/test?<params>")]
        fn test_route(params: FormHashMap) -> &'static str {
            assert_eq!(params.get("v"), Some(&OneOrMany::One("4.7.0".to_string())));
            "It's working !"
        }

        let rocket = rocket::ignite()
            .mount("/get", routes![test_route]);

        let mut req = MockRequest::new(Method::Get, "/get/test?v=4.7.0");

        let mut response = req.dispatch_with(&rocket);
        let body_str = response.body().and_then(|b| b.into_string());

        assert_eq!(response.status(), Status::Ok);
        assert_eq!(body_str, Some("It's working !".to_string()));
    }

    // TODO: test json
    /*
    /// let req = MockRequest::new(Post, "/")
    ///     .header(ContentType::JSON)
    ///     .body(r#"{ "key": "value", "array": [1, 2, 3], }"#);
    */

    // TODO: add test lifetime
}<commit_msg>FormHashMap > renamed tests & updated log<commit_after>//! File holding the FormHashMap type and associated tests
//!
//! Author: [Boris](mailto:boris@humanenginuity.com)
//! Version: 1.1

// =======================================================================
// ATTRIBUTES
// =======================================================================
#![allow(dead_code)]

// =======================================================================
// LIBRARY IMPORTS
// =======================================================================
use std::collections::HashMap;
use std::error::Error;
use std::fmt::Debug;
use std::io::Read;
use std::marker::PhantomData;

use rocket;
use rocket::{ Request, Data };
use rocket::data::FromData;
use rocket::http::Status;
use rocket::outcome::IntoOutcome;
use rocket::request::{ FromForm, FromFormValue, FormItems };

use types::OneOrMany;

// =======================================================================
// FORMVALUES INNER STRUCT DEFINITION
// =======================================================================
/// Private structure to hold a random number of values
/// providing utility methods to `push()`or `get()` the underlying data
struct FormValues<'v, T: 'v> {
    value: Option<OneOrMany<T>>,
    _phantom: PhantomData<&'v T>,
}

/// Generic structure to hold the value in a key/value pair
/// since we can have an arbitrary number of values associated to a key
impl<'v, T: 'v> FormValues<'v, T> {
    fn new() -> FormValues<'v, T> {
        FormValues {
            value: None,
            _phantom: PhantomData
        }
    }

    /// Set/add a new value
    fn push(&mut self, new_value: T) {
        let old_value = ::std::mem::replace(&mut self.value, None);
        self._phantom = PhantomData;
        self.value = match old_value {
            None => {
                Some(OneOrMany::One(new_value))
            }
            Some(OneOrMany::One(existing_value)) => {
                Some(OneOrMany::Many(vec![existing_value, new_value]))
            }
            Some(OneOrMany::Many(mut vec)) => {
                vec.push(new_value);
                Some(OneOrMany::Many(vec))
            }
        }
    }

    /// Get a reference to this object's value
    fn get(&self) -> Option<&OneOrMany<T>> {
        self.value.as_ref()
    }

    /// Consume this object (since it takes `self`) and move out its content
    fn into_inner(self) -> Option<OneOrMany<T>> {
        self.value
    }
}

impl<'v, T: Debug + 'v> Debug for FormValues<'v, T> {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        write!(f, "FormValues {{ values: {:?} }}", self.value)
    }
}

// =======================================================================
// FORMHASHMAP (implement FormData and FromForm)
// =======================================================================

/// A `FromData` type that creates a map of the key/value pairs from a
/// `x-www-form-urlencoded` form `string`.
pub struct FormHashMap<'f> {
    form_string: String,
    form_hash: HashMap<&'f str, FormValues<'f, String>>,
    _phantom: PhantomData<&'f String>,
}

impl<'f> FormHashMap<'f> {
    /// Get a reference for the value (or values) associated with `key`.
    pub fn get(&'f self, key: &str) -> Option<&OneOrMany<String>> {
        // Note: The map method takes the self argument by value, consuming the original
        // `HashMap::get()` returns a reference to the value corresponding to the key
        // so we then consume *that* reference with `map`
        self.form_hash
            .get(key) // Option<&FormValues<String>> corresponding to the key
            .map(|form_value| form_value.get())
            .unwrap() // converted to an Option<&OneOrMany<String>> to 'hide' FormValues
    }

    /// Returns the raw form string that was used to parse the encapsulated
    /// object.
    pub fn raw_form_string(&self) -> &str {
        &self.form_string
    }

    // We'd like to have form objects have pointers directly to the form string.
    // This means that the form string has to live at least as long as the form object. So,
    // to enforce this, we store the form_string along with the form object.
    //
    // So far so good. Now, this means that the form_string can never be
    // deallocated while the object is alive. That implies that the
    // `form_string` value should never be moved away. We can enforce that
    // easily by 1) not making `form_string` public, and 2) not exposing any
    // `&mut self` methods that could modify `form_string`.
    fn new(form_string: String) -> Result<Self, String> {
        let long_lived_string: &'f str = unsafe {
            ::std::mem::transmute(form_string.as_str())
        };

        let mut items = FormItems::from(long_lived_string);

        // Handle parsing or decode errors
        let parsing_errors: Vec<_> = items.by_ref()
            .map(|(key, value)| (key, String::from_form_value(value)))
            .filter(|&(_, ref decoded_value)| decoded_value.is_err())
            .collect();

        if !parsing_errors.is_empty() {
            // Parsing errors => fail with invalid result
            return Err(format!("::AMIWO::CONTRIB::ROCKET::FORM_HASMAP::NEW::WARNING Unable to parse form string {}", form_string));
        }
        if !items.completed() {
            warn!("::AMIWO::CONTRIB::ROCKET::FORM_HASMAP::NEW::WARNING Form string {} couldn't be completely parsed", form_string);
        }

        Ok(FormHashMap {
            form_string: form_string,
            form_hash: FormItems::from(long_lived_string).by_ref()
                            .map(|(key, value)| (key, String::from_form_value(value)))
                            .filter(|&(_, ref decoded_value)| decoded_value.is_ok())
                            .fold(
                                HashMap::<&'f str, FormValues<String>>::new(),
                                |mut map, (key, decoded_value)| {
                                    map.entry(key).or_insert(FormValues::new()).push(decoded_value.unwrap());
                                    map
                                }
                            ),
            _phantom: PhantomData,
        })
    }
}

/// Parses a `FormHashMap` from incoming POST/... form data.
///
/// - If the content type of the request data is not
/// `application/x-www-form-urlencoded`, `Forward`s the request.
/// - If the form string is malformed, a `Failure` with status code
/// `BadRequest` is returned.
/// - Finally, if reading the incoming stream fails, returns a `Failure` with status code
/// `InternalServerError`.
/// In all failure cases, the raw form string is returned if it was able to be retrieved from the incoming stream.
///
/// All relevant warnings and errors are written to the console
impl<'f> FromData for FormHashMap<'f> {
    type Error = String;

    fn from_data(request: &Request, data: Data) -> rocket::data::Outcome<Self, Self::Error> {
        // TODO add support for application/json
        if !request.content_type().map_or(false, |ct| ct.is_form()) {
            error!("::AMIWO::CONTRIB::ROCKET::FORM_HASMAP::FROM_DATA::WARNING Form data does not have form content type.");
            return rocket::Outcome::Forward(data);
        }

        let size_limit = rocket::config::active()
            .and_then(|c| c.extras.get("limits.application")) // TODO: remove placeholder when upgrading to rocket version > 0.2.6
            // .and_then(|c| c.limits.get("application") // In next version
            .and_then(|limit| limit.as_integer())
            .unwrap_or(32768) as u64;

        let mut buffer = String::new();
        data.open()
            .take(size_limit)
            .read_to_string(&mut buffer)
            .or_else(|err| Err(format!("::AMIWO::CONTRIB::ROCKET::FORM_HASMAP::FROM_DATA::ERROR IO Error: {}", err.description())) )
            .and_then(|_| FormHashMap::new(buffer)) // Note: if ok, read_to_string() returns how many bytes where read
            .or_else(|error_message| {
                error!("{}", error_message);
                Err(error_message)
            }).into_outcome() // Note: trait implemented by Rocket FromData for Result<S,E> `fn into_outcome(self, status: Status) -> Outcome<S, E>`
    }
}

/// Parses a `FormHashMap` from incoming GET query strings.
///
/// - If the form string is malformed, a `Failure` with status code
/// `BadRequest` is returned.
/// - Finally, if reading the incoming stream fails, returns a `Failure` with status code
/// `InternalServerError`.
/// In all failure cases, the raw form string is returned if it was able to be retrieved from the incoming stream.
///
/// All relevant warnings and errors are written to the console
impl<'f> FromForm<'f> for FormHashMap<'f> {
    /// The raw form string, if it was able to be retrieved from the request.
    type Error = (Status, Option<String>);

    fn from_form_items(items: &mut FormItems<'f>) -> Result<Self, Self::Error> {
        FormHashMap::new(items.inner_str().to_string())
            .map(|map| {
                info!("::AMIWO::CONTRIB::ROCKET::FORM_HASMAP::FROM_FORM_ITEMS::INFO Successfully parsed input data => {:?}", map);
                map
            }).map_err(|invalid_string| {
                error!("::AMIWO::CONTRIB::ROCKET::FORM_HASMAP::FROM_FORM_ITEMS::ERROR The request's form string '{}' was malformed.", invalid_string);
                (Status::BadRequest, Some(invalid_string))
            })
    }
}

/// Implement Debug displaying '<internal data holding structure>' from string: <parsed string>'
impl<'f> Debug for FormHashMap<'f> {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        write!(f, "{:?} from string: {:?}", self.form_hash, self.form_string)
    }
}

// =======================================================================
// TESTS
// =======================================================================
#[cfg(test)]
mod tests {
    #![allow(unmounted_route)]
    #![allow(non_snake_case)]

    use super::FormHashMap;
    use types::OneOrMany;

    use rocket;
    use rocket::testing::MockRequest;
    use rocket::http::{ ContentType, Method, Status };

    #[test]
    fn FormHashMap_test_new() {
        let form_string = "a=b1&a=b2&b=c";

        match FormHashMap::new(form_string.to_string()) {
            Ok(map) => {
                assert_eq!(map.get("a"), Some(&OneOrMany::Many(vec!["b1".to_string(), "b2".to_string()])));
                assert_eq!(map.get("b"), Some(&OneOrMany::One("c".to_string())));
            },
            Err(invalid_string) => {
                panic!("Unable to parse {}", invalid_string);
            }
        }
    }

    #[test]
    fn FormHashMap_test_post_route() {
        #[post("/test", data= "<params>")]
        fn test_route(params: FormHashMap) -> &'static str {
            assert_eq!(params.get("a"), Some(&OneOrMany::Many(vec!["b1".to_string(), "b2".to_string()])));
            assert_eq!(params.get("b"), Some(&OneOrMany::One("c".to_string())));
            "It's working !"
        }

        let rocket = rocket::ignite()
            .mount("/post", routes![test_route]);

        let mut req = MockRequest::new(Method::Post, "/post/test")
            .header(ContentType::Form)
            .body("a=b1&a=b2&b=c");

        let mut response = req.dispatch_with(&rocket);
        let body_str = response.body().and_then(|b| b.into_string());

        assert_eq!(response.status(), Status::Ok);
        assert_eq!(body_str, Some("It's working !".to_string()));
    }

    #[test]
    fn FormHashMap_test_get_route() {
        #[get("/test?<params>")]
        fn test_route(params: FormHashMap) -> &'static str {
            assert_eq!(params.get("a"), Some(&OneOrMany::Many(vec!["b1".to_string(), "b2".to_string()])));
            assert_eq!(params.get("b"), Some(&OneOrMany::One("c".to_string())));
            "It's working !"
        }

        let rocket = rocket::ignite()
            .mount("/get", routes![test_route]);

        let mut req = MockRequest::new(Method::Get, "/get/test?a=b1&a=b2&b=c");

        let mut response = req.dispatch_with(&rocket);
        let body_str = response.body().and_then(|b| b.into_string());

        assert_eq!(response.status(), Status::Ok);
        assert_eq!(body_str, Some("It's working !".to_string()));
    }

    #[test]
    fn FormHashMap_test_get_qs_with_dot() {
        #[get("/test?<params>")]
        fn test_route(params: FormHashMap) -> &'static str {
            assert_eq!(params.get("v"), Some(&OneOrMany::One("4.7.0".to_string())));
            "It's working !"
        }

        let rocket = rocket::ignite()
            .mount("/get", routes![test_route]);

        let mut req = MockRequest::new(Method::Get, "/get/test?v=4.7.0");

        let mut response = req.dispatch_with(&rocket);
        let body_str = response.body().and_then(|b| b.into_string());

        assert_eq!(response.status(), Status::Ok);
        assert_eq!(body_str, Some("It's working !".to_string()));
    }

    // TODO: add test lifetime
}<|endoftext|>


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

extern crate devicemapper;
extern crate env_logger;
extern crate libstratis;
extern crate log;
extern crate serde_json;

mod util;

use std::fs::OpenOptions;
use std::path::{Path, PathBuf};

use serde_json::{Value, from_reader};

use self::devicemapper::{Bytes, Sectors};

use libstratis::engine::IEC;
use libstratis::engine::strat_engine::device::wipe_sectors;

use util::logger::init_logger;
use util::simple_tests::test_basic_metadata;
use util::simple_tests::test_empty_pool;
use util::simple_tests::test_force_flag_dirty;
use util::simple_tests::test_force_flag_stratis;
use util::simple_tests::test_linear_device;
use util::simple_tests::test_pool_blockdevs;
use util::simple_tests::test_setup;
use util::simple_tests::test_teardown;
use util::simple_tests::test_thinpool_device;

/// Set up count devices from configuration file.
/// Wipe first MiB on each device.
fn get_devices(count: u8) -> Option<Vec<PathBuf>> {
    let file = OpenOptions::new()
        .read(true)
        .open("tests/test_config.json")
        .unwrap();
    let config: Value = from_reader(&file).unwrap();
    let devpaths = config
        .get("ok_to_destroy_dev_array_key")
        .unwrap()
        .as_array()
        .unwrap();
    if devpaths.len() < count as usize {
        return None;
    }
    let devices: Vec<PathBuf> = devpaths
        .iter()
        .take(count as usize)
        .map(|x| PathBuf::from(x.as_str().unwrap()))
        .collect();

    let length = Bytes(IEC::Mi).sectors();
    for device in devices.iter() {
        wipe_sectors(device, Sectors(0), length).unwrap();
    }

    Some(devices)
}

/// Run test on count real devices.
fn test_with_spec<F>(count: u8, test: F) -> ()
    where F: Fn(&[&Path]) -> ()
{
    init_logger();
    let devices = get_devices(count).unwrap();
    let device_paths: Vec<&Path> = devices.iter().map(|x| x.as_path()).collect();
    test(&device_paths);
}

#[test]
pub fn real_test_force_flag_stratis() {
    test_with_spec(2, test_force_flag_stratis);
    test_with_spec(3, test_force_flag_stratis);
}

#[test]
pub fn real_test_linear_device() {
    test_with_spec(2, test_linear_device);
    test_with_spec(3, test_linear_device);
}

#[test]
pub fn real_test_thinpool_device() {
    test_with_spec(3, test_thinpool_device);
}

#[test]
pub fn real_test_pool_blockdevs() {
    test_with_spec(3, test_pool_blockdevs);
}

#[test]
pub fn real_test_force_flag_dirty() {
    test_with_spec(3, test_force_flag_dirty);
}

#[test]
pub fn real_test_teardown() {
    test_with_spec(2, test_teardown);
}

#[test]
pub fn real_test_setup() {
    test_with_spec(4, test_setup);
}

#[test]
pub fn real_test_empty_pool() {
    test_with_spec(0, test_empty_pool)
}

#[test]
pub fn real_test_basic_metadata() {
    test_with_spec(4, test_basic_metadata);
}
<commit_msg>wrap the path to a real device in a struct that implements Drop<commit_after>// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

extern crate devicemapper;
extern crate env_logger;
extern crate libstratis;
extern crate log;
extern crate serde_json;

mod util;

use std::fs::OpenOptions;
use std::path::{Path, PathBuf};

use serde_json::{Value, from_reader};

use self::devicemapper::{Bytes, Sectors};

use libstratis::engine::IEC;
use libstratis::engine::strat_engine::device::wipe_sectors;

use util::logger::init_logger;
use util::simple_tests::test_basic_metadata;
use util::simple_tests::test_empty_pool;
use util::simple_tests::test_force_flag_dirty;
use util::simple_tests::test_force_flag_stratis;
use util::simple_tests::test_linear_device;
use util::simple_tests::test_pool_blockdevs;
use util::simple_tests::test_setup;
use util::simple_tests::test_teardown;
use util::simple_tests::test_thinpool_device;

pub struct RealTestDev {
    path: PathBuf,
}

impl RealTestDev {
    /// Construct a new test device
    pub fn new(path: &str) -> RealTestDev {
        let dev_path = PathBuf::from(path);
        wipe_sectors(dev_path.as_path(), Sectors(0), Bytes(IEC::Mi).sectors()).unwrap();
        RealTestDev { path: dev_path }
    }

    fn as_path(&self) -> &Path {
        &self.path.as_path()
    }
}

impl Drop for RealTestDev {
    fn drop(&mut self) {
        wipe_sectors(self.as_path(), Sectors(0), Bytes(IEC::Mi).sectors()).unwrap();
    }
}

/// Set up count devices from configuration file.
/// Wipe first MiB on each device.
fn get_devices(count: u8) -> Option<Vec<RealTestDev>> {

    let file = OpenOptions::new()
        .read(true)
        .open("tests/test_config.json")
        .unwrap();
    let config: Value = from_reader(&file).unwrap();
    let devpaths = config
        .get("ok_to_destroy_dev_array_key")
        .unwrap()
        .as_array()
        .unwrap();
    if devpaths.len() < count as usize {
        return None;
    }
    let devices: Vec<RealTestDev> = devpaths
        .iter()
        .take(count as usize)
        .map(|x| RealTestDev::new(x.as_str().unwrap()))
        .collect();

    Some(devices)
}

/// Run test on count real devices.
fn test_with_spec<F>(count: u8, test: F) -> ()
    where F: Fn(&[&Path]) -> ()
{
    init_logger();
    let devices = get_devices(count).unwrap();
    let device_paths: Vec<&Path> = devices.iter().map(|x| x.as_path()).collect();
    test(&device_paths);
}

#[test]
pub fn real_test_force_flag_stratis() {
    test_with_spec(2, test_force_flag_stratis);
    test_with_spec(3, test_force_flag_stratis);
}

#[test]
pub fn real_test_linear_device() {
    test_with_spec(2, test_linear_device);
    test_with_spec(3, test_linear_device);
}

#[test]
pub fn real_test_thinpool_device() {
    test_with_spec(3, test_thinpool_device);
}

#[test]
pub fn real_test_pool_blockdevs() {
    test_with_spec(3, test_pool_blockdevs);
}

#[test]
pub fn real_test_force_flag_dirty() {
    test_with_spec(3, test_force_flag_dirty);
}

#[test]
pub fn real_test_teardown() {
    test_with_spec(2, test_teardown);
}

#[test]
pub fn real_test_setup() {
    test_with_spec(4, test_setup);
}

#[test]
pub fn real_test_empty_pool() {
    test_with_spec(0, test_empty_pool)
}

#[test]
pub fn real_test_basic_metadata() {
    test_with_spec(4, test_basic_metadata);
}
<|endoftext|>


<commit_before>// This file is part of Grust, GObject introspection bindings for Rust
//
// Copyright (C) 2015  Mikhail Zabaluev <mikhail.zabaluev@gmail.com>
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

#[macro_use]
extern crate grust;

use grust::value::Value;

use grust::boxed;
use grust::gtype;
use grust::mainloop::MainContext;
use grust::refcount::Ref;
use grust::wrap::Wrapper;

use std::fmt::Write;

#[test]
fn test_string() {
    let mut value = Value::new(gtype::STRING);
    {
        let os = value.get_string();
        assert!(os.is_none());
    }
    value.set_string(g_str!("Hello"));
    {
        let s = value.get_string().unwrap().to_bytes();
        assert_eq!(s, b"Hello");
    }
}

#[test]
fn test_reset() {
    let mut value = Value::new(gtype::STRING);
    value.set_string(g_str!("Hello"));
    value.reset();
    {
        let os = value.get_string();
        assert!(os.is_none());
    }
}

#[test]
fn test_debug() {
    let mut value = Value::new(gtype::STRING);
    value.set_string(g_str!("Hello"));

    let mut dump = String::new();
    write!(&mut dump, "{:?}", value).unwrap();
    assert_eq!(&dump[..], "GValue(\"Hello\")");
}

#[derive(Clone)]
struct MyData(String);

g_type_register_box!(MyData, "GrustTestMyData");

#[test]
fn test_boxed() {
    let mut value = Value::new(boxed::type_of::<Box<MyData>>());
    {
        let os = value.deref_boxed::<Box<MyData>>();
        assert!(os.is_none());
    }
    {
        let ob = value.dup_boxed::<Box<MyData>>();
        assert!(ob.is_none());
    }
    value.take_boxed(Box::new(MyData("Hello!".to_string())));
    let value = value.clone();
    {
        let d = value.deref_boxed::<Box<MyData>>().unwrap();
        let MyData(ref s) = *d;
        assert_eq!(&s[..], "Hello!");
    }
    {
        let b = value.dup_boxed::<Box<MyData>>().unwrap();
        let MyData(ref s) = *b;
        assert_eq!(&s[..], "Hello!");
    }
}

#[test]
#[should_fail]
fn test_deref_boxed_panic() {
    let value = Value::new(gtype::INT);
    let _ = value.deref_boxed::<Box<MyData>>();
}

#[test]
#[should_fail]
fn test_dup_boxed_panic() {
    let value = Value::new(gtype::INT);
    let _ = value.dup_boxed::<Box<MyData>>();
}

#[test]
fn test_boxed_ref() {
    let mut value = Value::new(boxed::type_of::<Ref<MainContext>>());
    value.take_boxed(Ref::new(MainContext::default()));
    let value = value.clone();
    let r = value.deref_boxed::<Ref<MainContext>>().unwrap();
    assert!(r.as_ptr() == MainContext::default().as_ptr());
}
<commit_msg>Test attribute #[should_fail] renamed to #[should_panic]<commit_after>// This file is part of Grust, GObject introspection bindings for Rust
//
// Copyright (C) 2015  Mikhail Zabaluev <mikhail.zabaluev@gmail.com>
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

#[macro_use]
extern crate grust;

use grust::value::Value;

use grust::boxed;
use grust::gtype;
use grust::mainloop::MainContext;
use grust::refcount::Ref;
use grust::wrap::Wrapper;

use std::fmt::Write;

#[test]
fn test_string() {
    let mut value = Value::new(gtype::STRING);
    {
        let os = value.get_string();
        assert!(os.is_none());
    }
    value.set_string(g_str!("Hello"));
    {
        let s = value.get_string().unwrap().to_bytes();
        assert_eq!(s, b"Hello");
    }
}

#[test]
fn test_reset() {
    let mut value = Value::new(gtype::STRING);
    value.set_string(g_str!("Hello"));
    value.reset();
    {
        let os = value.get_string();
        assert!(os.is_none());
    }
}

#[test]
fn test_debug() {
    let mut value = Value::new(gtype::STRING);
    value.set_string(g_str!("Hello"));

    let mut dump = String::new();
    write!(&mut dump, "{:?}", value).unwrap();
    assert_eq!(&dump[..], "GValue(\"Hello\")");
}

#[derive(Clone)]
struct MyData(String);

g_type_register_box!(MyData, "GrustTestMyData");

#[test]
fn test_boxed() {
    let mut value = Value::new(boxed::type_of::<Box<MyData>>());
    {
        let os = value.deref_boxed::<Box<MyData>>();
        assert!(os.is_none());
    }
    {
        let ob = value.dup_boxed::<Box<MyData>>();
        assert!(ob.is_none());
    }
    value.take_boxed(Box::new(MyData("Hello!".to_string())));
    let value = value.clone();
    {
        let d = value.deref_boxed::<Box<MyData>>().unwrap();
        let MyData(ref s) = *d;
        assert_eq!(&s[..], "Hello!");
    }
    {
        let b = value.dup_boxed::<Box<MyData>>().unwrap();
        let MyData(ref s) = *b;
        assert_eq!(&s[..], "Hello!");
    }
}

#[test]
#[should_panic]
fn test_deref_boxed_panic() {
    let value = Value::new(gtype::INT);
    let _ = value.deref_boxed::<Box<MyData>>();
}

#[test]
#[should_panic]
fn test_dup_boxed_panic() {
    let value = Value::new(gtype::INT);
    let _ = value.dup_boxed::<Box<MyData>>();
}

#[test]
fn test_boxed_ref() {
    let mut value = Value::new(boxed::type_of::<Ref<MainContext>>());
    value.take_boxed(Ref::new(MainContext::default()));
    let value = value.clone();
    let r = value.deref_boxed::<Ref<MainContext>>().unwrap();
    assert!(r.as_ptr() == MainContext::default().as_ptr());
}
<|endoftext|>


<commit_before>//! A double-ended iterator over entity references and entities.

use EntityRef;
use std::marker::PhantomData;
use std::slice;

/// Iterate over all keys in order.
pub struct Iter<'a, K: EntityRef, V>
where
    V: 'a,
{
    pos: usize,
    rev_pos: usize,
    iter: slice::Iter<'a, V>,
    unused: PhantomData<K>,
}

impl<'a, K: EntityRef, V> Iter<'a, K, V> {
    /// Create an `Iter` iterator that visits the `PrimaryMap` keys and values
    /// of `iter`.
    pub fn new(iter: slice::Iter<'a, V>) -> Self {
        Self {
            pos: 0,
            rev_pos: iter.len(),
            iter,
            unused: PhantomData,
        }
    }
}

impl<'a, K: EntityRef, V> Iterator for Iter<'a, K, V> {
    type Item = (K, &'a V);

    fn next(&mut self) -> Option<Self::Item> {
        if let Some(next) = self.iter.next() {
            let pos = self.pos;
            self.pos += 1;
            Some((K::new(pos), next))
        } else {
            None
        }
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        self.iter.size_hint()
    }
}

impl<'a, K: EntityRef, V> DoubleEndedIterator for Iter<'a, K, V> {
    fn next_back(&mut self) -> Option<Self::Item> {
        if let Some(next_back) = self.iter.next_back() {
            let rev_pos = self.rev_pos - 1;
            self.rev_pos -= 1;
            Some((K::new(rev_pos), next_back))
        } else {
            None
        }
    }
}

impl<'a, K: EntityRef, V> ExactSizeIterator for Iter<'a, K, V> {}

/// Iterate over all keys in order.
pub struct IterMut<'a, K: EntityRef, V>
where
    V: 'a,
{
    pos: usize,
    rev_pos: usize,
    iter: slice::IterMut<'a, V>,
    unused: PhantomData<K>,
}

impl<'a, K: EntityRef, V> IterMut<'a, K, V> {
    /// Create an `IterMut` iterator that visits the `PrimaryMap` keys and values
    /// of `iter`.
    pub fn new(iter: slice::IterMut<'a, V>) -> Self {
        Self {
            pos: 0,
            rev_pos: iter.len(),
            iter,
            unused: PhantomData,
        }
    }
}

impl<'a, K: EntityRef, V> Iterator for IterMut<'a, K, V> {
    type Item = (K, &'a mut V);

    fn next(&mut self) -> Option<Self::Item> {
        if let Some(next) = self.iter.next() {
            let pos = self.pos;
            self.pos += 1;
            Some((K::new(pos), next))
        } else {
            None
        }
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        self.iter.size_hint()
    }
}

impl<'a, K: EntityRef, V> DoubleEndedIterator for IterMut<'a, K, V> {
    fn next_back(&mut self) -> Option<Self::Item> {
        if let Some(next_back) = self.iter.next_back() {
            let rev_pos = self.rev_pos - 1;
            self.rev_pos -= 1;
            Some((K::new(rev_pos), next_back))
        } else {
            None
        }
    }
}

impl<'a, K: EntityRef, V> ExactSizeIterator for IterMut<'a, K, V> {}
<commit_msg>Implement entity's `Iter` in terms of `std::iter::Enumerate`.<commit_after>//! A double-ended iterator over entity references and entities.

use EntityRef;
use std::iter::Enumerate;
use std::marker::PhantomData;
use std::slice;

/// Iterate over all keys in order.
pub struct Iter<'a, K: EntityRef, V>
where
    V: 'a,
{
    enumerate: Enumerate<slice::Iter<'a, V>>,
    unused: PhantomData<K>,
}

impl<'a, K: EntityRef, V> Iter<'a, K, V> {
    /// Create an `Iter` iterator that visits the `PrimaryMap` keys and values
    /// of `iter`.
    pub fn new(iter: slice::Iter<'a, V>) -> Self {
        Self {
            enumerate: iter.enumerate(),
            unused: PhantomData,
        }
    }
}

impl<'a, K: EntityRef, V> Iterator for Iter<'a, K, V> {
    type Item = (K, &'a V);

    fn next(&mut self) -> Option<Self::Item> {
        self.enumerate.next().map(|(i, v)| (K::new(i), v))
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        self.enumerate.size_hint()
    }
}

impl<'a, K: EntityRef, V> DoubleEndedIterator for Iter<'a, K, V> {
    fn next_back(&mut self) -> Option<Self::Item> {
        self.enumerate.next_back().map(|(i, v)| (K::new(i), v))
    }
}

impl<'a, K: EntityRef, V> ExactSizeIterator for Iter<'a, K, V> {}

/// Iterate over all keys in order.
pub struct IterMut<'a, K: EntityRef, V>
where
    V: 'a,
{
    enumerate: Enumerate<slice::IterMut<'a, V>>,
    unused: PhantomData<K>,
}

impl<'a, K: EntityRef, V> IterMut<'a, K, V> {
    /// Create an `IterMut` iterator that visits the `PrimaryMap` keys and values
    /// of `iter`.
    pub fn new(iter: slice::IterMut<'a, V>) -> Self {
        Self {
            enumerate: iter.enumerate(),
            unused: PhantomData,
        }
    }
}

impl<'a, K: EntityRef, V> Iterator for IterMut<'a, K, V> {
    type Item = (K, &'a mut V);

    fn next(&mut self) -> Option<Self::Item> {
        self.enumerate.next().map(|(i, v)| (K::new(i), v))
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        self.enumerate.size_hint()
    }
}

impl<'a, K: EntityRef, V> DoubleEndedIterator for IterMut<'a, K, V> {
    fn next_back(&mut self) -> Option<Self::Item> {
        self.enumerate.next_back().map(|(i, v)| (K::new(i), v))
    }
}

impl<'a, K: EntityRef, V> ExactSizeIterator for IterMut<'a, K, V> {}
<|endoftext|>


<commit_before>//! Items Entity

mod path;
mod kind;
mod item;
mod content;

use std::collections::BTreeMap;
use hyper::method::Method;
use serde_json::{self, Value};
use ::connection::Connection;
use ::odata::Parameters;
use ::api::MultiOption;
use ::{Result, Error};

pub use self::path::Path;
pub use self::kind::Kind;
pub use self::item::Item;
pub use self::content::Content;

/// Items Entity implementation.
///
/// Items struct implemets methods of [Items API Entity](http://api.sharefile.com/rest/docs/resource.aspx?name=Items)
pub struct Items {
	conn: Connection,
	meta: bool,
}

impl Items {
	/// Create a new instance of Item Entities API
	pub fn new(conn: Connection) -> Self {
		Items {
			conn: conn,
			meta: false,
		}
	}

	/// Set the flag to inform all future API requests to include item meta information
	/// or omit it.
	pub fn include_meta(&mut self, include: bool) {
		self.meta = include;
	}

	/// Resolve given `path` to the Item ID. On success returns `Some(Path::Id(id))`
	// and None otherwise.
	pub fn resolve_path(&self, path: Path) -> Option<Path> {
		if let &Path::Id(_) = &path {
			// The path is the ID already
			Some(path)
		}
		else {
			// Resolve the path to the ID
			match self.stat(path, None) {
				Ok(MultiOption::One(item)) => Some(item.path()),
				_ => None
			}
		}
	}

	/// Search for Item(s) at the `path` given and return found. `parameters` can be used
	/// to provide additional options to the API request, like `includeDeleted`.
	pub fn stat(&self, path: Path, parameters: Option<Parameters>) -> Result<MultiOption<Item>> {
		self.query_items(path.entity_and_parameters(None, parameters))
	}

	/// List all items at the `path` given. `parameters` can be used
	/// to provide additional options to the API request, like `includeDeleted`.
	pub fn list(&self, path: Path, parameters: Option<Parameters>) -> Result<MultiOption<Item>> {
		match self.stat(path, None) {
			Ok(MultiOption::One(item)) => match item.kind {
				Kind::Folder => {
					self.query_items(item.path().entity_and_parameters(Some("/Children"), parameters))
				},
				Kind::File => {
					Ok(MultiOption::One(item))
				}
			},
			Ok(other) => Ok(other),
			Err(err) => err.result()
		}
	}

	/// Create folder with `parent` item and `name` given. On success returns the `Path` with the ID
	/// of the folder created.
	pub fn mkdir<T>(&self, parent: Path, name: T, description: Option<T>, overwite: bool) -> Result<Path>
	where T: Into<String> {
		if let Some(path) = self.resolve_path(parent) {
			// Prepare folder details
			let mut data = BTreeMap::new();
			data.insert(String::from("Name"), Value::String(name.into()));

			if let Some(desc) = description {
				data.insert(String::from("Description"), Value::String(desc.into()));
			}

			let body = Value::Object(data);

			// Create folder
			let parameters = Parameters::new()
				.custom(vec![
					("overwrite", super::bool_to_string(overwite)),
					("passthrough", String::from("false")) ]);

			let url = path.entity_and_parameters(Some("/Folder"), Some(parameters));

			self.conn.query_post(url, Some(body))
				.and_then(|r| Error::from_json(r))
				.and_then(|v| Path::from_json(v))
		}
		else {
			Error::new("Cannot resolve parent ID").result()
		}
	}

	/// Removes the item with the ID given. `single_version` set to `true` will delete
	/// only the specified version rather than all sibling files with the same filename
	/// and `force_sync` set to `true` will block the operation from taking place
	/// asynchronously.
	pub fn remove(&self, path: Path, single_version: bool, force_sync: bool) -> Result<()> {
		self.resolve_path(path)
			.ok_or(Error::new("The Item is not found"))
			.and_then(|path| {
				let parameters = Parameters::new()
					.custom(vec![
						("singleversion", super::bool_to_string(single_version)),
						("forceSync", super::bool_to_string(force_sync)) ]);

				let url = path.entity_and_parameters(None, Some(parameters));

				self.conn.query_delete(url)
					.map(|_| ())
			})
	}

	/// Download the item identified by `path`. The method returns reader which can be used
	/// to read data in any convenient manner.
	///
	/// The snippet of how the remote file can be downloaded to local.
	///
	/// ```ignore
	/// // Lets assume we have the opened connection already
	/// let path = Path::Absolute("/my_folder/remote_file.txt");
	///	let mut stream = conn.items().download(path).unwrap();
	/// let mut file = File::create("local_file.txt").unwrap();
	/// let mut buf = [0; 1024];
	/// loop {
	/// 	match stream.read(&mut buf) {
	///			Ok(0) => break, // Zero bytes mean the end of file
	///			Ok(n) => file.write_all(&buf[0..n]).unwrap(),
	///			Err(err) => panic!("{:?}", err)
	///		};
	///	}
	/// ```
	pub fn download(&self, path: Path) -> Result<Content> {
		if let Path::Id(id) = path {
			// We have the ID alredy so just start download
			Content::open_for_read(self.conn.clone(), id)
		}
		else {
			// We have a path which should be resolved to the id first
			match self.stat(path, None) {
				Ok(MultiOption::One(item)) => Content::open_for_read(self.conn.clone(), item.id),
				Ok(MultiOption::Many(_)) => Error::new("There are more than one Item on path").result(),
				Ok(MultiOption::None) => Error::new("The Item is not found").result(),
				Err(err) => err.result()
			}
		}
	}

	// Do API request which returns Item Collection (GET)
	fn query_items(&self, uri: String) -> Result<MultiOption<Item>> {
		match self.conn.query_string(Method::Get, uri, None, None) {
			Ok(ref json) => match serde_json::from_str(json) {
				Ok(data) => Item::from_value(data, self.meta),
				Err(err) => Error::new("JSON parse failed").because(err).result()
			},
			Err(err) => err.result()
		}
	}
}
<commit_msg>Add items Bulk Delete<commit_after>//! Items Entity

mod path;
mod kind;
mod item;
mod content;

use std::collections::BTreeMap;
use hyper::method::Method;
use serde_json::{self, Value};
use ::connection::Connection;
use ::odata::Parameters;
use ::api::MultiOption;
use ::{Result, Error};

pub use self::path::Path;
pub use self::kind::Kind;
pub use self::item::Item;
pub use self::content::Content;

/// Items Entity implementation.
///
/// Items struct implemets methods of [Items API Entity](http://api.sharefile.com/rest/docs/resource.aspx?name=Items)
pub struct Items {
	conn: Connection,
	meta: bool,
}

impl Items {
	/// Create a new instance of Item Entities API
	pub fn new(conn: Connection) -> Self {
		Items {
			conn: conn,
			meta: false,
		}
	}

	/// Set the flag to inform all future API requests to include item meta information
	/// or omit it.
	pub fn include_meta(&mut self, include: bool) {
		self.meta = include;
	}

	/// Resolve given `path` to the Item ID. On success returns `Some(Path::Id(id))`
	// and None otherwise.
	pub fn resolve_path(&self, path: Path) -> Option<Path> {
		if let &Path::Id(_) = &path {
			// The path is the ID already
			Some(path)
		}
		else {
			// Resolve the path to the ID
			match self.stat(path, None) {
				Ok(MultiOption::One(item)) => Some(item.path()),
				_ => None
			}
		}
	}

	/// Search for Item(s) at the `path` given and return found. `parameters` can be used
	/// to provide additional options to the API request, like `includeDeleted`.
	pub fn stat(&self, path: Path, parameters: Option<Parameters>) -> Result<MultiOption<Item>> {
		self.query_items(path.entity_and_parameters(None, parameters))
	}

	/// List all items at the `path` given. `parameters` can be used
	/// to provide additional options to the API request, like `includeDeleted`.
	pub fn list(&self, path: Path, parameters: Option<Parameters>) -> Result<MultiOption<Item>> {
		match self.stat(path, None) {
			Ok(MultiOption::One(item)) => match item.kind {
				Kind::Folder => {
					self.query_items(item.path().entity_and_parameters(Some("/Children"), parameters))
				},
				Kind::File => {
					Ok(MultiOption::One(item))
				}
			},
			Ok(other) => Ok(other),
			Err(err) => err.result()
		}
	}

	/// Create folder with `parent` item and `name` given. On success returns the `Path` with the ID
	/// of the folder created.
	pub fn mkdir<T>(&self, parent: Path, name: T, description: Option<T>, overwite: bool) -> Result<Path>
	where T: Into<String> {
		if let Some(path) = self.resolve_path(parent) {
			// Prepare folder details
			let mut data = BTreeMap::new();
			data.insert(String::from("Name"), Value::String(name.into()));

			if let Some(desc) = description {
				data.insert(String::from("Description"), Value::String(desc.into()));
			}

			let body = Value::Object(data);

			// Create folder
			let parameters = Parameters::new()
				.custom(vec![
					("overwrite", super::bool_to_string(overwite)),
					("passthrough", String::from("false")) ]);

			let url = path.entity_and_parameters(Some("/Folder"), Some(parameters));

			self.conn.query_post(url, Some(body))
				.and_then(|r| Error::from_json(r))
				.and_then(|v| Path::from_json(v))
		}
		else {
			Error::new("Cannot resolve parent ID").result()
		}
	}

	/// Removes the item with the ID given. `single_version` set to `true` will delete
	/// only the specified version rather than all sibling files with the same filename
	/// and `force_sync` set to `true` will block the operation from taking place
	/// asynchronously.
	pub fn remove(&self, path: Path, single_version: bool, force_sync: bool) -> Result<()> {
		self.resolve_path(path)
			.ok_or(Error::new("The Item is not found"))
			.and_then(|path| {
				let parameters = Parameters::new()
					.custom(vec![
						("singleversion", super::bool_to_string(single_version)),
						("forceSync", super::bool_to_string(force_sync)) ]);

				let url = path.entity_and_parameters(None, Some(parameters));

				self.conn.query_delete(url)
					.map(|_| ())
			})
	}

	/// Removes multiple items. All items in bulk delete must be children of the same parent.
	/// `delete_premanently` set to `true` will remove items from
	/// the Recycle Bin or bypass it entirely and `force_sync` set to `true` will block
	/// the operation from taking place asynchronously.
	pub fn remove_bulk(&self, parent: Path, items: Vec<Path>, delete_premanently: bool, force_sync: bool) -> Result<()> {
		self.resolve_path(parent)
			.ok_or(Error::new("The Parent Item is not found"))
			.and_then(|parent| {
				// Prepare item list
				let items: Vec<Value> = items.into_iter()
					.map(|path| self.resolve_path(path)) // Resolve each Path into an Item ID
					.filter(|path| path.is_some()) // Remove not resolved Paths
					.map(|path| path.unwrap()) // Extract Paths from Option
					.filter(|path| path.is_id()) // Remove those Paths which does not contain the ID
					.map(|path| Value::String(path.id())) // Extract Item IDs and convert into Value::String
					.collect();

				let body = Value::Array(items);

				// Perform Bulk Delete
				let parameters = Parameters::new()
					.custom(vec![
						("deletePermanently", super::bool_to_string(delete_premanently)),
						("forceSync", super::bool_to_string(force_sync)) ]);

				let url = parent.entity_and_parameters(Some("/BulkDelete"), Some(parameters));

				self.conn.query_post(url, Some(body))
					.and_then(|r| Error::from_json(r))
					.map(|_| ())
			})
	}

	/// Download the item identified by `path`. The method returns reader which can be used
	/// to read data in any convenient manner.
	///
	/// The snippet of how the remote file can be downloaded to local.
	///
	/// ```ignore
	/// // Lets assume we have the opened connection already
	/// let path = Path::Absolute("/my_folder/remote_file.txt");
	///	let mut stream = conn.items().download(path).unwrap();
	/// let mut file = File::create("local_file.txt").unwrap();
	/// let mut buf = [0; 1024];
	/// loop {
	/// 	match stream.read(&mut buf) {
	///			Ok(0) => break, // Zero bytes mean the end of file
	///			Ok(n) => file.write_all(&buf[0..n]).unwrap(),
	///			Err(err) => panic!("{:?}", err)
	///		};
	///	}
	/// ```
	pub fn download(&self, path: Path) -> Result<Content> {
		if let Path::Id(id) = path {
			// We have the ID alredy so just start download
			Content::open_for_read(self.conn.clone(), id)
		}
		else {
			// We have a path which should be resolved to the id first
			match self.stat(path, None) {
				Ok(MultiOption::One(item)) => Content::open_for_read(self.conn.clone(), item.id),
				Ok(MultiOption::Many(_)) => Error::new("There are more than one Item on path").result(),
				Ok(MultiOption::None) => Error::new("The Item is not found").result(),
				Err(err) => err.result()
			}
		}
	}

	// Do API request which returns Item Collection (GET)
	fn query_items(&self, uri: String) -> Result<MultiOption<Item>> {
		match self.conn.query_string(Method::Get, uri, None, None) {
			Ok(ref json) => match serde_json::from_str(json) {
				Ok(data) => Item::from_value(data, self.meta),
				Err(err) => Error::new("JSON parse failed").because(err).result()
			},
			Err(err) => err.result()
		}
	}
}
<|endoftext|>


<commit_before>extern crate csv;

use csv::Writer;

fn main() {
    println!("24 days of Rust - csv (day 3)");
    let dollar_films = vec![
        ("A Fistful of Dollars", "Rojo", 1964u),
        ("For a Few Dollars More", "El Indio", 1965u),
        ("The Good, the Bad and the Ugly", "Tuco", 1966u),
    ];
    let path = Path::new("westerns.csv");
    let mut writer = Writer::from_file(&path);
    for row in dollar_films.into_iter() {
        writer.encode(row).ok().expect("CSV writer error");
    }
}
<commit_msg>Struct and Reader example.<commit_after>extern crate csv;
extern crate serialize;

use csv::{Reader, Writer};

#[deriving(Decodable, Encodable)]
struct Movie {
    title: String,
    bad_guy: String,
    pub_year: uint,
}

fn main() {
    println!("24 days of Rust - csv (day 3)");
    let dollar_films = vec![
        ("A Fistful of Dollars", "Rojo", 1964u),
        ("For a Few Dollars More", "El Indio", 1965u),
        ("The Good, the Bad and the Ugly", "Tuco", 1966u),
    ];
    let path = Path::new("westerns.csv");
    let mut writer = Writer::from_file(&path);
    for row in dollar_films.into_iter() {
        writer.encode(row).ok().expect("CSV writer error");
    }
    let movie = Movie {
        title: "Hang 'Em High".to_string(),
        bad_guy: "Wilson".to_string(),
        pub_year: 1968u,
    };
    writer.encode(movie).ok().expect("CSV writer error");
    writer.flush().ok().expect("Flush error");
    let mut reader = Reader::from_file(&path).has_headers(false);
    for row in reader.decode() {
        let row: (String, String, uint) = row.unwrap();
        println!("{}", row);
    }
    let mut reader = Reader::from_file(&path).has_headers(false);
    for row in reader.decode() {
        let movie: Movie = row.unwrap();
        println!("{} was a bad guy in '{}' in {}",
            movie.bad_guy, movie.title, movie.pub_year);
    }
}
<|endoftext|>


<commit_before>// Dependency Graph Library in Rust

//! dglr is a Dependency Graph Library in Rust.
//! In short, you register elements and their dependencies, and then
//! ask for the dependencies of any element in an order that satisfies.
//!
//! Elements are simply &str strings.  You register them with
//! register_dependency() or register_dependencies().
//!
//! Dependenies are (currently) just a list of other elements that
//! the element in question depends on.  [In the future, we may add
//! boolean logic, but currently they are all AND-ed together].
//!
//! Then iterate over .iter() to get the ordered dependencies, and
//! the library does the magic and returns an order which will work.
//! It is possible that other orders also work, but the library's
//! algorithm is deterministic, so you'll always get the same
//! particular one.

#![crate_name = "dglr"]
#![crate_type = "lib"]

// Required for log and rustdoc:
#![feature(phase)]
#[phase(plugin, link)]

extern crate log;

use std::collections::{HashMap,HashSet};
use std::collections::hash_map::{Occupied,Vacant};
use std::iter::{Iterator};
#[allow(unused_imports)]
use std::task;

/// This is the dependency graph.  You can create it yourself, or
/// use the convenience methods of new(), register_dependency() and
/// register_dependencies() to build one up (that must be mutable).
pub struct DepGraph {
    /// List of dependencies.  Key is the element, values are the
    /// other elements that the key element depends upon.
    pub dependencies: HashMap<String,Vec<String>>,

    // (private) target we are trying to satisfy
    target: Option<String>,

    // (private) elements already satisfied
    satisfied: HashSet<String>,

    // (private) current path, for cycle detection
    curpath: HashSet<String>,
}

pub struct DepGraphIterator<'a> {
    depgraph: &'a mut DepGraph
}
pub struct DepGraphSatisfyingIterator<'a> {
    depgraph: &'a mut DepGraph
}

impl DepGraph {

    /// Create an empty DepGraph.
    pub fn new() -> DepGraph
    {
        DepGraph {
            dependencies: HashMap::new(),
            target: None,
            curpath: HashSet::new(),
            satisfied: HashSet::new(),
        }
    }

    /// Add a dependency to a DepGraph.  The thing does not need
    /// to pre-exist, nor do the dependency elements.  But if the
    /// thing does pre-exist, the depends_on will be added to its
    /// existing dependency list.
    pub fn register_dependency<'a>( &mut self,
                                thing: &'a str,
                                depends_on: &'a str )
    {
        match self.dependencies.entry( String::from_str(thing) ) {
            Vacant(entry) => { entry.set( vec![String::from_str(depends_on)] ); },
            Occupied(mut entry) => { (*entry.get_mut()).push(String::from_str(depends_on)); },
        }
    }

    /// Add multiple dependencies of one thing to a DepGraph.  The
    /// thing does not need to pre-exist, nor do the dependency elements.
    /// But if the thing does pre-exist, the depends_on will be added
    /// to its existing dependency list.
    pub fn register_dependencies<'a>( &mut self,
                                  thing: &'a str,
                                  depends_on: &'a[&'a str] )
    {
        let newvec: Vec<String> = depends_on.iter().map(
            |s| String::from_str(*s)).collect();

        match self.dependencies.entry( String::from_str(thing) ) {
            Vacant(entry) => { entry.set( newvec.clone() ); },
            Occupied(mut entry) => { (*entry.get_mut()).push_all(newvec.as_slice()); },
        }
    }

    pub fn set_target<'a>( &mut self, target: &'a str )
    {
        self.target = Some(String::from_str(target));
    }

    pub fn mark_as_satisfied<'a>( &mut self,
                                   things: &'a[&'a str] )
    {
        for thing in things.iter() {
            self.satisfied.insert(String::from_str(*thing));
        }
    }

    fn get_next_dependency(&mut self, thing: &String) -> String
    {
        if self.curpath.contains(thing) {
            panic!("Circular dependency graph at {}",thing);
        }
        self.curpath.insert(thing.clone());

        let deplist = match self.dependencies.get(thing) {
            None => return thing.clone(),
            Some(deplist) => deplist.clone() // ouch
        };

        for n in deplist.iter() {
            if self.satisfied.contains(n) {
                continue;
            }
            return self.get_next_dependency(n);
        }
        // things dependencies are satisfied
        thing.clone()
    }

    pub fn iter<'a>(&'a mut self) -> DepGraphIterator<'a>
    {
        DepGraphIterator {
            depgraph: self
        }
    }

    pub fn satisfying_iter<'a>(&'a mut self) -> DepGraphSatisfyingIterator<'a>
    {
        DepGraphSatisfyingIterator {
            depgraph: self
        }
    }
}

impl<'a> Iterator<String> for DepGraphIterator<'a> {
    fn next(&mut self) -> Option<String>
    {
        let thing = match self.depgraph.target {
            None => return None,
            Some(ref thing) => thing.clone()
        };
        if self.depgraph.satisfied.contains(&thing) {
            return None;
        }
        self.depgraph.curpath.clear();
        Some(self.depgraph.get_next_dependency(&thing))
    }
}

impl<'a> Iterator<String> for DepGraphSatisfyingIterator<'a> {
    fn next(&mut self) -> Option<String>
    {
        let thing = match self.depgraph.target {
            None => return None,
            Some(ref thing) => thing.clone()
        };
        if self.depgraph.satisfied.contains(&thing) {
            return None;
        }
        self.depgraph.curpath.clear();
        let next = self.depgraph.get_next_dependency(&thing);
        self.depgraph.mark_as_satisfied(&[next.as_slice()]);
        Some(next)
    }
}

#[test]
fn dglr_test_branching() {
    let mut depgraph: DepGraph = DepGraph::new();

    depgraph.register_dependencies("a",&["b","c","d"]);
    depgraph.register_dependency("b","d");
    depgraph.register_dependencies("c",&["e","m","g"]);
    depgraph.register_dependency("e","f");
    depgraph.register_dependency("g","h");
    depgraph.register_dependency("h","i");
    depgraph.register_dependencies("i",&["j","k"]);
    depgraph.register_dependencies("k",&["l","m"]);
    depgraph.register_dependency("m","n");

    depgraph.set_target("a");

    let mut results: Vec<String> = Vec::new();

    loop {
        // detect infinite looping bugs
        assert!(results.len() < 30);

        let thing = match depgraph.iter().next() {
            Some(x) => x,
            None => break,
        };
        depgraph.mark_as_satisfied([thing.as_slice()]);
        results.push(thing);
    }

    assert!( results == vec![String::from_str("d"),
                             String::from_str("b"),
                             String::from_str("f"),
                             String::from_str("e"),
                             String::from_str("n"),
                             String::from_str("m"),
                             String::from_str("j"),
                             String::from_str("l"),
                             String::from_str("k"),
                             String::from_str("i"),
                             String::from_str("h"),
                             String::from_str("g"),
                             String::from_str("c"),
                             String::from_str("a")] );
    //info!("Deps of a = {}",results);
}

#[test]
fn dglr_test_satisfying() {
    let mut depgraph: DepGraph = DepGraph::new();

    depgraph.register_dependencies("a",&["b","c","d"]);
    depgraph.register_dependency("b","d");
    depgraph.register_dependencies("c",&["e"]);

    depgraph.set_target("a");

    let mut results: Vec<String> = Vec::new();

    for thing in depgraph.satisfying_iter() {
        // detect infinite looping bugs
        assert!(results.len() < 30);
        results.push(thing);
    }

    assert!( results == vec![String::from_str("d"),
                             String::from_str("b"),
                             String::from_str("e"),
                             String::from_str("c"),
                             String::from_str("a")] );
    //info!("Deps of a = {}",results);
}

#[test]
fn dglr_test_circular() {

    let task_result = task::try(proc() {
        let mut depgraph: DepGraph = DepGraph::new();
        depgraph.register_dependency("a","b");
        depgraph.register_dependency("b","c");
        depgraph.register_dependency("c","a");
        depgraph.set_target("a");

        let mut results: Vec<String> = Vec::new();

        loop {
            // Detect infinite looping bugs by
            // breaking out successfully (successful
            // proc() means failed test!)
            if results.len() >= 30 { break; }

            let thing = match depgraph.iter().next() {
                Some(x) => x,
                None => break,
            };
            depgraph.mark_as_satisfied([thing.as_slice()]);
            results.push(thing);
        }
    });
    match task_result {
        Ok(_) => panic!("Should have failed at the circular dependency!"),
        Err(_) => () //info!("Successfully detected the circular dependency (ignore task failure)"),
    };
}

#[test]
fn dglr_test_satisfied_stoppage() {

    let mut depgraph: DepGraph = DepGraph::new();
    depgraph.register_dependencies("superconn", []);
    depgraph.register_dependencies("owneruser", ["superconn"]);
    depgraph.register_dependencies("appuser", ["superconn"]);
    depgraph.register_dependencies("database", ["owneruser"]);
    depgraph.register_dependencies("ownerconn", ["database","owneruser"]);
    depgraph.register_dependencies("adminconn", ["database"]);
    depgraph.register_dependencies("extensions", ["database","adminconn"]);
    depgraph.register_dependencies("schema_table", ["database","ownerconn"]);
    depgraph.register_dependencies("schemas", ["ownerconn","extensions","schema_table","appuser"]);
    depgraph.register_dependencies("appconn", ["database","appuser","schemas"]);

    depgraph.set_target("appconn");
    depgraph.mark_as_satisfied(["owneruser","appuser"]);

    let mut results: Vec<String> = Vec::new();

    loop {
        assert!(results.len() < 30);

        let thing = match depgraph.iter().next() {
            Some(x) => x,
            None => break,
        };
        depgraph.mark_as_satisfied([thing.as_slice()]);
        results.push(thing);
    }
    assert!( !results.contains(&String::from_str("superconn")) );
}
<commit_msg>upstream rust: replace proc() with move||<commit_after>// Dependency Graph Library in Rust

//! dglr is a Dependency Graph Library in Rust.
//! In short, you register elements and their dependencies, and then
//! ask for the dependencies of any element in an order that satisfies.
//!
//! Elements are simply &str strings.  You register them with
//! register_dependency() or register_dependencies().
//!
//! Dependenies are (currently) just a list of other elements that
//! the element in question depends on.  [In the future, we may add
//! boolean logic, but currently they are all AND-ed together].
//!
//! Then iterate over .iter() to get the ordered dependencies, and
//! the library does the magic and returns an order which will work.
//! It is possible that other orders also work, but the library's
//! algorithm is deterministic, so you'll always get the same
//! particular one.

#![crate_name = "dglr"]
#![crate_type = "lib"]

// Required for log and rustdoc:
#![feature(phase)]
#[phase(plugin, link)]

extern crate log;

use std::collections::{HashMap,HashSet};
use std::collections::hash_map::{Occupied,Vacant};
use std::iter::{Iterator};
#[allow(unused_imports)]
use std::task;

/// This is the dependency graph.  You can create it yourself, or
/// use the convenience methods of new(), register_dependency() and
/// register_dependencies() to build one up (that must be mutable).
pub struct DepGraph {
    /// List of dependencies.  Key is the element, values are the
    /// other elements that the key element depends upon.
    pub dependencies: HashMap<String,Vec<String>>,

    // (private) target we are trying to satisfy
    target: Option<String>,

    // (private) elements already satisfied
    satisfied: HashSet<String>,

    // (private) current path, for cycle detection
    curpath: HashSet<String>,
}

pub struct DepGraphIterator<'a> {
    depgraph: &'a mut DepGraph
}
pub struct DepGraphSatisfyingIterator<'a> {
    depgraph: &'a mut DepGraph
}

impl DepGraph {

    /// Create an empty DepGraph.
    pub fn new() -> DepGraph
    {
        DepGraph {
            dependencies: HashMap::new(),
            target: None,
            curpath: HashSet::new(),
            satisfied: HashSet::new(),
        }
    }

    /// Add a dependency to a DepGraph.  The thing does not need
    /// to pre-exist, nor do the dependency elements.  But if the
    /// thing does pre-exist, the depends_on will be added to its
    /// existing dependency list.
    pub fn register_dependency<'a>( &mut self,
                                thing: &'a str,
                                depends_on: &'a str )
    {
        match self.dependencies.entry( String::from_str(thing) ) {
            Vacant(entry) => { entry.set( vec![String::from_str(depends_on)] ); },
            Occupied(mut entry) => { (*entry.get_mut()).push(String::from_str(depends_on)); },
        }
    }

    /// Add multiple dependencies of one thing to a DepGraph.  The
    /// thing does not need to pre-exist, nor do the dependency elements.
    /// But if the thing does pre-exist, the depends_on will be added
    /// to its existing dependency list.
    pub fn register_dependencies<'a>( &mut self,
                                  thing: &'a str,
                                  depends_on: &'a[&'a str] )
    {
        let newvec: Vec<String> = depends_on.iter().map(
            |s| String::from_str(*s)).collect();

        match self.dependencies.entry( String::from_str(thing) ) {
            Vacant(entry) => { entry.set( newvec.clone() ); },
            Occupied(mut entry) => { (*entry.get_mut()).push_all(newvec.as_slice()); },
        }
    }

    pub fn set_target<'a>( &mut self, target: &'a str )
    {
        self.target = Some(String::from_str(target));
    }

    pub fn mark_as_satisfied<'a>( &mut self,
                                   things: &'a[&'a str] )
    {
        for thing in things.iter() {
            self.satisfied.insert(String::from_str(*thing));
        }
    }

    fn get_next_dependency(&mut self, thing: &String) -> String
    {
        if self.curpath.contains(thing) {
            panic!("Circular dependency graph at {}",thing);
        }
        self.curpath.insert(thing.clone());

        let deplist = match self.dependencies.get(thing) {
            None => return thing.clone(),
            Some(deplist) => deplist.clone() // ouch
        };

        for n in deplist.iter() {
            if self.satisfied.contains(n) {
                continue;
            }
            return self.get_next_dependency(n);
        }
        // things dependencies are satisfied
        thing.clone()
    }

    pub fn iter<'a>(&'a mut self) -> DepGraphIterator<'a>
    {
        DepGraphIterator {
            depgraph: self
        }
    }

    pub fn satisfying_iter<'a>(&'a mut self) -> DepGraphSatisfyingIterator<'a>
    {
        DepGraphSatisfyingIterator {
            depgraph: self
        }
    }
}

impl<'a> Iterator<String> for DepGraphIterator<'a> {
    fn next(&mut self) -> Option<String>
    {
        let thing = match self.depgraph.target {
            None => return None,
            Some(ref thing) => thing.clone()
        };
        if self.depgraph.satisfied.contains(&thing) {
            return None;
        }
        self.depgraph.curpath.clear();
        Some(self.depgraph.get_next_dependency(&thing))
    }
}

impl<'a> Iterator<String> for DepGraphSatisfyingIterator<'a> {
    fn next(&mut self) -> Option<String>
    {
        let thing = match self.depgraph.target {
            None => return None,
            Some(ref thing) => thing.clone()
        };
        if self.depgraph.satisfied.contains(&thing) {
            return None;
        }
        self.depgraph.curpath.clear();
        let next = self.depgraph.get_next_dependency(&thing);
        self.depgraph.mark_as_satisfied(&[next.as_slice()]);
        Some(next)
    }
}

#[test]
fn dglr_test_branching() {
    let mut depgraph: DepGraph = DepGraph::new();

    depgraph.register_dependencies("a",&["b","c","d"]);
    depgraph.register_dependency("b","d");
    depgraph.register_dependencies("c",&["e","m","g"]);
    depgraph.register_dependency("e","f");
    depgraph.register_dependency("g","h");
    depgraph.register_dependency("h","i");
    depgraph.register_dependencies("i",&["j","k"]);
    depgraph.register_dependencies("k",&["l","m"]);
    depgraph.register_dependency("m","n");

    depgraph.set_target("a");

    let mut results: Vec<String> = Vec::new();

    loop {
        // detect infinite looping bugs
        assert!(results.len() < 30);

        let thing = match depgraph.iter().next() {
            Some(x) => x,
            None => break,
        };
        depgraph.mark_as_satisfied([thing.as_slice()]);
        results.push(thing);
    }

    assert!( results == vec![String::from_str("d"),
                             String::from_str("b"),
                             String::from_str("f"),
                             String::from_str("e"),
                             String::from_str("n"),
                             String::from_str("m"),
                             String::from_str("j"),
                             String::from_str("l"),
                             String::from_str("k"),
                             String::from_str("i"),
                             String::from_str("h"),
                             String::from_str("g"),
                             String::from_str("c"),
                             String::from_str("a")] );
    //info!("Deps of a = {}",results);
}

#[test]
fn dglr_test_satisfying() {
    let mut depgraph: DepGraph = DepGraph::new();

    depgraph.register_dependencies("a",&["b","c","d"]);
    depgraph.register_dependency("b","d");
    depgraph.register_dependencies("c",&["e"]);

    depgraph.set_target("a");

    let mut results: Vec<String> = Vec::new();

    for thing in depgraph.satisfying_iter() {
        // detect infinite looping bugs
        assert!(results.len() < 30);
        results.push(thing);
    }

    assert!( results == vec![String::from_str("d"),
                             String::from_str("b"),
                             String::from_str("e"),
                             String::from_str("c"),
                             String::from_str("a")] );
    //info!("Deps of a = {}",results);
}

#[test]
fn dglr_test_circular() {

    let task_result = task::try(move|| {
        let mut depgraph: DepGraph = DepGraph::new();
        depgraph.register_dependency("a","b");
        depgraph.register_dependency("b","c");
        depgraph.register_dependency("c","a");
        depgraph.set_target("a");

        let mut results: Vec<String> = Vec::new();

        loop {
            // Detect infinite looping bugs by
            // breaking out successfully (successful
            // move|| means failed test!)
            if results.len() >= 30 { break; }

            let thing = match depgraph.iter().next() {
                Some(x) => x,
                None => break,
            };
            depgraph.mark_as_satisfied([thing.as_slice()]);
            results.push(thing);
        }
    });
    match task_result {
        Ok(_) => panic!("Should have failed at the circular dependency!"),
        Err(_) => () //info!("Successfully detected the circular dependency (ignore task failure)"),
    };
}

#[test]
fn dglr_test_satisfied_stoppage() {

    let mut depgraph: DepGraph = DepGraph::new();
    depgraph.register_dependencies("superconn", []);
    depgraph.register_dependencies("owneruser", ["superconn"]);
    depgraph.register_dependencies("appuser", ["superconn"]);
    depgraph.register_dependencies("database", ["owneruser"]);
    depgraph.register_dependencies("ownerconn", ["database","owneruser"]);
    depgraph.register_dependencies("adminconn", ["database"]);
    depgraph.register_dependencies("extensions", ["database","adminconn"]);
    depgraph.register_dependencies("schema_table", ["database","ownerconn"]);
    depgraph.register_dependencies("schemas", ["ownerconn","extensions","schema_table","appuser"]);
    depgraph.register_dependencies("appconn", ["database","appuser","schemas"]);

    depgraph.set_target("appconn");
    depgraph.mark_as_satisfied(["owneruser","appuser"]);

    let mut results: Vec<String> = Vec::new();

    loop {
        assert!(results.len() < 30);

        let thing = match depgraph.iter().next() {
            Some(x) => x,
            None => break,
        };
        depgraph.mark_as_satisfied([thing.as_slice()]);
        results.push(thing);
    }
    assert!( !results.contains(&String::from_str("superconn")) );
}
<|endoftext|>