<commit_before>use config::Config;
use coarsetime::Clock;
use dnstap::{self, DNSMessage, DNSTapBuilder, DNSTapPendingWriter, DNSTapWriter, MessageType,
             SocketProtocol};
use std::net::SocketAddr;

pub struct LogDNSTap {
    dnstap_pending_writer: Option<DNSTapPendingWriter>,
    dnstap_writer: Option<DNSTapWriter>,
    dnstap_identity: Option<Vec<u8>>,
    dnstap_version: Option<Vec<u8>>,
}

impl LogDNSTap {
    pub fn new(config: &Config) -> LogDNSTap {
        assert!(config.dnstap_enabled);
        let socket_path = config.dnstap_socket_path
            .clone()
            .expect("dnstap requires a UNIX socket path");
        let dnstap_pending_writer = DNSTapBuilder::default()
            .backlog(config.dnstap_backlog)
            .unix_socket_path(socket_path.clone())
            .listen()
            .unwrap();
        info!("dnstap writer started -- UNIX socket path is [{}]",
              socket_path);
        let dnstap_identity = config.dnstap_identity.as_ref().map(|x| x.as_bytes().to_owned());
        let dnstap_version = config.dnstap_version.as_ref().map(|x| x.as_bytes().to_owned());
        LogDNSTap {
            dnstap_pending_writer: Some(dnstap_pending_writer),
            dnstap_writer: None,
            dnstap_identity: dnstap_identity,
            dnstap_version: dnstap_version,
        }
    }

    pub fn start(&mut self) {
        let dnstap_pending_writer = self.dnstap_pending_writer.take().unwrap();
        let dnstap_writer = dnstap_pending_writer.start().unwrap();
        self.dnstap_writer = Some(dnstap_writer);
    }

    pub fn sender(&self) -> Sender {
        Sender::new(self.dnstap_writer.as_ref().unwrap(),
                    self.dnstap_identity.clone(),
                    self.dnstap_version.clone())
    }
}

#[derive(Clone)]
pub struct Sender {
    template_forwarder_response: DNSMessage,
    dnstap_sender: dnstap::Sender,
}

impl Sender {
    pub fn new(dnstap_writer: &DNSTapWriter,
               dnstap_identity: Option<Vec<u8>>,
               dnstap_version: Option<Vec<u8>>)
               -> Sender {
        Sender {
            template_forwarder_response: DNSMessage::new(dnstap_identity,
                                                         dnstap_version,
                                                         MessageType::FORWARDER_RESPONSE),
            dnstap_sender: dnstap_writer.sender(),
        }
    }

    pub fn send_forwarder_response(&self,
                                   packet: &[u8],
                                   client_addr: SocketAddr,
                                   client_port: u16) {
        let mut dns_message = self.template_forwarder_response.clone();
        dns_message.socket_protocol = Some(SocketProtocol::UDP);
        dns_message.query_port = Some(client_port);
        dns_message.response_address = Some(client_addr.ip());
        dns_message.response_port = Some(client_addr.port());
        dns_message.response_packet = Some(packet.to_owned());
        dns_message.response_time = Some(Clock::recent_since_epoch().into());
        let _ = self.dnstap_sender.send(dns_message);
    }
}
<commit_msg>Just keep dnstap::Sender values in our own Sender abstraction<commit_after>use config::Config;
use coarsetime::Clock;
use dnstap::{self, DNSMessage, DNSTapBuilder, DNSTapPendingWriter, DNSTapWriter, MessageType,
             SocketProtocol};
use std::net::SocketAddr;

pub struct LogDNSTap {
    dnstap_pending_writer: Option<DNSTapPendingWriter>,
    dnstap_writer: Option<DNSTapWriter>,
    dnstap_identity: Option<Vec<u8>>,
    dnstap_version: Option<Vec<u8>>,
}

impl LogDNSTap {
    pub fn new(config: &Config) -> LogDNSTap {
        assert!(config.dnstap_enabled);
        let socket_path = config.dnstap_socket_path
            .clone()
            .expect("dnstap requires a UNIX socket path");
        let dnstap_pending_writer = DNSTapBuilder::default()
            .backlog(config.dnstap_backlog)
            .unix_socket_path(socket_path.clone())
            .listen()
            .unwrap();
        info!("dnstap writer started -- UNIX socket path is [{}]",
              socket_path);
        let dnstap_identity = config.dnstap_identity.as_ref().map(|x| x.as_bytes().to_owned());
        let dnstap_version = config.dnstap_version.as_ref().map(|x| x.as_bytes().to_owned());
        LogDNSTap {
            dnstap_pending_writer: Some(dnstap_pending_writer),
            dnstap_writer: None,
            dnstap_identity: dnstap_identity,
            dnstap_version: dnstap_version,
        }
    }

    pub fn start(&mut self) {
        let dnstap_pending_writer = self.dnstap_pending_writer.take().unwrap();
        let dnstap_writer = dnstap_pending_writer.start().unwrap();
        self.dnstap_writer = Some(dnstap_writer);
    }

    pub fn sender(&self) -> Sender {
        Sender::new(self.dnstap_pending_writer.as_ref().unwrap().sender(),
                    self.dnstap_identity.clone(),
                    self.dnstap_version.clone())
    }
}

#[derive(Clone)]
pub struct Sender {
    template_forwarder_response: DNSMessage,
    dnstap_sender: dnstap::Sender,
}

impl Sender {
    pub fn new(dnstap_sender: dnstap::Sender,
               dnstap_identity: Option<Vec<u8>>,
               dnstap_version: Option<Vec<u8>>)
               -> Sender {
        Sender {
            template_forwarder_response: DNSMessage::new(dnstap_identity,
                                                         dnstap_version,
                                                         MessageType::FORWARDER_RESPONSE),
            dnstap_sender: dnstap_sender
        }
    }

    pub fn send_forwarder_response(&self,
                                   packet: &[u8],
                                   client_addr: SocketAddr,
                                   client_port: u16) {
        let mut dns_message = self.template_forwarder_response.clone();
        dns_message.socket_protocol = Some(SocketProtocol::UDP);
        dns_message.query_port = Some(client_port);
        dns_message.response_address = Some(client_addr.ip());
        dns_message.response_port = Some(client_addr.port());
        dns_message.response_packet = Some(packet.to_owned());
        dns_message.response_time = Some(Clock::recent_since_epoch().into());
        let _ = self.dnstap_sender.send(dns_message);
    }
}
<|endoftext|>


<commit_before>use frame::ChannelAssignment;

pub fn decode_left_side(buffer: &mut [i32]) {
  let block_size = buffer.len() / 2;

  for i in 0..block_size {
    let left = buffer[i];
    let side = buffer[i + block_size];

    // right channel
    buffer[i + block_size] = left - side;
  }
}

pub fn decode_right_side(buffer: &mut [i32]) {
  let block_size = buffer.len() / 2;

  for i in 0..block_size {
    let side  = buffer[i];
    let right = buffer[i + block_size];

    // left channel
    buffer[i] = side + right;
  }
}

pub fn decode_middle_side(buffer: &mut [i32]) {
  let block_size = buffer.len() / 2;

  for i in 0..block_size {
    let mut middle = buffer[i];
    let side       = buffer[i + block_size];

    middle = (middle << 1) | (side & 1);

    // left and right channel
    buffer[i]              = (middle + side) >> 1;
    buffer[i + block_size] = (middle - side) >> 1;
  }
}

pub fn decode(channel_assignment: ChannelAssignment, buffer: &mut [i32]) {
  match channel_assignment {
    ChannelAssignment::Independent => return,
    ChannelAssignment::LeftSide    => decode_left_side(buffer),
    ChannelAssignment::RightSide   => decode_right_side(buffer),
    ChannelAssignment::MiddleSide  => decode_middle_side(buffer),
  }
}

#[cfg(test)]
mod tests {
  use super::*;

  #[test]
  fn test_decode_left_side() {
    let mut channels = [ 2, 5, 83, 113, 127, -63, -45, -15
                       , 7, 38, 142, 238, 0, -152, -52, -18
                       ];
    let result       = [-5, -33, -59, -125, 127, 89, 7, 3];

    decode_left_side(&mut channels);

    assert_eq!(&channels[8..16], &result);
  }

  #[test]
  fn test_decode_right_side() {
    let mut channels = [ 7, 38, 142, 238, 0, -152, -52, -18
                       , -5, -33, -59, -125, 127, 89, 7, 3
                       ];
    let result       = [2, 5, 83, 113, 127, -63, -45, -15];

    decode_right_side(&mut channels);

    assert_eq!(&channels[0..8], &result);
  }

  #[test]
  fn test_decode_middle_side() {
    let mut channels = [ -2, -14, 12, -6, 127, 13, -19, -6
                       , 7, 38, 142, 238, 0, -152, -52, -18
                       ];
    let results      = [ 2, 5, 83, 113, 127, -63, -45, -15
                       , -5, -33, -59, -125, 127, 89, 7, 3
                       ];

    decode_middle_side(&mut channels);

    assert_eq!(&channels, &results);
  }
}
<commit_msg>Add `Independent` test for frame decode<commit_after>use frame::ChannelAssignment;

pub fn decode_left_side(buffer: &mut [i32]) {
  let block_size = buffer.len() / 2;

  for i in 0..block_size {
    let left = buffer[i];
    let side = buffer[i + block_size];

    // right channel
    buffer[i + block_size] = left - side;
  }
}

pub fn decode_right_side(buffer: &mut [i32]) {
  let block_size = buffer.len() / 2;

  for i in 0..block_size {
    let side  = buffer[i];
    let right = buffer[i + block_size];

    // left channel
    buffer[i] = side + right;
  }
}

pub fn decode_middle_side(buffer: &mut [i32]) {
  let block_size = buffer.len() / 2;

  for i in 0..block_size {
    let mut middle = buffer[i];
    let side       = buffer[i + block_size];

    middle = (middle << 1) | (side & 1);

    // left and right channel
    buffer[i]              = (middle + side) >> 1;
    buffer[i + block_size] = (middle - side) >> 1;
  }
}

pub fn decode(channel_assignment: ChannelAssignment, buffer: &mut [i32]) {
  match channel_assignment {
    ChannelAssignment::Independent => return,
    ChannelAssignment::LeftSide    => decode_left_side(buffer),
    ChannelAssignment::RightSide   => decode_right_side(buffer),
    ChannelAssignment::MiddleSide  => decode_middle_side(buffer),
  }
}

#[cfg(test)]
mod tests {
  use super::*;
  use frame::ChannelAssignment;

  #[test]
  fn test_decode_left_side() {
    let mut channels = [ 2, 5, 83, 113, 127, -63, -45, -15
                       , 7, 38, 142, 238, 0, -152, -52, -18
                       ];
    let result       = [-5, -33, -59, -125, 127, 89, 7, 3];

    decode_left_side(&mut channels);

    assert_eq!(&channels[8..16], &result);
  }

  #[test]
  fn test_decode_right_side() {
    let mut channels = [ 7, 38, 142, 238, 0, -152, -52, -18
                       , -5, -33, -59, -125, 127, 89, 7, 3
                       ];
    let result       = [2, 5, 83, 113, 127, -63, -45, -15];

    decode_right_side(&mut channels);

    assert_eq!(&channels[0..8], &result);
  }

  #[test]
  fn test_decode_middle_side() {
    let mut channels = [ -2, -14, 12, -6, 127, 13, -19, -6
                       , 7, 38, 142, 238, 0, -152, -52, -18
                       ];
    let results      = [ 2, 5, 83, 113, 127, -63, -45, -15
                       , -5, -33, -59, -125, 127, 89, 7, 3
                       ];

    decode_middle_side(&mut channels);

    assert_eq!(&channels, &results);
  }

  #[test]
  fn test_decode() {
    let mut channels = [ 2, 5, 83, 113, 127, -63, -45, -15
                       , 7, 38, 142, 238, 0, -152, -52, -18
                       ];

    let results = [ [ 2, 5, 83, 113, 127, -63, -45, -15
                    , 7, 38, 142, 238, 0, -152, -52, -18
                    ],
                    [ 2, 5, 83, 113, 127, -63, -45, -15
                    ,-5, -33, -59, -125, 127, 89, 7, 3
                    ]
                  ];

    decode(ChannelAssignment::Independent, &mut channels);
    assert_eq!(&channels, &results[0]);
  }
}
<|endoftext|>


<commit_before>use std::collections::VecDeque;
use std::fmt::Debug;
use std::time::Instant;

use actix_net::codec::Framed;
use actix_net::service::Service;

use futures::{Async, AsyncSink, Future, Poll, Sink, Stream};
use tokio_io::{AsyncRead, AsyncWrite};
use tokio_timer::Delay;

use error::{ParseError, PayloadError};
use payload::{Payload, PayloadSender, PayloadStatus, PayloadWriter};

use body::{Body, BodyStream};
use config::ServiceConfig;
use error::DispatchError;
use request::Request;
use response::Response;

use super::codec::Codec;
use super::{H1ServiceResult, Message, MessageType};

const MAX_PIPELINED_MESSAGES: usize = 16;

bitflags! {
    pub struct Flags: u8 {
        const STARTED            = 0b0000_0001;
        const KEEPALIVE_ENABLED  = 0b0000_0010;
        const KEEPALIVE          = 0b0000_0100;
        const POLLED             = 0b0000_1000;
        const FLUSHED            = 0b0001_0000;
        const SHUTDOWN           = 0b0010_0000;
        const DISCONNECTED       = 0b0100_0000;
    }
}

/// Dispatcher for HTTP/1.1 protocol
pub struct Dispatcher<T, S: Service>
where
    S::Error: Debug,
{
    service: S,
    flags: Flags,
    framed: Option<Framed<T, Codec>>,
    error: Option<DispatchError<S::Error>>,
    config: ServiceConfig,

    state: State<S>,
    payload: Option<PayloadSender>,
    messages: VecDeque<DispatcherMessage>,
    unhandled: Option<Request>,

    ka_expire: Instant,
    ka_timer: Option<Delay>,
}

enum DispatcherMessage {
    Item(Request),
    Error(Response),
}

enum State<S: Service> {
    None,
    ServiceCall(S::Future),
    SendResponse(Option<(Message<Response>, Body)>),
    SendPayload(Option<BodyStream>, Option<Message<Response>>),
}

impl<S: Service> State<S> {
    fn is_empty(&self) -> bool {
        if let State::None = self {
            true
        } else {
            false
        }
    }
}

impl<T, S> Dispatcher<T, S>
where
    T: AsyncRead + AsyncWrite,
    S: Service<Request = Request, Response = Response>,
    S::Error: Debug,
{
    /// Create http/1 dispatcher.
    pub fn new(stream: T, config: ServiceConfig, service: S) -> Self {
        Dispatcher::with_timeout(stream, config, None, service)
    }

    /// Create http/1 dispatcher with slow request timeout.
    pub fn with_timeout(
        stream: T,
        config: ServiceConfig,
        timeout: Option<Delay>,
        service: S,
    ) -> Self {
        let keepalive = config.keep_alive_enabled();
        let flags = if keepalive {
            Flags::KEEPALIVE | Flags::KEEPALIVE_ENABLED | Flags::FLUSHED
        } else {
            Flags::FLUSHED
        };
        let framed = Framed::new(stream, Codec::new(config.clone()));

        // keep-alive timer
        let (ka_expire, ka_timer) = if let Some(delay) = timeout {
            (delay.deadline(), Some(delay))
        } else if let Some(delay) = config.keep_alive_timer() {
            (delay.deadline(), Some(delay))
        } else {
            (config.now(), None)
        };

        Dispatcher {
            payload: None,
            state: State::None,
            error: None,
            messages: VecDeque::new(),
            framed: Some(framed),
            unhandled: None,
            service,
            flags,
            config,
            ka_expire,
            ka_timer,
        }
    }

    fn can_read(&self) -> bool {
        if self.flags.contains(Flags::DISCONNECTED) {
            return false;
        }

        if let Some(ref info) = self.payload {
            info.need_read() == PayloadStatus::Read
        } else {
            true
        }
    }

    // if checked is set to true, delay disconnect until all tasks have finished.
    fn client_disconnected(&mut self) {
        self.flags.insert(Flags::DISCONNECTED);
        if let Some(mut payload) = self.payload.take() {
            payload.set_error(PayloadError::Incomplete);
        }
    }

    /// Flush stream
    fn poll_flush(&mut self) -> Poll<(), DispatchError<S::Error>> {
        if !self.flags.contains(Flags::FLUSHED) {
            match self.framed.as_mut().unwrap().poll_complete() {
                Ok(Async::NotReady) => Ok(Async::NotReady),
                Err(err) => {
                    debug!("Error sending data: {}", err);
                    Err(err.into())
                }
                Ok(Async::Ready(_)) => {
                    // if payload is not consumed we can not use connection
                    if self.payload.is_some() && self.state.is_empty() {
                        return Err(DispatchError::PayloadIsNotConsumed);
                    }
                    self.flags.insert(Flags::FLUSHED);
                    Ok(Async::Ready(()))
                }
            }
        } else {
            Ok(Async::Ready(()))
        }
    }

    fn poll_response(&mut self) -> Result<(), DispatchError<S::Error>> {
        let mut retry = self.can_read();

        // process
        loop {
            let state = match self.state {
                State::None => if let Some(msg) = self.messages.pop_front() {
                    match msg {
                        DispatcherMessage::Item(req) => Some(self.handle_request(req)?),
                        DispatcherMessage::Error(res) => Some(State::SendResponse(
                            Some((Message::Item(res), Body::Empty)),
                        )),
                    }
                } else {
                    None
                },
                // call inner service
                State::ServiceCall(ref mut fut) => {
                    match fut.poll().map_err(DispatchError::Service)? {
                        Async::Ready(mut res) => {
                            self.framed
                                .as_mut()
                                .unwrap()
                                .get_codec_mut()
                                .prepare_te(&mut res);
                            let body = res.replace_body(Body::Empty);
                            Some(State::SendResponse(Some((Message::Item(res), body))))
                        }
                        Async::NotReady => None,
                    }
                }
                // send respons
                State::SendResponse(ref mut item) => {
                    let (msg, body) = item.take().expect("SendResponse is empty");
                    match self.framed.as_mut().unwrap().start_send(msg) {
                        Ok(AsyncSink::Ready) => {
                            self.flags.set(
                                Flags::KEEPALIVE,
                                self.framed.as_mut().unwrap().get_codec().keepalive(),
                            );
                            self.flags.remove(Flags::FLUSHED);
                            match body {
                                Body::Empty => Some(State::None),
                                Body::Binary(mut bin) => Some(State::SendPayload(
                                    None,
                                    Some(Message::Chunk(Some(bin.take()))),
                                )),
                                Body::Streaming(stream) => {
                                    Some(State::SendPayload(Some(stream), None))
                                }
                            }
                        }
                        Ok(AsyncSink::NotReady(msg)) => {
                            *item = Some((msg, body));
                            return Ok(());
                        }
                        Err(err) => {
                            if let Some(mut payload) = self.payload.take() {
                                payload.set_error(PayloadError::Incomplete);
                            }
                            return Err(DispatchError::Io(err));
                        }
                    }
                }
                // Send payload
                State::SendPayload(ref mut stream, ref mut bin) => {
                    if let Some(item) = bin.take() {
                        match self.framed.as_mut().unwrap().start_send(item) {
                            Ok(AsyncSink::Ready) => {
                                self.flags.remove(Flags::FLUSHED);
                            }
                            Ok(AsyncSink::NotReady(item)) => {
                                *bin = Some(item);
                                return Ok(());
                            }
                            Err(err) => return Err(DispatchError::Io(err)),
                        }
                    }
                    if let Some(ref mut stream) = stream {
                        match stream.poll() {
                            Ok(Async::Ready(Some(item))) => match self
                                .framed
                                .as_mut()
                                .unwrap()
                                .start_send(Message::Chunk(Some(item)))
                            {
                                Ok(AsyncSink::Ready) => {
                                    self.flags.remove(Flags::FLUSHED);
                                    continue;
                                }
                                Ok(AsyncSink::NotReady(msg)) => {
                                    *bin = Some(msg);
                                    return Ok(());
                                }
                                Err(err) => return Err(DispatchError::Io(err)),
                            },
                            Ok(Async::Ready(None)) => Some(State::SendPayload(
                                None,
                                Some(Message::Chunk(None)),
                            )),
                            Ok(Async::NotReady) => return Ok(()),
                            // Err(err) => return Err(DispatchError::Io(err)),
                            Err(_) => return Err(DispatchError::Unknown),
                        }
                    } else {
                        Some(State::None)
                    }
                }
            };

            match state {
                Some(state) => self.state = state,
                None => {
                    // if read-backpressure is enabled and we consumed some data.
                    // we may read more dataand retry
                    if !retry && self.can_read() && self.poll_request()? {
                        retry = self.can_read();
                        continue;
                    }
                    break;
                }
            }
        }

        Ok(())
    }

    fn handle_request(
        &mut self,
        req: Request,
    ) -> Result<State<S>, DispatchError<S::Error>> {
        let mut task = self.service.call(req);
        match task.poll().map_err(DispatchError::Service)? {
            Async::Ready(mut res) => {
                self.framed
                    .as_mut()
                    .unwrap()
                    .get_codec_mut()
                    .prepare_te(&mut res);
                let body = res.replace_body(Body::Empty);
                Ok(State::SendResponse(Some((Message::Item(res), body))))
            }
            Async::NotReady => Ok(State::ServiceCall(task)),
        }
    }

    /// Process one incoming requests
    pub(self) fn poll_request(&mut self) -> Result<bool, DispatchError<S::Error>> {
        // limit a mount of non processed requests
        if self.messages.len() >= MAX_PIPELINED_MESSAGES {
            return Ok(false);
        }

        let mut updated = false;
        loop {
            match self.framed.as_mut().unwrap().poll() {
                Ok(Async::Ready(Some(msg))) => {
                    updated = true;
                    self.flags.insert(Flags::STARTED);

                    match msg {
                        Message::Item(req) => {
                            match self
                                .framed
                                .as_ref()
                                .unwrap()
                                .get_codec()
                                .message_type()
                            {
                                MessageType::Payload => {
                                    let (ps, pl) = Payload::new(false);
                                    *req.inner.payload.borrow_mut() = Some(pl);
                                    self.payload = Some(ps);
                                }
                                MessageType::Unhandled => {
                                    self.unhandled = Some(req);
                                    return Ok(updated);
                                }
                                _ => (),
                            }

                            // handle request early
                            if self.state.is_empty() {
                                self.state = self.handle_request(req)?;
                            } else {
                                self.messages.push_back(DispatcherMessage::Item(req));
                            }
                        }
                        Message::Chunk(Some(chunk)) => {
                            if let Some(ref mut payload) = self.payload {
                                payload.feed_data(chunk);
                            } else {
                                error!(
                                    "Internal server error: unexpected payload chunk"
                                );
                                self.flags.insert(Flags::DISCONNECTED);
                                self.messages.push_back(DispatcherMessage::Error(
                                    Response::InternalServerError().finish(),
                                ));
                                self.error = Some(DispatchError::InternalError);
                                break;
                            }
                        }
                        Message::Chunk(None) => {
                            if let Some(mut payload) = self.payload.take() {
                                payload.feed_eof();
                            } else {
                                error!("Internal server error: unexpected eof");
                                self.flags.insert(Flags::DISCONNECTED);
                                self.messages.push_back(DispatcherMessage::Error(
                                    Response::InternalServerError().finish(),
                                ));
                                self.error = Some(DispatchError::InternalError);
                                break;
                            }
                        }
                    }
                }
                Ok(Async::Ready(None)) => {
                    self.client_disconnected();
                    break;
                }
                Ok(Async::NotReady) => break,
                Err(ParseError::Io(e)) => {
                    self.client_disconnected();
                    self.error = Some(DispatchError::Io(e));
                    break;
                }
                Err(e) => {
                    if let Some(mut payload) = self.payload.take() {
                        payload.set_error(PayloadError::EncodingCorrupted);
                    }

                    // Malformed requests should be responded with 400
                    self.messages.push_back(DispatcherMessage::Error(
                        Response::BadRequest().finish(),
                    ));
                    self.flags.insert(Flags::DISCONNECTED);
                    self.error = Some(e.into());
                    break;
                }
            }
        }

        if self.ka_timer.is_some() && updated {
            if let Some(expire) = self.config.keep_alive_expire() {
                self.ka_expire = expire;
            }
        }
        Ok(updated)
    }

    /// keep-alive timer
    fn poll_keepalive(&mut self) -> Result<(), DispatchError<S::Error>> {
        if let Some(ref mut timer) = self.ka_timer {
            match timer.poll() {
                Ok(Async::Ready(_)) => {
                    // if we get timer during shutdown, just drop connection
                    if self.flags.contains(Flags::SHUTDOWN) {
                        return Err(DispatchError::DisconnectTimeout);
                    } else if timer.deadline() >= self.ka_expire {
                        // check for any outstanding response processing
                        if self.state.is_empty() {
                            if self.flags.contains(Flags::STARTED) {
                                trace!("Keep-alive timeout, close connection");
                                self.flags.insert(Flags::SHUTDOWN);

                                // start shutdown timer
                                if let Some(deadline) =
                                    self.config.client_disconnect_timer()
                                {
                                    timer.reset(deadline);
                                    let _ = timer.poll();
                                } else {
                                    return Ok(());
                                }
                            } else {
                                // timeout on first request (slow request) return 408
                                trace!("Slow request timeout");
                                self.flags.insert(Flags::STARTED | Flags::DISCONNECTED);
                                self.state = State::SendResponse(Some((
                                    Message::Item(Response::RequestTimeout().finish()),
                                    Body::Empty,
                                )));
                            }
                        } else if let Some(deadline) = self.config.keep_alive_expire() {
                            timer.reset(deadline);
                            let _ = timer.poll();
                        }
                    } else {
                        timer.reset(self.ka_expire);
                        let _ = timer.poll();
                    }
                }
                Ok(Async::NotReady) => (),
                Err(e) => {
                    error!("Timer error {:?}", e);
                    return Err(DispatchError::Unknown);
                }
            }
        }

        Ok(())
    }
}

impl<T, S> Future for Dispatcher<T, S>
where
    T: AsyncRead + AsyncWrite,
    S: Service<Request = Request, Response = Response>,
    S::Error: Debug,
{
    type Item = H1ServiceResult<T>;
    type Error = DispatchError<S::Error>;

    #[inline]
    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        if self.flags.contains(Flags::SHUTDOWN) {
            self.poll_keepalive()?;
            try_ready!(self.poll_flush());
            let io = self.framed.take().unwrap().into_inner();
            Ok(Async::Ready(H1ServiceResult::Shutdown(io)))
        } else {
            self.poll_keepalive()?;
            self.poll_request()?;
            self.poll_response()?;
            self.poll_flush()?;

            // keep-alive and stream errors
            if self.state.is_empty() && self.flags.contains(Flags::FLUSHED) {
                if let Some(err) = self.error.take() {
                    Err(err)
                } else if self.flags.contains(Flags::DISCONNECTED) {
                    Ok(Async::Ready(H1ServiceResult::Disconnected))
                }
                // unhandled request (upgrade or connect)
                else if self.unhandled.is_some() {
                    let req = self.unhandled.take().unwrap();
                    let framed = self.framed.take().unwrap();
                    Ok(Async::Ready(H1ServiceResult::Unhandled(req, framed)))
                }
                // disconnect if keep-alive is not enabled
                else if self.flags.contains(Flags::STARTED) && !self
                    .flags
                    .intersects(Flags::KEEPALIVE | Flags::KEEPALIVE_ENABLED)
                {
                    let io = self.framed.take().unwrap().into_inner();
                    Ok(Async::Ready(H1ServiceResult::Shutdown(io)))
                } else {
                    Ok(Async::NotReady)
                }
            } else {
                Ok(Async::NotReady)
            }
        }
    }
}
<commit_msg>do not stop on keep-alive timer if sink is not completly flushed<commit_after>use std::collections::VecDeque;
use std::fmt::Debug;
use std::time::Instant;

use actix_net::codec::Framed;
use actix_net::service::Service;

use futures::{Async, AsyncSink, Future, Poll, Sink, Stream};
use tokio_io::{AsyncRead, AsyncWrite};
use tokio_timer::Delay;

use error::{ParseError, PayloadError};
use payload::{Payload, PayloadSender, PayloadStatus, PayloadWriter};

use body::{Body, BodyStream};
use config::ServiceConfig;
use error::DispatchError;
use request::Request;
use response::Response;

use super::codec::Codec;
use super::{H1ServiceResult, Message, MessageType};

const MAX_PIPELINED_MESSAGES: usize = 16;

bitflags! {
    pub struct Flags: u8 {
        const STARTED            = 0b0000_0001;
        const KEEPALIVE_ENABLED  = 0b0000_0010;
        const KEEPALIVE          = 0b0000_0100;
        const POLLED             = 0b0000_1000;
        const FLUSHED            = 0b0001_0000;
        const SHUTDOWN           = 0b0010_0000;
        const DISCONNECTED       = 0b0100_0000;
    }
}

/// Dispatcher for HTTP/1.1 protocol
pub struct Dispatcher<T, S: Service>
where
    S::Error: Debug,
{
    service: S,
    flags: Flags,
    framed: Option<Framed<T, Codec>>,
    error: Option<DispatchError<S::Error>>,
    config: ServiceConfig,

    state: State<S>,
    payload: Option<PayloadSender>,
    messages: VecDeque<DispatcherMessage>,
    unhandled: Option<Request>,

    ka_expire: Instant,
    ka_timer: Option<Delay>,
}

enum DispatcherMessage {
    Item(Request),
    Error(Response),
}

enum State<S: Service> {
    None,
    ServiceCall(S::Future),
    SendResponse(Option<(Message<Response>, Body)>),
    SendPayload(Option<BodyStream>, Option<Message<Response>>),
}

impl<S: Service> State<S> {
    fn is_empty(&self) -> bool {
        if let State::None = self {
            true
        } else {
            false
        }
    }
}

impl<T, S> Dispatcher<T, S>
where
    T: AsyncRead + AsyncWrite,
    S: Service<Request = Request, Response = Response>,
    S::Error: Debug,
{
    /// Create http/1 dispatcher.
    pub fn new(stream: T, config: ServiceConfig, service: S) -> Self {
        Dispatcher::with_timeout(stream, config, None, service)
    }

    /// Create http/1 dispatcher with slow request timeout.
    pub fn with_timeout(
        stream: T,
        config: ServiceConfig,
        timeout: Option<Delay>,
        service: S,
    ) -> Self {
        let keepalive = config.keep_alive_enabled();
        let flags = if keepalive {
            Flags::KEEPALIVE | Flags::KEEPALIVE_ENABLED | Flags::FLUSHED
        } else {
            Flags::FLUSHED
        };
        let framed = Framed::new(stream, Codec::new(config.clone()));

        // keep-alive timer
        let (ka_expire, ka_timer) = if let Some(delay) = timeout {
            (delay.deadline(), Some(delay))
        } else if let Some(delay) = config.keep_alive_timer() {
            (delay.deadline(), Some(delay))
        } else {
            (config.now(), None)
        };

        Dispatcher {
            payload: None,
            state: State::None,
            error: None,
            messages: VecDeque::new(),
            framed: Some(framed),
            unhandled: None,
            service,
            flags,
            config,
            ka_expire,
            ka_timer,
        }
    }

    fn can_read(&self) -> bool {
        if self.flags.contains(Flags::DISCONNECTED) {
            return false;
        }

        if let Some(ref info) = self.payload {
            info.need_read() == PayloadStatus::Read
        } else {
            true
        }
    }

    // if checked is set to true, delay disconnect until all tasks have finished.
    fn client_disconnected(&mut self) {
        self.flags.insert(Flags::DISCONNECTED);
        if let Some(mut payload) = self.payload.take() {
            payload.set_error(PayloadError::Incomplete);
        }
    }

    /// Flush stream
    fn poll_flush(&mut self) -> Poll<(), DispatchError<S::Error>> {
        if !self.flags.contains(Flags::FLUSHED) {
            match self.framed.as_mut().unwrap().poll_complete() {
                Ok(Async::NotReady) => Ok(Async::NotReady),
                Err(err) => {
                    debug!("Error sending data: {}", err);
                    Err(err.into())
                }
                Ok(Async::Ready(_)) => {
                    // if payload is not consumed we can not use connection
                    if self.payload.is_some() && self.state.is_empty() {
                        return Err(DispatchError::PayloadIsNotConsumed);
                    }
                    self.flags.insert(Flags::FLUSHED);
                    Ok(Async::Ready(()))
                }
            }
        } else {
            Ok(Async::Ready(()))
        }
    }

    fn poll_response(&mut self) -> Result<(), DispatchError<S::Error>> {
        let mut retry = self.can_read();

        // process
        loop {
            let state = match self.state {
                State::None => if let Some(msg) = self.messages.pop_front() {
                    match msg {
                        DispatcherMessage::Item(req) => Some(self.handle_request(req)?),
                        DispatcherMessage::Error(res) => Some(State::SendResponse(
                            Some((Message::Item(res), Body::Empty)),
                        )),
                    }
                } else {
                    None
                },
                // call inner service
                State::ServiceCall(ref mut fut) => {
                    match fut.poll().map_err(DispatchError::Service)? {
                        Async::Ready(mut res) => {
                            self.framed
                                .as_mut()
                                .unwrap()
                                .get_codec_mut()
                                .prepare_te(&mut res);
                            let body = res.replace_body(Body::Empty);
                            Some(State::SendResponse(Some((Message::Item(res), body))))
                        }
                        Async::NotReady => None,
                    }
                }
                // send respons
                State::SendResponse(ref mut item) => {
                    let (msg, body) = item.take().expect("SendResponse is empty");
                    match self.framed.as_mut().unwrap().start_send(msg) {
                        Ok(AsyncSink::Ready) => {
                            self.flags.set(
                                Flags::KEEPALIVE,
                                self.framed.as_mut().unwrap().get_codec().keepalive(),
                            );
                            self.flags.remove(Flags::FLUSHED);
                            match body {
                                Body::Empty => Some(State::None),
                                Body::Binary(mut bin) => Some(State::SendPayload(
                                    None,
                                    Some(Message::Chunk(Some(bin.take()))),
                                )),
                                Body::Streaming(stream) => {
                                    Some(State::SendPayload(Some(stream), None))
                                }
                            }
                        }
                        Ok(AsyncSink::NotReady(msg)) => {
                            *item = Some((msg, body));
                            return Ok(());
                        }
                        Err(err) => {
                            if let Some(mut payload) = self.payload.take() {
                                payload.set_error(PayloadError::Incomplete);
                            }
                            return Err(DispatchError::Io(err));
                        }
                    }
                }
                // Send payload
                State::SendPayload(ref mut stream, ref mut bin) => {
                    if let Some(item) = bin.take() {
                        match self.framed.as_mut().unwrap().start_send(item) {
                            Ok(AsyncSink::Ready) => {
                                self.flags.remove(Flags::FLUSHED);
                            }
                            Ok(AsyncSink::NotReady(item)) => {
                                *bin = Some(item);
                                return Ok(());
                            }
                            Err(err) => return Err(DispatchError::Io(err)),
                        }
                    }
                    if let Some(ref mut stream) = stream {
                        match stream.poll() {
                            Ok(Async::Ready(Some(item))) => match self
                                .framed
                                .as_mut()
                                .unwrap()
                                .start_send(Message::Chunk(Some(item)))
                            {
                                Ok(AsyncSink::Ready) => {
                                    self.flags.remove(Flags::FLUSHED);
                                    continue;
                                }
                                Ok(AsyncSink::NotReady(msg)) => {
                                    *bin = Some(msg);
                                    return Ok(());
                                }
                                Err(err) => return Err(DispatchError::Io(err)),
                            },
                            Ok(Async::Ready(None)) => Some(State::SendPayload(
                                None,
                                Some(Message::Chunk(None)),
                            )),
                            Ok(Async::NotReady) => return Ok(()),
                            // Err(err) => return Err(DispatchError::Io(err)),
                            Err(_) => return Err(DispatchError::Unknown),
                        }
                    } else {
                        Some(State::None)
                    }
                }
            };

            match state {
                Some(state) => self.state = state,
                None => {
                    // if read-backpressure is enabled and we consumed some data.
                    // we may read more dataand retry
                    if !retry && self.can_read() && self.poll_request()? {
                        retry = self.can_read();
                        continue;
                    }
                    break;
                }
            }
        }

        Ok(())
    }

    fn handle_request(
        &mut self,
        req: Request,
    ) -> Result<State<S>, DispatchError<S::Error>> {
        let mut task = self.service.call(req);
        match task.poll().map_err(DispatchError::Service)? {
            Async::Ready(mut res) => {
                self.framed
                    .as_mut()
                    .unwrap()
                    .get_codec_mut()
                    .prepare_te(&mut res);
                let body = res.replace_body(Body::Empty);
                Ok(State::SendResponse(Some((Message::Item(res), body))))
            }
            Async::NotReady => Ok(State::ServiceCall(task)),
        }
    }

    /// Process one incoming requests
    pub(self) fn poll_request(&mut self) -> Result<bool, DispatchError<S::Error>> {
        // limit a mount of non processed requests
        if self.messages.len() >= MAX_PIPELINED_MESSAGES {
            return Ok(false);
        }

        let mut updated = false;
        loop {
            match self.framed.as_mut().unwrap().poll() {
                Ok(Async::Ready(Some(msg))) => {
                    updated = true;
                    self.flags.insert(Flags::STARTED);

                    match msg {
                        Message::Item(req) => {
                            match self
                                .framed
                                .as_ref()
                                .unwrap()
                                .get_codec()
                                .message_type()
                            {
                                MessageType::Payload => {
                                    let (ps, pl) = Payload::new(false);
                                    *req.inner.payload.borrow_mut() = Some(pl);
                                    self.payload = Some(ps);
                                }
                                MessageType::Unhandled => {
                                    self.unhandled = Some(req);
                                    return Ok(updated);
                                }
                                _ => (),
                            }

                            // handle request early
                            if self.state.is_empty() {
                                self.state = self.handle_request(req)?;
                            } else {
                                self.messages.push_back(DispatcherMessage::Item(req));
                            }
                        }
                        Message::Chunk(Some(chunk)) => {
                            if let Some(ref mut payload) = self.payload {
                                payload.feed_data(chunk);
                            } else {
                                error!(
                                    "Internal server error: unexpected payload chunk"
                                );
                                self.flags.insert(Flags::DISCONNECTED);
                                self.messages.push_back(DispatcherMessage::Error(
                                    Response::InternalServerError().finish(),
                                ));
                                self.error = Some(DispatchError::InternalError);
                                break;
                            }
                        }
                        Message::Chunk(None) => {
                            if let Some(mut payload) = self.payload.take() {
                                payload.feed_eof();
                            } else {
                                error!("Internal server error: unexpected eof");
                                self.flags.insert(Flags::DISCONNECTED);
                                self.messages.push_back(DispatcherMessage::Error(
                                    Response::InternalServerError().finish(),
                                ));
                                self.error = Some(DispatchError::InternalError);
                                break;
                            }
                        }
                    }
                }
                Ok(Async::Ready(None)) => {
                    self.client_disconnected();
                    break;
                }
                Ok(Async::NotReady) => break,
                Err(ParseError::Io(e)) => {
                    self.client_disconnected();
                    self.error = Some(DispatchError::Io(e));
                    break;
                }
                Err(e) => {
                    if let Some(mut payload) = self.payload.take() {
                        payload.set_error(PayloadError::EncodingCorrupted);
                    }

                    // Malformed requests should be responded with 400
                    self.messages.push_back(DispatcherMessage::Error(
                        Response::BadRequest().finish(),
                    ));
                    self.flags.insert(Flags::DISCONNECTED);
                    self.error = Some(e.into());
                    break;
                }
            }
        }

        if self.ka_timer.is_some() && updated {
            if let Some(expire) = self.config.keep_alive_expire() {
                self.ka_expire = expire;
            }
        }
        Ok(updated)
    }

    /// keep-alive timer
    fn poll_keepalive(&mut self) -> Result<(), DispatchError<S::Error>> {
        if let Some(ref mut timer) = self.ka_timer {
            match timer.poll() {
                Ok(Async::Ready(_)) => {
                    // if we get timer during shutdown, just drop connection
                    if self.flags.contains(Flags::SHUTDOWN) {
                        return Err(DispatchError::DisconnectTimeout);
                    } else if timer.deadline() >= self.ka_expire {
                        // check for any outstanding response processing
                        if self.state.is_empty() && self.flags.contains(Flags::FLUSHED) {
                            if self.flags.contains(Flags::STARTED) {
                                trace!("Keep-alive timeout, close connection");
                                self.flags.insert(Flags::SHUTDOWN);

                                // start shutdown timer
                                if let Some(deadline) =
                                    self.config.client_disconnect_timer()
                                {
                                    timer.reset(deadline);
                                    let _ = timer.poll();
                                } else {
                                    return Ok(());
                                }
                            } else {
                                // timeout on first request (slow request) return 408
                                trace!("Slow request timeout");
                                self.flags.insert(Flags::STARTED | Flags::DISCONNECTED);
                                self.state = State::SendResponse(Some((
                                    Message::Item(Response::RequestTimeout().finish()),
                                    Body::Empty,
                                )));
                            }
                        } else if let Some(deadline) = self.config.keep_alive_expire() {
                            timer.reset(deadline);
                            let _ = timer.poll();
                        }
                    } else {
                        timer.reset(self.ka_expire);
                        let _ = timer.poll();
                    }
                }
                Ok(Async::NotReady) => (),
                Err(e) => {
                    error!("Timer error {:?}", e);
                    return Err(DispatchError::Unknown);
                }
            }
        }

        Ok(())
    }
}

impl<T, S> Future for Dispatcher<T, S>
where
    T: AsyncRead + AsyncWrite,
    S: Service<Request = Request, Response = Response>,
    S::Error: Debug,
{
    type Item = H1ServiceResult<T>;
    type Error = DispatchError<S::Error>;

    #[inline]
    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        if self.flags.contains(Flags::SHUTDOWN) {
            self.poll_keepalive()?;
            try_ready!(self.poll_flush());
            let io = self.framed.take().unwrap().into_inner();
            Ok(Async::Ready(H1ServiceResult::Shutdown(io)))
        } else {
            self.poll_keepalive()?;
            self.poll_request()?;
            self.poll_response()?;
            self.poll_flush()?;

            // keep-alive and stream errors
            if self.state.is_empty() && self.flags.contains(Flags::FLUSHED) {
                if let Some(err) = self.error.take() {
                    Err(err)
                } else if self.flags.contains(Flags::DISCONNECTED) {
                    Ok(Async::Ready(H1ServiceResult::Disconnected))
                }
                // unhandled request (upgrade or connect)
                else if self.unhandled.is_some() {
                    let req = self.unhandled.take().unwrap();
                    let framed = self.framed.take().unwrap();
                    Ok(Async::Ready(H1ServiceResult::Unhandled(req, framed)))
                }
                // disconnect if keep-alive is not enabled
                else if self.flags.contains(Flags::STARTED) && !self
                    .flags
                    .intersects(Flags::KEEPALIVE | Flags::KEEPALIVE_ENABLED)
                {
                    let io = self.framed.take().unwrap().into_inner();
                    Ok(Async::Ready(H1ServiceResult::Shutdown(io)))
                } else {
                    Ok(Async::NotReady)
                }
            } else {
                Ok(Async::NotReady)
            }
        }
    }
}
<|endoftext|>


<commit_before>#[link(name = "distrust",
       vers = "0",
       url  = "http://github.com/thewonderidiot/distrust")];
#[desc = "A simple disassembler in Rust"];
#[license = "MIT"];
#[crate_type = "bin"];

fn main() {
    println("Hello!");
}
<commit_msg>Simple option handling and file opening, lots of not-really-useful-yet stuff<commit_after>#[link(name = "distrust",
       vers = "0",
       url  = "http://github.com/thewonderidiot/distrust")];
#[desc = "A simple disassembler in Rust"];
#[license = "MIT"];
#[crate_type = "bin"];

extern mod extra;
use extra::getopts::*;
use std::path::Path;
use std::os;
use std::io;

fn print_usage() {
    println("Usage: distrust [OPTIONS] INPUT\n");
    println("Options:");
    println("    -h --help    Display this message");
    println("");
}

fn main() {
    let args = os::args();
    if args.len() == 1 {
        print_usage();
        return;
    }

    let opts = [
        optflag("h"),
        optflag("help")
    ];
    let matches = getopts(args.tail(), opts).unwrap();

    if matches.opt_present("h") || matches.opt_present("help") {
        print_usage();
        return;
    }
    // process more (actually useful) arguments...

    let file = match matches.free.len() {
        0u => fail!("no filename supplied"),
        1u => io::file_reader(&Path(matches.free[0])).unwrap(),
        _  => fail!("multiple input filenames")
    };

    println!("Successfully opened {}", matches.free[0]);
}
<|endoftext|>


<commit_before>use core::cell::Cell;
use process::{Callback, NUM_PROCS};
use hil::Driver;
use hil::alarm::{Alarm, AlarmClient, Frequency};
use hil::timer::{Timer, TimerClient};

#[derive(Copy, Clone)]
enum Schedule {
    Oneshot,
    Repeating { interval: u32 }
}

pub struct AlarmToTimer<'a, Alrm: Alarm + 'a> {
    schedule: Cell<Schedule>,
    alarm: &'a Alrm,
    client: Cell<Option<&'a TimerClient>>
}

impl<'a, Alrm: Alarm> AlarmToTimer<'a, Alrm> {
    pub const fn new(alarm: &'a Alrm) -> AlarmToTimer<'a, Alrm> {
        AlarmToTimer {
            schedule: Cell::new(Schedule::Oneshot),
            alarm: alarm,
            client: Cell::new(None)
        }
    }

    pub fn set_client(&self, client: &'a TimerClient) {
        self.client.set(Some(client));
    }
}

impl<'a, Alrm: Alarm> Timer for AlarmToTimer<'a, Alrm> {
    fn now(&self) -> u32 {
        self.alarm.now()
    }

    fn oneshot(&self, interval_ms: u32) {
        let interval = interval_ms * <Alrm::Frequency>::frequency() / 1000;

        self.schedule.set(Schedule::Oneshot);

        let when = interval.wrapping_add(self.alarm.now());
        self.alarm.set_alarm(when);
    }

    #[inline(never)]
    fn repeat(&self, interval_ms: u32) {
        let interval = interval_ms * <Alrm::Frequency>::frequency() / 1000;

        self.schedule.set(Schedule::Repeating {interval: interval});

        let when = interval.wrapping_add(self.alarm.now());
        self.alarm.set_alarm(when);
    }
}

impl<'a, Alrm: Alarm> AlarmClient for AlarmToTimer<'a, Alrm> {
    fn fired(&self) {
        let now = self.now();

        match self.schedule.get() {
            Schedule::Oneshot => self.alarm.disable_alarm(),

            Schedule::Repeating { interval } => {
                let when = interval.wrapping_add(now);
                self.alarm.set_alarm(when);
            }
        }

        self.client.get().map(|client| client.fired(now) );
    }
}

#[derive(Copy, Clone)]
pub struct TimerData {
    t0: u32,
    interval: u32,
    repeating: bool,
    callback: Callback
}

pub struct TimerDriver<'a, T: Timer + 'a> {
    timer: &'a T,
    app_timers: [Cell<Option<TimerData>>; NUM_PROCS],
}

impl<'a, T: Timer> TimerDriver<'a, T> {
    pub const fn new(timer: &'a T) -> TimerDriver<'a, T> {
        TimerDriver {
            timer: timer,
            app_timers: [Cell::new(None); NUM_PROCS],
        }
    }
}

impl<'a, T: Timer> Driver for TimerDriver<'a, T> {
    fn subscribe(&self, _: usize, callback: Callback) -> isize {
        self.app_timers[callback.app_id().idx()].set(Some(TimerData {
            t0: 0,
            interval: 0,
            repeating: false,
            callback: callback
        }));
        0
    }

    fn command(&self, cmd_type: usize, interval: usize) -> isize {
        let interval = interval as u32;
        self.app_timers[0].get().map(|td| {
            match cmd_type {
                0 /* Oneshot */ => {
                    self.app_timers[0].set(
                            Some(TimerData {
                                t0: self.timer.now(),
                                interval: interval,
                                repeating: false,
                                callback: td.callback
                            })
                    );
                    self.timer.oneshot(interval);
                    0
                },
                1 /* Repeating */ => {
                    self.app_timers[0].set(
                            Some(TimerData {
                                t0: self.timer.now(),
                                interval: interval,
                                repeating: true,
                                callback: td.callback
                            })
                    );
                    self.timer.repeat(interval);
                    0
                },
                _ => -1
            }
        }).unwrap_or(-2)
    }
}

impl<'a, T: Timer> TimerClient for TimerDriver<'a, T> {
    fn fired(&self, now: u32) {
        for mtimer in self.app_timers.iter() {
            mtimer.get().map(|timer| {
                let elapsed = now.wrapping_sub(timer.t0);
                if elapsed >= timer.interval {
                    let mut cb = timer.callback;
                    cb.schedule(now as usize, 0, 0);
                }
            });
        }
    }
}

<commit_msg>Timer: fix bug in repeat<commit_after>use core::cell::Cell;
use process::{Callback, NUM_PROCS};
use hil::Driver;
use hil::alarm::{Alarm, AlarmClient, Frequency};
use hil::timer::{Timer, TimerClient};

#[derive(Copy, Clone)]
enum Schedule {
    Oneshot,
    Repeating { interval: u32 }
}

pub struct AlarmToTimer<'a, Alrm: Alarm + 'a> {
    schedule: Cell<Schedule>,
    alarm: &'a Alrm,
    client: Cell<Option<&'a TimerClient>>
}

impl<'a, Alrm: Alarm> AlarmToTimer<'a, Alrm> {
    pub const fn new(alarm: &'a Alrm) -> AlarmToTimer<'a, Alrm> {
        AlarmToTimer {
            schedule: Cell::new(Schedule::Oneshot),
            alarm: alarm,
            client: Cell::new(None)
        }
    }

    pub fn set_client(&self, client: &'a TimerClient) {
        self.client.set(Some(client));
    }
}

impl<'a, Alrm: Alarm> Timer for AlarmToTimer<'a, Alrm> {
    fn now(&self) -> u32 {
        self.alarm.now()
    }

    fn oneshot(&self, interval_ms: u32) {
        let interval = interval_ms * <Alrm::Frequency>::frequency() / 1000;

        self.schedule.set(Schedule::Oneshot);

        let when = interval.wrapping_add(self.alarm.now());
        self.alarm.set_alarm(when);
    }

    fn repeat(&self, interval_ms: u32) {
        let interval = interval_ms * <Alrm::Frequency>::frequency() / 1000;

        self.schedule.set(Schedule::Repeating {interval: interval});

        let when = interval.wrapping_add(self.alarm.now());
        self.alarm.set_alarm(when);
    }
}

impl<'a, Alrm: Alarm> AlarmClient for AlarmToTimer<'a, Alrm> {
    fn fired(&self) {
        let now = self.now();

        match self.schedule.get() {
            Schedule::Oneshot => self.alarm.disable_alarm(),

            Schedule::Repeating { interval } => {
                let when = interval.wrapping_add(now);
                self.alarm.set_alarm(when);
            }
        }

        self.client.get().map(|client| client.fired(now) );
    }
}

#[derive(Copy, Clone)]
pub struct TimerData {
    t0: u32,
    interval: u32,
    repeating: bool,
    callback: Callback
}

pub struct TimerDriver<'a, T: Timer + 'a> {
    timer: &'a T,
    app_timers: [Cell<Option<TimerData>>; NUM_PROCS],
}

impl<'a, T: Timer> TimerDriver<'a, T> {
    pub const fn new(timer: &'a T) -> TimerDriver<'a, T> {
        TimerDriver {
            timer: timer,
            app_timers: [Cell::new(None); NUM_PROCS],
        }
    }
}

impl<'a, T: Timer> Driver for TimerDriver<'a, T> {
    fn subscribe(&self, _: usize, callback: Callback) -> isize {
        self.app_timers[callback.app_id().idx()].set(Some(TimerData {
            t0: 0,
            interval: 0,
            repeating: false,
            callback: callback
        }));
        0
    }

    fn command(&self, cmd_type: usize, interval: usize) -> isize {
        let interval = interval as u32;
        self.app_timers[0].get().map(|td| {
            match cmd_type {
                0 /* Oneshot */ => {
                    self.app_timers[0].set(
                            Some(TimerData {
                                t0: self.timer.now(),
                                interval: interval,
                                repeating: false,
                                callback: td.callback
                            })
                    );
                    self.timer.oneshot(interval);
                    0
                },
                1 /* Repeating */ => {
                    self.app_timers[0].set(
                            Some(TimerData {
                                t0: self.timer.now(),
                                interval: interval,
                                repeating: true,
                                callback: td.callback
                            })
                    );
                    self.timer.repeat(interval);
                    0
                },
                _ => -1
            }
        }).unwrap_or(-2)
    }
}

impl<'a, T: Timer> TimerClient for TimerDriver<'a, T> {
    fn fired(&self, now: u32) {
        for mtimer in self.app_timers.iter() {
            mtimer.get().map(|timer| {
                let elapsed = now.wrapping_sub(timer.t0);
                if elapsed >= timer.interval {
                    let mut cb = timer.callback;
                    cb.schedule(now as usize, 0, 0);
                }
            });
        }
    }
}

<|endoftext|>


<commit_before>use super::super::{Y, X, Coord, Grid};
use super::*;

pub struct Field {
    size: i32,
    n_alpha: i32,
    cand: Grid<Cand>,
    value: Grid<Value>,
    clue_front: Vec<Clue>,
    clue_back: Vec<Clue>,
    inconsistent: bool,
    solved: bool,
}

impl Field {
    pub fn new(size: i32, n_alpha: i32) -> Field {
        assert!(n_alpha >= 2);
        Field {
            size,
            n_alpha,
            cand: Grid::new(size, size, Cand((1u32 << n_alpha) - 1)),
            value: Grid::new(size, size, UNDECIDED),
            clue_front: vec![NO_CLUE; (2 * size) as usize],
            clue_back: vec![NO_CLUE; (2 * size) as usize],
            inconsistent: false,
            solved: false,
        }
    }
    pub fn from_problem(problem: &Problem) -> Field {
        let size = problem.size();
        let mut ret = Field::new(size, problem.n_alpha());
        for &loc in &[ClueLoc::Left, ClueLoc::Right, ClueLoc::Top, ClueLoc::Bottom] {
            for i in 0..size {
                let clue = problem.get_clue(loc, i);
                if clue != NO_CLUE {
                    ret.set_clue(loc, i, clue);
                }
            }
        }
        ret
    }
    pub fn get_value(&self, cell: Coord) -> Value {
        self.value[cell]
    }
    pub fn inconsistent(&self) -> bool {
        self.inconsistent
    }
    pub fn get_clue(&self, loc: ClueLoc, idx: i32) -> Clue {
        match loc {
            ClueLoc::Left => self.clue_front[idx as usize],
            ClueLoc::Right => self.clue_back[idx as usize],
            ClueLoc::Top => self.clue_front[(idx + self.size) as usize],
            ClueLoc::Bottom => self.clue_back[(idx + self.size) as usize],
        }
    }
    pub fn set_clue(&mut self, loc: ClueLoc, idx: i32, clue: Clue) {
        let current = self.get_clue(loc, idx);
        if current != NO_CLUE {
            if current != clue {
                self.inconsistent = true;
            }
            return;
        }
        let size = self.size;
        match loc {
            ClueLoc::Left => self.clue_front[idx as usize] = clue,
            ClueLoc::Right => self.clue_back[idx as usize] = clue,
            ClueLoc::Top => self.clue_front[(idx + size) as usize] = clue,
            ClueLoc::Bottom => self.clue_back[(idx + size) as usize] = clue,
        }
        if loc == ClueLoc::Left || loc == ClueLoc::Right {
            self.inspect_row(idx);
        } else {
            self.inspect_row(idx + size);
        }
    }
    pub fn decide(&mut self, cell: Coord, val: Value) {
        let current = self.value[cell];
        if current.0 >= 0 && val == SOME {
            return;
        }
        if current != UNDECIDED && !(current == SOME && val != EMPTY) {
            if current != val {
                self.inconsistent = true;
            }
            return;
        }

        self.value[cell] = val;

        if val == EMPTY {
            self.limit_cand(cell, Cand(0));
        } else if val == SOME {
            self.inspect_cell(cell);
        } else if val != UNDECIDED {
            self.limit_cand(cell, Cand::singleton(val.0));

            let (Y(y), X(x)) = cell;
            let limit = !Cand::singleton(val.0);
            for y2 in 0..self.size {
                if y != y2 { self.limit_cand((Y(y2), X(x)), limit); }
            }
            for x2 in 0..self.size {
                if x != x2 { self.limit_cand((Y(y), X(x2)), limit); }
            }
        }
    }
    /// Returns `pos`-th cell of group `gid`.
    fn group(&self, gid: i32, pos: i32) -> Coord {
        if gid < self.size {
            (Y(gid), X(pos))
        } else {
            (Y(pos), X(gid - self.size))
        }
    }
    /// Returns `pos`-th cell of group `gid` with reversed indexing of cells when `dir` is `true`.
    fn directed_group(&self, gid: i32, pos: i32, dir: bool) -> Coord {
        self.group(gid, if dir { self.size - pos - 1 } else { pos })
    }
    fn limit_cand(&mut self, cell: Coord, lim: Cand) {
        let current_cand = self.cand[cell];

        if (current_cand & lim) == current_cand {
            return;
        }

        let new_cand = current_cand & lim;
        self.cand[cell] = new_cand;

        if self.cand[cell] == Cand(0) {
            self.decide(cell, EMPTY);
        }
        self.inspect_cell(cell);
    }
    fn inspect_cell(&mut self, cell: Coord) {
        if self.value[cell] == SOME && self.cand[cell].count_set_cands() == 1 {
            let val = Value(self.cand[cell].smallest_set_cand());
            self.decide(cell, val);
        }
        let size = self.size;
        let (Y(y), X(x)) = cell;
        self.inspect_row(y);
        self.inspect_row(x + size);
    }
    fn inspect_row(&mut self, group: i32) {
        let size = self.size;
        let n_alpha = self.n_alpha;

        let mut n_some = 0;
        let mut n_empty = 0;

        for i in 0..size {
            let v = self.value[self.group(group, i)];
            if v == EMPTY {
                n_empty += 1;
            } else if v != UNDECIDED {
                n_some += 1;
            }
        }

        if n_some == n_alpha {
            for i in 0..size {
                let c = self.group(group, i);
                if self.value[c] == UNDECIDED {
                    self.decide(c, EMPTY);
                }
            }
        }
        if n_empty == size - n_alpha {
            for i in 0..size {
                let c = self.group(group, i);
                if self.value[c] == UNDECIDED {
                    self.decide(c, SOME);
                }
            }
        }

        for a in 0..n_alpha {
            let mut loc = -1;
            for i in 0..size {
                if self.cand[self.group(group, i)].is_set(a) {
                    if loc == -1 {
                        loc = i;
                    } else {
                        loc = -2;
                        break;
                    }
                }
            }
            if loc == -1 {
                self.inconsistent = true;
                return;
            } else if loc != -2 {
                let c = self.group(group, loc);
                self.decide(c, Value(a));
            }
        }
        for &dir in [true, false].iter() {
            let clue = if !dir { self.clue_front[group as usize] } else { self.clue_back[group as usize] };
            if clue == NO_CLUE {
                continue;
            }

            let mut first_nonempty_id = -1;
            for i in 0..size {
                let v = self.value[self.directed_group(group, i, dir)];
                if v != EMPTY {
                    first_nonempty_id = i;
                    break;
                }
            }
            if first_nonempty_id == -1 {
                self.inconsistent = true;
                return;
            }
            let first_nonempty_cell = self.directed_group(group, first_nonempty_id, dir);
            self.limit_cand(first_nonempty_cell, Cand::singleton(clue.0));

            let mut first_diff_id = -1;
            for i in 0..size {
                let v = self.value[self.directed_group(group, i, dir)];
                if v == SOME && !self.cand[self.directed_group(group, i, dir)].is_set(clue.0) {
                    first_diff_id = i;
                }
            }
            if first_diff_id != -1 {
                for i in (first_diff_id + 1)..size {
                    let c = self.directed_group(group, i, dir);
                    self.limit_cand(c, !Cand::singleton(clue.0));
                }
            }

            let mut n_back_diff = n_alpha - 1;
            for i in 0..size {
                let c = self.directed_group(group, i, !dir);
                let v = self.value[c];
                if v != EMPTY {
                    self.limit_cand(c, !Cand::singleton(clue.0));
                    n_back_diff -= 1;
                    if n_back_diff == 0 { break; }
                }
            }

            let mut mask = Cand((1u32 << n_alpha) - 1) & !Cand::singleton(clue.0);
            for i in 0..size {
                let c = self.directed_group(group, i, !dir);
                self.limit_cand(c, !Cand::singleton(clue.0));
                mask &= !self.cand[c];
                if mask == Cand(0) {
                    break;
                }
            }
        }
    }
    /// Apply *hidden candidate method* to the field.
    /// Note: runs in O*(2^(n_alpha)) and works only if n_alpha < 32.
    pub fn hidden_candidate(&mut self) {
        let size = self.size;
        let n_alpha = self.n_alpha;
        for bits in 1..(1u32 << n_alpha) {
            let mask = Cand(bits);
            for g in 0..(2 * size) {
                let mut n_match = 0;
                for i in 0..size {
                    if self.cand[self.group(g, i)] & mask != Cand(0) {
                        n_match += 1;
                    }
                }
                if n_match < bits.count_ones() {
                    self.inconsistent = true;
                    return;
                } else if n_match == bits.count_ones() {
                    for i in 0..size {
                        let c = self.group(g, i);
                        if self.cand[c] & mask != Cand(0) {
                            self.decide(c, SOME);
                            self.limit_cand(c, mask);
                        }
                    }
                }
            }
        }
    }
    /// Apply *fishy method* (like *X-wing* and *Sword fish* in Sudoku) to the field.
    /// Note: runs in O*(2^size) and works only if size < 32.
    pub fn fishy_method(&mut self) {
        let size = self.size;
        for i in 0..self.n_alpha {
            let mut masks = vec![];
            for y in 0..size {
                let mut mask = 0u32;
                for x in 0..size {
                    if self.cand[(Y(y), X(x))].is_set(i) {
                        mask |= 1u32 << x;
                    }
                }
                masks.push(mask);
            }
            for bits in 1..(1u32 << size) {
                let mut ors = 0u32;
                for y in 0..size {
                    if (bits & (1u32 << y)) != 0 {
                        ors |= masks[y as usize];
                    }
                }
                if bits.count_ones() > ors.count_ones() {
                    self.inconsistent = true;
                    return;
                } else if bits.count_ones() == ors.count_ones() {
                    for y in 0..size {
                        if (bits & (1u32 << y)) == 0 {
                            masks[y as usize] &= !ors;
                        }
                    }
                }
            }
            for y in 0..size {
                for x in 0..size {
                    if (masks[y as usize] & (1u32 << x)) == 0 {
                        self.limit_cand((Y(y), X(x)), !Cand::singleton(i));
                    }
                }
            }
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_deduction() {
        {
            // a symbol shouldn't occur more than once in a row / a column
            let mut field = Field::new(5, 3);

            assert_eq!(field.cand[(Y(0), X(0))], Cand(7));
            assert_eq!(field.cand[(Y(0), X(1))], Cand(7));
            assert_eq!(field.cand[(Y(1), X(1))], Cand(7));

            field.decide((Y(0), X(0)), Value(0));

            assert_eq!(field.inconsistent, false);
            assert_eq!(field.cand[(Y(0), X(0))], Cand(1));
            assert_eq!(field.cand[(Y(0), X(1))], Cand(6));
            assert_eq!(field.cand[(Y(1), X(0))], Cand(6));
            assert_eq!(field.cand[(Y(1), X(1))], Cand(7));
        }
        {
            // there must be exactly `n_alpha` symbols in a row / a column
            let mut field = Field::new(5, 3);

            field.decide((Y(1), X(0)), SOME);
            field.decide((Y(1), X(1)), SOME);
            field.decide((Y(1), X(2)), SOME);

            assert_eq!(field.inconsistent, false);
            assert_eq!(field.value[(Y(1), X(3))], EMPTY);
        }
        {
            // there must be exactly `n_alpha` symbols in a row / a column
            let mut field = Field::new(5, 3);

            field.decide((Y(3), X(2)), EMPTY);
            field.decide((Y(4), X(2)), EMPTY);

            assert_eq!(field.inconsistent, false);
            assert_eq!(field.value[(Y(1), X(2))], SOME);
        }
        {
            let mut field = Field::new(5, 3);

            field.limit_cand((Y(0), X(2)), Cand(5));
            field.limit_cand((Y(2), X(2)), Cand(5));
            field.limit_cand((Y(3), X(2)), Cand(5));
            field.limit_cand((Y(4), X(2)), Cand(5));

            assert_eq!(field.inconsistent, false);
            assert_eq!(field.value[(Y(1), X(2))], Value(1));
            assert_eq!(field.cand[(Y(1), X(3))], Cand(5));
        }
    }

    #[test]
    fn test_clue() {
        {
            let mut field = Field::new(5, 3);

            field.set_clue(ClueLoc::Left, 0, Clue(0));

            assert_eq!(field.cand[(Y(0), X(0))], Cand(1));
            assert_eq!(field.cand[(Y(0), X(3))], Cand(6));
            assert_eq!(field.cand[(Y(0), X(4))], Cand(6));
        }
    }

    #[test]
    fn test_problem() {
        {
            let mut problem = Problem::new(5, 3);
            problem.set_clue(ClueLoc::Top, 1, Clue(1));

            let field = Field::from_problem(&problem);

            assert_eq!(field.cand[(Y(0), X(1))], Cand(2));
            assert_eq!(field.cand[(Y(4), X(1))], Cand(5));
        }
    }
}
<commit_msg>Endview: add total_cands<commit_after>use super::super::{Y, X, Coord, Grid};
use super::*;

pub struct Field {
    size: i32,
    n_alpha: i32,
    cand: Grid<Cand>,
    value: Grid<Value>,
    clue_front: Vec<Clue>,
    clue_back: Vec<Clue>,
    total_cands: i32,
    inconsistent: bool,
}

impl Field {
    pub fn new(size: i32, n_alpha: i32) -> Field {
        assert!(n_alpha >= 2);
        Field {
            size,
            n_alpha,
            cand: Grid::new(size, size, Cand((1u32 << n_alpha) - 1)),
            value: Grid::new(size, size, UNDECIDED),
            clue_front: vec![NO_CLUE; (2 * size) as usize],
            clue_back: vec![NO_CLUE; (2 * size) as usize],
            total_cands: size * size * (n_alpha + 1),
            inconsistent: false,
        }
    }
    pub fn from_problem(problem: &Problem) -> Field {
        let size = problem.size();
        let mut ret = Field::new(size, problem.n_alpha());
        for &loc in &[ClueLoc::Left, ClueLoc::Right, ClueLoc::Top, ClueLoc::Bottom] {
            for i in 0..size {
                let clue = problem.get_clue(loc, i);
                if clue != NO_CLUE {
                    ret.set_clue(loc, i, clue);
                }
            }
        }
        ret
    }
    pub fn get_value(&self, cell: Coord) -> Value {
        self.value[cell]
    }
    pub fn inconsistent(&self) -> bool {
        self.inconsistent
    }
    pub fn total_cands(&self) -> i32 {
        self.total_cands
    }
    pub fn is_solved(&self) -> bool {
        self.total_cands == self.size * self.n_alpha
    }
    pub fn get_clue(&self, loc: ClueLoc, idx: i32) -> Clue {
        match loc {
            ClueLoc::Left => self.clue_front[idx as usize],
            ClueLoc::Right => self.clue_back[idx as usize],
            ClueLoc::Top => self.clue_front[(idx + self.size) as usize],
            ClueLoc::Bottom => self.clue_back[(idx + self.size) as usize],
        }
    }
    pub fn set_clue(&mut self, loc: ClueLoc, idx: i32, clue: Clue) {
        let current = self.get_clue(loc, idx);
        if current != NO_CLUE {
            if current != clue {
                self.inconsistent = true;
            }
            return;
        }
        let size = self.size;
        match loc {
            ClueLoc::Left => self.clue_front[idx as usize] = clue,
            ClueLoc::Right => self.clue_back[idx as usize] = clue,
            ClueLoc::Top => self.clue_front[(idx + size) as usize] = clue,
            ClueLoc::Bottom => self.clue_back[(idx + size) as usize] = clue,
        }
        if loc == ClueLoc::Left || loc == ClueLoc::Right {
            self.inspect_row(idx);
        } else {
            self.inspect_row(idx + size);
        }
    }
    pub fn decide(&mut self, cell: Coord, val: Value) {
        let current = self.value[cell];
        if current.0 >= 0 && val == SOME {
            return;
        }
        if current != UNDECIDED && !(current == SOME && val != EMPTY) {
            if current != val {
                self.inconsistent = true;
            }
            return;
        }
        if current == UNDECIDED {
            if val == UNDECIDED { return; }
            self.total_cands -= 1;
        }

        self.value[cell] = val;

        if val == EMPTY {
            self.limit_cand(cell, Cand(0));
        } else if val == SOME {
            self.inspect_cell(cell);
        } else if val != UNDECIDED {
            self.limit_cand(cell, Cand::singleton(val.0));

            let (Y(y), X(x)) = cell;
            let limit = !Cand::singleton(val.0);
            for y2 in 0..self.size {
                if y != y2 { self.limit_cand((Y(y2), X(x)), limit); }
            }
            for x2 in 0..self.size {
                if x != x2 { self.limit_cand((Y(y), X(x2)), limit); }
            }
        }
    }
    /// Returns `pos`-th cell of group `gid`.
    fn group(&self, gid: i32, pos: i32) -> Coord {
        if gid < self.size {
            (Y(gid), X(pos))
        } else {
            (Y(pos), X(gid - self.size))
        }
    }
    /// Returns `pos`-th cell of group `gid` with reversed indexing of cells when `dir` is `true`.
    fn directed_group(&self, gid: i32, pos: i32, dir: bool) -> Coord {
        self.group(gid, if dir { self.size - pos - 1 } else { pos })
    }
    fn limit_cand(&mut self, cell: Coord, lim: Cand) {
        let current_cand = self.cand[cell];

        if (current_cand & lim) == current_cand {
            return;
        }

        let new_cand = current_cand & lim;
        self.cand[cell] = new_cand;
        self.total_cands -= (current_cand.0.count_ones() - new_cand.0.count_ones()) as i32;

        if self.cand[cell] == Cand(0) {
            self.decide(cell, EMPTY);
        }
        self.inspect_cell(cell);
    }
    fn inspect_cell(&mut self, cell: Coord) {
        if self.value[cell] == SOME && self.cand[cell].count_set_cands() == 1 {
            let val = Value(self.cand[cell].smallest_set_cand());
            self.decide(cell, val);
        }
        let size = self.size;
        let (Y(y), X(x)) = cell;
        self.inspect_row(y);
        self.inspect_row(x + size);
    }
    fn inspect_row(&mut self, group: i32) {
        let size = self.size;
        let n_alpha = self.n_alpha;

        let mut n_some = 0;
        let mut n_empty = 0;

        for i in 0..size {
            let v = self.value[self.group(group, i)];
            if v == EMPTY {
                n_empty += 1;
            } else if v != UNDECIDED {
                n_some += 1;
            }
        }

        if n_some == n_alpha {
            for i in 0..size {
                let c = self.group(group, i);
                if self.value[c] == UNDECIDED {
                    self.decide(c, EMPTY);
                }
            }
        }
        if n_empty == size - n_alpha {
            for i in 0..size {
                let c = self.group(group, i);
                if self.value[c] == UNDECIDED {
                    self.decide(c, SOME);
                }
            }
        }

        for a in 0..n_alpha {
            let mut loc = -1;
            for i in 0..size {
                if self.cand[self.group(group, i)].is_set(a) {
                    if loc == -1 {
                        loc = i;
                    } else {
                        loc = -2;
                        break;
                    }
                }
            }
            if loc == -1 {
                self.inconsistent = true;
                return;
            } else if loc != -2 {
                let c = self.group(group, loc);
                self.decide(c, Value(a));
            }
        }
        for &dir in [true, false].iter() {
            let clue = if !dir { self.clue_front[group as usize] } else { self.clue_back[group as usize] };
            if clue == NO_CLUE {
                continue;
            }

            let mut first_nonempty_id = -1;
            for i in 0..size {
                let v = self.value[self.directed_group(group, i, dir)];
                if v != EMPTY {
                    first_nonempty_id = i;
                    break;
                }
            }
            if first_nonempty_id == -1 {
                self.inconsistent = true;
                return;
            }
            let first_nonempty_cell = self.directed_group(group, first_nonempty_id, dir);
            self.limit_cand(first_nonempty_cell, Cand::singleton(clue.0));

            let mut first_diff_id = -1;
            for i in 0..size {
                let v = self.value[self.directed_group(group, i, dir)];
                if v == SOME && !self.cand[self.directed_group(group, i, dir)].is_set(clue.0) {
                    first_diff_id = i;
                }
            }
            if first_diff_id != -1 {
                for i in (first_diff_id + 1)..size {
                    let c = self.directed_group(group, i, dir);
                    self.limit_cand(c, !Cand::singleton(clue.0));
                }
            }

            let mut n_back_diff = n_alpha - 1;
            for i in 0..size {
                let c = self.directed_group(group, i, !dir);
                let v = self.value[c];
                if v != EMPTY {
                    self.limit_cand(c, !Cand::singleton(clue.0));
                    n_back_diff -= 1;
                    if n_back_diff == 0 { break; }
                }
            }

            let mut mask = Cand((1u32 << n_alpha) - 1) & !Cand::singleton(clue.0);
            for i in 0..size {
                let c = self.directed_group(group, i, !dir);
                self.limit_cand(c, !Cand::singleton(clue.0));
                mask &= !self.cand[c];
                if mask == Cand(0) {
                    break;
                }
            }
        }
    }
    /// Apply *hidden candidate method* to the field.
    /// Note: runs in O*(2^(n_alpha)) and works only if n_alpha < 32.
    pub fn hidden_candidate(&mut self) {
        let size = self.size;
        let n_alpha = self.n_alpha;
        for bits in 1..(1u32 << n_alpha) {
            let mask = Cand(bits);
            for g in 0..(2 * size) {
                let mut n_match = 0;
                for i in 0..size {
                    if self.cand[self.group(g, i)] & mask != Cand(0) {
                        n_match += 1;
                    }
                }
                if n_match < bits.count_ones() {
                    self.inconsistent = true;
                    return;
                } else if n_match == bits.count_ones() {
                    for i in 0..size {
                        let c = self.group(g, i);
                        if self.cand[c] & mask != Cand(0) {
                            self.decide(c, SOME);
                            self.limit_cand(c, mask);
                        }
                    }
                }
            }
        }
    }
    /// Apply *fishy method* (like *X-wing* and *Sword fish* in Sudoku) to the field.
    /// Note: runs in O*(2^size) and works only if size < 32.
    pub fn fishy_method(&mut self) {
        let size = self.size;
        for i in 0..self.n_alpha {
            let mut masks = vec![];
            for y in 0..size {
                let mut mask = 0u32;
                for x in 0..size {
                    if self.cand[(Y(y), X(x))].is_set(i) {
                        mask |= 1u32 << x;
                    }
                }
                masks.push(mask);
            }
            for bits in 1..(1u32 << size) {
                let mut ors = 0u32;
                for y in 0..size {
                    if (bits & (1u32 << y)) != 0 {
                        ors |= masks[y as usize];
                    }
                }
                if bits.count_ones() > ors.count_ones() {
                    self.inconsistent = true;
                    return;
                } else if bits.count_ones() == ors.count_ones() {
                    for y in 0..size {
                        if (bits & (1u32 << y)) == 0 {
                            masks[y as usize] &= !ors;
                        }
                    }
                }
            }
            for y in 0..size {
                for x in 0..size {
                    if (masks[y as usize] & (1u32 << x)) == 0 {
                        self.limit_cand((Y(y), X(x)), !Cand::singleton(i));
                    }
                }
            }
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_deduction() {
        {
            // a symbol shouldn't occur more than once in a row / a column
            let mut field = Field::new(5, 3);

            assert_eq!(field.cand[(Y(0), X(0))], Cand(7));
            assert_eq!(field.cand[(Y(0), X(1))], Cand(7));
            assert_eq!(field.cand[(Y(1), X(1))], Cand(7));

            field.decide((Y(0), X(0)), Value(0));

            assert_eq!(field.inconsistent, false);
            assert_eq!(field.cand[(Y(0), X(0))], Cand(1));
            assert_eq!(field.cand[(Y(0), X(1))], Cand(6));
            assert_eq!(field.cand[(Y(1), X(0))], Cand(6));
            assert_eq!(field.cand[(Y(1), X(1))], Cand(7));
        }
        {
            // there must be exactly `n_alpha` symbols in a row / a column
            let mut field = Field::new(5, 3);

            field.decide((Y(1), X(0)), SOME);
            field.decide((Y(1), X(1)), SOME);
            field.decide((Y(1), X(2)), SOME);

            assert_eq!(field.inconsistent, false);
            assert_eq!(field.value[(Y(1), X(3))], EMPTY);
        }
        {
            // there must be exactly `n_alpha` symbols in a row / a column
            let mut field = Field::new(5, 3);

            field.decide((Y(3), X(2)), EMPTY);
            field.decide((Y(4), X(2)), EMPTY);

            assert_eq!(field.inconsistent, false);
            assert_eq!(field.value[(Y(1), X(2))], SOME);
        }
        {
            let mut field = Field::new(5, 3);

            field.limit_cand((Y(0), X(2)), Cand(5));
            field.limit_cand((Y(2), X(2)), Cand(5));
            field.limit_cand((Y(3), X(2)), Cand(5));
            field.limit_cand((Y(4), X(2)), Cand(5));

            assert_eq!(field.inconsistent, false);
            assert_eq!(field.value[(Y(1), X(2))], Value(1));
            assert_eq!(field.cand[(Y(1), X(3))], Cand(5));
        }
    }

    #[test]
    fn test_clue() {
        {
            let mut field = Field::new(5, 3);

            field.set_clue(ClueLoc::Left, 0, Clue(0));

            assert_eq!(field.cand[(Y(0), X(0))], Cand(1));
            assert_eq!(field.cand[(Y(0), X(3))], Cand(6));
            assert_eq!(field.cand[(Y(0), X(4))], Cand(6));
        }
    }

    #[test]
    fn test_problem() {
        {
            let mut problem = Problem::new(5, 3);
            problem.set_clue(ClueLoc::Top, 1, Clue(1));

            let field = Field::from_problem(&problem);

            assert_eq!(field.cand[(Y(0), X(1))], Cand(2));
            assert_eq!(field.cand[(Y(4), X(1))], Cand(5));
        }
    }
}
<|endoftext|>