<commit_before>// Copyright (c) 2015 Takeru Ohta <phjgt308@gmail.com>
//
// This software is released under the MIT License,
// see the LICENSE file at the top-level directory.

use bit_vec::BitVec;

pub struct Allocator {
    head: usize,
    bits: BitVec,
    nexts: Vec<isize>,
    prevs: Vec<isize>,
    offset: usize,
}

const BUFFER_SIZE: usize = 89120;

impl Allocator {
    pub fn new() -> Self {
        let mut prevs = vec![0; BUFFER_SIZE];
        let mut nexts = vec![0; BUFFER_SIZE];
        for i in 0..BUFFER_SIZE {
            nexts[i] = i as isize + 1;
            prevs[i] = i as isize - 1;
        }
        Allocator {
            head: 0x100,
            bits: BitVec::from_elem(BUFFER_SIZE, false),
            nexts: nexts,
            prevs: prevs,
            offset: 0,
        }
    }

    pub fn allocate(&mut self, arcs: &[u8]) -> u32 {
        assert!(arcs.len() > 0);

        let front = arcs[0];
        let head = self.head;
        let mut curr = self.get_next(head);
        loop {
            let base = curr - front as isize;
            if base > 0 && self.can_allocate(base as usize, &arcs[1..]) {
                self.allocate_impl(base as usize, &arcs);
                return base as u32;
            }
            curr = self.get_next(curr as usize);
        }
    }

    fn allocate_impl(&mut self, index: usize, arcs: &[u8]) {
        if self.offset <= index {
            self.bits.set(index - self.offset, true);
        }

        let base = index;
        for arc in arcs.iter() {
            let index = base + *arc as usize;
            if self.offset <= index {
                self.get(index);

                let j = index - self.offset;
                let prev = self.prevs[j];
                let next = self.nexts[j];
                assert!(prev != -1);
                assert!(next != -1);

                self.prevs[j] = -1; // TOOD: => None
                self.nexts[j] = -1;

                if self.head == index {
                    self.head = next as usize;
                }
                if self.offset <= prev as usize {
                    self.nexts[prev as usize - self.offset] = next;
                }
                if self.offset <= next as usize {
                    self.get(next as usize);
                    self.prevs[next as usize - self.offset] = prev;
                }
            }
        }
    }

    fn get_next(&mut self, index: usize) -> isize {
        self.get(index)
    }

    fn get(&mut self, index: usize) -> isize {
        if self.offset + BUFFER_SIZE <= index {
            self.shift();
            self.get(index)
        } else {
            self.nexts[index - self.offset]
        }
    }

    fn can_allocate(&mut self, index: usize, arcs: &[u8]) -> bool {
        if self.is_allocated(index) {
            return false; // already used
        }
        arcs.iter().all(|a| self.get(index + *a as usize) != -1)
    }

    fn is_allocated(&mut self, index: usize) -> bool {
        if self.offset > index {
            true
        } else {
            if self.offset + BUFFER_SIZE <= index {
                self.shift();
                self.is_allocated(index)
            } else {
                self.bits.get(index - self.offset).unwrap()
            }
        }
    }

    fn shift(&mut self) {
        let mut new_offset = self.head;
        while new_offset < self.offset + BUFFER_SIZE - 0x100 * 2 {
            new_offset = self.nexts[new_offset - self.offset] as usize;
        }

        let delta = new_offset - self.offset;
        let use_len = BUFFER_SIZE - delta;

        for i in 0..use_len {
            let x = self.bits[delta + i];
            self.bits.set(i, x);
        }
        for i in use_len..BUFFER_SIZE {
            self.bits.set(i, false);
        }

        self.offset = new_offset;
        for i in 0..use_len {
            let x = self.nexts[delta + i];
            let y = self.prevs[delta + i];
            self.nexts[i] = x;
            self.prevs[i] = y;
        }
        for i in use_len..BUFFER_SIZE {
            self.nexts[i] = (self.offset + i + 1) as isize;
            self.prevs[i] = (self.offset + i - 1) as isize;
        }

        self.head = self.offset;
        while self.head < self.offset + 0x100 {
            let next = self.nexts[self.head - self.offset];
            self.head = next as usize;
        }
    }
}
<commit_msg>Abolish constant memory allocator because it's memory saving does not affect overall consumption<commit_after>// Copyright (c) 2015 Takeru Ohta <phjgt308@gmail.com>
//
// This software is released under the MIT License,
// see the LICENSE file at the top-level directory.

use bit_vec::BitVec;

pub struct Allocator {
    head: usize,
    bits: BitVec,
    nexts: Vec<Option<u32>>,
    prevs: Vec<Option<u32>>,
}

impl Allocator {
    pub fn new() -> Self {
        Allocator {
            head: 0x100,
            bits: BitVec::from_elem(1, false),
            nexts: vec![Some(1)],
            prevs: vec![None],
        }
    }

    pub fn allocate(&mut self, arcs: &[u8]) -> u32 {
        assert!(arcs.len() > 0);

        // let mut count = 0;
        let front = arcs[0];
        let head = self.head;
        let mut curr = self.get_next(head);
        loop {
            let base = curr - front as u32;
            if self.can_allocate(base as usize, &arcs[1..]) {
                self.allocate_impl(base as usize, &arcs);
                // TODO: optimize
                // if count > 10 {
                //     let head = self.head;
                //     let next_head = self.get_next(head) as usize;
                //     self.head = next_head;
                // }
                return base;
            }
            // count += 1;
            curr = self.get_next(curr as usize);
        }
    }

    fn allocate_impl(&mut self, index: usize, arcs: &[u8]) {
        self.bits.set(index, true);

        let base = index;
        for arc in arcs.iter() {
            let index = base + *arc as usize;
            self.extend_if_needed(index);

            let prev = self.prevs[index].unwrap() as usize;
            let next = self.nexts[index].unwrap() as usize;

            self.prevs[index] = None;
            self.nexts[index] = None;

            if self.head == index {
                self.head = next;
            }
            self.nexts[prev] = Some(next as u32);

            self.extend_if_needed(next);
            self.prevs[next] = Some(prev as u32);
        }
    }

    fn get_next(&mut self, index: usize) -> u32 {
        self.extend_if_needed(index);
        self.nexts[index].unwrap()
    }

    fn can_allocate(&mut self, index: usize, arcs: &[u8]) -> bool {
        if self.is_allocated(index) {
            return false; // already used
        }
        arcs.iter().all(|a| self.nexts.get(index + *a as usize).map_or(true, |x| x.is_some()))
    }

    fn is_allocated(&mut self, index: usize) -> bool {
        self.extend_if_needed(index);
        self.bits.get(index).unwrap()
    }

    fn extend_if_needed(&mut self, index: usize) {
        if index < self.prevs.len() {
            return;
        }
        let size = self.prevs.len();
        for i in size..index + 1 {
            self.nexts.push(Some(i as u32 + 1));
            self.prevs.push(Some(i as u32 - 1));
        }
        self.bits.grow(index + 1 - size, false);
    }
}
<|endoftext|>


<commit_before>#![feature(try_from)]
extern crate bincode;
extern crate chrono;
extern crate cita_crypto as crypto;
#[macro_use]
extern crate clap;
#[macro_use]
extern crate libproto;
#[macro_use]
extern crate log;
extern crate logger;
extern crate proof;
extern crate pubsub;
#[macro_use]
extern crate serde_derive;
extern crate serde_yaml;
extern crate util;

use bincode::{serialize, Infinite};
use clap::{App};
use crypto::{CreateKey, KeyPair, PrivKey, Sign, Signature};
use libproto::blockchain::{Block, BlockBody, BlockTxs, BlockWithProof};
use libproto::router::{MsgType, RoutingKey, SubModules};
use libproto::Message;
use proof::TendermintProof;
use pubsub::start_pubsub;
use std::collections::HashMap;
use std::convert::{Into, TryFrom, TryInto};
use std::sync::mpsc::{channel, Sender};
use std::time::{Duration, Instant, SystemTime, UNIX_EPOCH};
use std::thread::sleep;
use util::{Address, H256, Hashable};

pub type PubType = (String, Vec<u8>);

#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone, Copy, Hash)]
pub enum Step {
    Propose,
    Prevote,
    Precommit,
    Commit,
}

fn build_proof(height: u64, sender: Address, privkey: &PrivKey) -> TendermintProof {
    let mut proof = TendermintProof::default();
    proof.height = (height - 1) as usize;
    proof.round = 0;
    proof.proposal = H256::default();

    let mut commits = HashMap::new();
    let message = serialize(
        &(
            proof.height,
            proof.round,
            Step::Precommit,
            sender.clone(),
            Some(proof.proposal.clone()),
        ),
        Infinite,
    ).unwrap();

    let signature = Signature::sign(privkey, &message.crypt_hash().into()).unwrap();
    commits.insert((*sender).into(), signature.into());
    proof.commits = commits;
    proof
}

fn build_block(
    //txs: &Vec<SignedTransaction>,
    body: &BlockBody,
    pre_block_hash: H256,
    height: u64,
    privkey: &PrivKey,
    time_stamp: u64,
) -> (Vec<u8>, BlockWithProof) {
    let sender = KeyPair::from_privkey(*privkey).unwrap().address().clone();
    let mut block = Block::new();
    let proof = build_proof(height, sender, privkey);
    let transaction_root = body.transactions_root().to_vec();
    let mut proof_blk = BlockWithProof::new();

    block.mut_header().set_timestamp(time_stamp);
    block.mut_header().set_height(height);
    block.mut_header().set_prevhash(pre_block_hash.0.to_vec());
    block.mut_header().set_proof(proof.clone().into());
    block.mut_header().set_transactions_root(transaction_root);
    block.set_body(body.clone());

    proof_blk.set_blk(block);
    proof_blk.set_proof(proof.into());

    let msg: Message = proof_blk.clone().into();
    (msg.try_into().unwrap(), proof_blk)
}

fn send_block(
    pre_block_hash: H256,
    height: u64,
    pub_sender: Sender<PubType>,
    timestamp: u64,
    block_txs: &BlockTxs,
    privkey: &PrivKey,
) {
    // let txs = &block_txs.body.get_ref().transactions.clone().into_vec();
    let (send_data, _block) = build_block(
        &block_txs.body.get_ref(),
        pre_block_hash,
        height,
        privkey,
        timestamp,
    );
    pub_sender
        .send((
            routing_key!(Consensus >> BlockWithProof).into(),
            send_data.clone(),
        ))
        .unwrap();
}

fn main() {
    logger::init();
    info!("CITA: Consensus Mock");

    // set up the clap to receive info from CLI
    let matches = App::new("consensus mock")
        .version("0.1")
        .author("Cryptape")
        .about("Mock the process of consensus")
        .arg(
            clap::Arg::with_name("interval")
                .short("i")
                .long("interval(seconds) of block generating, default: 3")
                .required(true)
                .takes_value(true)
                .help("Set the path of mock data in YAML format"),
        )
        .get_matches();

    let default_interval = 3;
    // get the mock data and parse it to serde_yaml format
    let interval = value_t!(matches, "interval", u64).unwrap_or(default_interval);
    let key_pair = KeyPair::gen_keypair();
    let pk_miner = key_pair.privkey();

    let (tx_sub, rx_sub) = channel();
    let (tx_pub, rx_pub) = channel();

    start_pubsub(
        "consensus",
        routing_key!([Auth >> BlockTxs, Chain >> RichStatus,]),
        tx_sub,
        rx_pub,
    );

    let mut received_block_txs: HashMap<usize, BlockTxs> = HashMap::new();

    let mut send_height = 0;
    let interval_duration = Duration::new(interval, 0);
    let mut last_new_block_at = Instant::now();
    loop {
        match rx_sub.recv_timeout(interval_duration) {
            Ok((key, body)) => {
                let routing_key = RoutingKey::from(&key);
                let mut msg = Message::try_from(body).unwrap();

                match routing_key {
                    routing_key!(Auth >> BlockTxs) => {
                        // add received block
                        let block_txs = msg.take_block_txs().unwrap();
                        let height = block_txs.get_height() as usize;
                        received_block_txs.insert(height, block_txs);
                    }
                    routing_key!(Chain >> RichStatus) => {
                        // update rich status
                        let rich_status = msg.take_rich_status().unwrap();
                        if rich_status.height < send_height {
                            continue;
                        }

                        // sleep until hit inteval
                        let seconds_since_last = last_new_block_at.elapsed().as_secs();
                        if seconds_since_last < interval {
                            sleep(Duration::from_secs(interval - seconds_since_last));
                        } else {
                            last_new_block_at = Instant::now();
                        }

                        // current timestamp
                        let timestamp = SystemTime::now().duration_since(UNIX_EPOCH).expect("get timestamp error").as_secs();

                        if let Some(block_txs) = received_block_txs.remove(&(rich_status.height as usize)) {
                            send_height = rich_status.height + 1;
                            send_block(
                                H256::from_slice(&rich_status.hash),
                                send_height,
                                tx_pub.clone(),
                                timestamp,
                                &block_txs,
                                &pk_miner,
                            );
                        } else {
                            warn!(
                                "No received block_txs at rich_status_height = {:?}",
                                rich_status.height
                            );
                        }
                        trace!("get new local status {:?}", rich_status);
                    }
                    _ => {}
                }
            }
            Err(err) => { error!("timeout err {:?}", err) }
        }
    }
}
<commit_msg>ignore consensus-mock timeout error<commit_after>#![feature(try_from)]
extern crate bincode;
extern crate chrono;
extern crate cita_crypto as crypto;
#[macro_use]
extern crate clap;
#[macro_use]
extern crate libproto;
#[macro_use]
extern crate log;
extern crate logger;
extern crate proof;
extern crate pubsub;
#[macro_use]
extern crate serde_derive;
extern crate serde_yaml;
extern crate util;

use bincode::{serialize, Infinite};
use clap::App;
use crypto::{CreateKey, KeyPair, PrivKey, Sign, Signature};
use libproto::blockchain::{Block, BlockBody, BlockTxs, BlockWithProof};
use libproto::router::{MsgType, RoutingKey, SubModules};
use libproto::Message;
use proof::TendermintProof;
use pubsub::start_pubsub;
use std::collections::HashMap;
use std::convert::{Into, TryFrom, TryInto};
use std::sync::mpsc::{channel, Sender, RecvTimeoutError};
use std::time::{Duration, Instant, SystemTime, UNIX_EPOCH};
use std::thread::sleep;
use util::{Address, H256, Hashable};

pub type PubType = (String, Vec<u8>);

#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone, Copy, Hash)]
pub enum Step {
    Propose,
    Prevote,
    Precommit,
    Commit,
}

fn build_proof(height: u64, sender: Address, privkey: &PrivKey) -> TendermintProof {
    let mut proof = TendermintProof::default();
    proof.height = (height - 1) as usize;
    proof.round = 0;
    proof.proposal = H256::default();

    let mut commits = HashMap::new();
    let message = serialize(
        &(
            proof.height,
            proof.round,
            Step::Precommit,
            sender.clone(),
            Some(proof.proposal.clone()),
        ),
        Infinite,
    ).unwrap();

    let signature = Signature::sign(privkey, &message.crypt_hash().into()).unwrap();
    commits.insert((*sender).into(), signature.into());
    proof.commits = commits;
    proof
}

fn build_block(
    //txs: &Vec<SignedTransaction>,
    body: &BlockBody,
    pre_block_hash: H256,
    height: u64,
    privkey: &PrivKey,
    time_stamp: u64,
) -> (Vec<u8>, BlockWithProof) {
    let sender = KeyPair::from_privkey(*privkey).unwrap().address().clone();
    let mut block = Block::new();
    let proof = build_proof(height, sender, privkey);
    let transaction_root = body.transactions_root().to_vec();
    let mut proof_blk = BlockWithProof::new();

    block.mut_header().set_timestamp(time_stamp);
    block.mut_header().set_height(height);
    block.mut_header().set_prevhash(pre_block_hash.0.to_vec());
    block.mut_header().set_proof(proof.clone().into());
    block.mut_header().set_transactions_root(transaction_root);
    block.set_body(body.clone());

    proof_blk.set_blk(block);
    proof_blk.set_proof(proof.into());

    let msg: Message = proof_blk.clone().into();
    (msg.try_into().unwrap(), proof_blk)
}

fn send_block(
    pre_block_hash: H256,
    height: u64,
    pub_sender: Sender<PubType>,
    timestamp: u64,
    block_txs: &BlockTxs,
    privkey: &PrivKey,
) {
    // let txs = &block_txs.body.get_ref().transactions.clone().into_vec();
    let (send_data, _block) = build_block(
        &block_txs.body.get_ref(),
        pre_block_hash,
        height,
        privkey,
        timestamp,
    );
    pub_sender
        .send((
            routing_key!(Consensus >> BlockWithProof).into(),
            send_data.clone(),
        ))
        .unwrap();
}

fn main() {
    logger::init();
    info!("CITA: Consensus Mock");

    // set up the clap to receive info from CLI
    let matches = App::new("consensus mock")
        .version("0.1")
        .author("Cryptape")
        .about("Mock the process of consensus")
        .arg(
            clap::Arg::with_name("interval")
                .short("i")
                .long("interval(seconds) of block generating, default: 3")
                .required(true)
                .takes_value(true)
                .help("Set the path of mock data in YAML format"),
        )
        .get_matches();

    let default_interval = 3;
    // get the mock data and parse it to serde_yaml format
    let interval = value_t!(matches, "interval", u64).unwrap_or(default_interval);
    let key_pair = KeyPair::gen_keypair();
    let pk_miner = key_pair.privkey();

    let (tx_sub, rx_sub) = channel();
    let (tx_pub, rx_pub) = channel();

    start_pubsub(
        "consensus",
        routing_key!([Auth >> BlockTxs, Chain >> RichStatus,]),
        tx_sub,
        rx_pub,
    );

    let mut received_block_txs: HashMap<usize, BlockTxs> = HashMap::new();

    let mut send_height = 0;
    let interval_duration = Duration::new(interval, 0);
    let mut last_new_block_at = Instant::now();
    loop {
        match rx_sub.recv_timeout(interval_duration) {
            Ok((key, body)) => {
                let routing_key = RoutingKey::from(&key);
                let mut msg = Message::try_from(body).unwrap();

                match routing_key {
                    routing_key!(Auth >> BlockTxs) => {
                        // add received block
                        let block_txs = msg.take_block_txs().unwrap();
                        let height = block_txs.get_height() as usize;
                        received_block_txs.insert(height, block_txs);
                    }
                    routing_key!(Chain >> RichStatus) => {
                        // update rich status
                        let rich_status = msg.take_rich_status().unwrap();
                        if rich_status.height < send_height {
                            continue;
                        }

                        // sleep until hit inteval
                        let seconds_since_last = last_new_block_at.elapsed().as_secs();
                        if seconds_since_last < interval {
                            sleep(Duration::from_secs(interval - seconds_since_last));
                        } else {
                            last_new_block_at = Instant::now();
                        }

                        // current timestamp
                        let timestamp = SystemTime::now().duration_since(UNIX_EPOCH).expect("get timestamp error").as_secs();

                        if let Some(block_txs) = received_block_txs.remove(&(rich_status.height as usize)) {
                            send_height = rich_status.height + 1;
                            send_block(
                                H256::from_slice(&rich_status.hash),
                                send_height,
                                tx_pub.clone(),
                                timestamp,
                                &block_txs,
                                &pk_miner,
                            );
                        } else {
                            warn!(
                                "No received block_txs at rich_status_height = {:?}",
                                rich_status.height
                            );
                        }
                        trace!("get new local status {:?}", rich_status);
                    }
                    _ => {}
                }
            }
            Err(err) => {
                if err != RecvTimeoutError::Timeout {
                    error!("consensus err {:?}", err)
                }
            }
        }
    }
}
<|endoftext|>


<commit_before>extern crate http;

use std::vec::Vec;
use std::io::net::ip::{SocketAddr, Ipv4Addr};
use std::io::Writer;
use http::server::{Config, Server, Request, ResponseWriter};
use http::server::request::AbsolutePath;
use http::status::NotFound;
use http::headers;

#[test]
fn test_nothing() {
    assert_eq!(1, 1);
}

#[deriving(Clone)]
struct TileServer;

impl Server for TileServer {
    fn get_config(&self) -> Config {
        Config {
            bind_address: SocketAddr {
                ip: Ipv4Addr(0, 0, 0, 0),
                port: 8001,
            },
        }
    }

    fn handle_request(&self, r: &Request, w: &mut ResponseWriter) {
        w.headers.content_type = Some(headers::content_type::MediaType {
            type_: ~"text",
            subtype: ~"html",
            parameters: Vec::new(),
        });

        match r.request_uri {
            AbsolutePath(ref url) => {
                if url == &~"/" {
                    w.write(index_html.as_bytes()).unwrap();
                    return;
                }
            },
            _ => {}
        };

        w.status = NotFound;
        w.write("Page not found :(\n".as_bytes()).unwrap();

    }
}

fn main() {
    TileServer.serve_forever();
}

static index_html: &'static str = "<!doctype html>\
<meta charset='utf-8'>\n\
<link rel='stylesheet' href='//cdnjs.cloudflare.com/ajax/libs/leaflet/0.7.2/leaflet.css'>\n\

\n\

";
<commit_msg>page title<commit_after>extern crate http;

use std::vec::Vec;
use std::io::net::ip::{SocketAddr, Ipv4Addr};
use std::io::Writer;
use http::server::{Config, Server, Request, ResponseWriter};
use http::server::request::AbsolutePath;
use http::status::NotFound;
use http::headers;

#[test]
fn test_nothing() {
    assert_eq!(1, 1);
}

#[deriving(Clone)]
struct TileServer;

impl Server for TileServer {
    fn get_config(&self) -> Config {
        Config {
            bind_address: SocketAddr {
                ip: Ipv4Addr(0, 0, 0, 0),
                port: 8001,
            },
        }
    }

    fn handle_request(&self, r: &Request, w: &mut ResponseWriter) {
        w.headers.content_type = Some(headers::content_type::MediaType {
            type_: ~"text",
            subtype: ~"html",
            parameters: Vec::new(),
        });

        match r.request_uri {
            AbsolutePath(ref url) => {
                if url == &~"/" {
                    w.write(index_html.as_bytes()).unwrap();
                    return;
                }
            },
            _ => {}
        };

        w.status = NotFound;
        w.write("Page not found :(\n".as_bytes()).unwrap();

    }
}

fn main() {
    TileServer.serve_forever();
}

static index_html: &'static str = "<!doctype html>\
<meta charset='utf-8'>\n\
<title>RusTiles demo</title>\n\
<link rel='stylesheet' href='//cdnjs.cloudflare.com/ajax/libs/leaflet/0.7.2/leaflet.css'>\n\

\n\

";
<|endoftext|>


<commit_before>//! A [`SpriteBatch`](struct.SpriteBatch.html) is a way to
//! efficiently draw a large number of copies of the same image, or part
//! of the same image.  It's useful for implementing tiled maps,
//! spritesheets, particles, and other such things.
//!
//! Essentially this uses a technique called "instancing" to queue up
//! a large amount of location/position data in a buffer, then feed it
//! to the graphics card all in one go.
//!
//! Also it's super slow in `rustc`'s default debug mode, because
//! `rustc` adds a lot of checking to the vector accesses and math.
//! If you use it, it's recommended to crank up the `opt-level` for
//! debug mode in your game's `Cargo.toml`.

use crate::context::Context;
use crate::error;
use crate::error::GameResult;
use crate::graphics::shader::BlendMode;
use crate::graphics::types::FilterMode;
use crate::graphics::{self, transform_rect, BackendSpec, DrawParam, DrawTransform, Rect};
use gfx;
use gfx::Factory;

/// A `SpriteBatch` draws a number of copies of the same image, using a single draw call.
///
/// This is generally faster than drawing the same sprite with many
/// invocations of [`draw()`](../fn.draw.html), though it has a bit of
/// overhead to set up the batch.  This overhead makes it run very
/// slowly in `debug` mode because it spends a lot of time on array
/// bounds checking and un-optimized math; you need to build with
/// optimizations enabled to really get the speed boost.
#[derive(Debug, Clone, PartialEq)]
pub struct SpriteBatch {
    image: graphics::Image,
    sprites: Vec<graphics::DrawParam>,
    blend_mode: Option<BlendMode>,
}

/// An index of a particular sprite in a `SpriteBatch`.
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct SpriteIdx(pub usize);

impl SpriteBatch {
    /// Creates a new `SpriteBatch`, drawing with the given image.
    ///
    /// Takes ownership of the `Image`, but cloning an `Image` is
    /// cheap since they have an internal `Arc` containing the actual
    /// image data.
    pub fn new(image: graphics::Image) -> Self {
        Self {
            image,
            sprites: vec![],
            blend_mode: None,
        }
    }

    /// Adds a new sprite to the sprite batch.
    ///
    /// Returns a handle with which to modify the sprite using
    /// [`set()`](#method.set)
    pub fn add<P>(&mut self, param: P) -> SpriteIdx
    where
        P: Into<graphics::DrawParam>,
    {
        self.sprites.push(param.into());
        SpriteIdx(self.sprites.len() - 1)
    }

    /// Alters a sprite in the batch to use the given draw params
    pub fn set<P>(&mut self, handle: SpriteIdx, param: P) -> GameResult
    where
        P: Into<graphics::DrawParam>,
    {
        if handle.0 < self.sprites.len() {
            self.sprites[handle.0] = param.into();
            Ok(())
        } else {
            Err(error::GameError::RenderError(String::from(
                "Provided index is out of bounds.",
            )))
        }
    }

    /// Immediately sends all data in the batch to the graphics card.
    ///
    /// Generally just calling [`graphics::draw()`](../fn.draw.html) on the `SpriteBatch`
    /// will do this automatically.
    fn flush(&self, ctx: &mut Context, image: &graphics::Image) -> GameResult {
        // This is a little awkward but this is the right place
        // to do whatever transformations need to happen to DrawParam's.
        // We have a Context, and *everything* must pass through this
        // function to be drawn, so.
        // Though we do awkwardly have to allocate a new vector.
        // ...though upon benchmarking, the actual allocation is basically nothing,
        // the cost in debug mode is alllll math.
        let new_sprites = self
            .sprites
            .iter()
            .map(|param| {
                // Copy old params
                let mut new_param = *param;
                let src_width = param.src.w;
                let src_height = param.src.h;
                let real_scale = graphics::Vector2::new(
                    src_width * param.scale.x * f32::from(image.width),
                    src_height * param.scale.y * f32::from(image.height),
                );
                new_param.scale = real_scale.into();
                new_param.color = new_param.color;
                let primitive_param = graphics::DrawTransform::from(new_param);
                primitive_param.to_instance_properties(ctx.gfx_context.is_srgb())
            })
            .collect::<Vec<_>>();

        let gfx = &mut ctx.gfx_context;
        if gfx.data.rect_instance_properties.len() < self.sprites.len() {
            gfx.data.rect_instance_properties = gfx.factory.create_buffer(
                self.sprites.len(),
                gfx::buffer::Role::Vertex,
                gfx::memory::Usage::Dynamic,
                gfx::memory::Bind::TRANSFER_DST,
            )?;
        }
        gfx.encoder
            .update_buffer(&gfx.data.rect_instance_properties, &new_sprites[..], 0)?;
        Ok(())
    }

    /// Removes all data from the sprite batch.
    pub fn clear(&mut self) {
        self.sprites.clear();
    }

    /// Unwraps and returns the contained `Image`
    pub fn into_inner(self) -> graphics::Image {
        self.image
    }

    /// Replaces the contained `Image`, returning the old one.
    pub fn set_image(&mut self, image: graphics::Image) -> graphics::Image {
        use std::mem;
        mem::replace(&mut self.image, image)
    }

    /// Get the filter mode for the SpriteBatch.
    pub fn filter(&self) -> FilterMode {
        self.image.filter()
    }

    /// Set the filter mode for the SpriteBatch.
    pub fn set_filter(&mut self, mode: FilterMode) {
        self.image.set_filter(mode);
    }
}

impl graphics::Drawable for SpriteBatch {
    fn draw(&self, ctx: &mut Context, param: DrawParam) -> GameResult {
        // Awkwardly we must update values on all sprites and such.
        // Also awkwardly we have this chain of colors with differing priorities.
        self.flush(ctx, &self.image)?;
        let gfx = &mut ctx.gfx_context;
        let sampler = gfx
            .samplers
            .get_or_insert(self.image.sampler_info, gfx.factory.as_mut());
        gfx.data.vbuf = gfx.quad_vertex_buffer.clone();
        let typed_thingy = gfx
            .backend_spec
            .raw_to_typed_shader_resource(self.image.texture.clone());
        gfx.data.tex = (typed_thingy, sampler);

        let mut slice = gfx.quad_slice.clone();
        slice.instances = Some((self.sprites.len() as u32, 0));
        let curr_transform = gfx.transform();
        let m: DrawTransform = param.into();
        // TODO: Verify this is correct with row/col matrixes
        gfx.push_transform(m.matrix * curr_transform);
        gfx.calculate_transform_matrix();
        gfx.update_globals()?;
        let previous_mode: Option<BlendMode> = if let Some(mode) = self.blend_mode {
            let current_mode = gfx.blend_mode();
            if current_mode != mode {
                gfx.set_blend_mode(mode)?;
                Some(current_mode)
            } else {
                None
            }
        } else {
            None
        };
        gfx.draw(Some(&slice))?;
        if let Some(mode) = previous_mode {
            gfx.set_blend_mode(mode)?;
        }
        gfx.pop_transform();
        gfx.calculate_transform_matrix();
        gfx.update_globals()?;
        Ok(())
    }
    fn dimensions(&self, _ctx: &mut Context) -> Option<Rect> {
        if self.sprites.is_empty() {
            return None;
        }
        let dimensions = self.image.dimensions();
        self.sprites
            .iter()
            .map(|&param| transform_rect(dimensions, param))
            .fold(None, |acc: Option<Rect>, rect| {
                Some(if let Some(acc) = acc {
                    acc.combine_with(rect)
                } else {
                    rect
                })
            })
    }
    fn set_blend_mode(&mut self, mode: Option<BlendMode>) {
        self.blend_mode = mode;
    }
    fn blend_mode(&self) -> Option<BlendMode> {
        self.blend_mode
    }
}
<commit_msg>Removes redundant imports on spritebatch.rs<commit_after>//! A [`SpriteBatch`](struct.SpriteBatch.html) is a way to
//! efficiently draw a large number of copies of the same image, or part
//! of the same image.  It's useful for implementing tiled maps,
//! spritesheets, particles, and other such things.
//!
//! Essentially this uses a technique called "instancing" to queue up
//! a large amount of location/position data in a buffer, then feed it
//! to the graphics card all in one go.
//!
//! Also it's super slow in `rustc`'s default debug mode, because
//! `rustc` adds a lot of checking to the vector accesses and math.
//! If you use it, it's recommended to crank up the `opt-level` for
//! debug mode in your game's `Cargo.toml`.

use crate::context::Context;
use crate::error;
use crate::error::GameResult;
use crate::graphics::shader::BlendMode;
use crate::graphics::types::FilterMode;
use crate::graphics::{self, transform_rect, BackendSpec, DrawParam, DrawTransform, Rect};
use gfx::Factory;

/// A `SpriteBatch` draws a number of copies of the same image, using a single draw call.
///
/// This is generally faster than drawing the same sprite with many
/// invocations of [`draw()`](../fn.draw.html), though it has a bit of
/// overhead to set up the batch.  This overhead makes it run very
/// slowly in `debug` mode because it spends a lot of time on array
/// bounds checking and un-optimized math; you need to build with
/// optimizations enabled to really get the speed boost.
#[derive(Debug, Clone, PartialEq)]
pub struct SpriteBatch {
    image: graphics::Image,
    sprites: Vec<graphics::DrawParam>,
    blend_mode: Option<BlendMode>,
}

/// An index of a particular sprite in a `SpriteBatch`.
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct SpriteIdx(pub usize);

impl SpriteBatch {
    /// Creates a new `SpriteBatch`, drawing with the given image.
    ///
    /// Takes ownership of the `Image`, but cloning an `Image` is
    /// cheap since they have an internal `Arc` containing the actual
    /// image data.
    pub fn new(image: graphics::Image) -> Self {
        Self {
            image,
            sprites: vec![],
            blend_mode: None,
        }
    }

    /// Adds a new sprite to the sprite batch.
    ///
    /// Returns a handle with which to modify the sprite using
    /// [`set()`](#method.set)
    pub fn add<P>(&mut self, param: P) -> SpriteIdx
    where
        P: Into<graphics::DrawParam>,
    {
        self.sprites.push(param.into());
        SpriteIdx(self.sprites.len() - 1)
    }

    /// Alters a sprite in the batch to use the given draw params
    pub fn set<P>(&mut self, handle: SpriteIdx, param: P) -> GameResult
    where
        P: Into<graphics::DrawParam>,
    {
        if handle.0 < self.sprites.len() {
            self.sprites[handle.0] = param.into();
            Ok(())
        } else {
            Err(error::GameError::RenderError(String::from(
                "Provided index is out of bounds.",
            )))
        }
    }

    /// Immediately sends all data in the batch to the graphics card.
    ///
    /// Generally just calling [`graphics::draw()`](../fn.draw.html) on the `SpriteBatch`
    /// will do this automatically.
    fn flush(&self, ctx: &mut Context, image: &graphics::Image) -> GameResult {
        // This is a little awkward but this is the right place
        // to do whatever transformations need to happen to DrawParam's.
        // We have a Context, and *everything* must pass through this
        // function to be drawn, so.
        // Though we do awkwardly have to allocate a new vector.
        // ...though upon benchmarking, the actual allocation is basically nothing,
        // the cost in debug mode is alllll math.
        let new_sprites = self
            .sprites
            .iter()
            .map(|param| {
                // Copy old params
                let mut new_param = *param;
                let src_width = param.src.w;
                let src_height = param.src.h;
                let real_scale = graphics::Vector2::new(
                    src_width * param.scale.x * f32::from(image.width),
                    src_height * param.scale.y * f32::from(image.height),
                );
                new_param.scale = real_scale.into();
                new_param.color = new_param.color;
                let primitive_param = graphics::DrawTransform::from(new_param);
                primitive_param.to_instance_properties(ctx.gfx_context.is_srgb())
            })
            .collect::<Vec<_>>();

        let gfx = &mut ctx.gfx_context;
        if gfx.data.rect_instance_properties.len() < self.sprites.len() {
            gfx.data.rect_instance_properties = gfx.factory.create_buffer(
                self.sprites.len(),
                gfx::buffer::Role::Vertex,
                gfx::memory::Usage::Dynamic,
                gfx::memory::Bind::TRANSFER_DST,
            )?;
        }
        gfx.encoder
            .update_buffer(&gfx.data.rect_instance_properties, &new_sprites[..], 0)?;
        Ok(())
    }

    /// Removes all data from the sprite batch.
    pub fn clear(&mut self) {
        self.sprites.clear();
    }

    /// Unwraps and returns the contained `Image`
    pub fn into_inner(self) -> graphics::Image {
        self.image
    }

    /// Replaces the contained `Image`, returning the old one.
    pub fn set_image(&mut self, image: graphics::Image) -> graphics::Image {
        use std::mem;
        mem::replace(&mut self.image, image)
    }

    /// Get the filter mode for the SpriteBatch.
    pub fn filter(&self) -> FilterMode {
        self.image.filter()
    }

    /// Set the filter mode for the SpriteBatch.
    pub fn set_filter(&mut self, mode: FilterMode) {
        self.image.set_filter(mode);
    }
}

impl graphics::Drawable for SpriteBatch {
    fn draw(&self, ctx: &mut Context, param: DrawParam) -> GameResult {
        // Awkwardly we must update values on all sprites and such.
        // Also awkwardly we have this chain of colors with differing priorities.
        self.flush(ctx, &self.image)?;
        let gfx = &mut ctx.gfx_context;
        let sampler = gfx
            .samplers
            .get_or_insert(self.image.sampler_info, gfx.factory.as_mut());
        gfx.data.vbuf = gfx.quad_vertex_buffer.clone();
        let typed_thingy = gfx
            .backend_spec
            .raw_to_typed_shader_resource(self.image.texture.clone());
        gfx.data.tex = (typed_thingy, sampler);

        let mut slice = gfx.quad_slice.clone();
        slice.instances = Some((self.sprites.len() as u32, 0));
        let curr_transform = gfx.transform();
        let m: DrawTransform = param.into();
        // TODO: Verify this is correct with row/col matrixes
        gfx.push_transform(m.matrix * curr_transform);
        gfx.calculate_transform_matrix();
        gfx.update_globals()?;
        let previous_mode: Option<BlendMode> = if let Some(mode) = self.blend_mode {
            let current_mode = gfx.blend_mode();
            if current_mode != mode {
                gfx.set_blend_mode(mode)?;
                Some(current_mode)
            } else {
                None
            }
        } else {
            None
        };
        gfx.draw(Some(&slice))?;
        if let Some(mode) = previous_mode {
            gfx.set_blend_mode(mode)?;
        }
        gfx.pop_transform();
        gfx.calculate_transform_matrix();
        gfx.update_globals()?;
        Ok(())
    }
    fn dimensions(&self, _ctx: &mut Context) -> Option<Rect> {
        if self.sprites.is_empty() {
            return None;
        }
        let dimensions = self.image.dimensions();
        self.sprites
            .iter()
            .map(|&param| transform_rect(dimensions, param))
            .fold(None, |acc: Option<Rect>, rect| {
                Some(if let Some(acc) = acc {
                    acc.combine_with(rect)
                } else {
                    rect
                })
            })
    }
    fn set_blend_mode(&mut self, mode: Option<BlendMode>) {
        self.blend_mode = mode;
    }
    fn blend_mode(&self) -> Option<BlendMode> {
        self.blend_mode
    }
}
<|endoftext|>


<commit_before>// http://rosettacode.org/wiki/Greatest_element_of_a_list
#![cfg(not_tested)]
/*
	Generic function to find max value in list.
	return an Option that can contains a reference to the max of the list

	The type T requires to implement Ord to be compared.

	'a is used to define the lifetime of the returned reference.
	<'a, ...>: define a lifetime named 'a.
	(lst: &'a Vec<T>): 'a is equal to the lifetime of lst
	Option<&'a T>> the returned reference is defined to have the lifetime 'a, which is the same lifetime of the vector
	This means that the reference contained in the Option will be valid as long as the vector is valid.
	In fact, this mechanism exist to avoid having a refence to something that does not exist anymore. One of the Rust safety mechanism.

	For more information about lifetime, see http://static.rust-lang.org/doc/master/guide-lifetimes.html
*/
fn max_list<'a, T: Ord>(lst: &'a Vec<T>) -> Option<&'a T> {

	let mut max = None; //None is one of the Option values

	for i in lst.iter() {
		max = match max { //Max being Option(which is an enum), we deconstruct max to get its  possible values
			None => Some(i), //if no max. some wrap i in an Option.
			Some(ref m) if i > *m => Some(i), //m is a reference of the value contained in max
			_ => max //default value if i <= max
		}
	}
	max
}

fn main()
{
	//greater element of a list main
	let list1 = vec!(1,2,3,4,5,6,7,8,9);
	println!("Max of first list {}", max_list(&list1).unwrap());

	let list2 = vec!(123,3543,23,432,5,2,34,234,234,2,4,234,23,4,24,25,7,658,68);
	println!("Max of the second list {}", max_list(&list2).unwrap());

	let list3 = vec!('a','b','c','d','e');
	println!("Max of first list {}", max_list(&list3).unwrap());
}
<commit_msg>fix find max<commit_after>// http://rosettacode.org/wiki/Greatest_element_of_a_list

#![cfg(not_tested)]
fn main()
{
	//greater element of a list main
	let list1 = vec!(1,2,3,4,5,6,7,8,9);
	println!("Max of first list {}", list1.iter().max_by(|x|{*x}).unwrap());

	let list2 = vec!(123,3543,23,432,5,2,34,234,234,2,4,234,23,4,24,25,7,658,68);
	println!("Max of the second list {}", list2.iter().max_by(|x|{*x}).unwrap());

	let list3 = vec!('a','b','c','d','e');
	println!("Max of Third list {}", list3.iter().max_by(|x|{*x}).unwrap());

	let list4 = vec!("Bonjour","Hola","Hello","Hallo","Bongiorno");
	println!("Max of Forth list {}", list4.iter().max_by(|x|{*x}).unwrap());
}
<|endoftext|>


<commit_before>// Copyright (C) 2020 O.S. Systems Sofware LTDA
//
// SPDX-License-Identifier: Apache-2.0

use crate::{api, Error, Result};
use awc::{
    http::{
        header::{self, HeaderName, CONTENT_TYPE, RANGE, USER_AGENT},
        StatusCode,
    },
    ClientBuilder,
};
use serde::Serialize;
use slog_scope::debug;
use std::{
    convert::{TryFrom, TryInto},
    path::Path,
    time::Duration,
};
use tokio::{
    io::{self, AsyncWriteExt},
    stream::StreamExt,
};

pub struct Client<'a> {
    client: awc::Client,
    server: &'a str,
}

impl From<awc::error::SendRequestError> for Error {
    fn from(err: awc::error::SendRequestError) -> Self {
        if let awc::error::SendRequestError::Http(err) = err {
            return Error::Http(err);
        }
        Error::SendRequestError(format!("{}", err))
    }
}

pub async fn get<W>(url: &str, handle: &mut W) -> Result<()>
where
    W: io::AsyncWrite + Unpin,
{
    let req = awc::Client::new().get(url);
    save_body_to(req, handle).await
}

async fn save_body_to<W>(req: awc::ClientRequest, handle: &mut W) -> Result<()>
where
    W: io::AsyncWrite + Unpin,
{
    use std::str::FromStr;

    let mut rep = req.send().await?;
    if !rep.status().is_success() {
        return Err(Error::InvalidStatusResponse(rep.status()));
    }
    let length = usize::from_str(
        rep.headers()
            .get(header::CONTENT_LENGTH)
            .ok_or_else(|| Error::MissingContentLength)?
            .to_str()?,
    )?;
    let mut written: f32 = 0.;
    let mut threshold = 10;

    while let Some(chunk) = rep.next().await {
        let chunk = &chunk?;
        handle.write_all(&chunk).await?;
        written += chunk.len() as f32 / (length / 100) as f32;
        if written as usize >= threshold {
            threshold += 20;
            debug!("{}% of the file has been downloaded", written as usize);
        }
    }
    debug!("100% of the file has been downloaded");

    Ok(())
}

impl<'a> Client<'a> {
    pub fn new(server: &'a str) -> Self {
        let client = ClientBuilder::new()
            .timeout(Duration::from_secs(10))
            .header(USER_AGENT, "updatehub/next")
            .header(CONTENT_TYPE, "application/json")
            .header(
                HeaderName::from_static("api-content-type"),
                "application/vnd.updatehub-v1+json",
            )
            .finish();
        Self { server, client }
    }

    pub async fn probe(
        &self,
        num_retries: u64,
        firmware: api::FirmwareMetadata<'_>,
    ) -> Result<api::ProbeResponse> {
        let mut response = self
            .client
            .post(&format!("{}/upgrades", &self.server))
            .header(HeaderName::from_static("api-retries"), num_retries)
            .send_json(&firmware)
            .await?;

        match response.status() {
            StatusCode::NOT_FOUND => Ok(api::ProbeResponse::NoUpdate),
            StatusCode::OK => {
                match response
                    .headers()
                    .get("add-extra-poll")
                    .and_then(|extra_poll| extra_poll.to_str().ok())
                    .and_then(|extra_poll| extra_poll.parse().ok())
                {
                    Some(extra_poll) => Ok(api::ProbeResponse::ExtraPoll(extra_poll)),
                    None => {
                        let signature = response
                            .headers()
                            .get("UH-Signature")
                            .map(TryInto::try_into)
                            .transpose()?;
                        Ok(api::ProbeResponse::Update(
                            api::UpdatePackage::parse(&response.body().await?)?,
                            signature,
                        ))
                    }
                }
            }
            s => Err(Error::InvalidStatusResponse(s)),
        }
    }

    pub async fn download_object(
        &self,
        product_uid: &str,
        package_uid: &str,
        download_dir: &Path,
        object: &str,
    ) -> Result<()> {
        use tokio::fs::{create_dir_all, OpenOptions};

        // FIXME: Discuss the need of packages inside the route
        let mut request = self.client.get(&format!(
            "{}/products/{}/packages/{}/objects/{}",
            &self.server, product_uid, package_uid, object
        ));

        if !download_dir.exists() {
            debug!("Creating directory to store the downloads.");
            create_dir_all(download_dir).await?;
        }

        let file = download_dir.join(object);
        if file.exists() {
            request = request
                .header(RANGE, format!("bytes={}-", file.metadata()?.len().saturating_sub(1)));
        }

        let mut file = OpenOptions::new().create(true).append(true).open(&file).await?;

        save_body_to(request, &mut file).await
    }

    pub async fn report(
        &self,
        state: &str,
        firmware: api::FirmwareMetadata<'_>,
        package_uid: &str,
        previous_state: Option<&str>,
        error_message: Option<String>,
        current_log: Option<String>,
    ) -> Result<()> {
        #[derive(Serialize)]
        #[serde(rename_all = "kebab-case")]
        struct Payload<'a> {
            #[serde(rename = "status")]
            state: &'a str,
            #[serde(flatten)]
            firmware: api::FirmwareMetadata<'a>,
            package_uid: &'a str,
            #[serde(skip_serializing_if = "Option::is_none")]
            previous_state: Option<&'a str>,
            #[serde(skip_serializing_if = "Option::is_none")]
            error_message: Option<String>,
            #[serde(skip_serializing_if = "Option::is_none")]
            current_log: Option<String>,
        }

        let payload =
            Payload { state, firmware, package_uid, previous_state, error_message, current_log };

        self.client.post(&format!("{}/report", &self.server)).send_json(&payload).await?;
        Ok(())
    }
}

impl TryFrom<&header::HeaderValue> for api::Signature {
    type Error = Error;

    fn try_from(value: &header::HeaderValue) -> Result<Self> {
        Ok(Self::from_base64_str(value.to_str()?)?)
    }
}
<commit_msg>cloud-sdk: Avoid error when content length is not set<commit_after>// Copyright (C) 2020 O.S. Systems Sofware LTDA
//
// SPDX-License-Identifier: Apache-2.0

use crate::{api, Error, Result};
use awc::{
    http::{
        header::{self, HeaderName, CONTENT_TYPE, RANGE, USER_AGENT},
        StatusCode,
    },
    ClientBuilder,
};
use serde::Serialize;
use slog_scope::debug;
use std::{
    convert::{TryFrom, TryInto},
    path::Path,
    time::Duration,
};
use tokio::{
    io::{self, AsyncWriteExt},
    stream::StreamExt,
};

pub struct Client<'a> {
    client: awc::Client,
    server: &'a str,
}

impl From<awc::error::SendRequestError> for Error {
    fn from(err: awc::error::SendRequestError) -> Self {
        if let awc::error::SendRequestError::Http(err) = err {
            return Error::Http(err);
        }
        Error::SendRequestError(format!("{}", err))
    }
}

pub async fn get<W>(url: &str, handle: &mut W) -> Result<()>
where
    W: io::AsyncWrite + Unpin,
{
    let req = awc::Client::new().get(url);
    save_body_to(req, handle).await
}

async fn save_body_to<W>(req: awc::ClientRequest, handle: &mut W) -> Result<()>
where
    W: io::AsyncWrite + Unpin,
{
    use std::str::FromStr;

    let mut rep = req.send().await?;
    if !rep.status().is_success() {
        return Err(Error::InvalidStatusResponse(rep.status()));
    }

    let mut written: f32 = 0.;
    let mut threshold = 10;
    let length = match rep.headers().get(header::CONTENT_LENGTH) {
        Some(v) => usize::from_str(v.to_str()?)?,
        None => 0,
    };

    while let Some(chunk) = rep.next().await {
        let chunk = &chunk?;
        handle.write_all(&chunk).await?;
        if length > 0 {
            written += chunk.len() as f32 / (length / 100) as f32;
            if written as usize >= threshold {
                threshold += 20;
                debug!("{}% of the file has been downloaded", std::cmp::max(written as usize, 100));
            }
        }
    }
    debug!("100% of the file has been downloaded");

    Ok(())
}

impl<'a> Client<'a> {
    pub fn new(server: &'a str) -> Self {
        let client = ClientBuilder::new()
            .timeout(Duration::from_secs(10))
            .header(USER_AGENT, "updatehub/next")
            .header(CONTENT_TYPE, "application/json")
            .header(
                HeaderName::from_static("api-content-type"),
                "application/vnd.updatehub-v1+json",
            )
            .finish();
        Self { server, client }
    }

    pub async fn probe(
        &self,
        num_retries: u64,
        firmware: api::FirmwareMetadata<'_>,
    ) -> Result<api::ProbeResponse> {
        let mut response = self
            .client
            .post(&format!("{}/upgrades", &self.server))
            .header(HeaderName::from_static("api-retries"), num_retries)
            .send_json(&firmware)
            .await?;

        match response.status() {
            StatusCode::NOT_FOUND => Ok(api::ProbeResponse::NoUpdate),
            StatusCode::OK => {
                match response
                    .headers()
                    .get("add-extra-poll")
                    .and_then(|extra_poll| extra_poll.to_str().ok())
                    .and_then(|extra_poll| extra_poll.parse().ok())
                {
                    Some(extra_poll) => Ok(api::ProbeResponse::ExtraPoll(extra_poll)),
                    None => {
                        let signature = response
                            .headers()
                            .get("UH-Signature")
                            .map(TryInto::try_into)
                            .transpose()?;
                        Ok(api::ProbeResponse::Update(
                            api::UpdatePackage::parse(&response.body().await?)?,
                            signature,
                        ))
                    }
                }
            }
            s => Err(Error::InvalidStatusResponse(s)),
        }
    }

    pub async fn download_object(
        &self,
        product_uid: &str,
        package_uid: &str,
        download_dir: &Path,
        object: &str,
    ) -> Result<()> {
        use tokio::fs::{create_dir_all, OpenOptions};

        // FIXME: Discuss the need of packages inside the route
        let mut request = self.client.get(&format!(
            "{}/products/{}/packages/{}/objects/{}",
            &self.server, product_uid, package_uid, object
        ));

        if !download_dir.exists() {
            debug!("Creating directory to store the downloads.");
            create_dir_all(download_dir).await?;
        }

        let file = download_dir.join(object);
        if file.exists() {
            request = request
                .header(RANGE, format!("bytes={}-", file.metadata()?.len().saturating_sub(1)));
        }

        let mut file = OpenOptions::new().create(true).append(true).open(&file).await?;

        save_body_to(request, &mut file).await
    }

    pub async fn report(
        &self,
        state: &str,
        firmware: api::FirmwareMetadata<'_>,
        package_uid: &str,
        previous_state: Option<&str>,
        error_message: Option<String>,
        current_log: Option<String>,
    ) -> Result<()> {
        #[derive(Serialize)]
        #[serde(rename_all = "kebab-case")]
        struct Payload<'a> {
            #[serde(rename = "status")]
            state: &'a str,
            #[serde(flatten)]
            firmware: api::FirmwareMetadata<'a>,
            package_uid: &'a str,
            #[serde(skip_serializing_if = "Option::is_none")]
            previous_state: Option<&'a str>,
            #[serde(skip_serializing_if = "Option::is_none")]
            error_message: Option<String>,
            #[serde(skip_serializing_if = "Option::is_none")]
            current_log: Option<String>,
        }

        let payload =
            Payload { state, firmware, package_uid, previous_state, error_message, current_log };

        self.client.post(&format!("{}/report", &self.server)).send_json(&payload).await?;
        Ok(())
    }
}

impl TryFrom<&header::HeaderValue> for api::Signature {
    type Error = Error;

    fn try_from(value: &header::HeaderValue) -> Result<Self> {
        Ok(Self::from_base64_str(value.to_str()?)?)
    }
}
<|endoftext|>


<commit_before>use std::{
    convert::From,
    path::Path,
};

use serde::{
    Deserialize,
    Serialize,
};

use anyhow::Result;

#[derive(Debug, Deserialize, Serialize)]
pub struct Accession {
    accession: String,
    is_active: bool,
    description: String,
    gene: Option<String>,
    optional_id: Option<String>,
    database: String,
    species: Option<String>,
    common_name: Option<String>,
    feature_name: Option<String>,
    ncrna_class: Option<String>,
    locus_tag: Option<String>,
    organelle: Option<String>,
    lineage: Option<String>,
    all_species: Vec<String>,
    all_common_names: Vec<String>,
    so_rna_type: Option<String>,
}

#[derive(Debug, Deserialize, Serialize)]
pub struct RfamHit {
    rfam_hit_id: usize,
    model: String,
    model_rna_type: Option<String>,
    model_domain: Option<String>,
    model_name: String,
    model_long_name: String,
    model_completeness: f64,
    model_start: usize,
    model_stop: usize,
    sequence_completeness: f64,
    sequence_start: usize,
    sequence_stop: usize,
}

#[derive(Debug, Deserialize, Serialize)]
pub struct R2dtHit {
    model_id: String,
    model_name: String,
    model_source: String,
    model_so_term: Option<String>,
    sequence_coverage: Option<f64>,
    model_coverage: Option<f64>,
    sequence_basepairs: Option<usize>,
    model_basepairs: Option<usize>,
}

#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Previous {
    id: String,
    upi: String,
    taxid: usize,
    databases: String,
    description: Option<String>,
    has_coordinates: bool,
    is_active: bool,
    is_fragment: bool,
    is_locus_representative: bool,
    last_release: usize,
    rfam_problems: String,
    rna_type: String,
    short_description: Option<String>,
    so_rna_type: Option<String>,
    update_date: Option<String>,
}

#[derive(Debug, Deserialize, Serialize)]
pub struct RawAccessionEntry {
    accession: String,
    is_active: bool,
    description: String,
    gene: Option<String>,
    optional_id: Option<String>,
    database: String,
    species: Option<String>,
    common_name: Option<String>,
    feature_name: Option<String>,
    ncrna_class: Option<String>,
    locus_tag: Option<String>,
    organelle: Option<String>,
    lineage: Option<String>,
    all_species: Vec<Option<String>>,
    all_common_names: Vec<Option<String>>,
    so_rna_type: Option<String>,
}

#[derive(Debug, Deserialize, Serialize)]
pub struct Coordinate {
    assembly_id: String,
    chromosome: String,
    strand: String,
    start: usize,
    stop: usize,
}

#[derive(Debug, Deserialize, Serialize)]
pub struct Xref {
    length: usize,
    deleted: String,
    last_release: usize,
}

#[derive(Debug, Deserialize, Serialize)]
pub struct Raw {
    id: String,
    #[serde(rename = "xref")]
    xrefs: Vec<Xref>,
    accessions: Vec<RawAccessionEntry>,
    coordinates: Vec<Coordinate>,

    #[serde(rename = "rfam-hits")]
    rfam_hits: Vec<RfamHit>,

    #[serde(rename = "r2dt-hits")]
    r2dt_hits: Vec<R2dtHit>,
    previous: Vec<Previous>,
}

#[derive(Debug, Deserialize, Serialize)]
pub struct Normalized {
    upi: String,
    taxid: usize,
    length: usize,
    last_release: usize,
    coordinates: Vec<Coordinate>,
    accessions: Vec<Accession>,
    deleted: Vec<bool>,
    previous: Option<Previous>,
    rfam_hits: Vec<RfamHit>,
    r2dt_hits: Vec<R2dtHit>,
}

impl From<RawAccessionEntry> for Accession {
    fn from(raw: RawAccessionEntry) -> Self {
        return Self {
            accession: raw.accession,
            is_active: raw.is_active,
            description: raw.description,
            gene: raw.gene,
            optional_id: raw.optional_id,
            database: raw.database,
            species: raw.species,
            common_name: raw.common_name,
            feature_name: raw.feature_name,
            ncrna_class: raw.ncrna_class,
            locus_tag: raw.locus_tag,
            organelle: raw.organelle,
            lineage: raw.lineage,
            all_species: raw.all_species.into_iter().filter_map(|s| s).collect(),
            all_common_names: raw.all_common_names.into_iter().filter_map(|s| s).collect(),
            so_rna_type: raw.so_rna_type,
        };
    }
}

impl From<Raw> for Normalized {
    fn from(raw: Raw) -> Self {
        let parts: Vec<&str> = raw.id.split("_").collect();
        let upi = parts[0].to_owned();
        let taxid = parts[1].parse::<usize>().unwrap();
        let previous = raw.previous.get(0).cloned();
        let length = raw.xrefs[0].length;
        let last_release = raw.xrefs.iter().map(|x| x.last_release).max().unwrap();

        let mut deleted = true;
        let mut accessions = Vec::with_capacity(raw.accessions.len());
        for raw_accession in raw.accessions {
            if raw_accession.is_active {
                deleted = false;
            }
            accessions.push(Accession::from(raw_accession));
        }

        return Self {
            upi,
            taxid,
            length,
            last_release,
            coordinates: raw.coordinates,
            accessions,
            deleted: vec![deleted],
            previous,
            rfam_hits: raw.rfam_hits,
            r2dt_hits: raw.r2dt_hits,
        };
    }
}

pub fn write(filename: &Path, output: &Path) -> Result<()> {
    let mut reader = rnc_utils::buf_reader(filename)?;
    let mut output = rnc_utils::buf_writer(output)?;
    let mut buf = String::new();
    loop {
        match reader.read_line(&mut buf)? {
            0 => break,
            _ => {
                let cleaned = buf.replace("\\\\", "\\");
                let raw: Raw = serde_json::from_str(&cleaned)?;
                let norm: Normalized = Normalized::from(raw);
                serde_json::to_writer(&mut output, &norm)?;
                writeln!(&mut output)?;
                buf.clear();
            },
        }
    }

    Ok(())
}
<commit_msg>May end up using sets for some things<commit_after>use std::{
    convert::From,
    path::Path,
};

use serde::{
    Deserialize,
    Serialize,
};

use anyhow::Result;

#[derive(Debug, Deserialize, Serialize, PartialEq)]
pub struct Accession {
    accession: String,
    is_active: bool,
    description: String,
    gene: Option<String>,
    optional_id: Option<String>,
    database: String,
    species: Option<String>,
    common_name: Option<String>,
    feature_name: Option<String>,
    ncrna_class: Option<String>,
    locus_tag: Option<String>,
    organelle: Option<String>,
    lineage: Option<String>,
    all_species: Vec<String>,
    all_common_names: Vec<String>,
    so_rna_type: Option<String>,
}

#[derive(Debug, Deserialize, Serialize, PartialEq)]
pub struct RfamHit {
    rfam_hit_id: usize,
    model: String,
    model_rna_type: Option<String>,
    model_domain: Option<String>,
    model_name: String,
    model_long_name: String,
    model_completeness: f64,
    model_start: usize,
    model_stop: usize,
    sequence_completeness: f64,
    sequence_start: usize,
    sequence_stop: usize,
}

#[derive(Debug, Deserialize, Serialize, PartialEq)]
pub struct R2dtHit {
    model_id: String,
    model_name: String,
    model_source: String,
    model_so_term: Option<String>,
    sequence_coverage: Option<f64>,
    model_coverage: Option<f64>,
    sequence_basepairs: Option<usize>,
    model_basepairs: Option<usize>,
}

#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
pub struct Previous {
    id: String,
    upi: String,
    taxid: usize,
    databases: String,
    description: Option<String>,
    has_coordinates: bool,
    is_active: bool,
    is_fragment: bool,
    is_locus_representative: bool,
    last_release: usize,
    rfam_problems: String,
    rna_type: String,
    short_description: Option<String>,
    so_rna_type: Option<String>,
    update_date: Option<String>,
}

#[derive(Debug, Deserialize, Serialize)]
pub struct RawAccessionEntry {
    accession: String,
    is_active: bool,
    description: String,
    gene: Option<String>,
    optional_id: Option<String>,
    database: String,
    species: Option<String>,
    common_name: Option<String>,
    feature_name: Option<String>,
    ncrna_class: Option<String>,
    locus_tag: Option<String>,
    organelle: Option<String>,
    lineage: Option<String>,
    all_species: Vec<Option<String>>,
    all_common_names: Vec<Option<String>>,
    so_rna_type: Option<String>,
}

#[derive(Debug, Deserialize, Serialize, PartialEq)]
pub struct Coordinate {
    assembly_id: String,
    chromosome: String,
    strand: String,
    start: usize,
    stop: usize,
}

#[derive(Debug, Deserialize, Serialize)]
pub struct Xref {
    length: usize,
    deleted: String,
    last_release: usize,
}

#[derive(Debug, Deserialize, Serialize)]
pub struct Raw {
    id: String,
    #[serde(rename = "xref")]
    xrefs: Vec<Xref>,
    accessions: Vec<RawAccessionEntry>,
    coordinates: Vec<Coordinate>,

    #[serde(rename = "rfam-hits")]
    rfam_hits: Vec<RfamHit>,

    #[serde(rename = "r2dt-hits")]
    r2dt_hits: Vec<R2dtHit>,
    previous: Vec<Previous>,
}

#[derive(Debug, Deserialize, Serialize)]
pub struct Normalized {
    upi: String,
    taxid: usize,
    length: usize,
    last_release: usize,
    coordinates: Vec<Coordinate>,
    accessions: Vec<Accession>,
    deleted: Vec<bool>,
    previous: Option<Previous>,
    rfam_hits: Vec<RfamHit>,
    r2dt_hits: Vec<R2dtHit>,
}

impl From<RawAccessionEntry> for Accession {
    fn from(raw: RawAccessionEntry) -> Self {
        return Self {
            accession: raw.accession,
            is_active: raw.is_active,
            description: raw.description,
            gene: raw.gene,
            optional_id: raw.optional_id,
            database: raw.database,
            species: raw.species,
            common_name: raw.common_name,
            feature_name: raw.feature_name,
            ncrna_class: raw.ncrna_class,
            locus_tag: raw.locus_tag,
            organelle: raw.organelle,
            lineage: raw.lineage,
            all_species: raw.all_species.into_iter().filter_map(|s| s).collect(),
            all_common_names: raw.all_common_names.into_iter().filter_map(|s| s).collect(),
            so_rna_type: raw.so_rna_type,
        };
    }
}

impl From<Raw> for Normalized {
    fn from(raw: Raw) -> Self {
        let parts: Vec<&str> = raw.id.split("_").collect();
        let upi = parts[0].to_owned();
        let taxid = parts[1].parse::<usize>().unwrap();
        let previous = raw.previous.get(0).cloned();
        let length = raw.xrefs[0].length;
        let last_release = raw.xrefs.iter().map(|x| x.last_release).max().unwrap();

        let mut deleted = true;
        let mut accessions = Vec::with_capacity(raw.accessions.len());
        for raw_accession in raw.accessions {
            if raw_accession.is_active {
                deleted = false;
            }
            accessions.push(Accession::from(raw_accession));
        }

        return Self {
            upi,
            taxid,
            length,
            last_release,
            coordinates: raw.coordinates,
            accessions,
            deleted: vec![deleted],
            previous,
            rfam_hits: raw.rfam_hits,
            r2dt_hits: raw.r2dt_hits,
        };
    }
}

pub fn write(filename: &Path, output: &Path) -> Result<()> {
    let mut reader = rnc_utils::buf_reader(filename)?;
    let mut output = rnc_utils::buf_writer(output)?;
    let mut buf = String::new();
    loop {
        match reader.read_line(&mut buf)? {
            0 => break,
            _ => {
                let cleaned = buf.replace("\\\\", "\\");
                let raw: Raw = serde_json::from_str(&cleaned)?;
                let norm: Normalized = Normalized::from(raw);
                serde_json::to_writer(&mut output, &norm)?;
                writeln!(&mut output)?;
                buf.clear();
            },
        }
    }

    Ok(())
}
<|endoftext|>


<commit_before>//! The datum module provides a data structure, Datum, that implements the Unify trait.
//! Datum aims to be a drop-in for any algorithm in ai_kit that operates on the Unify trait.

#[cfg(feature = "with-constraint")]
use constraints::ConstraintValue;
use core;
use std;
use std::collections::{BTreeMap, HashMap};
use std::str;
use utils;

#[derive(Clone, Debug, Serialize, Deserialize, PartialOrd)]
pub enum Datum {
    #[serde(rename = "null")] Nil,
    #[serde(rename = "bool")] Bool(bool),
    #[serde(rename = "str")] String(String),
    #[serde(rename = "int")] Int(i64),
    #[serde(rename = "float")] Float(f64),
    #[serde(rename = "var")] Variable(String),
    #[serde(rename = "vec")] Vector(Vec<Datum>),
    #[serde(rename = "map")] Map(BTreeMap<String, Datum>),
    #[serde(rename = "fn")] Function { head: Box<Datum>, args: Vec<Datum> },
}

impl Datum {
    pub fn to_bool(&self) -> Option<bool> {
        match *self {
            Datum::Bool(ref value) => Some(value.clone()),
            _ => None,
        }
    }

    pub fn to_string(&self) -> Option<String> {
        match *self {
            Datum::String(ref value) => Some(value.clone()),
            _ => None,
        }
    }

    pub fn to_int(&self) -> Option<i64> {
        match *self {
            Datum::Int(ref value) => Some(value.clone()),
            _ => None,
        }
    }

    pub fn to_float(&self) -> Option<f64> {
        match *self {
            Datum::Float(ref f_value) => Some(f_value.clone()),
            Datum::Int(ref i_value) => Some(i_value.clone() as f64),
            _ => None,
        }
    }

    pub fn to_variable(&self) -> Option<String> {
        match *self {
            Datum::Variable(ref value) => Some(value.clone()),
            _ => None,
        }
    }

    pub fn function_head<'a>(&'a self) -> Option<&'a Box<Self>> {
        match *self {
            Datum::Function { ref head, .. } => Some(head),
            _ => None,
        }
    }

    pub fn function_args<'a>(&'a self) -> Option<&'a Vec<Self>> {
        match *self {
            Datum::Function { ref args, .. } => Some(args),
            _ => None,
        }
    }

    pub fn pprint(&self) -> String {
        match *self {
            Datum::Nil => format!("nil"),
            Datum::Bool(ref b) => format!("{}", b),
            Datum::String(ref s) => format!("{}", s),
            Datum::Int(ref i) => format!("{}", i),
            Datum::Float(ref f) => format!("{}", f),
            Datum::Variable(ref v) => format!("{}", v),
            Datum::Vector(ref args) => {
                let elements: Vec<String> = args.iter().map(|e| e.pprint()).collect();
                format!("({})", elements.join(","))
            }
            Datum::Map(ref args) => {
                let elements: Vec<String> = args.iter()
                    .map(|(k, v)| format!("{} => {}", k, v.pprint()))
                    .collect();
                format!("({})", elements.join(","))
            }
            Datum::Function { ref head, ref args } => {
                let elements: Vec<String> = args.iter().map(|e| e.pprint()).collect();
                format!("({} ({}))", head, elements.join(","))
            }
        }
    }

    pub fn is_nil(&self) -> bool {
        match *self {
            Datum::Nil => true,
            _ => false,
        }
    }

    pub fn is_bool(&self) -> bool {
        match *self {
            Datum::Bool(_) => true,
            _ => false,
        }
    }

    pub fn is_int(&self) -> bool {
        match *self {
            Datum::Int(_) => true,
            _ => false,
        }
    }

    pub fn is_float(&self) -> bool {
        match *self {
            Datum::Float(_) => true,
            _ => false,
        }
    }

    pub fn is_string(&self) -> bool {
        match *self {
            Datum::String(_) => true,
            _ => false,
        }
    }

    pub fn is_variable(&self) -> bool {
        match *self {
            Datum::Variable(_) => true,
            _ => false,
        }
    }

    pub fn is_vector(&self) -> bool {
        match *self {
            Datum::Vector(_) => true,
            _ => false,
        }
    }

    pub fn is_map(&self) -> bool {
        match *self {
            Datum::Map { .. } => true,
            _ => false,
        }
    }

    pub fn is_function(&self) -> bool {
        match *self {
            Datum::Function { .. } => true,
            _ => false,
        }
    }
}

impl Default for Datum {
    fn default() -> Self {
        Datum::Nil
    }
}

impl PartialEq for Datum {
    fn eq(&self, other: &Datum) -> bool {
        match *self {
            Datum::Nil => match *other {
                Datum::Nil => true,
                _ => false,
            },
            Datum::Bool(b) => match *other {
                Datum::Bool(b2) => b == b2,
                _ => false,
            },
            Datum::String(ref s) => match *other {
                Datum::String(ref s2) => s == s2,
                _ => false,
            },
            Datum::Int(ref i) => match *other {
                Datum::Int(ref i2) => i == i2,
                _ => false,
            },
            Datum::Float(ref f) => match *other {
                Datum::Float(ref f2) => f == f2,
                _ => false,
            },
            Datum::Variable(ref v) => match *other {
                Datum::Variable(ref v2) => v == v2,
                _ => false,
            },
            Datum::Vector(ref args) => match *other {
                Datum::Vector(ref args2) => args == args2,
                _ => false,
            },
            Datum::Map(ref args) => match *other {
                Datum::Map(ref args2) => args == args2,
                _ => false,
            },
            Datum::Function { ref head, ref args } => match *other {
                Datum::Function {
                    head: ref head2,
                    args: ref args2,
                } if args.len() == args2.len() =>
                {
                    head == head2 && args == args2
                }
                _ => false,
            },
        }
    }
}

impl Eq for Datum {}
impl Ord for Datum {
    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
        self.partial_cmp(other).unwrap()
    }
}

impl core::BindingsValue for Datum {
    fn variable(s: &String) -> Option<Self> {
        Some(Datum::Variable(s.clone()))
    }
    fn to_variable(&self) -> Option<String> {
        self.to_variable()
    }
}

#[cfg(feature = "with-constraint")]
impl ConstraintValue for Datum {
    fn to_float(&self) -> Option<f64> {
        self.to_float()
    }
    fn float(c: f64) -> Self {
        Datum::Float(c)
    }
}

impl core::Unify<Datum> for Datum {
    fn unify(&self, other: &Datum, bindings: &core::Bindings<Self>) -> Option<core::Bindings<Self>> {
        fn unify_args(args: &Vec<Datum>, args2: &Vec<Datum>, bindings: &core::Bindings<Datum>) -> Option<core::Bindings<Datum>> {
            utils::fold_while_some(
                bindings.clone(),
                &mut args.iter().zip(args2.iter()),
                &|bindings: core::Bindings<Datum>, (ref a, ref b): (&Datum, &Datum)| a.unify(&b, &bindings),
            )
        }

        fn unify_maps(
            args: &BTreeMap<String, Datum>,
            args2: &BTreeMap<String, Datum>,
            bindings: &core::Bindings<Datum>,
        ) -> Option<core::Bindings<Datum>> {
            if args.len() != args2.len() {
                None
            } else {
                utils::fold_while_some(
                    bindings.clone(),
                    &mut args.iter(),
                    &|bindings: core::Bindings<Datum>, (ref k, ref v): (&String, &Datum)| args2.get(*k).and_then(|v2| v.unify(v2, &bindings)),
                )
            }
        }
        match *self {
            Datum::Variable(ref var_name) => bindings.update_bindings(var_name, other),
            Datum::Vector(ref args) => match *other {
                Datum::Vector(ref args2) if args.len() == args2.len() => unify_args(args, args2, &bindings),
                _ => None,
            },
            Datum::Map(ref args) => match *other {
                Datum::Map(ref args2) if args.len() == args2.len() => unify_maps(args, args2, &bindings),
                _ => None,
            },
            _ => match *other {
                Datum::Variable(ref var_name) => bindings.update_bindings(var_name, self),
                _ => {
                    if self == other {
                        Some(bindings.clone())
                    } else {
                        None
                    }
                }
            },
        }
    }

    fn apply_bindings(&self, bindings: &core::Bindings<Self>) -> Option<Self> {
        fn apply_bindings_to_args(args: &Vec<Datum>, bindings: &core::Bindings<Datum>) -> Option<Vec<Datum>> {
            utils::map_while_some(&mut args.iter(), &|arg| {
                arg.apply_bindings(bindings)
            })
        }
        fn apply_bindings_to_map(args: &BTreeMap<String, Datum>, bindings: &core::Bindings<Datum>) -> Option<BTreeMap<String, Datum>> {
            utils::map_while_some(&mut args.iter(), &|(k, v)| {
                v.apply_bindings(bindings)
                    .and_then(|v| Some((k.clone(), v)))
            }).and_then(|tuple_vec| Some(tuple_vec.into_iter().collect::<BTreeMap<String, Datum>>()))
        }
        match *self {
            Datum::Variable(ref var_name) => bindings
                .get_binding(var_name)
                .or_else(|| Some(self.clone())),
            Datum::Vector(ref args) => apply_bindings_to_args(args, bindings).and_then(|args| Some(Datum::Vector(args))),
            Datum::Map(ref args) => apply_bindings_to_map(args, bindings).and_then(|args| Some(Datum::Map(args))),
            _ => Some(self.clone()),
        }
    }

    fn variables(&self) -> Vec<String> {
        match *self {
            Datum::Variable(ref v) => vec![v.clone()],
            Datum::Vector(ref args) => {
                let mut variables = Vec::new();
                for arg in args.iter() {
                    variables.extend(arg.variables().into_iter());
                }
                variables
            }
            Datum::Map(ref args) => {
                let mut variables = Vec::new();
                for v in args.values() {
                    variables.extend(v.variables().into_iter());
                }
                variables
            }
            _ => Vec::new(),
        }
    }

    fn rename_variables(&self, renamed_variables: &HashMap<String, String>) -> Self {
        match *self {
            Datum::Variable(ref v) => renamed_variables
                .get(v)
                .and_then(|new_v| Some(Datum::Variable(new_v.clone())))
                .or_else(|| Some(self.clone()))
                .unwrap(),
            Datum::Vector(ref args) => Datum::Vector(
                args.iter()
                    .map(|arg| arg.rename_variables(renamed_variables))
                    .collect(),
            ),
            Datum::Map(ref args) => Datum::Map(
                args.iter()
                    .map(|(k, v)| (k.clone(), v.rename_variables(renamed_variables)))
                    .collect(),
            ),
            _ => self.clone(),
        }
    }

    fn nil() -> Self {
        Datum::Nil
    }
}

impl std::fmt::Display for Datum {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        write!(f, "{}", self.pprint())
    }
}

#[cfg(test)]
mod tests;
<commit_msg>Added Datum method, has_same_shape_as for comparing two Datums<commit_after>//! The datum module provides a data structure, Datum, that implements the Unify trait.
//! Datum aims to be a drop-in for any algorithm in ai_kit that operates on the Unify trait.

#[cfg(feature = "with-constraint")]
use constraints::ConstraintValue;
use core;
use std;
use std::collections::{BTreeMap, HashMap};
use std::str;
use utils;

#[derive(Clone, Debug, Serialize, Deserialize, PartialOrd)]
pub enum Datum {
    #[serde(rename = "null")] Nil,
    #[serde(rename = "bool")] Bool(bool),
    #[serde(rename = "str")] String(String),
    #[serde(rename = "int")] Int(i64),
    #[serde(rename = "float")] Float(f64),
    #[serde(rename = "var")] Variable(String),
    #[serde(rename = "vec")] Vector(Vec<Datum>),
    #[serde(rename = "map")] Map(BTreeMap<String, Datum>),
    #[serde(rename = "fn")] Function { head: Box<Datum>, args: Vec<Datum> },
}

impl Datum {
    pub fn to_bool(&self) -> Option<bool> {
        match *self {
            Datum::Bool(ref value) => Some(value.clone()),
            _ => None,
        }
    }

    pub fn to_string(&self) -> Option<String> {
        match *self {
            Datum::String(ref value) => Some(value.clone()),
            _ => None,
        }
    }

    pub fn to_int(&self) -> Option<i64> {
        match *self {
            Datum::Int(ref value) => Some(value.clone()),
            _ => None,
        }
    }

    pub fn to_float(&self) -> Option<f64> {
        match *self {
            Datum::Float(ref f_value) => Some(f_value.clone()),
            Datum::Int(ref i_value) => Some(i_value.clone() as f64),
            _ => None,
        }
    }

    pub fn to_variable(&self) -> Option<String> {
        match *self {
            Datum::Variable(ref value) => Some(value.clone()),
            _ => None,
        }
    }

    pub fn function_head<'a>(&'a self) -> Option<&'a Box<Self>> {
        match *self {
            Datum::Function { ref head, .. } => Some(head),
            _ => None,
        }
    }

    pub fn function_args<'a>(&'a self) -> Option<&'a Vec<Self>> {
        match *self {
            Datum::Function { ref args, .. } => Some(args),
            _ => None,
        }
    }

    pub fn pprint(&self) -> String {
        match *self {
            Datum::Nil => format!("nil"),
            Datum::Bool(ref b) => format!("{}", b),
            Datum::String(ref s) => format!("{}", s),
            Datum::Int(ref i) => format!("{}", i),
            Datum::Float(ref f) => format!("{}", f),
            Datum::Variable(ref v) => format!("{}", v),
            Datum::Vector(ref args) => {
                let elements: Vec<String> = args.iter().map(|e| e.pprint()).collect();
                format!("({})", elements.join(","))
            }
            Datum::Map(ref args) => {
                let elements: Vec<String> = args.iter()
                    .map(|(k, v)| format!("{} => {}", k, v.pprint()))
                    .collect();
                format!("({})", elements.join(","))
            }
            Datum::Function { ref head, ref args } => {
                let elements: Vec<String> = args.iter().map(|e| e.pprint()).collect();
                format!("({} ({}))", head, elements.join(","))
            }
        }
    }

    pub fn is_nil(&self) -> bool {
        match *self {
            Datum::Nil => true,
            _ => false,
        }
    }

    pub fn is_bool(&self) -> bool {
        match *self {
            Datum::Bool(_) => true,
            _ => false,
        }
    }

    pub fn is_int(&self) -> bool {
        match *self {
            Datum::Int(_) => true,
            _ => false,
        }
    }

    pub fn is_float(&self) -> bool {
        match *self {
            Datum::Float(_) => true,
            _ => false,
        }
    }

    pub fn is_string(&self) -> bool {
        match *self {
            Datum::String(_) => true,
            _ => false,
        }
    }

    pub fn is_variable(&self) -> bool {
        match *self {
            Datum::Variable(_) => true,
            _ => false,
        }
    }

    pub fn is_vector(&self) -> bool {
        match *self {
            Datum::Vector(_) => true,
            _ => false,
        }
    }

    pub fn is_map(&self) -> bool {
        match *self {
            Datum::Map { .. } => true,
            _ => false,
        }
    }

    pub fn is_function(&self) -> bool {
        match *self {
            Datum::Function { .. } => true,
            _ => false,
        }
    }

    pub fn has_same_shape_as(&self, other: &Datum) -> bool {
        match (self, other) {
            (&Datum::Nil, &Datum::Nil) => true,
            (&Datum::Bool(_), &Datum::Bool(_)) => true,
            (&Datum::Int(_), &Datum::Int(_)) => true,
            (&Datum::Float(_), &Datum::Float(_)) => true,
            (&Datum::String(_), &Datum::String(_)) => true,
            (&Datum::Variable(_), &Datum::Variable(_)) => true,
            (&Datum::Vector(ref x), &Datum::Vector(ref y)) => x.len() == y.len(),
            (&Datum::Map(ref x), &Datum::Map(ref y)) => x.len() == y.len(),
            (
                &Datum::Function { ref head, ref args },
                &Datum::Function {
                    head: ref head2,
                    args: ref args2,
                },
            ) => {
                head.has_same_shape_as(head2)
                    && args.iter()
                        .zip(args2.iter())
                        .all(|(x, y)| x.has_same_shape_as(y))
            }
            _ => false,
        }
    }
}

impl Default for Datum {
    fn default() -> Self {
        Datum::Nil
    }
}

impl PartialEq for Datum {
    fn eq(&self, other: &Datum) -> bool {
        match *self {
            Datum::Nil => match *other {
                Datum::Nil => true,
                _ => false,
            },
            Datum::Bool(b) => match *other {
                Datum::Bool(b2) => b == b2,
                _ => false,
            },
            Datum::String(ref s) => match *other {
                Datum::String(ref s2) => s == s2,
                _ => false,
            },
            Datum::Int(ref i) => match *other {
                Datum::Int(ref i2) => i == i2,
                _ => false,
            },
            Datum::Float(ref f) => match *other {
                Datum::Float(ref f2) => f == f2,
                _ => false,
            },
            Datum::Variable(ref v) => match *other {
                Datum::Variable(ref v2) => v == v2,
                _ => false,
            },
            Datum::Vector(ref args) => match *other {
                Datum::Vector(ref args2) => args == args2,
                _ => false,
            },
            Datum::Map(ref args) => match *other {
                Datum::Map(ref args2) => args == args2,
                _ => false,
            },
            Datum::Function { ref head, ref args } => match *other {
                Datum::Function {
                    head: ref head2,
                    args: ref args2,
                } if args.len() == args2.len() =>
                {
                    head == head2 && args == args2
                }
                _ => false,
            },
        }
    }
}

impl Eq for Datum {}
impl Ord for Datum {
    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
        self.partial_cmp(other).unwrap()
    }
}

impl core::BindingsValue for Datum {
    fn variable(s: &String) -> Option<Self> {
        Some(Datum::Variable(s.clone()))
    }
    fn to_variable(&self) -> Option<String> {
        self.to_variable()
    }
}

#[cfg(feature = "with-constraint")]
impl ConstraintValue for Datum {
    fn to_float(&self) -> Option<f64> {
        self.to_float()
    }
    fn float(c: f64) -> Self {
        Datum::Float(c)
    }
}

impl core::Unify<Datum> for Datum {
    fn unify(&self, other: &Datum, bindings: &core::Bindings<Self>) -> Option<core::Bindings<Self>> {
        fn unify_args(args: &Vec<Datum>, args2: &Vec<Datum>, bindings: &core::Bindings<Datum>) -> Option<core::Bindings<Datum>> {
            utils::fold_while_some(
                bindings.clone(),
                &mut args.iter().zip(args2.iter()),
                &|bindings: core::Bindings<Datum>, (ref a, ref b): (&Datum, &Datum)| a.unify(&b, &bindings),
            )
        }

        fn unify_maps(
            args: &BTreeMap<String, Datum>,
            args2: &BTreeMap<String, Datum>,
            bindings: &core::Bindings<Datum>,
        ) -> Option<core::Bindings<Datum>> {
            if args.len() != args2.len() {
                None
            } else {
                utils::fold_while_some(
                    bindings.clone(),
                    &mut args.iter(),
                    &|bindings: core::Bindings<Datum>, (ref k, ref v): (&String, &Datum)| args2.get(*k).and_then(|v2| v.unify(v2, &bindings)),
                )
            }
        }
        match *self {
            Datum::Variable(ref var_name) => bindings.update_bindings(var_name, other),
            Datum::Vector(ref args) => match *other {
                Datum::Vector(ref args2) if args.len() == args2.len() => unify_args(args, args2, &bindings),
                _ => None,
            },
            Datum::Map(ref args) => match *other {
                Datum::Map(ref args2) if args.len() == args2.len() => unify_maps(args, args2, &bindings),
                _ => None,
            },
            _ => match *other {
                Datum::Variable(ref var_name) => bindings.update_bindings(var_name, self),
                _ => {
                    if self == other {
                        Some(bindings.clone())
                    } else {
                        None
                    }
                }
            },
        }
    }

    fn apply_bindings(&self, bindings: &core::Bindings<Self>) -> Option<Self> {
        fn apply_bindings_to_args(args: &Vec<Datum>, bindings: &core::Bindings<Datum>) -> Option<Vec<Datum>> {
            utils::map_while_some(&mut args.iter(), &|arg| {
                arg.apply_bindings(bindings)
            })
        }
        fn apply_bindings_to_map(args: &BTreeMap<String, Datum>, bindings: &core::Bindings<Datum>) -> Option<BTreeMap<String, Datum>> {
            utils::map_while_some(&mut args.iter(), &|(k, v)| {
                v.apply_bindings(bindings)
                    .and_then(|v| Some((k.clone(), v)))
            }).and_then(|tuple_vec| Some(tuple_vec.into_iter().collect::<BTreeMap<String, Datum>>()))
        }
        match *self {
            Datum::Variable(ref var_name) => bindings
                .get_binding(var_name)
                .or_else(|| Some(self.clone())),
            Datum::Vector(ref args) => apply_bindings_to_args(args, bindings).and_then(|args| Some(Datum::Vector(args))),
            Datum::Map(ref args) => apply_bindings_to_map(args, bindings).and_then(|args| Some(Datum::Map(args))),
            _ => Some(self.clone()),
        }
    }

    fn variables(&self) -> Vec<String> {
        match *self {
            Datum::Variable(ref v) => vec![v.clone()],
            Datum::Vector(ref args) => {
                let mut variables = Vec::new();
                for arg in args.iter() {
                    variables.extend(arg.variables().into_iter());
                }
                variables
            }
            Datum::Map(ref args) => {
                let mut variables = Vec::new();
                for v in args.values() {
                    variables.extend(v.variables().into_iter());
                }
                variables
            }
            _ => Vec::new(),
        }
    }

    fn rename_variables(&self, renamed_variables: &HashMap<String, String>) -> Self {
        match *self {
            Datum::Variable(ref v) => renamed_variables
                .get(v)
                .and_then(|new_v| Some(Datum::Variable(new_v.clone())))
                .or_else(|| Some(self.clone()))
                .unwrap(),
            Datum::Vector(ref args) => Datum::Vector(
                args.iter()
                    .map(|arg| arg.rename_variables(renamed_variables))
                    .collect(),
            ),
            Datum::Map(ref args) => Datum::Map(
                args.iter()
                    .map(|(k, v)| (k.clone(), v.rename_variables(renamed_variables)))
                    .collect(),
            ),
            _ => self.clone(),
        }
    }

    fn nil() -> Self {
        Datum::Nil
    }
}

impl std::fmt::Display for Datum {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        write!(f, "{}", self.pprint())
    }
}

#[cfg(test)]
mod tests;
<|endoftext|>