<commit_before>
use std;
use input;
use event::{
    GenericEvent,
    PressEvent,
    ReleaseEvent,
    UpdateEvent,
};
use {
    Action,
    After,
    AlwaysSucceed,
    Behavior,
    Failure,
    If,
    Fail,
    Pressed,
    Released,
    Running,
    Select,
    Sequence,
    Status,
    Success,
    Wait,
    WaitForever,
    WhenAll,
    WhenAny,
    While,
};

pub static RUNNING: (Status, f64) = (Running, 0.0);

/// Keeps track of a behavior.
#[deriving(Clone, Decodable, Encodable, PartialEq)]
pub enum State<A, S> {
    /// Returns `Success` when button is pressed.
    PressedState(input::Button),
    /// Returns `Success` when button is released.
    ReleasedState(input::Button),
    /// Executes an action.
    ActionState(A, Option<S>),
    /// Converts `Success` into `Failure` and vice versa.
    FailState(Box<State<A, S>>),
    /// Ignores failures and always return `Success`.
    AlwaysSucceedState(Box<State<A, S>>),
    /// Keeps track of waiting for a period of time before continuing.
    ///
    /// f64: Total time in seconds to wait
    ///
    /// f64: Time elapsed in seconds
    WaitState(f64, f64),
    /// Waits forever.
    WaitForeverState,
    /// Keeps track of an `If` behavior.
    /// If status is `Running`, then it evaluates the condition.
    /// If status is `Success`, then it evaluates the success behavior.
    /// If status is `Failure`, then it evaluates the failure behavior.
    IfState(Box<Behavior<A>>, Box<Behavior<A>>, Status, Box<State<A, S>>),
    /// Keeps track of a `Select` behavior.
    SelectState(Vec<Behavior<A>>, uint, Box<State<A, S>>),
    /// Keeps track of an `Sequence` behavior.
    SequenceState(Vec<Behavior<A>>, uint, Box<State<A, S>>),
    /// Keeps track of a `While` behavior.
    WhileState(Box<State<A, S>>, Vec<Behavior<A>>, uint, Box<State<A, S>>),
    /// Keeps track of a `WhenAll` behavior.
    WhenAllState(Vec<Option<State<A, S>>>),
    /// Keeps track of a `WhenAny` behavior.
    WhenAnyState(Vec<Option<State<A, S>>>),
    /// Keeps track of an `After` behavior.
    AfterState(uint, Vec<State<A, S>>),
}

// `Sequence` and `Select` share same algorithm.
//
// `Sequence` fails if any fails and succeeds when all succeeds.
// `Select` succeeds if any succeeds and fails when all fails.
fn sequence<A: Clone, S, E: GenericEvent>(
    select: bool,
    upd: Option<f64>,
    seq: &Vec<Behavior<A>>,
    i: &mut uint,
    cursor: &mut Box<State<A, S>>,
    e: &E,
    f: |e: &E, dt: f64, action: &A, state: &mut Option<S>| -> (Status, f64)
) -> (Status, f64) {
    let (status, inv_status) = if select {
        // `Select`
        (Failure, Success)
    } else {
        // `Sequence`
        (Success, Failure)
    };
    let mut remaining_dt = upd.unwrap_or(0.0);
    let mut remaining_e;
    while *i < seq.len() {
        match cursor.event(
            match upd {
                Some(_) => {
                    remaining_e = UpdateEvent::from_dt(remaining_dt).unwrap();
                    &remaining_e
                }
                _ => e
            },
            |e, dt, a, s| f(e, dt, a, s)) {
            (Running, _) => { break; },
            (s, new_dt) if s == inv_status => {
                return (inv_status, new_dt);
            }
            (s, new_dt) if s == status => {
                remaining_dt = match upd {
                    // Change update event with remaining delta time.
                    Some(_) => new_dt,
                    // Other events are 'consumed' and not passed to next.
                    // If this is the last event, then the sequence succeeded.
                    _ => if *i == seq.len() - 1 {
                            return (status, new_dt)
                        } else {
                            return RUNNING
                        }
                }
            }
            _ => unreachable!()
        };
        *i += 1;
        // If end of sequence,
        // return the 'dt' that is left.
        if *i >= seq.len() { return (status, remaining_dt); }
        // Create a new cursor for next event.
        // Use the same pointer to avoid allocation.
        **cursor  = State::new(seq[*i].clone());
    }
    RUNNING
}

// `WhenAll` and `WhenAny` share same algorithm.
//
// `WhenAll` fails if any fails and succeeds when all succeeds.
// `WhenAny` succeeds if any succeeds and fails when all fails.
fn when_all<A: Clone, S, E: GenericEvent>(
    any: bool,
    upd: Option<f64>,
    cursors: &mut Vec<Option<State<A, S>>>,
    e: &E,
    f: |e: &E, dt: f64, action: &A, state: &mut Option<S>| -> (Status, f64)
) -> (Status, f64) {
    let (status, inv_status) = if any {
        // `WhenAny`
        (Failure, Success)
    } else {
        // `WhenAll`
        (Success, Failure)
    };
    // Get the least delta time left over.
    let mut min_dt = std::f64::MAX_VALUE;
    // Count number of terminated events.
    let mut terminated = 0;
    for cur in cursors.iter_mut() {
        match *cur {
            None => {}
            Some(ref mut cur) => {
                match cur.event(e, |e, dt, a, s| f(e, dt, a, s)) {
                    (Running, _) => { continue; },
                    (s, new_dt) if s == inv_status => {
                        // Fail for `WhenAll`.
                        // Succeed for `WhenAny`.
                        return (inv_status, new_dt);
                    }
                    (s, new_dt) if s == status => {
                        min_dt = min_dt.min(new_dt);
                    }
                    _ => unreachable!()
                }
            }
        }

        terminated += 1;
        *cur = None;
    }
    match terminated {
        // If there are no events, there is a whole 'dt' left.
        0 if cursors.len() == 0 => (status, match upd {
                Some(dt) => dt,
                // Other kind of events happen instantly.
                _ => 0.0
            }),
        // If all events terminated, the least delta time is left.
        n if cursors.len() == n => (status, min_dt),
        _ => RUNNING
    }
}

impl<A: Clone, S> State<A, S> {
    /// Creates a state from a behavior.
    pub fn new(behavior: Behavior<A>) -> State<A, S> {
        match behavior {
            Pressed(button) => PressedState(button),
            Released(button) => ReleasedState(button),
            Action(action) => ActionState(action, None),
            Fail(ev) => FailState(box State::new(*ev)),
            AlwaysSucceed(ev) => AlwaysSucceedState(box State::new(*ev)),
            Wait(dt) => WaitState(dt, 0.0),
            WaitForever => WaitForeverState,
            If(condition, success, failure) => {
                let state = State::new(*condition);
                IfState(success, failure, Running, box state)
            }
            Select(sel) => {
                let state = State::new(sel[0].clone());
                SelectState(sel, 0, box state)
            }
            Sequence(seq) => {
                let state = State::new(seq[0].clone());
                SequenceState(seq, 0, box state)
            }
            While(ev, rep) => {
                let state = State::new(rep[0].clone());
                WhileState(box State::new(*ev), rep, 0, box state)
            }
            WhenAll(all)
                => WhenAllState(all.into_iter().map(
                    |ev| Some(State::new(ev))).collect()),
            WhenAny(all)
                => WhenAnyState(all.into_iter().map(
                    |ev| Some(State::new(ev))).collect()),
            After(seq)
                => AfterState(0, seq.into_iter().map(
                    |ev| State::new(ev)).collect()),
        }
    }

    /// Updates the cursor that tracks an event.
    ///
    /// The action need to return status and remaining delta time.
    /// Returns status and the remaining delta time.
    pub fn event<E: GenericEvent>(
        &mut self,
        e: &E,
        f: |e: &E, dt: f64, action: &A, state: &mut Option<S>| -> (Status, f64)
    ) -> (Status, f64) {
        let upd = e.update(|args| Some(args.dt)).unwrap_or(None);
        match (upd, self) {
            (None, &PressedState(button)) => {
                e.press(|button_pressed| {
                    if button_pressed != button { return RUNNING; }

                    // Button press is considered to happen instantly.
                    // There is no remaining delta time because
                    // this is input event.
                    (Success, 0.0)
                }).unwrap_or(RUNNING)
            }
            (None, &ReleasedState(button)) => {
                e.release(|button_released| {
                    if button_released != button { return RUNNING; }

                    // Button release is considered to happen instantly.
                    // There is no remaining delta time because
                    // this is input event.
                    (Success, 0.0)
                }).unwrap_or(RUNNING)
            }
            (_, &ActionState(ref action, ref mut state)) => {
                // Execute action.
                f(e, upd.unwrap_or(0.0), action, state)
            }
            (_, &FailState(ref mut cur)) => {
                match cur.event(e, f) {
                    (Running, dt) => (Running, dt),
                    (Failure, dt) => (Success, dt),
                    (Success, dt) => (Failure, dt),
                }
            }
            (_, &AlwaysSucceedState(ref mut cur)) => {
                match cur.event(e, f) {
                    (Running, dt) => (Running, dt),
                    (_, dt) => (Success, dt),
                }
            }
            (Some(dt), &WaitState(wait_t, ref mut t)) => {
                if *t + dt >= wait_t {
                    let remaining_dt = *t + dt - wait_t;
                    *t = wait_t;
                    (Success, remaining_dt)
                } else {
                    *t += dt;
                    RUNNING
                }
            }
            (_, &IfState(ref success, ref failure,
                         ref mut status, ref mut state)) => {
                let mut remaining_dt = upd.unwrap_or(0.0);
                let mut remaining_e;
                // Run in a loop to evaluate success or failure with
                // remaining delta time after condition.
                loop {
                    *status = match *status {
                        Running => {
                            match state.event(e, |e, dt, a, s| f(e, dt, a, s)) {
                                (Running, dt) => { return (Running, dt); },
                                (Success, dt) => {
                                    **state = State::new((**success).clone());
                                    remaining_dt = dt;
                                    Success
                                }
                                (Failure, dt) => {
                                    **state = State::new((**failure).clone());
                                    remaining_dt = dt;
                                    Failure
                                }
                            }
                        }
                        _ => {
                            return state.event(match upd {
                                Some(_) => {
                                    remaining_e = UpdateEvent::from_dt(
                                        remaining_dt).unwrap();
                                    &remaining_e
                                }
                                _ => e
                            }, |e, dt, a, s| f(e, dt, a, s));
                        }
                    }
                }
            }
            (_, &SelectState(ref seq, ref mut i, ref mut cursor)) => {
                let select = true;
                sequence(select, upd, seq, i, cursor, e, f)
            }
            (_, &SequenceState(ref seq, ref mut i, ref mut cursor)) => {
                let select = false;
                sequence(select, upd, seq, i, cursor, e, f)
            }
            (_, &WhileState(ref mut ev_cursor, ref rep, ref mut i,
                            ref mut cursor)) => {
                // If the event terminates, do not execute the loop.
                match ev_cursor.event(e, |e, dt, a, s| f(e, dt, a, s)) {
                    (Running, _) => {}
                    x => return x,
                };
                let cur = cursor;
                let mut remaining_dt = upd.unwrap_or(0.0);
                let mut remaining_e;
                loop {
                    match cur.event(match upd {
                            Some(_) => {
                                remaining_e = UpdateEvent::from_dt(
                                    remaining_dt).unwrap();
                                &remaining_e
                            }
                            _ => e
                        },
                        |e, dt, a, s| f(e, dt, a, s)) {
                        (Failure, x) => return (Failure, x),
                        (Running, _) => { break },
                        (Success, new_dt) => {
                            remaining_dt = match upd {
                                // Change update event with remaining delta time.
                                Some(_) => new_dt,
                                // Other events are 'consumed' and not passed to next.
                                _ => return RUNNING
                            }
                        }
                    };
                    *i += 1;
                    // If end of repeated events,
                    // start over from the first one.
                    if *i >= rep.len() { *i = 0; }
                    // Create a new cursor for next event.
                    // Use the same pointer to avoid allocation.
                    **cur = State::new(rep[*i].clone());
                }
                RUNNING
            }
            (_, &WhenAllState(ref mut cursors)) => {
                let any = false;
                when_all(any, upd, cursors, e, f)
            }
            (_, &WhenAnyState(ref mut cursors)) => {
                let any = true;
                when_all(any, upd, cursors, e, f)
            }
            (_, &AfterState(ref mut i, ref mut cursors)) => {
                // Get the least delta time left over.
                let mut min_dt = std::f64::MAX_VALUE;
                for j in range(*i, cursors.len()) {
                    match cursors[j].event(
                        e, |e, dt, a, s| f(e, dt, a, s)
                    ) {
                        (Running, _) => { min_dt = 0.0; }
                        (Success, new_dt) => {
                            // Remaining delta time must be less to succeed.
                            if *i == j && new_dt < min_dt {
                                *i += 1;
                                min_dt = new_dt;
                            } else {
                                // Return least delta time because
                                // that is when failure is detected.
                                return (Failure, min_dt.min(new_dt));
                            }
                        }
                        (Failure, new_dt) => {
                            return (Failure, new_dt);
                        }
                    };
                }
                if *i == cursors.len() {
                    (Success, min_dt)
                } else {
                    RUNNING
                }
            }
            _ => RUNNING
        }
    }
}
<commit_msg>Use FloatMath - fixes recent nightly change #9<commit_after>
use std;
use input;
use event::{
    GenericEvent,
    PressEvent,
    ReleaseEvent,
    UpdateEvent,
};
use {
    Action,
    After,
    AlwaysSucceed,
    Behavior,
    Failure,
    If,
    Fail,
    Pressed,
    Released,
    Running,
    Select,
    Sequence,
    Status,
    Success,
    Wait,
    WaitForever,
    WhenAll,
    WhenAny,
    While,
};
use std::num::FloatMath;

pub static RUNNING: (Status, f64) = (Running, 0.0);

/// Keeps track of a behavior.
#[deriving(Clone, Decodable, Encodable, PartialEq)]
pub enum State<A, S> {
    /// Returns `Success` when button is pressed.
    PressedState(input::Button),
    /// Returns `Success` when button is released.
    ReleasedState(input::Button),
    /// Executes an action.
    ActionState(A, Option<S>),
    /// Converts `Success` into `Failure` and vice versa.
    FailState(Box<State<A, S>>),
    /// Ignores failures and always return `Success`.
    AlwaysSucceedState(Box<State<A, S>>),
    /// Keeps track of waiting for a period of time before continuing.
    ///
    /// f64: Total time in seconds to wait
    ///
    /// f64: Time elapsed in seconds
    WaitState(f64, f64),
    /// Waits forever.
    WaitForeverState,
    /// Keeps track of an `If` behavior.
    /// If status is `Running`, then it evaluates the condition.
    /// If status is `Success`, then it evaluates the success behavior.
    /// If status is `Failure`, then it evaluates the failure behavior.
    IfState(Box<Behavior<A>>, Box<Behavior<A>>, Status, Box<State<A, S>>),
    /// Keeps track of a `Select` behavior.
    SelectState(Vec<Behavior<A>>, uint, Box<State<A, S>>),
    /// Keeps track of an `Sequence` behavior.
    SequenceState(Vec<Behavior<A>>, uint, Box<State<A, S>>),
    /// Keeps track of a `While` behavior.
    WhileState(Box<State<A, S>>, Vec<Behavior<A>>, uint, Box<State<A, S>>),
    /// Keeps track of a `WhenAll` behavior.
    WhenAllState(Vec<Option<State<A, S>>>),
    /// Keeps track of a `WhenAny` behavior.
    WhenAnyState(Vec<Option<State<A, S>>>),
    /// Keeps track of an `After` behavior.
    AfterState(uint, Vec<State<A, S>>),
}

// `Sequence` and `Select` share same algorithm.
//
// `Sequence` fails if any fails and succeeds when all succeeds.
// `Select` succeeds if any succeeds and fails when all fails.
fn sequence<A: Clone, S, E: GenericEvent>(
    select: bool,
    upd: Option<f64>,
    seq: &Vec<Behavior<A>>,
    i: &mut uint,
    cursor: &mut Box<State<A, S>>,
    e: &E,
    f: |e: &E, dt: f64, action: &A, state: &mut Option<S>| -> (Status, f64)
) -> (Status, f64) {
    let (status, inv_status) = if select {
        // `Select`
        (Failure, Success)
    } else {
        // `Sequence`
        (Success, Failure)
    };
    let mut remaining_dt = upd.unwrap_or(0.0);
    let mut remaining_e;
    while *i < seq.len() {
        match cursor.event(
            match upd {
                Some(_) => {
                    remaining_e = UpdateEvent::from_dt(remaining_dt).unwrap();
                    &remaining_e
                }
                _ => e
            },
            |e, dt, a, s| f(e, dt, a, s)) {
            (Running, _) => { break; },
            (s, new_dt) if s == inv_status => {
                return (inv_status, new_dt);
            }
            (s, new_dt) if s == status => {
                remaining_dt = match upd {
                    // Change update event with remaining delta time.
                    Some(_) => new_dt,
                    // Other events are 'consumed' and not passed to next.
                    // If this is the last event, then the sequence succeeded.
                    _ => if *i == seq.len() - 1 {
                            return (status, new_dt)
                        } else {
                            return RUNNING
                        }
                }
            }
            _ => unreachable!()
        };
        *i += 1;
        // If end of sequence,
        // return the 'dt' that is left.
        if *i >= seq.len() { return (status, remaining_dt); }
        // Create a new cursor for next event.
        // Use the same pointer to avoid allocation.
        **cursor  = State::new(seq[*i].clone());
    }
    RUNNING
}

// `WhenAll` and `WhenAny` share same algorithm.
//
// `WhenAll` fails if any fails and succeeds when all succeeds.
// `WhenAny` succeeds if any succeeds and fails when all fails.
fn when_all<A: Clone, S, E: GenericEvent>(
    any: bool,
    upd: Option<f64>,
    cursors: &mut Vec<Option<State<A, S>>>,
    e: &E,
    f: |e: &E, dt: f64, action: &A, state: &mut Option<S>| -> (Status, f64)
) -> (Status, f64) {
    let (status, inv_status) = if any {
        // `WhenAny`
        (Failure, Success)
    } else {
        // `WhenAll`
        (Success, Failure)
    };
    // Get the least delta time left over.
    let mut min_dt = std::f64::MAX_VALUE;
    // Count number of terminated events.
    let mut terminated = 0;
    for cur in cursors.iter_mut() {
        match *cur {
            None => {}
            Some(ref mut cur) => {
                match cur.event(e, |e, dt, a, s| f(e, dt, a, s)) {
                    (Running, _) => { continue; },
                    (s, new_dt) if s == inv_status => {
                        // Fail for `WhenAll`.
                        // Succeed for `WhenAny`.
                        return (inv_status, new_dt);
                    }
                    (s, new_dt) if s == status => {
                        min_dt = min_dt.min(new_dt);
                    }
                    _ => unreachable!()
                }
            }
        }

        terminated += 1;
        *cur = None;
    }
    match terminated {
        // If there are no events, there is a whole 'dt' left.
        0 if cursors.len() == 0 => (status, match upd {
                Some(dt) => dt,
                // Other kind of events happen instantly.
                _ => 0.0
            }),
        // If all events terminated, the least delta time is left.
        n if cursors.len() == n => (status, min_dt),
        _ => RUNNING
    }
}

impl<A: Clone, S> State<A, S> {
    /// Creates a state from a behavior.
    pub fn new(behavior: Behavior<A>) -> State<A, S> {
        match behavior {
            Pressed(button) => PressedState(button),
            Released(button) => ReleasedState(button),
            Action(action) => ActionState(action, None),
            Fail(ev) => FailState(box State::new(*ev)),
            AlwaysSucceed(ev) => AlwaysSucceedState(box State::new(*ev)),
            Wait(dt) => WaitState(dt, 0.0),
            WaitForever => WaitForeverState,
            If(condition, success, failure) => {
                let state = State::new(*condition);
                IfState(success, failure, Running, box state)
            }
            Select(sel) => {
                let state = State::new(sel[0].clone());
                SelectState(sel, 0, box state)
            }
            Sequence(seq) => {
                let state = State::new(seq[0].clone());
                SequenceState(seq, 0, box state)
            }
            While(ev, rep) => {
                let state = State::new(rep[0].clone());
                WhileState(box State::new(*ev), rep, 0, box state)
            }
            WhenAll(all)
                => WhenAllState(all.into_iter().map(
                    |ev| Some(State::new(ev))).collect()),
            WhenAny(all)
                => WhenAnyState(all.into_iter().map(
                    |ev| Some(State::new(ev))).collect()),
            After(seq)
                => AfterState(0, seq.into_iter().map(
                    |ev| State::new(ev)).collect()),
        }
    }

    /// Updates the cursor that tracks an event.
    ///
    /// The action need to return status and remaining delta time.
    /// Returns status and the remaining delta time.
    pub fn event<E: GenericEvent>(
        &mut self,
        e: &E,
        f: |e: &E, dt: f64, action: &A, state: &mut Option<S>| -> (Status, f64)
    ) -> (Status, f64) {
        let upd = e.update(|args| Some(args.dt)).unwrap_or(None);
        match (upd, self) {
            (None, &PressedState(button)) => {
                e.press(|button_pressed| {
                    if button_pressed != button { return RUNNING; }

                    // Button press is considered to happen instantly.
                    // There is no remaining delta time because
                    // this is input event.
                    (Success, 0.0)
                }).unwrap_or(RUNNING)
            }
            (None, &ReleasedState(button)) => {
                e.release(|button_released| {
                    if button_released != button { return RUNNING; }

                    // Button release is considered to happen instantly.
                    // There is no remaining delta time because
                    // this is input event.
                    (Success, 0.0)
                }).unwrap_or(RUNNING)
            }
            (_, &ActionState(ref action, ref mut state)) => {
                // Execute action.
                f(e, upd.unwrap_or(0.0), action, state)
            }
            (_, &FailState(ref mut cur)) => {
                match cur.event(e, f) {
                    (Running, dt) => (Running, dt),
                    (Failure, dt) => (Success, dt),
                    (Success, dt) => (Failure, dt),
                }
            }
            (_, &AlwaysSucceedState(ref mut cur)) => {
                match cur.event(e, f) {
                    (Running, dt) => (Running, dt),
                    (_, dt) => (Success, dt),
                }
            }
            (Some(dt), &WaitState(wait_t, ref mut t)) => {
                if *t + dt >= wait_t {
                    let remaining_dt = *t + dt - wait_t;
                    *t = wait_t;
                    (Success, remaining_dt)
                } else {
                    *t += dt;
                    RUNNING
                }
            }
            (_, &IfState(ref success, ref failure,
                         ref mut status, ref mut state)) => {
                let mut remaining_dt = upd.unwrap_or(0.0);
                let mut remaining_e;
                // Run in a loop to evaluate success or failure with
                // remaining delta time after condition.
                loop {
                    *status = match *status {
                        Running => {
                            match state.event(e, |e, dt, a, s| f(e, dt, a, s)) {
                                (Running, dt) => { return (Running, dt); },
                                (Success, dt) => {
                                    **state = State::new((**success).clone());
                                    remaining_dt = dt;
                                    Success
                                }
                                (Failure, dt) => {
                                    **state = State::new((**failure).clone());
                                    remaining_dt = dt;
                                    Failure
                                }
                            }
                        }
                        _ => {
                            return state.event(match upd {
                                Some(_) => {
                                    remaining_e = UpdateEvent::from_dt(
                                        remaining_dt).unwrap();
                                    &remaining_e
                                }
                                _ => e
                            }, |e, dt, a, s| f(e, dt, a, s));
                        }
                    }
                }
            }
            (_, &SelectState(ref seq, ref mut i, ref mut cursor)) => {
                let select = true;
                sequence(select, upd, seq, i, cursor, e, f)
            }
            (_, &SequenceState(ref seq, ref mut i, ref mut cursor)) => {
                let select = false;
                sequence(select, upd, seq, i, cursor, e, f)
            }
            (_, &WhileState(ref mut ev_cursor, ref rep, ref mut i,
                            ref mut cursor)) => {
                // If the event terminates, do not execute the loop.
                match ev_cursor.event(e, |e, dt, a, s| f(e, dt, a, s)) {
                    (Running, _) => {}
                    x => return x,
                };
                let cur = cursor;
                let mut remaining_dt = upd.unwrap_or(0.0);
                let mut remaining_e;
                loop {
                    match cur.event(match upd {
                            Some(_) => {
                                remaining_e = UpdateEvent::from_dt(
                                    remaining_dt).unwrap();
                                &remaining_e
                            }
                            _ => e
                        },
                        |e, dt, a, s| f(e, dt, a, s)) {
                        (Failure, x) => return (Failure, x),
                        (Running, _) => { break },
                        (Success, new_dt) => {
                            remaining_dt = match upd {
                                // Change update event with remaining delta time.
                                Some(_) => new_dt,
                                // Other events are 'consumed' and not passed to next.
                                _ => return RUNNING
                            }
                        }
                    };
                    *i += 1;
                    // If end of repeated events,
                    // start over from the first one.
                    if *i >= rep.len() { *i = 0; }
                    // Create a new cursor for next event.
                    // Use the same pointer to avoid allocation.
                    **cur = State::new(rep[*i].clone());
                }
                RUNNING
            }
            (_, &WhenAllState(ref mut cursors)) => {
                let any = false;
                when_all(any, upd, cursors, e, f)
            }
            (_, &WhenAnyState(ref mut cursors)) => {
                let any = true;
                when_all(any, upd, cursors, e, f)
            }
            (_, &AfterState(ref mut i, ref mut cursors)) => {
                // Get the least delta time left over.
                let mut min_dt = std::f64::MAX_VALUE;
                for j in range(*i, cursors.len()) {
                    match cursors[j].event(
                        e, |e, dt, a, s| f(e, dt, a, s)
                    ) {
                        (Running, _) => { min_dt = 0.0; }
                        (Success, new_dt) => {
                            // Remaining delta time must be less to succeed.
                            if *i == j && new_dt < min_dt {
                                *i += 1;
                                min_dt = new_dt;
                            } else {
                                // Return least delta time because
                                // that is when failure is detected.
                                return (Failure, min_dt.min(new_dt));
                            }
                        }
                        (Failure, new_dt) => {
                            return (Failure, new_dt);
                        }
                    };
                }
                if *i == cursors.len() {
                    (Success, min_dt)
                } else {
                    RUNNING
                }
            }
            _ => RUNNING
        }
    }
}
<|endoftext|>


<commit_before>// Copyright © 2016, Canal TP and/or its affiliates. All rights reserved.
//
// This file is part of Navitia,
//     the software to build cool stuff with public transport.
//
// Hope you'll enjoy and contribute to this project,
//     powered by Canal TP (www.canaltp.fr).
// Help us simplify mobility and open public transport:
//     a non ending quest to the responsive locomotion way of traveling!
//
// LICENCE: This program is free software; you can redistribute it
// and/or modify it under the terms of the GNU Affero General Public
// License as published by the Free Software Foundation, either
// version 3 of the License, or (at your option) any later version.
//
// This program 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
// Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public
// License along with this program. If not, see
// <http://www.gnu.org/licenses/>.
//
// Stay tuned using
// twitter @navitia
// IRC #navitia on freenode
// https://groups.google.com/d/forum/navitia
// www.navitia.io

use std::rc::Rc;
use mimir::rubber::{Rubber, TypedIndex};
use utils::{format_label, get_zip_codes_from_admins};
use mimir;
use admin_geofinder::AdminGeoFinder;
use std::collections::HashMap;
use std::mem::replace;

const GLOBAL_STOP_INDEX_NAME: &'static str = "munin_global_stops";

pub fn set_weights<'a, It>(stops: It, nb_stop_points: &HashMap<String, u32>)
where
    It: Iterator<Item = &'a mut mimir::Stop>,
{
    let max = *nb_stop_points.values().max().unwrap_or(&1) as f64;
    for stop in stops {
        stop.weight = if let Some(weight) = nb_stop_points.get(&stop.id) {
            *weight as f64 / max
        } else {
            0.
        };
    }
}

pub fn import_stops(mut stops: Vec<mimir::Stop>, connection_string: &str, dataset: &str) {
    info!("creation of indexes");
    let mut rubber = Rubber::new(connection_string);
    rubber.initialize_templates().unwrap();

    attach_stops_to_admins(stops.iter_mut(), &mut rubber);

    for stop in &mut stops {
        stop.coverages.push(dataset.to_string());
    }

    let global_index = update_global_stop_index(&mut rubber, stops.iter(), dataset).unwrap();

    info!("Importing {} stops into Mimir", stops.len());
    let nb_stops = rubber.index(dataset, stops.iter()).unwrap();
    info!("Nb of indexed stops: {}", nb_stops);

    publish_global_index(&mut rubber, &global_index).unwrap();
}

fn attach_stop(stop: &mut mimir::Stop, admins: Vec<Rc<mimir::Admin>>) {
    stop.administrative_regions = admins;
    stop.label = format_label(&stop.administrative_regions, &stop.name);
    stop.zip_codes = get_zip_codes_from_admins(&stop.administrative_regions);
}

/// Attach the stops to administrative regions
///
/// The admins are loaded from Elasticsearch and stored in a quadtree
/// We attach a stop with all the admins that have a boundary containing
/// the coordinate of the stop
fn attach_stops_to_admins<'a, It: Iterator<Item = &'a mut mimir::Stop>>(
    stops: It,
    rubber: &mut Rubber,
) {
    let admins = rubber.get_all_admins().unwrap_or_else(|_| {
        info!("Administratives regions not found in elasticsearch db");
        vec![]
    });

    info!("{} administrative regions loaded from mimir", admins.len());

    let admins_geofinder = admins.into_iter().collect::<AdminGeoFinder>();

    let mut nb_unmatched = 0u32;
    let mut nb_matched = 0u32;
    for mut stop in stops {
        let admins = admins_geofinder.get(&stop.coord);

        if admins.is_empty() {
            nb_unmatched += 1;
        } else {
            nb_matched += 1;
        }

        attach_stop(&mut stop, admins);
    }

    info!(
        "there are {}/{} stops without any admin",
        nb_unmatched,
        nb_matched + nb_unmatched
    );
}
fn merge_collection<T: Ord>(target: &mut Vec<T>, source: Vec<T>) {
    use std::collections::BTreeSet;
    let tmp = replace(target, vec![]);
    *target = tmp.into_iter()
        .chain(source)
        .collect::<BTreeSet<_>>()
        .into_iter()
        .collect();
}

/// merge the stops from all the different indexes
/// for the moment the merge is very simple and uses only the ID
/// (and we take the data from the first stop inserted)
fn merge_stops<It: IntoIterator<Item = mimir::Stop>>(
    stops: It,
) -> Box<Iterator<Item = mimir::Stop>> {
    let mut stops_by_id = HashMap::<String, mimir::Stop>::new();
    for mut stop in stops.into_iter() {
        let cov = replace(&mut stop.coverages, vec![]);
        let mut codes = replace(&mut stop.codes, vec![]);
        let mut physical_modes = replace(&mut stop.physical_modes, vec![]);
        let mut commercial_modes = replace(&mut stop.commercial_modes, vec![]);
        let mut properties = replace(&mut stop.properties, vec![]);

        let mut stop_in_map = stops_by_id.entry(stop.id.clone()).or_insert(stop);

        merge_collection(&mut stop_in_map.codes, codes);
        merge_collection(&mut stop_in_map.physical_modes, physical_modes);
        merge_collection(&mut stop_in_map.commercial_modes, commercial_modes);
        merge_collection(&mut stop_in_map.coverages, cov);
        merge_collection(&mut stop_in_map.properties, properties);
    }
    Box::new(stops_by_id.into_iter().map(|(_, v)| v))
}

fn get_all_stops(rubber: &mut Rubber, index: String) -> Result<Vec<mimir::Stop>, String> {
    rubber
        .get_all_objects_from_index(&index)
        .map_err(|e| e.to_string())
}

fn update_global_stop_index<'a, It: Iterator<Item = &'a mimir::Stop>>(
    rubber: &mut Rubber,
    stops: It,
    dataset: &str,
) -> Result<String, String> {
    let dataset_index = mimir::rubber::get_main_type_and_dataset_index::<mimir::Stop>(dataset);
    let stops_indexes = rubber
        .get_all_aliased_index(&mimir::rubber::get_main_type_index::<mimir::Stop>())?
        .into_iter()
        .filter(|&(_, ref aliases)| !aliases.contains(&dataset_index))
        .map(|(index, _)| index);

    let all_other_es_stops: Vec<_> = stops_indexes
        .map(|index| get_all_stops(rubber, index).unwrap())
        .flat_map(|stops| stops.into_iter())
        .collect();

    let all_es_stops = all_other_es_stops
        .into_iter()
        .chain(stops.into_iter().cloned());

    let all_merged_stops = merge_stops(all_es_stops);
    let es_index_name = mimir::rubber::get_date_index_name(GLOBAL_STOP_INDEX_NAME);

    rubber.create_index(&es_index_name)?;
    let typed_index = TypedIndex::new(es_index_name.clone());

    let nb_stops_added = rubber
        .bulk_index(&typed_index, all_merged_stops)
        .map_err(|e| e.to_string())?;
    info!("{} stops added in the global index", nb_stops_added);
    // create global index
    // fill structure for each stop indexes
    Ok(es_index_name)
}

// publish the global stop index
// alias the new index to the global stop alias, and remove the old index
fn publish_global_index(rubber: &mut Rubber, new_global_index: &str) -> Result<(), String> {
    let last_global_indexes: Vec<_> = rubber
        .get_all_aliased_index(GLOBAL_STOP_INDEX_NAME)?
        .into_iter()
        .map(|(k, _)| k)
        .filter(|k| k != new_global_index)
        .collect();
    rubber.alias(
        GLOBAL_STOP_INDEX_NAME,
        &vec![new_global_index.to_string()],
        &last_global_indexes,
    )?;

    for index in last_global_indexes {
        rubber.delete_index(&index)?;
    }
    Ok(())
}
<commit_msg>remove useless mut<commit_after>// Copyright © 2016, Canal TP and/or its affiliates. All rights reserved.
//
// This file is part of Navitia,
//     the software to build cool stuff with public transport.
//
// Hope you'll enjoy and contribute to this project,
//     powered by Canal TP (www.canaltp.fr).
// Help us simplify mobility and open public transport:
//     a non ending quest to the responsive locomotion way of traveling!
//
// LICENCE: This program is free software; you can redistribute it
// and/or modify it under the terms of the GNU Affero General Public
// License as published by the Free Software Foundation, either
// version 3 of the License, or (at your option) any later version.
//
// This program 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
// Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public
// License along with this program. If not, see
// <http://www.gnu.org/licenses/>.
//
// Stay tuned using
// twitter @navitia
// IRC #navitia on freenode
// https://groups.google.com/d/forum/navitia
// www.navitia.io

use std::rc::Rc;
use mimir::rubber::{Rubber, TypedIndex};
use utils::{format_label, get_zip_codes_from_admins};
use mimir;
use admin_geofinder::AdminGeoFinder;
use std::collections::HashMap;
use std::mem::replace;

const GLOBAL_STOP_INDEX_NAME: &'static str = "munin_global_stops";

pub fn set_weights<'a, It>(stops: It, nb_stop_points: &HashMap<String, u32>)
where
    It: Iterator<Item = &'a mut mimir::Stop>,
{
    let max = *nb_stop_points.values().max().unwrap_or(&1) as f64;
    for stop in stops {
        stop.weight = if let Some(weight) = nb_stop_points.get(&stop.id) {
            *weight as f64 / max
        } else {
            0.
        };
    }
}

pub fn import_stops(mut stops: Vec<mimir::Stop>, connection_string: &str, dataset: &str) {
    info!("creation of indexes");
    let mut rubber = Rubber::new(connection_string);
    rubber.initialize_templates().unwrap();

    attach_stops_to_admins(stops.iter_mut(), &mut rubber);

    for stop in &mut stops {
        stop.coverages.push(dataset.to_string());
    }

    let global_index = update_global_stop_index(&mut rubber, stops.iter(), dataset).unwrap();

    info!("Importing {} stops into Mimir", stops.len());
    let nb_stops = rubber.index(dataset, stops.iter()).unwrap();
    info!("Nb of indexed stops: {}", nb_stops);

    publish_global_index(&mut rubber, &global_index).unwrap();
}

fn attach_stop(stop: &mut mimir::Stop, admins: Vec<Rc<mimir::Admin>>) {
    stop.administrative_regions = admins;
    stop.label = format_label(&stop.administrative_regions, &stop.name);
    stop.zip_codes = get_zip_codes_from_admins(&stop.administrative_regions);
}

/// Attach the stops to administrative regions
///
/// The admins are loaded from Elasticsearch and stored in a quadtree
/// We attach a stop with all the admins that have a boundary containing
/// the coordinate of the stop
fn attach_stops_to_admins<'a, It: Iterator<Item = &'a mut mimir::Stop>>(
    stops: It,
    rubber: &mut Rubber,
) {
    let admins = rubber.get_all_admins().unwrap_or_else(|_| {
        info!("Administratives regions not found in elasticsearch db");
        vec![]
    });

    info!("{} administrative regions loaded from mimir", admins.len());

    let admins_geofinder = admins.into_iter().collect::<AdminGeoFinder>();

    let mut nb_unmatched = 0u32;
    let mut nb_matched = 0u32;
    for mut stop in stops {
        let admins = admins_geofinder.get(&stop.coord);

        if admins.is_empty() {
            nb_unmatched += 1;
        } else {
            nb_matched += 1;
        }

        attach_stop(&mut stop, admins);
    }

    info!(
        "there are {}/{} stops without any admin",
        nb_unmatched,
        nb_matched + nb_unmatched
    );
}
fn merge_collection<T: Ord>(target: &mut Vec<T>, source: Vec<T>) {
    use std::collections::BTreeSet;
    let tmp = replace(target, vec![]);
    *target = tmp.into_iter()
        .chain(source)
        .collect::<BTreeSet<_>>()
        .into_iter()
        .collect();
}

/// merge the stops from all the different indexes
/// for the moment the merge is very simple and uses only the ID
/// (and we take the data from the first stop inserted)
fn merge_stops<It: IntoIterator<Item = mimir::Stop>>(
    stops: It,
) -> Box<Iterator<Item = mimir::Stop>> {
    let mut stops_by_id = HashMap::<String, mimir::Stop>::new();
    for mut stop in stops.into_iter() {
        let cov = replace(&mut stop.coverages, vec![]);
        let codes = replace(&mut stop.codes, vec![]);
        let physical_modes = replace(&mut stop.physical_modes, vec![]);
        let commercial_modes = replace(&mut stop.commercial_modes, vec![]);
        let properties = replace(&mut stop.properties, vec![]);

        let mut stop_in_map = stops_by_id.entry(stop.id.clone()).or_insert(stop);

        merge_collection(&mut stop_in_map.codes, codes);
        merge_collection(&mut stop_in_map.physical_modes, physical_modes);
        merge_collection(&mut stop_in_map.commercial_modes, commercial_modes);
        merge_collection(&mut stop_in_map.coverages, cov);
        merge_collection(&mut stop_in_map.properties, properties);
    }
    Box::new(stops_by_id.into_iter().map(|(_, v)| v))
}

fn get_all_stops(rubber: &mut Rubber, index: String) -> Result<Vec<mimir::Stop>, String> {
    rubber
        .get_all_objects_from_index(&index)
        .map_err(|e| e.to_string())
}

fn update_global_stop_index<'a, It: Iterator<Item = &'a mimir::Stop>>(
    rubber: &mut Rubber,
    stops: It,
    dataset: &str,
) -> Result<String, String> {
    let dataset_index = mimir::rubber::get_main_type_and_dataset_index::<mimir::Stop>(dataset);
    let stops_indexes = rubber
        .get_all_aliased_index(&mimir::rubber::get_main_type_index::<mimir::Stop>())?
        .into_iter()
        .filter(|&(_, ref aliases)| !aliases.contains(&dataset_index))
        .map(|(index, _)| index);

    let all_other_es_stops: Vec<_> = stops_indexes
        .map(|index| get_all_stops(rubber, index).unwrap())
        .flat_map(|stops| stops.into_iter())
        .collect();

    let all_es_stops = all_other_es_stops
        .into_iter()
        .chain(stops.into_iter().cloned());

    let all_merged_stops = merge_stops(all_es_stops);
    let es_index_name = mimir::rubber::get_date_index_name(GLOBAL_STOP_INDEX_NAME);

    rubber.create_index(&es_index_name)?;
    let typed_index = TypedIndex::new(es_index_name.clone());

    let nb_stops_added = rubber
        .bulk_index(&typed_index, all_merged_stops)
        .map_err(|e| e.to_string())?;
    info!("{} stops added in the global index", nb_stops_added);
    // create global index
    // fill structure for each stop indexes
    Ok(es_index_name)
}

// publish the global stop index
// alias the new index to the global stop alias, and remove the old index
fn publish_global_index(rubber: &mut Rubber, new_global_index: &str) -> Result<(), String> {
    let last_global_indexes: Vec<_> = rubber
        .get_all_aliased_index(GLOBAL_STOP_INDEX_NAME)?
        .into_iter()
        .map(|(k, _)| k)
        .filter(|k| k != new_global_index)
        .collect();
    rubber.alias(
        GLOBAL_STOP_INDEX_NAME,
        &vec![new_global_index.to_string()],
        &last_global_indexes,
    )?;

    for index in last_global_indexes {
        rubber.delete_index(&index)?;
    }
    Ok(())
}
<|endoftext|>


<commit_before>//! The ReQL data types

use std::result;
use std::ops::Deref;

use {Result, DateTime, chrono};
use errors::DriverError;
use ql2::proto::{Term, Datum, Term_TermType as TermType, Term_AssocPair as TermPair,
                 Datum_DatumType as DatumType, Datum_AssocPair as DatumPair};
use serde_json::value::{Value, ToJson};
use protobuf::repeated::RepeatedField;
use protobuf::ProtobufEnum;
use serde::{Serialize, Deserialize, Serializer, Deserializer};

pub trait FromJson {
    fn from_json<T: ToJson>(t: T) -> Result<Term> {
        // Datum
        let mut datum = Datum::new();
        match t.to_json()? {
            Value::String(val) => {
                datum.set_field_type(DatumType::R_STR);
                datum.set_r_str(val);
            }
            Value::Bool(val) => {
                datum.set_field_type(DatumType::R_BOOL);
                datum.set_r_bool(val);
            }
            Value::Number(val) => {
                match val.as_f64() {
                    Some(val) => {
                        datum.set_field_type(DatumType::R_NUM);
                        datum.set_r_num(val);
                    }
                    None => {
                        let msg = String::from("Value::Number could not be coerced to f64");
                        return Err(DriverError::Other(msg))?;
                    }
                }
            }
            Value::Array(val) => {
                datum.set_field_type(DatumType::R_ARRAY);
                let mut args = Vec::new();
                for a in val.iter() {
                    args.push(Term::from_json(a)?.take_datum());
                }
                let arr = RepeatedField::from_vec(args);
                datum.set_r_array(arr);
            }
            Value::Object(val) => {
                datum.set_field_type(DatumType::R_OBJECT);
                let mut args = Vec::new();
                for (name, arg) in val.into_iter() {
                    let mut obj = DatumPair::new();
                    obj.set_key(name.into());
                    obj.set_val(Term::from_json(arg)?.take_datum());
                    args.push(obj);
                }
                let obj = RepeatedField::from_vec(args);
                datum.set_r_object(obj);
            }
            Value::Null => {
                datum.set_field_type(DatumType::R_NULL);
            }
        }
        // Term
        let mut term = Term::new();
        term.set_field_type(TermType::DATUM);
        term.set_datum(datum);
        Ok(term)
    }
}

impl FromJson for Term {}

trait IsDatum {
    fn is_datum(&self) -> bool;
}

trait IsEmpty {
    fn is_empty(&self) -> bool;
}

pub trait Encode {
    fn encode(&self) -> String;
}

impl IsDatum for Term {
    fn is_datum(&self) -> bool {
        self.get_field_type() == TermType::DATUM
    }
}

impl IsEmpty for Term {
    fn is_empty(&self) -> bool {
        *self == Term::new()
    }
}

impl Encode for Vec<TermPair> {
    fn encode(&self) -> String {
        let mut opts = String::from("{");
        for term in self {
            opts.push_str(&format!("\"{}\":{},", term.get_key(), term.get_val().encode()));
        }
        opts = opts.trim_right_matches(",").to_string();
        opts.push_str("}");
        opts
    }
}

impl Encode for Datum {
    fn encode(&self) -> String {
        match self.get_field_type() {
            DatumType::R_NULL => String::from("null"),
            DatumType::R_BOOL => format!("{}", self.get_r_bool()),
            DatumType::R_NUM => format!("{}", self.get_r_num()),
            DatumType::R_STR => format!("\"{}\"", self.get_r_str()),
            DatumType::R_ARRAY => {
                let mut args = format!("[{},[", TermType::MAKE_ARRAY.value());
                for term in self.get_r_array() {
                    args.push_str(&format!("{},", term.encode()));
                }
                args = args.trim_right_matches(",").to_string();
                args.push_str("]]");
                args
            }
            DatumType::R_OBJECT => {
                let mut args = String::from("{");
                for term in self.get_r_object() {
                    args.push_str(&format!("\"{}\":{},", term.get_key(), term.get_val().encode()));
                }
                args = args.trim_right_matches(",").to_string();
                args.push_str("}");
                args
            }
            DatumType::R_JSON => {
                unimplemented!();
            }
        }
    }
}

impl Encode for Term {
    fn encode(&self) -> String {
        let mut res = Vec::new();
        if !self.is_datum() {
            res.push(format!("[{}", self.get_field_type().value()));
        }
        if self.has_datum() {
            let datum = self.get_datum();
            res.push(datum.encode());
        }
        let terms = self.get_args();
        if !terms.is_empty() {
            let mut args = if self.has_field_type() {
                String::from("[")
            } else {
                String::new()
            };
            for term in terms {
                args.push_str(&format!("{},", term.encode()));
            }
            args = args.trim_right_matches(",").to_string();
            if self.has_field_type() {
                args.push_str("]");
            }
            res.push(args);
        }
        let opts = self.clone().take_optargs().into_vec();
        if !opts.is_empty() {
            res.push(format!("{}", opts.encode()));
        }
        let mut res = res.join(",");
        if !self.is_datum() {
            res.push_str("]");
        }
        res
    }
}

#[derive(Debug, Serialize, Deserialize)]
struct Time {
    #[serde(rename = "$reql_type$")]
    reql_type: String,
    epoch_time: f64,
    timezone: String,
}

impl Deserialize for DateTime {
    fn deserialize<D>(deserializer: D) -> result::Result<Self, D::Error>
        where D: Deserializer
    {
        let time = Time::deserialize(deserializer)?;
        let secs = time.epoch_time.trunc() as i64;
        // RethinkDB timestamps have millisecond precision so we need
        // to convert the milliseconds to nanoseconds first
        let nsecs = (time.epoch_time.fract().abs() * 1_000_000) as u32;
        let naive = chrono::NaiveDateTime::from_timestamp(secs, nsecs);
        let dt = chrono::DateTime::<chrono::UTC>::from_utc(naive, chrono::UTC);
        Ok(DateTime(dt))
    }
}

impl Serialize for DateTime {
    fn serialize<S>(&self, _serializer: S) -> result::Result<S::Ok, S::Error>
        where S: Serializer
    {
        unimplemented!();
    }
}

impl Deref for DateTime {
    type Target = chrono::DateTime<chrono::UTC>;

    fn deref(&self) -> &Self::Target {
        &self.0
    }
}
<commit_msg>Correct time serialisation<commit_after>//! The ReQL data types

use std::result;
use std::ops::Deref;

use {Result, DateTime, chrono};
use errors::DriverError;
use ql2::proto::{Term, Datum, Term_TermType as TermType, Term_AssocPair as TermPair,
                 Datum_DatumType as DatumType, Datum_AssocPair as DatumPair};
use serde_json::value::{Value, ToJson};
use protobuf::repeated::RepeatedField;
use protobuf::ProtobufEnum;
use serde::{Serialize, Deserialize, Serializer, Deserializer};

pub trait FromJson {
    fn from_json<T: ToJson>(t: T) -> Result<Term> {
        // Datum
        let mut datum = Datum::new();
        match t.to_json()? {
            Value::String(val) => {
                datum.set_field_type(DatumType::R_STR);
                datum.set_r_str(val);
            }
            Value::Bool(val) => {
                datum.set_field_type(DatumType::R_BOOL);
                datum.set_r_bool(val);
            }
            Value::Number(val) => {
                match val.as_f64() {
                    Some(val) => {
                        datum.set_field_type(DatumType::R_NUM);
                        datum.set_r_num(val);
                    }
                    None => {
                        let msg = String::from("Value::Number could not be coerced to f64");
                        return Err(DriverError::Other(msg))?;
                    }
                }
            }
            Value::Array(val) => {
                datum.set_field_type(DatumType::R_ARRAY);
                let mut args = Vec::new();
                for a in val.iter() {
                    args.push(Term::from_json(a)?.take_datum());
                }
                let arr = RepeatedField::from_vec(args);
                datum.set_r_array(arr);
            }
            Value::Object(val) => {
                datum.set_field_type(DatumType::R_OBJECT);
                let mut args = Vec::new();
                for (name, arg) in val.into_iter() {
                    let mut obj = DatumPair::new();
                    obj.set_key(name.into());
                    obj.set_val(Term::from_json(arg)?.take_datum());
                    args.push(obj);
                }
                let obj = RepeatedField::from_vec(args);
                datum.set_r_object(obj);
            }
            Value::Null => {
                datum.set_field_type(DatumType::R_NULL);
            }
        }
        // Term
        let mut term = Term::new();
        term.set_field_type(TermType::DATUM);
        term.set_datum(datum);
        Ok(term)
    }
}

impl FromJson for Term {}

trait IsDatum {
    fn is_datum(&self) -> bool;
}

trait IsEmpty {
    fn is_empty(&self) -> bool;
}

pub trait Encode {
    fn encode(&self) -> String;
}

impl IsDatum for Term {
    fn is_datum(&self) -> bool {
        self.get_field_type() == TermType::DATUM
    }
}

impl IsEmpty for Term {
    fn is_empty(&self) -> bool {
        *self == Term::new()
    }
}

impl Encode for Vec<TermPair> {
    fn encode(&self) -> String {
        let mut opts = String::from("{");
        for term in self {
            opts.push_str(&format!("\"{}\":{},", term.get_key(), term.get_val().encode()));
        }
        opts = opts.trim_right_matches(",").to_string();
        opts.push_str("}");
        opts
    }
}

impl Encode for Datum {
    fn encode(&self) -> String {
        match self.get_field_type() {
            DatumType::R_NULL => String::from("null"),
            DatumType::R_BOOL => format!("{}", self.get_r_bool()),
            DatumType::R_NUM => format!("{}", self.get_r_num()),
            DatumType::R_STR => format!("\"{}\"", self.get_r_str()),
            DatumType::R_ARRAY => {
                let mut args = format!("[{},[", TermType::MAKE_ARRAY.value());
                for term in self.get_r_array() {
                    args.push_str(&format!("{},", term.encode()));
                }
                args = args.trim_right_matches(",").to_string();
                args.push_str("]]");
                args
            }
            DatumType::R_OBJECT => {
                let mut args = String::from("{");
                for term in self.get_r_object() {
                    args.push_str(&format!("\"{}\":{},", term.get_key(), term.get_val().encode()));
                }
                args = args.trim_right_matches(",").to_string();
                args.push_str("}");
                args
            }
            DatumType::R_JSON => {
                unimplemented!();
            }
        }
    }
}

impl Encode for Term {
    fn encode(&self) -> String {
        let mut res = Vec::new();
        if !self.is_datum() {
            res.push(format!("[{}", self.get_field_type().value()));
        }
        if self.has_datum() {
            let datum = self.get_datum();
            res.push(datum.encode());
        }
        let terms = self.get_args();
        if !terms.is_empty() {
            let mut args = if self.has_field_type() {
                String::from("[")
            } else {
                String::new()
            };
            for term in terms {
                args.push_str(&format!("{},", term.encode()));
            }
            args = args.trim_right_matches(",").to_string();
            if self.has_field_type() {
                args.push_str("]");
            }
            res.push(args);
        }
        let opts = self.clone().take_optargs().into_vec();
        if !opts.is_empty() {
            res.push(format!("{}", opts.encode()));
        }
        let mut res = res.join(",");
        if !self.is_datum() {
            res.push_str("]");
        }
        res
    }
}

#[derive(Debug, Serialize, Deserialize)]
struct Time {
    #[serde(rename = "$reql_type$")]
    reql_type: String,
    epoch_time: f64,
    timezone: String,
}

impl Deserialize for DateTime {
    fn deserialize<D>(deserializer: D) -> result::Result<Self, D::Error>
        where D: Deserializer
    {
        let time = Time::deserialize(deserializer)?;
        let secs = time.epoch_time.trunc() as i64;
        // RethinkDB timestamps have millisecond precision so we need
        // to convert the milliseconds to nanoseconds first
        let msecs = time.epoch_time.fract().abs() as u32;
        let naive = chrono::NaiveDateTime::from_timestamp(secs, msecs * 1_000_000);
        let dt = chrono::DateTime::<chrono::UTC>::from_utc(naive, chrono::UTC);
        Ok(DateTime(dt))
    }
}

impl Serialize for DateTime {
    fn serialize<S>(&self, _serializer: S) -> result::Result<S::Ok, S::Error>
        where S: Serializer
    {
        unimplemented!();
    }
}

impl Deref for DateTime {
    type Target = chrono::DateTime<chrono::UTC>;

    fn deref(&self) -> &Self::Target {
        &self.0
    }
}
<|endoftext|>


<commit_before>extern crate num;

use std::mem;

type c32 = num::Complex<f32>;
type c64 = num::Complex<f64>;

const UNION_SIZE : usize = 8; //mem::size_of::<usize>();

#[repr(C)]
struct Union {
    data: [usize; UNION_SIZE]
}

type c32_vec = Vec<c32>;
type c64_vec = Vec<c64>;

impl Union {
    unsafe fn as_c32_vec(&self) -> *const c32_vec {
        let p = self as *const _ as *const c32_vec;
        p
    }

    unsafe fn as_c64_vec(&self) -> *const c64_vec {
        let p = self as *const _ as *const c64_vec;
        p
    }

    //unsafe fn as_c32_vec_mut(&self) -> *mut c32_vec {
    //    let p = self as *mut _ as *mut c32_vec;
    //    &mut p
    //}

    //unsafe fn as_c64_vec_mut(&self) -> *mut c64_vec {
    //    let p = self as *mut _ as *mut c64_vec;
    //    &mut p
    //}

}

fn main() {
    println!("Rust union test");

}
<commit_msg>finished union test.<commit_after>extern crate num;

use std::mem;

type c32 = num::Complex<f32>;
type c64 = num::Complex<f64>;

const UNION_SIZE : usize = 8; //mem::size_of::<usize>();

#[repr(C)]
struct Union {
    data: [usize; UNION_SIZE]
}

type c32_vec = Vec<c32>;
type c64_vec = Vec<c64>;

impl Union {
    fn new() -> Union {
        Union { data: [0; UNION_SIZE] }
    }

    unsafe fn as_c32_vec(&self) -> *const c32_vec {
        let p = self as *const _ as *const c32_vec;
        p
    }

    unsafe fn as_c64_vec(&self) -> *const c64_vec {
        let p = self as *const _ as *const c64_vec;
        p
    }

    unsafe fn as_c32_vec_mut(&mut self) -> *mut c32_vec {
        let p = self as *mut _ as *mut c32_vec;
        p
    }

    unsafe fn as_c64_vec_mut(&mut self) -> *mut c64_vec {
        let p = self as *mut _ as *mut c64_vec;
        p
    }
}

fn main() {
    println!("Rust union test");

    unsafe {
        let mut union1 = Union::new();
        let mut c32_vec_ptr = union1.as_c32_vec_mut();
        (*c32_vec_ptr).push(c32::new(0.0,1.0));
        (*c32_vec_ptr).push(c32::new(1.0,0.0));
        println!("(*c32_vec_ptr) : {:?}", (*c32_vec_ptr));

        let mut union2 = Union::new();
        let mut c64_vec_ptr = union2.as_c64_vec_mut();
        (*c64_vec_ptr).push(c64::new(0.0,1.0));
        (*c64_vec_ptr).push(c64::new(1.0,0.0));
        println!("(*c64_vec_ptr) : {:?}", (*c64_vec_ptr));

    }
}
<|endoftext|>


<commit_before>use std::ptr;
use std::io;
use std::fs::{create_dir, remove_dir_all, read_dir, remove_file, remove_dir};
use std::fs::{metadata};
use std::path::{Path, PathBuf};
use std::path::Component::Normal;
use std::io::Error as IoError;
use std::io::ErrorKind::{AlreadyExists, NotFound};
use std::ffi::CString;
use std::env::current_dir;

use nix::sys::signal::{SIGQUIT, SIGSEGV, SIGBUS, SIGHUP, SIGILL, SIGABRT};
use nix::sys::signal::{SIGFPE, SIGUSR1, SIGUSR2};
use libc::{c_int, c_char, timeval, c_void, mode_t, uid_t, gid_t};
use libc::{chmod, chdir, chown};
use signal::trap::Trap;

use super::sandbox_config::Range;
use super::id_map::IdMap;

pub type Time = f64;
pub type SigNum = i32;
// TODO(tailhook) signal::Trap might use nix signals instead of i32
pub const ABNORMAL_TERM_SIGNALS: &'static [SigNum] = &[
    SIGQUIT as SigNum, SIGSEGV as SigNum, SIGBUS as SigNum, SIGHUP as SigNum,
    SIGILL as SigNum, SIGABRT as SigNum, SIGFPE as SigNum, SIGUSR1 as SigNum,
    SIGUSR2 as SigNum,
];

pub struct FsUidGuard(bool);

extern {
    fn chroot(dir: *const c_char) -> c_int;
    fn pivot_root(new_root: *const c_char, put_old: *const c_char) -> c_int;
    fn gettimeofday(tp: *mut timeval, tzp: *mut c_void) -> c_int;

    // TODO(tailhook) move to libc and nix
    fn setfsuid(uid: uid_t) -> c_int;
    fn setfsgid(gid: gid_t) -> c_int;
}

pub fn temporary_change_root<T, F>(path: &Path, fun: F)
    -> Result<T, String>
    where F: Fn() -> Result<T, String>
{
    // The point is: if we gat fatal signal in the chroot, we have 2 issues:
    //
    // 1. Process can't actually restart (the binary path is wrong)
    // 2. Even if it finds the binary, it will be angry restarting in chroot
    //
    let _trap = Trap::trap(ABNORMAL_TERM_SIGNALS);

    let cwd = current_dir().unwrap();
    if unsafe { chdir(CString::new("/").unwrap().as_ptr()) } != 0 {
        return Err(format!("Error chdir to root: {}",
                           IoError::last_os_error()));
    }
    if unsafe { chroot(cpath(&path).as_ptr()) } != 0 {
        return Err(format!("Error chroot to {:?}: {}",
                           path, IoError::last_os_error()));
    }
    let res = fun();
    if unsafe { chroot(CString::new(".").unwrap().as_ptr()) } != 0 {
        return Err(format!("Error chroot back: {}",
                           IoError::last_os_error()));
    }
    if unsafe { chdir(cpath(&cwd).as_ptr()) } != 0 {
        return Err(format!("Error chdir to workdir back: {}",
                           IoError::last_os_error()));
    }
    return res;
}

pub fn in_range(ranges: &Vec<Range>, value: u32) -> bool {
    for rng in ranges.iter() {
        if rng.start <= value && rng.end >= value {
            return true;
        }
    }
    return false;
}

pub fn in_mapping(mapping: &Vec<IdMap>, value: u32) -> bool {
    for mp in mapping.iter() {
        if value >= mp.inside && value < mp.inside + mp.count {
            return true;
        }
    }
    return false;
}

pub fn check_mapping(ranges: &Vec<Range>, map: &Vec<IdMap>) -> bool {
    // TODO(tailhook) do more comprehensive algo
    'map: for item in map.iter() {
        for rng in ranges.iter() {
            if rng.start <= item.outside &&
                rng.end >= item.outside + item.count - 1
            {
                continue 'map;
            }
        }
        return false;
    }
    return true;
}

pub fn change_root(new_root: &Path, put_old: &Path) -> Result<(), String>
{
    if unsafe { pivot_root(
            cpath(new_root).as_ptr(),
            cpath(put_old).as_ptr()) } != 0
    {
        return Err(format!("Error pivot_root to {}: {}", new_root.display(),
                           IoError::last_os_error()));
    }
    if unsafe { chdir(CString::new("/").unwrap().as_ptr()) } != 0
    {
        return Err(format!("Error chdir to root: {}",
                           IoError::last_os_error()));
    }
    return Ok(());
}

pub fn ensure_dir(dir: &Path) -> Result<(), String> {
    if let Ok(dmeta) = metadata(dir) {
        if !dmeta.is_dir() {
            return Err(format!(concat!("Can't create dir {:?}, ",
                "path already exists but not a directory"), dir));
        }
        return Ok(());
    }

    match create_dir(dir) {
        Ok(()) => return Ok(()),
        Err(ref e) if e.kind() == AlreadyExists => {
            let dmeta = metadata(dir);
            if dmeta.is_ok() && dmeta.unwrap().is_dir() {
                return Ok(());
            } else {
                return Err(format!(concat!("Can't create dir {:?}, ",
                    "path already exists but not a directory"),
                    dir));
            }
        }
        Err(ref e) => {
            return Err(format!(concat!("Can't create dir {:?}: {} ",
                "path already exists but not a directory"), dir, e));
        }
    }
}

pub fn clean_dir(dir: &Path, remove_dir_itself: bool) -> Result<(), String> {
    if let Err(e) = metadata(dir) {
        if e.kind() == NotFound {
            return Ok(());
        } else {
            return Err(format!("Can't stat dir {:?}: {}", dir, e));
        }
    }
    // We temporarily change root, so that symlinks inside the dir
    // would do no harm. But note that dir itself can be a symlink
    try!(temporary_change_root(dir, || {
        let dirlist = try!(read_dir("/")
             .map_err(|e| format!("Can't read directory {:?}: {}", dir, e)))
             .filter_map(|x| x.ok())
             .collect::<Vec<_>>();
        for entry in dirlist.into_iter() {
            match metadata(entry.path()) {
                Ok(ref meta) if meta.is_dir() => {
                    try!(remove_dir_all(entry.path())
                        .map_err(|e| format!("Can't remove directory {:?}{:?}: {}",
                            dir, entry.path(), e)));
                }
                Ok(_) => {
                    try!(remove_file(entry.path())
                        .map_err(|e| format!("Can't remove file {:?}{:?}: {}",
                            dir, entry.path(), e)));
                }
                Err(_) => {
                    return Err(format!("Can't stat file {:?}", entry.path()));
                }
            }
        }
        Ok(())
    }));
    if remove_dir_itself {
        try!(remove_dir(dir)
            .map_err(|e| format!("Can't remove dir {:?}: {}", dir, e)));
    }
    return Ok(());
}

pub fn join<S1, S2, I>(mut iter: I, sep: S2) -> String
    where S1:AsRef<str>, S2:AsRef<str>, I:Iterator<Item=S1>
{
    let mut buf = String::new();
    match iter.next() {
        Some(x) => buf.push_str(x.as_ref()),
        None => {}
    }
    for i in iter {
        buf.push_str(sep.as_ref());
        buf.push_str(i.as_ref());
    }
    return buf;
}

pub fn get_time() -> Time {
    let mut tv = timeval { tv_sec: 0, tv_usec: 0 };
    unsafe { gettimeofday(&mut tv, ptr::null_mut()) };
    return tv.tv_sec as f64 +  tv.tv_usec as f64 * 0.000001;
}

pub fn set_file_owner(path: &Path, owner: uid_t, group: gid_t)
    -> Result<(), IoError>
{
    let cpath = cpath(path);
    let rc = unsafe { chown(cpath.as_ptr(), owner, group) };
    if rc < 0 {
        return Err(IoError::last_os_error());
    }
    return Ok(());
}

pub fn set_file_mode(path: &Path, mode: mode_t) -> Result<(), IoError> {
    let cpath = cpath(path);
    let rc = unsafe { chmod(cpath.as_ptr(), mode) };
    if rc < 0 {
        return Err(IoError::last_os_error());
    }
    return Ok(());
}

pub fn cpath<P:AsRef<Path>>(path: P) -> CString {
    CString::new(path.as_ref().to_str().unwrap()).unwrap()
}

pub fn relative(child: &Path, base: &Path) -> PathBuf {
    assert!(child.starts_with(base));
    let mut res = PathBuf::new();
    for cmp in child.components().skip(base.components().count()) {
        if let Normal(ref chunk) = cmp {
            res.push(chunk);
        } else {
            panic!("Bad path for relative ({:?} from {:?} against {:?})",
                cmp, child, base);
        }
    }
    return res
}

impl FsUidGuard {
    pub fn set(uid: u32, gid: u32) -> FsUidGuard {
        if uid != 0 || gid != 0 {
            unsafe { setfsuid(uid) };
            if unsafe { setfsuid(uid) } != uid as i32 {
                error!("Can't set fs gid to open socket: {}. Ignoring.",
                    io::Error::last_os_error());
            }
            unsafe { setfsgid(gid) };
            if unsafe { setfsgid(gid) } != gid as i32 {
                error!("Can't set fs uid to open socket: {}. Ignoring.",
                    io::Error::last_os_error());
            }
            FsUidGuard(true)
        } else {
            FsUidGuard(false)
        }
    }
}

impl Drop for FsUidGuard {
    fn drop(&mut self) {
        if self.0 {
            unsafe { setfsuid(0) };
            if unsafe { setfsuid(0) } != 0 {
                let err = io::Error::last_os_error();
                error!("Can't return fs uid back to zero: {}. Aborting.", err);
                panic!("Can't return fs uid back to zero: {}. Aborting.", err);
            }
            unsafe { setfsgid(0) };
            if unsafe { setfsgid(0) } != 0 {
                let err = io::Error::last_os_error();
                error!("Can't return fs gid back to zero: {}. Aborting.", err);
                panic!("Can't return fs gid back to zero: {}. Aborting.", err);
            }
        }
    }
}
<commit_msg>Better error when current working directory is deleted<commit_after>use std::ptr;
use std::io;
use std::fs::{create_dir, remove_dir_all, read_dir, remove_file, remove_dir};
use std::fs::{metadata};
use std::path::{Path, PathBuf};
use std::path::Component::Normal;
use std::io::Error as IoError;
use std::io::ErrorKind::{AlreadyExists, NotFound};
use std::ffi::CString;
use std::env::current_dir;

use nix::sys::signal::{SIGQUIT, SIGSEGV, SIGBUS, SIGHUP, SIGILL, SIGABRT};
use nix::sys::signal::{SIGFPE, SIGUSR1, SIGUSR2};
use libc::{c_int, c_char, timeval, c_void, mode_t, uid_t, gid_t};
use libc::{chmod, chdir, chown};
use signal::trap::Trap;

use super::sandbox_config::Range;
use super::id_map::IdMap;

pub type Time = f64;
pub type SigNum = i32;
// TODO(tailhook) signal::Trap might use nix signals instead of i32
pub const ABNORMAL_TERM_SIGNALS: &'static [SigNum] = &[
    SIGQUIT as SigNum, SIGSEGV as SigNum, SIGBUS as SigNum, SIGHUP as SigNum,
    SIGILL as SigNum, SIGABRT as SigNum, SIGFPE as SigNum, SIGUSR1 as SigNum,
    SIGUSR2 as SigNum,
];

pub struct FsUidGuard(bool);

extern {
    fn chroot(dir: *const c_char) -> c_int;
    fn pivot_root(new_root: *const c_char, put_old: *const c_char) -> c_int;
    fn gettimeofday(tp: *mut timeval, tzp: *mut c_void) -> c_int;

    // TODO(tailhook) move to libc and nix
    fn setfsuid(uid: uid_t) -> c_int;
    fn setfsgid(gid: gid_t) -> c_int;
}

pub fn temporary_change_root<T, F>(path: &Path, fun: F)
    -> Result<T, String>
    where F: Fn() -> Result<T, String>
{
    // The point is: if we gat fatal signal in the chroot, we have 2 issues:
    //
    // 1. Process can't actually restart (the binary path is wrong)
    // 2. Even if it finds the binary, it will be angry restarting in chroot
    //
    let _trap = Trap::trap(ABNORMAL_TERM_SIGNALS);

    let cwd = current_dir().map_err(|e| {
        format!("Can't determine current dir: {}. \
            This usually happens if the directory \
            your're in is already deleted", e)
    })?;
    if unsafe { chdir(CString::new("/").unwrap().as_ptr()) } != 0 {
        return Err(format!("Error chdir to root: {}",
                           IoError::last_os_error()));
    }
    if unsafe { chroot(cpath(&path).as_ptr()) } != 0 {
        return Err(format!("Error chroot to {:?}: {}",
                           path, IoError::last_os_error()));
    }
    let res = fun();
    if unsafe { chroot(CString::new(".").unwrap().as_ptr()) } != 0 {
        return Err(format!("Error chroot back: {}",
                           IoError::last_os_error()));
    }
    if unsafe { chdir(cpath(&cwd).as_ptr()) } != 0 {
        return Err(format!("Error chdir to workdir back: {}",
                           IoError::last_os_error()));
    }
    return res;
}

pub fn in_range(ranges: &Vec<Range>, value: u32) -> bool {
    for rng in ranges.iter() {
        if rng.start <= value && rng.end >= value {
            return true;
        }
    }
    return false;
}

pub fn in_mapping(mapping: &Vec<IdMap>, value: u32) -> bool {
    for mp in mapping.iter() {
        if value >= mp.inside && value < mp.inside + mp.count {
            return true;
        }
    }
    return false;
}

pub fn check_mapping(ranges: &Vec<Range>, map: &Vec<IdMap>) -> bool {
    // TODO(tailhook) do more comprehensive algo
    'map: for item in map.iter() {
        for rng in ranges.iter() {
            if rng.start <= item.outside &&
                rng.end >= item.outside + item.count - 1
            {
                continue 'map;
            }
        }
        return false;
    }
    return true;
}

pub fn change_root(new_root: &Path, put_old: &Path) -> Result<(), String>
{
    if unsafe { pivot_root(
            cpath(new_root).as_ptr(),
            cpath(put_old).as_ptr()) } != 0
    {
        return Err(format!("Error pivot_root to {}: {}", new_root.display(),
                           IoError::last_os_error()));
    }
    if unsafe { chdir(CString::new("/").unwrap().as_ptr()) } != 0
    {
        return Err(format!("Error chdir to root: {}",
                           IoError::last_os_error()));
    }
    return Ok(());
}

pub fn ensure_dir(dir: &Path) -> Result<(), String> {
    if let Ok(dmeta) = metadata(dir) {
        if !dmeta.is_dir() {
            return Err(format!(concat!("Can't create dir {:?}, ",
                "path already exists but not a directory"), dir));
        }
        return Ok(());
    }

    match create_dir(dir) {
        Ok(()) => return Ok(()),
        Err(ref e) if e.kind() == AlreadyExists => {
            let dmeta = metadata(dir);
            if dmeta.is_ok() && dmeta.unwrap().is_dir() {
                return Ok(());
            } else {
                return Err(format!(concat!("Can't create dir {:?}, ",
                    "path already exists but not a directory"),
                    dir));
            }
        }
        Err(ref e) => {
            return Err(format!(concat!("Can't create dir {:?}: {} ",
                "path already exists but not a directory"), dir, e));
        }
    }
}

pub fn clean_dir(dir: &Path, remove_dir_itself: bool) -> Result<(), String> {
    if let Err(e) = metadata(dir) {
        if e.kind() == NotFound {
            return Ok(());
        } else {
            return Err(format!("Can't stat dir {:?}: {}", dir, e));
        }
    }
    // We temporarily change root, so that symlinks inside the dir
    // would do no harm. But note that dir itself can be a symlink
    try!(temporary_change_root(dir, || {
        let dirlist = try!(read_dir("/")
             .map_err(|e| format!("Can't read directory {:?}: {}", dir, e)))
             .filter_map(|x| x.ok())
             .collect::<Vec<_>>();
        for entry in dirlist.into_iter() {
            match metadata(entry.path()) {
                Ok(ref meta) if meta.is_dir() => {
                    try!(remove_dir_all(entry.path())
                        .map_err(|e| format!("Can't remove directory {:?}{:?}: {}",
                            dir, entry.path(), e)));
                }
                Ok(_) => {
                    try!(remove_file(entry.path())
                        .map_err(|e| format!("Can't remove file {:?}{:?}: {}",
                            dir, entry.path(), e)));
                }
                Err(_) => {
                    return Err(format!("Can't stat file {:?}", entry.path()));
                }
            }
        }
        Ok(())
    }));
    if remove_dir_itself {
        try!(remove_dir(dir)
            .map_err(|e| format!("Can't remove dir {:?}: {}", dir, e)));
    }
    return Ok(());
}

pub fn join<S1, S2, I>(mut iter: I, sep: S2) -> String
    where S1:AsRef<str>, S2:AsRef<str>, I:Iterator<Item=S1>
{
    let mut buf = String::new();
    match iter.next() {
        Some(x) => buf.push_str(x.as_ref()),
        None => {}
    }
    for i in iter {
        buf.push_str(sep.as_ref());
        buf.push_str(i.as_ref());
    }
    return buf;
}

pub fn get_time() -> Time {
    let mut tv = timeval { tv_sec: 0, tv_usec: 0 };
    unsafe { gettimeofday(&mut tv, ptr::null_mut()) };
    return tv.tv_sec as f64 +  tv.tv_usec as f64 * 0.000001;
}

pub fn set_file_owner(path: &Path, owner: uid_t, group: gid_t)
    -> Result<(), IoError>
{
    let cpath = cpath(path);
    let rc = unsafe { chown(cpath.as_ptr(), owner, group) };
    if rc < 0 {
        return Err(IoError::last_os_error());
    }
    return Ok(());
}

pub fn set_file_mode(path: &Path, mode: mode_t) -> Result<(), IoError> {
    let cpath = cpath(path);
    let rc = unsafe { chmod(cpath.as_ptr(), mode) };
    if rc < 0 {
        return Err(IoError::last_os_error());
    }
    return Ok(());
}

pub fn cpath<P:AsRef<Path>>(path: P) -> CString {
    CString::new(path.as_ref().to_str().unwrap()).unwrap()
}

pub fn relative(child: &Path, base: &Path) -> PathBuf {
    assert!(child.starts_with(base));
    let mut res = PathBuf::new();
    for cmp in child.components().skip(base.components().count()) {
        if let Normal(ref chunk) = cmp {
            res.push(chunk);
        } else {
            panic!("Bad path for relative ({:?} from {:?} against {:?})",
                cmp, child, base);
        }
    }
    return res
}

impl FsUidGuard {
    pub fn set(uid: u32, gid: u32) -> FsUidGuard {
        if uid != 0 || gid != 0 {
            unsafe { setfsuid(uid) };
            if unsafe { setfsuid(uid) } != uid as i32 {
                error!("Can't set fs gid to open socket: {}. Ignoring.",
                    io::Error::last_os_error());
            }
            unsafe { setfsgid(gid) };
            if unsafe { setfsgid(gid) } != gid as i32 {
                error!("Can't set fs uid to open socket: {}. Ignoring.",
                    io::Error::last_os_error());
            }
            FsUidGuard(true)
        } else {
            FsUidGuard(false)
        }
    }
}

impl Drop for FsUidGuard {
    fn drop(&mut self) {
        if self.0 {
            unsafe { setfsuid(0) };
            if unsafe { setfsuid(0) } != 0 {
                let err = io::Error::last_os_error();
                error!("Can't return fs uid back to zero: {}. Aborting.", err);
                panic!("Can't return fs uid back to zero: {}. Aborting.", err);
            }
            unsafe { setfsgid(0) };
            if unsafe { setfsgid(0) } != 0 {
                let err = io::Error::last_os_error();
                error!("Can't return fs gid back to zero: {}. Aborting.", err);
                panic!("Can't return fs gid back to zero: {}. Aborting.", err);
            }
        }
    }
}
<|endoftext|>


<commit_before>use num::bigint::{BigInt};

#[derive(Debug, PartialEq, PartialOrd)]
pub enum Value {
    None,
    Bool(bool),
    Int(BigInt),
    String(Vec<u8>),
    Unicode(String),
    List(Vec<Value>),
    Tuple(Vec<Value>),
    Dict(Vec<(Value, Value)>),
}
<commit_msg>Add float value<commit_after>use num::bigint::{BigInt};

#[derive(Debug, PartialEq, PartialOrd)]
pub enum Value {
    None,
    Bool(bool),
    Int(BigInt),
    Float(f64),
    String(Vec<u8>),
    Unicode(String),
    List(Vec<Value>),
    Tuple(Vec<Value>),
    Dict(Vec<(Value, Value)>),
}
<|endoftext|>


<commit_before>use ffi;
use libc;
use super::Connection;

use std::mem;
use std::cell::RefCell;
use std::os::unix::io::{RawFd, AsRawFd};
use std::os::raw::{c_void, c_uint};

/// A file descriptor to watch for incoming events (for async I/O).
///
/// # Example
/// ```
/// extern crate libc;
/// extern crate dbus;
/// fn main() {
///     use dbus::{Connection, BusType, WatchEvent};
///     let c = Connection::get_private(BusType::Session).unwrap();
///
///     // Get a list of fds to poll for
///     let mut fds: Vec<_> = c.watch_fds().iter().map(|w| w.to_pollfd()).collect();
///
///     // Poll them with a 1 s timeout
///     let r = unsafe { libc::poll(fds.as_mut_ptr(), fds.len() as libc::c_ulong, 1000) };
///     assert!(r >= 0);
///
///     // And handle incoming events
///     for pfd in fds.iter().filter(|pfd| pfd.revents != 0) {
///         for item in c.watch_handle(pfd.fd, WatchEvent::from_revents(pfd.revents)) {
///             // Handle item
///             println!("Received ConnectionItem: {:?}", item);
///         }
///     }
/// }
/// ```

#[repr(C)]
#[derive(Debug, PartialEq, Copy, Clone)]
pub enum WatchEvent {
    Readable = 1,
    Writable = 2,
    Error = 4,
    Hangup = 8,
}

impl WatchEvent {
    /// After running poll, this transforms the revents into a parameter you can send into `Connection::watch_handle`
    pub fn from_revents(revents: libc::c_short) -> c_uint {
        0 +
        if (revents & libc::POLLIN) != 0 { WatchEvent::Readable as c_uint } else { 0 } +
        if (revents & libc::POLLOUT) != 0 { WatchEvent::Writable as c_uint } else { 0 } +
        if (revents & libc::POLLERR) != 0 { WatchEvent::Error as c_uint } else { 0 } +
        if (revents & libc::POLLHUP) != 0 { WatchEvent::Hangup as c_uint } else { 0 }
    }
}

#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
pub struct Watch {
    fd: RawFd,
    read: bool,
    write: bool,
}

impl Watch {
    /// Get the RawFd this Watch is for
    pub fn fd(&self) -> RawFd { self.fd }
    /// Add POLLIN to events to listen for
    pub fn readable(&self) -> bool { self.read }
    /// Add POLLOUT to events to listen for
    pub fn writable(&self) -> bool { self.write }
    /// Returns the current watch as a libc::pollfd, to use with libc::poll
    pub fn to_pollfd(&self) -> libc::pollfd {
        libc::pollfd { fd: self.fd, revents: 0, events: libc::POLLERR + libc::POLLHUP +
            if self.readable() { libc::POLLIN } else { 0 } +
            if self.writable() { libc::POLLOUT } else { 0 },
        }
    }
}

impl AsRawFd for Watch {
    fn as_raw_fd(&self) -> RawFd { self.fd }
}

/// Note - internal struct, not to be used outside API. Moving it outside its box will break things.
pub struct WatchList {
    watches: RefCell<Vec<*mut ffi::DBusWatch>>,
    enabled_fds: RefCell<Vec<Watch>>,
    on_update: Box<Fn(Watch)>
}

impl WatchList {
    pub fn new(c: &Connection, on_update: Box<Fn(Watch)>) -> Box<WatchList> {
        let w = Box::new(WatchList { on_update: on_update, watches: RefCell::new(vec!()), enabled_fds: RefCell::new(vec!()) });
        if unsafe { ffi::dbus_connection_set_watch_functions(super::connection::conn_handle(c),
            Some(add_watch_cb), Some(remove_watch_cb), Some(toggled_watch_cb), &*w as *const _ as *mut _, None) } == 0 {
            panic!("dbus_connection_set_watch_functions failed");
        }
        w
    }

    pub fn watch_handle(&self, fd: RawFd, flags: c_uint) {
        // println!("watch_handle {} flags {}", fd, flags);
        for &q in self.watches.borrow().iter() {
            let w = self.get_watch(q);
            if w.fd != fd { continue };
            if unsafe { ffi::dbus_watch_handle(q, flags) } == 0 {
                panic!("dbus_watch_handle failed");
            }
            self.update(q);
        };
    }

    pub fn get_enabled_fds(&self) -> Vec<Watch> {
        self.enabled_fds.borrow().clone()
    }

    fn get_watch(&self, watch: *mut ffi::DBusWatch) -> Watch {
        let mut w = Watch { fd: unsafe { ffi::dbus_watch_get_unix_fd(watch) }, read: false, write: false};
        let enabled = self.watches.borrow().contains(&watch) && unsafe { ffi::dbus_watch_get_enabled(watch) != 0 };
        let flags = unsafe { ffi::dbus_watch_get_flags(watch) };
        if enabled {
            w.read = (flags & WatchEvent::Readable as c_uint) != 0;
            w.write = (flags & WatchEvent::Writable as c_uint) != 0;
        }
        // println!("Get watch fd {:?} ptr {:?} enabled {:?} flags {:?}", w, watch, enabled, flags);
        w
    }

    fn update(&self, watch: *mut ffi::DBusWatch) {
        let mut w = self.get_watch(watch);

        for &q in self.watches.borrow().iter() {
            if q == watch { continue };
            let ww = self.get_watch(q);
            if ww.fd != w.fd { continue };
            w.read |= ww.read;
            w.write |= ww.write;
        }
        // println!("Updated sum: {:?}", w);

        {
            let mut fdarr = self.enabled_fds.borrow_mut();

            if w.write || w.read {
                if fdarr.contains(&w) { return; } // Nothing changed
            }
            else if !fdarr.iter().any(|q| w.fd == q.fd) { return; } // Nothing changed

            fdarr.retain(|f| f.fd != w.fd);
            if w.write || w.read { fdarr.push(w) };
        }
        (*self.on_update)(w);
    }
}

extern "C" fn add_watch_cb(watch: *mut ffi::DBusWatch, data: *mut c_void) -> u32 {
    let wlist: &WatchList = unsafe { mem::transmute(data) };
    // println!("Add watch {:?}", watch);
    wlist.watches.borrow_mut().push(watch);
    wlist.update(watch);
    1
}

extern "C" fn remove_watch_cb(watch: *mut ffi::DBusWatch, data: *mut c_void) {
    let wlist: &WatchList = unsafe { mem::transmute(data) };
    // println!("Removed watch {:?}", watch);
    wlist.watches.borrow_mut().retain(|w| *w != watch);
    wlist.update(watch);
}

extern "C" fn toggled_watch_cb(watch: *mut ffi::DBusWatch, data: *mut c_void) {
    let wlist: &WatchList = unsafe { mem::transmute(data) };
    // println!("Toggled watch {:?}", watch);
    wlist.update(watch);
}

#[cfg(test)]
mod test {
    use libc;
    use super::super::{Connection, Message, BusType, WatchEvent, ConnectionItem, MessageType};

    #[test]
    fn async() {
        let c = Connection::get_private(BusType::Session).unwrap();
        c.register_object_path("/test").unwrap();
        let m = Message::new_method_call(&c.unique_name(), "/test", "com.example.asynctest", "AsyncTest").unwrap();
        let serial = c.send(m).unwrap();
        println!("Async: sent serial {}", serial);

        let mut fds: Vec<_> = c.watch_fds().iter().map(|w| w.to_pollfd()).collect();
        let mut new_fds = None;
        let mut i = 0;
        let mut success = false;
        while !success {
            i += 1;
            if let Some(q) = new_fds { fds = q; new_fds = None };

            for f in fds.iter_mut() { f.revents = 0 };
            assert!(unsafe { libc::poll(fds.as_mut_ptr(), fds.len() as libc::c_ulong, 1000) } > 0);

            for f in fds.iter().filter(|pfd| pfd.revents != 0) {
                let m = WatchEvent::from_revents(f.revents);
                println!("Async: fd {}, revents {} -> {}", f.fd, f.revents, m);
                assert!(f.revents & libc::POLLIN != 0 || f.revents & libc::POLLOUT != 0);

                for e in c.watch_handle(f.fd, m) {
                    println!("Async: got {:?}", e);
                    match e {
                        ConnectionItem::WatchFd(_) => new_fds = Some(c.watch_fds().iter().map(|w| w.to_pollfd()).collect()),
                        ConnectionItem::MethodCall(m) => {
                            assert_eq!(m.headers(), (MessageType::MethodCall, Some("/test".to_string()),
                                Some("com.example.asynctest".into()), Some("AsyncTest".to_string())));
                            let mut mr = Message::new_method_return(&m).unwrap();
                            mr.append_items(&["Goodies".into()]);
                            c.send(mr).unwrap();
                        }
                        ConnectionItem::MethodReturn(m) => {
                            assert_eq!(m.headers().0, MessageType::MethodReturn);
                            assert_eq!(m.get_reply_serial().unwrap(), serial);
                            let i = m.get_items();
                            let s: &str = i[0].inner().unwrap();
                            assert_eq!(s, "Goodies");
                            success = true;
                        }
                        _ => (),
                    }
                }
                if i > 100 { panic!() };
            }
        }
    }
}
<commit_msg>Add some missing documentation<commit_after>use ffi;
use libc;
use super::Connection;

use std::mem;
use std::cell::RefCell;
use std::os::unix::io::{RawFd, AsRawFd};
use std::os::raw::{c_void, c_uint};

/// A file descriptor to watch for incoming events (for async I/O).
///
/// # Example
/// ```
/// extern crate libc;
/// extern crate dbus;
/// fn main() {
///     use dbus::{Connection, BusType, WatchEvent};
///     let c = Connection::get_private(BusType::Session).unwrap();
///
///     // Get a list of fds to poll for
///     let mut fds: Vec<_> = c.watch_fds().iter().map(|w| w.to_pollfd()).collect();
///
///     // Poll them with a 1 s timeout
///     let r = unsafe { libc::poll(fds.as_mut_ptr(), fds.len() as libc::c_ulong, 1000) };
///     assert!(r >= 0);
///
///     // And handle incoming events
///     for pfd in fds.iter().filter(|pfd| pfd.revents != 0) {
///         for item in c.watch_handle(pfd.fd, WatchEvent::from_revents(pfd.revents)) {
///             // Handle item
///             println!("Received ConnectionItem: {:?}", item);
///         }
///     }
/// }
/// ```

#[repr(C)]
#[derive(Debug, PartialEq, Copy, Clone)]
/// The enum is here for backwards compatibility mostly.
///
/// It should really be bitflags instead.
pub enum WatchEvent {
    /// The fd is readable
    Readable = 1,
    /// The fd is writable
    Writable = 2,
    /// An error occured on the fd
    Error = 4,
    /// The fd received a hangup.
    Hangup = 8,
}

impl WatchEvent {
    /// After running poll, this transforms the revents into a parameter you can send into `Connection::watch_handle`
    pub fn from_revents(revents: libc::c_short) -> c_uint {
        0 +
        if (revents & libc::POLLIN) != 0 { WatchEvent::Readable as c_uint } else { 0 } +
        if (revents & libc::POLLOUT) != 0 { WatchEvent::Writable as c_uint } else { 0 } +
        if (revents & libc::POLLERR) != 0 { WatchEvent::Error as c_uint } else { 0 } +
        if (revents & libc::POLLHUP) != 0 { WatchEvent::Hangup as c_uint } else { 0 }
    }
}

#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
/// A file descriptor, and an indication whether it should be read from, written to, or both.
pub struct Watch {
    fd: RawFd,
    read: bool,
    write: bool,
}

impl Watch {
    /// Get the RawFd this Watch is for
    pub fn fd(&self) -> RawFd { self.fd }
    /// Add POLLIN to events to listen for
    pub fn readable(&self) -> bool { self.read }
    /// Add POLLOUT to events to listen for
    pub fn writable(&self) -> bool { self.write }
    /// Returns the current watch as a libc::pollfd, to use with libc::poll
    pub fn to_pollfd(&self) -> libc::pollfd {
        libc::pollfd { fd: self.fd, revents: 0, events: libc::POLLERR + libc::POLLHUP +
            if self.readable() { libc::POLLIN } else { 0 } +
            if self.writable() { libc::POLLOUT } else { 0 },
        }
    }
}

impl AsRawFd for Watch {
    fn as_raw_fd(&self) -> RawFd { self.fd }
}

/// Note - internal struct, not to be used outside API. Moving it outside its box will break things.
pub struct WatchList {
    watches: RefCell<Vec<*mut ffi::DBusWatch>>,
    enabled_fds: RefCell<Vec<Watch>>,
    on_update: Box<Fn(Watch)>
}

impl WatchList {
    pub fn new(c: &Connection, on_update: Box<Fn(Watch)>) -> Box<WatchList> {
        let w = Box::new(WatchList { on_update: on_update, watches: RefCell::new(vec!()), enabled_fds: RefCell::new(vec!()) });
        if unsafe { ffi::dbus_connection_set_watch_functions(super::connection::conn_handle(c),
            Some(add_watch_cb), Some(remove_watch_cb), Some(toggled_watch_cb), &*w as *const _ as *mut _, None) } == 0 {
            panic!("dbus_connection_set_watch_functions failed");
        }
        w
    }

    pub fn watch_handle(&self, fd: RawFd, flags: c_uint) {
        // println!("watch_handle {} flags {}", fd, flags);
        for &q in self.watches.borrow().iter() {
            let w = self.get_watch(q);
            if w.fd != fd { continue };
            if unsafe { ffi::dbus_watch_handle(q, flags) } == 0 {
                panic!("dbus_watch_handle failed");
            }
            self.update(q);
        };
    }

    pub fn get_enabled_fds(&self) -> Vec<Watch> {
        self.enabled_fds.borrow().clone()
    }

    fn get_watch(&self, watch: *mut ffi::DBusWatch) -> Watch {
        let mut w = Watch { fd: unsafe { ffi::dbus_watch_get_unix_fd(watch) }, read: false, write: false};
        let enabled = self.watches.borrow().contains(&watch) && unsafe { ffi::dbus_watch_get_enabled(watch) != 0 };
        let flags = unsafe { ffi::dbus_watch_get_flags(watch) };
        if enabled {
            w.read = (flags & WatchEvent::Readable as c_uint) != 0;
            w.write = (flags & WatchEvent::Writable as c_uint) != 0;
        }
        // println!("Get watch fd {:?} ptr {:?} enabled {:?} flags {:?}", w, watch, enabled, flags);
        w
    }

    fn update(&self, watch: *mut ffi::DBusWatch) {
        let mut w = self.get_watch(watch);

        for &q in self.watches.borrow().iter() {
            if q == watch { continue };
            let ww = self.get_watch(q);
            if ww.fd != w.fd { continue };
            w.read |= ww.read;
            w.write |= ww.write;
        }
        // println!("Updated sum: {:?}", w);

        {
            let mut fdarr = self.enabled_fds.borrow_mut();

            if w.write || w.read {
                if fdarr.contains(&w) { return; } // Nothing changed
            }
            else if !fdarr.iter().any(|q| w.fd == q.fd) { return; } // Nothing changed

            fdarr.retain(|f| f.fd != w.fd);
            if w.write || w.read { fdarr.push(w) };
        }
        (*self.on_update)(w);
    }
}

extern "C" fn add_watch_cb(watch: *mut ffi::DBusWatch, data: *mut c_void) -> u32 {
    let wlist: &WatchList = unsafe { mem::transmute(data) };
    // println!("Add watch {:?}", watch);
    wlist.watches.borrow_mut().push(watch);
    wlist.update(watch);
    1
}

extern "C" fn remove_watch_cb(watch: *mut ffi::DBusWatch, data: *mut c_void) {
    let wlist: &WatchList = unsafe { mem::transmute(data) };
    // println!("Removed watch {:?}", watch);
    wlist.watches.borrow_mut().retain(|w| *w != watch);
    wlist.update(watch);
}

extern "C" fn toggled_watch_cb(watch: *mut ffi::DBusWatch, data: *mut c_void) {
    let wlist: &WatchList = unsafe { mem::transmute(data) };
    // println!("Toggled watch {:?}", watch);
    wlist.update(watch);
}

#[cfg(test)]
mod test {
    use libc;
    use super::super::{Connection, Message, BusType, WatchEvent, ConnectionItem, MessageType};

    #[test]
    fn async() {
        let c = Connection::get_private(BusType::Session).unwrap();
        c.register_object_path("/test").unwrap();
        let m = Message::new_method_call(&c.unique_name(), "/test", "com.example.asynctest", "AsyncTest").unwrap();
        let serial = c.send(m).unwrap();
        println!("Async: sent serial {}", serial);

        let mut fds: Vec<_> = c.watch_fds().iter().map(|w| w.to_pollfd()).collect();
        let mut new_fds = None;
        let mut i = 0;
        let mut success = false;
        while !success {
            i += 1;
            if let Some(q) = new_fds { fds = q; new_fds = None };

            for f in fds.iter_mut() { f.revents = 0 };
            assert!(unsafe { libc::poll(fds.as_mut_ptr(), fds.len() as libc::c_ulong, 1000) } > 0);

            for f in fds.iter().filter(|pfd| pfd.revents != 0) {
                let m = WatchEvent::from_revents(f.revents);
                println!("Async: fd {}, revents {} -> {}", f.fd, f.revents, m);
                assert!(f.revents & libc::POLLIN != 0 || f.revents & libc::POLLOUT != 0);

                for e in c.watch_handle(f.fd, m) {
                    println!("Async: got {:?}", e);
                    match e {
                        ConnectionItem::WatchFd(_) => new_fds = Some(c.watch_fds().iter().map(|w| w.to_pollfd()).collect()),
                        ConnectionItem::MethodCall(m) => {
                            assert_eq!(m.headers(), (MessageType::MethodCall, Some("/test".to_string()),
                                Some("com.example.asynctest".into()), Some("AsyncTest".to_string())));
                            let mut mr = Message::new_method_return(&m).unwrap();
                            mr.append_items(&["Goodies".into()]);
                            c.send(mr).unwrap();
                        }
                        ConnectionItem::MethodReturn(m) => {
                            assert_eq!(m.headers().0, MessageType::MethodReturn);
                            assert_eq!(m.get_reply_serial().unwrap(), serial);
                            let i = m.get_items();
                            let s: &str = i[0].inner().unwrap();
                            assert_eq!(s, "Goodies");
                            success = true;
                        }
                        _ => (),
                    }
                }
                if i > 100 { panic!() };
            }
        }
    }
}
<|endoftext|>