<commit_before>use std::io::Write;
use serde::ser::{Impossible, Serialize, Serializer, SerializeSeq, SerializeStruct, SerializeTuple};

use error::{Error, ResultE};
use super::bundle_serializer::BundleSerializer;
use super::msg_serializer::MsgSerializer;
use super::pkt_type_decoder::{PktType, PktTypeDecoder};

/// Serializes an entire OSC packet, which contains either one message or one
/// bundle.
///
/// The data being serialized may be either a tuple, a struct (in which case
/// each field is serialized in sequence, ignore the field names), or a Serde
/// sequence.
///
/// If the packet is a message, then the first field of the object being serialized
/// should be a `str`-type that represents the OSC address. The next field should
/// contain all the arguments. For example, the `message` instance below will serialize
/// to a message addressed to "/audio/play" with a payload of `4i32` and `0.5f32`.
///
/// ```
/// #[macro_use]
/// extern crate serde_derive;
///
/// #[derive(Serialize)]
/// struct AudioPlayer {
///     address: String,
///     args: (i32, f32),
/// }
///# fn main() {
/// let message = AudioPlayer{ address: "/audio/play".to_string(), args: (4, 0.5) };
///# }
/// ```
///
/// To serialize a bundle, simply omit the address field, add a `(u32, u32)` field
/// to transmit the [time-tag] associated with the bundle, and make sure all
/// subsequent fields are themselves something that is serializable as a message.
/// For example, an instance of the below `MyBundle` struct would serialize as a bundle.
///
/// ```
///# #[macro_use]
///# extern crate serde_derive;
///#
/// #[derive(Serialize)]
/// struct MyBundle {
///     time: (u32, u32),
///     msg1: AudioPlayer,
///     msg2: AudioPlayer,
///     // ... And so on. Note that the messages don't need to be of homogeneous type;
///     // msg1 could be AudioPlayer and msg2 some other Serialize-able type.
///     // Additionally, this object would still be serialized as a bundle even
///     // if it contained only one message.
/// }
/// ```
///
/// Note: the time-tag can also be `[u32; 2]`, a struct containing two `u32` members,
/// or *anything* that serializes as a flat sequence of two `u32`s.
///
/// [time-tag]: http://opensoundcontrol.org/node/3/#timetags
pub struct PktSerializer<W: Write> {
    output: W,
}

/// After the State receives a serialize_seq call,
/// we return one of these. If the next data is a string, then it's the message
/// address & we're serializing a message.
/// If the next data is a sequence, we're serializing a bundle, and that sequence is
/// the (u32, u32) time tag.
pub struct PktContents<'a, W: Write + 'a> {
    output: &'a mut PktSerializer<W>,
    state: State,
}

enum State {
    UnknownType,
    Msg(MsgSerializer),
    Bundle(BundleSerializer),
}

impl<W: Write> PktSerializer<W> {
    pub fn new(output: W) -> Self {
        Self{ output }
    }
}

impl<'a, W: Write> Serializer for &'a mut PktSerializer<W> {
    type Ok = ();
    type Error = Error;
    type SerializeSeq = PktContents<'a, W>;
    type SerializeTuple = Self::SerializeSeq;
    type SerializeStruct = Self::SerializeSeq;
    type SerializeTupleStruct = Impossible<Self::Ok, Error>;
    type SerializeTupleVariant = Impossible<Self::Ok, Error>;
    type SerializeMap = Impossible<Self::Ok, Error>;
    type SerializeStructVariant = Impossible<Self::Ok, Error>;

    default_ser!{bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char
        str bytes none some unit unit_struct unit_variant newtype_struct newtype_variant
        tuple_struct tuple_variant map struct_variant}
    fn serialize_seq(
        self,
        _size: Option<usize>
    ) -> ResultE<Self::SerializeSeq>
    {
        Ok(PktContents{ output: self, state: State::UnknownType })
    }
    fn serialize_tuple(
        self,
        size: usize
    ) -> ResultE<Self::SerializeTuple>
    {
        self.serialize_seq(Some(size))
    }
    fn serialize_struct(
        self,
        _: &'static str,
        size: usize
    ) -> ResultE<Self::SerializeStruct>
    {
        self.serialize_seq(Some(size))
    }
}

impl<'a, W: Write + 'a> SerializeSeq for PktContents<'a, W> {
    type Ok = ();
    type Error = Error;

    fn serialize_element<'b, T: ?Sized>(&'b mut self, value: &T) -> ResultE<()>
        where T: Serialize
    {
        match self.state {
            State::UnknownType => {
                // Determine the type of the packet.
                // If the first element is a string, then we become a message;
                //   will accept i32, f32, blob, str args.
                // If the first element we see is a timecode (seq of u32, u32),
                //   then we become a bundle.
                let mut decoder = PktTypeDecoder::new();
                value.serialize(&mut decoder)?;

                match decoder.pkt_type() {
                    PktType::Unknown => Err(Error::BadFormat),
                    PktType::Msg => {
                        self.state = State::Msg(MsgSerializer::new(
                            decoder.data()
                        )?);
                        Ok(())
                    },
                    PktType::Bundle => {
                        self.state = State::Bundle(BundleSerializer::new(
                            decoder.data()
                        ));
                        Ok(())
                    },
                }
            },
            State::Msg(ref mut msg) => {
                value.serialize(msg)
            },
            State::Bundle(ref mut bundle) => {
                value.serialize(bundle)
            },
        }
    }

    fn end(self) -> ResultE<()> {
        match self.state {
            // Packet has no contents!
            State::UnknownType => Err(Error::BadFormat),
            // Write the message header & data to the output
            State::Msg(msg) => {
                Ok(msg.write_into(&mut self.output.output)?)
            },
            // Write the bundle header & data to the output
            State::Bundle(bundle) => {
                Ok(bundle.write_into(&mut self.output.output)?)
            }
        }
    }
}

impl<'a, W: Write + 'a> SerializeStruct for PktContents<'a, W> {
    type Ok = ();
    type Error = Error;

    fn serialize_field<T: ?Sized>(&mut self, _key: &'static str, value: &T) -> ResultE<()>
        where T: Serialize
    {
        SerializeSeq::serialize_element(self, value)
    }

    fn end(self) -> ResultE<()> {
        SerializeSeq::end(self)
    }
}

impl<'a, W: Write + 'a> SerializeTuple for PktContents<'a, W> {
    type Ok = ();
    type Error = Error;

    fn serialize_element<T: ?Sized>(&mut self, value: &T) -> ResultE<()>
        where T: Serialize
    {
        SerializeSeq::serialize_element(self, value)
    }

    fn end(self) -> ResultE<()> {
        SerializeSeq::end(self)
    }
}

<commit_msg>Formatting<commit_after>use std::io::Write;
use serde::ser::{Impossible, Serialize, Serializer, SerializeSeq, SerializeStruct, SerializeTuple};

use error::{Error, ResultE};
use super::bundle_serializer::BundleSerializer;
use super::msg_serializer::MsgSerializer;
use super::pkt_type_decoder::{PktType, PktTypeDecoder};

/// Serializes an entire OSC packet, which contains either one message or one
/// bundle.
///
/// The data being serialized may be either a tuple, a struct (in which case
/// each field is serialized in sequence, ignore the field names), or a Serde
/// sequence.
///
/// If the packet is a message, then the first field of the object being serialized
/// should be a `str`-type that represents the OSC address. The next field should
/// contain all the arguments. For example, the `message` instance below will serialize
/// to a message addressed to "/audio/play" with a payload of `4i32` and `0.5f32`.
///
/// ```
/// #[macro_use]
/// extern crate serde_derive;
///
/// #[derive(Serialize)]
/// struct AudioPlayer {
///     address: String,
///     args: (i32, f32),
/// }
///# fn main() {
/// let message = AudioPlayer{ address: "/audio/play".to_string(), args: (4, 0.5) };
///# }
/// ```
///
/// To serialize a bundle, simply omit the address field, add a `(u32, u32)` field
/// to transmit the [time-tag] associated with the bundle, and make sure all
/// subsequent fields are themselves something that is serializable as a message.
/// For example, an instance of the below `MyBundle` struct would serialize as a bundle.
///
/// ```
///# #[macro_use]
///# extern crate serde_derive;
///#
/// #[derive(Serialize)]
/// struct MyBundle {
///     time: (u32, u32),
///     msg1: AudioPlayer,
///     msg2: AudioPlayer,
///     // ... And so on. Note that the messages don't need to be of homogeneous type;
///     // msg1 could be AudioPlayer and msg2 some other Serialize-able type.
///     // Additionally, this object would still be serialized as a bundle even
///     // if it contained only one message.
/// }
/// ```
///
/// Note: the time-tag can also be `[u32; 2]`, a struct containing two `u32` members,
/// or *anything* that serializes as a flat sequence of two `u32`s.
///
/// [time-tag]: http://opensoundcontrol.org/node/3/#timetags
pub struct PktSerializer<W: Write> {
    output: W,
}

/// After the State receives a serialize_seq call,
/// we return one of these. If the next data is a string, then it's the message
/// address & we're serializing a message.
/// If the next data is a sequence, we're serializing a bundle, and that sequence is
/// the (u32, u32) time tag.
pub struct PktContents<'a, W: Write + 'a> {
    output: &'a mut PktSerializer<W>,
    state: State,
}

enum State {
    UnknownType,
    Msg(MsgSerializer),
    Bundle(BundleSerializer),
}

impl<W: Write> PktSerializer<W> {
    pub fn new(output: W) -> Self {
        Self{ output }
    }
}

impl<'a, W: Write> Serializer for &'a mut PktSerializer<W> {
    type Ok = ();
    type Error = Error;
    type SerializeSeq = PktContents<'a, W>;
    type SerializeTuple = Self::SerializeSeq;
    type SerializeStruct = Self::SerializeSeq;
    type SerializeTupleStruct = Impossible<Self::Ok, Error>;
    type SerializeTupleVariant = Impossible<Self::Ok, Error>;
    type SerializeMap = Impossible<Self::Ok, Error>;
    type SerializeStructVariant = Impossible<Self::Ok, Error>;

    default_ser!{bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char
        str bytes none some unit unit_struct unit_variant newtype_struct newtype_variant
        tuple_struct tuple_variant map struct_variant}
    fn serialize_seq(
        self,
        _size: Option<usize>
    ) -> ResultE<Self::SerializeSeq>
    {
        Ok(PktContents{ output: self, state: State::UnknownType })
    }
    fn serialize_tuple(
        self,
        size: usize
    ) -> ResultE<Self::SerializeTuple>
    {
        self.serialize_seq(Some(size))
    }
    fn serialize_struct(
        self,
        _: &'static str,
        size: usize
    ) -> ResultE<Self::SerializeStruct>
    {
        self.serialize_seq(Some(size))
    }
}

impl<'a, W: Write + 'a> SerializeSeq for PktContents<'a, W> {
    type Ok = ();
    type Error = Error;

    fn serialize_element<'b, T: ?Sized>(&'b mut self, value: &T) -> ResultE<()>
        where T: Serialize
    {
        match self.state {
            State::UnknownType => {
                // Determine the type of the packet.
                // If the first element is a string, then we become a message;
                //   will accept i32, f32, blob, str args.
                // If the first element we see is a timecode (seq of u32, u32),
                //   then we become a bundle.
                let mut decoder = PktTypeDecoder::new();
                value.serialize(&mut decoder)?;

                match decoder.pkt_type() {
                    PktType::Unknown => Err(Error::BadFormat),
                    PktType::Msg => {
                        self.state = State::Msg(MsgSerializer::new(
                            decoder.data()
                        )?);
                        Ok(())
                    },
                    PktType::Bundle => {
                        self.state = State::Bundle(BundleSerializer::new(
                            decoder.data()
                        ));
                        Ok(())
                    },
                }
            },
            State::Msg(ref mut msg) => {
                value.serialize(msg)
            },
            State::Bundle(ref mut bundle) => {
                value.serialize(bundle)
            },
        }
    }

    fn end(self) -> ResultE<()> {
        match self.state {
            // Packet has no contents!
            State::UnknownType => Err(Error::BadFormat),
            // Write the message header & data to the output
            State::Msg(msg) => {
                msg.write_into(&mut self.output.output)
            },
            // Write the bundle header & data to the output
            State::Bundle(bundle) => {
                bundle.write_into(&mut self.output.output)
            }
        }
    }
}

impl<'a, W: Write + 'a> SerializeStruct for PktContents<'a, W> {
    type Ok = ();
    type Error = Error;

    fn serialize_field<T: ?Sized>(&mut self, _key: &'static str, value: &T) -> ResultE<()>
        where T: Serialize
    {
        SerializeSeq::serialize_element(self, value)
    }

    fn end(self) -> ResultE<()> {
        SerializeSeq::end(self)
    }
}

impl<'a, W: Write + 'a> SerializeTuple for PktContents<'a, W> {
    type Ok = ();
    type Error = Error;

    fn serialize_element<T: ?Sized>(&mut self, value: &T) -> ResultE<()>
        where T: Serialize
    {
        SerializeSeq::serialize_element(self, value)
    }

    fn end(self) -> ResultE<()> {
        SerializeSeq::end(self)
    }
}

<|endoftext|>


<commit_before>use std::collections::HashMap;
use std::sync::mpsc::{Sender, Receiver, channel};
use std::sync::mpsc::TryRecvError;
use std::sync::{Arc, Mutex};
use std::old_io::timer;
use std::time::Duration;

use messages::{ActorMessages, TransactionRequest, MarketMessages, MarketHistory};
use messages::ActorMessages::{StockRequest, MoneyRequest, CommitTransaction, AbortTransaction, History, Time};
use messages::MarketMessages::{SellRequest, Commit, Cancel, RegisterActor, MatchRequest};
use actor::Actor;

// Smarter actor
// (monitors price last sold at and put a sell request if any stocks are above their purchase price)

pub fn start_smarter_actor(actor_id: usize, existing_markets: HashMap<usize, Sender<MarketMessages>>, actor_tx: Sender<ActorMessages>, actor_rx: Receiver<ActorMessages>) {
  println!("Starting Smarter_Actor {}", actor_id);
  let mut init_history = false;
  let mut actor = Actor { id: actor_id,
                          money: 100,
                          stocks: HashMap::new(),
                          pending_money: 0,
                          pending_stock: (0, 0),
                          markets: existing_markets,
                          history: Arc::new(Mutex::new(MarketHistory {history: HashMap::new(), stocks: vec![]}))
                          };
  // Stocks = HashMap<market_id, HashMap<stock_id, (price,quantity)>>
  let mut bought_stocks : HashMap<usize, HashMap<usize,(usize,usize)>> = HashMap::new();

  for (_, market_tx) in actor.markets.iter() {
    market_tx.send(RegisterActor(actor.id, actor_tx.clone())).unwrap();
  }

  loop {
    //Logic
    let mark_clone = actor.markets.clone();
    let stock_clone = actor.stocks.clone();

    if(init_history){
      let hist = actor.history.lock().unwrap();

      // For each stock in history
      for stock in hist.stocks.iter(){
        match(hist.history.get(stock)){
          Some(transactions) => {
            println!("Length of transactions is {} for {}.",transactions.len(),stock);
            for transaction in transactions.iter(){
              println!("Transaction  b:{} s:{}.",transaction.0,transaction.1);
            }
            // if we own the stock and the last sold transaction was above my bought price submit a sell
            // if we don't own the stock submit a buy for the last sold transaction
            },
          None => {}
        }

      }

      println!("History has length {} for smarter_actor.",hist.stocks.len());
    }

    match actor_rx.try_recv() {
      Ok(message) => {
          match message {
            StockRequest(stock_request) => {
              println!("Started Stock Request in smarter_actor {}", actor.id);
              let market_tx;
              let tx_text = mark_clone.get(&stock_request.market_id);
              match tx_text {
                Some(tx) => {
                  market_tx = tx;
                },
                None => {
                  return; //HOW DID WE GET A MISSING MARKET?
                }
              }
              if has_pending_transaction(&actor) {
                market_tx.send(Cancel(actor.id)).unwrap();
              }
              else {
                //if we have the stock. set it aside.
                let stock_id = stock_request.stock_id;
                let quantity = stock_request.quantity;
                let stock = stock_clone.get(&stock_id);
                match stock {
                  Some(owned_quantity) => {
                    if *owned_quantity >= quantity {
                      remove_stock(&mut actor, (stock_id, quantity));
                      actor.pending_stock = (stock_id, quantity);
                      market_tx.send(Commit(actor.id)).unwrap();
                    }
                    else {
                      market_tx.send(Cancel(actor.id)).unwrap();
                    }
                  },
                  None => {
                    market_tx.send(Cancel(actor.id)).unwrap();
                  }
                }
              }
              print_status(&actor);
              },
            MoneyRequest(money_request) => {
              let market_tx;
              let tx_text = actor.markets.get(&money_request.market_id);
              match tx_text {
                Some(tx) => {
                  market_tx = tx;
                },
                None => {
                  return; //HOW DID WE GET A MISSING MARKET?
                }
              }
              if has_pending_transaction(&actor) {
                market_tx.send(Cancel(actor.id)).unwrap();
              }
              else {
                //if we have the money. set it aside.
                if actor.money >= money_request.amount {
                  actor.money = actor.money - money_request.amount;
                  actor.pending_money = money_request.amount;
                  market_tx.send(Commit(actor.id)).unwrap();
                }
                else {
                  market_tx.send(Cancel(actor.id)).unwrap();
                }
              }
              print_status(&actor);
              },
            CommitTransaction(commit_transaction_request) => {
              //if we have money pending, then look up the stock id and add that quantity purchased.
              //remove the pending money
              if actor.pending_money > 0 {
                let price_per_unit = commit_transaction_request.price;
                let units = commit_transaction_request.quantity;
                let leftover_money = actor.pending_money - price_per_unit * units;

                //make a function for adding stock.
                add_stock(&mut actor, (commit_transaction_request.stock_id, units));
                actor.money = actor.money + leftover_money;

                actor.pending_money = 0;
              }

              //if we have stock pending, look up the quantity purchased and add the money.
              //remove the pending stock
              if actor.pending_stock.1 > 0 {
                let money = commit_transaction_request.price * commit_transaction_request.quantity;
                let restore_stock = (commit_transaction_request.stock_id, actor.pending_stock.1 - commit_transaction_request.quantity);
                if restore_stock.1 > 0 {
                  add_stock(&mut actor, restore_stock);
                }
                actor.money = actor.money + money;
                actor.pending_stock = (0,0);
              }
              println!("After a committed transaction in smarter_actor {} ", actor.id);
              print_status(&actor);
              },
            AbortTransaction => {
              //move pending stock back into stocks.
              if actor.pending_stock.1 != 0 {
                let pending_stock_clone = actor.pending_stock.clone();
                add_stock(&mut actor, pending_stock_clone);
                //now that we have moved it. Clear out the pending stock.
                actor.pending_stock = (0,0); //setting the quantity to zero clears it.
              }
              for (stock_id, quantity) in actor.stocks.iter() {
                println!("After aborting the transaction, smarter_actor {} now has StockId: {} Quantity: {}", actor.id, *stock_id, *quantity);
              }

              //move pending money back into money.
              if actor.pending_money > 0 {
                actor.money = actor.money + actor.pending_money;
                actor.pending_money = 0;
              }
              println!("After aborting the transaction, smarter_actor {} now has {} money.", actor.id, actor.money);
            },
            History(history) => {
              println!("Smarter_actor {} received history {}", actor.id, *(history.lock().unwrap()));
              actor.history = history;
              init_history = true;
              },
            Time(current, max) => {
              println!("Smarter_actor {} received time {}", actor.id, current);
            }
          }
        },
      Err(TryRecvError::Empty) => {timer::sleep(Duration::milliseconds(10));},
      Err(TryRecvError::Disconnected) => {println!("ERROR: Smarter_actor {} disconnected", actor.id);}
    }
  }
}

fn add_stock(actor: &mut Actor, stock_to_add: (usize, usize)) {
  let stock_clone = actor.stocks.clone();
  let held_stock = stock_clone.get(&stock_to_add.0);
  match held_stock {
    Some(stock_count) => {
        //we have some stock. We need to add to our reserve.
        actor.stocks.insert(stock_to_add.0, stock_to_add.1 + *stock_count);
      },
    None => {
      //we don't have any stock left. Just add it back.
      actor.stocks.insert(stock_to_add.0, stock_to_add.1);
    }
  }
}

fn remove_stock(actor: &mut Actor, stock_to_remove: (usize, usize)) {
  let stock_clone = actor.stocks.clone();
  let held_stock = stock_clone.get(&stock_to_remove.0);
  match held_stock {
    Some(stock_count) => {
        //we have some stock. We need to add to our reserve.
        actor.stocks.insert(stock_to_remove.0, *stock_count - stock_to_remove.1);
      },
    None => {} //TODO Should we error handle here?
  }
}

fn print_status(actor: &Actor) {
  for (stock_id, quantity) in (*actor).stocks.iter() {
    println!("Actor {} now has StockId: {} Quantity: {}", (*actor).id, *stock_id, *quantity);
  }
  println!("Actor {} has {} money.", (*actor).id, (*actor).money);
}

fn has_pending_transaction(actor: &Actor) -> bool {
  (*actor).pending_money > 0 || (*actor).pending_stock.1 > 0
}
<commit_msg>parts of the logic added for smarter actor<commit_after>use std::collections::HashMap;
use std::sync::mpsc::{Sender, Receiver, channel};
use std::sync::mpsc::TryRecvError;
use std::sync::{Arc, Mutex};
use std::old_io::timer;
use std::time::Duration;

use messages::{ActorMessages, TransactionRequest, MarketMessages, MarketHistory};
use messages::ActorMessages::{StockRequest, MoneyRequest, CommitTransaction, AbortTransaction, History, Time};
use messages::MarketMessages::{BuyRequest, SellRequest, Commit, Cancel, RegisterActor, MatchRequest};
use actor::Actor;

// Smarter actor
// (monitors price last sold at and put a sell request if any stocks are above their purchase price)

pub fn start_smarter_actor(actor_id: usize, existing_markets: HashMap<usize, Sender<MarketMessages>>, actor_tx: Sender<ActorMessages>, actor_rx: Receiver<ActorMessages>) {
  println!("Starting Smarter_Actor {}", actor_id);
  let mut init_history = false;
  let mut actor = Actor { id: actor_id,
                          money: 100,
                          stocks: HashMap::new(),
                          pending_money: 0,
                          pending_stock: (0, 0),
                          markets: existing_markets,
                          history: Arc::new(Mutex::new(MarketHistory {history: HashMap::new(), stocks: vec![]}))
                          };
  // Stocks = HashMap<market_id, HashMap<stock_id, (price,quantity)>>
  let mut buy_requests : HashMap<usize, HashMap<usize,(usize,usize)>> = HashMap::new();
  let mut unique_id : usize = 0;

  for (_, market_tx) in actor.markets.iter() {
    market_tx.send(RegisterActor(actor.id, actor_tx.clone())).unwrap();
  }

  loop {
    //Logic
    let mark_clone = actor.markets.clone();
    let stock_clone = actor.stocks.clone();

    if(init_history){
      let hist = actor.history.lock().unwrap();

      // For each stock in history
      for stock in hist.stocks.iter(){
        match(hist.history.get(stock)){
          Some(mut transactions) => {
            println!("Length of transactions is {} for {}.",transactions.len(),stock);
            if(transactions.len() > 0){
              let (buyer,seller) = transactions[transactions.len()-1].clone();
              match buy_requests.get(&0){
                Some(stock_requests) => {
                  match stock_requests.get(stock){
                    Some(&(request_price,request_quantity)) => {
                      // If price is above out request a sell
                      if(buyer.price > request_price){
                        send_message(0,&mark_clone,BuyRequest(TransactionRequest {transaction_id: unique_id, actor_id:actor_id, stock_id: stock.clone(), price:buyer.price, quantity:buyer.quantity }));
                        unique_id = unique_id + 1;
                      }
                    },
                    None => {
                      // Submit new buy request
                    }
                  }
                },
                None =>{} // Market didn't exist?

              }
            }

            },
          None => {}
        }

      }

      println!("History has length {} for smarter_actor.",hist.stocks.len());
    }

    match actor_rx.try_recv() {
      Ok(message) => {
          match message {
            StockRequest(stock_request) => {
              println!("Started Stock Request in smarter_actor {}", actor.id);
              let market_tx;
              let tx_text = mark_clone.get(&stock_request.market_id);
              match tx_text {
                Some(tx) => {
                  market_tx = tx;
                },
                None => {
                  return; //HOW DID WE GET A MISSING MARKET?
                }
              }
              if has_pending_transaction(&actor) {
                market_tx.send(Cancel(actor.id)).unwrap();
              }
              else {
                //if we have the stock. set it aside.
                let stock_id = stock_request.stock_id;
                let quantity = stock_request.quantity;
                let stock = stock_clone.get(&stock_id);
                match stock {
                  Some(owned_quantity) => {
                    if *owned_quantity >= quantity {
                      remove_stock(&mut actor, (stock_id, quantity));
                      actor.pending_stock = (stock_id, quantity);
                      market_tx.send(Commit(actor.id)).unwrap();
                    }
                    else {
                      market_tx.send(Cancel(actor.id)).unwrap();
                    }
                  },
                  None => {
                    market_tx.send(Cancel(actor.id)).unwrap();
                  }
                }
              }
              print_status(&actor);
              },
            MoneyRequest(money_request) => {
              let market_tx;
              let tx_text = actor.markets.get(&money_request.market_id);
              match tx_text {
                Some(tx) => {
                  market_tx = tx;
                },
                None => {
                  return; //HOW DID WE GET A MISSING MARKET?
                }
              }
              if has_pending_transaction(&actor) {
                market_tx.send(Cancel(actor.id)).unwrap();
              }
              else {
                //if we have the money. set it aside.
                if actor.money >= money_request.amount {
                  actor.money = actor.money - money_request.amount;
                  actor.pending_money = money_request.amount;
                  market_tx.send(Commit(actor.id)).unwrap();
                }
                else {
                  market_tx.send(Cancel(actor.id)).unwrap();
                }
              }
              print_status(&actor);
              },
            CommitTransaction(commit_transaction_request) => {
              //if we have money pending, then look up the stock id and add that quantity purchased.
              //remove the pending money
              if actor.pending_money > 0 {
                let price_per_unit = commit_transaction_request.price;
                let units = commit_transaction_request.quantity;
                let leftover_money = actor.pending_money - price_per_unit * units;

                //make a function for adding stock.
                add_stock(&mut actor, (commit_transaction_request.stock_id, units));
                actor.money = actor.money + leftover_money;

                actor.pending_money = 0;
              }

              //if we have stock pending, look up the quantity purchased and add the money.
              //remove the pending stock
              if actor.pending_stock.1 > 0 {
                let money = commit_transaction_request.price * commit_transaction_request.quantity;
                let restore_stock = (commit_transaction_request.stock_id, actor.pending_stock.1 - commit_transaction_request.quantity);
                if restore_stock.1 > 0 {
                  add_stock(&mut actor, restore_stock);
                }
                actor.money = actor.money + money;
                actor.pending_stock = (0,0);
              }
              println!("After a committed transaction in smarter_actor {} ", actor.id);
              print_status(&actor);
              },
            AbortTransaction => {
              //move pending stock back into stocks.
              if actor.pending_stock.1 != 0 {
                let pending_stock_clone = actor.pending_stock.clone();
                add_stock(&mut actor, pending_stock_clone);
                //now that we have moved it. Clear out the pending stock.
                actor.pending_stock = (0,0); //setting the quantity to zero clears it.
              }
              for (stock_id, quantity) in actor.stocks.iter() {
                println!("After aborting the transaction, smarter_actor {} now has StockId: {} Quantity: {}", actor.id, *stock_id, *quantity);
              }

              //move pending money back into money.
              if actor.pending_money > 0 {
                actor.money = actor.money + actor.pending_money;
                actor.pending_money = 0;
              }
              println!("After aborting the transaction, smarter_actor {} now has {} money.", actor.id, actor.money);
            },
            History(history) => {
              println!("Smarter_actor {} received history {}", actor.id, *(history.lock().unwrap()));
              actor.history = history;
              init_history = true;
              },
            Time(current, max) => {
              println!("Smarter_actor {} received time {}", actor.id, current);
            }
          }
        },
      Err(TryRecvError::Empty) => {timer::sleep(Duration::milliseconds(10));},
      Err(TryRecvError::Disconnected) => {println!("ERROR: Smarter_actor {} disconnected", actor.id);}
    }
  }
}

fn add_stock(actor: &mut Actor, stock_to_add: (usize, usize)) {
  let stock_clone = actor.stocks.clone();
  let held_stock = stock_clone.get(&stock_to_add.0);
  match held_stock {
    Some(stock_count) => {
        //we have some stock. We need to add to our reserve.
        actor.stocks.insert(stock_to_add.0, stock_to_add.1 + *stock_count);
      },
    None => {
      //we don't have any stock left. Just add it back.
      actor.stocks.insert(stock_to_add.0, stock_to_add.1);
    }
  }
}

// send_message(0,actor.markets,BuyRequest(TransactionRequest {transaction_id: unique_id, actor_id:actor_id, stock_id: stock, price:buyer.price, quantity:buyer.quantity }));

fn send_message(market_id : usize, markets: &HashMap<usize, Sender<MarketMessages>>, message: MarketMessages){
  match markets.get(&market_id){
    Some(market) => {
      market.send(message);
      },
    None => {}
  }
}

fn remove_stock(actor: &mut Actor, stock_to_remove: (usize, usize)) {
  let stock_clone = actor.stocks.clone();
  let held_stock = stock_clone.get(&stock_to_remove.0);
  match held_stock {
    Some(stock_count) => {
        //we have some stock. We need to add to our reserve.
        actor.stocks.insert(stock_to_remove.0, *stock_count - stock_to_remove.1);
      },
    None => {} //TODO Should we error handle here?
  }
}

fn print_status(actor: &Actor) {
  for (stock_id, quantity) in (*actor).stocks.iter() {
    println!("Actor {} now has StockId: {} Quantity: {}", (*actor).id, *stock_id, *quantity);
  }
  println!("Actor {} has {} money.", (*actor).id, (*actor).money);
}

fn has_pending_transaction(actor: &Actor) -> bool {
  (*actor).pending_money > 0 || (*actor).pending_stock.1 > 0
}
<|endoftext|>


<commit_before>use super::*;

#[derive(Debug, Clone, Hash, PartialEq)]
pub enum ArenaInput {
    Start,
    Turn(Direction),
}

impl ArenaInput {
    pub fn process_into_updates(self, arena: &Arena, player_id: PlayerId) -> Vec<ArenaUpdate> {
        match self {
            ArenaInput::Start => {
                if arena.started.is_some() {
                    trace!(
                        "Refusing to start arena that is already started: {}",
                        arena.id
                    );
                    return vec![];
                }

                let mut updates = Vec::with_capacity(
                    arena.lightcycles.len() + arena.trails.len() + (arena.players.len() * 2) + 1,
                );

                // remove existing lightcycles
                arena
                    .lightcycles
                    .keys()
                    .copied()
                    .for_each(|id| updates.push(ArenaUpdate::RemoveLightcycle(id)));

                // remove existing trails
                arena
                    .trails
                    .keys()
                    .copied()
                    .for_each(|id| updates.push(ArenaUpdate::RemoveTrail(id)));

                // add new lightcycles and trails
                let player_ids = arena.players.keys().copied().collect();
                calculate_spawnpoints(player_ids).drain(..).for_each(
                    |(player_id, spawn_position, spawn_direction)| {
                        updates.push(ArenaUpdate::AddLightcycle(
                            player_id,
                            Lightcycle {
                                position: spawn_position,
                                direction: spawn_direction,
                                ..Default::default()
                            },
                        ));
                        updates.push(ArenaUpdate::AddTrail(
                            player_id,
                            Trail {
                                points: vec![spawn_position, spawn_position],
                            },
                        ));
                    },
                );

                // begin countdown
                updates.push(ArenaUpdate::Start(
                    Utc::now() + OldDuration::seconds(ARENA_START_TIMER_SECONDS),
                ));

                updates
            }

            ArenaInput::Turn(direction) => {
                let lightcycle = match arena.lightcycles.get(&player_id) {
                    Some(lightcycle) => lightcycle,
                    None => {
                        error!("Lightcycle {} not found", player_id);
                        return vec![];
                    }
                };

                if lightcycle.dead {
                    trace!("Refusing to turn dead lightcycle");
                    return vec![];
                }

                if lightcycle.direction.is_opposite(direction) {
                    trace!("Refusing to turn lightcycle in opposite direction");
                    return vec![];
                }

                return vec![ArenaUpdate::UpdateLightcycleDirection(player_id, direction)];
            }
        }
    }
}
<commit_msg>fixed arena not appending trail points on lightcycle turns<commit_after>use super::*;

#[derive(Debug, Clone, Hash, PartialEq)]
pub enum ArenaInput {
    Start,
    Turn(Direction),
}

impl ArenaInput {
    pub fn process_into_updates(self, arena: &Arena, player_id: PlayerId) -> Vec<ArenaUpdate> {
        match self {
            ArenaInput::Start => {
                if arena.started.is_some() {
                    trace!(
                        "Refusing to start arena that is already started: {}",
                        arena.id
                    );
                    return vec![];
                }

                let mut updates = Vec::with_capacity(
                    arena.lightcycles.len() + arena.trails.len() + (arena.players.len() * 2) + 1,
                );

                // remove existing lightcycles
                arena
                    .lightcycles
                    .keys()
                    .copied()
                    .for_each(|id| updates.push(ArenaUpdate::RemoveLightcycle(id)));

                // remove existing trails
                arena
                    .trails
                    .keys()
                    .copied()
                    .for_each(|id| updates.push(ArenaUpdate::RemoveTrail(id)));

                // add new lightcycles and trails
                let player_ids = arena.players.keys().copied().collect();
                calculate_spawnpoints(player_ids).drain(..).for_each(
                    |(player_id, spawn_position, spawn_direction)| {
                        updates.push(ArenaUpdate::AddLightcycle(
                            player_id,
                            Lightcycle {
                                position: spawn_position,
                                direction: spawn_direction,
                                ..Default::default()
                            },
                        ));
                        updates.push(ArenaUpdate::AddTrail(
                            player_id,
                            Trail {
                                points: vec![spawn_position, spawn_position],
                            },
                        ));
                    },
                );

                // begin countdown
                updates.push(ArenaUpdate::Start(
                    Utc::now() + OldDuration::seconds(ARENA_START_TIMER_SECONDS),
                ));

                updates
            }

            ArenaInput::Turn(direction) => {
                let lightcycle = match arena.lightcycles.get(&player_id) {
                    Some(lightcycle) => lightcycle,
                    None => {
                        error!("Lightcycle {} not found", player_id);
                        return vec![];
                    }
                };

                if lightcycle.dead {
                    trace!("Refusing to turn dead lightcycle");
                    return vec![];
                }

                if lightcycle.direction.is_opposite(direction) {
                    trace!("Refusing to turn lightcycle in opposite direction");
                    return vec![];
                }

                return vec![
                    ArenaUpdate::UpdateTrailAppendPoint(player_id, lightcycle.position),
                    ArenaUpdate::UpdateLightcycleDirection(player_id, direction),
                ];
            }
        }
    }
}
<|endoftext|>


<commit_before>//! # Page table entry
//! Some code borrowed from [Phil Opp's Blog](http://os.phil-opp.com/modifying-page-tables.html)

use crate::memory::Frame;

use super::{PageFlags, PhysicalAddress, RmmA, RmmArch};

/// A page table entry
#[repr(packed(8))]
pub struct Entry(u64);

bitflags! {
    pub struct EntryFlags: usize {
        const PRESENT =         RmmA::ENTRY_FLAG_PRESENT;
        const WRITABLE =        RmmA::ENTRY_FLAG_READWRITE;
        const USER_ACCESSIBLE = RmmA::ENTRY_FLAG_USER;
        const NO_CACHE =        1 << 4;
        const HUGE_PAGE =       1 << 7;
        const NO_EXECUTE =      RmmA::ENTRY_FLAG_NO_EXEC;
    }
}

pub const COUNTER_MASK: u64 = 0x3ff0_0000_0000_0000;

impl Entry {
    /// Clear entry
    pub fn set_zero(&mut self) {
        self.0 = 0;
    }

    /// Is the entry unused?
    pub fn is_unused(&self) -> bool {
        self.0 == (self.0 & COUNTER_MASK)
    }

    /// Make the entry unused
    pub fn set_unused(&mut self) {
        self.0 &= COUNTER_MASK;
    }

    /// Get the address this page references
    pub fn address(&self) -> PhysicalAddress {
        PhysicalAddress::new(self.0 as usize & RmmA::PAGE_ADDRESS_MASK)
    }

    /// Get the current entry flags
    pub fn flags(&self) -> PageFlags<RmmA> {
        unsafe { PageFlags::from_data((self.0 as usize & RmmA::ENTRY_FLAGS_MASK) & !(COUNTER_MASK as usize)) }
    }

    /// Get the associated frame, if available
    pub fn pointed_frame(&self) -> Option<Frame> {
        if self.flags().has_present() {
            Some(Frame::containing_address(self.address()))
        } else {
            None
        }
    }

    pub fn set(&mut self, frame: Frame, flags: PageFlags<RmmA>) {
        debug_assert!(frame.start_address().data() & !RmmA::PAGE_ADDRESS_MASK == 0);
        self.0 = (frame.start_address().data() as u64) | (flags.data() as u64) | (self.0 & COUNTER_MASK);
    }

    /// Get bits 52-61 in entry, used as counter for page table
    pub fn counter_bits(&self) -> u64 {
        (self.0 & COUNTER_MASK) >> 52
    }

    /// Set bits 52-61 in entry, used as counter for page table
    pub fn set_counter_bits(&mut self, count: u64) {
        self.0 = (self.0 & !COUNTER_MASK) | (count << 52);
    }
}

#[cfg(test)]
mod tests {
    #[test]
    fn entry_has_required_arch_alignment() {
        use super::Entry;
        assert!(core::mem::align_of::<Entry>() >= core::mem::align_of::<u64>(), "alignment of Entry is less than the required alignment of u64 ({} < {})", core::mem::align_of::<Entry>(), core::mem::align_of::<u64>());
    }
}
<commit_msg>Remove unused flags from old EntryFlags<commit_after>//! # Page table entry
//! Some code borrowed from [Phil Opp's Blog](http://os.phil-opp.com/modifying-page-tables.html)

use crate::memory::Frame;

use super::{PageFlags, PhysicalAddress, RmmA, RmmArch};

/// A page table entry
#[repr(packed(8))]
pub struct Entry(u64);

bitflags! {
    pub struct EntryFlags: usize {
        const NO_CACHE =        1 << 4;
        const HUGE_PAGE =       1 << 7;
    }
}

pub const COUNTER_MASK: u64 = 0x3ff0_0000_0000_0000;

impl Entry {
    /// Clear entry
    pub fn set_zero(&mut self) {
        self.0 = 0;
    }

    /// Is the entry unused?
    pub fn is_unused(&self) -> bool {
        self.0 == (self.0 & COUNTER_MASK)
    }

    /// Make the entry unused
    pub fn set_unused(&mut self) {
        self.0 &= COUNTER_MASK;
    }

    /// Get the address this page references
    pub fn address(&self) -> PhysicalAddress {
        PhysicalAddress::new(self.0 as usize & RmmA::PAGE_ADDRESS_MASK)
    }

    /// Get the current entry flags
    pub fn flags(&self) -> PageFlags<RmmA> {
        unsafe { PageFlags::from_data((self.0 as usize & RmmA::ENTRY_FLAGS_MASK) & !(COUNTER_MASK as usize)) }
    }

    /// Get the associated frame, if available
    pub fn pointed_frame(&self) -> Option<Frame> {
        if self.flags().has_present() {
            Some(Frame::containing_address(self.address()))
        } else {
            None
        }
    }

    pub fn set(&mut self, frame: Frame, flags: PageFlags<RmmA>) {
        debug_assert!(frame.start_address().data() & !RmmA::PAGE_ADDRESS_MASK == 0);
        self.0 = (frame.start_address().data() as u64) | (flags.data() as u64) | (self.0 & COUNTER_MASK);
    }

    /// Get bits 52-61 in entry, used as counter for page table
    pub fn counter_bits(&self) -> u64 {
        (self.0 & COUNTER_MASK) >> 52
    }

    /// Set bits 52-61 in entry, used as counter for page table
    pub fn set_counter_bits(&mut self, count: u64) {
        self.0 = (self.0 & !COUNTER_MASK) | (count << 52);
    }
}

#[cfg(test)]
mod tests {
    #[test]
    fn entry_has_required_arch_alignment() {
        use super::Entry;
        assert!(core::mem::align_of::<Entry>() >= core::mem::align_of::<u64>(), "alignment of Entry is less than the required alignment of u64 ({} < {})", core::mem::align_of::<Entry>(), core::mem::align_of::<u64>());
    }
}
<|endoftext|>


<commit_before>// Copyright 2016 Jeremy Mason
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
// http://opensource.org/licenses/MIT>, at your option. This file may not be
// copied, modified, or distributed except according to those terms.

#![feature(test)]

extern crate mayda;
extern crate num;
extern crate rand;
extern crate test;

use mayda::{Access, Encode, Unimodal};
use num::{Bounded, FromPrimitive, ToPrimitive};
use rand::distributions::{IndependentSample, Range, Normal};
use test::Bencher;

fn rand_outliers<T>(mean: T, std_dev: T, length: usize) -> Vec<T>
  where T: PartialOrd +
           Bounded +
           FromPrimitive +
           ToPrimitive +
           rand::distributions::range::SampleRange {
  let mut output: Vec<T> = Vec::with_capacity(length);
  if length > 0 {
    let val = Normal::new(mean.to_f64().unwrap(), std_dev.to_f64().unwrap());
    let mut rng = rand::thread_rng();
    for _ in 0..length {
      output.push(FromPrimitive::from_f64(val.ind_sample(&mut rng)).unwrap());
    }
    let idx = Range::new(0, length);
    let val = Range::new(Bounded::min_value(), Bounded::max_value());
    for _ in 0..(length / 16) {
      output[idx.ind_sample(&mut rng)] = val.ind_sample(&mut rng);
    }
  }
  output
}
/*
macro_rules! encode_bench {
  ($(($t: ty: $mean: expr, $std_dev: expr, $length: expr, $name: ident))*) => ($(
    #[bench]
    fn $name(b: &mut Bencher) {
      let mut bin = Unimodal::new();
      let input: Vec<$t> = rand_outliers($mean, $std_dev, $length);
      b.iter(|| {
        bin.encode(&input).unwrap();
      });
      let output = bin.decode();
      assert_eq!(input, output);
    }
  )*)
}

encode_bench!{
  (u32: 1024, 32, 15, en_u32_1024_32_15)
  (u32: 1024, 32, 16, en_u32_1024_32_16)
  (u32: 1024, 32, 31, en_u32_1024_32_31)
  (u32: 1024, 32, 32, en_u32_1024_32_32)
  (u32: 1024, 32, 127, en_u32_1024_32_127)
  (u32: 1024, 32, 128, en_u32_1024_32_128)
  (u8: 128, 16, 32768, en_u8_128_16_32768)
  (u16: 1024, 32, 32768, en_u16_1024_32_32768)
  (u32: 1024, 32, 32768, en_u32_1024_32_32768)
  (u64: 1024, 32, 32768, en_u64_1024_32_32768)
  (i32: 0, 32, 15, en_i32_0_32_15)
  (i32: 0, 32, 16, en_i32_0_32_16)
  (i32: 0, 32, 31, en_i32_0_32_31)
  (i32: 0, 32, 32, en_i32_0_32_32)
  (i32: 0, 32, 127, en_i32_0_32_127)
  (i32: 0, 32, 128, en_i32_0_32_128)
  (i8: 0, 16, 32768, en_i8_0_16_32768)
  (i16: 0, 32, 32768, en_i16_0_32_32768)
  (i32: 0, 32, 32768, en_i32_0_32_32768)
  (i64: 0, 32, 32768, en_i64_0_32_32768)
}

macro_rules! decode_bench {
  ($(($t: ty: $mean: expr, $std_dev: expr, $length: expr, $name: ident))*) => ($(
    #[bench]
    fn $name(b: &mut Bencher) {
      let mut bin = Unimodal::new();
      let input: Vec<$t> = rand_outliers($mean, $std_dev, $length);
      bin.encode(&input).unwrap();
      let mut output = vec![0; $length];
      b.iter(|| {
        bin.decode_into(&mut *output);
      });
      assert_eq!(input, output);
    }
  )*)
}

decode_bench!{
  (u32: 1024, 32, 15, de_u32_1024_32_15)
  (u32: 1024, 32, 16, de_u32_1024_32_16)
  (u32: 1024, 32, 31, de_u32_1024_32_31)
  (u32: 1024, 32, 32, de_u32_1024_32_32)
  (u32: 1024, 32, 127, de_u32_1024_32_127)
  (u32: 1024, 32, 128, de_u32_1024_32_128)
  (u8: 128, 16, 32768, de_u8_128_16_32768)
  (u16: 1024, 32, 32768, de_u16_1024_32_32768)
  (u32: 1024, 32, 32768, de_u32_1024_32_32768)
  (u64: 1024, 32, 32768, de_u64_1024_32_32768)
  (i32: 0, 32, 15, de_i32_0_32_15)
  (i32: 0, 32, 16, de_i32_0_32_16)
  (i32: 0, 32, 31, de_i32_0_32_31)
  (i32: 0, 32, 32, de_i32_0_32_32)
  (i32: 0, 32, 127, de_i32_0_32_127)
  (i32: 0, 32, 128, de_i32_0_32_128)
  (i8: 0, 16, 32768, de_i8_0_16_32768)
  (i16: 0, 32, 32768, de_i16_0_32_32768)
  (i32: 0, 32, 32768, de_i32_0_32_32768)
  (i64: 0, 32, 32768, de_i64_0_32_32768)
}

macro_rules! indexing_bench {
  ($(($t: ty: $mean: expr, $std_dev: expr, $length: expr, $idx: expr, $name: ident))*) => ($(
    #[bench]
    fn $name(b: &mut Bencher) {
      let mut bin = Unimodal::new();
      let input: Vec<$t> = rand_outliers($mean, $std_dev, $length);
      bin.encode(&input).unwrap();
      let mut v: $t = 0;
      b.iter(|| {
        v = bin.access($idx);
      });
      assert_eq!(input[$idx], v);
    }
  )*)
}

indexing_bench!{
  (u8: 128, 16, 32768, 128, idx_u8_128_16_32768_128)
  (u16: 1024, 32, 32768, 128, idx_u16_1024_32_32768_128)
  (u32: 1024, 32, 32768, 128, idx_u32_1024_32_32768_128)
  (u64: 1024, 32, 32768, 128, idx_u64_1024_32_32768_128)
  (u8: 128, 16, 32768, 32767, idx_u8_128_16_32768_32767)
  (u16: 1024, 32, 32768, 32767, idx_u16_1024_32_32768_32767)
  (u32: 1024, 32, 32768, 32767, idx_u32_1024_32_32768_32767)
  (u64: 1024, 32, 32768, 32767, idx_u64_1024_32_32768_32767)
}
*/
macro_rules! range_bench {
  ($(($t: ty: $mean: expr, $std_dev: expr, $length: expr, $lwr: expr, $upr: expr, $name: ident))*) => ($(
    #[bench]
    fn $name(b: &mut Bencher) {
      let mut bin = Unimodal::new();
      let input: Vec<$t> = rand_outliers($mean, $std_dev, $length);
      bin.encode(&input).unwrap();
      let mut vec = Vec::new();
      b.iter(|| {
        vec = bin.access($lwr..$upr);
      });
      assert_eq!(&input[$lwr..$upr], &vec[..]);
    }
  )*)
}

range_bench!{
  (u8: 128, 16, 1024, 892, 900, r_u8_0_MAX_1024_892_900)
  (u16: 1024, 32, 1024, 892, 900, r_u16_0_MAX_1024_892_900)
  (u32: 1024, 32, 1024, 892, 900, r_u32_0_MAX_1024_892_900)
  (u64: 1024, 32, 1024, 892, 900, r_u64_0_MAX_1024_892_900)
  (u8: 128, 16, 1024, 892, 900, r_i8_MIN_MAX_1024_892_900)
  (u16: 1024, 32, 1024, 892, 900, r_i16_MIN_MAX_1024_892_900)
  (u32: 1024, 32, 1024, 892, 900, r_i32_MIN_MAX_1024_892_900)
  (u64: 1024, 32, 1024, 892, 900, r_i64_MIN_MAX_1024_892_900)
}
<commit_msg>Unimodal benches consistent with others<commit_after>// Copyright 2016 Jeremy Mason
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
// http://opensource.org/licenses/MIT>, at your option. This file may not be
// copied, modified, or distributed except according to those terms.

#![feature(test)]

extern crate mayda;
extern crate num;
extern crate rand;
extern crate test;

use mayda::{Access, Encode, Unimodal};
use num::{Bounded, FromPrimitive, ToPrimitive};
use rand::distributions::{IndependentSample, Range, Normal};
use test::Bencher;

fn rand_outliers<T>(mean: T, std_dev: T, length: usize) -> Vec<T>
  where T: PartialOrd +
           Bounded +
           FromPrimitive +
           ToPrimitive +
           rand::distributions::range::SampleRange {
  let mut output: Vec<T> = Vec::with_capacity(length);
  if length > 0 {
    let val = Normal::new(mean.to_f64().unwrap(), std_dev.to_f64().unwrap());
    let mut rng = rand::thread_rng();
    for _ in 0..length {
      output.push(FromPrimitive::from_f64(val.ind_sample(&mut rng)).unwrap());
    }
    let idx = Range::new(0, length);
    let val = Range::new(Bounded::min_value(), Bounded::max_value());
    for _ in 0..(length / 16) {
      output[idx.ind_sample(&mut rng)] = val.ind_sample(&mut rng);
    }
  }
  output
}

macro_rules! encode_bench {
  ($(($t: ty: $mean: expr, $std_dev: expr, $length: expr, $name: ident))*) => ($(
    #[bench]
    fn $name(b: &mut Bencher) {
      let mut bin = Unimodal::new();
      let input: Vec<$t> = rand_outliers($mean, $std_dev, $length);
      b.iter(|| {
        bin.encode(&input).unwrap();
      });
      let output = bin.decode();
      assert_eq!(input, output);
    }
  )*)
}

encode_bench!{
  (u32: 1024, 32, 15, en_u32_1024_32_15)
  (u32: 1024, 32, 16, en_u32_1024_32_16)
  (u32: 1024, 32, 31, en_u32_1024_32_31)
  (u32: 1024, 32, 32, en_u32_1024_32_32)
  (u32: 1024, 32, 127, en_u32_1024_32_127)
  (u32: 1024, 32, 128, en_u32_1024_32_128)
  (u8: 128, 16, 32768, en_u8_128_16_32768)
  (u16: 1024, 32, 32768, en_u16_1024_32_32768)
  (u32: 1024, 32, 32768, en_u32_1024_32_32768)
  (u64: 1024, 32, 32768, en_u64_1024_32_32768)
  (i32: 0, 32, 15, en_i32_0_32_15)
  (i32: 0, 32, 16, en_i32_0_32_16)
  (i32: 0, 32, 31, en_i32_0_32_31)
  (i32: 0, 32, 32, en_i32_0_32_32)
  (i32: 0, 32, 127, en_i32_0_32_127)
  (i32: 0, 32, 128, en_i32_0_32_128)
  (i8: 0, 16, 32768, en_i8_0_16_32768)
  (i16: 0, 32, 32768, en_i16_0_32_32768)
  (i32: 0, 32, 32768, en_i32_0_32_32768)
  (i64: 0, 32, 32768, en_i64_0_32_32768)
}

macro_rules! decode_bench {
  ($(($t: ty: $mean: expr, $std_dev: expr, $length: expr, $name: ident))*) => ($(
    #[bench]
    fn $name(b: &mut Bencher) {
      let mut bin = Unimodal::new();
      let input: Vec<$t> = rand_outliers($mean, $std_dev, $length);
      bin.encode(&input).unwrap();
      let mut output = vec![0; $length];
      b.iter(|| {
        bin.decode_into(&mut *output);
      });
      assert_eq!(input, output);
    }
  )*)
}

decode_bench!{
  (u32: 1024, 32, 15, de_u32_1024_32_15)
  (u32: 1024, 32, 16, de_u32_1024_32_16)
  (u32: 1024, 32, 31, de_u32_1024_32_31)
  (u32: 1024, 32, 32, de_u32_1024_32_32)
  (u32: 1024, 32, 127, de_u32_1024_32_127)
  (u32: 1024, 32, 128, de_u32_1024_32_128)
  (u8: 128, 16, 32768, de_u8_128_16_32768)
  (u16: 1024, 32, 32768, de_u16_1024_32_32768)
  (u32: 1024, 32, 32768, de_u32_1024_32_32768)
  (u64: 1024, 32, 32768, de_u64_1024_32_32768)
  (i32: 0, 32, 15, de_i32_0_32_15)
  (i32: 0, 32, 16, de_i32_0_32_16)
  (i32: 0, 32, 31, de_i32_0_32_31)
  (i32: 0, 32, 32, de_i32_0_32_32)
  (i32: 0, 32, 127, de_i32_0_32_127)
  (i32: 0, 32, 128, de_i32_0_32_128)
  (i8: 0, 16, 32768, de_i8_0_16_32768)
  (i16: 0, 32, 32768, de_i16_0_32_32768)
  (i32: 0, 32, 32768, de_i32_0_32_32768)
  (i64: 0, 32, 32768, de_i64_0_32_32768)
}

macro_rules! indexing_bench {
  ($(($t: ty: $mean: expr, $std_dev: expr, $length: expr, $idx: expr, $name: ident))*) => ($(
    #[bench]
    fn $name(b: &mut Bencher) {
      let mut bin = Unimodal::new();
      let input: Vec<$t> = rand_outliers($mean, $std_dev, $length);
      bin.encode(&input).unwrap();
      let mut v: $t = 0;
      b.iter(|| {
        v = bin.access($idx);
      });
      assert_eq!(input[$idx], v);
    }
  )*)
}

indexing_bench!{
  (u8: 128, 16, 32768, 128, idx_u8_128_16_32768_128)
  (u16: 1024, 32, 32768, 128, idx_u16_1024_32_32768_128)
  (u32: 1024, 32, 32768, 128, idx_u32_1024_32_32768_128)
  (u64: 1024, 32, 32768, 128, idx_u64_1024_32_32768_128)
  (u8: 128, 16, 32768, 32767, idx_u8_128_16_32768_32767)
  (u16: 1024, 32, 32768, 32767, idx_u16_1024_32_32768_32767)
  (u32: 1024, 32, 32768, 32767, idx_u32_1024_32_32768_32767)
  (u64: 1024, 32, 32768, 32767, idx_u64_1024_32_32768_32767)
}

macro_rules! range_bench {
  ($(($t: ty: $mean: expr, $std_dev: expr, $length: expr, $lwr: expr, $upr: expr, $name: ident))*) => ($(
    #[bench]
    fn $name(b: &mut Bencher) {
      let mut bin = Unimodal::new();
      let input: Vec<$t> = rand_outliers($mean, $std_dev, $length);
      bin.encode(&input).unwrap();
      let mut vec = Vec::new();
      b.iter(|| {
        vec = bin.access($lwr..$upr);
      });
      assert_eq!(&input[$lwr..$upr], &vec[..]);
    }
  )*)
}

range_bench!{
  (u8: 128, 16, 1024, 892, 900, r_u8_0_MAX_1024_892_900)
  (u16: 1024, 32, 1024, 892, 900, r_u16_0_MAX_1024_892_900)
  (u32: 1024, 32, 1024, 892, 900, r_u32_0_MAX_1024_892_900)
  (u64: 1024, 32, 1024, 892, 900, r_u64_0_MAX_1024_892_900)
  (u8: 128, 16, 1024, 892, 900, r_i8_MIN_MAX_1024_892_900)
  (u16: 1024, 32, 1024, 892, 900, r_i16_MIN_MAX_1024_892_900)
  (u32: 1024, 32, 1024, 892, 900, r_i32_MIN_MAX_1024_892_900)
  (u64: 1024, 32, 1024, 892, 900, r_i64_MIN_MAX_1024_892_900)
}
<|endoftext|>


<commit_before>//! Benchmark sqrt and cbrt

#![feature(test)]

extern crate num_integer;
extern crate num_traits;
extern crate test;

use num_integer::Integer;
use num_traits::{AsPrimitive, PrimInt, WrappingAdd, WrappingMul};
use test::{black_box, Bencher};

trait BenchInteger: Integer + PrimInt + WrappingAdd + WrappingMul + 'static {}

impl<T> BenchInteger for T where T: Integer + PrimInt + WrappingAdd + WrappingMul + 'static {}

trait NaiveAverage {
    fn naive_average_floor(&self, other: &Self) -> Self;
    fn naive_average_ceil(&self, other: &Self) -> Self;
}

trait UncheckedAverage {
    fn unchecked_average_floor(&self, other: &Self) -> Self;
    fn unchecked_average_ceil(&self, other: &Self) -> Self;
}

fn bench<T, F>(b: &mut Bencher, v: &[(T, T)], f: F)
where
    T: Integer,
    F: Fn(&T, &T) -> T,
{
    b.iter(|| {
        for (x, y) in v {
            black_box(f(x, y));
        }
    });
}

// Simple PRNG so we don't have to worry about rand compatibility
fn lcg<T>(x: T) -> T
where
    u32: AsPrimitive<T>,
    T: BenchInteger,
{
    // LCG parameters from Numerical Recipes
    // (but we're applying it to arbitrary sizes)
    const LCG_A: u32 = 1664525;
    const LCG_C: u32 = 1013904223;
    x.wrapping_mul(&LCG_A.as_()).wrapping_add(&LCG_C.as_())
}

macro_rules! naive_average {
    ($T:ident) => {
        impl super::NaiveAverage for $T {
            fn naive_average_floor(&self, other: &$T) -> $T {
                match self.checked_add(*other) {
                    Some(z) => z / 2,
                    None => {
                        if self > other {
                            let diff = self - other;
                            other + diff / 2
                        } else {
                            let diff = other - self;
                            self + diff / 2
                        }
                    }
                }
            }
            fn naive_average_ceil(&self, other: &$T) -> $T {
                match self.checked_add(*other).and_then(|x| x.checked_add(1)) {
                    Some(z) => z / 2,
                    None => {
                        if self > other {
                            let diff = self - other;
                            self - diff / 2
                        } else {
                            let diff = other - self;
                            other - diff / 2
                        }
                    }
                }
            }
        }
    };
}

macro_rules! unchecked_average {
    ($T:ident) => {
        impl super::UncheckedAverage for $T {
            fn unchecked_average_floor(&self, other: &$T) -> $T {
                self.wrapping_add(*other) / 2
            }
            fn unchecked_average_ceil(&self, other: &$T) -> $T {
                (self.wrapping_add(*other) / 2).wrapping_add(1)
            }
        }
    };
}

macro_rules! bench_average {
    ($($T:ident),*) => {$(
        mod $T {
            use test::Bencher;
            use num_integer::Average;
            use UncheckedAverage;
            use NaiveAverage;

            naive_average!($T);
            unchecked_average!($T);

            const SIZE: $T = 30;

            fn overflowing() -> Vec<($T, $T)> {
                (($T::max_value()-SIZE)..$T::max_value())
                    .flat_map(|x| -> Vec<_> {
                        (($T::max_value()-100)..($T::max_value()-100+SIZE))
                            .map(|y| (x, y))
                            .collect()
                    })
                    .collect()
            }

            fn small() -> Vec<($T, $T)> {
                (0..SIZE)
                   .flat_map(|x| -> Vec<_> {(0..SIZE).map(|y| (x, y)).collect()})
                   .collect()
            }

            fn rand() -> Vec<($T, $T)> {
                small()
                    .into_iter()
                    .map(|(x, y)| (super::lcg(x), super::lcg(y)))
                    .collect()
            }

            #[bench]
            fn average_floor_small(b: &mut Bencher) {
                let v = small();
                super::bench(b, &v, |x: &$T, y: &$T| x.average_floor(y));
            }

            #[bench]
            fn average_floor_small_naive(b: &mut Bencher) {
                let v = small();
                super::bench(b, &v, |x: &$T, y: &$T| x.naive_average_floor(y));
            }

            #[bench]
            fn average_floor_small_unchecked(b: &mut Bencher) {
                let v = small();
                super::bench(b, &v, |x: &$T, y: &$T| x.unchecked_average_floor(y));
            }

            #[bench]
            fn average_floor_overflowing(b: &mut Bencher) {
                let v = overflowing();
                super::bench(b, &v, |x: &$T, y: &$T| x.average_floor(y));
            }

            #[bench]
            fn average_floor_overflowing_naive(b: &mut Bencher) {
                let v = overflowing();
                super::bench(b, &v, |x: &$T, y: &$T| x.naive_average_floor(y));
            }

            #[bench]
            fn average_floor_overflowing_unchecked(b: &mut Bencher) {
                let v = overflowing();
                super::bench(b, &v, |x: &$T, y: &$T| x.unchecked_average_floor(y));
            }

            #[bench]
            fn average_floor_rand(b: &mut Bencher) {
                let v = rand();
                super::bench(b, &v, |x: &$T, y: &$T| x.average_floor(y));
            }

            #[bench]
            fn average_floor_rand_naive(b: &mut Bencher) {
                let v = rand();
                super::bench(b, &v, |x: &$T, y: &$T| x.naive_average_floor(y));
            }

            #[bench]
            fn average_floor_rand_unchecked(b: &mut Bencher) {
                let v = rand();
                super::bench(b, &v, |x: &$T, y: &$T| x.unchecked_average_floor(y));
            }
        }
    )*}
}

bench_average!(i8, i16, i32, i64, i128, isize);
bench_average!(u8, u16, u32, u64, u128, usize);
<commit_msg>Refactor `benches/average.rs` and check results of methods that should be exact<commit_after>//! Benchmark sqrt and cbrt

#![feature(test)]

extern crate num_integer;
extern crate num_traits;
extern crate test;

use std::cmp::{min, max};
use std::fmt::Debug;
use num_integer::Integer;
use num_traits::{AsPrimitive, PrimInt, WrappingAdd, WrappingMul};
use test::{black_box, Bencher};

// --- Utilities for RNG ----------------------------------------------------

trait BenchInteger: Integer + PrimInt + WrappingAdd + WrappingMul + 'static {}

impl<T> BenchInteger for T where T: Integer + PrimInt + WrappingAdd + WrappingMul + 'static {}

// Simple PRNG so we don't have to worry about rand compatibility
fn lcg<T>(x: T) -> T
where
    u32: AsPrimitive<T>,
    T: BenchInteger,
{
    // LCG parameters from Numerical Recipes
    // (but we're applying it to arbitrary sizes)
    const LCG_A: u32 = 1664525;
    const LCG_C: u32 = 1013904223;
    x.wrapping_mul(&LCG_A.as_()).wrapping_add(&LCG_C.as_())
}

// --- Alt. Implementations -------------------------------------------------

trait NaiveAverage {
    fn naive_average_ceil(&self, other: &Self) -> Self;
    fn naive_average_floor(&self, other: &Self) -> Self;
}

trait UncheckedAverage {
    fn unchecked_average_ceil(&self, other: &Self) -> Self;
    fn unchecked_average_floor(&self, other: &Self) -> Self;
}

trait ModuloAverage {
    fn modulo_average_ceil(&self, other: &Self) -> Self;
    fn modulo_average_floor(&self, other: &Self) -> Self;
}

macro_rules! naive_average {
    ($T:ident) => {
        impl super::NaiveAverage for $T {
            fn naive_average_floor(&self, other: &$T) -> $T {
                match self.checked_add(*other) {
                    Some(z) => z.div_floor(&2),
                    None => {
                        if self > other {
                            let diff = self - other;
                            other + diff.div_floor(&2)
                        } else {
                            let diff = other - self;
                            self + diff.div_floor(&2)
                        }
                    }
                }
            }
            fn naive_average_ceil(&self, other: &$T) -> $T {
                match self.checked_add(*other).and_then(|x| x.checked_add(1)) {
                    Some(z) => z.div_ceil(&2),
                    None => {
                        if self > other {
                            let diff = self - other;
                            self - diff / 2
                        } else {
                            let diff = other - self;
                            other - diff / 2
                        }
                    }
                }
            }
        }
    };
}

macro_rules! unchecked_average {
    ($T:ident) => {
        impl super::UncheckedAverage for $T {
            fn unchecked_average_floor(&self, other: &$T) -> $T {
                self.wrapping_add(*other) / 2
            }
            fn unchecked_average_ceil(&self, other: &$T) -> $T {
                (self.wrapping_add(*other) / 2).wrapping_add(1)
            }
        }
    };
}

macro_rules! modulo_average {
    ($T:ident) => {
        impl super::ModuloAverage for $T {
            fn modulo_average_ceil(&self, other: &$T) -> $T {
                let (q1, r1) = self.div_mod_floor(&2);
                let (q2, r2) = other.div_mod_floor(&2);
                q1 + q2 + (r1 * r2)
            }
            fn modulo_average_floor(&self, other: &$T) -> $T {
                let (q1, r1) = self.div_mod_floor(&2);
                let (q2, r2) = other.div_mod_floor(&2);
                q1 + q2 + (r1 * r2)
            }
        }
    };
}

// --- Bench functions ------------------------------------------------------

fn bench_unchecked<T, F>(b: &mut Bencher, v: &[(T, T)], f: F)
where
    T: Integer + Debug + Copy,
    F: Fn(&T, &T) -> T,
{
    b.iter(|| {
        for (x, y) in v {
            black_box(f(x, y));
        }
    });
}

fn bench_ceil<T, F>(b: &mut Bencher, v: &[(T, T)], f: F)
where
    T: Integer + Debug + Copy,
    F: Fn(&T, &T) -> T,
{
    for &(i, j) in v {
        let rt = f(&i, &j);
        let (a, b) = (min(i, j), max(i, j));
        if (b - a).is_even() {
            assert_eq!(rt - a, b - rt);
        } else {
            assert_eq!(rt - a, b - rt + T::one());
        }
    }
    bench_unchecked(b, v, f);
}

fn bench_floor<T, F>(b: &mut Bencher, v: &[(T, T)], f: F)
where
    T: Integer + Debug + Copy,
    F: Fn(&T, &T) -> T,
{
    for &(i, j) in v {
        let rt = f(&i, &j);
        let (a, b) = (min(i, j), max(i, j));
        println!("{:?} + {:?} / 2 = {:?}", a, b, rt);
        // if both number are the same sign, check rt is in the middle
        if (a < T::zero()) == (b < T::zero()) {
            if (b - a).is_even() {
                assert_eq!(rt - a, b - rt);
            } else {
                assert_eq!(rt - a + T::one(), b - rt);
            }
        // if both number have a different sign,
        } else {
            if (a + b).is_even() {
                assert_eq!(rt, (a + b) / (T::one() + T::one()))
            } else {
                assert_eq!(rt, (a + b - T::one()) / (T::one() + T::one()))
            }
        }
    }
    bench_unchecked(b, v, f);
}

// --- Bench implementation -------------------------------------------------

macro_rules! bench_average {
    ($($T:ident),*) => {$(
        mod $T {
            use test::Bencher;
            use num_integer::{Average, Integer};
            use super::{UncheckedAverage, NaiveAverage, ModuloAverage};
            use super::{bench_ceil, bench_floor, bench_unchecked};

            naive_average!($T);
            unchecked_average!($T);
            modulo_average!($T);

            const SIZE: $T = 30;

            fn overflowing() -> Vec<($T, $T)> {
                (($T::max_value()-SIZE)..$T::max_value())
                    .flat_map(|x| -> Vec<_> {
                        (($T::max_value()-100)..($T::max_value()-100+SIZE))
                            .map(|y| (x, y))
                            .collect()
                    })
                    .collect()
            }

            fn small() -> Vec<($T, $T)> {
                (0..SIZE)
                   .flat_map(|x| -> Vec<_> {(0..SIZE).map(|y| (x, y)).collect()})
                   .collect()
            }

            fn rand() -> Vec<($T, $T)> {
                small()
                    .into_iter()
                    .map(|(x, y)| (super::lcg(x), super::lcg(y)))
                    .collect()
            }

            mod floor {

                use super::*;

                mod small {

                    use super::*;

                    #[bench]
                    fn optimized(b: &mut Bencher) {
                        let v = small();
                        bench_floor(b, &v, |x: &$T, y: &$T| x.average_floor(y));
                    }

                    #[bench]
                    fn naive(b: &mut Bencher) {
                        let v = small();
                        bench_floor(b, &v, |x: &$T, y: &$T| x.naive_average_floor(y));
                    }

                    #[bench]
                    fn unchecked(b: &mut Bencher) {
                        let v = small();
                        bench_unchecked(b, &v, |x: &$T, y: &$T| x.unchecked_average_floor(y));
                    }

                    #[bench]
                    fn modulo(b: &mut Bencher) {
                        let v = small();
                        bench_floor(b, &v, |x: &$T, y: &$T| x.modulo_average_floor(y));
                    }
                }

                mod overflowing {

                    use super::*;

                    #[bench]
                    fn optimized(b: &mut Bencher) {
                        let v = overflowing();
                        bench_floor(b, &v, |x: &$T, y: &$T| x.average_floor(y));
                    }

                    #[bench]
                    fn naive(b: &mut Bencher) {
                        let v = overflowing();
                        bench_floor(b, &v, |x: &$T, y: &$T| x.naive_average_floor(y));
                    }

                    #[bench]
                    fn unchecked(b: &mut Bencher) {
                        let v = overflowing();
                        bench_unchecked(b, &v, |x: &$T, y: &$T| x.unchecked_average_floor(y));
                    }

                    #[bench]
                    fn modulo(b: &mut Bencher) {
                        let v = overflowing();
                        bench_floor(b, &v, |x: &$T, y: &$T| x.modulo_average_floor(y));
                    }
                }

                mod rand {

                    use super::*;

                    #[bench]
                    fn optimized(b: &mut Bencher) {
                        let v = rand();
                        bench_floor(b, &v, |x: &$T, y: &$T| x.average_floor(y));
                    }

                    #[bench]
                    fn naive(b: &mut Bencher) {
                        let v = rand();
                        bench_floor(b, &v, |x: &$T, y: &$T| x.naive_average_floor(y));
                    }

                    #[bench]
                    fn unchecked(b: &mut Bencher) {
                        let v = rand();
                        bench_unchecked(b, &v, |x: &$T, y: &$T| x.unchecked_average_floor(y));
                    }

                    #[bench]
                    fn modulo(b: &mut Bencher) {
                        let v = rand();
                        bench_floor(b, &v, |x: &$T, y: &$T| x.modulo_average_floor(y));
                    }
                }

            }

        }
    )*}
}

bench_average!(i8, i16, i32, i64, i128, isize);
bench_average!(u8, u16, u32, u64, u128, usize);
<|endoftext|>


<commit_before>// =================================================================
//
//                           * WARNING *
//
//                    This file is generated!
//
//  Changes made to this file will be overwritten. If changes are
//  required to the generated code, the service_crategen project
//  must be updated to generate the changes.
//
// =================================================================

use std::error::Error;
use std::fmt;
use std::io;

#[allow(warnings)]
use futures::future;
use futures::Future;
use rusoto_core::region;
use rusoto_core::request::{BufferedHttpResponse, DispatchSignedRequest};
use rusoto_core::{Client, RusotoFuture};

use rusoto_core::credential::{CredentialsError, ProvideAwsCredentials};
use rusoto_core::request::HttpDispatchError;

use rusoto_core::signature::SignedRequest;
use serde_json;
use serde_json::from_slice;
use serde_json::Value as SerdeJsonValue;
#[derive(Default, Debug, Clone, PartialEq, Serialize)]
pub struct InvokeEndpointInput {
    ///
The desired MIME type of the inference in the response.

    #[serde(rename = "Accept")]
    #[serde(skip_serializing_if = "Option::is_none")]
    pub accept: Option<String>,
    ///
Provides input data, in the format specified in the ContentType request header. Amazon SageMaker passes all of the data in the body to the model.

    #[serde(rename = "Body")]
    #[serde(
        deserialize_with = "::rusoto_core::serialization::SerdeBlob::deserialize_blob",
        serialize_with = "::rusoto_core::serialization::SerdeBlob::serialize_blob",
        default
    )]
    pub body: Vec<u8>,
    ///
The MIME type of the input data in the request body.

    #[serde(rename = "ContentType")]
    #[serde(skip_serializing_if = "Option::is_none")]
    pub content_type: Option<String>,
    ///
The name of the endpoint that you specified when you created the endpoint using the CreateEndpoint API.

    #[serde(rename = "EndpointName")]
    pub endpoint_name: String,
}

#[derive(Default, Debug, Clone, PartialEq)]
pub struct InvokeEndpointOutput {
    ///
Includes the inference provided by the model.

    pub body: Vec<u8>,
    ///
The MIME type of the inference returned in the response body.

    pub content_type: Option<String>,
    ///
Identifies the production variant that was invoked.

    pub invoked_production_variant: Option<String>,
}

/// Errors returned by InvokeEndpoint
#[derive(Debug, PartialEq)]
pub enum InvokeEndpointError {
    ///
 Internal failure occurred.

    InternalFailure(String),
    ///
 Model (owned by the customer in the container) returned an error 500.

    ModelError(String),
    ///
 Service is unavailable. Try your call again.

    ServiceUnavailable(String),
    ///
 Inspect your request and try again.

    ValidationError(String),
    /// An error occurred dispatching the HTTP request
    HttpDispatch(HttpDispatchError),
    /// An error was encountered with AWS credentials.
    Credentials(CredentialsError),
    /// A validation error occurred.  Details from AWS are provided.
    Validation(String),
    /// An error occurred parsing the response payload.
    ParseError(String),
    /// An unknown error occurred.  The raw HTTP response is provided.
    Unknown(BufferedHttpResponse),
}

impl InvokeEndpointError {
    // see boto RestJSONParser impl for parsing errors
    // https://github.com/boto/botocore/blob/4dff78c840403d1d17db9b3f800b20d3bd9fbf9f/botocore/parsers.py#L838-L850
    pub fn from_response(res: BufferedHttpResponse) -> InvokeEndpointError {
        if let Ok(json) = from_slice::<SerdeJsonValue>(&res.body) {
            let error_type = match res.headers.get("x-amzn-errortype") {
                Some(raw_error_type) => raw_error_type
                    .split(':')
                    .next()
                    .unwrap_or_else(|| "Unknown"),
                _ => json
                    .get("code")
                    .or_else(|| json.get("Code"))
                    .and_then(|c| c.as_str())
                    .unwrap_or_else(|| "Unknown"),
            };

            // message can come in either "message" or "Message"
            // see boto BaseJSONParser impl for parsing message
            // https://github.com/boto/botocore/blob/4dff78c840403d1d17db9b3f800b20d3bd9fbf9f/botocore/parsers.py#L595-L598
            let error_message = json
                .get("message")
                .or_else(|| json.get("Message"))
                .and_then(|m| m.as_str())
                .unwrap_or("");

            match error_type {
                "InternalFailure" => {
                    return InvokeEndpointError::InternalFailure(String::from(error_message))
                }
                "ModelError" => return InvokeEndpointError::ModelError(String::from(error_message)),
                "ServiceUnavailable" => {
                    return InvokeEndpointError::ServiceUnavailable(String::from(error_message))
                }
                "ValidationError" => {
                    return InvokeEndpointError::ValidationError(String::from(error_message))
                }
                "ValidationException" => {
                    return InvokeEndpointError::Validation(error_message.to_string())
                }
                _ => {}
            }
        }
        return InvokeEndpointError::Unknown(res);
    }
}

impl From<serde_json::error::Error> for InvokeEndpointError {
    fn from(err: serde_json::error::Error) -> InvokeEndpointError {
        InvokeEndpointError::ParseError(err.description().to_string())
    }
}
impl From<CredentialsError> for InvokeEndpointError {
    fn from(err: CredentialsError) -> InvokeEndpointError {
        InvokeEndpointError::Credentials(err)
    }
}
impl From<HttpDispatchError> for InvokeEndpointError {
    fn from(err: HttpDispatchError) -> InvokeEndpointError {
        InvokeEndpointError::HttpDispatch(err)
    }
}
impl From<io::Error> for InvokeEndpointError {
    fn from(err: io::Error) -> InvokeEndpointError {
        InvokeEndpointError::HttpDispatch(HttpDispatchError::from(err))
    }
}
impl fmt::Display for InvokeEndpointError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.description())
    }
}
impl Error for InvokeEndpointError {
    fn description(&self) -> &str {
        match *self {
            InvokeEndpointError::InternalFailure(ref cause) => cause,
            InvokeEndpointError::ModelError(ref cause) => cause,
            InvokeEndpointError::ServiceUnavailable(ref cause) => cause,
            InvokeEndpointError::ValidationError(ref cause) => cause,
            InvokeEndpointError::Validation(ref cause) => cause,
            InvokeEndpointError::Credentials(ref err) => err.description(),
            InvokeEndpointError::HttpDispatch(ref dispatch_error) => dispatch_error.description(),
            InvokeEndpointError::ParseError(ref cause) => cause,
            InvokeEndpointError::Unknown(_) => "unknown error",
        }
    }
}
/// Trait representing the capabilities of the Amazon SageMaker Runtime API. Amazon SageMaker Runtime clients implement this trait.
pub trait SageMakerRuntime {
    ///
After you deploy a model into production using Amazon SageMaker hosting services, your client applications use this API to get inferences from the model hosted at the specified endpoint.

For an overview of Amazon SageMaker, see How It Works

 Amazon SageMaker strips all POST headers except those supported by the API. Amazon SageMaker might add additional headers. You should not rely on the behavior of headers outside those enumerated in the request syntax.

    fn invoke_endpoint(
        &self,
        input: InvokeEndpointInput,
    ) -> RusotoFuture<InvokeEndpointOutput, InvokeEndpointError>;
}
/// A client for the Amazon SageMaker Runtime API.
pub struct SageMakerRuntimeClient {
    client: Client,
    region: region::Region,
}

impl SageMakerRuntimeClient {
    /// Creates a client backed by the default tokio event loop.
    ///
    /// The client will use the default credentials provider and tls client.
    pub fn new(region: region::Region) -> SageMakerRuntimeClient {
        SageMakerRuntimeClient {
            client: Client::shared(),
            region: region,
        }
    }

    pub fn new_with
(
        request_dispatcher: D,
        credentials_provider: P,
        region: region::Region,
    ) -> SageMakerRuntimeClient
    where
        P: ProvideAwsCredentials + Send + Sync + 'static,
        P::Future: Send,
        D: DispatchSignedRequest + Send + Sync + 'static,
        D::Future: Send,
    {
        SageMakerRuntimeClient {
            client: Client::new_with(credentials_provider, request_dispatcher),
            region: region,
        }
    }
}

impl SageMakerRuntime for SageMakerRuntimeClient {
    ///
After you deploy a model into production using Amazon SageMaker hosting services, your client applications use this API to get inferences from the model hosted at the specified endpoint.

For an overview of Amazon SageMaker, see How It Works

 Amazon SageMaker strips all POST headers except those supported by the API. Amazon SageMaker might add additional headers. You should not rely on the behavior of headers outside those enumerated in the request syntax.

    fn invoke_endpoint(
        &self,
        input: InvokeEndpointInput,
    ) -> RusotoFuture<InvokeEndpointOutput, InvokeEndpointError> {
        let request_uri = format!(
            "/endpoints/{endpoint_name}/invocations",
            endpoint_name = input.endpoint_name
        );

        let mut request = SignedRequest::new("POST", "sagemaker", &self.region, &request_uri);
        request.set_content_type("application/x-amz-json-1.1".to_owned());

        request.set_endpoint_prefix("runtime.sagemaker".to_string());
        let encoded = Some(input.body.to_owned());
        request.set_payload(encoded);

        if let Some(ref accept) = input.accept {
            request.add_header("Accept", &accept.to_string());
        }

        if let Some(ref content_type) = input.content_type {
            request.add_header("Content-Type", &content_type.to_string());
        }

        self.client.sign_and_dispatch(request, |response| {
            if response.status.is_success() {
                Box::new(response.buffer().from_err().map(|response| {
                    let mut result = InvokeEndpointOutput::default();
                    result.body = response.body;

                    if let Some(content_type) = response.headers.get("Content-Type") {
                        let value = content_type.to_owned();
                        result.content_type = Some(value)
                    };
                    if let Some(invoked_production_variant) =
                        response.headers.get("x-Amzn-Invoked-Production-Variant")
                    {
                        let value = invoked_production_variant.to_owned();
                        result.invoked_production_variant = Some(value)
                    };

                    result
                }))
            } else {
                Box::new(
                    response
                        .buffer()
                        .from_err()
                        .and_then(|response| Err(InvokeEndpointError::from_response(response))),
                )
            }
        })
    }
}

#[cfg(test)]
mod protocol_tests {}
<commit_msg>gen: Fix Content-Type header in SageMaker Runtime<commit_after>// =================================================================
//
//                           * WARNING *
//
//                    This file is generated!
//
//  Changes made to this file will be overwritten. If changes are
//  required to the generated code, the service_crategen project
//  must be updated to generate the changes.
//
// =================================================================

use std::error::Error;
use std::fmt;
use std::io;

#[allow(warnings)]
use futures::future;
use futures::Future;
use rusoto_core::region;
use rusoto_core::request::{BufferedHttpResponse, DispatchSignedRequest};
use rusoto_core::{Client, RusotoFuture};

use rusoto_core::credential::{CredentialsError, ProvideAwsCredentials};
use rusoto_core::request::HttpDispatchError;

use rusoto_core::signature::SignedRequest;
use serde_json;
use serde_json::from_slice;
use serde_json::Value as SerdeJsonValue;
#[derive(Default, Debug, Clone, PartialEq, Serialize)]
pub struct InvokeEndpointInput {
    ///
The desired MIME type of the inference in the response.

    #[serde(rename = "Accept")]
    #[serde(skip_serializing_if = "Option::is_none")]
    pub accept: Option<String>,
    ///
Provides input data, in the format specified in the ContentType request header. Amazon SageMaker passes all of the data in the body to the model.

    #[serde(rename = "Body")]
    #[serde(
        deserialize_with = "::rusoto_core::serialization::SerdeBlob::deserialize_blob",
        serialize_with = "::rusoto_core::serialization::SerdeBlob::serialize_blob",
        default
    )]
    pub body: Vec<u8>,
    ///
The MIME type of the input data in the request body.

    #[serde(rename = "ContentType")]
    #[serde(skip_serializing_if = "Option::is_none")]
    pub content_type: Option<String>,
    ///
The name of the endpoint that you specified when you created the endpoint using the CreateEndpoint API.

    #[serde(rename = "EndpointName")]
    pub endpoint_name: String,
}

#[derive(Default, Debug, Clone, PartialEq)]
pub struct InvokeEndpointOutput {
    ///
Includes the inference provided by the model.

    pub body: Vec<u8>,
    ///
The MIME type of the inference returned in the response body.

    pub content_type: Option<String>,
    ///
Identifies the production variant that was invoked.

    pub invoked_production_variant: Option<String>,
}

/// Errors returned by InvokeEndpoint
#[derive(Debug, PartialEq)]
pub enum InvokeEndpointError {
    ///
 Internal failure occurred.

    InternalFailure(String),
    ///
 Model (owned by the customer in the container) returned an error 500.

    ModelError(String),
    ///
 Service is unavailable. Try your call again.

    ServiceUnavailable(String),
    ///
 Inspect your request and try again.

    ValidationError(String),
    /// An error occurred dispatching the HTTP request
    HttpDispatch(HttpDispatchError),
    /// An error was encountered with AWS credentials.
    Credentials(CredentialsError),
    /// A validation error occurred.  Details from AWS are provided.
    Validation(String),
    /// An error occurred parsing the response payload.
    ParseError(String),
    /// An unknown error occurred.  The raw HTTP response is provided.
    Unknown(BufferedHttpResponse),
}

impl InvokeEndpointError {
    // see boto RestJSONParser impl for parsing errors
    // https://github.com/boto/botocore/blob/4dff78c840403d1d17db9b3f800b20d3bd9fbf9f/botocore/parsers.py#L838-L850
    pub fn from_response(res: BufferedHttpResponse) -> InvokeEndpointError {
        if let Ok(json) = from_slice::<SerdeJsonValue>(&res.body) {
            let error_type = match res.headers.get("x-amzn-errortype") {
                Some(raw_error_type) => raw_error_type
                    .split(':')
                    .next()
                    .unwrap_or_else(|| "Unknown"),
                _ => json
                    .get("code")
                    .or_else(|| json.get("Code"))
                    .and_then(|c| c.as_str())
                    .unwrap_or_else(|| "Unknown"),
            };

            // message can come in either "message" or "Message"
            // see boto BaseJSONParser impl for parsing message
            // https://github.com/boto/botocore/blob/4dff78c840403d1d17db9b3f800b20d3bd9fbf9f/botocore/parsers.py#L595-L598
            let error_message = json
                .get("message")
                .or_else(|| json.get("Message"))
                .and_then(|m| m.as_str())
                .unwrap_or("");

            match error_type {
                "InternalFailure" => {
                    return InvokeEndpointError::InternalFailure(String::from(error_message));
                }
                "ModelError" => return InvokeEndpointError::ModelError(String::from(error_message)),
                "ServiceUnavailable" => {
                    return InvokeEndpointError::ServiceUnavailable(String::from(error_message));
                }
                "ValidationError" => {
                    return InvokeEndpointError::ValidationError(String::from(error_message));
                }
                "ValidationException" => {
                    return InvokeEndpointError::Validation(error_message.to_string());
                }
                _ => {}
            }
        }
        return InvokeEndpointError::Unknown(res);
    }
}

impl From<serde_json::error::Error> for InvokeEndpointError {
    fn from(err: serde_json::error::Error) -> InvokeEndpointError {
        InvokeEndpointError::ParseError(err.description().to_string())
    }
}
impl From<CredentialsError> for InvokeEndpointError {
    fn from(err: CredentialsError) -> InvokeEndpointError {
        InvokeEndpointError::Credentials(err)
    }
}
impl From<HttpDispatchError> for InvokeEndpointError {
    fn from(err: HttpDispatchError) -> InvokeEndpointError {
        InvokeEndpointError::HttpDispatch(err)
    }
}
impl From<io::Error> for InvokeEndpointError {
    fn from(err: io::Error) -> InvokeEndpointError {
        InvokeEndpointError::HttpDispatch(HttpDispatchError::from(err))
    }
}
impl fmt::Display for InvokeEndpointError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.description())
    }
}
impl Error for InvokeEndpointError {
    fn description(&self) -> &str {
        match *self {
            InvokeEndpointError::InternalFailure(ref cause) => cause,
            InvokeEndpointError::ModelError(ref cause) => cause,
            InvokeEndpointError::ServiceUnavailable(ref cause) => cause,
            InvokeEndpointError::ValidationError(ref cause) => cause,
            InvokeEndpointError::Validation(ref cause) => cause,
            InvokeEndpointError::Credentials(ref err) => err.description(),
            InvokeEndpointError::HttpDispatch(ref dispatch_error) => dispatch_error.description(),
            InvokeEndpointError::ParseError(ref cause) => cause,
            InvokeEndpointError::Unknown(_) => "unknown error",
        }
    }
}
/// Trait representing the capabilities of the Amazon SageMaker Runtime API. Amazon SageMaker Runtime clients implement this trait.
pub trait SageMakerRuntime {
    ///
After you deploy a model into production using Amazon SageMaker hosting services, your client applications use this API to get inferences from the model hosted at the specified endpoint.

For an overview of Amazon SageMaker, see How It Works

 Amazon SageMaker strips all POST headers except those supported by the API. Amazon SageMaker might add additional headers. You should not rely on the behavior of headers outside those enumerated in the request syntax.

    fn invoke_endpoint(
        &self,
        input: InvokeEndpointInput,
    ) -> RusotoFuture<InvokeEndpointOutput, InvokeEndpointError>;
}
/// A client for the Amazon SageMaker Runtime API.
pub struct SageMakerRuntimeClient {
    client: Client,
    region: region::Region,
}

impl SageMakerRuntimeClient {
    /// Creates a client backed by the default tokio event loop.
    ///
    /// The client will use the default credentials provider and tls client.
    pub fn new(region: region::Region) -> SageMakerRuntimeClient {
        SageMakerRuntimeClient {
            client: Client::shared(),
            region: region,
        }
    }

    pub fn new_with
(
        request_dispatcher: D,
        credentials_provider: P,
        region: region::Region,
    ) -> SageMakerRuntimeClient
    where
        P: ProvideAwsCredentials + Send + Sync + 'static,
        P::Future: Send,
        D: DispatchSignedRequest + Send + Sync + 'static,
        D::Future: Send,
    {
        SageMakerRuntimeClient {
            client: Client::new_with(credentials_provider, request_dispatcher),
            region: region,
        }
    }
}

impl SageMakerRuntime for SageMakerRuntimeClient {
    ///
After you deploy a model into production using Amazon SageMaker hosting services, your client applications use this API to get inferences from the model hosted at the specified endpoint.

For an overview of Amazon SageMaker, see How It Works

 Amazon SageMaker strips all POST headers except those supported by the API. Amazon SageMaker might add additional headers. You should not rely on the behavior of headers outside those enumerated in the request syntax.

    fn invoke_endpoint(
        &self,
        input: InvokeEndpointInput,
    ) -> RusotoFuture<InvokeEndpointOutput, InvokeEndpointError> {
        let request_uri = format!(
            "/endpoints/{endpoint_name}/invocations",
            endpoint_name = input.endpoint_name
        );

        let mut request = SignedRequest::new("POST", "sagemaker", &self.region, &request_uri);
        if input.content_type.is_none() {
            request.set_content_type("application/x-amz-json-1.1".to_owned());
        }

        request.set_endpoint_prefix("runtime.sagemaker".to_string());
        let encoded = Some(input.body.to_owned());
        request.set_payload(encoded);

        if let Some(ref accept) = input.accept {
            request.add_header("Accept", &accept.to_string());
        }

        if let Some(ref content_type) = input.content_type {
            request.add_header("Content-Type", &content_type.to_string());
        }

        self.client.sign_and_dispatch(request, |response| {
            if response.status.is_success() {
                Box::new(response.buffer().from_err().map(|response| {
                    let mut result = InvokeEndpointOutput::default();
                    result.body = response.body;

                    if let Some(content_type) = response.headers.get("Content-Type") {
                        let value = content_type.to_owned();
                        result.content_type = Some(value)
                    };
                    if let Some(invoked_production_variant) =
                        response.headers.get("x-Amzn-Invoked-Production-Variant")
                    {
                        let value = invoked_production_variant.to_owned();
                        result.invoked_production_variant = Some(value)
                    };

                    result
                }))
            } else {
                Box::new(
                    response
                        .buffer()
                        .from_err()
                        .and_then(|response| Err(InvokeEndpointError::from_response(response))),
                )
            }
        })
    }
}

#[cfg(test)]
mod protocol_tests {}
<|endoftext|>


<commit_before>/*
 * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
 * SPDX-License-Identifier: Apache-2.0.
 */

//! Use lazy_static and AsyncOnce to allow on-demand access to a global config & client.
//! Configs and clients are both cheap to clone (they are Tower stacks).
//! This example will log "Initializing SdkConfig" and "Initializing S3 Client" once each.
//! The requests then use clones of the globally initialized values.

use async_once::AsyncOnce;
use aws_config::SdkConfig;
use aws_sdk_s3::Client;
use lazy_static::lazy_static;
use tracing::{error, info};

lazy_static! {
    static ref SDK_CONFIG: AsyncOnce<SdkConfig> = AsyncOnce::new(async {
        info!("Initializing SdkConfig");
        aws_config::load_from_env().await
    });
    static ref S3_CLIENT: AsyncOnce<Client> = AsyncOnce::new(async {
        info!("Initializing S3 Client");
        let config = SDK_CONFIG.get().await;
        aws_sdk_s3::Client::new(config)
    });
}

async fn request(name: &str) {
    info!(name, "Starting request");

    // Get a clone of the client.
    let client = S3_CLIENT.get().await.clone();
    info!(name, "Client retrieved");

    // Use our clone to make a request.
    match client.list_buckets().send().await {
        Ok(response) => {
            info!(
                name,
                len = response.buckets().unwrap_or_default().len(),
                "Got buckets"
            )
        }
        Err(err) => {
            error!(name, %err, "Had an error");
        }
    }
}

#[tokio::main]
async fn main() {
    // Basic logging. Always log at info.
    std::env::set_var("RUST_LOG", "info");
    tracing_subscriber::fmt::init();

    // Run the request three times, but initialization only happens once.
    tokio::join!(request("a"), request("b"), request("c"),);
}
<commit_msg>Editorial<commit_after>/*
 * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
 * SPDX-License-Identifier: Apache-2.0.
 */

//! Use lazy_static and AsyncOnce to allow on demand access to a global config and client.
//! Configs and clients are both cheap to clone (they are Tower stacks).
//! This example will log "Initializing SdkConfig" and "Initializing S3 Client" once each.
//! The requests then use clones of the globally initialized values.

use async_once::AsyncOnce;
use aws_config::SdkConfig;
use aws_sdk_s3::Client;
use lazy_static::lazy_static;
use tracing::{error, info};

lazy_static! {
    static ref SDK_CONFIG: AsyncOnce<SdkConfig> = AsyncOnce::new(async {
        info!("Initializing SdkConfig");
        aws_config::load_from_env().await
    });
    static ref S3_CLIENT: AsyncOnce<Client> = AsyncOnce::new(async {
        info!("Initializing S3 Client");
        let config = SDK_CONFIG.get().await;
        aws_sdk_s3::Client::new(config)
    });
}

async fn request(name: &str) {
    info!(name, "Starting request");

    // Get a clone of the client.
    let client = S3_CLIENT.get().await.clone();
    info!(name, "Client retrieved");

    // Use our clone to make a request.
    match client.list_buckets().send().await {
        Ok(response) => {
            info!(
                name,
                len = response.buckets().unwrap_or_default().len(),
                "Got buckets"
            )
        }
        Err(err) => {
            error!(name, %err, "Had an error");
        }
    }
}

#[tokio::main]
async fn main() {
    // Basic logging. Always log at info.
    std::env::set_var("RUST_LOG", "info");
    tracing_subscriber::fmt::init();

    // Run the request three times, but initialization only happens once.
    tokio::join!(request("a"), request("b"), request("c"),);
}
<|endoftext|>