<commit_before>#![allow(dead_code, unused_must_use, unused_variables, unused_imports)]

use std::thread::{self,Thread,Builder};
use std::sync::mpsc::{self,channel,Receiver};
use mio::tcp::*;
use mio::*;
use bytes::{ByteBuf,MutByteBuf};
use std::collections::HashMap;
use std::io::{self,Read,ErrorKind};
use nom::HexDisplay;
use std::error::Error;
use mio::util::Slab;
use std::io::Write;
use std::str::FromStr;
use std::marker::PhantomData;
use std::fmt::Debug;
use time::precise_time_ns;
use rand::random;

use network::{ClientResult,ServerMessage,ConnectionError,SocketType,socket_type,ProxyOrder,RequiredEvents};
use network::metrics::{METRICS,ProxyMetrics};

use messages::{TcpFront,Command,Instance};

const SERVER: Token = Token(0);
const FRONT_TIMEOUT: u64 = 10000;
const BACK_TIMEOUT:  u64 = 10000;
type ClientToken = Token;

pub trait ProxyClient {
  fn front_socket(&self) -> &TcpStream;
  fn back_socket(&self)  -> Option<&TcpStream>;
  fn front_token(&self)  -> Option<Token>;
  fn back_token(&self)   -> Option<Token>;
  fn set_back_socket(&mut self, TcpStream);
  fn set_front_token(&mut self, token: Token);
  fn set_back_token(&mut self, token: Token);
  fn front_timeout(&mut self) -> Option<Timeout>;
  fn back_timeout(&mut self)  -> Option<Timeout>;
  fn set_front_timeout(&mut self, timeout: Timeout);
  fn set_back_timeout(&mut self, timeout: Timeout);
  fn set_tokens(&mut self, token: Token, backend: Token);
  fn front_hup(&mut self)     -> ClientResult;
  fn back_hup(&mut self)      -> ClientResult;
  fn readable(&mut self)      -> (RequiredEvents, ClientResult);
  fn writable(&mut self)      -> (RequiredEvents, ClientResult);
  fn back_readable(&mut self) -> (RequiredEvents, ClientResult);
  fn back_writable(&mut self) -> (RequiredEvents, ClientResult);
  fn remove_backend(&mut self);
}

pub trait ProxyConfiguration<Server:Handler,Client> {
  fn add_tcp_front(&mut self, port: u16, app_id: &str, event_loop: &mut EventLoop<Server>) -> Option<Token>;
  fn connect_to_backend(&mut self, client:&mut Client) ->Result<TcpStream,ConnectionError>;
  fn notify(&mut self, event_loop: &mut EventLoop<Server>, message: ProxyOrder);
  fn accept(&mut self, token: Token) -> Option<(Client, bool)>;
}

pub struct Server<ServerConfiguration,Client> {
  configuration:   ServerConfiguration,
  clients:         Slab<Client>,
  backend:         Slab<ClientToken>,
  max_listeners:   usize,
  max_connections: usize,
}

impl<ServerConfiguration:ProxyConfiguration<Server<ServerConfiguration,Client>, Client>,Client:ProxyClient> Server<ServerConfiguration,Client> {
  pub fn new(max_listeners: usize, max_connections: usize, configuration: ServerConfiguration) -> Self {
    Server {
      configuration:   configuration,
      clients:         Slab::new_starting_at(Token(max_listeners), max_connections),
      backend:         Slab::new_starting_at(Token(max_listeners+max_connections), max_connections),
      max_listeners:   max_listeners,
      max_connections: max_connections,
    }
  }

  pub fn configuration(&mut self) -> &mut ServerConfiguration {
    &mut self.configuration
  }

  pub fn close_client(&mut self, event_loop: &mut EventLoop<Self>, token: Token) {
    self.clients[token].front_socket().shutdown(Shutdown::Both);
    event_loop.deregister(self.clients[token].front_socket());
    if let Some(sock) = self.clients[token].back_socket() {
      sock.shutdown(Shutdown::Both);
      event_loop.deregister(sock);
    }

    if let Some(backend_token) = self.clients[token].back_token() {
      if self.backend.contains(backend_token) {
        self.backend.remove(backend_token);
      }
    }
    self.clients.remove(token);
  }

  pub fn close_backend(&mut self, event_loop: &mut EventLoop<Self>, token: Token) {
    if let Some(backend_token) = self.clients[token].back_token() {
      if self.backend.contains(backend_token) {
        self.backend.remove(backend_token);
        self.clients[token].remove_backend();
      }
    }
  }

  pub fn accept(&mut self, event_loop: &mut EventLoop<Self>, token: Token) {
    if let Some((client, should_connect)) = self.configuration.accept(token) {
      if let Ok(client_token) = self.clients.insert(client) {
        event_loop.register(self.clients[client_token].front_socket(), client_token, EventSet::readable(), PollOpt::edge());
        &self.clients[client_token].set_front_token(client_token);
        if let Ok(timeout) = event_loop.timeout_ms(client_token.as_usize(), FRONT_TIMEOUT) {
          &self.clients[client_token].set_front_timeout(timeout);
        }
        METRICS.lock().unwrap().gauge("accept", 1);
        if should_connect {
          self.connect_to_backend(event_loop, client_token);
        }
      } else {
        error!("could not add client to slab");
      }
    } else {
      error!("could not create a client");
    }
  }

  pub fn connect_to_backend(&mut self, event_loop: &mut EventLoop<Self>, token: Token) {
    if let Ok(socket) = self.configuration.connect_to_backend(&mut self.clients[token]) {
      if let Ok(backend_token) = self.backend.insert(token) {
        self.clients[token].set_back_socket(socket);
        self.clients[token].set_back_token(backend_token);

        if let Some(sock) = self.clients[token].back_socket() {
          event_loop.register(sock, backend_token, EventSet::writable(), PollOpt::edge());
        }
        if let Ok(timeout) = event_loop.timeout_ms(backend_token.as_usize(), BACK_TIMEOUT) {
          &self.clients[token].set_back_timeout(timeout);
        }
        return;
      }
    } else {
      // ToDo serve page explaining what happened
      // - "domain not found" (aka "404 clever") page
      // - 503 "service unavailable" (aka "your app is deploying") page
      // - check other failing conditions
    }
    self.close_client(event_loop, token);
  }

  pub fn get_client_token(&self, token: Token) -> Option<Token> {
    if token.as_usize() < self.max_listeners {
      None
    } else if token.as_usize() < self.max_listeners + self.max_connections && self.clients.contains(token) {
      Some(token)
    } else if token.as_usize() < self.max_listeners + 2 * self.max_connections && self.backend.contains(token) {
      if self.clients.contains(self.backend[token]) {
        Some(self.backend[token])
      } else {
        None
      }
    } else {
      None
    }
  }

  pub fn interpret_client_order(&mut self, event_loop: &mut EventLoop<Self>, token: Token, order: (RequiredEvents, ClientResult)) {
    //println!("ORDER: {:?}", order);
    match order.1 {
      ClientResult::CloseClient      => self.close_client(event_loop, token),
      ClientResult::CloseBackend     => self.close_backend(event_loop, token),
      ClientResult::CloseBothSuccess => self.close_client(event_loop, token),
      ClientResult::CloseBothFailure => self.close_client(event_loop, token),
      ClientResult::ConnectBackend   => {
        let mut front_interest = EventSet::hup();
        let mut back_interest  = EventSet::hup();
        front_interest.insert(EventSet::readable());
        back_interest.insert(EventSet::writable());
        self.reregister(event_loop, token, front_interest, back_interest);
        self.connect_to_backend(event_loop, token)
      },
      ClientResult::Continue         => {
        let mut front_interest = EventSet::hup();
        let mut back_interest  = EventSet::hup();
        if order.0.front_readable() {
          front_interest.insert(EventSet::readable());
        }
        if order.0.front_writable() {
          front_interest.insert(EventSet::writable());
        }
        if order.0.back_readable() {
          back_interest.insert(EventSet::readable());
        }
        if order.0.back_writable() {
          back_interest.insert(EventSet::writable());
        }
        self.reregister(event_loop, token, front_interest, back_interest)
      }
    }
  }

  fn reregister(&self, event_loop: &mut EventLoop<Self>, token: Token, front_interest: EventSet, back_interest: EventSet) {
    let client = &self.clients[token];
    /*
    let mut front_interest = EventSet::hup();
    let mut back_interest  = EventSet::hup();
    front_interest.insert(EventSet::readable());
    front_interest.insert(EventSet::writable());
    back_interest.insert(EventSet::writable());
    back_interest.insert(EventSet::readable());
    */

    if let Some(frontend_token) = client.front_token() {
      event_loop.reregister(client.front_socket(), frontend_token, front_interest, PollOpt::level() | PollOpt::oneshot());
    }
     if let Some(backend_token) = client.back_token() {
       if let Some(sock) = client.back_socket() {
         event_loop.reregister(sock, backend_token, back_interest, PollOpt::level() | PollOpt::oneshot());
       }
     }
  }
}

impl<ServerConfiguration:ProxyConfiguration<Server<ServerConfiguration,Client>, Client>,Client:ProxyClient> Handler for Server<ServerConfiguration,Client> {
  type Timeout = usize;
  type Message = ProxyOrder;

  fn ready(&mut self, event_loop: &mut EventLoop<Self>, token: Token, events: EventSet) {
    trace!("{:?} got events: {:?}", token, events);
    if events.is_readable() {
      trace!("{:?} is readable", token);

      match socket_type(token, self.max_listeners, self.max_connections) {
        Some(SocketType::Listener) => {
          self.accept(event_loop, token)
        }

        Some(SocketType::FrontClient) => {
          if self.clients.contains(token) {
            let order = self.clients[token].readable();

            // FIXME: should clear the timeout only if data was consumed
            if let Some(timeout) = self.clients[token].front_timeout() {
              //println!("[{}] clearing timeout", token.as_usize());
              event_loop.clear_timeout(timeout);
            }
            if let Ok(timeout) = event_loop.timeout_ms(token.as_usize(), FRONT_TIMEOUT) {
              //println!("[{}] resetting timeout", token.as_usize());
              &self.clients[token].set_front_timeout(timeout);
            }

            self.interpret_client_order(event_loop, token, order);
          } else {
            info!("client {:?} was removed", token);
          }
        }

        Some(SocketType::BackClient) => {
          if let Some(tok) = self.get_client_token(token) {
            let order = self.clients[tok].back_readable();

            // FIXME: should clear the timeout only if data was consumed
            if let Some(timeout) = self.clients[tok].back_timeout() {
              //println!("[{}] clearing timeout", token.as_usize());
              event_loop.clear_timeout(timeout);
            }
            if let Ok(timeout) = event_loop.timeout_ms(token.as_usize(), BACK_TIMEOUT) {
              //println!("[{}] resetting timeout", token.as_usize());
              &self.clients[tok].set_back_timeout(timeout);
            }

            self.interpret_client_order(event_loop, tok, order);
          }
        }

        None => {}
      }
    }

    if events.is_writable() {
      trace!("{:?} is writable", token);

      match socket_type(token, self.max_listeners, self.max_connections) {
        Some(SocketType::Listener) => {
          error!("received writable for listener {:?}, this should not happen", token);
        }

        Some(SocketType::FrontClient) => {
          if self.clients.contains(token) {
            let order = self.clients[token].writable();
            trace!("interpreting client order {:?}", order);
            self.interpret_client_order(event_loop, token, order);
          } else {
            info!("client {:?} was removed", token);
          }
        }

        Some(SocketType::BackClient) => {
          if let Some(tok) = self.get_client_token(token) {
            let order = self.clients[tok].back_writable();
            self.interpret_client_order(event_loop, tok, order);
          }
        }

        None => {}
      }
    }

    if events.is_hup() {
      match socket_type(token, self.max_listeners, self.max_connections) {
        Some(SocketType::Listener) => {
          error!("should not happen: server {:?} closed", token);
        }

        Some(SocketType::FrontClient) => {
          if self.clients.contains(token) {
            if self.clients[token].front_hup() == ClientResult::CloseClient {
              self.close_client(event_loop, token);
            }
          } else {
            info!("client {:?} was removed", token);
          }
        }

        Some(SocketType::BackClient) => {
          if let Some(tok) = self.get_client_token(token) {
            if self.clients[tok].front_hup() == ClientResult::CloseClient {
              self.close_client(event_loop, tok);
            }
          }
        }

        None => {}
      }
    }
  }

  fn notify(&mut self, event_loop: &mut EventLoop<Self>, message: Self::Message) {
    self.configuration.notify(event_loop, message);
  }

  fn timeout(&mut self, event_loop: &mut EventLoop<Self>, timeout: Self::Timeout) {
    let token = Token(timeout);
    match socket_type(token, self.max_listeners, self.max_connections) {
      Some(SocketType::Listener) => {
        error!("the listener socket should have no timeout set");
      },
      Some(SocketType::FrontClient) => {
        if self.clients.contains(token) {
          error!("frontend [{}] got timeout, closing", timeout);
          self.close_client(event_loop, token);
        }
      },
      Some(SocketType::BackClient) => {
        if let Some(tok) = self.get_client_token(token) {
          error!("backend [{}] got timeout, closing", timeout);
          self.close_client(event_loop, tok);
        }
      }
      None => {}
    }
  }

  fn interrupted(&mut self, event_loop: &mut EventLoop<Self>) {
    warn!("interrupted");
  }
}

<commit_msg>remove useless code<commit_after>#![allow(dead_code, unused_must_use, unused_variables, unused_imports)]

use std::thread::{self,Thread,Builder};
use std::sync::mpsc::{self,channel,Receiver};
use mio::tcp::*;
use mio::*;
use bytes::{ByteBuf,MutByteBuf};
use std::collections::HashMap;
use std::io::{self,Read,ErrorKind};
use nom::HexDisplay;
use std::error::Error;
use mio::util::Slab;
use std::io::Write;
use std::str::FromStr;
use std::marker::PhantomData;
use std::fmt::Debug;
use time::precise_time_ns;
use rand::random;

use network::{ClientResult,ServerMessage,ConnectionError,SocketType,socket_type,ProxyOrder,RequiredEvents};
use network::metrics::{METRICS,ProxyMetrics};

use messages::{TcpFront,Command,Instance};

const SERVER: Token = Token(0);
const FRONT_TIMEOUT: u64 = 10000;
const BACK_TIMEOUT:  u64 = 10000;
type ClientToken = Token;

pub trait ProxyClient {
  fn front_socket(&self) -> &TcpStream;
  fn back_socket(&self)  -> Option<&TcpStream>;
  fn front_token(&self)  -> Option<Token>;
  fn back_token(&self)   -> Option<Token>;
  fn set_back_socket(&mut self, TcpStream);
  fn set_front_token(&mut self, token: Token);
  fn set_back_token(&mut self, token: Token);
  fn front_timeout(&mut self) -> Option<Timeout>;
  fn back_timeout(&mut self)  -> Option<Timeout>;
  fn set_front_timeout(&mut self, timeout: Timeout);
  fn set_back_timeout(&mut self, timeout: Timeout);
  fn set_tokens(&mut self, token: Token, backend: Token);
  fn front_hup(&mut self)     -> ClientResult;
  fn back_hup(&mut self)      -> ClientResult;
  fn readable(&mut self)      -> (RequiredEvents, ClientResult);
  fn writable(&mut self)      -> (RequiredEvents, ClientResult);
  fn back_readable(&mut self) -> (RequiredEvents, ClientResult);
  fn back_writable(&mut self) -> (RequiredEvents, ClientResult);
  fn remove_backend(&mut self);
}

pub trait ProxyConfiguration<Server:Handler,Client> {
  fn add_tcp_front(&mut self, port: u16, app_id: &str, event_loop: &mut EventLoop<Server>) -> Option<Token>;
  fn connect_to_backend(&mut self, client:&mut Client) ->Result<TcpStream,ConnectionError>;
  fn notify(&mut self, event_loop: &mut EventLoop<Server>, message: ProxyOrder);
  fn accept(&mut self, token: Token) -> Option<(Client, bool)>;
}

pub struct Server<ServerConfiguration,Client> {
  configuration:   ServerConfiguration,
  clients:         Slab<Client>,
  backend:         Slab<ClientToken>,
  max_listeners:   usize,
  max_connections: usize,
}

impl<ServerConfiguration:ProxyConfiguration<Server<ServerConfiguration,Client>, Client>,Client:ProxyClient> Server<ServerConfiguration,Client> {
  pub fn new(max_listeners: usize, max_connections: usize, configuration: ServerConfiguration) -> Self {
    Server {
      configuration:   configuration,
      clients:         Slab::new_starting_at(Token(max_listeners), max_connections),
      backend:         Slab::new_starting_at(Token(max_listeners+max_connections), max_connections),
      max_listeners:   max_listeners,
      max_connections: max_connections,
    }
  }

  pub fn configuration(&mut self) -> &mut ServerConfiguration {
    &mut self.configuration
  }

  pub fn close_client(&mut self, event_loop: &mut EventLoop<Self>, token: Token) {
    self.clients[token].front_socket().shutdown(Shutdown::Both);
    event_loop.deregister(self.clients[token].front_socket());
    if let Some(sock) = self.clients[token].back_socket() {
      sock.shutdown(Shutdown::Both);
      event_loop.deregister(sock);
    }

    if let Some(backend_token) = self.clients[token].back_token() {
      if self.backend.contains(backend_token) {
        self.backend.remove(backend_token);
      }
    }
    self.clients.remove(token);
  }

  pub fn close_backend(&mut self, event_loop: &mut EventLoop<Self>, token: Token) {
    if let Some(backend_token) = self.clients[token].back_token() {
      if self.backend.contains(backend_token) {
        self.backend.remove(backend_token);
        self.clients[token].remove_backend();
      }
    }
  }

  pub fn accept(&mut self, event_loop: &mut EventLoop<Self>, token: Token) {
    if let Some((client, should_connect)) = self.configuration.accept(token) {
      if let Ok(client_token) = self.clients.insert(client) {
        event_loop.register(self.clients[client_token].front_socket(), client_token, EventSet::readable(), PollOpt::edge());
        &self.clients[client_token].set_front_token(client_token);
        if let Ok(timeout) = event_loop.timeout_ms(client_token.as_usize(), FRONT_TIMEOUT) {
          &self.clients[client_token].set_front_timeout(timeout);
        }
        METRICS.lock().unwrap().gauge("accept", 1);
        if should_connect {
          self.connect_to_backend(event_loop, client_token);
        }
      } else {
        error!("could not add client to slab");
      }
    } else {
      error!("could not create a client");
    }
  }

  pub fn connect_to_backend(&mut self, event_loop: &mut EventLoop<Self>, token: Token) {
    if let Ok(socket) = self.configuration.connect_to_backend(&mut self.clients[token]) {
      if let Ok(backend_token) = self.backend.insert(token) {
        self.clients[token].set_back_socket(socket);
        self.clients[token].set_back_token(backend_token);

        if let Some(sock) = self.clients[token].back_socket() {
          event_loop.register(sock, backend_token, EventSet::writable(), PollOpt::edge());
        }
        if let Ok(timeout) = event_loop.timeout_ms(backend_token.as_usize(), BACK_TIMEOUT) {
          &self.clients[token].set_back_timeout(timeout);
        }
        return;
      }
    } else {
      // ToDo serve page explaining what happened
      // - "domain not found" (aka "404 clever") page
      // - 503 "service unavailable" (aka "your app is deploying") page
      // - check other failing conditions
    }
    self.close_client(event_loop, token);
  }

  pub fn get_client_token(&self, token: Token) -> Option<Token> {
    if token.as_usize() < self.max_listeners {
      None
    } else if token.as_usize() < self.max_listeners + self.max_connections && self.clients.contains(token) {
      Some(token)
    } else if token.as_usize() < self.max_listeners + 2 * self.max_connections && self.backend.contains(token) {
      if self.clients.contains(self.backend[token]) {
        Some(self.backend[token])
      } else {
        None
      }
    } else {
      None
    }
  }

  pub fn interpret_client_order(&mut self, event_loop: &mut EventLoop<Self>, token: Token, order: (RequiredEvents, ClientResult)) {
    //println!("ORDER: {:?}", order);
    match order.1 {
      ClientResult::CloseClient      => self.close_client(event_loop, token),
      ClientResult::CloseBackend     => self.close_backend(event_loop, token),
      ClientResult::CloseBothSuccess => self.close_client(event_loop, token),
      ClientResult::CloseBothFailure => self.close_client(event_loop, token),
      ClientResult::ConnectBackend   => {
        let mut front_interest = EventSet::hup();
        let mut back_interest  = EventSet::hup();
        front_interest.insert(EventSet::readable());
        back_interest.insert(EventSet::writable());
        self.reregister(event_loop, token, front_interest, back_interest);
        self.connect_to_backend(event_loop, token)
      },
      ClientResult::Continue         => {
        let mut front_interest = EventSet::hup();
        let mut back_interest  = EventSet::hup();
        if order.0.front_readable() {
          front_interest.insert(EventSet::readable());
        }
        if order.0.front_writable() {
          front_interest.insert(EventSet::writable());
        }
        if order.0.back_readable() {
          back_interest.insert(EventSet::readable());
        }
        if order.0.back_writable() {
          back_interest.insert(EventSet::writable());
        }
        self.reregister(event_loop, token, front_interest, back_interest)
      }
    }
  }

  fn reregister(&self, event_loop: &mut EventLoop<Self>, token: Token, front_interest: EventSet, back_interest: EventSet) {
    let client = &self.clients[token];

    if let Some(frontend_token) = client.front_token() {
      event_loop.reregister(client.front_socket(), frontend_token, front_interest, PollOpt::level() | PollOpt::oneshot());
    }
     if let Some(backend_token) = client.back_token() {
       if let Some(sock) = client.back_socket() {
         event_loop.reregister(sock, backend_token, back_interest, PollOpt::level() | PollOpt::oneshot());
       }
     }
  }
}

impl<ServerConfiguration:ProxyConfiguration<Server<ServerConfiguration,Client>, Client>,Client:ProxyClient> Handler for Server<ServerConfiguration,Client> {
  type Timeout = usize;
  type Message = ProxyOrder;

  fn ready(&mut self, event_loop: &mut EventLoop<Self>, token: Token, events: EventSet) {
    trace!("{:?} got events: {:?}", token, events);
    if events.is_readable() {
      trace!("{:?} is readable", token);

      match socket_type(token, self.max_listeners, self.max_connections) {
        Some(SocketType::Listener) => {
          self.accept(event_loop, token)
        }

        Some(SocketType::FrontClient) => {
          if self.clients.contains(token) {
            let order = self.clients[token].readable();

            // FIXME: should clear the timeout only if data was consumed
            if let Some(timeout) = self.clients[token].front_timeout() {
              //println!("[{}] clearing timeout", token.as_usize());
              event_loop.clear_timeout(timeout);
            }
            if let Ok(timeout) = event_loop.timeout_ms(token.as_usize(), FRONT_TIMEOUT) {
              //println!("[{}] resetting timeout", token.as_usize());
              &self.clients[token].set_front_timeout(timeout);
            }

            self.interpret_client_order(event_loop, token, order);
          } else {
            info!("client {:?} was removed", token);
          }
        }

        Some(SocketType::BackClient) => {
          if let Some(tok) = self.get_client_token(token) {
            let order = self.clients[tok].back_readable();

            // FIXME: should clear the timeout only if data was consumed
            if let Some(timeout) = self.clients[tok].back_timeout() {
              //println!("[{}] clearing timeout", token.as_usize());
              event_loop.clear_timeout(timeout);
            }
            if let Ok(timeout) = event_loop.timeout_ms(token.as_usize(), BACK_TIMEOUT) {
              //println!("[{}] resetting timeout", token.as_usize());
              &self.clients[tok].set_back_timeout(timeout);
            }

            self.interpret_client_order(event_loop, tok, order);
          }
        }

        None => {}
      }
    }

    if events.is_writable() {
      trace!("{:?} is writable", token);

      match socket_type(token, self.max_listeners, self.max_connections) {
        Some(SocketType::Listener) => {
          error!("received writable for listener {:?}, this should not happen", token);
        }

        Some(SocketType::FrontClient) => {
          if self.clients.contains(token) {
            let order = self.clients[token].writable();
            trace!("interpreting client order {:?}", order);
            self.interpret_client_order(event_loop, token, order);
          } else {
            info!("client {:?} was removed", token);
          }
        }

        Some(SocketType::BackClient) => {
          if let Some(tok) = self.get_client_token(token) {
            let order = self.clients[tok].back_writable();
            self.interpret_client_order(event_loop, tok, order);
          }
        }

        None => {}
      }
    }

    if events.is_hup() {
      match socket_type(token, self.max_listeners, self.max_connections) {
        Some(SocketType::Listener) => {
          error!("should not happen: server {:?} closed", token);
        }

        Some(SocketType::FrontClient) => {
          if self.clients.contains(token) {
            if self.clients[token].front_hup() == ClientResult::CloseClient {
              self.close_client(event_loop, token);
            }
          } else {
            info!("client {:?} was removed", token);
          }
        }

        Some(SocketType::BackClient) => {
          if let Some(tok) = self.get_client_token(token) {
            if self.clients[tok].front_hup() == ClientResult::CloseClient {
              self.close_client(event_loop, tok);
            }
          }
        }

        None => {}
      }
    }
  }

  fn notify(&mut self, event_loop: &mut EventLoop<Self>, message: Self::Message) {
    self.configuration.notify(event_loop, message);
  }

  fn timeout(&mut self, event_loop: &mut EventLoop<Self>, timeout: Self::Timeout) {
    let token = Token(timeout);
    match socket_type(token, self.max_listeners, self.max_connections) {
      Some(SocketType::Listener) => {
        error!("the listener socket should have no timeout set");
      },
      Some(SocketType::FrontClient) => {
        if self.clients.contains(token) {
          error!("frontend [{}] got timeout, closing", timeout);
          self.close_client(event_loop, token);
        }
      },
      Some(SocketType::BackClient) => {
        if let Some(tok) = self.get_client_token(token) {
          error!("backend [{}] got timeout, closing", timeout);
          self.close_client(event_loop, tok);
        }
      }
      None => {}
    }
  }

  fn interrupted(&mut self, event_loop: &mut EventLoop<Self>) {
    warn!("interrupted");
  }
}

<|endoftext|>


<commit_before>use crate::database::*;
use multimap::MultiMap;
use std::collections::{BTreeMap, HashMap};
use std::io::Write;

// 2D bit array
pub struct BitMatrix {
    pub frames: usize,
    pub bits: usize,
    data: Vec<bool>,
}

impl BitMatrix {
    // Create new empty bitmatrix
    pub fn new(frames: usize, bits: usize) -> BitMatrix {
        BitMatrix {
            frames: frames,
            bits: bits,
            data: vec![false; frames * bits],
        }
    }
    // Getting and setting bits
    pub fn get(&self, frame: usize, bit: usize) -> bool {
        self.data[frame * self.bits + bit]
    }
    pub fn set(&mut self, frame: usize, bit: usize, val: bool) {
        self.data[frame * self.bits + bit] = val
    }
    // Copy another bitmatrix to a window of this one
    pub fn copy_window(&mut self, from: &Self, start_frame: usize, start_bit: usize) {
        for f in 0..from.frames {
            for b in 0..from.bits {
                self.data[(f + start_frame) * self.bits + (b + start_bit)] =
                    from.data[f * from.bits + b];
            }
        }
    }
    // Copy a window another bitmatrix  to this one
    pub fn copy_from_window(&mut self, from: &Self, start_frame: usize, start_bit: usize) {
        for f in 0..self.frames {
            for b in 0..self.bits {
                self.data[f * self.bits + b] =
                    from.data[(f + start_frame) * from.bits + (b + start_bit)];
            }
        }
    }
    // Get a list of the differences
    // as a tuple (frame, bit, new value)
    pub fn delta(&self, base: &Self) -> Vec<(usize, usize, bool)> {
        base.data
            .iter()
            .zip(self.data.iter())
            .enumerate()
            .filter_map(|(i, (o, n))| {
                let f = i / self.bits;
                let b = i % self.bits;
                match (o, n) {
                    (false, true) => Some((f, b, true)),  // going high
                    (true, false) => Some((f, b, false)), // going low
                    _ => None,
                }
            })
            .collect()
    }
    // Pretty-print a list of frame-bits
    pub fn print(&self, mut out: &mut dyn Write) {
        for (i, _x) in self.data.iter().enumerate().filter(|(_i, x)| **x) {
            let f = i / self.bits;
            let b = i % self.bits;
            writeln!(&mut out, "F{}B{}", f, b).unwrap();
        }
    }
    // Return true if any bit is set
    pub fn any(&self) -> bool {
        return self.data.iter().any(|x| *x);
    }
}

pub struct Chip {
    // Family name
    pub family: String,
    // Device name
    pub device: String,
    // Device data
    pub data: DeviceData,
    // Entire main bitstream content
    pub cram: BitMatrix,
    // All of the tiles in the chip
    pub tiles: Vec<Tile>,
    // IP core and EBR configuration
    pub ipconfig: BTreeMap<u32, u32>,
    // Fast references to tiles
    tiles_by_name: HashMap<String, usize>,
    tiles_by_loc: MultiMap<(u32, u32), usize>,
    // Metadata (comment strings in bitstream)
    pub metadata: Vec<String>,
}

impl Chip {
    pub fn new(family: &str, device: &str, data: &DeviceData, tiles: &DeviceTilegrid) -> Chip {
        let mut c = Chip {
            family: family.to_string(),
            device: device.to_string(),
            data: data.clone(),
            cram: BitMatrix::new(data.frames, data.bits_per_frame),
            tiles: tiles
                .tiles
                .iter()
                .map(|(name, data)| Tile::new(name, data))
                .collect(),
            ipconfig: BTreeMap::new(),
            tiles_by_name: HashMap::new(),
            tiles_by_loc: MultiMap::new(),
            metadata: Vec::new(),
        };
        c.tiles_by_name = c
            .tiles
            .iter()
            .enumerate()
            .map(|(i, t)| (t.name.to_string(), i))
            .collect();
        c.tiles_by_loc = c
            .tiles
            .iter()
            .enumerate()
            .map(|(i, t)| ((t.x, t.y), i))
            .collect();
        c
    }
    // Create a new chip from the database based on IDCODE or name
    pub fn from_idcode(db: &mut Database, idcode: u32) -> Chip {
        let (fam, device, data) = db.device_by_idcode(idcode).expect(&format!(
            "no device in database with IDCODE {:08x}\n",
            idcode
        ));
        Chip::new(&fam, &device, &data, db.device_tilegrid(&fam, &device))
    }

    // Copy the whole-chip CRAM to the per-tile CRAM
    pub fn cram_to_tiles(&mut self) {
        for t in self.tiles.iter_mut() {
            t.cram
                .copy_from_window(&self.cram, t.start_frame, t.start_bit);
        }
    }
    // Copy the per-tile CRAM windows to the whole chip CRAM
    pub fn tiles_to_cram(&mut self) {
        for t in self.tiles.iter() {
            self.cram.copy_window(&t.cram, t.start_frame, t.start_bit);
        }
    }
    // Get a tile by name
    pub fn tile_by_name(&self, name: &str) -> Result<&Tile, &'static str> {
        match self.tiles_by_name.get(name) {
            None => {
                println!("no tile named {}", name);
                Err("unknown tile name")
            }
            Some(i) => Ok(&self.tiles[*i]),
        }
    }
    // Get a mutable tile by name
    pub fn tile_by_name_mut(&mut self, name: &str) -> Result<&mut Tile, &'static str> {
        match self.tiles_by_name.get(name) {
            None => {
                println!("no tile named {}", name);
                Err("unknown tile name")
            }
            Some(i) => Ok(&mut self.tiles[*i]),
        }
    }
    // Get all tiles at a location
    pub fn tiles_by_xy(&self, x: u32, y: u32) -> Vec<&Tile> {
        match self.tiles_by_loc.get_vec(&(x, y)) {
            None => Vec::new(),
            Some(v) => v.iter().map(|i| &self.tiles[*i]).collect(),
        }
    }
    // Compare two chips
    pub fn delta(&self, base: &Self) -> BTreeMap<String, Vec<(usize, usize, bool)>> {
        base.tiles
            .iter()
            .zip(self.tiles.iter())
            .map(|(t1, t2)| {
                assert_eq!(t1.name, t2.name);
                (t1.name.to_string(), t2.cram.delta(&t1.cram))
            })
            .filter(|(_k, v)| v.len() > 0)
            .collect()
    }
    // Dump chip to a simple text format for debugging
    pub fn print(&self, mut out: &mut dyn Write) {
        writeln!(&mut out, ".device {}", self.device).unwrap();
        for m in self.metadata.iter() {
            writeln!(&mut out, ".metadata {}", m).unwrap();
        }
        for t in self.tiles.iter() {
            t.print(&mut out);
        }
        for (addr, data) in self.ipconfig.iter() {
            writeln!(&mut out, ".write 0x{:08x} 0x{:08x}", addr, data).unwrap();
        }
    }
    // Convert frame address to flat frame index
    pub fn frame_addr_to_idx(&self, addr: u32) -> usize {
        match addr {
            0x0000..=0x7FFF => (self.cram.frames - 1) - (addr as usize),
            0x8000..=0x800F => (addr - 0x8000) as usize, // left side IO
            0x8010..=0x801F => ((addr - 0x8010) as usize) + 40, // right side IO
            0x8020..=0x8037 => ((addr - 0x8020) as usize) + 16, // TAPs (row-segment clocking)
            _ => panic!("unable to process frame address 0x{:08x}", addr),
        }
    }
}

// Actual instance of a tile
pub struct Tile {
    pub name: String,
    pub tiletype: String,
    pub x: u32,
    pub y: u32,
    pub start_bit: usize,
    pub start_frame: usize,
    pub cram: BitMatrix,
}

impl Tile {
    pub fn new(name: &str, data: &TileData) -> Tile {
        Tile {
            name: name.to_string(),
            tiletype: data.tiletype.to_string(),
            x: data.x,
            y: data.y,
            start_bit: data.start_bit,
            start_frame: data.start_frame,
            cram: BitMatrix::new(data.frames, data.bits),
        }
    }
    pub fn print(&self, mut out: &mut dyn Write) {
        if self.cram.any() {
            writeln!(&mut out, ".tile {}:{}", self.name, self.tiletype).unwrap();
            self.cram.print(&mut out);
        }
    }
}
<commit_msg>Fix edge tile addressing<commit_after>use crate::database::*;
use multimap::MultiMap;
use std::collections::{BTreeMap, HashMap};
use std::io::Write;

// 2D bit array
pub struct BitMatrix {
    pub frames: usize,
    pub bits: usize,
    data: Vec<bool>,
}

impl BitMatrix {
    // Create new empty bitmatrix
    pub fn new(frames: usize, bits: usize) -> BitMatrix {
        BitMatrix {
            frames: frames,
            bits: bits,
            data: vec![false; frames * bits],
        }
    }
    // Getting and setting bits
    pub fn get(&self, frame: usize, bit: usize) -> bool {
        self.data[frame * self.bits + bit]
    }
    pub fn set(&mut self, frame: usize, bit: usize, val: bool) {
        self.data[frame * self.bits + bit] = val
    }
    // Copy another bitmatrix to a window of this one
    pub fn copy_window(&mut self, from: &Self, start_frame: usize, start_bit: usize) {
        for f in 0..from.frames {
            for b in 0..from.bits {
                self.data[(f + start_frame) * self.bits + (b + start_bit)] =
                    from.data[f * from.bits + b];
            }
        }
    }
    // Copy a window another bitmatrix  to this one
    pub fn copy_from_window(&mut self, from: &Self, start_frame: usize, start_bit: usize) {
        for f in 0..self.frames {
            for b in 0..self.bits {
                self.data[f * self.bits + b] =
                    from.data[(f + start_frame) * from.bits + (b + start_bit)];
            }
        }
    }
    // Get a list of the differences
    // as a tuple (frame, bit, new value)
    pub fn delta(&self, base: &Self) -> Vec<(usize, usize, bool)> {
        base.data
            .iter()
            .zip(self.data.iter())
            .enumerate()
            .filter_map(|(i, (o, n))| {
                let f = i / self.bits;
                let b = i % self.bits;
                match (o, n) {
                    (false, true) => Some((f, b, true)),  // going high
                    (true, false) => Some((f, b, false)), // going low
                    _ => None,
                }
            })
            .collect()
    }
    // Pretty-print a list of frame-bits
    pub fn print(&self, mut out: &mut dyn Write) {
        for (i, _x) in self.data.iter().enumerate().filter(|(_i, x)| **x) {
            let f = i / self.bits;
            let b = i % self.bits;
            writeln!(&mut out, "F{}B{}", f, b).unwrap();
        }
    }
    // Return true if any bit is set
    pub fn any(&self) -> bool {
        return self.data.iter().any(|x| *x);
    }
}

pub struct Chip {
    // Family name
    pub family: String,
    // Device name
    pub device: String,
    // Device data
    pub data: DeviceData,
    // Entire main bitstream content
    pub cram: BitMatrix,
    // All of the tiles in the chip
    pub tiles: Vec<Tile>,
    // IP core and EBR configuration
    pub ipconfig: BTreeMap<u32, u32>,
    // Fast references to tiles
    tiles_by_name: HashMap<String, usize>,
    tiles_by_loc: MultiMap<(u32, u32), usize>,
    // Metadata (comment strings in bitstream)
    pub metadata: Vec<String>,
}

impl Chip {
    pub fn new(family: &str, device: &str, data: &DeviceData, tiles: &DeviceTilegrid) -> Chip {
        let mut c = Chip {
            family: family.to_string(),
            device: device.to_string(),
            data: data.clone(),
            cram: BitMatrix::new(data.frames, data.bits_per_frame),
            tiles: tiles
                .tiles
                .iter()
                .map(|(name, data)| Tile::new(name, data))
                .collect(),
            ipconfig: BTreeMap::new(),
            tiles_by_name: HashMap::new(),
            tiles_by_loc: MultiMap::new(),
            metadata: Vec::new(),
        };
        c.tiles_by_name = c
            .tiles
            .iter()
            .enumerate()
            .map(|(i, t)| (t.name.to_string(), i))
            .collect();
        c.tiles_by_loc = c
            .tiles
            .iter()
            .enumerate()
            .map(|(i, t)| ((t.x, t.y), i))
            .collect();
        c
    }
    // Create a new chip from the database based on IDCODE or name
    pub fn from_idcode(db: &mut Database, idcode: u32) -> Chip {
        let (fam, device, data) = db.device_by_idcode(idcode).expect(&format!(
            "no device in database with IDCODE {:08x}\n",
            idcode
        ));
        Chip::new(&fam, &device, &data, db.device_tilegrid(&fam, &device))
    }

    // Copy the whole-chip CRAM to the per-tile CRAM
    pub fn cram_to_tiles(&mut self) {
        for t in self.tiles.iter_mut() {
            t.cram
                .copy_from_window(&self.cram, t.start_frame, t.start_bit);
        }
    }
    // Copy the per-tile CRAM windows to the whole chip CRAM
    pub fn tiles_to_cram(&mut self) {
        for t in self.tiles.iter() {
            self.cram.copy_window(&t.cram, t.start_frame, t.start_bit);
        }
    }
    // Get a tile by name
    pub fn tile_by_name(&self, name: &str) -> Result<&Tile, &'static str> {
        match self.tiles_by_name.get(name) {
            None => {
                println!("no tile named {}", name);
                Err("unknown tile name")
            }
            Some(i) => Ok(&self.tiles[*i]),
        }
    }
    // Get a mutable tile by name
    pub fn tile_by_name_mut(&mut self, name: &str) -> Result<&mut Tile, &'static str> {
        match self.tiles_by_name.get(name) {
            None => {
                println!("no tile named {}", name);
                Err("unknown tile name")
            }
            Some(i) => Ok(&mut self.tiles[*i]),
        }
    }
    // Get all tiles at a location
    pub fn tiles_by_xy(&self, x: u32, y: u32) -> Vec<&Tile> {
        match self.tiles_by_loc.get_vec(&(x, y)) {
            None => Vec::new(),
            Some(v) => v.iter().map(|i| &self.tiles[*i]).collect(),
        }
    }
    // Compare two chips
    pub fn delta(&self, base: &Self) -> BTreeMap<String, Vec<(usize, usize, bool)>> {
        base.tiles
            .iter()
            .zip(self.tiles.iter())
            .map(|(t1, t2)| {
                assert_eq!(t1.name, t2.name);
                (t1.name.to_string(), t2.cram.delta(&t1.cram))
            })
            .filter(|(_k, v)| v.len() > 0)
            .collect()
    }
    // Dump chip to a simple text format for debugging
    pub fn print(&self, mut out: &mut dyn Write) {
        writeln!(&mut out, ".device {}", self.device).unwrap();
        for m in self.metadata.iter() {
            writeln!(&mut out, ".metadata {}", m).unwrap();
        }
        for t in self.tiles.iter() {
            t.print(&mut out);
        }
        for (addr, data) in self.ipconfig.iter() {
            writeln!(&mut out, ".write 0x{:08x} 0x{:08x}", addr, data).unwrap();
        }
    }
    // Convert frame address to flat frame index
    pub fn frame_addr_to_idx(&self, addr: u32) -> usize {
        match addr {
            0x0000..=0x7FFF => (self.cram.frames - 1) - (addr as usize),
            0x8000..=0x800F => (15 - ((addr - 0x8000) as usize)) + 40, // right side IO
            0x8010..=0x801F => (15 - ((addr - 0x8010) as usize)) + 0,  // left side IO
            0x8020..=0x8037 => ((addr - 0x8020) as usize) + 16, // TAPs (row-segment clocking)
            _ => panic!("unable to process frame address 0x{:08x}", addr),
        }
    }
}

// Actual instance of a tile
pub struct Tile {
    pub name: String,
    pub tiletype: String,
    pub x: u32,
    pub y: u32,
    pub start_bit: usize,
    pub start_frame: usize,
    pub cram: BitMatrix,
}

impl Tile {
    pub fn new(name: &str, data: &TileData) -> Tile {
        Tile {
            name: name.to_string(),
            tiletype: data.tiletype.to_string(),
            x: data.x,
            y: data.y,
            start_bit: data.start_bit,
            start_frame: data.start_frame,
            cram: BitMatrix::new(data.frames, data.bits),
        }
    }
    pub fn print(&self, mut out: &mut dyn Write) {
        if self.cram.any() {
            writeln!(&mut out, ".tile {}:{}", self.name, self.tiletype).unwrap();
            self.cram.print(&mut out);
        }
    }
}
<|endoftext|>


<commit_before>use string::{String, ToString};
use vec::Vec;

use syscall::{sys_clone, sys_execve, sys_spawnve, sys_exit, sys_waitpid};
use syscall::common::{CLONE_VM, CLONE_VFORK};

pub struct ExitStatus {
    status: usize
}

impl ExitStatus {
    pub fn success(&self) -> bool {
        self.status == 0
    }

    pub fn code(&self) -> Option<i32> {
        Some(self.status as i32)
    }
}

pub struct Child {
    pid: isize
}

impl Child {
    pub fn id(&self) -> u32 {
        self.pid as u32
    }

    pub fn wait(&mut self) -> Option<ExitStatus> {
        let mut status: usize = 0;
        if unsafe { sys_waitpid(self.pid, &mut status, 0) } as isize >= 0 {
            Some(ExitStatus {
                status: status
            })
        } else {
            None
        }
    }
}

pub struct Command {
    pub path: String,
    pub args: Vec<String>
}

impl Command {
    pub fn new(path: &str) -> Command {
        Command {
            path: path.to_string(),
            args: Vec::new()
        }
    }

    pub fn arg(&mut self, arg: &str) -> &mut Command {
        self.args.push(arg.to_string());
        self
    }

    pub fn spawn(&mut self) -> Option<Child> {
        let pid = unsafe { sys_clone(CLONE_VM | CLONE_VFORK) } as isize;
        if pid == 0 {
            let path_c = self.path.to_string() + "\0";

            let mut args_vec: Vec<String> = Vec::new();
            for arg in self.args.iter() {
                args_vec.push(arg.to_string() + "\0");
            }

            let mut args_c: Vec<*const u8> = Vec::new();
            for arg_vec in args_vec.iter() {
                args_c.push(arg_vec.as_ptr());
            }
            args_c.push(0 as *const u8);

            unsafe {
                sys_execve(path_c.as_ptr(), args_c.as_ptr());
                sys_exit(127);
            }
            None
        } else if pid > 0 {
            Some(Child {
                pid: pid
            })
        } else {
            None
        }
    }

    pub fn spawn_scheme(&mut self) -> Option<Child> {
        let path_c = self.path.to_string() + "\0";

        let mut args_vec: Vec<String> = Vec::new();
        for arg in self.args.iter() {
            args_vec.push(arg.to_string() + "\0");
        }

        let mut args_c: Vec<*const u8> = Vec::new();
        for arg_vec in args_vec.iter() {
            args_c.push(arg_vec.as_ptr());
        }
        args_c.push(0 as *const u8);

        let pid = unsafe { sys_spawnve(path_c.as_ptr(), args_c.as_ptr()) } as isize;
        if pid > 0 {
            Some(Child {
                pid: pid
            })
        } else {
            None
        }
    }
}
<commit_msg>Drop ptrs to args after execve<commit_after>use string::{String, ToString};
use vec::Vec;

use syscall::{sys_clone, sys_execve, sys_spawnve, sys_exit, sys_waitpid};
use syscall::common::{CLONE_VM, CLONE_VFORK};

pub struct ExitStatus {
    status: usize
}

impl ExitStatus {
    pub fn success(&self) -> bool {
        self.status == 0
    }

    pub fn code(&self) -> Option<i32> {
        Some(self.status as i32)
    }
}

pub struct Child {
    pid: isize
}

impl Child {
    pub fn id(&self) -> u32 {
        self.pid as u32
    }

    pub fn wait(&mut self) -> Option<ExitStatus> {
        let mut status: usize = 0;
        if unsafe { sys_waitpid(self.pid, &mut status, 0) } as isize >= 0 {
            Some(ExitStatus {
                status: status
            })
        } else {
            None
        }
    }
}

pub struct Command {
    pub path: String,
    pub args: Vec<String>
}

impl Command {
    pub fn new(path: &str) -> Command {
        Command {
            path: path.to_string(),
            args: Vec::new()
        }
    }

    pub fn arg(&mut self, arg: &str) -> &mut Command {
        self.args.push(arg.to_string());
        self
    }

    pub fn spawn(&mut self) -> Option<Child> {
        let path_c = self.path.to_string() + "\0";

        let mut args_vec: Vec<String> = Vec::new();
        for arg in self.args.iter() {
            args_vec.push(arg.to_string() + "\0");
        }

        let mut args_c: Vec<*const u8> = Vec::new();
        for arg_vec in args_vec.iter() {
            args_c.push(arg_vec.as_ptr());
        }
        args_c.push(0 as *const u8);

        let pid = unsafe { sys_clone(CLONE_VM | CLONE_VFORK) } as isize;
        if pid == 0 {
            unsafe {
                sys_execve(path_c.as_ptr(), args_c.as_ptr());
                sys_exit(127);
            }
            None
        } else if pid > 0 {
            Some(Child {
                pid: pid
            })
        } else {
            None
        }
    }

    pub fn spawn_scheme(&mut self) -> Option<Child> {
        let path_c = self.path.to_string() + "\0";

        let mut args_vec: Vec<String> = Vec::new();
        for arg in self.args.iter() {
            args_vec.push(arg.to_string() + "\0");
        }

        let mut args_c: Vec<*const u8> = Vec::new();
        for arg_vec in args_vec.iter() {
            args_c.push(arg_vec.as_ptr());
        }
        args_c.push(0 as *const u8);

        let pid = unsafe { sys_spawnve(path_c.as_ptr(), args_c.as_ptr()) } as isize;
        if pid > 0 {
            Some(Child {
                pid: pid
            })
        } else {
            None
        }
    }
}
<|endoftext|>


<commit_before>// Copyright 2018 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

use pci::PciInterruptPin;

// The number of 32bit registers in the config space, 256 bytes.
const NUM_CONFIGURATION_REGISTERS: usize = 64;

const BAR0_REG: usize = 4;
const BAR_IO_ADDR_MASK: u32 = 0xffff_fffc;
const BAR_IO_BIT: u32 = 0x0000_0001;
const BAR_MEM_ADDR_MASK: u32 = 0xffff_fff0;
const NUM_BAR_REGS: usize = 6;

const INTERRUPT_LINE_PIN_REG: usize = 15;

/// Represents the types of PCI headers allowed in the configuration registers.
#[derive(Copy, Clone)]
pub enum PciHeaderType {
    Device,
    Bridge,
}

/// Classes of PCI nodes.
#[allow(dead_code)]
#[derive(Copy, Clone)]
pub enum PciClassCode {
    TooOld,
    MassStorage,
    NetworkController,
    DisplayController,
    MultimediaController,
    MemoryController,
    BridgeDevice,
    SimpleCommunicationController,
    BaseSystemPeripheral,
    InputDevice,
    DockingStation,
    Processor,
    SerialBusController,
    WirelessController,
    IntelligentIoController,
    EncryptionController,
    DataAcquisitionSignalProcessing,
    Other = 0xff,
}

impl PciClassCode {
    pub fn get_register_value(&self) -> u8 {
        *self as u8
    }
}

/// A PCI sublcass. Each class in `PciClassCode` can specify a unique set of subclasses. This trait
/// is implemented by each subclass. It allows use of a trait object to generate configurations.
pub trait PciSubclass {
    /// Convert this subclass to the value used in the PCI specification.
    fn get_register_value(&self) -> u8;
}

/// Subclasses of the MultimediaController class.
#[allow(dead_code)]
#[derive(Copy, Clone)]
pub enum PciMultimediaSubclass {
    VideoController = 0x00,
    AudioController = 0x01,
    TelephonyDevice = 0x02,
    AudioDevice = 0x03,
    Other = 0x80,
}

impl PciSubclass for PciMultimediaSubclass {
    fn get_register_value(&self) -> u8 {
        *self as u8
    }
}

/// Subclasses of the BridgeDevice
#[allow(dead_code)]
#[derive(Copy, Clone)]
pub enum PciBridgeSubclass {
    HostBridge = 0x00,
    IsaBridge = 0x01,
    EisaBridge = 0x02,
    McaBridge = 0x03,
    PciToPciBridge = 0x04,
    PcmciaBridge = 0x05,
    NuBusBridge = 0x06,
    CardBusBridge = 0x07,
    RACEwayBridge = 0x08,
    PciToPciSemiTransparentBridge = 0x09,
    InfiniBrandToPciHostBridge = 0x0a,
    OtherBridgeDevice = 0x80,
}

impl PciSubclass for PciBridgeSubclass {
    fn get_register_value(&self) -> u8 {
        *self as u8
    }
}

/// Subclass of the SerialBus
#[allow(dead_code)]
#[derive(Copy, Clone)]
pub enum PciSerialBusSubClass {
    Firewire = 0x00,
    ACCESSbus = 0x01,
    SSA = 0x02,
    USB = 0x03,
}

impl PciSubclass for PciSerialBusSubClass {
    fn get_register_value(&self) -> u8 {
        *self as u8
    }
}

/// Contains the configuration space of a PCI node.
/// See the [specification](https://en.wikipedia.org/wiki/PCI_configuration_space).
/// The configuration space is accessed with DWORD reads and writes from the guest.
pub struct PciConfiguration {
    registers: [u32; NUM_CONFIGURATION_REGISTERS],
    writable_bits: [u32; NUM_CONFIGURATION_REGISTERS], // writable bits for each register.
    num_bars: usize,
}

impl PciConfiguration {
    pub fn new(
        vendor_id: u16,
        device_id: u16,
        class_code: PciClassCode,
        subclass: &PciSubclass,
        header_type: PciHeaderType,
    ) -> Self {
        let mut registers = [0u32; NUM_CONFIGURATION_REGISTERS];
        registers[0] = u32::from(device_id) << 16 | u32::from(vendor_id);
        registers[2] = u32::from(class_code.get_register_value()) << 24
            | u32::from(subclass.get_register_value()) << 16;
        match header_type {
            PciHeaderType::Device => (),
            PciHeaderType::Bridge => registers[3] = 0x0001_0000,
        };
        PciConfiguration {
            registers,
            writable_bits: [0xffff_ffff; NUM_CONFIGURATION_REGISTERS],
            num_bars: 0,
        }
    }

    /// Reads a 32bit register from `reg_idx` in the register map.
    pub fn read_reg(&self, reg_idx: usize) -> u32 {
        *(self.registers.get(reg_idx).unwrap_or(&0xffff_ffff))
    }

    /// Writes a 32bit register to `reg_idx` in the register map.
    pub fn write_reg(&mut self, reg_idx: usize, value: u32) {
        if let Some(r) = self.registers.get_mut(reg_idx) {
            *r = value & self.writable_bits[reg_idx];
        } else {
            warn!("bad PCI register write {}", reg_idx);
        }
    }

    /// Writes a 16bit word to `offset`. `offset` must be 16bit aligned.
    pub fn write_word(&mut self, offset: usize, value: u16) {
        let shift = match offset % 4 {
            0 => 0,
            2 => 16,
            _ => {
                warn!("bad PCI config write offset {}", offset);
                return;
            }
        };
        let reg_idx = offset / 4;

        if let Some(r) = self.registers.get_mut(reg_idx) {
            let writable_mask = self.writable_bits[reg_idx];
            let mask = (0xffffu32 << shift) & writable_mask;
            let shifted_value = (u32::from(value) << shift) & writable_mask;
            *r = *r & !mask | shifted_value;
        } else {
            warn!("bad PCI config write offset {}", offset);
        }
    }

    /// Writes a byte to `offset`.
    pub fn write_byte(&mut self, offset: usize, value: u8) {
        let shift = (offset % 4) * 8;
        let reg_idx = offset / 4;

        if let Some(r) = self.registers.get_mut(reg_idx) {
            let writable_mask = self.writable_bits[reg_idx];
            let mask = (0xffu32 << shift) & writable_mask;
            let shifted_value = (u32::from(value) << shift) & writable_mask;
            *r = *r & !mask | shifted_value;
        } else {
            warn!("bad PCI config write offset {}", offset);
        }
    }

    // Add either an IO or memory region, depending on `mem_type` mask, which is ORed in to the
    // value before saving it.
    fn add_bar(&mut self, addr: u64, size: u64, addr_mask: u32, mem_type: u32) -> Option<usize> {
        if self.num_bars >= NUM_BAR_REGS {
            return None;
        }
        if size.count_ones() != 1 {
            return None;
        }

        // TODO(dgreid) Allow 64 bit address and size.
        if addr.checked_add(size)? > u64::from(u32::max_value()) {
                return None;
        }

        let bar_idx = BAR0_REG + self.num_bars;

        self.registers[bar_idx] = addr as u32 & addr_mask | mem_type;
        // The first writable bit represents the size of the region.
        self.writable_bits[bar_idx] = !(size - 1) as u32;

        self.num_bars += 1;
        Some(bar_idx)
    }

    /// Adds a memory region of `size` at `addr`. Configures the next available BAR register to
    /// report this region and size to the guest kernel. Returns 'None' if all BARs are full, or
    /// `Some(BarIndex)` on success. `size` must be a power of 2.
    pub fn add_memory_region(&mut self, addr: u64, size: u64) -> Option<usize> {
        self.add_bar(addr, size, BAR_MEM_ADDR_MASK, 0)
    }

    /// Adds an IO region of `size` at `addr`. Configures the next available BAR register to
    /// report this region and size to the guest kernel. Returns 'None' if all BARs are full, or
    /// `Some(BarIndex)` on success. `size` must be a power of 2.
    pub fn add_io_region(&mut self, addr: u64, size: u64) -> Option<usize> {
        self.add_bar(addr, size, BAR_IO_ADDR_MASK, BAR_IO_BIT)
    }

    /// Returns the address of the given BAR region.
    pub fn get_bar_addr(&self, bar_num: usize) -> u32 {
        let bar_idx = BAR0_REG + bar_num;

        self.registers[bar_idx] & BAR_MEM_ADDR_MASK
    }

    /// Configures the IRQ line and pin used by this device.
    pub fn set_irq(&mut self, line: u8, pin: PciInterruptPin) {
        // `pin` is 1-based in the pci config space.
        let pin_idx = (pin as u32) + 1;
        self.registers[INTERRUPT_LINE_PIN_REG] = (self.registers[INTERRUPT_LINE_PIN_REG]
            & 0xffff_0000) | (pin_idx << 8)
            | u32::from(line);
    }
}
<commit_msg>Add capabilities to PCI configuration space<commit_after>// Copyright 2018 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

use pci::PciInterruptPin;

// The number of 32bit registers in the config space, 256 bytes.
const NUM_CONFIGURATION_REGISTERS: usize = 64;

const STATUS_REG: usize = 1;
const STATUS_REG_CAPABILITIES_USED_MASK: u32 = 0x0000_0010;
const BAR0_REG: usize = 4;
const BAR_IO_ADDR_MASK: u32 = 0xffff_fffc;
const BAR_IO_BIT: u32 = 0x0000_0001;
const BAR_MEM_ADDR_MASK: u32 = 0xffff_fff0;
const NUM_BAR_REGS: usize = 6;
const CAPABILITY_LIST_HEAD_OFFSET: usize = 0x34;
const FIRST_CAPABILITY_OFFSET: usize = 0x40;
const CAPABILITY_MAX_OFFSET: usize = 192;

const INTERRUPT_LINE_PIN_REG: usize = 15;

/// Represents the types of PCI headers allowed in the configuration registers.
#[derive(Copy, Clone)]
pub enum PciHeaderType {
    Device,
    Bridge,
}

/// Classes of PCI nodes.
#[allow(dead_code)]
#[derive(Copy, Clone)]
pub enum PciClassCode {
    TooOld,
    MassStorage,
    NetworkController,
    DisplayController,
    MultimediaController,
    MemoryController,
    BridgeDevice,
    SimpleCommunicationController,
    BaseSystemPeripheral,
    InputDevice,
    DockingStation,
    Processor,
    SerialBusController,
    WirelessController,
    IntelligentIoController,
    EncryptionController,
    DataAcquisitionSignalProcessing,
    Other = 0xff,
}

impl PciClassCode {
    pub fn get_register_value(&self) -> u8 {
        *self as u8
    }
}

/// A PCI sublcass. Each class in `PciClassCode` can specify a unique set of subclasses. This trait
/// is implemented by each subclass. It allows use of a trait object to generate configurations.
pub trait PciSubclass {
    /// Convert this subclass to the value used in the PCI specification.
    fn get_register_value(&self) -> u8;
}

/// Subclasses of the MultimediaController class.
#[allow(dead_code)]
#[derive(Copy, Clone)]
pub enum PciMultimediaSubclass {
    VideoController = 0x00,
    AudioController = 0x01,
    TelephonyDevice = 0x02,
    AudioDevice = 0x03,
    Other = 0x80,
}

impl PciSubclass for PciMultimediaSubclass {
    fn get_register_value(&self) -> u8 {
        *self as u8
    }
}

/// Subclasses of the BridgeDevice
#[allow(dead_code)]
#[derive(Copy, Clone)]
pub enum PciBridgeSubclass {
    HostBridge = 0x00,
    IsaBridge = 0x01,
    EisaBridge = 0x02,
    McaBridge = 0x03,
    PciToPciBridge = 0x04,
    PcmciaBridge = 0x05,
    NuBusBridge = 0x06,
    CardBusBridge = 0x07,
    RACEwayBridge = 0x08,
    PciToPciSemiTransparentBridge = 0x09,
    InfiniBrandToPciHostBridge = 0x0a,
    OtherBridgeDevice = 0x80,
}

impl PciSubclass for PciBridgeSubclass {
    fn get_register_value(&self) -> u8 {
        *self as u8
    }
}

/// Subclass of the SerialBus
#[allow(dead_code)]
#[derive(Copy, Clone)]
pub enum PciSerialBusSubClass {
    Firewire = 0x00,
    ACCESSbus = 0x01,
    SSA = 0x02,
    USB = 0x03,
}

impl PciSubclass for PciSerialBusSubClass {
    fn get_register_value(&self) -> u8 {
        *self as u8
    }
}

/// Types of PCI capabilities.
pub enum PciCapabilityID {
    ListID = 0,
    PowerManagement = 0x01,
    AcceleratedGraphicsPort = 0x02,
    VitalProductData = 0x03,
    SlotIdentification = 0x04,
    MessageSignalledInterrupts = 0x05,
    CompactPCIHotSwap = 0x06,
    PCIX = 0x07,
    HyperTransport = 0x08,
    VendorSpecific = 0x09,
    Debugport = 0x0A,
    CompactPCICentralResourceControl = 0x0B,
    PCIStandardHotPlugController = 0x0C,
    BridgeSubsystemVendorDeviceID = 0x0D,
    AGPTargetPCIPCIbridge = 0x0E,
    SecureDevice = 0x0F,
    PCIExpress = 0x10,
    MSIX = 0x11,
    SATADataIndexConf = 0x12,
    PCIAdvancedFeatures = 0x13,
    PCIEnhancedAllocation = 0x14,
}

/// A PCI capability list. Devices can optionally specify capabilities in their configuration space.
pub trait PciCapability {
    fn bytes(&self) -> &[u8];
    fn id(&self) -> PciCapabilityID;
}

/// Contains the configuration space of a PCI node.
/// See the [specification](https://en.wikipedia.org/wiki/PCI_configuration_space).
/// The configuration space is accessed with DWORD reads and writes from the guest.
pub struct PciConfiguration {
    registers: [u32; NUM_CONFIGURATION_REGISTERS],
    writable_bits: [u32; NUM_CONFIGURATION_REGISTERS], // writable bits for each register.
    num_bars: usize,
    // Contains the byte offset and size of the last capability.
    last_capability: Option<(usize, usize)>,
}

impl PciConfiguration {
    pub fn new(
        vendor_id: u16,
        device_id: u16,
        class_code: PciClassCode,
        subclass: &PciSubclass,
        header_type: PciHeaderType,
    ) -> Self {
        let mut registers = [0u32; NUM_CONFIGURATION_REGISTERS];
        registers[0] = u32::from(device_id) << 16 | u32::from(vendor_id);
        registers[2] = u32::from(class_code.get_register_value()) << 24
            | u32::from(subclass.get_register_value()) << 16;
        match header_type {
            PciHeaderType::Device => (),
            PciHeaderType::Bridge => registers[3] = 0x0001_0000,
        };
        PciConfiguration {
            registers,
            writable_bits: [0xffff_ffff; NUM_CONFIGURATION_REGISTERS],
            num_bars: 0,
            last_capability: None,
        }
    }

    /// Reads a 32bit register from `reg_idx` in the register map.
    pub fn read_reg(&self, reg_idx: usize) -> u32 {
        *(self.registers.get(reg_idx).unwrap_or(&0xffff_ffff))
    }

    /// Writes a 32bit register to `reg_idx` in the register map.
    pub fn write_reg(&mut self, reg_idx: usize, value: u32) {
        if let Some(r) = self.registers.get_mut(reg_idx) {
            *r = value & self.writable_bits[reg_idx];
        } else {
            warn!("bad PCI register write {}", reg_idx);
        }
    }

    /// Writes a 16bit word to `offset`. `offset` must be 16bit aligned.
    pub fn write_word(&mut self, offset: usize, value: u16) {
        let shift = match offset % 4 {
            0 => 0,
            2 => 16,
            _ => {
                warn!("bad PCI config write offset {}", offset);
                return;
            }
        };
        let reg_idx = offset / 4;

        if let Some(r) = self.registers.get_mut(reg_idx) {
            let writable_mask = self.writable_bits[reg_idx];
            let mask = (0xffffu32 << shift) & writable_mask;
            let shifted_value = (u32::from(value) << shift) & writable_mask;
            *r = *r & !mask | shifted_value;
        } else {
            warn!("bad PCI config write offset {}", offset);
        }
    }

    /// Writes a byte to `offset`.
    pub fn write_byte(&mut self, offset: usize, value: u8) {
        let shift = (offset % 4) * 8;
        let reg_idx = offset / 4;

        if let Some(r) = self.registers.get_mut(reg_idx) {
            let writable_mask = self.writable_bits[reg_idx];
            let mask = (0xffu32 << shift) & writable_mask;
            let shifted_value = (u32::from(value) << shift) & writable_mask;
            *r = *r & !mask | shifted_value;
        } else {
            warn!("bad PCI config write offset {}", offset);
        }
    }

    // Add either an IO or memory region, depending on `mem_type` mask, which is ORed in to the
    // value before saving it.
    fn add_bar(&mut self, addr: u64, size: u64, addr_mask: u32, mem_type: u32) -> Option<usize> {
        if self.num_bars >= NUM_BAR_REGS {
            return None;
        }
        if size.count_ones() != 1 {
            return None;
        }

        // TODO(dgreid) Allow 64 bit address and size.
        if addr.checked_add(size)? > u64::from(u32::max_value()) {
                return None;
        }

        let bar_idx = BAR0_REG + self.num_bars;

        self.registers[bar_idx] = addr as u32 & addr_mask | mem_type;
        // The first writable bit represents the size of the region.
        self.writable_bits[bar_idx] = !(size - 1) as u32;

        self.num_bars += 1;
        Some(bar_idx)
    }

    /// Adds a memory region of `size` at `addr`. Configures the next available BAR register to
    /// report this region and size to the guest kernel. Returns 'None' if all BARs are full, or
    /// `Some(BarIndex)` on success. `size` must be a power of 2.
    pub fn add_memory_region(&mut self, addr: u64, size: u64) -> Option<usize> {
        self.add_bar(addr, size, BAR_MEM_ADDR_MASK, 0)
    }

    /// Adds an IO region of `size` at `addr`. Configures the next available BAR register to
    /// report this region and size to the guest kernel. Returns 'None' if all BARs are full, or
    /// `Some(BarIndex)` on success. `size` must be a power of 2.
    pub fn add_io_region(&mut self, addr: u64, size: u64) -> Option<usize> {
        self.add_bar(addr, size, BAR_IO_ADDR_MASK, BAR_IO_BIT)
    }

    /// Returns the address of the given BAR region.
    pub fn get_bar_addr(&self, bar_num: usize) -> u32 {
        let bar_idx = BAR0_REG + bar_num;

        self.registers[bar_idx] & BAR_MEM_ADDR_MASK
    }

    /// Configures the IRQ line and pin used by this device.
    pub fn set_irq(&mut self, line: u8, pin: PciInterruptPin) {
        // `pin` is 1-based in the pci config space.
        let pin_idx = (pin as u32) + 1;
        self.registers[INTERRUPT_LINE_PIN_REG] = (self.registers[INTERRUPT_LINE_PIN_REG]
            & 0xffff_0000) | (pin_idx << 8)
            | u32::from(line);
    }

    /// Adds the capability `cap_data` to the list of capabilities.
    /// `cap_data` should include the three byte PCI capability header: type, next, length.
    pub fn add_capability(&mut self, cap_data: &PciCapability) -> Option<usize> {
        let total_len = cap_data.bytes().len() + 2;
        // Check that the length is valid.
        if cap_data.bytes().len() < 1 {
            return None;
        }
        let (cap_offset, tail_offset) = match self.last_capability {
            Some((offset, len)) => (Self::next_dword(offset, len), offset + 1),
            None => (FIRST_CAPABILITY_OFFSET, CAPABILITY_LIST_HEAD_OFFSET),
        };
        if cap_offset.checked_add(cap_data.bytes().len() + 2)? > CAPABILITY_MAX_OFFSET {
            return None;
        }
        self.registers[STATUS_REG] |= STATUS_REG_CAPABILITIES_USED_MASK;
        self.write_byte(tail_offset, cap_offset as u8);
        self.write_byte(cap_offset, cap_data.id() as u8);
        self.write_byte(cap_offset + 1, 0); // Next pointer.
        for (i, byte) in cap_data.bytes().iter().enumerate() {
            self.write_byte(cap_offset + i + 2, *byte);
        }
        self.last_capability = Some((cap_offset, total_len));
        Some(cap_offset)
    }

    // Find the next aligned offset after the one given.
    fn next_dword(offset: usize, len: usize) -> usize {
        let next = offset + len;
        (next + 3) & !3
    }
}
<|endoftext|>


<commit_before>// Copyright (c) Facebook, Inc. and its affiliates
// SPDX-License-Identifier: MIT OR Apache-2.0

use serde_generate::{
    swift, test_utils,
    test_utils::{Choice, Runtime, Test},
    CodeGeneratorConfig, SourceInstaller,
};
use std::{fs::File, io::Write, process::Command, sync::Mutex};

lazy_static::lazy_static! {
    // Avoid interleaving compiler calls because the output gets very messy.
    static ref MUTEX: Mutex<()> = Mutex::new(());
}

#[test]
fn test_swift_runtime_autotests() {
    let runtime_path = std::env::current_exe()
        .unwrap()
        .parent()
        .unwrap()
        .join("../../../serde-generate/runtime/swift");

    let status = Command::new("swift")
        .current_dir(runtime_path.to_str().unwrap())
        .arg("test")
        .status()
        .unwrap();
    assert!(status.success());
}

#[test]
fn test_swift_bcs_runtime_on_simple_data() {
    test_swift_runtime_on_simple_data(Runtime::Bcs);
}

#[test]
fn test_swift_bincode_runtime_on_simple_data() {
    test_swift_runtime_on_simple_data(Runtime::Bincode);
}

fn test_swift_runtime_on_simple_data(runtime: Runtime) {
    // To see the source, uncomment this and replace `dir.path()` by `my_path` below.
    // let my_path = std::path::Path::new("../test");
    // std::fs::remove_dir_all(my_path).unwrap_or(());
    // std::fs::create_dir_all(my_path).unwrap();
    let dir = tempfile::tempdir().unwrap();
    let config =
        CodeGeneratorConfig::new("Testing".to_string()).with_encodings(vec![runtime.into()]);
    let registry = test_utils::get_simple_registry().unwrap();
    let installer = swift::Installer::new(dir.path().to_path_buf());
    installer.install_module(&config, &registry).unwrap();
    installer.install_serde_runtime().unwrap(); // also installs bcs and bincode

    let reference = runtime.serialize(&Test {
        a: vec![4, 6],
        b: (-3, 5),
        c: Choice::C { x: 7 },
    });

    std::fs::create_dir_all(dir.path().join("Sources/main")).unwrap();
    let main_path = dir.path().join("Sources/main/main.swift");
    let mut main = File::create(main_path).unwrap();
    writeln!(
        main,
        r#"
import Serde
import Testing

var input : [UInt8] = [{0}]
let value = try Test.{1}Deserialize(input: input)

let value2 = Test.init(
    a: [4, 6],
    b: Tuple2.init(-3, 5),
    c: Choice.C(x: 7)
)
assert(value == value2, "value != value2")

let output = try value2.{1}Serialize()
assert(input == output, "input != output")

input += [0]
do {{
    let _ = try Test.{1}Deserialize(input: input)
    assertionFailure("Was expecting an error")
}}
catch {{}}

do {{
    let input2 : [UInt8] = [0, 1]
    let _ = try Test.{1}Deserialize(input: input2)
    assertionFailure("Was expecting an error")
}}
catch {{}}
"#,
        reference
            .iter()
            .map(|x| format!("{}", x))
            .collect::<Vec<_>>()
            .join(", "),
        runtime.name(),
    )
    .unwrap();

    let mut file = File::create(dir.path().join("Package.swift")).unwrap();
    write!(
        file,
        r#"// swift-tools-version:5.3

import PackageDescription

let package = Package(
    name: "Testing",
    targets: [
        .target(
            name: "Serde",
            dependencies: []),
        .target(
            name: "Testing",
            dependencies: ["Serde"]),
        .target(
            name: "main",
            dependencies: ["Serde", "Testing"]
        ),
    ]
)
"#
    )
    .unwrap();

    {
        let _lock = MUTEX.lock().unwrap();
        let status = Command::new("swift")
            .current_dir(dir.path())
            .arg("run")
            .status()
            .unwrap();
        assert!(status.success());
    }
}
<commit_msg>[swift] make extended runtime tests pass for bincode<commit_after>// Copyright (c) Facebook, Inc. and its affiliates
// SPDX-License-Identifier: MIT OR Apache-2.0

use serde_generate::{
    swift, test_utils,
    test_utils::{Choice, Runtime, Test},
    CodeGeneratorConfig, SourceInstaller,
};
use std::{fs::File, io::Write, process::Command, sync::Mutex};

lazy_static::lazy_static! {
    // Avoid interleaving compiler calls because the output gets very messy.
    static ref MUTEX: Mutex<()> = Mutex::new(());
}

#[test]
fn test_swift_runtime_autotests() {
    let runtime_path = std::env::current_exe()
        .unwrap()
        .parent()
        .unwrap()
        .join("../../../serde-generate/runtime/swift");

    let status = Command::new("swift")
        .current_dir(runtime_path.to_str().unwrap())
        .arg("test")
        .status()
        .unwrap();
    assert!(status.success());
}

#[test]
fn test_swift_bcs_runtime_on_simple_data() {
    test_swift_runtime_on_simple_data(Runtime::Bcs);
}

#[test]
fn test_swift_bincode_runtime_on_simple_data() {
    test_swift_runtime_on_simple_data(Runtime::Bincode);
}

fn test_swift_runtime_on_simple_data(runtime: Runtime) {
    // To see the source, uncomment this and replace `dir.path()` by `my_path` below.
    // let my_path = std::path::Path::new("../test");
    // std::fs::remove_dir_all(my_path).unwrap_or(());
    // std::fs::create_dir_all(my_path).unwrap();
    let dir = tempfile::tempdir().unwrap();
    let config =
        CodeGeneratorConfig::new("Testing".to_string()).with_encodings(vec![runtime.into()]);
    let registry = test_utils::get_simple_registry().unwrap();
    let installer = swift::Installer::new(dir.path().to_path_buf());
    installer.install_module(&config, &registry).unwrap();
    installer.install_serde_runtime().unwrap(); // also installs bcs and bincode

    let reference = runtime.serialize(&Test {
        a: vec![4, 6],
        b: (-3, 5),
        c: Choice::C { x: 7 },
    });

    std::fs::create_dir_all(dir.path().join("Sources/main")).unwrap();
    let main_path = dir.path().join("Sources/main/main.swift");
    let mut main = File::create(main_path).unwrap();
    writeln!(
        main,
        r#"
import Serde
import Testing

var input : [UInt8] = [{0}]
let value = try Test.{1}Deserialize(input: input)

let value2 = Test.init(
    a: [4, 6],
    b: Tuple2.init(-3, 5),
    c: Choice.C(x: 7)
)
assert(value == value2, "value != value2")

let output = try value2.{1}Serialize()
assert(input == output, "input != output")

input += [0]
do {{
    let _ = try Test.{1}Deserialize(input: input)
    assertionFailure("Was expecting an error")
}}
catch {{}}

do {{
    let input2 : [UInt8] = [0, 1]
    let _ = try Test.{1}Deserialize(input: input2)
    assertionFailure("Was expecting an error")
}}
catch {{}}
"#,
        reference
            .iter()
            .map(|x| format!("{}", x))
            .collect::<Vec<_>>()
            .join(", "),
        runtime.name(),
    )
    .unwrap();

    let mut file = File::create(dir.path().join("Package.swift")).unwrap();
    write!(
        file,
        r#"// swift-tools-version:5.3

import PackageDescription

let package = Package(
    name: "Testing",
    targets: [
        .target(
            name: "Serde",
            dependencies: []),
        .target(
            name: "Testing",
            dependencies: ["Serde"]),
        .target(
            name: "main",
            dependencies: ["Serde", "Testing"]
        ),
    ]
)
"#
    )
    .unwrap();

    {
        let _lock = MUTEX.lock().unwrap();
        let status = Command::new("swift")
            .current_dir(dir.path())
            .arg("run")
            .status()
            .unwrap();
        assert!(status.success());
    }
}

#[test]
fn test_swift_bincode_runtime_on_supported_types() {
    test_swift_runtime_on_supported_types(Runtime::Bincode);
}

fn quote_bytes(bytes: &[u8]) -> String {
    format!(
        "[{}]",
        bytes
            .iter()
            .map(|x| format!("{}", x))
            .collect::<Vec<_>>()
            .join(", ")
    )
}

fn test_swift_runtime_on_supported_types(runtime: Runtime) {
    // To see the source, uncomment this and replace `dir.path()` by `my_path` below.
    // let my_path = std::path::Path::new("../test");
    // std::fs::remove_dir_all(my_path).unwrap_or(());
    // std::fs::create_dir_all(my_path).unwrap();
    let dir = tempfile::tempdir().unwrap();
    let config =
        CodeGeneratorConfig::new("Testing".to_string()).with_encodings(vec![runtime.into()]);
    let registry = test_utils::get_registry().unwrap();
    let installer = swift::Installer::new(dir.path().to_path_buf());
    installer.install_module(&config, &registry).unwrap();
    installer.install_serde_runtime().unwrap(); // also installs bcs and bincode

    std::fs::create_dir_all(dir.path().join("Sources/main")).unwrap();
    let main_path = dir.path().join("Sources/main/main.swift");
    let mut main = File::create(main_path).unwrap();

    let positive_encodings = runtime
        .get_positive_samples_quick()
        .iter()
        .map(|bytes| quote_bytes(bytes))
        .collect::<Vec<_>>()
        .join(", ");

    let negative_encodings = runtime
        .get_negative_samples()
        .iter()
        .map(|bytes| quote_bytes(bytes))
        .collect::<Vec<_>>()
        .join(", ");

    writeln!(
        main,
        r#"
import Serde
import Testing

let positive_inputs : [[UInt8]] = [{0}]
let negative_inputs : [[UInt8]] = [{1}]

for input in positive_inputs {{
    let value = try SerdeData.{2}Deserialize(input: input)
    let output = try value.{2}Serialize()
    assert(input == output, "input != output:\n  \(input)\n  \(output)")

    // Test self-equality for the Serde value.
    let value2 = try SerdeData.{2}Deserialize(input: input)
    assert(value == value2, "Deserialized value should test equal to itself: \(input)")

    // Test simple mutations of the input.
    for i in 0..<min(40, input.count) {{
        var input3 = input
        input3[i] ^= 0x80
        let value3 = try? SerdeData.{2}Deserialize(input: input3)
        if let value3 = value3 {{
            assert(value3 != value, "Modified input should give a different value:\n  \(input)\n  \(input3)")
        }}
    }}

}}

for input in negative_inputs {{
    if let _ = try? SerdeData.{2}Deserialize(input: input) {{
        assertionFailure("Input should fail to deserialize: \(input)")
    }}
}}
"#,
        positive_encodings,
        negative_encodings,
        runtime.name(),
    )
    .unwrap();

    let mut file = File::create(dir.path().join("Package.swift")).unwrap();
    write!(
        file,
        r#"// swift-tools-version:5.3

import PackageDescription

let package = Package(
    name: "Testing",
    targets: [
        .target(
            name: "Serde",
            dependencies: []),
        .target(
            name: "Testing",
            dependencies: ["Serde"]),
        .target(
            name: "main",
            dependencies: ["Serde", "Testing"]
        ),
    ]
)
"#
    )
    .unwrap();

    {
        let _lock = MUTEX.lock().unwrap();
        let status = Command::new("swift")
            .current_dir(dir.path())
            .arg("run")
            .status()
            .unwrap();
        assert!(status.success());
    }
}
<|endoftext|>


<commit_before>//! Dummy frontend that does nothing.

use frontend_api::{FrontendAction, Renderer, AudioSink};

/// Renderer that just does nothing.
#[derive(Default)]
pub struct DummyRenderer;

impl Renderer for DummyRenderer {
    fn render(&mut self, _frame_data: &[u8]) -> Option<FrontendAction> { None }
    fn set_rom_title(&mut self, _title: &str) {}
}

/// Dummy audio sink with no output
#[derive(Default)]
pub struct DummySink;

impl AudioSink for DummySink {
    fn write(&mut self, _data: &[(i16, i16)]) {}
}
<commit_msg>DummyRenderer: Save last frame of output<commit_after>//! Dummy frontend that does nothing.

use frontend_api::{FrontendAction, Renderer, AudioSink};

/// Renderer that just does nothing, apart from saving the PPU output for later use. This allows
/// users to extract single rendered frames without having to implement `Renderer`.
#[derive(Default)]
pub struct DummyRenderer {
    last_frame: Vec<u8>,
}

impl DummyRenderer {
    pub fn last_frame(&self) -> &[u8] {
        &self.last_frame
    }
}

impl Renderer for DummyRenderer {
    fn render(&mut self, frame_data: &[u8]) -> Option<FrontendAction> {
        self.last_frame.clear();
        self.last_frame.extend_from_slice(frame_data);
        None
    }

    fn set_rom_title(&mut self, _title: &str) {}
}

/// Dummy audio sink with no output
#[derive(Default)]
pub struct DummySink;

impl AudioSink for DummySink {
    fn write(&mut self, _data: &[(i16, i16)]) {}
}
<|endoftext|>


<commit_before>use std::cmp::Eq;
use std::fmt::Display;
use std::iter::FromIterator;

trait Parser<T: Display + Eq, E>: Sized {
    fn preview(&self) -> Option<&T>;
    fn consume(&mut self) -> Option<T>;
    fn current_pos(&self) -> (i32, i32);
    fn error<S: Into<String>>(&self, message: S) -> E;

    fn export(&self) -> Self;
    fn import(&mut self, backup: Self);

    fn next(&mut self) -> Result<T, E> {
        self.consume().ok_or(self.error("unexpected eof"))
    }

    fn predicate<F>(&mut self, pred: F) -> Result<T, E>
        where F: Fn(&T) -> bool
    {
        let x = try!(self.next());
        if pred(&x) {
            Ok(x)
        } else {
            Err(self.error(format!("unexpected token {}", x)))
        }
    }

    fn atom(&mut self, expected: T) -> Result<T, E> {
        let x = try!(self.next());
        if x == expected {
            Ok(x)
        } else {
            Err(self.error(format!("unexpected token {}, expected {}", x, expected)))
        }
    }

    fn string<S, O>(&mut self, s: S) -> Result<O, E>
        where S: IntoIterator<Item = T>,
              O: FromIterator<T>
    {
        let mut res: Vec<T> = Vec::new();
        for c in s {
            match self.atom(c) {
                Ok(x) => res.push(x),
                Err(err) => return Err(err),
            }
        }
        Ok(O::from_iter(res))
    }

    fn try<O, F>(&mut self, parser: F) -> Result<O, E>
        where F: Fn(&mut Self) -> Result<O, E>
    {
        let backup = self.export();
        parser(self).map_err(|x| {
                                 self.import(backup);
                                 x
                             })
    }

    fn choose<O>(&mut self, parsers: &[&Fn(&mut Self) -> Result<O, E>]) -> Result<O, E> {
        for parser in parsers {
            match self.try(|p| parser(p)) {
                Ok(x) => return Ok(x),
                Err(_) => continue,
            }
        }

        Err(self.error(match self.preview() {
                           Some(x) => format!("unexpected token {}", x),
                           None => String::from("unexpected eof"),
                       }))
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::collections::vec_deque::VecDeque;

    struct TP {
        input: VecDeque<i32>,
    }

    impl TP {
        fn new(input: &[i32]) -> TP {
            TP { input: VecDeque::from(input.to_vec()) }
        }
    }

    impl Parser<i32, String> for TP {
        fn consume(&mut self) -> Option<i32> {
            self.input.pop_front()
        }

        fn preview(&self) -> Option<&i32> {
            self.input.front()
        }

        fn current_pos(&self) -> (i32, i32) {
            (0, 0)
        }

        fn error<S: Into<String>>(&self, message: S) -> String {
            message.into()
        }

        fn export(&self) -> Self {
            TP { input: self.input.clone() }
        }

        fn import(&mut self, backup: Self) {
            self.input = backup.input;
        }
    }

    type TPR = Result<Vec<i32>, String>;

    fn err<T>(m: &str) -> Result<T, String> {
        Err(String::from(m))
    }

    #[test]
    fn next_success() {
        let mut p = TP::new(&[1, 2, 3]);
        assert_eq!(p.next(), Ok(1));
        assert_eq!(p.next(), Ok(2));
        assert_eq!(p.next(), Ok(3));
    }

    #[test]
    fn next_fail_empty() {
        let mut p = TP::new(&[]);
        assert_eq!(p.next(), err("unexpected eof"));
    }

    #[test]
    fn predicate_success() {
        let mut p = TP::new(&[2, 4, 6]);
        assert_eq!(p.predicate(|x| x % 2 == 0), Ok(2));
        assert_eq!(p.predicate(|x| x % 2 == 0), Ok(4));
        assert_eq!(p.predicate(|x| x % 2 == 0), Ok(6));
    }

    #[test]
    fn predicate_fail_empty() {
        let mut p = TP::new(&[]);
        assert_eq!(p.predicate(|x| x % 2 == 0), err("unexpected eof"));
    }

    #[test]
    fn predicate_fail_not_satisfy() {
        let mut p = TP::new(&[3, 5, 7]);
        assert_eq!(p.predicate(|x| x % 2 == 0), err("unexpected token 3"));
    }

    #[test]
    fn atom_success() {
        let mut p = TP::new(&[2, 4, 6]);
        assert_eq!(p.atom(2), Ok(2));
        assert_eq!(p.atom(4), Ok(4));
        assert_eq!(p.atom(6), Ok(6));
    }

    #[test]
    fn atom_fail_empty() {
        let mut p = TP::new(&[]);
        assert_eq!(p.atom(2), err("unexpected eof"));
    }

    #[test]
    fn atom_fail_not_expected() {
        let mut p = TP::new(&[3, 5, 7]);
        assert_eq!(p.atom(3), Ok(3));
        assert_eq!(p.atom(4), err("unexpected token 5, expected 4"));
    }

    #[test]
    fn string_success() {
        let mut p = TP::new(&[2, 4, 6]);
        assert_eq!(p.string(vec![2, 4, 6]), Ok(vec![2, 4, 6]));
    }

    #[test]
    fn string_fail_empty() {
        let mut p = TP::new(&[]);
        assert_eq!(p.string(vec![2, 4, 6]) as TPR, err("unexpected eof"));
    }

    #[test]
    fn string_fail_not_expected() {
        let mut p = TP::new(&[2, 5, 6]);
        assert_eq!(p.string(vec![2, 4, 6]) as TPR,
                   err("unexpected token 5, expected 4"));
    }

    #[test]
    fn try_success() {
        let mut p = TP::new(&[2, 4, 6]);
        assert_eq!(p.try(|p| p.string(vec![2, 4, 6])), Ok(vec![2, 4, 6]));
    }

    #[test]
    fn try_fail_recover() {
        let mut p = TP::new(&[2, 4, 6]);
        assert_eq!(p.try(|p| p.string(vec![2, 4, 7])) as TPR,
                   err("unexpected token 6, expected 7"));
        assert_eq!(p.try(|p| p.string(vec![2, 4, 6])), Ok(vec![2, 4, 6]));
    }

    #[test]
    fn choose_success() {
        let mut p = TP::new(&[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
        assert_eq!(p.choose(&[&|p| p.string(vec![1, 2, 3]),
                              &|p| p.string(vec![4, 5, 6, 7]),
                              &|p| p.string(vec![4, 5, 6])]),
                   Ok(vec![1, 2, 3]));
    }

    #[test]
    fn choose_success_with_recover() {
        let mut p = TP::new(&[4, 5, 6, 7, 8, 9, 10]);
        assert_eq!(p.choose(&[&|p| p.string(vec![1, 2, 3]),
                              &|p| p.string(vec![4, 5, 6, 8]),
                              &|p| p.string(vec![4, 5, 6])]),
                   Ok(vec![4, 5, 6]));
    }

    #[test]
    fn fail_choose_no_match() {
        let mut p = TP::new(&[5, 6, 7, 8, 9, 10]);
        assert_eq!(p.choose(&[&|p| p.string(vec![1, 2, 3]),
                              &|p| p.string(vec![4, 5, 6, 8]),
                              &|p| p.string(vec![4, 5, 6])]) as TPR,
                   err("unexpected token 5"));
    }

    #[test]
    fn fail_choose_empty() {
        let mut p = TP::new(&[]);
        assert_eq!(p.choose(&[&|p| p.string(vec![1, 2, 3]),
                              &|p| p.string(vec![4, 5, 6, 8]),
                              &|p| p.string(vec![4, 5, 6])]) as TPR,
                   err("unexpected eof"));
    }
}
<commit_msg>Rename some tests<commit_after>use std::cmp::Eq;
use std::fmt::Display;
use std::iter::FromIterator;

trait Parser<T: Display + Eq, E>: Sized {
    fn preview(&self) -> Option<&T>;
    fn consume(&mut self) -> Option<T>;
    fn current_pos(&self) -> (i32, i32);
    fn error<S: Into<String>>(&self, message: S) -> E;

    fn export(&self) -> Self;
    fn import(&mut self, backup: Self);

    fn next(&mut self) -> Result<T, E> {
        self.consume().ok_or(self.error("unexpected eof"))
    }

    fn predicate<F>(&mut self, pred: F) -> Result<T, E>
        where F: Fn(&T) -> bool
    {
        let x = try!(self.next());
        if pred(&x) {
            Ok(x)
        } else {
            Err(self.error(format!("unexpected token {}", x)))
        }
    }

    fn atom(&mut self, expected: T) -> Result<T, E> {
        let x = try!(self.next());
        if x == expected {
            Ok(x)
        } else {
            Err(self.error(format!("unexpected token {}, expected {}", x, expected)))
        }
    }

    fn string<S, O>(&mut self, s: S) -> Result<O, E>
        where S: IntoIterator<Item = T>,
              O: FromIterator<T>
    {
        let mut res: Vec<T> = Vec::new();
        for c in s {
            match self.atom(c) {
                Ok(x) => res.push(x),
                Err(err) => return Err(err),
            }
        }
        Ok(O::from_iter(res))
    }

    fn try<O, F>(&mut self, parser: F) -> Result<O, E>
        where F: Fn(&mut Self) -> Result<O, E>
    {
        let backup = self.export();
        parser(self).map_err(|x| {
                                 self.import(backup);
                                 x
                             })
    }

    fn choose<O>(&mut self, parsers: &[&Fn(&mut Self) -> Result<O, E>]) -> Result<O, E> {
        for parser in parsers {
            match self.try(|p| parser(p)) {
                Ok(x) => return Ok(x),
                Err(_) => continue,
            }
        }

        Err(self.error(match self.preview() {
                           Some(x) => format!("unexpected token {}", x),
                           None => String::from("unexpected eof"),
                       }))
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::collections::vec_deque::VecDeque;

    struct TP {
        input: VecDeque<i32>,
    }

    impl TP {
        fn new(input: &[i32]) -> TP {
            TP { input: VecDeque::from(input.to_vec()) }
        }
    }

    impl Parser<i32, String> for TP {
        fn consume(&mut self) -> Option<i32> {
            self.input.pop_front()
        }

        fn preview(&self) -> Option<&i32> {
            self.input.front()
        }

        fn current_pos(&self) -> (i32, i32) {
            (0, 0)
        }

        fn error<S: Into<String>>(&self, message: S) -> String {
            message.into()
        }

        fn export(&self) -> Self {
            TP { input: self.input.clone() }
        }

        fn import(&mut self, backup: Self) {
            self.input = backup.input;
        }
    }

    type TPR = Result<Vec<i32>, String>;

    fn err<T>(m: &str) -> Result<T, String> {
        Err(String::from(m))
    }

    #[test]
    fn next_success() {
        let mut p = TP::new(&[1, 2, 3]);
        assert_eq!(p.next(), Ok(1));
        assert_eq!(p.next(), Ok(2));
        assert_eq!(p.next(), Ok(3));
    }

    #[test]
    fn next_fail_empty() {
        let mut p = TP::new(&[]);
        assert_eq!(p.next(), err("unexpected eof"));
    }

    #[test]
    fn predicate_success() {
        let mut p = TP::new(&[2, 4, 6]);
        assert_eq!(p.predicate(|x| x % 2 == 0), Ok(2));
        assert_eq!(p.predicate(|x| x % 2 == 0), Ok(4));
        assert_eq!(p.predicate(|x| x % 2 == 0), Ok(6));
    }

    #[test]
    fn predicate_fail_empty() {
        let mut p = TP::new(&[]);
        assert_eq!(p.predicate(|x| x % 2 == 0), err("unexpected eof"));
    }

    #[test]
    fn predicate_fail_not_satisfy() {
        let mut p = TP::new(&[3, 5, 7]);
        assert_eq!(p.predicate(|x| x % 2 == 0), err("unexpected token 3"));
    }

    #[test]
    fn atom_success() {
        let mut p = TP::new(&[2, 4, 6]);
        assert_eq!(p.atom(2), Ok(2));
        assert_eq!(p.atom(4), Ok(4));
        assert_eq!(p.atom(6), Ok(6));
    }

    #[test]
    fn atom_fail_empty() {
        let mut p = TP::new(&[]);
        assert_eq!(p.atom(2), err("unexpected eof"));
    }

    #[test]
    fn atom_fail_not_expected() {
        let mut p = TP::new(&[3, 5, 7]);
        assert_eq!(p.atom(3), Ok(3));
        assert_eq!(p.atom(4), err("unexpected token 5, expected 4"));
    }

    #[test]
    fn string_success() {
        let mut p = TP::new(&[2, 4, 6]);
        assert_eq!(p.string(vec![2, 4, 6]), Ok(vec![2, 4, 6]));
    }

    #[test]
    fn string_fail_empty() {
        let mut p = TP::new(&[]);
        assert_eq!(p.string(vec![2, 4, 6]) as TPR, err("unexpected eof"));
    }

    #[test]
    fn string_fail_not_expected() {
        let mut p = TP::new(&[2, 5, 6]);
        assert_eq!(p.string(vec![2, 4, 6]) as TPR,
                   err("unexpected token 5, expected 4"));
    }

    #[test]
    fn try_success() {
        let mut p = TP::new(&[2, 4, 6]);
        assert_eq!(p.try(|p| p.string(vec![2, 4, 6])), Ok(vec![2, 4, 6]));
    }

    #[test]
    fn try_fail_recover() {
        let mut p = TP::new(&[2, 4, 6]);
        assert_eq!(p.try(|p| p.string(vec![2, 4, 7])) as TPR,
                   err("unexpected token 6, expected 7"));
        assert_eq!(p.try(|p| p.string(vec![2, 4, 6])), Ok(vec![2, 4, 6]));
    }

    #[test]
    fn choose_success() {
        let mut p = TP::new(&[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
        assert_eq!(p.choose(&[&|p| p.string(vec![1, 2, 3]),
                              &|p| p.string(vec![4, 5, 6, 7]),
                              &|p| p.string(vec![4, 5, 6])]),
                   Ok(vec![1, 2, 3]));
    }

    #[test]
    fn choose_success_with_recover() {
        let mut p = TP::new(&[4, 5, 6, 7, 8, 9, 10]);
        assert_eq!(p.choose(&[&|p| p.string(vec![1, 2, 3]),
                              &|p| p.string(vec![4, 5, 6, 8]),
                              &|p| p.string(vec![4, 5, 6])]),
                   Ok(vec![4, 5, 6]));
    }

    #[test]
    fn choose_fail_no_match() {
        let mut p = TP::new(&[5, 6, 7, 8, 9, 10]);
        assert_eq!(p.choose(&[&|p| p.string(vec![1, 2, 3]),
                              &|p| p.string(vec![4, 5, 6, 8]),
                              &|p| p.string(vec![4, 5, 6])]) as TPR,
                   err("unexpected token 5"));
    }

    #[test]
    fn choose_fail_empty() {
        let mut p = TP::new(&[]);
        assert_eq!(p.choose(&[&|p| p.string(vec![1, 2, 3]),
                              &|p| p.string(vec![4, 5, 6, 8]),
                              &|p| p.string(vec![4, 5, 6])]) as TPR,
                   err("unexpected eof"));
    }
}
<|endoftext|>