<commit_before>use std::cell::RefCell;
use std::cmp;
use std::io;
use std::net::{Ipv4Addr, SocketAddr};
use std::rc::{Rc, Weak};
use log::LogLevel;
use mio::{Event, PollOpt, Ready, Token};
use mio::net::TcpStream;

use super::binary;
use super::client::Client;
use super::connection::{self, Connection, ConnectionId};
use super::ipv4_header::IPv4Header;
use super::ipv4_packet::{IPv4Packet, MAX_PACKET_LENGTH};
use super::packetizer::Packetizer;
use super::selector::Selector;
use super::stream_buffer::StreamBuffer;
use super::tcp_header::{self, TCPHeader};
use super::transport_header::{TransportHeader, TransportHeaderMut};

const TAG: &'static str = "TCPConnection";

const MAX_PAYLOAD_LENGTH: u16 = 1400;

#[derive(PartialEq, Eq)]
enum TCPState {
    Init,
    SynSent,
//    SynReceived,
    Established,
    CloseWait,
    LastAck,
}

struct TCPConnection {
    id: ConnectionId,
    client: Weak<RefCell<Client>>,
    stream: TcpStream,
    token: Token,
    client_to_network: StreamBuffer,
    network_to_client: Packetizer,
    packet_for_client_length: Option<u16>,
    closed: bool,
    state: TCPState,
    syn_sequence_number: u32,
    sequence_number: u32,
    acknowledgement_number: u32,
    their_acknowledgement_number: u32,
    client_window: u16,
    remote_closed: bool,
}

impl TCPConnection {
    pub fn new(selector: &mut Selector, id: ConnectionId, client: Weak<RefCell<Client>>, ipv4_header: &IPv4Header, transport_header: &TransportHeader) -> io::Result<Rc<RefCell<Self>>> {
        let stream = TCPConnection::create_stream(&id)?;

        if let TransportHeader::TCP(ref tcp_header) = *transport_header {
            // shrink the TCP options to pass a minimal refrence header to the packetizer
            let mut shrinked_tcp_header_raw = [0u8; 20];
            shrinked_tcp_header_raw.copy_from_slice(&tcp_header.raw()[..20]);
            let mut shrinked_tcp_header_data = tcp_header.data().clone();
            {
                let mut shrinked_tcp_header = shrinked_tcp_header_data.bind_mut(&mut shrinked_tcp_header_raw);
                shrinked_tcp_header.shrink_options();
                assert_eq!(20, shrinked_tcp_header.header_length());
            }

            let shrinked_transport_header = shrinked_tcp_header_data.bind(&shrinked_tcp_header_raw).into();

            let packetizer = Packetizer::new(&ipv4_header, &shrinked_transport_header);

            let rc = Rc::new(RefCell::new(Self {
                id: id,
                client: client,
                stream: stream,
                token: Token(0), // default value, will be set afterwards
                client_to_network: StreamBuffer::new(4 * MAX_PACKET_LENGTH),
                network_to_client: packetizer,
                packet_for_client_length: None,
                closed: false,
                state: TCPState::Init,
                syn_sequence_number: 0,
                sequence_number: 0,
                acknowledgement_number: 0,
                their_acknowledgement_number: 0,
                client_window: 0,
                remote_closed: false,
            }));

            {
                let rc_clone = rc.clone();
                let handler = move |selector: &mut Selector, ready| {
                    let mut self_ref = rc_clone.borrow_mut();
                    self_ref.on_ready(selector, ready);
                };
                let mut self_ref = rc.borrow_mut();
                let token = selector.register(&self_ref.stream, handler, Ready::readable(), PollOpt::level())?;
                self_ref.token = token;
            }
            Ok(rc)
        } else {
            panic!("Not a TCP header");
        }
    }

    fn create_stream(id: &ConnectionId) -> io::Result<TcpStream> {
        let rewritten_destination = connection::rewritten_destination(id.destination_ip(), id.destination_port()).into();
        TcpStream::connect(&rewritten_destination)
    }

    fn close(&mut self, selector: &mut Selector) {

    }

    fn process_send(&mut self, selector: &mut Selector) {
        match self.client_to_network.write_to(&mut self.stream) {
            Ok(w) => if w == 0 {
                self.close(selector);
            },
            Err(err) => {
                error!(target: TAG, "{} Cannot write: {}", self.id, err);
                self.reset_connection(selector);
            }
        }
    }

    fn process_receive(&mut self, selector: &mut Selector) {
        assert!(self.packet_for_client_length.is_none(), "A pending packet was not sent");
        let remaining_client_window = self.get_remaining_client_window();
        assert!(remaining_client_window > 0, "process_received() must not be called when window == 0");
        let max_payload_length = cmp::min(remaining_client_window, MAX_PAYLOAD_LENGTH) as usize;
        self.update_headers(tcp_header::FLAG_ACK | tcp_header::FLAG_PSH);
        // the packet is bound to the lifetime of self, so we cannot borrow self to call methods
        // defer the other branches in a separate match-block
        let non_lexical_lifetime_workaround = match self.network_to_client.packetize_read(&mut self.stream, Some(max_payload_length)) {
            Ok(Some(ipv4_packet)) => {
                // TODO send packet
                Ok(Some(()))
            },
            Ok(None) => Ok(None),
            Err(err) => Err(err),
        };
        match non_lexical_lifetime_workaround {
            Ok(None) => self.eof(selector),
            Err(err) => {
                error!(target: TAG, "{} Cannot read: {}", self.id, err);
                self.reset_connection(selector);
            },
            Ok(Some(_)) => () // already handled
        }
        // TODO
    }

    fn eof(&mut self, selector: &mut Selector) {
        self.remote_closed = true;
        if self.state == TCPState::CloseWait {
            let id = self.id;
            let ipv4_packet = self.create_empty_response_packet(tcp_header::FLAG_FIN);
            self.sequence_number += 1; // FIN counts for 1 byte

            let client_rc = self.client.upgrade().expect("expected client not found");
            if let Err(err) = client_rc.borrow_mut().send_to_client(selector, &ipv4_packet) {
                warn!(target: TAG, "{} Cannot send packet to client: {}", id, err);
            }
        }
    }

    fn update_headers(&mut self, flags: u16) {
        if let TransportHeaderMut::TCP(ref mut tcp_header) = self.network_to_client.transport_header_mut() {
            tcp_header.set_flags(flags);
            tcp_header.set_sequence_number(self.sequence_number);
            tcp_header.set_acknowledgement_number(self.acknowledgement_number);
        } else {
            panic!("Not a TCP header");
        }
    }

    fn create_empty_response_packet(&mut self, flags: u16) -> IPv4Packet {
        self.update_headers(flags);
        debug!(target: TAG, "{} Forging empty response (flags={}) {}", self.id, flags, self.numbers());
        if (flags & tcp_header::FLAG_ACK) != 0 {
            debug!(target: TAG, "{} Acking {}", self.id, self.numbers());
        }
        let ipv4_packet = self.network_to_client.packetize_empty_payload();
        if log_enabled!(target: TAG, LogLevel::Trace) {
            binary::to_string(ipv4_packet.raw());
        }
        ipv4_packet
    }

    fn reset_connection(&mut self, selector: &mut Selector) {
        // TODO
    }

    fn update_interests(&mut self, selector: &mut Selector) {
        if !self.closed {
            let mut ready = Ready::empty();
            if self.may_read() {
                ready = ready | Ready::readable()
            }
            if self.may_write() {
                ready = ready | Ready::writable()
            }
            selector.reregister(&self.stream, self.token, ready, PollOpt::level()).expect("Cannot register on poll");
        }
    }

    fn may_read(&self) -> bool {
        !self.remote_closed &&
                self.packet_for_client_length.is_some() &&
                self.get_remaining_client_window() > 0
    }

    fn may_write(&self) -> bool {
        !self.client_to_network.is_empty()
    }

    fn on_ready(&mut self, selector: &mut Selector, event: Event) {
        assert!(!self.closed);
        let ready = event.readiness();
        if ready.is_writable() {
            self.process_send(selector);
        }
        if !self.closed && ready.is_readable() {
            self.process_receive(selector);
        }
        if !self.closed {
            self.update_interests(selector);
        }
    }

    fn get_remaining_client_window(&self) -> u16 {
        // TODO
        42
    }

    fn numbers(&self) -> String {
        format!("(seq={}, ack={})", self.sequence_number, self.acknowledgement_number)
    }
}

impl Connection for TCPConnection {
    fn id(&self) -> &ConnectionId {
        &self.id
    }

    fn send_to_network(&mut self, selector: &mut Selector, ipv4_packet: &IPv4Packet) {
        // TODO
    }

    fn disconnect(&mut self, selector: &mut Selector) {
        info!(target: TAG, "{} Close", self.id);
        selector.deregister(&self.stream, self.token).unwrap();
        // socket will be closed by RAII
    }

    fn is_expired(&self) -> bool {
        // no external timeout expiration
        false
    }
}
<commit_msg>Refactor functions not to mutably borrow self<commit_after>use std::cell::RefCell;
use std::cmp;
use std::io;
use std::net::{Ipv4Addr, SocketAddr};
use std::rc::{Rc, Weak};
use log::LogLevel;
use mio::{Event, PollOpt, Ready, Token};
use mio::net::TcpStream;

use super::binary;
use super::client::Client;
use super::connection::{self, Connection, ConnectionId};
use super::ipv4_header::IPv4Header;
use super::ipv4_packet::{IPv4Packet, MAX_PACKET_LENGTH};
use super::packetizer::Packetizer;
use super::selector::Selector;
use super::stream_buffer::StreamBuffer;
use super::tcp_header::{self, TCPHeader};
use super::transport_header::{TransportHeader, TransportHeaderMut};

const TAG: &'static str = "TCPConnection";

const MAX_PAYLOAD_LENGTH: u16 = 1400;

#[derive(PartialEq, Eq)]
enum TCPState {
    Init,
    SynSent,
//    SynReceived,
    Established,
    CloseWait,
    LastAck,
}

struct TCPConnection {
    id: ConnectionId,
    client: Weak<RefCell<Client>>,
    stream: TcpStream,
    token: Token,
    client_to_network: StreamBuffer,
    network_to_client: Packetizer,
    packet_for_client_length: Option<u16>,
    closed: bool,
    state: TCPState,
    syn_sequence_number: u32,
    sequence_number: u32,
    acknowledgement_number: u32,
    their_acknowledgement_number: u32,
    client_window: u16,
    remote_closed: bool,
}

impl TCPConnection {
    pub fn new(selector: &mut Selector, id: ConnectionId, client: Weak<RefCell<Client>>, ipv4_header: &IPv4Header, transport_header: &TransportHeader) -> io::Result<Rc<RefCell<Self>>> {
        let stream = TCPConnection::create_stream(&id)?;

        if let TransportHeader::TCP(ref tcp_header) = *transport_header {
            // shrink the TCP options to pass a minimal refrence header to the packetizer
            let mut shrinked_tcp_header_raw = [0u8; 20];
            shrinked_tcp_header_raw.copy_from_slice(&tcp_header.raw()[..20]);
            let mut shrinked_tcp_header_data = tcp_header.data().clone();
            {
                let mut shrinked_tcp_header = shrinked_tcp_header_data.bind_mut(&mut shrinked_tcp_header_raw);
                shrinked_tcp_header.shrink_options();
                assert_eq!(20, shrinked_tcp_header.header_length());
            }

            let shrinked_transport_header = shrinked_tcp_header_data.bind(&shrinked_tcp_header_raw).into();

            let packetizer = Packetizer::new(&ipv4_header, &shrinked_transport_header);

            let rc = Rc::new(RefCell::new(Self {
                id: id,
                client: client,
                stream: stream,
                token: Token(0), // default value, will be set afterwards
                client_to_network: StreamBuffer::new(4 * MAX_PACKET_LENGTH),
                network_to_client: packetizer,
                packet_for_client_length: None,
                closed: false,
                state: TCPState::Init,
                syn_sequence_number: 0,
                sequence_number: 0,
                acknowledgement_number: 0,
                their_acknowledgement_number: 0,
                client_window: 0,
                remote_closed: false,
            }));

            {
                let rc_clone = rc.clone();
                let handler = move |selector: &mut Selector, ready| {
                    let mut self_ref = rc_clone.borrow_mut();
                    self_ref.on_ready(selector, ready);
                };
                let mut self_ref = rc.borrow_mut();
                let token = selector.register(&self_ref.stream, handler, Ready::readable(), PollOpt::level())?;
                self_ref.token = token;
            }
            Ok(rc)
        } else {
            panic!("Not a TCP header");
        }
    }

    fn create_stream(id: &ConnectionId) -> io::Result<TcpStream> {
        let rewritten_destination = connection::rewritten_destination(id.destination_ip(), id.destination_port()).into();
        TcpStream::connect(&rewritten_destination)
    }

    fn close(&mut self, selector: &mut Selector) {

    }

    fn process_send(&mut self, selector: &mut Selector) {
        match self.client_to_network.write_to(&mut self.stream) {
            Ok(w) => if w == 0 {
                self.close(selector);
            },
            Err(err) => {
                error!(target: TAG, "{} Cannot write: {}", self.id, err);
                self.reset_connection(selector);
            }
        }
    }

    fn process_receive(&mut self, selector: &mut Selector) {
        assert!(self.packet_for_client_length.is_none(), "A pending packet was not sent");
        let remaining_client_window = self.get_remaining_client_window();
        assert!(remaining_client_window > 0, "process_received() must not be called when window == 0");
        let max_payload_length = cmp::min(remaining_client_window, MAX_PAYLOAD_LENGTH) as usize;
        TCPConnection::update_headers(&mut self.network_to_client, self.sequence_number, self.acknowledgement_number, tcp_header::FLAG_ACK | tcp_header::FLAG_PSH);
        // the packet is bound to the lifetime of self, so we cannot borrow self to call methods
        // defer the other branches in a separate match-block
        let non_lexical_lifetime_workaround = match self.network_to_client.packetize_read(&mut self.stream, Some(max_payload_length)) {
            Ok(Some(ipv4_packet)) => {
                // TODO send packet
                Ok(Some(()))
            },
            Ok(None) => Ok(None),
            Err(err) => Err(err),
        };
        match non_lexical_lifetime_workaround {
            Ok(None) => self.eof(selector),
            Err(err) => {
                error!(target: TAG, "{} Cannot read: {}", self.id, err);
                self.reset_connection(selector);
            },
            Ok(Some(_)) => () // already handled
        }
        // TODO
    }

    fn eof(&mut self, selector: &mut Selector) {
        self.remote_closed = true;
        if self.state == TCPState::CloseWait {
            let ipv4_packet = TCPConnection::create_empty_response_packet(&self.id, &mut self.network_to_client, self.sequence_number, self.acknowledgement_number, tcp_header::FLAG_FIN);
            self.sequence_number += 1; // FIN counts for 1 byte

            let client_rc = self.client.upgrade().expect("expected client not found");
            let mut client = client_rc.borrow_mut();
            if let Err(err) = client.send_to_client(selector, &ipv4_packet) {
                warn!(target: TAG, "{} Cannot send packet to client: {}", &self.id, err);
            }
        }
    }

    fn update_headers(packetizer: &mut Packetizer, sequence_number: u32, acknowledgement_number: u32, flags: u16) {
        if let TransportHeaderMut::TCP(ref mut tcp_header) = packetizer.transport_header_mut() {
            tcp_header.set_sequence_number(sequence_number);
            tcp_header.set_acknowledgement_number(acknowledgement_number);
            tcp_header.set_flags(flags);
        } else {
            panic!("Not a TCP header");
        }
    }

    fn create_empty_response_packet<'a>(id: &ConnectionId, packetizer: &'a mut Packetizer, sequence_number: u32, acknowledgement_number: u32, flags: u16) -> IPv4Packet<'a> {
        TCPConnection::update_headers(packetizer, sequence_number, acknowledgement_number, flags);
        debug!(target: TAG, "{} Forging empty response (flags={}) {}", id, flags, "TODO");
        if (flags & tcp_header::FLAG_ACK) != 0 {
            debug!(target: TAG, "{} Acking {}", id, "TODO");
        }
        let ipv4_packet = packetizer.packetize_empty_payload();
        if log_enabled!(target: TAG, LogLevel::Trace) {
            binary::to_string(ipv4_packet.raw());
        }
        ipv4_packet
    }

    fn reset_connection(&mut self, selector: &mut Selector) {
        // TODO
    }

    fn update_interests(&mut self, selector: &mut Selector) {
        if !self.closed {
            let mut ready = Ready::empty();
            if self.may_read() {
                ready = ready | Ready::readable()
            }
            if self.may_write() {
                ready = ready | Ready::writable()
            }
            selector.reregister(&self.stream, self.token, ready, PollOpt::level()).expect("Cannot register on poll");
        }
    }

    fn may_read(&self) -> bool {
        !self.remote_closed &&
                self.packet_for_client_length.is_some() &&
                self.get_remaining_client_window() > 0
    }

    fn may_write(&self) -> bool {
        !self.client_to_network.is_empty()
    }

    fn on_ready(&mut self, selector: &mut Selector, event: Event) {
        assert!(!self.closed);
        let ready = event.readiness();
        if ready.is_writable() {
            self.process_send(selector);
        }
        if !self.closed && ready.is_readable() {
            self.process_receive(selector);
        }
        if !self.closed {
            self.update_interests(selector);
        }
    }

    fn get_remaining_client_window(&self) -> u16 {
        // TODO
        42
    }

    fn numbers(&self) -> String {
        format!("(seq={}, ack={})", self.sequence_number, self.acknowledgement_number)
    }
}

impl Connection for TCPConnection {
    fn id(&self) -> &ConnectionId {
        &self.id
    }

    fn send_to_network(&mut self, selector: &mut Selector, ipv4_packet: &IPv4Packet) {
        // TODO
    }

    fn disconnect(&mut self, selector: &mut Selector) {
        info!(target: TAG, "{} Close", self.id);
        selector.deregister(&self.stream, self.token).unwrap();
        // socket will be closed by RAII
    }

    fn is_expired(&self) -> bool {
        // no external timeout expiration
        false
    }
}
<|endoftext|>


<commit_before>// 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.

#![allow(missing_docs)]

use std::sync::{Arc, Mutex, MutexGuard};
use time::{get_time, Timespec};
use utils::EWMA;

const WINDOW: [f64; 3] = [1.0, 5.0, 15.0];

// A MeterSnapshot
#[derive(Debug)]
pub struct MeterSnapshot {
    pub count: i64,
    pub rates: [f64; 3],
    pub mean: f64,
}

#[derive(Debug)]
struct StdMeterData {
    count: i64,
    rates: [f64; 3],
    mean: f64,
    ewma: [EWMA; 3],
}

// A StdMeter struct
#[derive(Debug)]
pub struct StdMeter {
    data: Mutex<StdMeterData>,
    start: Timespec,
}

// A Meter trait
pub trait Meter {
    fn snapshot(&self) -> MeterSnapshot;

    fn mark(&self, n: i64);

    fn tick(&self);

    fn rate(&self, rate: f64) -> f64;

    fn mean(&self) -> f64;

    fn count(&self) -> i64;
}

impl Meter for StdMeter {
    fn snapshot(&self) -> MeterSnapshot {
        let s = self.data.lock().unwrap();

        MeterSnapshot {
            count: s.count,
            rates: s.rates,
            mean: s.mean,
        }
    }

    fn mark(&self, n: i64) {
        let mut s = self.data.lock().unwrap();

        s.count += n;

        for i in 0..WINDOW.len() {
            s.ewma[i].update(n as usize);
        }

        self.update_data(s);
    }

    fn tick(&self) {
        let mut s = self.data.lock().unwrap();

        for i in 0..WINDOW.len() {
            s.ewma[i].tick();
        }

        self.update_data(s);
    }

    /// Return the given EWMA for a rate like 1, 5, 15 minutes
    fn rate(&self, rate: f64) -> f64 {
        let s = self.data.lock().unwrap();

        if let Some(pos) = WINDOW.iter().position(|w| *w == rate) {
            return s.rates[pos];
        }
        0.0
    }
    /// Return the mean rate
    fn mean(&self) -> f64 {
        let s = self.data.lock().unwrap();

        s.mean
    }

    fn count(&self) -> i64 {
        let s = self.data.lock().unwrap();

        s.count
    }
}

impl StdMeter {
    fn update_data(&self, mut s: MutexGuard<StdMeterData>) {
        for i in 0..WINDOW.len() {
            s.rates[i] = s.ewma[i].rate();
        }

        let diff = get_time() - self.start;
        s.mean = s.count as f64 / diff.num_seconds() as f64;
    }

    pub fn new() -> Arc<Self> {
        Arc::new(StdMeter {
            data: Mutex::new(StdMeterData {
                count: 0,
                rates: [0.0, 0.0, 0.0],
                mean: 0.0,
                ewma: [EWMA::new(1.0), EWMA::new(5.0), EWMA::new(15.0)],
            }),
            start: get_time(),
        })
    }
}

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

    #[test]
    fn zero() {
        let m = StdMeter::new();
        let s = m.snapshot();

        assert_eq!(s.count, 0);
    }

    #[test]
    fn non_zero() {
        let m = StdMeter::new();
        m.mark(3);

        let s = m.snapshot();

        assert_eq!(s.count, 3);
    }

    #[test]
    fn snapshot() {
        let m = StdMeter::new();
        m.mark(1);
        m.mark(1);

        let s = m.snapshot();

        m.mark(1);

        assert_eq!(s.count, 2);
        assert_eq!(m.snapshot().count, 3);
    }

    // Test that decay works correctly
    #[test]
    fn decay() {
        let m = StdMeter::new();

        m.tick();
    }
}
<commit_msg>Meter must be Send+Sync.<commit_after>// 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.

#![allow(missing_docs)]

use std::sync::{Arc, Mutex, MutexGuard};
use time::{get_time, Timespec};
use utils::EWMA;

const WINDOW: [f64; 3] = [1.0, 5.0, 15.0];

// A MeterSnapshot
#[derive(Debug)]
pub struct MeterSnapshot {
    pub count: i64,
    pub rates: [f64; 3],
    pub mean: f64,
}

#[derive(Debug)]
struct StdMeterData {
    count: i64,
    rates: [f64; 3],
    mean: f64,
    ewma: [EWMA; 3],
}

// A StdMeter struct
#[derive(Debug)]
pub struct StdMeter {
    data: Mutex<StdMeterData>,
    start: Timespec,
}

// A Meter trait
pub trait Meter: Send + Sync {
    fn snapshot(&self) -> MeterSnapshot;

    fn mark(&self, n: i64);

    fn tick(&self);

    fn rate(&self, rate: f64) -> f64;

    fn mean(&self) -> f64;

    fn count(&self) -> i64;
}

impl Meter for StdMeter {
    fn snapshot(&self) -> MeterSnapshot {
        let s = self.data.lock().unwrap();

        MeterSnapshot {
            count: s.count,
            rates: s.rates,
            mean: s.mean,
        }
    }

    fn mark(&self, n: i64) {
        let mut s = self.data.lock().unwrap();

        s.count += n;

        for i in 0..WINDOW.len() {
            s.ewma[i].update(n as usize);
        }

        self.update_data(s);
    }

    fn tick(&self) {
        let mut s = self.data.lock().unwrap();

        for i in 0..WINDOW.len() {
            s.ewma[i].tick();
        }

        self.update_data(s);
    }

    /// Return the given EWMA for a rate like 1, 5, 15 minutes
    fn rate(&self, rate: f64) -> f64 {
        let s = self.data.lock().unwrap();

        if let Some(pos) = WINDOW.iter().position(|w| *w == rate) {
            return s.rates[pos];
        }
        0.0
    }
    /// Return the mean rate
    fn mean(&self) -> f64 {
        let s = self.data.lock().unwrap();

        s.mean
    }

    fn count(&self) -> i64 {
        let s = self.data.lock().unwrap();

        s.count
    }
}

impl StdMeter {
    fn update_data(&self, mut s: MutexGuard<StdMeterData>) {
        for i in 0..WINDOW.len() {
            s.rates[i] = s.ewma[i].rate();
        }

        let diff = get_time() - self.start;
        s.mean = s.count as f64 / diff.num_seconds() as f64;
    }

    pub fn new() -> Arc<Self> {
        Arc::new(StdMeter {
            data: Mutex::new(StdMeterData {
                count: 0,
                rates: [0.0, 0.0, 0.0],
                mean: 0.0,
                ewma: [EWMA::new(1.0), EWMA::new(5.0), EWMA::new(15.0)],
            }),
            start: get_time(),
        })
    }
}

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

    #[test]
    fn zero() {
        let m = StdMeter::new();
        let s = m.snapshot();

        assert_eq!(s.count, 0);
    }

    #[test]
    fn non_zero() {
        let m = StdMeter::new();
        m.mark(3);

        let s = m.snapshot();

        assert_eq!(s.count, 3);
    }

    #[test]
    fn snapshot() {
        let m = StdMeter::new();
        m.mark(1);
        m.mark(1);

        let s = m.snapshot();

        m.mark(1);

        assert_eq!(s.count, 2);
        assert_eq!(m.snapshot().count, 3);
    }

    // Test that decay works correctly
    #[test]
    fn decay() {
        let m = StdMeter::new();

        m.tick();
    }
}
<|endoftext|>


<commit_before>#![crate_name = "uu_mkfifo"]

/*
 * This file is part of the uutils coreutils package.
 *
 * (c) Michael Gehring <mg@ebfe.org>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

extern crate getopts;
extern crate libc;

#[macro_use]
extern crate uucore;

use libc::mkfifo;
use std::ffi::CString;
use std::io::Error;

static NAME: &str = "mkfifo";
static VERSION: &str = env!("CARGO_PKG_VERSION");

pub fn uumain(args: Vec<String>) -> i32 {
    let mut opts = getopts::Options::new();

    opts.optopt(
        "m",
        "mode",
        "file permissions for the fifo",
        "(default 0666)",
    );
    opts.optflag("h", "help", "display this help and exit");
    opts.optflag("V", "version", "output version information and exit");

    let matches = match opts.parse(&args[1..]) {
        Ok(m) => m,
        Err(err) => panic!("{}", err),
    };

    if matches.opt_present("version") {
        println!("{} {}", NAME, VERSION);
        return 0;
    }

    if matches.opt_present("help") || matches.free.is_empty() {
        let msg = format!(
            "{0} {1}

Usage:
  {0} [OPTIONS] NAME...

Create a FIFO with the given name.",
            NAME, VERSION
        );

        print!("{}", opts.usage(&msg));
        if matches.free.is_empty() {
            return 1;
        }
        return 0;
    }

    let mode = match matches.opt_str("m") {
        Some(m) => match usize::from_str_radix(&m, 8) {
            Ok(m) => m,
            Err(e) => {
                show_error!("invalid mode: {}", e);
                return 1;
            }
        },
        None => 0o666,
    };

    let mut exit_status = 0;
    for f in &matches.free {
        let err = unsafe {
            mkfifo(
                CString::new(f.as_bytes()).unwrap().as_ptr(),
                mode as libc::mode_t,
            )
        };
        if err == -1 {
            show_error!(
                "creating '{}': {}",
                f,
                Error::last_os_error().raw_os_error().unwrap()
            );
            exit_status = 1;
        }
    }

    exit_status
}
<commit_msg>refactor/polish ~ fix `cargo clippy` complaints (fatal/temporary_cstring_as_ptr)<commit_after>#![crate_name = "uu_mkfifo"]

/*
 * This file is part of the uutils coreutils package.
 *
 * (c) Michael Gehring <mg@ebfe.org>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

extern crate getopts;
extern crate libc;

#[macro_use]
extern crate uucore;

use libc::mkfifo;
use std::ffi::CString;
use std::io::Error;

static NAME: &str = "mkfifo";
static VERSION: &str = env!("CARGO_PKG_VERSION");

pub fn uumain(args: Vec<String>) -> i32 {
    let mut opts = getopts::Options::new();

    opts.optopt(
        "m",
        "mode",
        "file permissions for the fifo",
        "(default 0666)",
    );
    opts.optflag("h", "help", "display this help and exit");
    opts.optflag("V", "version", "output version information and exit");

    let matches = match opts.parse(&args[1..]) {
        Ok(m) => m,
        Err(err) => panic!("{}", err),
    };

    if matches.opt_present("version") {
        println!("{} {}", NAME, VERSION);
        return 0;
    }

    if matches.opt_present("help") || matches.free.is_empty() {
        let msg = format!(
            "{0} {1}

Usage:
  {0} [OPTIONS] NAME...

Create a FIFO with the given name.",
            NAME, VERSION
        );

        print!("{}", opts.usage(&msg));
        if matches.free.is_empty() {
            return 1;
        }
        return 0;
    }

    let mode = match matches.opt_str("m") {
        Some(m) => match usize::from_str_radix(&m, 8) {
            Ok(m) => m,
            Err(e) => {
                show_error!("invalid mode: {}", e);
                return 1;
            }
        },
        None => 0o666,
    };

    let mut exit_status = 0;
    for f in &matches.free {
        let err = unsafe {
            let name = CString::new(f.as_bytes()).unwrap();
            mkfifo(
                name.as_ptr(),
                mode as libc::mode_t,
            )
        };
        if err == -1 {
            show_error!(
                "creating '{}': {}",
                f,
                Error::last_os_error().raw_os_error().unwrap()
            );
            exit_status = 1;
        }
    }

    exit_status
}
<|endoftext|>


<commit_before>use codespan::{CodeMap, LineIndex, RawIndex};
use std::io;
use termcolor::{Color, ColorSpec, WriteColor};

use crate::{Diagnostic, LabelStyle, Severity};

pub fn emit<W, S>(mut writer: W, codemap: &CodeMap<S>, diagnostic: &Diagnostic) -> io::Result<()>
where
    W: WriteColor,
    S: AsRef<str>,
{
    let gutter_color = ColorSpec::new().set_fg(Some(gutter_color())).clone();
    let diagnostic_color = ColorSpec::new()
        .set_fg(Some(severity_color(diagnostic.severity)))
        .clone();

    let highlight_color = ColorSpec::new().set_bold(true).set_intense(true).clone();

    // Diagnostic header

    writer.set_color(
        &highlight_color
            .clone()
            .set_fg(Some(severity_color(diagnostic.severity))),
    )?;

    // Severity
    //
    // ```
    // error
    // ```
    write!(writer, "{}", severity_name(diagnostic.severity))?;

    // Error code
    //
    // ```
    // [E0001]
    // ```
    if let Some(code) = &diagnostic.code {
        write!(writer, "[{}]", code)?;
    }

    // Diagnostic message
    //
    // ```
    // : Unexpected type in `+` application
    // ```
    writer.set_color(&highlight_color)?;
    writeln!(writer, ": {}", diagnostic.message)?;
    writer.reset()?;

    // Diagnostic Labels

    for label in &diagnostic.labels {
        match codemap.find_file(label.span.start()) {
            None => {
                if !label.message.is_empty() {
                    writeln!(writer, "- {}", label.message)?
                }
            },
            Some(file) => {
                let (start_line, column) =
                    file.location(label.span.start()).expect("location_start");
                let (end_line, _) = file.location(label.span.end()).expect("location_end");

                // File name
                //
                // ```
                // - <test>:2:9
                // ```

                writeln!(
                    writer,
                    "- {file}:{line}:{column}",
                    file = file.name(),
                    line = start_line.number(),
                    column = column.number(),
                )?;

                // Source code snippet
                //
                // ```
                //   |
                // 2 | (+ test "")
                //   |         ^^ Expected integer but got string
                //   |
                // ```

                let start_line_span = file.line_span(start_line).expect("line_span");
                let end_line_span = file.line_span(end_line).expect("line_span");
                let line_location_width = end_line.number().to_string().len();

                let label_color = match label.style {
                    LabelStyle::Primary => diagnostic_color.clone(),
                    LabelStyle::Secondary => {
                        ColorSpec::new().set_fg(Some(secondary_color())).clone()
                    },
                };

                // Write prefix to marked section

                writer.set_color(&gutter_color)?;
                let line_string = start_line.number().to_string();
                writeln!(writer, "{: <width$} | ", "", width = line_location_width)?;
                write!(writer, "{} | ", line_string)?;

                let prefix = file
                    .src_slice(start_line_span.with_end(label.span.start()))
                    .expect("prefix");
                writer.reset()?;
                write!(writer, "{}", prefix)?;

                // Write marked section
                let mark_len = if start_line == end_line {
                    // Single line

                    let marked = file.src_slice(label.span).expect("marked");
                    writer.set_color(&label_color)?;
                    write!(writer, "{}", marked)?;
                    marked.len()
                } else {
                    // Multiple lines

                    let marked = file
                        .src_slice(start_line_span.with_start(label.span.start()))
                        .expect("start_of_marked");
                    writer.set_color(&label_color)?;
                    write!(writer, "{}", marked)?;

                    for line_index in ((start_line.to_usize() + 1)..end_line.to_usize())
                        .map(|i| LineIndex::from(i as RawIndex))
                    {
                        writer.set_color(&gutter_color)?;
                        write!(writer, "{} | ", line_index.number())?;

                        let line_span = file.line_span(line_index).expect("marked_line_span");
                        let line = file
                            .src_slice(line_span)
                            .expect("line")
                            .trim_end_matches(|ch: char| ch == '\r' || ch == '\n');
                        writer.set_color(&label_color)?;
                        writeln!(writer, "{}", line)?;
                    }

                    writer.set_color(&gutter_color)?;
                    write!(writer, "{} | ", end_line.number())?;
                    let line = file
                        .src_slice(end_line_span.with_end(label.span.end()))
                        .expect("line");
                    writer.set_color(&label_color)?;
                    write!(writer, "{}", line)?;
                    line.len()
                };

                // Write suffix to marked section

                let suffix = file
                    .src_slice(end_line_span.with_start(label.span.end()))
                    .expect("suffix")
                    .trim_end_matches(|ch: char| ch == '\r' || ch == '\n');
                writer.reset()?;
                writeln!(writer, "{}", suffix)?;

                // Write mark and label

                writer.set_color(&gutter_color)?;
                write!(writer, "{: <width$} | ", "", width = line_location_width)?;
                writer.reset()?;

                writer.set_color(&label_color)?;
                write!(writer, "{: <width$}", "", width = prefix.len())?;
                for _ in 0..mark_len {
                    write!(writer, "{}", underline_mark(label.style))?;
                }
                writer.reset()?;

                if !label.message.is_empty() {
                    writer.set_color(&label_color)?;
                    writeln!(writer, " {}", label.message)?;
                    writer.reset()?;
                }
                writer.set_color(&gutter_color)?;
                writeln!(writer, "{: <width$} | ", "", width = line_location_width)?;
                writer.reset()?;
            },
        }
    }
    Ok(())
}

// Blue is really difficult to see on the standard windows command line
// FIXME: Make colors configurable
#[cfg(windows)]
const BLUE: Color = Color::Cyan;
#[cfg(not(windows))]
const BLUE: Color = Color::Blue;

/// Return the termcolor to use when rendering messages of this diagnostic severity.
fn severity_color(severity: Severity) -> Color {
    match severity {
        Severity::Bug | Severity::Error => Color::Red,
        Severity::Warning => Color::Yellow,
        Severity::Note => Color::Green,
        Severity::Help => Color::Cyan,
    }
}

/// The color to use for secondary highlights.
fn secondary_color() -> Color {
    BLUE
}

/// The color to use for gutters highlights.
fn gutter_color() -> Color {
    BLUE
}

/// A string that explains this diagnostic severity.
fn severity_name(severity: Severity) -> &'static str {
    match severity {
        Severity::Bug => "bug",
        Severity::Error => "error",
        Severity::Warning => "warning",
        Severity::Note => "note",
        Severity::Help => "help",
    }
}

/// The mark used for the underlined section of code.
fn underline_mark(label_style: LabelStyle) -> char {
    match label_style {
        LabelStyle::Primary => '^',
        LabelStyle::Secondary => '-',
    }
}
<commit_msg>Correctly pad line numbers<commit_after>use codespan::{CodeMap, LineIndex, RawIndex};
use std::io;
use termcolor::{Color, ColorSpec, WriteColor};

use crate::{Diagnostic, LabelStyle, Severity};

pub fn emit<W, S>(mut writer: W, codemap: &CodeMap<S>, diagnostic: &Diagnostic) -> io::Result<()>
where
    W: WriteColor,
    S: AsRef<str>,
{
    let gutter_color = ColorSpec::new().set_fg(Some(gutter_color())).clone();
    let diagnostic_color = ColorSpec::new()
        .set_fg(Some(severity_color(diagnostic.severity)))
        .clone();

    let highlight_color = ColorSpec::new().set_bold(true).set_intense(true).clone();

    // Diagnostic header

    writer.set_color(
        &highlight_color
            .clone()
            .set_fg(Some(severity_color(diagnostic.severity))),
    )?;

    // Severity
    //
    // ```
    // error
    // ```
    write!(writer, "{}", severity_name(diagnostic.severity))?;

    // Error code
    //
    // ```
    // [E0001]
    // ```
    if let Some(code) = &diagnostic.code {
        write!(writer, "[{}]", code)?;
    }

    // Diagnostic message
    //
    // ```
    // : Unexpected type in `+` application
    // ```
    writer.set_color(&highlight_color)?;
    writeln!(writer, ": {}", diagnostic.message)?;
    writer.reset()?;

    // Diagnostic Labels

    for label in &diagnostic.labels {
        match codemap.find_file(label.span.start()) {
            None => {
                if !label.message.is_empty() {
                    writeln!(writer, "- {}", label.message)?
                }
            },
            Some(file) => {
                let (start_line, column) =
                    file.location(label.span.start()).expect("location_start");
                let (end_line, _) = file.location(label.span.end()).expect("location_end");

                // File name
                //
                // ```
                // - <test>:2:9
                // ```

                writeln!(
                    writer,
                    "- {file}:{line}:{column}",
                    file = file.name(),
                    line = start_line.number(),
                    column = column.number(),
                )?;

                // Source code snippet
                //
                // ```
                //   |
                // 2 | (+ test "")
                //   |         ^^ Expected integer but got string
                //   |
                // ```

                let start_line_span = file.line_span(start_line).expect("line_span");
                let end_line_span = file.line_span(end_line).expect("line_span");
                // Use the length of the last line number as the gutter padding
                let gutter_padding = format!("{}", end_line.number()).len();

                let label_color = match label.style {
                    LabelStyle::Primary => diagnostic_color.clone(),
                    LabelStyle::Secondary => {
                        ColorSpec::new().set_fg(Some(secondary_color())).clone()
                    },
                };

                // Write prefix to marked section

                writer.set_color(&gutter_color)?;
                writeln!(writer, "{: >width$} | ", "", width = gutter_padding)?;
                write!(
                    writer,
                    "{: >width$} | ",
                    start_line.number(),
                    width = gutter_padding,
                )?;

                let prefix = file
                    .src_slice(start_line_span.with_end(label.span.start()))
                    .expect("prefix");
                writer.reset()?;
                write!(writer, "{}", prefix)?;

                // Write marked section
                let mark_len = if start_line == end_line {
                    // Single line

                    let marked = file.src_slice(label.span).expect("marked");
                    writer.set_color(&label_color)?;
                    write!(writer, "{}", marked)?;
                    marked.len()
                } else {
                    // Multiple lines

                    let marked = file
                        .src_slice(start_line_span.with_start(label.span.start()))
                        .expect("start_of_marked");
                    writer.set_color(&label_color)?;
                    write!(writer, "{}", marked)?;

                    for line_index in ((start_line.to_usize() + 1)..end_line.to_usize())
                        .map(|i| LineIndex::from(i as RawIndex))
                    {
                        writer.set_color(&gutter_color)?;
                        write!(
                            writer,
                            "{: >width$} | ",
                            line_index.number(),
                            width = gutter_padding,
                        )?;

                        let line_span = file.line_span(line_index).expect("marked_line_span");
                        let line = file
                            .src_slice(line_span)
                            .expect("line")
                            .trim_end_matches(|ch: char| ch == '\r' || ch == '\n');
                        writer.set_color(&label_color)?;
                        writeln!(writer, "{}", line)?;
                    }

                    writer.set_color(&gutter_color)?;
                    write!(
                        writer,
                        "{: >width$} | ",
                        end_line.number(),
                        width = gutter_padding,
                    )?;
                    let line = file
                        .src_slice(end_line_span.with_end(label.span.end()))
                        .expect("line");
                    writer.set_color(&label_color)?;
                    write!(writer, "{}", line)?;
                    line.len()
                };

                // Write suffix to marked section

                let suffix = file
                    .src_slice(end_line_span.with_start(label.span.end()))
                    .expect("suffix")
                    .trim_end_matches(|ch: char| ch == '\r' || ch == '\n');
                writer.reset()?;
                writeln!(writer, "{}", suffix)?;

                // Write mark and label

                writer.set_color(&gutter_color)?;
                write!(writer, "{: >width$} | ", "", width = gutter_padding)?;
                writer.reset()?;

                writer.set_color(&label_color)?;
                write!(writer, "{: >width$}", "", width = prefix.len())?;
                for _ in 0..mark_len {
                    write!(writer, "{}", underline_mark(label.style))?;
                }
                writer.reset()?;

                if !label.message.is_empty() {
                    writer.set_color(&label_color)?;
                    writeln!(writer, " {}", label.message)?;
                    writer.reset()?;
                }
                writer.set_color(&gutter_color)?;
                writeln!(writer, "{: >width$} | ", "", width = gutter_padding)?;
                writer.reset()?;
            },
        }
    }
    Ok(())
}

// Blue is really difficult to see on the standard windows command line
// FIXME: Make colors configurable
#[cfg(windows)]
const BLUE: Color = Color::Cyan;
#[cfg(not(windows))]
const BLUE: Color = Color::Blue;

/// Return the termcolor to use when rendering messages of this diagnostic severity.
fn severity_color(severity: Severity) -> Color {
    match severity {
        Severity::Bug | Severity::Error => Color::Red,
        Severity::Warning => Color::Yellow,
        Severity::Note => Color::Green,
        Severity::Help => Color::Cyan,
    }
}

/// The color to use for secondary highlights.
fn secondary_color() -> Color {
    BLUE
}

/// The color to use for gutters highlights.
fn gutter_color() -> Color {
    BLUE
}

/// A string that explains this diagnostic severity.
fn severity_name(severity: Severity) -> &'static str {
    match severity {
        Severity::Bug => "bug",
        Severity::Error => "error",
        Severity::Warning => "warning",
        Severity::Note => "note",
        Severity::Help => "help",
    }
}

/// The mark used for the underlined section of code.
fn underline_mark(label_style: LabelStyle) -> char {
    match label_style {
        LabelStyle::Primary => '^',
        LabelStyle::Secondary => '-',
    }
}
<|endoftext|>


<commit_before>use analysis::ai::{domain, interpreter, memory};
use analysis::fixed_point;
use error::*;
use executor::eval;
use il;
use std::collections::{BTreeMap, BTreeSet, HashMap};
use std::fmt;
use types::Endian;

const MAX_CARDINALITY: usize = 4;

pub type KMemory = memory::Memory<KSet>;
pub type KState = domain::State<KMemory, KSet>;

#[allow(dead_code)]
pub fn kset<'k>(function: &'k il::Function, endian: Endian, initial_memory: KMemory)
-> Result<BTreeMap<il::RefProgramLocation<'k>, KState>> {
    let domain = KSetDomain { endian: endian, memory: initial_memory };
    let interpreter = interpreter::Interpreter {
        m: ::std::marker::PhantomData,
        v: ::std::marker::PhantomData,
        domain: domain
    };
    fixed_point::fixed_point_forward(interpreter, function)
}

#[derive(Clone, Debug, Deserialize, Eq, Ord, PartialEq, PartialOrd, Serialize)]
pub enum KSet {
    Top(usize),
    Value(BTreeSet<il::Constant>),
    Bottom(usize)
}

impl KSet {
    fn binop<F>(lhs: &KSet, rhs: &KSet, op: F) -> Result<KSet>
    where F: Fn(&il::Constant, &il::Constant) -> Result<il::Constant> {
        Ok(match *lhs {
            KSet::Top(bits) => KSet::Top(bits),
            KSet::Bottom(bits) => KSet::Bottom(bits),
            KSet::Value(ref lhs_value) => {
                match *rhs {
                    KSet::Top(bits) => KSet::Top(bits),
                    KSet::Bottom(bits) => KSet::Bottom(bits),
                    KSet::Value(ref rhs_value) => {
                        let mut b: BTreeSet<il::Constant> = BTreeSet::new();
                        for l in lhs_value {
                            for r in rhs_value {
                                b.insert(op(l, r)?);
                            }
                            if b.len() > MAX_CARDINALITY {
                                return Ok(KSet::Top(b.iter().next().unwrap().bits()));
                            }
                        }
                        if b.len() > MAX_CARDINALITY {
                            KSet::Top(b.iter().next().unwrap().bits())
                        }
                        else {
                            KSet::Value(b)
                        }
                    }
                }
            }
        })
    }

    fn ext<F>(bits: usize, k: &KSet, op: F) -> Result<KSet>
    where F: Fn(usize, &il::Constant) -> Result<il::Constant> {
        Ok(match *k {
            KSet::Top(_) => KSet::Top(bits),
            KSet::Bottom(_) => KSet::Bottom(bits),
            KSet::Value(ref value) => {
                let mut b: BTreeSet<il::Constant> = BTreeSet::new();
                for v in value {
                    b.insert(op(bits, v)?);
                }
                KSet::Value(b)
            }
        })
    }

    pub fn eval(expr: &domain::Expression<KSet>) -> Result<KSet> {
        match *expr {
            domain::Expression::Value(ref kset) => Ok(kset.clone()),
            domain::Expression::Add(ref lhs, ref rhs) =>
                KSet::binop(&KSet::eval(lhs)?, &KSet::eval(rhs)?, |l, r| {
                    eval(&il::Expression::add(l.clone().into(), r.clone().into())?)
                }),
            domain::Expression::Sub(ref lhs, ref rhs) =>
                KSet::binop(&KSet::eval(lhs)?, &KSet::eval(rhs)?, |l, r| {
                    eval(&il::Expression::sub(l.clone().into(), r.clone().into())?)
                }),
            domain::Expression::Mul(ref lhs, ref rhs) =>
                KSet::binop(&KSet::eval(lhs)?, &KSet::eval(rhs)?, |l, r| {
                    eval(&il::Expression::mul(l.clone().into(), r.clone().into())?)
                }),
            domain::Expression::Divu(ref lhs, ref rhs) =>
                KSet::binop(&KSet::eval(lhs)?, &KSet::eval(rhs)?, |l, r| {
                    eval(&il::Expression::divu(l.clone().into(), r.clone().into())?)
                }),
            domain::Expression::Modu(ref lhs, ref rhs) =>
                KSet::binop(&KSet::eval(lhs)?, &KSet::eval(rhs)?, |l, r| {
                    eval(&il::Expression::modu(l.clone().into(), r.clone().into())?)
                }),
            domain::Expression::Divs(ref lhs, ref rhs) =>
                KSet::binop(&KSet::eval(lhs)?, &KSet::eval(rhs)?, |l, r| {
                    eval(&il::Expression::divs(l.clone().into(), r.clone().into())?)
                }),
            domain::Expression::Mods(ref lhs, ref rhs) =>
                KSet::binop(&KSet::eval(lhs)?, &KSet::eval(rhs)?, |l, r| {
                    eval(&il::Expression::mods(l.clone().into(), r.clone().into())?)
                }),
            domain::Expression::And(ref lhs, ref rhs) =>
                KSet::binop(&KSet::eval(lhs)?, &KSet::eval(rhs)?, |l, r| {
                    eval(&il::Expression::and(l.clone().into(), r.clone().into())?)
                }),
            domain::Expression::Or(ref lhs, ref rhs) =>
                KSet::binop(&KSet::eval(lhs)?, &KSet::eval(rhs)?, |l, r| {
                    eval(&il::Expression::or(l.clone().into(), r.clone().into())?)
                }),
            domain::Expression::Xor(ref lhs, ref rhs) =>
                KSet::binop(&KSet::eval(lhs)?, &KSet::eval(rhs)?, |l, r| {
                    eval(&il::Expression::xor(l.clone().into(), r.clone().into())?)
                }),
            domain::Expression::Shl(ref lhs, ref rhs) =>
                KSet::binop(&KSet::eval(lhs)?, &KSet::eval(rhs)?, |l, r| {
                    eval(&il::Expression::shl(l.clone().into(), r.clone().into())?)
                }),
            domain::Expression::Shr(ref lhs, ref rhs) =>
                KSet::binop(&KSet::eval(lhs)?, &KSet::eval(rhs)?, |l, r| {
                    eval(&il::Expression::shr(l.clone().into(), r.clone().into())?)
                }),
            domain::Expression::Cmpeq(ref lhs, ref rhs) =>
                KSet::binop(&KSet::eval(lhs)?, &KSet::eval(rhs)?, |l, r| {
                    eval(&il::Expression::cmpeq(l.clone().into(), r.clone().into())?)
                }),
            domain::Expression::Cmpneq(ref lhs, ref rhs) =>
                KSet::binop(&KSet::eval(lhs)?, &KSet::eval(rhs)?, |l, r| {
                    eval(&il::Expression::cmpneq(l.clone().into(), r.clone().into())?)
                }),
            domain::Expression::Cmplts(ref lhs, ref rhs) =>
                KSet::binop(&KSet::eval(lhs)?, &KSet::eval(rhs)?, |l, r| {
                    eval(&il::Expression::cmplts(l.clone().into(), r.clone().into())?)
                }),
            domain::Expression::Cmpltu(ref lhs, ref rhs) =>
                KSet::binop(&KSet::eval(lhs)?, &KSet::eval(rhs)?, |l, r| {
                    eval(&il::Expression::cmpltu(l.clone().into(), r.clone().into())?)
                }),
            domain::Expression::Zext(bits, ref v) =>
                KSet::ext(bits, &KSet::eval(v)?, |bits, v| {
                    eval(&il::Expression::zext(bits, v.clone().into())?)
                }),
            domain::Expression::Sext(bits, ref v) =>
                KSet::ext(bits, &KSet::eval(v)?, |bits, v| {
                    eval(&il::Expression::sext(bits, v.clone().into())?)
                }),
            domain::Expression::Trun(bits, ref v) =>
                KSet::ext(bits, &KSet::eval(v)?, |bits, v| {
                    eval(&il::Expression::trun(bits, v.clone().into())?)
                })
        }
    }

    pub fn bits(&self) -> usize {
        match *self {
            KSet::Top(bits) => bits,
            KSet::Bottom(bits) => bits,
            KSet::Value(ref v) => v.iter().next().unwrap().bits()
        }
    }

    pub fn constant(constant: il::Constant) -> KSet {
        let mut b = BTreeSet::new();
        b.insert(constant);
        KSet::Value(b)
    }

    pub fn join(&self, rhs: &KSet) -> Result<KSet> {
        Ok(match *self {
            KSet::Top(bits) => KSet::Top(bits),
            KSet::Bottom(_) => rhs.clone(),
            KSet::Value(ref lhs_value) => {
                match *rhs {
                    KSet::Top(bits) => KSet::Top(bits),
                    KSet::Bottom(_) => self.clone(),
                    KSet::Value(ref rhs_value) => {
                        let mut lhs_value = lhs_value.clone();
                        for r in rhs_value {
                            lhs_value.insert(r.clone());
                        }
                        if lhs_value.len() > MAX_CARDINALITY {
                            KSet::Top(lhs_value.iter().next().unwrap().bits())
                        }
                        else {
                            KSet::Value(lhs_value)
                        }
                    }
                }
            }
        })
    }

    pub fn empty(bits: usize) -> KSet {
        KSet::Bottom(bits)
    }
}

impl Into<domain::Expression<KSet>> for KSet {
    fn into(self) -> domain::Expression<KSet> {
        domain::Expression::Value(self)
    }
}

impl memory::MemoryValue for KSet {
    fn bits(&self) -> usize {
        self.bits()
    }

    fn shl(&self, bits: usize) -> Result<KSet> {
        KSet::eval(&domain::Expression::shl(
            self.clone().into(),
            KSet::constant(il::const_(bits as u64, self.bits())).into()
        ))
    }

    fn shr(&self, bits: usize) -> Result<KSet> {
        KSet::eval(&domain::Expression::shr(
            self.clone().into(),
            KSet::constant(il::const_(bits as u64, self.bits())).into()
        ))
    }

    fn trun(&self, bits: usize) -> Result<KSet> {
        KSet::eval(&domain::Expression::trun(bits, self.clone().into()))
    }

    fn zext(&self, bits: usize) -> Result<KSet> {
        KSet::eval(&domain::Expression::zext(bits, self.clone().into()))
    }

    fn or(&self, other: &KSet) -> Result<KSet> {
        KSet::eval(&domain::Expression::or(
            self.clone().into(),
            other.clone().into()
        ))
    }

    fn join(&self, other: &KSet) -> Result<KSet> {
        KSet::join(self, other)
    }

    fn empty(bits: usize) -> KSet {
        KSet::empty(bits)
    }
}

impl domain::Value for KSet {
    fn join(&self, other: &KSet) -> Result<KSet> {
        self.join(other)
    }

    fn empty(bits: usize) -> KSet {
        KSet::empty(bits)
    }

    fn constant(constant: il::Constant) -> KSet {
        KSet::constant(constant)
    }
}

impl domain::Memory<KSet> for KMemory {
    fn store(&mut self, index: &KSet, value: KSet) -> Result<()> {
        if let KSet::Value(ref kindex) = *index {
            for i in kindex {
                self.store(i.value(), value.clone())?
            }
        }
        Ok(())
    }

    fn load(&self, index: &KSet, bits: usize) -> Result<KSet> {
        if let KSet::Value(ref kindex) = *index {
            let mut b = KSet::empty(index.bits());
            for i in kindex {
                b = b.join(&self.load(i.value(), bits)?)?;
            }
            Ok(b)
        }
        else {
            Ok(KSet::empty(index.bits()))
        }
    }

    fn new(endian: Endian) -> KMemory {
        memory::Memory::<KSet>::new(endian)
    }

    fn join(self, other: &KMemory) -> Result<KMemory> {
        memory::Memory::<KSet>::join(self, other)
    }
}

struct KSetDomain {
    endian: Endian,
    memory: KMemory
}

impl domain::Domain<KMemory, KSet> for KSetDomain {
    fn eval(&self, expr: &domain::Expression<KSet>) -> Result<KSet> {
        KSet::eval(expr)
    }

    fn brc(&self, _: &KSet, _: &KSet, state: KState) -> Result<KState> {
        Ok(state)
    }

    fn raise(&self, _: &KSet, state: KState) -> Result<KState> {
        Ok(state)
    }

    fn endian(&self) -> Endian {
        self.endian.clone()
    }

    fn new_state(&self) -> KState {
        KState {
            variables: HashMap::new(),
            memory: self.memory.clone()
        }
    }
}

impl fmt::Display for KSet {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            KSet::Top(bits) => write!(f, "⊤:{}", bits),
            KSet::Bottom(bits) => write!(f, "⊥:{}", bits),
            KSet::Value(ref values) => write!(f, "{{{}}}", values
                .iter()
                .map(|v| format!("{}", v))
                .collect::<Vec<String>>()
                .join(","))
        }
    }
}<commit_msg>Allow converting KState into just variables with into()<commit_after>use analysis::ai::{domain, interpreter, memory};
use analysis::fixed_point;
use error::*;
use executor::eval;
use il;
use std::collections::{BTreeMap, BTreeSet, HashMap};
use std::fmt;
use types::Endian;

const MAX_CARDINALITY: usize = 4;

pub type KMemory = memory::Memory<KSet>;
pub type KState = domain::State<KMemory, KSet>;

#[allow(dead_code)]
pub fn kset<'k>(function: &'k il::Function, endian: Endian, initial_memory: KMemory)
-> Result<BTreeMap<il::RefProgramLocation<'k>, KState>> {
    let domain = KSetDomain { endian: endian, memory: initial_memory };
    let interpreter = interpreter::Interpreter {
        m: ::std::marker::PhantomData,
        v: ::std::marker::PhantomData,
        domain: domain
    };
    fixed_point::fixed_point_forward(interpreter, function)
}

#[derive(Clone, Debug, Deserialize, Eq, Ord, PartialEq, PartialOrd, Serialize)]
pub enum KSet {
    Top(usize),
    Value(BTreeSet<il::Constant>),
    Bottom(usize)
}

impl KSet {
    fn binop<F>(lhs: &KSet, rhs: &KSet, op: F) -> Result<KSet>
    where F: Fn(&il::Constant, &il::Constant) -> Result<il::Constant> {
        Ok(match *lhs {
            KSet::Top(bits) => KSet::Top(bits),
            KSet::Bottom(bits) => KSet::Bottom(bits),
            KSet::Value(ref lhs_value) => {
                match *rhs {
                    KSet::Top(bits) => KSet::Top(bits),
                    KSet::Bottom(bits) => KSet::Bottom(bits),
                    KSet::Value(ref rhs_value) => {
                        let mut b: BTreeSet<il::Constant> = BTreeSet::new();
                        for l in lhs_value {
                            for r in rhs_value {
                                b.insert(op(l, r)?);
                            }
                            if b.len() > MAX_CARDINALITY {
                                return Ok(KSet::Top(b.iter().next().unwrap().bits()));
                            }
                        }
                        if b.len() > MAX_CARDINALITY {
                            KSet::Top(b.iter().next().unwrap().bits())
                        }
                        else {
                            KSet::Value(b)
                        }
                    }
                }
            }
        })
    }

    fn ext<F>(bits: usize, k: &KSet, op: F) -> Result<KSet>
    where F: Fn(usize, &il::Constant) -> Result<il::Constant> {
        Ok(match *k {
            KSet::Top(_) => KSet::Top(bits),
            KSet::Bottom(_) => KSet::Bottom(bits),
            KSet::Value(ref value) => {
                let mut b: BTreeSet<il::Constant> = BTreeSet::new();
                for v in value {
                    b.insert(op(bits, v)?);
                }
                KSet::Value(b)
            }
        })
    }

    pub fn eval(expr: &domain::Expression<KSet>) -> Result<KSet> {
        match *expr {
            domain::Expression::Value(ref kset) => Ok(kset.clone()),
            domain::Expression::Add(ref lhs, ref rhs) =>
                KSet::binop(&KSet::eval(lhs)?, &KSet::eval(rhs)?, |l, r| {
                    eval(&il::Expression::add(l.clone().into(), r.clone().into())?)
                }),
            domain::Expression::Sub(ref lhs, ref rhs) =>
                KSet::binop(&KSet::eval(lhs)?, &KSet::eval(rhs)?, |l, r| {
                    eval(&il::Expression::sub(l.clone().into(), r.clone().into())?)
                }),
            domain::Expression::Mul(ref lhs, ref rhs) =>
                KSet::binop(&KSet::eval(lhs)?, &KSet::eval(rhs)?, |l, r| {
                    eval(&il::Expression::mul(l.clone().into(), r.clone().into())?)
                }),
            domain::Expression::Divu(ref lhs, ref rhs) =>
                KSet::binop(&KSet::eval(lhs)?, &KSet::eval(rhs)?, |l, r| {
                    eval(&il::Expression::divu(l.clone().into(), r.clone().into())?)
                }),
            domain::Expression::Modu(ref lhs, ref rhs) =>
                KSet::binop(&KSet::eval(lhs)?, &KSet::eval(rhs)?, |l, r| {
                    eval(&il::Expression::modu(l.clone().into(), r.clone().into())?)
                }),
            domain::Expression::Divs(ref lhs, ref rhs) =>
                KSet::binop(&KSet::eval(lhs)?, &KSet::eval(rhs)?, |l, r| {
                    eval(&il::Expression::divs(l.clone().into(), r.clone().into())?)
                }),
            domain::Expression::Mods(ref lhs, ref rhs) =>
                KSet::binop(&KSet::eval(lhs)?, &KSet::eval(rhs)?, |l, r| {
                    eval(&il::Expression::mods(l.clone().into(), r.clone().into())?)
                }),
            domain::Expression::And(ref lhs, ref rhs) =>
                KSet::binop(&KSet::eval(lhs)?, &KSet::eval(rhs)?, |l, r| {
                    eval(&il::Expression::and(l.clone().into(), r.clone().into())?)
                }),
            domain::Expression::Or(ref lhs, ref rhs) =>
                KSet::binop(&KSet::eval(lhs)?, &KSet::eval(rhs)?, |l, r| {
                    eval(&il::Expression::or(l.clone().into(), r.clone().into())?)
                }),
            domain::Expression::Xor(ref lhs, ref rhs) =>
                KSet::binop(&KSet::eval(lhs)?, &KSet::eval(rhs)?, |l, r| {
                    eval(&il::Expression::xor(l.clone().into(), r.clone().into())?)
                }),
            domain::Expression::Shl(ref lhs, ref rhs) =>
                KSet::binop(&KSet::eval(lhs)?, &KSet::eval(rhs)?, |l, r| {
                    eval(&il::Expression::shl(l.clone().into(), r.clone().into())?)
                }),
            domain::Expression::Shr(ref lhs, ref rhs) =>
                KSet::binop(&KSet::eval(lhs)?, &KSet::eval(rhs)?, |l, r| {
                    eval(&il::Expression::shr(l.clone().into(), r.clone().into())?)
                }),
            domain::Expression::Cmpeq(ref lhs, ref rhs) =>
                KSet::binop(&KSet::eval(lhs)?, &KSet::eval(rhs)?, |l, r| {
                    eval(&il::Expression::cmpeq(l.clone().into(), r.clone().into())?)
                }),
            domain::Expression::Cmpneq(ref lhs, ref rhs) =>
                KSet::binop(&KSet::eval(lhs)?, &KSet::eval(rhs)?, |l, r| {
                    eval(&il::Expression::cmpneq(l.clone().into(), r.clone().into())?)
                }),
            domain::Expression::Cmplts(ref lhs, ref rhs) =>
                KSet::binop(&KSet::eval(lhs)?, &KSet::eval(rhs)?, |l, r| {
                    eval(&il::Expression::cmplts(l.clone().into(), r.clone().into())?)
                }),
            domain::Expression::Cmpltu(ref lhs, ref rhs) =>
                KSet::binop(&KSet::eval(lhs)?, &KSet::eval(rhs)?, |l, r| {
                    eval(&il::Expression::cmpltu(l.clone().into(), r.clone().into())?)
                }),
            domain::Expression::Zext(bits, ref v) =>
                KSet::ext(bits, &KSet::eval(v)?, |bits, v| {
                    eval(&il::Expression::zext(bits, v.clone().into())?)
                }),
            domain::Expression::Sext(bits, ref v) =>
                KSet::ext(bits, &KSet::eval(v)?, |bits, v| {
                    eval(&il::Expression::sext(bits, v.clone().into())?)
                }),
            domain::Expression::Trun(bits, ref v) =>
                KSet::ext(bits, &KSet::eval(v)?, |bits, v| {
                    eval(&il::Expression::trun(bits, v.clone().into())?)
                })
        }
    }

    pub fn bits(&self) -> usize {
        match *self {
            KSet::Top(bits) => bits,
            KSet::Bottom(bits) => bits,
            KSet::Value(ref v) => v.iter().next().unwrap().bits()
        }
    }

    pub fn constant(constant: il::Constant) -> KSet {
        let mut b = BTreeSet::new();
        b.insert(constant);
        KSet::Value(b)
    }

    pub fn join(&self, rhs: &KSet) -> Result<KSet> {
        Ok(match *self {
            KSet::Top(bits) => KSet::Top(bits),
            KSet::Bottom(_) => rhs.clone(),
            KSet::Value(ref lhs_value) => {
                match *rhs {
                    KSet::Top(bits) => KSet::Top(bits),
                    KSet::Bottom(_) => self.clone(),
                    KSet::Value(ref rhs_value) => {
                        let mut lhs_value = lhs_value.clone();
                        for r in rhs_value {
                            lhs_value.insert(r.clone());
                        }
                        if lhs_value.len() > MAX_CARDINALITY {
                            KSet::Top(lhs_value.iter().next().unwrap().bits())
                        }
                        else {
                            KSet::Value(lhs_value)
                        }
                    }
                }
            }
        })
    }

    pub fn empty(bits: usize) -> KSet {
        KSet::Bottom(bits)
    }
}

impl Into<domain::Expression<KSet>> for KSet {
    fn into(self) -> domain::Expression<KSet> {
        domain::Expression::Value(self)
    }
}

impl memory::MemoryValue for KSet {
    fn bits(&self) -> usize {
        self.bits()
    }

    fn shl(&self, bits: usize) -> Result<KSet> {
        KSet::eval(&domain::Expression::shl(
            self.clone().into(),
            KSet::constant(il::const_(bits as u64, self.bits())).into()
        ))
    }

    fn shr(&self, bits: usize) -> Result<KSet> {
        KSet::eval(&domain::Expression::shr(
            self.clone().into(),
            KSet::constant(il::const_(bits as u64, self.bits())).into()
        ))
    }

    fn trun(&self, bits: usize) -> Result<KSet> {
        KSet::eval(&domain::Expression::trun(bits, self.clone().into()))
    }

    fn zext(&self, bits: usize) -> Result<KSet> {
        KSet::eval(&domain::Expression::zext(bits, self.clone().into()))
    }

    fn or(&self, other: &KSet) -> Result<KSet> {
        KSet::eval(&domain::Expression::or(
            self.clone().into(),
            other.clone().into()
        ))
    }

    fn join(&self, other: &KSet) -> Result<KSet> {
        KSet::join(self, other)
    }

    fn empty(bits: usize) -> KSet {
        KSet::empty(bits)
    }
}

impl domain::Value for KSet {
    fn join(&self, other: &KSet) -> Result<KSet> {
        self.join(other)
    }

    fn empty(bits: usize) -> KSet {
        KSet::empty(bits)
    }

    fn constant(constant: il::Constant) -> KSet {
        KSet::constant(constant)
    }
}

impl domain::Memory<KSet> for KMemory {
    fn store(&mut self, index: &KSet, value: KSet) -> Result<()> {
        if let KSet::Value(ref kindex) = *index {
            for i in kindex {
                self.store(i.value(), value.clone())?
            }
        }
        Ok(())
    }

    fn load(&self, index: &KSet, bits: usize) -> Result<KSet> {
        if let KSet::Value(ref kindex) = *index {
            let mut b = KSet::empty(index.bits());
            for i in kindex {
                b = b.join(&self.load(i.value(), bits)?)?;
            }
            Ok(b)
        }
        else {
            Ok(KSet::empty(index.bits()))
        }
    }

    fn new(endian: Endian) -> KMemory {
        memory::Memory::<KSet>::new(endian)
    }

    fn join(self, other: &KMemory) -> Result<KMemory> {
        memory::Memory::<KSet>::join(self, other)
    }
}

struct KSetDomain {
    endian: Endian,
    memory: KMemory
}

impl domain::Domain<KMemory, KSet> for KSetDomain {
    fn eval(&self, expr: &domain::Expression<KSet>) -> Result<KSet> {
        KSet::eval(expr)
    }

    fn brc(&self, _: &KSet, _: &KSet, state: KState) -> Result<KState> {
        Ok(state)
    }

    fn raise(&self, _: &KSet, state: KState) -> Result<KState> {
        Ok(state)
    }

    fn endian(&self) -> Endian {
        self.endian.clone()
    }

    fn new_state(&self) -> KState {
        KState {
            variables: HashMap::new(),
            memory: self.memory.clone()
        }
    }
}

impl fmt::Display for KSet {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            KSet::Top(bits) => write!(f, "⊤:{}", bits),
            KSet::Bottom(bits) => write!(f, "⊥:{}", bits),
            KSet::Value(ref values) => write!(f, "{{{}}}", values
                .iter()
                .map(|v| format!("{}", v))
                .collect::<Vec<String>>()
                .join(","))
        }
    }
}

impl Into<HashMap<il::Scalar, KSet>> for KState {
    fn into(self) -> HashMap<il::Scalar, KSet> {
        self.variables
    }
}<|endoftext|>