<commit_before>use std::any::Any;
use std::error::Error;
use std::fmt;
use std::fmt::Debug;
use std::result;
use std::sync::mpsc;
use std::thread;

use time::{Duration, SteadyTime};

pub type InitResult<E> = result::Result<Option<u64>, E>;
pub type ActorResult<T> = result::Result<T, ActorError>;
pub type StartResult<T, E> = result::Result<Actor<T>, E>;
pub type ActorSender<T> = mpsc::Sender<Message<T>>;
pub type Receiver<T> = mpsc::Receiver<Message<T>>;

pub struct Actor<T>
    where T: Any + Send
{
    pub sender: ActorSender<T>,
    pub receiver: Receiver<T>,
    pub handle: thread::JoinHandle<ActorResult<()>>,
    pub name: Option<String>,
}

impl<T> Actor<T>
    where T: Any + Send
{
    /// Create a new actor handler struct.
    pub fn new(sender: ActorSender<T>,
               receiver: Receiver<T>,
               handle: thread::JoinHandle<ActorResult<()>>,
               name: Option<String>)
               -> Self {
        Actor {
            sender: sender,
            receiver: receiver,
            handle: handle,
            name: name,
        }
    }

    pub fn cast(&self, message: T) -> ActorResult<()> {
        self::cast(&self.sender, message)
    }

    pub fn call(&self, message: T) -> ActorResult<T> {
        self::call(&self.sender, &self.receiver, message)
    }
}

pub fn cast<T: Any + Send>(tx: &ActorSender<T>, message: T) -> ActorResult<()> {
    match tx.send(Message::Cast(message)) {
        Ok(()) => Ok(()),
        Err(err) => Err(ActorError::from(err)),
    }
}

pub fn call<T: Any + Send>(tx: &ActorSender<T>, rx: &Receiver<T>, message: T) -> ActorResult<T> {
    match tx.send(Message::Call(message)) {
        Ok(()) => {
            match rx.recv() {
                Ok(Message::Reply(msg)) => Ok(msg),
                Ok(_) => panic!("must reply from a call!"),
                Err(err) => Err(ActorError::from(err)),
            }
        }
        Err(err) => Err(ActorError::from(err)),
    }
}

pub struct Builder<T: GenServer> {
    name: Option<String>,
    spec: T,
}

impl<A: GenServer> Builder<A> {
    pub fn new(spec: A) -> Self {
        Builder {
            name: None,
            spec: spec,
        }
    }

    pub fn name(mut self, name: String) -> Builder<A> {
        self.name = Some(name);
        self
    }

    /// Start an actor on a new thread and return an Actor.
    pub fn start(self, mut state: A::S) -> StartResult<A::T, A::E> {
        let (otx, orx) = mpsc::channel::<Message<A::T>>();
        let (itx, irx) = mpsc::channel::<Message<A::T>>();
        let initial_wait_ms = match self.spec.init(&itx, &mut state) {
            Ok(result) => result,
            Err(err) => return Err(err),
        };
        let itx2 = itx.clone(); // clone inner receive loop's sender for actor struct
        let name = self.name.clone();
        let thread_name = name.clone().unwrap_or("GenServer".to_string());
        let handle = thread::Builder::new()
            .name(thread_name.clone())
            .spawn(move || {
                let mut timeout: Option<SteadyTime> = None;
                if let Some(ms) = initial_wait_ms {
                    set_timeout(ms, &mut timeout);
                }
                loop {
                    if let Some(go_time) = timeout {
                        if go_time <= SteadyTime::now() {
                            match self.spec.handle_timeout(&otx, &itx, &mut state) {
                                HandleResult::Stop(reason, None) => {
                                    return shutdown(reason, None, &otx)
                                }
                                HandleResult::NoReply(Some(0)) => {
                                    set_timeout(0, &mut timeout);
                                    continue;
                                }
                                HandleResult::NoReply(new_timeout) => {
                                    if let Some(ms) = new_timeout {
                                        set_timeout(ms, &mut timeout);
                                    }
                                }
                                hr => {
                                    panic!("unexpected `HandleResult` returned from \
                                            handle_timeout: {:?}",
                                           hr)
                                }
                            }
                        }
                    }
                    match irx.try_recv() {
                        Ok(Message::Call(msg)) => {
                            match self.spec.handle_call(msg, &otx, &itx, &mut state) {
                                HandleResult::Reply(msg, new_timeout) => {
                                    try!(otx.send(Message::Reply(msg)));
                                    if let Some(ms) = new_timeout {
                                        set_timeout(ms, &mut timeout);
                                    }
                                }
                                HandleResult::NoReply(new_timeout) => {
                                    if let Some(ms) = new_timeout {
                                        set_timeout(ms, &mut timeout);
                                    }
                                }
                                HandleResult::Stop(reason, reply) => {
                                    return shutdown(reason, reply, &otx)
                                }
                            }
                        }
                        Ok(Message::Cast(msg)) => {
                            match self.spec.handle_cast(msg, &otx, &itx, &mut state) {
                                HandleResult::Stop(reason, reply) => {
                                    return shutdown(reason, reply, &otx)
                                }
                                HandleResult::NoReply(new_timeout) => {
                                    if let Some(ms) = new_timeout {
                                        set_timeout(ms, &mut timeout);
                                    }
                                }
                                hr => {
                                    panic!("unexpected `HandleResult` returned from handle_cast: \
                                            {:?}",
                                           hr)
                                }
                            }
                        }
                        Ok(hr) => panic!("received unexpected message type: {:?}", hr),
                        Err(mpsc::TryRecvError::Disconnected) => {
                            break;
                        }
                        Err(mpsc::TryRecvError::Empty) => {}
                    }
                    // This is absolutely the wrong solution. I need to park the thread or call
                    // recv instead of try_recv and schedule the timeout mechanism another way.
                    // This is a quick and dirty workaround that should be short lived while the API
                    // stabilizes and is leveraged in our other applications.
                    //
                    // I'm so sorry for doing this.
                    //      - Jamie
                    thread::sleep_ms(30)
                }
                Ok(())
            })
            .unwrap();
        Ok(Actor::new(itx2, orx, handle, name))
    }
}

#[derive(Debug)]
pub enum ActorError {
    InitFailure(String),
    AbnormalShutdown(String),
    SendError,
    RecvError,
}

impl<T: Any + Send> From<mpsc::SendError<Message<T>>> for ActorError {
    fn from(_err: mpsc::SendError<Message<T>>) -> Self {
        ActorError::SendError
    }
}

impl From<mpsc::RecvError> for ActorError {
    fn from(_err: mpsc::RecvError) -> Self {
        ActorError::RecvError
    }
}

#[derive(Debug)]
pub enum StopReason {
    Normal,
    Fatal(String),
}

#[derive(Debug)]
pub enum HandleResult<T>
    where T: Any + Send
{
    Reply(T, Option<u64>),
    NoReply(Option<u64>),
    Stop(StopReason, Option<T>),
}

pub enum Message<T>
    where T: Any + Send
{
    Call(T),
    Cast(T),
    Reply(T),
}

impl<T> Debug for Message<T>
    where T: Any + Send + Debug
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            &Message::Call(ref msg) => write!(f, "CALL: {:?}", msg),
            &Message::Cast(ref msg) => write!(f, "CAST: {:?}", msg),
            &Message::Reply(ref msg) => write!(f, "REPLY: {:?}", msg),
        }
    }
}

pub trait GenServer: Send + 'static {
    type T: Send + Any + Debug;
    type S: Send + Any;
    type E: Error + 'static;

    fn init(&self, _tx: &ActorSender<Self::T>, state: &mut Self::S) -> InitResult<Self::E>;

    fn handle_call(&self,
                   message: Self::T,
                   _tx: &ActorSender<Self::T>,
                   _me: &ActorSender<Self::T>,
                   _state: &mut Self::S)
                   -> HandleResult<Self::T> {
        panic!("handle_call callback not implemented; received: {:?}",
               message);
    }

    fn handle_cast(&self,
                   message: Self::T,
                   _tx: &ActorSender<Self::T>,
                   _me: &ActorSender<Self::T>,
                   _state: &mut Self::S)
                   -> HandleResult<Self::T> {
        panic!("handle_cast callback not implemented; received: {:?}",
               message);
    }

    fn handle_timeout(&self,
                      _tx: &ActorSender<Self::T>,
                      _me: &ActorSender<Self::T>,
                      _state: &mut Self::S)
                      -> HandleResult<Self::T> {
        HandleResult::NoReply(None)
    }
}

fn set_timeout(wait_ms: u64, current_timeout: &mut Option<SteadyTime>) {
    *current_timeout = Some(SteadyTime::now() + Duration::milliseconds(wait_ms as i64));
}

fn shutdown<T: Any + Send>(reason: StopReason,
                           reply: Option<T>,
                           sender: &ActorSender<T>)
                           -> Result<(), ActorError> {
    if let Some(msg) = reply {
        let _result = sender.send(Message::Reply(msg));
    }
    match reason {
        StopReason::Normal => Ok(()),
        StopReason::Fatal(e) => Err(ActorError::AbnormalShutdown(e)),
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::fmt;
    use std::error::Error;

    struct Worker;

    struct MyState {
        pub initialized: bool,
    }

    impl MyState {
        pub fn new() -> Self {
            MyState { initialized: false }
        }
    }

    #[derive(Debug)]
    enum MyError {
        DirtyState,
    }

    #[derive(Debug)]
    enum MyMessage {
        Ok,
        Stop,
        State(bool),
        GetState,
        SetState(bool),
    }

    impl GenServer for Worker {
        type T = MyMessage;
        type S = MyState;
        type E = MyError;

        fn init(&self, _tx: &ActorSender<Self::T>, state: &mut Self::S) -> InitResult<Self::E> {
            if state.initialized {
                Err(MyError::DirtyState)
            } else {
                state.initialized = true;
                Ok(None)
            }
        }

        fn handle_call(&self,
                       msg: Self::T,
                       _: &ActorSender<Self::T>,
                       _: &ActorSender<Self::T>,
                       state: &mut Self::S)
                       -> HandleResult<Self::T> {
            match msg {
                MyMessage::Stop => HandleResult::Stop(StopReason::Normal, Some(MyMessage::Ok)),
                MyMessage::GetState => {
                    HandleResult::Reply(MyMessage::State(state.initialized), None)
                }
                MyMessage::SetState(value) => {
                    state.initialized = value;
                    HandleResult::Reply(MyMessage::Ok, None)
                }
                _ => HandleResult::Stop(StopReason::Fatal(String::from("Nope")), None),
            }
        }

        fn handle_cast(&self,
                       msg: Self::T,
                       _: &ActorSender<Self::T>,
                       _: &ActorSender<Self::T>,
                       state: &mut Self::S)
                       -> HandleResult<Self::T> {
            match msg {
                MyMessage::SetState(value) => {
                    state.initialized = value;
                    HandleResult::NoReply(None)
                }
                _ => HandleResult::NoReply(None),
            }
        }
    }

    impl fmt::Display for MyError {
        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
            match *self {
                MyError::DirtyState => write!(f, "state already initialized"),
            }
        }
    }

    impl Error for MyError {
        fn description(&self) -> &str {
            match *self {
                MyError::DirtyState => "state already initialized",
            }
        }
    }

    #[test]
    fn error_on_init() {
        let mut state = MyState::new();
        state.initialized = true;
        match Builder::new(Worker).start(state) {
            Err(MyError::DirtyState) => assert!(true),
            Ok(_) => assert!(false),
        }
    }

    #[test]
    fn call_set_get_state() {
        let state = MyState::new();
        let actor = Builder::new(Worker).start(state).unwrap();
        match actor.call(MyMessage::GetState) {
            Ok(MyMessage::State(true)) => assert!(true),
            _ => assert!(false),
        }
        assert!(actor.call(MyMessage::SetState(false)).is_ok());
        match actor.call(MyMessage::GetState) {
            Ok(MyMessage::State(false)) => assert!(true),
            _ => assert!(false),
        }
    }

    #[test]
    fn multiple_cast_and_call_ordered() {
        let state = MyState::new();
        let actor = Builder::new(Worker).start(state).unwrap();
        assert!(actor.cast(MyMessage::SetState(false)).is_ok());
        assert!(actor.cast(MyMessage::SetState(true)).is_ok());
        assert!(actor.cast(MyMessage::SetState(false)).is_ok());
        match actor.call(MyMessage::GetState) {
            Ok(MyMessage::State(result)) => assert_eq!(result, false),
            _ => assert!(false),
        }
    }

    #[test]
    fn stopping_an_actor() {
        let state = MyState::new();
        let actor = Builder::new(Worker).start(state).unwrap();
        match actor.call(MyMessage::Stop) {
            Ok(MyMessage::Ok) => assert!(true),
            _ => assert!(false),
        }
        match actor.handle.join() {
            Ok(_) => assert!(true),
            Err(_) => assert!(false),
        }
    }

    #[test]
    fn explicitly_naming_actor() {
        let state = MyState::new();
        let actor = Builder::new(Worker).name("batman".to_string()).start(state).unwrap();
        assert!(actor.name.is_some());
        assert_eq!(actor.name.unwrap(), "batman".to_string());
    }

    #[test]
    fn default_named_actor() {
        let state = MyState::new();
        let actor = Builder::new(Worker).start(state).unwrap();
        assert!(actor.name.is_none());
    }
}
<commit_msg>fix compiler warnings<commit_after>use std::any::Any;
use std::error::Error;
use std::fmt;
use std::fmt::Debug;
use std::result;
use std::sync::mpsc;
use std::thread;
use std::time;

use time::{Duration, SteadyTime};

pub type InitResult<E> = result::Result<Option<u64>, E>;
pub type ActorResult<T> = result::Result<T, ActorError>;
pub type StartResult<T, E> = result::Result<Actor<T>, E>;
pub type ActorSender<T> = mpsc::Sender<Message<T>>;
pub type Receiver<T> = mpsc::Receiver<Message<T>>;

pub struct Actor<T>
    where T: Any + Send
{
    pub sender: ActorSender<T>,
    pub receiver: Receiver<T>,
    pub handle: thread::JoinHandle<ActorResult<()>>,
    pub name: Option<String>,
}

impl<T> Actor<T>
    where T: Any + Send
{
    /// Create a new actor handler struct.
    pub fn new(sender: ActorSender<T>,
               receiver: Receiver<T>,
               handle: thread::JoinHandle<ActorResult<()>>,
               name: Option<String>)
               -> Self {
        Actor {
            sender: sender,
            receiver: receiver,
            handle: handle,
            name: name,
        }
    }

    pub fn cast(&self, message: T) -> ActorResult<()> {
        self::cast(&self.sender, message)
    }

    pub fn call(&self, message: T) -> ActorResult<T> {
        self::call(&self.sender, &self.receiver, message)
    }
}

pub fn cast<T: Any + Send>(tx: &ActorSender<T>, message: T) -> ActorResult<()> {
    match tx.send(Message::Cast(message)) {
        Ok(()) => Ok(()),
        Err(err) => Err(ActorError::from(err)),
    }
}

pub fn call<T: Any + Send>(tx: &ActorSender<T>, rx: &Receiver<T>, message: T) -> ActorResult<T> {
    match tx.send(Message::Call(message)) {
        Ok(()) => {
            match rx.recv() {
                Ok(Message::Reply(msg)) => Ok(msg),
                Ok(_) => panic!("must reply from a call!"),
                Err(err) => Err(ActorError::from(err)),
            }
        }
        Err(err) => Err(ActorError::from(err)),
    }
}

pub struct Builder<T: GenServer> {
    name: Option<String>,
    spec: T,
}

impl<A: GenServer> Builder<A> {
    pub fn new(spec: A) -> Self {
        Builder {
            name: None,
            spec: spec,
        }
    }

    pub fn name(mut self, name: String) -> Builder<A> {
        self.name = Some(name);
        self
    }

    /// Start an actor on a new thread and return an Actor.
    pub fn start(self, mut state: A::S) -> StartResult<A::T, A::E> {
        let (otx, orx) = mpsc::channel::<Message<A::T>>();
        let (itx, irx) = mpsc::channel::<Message<A::T>>();
        let initial_wait_ms = match self.spec.init(&itx, &mut state) {
            Ok(result) => result,
            Err(err) => return Err(err),
        };
        let itx2 = itx.clone(); // clone inner receive loop's sender for actor struct
        let name = self.name.clone();
        let thread_name = name.clone().unwrap_or("GenServer".to_string());
        let handle = thread::Builder::new()
            .name(thread_name.clone())
            .spawn(move || {
                let mut timeout: Option<SteadyTime> = None;
                if let Some(ms) = initial_wait_ms {
                    set_timeout(ms, &mut timeout);
                }
                loop {
                    if let Some(go_time) = timeout {
                        if go_time <= SteadyTime::now() {
                            match self.spec.handle_timeout(&otx, &itx, &mut state) {
                                HandleResult::Stop(reason, None) => {
                                    return shutdown(reason, None, &otx)
                                }
                                HandleResult::NoReply(Some(0)) => {
                                    set_timeout(0, &mut timeout);
                                    continue;
                                }
                                HandleResult::NoReply(new_timeout) => {
                                    if let Some(ms) = new_timeout {
                                        set_timeout(ms, &mut timeout);
                                    }
                                }
                                hr => {
                                    panic!("unexpected `HandleResult` returned from \
                                            handle_timeout: {:?}",
                                           hr)
                                }
                            }
                        }
                    }
                    match irx.try_recv() {
                        Ok(Message::Call(msg)) => {
                            match self.spec.handle_call(msg, &otx, &itx, &mut state) {
                                HandleResult::Reply(msg, new_timeout) => {
                                    try!(otx.send(Message::Reply(msg)));
                                    if let Some(ms) = new_timeout {
                                        set_timeout(ms, &mut timeout);
                                    }
                                }
                                HandleResult::NoReply(new_timeout) => {
                                    if let Some(ms) = new_timeout {
                                        set_timeout(ms, &mut timeout);
                                    }
                                }
                                HandleResult::Stop(reason, reply) => {
                                    return shutdown(reason, reply, &otx)
                                }
                            }
                        }
                        Ok(Message::Cast(msg)) => {
                            match self.spec.handle_cast(msg, &otx, &itx, &mut state) {
                                HandleResult::Stop(reason, reply) => {
                                    return shutdown(reason, reply, &otx)
                                }
                                HandleResult::NoReply(new_timeout) => {
                                    if let Some(ms) = new_timeout {
                                        set_timeout(ms, &mut timeout);
                                    }
                                }
                                hr => {
                                    panic!("unexpected `HandleResult` returned from handle_cast: \
                                            {:?}",
                                           hr)
                                }
                            }
                        }
                        Ok(hr) => panic!("received unexpected message type: {:?}", hr),
                        Err(mpsc::TryRecvError::Disconnected) => {
                            break;
                        }
                        Err(mpsc::TryRecvError::Empty) => {}
                    }
                    // This is absolutely the wrong solution. I need to park the thread or call
                    // recv instead of try_recv and schedule the timeout mechanism another way.
                    // This is a quick and dirty workaround that should be short lived while the API
                    // stabilizes and is leveraged in our other applications.
                    //
                    // I'm so sorry for doing this.
                    //      - Jamie
                    thread::sleep(time::Duration::from_millis(30));
                }
                Ok(())
            })
            .unwrap();
        Ok(Actor::new(itx2, orx, handle, name))
    }
}

#[derive(Debug)]
pub enum ActorError {
    InitFailure(String),
    AbnormalShutdown(String),
    SendError,
    RecvError,
}

impl<T: Any + Send> From<mpsc::SendError<Message<T>>> for ActorError {
    fn from(_err: mpsc::SendError<Message<T>>) -> Self {
        ActorError::SendError
    }
}

impl From<mpsc::RecvError> for ActorError {
    fn from(_err: mpsc::RecvError) -> Self {
        ActorError::RecvError
    }
}

#[derive(Debug)]
pub enum StopReason {
    Normal,
    Fatal(String),
}

#[derive(Debug)]
pub enum HandleResult<T>
    where T: Any + Send
{
    Reply(T, Option<u64>),
    NoReply(Option<u64>),
    Stop(StopReason, Option<T>),
}

pub enum Message<T>
    where T: Any + Send
{
    Call(T),
    Cast(T),
    Reply(T),
}

impl<T> Debug for Message<T>
    where T: Any + Send + Debug
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            &Message::Call(ref msg) => write!(f, "CALL: {:?}", msg),
            &Message::Cast(ref msg) => write!(f, "CAST: {:?}", msg),
            &Message::Reply(ref msg) => write!(f, "REPLY: {:?}", msg),
        }
    }
}

pub trait GenServer: Send + 'static {
    type T: Send + Any + Debug;
    type S: Send + Any;
    type E: Error + 'static;

    fn init(&self, _tx: &ActorSender<Self::T>, state: &mut Self::S) -> InitResult<Self::E>;

    fn handle_call(&self,
                   message: Self::T,
                   _tx: &ActorSender<Self::T>,
                   _me: &ActorSender<Self::T>,
                   _state: &mut Self::S)
                   -> HandleResult<Self::T> {
        panic!("handle_call callback not implemented; received: {:?}",
               message);
    }

    fn handle_cast(&self,
                   message: Self::T,
                   _tx: &ActorSender<Self::T>,
                   _me: &ActorSender<Self::T>,
                   _state: &mut Self::S)
                   -> HandleResult<Self::T> {
        panic!("handle_cast callback not implemented; received: {:?}",
               message);
    }

    fn handle_timeout(&self,
                      _tx: &ActorSender<Self::T>,
                      _me: &ActorSender<Self::T>,
                      _state: &mut Self::S)
                      -> HandleResult<Self::T> {
        HandleResult::NoReply(None)
    }
}

fn set_timeout(wait_ms: u64, current_timeout: &mut Option<SteadyTime>) {
    *current_timeout = Some(SteadyTime::now() + Duration::milliseconds(wait_ms as i64));
}

fn shutdown<T: Any + Send>(reason: StopReason,
                           reply: Option<T>,
                           sender: &ActorSender<T>)
                           -> Result<(), ActorError> {
    if let Some(msg) = reply {
        let _result = sender.send(Message::Reply(msg));
    }
    match reason {
        StopReason::Normal => Ok(()),
        StopReason::Fatal(e) => Err(ActorError::AbnormalShutdown(e)),
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::fmt;
    use std::error::Error;

    struct Worker;

    struct MyState {
        pub initialized: bool,
    }

    impl MyState {
        pub fn new() -> Self {
            MyState { initialized: false }
        }
    }

    #[derive(Debug)]
    enum MyError {
        DirtyState,
    }

    #[derive(Debug)]
    enum MyMessage {
        Ok,
        Stop,
        State(bool),
        GetState,
        SetState(bool),
    }

    impl GenServer for Worker {
        type T = MyMessage;
        type S = MyState;
        type E = MyError;

        fn init(&self, _tx: &ActorSender<Self::T>, state: &mut Self::S) -> InitResult<Self::E> {
            if state.initialized {
                Err(MyError::DirtyState)
            } else {
                state.initialized = true;
                Ok(None)
            }
        }

        fn handle_call(&self,
                       msg: Self::T,
                       _: &ActorSender<Self::T>,
                       _: &ActorSender<Self::T>,
                       state: &mut Self::S)
                       -> HandleResult<Self::T> {
            match msg {
                MyMessage::Stop => HandleResult::Stop(StopReason::Normal, Some(MyMessage::Ok)),
                MyMessage::GetState => {
                    HandleResult::Reply(MyMessage::State(state.initialized), None)
                }
                MyMessage::SetState(value) => {
                    state.initialized = value;
                    HandleResult::Reply(MyMessage::Ok, None)
                }
                _ => HandleResult::Stop(StopReason::Fatal(String::from("Nope")), None),
            }
        }

        fn handle_cast(&self,
                       msg: Self::T,
                       _: &ActorSender<Self::T>,
                       _: &ActorSender<Self::T>,
                       state: &mut Self::S)
                       -> HandleResult<Self::T> {
            match msg {
                MyMessage::SetState(value) => {
                    state.initialized = value;
                    HandleResult::NoReply(None)
                }
                _ => HandleResult::NoReply(None),
            }
        }
    }

    impl fmt::Display for MyError {
        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
            match *self {
                MyError::DirtyState => write!(f, "state already initialized"),
            }
        }
    }

    impl Error for MyError {
        fn description(&self) -> &str {
            match *self {
                MyError::DirtyState => "state already initialized",
            }
        }
    }

    #[test]
    fn error_on_init() {
        let mut state = MyState::new();
        state.initialized = true;
        match Builder::new(Worker).start(state) {
            Err(MyError::DirtyState) => assert!(true),
            Ok(_) => assert!(false),
        }
    }

    #[test]
    fn call_set_get_state() {
        let state = MyState::new();
        let actor = Builder::new(Worker).start(state).unwrap();
        match actor.call(MyMessage::GetState) {
            Ok(MyMessage::State(true)) => assert!(true),
            _ => assert!(false),
        }
        assert!(actor.call(MyMessage::SetState(false)).is_ok());
        match actor.call(MyMessage::GetState) {
            Ok(MyMessage::State(false)) => assert!(true),
            _ => assert!(false),
        }
    }

    #[test]
    fn multiple_cast_and_call_ordered() {
        let state = MyState::new();
        let actor = Builder::new(Worker).start(state).unwrap();
        assert!(actor.cast(MyMessage::SetState(false)).is_ok());
        assert!(actor.cast(MyMessage::SetState(true)).is_ok());
        assert!(actor.cast(MyMessage::SetState(false)).is_ok());
        match actor.call(MyMessage::GetState) {
            Ok(MyMessage::State(result)) => assert_eq!(result, false),
            _ => assert!(false),
        }
    }

    #[test]
    fn stopping_an_actor() {
        let state = MyState::new();
        let actor = Builder::new(Worker).start(state).unwrap();
        match actor.call(MyMessage::Stop) {
            Ok(MyMessage::Ok) => assert!(true),
            _ => assert!(false),
        }
        match actor.handle.join() {
            Ok(_) => assert!(true),
            Err(_) => assert!(false),
        }
    }

    #[test]
    fn explicitly_naming_actor() {
        let state = MyState::new();
        let actor = Builder::new(Worker).name("batman".to_string()).start(state).unwrap();
        assert!(actor.name.is_some());
        assert_eq!(actor.name.unwrap(), "batman".to_string());
    }

    #[test]
    fn default_named_actor() {
        let state = MyState::new();
        let actor = Builder::new(Worker).start(state).unwrap();
        assert!(actor.name.is_none());
    }
}
<|endoftext|>


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

use num_traits::{Float, FloatConst, Zero};
use core::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Rem, Sub, SubAssign};
use core::cmp::{Eq, PartialEq};
use core::hash::{Hash};
use trig::Trig;
#[cfg(feature = "serde")]
use serde;

/// An angle in radians
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct Angle<T> {
    pub radians: T,
}

impl<T> Angle<T> {
    #[inline]
    pub fn radians(radians: T) -> Self {
        Angle { radians }
    }

    #[inline]
    pub fn get(self) -> T {
        self.radians
    }
}

impl<T> Angle<T>
where
    T: Trig,
{
    #[inline]
    pub fn degrees(deg: T) -> Self {
        Angle {
            radians: T::degrees_to_radians(deg),
        }
    }

    #[inline]
    pub fn to_degrees(self) -> T {
        T::radians_to_degrees(self.radians)
    }
}

impl<T> Angle<T>
where
    T: Rem<Output = T> + Sub<Output = T> + Add<Output = T> + Zero + FloatConst + PartialOrd + Copy,
{
    /// Returns this angle in the [0..2*PI[ range.
    pub fn positive(&self) -> Self {
        let two_pi = T::PI() + T::PI();
        let mut a = self.radians % two_pi;
        if a < T::zero() {
            a = a + two_pi;
        }
        Angle::radians(a)
    }

    /// Returns this angle in the ]-PI..PI] range.
    pub fn signed(&self) -> Self {
        Angle::pi() - (Angle::pi() - *self).positive()
    }
}

impl<T> Angle<T>
where
    T: Float,
{
    /// Returns (sin(self), cos(self)).
    pub fn sin_cos(self) -> (T, T) {
        self.radians.sin_cos()
    }
}

impl<T> Angle<T>
where
    T: Zero,
{
    pub fn zero() -> Self {
        Angle::radians(T::zero())
    }
}

impl<T> Angle<T>
where
    T: FloatConst + Add<Output = T>,
{
    pub fn pi() -> Self {
        Angle::radians(T::PI())
    }

    pub fn two_pi() -> Self {
        Angle::radians(T::PI() + T::PI())
    }

    pub fn frac_pi_2() -> Self {
        Angle::radians(T::FRAC_PI_2())
    }

    pub fn frac_pi_3() -> Self {
        Angle::radians(T::FRAC_PI_3())
    }

    pub fn frac_pi_4() -> Self {
        Angle::radians(T::FRAC_PI_4())
    }
}

impl<T: Add<T, Output = T>> Add for Angle<T> {
    type Output = Angle<T>;
    fn add(self, other: Angle<T>) -> Angle<T> {
        Angle::radians(self.radians + other.radians)
    }
}

impl<T: AddAssign<T>> AddAssign for Angle<T> {
    fn add_assign(&mut self, other: Angle<T>) {
        self.radians += other.radians;
    }
}

impl<T: Sub<T, Output = T>> Sub<Angle<T>> for Angle<T> {
    type Output = Angle<T>;
    fn sub(self, other: Angle<T>) -> <Self as Sub>::Output {
        Angle::radians(self.radians - other.radians)
    }
}

impl<T: SubAssign<T>> SubAssign for Angle<T> {
    fn sub_assign(&mut self, other: Angle<T>) {
        self.radians -= other.radians;
    }
}

impl<T: Div<T, Output = T>> Div<Angle<T>> for Angle<T> {
    type Output = T;
    #[inline]
    fn div(self, other: Angle<T>) -> T {
        self.radians / other.radians
    }
}

impl<T: Div<T, Output = T>> Div<T> for Angle<T> {
    type Output = Angle<T>;
    #[inline]
    fn div(self, factor: T) -> Angle<T> {
        Angle::radians(self.radians / factor)
    }
}

impl<T: DivAssign<T>> DivAssign<T> for Angle<T> {
    fn div_assign(&mut self, factor: T) {
        self.radians /= factor;
    }
}

impl<T: Mul<T, Output = T>> Mul<T> for Angle<T> {
    type Output = Angle<T>;
    #[inline]
    fn mul(self, factor: T) -> Angle<T> {
        Angle::radians(self.radians * factor)
    }
}

impl<T: MulAssign<T>> MulAssign<T> for Angle<T> {
    fn mul_assign(&mut self, factor: T) {
        self.radians *= factor;
    }
}

impl<T: Neg<Output = T>> Neg for Angle<T> {
    type Output = Self;
    fn neg(self) -> Self {
        Angle::radians(-self.radians)
    }
}

#[test]
fn wrap_angles() {
    use approxeq::ApproxEq;
    use core::f32::consts::{FRAC_PI_2, PI};

    assert!(Angle::radians(0.0).positive().radians.approx_eq(&0.0));
    assert!(
        Angle::radians(FRAC_PI_2)
            .positive()
            .radians
            .approx_eq(&FRAC_PI_2)
    );
    assert!(
        Angle::radians(-FRAC_PI_2)
            .positive()
            .radians
            .approx_eq(&(3.0 * FRAC_PI_2))
    );
    assert!(
        Angle::radians(3.0 * FRAC_PI_2)
            .positive()
            .radians
            .approx_eq(&(3.0 * FRAC_PI_2))
    );
    assert!(
        Angle::radians(5.0 * FRAC_PI_2)
            .positive()
            .radians
            .approx_eq(&FRAC_PI_2)
    );
    assert!(Angle::radians(2.0 * PI).positive().radians.approx_eq(&0.0));
    assert!(Angle::radians(-2.0 * PI).positive().radians.approx_eq(&0.0));
    assert!(Angle::radians(PI).positive().radians.approx_eq(&PI));
    assert!(Angle::radians(-PI).positive().radians.approx_eq(&PI));

    assert!(
        Angle::radians(FRAC_PI_2)
            .signed()
            .radians
            .approx_eq(&FRAC_PI_2)
    );
    assert!(
        Angle::radians(3.0 * FRAC_PI_2)
            .signed()
            .radians
            .approx_eq(&-FRAC_PI_2)
    );
    assert!(
        Angle::radians(5.0 * FRAC_PI_2)
            .signed()
            .radians
            .approx_eq(&FRAC_PI_2)
    );
    assert!(Angle::radians(2.0 * PI).signed().radians.approx_eq(&0.0));
    assert!(Angle::radians(-2.0 * PI).signed().radians.approx_eq(&0.0));
    assert!(Angle::radians(-PI).signed().radians.approx_eq(&PI));
    assert!(Angle::radians(PI).signed().radians.approx_eq(&PI));
}
<commit_msg>Implemented ApproxEq<T> for Angle<T><commit_after>// Copyright 2013 The Servo Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use num_traits::{Float, FloatConst, Zero};
use core::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Rem, Sub, SubAssign};
use core::cmp::{Eq, PartialEq};
use core::hash::{Hash};
use trig::Trig;
use approxeq::ApproxEq;
#[cfg(feature = "serde")]
use serde;

/// An angle in radians
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct Angle<T> {
    pub radians: T,
}

impl<T> Angle<T> {
    #[inline]
    pub fn radians(radians: T) -> Self {
        Angle { radians }
    }

    #[inline]
    pub fn get(self) -> T {
        self.radians
    }
}

impl<T> Angle<T>
where
    T: Trig,
{
    #[inline]
    pub fn degrees(deg: T) -> Self {
        Angle {
            radians: T::degrees_to_radians(deg),
        }
    }

    #[inline]
    pub fn to_degrees(self) -> T {
        T::radians_to_degrees(self.radians)
    }
}

impl<T> Angle<T>
where
    T: Rem<Output = T> + Sub<Output = T> + Add<Output = T> + Zero + FloatConst + PartialOrd + Copy,
{
    /// Returns this angle in the [0..2*PI[ range.
    pub fn positive(&self) -> Self {
        let two_pi = T::PI() + T::PI();
        let mut a = self.radians % two_pi;
        if a < T::zero() {
            a = a + two_pi;
        }
        Angle::radians(a)
    }

    /// Returns this angle in the ]-PI..PI] range.
    pub fn signed(&self) -> Self {
        Angle::pi() - (Angle::pi() - *self).positive()
    }
}

impl<T> Angle<T>
where
    T: Float,
{
    /// Returns (sin(self), cos(self)).
    pub fn sin_cos(self) -> (T, T) {
        self.radians.sin_cos()
    }
}

impl<T> Angle<T>
where
    T: Zero,
{
    pub fn zero() -> Self {
        Angle::radians(T::zero())
    }
}

impl<T> Angle<T>
where
    T: FloatConst + Add<Output = T>,
{
    pub fn pi() -> Self {
        Angle::radians(T::PI())
    }

    pub fn two_pi() -> Self {
        Angle::radians(T::PI() + T::PI())
    }

    pub fn frac_pi_2() -> Self {
        Angle::radians(T::FRAC_PI_2())
    }

    pub fn frac_pi_3() -> Self {
        Angle::radians(T::FRAC_PI_3())
    }

    pub fn frac_pi_4() -> Self {
        Angle::radians(T::FRAC_PI_4())
    }
}

impl<T: Add<T, Output = T>> Add for Angle<T> {
    type Output = Angle<T>;
    fn add(self, other: Angle<T>) -> Angle<T> {
        Angle::radians(self.radians + other.radians)
    }
}

impl<T: AddAssign<T>> AddAssign for Angle<T> {
    fn add_assign(&mut self, other: Angle<T>) {
        self.radians += other.radians;
    }
}

impl<T: Sub<T, Output = T>> Sub<Angle<T>> for Angle<T> {
    type Output = Angle<T>;
    fn sub(self, other: Angle<T>) -> <Self as Sub>::Output {
        Angle::radians(self.radians - other.radians)
    }
}

impl<T: SubAssign<T>> SubAssign for Angle<T> {
    fn sub_assign(&mut self, other: Angle<T>) {
        self.radians -= other.radians;
    }
}

impl<T: Div<T, Output = T>> Div<Angle<T>> for Angle<T> {
    type Output = T;
    #[inline]
    fn div(self, other: Angle<T>) -> T {
        self.radians / other.radians
    }
}

impl<T: Div<T, Output = T>> Div<T> for Angle<T> {
    type Output = Angle<T>;
    #[inline]
    fn div(self, factor: T) -> Angle<T> {
        Angle::radians(self.radians / factor)
    }
}

impl<T: DivAssign<T>> DivAssign<T> for Angle<T> {
    fn div_assign(&mut self, factor: T) {
        self.radians /= factor;
    }
}

impl<T: Mul<T, Output = T>> Mul<T> for Angle<T> {
    type Output = Angle<T>;
    #[inline]
    fn mul(self, factor: T) -> Angle<T> {
        Angle::radians(self.radians * factor)
    }
}

impl<T: MulAssign<T>> MulAssign<T> for Angle<T> {
    fn mul_assign(&mut self, factor: T) {
        self.radians *= factor;
    }
}

impl<T: Neg<Output = T>> Neg for Angle<T> {
    type Output = Self;
    fn neg(self) -> Self {
        Angle::radians(-self.radians)
    }
}

impl<T: ApproxEq<T>> ApproxEq<T> for Angle<T> {
    #[inline]
    fn approx_epsilon() -> T {
        T::approx_epsilon()
    }

    #[inline]
    fn approx_eq_eps(&self, other: &Angle<T>, approx_epsilon: &T) -> bool {
        self.radians.approx_eq_eps(&other.radians, approx_epsilon)
    }
}

#[test]
fn wrap_angles() {
    use approxeq::ApproxEq;
    use core::f32::consts::{FRAC_PI_2, PI};

    assert!(Angle::radians(0.0).positive().radians.approx_eq(&0.0));
    assert!(
        Angle::radians(FRAC_PI_2)
            .positive()
            .radians
            .approx_eq(&FRAC_PI_2)
    );
    assert!(
        Angle::radians(-FRAC_PI_2)
            .positive()
            .radians
            .approx_eq(&(3.0 * FRAC_PI_2))
    );
    assert!(
        Angle::radians(3.0 * FRAC_PI_2)
            .positive()
            .radians
            .approx_eq(&(3.0 * FRAC_PI_2))
    );
    assert!(
        Angle::radians(5.0 * FRAC_PI_2)
            .positive()
            .radians
            .approx_eq(&FRAC_PI_2)
    );
    assert!(Angle::radians(2.0 * PI).positive().radians.approx_eq(&0.0));
    assert!(Angle::radians(-2.0 * PI).positive().radians.approx_eq(&0.0));
    assert!(Angle::radians(PI).positive().radians.approx_eq(&PI));
    assert!(Angle::radians(-PI).positive().radians.approx_eq(&PI));

    assert!(
        Angle::radians(FRAC_PI_2)
            .signed()
            .radians
            .approx_eq(&FRAC_PI_2)
    );
    assert!(
        Angle::radians(3.0 * FRAC_PI_2)
            .signed()
            .radians
            .approx_eq(&-FRAC_PI_2)
    );
    assert!(
        Angle::radians(5.0 * FRAC_PI_2)
            .signed()
            .radians
            .approx_eq(&FRAC_PI_2)
    );
    assert!(Angle::radians(2.0 * PI).signed().radians.approx_eq(&0.0));
    assert!(Angle::radians(-2.0 * PI).signed().radians.approx_eq(&0.0));
    assert!(Angle::radians(-PI).signed().radians.approx_eq(&PI));
    assert!(Angle::radians(PI).signed().radians.approx_eq(&PI));
}
<|endoftext|>


<commit_before>//! Wrappers around `rados_completion_t`, providing a safe, futures-based API
//! for asynchronous RADOS operations.

use std::ffi::CString;
use std::mem;
use std::ptr;
use std::sync::Arc;

use ceph_rust::rados::{self, rados_completion_t};
use chrono::{Local, TimeZone};
use futures::{Async, Future, Poll};
use futures::task::AtomicTask;
use libc;

use errors::{self, Error, ErrorKind, Result, get_error_string};
use rados::RadosStat;

/// An abstraction over the handling of RADOS completions which have finished execution.
pub trait Finalize {
    type Output;

    /// On success, we produce output from the state stored in the `Self` type.
    fn on_success(self) -> Self::Output;

    /// On failure, we may either recover from the raw error code or convert the raw error code
    /// into a nicely readable error.
    fn on_failure(self, u32) -> Result<Self::Output>;
}

struct CompletionInfo {
    task: AtomicTask,
}

extern "C" fn callback(_handle: rados_completion_t, info_ptr: *mut libc::c_void) {
    println!("RADOS callback, future ready: {:p}", _handle);

    let info = unsafe { Arc::from_raw(info_ptr as *const CompletionInfo) };

    info.task.notify();
    mem::drop(info);
}

/// Asynchronous I/O through RADOS is abstracted behind the `RadosFuture` type.  Different
/// behaviors corresponding to different AIO operations are implemented as differing type
/// parameters implementing `Finalize`. Use of the `Finalize` trait instead of directly
/// implementing `Future` for every unique AIO operation reduces the risk of incorrectly
/// implementing the different completion modes (called `RadosCaution` here, we allow AIO
/// operations to wait for either acknowledgement from the cluster or for the assurance that the
/// operation has been committed to stable memory.)
pub struct RadosFuture<F: Finalize> {
    info: Arc<CompletionInfo>,
    caution: RadosCaution,
    finalize: Option<F>,
    handle: rados_completion_t,
}

// `RadosFuture` is send as long as the finalizer is. It does not implement `Clone` nor `Sync`,
// however, so all accesses to the `rados_completion_t` - the sole dangerous component - are forced
// to be single-threaded.
unsafe impl<F: Finalize + Send> Send for RadosFuture<F> {}

/// The `RadosCaution` enum is used to denote the level of safety the caller desires from an
/// asynchronous operation.
#[derive(Clone, Copy, PartialEq, Debug)]
pub enum RadosCaution {
    /// Wait for the operation to be acknowledged by the cluster. This indicates
    /// the operation is in-memory in the cluster, but has not yet necessarily
    /// been written to disk.
    Complete,

    /// Wait for the operation to be guaranteed to be successfully written to
    /// disk.
    Safe,
}

impl<F: Finalize> Drop for RadosFuture<F> {
    fn drop(&mut self) {
        println!("RADOS future dropping: {:p}", self.handle);

        unsafe {
            rados::rados_aio_release(self.handle);
        }

        println!("RADOS future dropped: {:p}", self.handle);
    }
}

impl<F: Finalize> RadosFuture<F> {
    /// Create a new `RadosFuture` given a function to initialize the completion, a caution level,
    /// and a finalizer. `rados_aio_release_completion` should *not* be called on the
    /// `rados_completion_t` passed into the initializer.
    pub fn new<G>(caution: RadosCaution, finalize: F, init: G) -> Result<RadosFuture<F>>
    where
        G: FnOnce(rados_completion_t) -> Result<()>,
    {
        let mut completion_handle = ptr::null_mut();

        let info = Arc::new(CompletionInfo { task: AtomicTask::new() });

        let info_ptr = Arc::into_raw(info.clone()) as *mut CompletionInfo;
        let callback_ptr = callback as extern "C" fn(*mut libc::c_void, *mut libc::c_void);

        let (complete_cb, safe_cb) = match caution {
            RadosCaution::Complete => (Some(callback_ptr), None),
            RadosCaution::Safe => (None, Some(callback_ptr)),
        };

        let err = unsafe {
            rados::rados_aio_create_completion(
                info_ptr as *mut libc::c_void,
                complete_cb,
                safe_cb,
                &mut completion_handle,
            )
        };

        if err < 0 {
            Err(
                ErrorKind::CompletionFailed(try!(errors::get_error_string(-err as u32))).into(),
            )
        } else {
            init(completion_handle)?;

            Ok(RadosFuture {
                info,
                caution,
                finalize: Some(finalize),
                handle: completion_handle,
            })
        }
    }

    /// Poll the underlying `rados_completion_t` to check whether the operation has been acked by
    /// the cluster.
    pub fn is_complete(&self) -> bool {
        unsafe { rados::rados_aio_is_complete(self.handle) != 0 }
    }

    /// Poll the underlying `rados_completion_t` to check whether the operation has been committed
    /// to stable memory.
    pub fn is_safe(&self) -> bool {
        unsafe { rados::rados_aio_is_safe(self.handle) != 0 }
    }

    /// Get the error value of the completion, if the completion has errored.
    ///
    /// *Precondition:* this function should only be called after the completion is complete or
    /// safe.
    ///
    /// If an error has occurred, the raw error code is returned as a u32.
    pub fn get_error_value(&self) -> Option<u32> {
        let err = unsafe { rados::rados_aio_get_return_value(self.handle) };

        if err < 0 { Some(-err as u32) } else { None }
    }

    /// Take the finalizer value out of the `RadosFuture`. This is called when the future is
    /// complete and will not be `poll`ed again.
    ///
    /// *Precondition:* the future is done executing, and has not had its value read yet. If
    /// `take_finalize` is called again after the future is finished executing, it will panic due
    /// to the underlying call to `Option::take`.
    fn take_finalize(&mut self) -> F {
        self.finalize.take().expect(
            "RadosFuture should not be polled a second time after completing!",
        )
    }
}

impl<F: Finalize> Future for RadosFuture<F> {
    type Item = F::Output;
    type Error = Error;

    fn poll(&mut self) -> Poll<F::Output, Error> {
        match (self.caution, self.get_error_value()) {
            // If `self.get_error_value()` is `Some`, an error has occurred. We can only be certain
            // that an error has occurred if the operation has been acked or is safe, so we check
            // to ensure that one of the two is true before returning an error.
            (_, Some(error)) => {
                // Since we cannot bind by-move into a pattern guard, we must resort to an
                // if-statement here.
                if self.is_complete() || self.is_safe() {
                    self.take_finalize().on_failure(error).map(Async::Ready)
                } else {
                    Ok(Async::NotReady)
                }
            }

            (RadosCaution::Complete, None) if self.is_complete() || self.is_safe() => {
                Ok(Async::Ready(self.take_finalize().on_success()))
            }
            (RadosCaution::Safe, None) if self.is_safe() => {
                Ok(Async::Ready(self.take_finalize().on_success()))
            }

            _ => {
                self.info.task.register();
                Ok(Async::NotReady)
            }
        }
    }
}

/// The finalizer for a `rados_aio_write`.
pub struct RadosFinishWrite {
    pub oid: CString,
    pub len: usize,
    pub off: u64,
}

impl Finalize for RadosFinishWrite {
    type Output = ();

    fn on_success(self) -> () {
        ()
    }

    fn on_failure(self, error: u32) -> Result<()> {
        Err(
            ErrorKind::AsyncWriteFailed(self.oid, self.len, self.off, get_error_string(error)?)
                .into(),
        )
    }
}

/// The finalizer for a `rados_aio_append`.
pub struct RadosFinishAppend {
    pub oid: CString,
    pub len: usize,
}

impl Finalize for RadosFinishAppend {
    type Output = ();

    fn on_success(self) -> () {
        ()
    }

    fn on_failure(self, error: u32) -> Result<()> {
        Err(
            ErrorKind::AsyncAppendFailed(self.oid, self.len, get_error_string(error)?).into(),
        )
    }
}

/// The finalizer for a `rados_aio_write_full`.
pub struct RadosFinishFullWrite {
    pub oid: CString,
    pub len: usize,
}

impl Finalize for RadosFinishFullWrite {
    type Output = ();

    fn on_success(self) -> () {
        ()
    }
    fn on_failure(self, error: u32) -> Result<()> {
        Err(
            ErrorKind::AsyncFullWriteFailed(self.oid, self.len, get_error_string(error)?).into(),
        )
    }
}

/// The finalizer for a `rados_aio_remove`.
pub struct RadosFinishRemove {
    pub oid: CString,
}

impl Finalize for RadosFinishRemove {
    type Output = ();

    fn on_success(self) -> () {
        ()
    }
    fn on_failure(self, error: u32) -> Result<()> {
        Err(
            ErrorKind::AsyncRemoveFailed(self.oid, get_error_string(error)?).into(),
        )
    }
}

/// The finalizer for a `rados_aio_flush`.
pub struct RadosFinishFlush;

impl Finalize for RadosFinishFlush {
    type Output = ();

    fn on_success(self) -> () {
        ()
    }
    fn on_failure(self, error: u32) -> Result<()> {
        Err(ErrorKind::AsyncFlushFailed(get_error_string(error)?).into())
    }
}

/// The finalizer for a `rados_aio_read`.
///
/// NOTE: as per the librados documentation, [`rados_aio_read` does not ever become "safe" - only
/// "complete"/acked - because it makes no sense for a read operation to become committed to
/// cluster memory.](http://docs.ceph.com/docs/master/rados/api/librados/#rados_aio_read)
pub struct RadosFinishRead<'a> {
    // The location in which to store the read data. We hold onto these until
    // they are guaranteed written.
    pub bytes: &'a mut [u8],

    pub oid: CString,
    pub off: u64,
}

impl<'a> Finalize for RadosFinishRead<'a> {
    type Output = &'a mut [u8];

    fn on_success(self) -> &'a mut [u8] {
        self.bytes
    }

    fn on_failure(self, error: u32) -> Result<&'a mut [u8]> {
        Err(
            ErrorKind::AsyncReadFailed(
                self.oid,
                self.bytes.len(),
                self.off,
                get_error_string(error)?,
            ).into(),
        )
    }
}

/// The finalizer for a `rados_aio_stat`.
pub struct RadosFinishStat {
    pub oid: CString,

    // We keep the size and time boxed so that their locations remain stable until their values are
    // finally read. Alternatively this could be done with references and lifetime parameters like
    // `RadosFinishRead` but this would be unintuitive to the user as `RadosContext::stat` does not
    // require input in which to store the read stats.
    pub boxed: Box<(u64, libc::time_t)>,
}

impl Finalize for RadosFinishStat {
    type Output = RadosStat;

    fn on_success(self) -> RadosStat {
        let (size, time) = *self.boxed;

        RadosStat {
            size,
            last_modified: Local.timestamp(time, 0),
        }
    }

    fn on_failure(self, error: u32) -> Result<RadosStat> {
        Err(
            ErrorKind::AsyncStatFailed(self.oid, get_error_string(error)?).into(),
        )
    }
}

/// The finalizer for checking whether or not an object exists. This is implemented as a call to
/// `rados_aio_stat`.
pub struct RadosFinishExists {
    pub oid: CString,
}

impl Finalize for RadosFinishExists {
    type Output = bool;

    fn on_success(self) -> bool {
        true
    }

    fn on_failure(self, error: u32) -> Result<bool> {
        // We are checking for existence of the object. If we receive an `ENOENT` error (entry not
        // found) then we assume that indicates the object does not exist.
        if error as i32 == libc::ENOENT {
            Ok(false)
        } else {
            Err(
                ErrorKind::AsyncExistsFailed(self.oid, get_error_string(error)?).into(),
            )
        }
    }
}
<commit_msg>Remove debug print statement again<commit_after>//! Wrappers around `rados_completion_t`, providing a safe, futures-based API
//! for asynchronous RADOS operations.

use std::ffi::CString;
use std::mem;
use std::ptr;
use std::sync::Arc;

use ceph_rust::rados::{self, rados_completion_t};
use chrono::{Local, TimeZone};
use futures::{Async, Future, Poll};
use futures::task::AtomicTask;
use libc;

use errors::{self, Error, ErrorKind, Result, get_error_string};
use rados::RadosStat;

/// An abstraction over the handling of RADOS completions which have finished execution.
pub trait Finalize {
    type Output;

    /// On success, we produce output from the state stored in the `Self` type.
    fn on_success(self) -> Self::Output;

    /// On failure, we may either recover from the raw error code or convert the raw error code
    /// into a nicely readable error.
    fn on_failure(self, u32) -> Result<Self::Output>;
}

struct CompletionInfo {
    task: AtomicTask,
}

extern "C" fn callback(_handle: rados_completion_t, info_ptr: *mut libc::c_void) {
    let info = unsafe { Arc::from_raw(info_ptr as *const CompletionInfo) };

    info.task.notify();
    mem::drop(info);
}

/// Asynchronous I/O through RADOS is abstracted behind the `RadosFuture` type.  Different
/// behaviors corresponding to different AIO operations are implemented as differing type
/// parameters implementing `Finalize`. Use of the `Finalize` trait instead of directly
/// implementing `Future` for every unique AIO operation reduces the risk of incorrectly
/// implementing the different completion modes (called `RadosCaution` here, we allow AIO
/// operations to wait for either acknowledgement from the cluster or for the assurance that the
/// operation has been committed to stable memory.)
pub struct RadosFuture<F: Finalize> {
    info: Arc<CompletionInfo>,
    caution: RadosCaution,
    finalize: Option<F>,
    handle: rados_completion_t,
}

// `RadosFuture` is send as long as the finalizer is. It does not implement `Clone` nor `Sync`,
// however, so all accesses to the `rados_completion_t` - the sole dangerous component - are forced
// to be single-threaded.
unsafe impl<F: Finalize + Send> Send for RadosFuture<F> {}

/// The `RadosCaution` enum is used to denote the level of safety the caller desires from an
/// asynchronous operation.
#[derive(Clone, Copy, PartialEq, Debug)]
pub enum RadosCaution {
    /// Wait for the operation to be acknowledged by the cluster. This indicates
    /// the operation is in-memory in the cluster, but has not yet necessarily
    /// been written to disk.
    Complete,

    /// Wait for the operation to be guaranteed to be successfully written to
    /// disk.
    Safe,
}

impl<F: Finalize> Drop for RadosFuture<F> {
    fn drop(&mut self) {
        unsafe {
            rados::rados_aio_release(self.handle);
        }
    }
}

impl<F: Finalize> RadosFuture<F> {
    /// Create a new `RadosFuture` given a function to initialize the completion, a caution level,
    /// and a finalizer. `rados_aio_release_completion` should *not* be called on the
    /// `rados_completion_t` passed into the initializer.
    pub fn new<G>(caution: RadosCaution, finalize: F, init: G) -> Result<RadosFuture<F>>
    where
        G: FnOnce(rados_completion_t) -> Result<()>,
    {
        let mut completion_handle = ptr::null_mut();

        let info = Arc::new(CompletionInfo { task: AtomicTask::new() });

        let info_ptr = Arc::into_raw(info.clone()) as *mut CompletionInfo;
        let callback_ptr = callback as extern "C" fn(*mut libc::c_void, *mut libc::c_void);

        let (complete_cb, safe_cb) = match caution {
            RadosCaution::Complete => (Some(callback_ptr), None),
            RadosCaution::Safe => (None, Some(callback_ptr)),
        };

        let err = unsafe {
            rados::rados_aio_create_completion(
                info_ptr as *mut libc::c_void,
                complete_cb,
                safe_cb,
                &mut completion_handle,
            )
        };

        if err < 0 {
            Err(
                ErrorKind::CompletionFailed(try!(errors::get_error_string(-err as u32))).into(),
            )
        } else {
            init(completion_handle)?;

            Ok(RadosFuture {
                info,
                caution,
                finalize: Some(finalize),
                handle: completion_handle,
            })
        }
    }

    /// Poll the underlying `rados_completion_t` to check whether the operation has been acked by
    /// the cluster.
    pub fn is_complete(&self) -> bool {
        unsafe { rados::rados_aio_is_complete(self.handle) != 0 }
    }

    /// Poll the underlying `rados_completion_t` to check whether the operation has been committed
    /// to stable memory.
    pub fn is_safe(&self) -> bool {
        unsafe { rados::rados_aio_is_safe(self.handle) != 0 }
    }

    /// Get the error value of the completion, if the completion has errored.
    ///
    /// *Precondition:* this function should only be called after the completion is complete or
    /// safe.
    ///
    /// If an error has occurred, the raw error code is returned as a u32.
    pub fn get_error_value(&self) -> Option<u32> {
        let err = unsafe { rados::rados_aio_get_return_value(self.handle) };

        if err < 0 { Some(-err as u32) } else { None }
    }

    /// Take the finalizer value out of the `RadosFuture`. This is called when the future is
    /// complete and will not be `poll`ed again.
    ///
    /// *Precondition:* the future is done executing, and has not had its value read yet. If
    /// `take_finalize` is called again after the future is finished executing, it will panic due
    /// to the underlying call to `Option::take`.
    fn take_finalize(&mut self) -> F {
        self.finalize.take().expect(
            "RadosFuture should not be polled a second time after completing!",
        )
    }
}

impl<F: Finalize> Future for RadosFuture<F> {
    type Item = F::Output;
    type Error = Error;

    fn poll(&mut self) -> Poll<F::Output, Error> {
        match (self.caution, self.get_error_value()) {
            // If `self.get_error_value()` is `Some`, an error has occurred. We can only be certain
            // that an error has occurred if the operation has been acked or is safe, so we check
            // to ensure that one of the two is true before returning an error.
            (_, Some(error)) => {
                // Since we cannot bind by-move into a pattern guard, we must resort to an
                // if-statement here.
                if self.is_complete() || self.is_safe() {
                    self.take_finalize().on_failure(error).map(Async::Ready)
                } else {
                    Ok(Async::NotReady)
                }
            }

            (RadosCaution::Complete, None) if self.is_complete() || self.is_safe() => {
                Ok(Async::Ready(self.take_finalize().on_success()))
            }
            (RadosCaution::Safe, None) if self.is_safe() => {
                Ok(Async::Ready(self.take_finalize().on_success()))
            }

            _ => {
                self.info.task.register();
                Ok(Async::NotReady)
            }
        }
    }
}

/// The finalizer for a `rados_aio_write`.
pub struct RadosFinishWrite {
    pub oid: CString,
    pub len: usize,
    pub off: u64,
}

impl Finalize for RadosFinishWrite {
    type Output = ();

    fn on_success(self) -> () {
        ()
    }

    fn on_failure(self, error: u32) -> Result<()> {
        Err(
            ErrorKind::AsyncWriteFailed(self.oid, self.len, self.off, get_error_string(error)?)
                .into(),
        )
    }
}

/// The finalizer for a `rados_aio_append`.
pub struct RadosFinishAppend {
    pub oid: CString,
    pub len: usize,
}

impl Finalize for RadosFinishAppend {
    type Output = ();

    fn on_success(self) -> () {
        ()
    }

    fn on_failure(self, error: u32) -> Result<()> {
        Err(
            ErrorKind::AsyncAppendFailed(self.oid, self.len, get_error_string(error)?).into(),
        )
    }
}

/// The finalizer for a `rados_aio_write_full`.
pub struct RadosFinishFullWrite {
    pub oid: CString,
    pub len: usize,
}

impl Finalize for RadosFinishFullWrite {
    type Output = ();

    fn on_success(self) -> () {
        ()
    }
    fn on_failure(self, error: u32) -> Result<()> {
        Err(
            ErrorKind::AsyncFullWriteFailed(self.oid, self.len, get_error_string(error)?).into(),
        )
    }
}

/// The finalizer for a `rados_aio_remove`.
pub struct RadosFinishRemove {
    pub oid: CString,
}

impl Finalize for RadosFinishRemove {
    type Output = ();

    fn on_success(self) -> () {
        ()
    }
    fn on_failure(self, error: u32) -> Result<()> {
        Err(
            ErrorKind::AsyncRemoveFailed(self.oid, get_error_string(error)?).into(),
        )
    }
}

/// The finalizer for a `rados_aio_flush`.
pub struct RadosFinishFlush;

impl Finalize for RadosFinishFlush {
    type Output = ();

    fn on_success(self) -> () {
        ()
    }
    fn on_failure(self, error: u32) -> Result<()> {
        Err(ErrorKind::AsyncFlushFailed(get_error_string(error)?).into())
    }
}

/// The finalizer for a `rados_aio_read`.
///
/// NOTE: as per the librados documentation, [`rados_aio_read` does not ever become "safe" - only
/// "complete"/acked - because it makes no sense for a read operation to become committed to
/// cluster memory.](http://docs.ceph.com/docs/master/rados/api/librados/#rados_aio_read)
pub struct RadosFinishRead<'a> {
    // The location in which to store the read data. We hold onto these until
    // they are guaranteed written.
    pub bytes: &'a mut [u8],

    pub oid: CString,
    pub off: u64,
}

impl<'a> Finalize for RadosFinishRead<'a> {
    type Output = &'a mut [u8];

    fn on_success(self) -> &'a mut [u8] {
        self.bytes
    }

    fn on_failure(self, error: u32) -> Result<&'a mut [u8]> {
        Err(
            ErrorKind::AsyncReadFailed(
                self.oid,
                self.bytes.len(),
                self.off,
                get_error_string(error)?,
            ).into(),
        )
    }
}

/// The finalizer for a `rados_aio_stat`.
pub struct RadosFinishStat {
    pub oid: CString,

    // We keep the size and time boxed so that their locations remain stable until their values are
    // finally read. Alternatively this could be done with references and lifetime parameters like
    // `RadosFinishRead` but this would be unintuitive to the user as `RadosContext::stat` does not
    // require input in which to store the read stats.
    pub boxed: Box<(u64, libc::time_t)>,
}

impl Finalize for RadosFinishStat {
    type Output = RadosStat;

    fn on_success(self) -> RadosStat {
        let (size, time) = *self.boxed;

        RadosStat {
            size,
            last_modified: Local.timestamp(time, 0),
        }
    }

    fn on_failure(self, error: u32) -> Result<RadosStat> {
        Err(
            ErrorKind::AsyncStatFailed(self.oid, get_error_string(error)?).into(),
        )
    }
}

/// The finalizer for checking whether or not an object exists. This is implemented as a call to
/// `rados_aio_stat`.
pub struct RadosFinishExists {
    pub oid: CString,
}

impl Finalize for RadosFinishExists {
    type Output = bool;

    fn on_success(self) -> bool {
        true
    }

    fn on_failure(self, error: u32) -> Result<bool> {
        // We are checking for existence of the object. If we receive an `ENOENT` error (entry not
        // found) then we assume that indicates the object does not exist.
        if error as i32 == libc::ENOENT {
            Ok(false)
        } else {
            Err(
                ErrorKind::AsyncExistsFailed(self.oid, get_error_string(error)?).into(),
            )
        }
    }
}
<|endoftext|>


<commit_before>extern crate pcre;
use self::pcre::Pcre;

const DATA: &'static str = include_str!("../data/input_5.txt");

pub fn main() -> Vec<String> {
    let s1 = nice_count(DATA);
    let s2 = new_nice_count(DATA);
    vec![s1.to_string(), s2.to_string()]
}

fn nice_count(input: &str) -> usize {
    let mut vowels = Pcre::compile(r"[aeiou]").unwrap();
    let mut has_double = Pcre::compile(r"(.)\1").unwrap();
    let mut bad_pairs = Pcre::compile(r"(ab|cd|pq|xy)").unwrap();

    input.lines()
         .filter(|line| vowels.matches(line).count() >= 3)
         .filter(|line| has_double.exec(line).is_some())
         .filter(|line| bad_pairs.exec(line).is_none())
         .count()
}

#[test]
fn test_nice_string() {
    assert_eq!(nice_count("ugknbfddgicrmopn"), 1);
    assert_eq!(nice_count("aaa"), 1);
    assert_eq!(nice_count("jchzalrnumimnmhp"), 0);
    assert_eq!(nice_count("haegwjzuvuyypxyu"), 0);
    assert_eq!(nice_count("dvszwmarrgswjxmb"), 0);
}

fn new_nice_count(input: &str) -> usize {
    let mut pairs = Pcre::compile(r"(..).*\1").unwrap();
    let mut sandwich = Pcre::compile(r"(.).\1").unwrap();

    input.lines()
         .filter(|line| pairs.exec(line).is_some())
         .filter(|line| sandwich.exec(line).is_some())
         .count()
}

#[test]
fn test_new_nice_string() {
    assert_eq!(new_nice_count("qjhvhtzxzqqjkmpb"), 1);
    assert_eq!(new_nice_count("xxyxx"), 1);
    assert_eq!(new_nice_count("uurcxstgmygtbstg"), 0);
    assert_eq!(new_nice_count("eodomkazucvgmuy"), 0);
}
<commit_msg>day05: rework without using pcre regex<commit_after>use std::str;

const DATA: &'static str = include_str!("../data/input_5.txt");

pub fn main() -> Vec<String> {
    let s1 = nice_count(DATA);
    let s2 = nicer_count(DATA);
    vec![s1.to_string(), s2.to_string()]
}

fn nice(s: &str) -> bool {
    let has_three_vowels = |s: &str| s.chars().filter(|c| "aeiou".contains(*c)).count() >= 3;
    let has_doubles = |s: &str| s.as_bytes().windows(2).any(|w| w[0] == w[1]);
    let has_bad_pairs = |s: &str| {
        s.as_bytes()
         .windows(2)
         .any(|w| ["ab", "cd", "pq", "xy"].contains(&(unsafe { str::from_utf8_unchecked(w) })))
    };
    has_three_vowels(s) && has_doubles(s) && !has_bad_pairs(s)
}

fn nice_count(input: &str) -> usize {
    input.lines()
         .filter(|line| nice(line))
         .count()
}

fn nicer(s: &str) -> bool {
    let has_double_pairs = |s: &str| {
        let bs = s.as_bytes();
        (0..bs.len() - 3)
            .any(|n| bs[n + 2..].windows(2).any(|w| w[0] == bs[n] && w[1] == bs[n + 1]))
    };
    let has_sandwich = |s: &str| s.as_bytes().windows(3).any(|w| w[0] == w[2]);
    has_double_pairs(s) && has_sandwich(s)
}

fn nicer_count(input: &str) -> usize {
    input.lines()
         .filter(|line| nicer(line))
         .count()
}

#[cfg(test)]
mod test {
    use super::{nice_count, nicer_count};

    #[test]
    fn test_nice_string() {
        assert_eq!(nice_count("ugknbfddgicrmopn"), 1);
        assert_eq!(nice_count("aaa"), 1);
        assert_eq!(nice_count("jchzalrnumimnmhp"), 0);
        assert_eq!(nice_count("haegwjzuvuyypxyu"), 0);
        assert_eq!(nice_count("dvszwmarrgswjxmb"), 0);
    }

    #[test]
    fn test_nicer_string() {
        assert_eq!(nicer_count("qjhvhtzxzqqjkmpb"), 1);
        assert_eq!(nicer_count("xxyxx"), 1);
        assert_eq!(nicer_count("uurcxstgmygtbstg"), 0);
        assert_eq!(nicer_count("eodomkazucvgmuy"), 0);
    }
}
<|endoftext|>


<commit_before>use std::fs::File;
use std::io::prelude::*;
use std::io::BufReader;
use std::collection::{HashMap, HashSet};

pub fn single_night(file: &str) -> i32 {
    let input = File::open(file).expect("File open fail.");
    let reader = BufReader::new(input);

    //TODO probably need a graph
    let locs = HashSet::new();
    let dists = HashMap::new();
    for line in reader.lines() {
        let line = line.unwrap();
        let s = String::from(line.trim());
        println!("{}", s);

        while let Some(w) = s.split_whitespace() {
            if w != "to" && w != "=" {
                let loc_dist = w.parse::<i32>();
                match loc_dist {
                    Ok(n) => {
                        dists.insert(from_to, n);
                    },
                    Err(w) => {
                        locs.insert(w);
                    },
                }
            }
        }
    }
    -1
}
<commit_msg>Update graph implementation using std::collections<commit_after>use std::fs::File;
use std::io::prelude::*;
use std::io::BufReader;
use std::cmp::{Ordering, };
use std::collections::{HashMap, HashSet, BinaryHeap};

pub fn single_night(file: &str) -> i64 {
    let input = File::open(file).expect("File open fail.");
    let reader = BufReader::new(input);

    #[derive(Debug, Hash)]
    struct Node(String, i64);

    impl PartialEq for Node {
        fn eq(&self, other: &Node) -> bool {
            self.0.eq(&other.0)
        }
    }

    impl Eq for Node {}

    impl PartialOrd for Node {
        fn partial_cmp(&self, other: &Node) -> Option<Ordering> {
            Some(self.cmp(other))
        }
    }

    impl Ord for Node {
        fn cmp(&self, other: &Node) -> Ordering {
            self.1.cmp(&other.1)
        }
    }

    impl Clone for Node {
        fn clone(&self) -> Self {
            Node(self.0.clone(), self.1)
        }
    }

    let mut nodes = HashSet::new();
    let mut edges = HashMap::new();
    for line in reader.lines() {
        let line = line.unwrap();
        // println!("{}", s);

        let words: Vec<&str> = line.split_whitespace().collect();
        let from = Node(String::from(words[0]), i64::min_value());
        let to = Node(String::from(words[2]), i64::min_value());
        let distance = words[4]
            .parse::<i64>().expect("parse error");

        nodes.insert(from.clone());
        nodes.insert(to.clone());
        // negate distance because <BinaryHeap>.pop() returns highest
        edges.insert((from, to), -distance);
    }
    let mut nodes: Vec<Node> = nodes.iter().cloned().collect();
    let mut p_queue = BinaryHeap::new();
    let source = nodes.pop().unwrap();
    let source = Node(source.0, 0);
    nodes.push(source);
    println!("nodes");
    for node in nodes.clone() {
        println!("{:?}", node);
        p_queue.push(node);
    }
    println!("queue");
    for n in p_queue.clone().into_vec() {
        println!("{:?}", n);
    }
    let mut nodes = nodes;
    println!("calculating...");
    loop {
        if p_queue.is_empty() { break; }

        let node = p_queue.pop().unwrap();

        println!("Pop {:?}", node);
        // for each neighbor of n
        for (from_to, edge) in edges.iter() {
            let (ref from, ref to) = *from_to;
            if from == &node {
                let alt = node.1 - edge;
                if let Some(neighbor)
                    = p_queue.clone().iter().find(|&n| n == to) {
                    if alt > neighbor.1 {
                        p_queue.push(Node(node.0.clone(), alt));
                    }
                    println!("Push {:?} {:?}", neighbor, alt);
                }
                //println!("{:?} {:?} {:?} {:?}", from, to, edge, node);
            }
        }
    }
    -1
}
<|endoftext|>


<commit_before>const DATA: &'static str = include_str!("../data/input_17.txt");

pub fn main() -> Vec<String> {
    vec![part1().to_string(), part2().to_string()]
}

fn part1() -> usize {
    let data: Vec<u32> = DATA.lines().map(|l| l.parse::<u32>().unwrap()).collect();
    let ps = PowerSet::new(&data);
    let v = ps.filter(|ss| ss.iter().sum::<u32>() == 150).collect::<Vec<_>>();
    v.len()
}

fn part2() -> usize {
    let data: Vec<u32> = DATA.lines().map(|l| l.parse::<u32>().unwrap()).collect();
    let ps = PowerSet::new(&data);
    let v = ps.filter(|ss| ss.iter().sum::<u32>() == 150).collect::<Vec<_>>();
    let min = v.iter().map(|ss| ss.len()).min().unwrap();
    v.iter().filter(|ss| ss.len() == min).count()
}

struct PowerSet<T> {
    stack: Vec<(Vec<T>, Vec<T>)>,
}

impl<T: Copy> PowerSet<T> {
    fn new(data: &[T]) -> PowerSet<T> {
        let mut stack = Vec::new();
        if let Some((selected, remaining)) = data.split_last() {
            stack.push((vec![*selected], remaining.to_vec()));
            stack.push((vec![], remaining.to_vec()));
        } else {
            stack.push((vec![], vec![]));
        }
        PowerSet { stack: stack }
    }
}

impl<T: Copy> Iterator for PowerSet<T> {
    type Item = Vec<T>;
    fn next(&mut self) -> Option<Vec<T>> {
        if let Some((selected, remaining)) = self.stack.pop() {
            if let Some((sel, rem)) = remaining.split_last() {
                let mut r = selected.clone();
                r.push(*sel);
                self.stack.push((r, rem.to_vec()));
                self.stack.push((selected.clone(), rem.to_vec()));
                self.next()
            } else {
                Some(selected)
            }
        } else {
            None
        }
    }
}
<commit_msg>day 17: pruning condition to cut down search tree<commit_after>const DATA: &'static str = include_str!("../data/input_17.txt");

pub fn main() -> Vec<String> {
    vec![part1().to_string(), part2().to_string()]
}

fn part1() -> usize {
    let mut data: Vec<u32> = DATA.lines().map(|l| l.parse::<u32>().unwrap()).collect();
    data.sort();
    let ps = PowerSet::with_prune_condition(&data, |ss| ss.iter().sum::<u32>() > 150);
    let v = ps.filter(|ss| ss.iter().sum::<u32>() == 150).collect::<Vec<_>>();
    v.len()
}

fn part2() -> usize {
    let mut data: Vec<u32> = DATA.lines().map(|l| l.parse::<u32>().unwrap()).collect();
    data.sort();
    let ps = PowerSet::with_prune_condition(&data, |ss| ss.iter().sum::<u32>() > 150);
    let v = ps.filter(|ss| ss.iter().sum::<u32>() == 150).collect::<Vec<_>>();
    let min = v.iter().map(|ss| ss.len()).min().unwrap();
    v.iter().filter(|ss| ss.len() == min).count()
}

struct PowerSet<T, F>
    where T: Copy,
          F: Fn(&[T]) -> bool
{
    stack: Vec<(Vec<T>, Vec<T>)>,
    stop: F,
}

impl<T, F> PowerSet<T, F>
    where T: Copy,
          F: Fn(&[T]) -> bool
{
    // not sure why this doesn't compile
    // expected type parameter, found fn item
    //
    //  fn new(data: &[T]) -> PowerSet<T, F> {
    //      PowerSet::with_prune_condition(data, |_| false)
    //  }

    fn with_prune_condition(data: &[T], stop: F) -> PowerSet<T, F> {
        let mut stack = Vec::new();
        if let Some((selected, remaining)) = data.split_last() {
            stack.push((vec![*selected], remaining.to_vec()));
            stack.push((vec![], remaining.to_vec()));
        } else {
            stack.push((vec![], vec![]));
        }
        PowerSet {
            stack: stack,
            stop: stop,
        }
    }
}

impl<T, F> Iterator for PowerSet<T, F>
    where T: Copy,
          F: Fn(&[T]) -> bool
{
    type Item = Vec<T>;

    fn next(&mut self) -> Option<Vec<T>> {
        if let Some((selected, remaining)) = self.stack.pop() {
            if let Some((sel, rem)) = remaining.split_last() {
                let mut r = selected.clone();
                r.push(*sel);
                if !(self.stop)(&selected) {
                    self.stack.push((r, rem.to_vec()));
                    self.stack.push((selected.clone(), rem.to_vec()));
                }
                self.next()
            } else {
                Some(selected)
            }
        } else {
            None
        }
    }
}
<|endoftext|>


<commit_before>//! Error types and conversions.

use std::error::Error;
use std::fmt::{Display, Formatter};
use std::fmt::Error as FmtError;
use std::io::Error as IoError;
use std::string::FromUtf8Error;
use std::sync::PoisonError;

use argon2rs::verifier::DecodeError;
use base64::Base64Error;
use diesel::result::{TransactionError, Error as DieselError};
use iron::{IronError, Response};
use iron::modifier::Modifier;
use iron::status::Status;
use macaroons::error::Error as MacaroonsError;
use persistent::PersistentError;
use r2d2::GetTimeout;
use ruma_identifiers::Error as RumaIdentifiersError;
use serde::ser::{Serialize, Serializer};
use serde_json::{Error as SerdeJsonError, to_string};

/// A client-facing error.
#[derive(Clone, Debug, Serialize)]
pub struct ApiError {
    errcode: ApiErrorCode,
    error: String,
}

impl ApiError {
    /// Create an error for invalid or incomplete input to event creation API endpoints.
    pub fn bad_event(message: Option<&str>) -> ApiError {
        ApiError {
            errcode: ApiErrorCode::BadEvent,
            error: message.unwrap_or("Invalid event data.").to_string(),
        }
    }

    /// Create an error for invalid or incomplete JSON in request bodies.
    pub fn bad_json(message: Option<&str>) -> ApiError {
        ApiError {
            errcode: ApiErrorCode::BadJson,
            error: message.unwrap_or("Invalid or missing key-value pairs in JSON.").to_string(),
        }
    }

    /// Create an error for endpoints where guest accounts are not supported.
    pub fn guest_forbidden(message: Option<&str>) -> ApiError {
        ApiError {
            errcode: ApiErrorCode::GuestAccessForbidden,
            error: message.unwrap_or("Guest accounts are forbidden.").to_string(),
        }
    }

    /// Create an error for requests missing a value for a required parameter.
    pub fn missing_param(param_name: &str) -> ApiError {
        ApiError {
            errcode: ApiErrorCode::MissingParam,
            error: format!("Missing value for required parameter: {}.", param_name),
        }
    }

    /// Create an error for requests that do not map to a resource.
    pub fn not_found(message: Option<&str>) -> ApiError {
        ApiError {
            errcode: ApiErrorCode::NotFound,
            error: message.unwrap_or("No resource was found for this request.").to_string(),
        }
    }

    /// Create an error for requests without JSON bodies.
    pub fn not_json(message: Option<&str>) -> ApiError {
        ApiError {
            errcode: ApiErrorCode::NotJson,
            error: message.unwrap_or("No JSON found in request body.").to_string(),
        }
    }

    /// Create an error for requests that are not marked as containing JSON.
    pub fn wrong_content_type(message: Option<&str>) -> ApiError {
        ApiError {
            errcode: ApiErrorCode::NotJson,
            error: message.unwrap_or(
                "Request's Content-Type header must be application/json."
            ).to_string(),
        }
    }

    /// Create an error for requests that did not provide required authentication parameters.
    pub fn unauthorized(message: Option<&str>) -> ApiError {
        ApiError {
            errcode: ApiErrorCode::Forbidden,
            error: message.unwrap_or("Authentication is required.").to_string(),
        }
    }

    /// Create an error for Matrix APIs that Ruma intentionally does not implement.
    pub fn unimplemented(message: Option<&str>) -> ApiError {
        ApiError {
            errcode: ApiErrorCode::Unimplemented,
            error: message.unwrap_or("The homeserver does not implement this API.").to_string(),
        }
    }

    /// Create a generic error for anything not specifically covered by the Matrix spec.
    pub fn unknown(message: Option<&str>) -> ApiError {
        ApiError {
            errcode: ApiErrorCode::Unknown,
            error: message.unwrap_or("An unknown server-side error occurred.").to_string(),
        }
    }
}

impl Display for ApiError {
    fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> {
        write!(f, "{}", self.error)
    }
}

impl Error for ApiError {
    fn description(&self) -> &str {
        &self.error
    }
}

impl From<IoError> for ApiError {
    fn from(error: IoError) -> ApiError {
        debug!("Converting to ApiError from: {:?}", error);

        ApiError::unknown(None)
    }
}

impl From<DecodeError> for ApiError {
    fn from(error: DecodeError) -> ApiError {
        debug!("Converting to ApiError from: {:?}", error);

        ApiError::unknown(None)
    }
}

impl From<Base64Error> for ApiError {
    fn from(error: Base64Error) -> ApiError {
        debug!("Converting to ApiError from: {:?}", error);

        ApiError::unknown(None)
    }
}

impl From<DieselError> for ApiError {
    fn from(error: DieselError) -> ApiError {
        debug!("Converting to ApiError from: {:?}", error);

        ApiError::unknown(None)
    }
}

impl<T> From<TransactionError<T>> for ApiError where T: Error {
    fn from(error: TransactionError<T>) -> ApiError {
        debug!("Converting to ApiError from: {:?}", error);

        ApiError::unknown(None)
    }
}

impl From<MacaroonsError> for ApiError {
    fn from(error: MacaroonsError) -> ApiError {
        debug!("Converting to ApiError from: {:?}", error);

        ApiError::unknown(None)
    }
}

impl From<PersistentError> for ApiError {
    fn from(error: PersistentError) -> ApiError {
        debug!("Converting to ApiError from: {:?}", error);

        ApiError::unknown(None)
    }
}

impl From<RumaIdentifiersError> for ApiError {
    fn from(error: RumaIdentifiersError) -> ApiError {
        debug!("Converting to ApiError from: {:?}", error);

        ApiError::unknown(None)
    }
}

impl From<GetTimeout> for ApiError {
    fn from(error: GetTimeout) -> ApiError {
        debug!("Converting to ApiError from: {:?}", error);

        ApiError::unknown(None)
    }
}

impl From<FromUtf8Error> for ApiError {
    fn from(error: FromUtf8Error) -> ApiError {
        debug!("Converting to ApiError from: {:?}", error);

        ApiError::unknown(None)
    }
}

impl<T> From<PoisonError<T>> for ApiError {
    fn from(error: PoisonError<T>) -> ApiError {
        debug!("Converting to ApiError from: {:?}", error);

        ApiError::unknown(None)
    }
}

impl From<SerdeJsonError> for ApiError {
    fn from(error: SerdeJsonError) -> ApiError {
        debug!("Converting to ApiError from: {:?}", error);

        ApiError::unknown(None)
    }
}

impl From<ApiError> for IronError {
    fn from(error: ApiError) -> IronError {
        IronError::new(error.clone(), error)
    }
}

impl Modifier<Response> for ApiError {
    fn modify(self, response: &mut Response) {
        response.status = Some(self.errcode.status_code());
        response.body = Some(Box::new(to_string(&self).expect("ApiError should always serialize")));
    }
}

/// The error code for a client-facing error.
#[derive(Clone, Debug)]
pub enum ApiErrorCode {
    /// Request contained an event that was not valid input for the requested API.
    BadEvent,
    /// The request contained valid JSON, but it was malformed in some way,
    /// e.g. missing required keys, invalid values for keys.
    BadJson,
    /// Forbidden access, e.g. joining a room without permission, failed login.
    Forbidden,
    /// Guests are not allowed to perform the requested operation.
    GuestAccessForbidden,
    /// Too many requests have been sent in a short period of time. Wait a while then try again.
    LimitExceeded,
    /// A required input parameter was not supplied, e.g. query string or URL path-based parameter.
    MissingParam,
    /// No resource was found for this request.
    NotFound,
    /// Request did not contain valid JSON.
    NotJson,
    /// Ruma does not implement the requested API.
    Unimplemented,
    /// Errors not fitting into another category.
    Unknown,
    /// The access token specified was not recognised.
    UnknownToken,
}

impl ApiErrorCode {
    /// The HTTP status code that should be used to represent the `ApiErrorCode`.
    pub fn status_code(&self) -> Status {
        match *self {
            ApiErrorCode::BadEvent => Status::UnprocessableEntity,
            ApiErrorCode::BadJson => Status::UnprocessableEntity,
            ApiErrorCode::Forbidden => Status::Forbidden,
            ApiErrorCode::GuestAccessForbidden => Status::Forbidden,
            ApiErrorCode::LimitExceeded => Status::TooManyRequests,
            ApiErrorCode::MissingParam => Status::BadRequest,
            ApiErrorCode::NotFound => Status::NotFound,
            ApiErrorCode::NotJson => Status::BadRequest,
            ApiErrorCode::Unimplemented => Status::NotFound,
            ApiErrorCode::Unknown => Status::InternalServerError,
            ApiErrorCode::UnknownToken => Status::Unauthorized,
        }
    }
}

impl Serialize for ApiErrorCode {
    fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error> where S: Serializer {
        let value = match *self {
            ApiErrorCode::BadEvent => "IO.RUMA_BAD_EVENT",
            ApiErrorCode::BadJson => "M_BAD_JSON",
            ApiErrorCode::Forbidden => "M_FORBIDDEN",
            ApiErrorCode::GuestAccessForbidden => "M_GUEST_ACCESS_FORBIDDEN",
            ApiErrorCode::LimitExceeded => "M_LIMIT_EXCEEDED",
            ApiErrorCode::MissingParam => "M_MISSING_PARAM",
            ApiErrorCode::NotFound => "M_NOT_FOUND",
            ApiErrorCode::NotJson => "M_NOT_JSON",
            ApiErrorCode::Unimplemented => "IO.RUMA_UNIMPLEMENTED",
            ApiErrorCode::Unknown => "M_UNKNOWN",
            ApiErrorCode::UnknownToken => "M_UNKNOWN_TOKEN",
        };

        serializer.serialize_str(value)
    }
}

/// An operator-facing error.
pub struct CliError {
    error: String,
}

impl CliError {
    /// Create a new `CliError` from any `Error` type.
    pub fn new<E>(error: E) -> CliError where E: Into<String> {
        CliError {
            error: error.into(),
        }
    }
}

impl<E> From<E> for CliError where E: Error {
    fn from(error: E) -> CliError {
        CliError::new(error.description())
    }
}

impl Display for CliError {
    fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> {
        write!(f, "{}", self.error)
    }
}
<commit_msg>Add MapApiError trait for better debugging info when an error occurs.<commit_after>//! Error types and conversions.

use std::error::Error;
use std::fmt::{Debug, Display, Formatter};
use std::fmt::Error as FmtError;
use std::io::Error as IoError;
use std::string::FromUtf8Error;
use std::sync::PoisonError;

use argon2rs::verifier::DecodeError;
use base64::Base64Error;
use diesel::result::{TransactionError, Error as DieselError};
use iron::{IronError, Response};
use iron::modifier::Modifier;
use iron::status::Status;
use macaroons::error::Error as MacaroonsError;
use persistent::PersistentError;
use r2d2::GetTimeout;
use ruma_identifiers::Error as RumaIdentifiersError;
use serde::ser::{Serialize, Serializer};
use serde_json::{Error as SerdeJsonError, to_string};

/// A client-facing error.
#[derive(Clone, Debug, Serialize)]
pub struct ApiError {
    errcode: ApiErrorCode,
    error: String,
}

/// The error code for a client-facing error.
#[derive(Clone, Debug)]
pub enum ApiErrorCode {
    /// Request contained an event that was not valid input for the requested API.
    BadEvent,
    /// The request contained valid JSON, but it was malformed in some way,
    /// e.g. missing required keys, invalid values for keys.
    BadJson,
    /// Forbidden access, e.g. joining a room without permission, failed login.
    Forbidden,
    /// Guests are not allowed to perform the requested operation.
    GuestAccessForbidden,
    /// Too many requests have been sent in a short period of time. Wait a while then try again.
    LimitExceeded,
    /// A required input parameter was not supplied, e.g. query string or URL path-based parameter.
    MissingParam,
    /// No resource was found for this request.
    NotFound,
    /// Request did not contain valid JSON.
    NotJson,
    /// Ruma does not implement the requested API.
    Unimplemented,
    /// Errors not fitting into another category.
    Unknown,
    /// The access token specified was not recognised.
    UnknownToken,
}

/// An operator-facing error.
pub struct CliError {
    error: String,
}

/// Extensions for `Result` to making handling Ruma API errors easier.
pub trait MapApiError {
    type Output;
    type Error: Debug;

    /// Similar to `map_err`, but prints the original error to the debug log and must always
    /// return an `ApiError`.
    fn map_api_err<O>(self, op: O) -> Result<Self::Output, ApiError>
    where O: FnOnce(Self::Error) -> ApiError;
}

impl ApiError {
    /// Create an error for invalid or incomplete input to event creation API endpoints.
    pub fn bad_event(message: Option<&str>) -> ApiError {
        ApiError {
            errcode: ApiErrorCode::BadEvent,
            error: message.unwrap_or("Invalid event data.").to_string(),
        }
    }

    /// Create an error for invalid or incomplete JSON in request bodies.
    pub fn bad_json(message: Option<&str>) -> ApiError {
        ApiError {
            errcode: ApiErrorCode::BadJson,
            error: message.unwrap_or("Invalid or missing key-value pairs in JSON.").to_string(),
        }
    }

    /// Create an error for endpoints where guest accounts are not supported.
    pub fn guest_forbidden(message: Option<&str>) -> ApiError {
        ApiError {
            errcode: ApiErrorCode::GuestAccessForbidden,
            error: message.unwrap_or("Guest accounts are forbidden.").to_string(),
        }
    }

    /// Create an error for requests missing a value for a required parameter.
    pub fn missing_param(param_name: &str) -> ApiError {
        ApiError {
            errcode: ApiErrorCode::MissingParam,
            error: format!("Missing value for required parameter: {}.", param_name),
        }
    }

    /// Create an error for requests that do not map to a resource.
    pub fn not_found(message: Option<&str>) -> ApiError {
        ApiError {
            errcode: ApiErrorCode::NotFound,
            error: message.unwrap_or("No resource was found for this request.").to_string(),
        }
    }

    /// Create an error for requests without JSON bodies.
    pub fn not_json(message: Option<&str>) -> ApiError {
        ApiError {
            errcode: ApiErrorCode::NotJson,
            error: message.unwrap_or("No JSON found in request body.").to_string(),
        }
    }

    /// Create an error for requests that are not marked as containing JSON.
    pub fn wrong_content_type(message: Option<&str>) -> ApiError {
        ApiError {
            errcode: ApiErrorCode::NotJson,
            error: message.unwrap_or(
                "Request's Content-Type header must be application/json."
            ).to_string(),
        }
    }

    /// Create an error for requests that did not provide required authentication parameters.
    pub fn unauthorized(message: Option<&str>) -> ApiError {
        ApiError {
            errcode: ApiErrorCode::Forbidden,
            error: message.unwrap_or("Authentication is required.").to_string(),
        }
    }

    /// Create an error for Matrix APIs that Ruma intentionally does not implement.
    pub fn unimplemented(message: Option<&str>) -> ApiError {
        ApiError {
            errcode: ApiErrorCode::Unimplemented,
            error: message.unwrap_or("The homeserver does not implement this API.").to_string(),
        }
    }

    /// Create a generic error for anything not specifically covered by the Matrix spec.
    pub fn unknown(message: Option<&str>) -> ApiError {
        ApiError {
            errcode: ApiErrorCode::Unknown,
            error: message.unwrap_or("An unknown server-side error occurred.").to_string(),
        }
    }
}

impl Display for ApiError {
    fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> {
        write!(f, "{}", self.error)
    }
}

impl Error for ApiError {
    fn description(&self) -> &str {
        &self.error
    }
}

impl From<IoError> for ApiError {
    fn from(error: IoError) -> ApiError {
        debug!("Converting to ApiError from: {:?}", error);

        ApiError::unknown(None)
    }
}

impl From<DecodeError> for ApiError {
    fn from(error: DecodeError) -> ApiError {
        debug!("Converting to ApiError from: {:?}", error);

        ApiError::unknown(None)
    }
}

impl From<Base64Error> for ApiError {
    fn from(error: Base64Error) -> ApiError {
        debug!("Converting to ApiError from: {:?}", error);

        ApiError::unknown(None)
    }
}

impl From<DieselError> for ApiError {
    fn from(error: DieselError) -> ApiError {
        debug!("Converting to ApiError from: {:?}", error);

        ApiError::unknown(None)
    }
}

impl<T> From<TransactionError<T>> for ApiError where T: Error {
    fn from(error: TransactionError<T>) -> ApiError {
        debug!("Converting to ApiError from: {:?}", error);

        ApiError::unknown(None)
    }
}

impl From<MacaroonsError> for ApiError {
    fn from(error: MacaroonsError) -> ApiError {
        debug!("Converting to ApiError from: {:?}", error);

        ApiError::unknown(None)
    }
}

impl From<PersistentError> for ApiError {
    fn from(error: PersistentError) -> ApiError {
        debug!("Converting to ApiError from: {:?}", error);

        ApiError::unknown(None)
    }
}

impl From<RumaIdentifiersError> for ApiError {
    fn from(error: RumaIdentifiersError) -> ApiError {
        debug!("Converting to ApiError from: {:?}", error);

        ApiError::unknown(None)
    }
}

impl From<GetTimeout> for ApiError {
    fn from(error: GetTimeout) -> ApiError {
        debug!("Converting to ApiError from: {:?}", error);

        ApiError::unknown(None)
    }
}

impl From<FromUtf8Error> for ApiError {
    fn from(error: FromUtf8Error) -> ApiError {
        debug!("Converting to ApiError from: {:?}", error);

        ApiError::unknown(None)
    }
}

impl<T> From<PoisonError<T>> for ApiError {
    fn from(error: PoisonError<T>) -> ApiError {
        debug!("Converting to ApiError from: {:?}", error);

        ApiError::unknown(None)
    }
}

impl From<SerdeJsonError> for ApiError {
    fn from(error: SerdeJsonError) -> ApiError {
        debug!("Converting to ApiError from: {:?}", error);

        ApiError::unknown(None)
    }
}

impl From<ApiError> for IronError {
    fn from(error: ApiError) -> IronError {
        IronError::new(error.clone(), error)
    }
}

impl Modifier<Response> for ApiError {
    fn modify(self, response: &mut Response) {
        response.status = Some(self.errcode.status_code());
        response.body = Some(Box::new(to_string(&self).expect("ApiError should always serialize")));
    }
}

impl ApiErrorCode {
    /// The HTTP status code that should be used to represent the `ApiErrorCode`.
    pub fn status_code(&self) -> Status {
        match *self {
            ApiErrorCode::BadEvent => Status::UnprocessableEntity,
            ApiErrorCode::BadJson => Status::UnprocessableEntity,
            ApiErrorCode::Forbidden => Status::Forbidden,
            ApiErrorCode::GuestAccessForbidden => Status::Forbidden,
            ApiErrorCode::LimitExceeded => Status::TooManyRequests,
            ApiErrorCode::MissingParam => Status::BadRequest,
            ApiErrorCode::NotFound => Status::NotFound,
            ApiErrorCode::NotJson => Status::BadRequest,
            ApiErrorCode::Unimplemented => Status::NotFound,
            ApiErrorCode::Unknown => Status::InternalServerError,
            ApiErrorCode::UnknownToken => Status::Unauthorized,
        }
    }
}

impl Serialize for ApiErrorCode {
    fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error> where S: Serializer {
        let value = match *self {
            ApiErrorCode::BadEvent => "IO.RUMA_BAD_EVENT",
            ApiErrorCode::BadJson => "M_BAD_JSON",
            ApiErrorCode::Forbidden => "M_FORBIDDEN",
            ApiErrorCode::GuestAccessForbidden => "M_GUEST_ACCESS_FORBIDDEN",
            ApiErrorCode::LimitExceeded => "M_LIMIT_EXCEEDED",
            ApiErrorCode::MissingParam => "M_MISSING_PARAM",
            ApiErrorCode::NotFound => "M_NOT_FOUND",
            ApiErrorCode::NotJson => "M_NOT_JSON",
            ApiErrorCode::Unimplemented => "IO.RUMA_UNIMPLEMENTED",
            ApiErrorCode::Unknown => "M_UNKNOWN",
            ApiErrorCode::UnknownToken => "M_UNKNOWN_TOKEN",
        };

        serializer.serialize_str(value)
    }
}

impl CliError {
    /// Create a new `CliError` from any `Error` type.
    pub fn new<E>(error: E) -> CliError where E: Into<String> {
        CliError {
            error: error.into(),
        }
    }
}

impl<E> From<E> for CliError where E: Error {
    fn from(error: E) -> CliError {
        CliError::new(error.description())
    }
}

impl Display for CliError {
    fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> {
        write!(f, "{}", self.error)
    }
}

impl<T, E> MapApiError for Result<T, E> where E: Debug {
    type Output = T;
    type Error = E;

    #[inline]
    fn map_api_err<O>(self, op: O) -> Result<T, ApiError> where O: FnOnce(E) -> ApiError {
        match self {
            Ok(t) => Ok(t),
            Err(e) => {
                debug!("Converting to ApiError from: {:?}", e);

                Err(op(e))
            }
        }
    }
}
<|endoftext|>