<commit_before>// Copyright (c) 2014 Robert Clipsham <robert@octarineparrot.com>
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Provides interfaces for interacting with packets and headers

#![macro_use]

/// Represents a generic network packet
pub trait Packet {
    /// Retreive the underlying buffer for the packet
    fn packet<'p>(&'p self) -> &'p [u8];

    /// Retreive the payload for the packet
    fn payload<'p>(&'p self) -> &'p [u8];
}

/// Represents a generic, mutable, network packet
pub trait MutablePacket {
    /// Retreive the underlying, mutable, buffer for the packet
    fn packet_mut<'p>(&'p mut self) -> &'p mut [u8];

    /// Retreive the mutable payload for the packet
    fn payload_mut<'p>(&'p mut self) -> &'p mut [u8];

    /// Initialize this packet by cloning another
    fn clone_from<'p, T : Packet>(&'p mut self, other: T) {
        use std::slice::bytes::copy_memory;
        copy_memory(self.packet_mut(), other.packet())
    }
}

pub mod ethernet;
pub mod ip;
pub mod ipv4;
pub mod ipv6;
pub mod udp;

<commit_msg>Type signature for `copy_memory` has reversed the argument positions.<commit_after>// Copyright (c) 2014 Robert Clipsham <robert@octarineparrot.com>
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Provides interfaces for interacting with packets and headers

#![macro_use]

/// Represents a generic network packet
pub trait Packet {
    /// Retreive the underlying buffer for the packet
    fn packet<'p>(&'p self) -> &'p [u8];

    /// Retreive the payload for the packet
    fn payload<'p>(&'p self) -> &'p [u8];
}

/// Represents a generic, mutable, network packet
pub trait MutablePacket {
    /// Retreive the underlying, mutable, buffer for the packet
    fn packet_mut<'p>(&'p mut self) -> &'p mut [u8];

    /// Retreive the mutable payload for the packet
    fn payload_mut<'p>(&'p mut self) -> &'p mut [u8];

    /// Initialize this packet by cloning another
    fn clone_from<'p, T : Packet>(&'p mut self, other: T) {
        use std::slice::bytes::copy_memory;
        copy_memory(other.packet(), self.packet_mut())
    }
}

pub mod ethernet;
pub mod ip;
pub mod ipv4;
pub mod ipv6;
pub mod udp;

<|endoftext|>


<commit_before>use std::thread::{self,Thread,Builder};
use std::sync::mpsc::{channel,Receiver};
use mio::tcp::*;
use mio::*;
use mio::buf::{ByteBuf,MutByteBuf};
use std::collections::HashMap;
use std::io::{self,Read,ErrorKind};
use nom::HexDisplay;
use std::error::Error;

const SERVER: Token = Token(0);

pub struct NetworkState {
  pub socket: NonBlock<TcpStream>,
  pub state:  ClientState,
  pub token:  usize,
  pub buffer: Option<MutByteBuf>
}

pub struct Client {
  network_state: NetworkState
}

pub struct Listener {
  t: Thread,
  rw: Receiver<u8>
}

pub trait NetworkClient {
  fn new(stream: NonBlock<TcpStream>, index: usize) -> Self;
  fn handle_message(&mut self, buffer: &mut ByteBuf) -> ClientErr;
  fn network_state(&mut self) -> &mut NetworkState;

  fn state(&mut self) -> ClientState {
    self.network_state().state.clone()
  }

  fn set_state(&mut self, st: ClientState) {
    self.network_state().state = st;
  }

  fn buffer(&mut self) -> Option<MutByteBuf> {
    self.network_state().buffer.take()
  }

  fn set_buffer(&mut self, buf: MutByteBuf) {
    self.network_state().buffer = Some(buf);
  }

  fn socket(&mut self) -> &mut NonBlock<TcpStream> {
    &mut self.network_state().socket
  }

  fn read_size(&mut self) -> ClientResult {
    let mut size_buf = ByteBuf::mut_with_capacity(4);
    match self.socket().read(&mut size_buf) {
      Ok(Some(size)) => {
        if size != 4 {
          Err(ClientErr::Continue)
        } else {
          let mut b = size_buf.flip();
          let b1 = b.read_byte().unwrap();
          let b2 = b.read_byte().unwrap();
          let b3 = b.read_byte().unwrap();
          let b4 = b.read_byte().unwrap();
          let sz = ((b1 as u32) << 24) + ((b2 as u32) << 16) + ((b3 as u32) << 8) + b4 as u32;
          //println!("found size: {}", sz);
          Ok(sz as usize)
        }
      },
      Ok(None) => Err(ClientErr::Continue),
      Err(e) => {
        match e.kind() {
          ErrorKind::BrokenPipe => {
            println!("broken pipe, removing client");
            Err(ClientErr::ShouldClose)
          },
          _ => {
            println!("error writing: {:?} | {:?} | {:?} | {:?}", e, e.description(), e.cause(), e.kind());
            Err(ClientErr::Continue)
          }
        }
      }
    }
  }

  fn read_to_buf(&mut self, buffer: &mut MutByteBuf) -> ClientResult {
    let mut bytes_read: usize = 0;
    loop {
      println!("remaining space: {}", buffer.remaining());
      match self.socket().read(buffer) {
        Ok(a) => {
          if a == None || a == Some(0) {
            println!("breaking because a == {:?}", a);
            break;
          }
          println!("Ok({:?})", a);
          if let Some(just_read) = a {
            bytes_read += just_read;
          }
        },
        Err(e) => {
          match e.kind() {
            ErrorKind::BrokenPipe => {
              println!("broken pipe, removing client");
              return Err(ClientErr::ShouldClose)
            },
            _ => {
              println!("error writing: {:?} | {:?} | {:?} | {:?}", e, e.description(), e.cause(), e.kind());
              return Err(ClientErr::Continue)
            }
          }
        }
      }
    }
    Ok(bytes_read)
  }

  fn write(&mut self, msg: &[u8]) -> ClientResult {
    match self.socket().write_slice(msg) {
      Ok(Some(o))  => {
        println!("sent message: {:?}", o);
        Ok(o)
      },
      Ok(None) => Err(ClientErr::Continue),
      Err(e) => {
        match e.kind() {
          ErrorKind::BrokenPipe => {
            println!("broken pipe, removing client");
            Err(ClientErr::ShouldClose)
          },
          _ => {
            println!("error writing: {:?} | {:?} | {:?} | {:?}", e, e.description(), e.cause(), e.kind());
            Err(ClientErr::Continue)
          }
        }
      }
    }
  }
}

impl NetworkClient for Client {
  fn new(stream: NonBlock<TcpStream>, index: usize) -> Client {
    Client{
      network_state: NetworkState {
        socket: stream,
        state: ClientState::Normal,
        token: index,
        buffer: None
      }
    }
  }

  fn network_state(&mut self) -> &mut NetworkState {
    &mut self.network_state
  }

  fn handle_message(&mut self, buffer: &mut ByteBuf) ->ClientErr {
    let size = buffer.remaining();
    let mut res: Vec<u8> = Vec::with_capacity(size);
    unsafe {
      res.set_len(size);
    }
    buffer.read_slice(&mut res[..]);
    println!("handle_message got {} bytes:\n{}", (&res[..]).len(), (&res[..]).to_hex(8));
    ClientErr::Continue
  }
}

#[derive(Debug)]
pub enum Message {
  Stop,
  Data(Vec<u8>),
  Close(usize)
}

#[derive(Debug,Clone)]
pub enum ClientState {
  Normal,
  Await(usize)
}

#[derive(Debug)]
pub enum ClientErr {
  Continue,
  ShouldClose
}

pub type ClientResult = Result<usize, ClientErr>;

pub struct TcpHandler<Client: NetworkClient> {
  pub listener:    NonBlock<TcpListener>,
  //pub storage_tx : mpsc::Sender<storage::Request>,
  pub counter:     u8,
  pub token_index: usize,
  pub clients:     HashMap<usize, Client>,
  pub available_tokens: Vec<usize>
}

impl<Client: NetworkClient> TcpHandler<Client> {
  fn accept(&mut self, event_loop: &mut EventLoop<Self>) {
    if let Ok(Some(stream)) = self.listener.accept() {
      let index = self.next_token();
      println!("got client n°{:?}", index);
      let token = Token(index);
      event_loop.register_opt(&stream, token, Interest::all(), PollOpt::edge());
      self.clients.insert(index, Client::new(stream, index));
    } else {
      println!("invalid connection");
    }
  }

  fn client_read(&mut self, event_loop: &mut EventLoop<Self>, tk: usize) {
    //println!("client n°{:?} readable", tk);
    if let Some(mut client) = self.clients.get_mut(&tk) {

      match client.state() {
        ClientState::Normal => {
          //println!("state normal");
          match client.read_size() {
            Ok(size) => {
              let mut buffer = ByteBuf::mut_with_capacity(size);

              let capacity = buffer.remaining();  // actual buffer capacity may be higher
              //println!("capacity: {}", capacity);
              if let Err(ClientErr::ShouldClose) = client.read_to_buf(&mut buffer) {
                event_loop.channel().send(Message::Close(tk));
              }

              if capacity - buffer.remaining() < size {
                //println!("read {} bytes", capacity - buffer.remaining());
                //client.state = ClientState::Await(size - (capacity - buffer.remaining()));
                client.set_state(ClientState::Await(size - (capacity - buffer.remaining())));
                //client.buffer = Some(buffer);
                client.set_buffer(buffer);
              } else {
                //println!("got enough bytes: {}", capacity - buffer.remaining());
                let mut text = String::new();
                let mut buf = buffer.flip();
                if let ClientErr::ShouldClose = client.handle_message(&mut buf) {
                  event_loop.channel().send(Message::Close(tk));
                }
              }
            },
            Err(ClientErr::ShouldClose) => {
              println!("should close");
              event_loop.channel().send(Message::Close(tk));
            },
            a => {
              println!("other error: {:?}", a);
            }
          }
        },
        ClientState::Await(sz) => {
          println!("awaits {} bytes", sz);
          //let mut buffer = client.buffer.take().unwrap();
          let mut buffer = client.buffer().unwrap();
          let capacity = buffer.remaining();

          if let Err(ClientErr::ShouldClose) = client.read_to_buf(&mut buffer) {
            event_loop.channel().send(Message::Close(tk));
          }
          if capacity - buffer.remaining() < sz {
            //client.state  = ClientState::Await(sz - (capacity - buffer.remaining()));
            client.set_state(ClientState::Await(sz - (capacity - buffer.remaining())));
            //client.buffer = Some(buffer);
            client.set_buffer(buffer);
          } else {
            let mut text = String::new();
            let mut buf = buffer.flip();
            if let ClientErr::ShouldClose = client.handle_message(&mut buf) {
              event_loop.channel().send(Message::Close(tk));
            }
          }
        }
      }
    }
  }

  fn client_write(&mut self, event_loop: &mut EventLoop<Self>, tk: usize) {
    //println!("client n°{:?} readable", tk);
    if let Some(mut client) = self.clients.get_mut(&tk) {
      let s = b"";
      client.write(s);
    }
  }

  fn next_token(&mut self) -> usize {
    match self.available_tokens.pop() {
      None        => {
        let index = self.token_index;
        self.token_index += 1;
        index
      },
      Some(index) => {
        index
      }
    }
  }

  fn close(&mut self, token: usize) {
    self.clients.remove(&token);
    self.available_tokens.push(token);
  }
}

impl<Client:NetworkClient> Handler for TcpHandler<Client> {
  type Timeout = ();
  type Message = Message;

  fn readable(&mut self, event_loop: &mut EventLoop<Self>, token: Token, _: ReadHint) {
    //println!("readable");
    match token {
      SERVER => {
        self.accept(event_loop);
      },
      Token(tk) => {
        self.client_read(event_loop, tk);
      }
    }
  }

  fn writable(&mut self, event_loop: &mut EventLoop<Self>, token: Token) {
    match token {
      SERVER => {
        println!("server writeable");
      },
      Token(tk) => {
        //println!("client n°{:?} writeable", tk);
        //self.client_write(event_loop, tk);
      }
    }
  }

  fn notify(&mut self, _reactor: &mut EventLoop<Self>, msg: Message) {
    println!("notify: {:?}", msg);
    match msg {
      Message::Close(token) => {
        println!("closing client n°{:?}", token);
        self.close(token)
      },
      _                     => println!("unknown message: {:?}", msg)
    }
  }

  fn timeout(&mut self, event_loop: &mut EventLoop<Self>, timeout: Self::Timeout) {
    println!("timeout");
  }

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

pub fn start_listener(address: &str) -> (Sender<Message>,thread::JoinHandle<()>)  {
  let mut event_loop:EventLoop<TcpHandler<Client>> = EventLoop::new().unwrap();
  let t2 = event_loop.channel();
  let jg = thread::spawn(move || {
    let listener = NonBlock::new(TcpListener::bind("127.0.0.1:9092").unwrap());
    event_loop.register(&listener, SERVER).unwrap();
    //let t = storage(&event_loop.channel(), "pouet");

    event_loop.run(&mut TcpHandler {
      listener: listener,
      //storage_tx: t,
      counter: 0,
      token_index: 1, // 0 is the server socket
      clients: HashMap::new(),
      available_tokens: Vec::new()
    }).unwrap();

  });

  (t2, jg)
}

<commit_msg>example of unit tests for network<commit_after>use std::thread::{self,Thread,Builder};
use std::sync::mpsc::{channel,Receiver};
use mio::tcp::*;
use mio::*;
use mio::buf::{ByteBuf,MutByteBuf};
use std::collections::HashMap;
use std::io::{self,Read,ErrorKind};
use nom::HexDisplay;
use std::error::Error;

const SERVER: Token = Token(0);

pub struct NetworkState {
  pub socket: NonBlock<TcpStream>,
  pub state:  ClientState,
  pub token:  usize,
  pub buffer: Option<MutByteBuf>
}

pub struct Client {
  network_state: NetworkState
}

pub struct Listener {
  t: Thread,
  rw: Receiver<u8>
}

pub trait NetworkClient {
  fn new(stream: NonBlock<TcpStream>, index: usize) -> Self;
  fn handle_message(&mut self, buffer: &mut ByteBuf) -> ClientErr;
  fn network_state(&mut self) -> &mut NetworkState;

  fn state(&mut self) -> ClientState {
    self.network_state().state.clone()
  }

  fn set_state(&mut self, st: ClientState) {
    self.network_state().state = st;
  }

  fn buffer(&mut self) -> Option<MutByteBuf> {
    self.network_state().buffer.take()
  }

  fn set_buffer(&mut self, buf: MutByteBuf) {
    self.network_state().buffer = Some(buf);
  }

  fn socket(&mut self) -> &mut NonBlock<TcpStream> {
    &mut self.network_state().socket
  }

  fn read_size(&mut self) -> ClientResult {
    let mut size_buf = ByteBuf::mut_with_capacity(4);
    match self.socket().read(&mut size_buf) {
      Ok(Some(size)) => {
        if size != 4 {
          Err(ClientErr::Continue)
        } else {
          let mut b = size_buf.flip();
          let b1 = b.read_byte().unwrap();
          let b2 = b.read_byte().unwrap();
          let b3 = b.read_byte().unwrap();
          let b4 = b.read_byte().unwrap();
          let sz = ((b1 as u32) << 24) + ((b2 as u32) << 16) + ((b3 as u32) << 8) + b4 as u32;
          //println!("found size: {}", sz);
          Ok(sz as usize)
        }
      },
      Ok(None) => Err(ClientErr::Continue),
      Err(e) => {
        match e.kind() {
          ErrorKind::BrokenPipe => {
            println!("broken pipe, removing client");
            Err(ClientErr::ShouldClose)
          },
          _ => {
            println!("error writing: {:?} | {:?} | {:?} | {:?}", e, e.description(), e.cause(), e.kind());
            Err(ClientErr::Continue)
          }
        }
      }
    }
  }

  fn read_to_buf(&mut self, buffer: &mut MutByteBuf) -> ClientResult {
    let mut bytes_read: usize = 0;
    loop {
      println!("remaining space: {}", buffer.remaining());
      match self.socket().read(buffer) {
        Ok(a) => {
          if a == None || a == Some(0) {
            println!("breaking because a == {:?}", a);
            break;
          }
          println!("Ok({:?})", a);
          if let Some(just_read) = a {
            bytes_read += just_read;
          }
        },
        Err(e) => {
          match e.kind() {
            ErrorKind::BrokenPipe => {
              println!("broken pipe, removing client");
              return Err(ClientErr::ShouldClose)
            },
            _ => {
              println!("error writing: {:?} | {:?} | {:?} | {:?}", e, e.description(), e.cause(), e.kind());
              return Err(ClientErr::Continue)
            }
          }
        }
      }
    }
    Ok(bytes_read)
  }

  fn write(&mut self, msg: &[u8]) -> ClientResult {
    match self.socket().write_slice(msg) {
      Ok(Some(o))  => {
        println!("sent message: {:?}", o);
        Ok(o)
      },
      Ok(None) => Err(ClientErr::Continue),
      Err(e) => {
        match e.kind() {
          ErrorKind::BrokenPipe => {
            println!("broken pipe, removing client");
            Err(ClientErr::ShouldClose)
          },
          _ => {
            println!("error writing: {:?} | {:?} | {:?} | {:?}", e, e.description(), e.cause(), e.kind());
            Err(ClientErr::Continue)
          }
        }
      }
    }
  }
}

impl NetworkClient for Client {
  fn new(stream: NonBlock<TcpStream>, index: usize) -> Client {
    Client{
      network_state: NetworkState {
        socket: stream,
        state: ClientState::Normal,
        token: index,
        buffer: None
      }
    }
  }

  fn network_state(&mut self) -> &mut NetworkState {
    &mut self.network_state
  }

  fn handle_message(&mut self, buffer: &mut ByteBuf) ->ClientErr {
    let size = buffer.remaining();
    let mut res: Vec<u8> = Vec::with_capacity(size);
    unsafe {
      res.set_len(size);
    }
    buffer.read_slice(&mut res[..]);
    println!("handle_message got {} bytes:\n{}", (&res[..]).len(), (&res[..]).to_hex(8));
    ClientErr::Continue
  }
}

#[derive(Debug)]
pub enum Message {
  Stop,
  Data(Vec<u8>),
  Close(usize)
}

#[derive(Debug,Clone)]
pub enum ClientState {
  Normal,
  Await(usize)
}

#[derive(Debug)]
pub enum ClientErr {
  Continue,
  ShouldClose
}

pub type ClientResult = Result<usize, ClientErr>;

pub struct TcpHandler<Client: NetworkClient> {
  pub listener:    NonBlock<TcpListener>,
  //pub storage_tx : mpsc::Sender<storage::Request>,
  pub counter:     u8,
  pub token_index: usize,
  pub clients:     HashMap<usize, Client>,
  pub available_tokens: Vec<usize>
}

impl<Client: NetworkClient> TcpHandler<Client> {
  fn accept(&mut self, event_loop: &mut EventLoop<Self>) {
    if let Ok(Some(stream)) = self.listener.accept() {
      let index = self.next_token();
      println!("got client n°{:?}", index);
      let token = Token(index);
      event_loop.register_opt(&stream, token, Interest::all(), PollOpt::edge());
      self.clients.insert(index, Client::new(stream, index));
    } else {
      println!("invalid connection");
    }
  }

  fn client_read(&mut self, event_loop: &mut EventLoop<Self>, tk: usize) {
    //println!("client n°{:?} readable", tk);
    if let Some(mut client) = self.clients.get_mut(&tk) {

      match client.state() {
        ClientState::Normal => {
          //println!("state normal");
          match client.read_size() {
            Ok(size) => {
              let mut buffer = ByteBuf::mut_with_capacity(size);

              let capacity = buffer.remaining();  // actual buffer capacity may be higher
              //println!("capacity: {}", capacity);
              if let Err(ClientErr::ShouldClose) = client.read_to_buf(&mut buffer) {
                event_loop.channel().send(Message::Close(tk));
              }

              if capacity - buffer.remaining() < size {
                //println!("read {} bytes", capacity - buffer.remaining());
                //client.state = ClientState::Await(size - (capacity - buffer.remaining()));
                client.set_state(ClientState::Await(size - (capacity - buffer.remaining())));
                //client.buffer = Some(buffer);
                client.set_buffer(buffer);
              } else {
                //println!("got enough bytes: {}", capacity - buffer.remaining());
                let mut text = String::new();
                let mut buf = buffer.flip();
                if let ClientErr::ShouldClose = client.handle_message(&mut buf) {
                  event_loop.channel().send(Message::Close(tk));
                }
              }
            },
            Err(ClientErr::ShouldClose) => {
              println!("should close");
              event_loop.channel().send(Message::Close(tk));
            },
            a => {
              println!("other error: {:?}", a);
            }
          }
        },
        ClientState::Await(sz) => {
          println!("awaits {} bytes", sz);
          //let mut buffer = client.buffer.take().unwrap();
          let mut buffer = client.buffer().unwrap();
          let capacity = buffer.remaining();

          if let Err(ClientErr::ShouldClose) = client.read_to_buf(&mut buffer) {
            event_loop.channel().send(Message::Close(tk));
          }
          if capacity - buffer.remaining() < sz {
            //client.state  = ClientState::Await(sz - (capacity - buffer.remaining()));
            client.set_state(ClientState::Await(sz - (capacity - buffer.remaining())));
            //client.buffer = Some(buffer);
            client.set_buffer(buffer);
          } else {
            let mut text = String::new();
            let mut buf = buffer.flip();
            if let ClientErr::ShouldClose = client.handle_message(&mut buf) {
              event_loop.channel().send(Message::Close(tk));
            }
          }
        }
      }
    }
  }

  fn client_write(&mut self, event_loop: &mut EventLoop<Self>, tk: usize) {
    //println!("client n°{:?} readable", tk);
    if let Some(mut client) = self.clients.get_mut(&tk) {
      let s = b"";
      client.write(s);
    }
  }

  fn next_token(&mut self) -> usize {
    match self.available_tokens.pop() {
      None        => {
        let index = self.token_index;
        self.token_index += 1;
        index
      },
      Some(index) => {
        index
      }
    }
  }

  fn close(&mut self, token: usize) {
    self.clients.remove(&token);
    self.available_tokens.push(token);
  }
}

impl<Client:NetworkClient> Handler for TcpHandler<Client> {
  type Timeout = ();
  type Message = Message;

  fn readable(&mut self, event_loop: &mut EventLoop<Self>, token: Token, _: ReadHint) {
    //println!("readable");
    match token {
      SERVER => {
        self.accept(event_loop);
      },
      Token(tk) => {
        self.client_read(event_loop, tk);
      }
    }
  }

  fn writable(&mut self, event_loop: &mut EventLoop<Self>, token: Token) {
    match token {
      SERVER => {
        println!("server writeable");
      },
      Token(tk) => {
        //println!("client n°{:?} writeable", tk);
        //self.client_write(event_loop, tk);
      }
    }
  }

  fn notify(&mut self, _reactor: &mut EventLoop<Self>, msg: Message) {
    println!("notify: {:?}", msg);
    match msg {
      Message::Close(token) => {
        println!("closing client n°{:?}", token);
        self.close(token)
      },
      _                     => println!("unknown message: {:?}", msg)
    }
  }

  fn timeout(&mut self, event_loop: &mut EventLoop<Self>, timeout: Self::Timeout) {
    println!("timeout");
  }

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

pub fn start_listener(address: &str) -> (Sender<Message>,thread::JoinHandle<()>)  {
  let mut event_loop:EventLoop<TcpHandler<Client>> = EventLoop::new().unwrap();
  let t2 = event_loop.channel();
  let jg = thread::spawn(move || {
    let listener = NonBlock::new(TcpListener::bind("127.0.0.1:9092").unwrap());
    event_loop.register(&listener, SERVER).unwrap();
    //let t = storage(&event_loop.channel(), "pouet");

    event_loop.run(&mut TcpHandler {
      listener: listener,
      //storage_tx: t,
      counter: 0,
      token_index: 1, // 0 is the server socket
      clients: HashMap::new(),
      available_tokens: Vec::new()
    }).unwrap();

  });

  (t2, jg)
}

#[cfg(test)]
mod tests {

  use std::net::{TcpListener, TcpStream};
  use std::io::{Read,Write};
  use std::{thread,str};

  #[allow(unused_mut, unused_must_use, unused_variables)]
  fn start_server() {
    let listener = TcpListener::bind("127.0.0.1:1234").unwrap();
    fn handle_client(stream: &mut TcpStream, id: u8) {
      let mut buf = [0; 128];
      while let Ok(sz) = stream.read(&mut buf[..]) {
        if sz > 0 {
          //println!("[{}] {:?}", id, str::from_utf8(&buf[..sz]));
          stream.write(&buf[..sz]);
        }
      }
    }

    let mut count = 0;
    thread::spawn(move|| {
      for conn in listener.incoming() {
        match conn {
          Ok(mut stream) => {
            thread::spawn(move|| {
              //println!("got a new client: {}", count);
              handle_client(&mut stream, count)
            });
          }
          Err(e) => { println!("connection failed"); }
        }
      }
    });
  }

  #[allow(unused_mut, unused_must_use, unused_variables)]
  #[test]
  fn hello() {
    start_server();
    let mut s1 = TcpStream::connect("127.0.0.1:1234").unwrap();
    let mut s2 = TcpStream::connect("127.0.0.1:1234").unwrap();
    s1.write(&b"hello"[..]);
    s2.write(&b"pouet pouet"[..]);

    let mut res = [0; 128];
    let sz2 = s2.read(&mut res[..]).unwrap();
    assert_eq!(&res[..sz2], &b"pouet pouet"[..]);
    let sz1 = s1.read(&mut res[..]).unwrap();
    assert_eq!(&res[..sz1], &b"hello"[..]);
  }
}
<|endoftext|>


<commit_before>use parking_lot::Mutex;
use std::{path::*, sync::Arc};

pub mod block;
pub mod index;
pub mod store;
pub mod verify;

pub use self::{
    block::*,
    index::{Indexer, WriteBatch},
    store::BlockStore,
    verify::TxErr,
};

use crate::{
    asset::{self, Asset},
    constants::*,
    crypto::*,
    script::*,
    tx::*,
};

#[derive(Clone, Debug)]
pub struct Properties {
    pub height: u64,
    pub owner: Box<OwnerTx>,
    pub token_supply: Asset,
    pub network_fee: Asset,
}

pub struct Blockchain {
    indexer: Arc<Indexer>,
    store: Mutex<BlockStore>,
}

impl Blockchain {
    ///
    /// Creates a new `Blockchain` with an associated indexer and backing
    /// storage is automatically created based on the given `path`.
    ///
    pub fn new(path: &Path) -> Blockchain {
        let indexer = Arc::new(Indexer::new(&Path::join(path, "index")));
        let store = BlockStore::new(&Path::join(path, "blklog"), Arc::clone(&indexer));
        Blockchain {
            indexer,
            store: Mutex::new(store),
        }
    }

    pub fn indexer(&self) -> Arc<Indexer> {
        Arc::clone(&self.indexer)
    }

    pub fn get_properties(&self) -> Properties {
        Properties {
            height: self.get_chain_height(),
            owner: Box::new(self.get_owner()),
            token_supply: self.indexer.get_token_supply(),
            network_fee: self
                .get_network_fee()
                .expect("unexpected error retrieving network fee"),
        }
    }

    #[inline]
    pub fn get_owner(&self) -> OwnerTx {
        self.indexer
            .get_owner()
            .expect("Failed to retrieve owner from index")
    }

    #[inline]
    pub fn get_chain_height(&self) -> u64 {
        self.indexer.get_chain_height()
    }

    pub fn get_chain_head(&self) -> Arc<SignedBlock> {
        let store = self.store.lock();
        let height = store.get_chain_height();
        store.get(height).expect("Failed to get blockchain head")
    }

    pub fn get_block(&self, height: u64) -> Option<Arc<SignedBlock>> {
        let store = self.store.lock();
        store.get(height)
    }

    pub fn get_total_fee(&self, hash: &ScriptHash) -> Option<Asset> {
        let net_fee = self.get_network_fee()?;
        let addr_fee = self.get_address_fee(hash)?;
        addr_fee.add(net_fee)
    }

    pub fn get_address_fee(&self, hash: &ScriptHash) -> Option<Asset> {
        let mut tx_count = 1;
        let mut delta = 0;

        macro_rules! handle_tx_match {
            ($tx:expr) => {
                let has_match = match $tx {
                    TxVariant::OwnerTx(_) => false,
                    TxVariant::MintTx(_) => false,
                    TxVariant::RewardTx(_) => false,
                    TxVariant::TransferTx(tx) => &tx.from == hash,
                };
                if has_match {
                    tx_count += 1;
                    delta = 0;
                }
            };
        }

        for i in (0..=self.get_chain_height()).rev() {
            delta += 1;
            let block = self.get_block(i).unwrap();
            for tx in &block.transactions {
                handle_tx_match!(tx);
            }
            if delta == FEE_RESET_WINDOW {
                break;
            }
        }

        let prec = asset::MAX_PRECISION;
        GRAEL_FEE_MIN.mul(GRAEL_FEE_MULT.pow(tx_count as u16, prec)?, prec)
    }

    pub fn get_network_fee(&self) -> Option<Asset> {
        // The network fee adjusts every 5 blocks so that users have a bigger time
        // frame to confirm the fee they want to spend without suddenly changing.
        use crate::constants::*;
        let max_height = self.get_chain_height();
        let max_height = max_height - (max_height % 5);
        let min_height = if max_height > NETWORK_FEE_AVG_WINDOW {
            max_height - NETWORK_FEE_AVG_WINDOW
        } else {
            0
        };

        let mut tx_count: u64 = 1;
        for i in min_height..=max_height {
            tx_count += self.get_block(i).unwrap().transactions.len() as u64;
        }
        tx_count /= NETWORK_FEE_AVG_WINDOW;
        if tx_count > u64::from(u16::max_value()) {
            return None;
        }

        let prec = asset::MAX_PRECISION;
        GRAEL_FEE_MIN.mul(GRAEL_FEE_NET_MULT.pow(tx_count as u16, prec)?, prec)
    }

    pub fn get_balance(&self, hash: &ScriptHash) -> Asset {
        self.indexer.get_balance(hash).unwrap_or_default()
    }

    pub fn get_balance_with_txs(&self, hash: &ScriptHash, txs: &[TxVariant]) -> Option<Asset> {
        let mut bal = self.indexer.get_balance(hash).unwrap_or_default();
        for tx in txs {
            match tx {
                TxVariant::OwnerTx(_) => {}
                TxVariant::MintTx(tx) => {
                    if &tx.to == hash {
                        bal = bal.add(tx.amount)?;
                    }
                }
                TxVariant::RewardTx(tx) => {
                    if &tx.to == hash {
                        bal = bal.add(tx.rewards)?;
                    }
                }
                TxVariant::TransferTx(tx) => {
                    if &tx.from == hash {
                        bal = bal.sub(tx.fee)?;
                        bal = bal.sub(tx.amount)?;
                    } else if &tx.to == hash {
                        bal = bal.add(tx.amount)?;
                    }
                }
            }
        }

        Some(bal)
    }

    pub fn insert_block(&self, block: SignedBlock) -> Result<(), verify::BlockError> {
        static CONFIG: verify::Config = verify::Config { skip_reward: true };
        self.verify_block(&block, &self.get_chain_head(), CONFIG)?;
        let mut batch = WriteBatch::new(Arc::clone(&self.indexer));
        for tx in &block.transactions {
            Self::index_tx(&mut batch, tx);
        }
        self.store.lock().insert(&mut batch, block);
        batch.commit();

        Ok(())
    }

    fn verify_block(
        &self,
        block: &SignedBlock,
        prev_block: &SignedBlock,
        config: verify::Config,
    ) -> Result<(), verify::BlockError> {
        if prev_block.height + 1 != block.height {
            return Err(verify::BlockError::InvalidBlockHeight);
        } else if !block.verify_tx_merkle_root() {
            return Err(verify::BlockError::InvalidMerkleRoot);
        } else if !block.verify_previous_hash(prev_block) {
            return Err(verify::BlockError::InvalidPrevHash);
        }

        let owner = self.get_owner();
        if !block.sig_pair.verify(block.calc_hash().as_ref()) {
            return Err(verify::BlockError::InvalidHash);
        } else if block.sig_pair.pub_key != owner.minter {
            return Err(verify::BlockError::InvalidSignature);
        }

        let len = block.transactions.len();
        for i in 0..len {
            let tx = &block.transactions[i];
            let txs = &block.transactions[0..i];
            if let Err(e) = self.verify_tx(&TxPrecompData::from_tx(tx), txs, config) {
                return Err(verify::BlockError::Tx(e));
            }
        }

        Ok(())
    }

    pub fn verify_tx(
        &self,
        data: &TxPrecompData,
        additional_txs: &[TxVariant],
        config: verify::Config,
    ) -> Result<(), TxErr> {
        macro_rules! check_zero_fee {
            ($asset:expr) => {
                if $asset.amount != 0 {
                    return Err(TxErr::InsufficientFeeAmount);
                }
            };
        }

        macro_rules! check_suf_bal {
            ($asset:expr) => {
                if $asset.amount < 0 {
                    return Err(TxErr::InsufficientBalance);
                }
            };
        }

        let tx = data.tx();
        match tx {
            TxVariant::OwnerTx(new_owner) => {
                check_zero_fee!(tx.fee);

                let owner = self.get_owner();
                if owner.wallet != (&new_owner.script).into() {
                    return Err(TxErr::ScriptHashMismatch);
                }

                let success = ScriptEngine::checked_new(data, &new_owner.script)
                    .map_err(TxErr::from)?
                    .eval()
                    .map_err(TxErr::ScriptEval)?;
                if !success {
                    return Err(TxErr::ScriptRetFalse);
                }
            }
            TxVariant::MintTx(mint_tx) => {
                check_zero_fee!(tx.fee);

                let owner = self.get_owner();
                if owner.wallet != (&mint_tx.script).into() {
                    return Err(TxErr::ScriptHashMismatch);
                }
                let success = ScriptEngine::checked_new(data, &mint_tx.script)
                    .map_err(TxErr::from)?
                    .eval()
                    .map_err(TxErr::ScriptEval)?;
                if !success {
                    return Err(TxErr::ScriptRetFalse);
                }

                // Sanity check to ensure too many new coins can't be minted
                self.get_balance_with_txs(&mint_tx.to, additional_txs)
                    .ok_or(TxErr::Arithmetic)?
                    .add(mint_tx.amount)
                    .ok_or(TxErr::Arithmetic)?;

                self.indexer
                    .get_token_supply()
                    .add(mint_tx.amount)
                    .ok_or(TxErr::Arithmetic)?;
            }
            TxVariant::RewardTx(tx) => {
                if !config.skip_reward {
                    return Err(TxErr::TxProhibited);
                }
                // Reward transactions are internally generated, thus should panic on failure
                if tx.fee.amount != 0 {
                    panic!("reward tx must have no fee");
                } else if !tx.signature_pairs.is_empty() {
                    panic!("reward tx must not be signed");
                } else if tx.timestamp != 0 {
                    panic!("reward tx must have a timestamp of 0");
                }
            }
            TxVariant::TransferTx(transfer) => {
                // TODO check against required address fee amount
                if tx.fee.amount < 0 {
                    return Err(TxErr::InsufficientFeeAmount);
                } else if transfer.from != (&transfer.script).into() {
                    return Err(TxErr::ScriptHashMismatch);
                }

                let success = ScriptEngine::checked_new(data, &transfer.script)
                    .map_err(TxErr::from)?
                    .eval()
                    .map_err(TxErr::ScriptEval)?;
                if !success {
                    return Err(TxErr::ScriptRetFalse);
                }

                let bal = self
                    .get_balance_with_txs(&transfer.from, additional_txs)
                    .ok_or(TxErr::Arithmetic)?
                    .sub(transfer.fee)
                    .ok_or(TxErr::Arithmetic)?
                    .sub(transfer.amount)
                    .ok_or(TxErr::Arithmetic)?;
                check_suf_bal!(bal);
            }
        }
        Ok(())
    }

    fn index_tx(batch: &mut WriteBatch, tx: &TxVariant) {
        match tx {
            TxVariant::OwnerTx(tx) => {
                batch.set_owner(tx.clone());
            }
            TxVariant::MintTx(tx) => {
                batch.add_token_supply(tx.amount);
                batch.add_bal(&tx.to, tx.amount);
            }
            TxVariant::RewardTx(tx) => {
                batch.add_bal(&tx.to, tx.rewards);
            }
            TxVariant::TransferTx(tx) => {
                batch.sub_bal(&tx.from, tx.fee.add(tx.amount).unwrap());
                batch.add_bal(&tx.to, tx.amount);
            }
        }
    }

    pub fn create_genesis_block(&self, minter_key: KeyPair) -> GenesisBlockInfo {
        let info = GenesisBlockInfo::new(minter_key);
        let timestamp = crate::util::get_epoch_ms();

        let owner_tx = OwnerTx {
            base: Tx {
                tx_type: TxType::OWNER,
                fee: "0 GRAEL".parse().unwrap(),
                timestamp,
                signature_pairs: Vec::new(),
            },
            minter: info.minter_key.0.clone(),
            wallet: (&info.script).into(),
            script: Builder::new().push(OpFrame::False).build(),
        };

        let block = (Block {
            height: 0,
            previous_hash: Digest::from_slice(&[0u8; 32]).unwrap(),
            tx_merkle_root: Digest::from_slice(&[0u8; 32]).unwrap(),
            timestamp,
            transactions: vec![TxVariant::OwnerTx(owner_tx.clone())],
        })
        .sign(&info.minter_key);

        let mut batch = WriteBatch::new(Arc::clone(&self.indexer));
        self.store.lock().insert_genesis(&mut batch, block);
        batch.set_owner(owner_tx);
        batch.commit();

        info
    }
}

pub struct GenesisBlockInfo {
    pub minter_key: KeyPair,
    pub wallet_keys: [KeyPair; 4],
    pub script: Script,
}

impl GenesisBlockInfo {
    pub fn new(minter_key: KeyPair) -> Self {
        let wallet_keys = [
            KeyPair::gen(),
            KeyPair::gen(),
            KeyPair::gen(),
            KeyPair::gen(),
        ];

        let script = Builder::new()
            .push(OpFrame::PubKey(wallet_keys[0].0.clone()))
            .push(OpFrame::PubKey(wallet_keys[1].0.clone()))
            .push(OpFrame::PubKey(wallet_keys[2].0.clone()))
            .push(OpFrame::PubKey(wallet_keys[3].0.clone()))
            .push(OpFrame::OpCheckMultiSig(2, 4))
            .build();

        Self {
            minter_key,
            wallet_keys,
            script,
        }
    }
}
<commit_msg>Handle transactions in the mempool when getting the address fee<commit_after>use parking_lot::Mutex;
use std::{path::*, sync::Arc};

pub mod block;
pub mod index;
pub mod store;
pub mod verify;

pub use self::{
    block::*,
    index::{Indexer, WriteBatch},
    store::BlockStore,
    verify::TxErr,
};

use crate::{
    asset::{self, Asset},
    constants::*,
    crypto::*,
    script::*,
    tx::*,
};

#[derive(Clone, Debug)]
pub struct Properties {
    pub height: u64,
    pub owner: Box<OwnerTx>,
    pub token_supply: Asset,
    pub network_fee: Asset,
}

pub struct Blockchain {
    indexer: Arc<Indexer>,
    store: Mutex<BlockStore>,
}

impl Blockchain {
    ///
    /// Creates a new `Blockchain` with an associated indexer and backing
    /// storage is automatically created based on the given `path`.
    ///
    pub fn new(path: &Path) -> Blockchain {
        let indexer = Arc::new(Indexer::new(&Path::join(path, "index")));
        let store = BlockStore::new(&Path::join(path, "blklog"), Arc::clone(&indexer));
        Blockchain {
            indexer,
            store: Mutex::new(store),
        }
    }

    pub fn indexer(&self) -> Arc<Indexer> {
        Arc::clone(&self.indexer)
    }

    pub fn get_properties(&self) -> Properties {
        Properties {
            height: self.get_chain_height(),
            owner: Box::new(self.get_owner()),
            token_supply: self.indexer.get_token_supply(),
            network_fee: self
                .get_network_fee()
                .expect("unexpected error retrieving network fee"),
        }
    }

    #[inline]
    pub fn get_owner(&self) -> OwnerTx {
        self.indexer
            .get_owner()
            .expect("Failed to retrieve owner from index")
    }

    #[inline]
    pub fn get_chain_height(&self) -> u64 {
        self.indexer.get_chain_height()
    }

    pub fn get_chain_head(&self) -> Arc<SignedBlock> {
        let store = self.store.lock();
        let height = store.get_chain_height();
        store.get(height).expect("Failed to get blockchain head")
    }

    pub fn get_block(&self, height: u64) -> Option<Arc<SignedBlock>> {
        let store = self.store.lock();
        store.get(height)
    }

    pub fn get_total_fee(&self, hash: &ScriptHash, additional_txs: &[TxVariant]) -> Option<Asset> {
        let net_fee = self.get_network_fee()?;
        let addr_fee = self.get_address_fee(hash, additional_txs)?;
        addr_fee.add(net_fee)
    }

    pub fn get_address_fee(
        &self,
        hash: &ScriptHash,
        additional_txs: &[TxVariant],
    ) -> Option<Asset> {
        let mut tx_count = 1;
        let mut delta = 0;

        macro_rules! handle_tx_match {
            ($tx:expr) => {
                let has_match = match $tx {
                    TxVariant::OwnerTx(_) => false,
                    TxVariant::MintTx(_) => false,
                    TxVariant::RewardTx(_) => false,
                    TxVariant::TransferTx(tx) => &tx.from == hash,
                };
                if has_match {
                    tx_count += 1;
                    delta = 0;
                }
            };
        }

        for tx in additional_txs {
            handle_tx_match!(tx);
        }

        for i in (0..=self.get_chain_height()).rev() {
            delta += 1;
            let block = self.get_block(i).unwrap();
            for tx in &block.transactions {
                handle_tx_match!(tx);
            }
            if delta == FEE_RESET_WINDOW {
                break;
            }
        }

        let prec = asset::MAX_PRECISION;
        GRAEL_FEE_MIN.mul(GRAEL_FEE_MULT.pow(tx_count as u16, prec)?, prec)
    }

    pub fn get_network_fee(&self) -> Option<Asset> {
        // The network fee adjusts every 5 blocks so that users have a bigger time
        // frame to confirm the fee they want to spend without suddenly changing.
        use crate::constants::*;
        let max_height = self.get_chain_height();
        let max_height = max_height - (max_height % 5);
        let min_height = if max_height > NETWORK_FEE_AVG_WINDOW {
            max_height - NETWORK_FEE_AVG_WINDOW
        } else {
            0
        };

        let mut tx_count: u64 = 1;
        for i in min_height..=max_height {
            tx_count += self.get_block(i).unwrap().transactions.len() as u64;
        }
        tx_count /= NETWORK_FEE_AVG_WINDOW;
        if tx_count > u64::from(u16::max_value()) {
            return None;
        }

        let prec = asset::MAX_PRECISION;
        GRAEL_FEE_MIN.mul(GRAEL_FEE_NET_MULT.pow(tx_count as u16, prec)?, prec)
    }

    pub fn get_balance(&self, hash: &ScriptHash) -> Asset {
        self.indexer.get_balance(hash).unwrap_or_default()
    }

    pub fn get_balance_with_txs(&self, hash: &ScriptHash, txs: &[TxVariant]) -> Option<Asset> {
        let mut bal = self.indexer.get_balance(hash).unwrap_or_default();
        for tx in txs {
            match tx {
                TxVariant::OwnerTx(_) => {}
                TxVariant::MintTx(tx) => {
                    if &tx.to == hash {
                        bal = bal.add(tx.amount)?;
                    }
                }
                TxVariant::RewardTx(tx) => {
                    if &tx.to == hash {
                        bal = bal.add(tx.rewards)?;
                    }
                }
                TxVariant::TransferTx(tx) => {
                    if &tx.from == hash {
                        bal = bal.sub(tx.fee)?;
                        bal = bal.sub(tx.amount)?;
                    } else if &tx.to == hash {
                        bal = bal.add(tx.amount)?;
                    }
                }
            }
        }

        Some(bal)
    }

    pub fn insert_block(&self, block: SignedBlock) -> Result<(), verify::BlockError> {
        static CONFIG: verify::Config = verify::Config { skip_reward: true };
        self.verify_block(&block, &self.get_chain_head(), CONFIG)?;
        let mut batch = WriteBatch::new(Arc::clone(&self.indexer));
        for tx in &block.transactions {
            Self::index_tx(&mut batch, tx);
        }
        self.store.lock().insert(&mut batch, block);
        batch.commit();

        Ok(())
    }

    fn verify_block(
        &self,
        block: &SignedBlock,
        prev_block: &SignedBlock,
        config: verify::Config,
    ) -> Result<(), verify::BlockError> {
        if prev_block.height + 1 != block.height {
            return Err(verify::BlockError::InvalidBlockHeight);
        } else if !block.verify_tx_merkle_root() {
            return Err(verify::BlockError::InvalidMerkleRoot);
        } else if !block.verify_previous_hash(prev_block) {
            return Err(verify::BlockError::InvalidPrevHash);
        }

        let owner = self.get_owner();
        if !block.sig_pair.verify(block.calc_hash().as_ref()) {
            return Err(verify::BlockError::InvalidHash);
        } else if block.sig_pair.pub_key != owner.minter {
            return Err(verify::BlockError::InvalidSignature);
        }

        let len = block.transactions.len();
        for i in 0..len {
            let tx = &block.transactions[i];
            let txs = &block.transactions[0..i];
            if let Err(e) = self.verify_tx(&TxPrecompData::from_tx(tx), txs, config) {
                return Err(verify::BlockError::Tx(e));
            }
        }

        Ok(())
    }

    pub fn verify_tx(
        &self,
        data: &TxPrecompData,
        additional_txs: &[TxVariant],
        config: verify::Config,
    ) -> Result<(), TxErr> {
        macro_rules! check_zero_fee {
            ($asset:expr) => {
                if $asset.amount != 0 {
                    return Err(TxErr::InsufficientFeeAmount);
                }
            };
        }

        macro_rules! check_suf_bal {
            ($asset:expr) => {
                if $asset.amount < 0 {
                    return Err(TxErr::InsufficientBalance);
                }
            };
        }

        let tx = data.tx();
        match tx {
            TxVariant::OwnerTx(new_owner) => {
                check_zero_fee!(tx.fee);

                let owner = self.get_owner();
                if owner.wallet != (&new_owner.script).into() {
                    return Err(TxErr::ScriptHashMismatch);
                }

                let success = ScriptEngine::checked_new(data, &new_owner.script)
                    .map_err(TxErr::from)?
                    .eval()
                    .map_err(TxErr::ScriptEval)?;
                if !success {
                    return Err(TxErr::ScriptRetFalse);
                }
            }
            TxVariant::MintTx(mint_tx) => {
                check_zero_fee!(tx.fee);

                let owner = self.get_owner();
                if owner.wallet != (&mint_tx.script).into() {
                    return Err(TxErr::ScriptHashMismatch);
                }
                let success = ScriptEngine::checked_new(data, &mint_tx.script)
                    .map_err(TxErr::from)?
                    .eval()
                    .map_err(TxErr::ScriptEval)?;
                if !success {
                    return Err(TxErr::ScriptRetFalse);
                }

                // Sanity check to ensure too many new coins can't be minted
                self.get_balance_with_txs(&mint_tx.to, additional_txs)
                    .ok_or(TxErr::Arithmetic)?
                    .add(mint_tx.amount)
                    .ok_or(TxErr::Arithmetic)?;

                self.indexer
                    .get_token_supply()
                    .add(mint_tx.amount)
                    .ok_or(TxErr::Arithmetic)?;
            }
            TxVariant::RewardTx(tx) => {
                if !config.skip_reward {
                    return Err(TxErr::TxProhibited);
                }
                // Reward transactions are internally generated, thus should panic on failure
                if tx.fee.amount != 0 {
                    panic!("reward tx must have no fee");
                } else if !tx.signature_pairs.is_empty() {
                    panic!("reward tx must not be signed");
                } else if tx.timestamp != 0 {
                    panic!("reward tx must have a timestamp of 0");
                }
            }
            TxVariant::TransferTx(transfer) => {
                let total_fee = self
                    .get_total_fee(&transfer.from, additional_txs)
                    .ok_or(TxErr::Arithmetic)?;
                if tx.fee.lt(total_fee).ok_or(TxErr::Arithmetic)? {
                    return Err(TxErr::InsufficientFeeAmount);
                } else if transfer.from != (&transfer.script).into() {
                    return Err(TxErr::ScriptHashMismatch);
                }

                let success = ScriptEngine::checked_new(data, &transfer.script)
                    .map_err(TxErr::from)?
                    .eval()
                    .map_err(TxErr::ScriptEval)?;
                if !success {
                    return Err(TxErr::ScriptRetFalse);
                }

                let bal = self
                    .get_balance_with_txs(&transfer.from, additional_txs)
                    .ok_or(TxErr::Arithmetic)?
                    .sub(transfer.fee)
                    .ok_or(TxErr::Arithmetic)?
                    .sub(transfer.amount)
                    .ok_or(TxErr::Arithmetic)?;
                check_suf_bal!(bal);
            }
        }
        Ok(())
    }

    fn index_tx(batch: &mut WriteBatch, tx: &TxVariant) {
        match tx {
            TxVariant::OwnerTx(tx) => {
                batch.set_owner(tx.clone());
            }
            TxVariant::MintTx(tx) => {
                batch.add_token_supply(tx.amount);
                batch.add_bal(&tx.to, tx.amount);
            }
            TxVariant::RewardTx(tx) => {
                batch.add_bal(&tx.to, tx.rewards);
            }
            TxVariant::TransferTx(tx) => {
                batch.sub_bal(&tx.from, tx.fee.add(tx.amount).unwrap());
                batch.add_bal(&tx.to, tx.amount);
            }
        }
    }

    pub fn create_genesis_block(&self, minter_key: KeyPair) -> GenesisBlockInfo {
        let info = GenesisBlockInfo::new(minter_key);
        let timestamp = crate::util::get_epoch_ms();

        let owner_tx = OwnerTx {
            base: Tx {
                tx_type: TxType::OWNER,
                fee: "0 GRAEL".parse().unwrap(),
                timestamp,
                signature_pairs: Vec::new(),
            },
            minter: info.minter_key.0.clone(),
            wallet: (&info.script).into(),
            script: Builder::new().push(OpFrame::False).build(),
        };

        let block = (Block {
            height: 0,
            previous_hash: Digest::from_slice(&[0u8; 32]).unwrap(),
            tx_merkle_root: Digest::from_slice(&[0u8; 32]).unwrap(),
            timestamp,
            transactions: vec![TxVariant::OwnerTx(owner_tx.clone())],
        })
        .sign(&info.minter_key);

        let mut batch = WriteBatch::new(Arc::clone(&self.indexer));
        self.store.lock().insert_genesis(&mut batch, block);
        batch.set_owner(owner_tx);
        batch.commit();

        info
    }
}

pub struct GenesisBlockInfo {
    pub minter_key: KeyPair,
    pub wallet_keys: [KeyPair; 4],
    pub script: Script,
}

impl GenesisBlockInfo {
    pub fn new(minter_key: KeyPair) -> Self {
        let wallet_keys = [
            KeyPair::gen(),
            KeyPair::gen(),
            KeyPair::gen(),
            KeyPair::gen(),
        ];

        let script = Builder::new()
            .push(OpFrame::PubKey(wallet_keys[0].0.clone()))
            .push(OpFrame::PubKey(wallet_keys[1].0.clone()))
            .push(OpFrame::PubKey(wallet_keys[2].0.clone()))
            .push(OpFrame::PubKey(wallet_keys[3].0.clone()))
            .push(OpFrame::OpCheckMultiSig(2, 4))
            .build();

        Self {
            minter_key,
            wallet_keys,
            script,
        }
    }
}
<|endoftext|>


<commit_before>/// Windows implementation of dynamic library loading.
///
/// This module should be expanded with more Windows-specific functionality in the future.

extern crate winapi;
extern crate kernel32;

use std::ffi::{CStr, OsStr, OsString};
use std::marker;
use std::mem;
use std::ptr;
use std::sync::atomic::{AtomicBool, Ordering};
use std::os::windows::ffi::{OsStrExt, OsStringExt};

/// A platform-specific equivalent of the cross-platform `Library`.
pub struct Library(winapi::HMODULE);

impl Library {
    /// Find and load a shared library (module).
    ///
    /// Locations where library is searched for is platform specific and can’t be adjusted
    /// portably.
    ///
    /// Corresponds to `LoadLibraryW(filename)`.
    #[inline]
    pub fn new<P: AsRef<OsStr>>(filename: P) -> ::Result<Library> {
        let mut wide_filename: Vec<u16> = filename.as_ref().encode_wide().collect();
        wide_filename.push(0);
        wide_filename.shrink_to_fit();
        let _guard = ErrorModeGuard::new();

        let ret = with_get_last_error(|| {
            // Make sure no winapi calls as a result of drop happen inside this closure, because
            // otherwise that might change the return value of the GetLastError.
            let handle = unsafe { kernel32::LoadLibraryW(wide_filename.as_ptr()) };
            if handle.is_null()  {
                None
            } else {
                Some(Library(handle))
            }
        }).map_err(|e| e.unwrap_or_else(||
            panic!("LoadLibraryW failed but GetLastError did not report the error")
        ));

        drop(wide_filename); // Drop wide_filename here to ensure it doesn’t get moved and dropped
                             // inside the closure by mistake.
        ret
    }

    /// Get a symbol by name.
    ///
    /// Mangling or symbol rustification is not done: trying to `get` something like `x::y`
    /// will not work.
    ///
    /// # Unsafety
    ///
    /// The pointer to a symbol of arbitrary type or kind is returned. Requesting for function
    /// pointer while the symbol is not one and vice versa is not memory safe.
    ///
    /// The return value does not ensure the symbol does not outlive the library.
    pub unsafe fn get<T>(&self, symbol: &CStr) -> ::Result<Symbol<T>> {
        with_get_last_error(|| {
            let symbol = kernel32::GetProcAddress(self.0, symbol.as_ptr());
            if symbol.is_null() {
                None
            } else {
                Some(Symbol {
                    pointer: symbol,
                    pd: marker::PhantomData
                })
            }
        }).map_err(|e| e.unwrap_or_else(||
            panic!("GetProcAddress failed but GetLastError did not report the error")
        ))
    }
}

impl Drop for Library {
    fn drop(&mut self) {
        with_get_last_error(|| {
            if unsafe { kernel32::FreeLibrary(self.0) == 0 } {
                None
            } else {
                Some(())
            }
        }).unwrap()
    }
}

impl ::std::fmt::Debug for Library {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        unsafe {
            let mut buf: [winapi::WCHAR; 1024] = mem::uninitialized();
            let len = kernel32::GetModuleFileNameW(self.0,
                                                   (&mut buf[..]).as_mut_ptr(), 1024) as usize;
            if len == 0 {
                f.write_str(&format!("Library@{:p}", self.0))
            } else {
                let string: OsString = OsString::from_wide(&buf[..len]);
                f.write_str(&format!("Library@{:p} from {:?}", self.0, string))
            }
        }
    }
}

pub struct Symbol<T> {
    pointer: winapi::FARPROC,
    pd: marker::PhantomData<T>
}

impl<T> ::std::ops::Deref for Symbol<T> {
    type Target = T;
    fn deref(&self) -> &T {
        unsafe {
            &*(&self.pointer as *const _ as *const T)
        }
    }
}

impl<T> ::std::fmt::Debug for Symbol<T> {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        f.write_str(&format!("Symbol@{:p}", self.pointer))
    }
}

static USE_ERRORMODE: AtomicBool = ATOMIC_BOOL_INIT;
struct ErrorModeGuard(winapi::DWORD);

impl ErrorModeGuard {
    fn new() -> ErrorModeGuard {
        let mut ret = ErrorModeGuard(0);

        if !USE_ERRORMODE.load(Ordering::Acquire) {
            if unsafe { kernel32::SetThreadErrorMode(1, &mut ret.0) == 0
                        && kernel32::GetLastError() == winapi::ERROR_CALL_NOT_IMPLEMENTED } {
                USE_ERRORMODE.store(true, Ordering::Release);
            } else {
                return ret;
            }
        }
        ret.0 = unsafe { kernel32::SetErrorMode(1) };
        ret
    }
}

impl Drop for ErrorModeGuard {
    fn drop(&mut self) {
        unsafe {
            if !USE_ERRORMODE.load(Ordering::Relaxed) {
                kernel32::SetThreadErrorMode(self.0, ptr::null_mut());
            } else {
                kernel32::SetErrorMode(self.0);
            }
        }
    }
}

fn with_get_last_error<T, F>(closure: F) -> Result<T, Option<String>>
where F: FnOnce() -> Option<T> {
    closure().ok_or_else(|| {
        let error = unsafe { kernel32::GetLastError() };
        if error == 0 {
            None
        } else {
            // TODO: Possibly use FormatMessage (lots of work here)
            Some(format!("Error {}", error))
        }
    })
}

#[test]
fn works_new_kernel32() {
    let that = Library::new("kernel32.dll").unwrap();
    unsafe {
        that.get::<*mut usize>(&::std::ffi::CString::new("GetLastError").unwrap()).unwrap();
    }
}

#[test]
fn fails_new_kernel23() {
    Library::new("kernel23").err().unwrap();
}
<commit_msg>Fix windows import<commit_after>/// Windows implementation of dynamic library loading.
///
/// This module should be expanded with more Windows-specific functionality in the future.

extern crate winapi;
extern crate kernel32;

use std::ffi::{CStr, OsStr, OsString};
use std::marker;
use std::mem;
use std::ptr;
use std::sync::atomic::{AtomicBool, ATOMIC_BOOL_INIT, Ordering};
use std::os::windows::ffi::{OsStrExt, OsStringExt};

/// A platform-specific equivalent of the cross-platform `Library`.
pub struct Library(winapi::HMODULE);

impl Library {
    /// Find and load a shared library (module).
    ///
    /// Locations where library is searched for is platform specific and can’t be adjusted
    /// portably.
    ///
    /// Corresponds to `LoadLibraryW(filename)`.
    #[inline]
    pub fn new<P: AsRef<OsStr>>(filename: P) -> ::Result<Library> {
        let mut wide_filename: Vec<u16> = filename.as_ref().encode_wide().collect();
        wide_filename.push(0);
        wide_filename.shrink_to_fit();
        let _guard = ErrorModeGuard::new();

        let ret = with_get_last_error(|| {
            // Make sure no winapi calls as a result of drop happen inside this closure, because
            // otherwise that might change the return value of the GetLastError.
            let handle = unsafe { kernel32::LoadLibraryW(wide_filename.as_ptr()) };
            if handle.is_null()  {
                None
            } else {
                Some(Library(handle))
            }
        }).map_err(|e| e.unwrap_or_else(||
            panic!("LoadLibraryW failed but GetLastError did not report the error")
        ));

        drop(wide_filename); // Drop wide_filename here to ensure it doesn’t get moved and dropped
                             // inside the closure by mistake.
        ret
    }

    /// Get a symbol by name.
    ///
    /// Mangling or symbol rustification is not done: trying to `get` something like `x::y`
    /// will not work.
    ///
    /// # Unsafety
    ///
    /// The pointer to a symbol of arbitrary type or kind is returned. Requesting for function
    /// pointer while the symbol is not one and vice versa is not memory safe.
    ///
    /// The return value does not ensure the symbol does not outlive the library.
    pub unsafe fn get<T>(&self, symbol: &CStr) -> ::Result<Symbol<T>> {
        with_get_last_error(|| {
            let symbol = kernel32::GetProcAddress(self.0, symbol.as_ptr());
            if symbol.is_null() {
                None
            } else {
                Some(Symbol {
                    pointer: symbol,
                    pd: marker::PhantomData
                })
            }
        }).map_err(|e| e.unwrap_or_else(||
            panic!("GetProcAddress failed but GetLastError did not report the error")
        ))
    }
}

impl Drop for Library {
    fn drop(&mut self) {
        with_get_last_error(|| {
            if unsafe { kernel32::FreeLibrary(self.0) == 0 } {
                None
            } else {
                Some(())
            }
        }).unwrap()
    }
}

impl ::std::fmt::Debug for Library {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        unsafe {
            let mut buf: [winapi::WCHAR; 1024] = mem::uninitialized();
            let len = kernel32::GetModuleFileNameW(self.0,
                                                   (&mut buf[..]).as_mut_ptr(), 1024) as usize;
            if len == 0 {
                f.write_str(&format!("Library@{:p}", self.0))
            } else {
                let string: OsString = OsString::from_wide(&buf[..len]);
                f.write_str(&format!("Library@{:p} from {:?}", self.0, string))
            }
        }
    }
}

pub struct Symbol<T> {
    pointer: winapi::FARPROC,
    pd: marker::PhantomData<T>
}

impl<T> ::std::ops::Deref for Symbol<T> {
    type Target = T;
    fn deref(&self) -> &T {
        unsafe {
            &*(&self.pointer as *const _ as *const T)
        }
    }
}

impl<T> ::std::fmt::Debug for Symbol<T> {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        f.write_str(&format!("Symbol@{:p}", self.pointer))
    }
}

static USE_ERRORMODE: AtomicBool = ATOMIC_BOOL_INIT;
struct ErrorModeGuard(winapi::DWORD);

impl ErrorModeGuard {
    fn new() -> ErrorModeGuard {
        let mut ret = ErrorModeGuard(0);

        if !USE_ERRORMODE.load(Ordering::Acquire) {
            if unsafe { kernel32::SetThreadErrorMode(1, &mut ret.0) == 0
                        && kernel32::GetLastError() == winapi::ERROR_CALL_NOT_IMPLEMENTED } {
                USE_ERRORMODE.store(true, Ordering::Release);
            } else {
                return ret;
            }
        }
        ret.0 = unsafe { kernel32::SetErrorMode(1) };
        ret
    }
}

impl Drop for ErrorModeGuard {
    fn drop(&mut self) {
        unsafe {
            if !USE_ERRORMODE.load(Ordering::Relaxed) {
                kernel32::SetThreadErrorMode(self.0, ptr::null_mut());
            } else {
                kernel32::SetErrorMode(self.0);
            }
        }
    }
}

fn with_get_last_error<T, F>(closure: F) -> Result<T, Option<String>>
where F: FnOnce() -> Option<T> {
    closure().ok_or_else(|| {
        let error = unsafe { kernel32::GetLastError() };
        if error == 0 {
            None
        } else {
            // TODO: Possibly use FormatMessage (lots of work here)
            Some(format!("Error {}", error))
        }
    })
}

#[test]
fn works_new_kernel32() {
    let that = Library::new("kernel32.dll").unwrap();
    unsafe {
        that.get::<*mut usize>(&::std::ffi::CString::new("GetLastError").unwrap()).unwrap();
    }
}

#[test]
fn fails_new_kernel23() {
    Library::new("kernel23").err().unwrap();
}
<|endoftext|>


<commit_before>macro_rules! declare_deprecated_lint {
    (pub $name: ident, $_reason: expr) => {
        declare_lint!(pub $name, Allow, "deprecated lint")
    }
}

declare_deprecated_lint! {
/// **What it does:** Nothing. This lint has been deprecated.
///
/// **Deprecation reason:** This used to check for `assert!(a == b)` and recommend
/// replacement with `assert_eq!(a, b)`, but this is no longer needed after RFC 2011.
    pub SHOULD_ASSERT_EQ,
    "`assert!()` will be more flexible with RFC 2011"
}

declare_deprecated_lint! {
/// **What it does:** Nothing. This lint has been deprecated.
///
/// **Deprecation reason:** This used to check for `Vec::extend`, which was slower than
/// `Vec::extend_from_slice`. Thanks to specialization, this is no longer true.
    pub EXTEND_FROM_SLICE,
    "`.extend_from_slice(_)` is a faster way to extend a Vec by a slice"
}

declare_deprecated_lint! {
/// **What it does:** Nothing. This lint has been deprecated.
///
/// **Deprecation reason:** `Range::step_by(0)` used to be linted since it's
/// an infinite iterator, which is better expressed by `iter::repeat`,
/// but the method has been removed for `Iterator::step_by` which panics
/// if given a zero
    pub RANGE_STEP_BY_ZERO,
    "`iterator.step_by(0)` panics nowadays"
}

declare_deprecated_lint! {
/// **What it does:** Nothing. This lint has been deprecated.
///
/// **Deprecation reason:** This used to check for `Vec::as_slice`, which was unstable with good
/// stable alternatives. `Vec::as_slice` has now been stabilized.
    pub UNSTABLE_AS_SLICE,
    "`Vec::as_slice` has been stabilized in 1.7"
}

declare_deprecated_lint! {
/// **What it does:** Nothing. This lint has been deprecated.
///
/// **Deprecation reason:** This used to check for `Vec::as_mut_slice`, which was unstable with good
/// stable alternatives. `Vec::as_mut_slice` has now been stabilized.
    pub UNSTABLE_AS_MUT_SLICE,
    "`Vec::as_mut_slice` has been stabilized in 1.7"
}

declare_deprecated_lint! {
/// **What it does:** Nothing. This lint has been deprecated.
///
/// **Deprecation reason:** This used to check for `.to_string()` method calls on values
/// of type `&str`. This is not unidiomatic and with specialization coming, `to_string` could be
/// specialized to be as efficient as `to_owned`.
    pub STR_TO_STRING,
    "using `str::to_string` is common even today and specialization will likely happen soon"
}

declare_deprecated_lint! {
/// **What it does:** Nothing. This lint has been deprecated.
///
/// **Deprecation reason:** This used to check for `.to_string()` method calls on values
/// of type `String`. This is not unidiomatic and with specialization coming, `to_string` could be
/// specialized to be as efficient as `clone`.
    pub STRING_TO_STRING,
    "using `string::to_string` is common even today and specialization will likely happen soon"
}

declare_deprecated_lint! {
/// **What it does:** Nothing. This lint has been deprecated.
///
/// **Deprecation reason:** This lint should never have applied to non-pointer types, as transmuting
/// between non-pointer types of differing alignment is well-defined behavior (it's semantically
/// equivalent to a memcpy). This lint has thus been refactored into two separate lints:
/// cast_ptr_alignment and transmute_ptr_to_ptr.
    pub MISALIGNED_TRANSMUTE,
    "this lint has been split into cast_ptr_alignment and transmute_ptr_to_ptr"
}

declare_deprecated_lint! {
/// **What it does:** Nothing. This lint has been deprecated.
///
/// **Deprecation reason:** This lint is too subjective, not having a good reason for being in clippy.
/// Additionally, compound assignment operators may be overloaded separately from their non-assigning
/// counterparts, so this lint may suggest a change in behavior or the code may not compile.
declare_deprecated_lint! {
    pub ASSIGN_OPS,
    "using compound assignment operators (e.g., `+=`) is harmless"
}

declare_deprecated_lint! {
/// **What it does:** Nothing. This lint has been deprecated.
///
/// **Deprecation reason:** The original rule will only lint for `if let`. After
/// making it support to lint `match`, naming as `if let` is not suitable for it.
/// So, this lint is deprecated.
    pub IF_LET_REDUNDANT_PATTERN_MATCHING,
    "this lint has been changed to redundant_pattern_matching"
}

declare_deprecated_lint! {
/// **What it does:** Nothing. This lint has been deprecated.
///
/// **Deprecation reason:** This lint used to suggest replacing `let mut vec =
/// Vec::with_capacity(n); vec.set_len(n);` with `let vec = vec![0; n];`. The
/// replacement has very different performance characteristics so the lint is
/// deprecated.
    pub UNSAFE_VECTOR_INITIALIZATION,
    "the replacement suggested by this lint had substantially different behavior"
}

declare_deprecated_lint! {
/// **What it does:** Nothing. This lint has been deprecated.
///
/// **Deprecation reason:** This lint has been superseded by the warn-by-default
/// `invalid_value` rustc lint.
    pub INVALID_REF,
    "superseded by rustc lint `invalid_value`"
}

declare_deprecated_lint! {
/// **What it does:** Nothing. This lint has been deprecated.
///
/// **Deprecation reason:** This lint has been superseded by #[must_use] in rustc.
    pub UNUSED_COLLECT,
    "`collect` has been marked as #[must_use] in rustc and that covers all cases of this lint"
}
<commit_msg>deprecated_lints: remove extraneous `declare_deprecated_lint`<commit_after>macro_rules! declare_deprecated_lint {
    (pub $name: ident, $_reason: expr) => {
        declare_lint!(pub $name, Allow, "deprecated lint")
    }
}

declare_deprecated_lint! {
/// **What it does:** Nothing. This lint has been deprecated.
///
/// **Deprecation reason:** This used to check for `assert!(a == b)` and recommend
/// replacement with `assert_eq!(a, b)`, but this is no longer needed after RFC 2011.
    pub SHOULD_ASSERT_EQ,
    "`assert!()` will be more flexible with RFC 2011"
}

declare_deprecated_lint! {
/// **What it does:** Nothing. This lint has been deprecated.
///
/// **Deprecation reason:** This used to check for `Vec::extend`, which was slower than
/// `Vec::extend_from_slice`. Thanks to specialization, this is no longer true.
    pub EXTEND_FROM_SLICE,
    "`.extend_from_slice(_)` is a faster way to extend a Vec by a slice"
}

declare_deprecated_lint! {
/// **What it does:** Nothing. This lint has been deprecated.
///
/// **Deprecation reason:** `Range::step_by(0)` used to be linted since it's
/// an infinite iterator, which is better expressed by `iter::repeat`,
/// but the method has been removed for `Iterator::step_by` which panics
/// if given a zero
    pub RANGE_STEP_BY_ZERO,
    "`iterator.step_by(0)` panics nowadays"
}

declare_deprecated_lint! {
/// **What it does:** Nothing. This lint has been deprecated.
///
/// **Deprecation reason:** This used to check for `Vec::as_slice`, which was unstable with good
/// stable alternatives. `Vec::as_slice` has now been stabilized.
    pub UNSTABLE_AS_SLICE,
    "`Vec::as_slice` has been stabilized in 1.7"
}

declare_deprecated_lint! {
/// **What it does:** Nothing. This lint has been deprecated.
///
/// **Deprecation reason:** This used to check for `Vec::as_mut_slice`, which was unstable with good
/// stable alternatives. `Vec::as_mut_slice` has now been stabilized.
    pub UNSTABLE_AS_MUT_SLICE,
    "`Vec::as_mut_slice` has been stabilized in 1.7"
}

declare_deprecated_lint! {
/// **What it does:** Nothing. This lint has been deprecated.
///
/// **Deprecation reason:** This used to check for `.to_string()` method calls on values
/// of type `&str`. This is not unidiomatic and with specialization coming, `to_string` could be
/// specialized to be as efficient as `to_owned`.
    pub STR_TO_STRING,
    "using `str::to_string` is common even today and specialization will likely happen soon"
}

declare_deprecated_lint! {
/// **What it does:** Nothing. This lint has been deprecated.
///
/// **Deprecation reason:** This used to check for `.to_string()` method calls on values
/// of type `String`. This is not unidiomatic and with specialization coming, `to_string` could be
/// specialized to be as efficient as `clone`.
    pub STRING_TO_STRING,
    "using `string::to_string` is common even today and specialization will likely happen soon"
}

declare_deprecated_lint! {
/// **What it does:** Nothing. This lint has been deprecated.
///
/// **Deprecation reason:** This lint should never have applied to non-pointer types, as transmuting
/// between non-pointer types of differing alignment is well-defined behavior (it's semantically
/// equivalent to a memcpy). This lint has thus been refactored into two separate lints:
/// cast_ptr_alignment and transmute_ptr_to_ptr.
    pub MISALIGNED_TRANSMUTE,
    "this lint has been split into cast_ptr_alignment and transmute_ptr_to_ptr"
}

/// **What it does:** Nothing. This lint has been deprecated.
///
/// **Deprecation reason:** This lint is too subjective, not having a good reason for being in clippy.
/// Additionally, compound assignment operators may be overloaded separately from their non-assigning
/// counterparts, so this lint may suggest a change in behavior or the code may not compile.
declare_deprecated_lint! {
    pub ASSIGN_OPS,
    "using compound assignment operators (e.g., `+=`) is harmless"
}

declare_deprecated_lint! {
/// **What it does:** Nothing. This lint has been deprecated.
///
/// **Deprecation reason:** The original rule will only lint for `if let`. After
/// making it support to lint `match`, naming as `if let` is not suitable for it.
/// So, this lint is deprecated.
    pub IF_LET_REDUNDANT_PATTERN_MATCHING,
    "this lint has been changed to redundant_pattern_matching"
}

declare_deprecated_lint! {
/// **What it does:** Nothing. This lint has been deprecated.
///
/// **Deprecation reason:** This lint used to suggest replacing `let mut vec =
/// Vec::with_capacity(n); vec.set_len(n);` with `let vec = vec![0; n];`. The
/// replacement has very different performance characteristics so the lint is
/// deprecated.
    pub UNSAFE_VECTOR_INITIALIZATION,
    "the replacement suggested by this lint had substantially different behavior"
}

declare_deprecated_lint! {
/// **What it does:** Nothing. This lint has been deprecated.
///
/// **Deprecation reason:** This lint has been superseded by the warn-by-default
/// `invalid_value` rustc lint.
    pub INVALID_REF,
    "superseded by rustc lint `invalid_value`"
}

declare_deprecated_lint! {
/// **What it does:** Nothing. This lint has been deprecated.
///
/// **Deprecation reason:** This lint has been superseded by #[must_use] in rustc.
    pub UNUSED_COLLECT,
    "`collect` has been marked as #[must_use] in rustc and that covers all cases of this lint"
}
<|endoftext|>


<commit_before>//! TODO Fill in

use std::fmt::{self, Display, Formatter};
use std::default::Default;
use rlua::{self, Table, Lua, UserData, ToLua, Value, UserDataMethods, AnyUserData};
use super::object::{self, Object, Objectable};
use super::class::{self, Class, ClassBuilder};
use super::property::Property;
use super::signal;

#[derive(Clone, Debug)]
pub struct TagState {
    name: Option<String>,
    selected: bool,
    // TODO Fill in
    dummy: i32
}

pub struct Tag<'lua>(Object<'lua>);

impl Default for TagState {
    fn default() -> Self {
        TagState {
            name: None,
            selected: false,
            dummy: 0
        }
    }
}

impl <'lua> Tag<'lua> {
    fn new(lua: &'lua Lua, args: Table) -> rlua::Result<Object<'lua>> {
        let class = class::class_setup(lua, "tag")?;
        Ok(Tag::allocate(lua, class)?
           .handle_constructor_argument(args)?
           .build())
    }
}

impl Display for TagState {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        write!(f, "Tag: {:p}", self)
    }
}

impl <'lua> ToLua<'lua> for Tag<'lua> {
    fn to_lua(self, lua: &'lua Lua) -> rlua::Result<Value<'lua>> {
        self.0.to_lua(lua)
    }
}

impl UserData for TagState {
    fn add_methods(methods: &mut UserDataMethods<Self>) {
        object::default_add_methods(methods);
    }
}

pub fn init(lua: &Lua) -> rlua::Result<Class> {
    method_setup(lua, Class::builder(lua, "tag", None)?)?
        .save_class("tag")?
        .build()
}

fn method_setup<'lua>(lua: &'lua Lua, builder: ClassBuilder<'lua>) -> rlua::Result<ClassBuilder<'lua>> {
    // TODO Do properly
    use super::dummy;
    builder.method("connect_signal".into(), lua.create_function(dummy)?)?
           .method("__call".into(), lua.create_function(|lua, args: Table| Tag::new(lua, args))?)?
           .property(Property::new("name".into(),
                                   Some(lua.create_function(set_name)?),
                                   Some(lua.create_function(get_name)?),
                                   Some(lua.create_function(set_name)?)))?
           .property(Property::new("selected".into(),
                                   Some(lua.create_function(set_selected)?),
                                   Some(lua.create_function(get_selected)?),
                                   Some(lua.create_function(set_selected)?)))
}

impl_objectable!(Tag, TagState);

fn set_name<'lua>(lua: &'lua Lua, (obj, val): (AnyUserData<'lua>, String))
                    -> rlua::Result<Value<'lua>> {
    let mut tag = Tag::cast(obj.clone().into())?;
    tag.get_object_mut()?.name = Some(val.clone());
    signal::emit_object_signal(lua,
                        obj.into(),
                        "property::name".into(),
                        ())?;
    Ok(Value::Nil)
}

fn get_name<'lua>(lua: &'lua Lua, obj: AnyUserData<'lua>)
                  -> rlua::Result<Value<'lua>> {
    match obj.borrow::<TagState>()?.name {
        None => Ok(Value::Nil),
        Some(ref name) => Ok(Value::String(lua.create_string(&name)?))
    }
}

fn set_selected<'lua>(lua: &'lua Lua, (obj, val): (AnyUserData<'lua>, bool))
                      -> rlua::Result<Value<'lua>> {
    let mut tag = Tag::cast(obj.clone().into())?;
    {
        let mut tag = tag.get_object_mut()?;
        if tag.selected == val {
            return Ok(Value::Nil)
        }
        tag.selected = val;
    }
    signal::emit_object_signal(lua,
                               obj.into(),
                               "property::selected".into(),
                               ())?;
    Ok(Value::Nil)
}

fn get_selected<'lua>(_: &'lua Lua, obj: AnyUserData<'lua>)
                  -> rlua::Result<Value<'lua>> {
    Ok(Value::Boolean(obj.borrow::<TagState>()?.selected))
}

#[cfg(test)]
mod test {
    use rlua::Lua;
    use super::super::tag;

    #[test]
    fn tag_name_empty() {
        let lua = Lua::new();
        tag::init(&lua).unwrap();
        lua.eval(r#"
assert(type(tag{}.name) == "nil")
"#, None).unwrap()
    }

    #[test]
    fn tag_name_change() {
        let lua = Lua::new();
        tag::init(&lua).unwrap();
        lua.eval(r#"
local t = tag{ name = "a very cool tag" }
assert(t.name == "a very cool tag")
"#, None).unwrap()
    }

    #[test]
    fn tag_name_signal() {
        let lua = Lua::new();
        tag::init(&lua).unwrap();
        lua.eval(r#"
local t = tag{}

local called = 0
t:connect_signal("property::name", function(t)
    assert(t.name == "bye")
    called = called + 1
end)

t.name = "bye"
assert(t.name == "bye")
assert(called == 1)
"#, None).unwrap()
    }

    #[test]
    fn tag_selected() {
        let lua = Lua::new();
        tag::init(&lua).unwrap();
        lua.eval(r#"
local t = tag{}
assert(t.selected == false)

local called = 0
t:connect_signal("property::selected", function(t)
    called = called + 1
end)

t.selected = false
assert(t.selected == false)
assert(called == 0)

t.selected = true
assert(t.selected == true)
assert(called == 1)

t.selected = true
assert(t.selected == true)
assert(called == 1)

t.selected = false
assert(t.selected == false)
assert(called == 2)
"#, None).unwrap()
    }
}
<commit_msg>tag: Add .activated property<commit_after>//! TODO Fill in

use std::fmt::{self, Display, Formatter};
use std::default::Default;
use rlua::{self, Table, Lua, UserData, ToLua, Value, UserDataMethods, AnyUserData};
use super::object::{self, Object, Objectable};
use super::class::{self, Class, ClassBuilder};
use super::property::Property;
use super::signal;

#[derive(Clone, Debug)]
pub struct TagState {
    name: Option<String>,
    selected: bool,
    activated: bool,
}

pub struct Tag<'lua>(Object<'lua>);

impl Default for TagState {
    fn default() -> Self {
        TagState {
            name: None,
            selected: false,
            activated: false,
        }
    }
}

impl <'lua> Tag<'lua> {
    fn new(lua: &'lua Lua, args: Table) -> rlua::Result<Object<'lua>> {
        let class = class::class_setup(lua, "tag")?;
        Ok(Tag::allocate(lua, class)?
           .handle_constructor_argument(args)?
           .build())
    }
}

impl Display for TagState {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        write!(f, "Tag: {:p}", self)
    }
}

impl <'lua> ToLua<'lua> for Tag<'lua> {
    fn to_lua(self, lua: &'lua Lua) -> rlua::Result<Value<'lua>> {
        self.0.to_lua(lua)
    }
}

impl UserData for TagState {
    fn add_methods(methods: &mut UserDataMethods<Self>) {
        object::default_add_methods(methods);
    }
}

pub fn init(lua: &Lua) -> rlua::Result<Class> {
    method_setup(lua, Class::builder(lua, "tag", None)?)?
        .save_class("tag")?
        .build()
}

fn method_setup<'lua>(lua: &'lua Lua, builder: ClassBuilder<'lua>) -> rlua::Result<ClassBuilder<'lua>> {
    // TODO Do properly
    use super::dummy;
    builder.method("connect_signal".into(), lua.create_function(dummy)?)?
           .method("__call".into(), lua.create_function(|lua, args: Table| Tag::new(lua, args))?)?
           .property(Property::new("name".into(),
                                   Some(lua.create_function(set_name)?),
                                   Some(lua.create_function(get_name)?),
                                   Some(lua.create_function(set_name)?)))?
           .property(Property::new("selected".into(),
                                   Some(lua.create_function(set_selected)?),
                                   Some(lua.create_function(get_selected)?),
                                   Some(lua.create_function(set_selected)?)))?
           .property(Property::new("activated".into(),
                                   Some(lua.create_function(set_activated)?),
                                   Some(lua.create_function(get_activated)?),
                                   Some(lua.create_function(set_activated)?)))
}

impl_objectable!(Tag, TagState);

fn set_name<'lua>(lua: &'lua Lua, (obj, val): (AnyUserData<'lua>, String))
                    -> rlua::Result<Value<'lua>> {
    let mut tag = Tag::cast(obj.clone().into())?;
    tag.get_object_mut()?.name = Some(val.clone());
    signal::emit_object_signal(lua,
                        obj.into(),
                        "property::name".into(),
                        ())?;
    Ok(Value::Nil)
}

fn get_name<'lua>(lua: &'lua Lua, obj: AnyUserData<'lua>)
                  -> rlua::Result<Value<'lua>> {
    match obj.borrow::<TagState>()?.name {
        None => Ok(Value::Nil),
        Some(ref name) => Ok(Value::String(lua.create_string(&name)?))
    }
}

fn set_selected<'lua>(lua: &'lua Lua, (obj, val): (AnyUserData<'lua>, bool))
                      -> rlua::Result<Value<'lua>> {
    let mut tag = Tag::cast(obj.clone().into())?;
    {
        let mut tag = tag.get_object_mut()?;
        if tag.selected == val {
            return Ok(Value::Nil)
        }
        tag.selected = val;
    }
    signal::emit_object_signal(lua,
                               obj.into(),
                               "property::selected".into(),
                               ())?;
    Ok(Value::Nil)
}

fn get_selected<'lua>(_: &'lua Lua, obj: AnyUserData<'lua>)
                  -> rlua::Result<Value<'lua>> {
    Ok(Value::Boolean(obj.borrow::<TagState>()?.selected))
}

fn set_activated<'lua>(lua: &'lua Lua, (obj, val): (AnyUserData<'lua>, bool))
                       -> rlua::Result<Value<'lua>> {
    let mut tag = Tag::cast(obj.clone().into())?;
    {
        let mut tag = tag.get_object_mut()?;
        if tag.activated == val {
            return Ok(Value::Nil)
        }
        tag.activated = val;
    }
    if !val {
        set_selected(lua, (obj.clone(), false))?;
    }
    signal::emit_object_signal(lua,
                               obj.into(),
                               "property::activated".into(),
                               ())?;
    Ok(Value::Nil)
}

fn get_activated<'lua>(_: &'lua Lua, obj: AnyUserData<'lua>)
                       -> rlua::Result<Value<'lua>> {
    Ok(Value::Boolean(obj.borrow::<TagState>()?.activated))
}

#[cfg(test)]
mod test {
    use rlua::Lua;
    use super::super::tag;

    #[test]
    fn tag_name_empty() {
        let lua = Lua::new();
        tag::init(&lua).unwrap();
        lua.eval(r#"
assert(type(tag{}.name) == "nil")
"#, None).unwrap()
    }

    #[test]
    fn tag_name_change() {
        let lua = Lua::new();
        tag::init(&lua).unwrap();
        lua.eval(r#"
local t = tag{ name = "a very cool tag" }
assert(t.name == "a very cool tag")
"#, None).unwrap()
    }

    #[test]
    fn tag_name_signal() {
        let lua = Lua::new();
        tag::init(&lua).unwrap();
        lua.eval(r#"
local t = tag{}

local called = 0
t:connect_signal("property::name", function(t)
    assert(t.name == "bye")
    called = called + 1
end)

t.name = "bye"
assert(t.name == "bye")
assert(called == 1)
"#, None).unwrap()
    }

    #[test]
    fn tag_selected() {
        let lua = Lua::new();
        tag::init(&lua).unwrap();
        lua.eval(r#"
local t = tag{}
assert(t.selected == false)

local called = 0
t:connect_signal("property::selected", function(t)
    called = called + 1
end)

t.selected = false
assert(t.selected == false)
assert(called == 0)

t.selected = true
assert(t.selected == true)
assert(called == 1)

t.selected = true
assert(t.selected == true)
assert(called == 1)

t.selected = false
assert(t.selected == false)
assert(called == 2)
"#, None).unwrap()
    }

    #[test]
    fn tag_activated() {
        let lua = Lua::new();
        tag::init(&lua).unwrap();
        lua.eval(r#"
local t = tag{}
assert(t.activated == false)

local called = 0
t:connect_signal("property::activated", function(t)
    called = called + 1
end)

t.activated = false
assert(t.activated == false)
assert(called == 0)

t.activated = true
assert(t.activated == true)
assert(called == 1)

t.activated = true
assert(t.activated == true)
assert(called == 1)

t.activated = false
assert(t.activated == false)
assert(called == 2)
"#, None).unwrap()
    }

    #[test]
    fn tag_activated_selected() {
        let lua = Lua::new();
        tag::init(&lua).unwrap();
        lua.eval(r#"
local t = tag{selected = true, activated = true}

local called_selected, called_activated = 0, 0
t:connect_signal("property::activated", function(t)
    called_activated = called_activated + 1
end)
t:connect_signal("property::selected", function(t)
    called_selected = called_selected + 1
end)

t.activated = false
assert(t.activated == false)
assert(t.selected == false)
assert(called_activated == 1)
assert(called_selected == 1)
"#, None).unwrap()
    }
}
<|endoftext|>


<commit_before>
use ndarray::*;
use ndarray_linalg::*;
use super::traits::*;

pub struct TimeSeries<'a, TEO, S, D>
    where S: DataMut,
          D: Dimension,
          TEO: TimeEvolutionBase<S, D> + 'a
{
    state: ArrayBase<S, D>,
    teo: &'a TEO,
}

pub fn time_series<'a, TEO, S, D>(x0: ArrayBase<S, D>, teo: &'a TEO) -> TimeSeries<'a, TEO, S, D>
    where S: DataMut,
          D: Dimension,
          TEO: TimeEvolutionBase<S, D>
{
    TimeSeries {
        state: x0,
        teo: teo,
    }
}

impl<'a, TEO, S, D> TimeSeries<'a, TEO, S, D>
    where S: DataMut + DataClone,
          D: Dimension,
          TEO: TimeEvolutionBase<S, D>
{
    pub fn iterate(&mut self) {
        self.teo.iterate(&mut self.state);
    }
}

impl<'a, TEO, S, D> Iterator for TimeSeries<'a, TEO, S, D>
    where S: DataMut + DataClone,
          D: Dimension,
          TEO: TimeEvolutionBase<S, D>
{
    type Item = ArrayBase<S, D>;
    fn next(&mut self) -> Option<Self::Item> {
        self.iterate();
        Some(self.state.clone())
    }
}

/// N-step adaptor
///
/// ```rust
/// use ndarray_odeint::*;
/// let teo = explicit::rk4(model::Lorenz63::default(), 0.01);
/// let nstep = nstep(teo, 10);
/// ```
pub struct NStep<TEO> {
    teo: TEO,
    n: usize,
}

pub fn nstep<TEO>(teo: TEO, n: usize) -> NStep<TEO> {
    NStep { teo, n }
}

impl<TEO, D> ModelSize<D> for NStep<TEO>
    where TEO: ModelSize<D>,
          D: Dimension
{
    fn model_size(&self) -> D::Pattern {
        self.teo.model_size()
    }
}

impl<TEO> TimeStep for NStep<TEO>
    where TEO: TimeStep
{
    type Time = TEO::Time;

    fn get_dt(&self) -> Self::Time {
        self.teo.get_dt() * into_scalar(self.n as f64)
    }

    fn set_dt(&mut self, dt: Self::Time) {
        self.teo.set_dt(dt / into_scalar(self.n as f64));
    }
}

impl<TEO, S, D> TimeEvolutionBase<S, D> for NStep<TEO>
    where TEO: TimeEvolutionBase<S, D>,
          S: DataMut,
          D: Dimension
{
    type Scalar = TEO::Scalar;

    fn iterate<'a>(&self, x: &'a mut ArrayBase<S, D>) -> &'a mut ArrayBase<S, D> {
        for _ in 0..self.n {
            self.teo.iterate(x);
        }
        x
    }
}

impl<TEO, A, D> TimeEvolution<A, D> for NStep<TEO>
    where A: Scalar,
          D: Dimension,
          TEO: TimeEvolution<A, D>
{
}
<commit_msg>Rewrite adopter using new TimeEvolution<commit_after>
use ndarray::*;
use ndarray_linalg::*;
use super::traits::*;

pub struct TimeSeries<'a, TEO, S, D>
    where S: DataMut,
          D: Dimension,
          TEO: TimeEvolution<D> + 'a
{
    state: ArrayBase<S, D>,
    buf: TEO::Buffer,
    teo: &'a TEO,
}

pub fn time_series<'a, TEO, S, D>(x0: ArrayBase<S, D>, teo: &'a TEO) -> TimeSeries<'a, TEO, S, D>
    where S: DataMut,
          D: Dimension,
          TEO: TimeEvolution<D>
{
    TimeSeries {
        state: x0,
        buf: teo.new_buffer(),
        teo: teo,
    }
}

impl<'a, TEO, A, S, D> TimeSeries<'a, TEO, S, D>
    where A: Scalar,
          S: DataMut<Elem = A> + DataClone,
          D: Dimension,
          TEO: TimeEvolution<D, Scalar = A>
{
    pub fn iterate(&mut self) {
        self.teo.iterate(&mut self.state, &mut self.buf);
    }
}

impl<'a, TEO, A, S, D> Iterator for TimeSeries<'a, TEO, S, D>
    where A: Scalar,
          S: DataMut<Elem = A> + DataClone,
          D: Dimension,
          TEO: TimeEvolution<D, Scalar = A>
{
    type Item = ArrayBase<S, D>;
    fn next(&mut self) -> Option<Self::Item> {
        self.iterate();
        Some(self.state.clone())
    }
}

/// N-step adaptor
///
/// ```rust
/// use ndarray_odeint::*;
/// let teo = explicit::rk4(model::Lorenz63::default(), 0.01);
/// let nstep = nstep(teo, 10);
/// ```
pub struct NStep<TEO> {
    teo: TEO,
    n: usize,
}

pub fn nstep<TEO>(teo: TEO, n: usize) -> NStep<TEO> {
    NStep { teo, n }
}

impl<TEO, D> ModelSize<D> for NStep<TEO>
    where TEO: ModelSize<D>,
          D: Dimension
{
    fn model_size(&self) -> D::Pattern {
        self.teo.model_size()
    }
}

impl<TEO> TimeStep for NStep<TEO>
    where TEO: TimeStep
{
    type Time = TEO::Time;

    fn get_dt(&self) -> Self::Time {
        self.teo.get_dt() * into_scalar(self.n as f64)
    }

    fn set_dt(&mut self, dt: Self::Time) {
        self.teo.set_dt(dt / into_scalar(self.n as f64));
    }
}

impl<TEO, D> TimeEvolution<D> for NStep<TEO>
    where TEO: TimeEvolution<D>,
          D: Dimension
{
    type Scalar = TEO::Scalar;
    type Buffer = TEO::Buffer;

    fn new_buffer(&self) -> Self::Buffer {
        self.teo.new_buffer()
    }

    fn iterate<'a, S>(&self,
                      x: &'a mut ArrayBase<S, D>,
                      mut buf: &mut Self::Buffer)
                      -> &'a mut ArrayBase<S, D>
        where S: DataMut<Elem = TEO::Scalar>
    {
        for _ in 0..self.n {
            self.teo.iterate(x, buf);
        }
        x
    }
}
<|endoftext|>