<commit_before>use std::fmt;

#[derive(Debug)]
pub enum BittrexOrderType {
    Sell,
    Buy,
    Both,
}

#[derive(Serialize, Deserialize)]
pub struct BittrexAPIResult<T> {
    pub success: bool,
    pub message: String,
    pub result: Option<T>,
}

#[derive(Serialize, Deserialize)]
pub struct BittrexAPIVecResult<T> {
    pub success: bool,
    pub message: String,
    pub result: Option<Vec<T>>,
}

#[derive(Serialize, Deserialize)]
pub struct BittrexUuid {
    #[serde(rename = "uuid")]
    pub uuid: String,
}

#[derive(Serialize, Deserialize)]
pub struct BittrexAddress {
    #[serde(rename = "Currency")]
    pub currency: String,
    #[serde(rename = "Address")]
    pub address: String,
}

#[derive(Serialize, Deserialize)]
pub struct BittrexCurrency {
    #[serde(rename = "Currency")]
    pub currency: String,
    #[serde(rename = "CurrencyLong")]
    pub currency_long: String,
    #[serde(rename = "MinConfirmation")]
    pub min_confirmation: u32,
    #[serde(rename = "TxFee")]
    pub tx_fee: f32,
    #[serde(rename = "IsActive")]
    pub is_active: bool,
    #[serde(rename = "CoinType")]
    pub coin_type: Option<String>,
    #[serde(rename = "BaseAddress")]
    pub base_address: Option<String>,
    #[serde(rename = "Notice")]
    pub notice: Option<String>,
}

#[derive(Serialize, Deserialize)]
pub struct BittrexMarket {
    #[serde(rename = "MarketCurrency")]
    pub market_currency: String,
    #[serde(rename = "BaseCurrency")]
    pub base_currency: String,
    #[serde(rename = "MarketCurrencyLong")]
    pub market_currency_long: String,
    #[serde(rename = "BaseCurrencyLong")]
    pub base_currency_long: String,
    #[serde(rename = "MinTradeSize")]
    pub min_trade_size: f32,
    #[serde(rename = "MarketName")]
    pub market_name: String,
    #[serde(rename = "IsActive")]
    pub is_active: bool,
    #[serde(rename = "Created")]
    pub created: String,
}

#[derive(Serialize, Deserialize)]
pub struct BittrexMarketSummary {
    #[serde(rename = "MarketName")]
    pub market_name: String,
    #[serde(rename = "High")]
    pub high: f32,
    #[serde(rename = "Low")]
    pub low: f32,
    #[serde(rename = "Volume")]
    pub volume: f64,
    #[serde(rename = "Last")]
    pub last: f64,
    #[serde(rename = "BaseVolume")]
    pub base_volume: f64,
    #[serde(rename = "TimeStamp")]
    pub time_stamp: String,
    #[serde(rename = "Bid")]
    pub bid: f32,
    #[serde(rename = "Ask")]
    pub ask: f32,
    #[serde(rename = "OpenBuyOrders")]
    pub open_buy_orders: u32,
    #[serde(rename = "OpenSellOrders")]
    pub open_sell_orders: u32,
    #[serde(rename = "PrevDay")]
    pub prev_day: f32,
    #[serde(rename = "Created")]
    pub created: String,
    #[serde(rename = "DisplayMarketName")]
    pub display_market_name: Option<String>,
}

#[derive(Serialize, Deserialize)]
pub struct BittrexTicker {
    #[serde(rename = "Ask")]
    pub ask: f32,
    #[serde(rename = "Bid")]
    pub bid: f32,
    #[serde(rename = "Last")]
    pub last: f32,
}

#[derive(Serialize, Deserialize)]
pub struct BittrexPublicOrderBook {
    #[serde(rename = "buy")]
    pub buy: Vec<BittrexPublicOrder>,
    #[serde(rename = "sell")]
    pub sell: Vec<BittrexPublicOrder>,
}

#[derive(Serialize, Deserialize)]
pub struct BittrexPublicOrder {
    #[serde(rename = "Quantity")]
    pub quantity: f32,
    #[serde(rename = "Rate")]
    pub rate: f32,
}

#[derive(Serialize, Deserialize)]
pub struct BittrexTrade {
    #[serde(rename = "Id")]
    pub id: u32,
    #[serde(rename = "TimeStamp")]
    pub time_stamp: String,
    #[serde(rename = "Quantity")]
    pub quantity: f32,
    #[serde(rename = "Price")]
    pub price: f32,
    #[serde(rename = "Total")]
    pub total: f32,
    #[serde(rename = "FillType")]
    pub fill_type: String,
    #[serde(rename = "OrderType")]
    pub order_type: String,
}

#[derive(Serialize, Deserialize)]
pub struct BittrexOpenOrder {
    #[serde(rename = "Uuid")]
    pub uuid: Option<String>,
    #[serde(rename = "OrderUuid")]
    pub order_uuid: String,
    #[serde(rename = "Exchange")]
    pub exchange: String,
    #[serde(rename = "OrderType")]
    pub order_type: String,
    #[serde(rename = "Quantity")]
    pub quantity: f32,
    #[serde(rename = "QuantityRemaining")]
    pub quantity_remaining: f32,
    #[serde(rename = "Limit")]
    pub limit: f32,
    #[serde(rename = "CommissionPaid")]
    pub comission_paid: f32,
    #[serde(rename = "Price")]
    pub price: f32,
    #[serde(rename = "PricePerUnit")]
    pub price_per_unit: Option<f32>,
    #[serde(rename = "Opened")]
    pub opened: String,
    #[serde(rename = "Closed")]
    pub closed: Option<String>,
    #[serde(rename = "CancelInitiated")]
    pub cancel_initiated: bool,
    #[serde(rename = "ImmediateOrCancel")]
    pub immediate_or_cancel: bool,
    #[serde(rename = "IsConditional")]
    pub is_conditional: bool,
    #[serde(rename = "Condition")]
    pub condition: Option<String>,
    #[serde(rename = "ConditionalTarget")]
    pub conditional_target: Option<String>,
}

#[derive(Serialize, Deserialize)]
pub struct BittrexHistoryOrder {
    #[serde(rename = "OrderUuid")]
    pub order_uuid: String,
    #[serde(rename = "Exchange")]
    pub exchange: String,
    #[serde(rename = "TimeStamp")]
    pub time_stamp: String,
    #[serde(rename = "OrderType")]
    pub order_type: String,
    #[serde(rename = "Quantity")]
    pub quantity: f32,
    #[serde(rename = "QuantityRemaining")]
    pub quantity_remaining: f32,
    #[serde(rename = "Limit")]
    pub limit: f32,
    #[serde(rename = "Commission")]
    pub comission: f32,
    #[serde(rename = "Price")]
    pub price: f32,
    #[serde(rename = "PricePerUnit")]
    pub price_per_unit: Option<f32>,
    #[serde(rename = "ImmediateOrCancel")]
    pub immediate_or_cancel: bool,
    #[serde(rename = "IsConditional")]
    pub is_conditional: bool,
    #[serde(rename = "Condition")]
    pub condition: Option<String>,
    #[serde(rename = "ConditionalTarget")]
    pub conditional_target: Option<String>,
}

#[derive(Serialize, Deserialize)]
pub struct BittrexOrder {
    #[serde(rename = "AccountId")]
    pub account_id: Option<String>,
    #[serde(rename = "OrderUuid")]
    pub order_uuid: String,
    #[serde(rename = "Exchange")]
    pub exchange: String,
    #[serde(rename = "Type")]
    pub order_type: String,
    #[serde(rename = "Quantity")]
    pub quantity: f32,
    #[serde(rename = "QuantityRemaining")]
    pub quantity_remaining: f32,
    #[serde(rename = "Limit")]
    pub limit: f32,
    #[serde(rename = "Reserved")]
    pub reserved: f32,
    #[serde(rename = "ReserveRemaining")]
    pub reserve_remaining: f32,
    #[serde(rename = "CommissionReserved")]
    pub commission_reserved: f32,
    #[serde(rename = "CommissionReserveRemaining")]
    pub commission_reserve_remaining: f32,
    #[serde(rename = "CommissionPaid")]
    pub comission_paid: f32,
    #[serde(rename = "Price")]
    pub price: f32,
    #[serde(rename = "PricePerUnit")]
    pub price_per_unit: Option<f32>,
    #[serde(rename = "Opened")]
    pub opened: String,
    #[serde(rename = "Closed")]
    pub closed: Option<String>,
    #[serde(rename = "IsOpen")]
    pub is_open: bool,
    #[serde(rename = "Sentinel")]
    pub sentinel: String,
    #[serde(rename = "CancelInitiated")]
    pub cancel_initiated: bool,
    #[serde(rename = "ImmediateOrCancel")]
    pub immediate_or_cancel: bool,
    #[serde(rename = "IsConditional")]
    pub is_conditional: bool,
    #[serde(rename = "Condition")]
    pub condition: Option<String>,
    #[serde(rename = "ConditionalTarget")]
    pub conditional_target: Option<String>,
}

#[derive(Serialize, Deserialize)]
pub struct BittrexTransaction {
    #[serde(rename = "PaymentUuid")]
    pub payment_uuid: String,
    #[serde(rename = "Currency")]
    pub currency: String,
    #[serde(rename = "Amount")]
    pub amount: f32,
    #[serde(rename = "Address")]
    pub address: String,
    #[serde(rename = "Opened")]
    pub opened: String,
    #[serde(rename = "Authorized")]
    pub authorized: bool,
    #[serde(rename = "PendingPayment")]
    pub pending_payment: bool,
    #[serde(rename = "TxCost")]
    pub tx_cost: f32,
    #[serde(rename = "TxId")]
    pub tx_id: Option<String>,
    #[serde(rename = "Canceled")]
    pub canceled: bool,
    #[serde(rename = "InvalidAddress")]
    pub invalid_address: bool,
}

#[derive(Serialize, Deserialize)]
pub struct BittrexBalance {
    #[serde(rename = "Currency")]
    pub currency: String,
    #[serde(rename = "Balance")]
    pub balance: f32,
    #[serde(rename = "Available")]
    pub available: f32,
    #[serde(rename = "Pending")]
    pub pending: f32,
    #[serde(rename = "CryptoAddress")]
    pub crypto_address: String,
    #[serde(rename = "Requested")]
    pub requested: bool,
    #[serde(rename = "Uuid")]
    pub uuid: Option<String>,
}

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

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

impl fmt::Display for BittrexAddress {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "Currency: {} (Address: {})", self.currency, self.address)
    }
}

impl fmt::Display for BittrexCurrency {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(
            f,
            "{} (Min. Confirmations: {}, Tx Fee: {})",
            self.currency,
            self.min_confirmation,
            self.tx_fee
        )
    }
}

impl fmt::Display for BittrexMarket {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(
            f,
            "{} (Min. Trade Size: {})",
            self.market_name,
            self.min_trade_size
        )
    }
}

impl fmt::Display for BittrexMarketSummary {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(
            f,
            "{} (High: {}, Low: {}, Volume: {})",
            self.market_name,
            self.high,
            self.low,
            self.volume
        )
    }
}

impl fmt::Display for BittrexTicker {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(
            f,
            "(Ask: {}, Bid: {}, Last: {})",
            self.ask,
            self.bid,
            self.last
        )
    }
}

impl fmt::Display for BittrexPublicOrderBook {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(
            f,
            "(Buy Quantity: {}, Sell Quantity: {})",
            self.buy.len(),
            self.sell.len()
        )
    }
}

impl fmt::Display for BittrexPublicOrder {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "(Quantity: {}, Rate: {})", self.quantity, self.rate)
    }
}

impl fmt::Display for BittrexTrade {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(
            f,
            "ID: {} (Quantity: {}, Price: {}, Total: {})",
            self.id,
            self.quantity,
            self.price,
            self.total
        )
    }
}

impl fmt::Display for BittrexOpenOrder {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(
            f,
            "Uuid: {} (Exchange: {}, Order Type: {}, Quantity: {}, Limit: {})",
            self.order_uuid,
            self.exchange,
            self.order_type,
            self.quantity,
            self.limit
        )
    }
}

impl fmt::Display for BittrexHistoryOrder {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(
            f,
            "Uuid: {} (Exchange: {}, Type: {}, Quantity: {}, Limit: {})",
            self.order_uuid,
            self.exchange,
            self.order_type,
            self.quantity,
            self.limit
        )
    }
}

impl fmt::Display for BittrexOrder {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(
            f,
            "Uuid: {} (Exchange: {}, Type: {}, Quantity: {}, Limit: {}, Is Open: {})",
            self.order_uuid,
            self.exchange,
            self.order_type,
            self.quantity,
            self.limit,
            self.is_open
        )
    }
}

impl fmt::Display for BittrexTransaction {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(
            f,
            "Uuid: {} (Currency: {}, Ammount: {}, Address: {}, Pending: {})",
            self.payment_uuid,
            self.currency,
            self.amount,
            self.address,
            self.pending_payment
        )
    }
}

impl fmt::Display for BittrexBalance {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(
            f,
            "Currency: {} (Balance: {}, Available: {}, Pending: {})",
            self.currency,
            self.balance,
            self.available,
            self.pending
        )
    }
}
<commit_msg>removed deprecated fields<commit_after>use std::fmt;

#[derive(Debug)]
pub enum BittrexOrderType {
    Sell,
    Buy,
    Both,
}

#[derive(Serialize, Deserialize)]
pub struct BittrexAPIResult<T> {
    pub success: bool,
    pub message: String,
    pub result: Option<T>,
}

#[derive(Serialize, Deserialize)]
pub struct BittrexAPIVecResult<T> {
    pub success: bool,
    pub message: String,
    pub result: Option<Vec<T>>,
}

#[derive(Serialize, Deserialize)]
pub struct BittrexUuid {
    #[serde(rename = "uuid")]
    pub uuid: String,
}

#[derive(Serialize, Deserialize)]
pub struct BittrexAddress {
    #[serde(rename = "Currency")]
    pub currency: String,
    #[serde(rename = "Address")]
    pub address: String,
}

#[derive(Serialize, Deserialize)]
pub struct BittrexCurrency {
    #[serde(rename = "Currency")]
    pub currency: String,
    #[serde(rename = "CurrencyLong")]
    pub currency_long: String,
    #[serde(rename = "MinConfirmation")]
    pub min_confirmation: u32,
    #[serde(rename = "TxFee")]
    pub tx_fee: f32,
    #[serde(rename = "IsActive")]
    pub is_active: bool,
    #[serde(rename = "CoinType")]
    pub coin_type: Option<String>,
    #[serde(rename = "BaseAddress")]
    pub base_address: Option<String>,
    #[serde(rename = "Notice")]
    pub notice: Option<String>,
}

#[derive(Serialize, Deserialize)]
pub struct BittrexMarket {
    #[serde(rename = "MarketCurrency")]
    pub market_currency: String,
    #[serde(rename = "BaseCurrency")]
    pub base_currency: String,
    #[serde(rename = "MarketCurrencyLong")]
    pub market_currency_long: String,
    #[serde(rename = "BaseCurrencyLong")]
    pub base_currency_long: String,
    #[serde(rename = "MinTradeSize")]
    pub min_trade_size: f32,
    #[serde(rename = "MarketName")]
    pub market_name: String,
    #[serde(rename = "IsActive")]
    pub is_active: bool,
    #[serde(rename = "Created")]
    pub created: String,
}

#[derive(Serialize, Deserialize)]
pub struct BittrexMarketSummary {
    #[serde(rename = "MarketName")]
    pub market_name: String,
    #[serde(rename = "High")]
    pub high: f32,
    #[serde(rename = "Low")]
    pub low: f32,
    #[serde(rename = "Volume")]
    pub volume: f64,
    #[serde(rename = "Last")]
    pub last: f64,
    #[serde(rename = "BaseVolume")]
    pub base_volume: f64,
    #[serde(rename = "TimeStamp")]
    pub time_stamp: String,
    #[serde(rename = "Bid")]
    pub bid: f32,
    #[serde(rename = "Ask")]
    pub ask: f32,
    #[serde(rename = "OpenBuyOrders")]
    pub open_buy_orders: u32,
    #[serde(rename = "OpenSellOrders")]
    pub open_sell_orders: u32,
    #[serde(rename = "PrevDay")]
    pub prev_day: f32,
    #[serde(rename = "Created")]
    pub created: String,
    #[serde(rename = "DisplayMarketName")]
    pub display_market_name: Option<String>,
}

#[derive(Serialize, Deserialize)]
pub struct BittrexTicker {
    #[serde(rename = "Ask")]
    pub ask: f32,
    #[serde(rename = "Bid")]
    pub bid: f32,
    #[serde(rename = "Last")]
    pub last: f32,
}

#[derive(Serialize, Deserialize)]
pub struct BittrexPublicOrderBook {
    #[serde(rename = "buy")]
    pub buy: Vec<BittrexPublicOrder>,
    #[serde(rename = "sell")]
    pub sell: Vec<BittrexPublicOrder>,
}

#[derive(Serialize, Deserialize)]
pub struct BittrexPublicOrder {
    #[serde(rename = "Quantity")]
    pub quantity: f32,
    #[serde(rename = "Rate")]
    pub rate: f32,
}

#[derive(Serialize, Deserialize)]
pub struct BittrexTrade {
    #[serde(rename = "Id")]
    pub id: u32,
    #[serde(rename = "TimeStamp")]
    pub time_stamp: String,
    #[serde(rename = "Quantity")]
    pub quantity: f32,
    #[serde(rename = "Price")]
    pub price: f32,
    #[serde(rename = "Total")]
    pub total: f32,
    #[serde(rename = "FillType")]
    pub fill_type: String,
    #[serde(rename = "OrderType")]
    pub order_type: String,
}

#[derive(Serialize, Deserialize)]
pub struct BittrexOpenOrder {
    #[serde(rename = "Uuid")]
    pub uuid: Option<String>,
    #[serde(rename = "OrderUuid")]
    pub order_uuid: String,
    #[serde(rename = "Exchange")]
    pub exchange: String,
    #[serde(rename = "OrderType")]
    pub order_type: String,
    #[serde(rename = "Quantity")]
    pub quantity: f32,
    #[serde(rename = "QuantityRemaining")]
    pub quantity_remaining: f32,
    #[serde(rename = "Limit")]
    pub limit: f32,
    #[serde(rename = "CommissionPaid")]
    pub comission_paid: f32,
    #[serde(rename = "Price")]
    pub price: f32,
    #[serde(rename = "PricePerUnit")]
    pub price_per_unit: Option<f32>,
    #[serde(rename = "Opened")]
    pub opened: String,
    #[serde(rename = "Closed")]
    pub closed: Option<String>,
    #[serde(rename = "CancelInitiated")]
    pub cancel_initiated: bool,
    #[serde(rename = "ImmediateOrCancel")]
    pub immediate_or_cancel: bool,
    #[serde(rename = "IsConditional")]
    pub is_conditional: bool,
    #[serde(rename = "Condition")]
    pub condition: Option<String>,
    #[serde(rename = "ConditionalTarget")]
    pub conditional_target: Option<String>,
}

#[derive(Serialize, Deserialize)]
pub struct BittrexHistoryOrder {
    #[serde(rename = "OrderUuid")]
    pub order_uuid: String,
    #[serde(rename = "Exchange")]
    pub exchange: String,
    #[serde(rename = "TimeStamp")]
    pub time_stamp: String,
    #[serde(rename = "OrderType")]
    pub order_type: String,
    #[serde(rename = "Quantity")]
    pub quantity: f32,
    #[serde(rename = "QuantityRemaining")]
    pub quantity_remaining: f32,
    #[serde(rename = "Limit")]
    pub limit: f32,
    #[serde(rename = "Commission")]
    pub comission: f32,
    #[serde(rename = "Price")]
    pub price: f32,
    #[serde(rename = "PricePerUnit")]
    pub price_per_unit: Option<f32>,
    #[serde(rename = "ImmediateOrCancel")]
    pub immediate_or_cancel: bool,
    #[serde(rename = "IsConditional")]
    pub is_conditional: bool,
    #[serde(rename = "Condition")]
    pub condition: Option<String>,
    #[serde(rename = "ConditionalTarget")]
    pub conditional_target: Option<String>,
}

#[derive(Serialize, Deserialize)]
pub struct BittrexOrder {
    #[serde(rename = "AccountId")]
    pub account_id: Option<String>,
    #[serde(rename = "OrderUuid")]
    pub order_uuid: String,
    #[serde(rename = "Exchange")]
    pub exchange: String,
    #[serde(rename = "Type")]
    pub order_type: String,
    #[serde(rename = "Quantity")]
    pub quantity: f32,
    #[serde(rename = "QuantityRemaining")]
    pub quantity_remaining: f32,
    #[serde(rename = "Limit")]
    pub limit: f32,
    #[serde(rename = "Reserved")]
    pub reserved: f32,
    #[serde(rename = "ReserveRemaining")]
    pub reserve_remaining: f32,
    #[serde(rename = "CommissionReserved")]
    pub commission_reserved: f32,
    #[serde(rename = "CommissionReserveRemaining")]
    pub commission_reserve_remaining: f32,
    #[serde(rename = "CommissionPaid")]
    pub comission_paid: f32,
    #[serde(rename = "Price")]
    pub price: f32,
    #[serde(rename = "PricePerUnit")]
    pub price_per_unit: Option<f32>,
    #[serde(rename = "Opened")]
    pub opened: String,
    #[serde(rename = "Closed")]
    pub closed: Option<String>,
    #[serde(rename = "IsOpen")]
    pub is_open: bool,
    #[serde(rename = "Sentinel")]
    pub sentinel: String,
    #[serde(rename = "CancelInitiated")]
    pub cancel_initiated: bool,
    #[serde(rename = "ImmediateOrCancel")]
    pub immediate_or_cancel: bool,
    #[serde(rename = "IsConditional")]
    pub is_conditional: bool,
    #[serde(rename = "Condition")]
    pub condition: Option<String>,
    #[serde(rename = "ConditionalTarget")]
    pub conditional_target: Option<String>,
}

#[derive(Serialize, Deserialize)]
pub struct BittrexTransaction {
    #[serde(rename = "PaymentUuid")]
    pub payment_uuid: String,
    #[serde(rename = "Currency")]
    pub currency: String,
    #[serde(rename = "Amount")]
    pub amount: f32,
    #[serde(rename = "Address")]
    pub address: String,
    #[serde(rename = "Opened")]
    pub opened: String,
    #[serde(rename = "Authorized")]
    pub authorized: bool,
    #[serde(rename = "PendingPayment")]
    pub pending_payment: bool,
    #[serde(rename = "TxCost")]
    pub tx_cost: f32,
    #[serde(rename = "TxId")]
    pub tx_id: Option<String>,
    #[serde(rename = "Canceled")]
    pub canceled: bool,
    #[serde(rename = "InvalidAddress")]
    pub invalid_address: bool,
}

#[derive(Serialize, Deserialize)]
pub struct BittrexBalance {
    #[serde(rename = "Currency")]
    pub currency: String,
    #[serde(rename = "Balance")]
    pub balance: f32,
    #[serde(rename = "Available")]
    pub available: f32,
    #[serde(rename = "Pending")]
    pub pending: f32,
    #[serde(rename = "CryptoAddress")]
    pub crypto_address: String,
}

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

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

impl fmt::Display for BittrexAddress {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "Currency: {} (Address: {})", self.currency, self.address)
    }
}

impl fmt::Display for BittrexCurrency {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(
            f,
            "{} (Min. Confirmations: {}, Tx Fee: {})",
            self.currency,
            self.min_confirmation,
            self.tx_fee
        )
    }
}

impl fmt::Display for BittrexMarket {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(
            f,
            "{} (Min. Trade Size: {})",
            self.market_name,
            self.min_trade_size
        )
    }
}

impl fmt::Display for BittrexMarketSummary {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(
            f,
            "{} (High: {}, Low: {}, Volume: {})",
            self.market_name,
            self.high,
            self.low,
            self.volume
        )
    }
}

impl fmt::Display for BittrexTicker {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(
            f,
            "(Ask: {}, Bid: {}, Last: {})",
            self.ask,
            self.bid,
            self.last
        )
    }
}

impl fmt::Display for BittrexPublicOrderBook {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(
            f,
            "(Buy Quantity: {}, Sell Quantity: {})",
            self.buy.len(),
            self.sell.len()
        )
    }
}

impl fmt::Display for BittrexPublicOrder {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "(Quantity: {}, Rate: {})", self.quantity, self.rate)
    }
}

impl fmt::Display for BittrexTrade {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(
            f,
            "ID: {} (Quantity: {}, Price: {}, Total: {})",
            self.id,
            self.quantity,
            self.price,
            self.total
        )
    }
}

impl fmt::Display for BittrexOpenOrder {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(
            f,
            "Uuid: {} (Exchange: {}, Order Type: {}, Quantity: {}, Limit: {})",
            self.order_uuid,
            self.exchange,
            self.order_type,
            self.quantity,
            self.limit
        )
    }
}

impl fmt::Display for BittrexHistoryOrder {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(
            f,
            "Uuid: {} (Exchange: {}, Type: {}, Quantity: {}, Limit: {})",
            self.order_uuid,
            self.exchange,
            self.order_type,
            self.quantity,
            self.limit
        )
    }
}

impl fmt::Display for BittrexOrder {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(
            f,
            "Uuid: {} (Exchange: {}, Type: {}, Quantity: {}, Limit: {}, Is Open: {})",
            self.order_uuid,
            self.exchange,
            self.order_type,
            self.quantity,
            self.limit,
            self.is_open
        )
    }
}

impl fmt::Display for BittrexTransaction {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(
            f,
            "Uuid: {} (Currency: {}, Ammount: {}, Address: {}, Pending: {})",
            self.payment_uuid,
            self.currency,
            self.amount,
            self.address,
            self.pending_payment
        )
    }
}

impl fmt::Display for BittrexBalance {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(
            f,
            "Currency: {} (Balance: {}, Available: {}, Pending: {})",
            self.currency,
            self.balance,
            self.available,
            self.pending
        )
    }
}
<|endoftext|>


<commit_before>extern crate urbit;

use urbit::{ream, unpack_pill};

#[test]
#[ignore] // FIXME
fn test_parse_hoon_hoon() {
    use std::fs::File;
    use std::io::prelude::*;

    let mut hoon_src = Vec::new();
    File::open("assets/hoon.hoon").unwrap().read_to_end(&mut hoon_src).unwrap();

    let mut twig_pill = Vec::new();
    File::open("assets/hoontwig.pill").unwrap().read_to_end(&mut twig_pill).unwrap();
    let twig = unpack_pill(twig_pill).unwrap();

    let parse = ream(&hoon_src);
    assert!(parse.is_ok(), "Failed to parse hoon.hoon");

    let parse_noun = parse.unwrap().1.to_noun();
    assert!(parse_noun == twig, "Parse result does not match reference version");
}
<commit_msg>Use baked-in assets in test crate<commit_after>extern crate urbit;

use urbit::{ream, unpack_pill};

const HOON_SRC: &'static str = include_str!("assets/hoon.hoon");
const HOON_TWIG: &'static [u8] = include_bytes!("assets/hoontwig.pill");

#[test]
#[ignore] // TODO
fn test_parse_hoon_hoon() {
    let twig = unpack_pill(HOON_TWIG.to_vec()).unwrap();

    let parse = ream(HOON_SRC.as_bytes());
    assert!(parse.is_ok(), "Failed to parse hoon.hoon");

    let parse_noun = parse.unwrap().1.to_noun();
    assert!(parse_noun == twig, "Parse result does not match reference version");
}
<|endoftext|>


<commit_before>use std::ptr::null;
use libc::{c_int, c_char, c_double};
use std::c_str::ToCStr;
use std::sync::{StaticMutex, MUTEX_INIT};
use utils::_string;

#[link(name="gdal")]
extern {
    fn OGRRegisterAll();
    fn OGROpen(pszName: *const c_char, bUpdate: c_int, pahDriverList: *const ()) -> *const ();
    fn OGR_DS_GetLayerCount(hDS: *const ()) -> c_int;
    fn OGR_DS_Destroy(hDataSource: *const ());
    fn OGR_DS_GetLayer(hDS: *const (), iLayer: c_int) -> *const ();
    fn OGR_L_GetLayerDefn(hLayer: *const ()) -> *const ();
    fn OGR_L_GetNextFeature(hLayer: *const ()) -> *const ();
    fn OGR_FD_GetFieldCount(hDefn: *const ()) -> c_int;
    fn OGR_FD_GetFieldDefn(hDefn: *const (), iField: c_int) -> *const ();
    fn OGR_F_GetFieldIndex(hFeat: *const (), pszName: *const c_char) -> c_int;
    fn OGR_F_GetFieldDefnRef(hFeat: *const (), i: c_int) -> *const ();
    fn OGR_F_GetFieldAsString(hFeat: *const (), iField: c_int) -> *const c_char;
    fn OGR_F_GetFieldAsDouble(hFeat: *const (), iField: c_int) -> c_double;
    fn OGR_F_GetGeometryRef(hFeat: *const ()) -> *const ();
    fn OGR_F_Destroy(hFeat: *const ());
    fn OGR_G_ExportToWkt(hGeom: *const (), ppszSrcText: *const *const c_char) -> c_int;
    fn OGR_G_ExportToJson(hGeometry: *const ()) -> *const c_char;
    fn OGR_Fld_GetNameRef(hDefn: *const ()) -> *const c_char;
    fn OGR_Fld_GetType(hDefn: *const ()) -> c_int;
    fn OGRFree(ptr: *const ());
    fn VSIFree(ptr: *const ());
}

const OFT_REAL:             c_int = 2;
const OFT_STRING:           c_int = 4;

static mut LOCK: StaticMutex = MUTEX_INIT;
static mut registered_drivers: bool = false;

fn register_drivers() {
    unsafe {
        let _g = LOCK.lock();
        if ! registered_drivers {
            OGRRegisterAll();
            registered_drivers = true;
        }
    }
}

pub struct VectorDataset {
    c_dataset: *const (),
}

impl VectorDataset {
    pub fn count(&self) -> isize {
        return unsafe { OGR_DS_GetLayerCount(self.c_dataset) } as isize;
    }

    pub fn layer<'a>(&'a self, idx: isize) -> Option<Layer<'a>> {
        let c_layer = unsafe { OGR_DS_GetLayer(self.c_dataset, idx as c_int) };
        return match c_layer.is_null() {
            true  => None,
            false => Some(Layer{_vector_dataset: self, c_layer: c_layer}),
        };
    }
}

impl Drop for VectorDataset {
    fn drop(&mut self) {
        unsafe { OGR_DS_Destroy(self.c_dataset); }
    }
}

pub struct Layer<'a> {
    _vector_dataset: &'a VectorDataset,
    c_layer: *const (),
}

impl<'a> Layer<'a> {
    pub fn fields(&'a self) -> FieldIterator<'a> {
        let c_feature_defn = unsafe { OGR_L_GetLayerDefn(self.c_layer) };
        let total = unsafe { OGR_FD_GetFieldCount(c_feature_defn) } as isize;
        return FieldIterator{
            layer: self,
            c_feature_defn: c_feature_defn,
            next_id: 0,
            total: total
        };
    }

    pub fn features(&'a self) -> FeatureIterator<'a> {
        return FeatureIterator{layer: self};
    }
}

pub struct FieldIterator<'a> {
    layer: &'a Layer<'a>,
    c_feature_defn: *const (),
    next_id: isize,
    total: isize,
}

impl<'a> Iterator for FieldIterator<'a> {
    type Item = Field<'a>;

    #[inline]
    fn next(&mut self) -> Option<Field<'a>> {
        if self.next_id == self.total {
            return None;
        }
        let field = Field{
            _layer: self.layer,
            c_field_defn: unsafe { OGR_FD_GetFieldDefn(
                self.c_feature_defn,
                self.next_id as c_int
            ) }
        };
        self.next_id += 1;
        return Some(field);
    }
}

pub struct Field<'a> {
    _layer: &'a Layer<'a>,
    c_field_defn: *const (),
}

impl<'a> Field<'a> {
    pub fn name(&'a self) -> String {
        let rv = unsafe { OGR_Fld_GetNameRef(self.c_field_defn) };
        return _string(rv);
    }
}

pub struct FeatureIterator<'a> {
    layer: &'a Layer<'a>,
}

impl<'a> Iterator for FeatureIterator<'a> {
    type Item = Feature<'a>;

    #[inline]
    fn next(&mut self) -> Option<Feature<'a>> {
        let c_feature = unsafe { OGR_L_GetNextFeature(self.layer.c_layer) };
        return match c_feature.is_null() {
            true  => None,
            false => Some(Feature{_layer: self.layer, c_feature: c_feature}),
        };
    }
}

pub struct Feature<'a> {
    _layer: &'a Layer<'a>,
    c_feature: *const (),
}

impl<'a> Feature<'a> {
    pub fn field(&self, name: &str) -> Option<FieldValue> {
        return name.with_c_str(|c_name| unsafe {
            let field_id = OGR_F_GetFieldIndex(self.c_feature, c_name);
            if field_id == -1 {
                return None;
            }
            let field_defn = OGR_F_GetFieldDefnRef(self.c_feature, field_id);
            let field_type = OGR_Fld_GetType(field_defn);
            return match field_type {
                OFT_STRING => {
                    let rv = OGR_F_GetFieldAsString(self.c_feature, field_id);
                    return Some(FieldValue::StringValue(_string(rv)));
                },
                OFT_REAL => {
                    let rv = OGR_F_GetFieldAsDouble(self.c_feature, field_id);
                    return Some(FieldValue::RealValue(rv as f64));
                },
                _ => panic!("Unknown field type {}", field_type)
            }
        });
    }

    pub fn wkt(&self) -> String {
        unsafe {
            let c_geom = OGR_F_GetGeometryRef(self.c_feature);
            let c_wkt: *const c_char = null();
            OGR_G_ExportToWkt(c_geom, &c_wkt);
            let wkt = _string(c_wkt);
            OGRFree(c_wkt as *const ());
            return wkt;
        }
    }

    pub fn json(&self) -> String {
        unsafe {
            let c_geom = OGR_F_GetGeometryRef(self.c_feature);
            let c_json = OGR_G_ExportToJson(c_geom);
            let json = _string(c_json);
            VSIFree(c_json as *const ());
            return json;
        }
    }
}

#[unsafe_destructor]
impl<'a> Drop for Feature<'a> {
    fn drop(&mut self) {
        unsafe { OGR_F_Destroy(self.c_feature); }
    }
}

pub fn open(path: &Path) -> Option<VectorDataset> {
    register_drivers();
    let filename = path.as_str().unwrap();
    let c_dataset = filename.with_c_str(|c_filename| {
        return unsafe { OGROpen(c_filename, 0, null()) };
    });
    return match c_dataset.is_null() {
        true  => None,
        false => Some(VectorDataset{c_dataset: c_dataset}),
    };
}

pub enum FieldValue {
    StringValue(String),
    RealValue(f64),
}

impl FieldValue {
    pub fn as_string(self) -> String {
        match self {
            FieldValue::StringValue(rv) => rv,
            _ => panic!("not a StringValue")
        }
    }

    pub fn as_real(self) -> f64 {
        match self {
            FieldValue::RealValue(rv) => rv,
            _ => panic!("not a RealValue")
        }
    }
}

#[cfg(test)]
mod test {
    use std::path::Path;
    use super::{Feature, FeatureIterator, open};

    fn fixtures() -> Path {
        return Path::new(file!()).dir_path().dir_path().join("fixtures");
    }

    fn assert_almost_eq(a: f64, b: f64) {
        let f: f64 = a / b;
        assert!(f < 1.00001);
        assert!(f > 0.99999);
    }

    #[test]
    fn test_layer_count() {
        let ds = open(&fixtures().join("roads.geojson")).unwrap();
        assert_eq!(ds.count(), 1);
    }

    fn with_features(fixture: &str, f: F) where F: Fn(FeatureIterator) {
        let ds = open(&fixtures().join(fixture)).unwrap();
        let layer = ds.layer(0).unwrap();
        f(layer.features());
    }

    fn with_first_feature(fixture: &str, f: F) where F: Fn(Feature) {
        with_features(fixture, |mut features| f(features.next().unwrap()));
    }

    #[test]
    fn test_iterate_features() {
        with_features("roads.geojson", |features| {
            let feature_vec: Vec<Feature> = features.collect();
            assert_eq!(feature_vec.len(), 21);
        });
    }

    #[test]
    fn test_string_field() {
        with_features("roads.geojson", |mut features| {
            let feature = features.next().unwrap();
            assert_eq!(feature.field("highway")
                              .unwrap()
                              .as_string(),
                       "footway".to_string());
            assert_eq!(
                features.filter(|field| {
                    let highway = field.field("highway")
                                       .unwrap()
                                       .as_string();
                    highway == "residential".to_string() })
                    .count(),
                2);
        });
    }

    #[test]
    fn test_float_field() {
        with_first_feature("roads.geojson", |feature| {
            assert_almost_eq(
                feature.field("sort_key")
                       .unwrap()
                       .as_real(),
                -9.0
            );
        });
    }

    #[test]
    fn test_missing_field() {
        with_first_feature("roads.geojson", |feature| {
            assert!(feature.field("no such field").is_none());
        });
    }

    #[test]
    fn test_wkt() {
        with_first_feature("roads.geojson", |feature| {
            let wkt = feature.wkt();
            let wkt_ok = format!("{}{}",
                "LINESTRING (26.1019276 44.4302748,",
                "26.1019382 44.4303191,26.1020002 44.4304202)"
                ).to_string();
            assert_eq!(wkt, wkt_ok);
        });
    }

    #[test]
    fn test_json() {
        with_first_feature("roads.geojson", |feature| {
            let json = feature.json();
            let json_ok = format!("{}{}{}{}",
                "{ \"type\": \"LineString\", \"coordinates\": [ ",
                "[ 26.1019276, 44.4302748 ], ",
                "[ 26.1019382, 44.4303191 ], ",
                "[ 26.1020002, 44.4304202 ] ] }"
                ).to_string();
            assert_eq!(json, json_ok);
        });
    }

    #[test]
    fn test_schema() {
        let ds = open(&fixtures().join("roads.geojson")).unwrap();
        let layer = ds.layer(0).unwrap();
        let name_list: Vec<String> = layer
            .fields()
            .map(|f| f.name())
            .collect();
        let ok_names: Vec<String> = vec!(
            "kind", "sort_key", "is_link", "is_tunnel",
            "is_bridge", "railway", "highway")
            .iter().map(|s| s.to_string()).collect();
        assert_eq!(name_list, ok_names);
    }
}
<commit_msg>fixup! 892e13e<commit_after>use std::ptr::null;
use libc::{c_int, c_char, c_double};
use std::c_str::ToCStr;
use std::sync::{StaticMutex, MUTEX_INIT};
use utils::_string;

#[link(name="gdal")]
extern {
    fn OGRRegisterAll();
    fn OGROpen(pszName: *const c_char, bUpdate: c_int, pahDriverList: *const ()) -> *const ();
    fn OGR_DS_GetLayerCount(hDS: *const ()) -> c_int;
    fn OGR_DS_Destroy(hDataSource: *const ());
    fn OGR_DS_GetLayer(hDS: *const (), iLayer: c_int) -> *const ();
    fn OGR_L_GetLayerDefn(hLayer: *const ()) -> *const ();
    fn OGR_L_GetNextFeature(hLayer: *const ()) -> *const ();
    fn OGR_FD_GetFieldCount(hDefn: *const ()) -> c_int;
    fn OGR_FD_GetFieldDefn(hDefn: *const (), iField: c_int) -> *const ();
    fn OGR_F_GetFieldIndex(hFeat: *const (), pszName: *const c_char) -> c_int;
    fn OGR_F_GetFieldDefnRef(hFeat: *const (), i: c_int) -> *const ();
    fn OGR_F_GetFieldAsString(hFeat: *const (), iField: c_int) -> *const c_char;
    fn OGR_F_GetFieldAsDouble(hFeat: *const (), iField: c_int) -> c_double;
    fn OGR_F_GetGeometryRef(hFeat: *const ()) -> *const ();
    fn OGR_F_Destroy(hFeat: *const ());
    fn OGR_G_ExportToWkt(hGeom: *const (), ppszSrcText: *const *const c_char) -> c_int;
    fn OGR_G_ExportToJson(hGeometry: *const ()) -> *const c_char;
    fn OGR_Fld_GetNameRef(hDefn: *const ()) -> *const c_char;
    fn OGR_Fld_GetType(hDefn: *const ()) -> c_int;
    fn OGRFree(ptr: *const ());
    fn VSIFree(ptr: *const ());
}

const OFT_REAL:             c_int = 2;
const OFT_STRING:           c_int = 4;

static mut LOCK: StaticMutex = MUTEX_INIT;
static mut registered_drivers: bool = false;

fn register_drivers() {
    unsafe {
        let _g = LOCK.lock();
        if ! registered_drivers {
            OGRRegisterAll();
            registered_drivers = true;
        }
    }
}

pub struct VectorDataset {
    c_dataset: *const (),
}

impl VectorDataset {
    pub fn count(&self) -> isize {
        return unsafe { OGR_DS_GetLayerCount(self.c_dataset) } as isize;
    }

    pub fn layer<'a>(&'a self, idx: isize) -> Option<Layer<'a>> {
        let c_layer = unsafe { OGR_DS_GetLayer(self.c_dataset, idx as c_int) };
        return match c_layer.is_null() {
            true  => None,
            false => Some(Layer{_vector_dataset: self, c_layer: c_layer}),
        };
    }
}

impl Drop for VectorDataset {
    fn drop(&mut self) {
        unsafe { OGR_DS_Destroy(self.c_dataset); }
    }
}

pub struct Layer<'a> {
    _vector_dataset: &'a VectorDataset,
    c_layer: *const (),
}

impl<'a> Layer<'a> {
    pub fn fields(&'a self) -> FieldIterator<'a> {
        let c_feature_defn = unsafe { OGR_L_GetLayerDefn(self.c_layer) };
        let total = unsafe { OGR_FD_GetFieldCount(c_feature_defn) } as isize;
        return FieldIterator{
            layer: self,
            c_feature_defn: c_feature_defn,
            next_id: 0,
            total: total
        };
    }

    pub fn features(&'a self) -> FeatureIterator<'a> {
        return FeatureIterator{layer: self};
    }
}

pub struct FieldIterator<'a> {
    layer: &'a Layer<'a>,
    c_feature_defn: *const (),
    next_id: isize,
    total: isize,
}

impl<'a> Iterator for FieldIterator<'a> {
    type Item = Field<'a>;

    #[inline]
    fn next(&mut self) -> Option<Field<'a>> {
        if self.next_id == self.total {
            return None;
        }
        let field = Field{
            _layer: self.layer,
            c_field_defn: unsafe { OGR_FD_GetFieldDefn(
                self.c_feature_defn,
                self.next_id as c_int
            ) }
        };
        self.next_id += 1;
        return Some(field);
    }
}

pub struct Field<'a> {
    _layer: &'a Layer<'a>,
    c_field_defn: *const (),
}

impl<'a> Field<'a> {
    pub fn name(&'a self) -> String {
        let rv = unsafe { OGR_Fld_GetNameRef(self.c_field_defn) };
        return _string(rv);
    }
}

pub struct FeatureIterator<'a> {
    layer: &'a Layer<'a>,
}

impl<'a> Iterator for FeatureIterator<'a> {
    type Item = Feature<'a>;

    #[inline]
    fn next(&mut self) -> Option<Feature<'a>> {
        let c_feature = unsafe { OGR_L_GetNextFeature(self.layer.c_layer) };
        return match c_feature.is_null() {
            true  => None,
            false => Some(Feature{_layer: self.layer, c_feature: c_feature}),
        };
    }
}

pub struct Feature<'a> {
    _layer: &'a Layer<'a>,
    c_feature: *const (),
}

impl<'a> Feature<'a> {
    pub fn field(&self, name: &str) -> Option<FieldValue> {
        return name.with_c_str(|c_name| unsafe {
            let field_id = OGR_F_GetFieldIndex(self.c_feature, c_name);
            if field_id == -1 {
                return None;
            }
            let field_defn = OGR_F_GetFieldDefnRef(self.c_feature, field_id);
            let field_type = OGR_Fld_GetType(field_defn);
            return match field_type {
                OFT_STRING => {
                    let rv = OGR_F_GetFieldAsString(self.c_feature, field_id);
                    return Some(FieldValue::StringValue(_string(rv)));
                },
                OFT_REAL => {
                    let rv = OGR_F_GetFieldAsDouble(self.c_feature, field_id);
                    return Some(FieldValue::RealValue(rv as f64));
                },
                _ => panic!("Unknown field type {}", field_type)
            }
        });
    }

    pub fn wkt(&self) -> String {
        unsafe {
            let c_geom = OGR_F_GetGeometryRef(self.c_feature);
            let c_wkt: *const c_char = null();
            OGR_G_ExportToWkt(c_geom, &c_wkt);
            let wkt = _string(c_wkt);
            OGRFree(c_wkt as *const ());
            return wkt;
        }
    }

    pub fn json(&self) -> String {
        unsafe {
            let c_geom = OGR_F_GetGeometryRef(self.c_feature);
            let c_json = OGR_G_ExportToJson(c_geom);
            let json = _string(c_json);
            VSIFree(c_json as *const ());
            return json;
        }
    }
}

#[unsafe_destructor]
impl<'a> Drop for Feature<'a> {
    fn drop(&mut self) {
        unsafe { OGR_F_Destroy(self.c_feature); }
    }
}

pub fn open(path: &Path) -> Option<VectorDataset> {
    register_drivers();
    let filename = path.as_str().unwrap();
    let c_dataset = filename.with_c_str(|c_filename| {
        return unsafe { OGROpen(c_filename, 0, null()) };
    });
    return match c_dataset.is_null() {
        true  => None,
        false => Some(VectorDataset{c_dataset: c_dataset}),
    };
}

pub enum FieldValue {
    StringValue(String),
    RealValue(f64),
}

impl FieldValue {
    pub fn as_string(self) -> String {
        match self {
            FieldValue::StringValue(rv) => rv,
            _ => panic!("not a StringValue")
        }
    }

    pub fn as_real(self) -> f64 {
        match self {
            FieldValue::RealValue(rv) => rv,
            _ => panic!("not a RealValue")
        }
    }
}

#[cfg(test)]
mod test {
    use std::path::Path;
    use super::{Feature, FeatureIterator, open};

    fn fixtures() -> Path {
        return Path::new(file!()).dir_path().dir_path().join("fixtures");
    }

    fn assert_almost_eq(a: f64, b: f64) {
        let f: f64 = a / b;
        assert!(f < 1.00001);
        assert!(f > 0.99999);
    }

    #[test]
    fn test_layer_count() {
        let ds = open(&fixtures().join("roads.geojson")).unwrap();
        assert_eq!(ds.count(), 1);
    }

    fn with_features<F>(fixture: &str, f: F) where F: Fn(FeatureIterator) {
        let ds = open(&fixtures().join(fixture)).unwrap();
        let layer = ds.layer(0).unwrap();
        f(layer.features());
    }

    fn with_first_feature<F>(fixture: &str, f: F) where F: Fn(Feature) {
        with_features(fixture, |mut features| f(features.next().unwrap()));
    }

    #[test]
    fn test_iterate_features() {
        with_features("roads.geojson", |features| {
            let feature_vec: Vec<Feature> = features.collect();
            assert_eq!(feature_vec.len(), 21);
        });
    }

    #[test]
    fn test_string_field() {
        with_features("roads.geojson", |mut features| {
            let feature = features.next().unwrap();
            assert_eq!(feature.field("highway")
                              .unwrap()
                              .as_string(),
                       "footway".to_string());
            assert_eq!(
                features.filter(|field| {
                    let highway = field.field("highway")
                                       .unwrap()
                                       .as_string();
                    highway == "residential".to_string() })
                    .count(),
                2);
        });
    }

    #[test]
    fn test_float_field() {
        with_first_feature("roads.geojson", |feature| {
            assert_almost_eq(
                feature.field("sort_key")
                       .unwrap()
                       .as_real(),
                -9.0
            );
        });
    }

    #[test]
    fn test_missing_field() {
        with_first_feature("roads.geojson", |feature| {
            assert!(feature.field("no such field").is_none());
        });
    }

    #[test]
    fn test_wkt() {
        with_first_feature("roads.geojson", |feature| {
            let wkt = feature.wkt();
            let wkt_ok = format!("{}{}",
                "LINESTRING (26.1019276 44.4302748,",
                "26.1019382 44.4303191,26.1020002 44.4304202)"
                ).to_string();
            assert_eq!(wkt, wkt_ok);
        });
    }

    #[test]
    fn test_json() {
        with_first_feature("roads.geojson", |feature| {
            let json = feature.json();
            let json_ok = format!("{}{}{}{}",
                "{ \"type\": \"LineString\", \"coordinates\": [ ",
                "[ 26.1019276, 44.4302748 ], ",
                "[ 26.1019382, 44.4303191 ], ",
                "[ 26.1020002, 44.4304202 ] ] }"
                ).to_string();
            assert_eq!(json, json_ok);
        });
    }

    #[test]
    fn test_schema() {
        let ds = open(&fixtures().join("roads.geojson")).unwrap();
        let layer = ds.layer(0).unwrap();
        let name_list: Vec<String> = layer
            .fields()
            .map(|f| f.name())
            .collect();
        let ok_names: Vec<String> = vec!(
            "kind", "sort_key", "is_link", "is_tunnel",
            "is_bridge", "railway", "highway")
            .iter().map(|s| s.to_string()).collect();
        assert_eq!(name_list, ok_names);
    }
}
<|endoftext|>


<commit_before>// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! The Rust prelude
//!
//! Because `std` is required by most serious Rust software, it is
//! imported at the topmost level of every crate by default, as if the
//! first line of each crate was
//!
//! ```ignore
//! extern crate std;
//! ```
//!
//! This means that the contents of std can be accessed from any context
//! with the `std::` path prefix, as in `use std::vec`, `use std::task::spawn`,
//! etc.
//!
//! Additionally, `std` contains a `prelude` module that reexports many of the
//! most common traits, types and functions. The contents of the prelude are
//! imported into every *module* by default.  Implicitly, all modules behave as if
//! they contained the following prologue:
//!
//! ```ignore
//! use std::prelude::*;
//! ```
//!
//! The prelude is primarily concerned with exporting *traits* that are so
//! pervasive that it would be obnoxious to import for every use, particularly
//! those that define methods on primitive types. It does include a few
//! particularly useful standalone functions, like `from_str`, `range`, and
//! `drop`, `spawn`, and `channel`.

#![experimental]

// Reexported core operators
#[doc(no_inline)] pub use kinds::{Copy, Send, Sized, Sync};
#[doc(no_inline)] pub use ops::{Add, Sub, Mul, Div, Rem, Neg, Not};
#[doc(no_inline)] pub use ops::{BitAnd, BitOr, BitXor};
#[doc(no_inline)] pub use ops::{Drop, Deref, DerefMut};
#[doc(no_inline)] pub use ops::{Shl, Shr};
#[doc(no_inline)] pub use ops::{Index, IndexMut};
#[doc(no_inline)] pub use ops::{Slice, SliceMut};
#[doc(no_inline)] pub use ops::{Fn, FnMut, FnOnce};
#[doc(no_inline)] pub use option::{Option, Some, None};
#[doc(no_inline)] pub use result::{Result, Ok, Err};

// Reexported functions
#[doc(no_inline)] pub use from_str::from_str;
#[doc(no_inline)] pub use iter::range;
#[doc(no_inline)] pub use mem::drop;

// Reexported types and traits

#[doc(no_inline)] pub use ascii::{Ascii, AsciiCast, OwnedAsciiCast, AsciiStr};
#[doc(no_inline)] pub use ascii::IntoBytes;
#[doc(no_inline)] pub use c_str::ToCStr;
#[doc(no_inline)] pub use char::{Char, UnicodeChar};
#[doc(no_inline)] pub use clone::Clone;
#[doc(no_inline)] pub use cmp::{PartialEq, PartialOrd, Eq, Ord};
#[doc(no_inline)] pub use cmp::{Ordering, Less, Equal, Greater, Equiv};
#[doc(no_inline)] pub use collections::{Collection, Mutable, Map, MutableMap, MutableSeq};
#[doc(no_inline)] pub use collections::{Set, MutableSet};
#[doc(no_inline)] pub use iter::{FromIterator, Extendable, ExactSize};
#[doc(no_inline)] pub use iter::{Iterator, DoubleEndedIterator};
#[doc(no_inline)] pub use iter::{RandomAccessIterator, CloneableIterator};
#[doc(no_inline)] pub use iter::{OrdIterator, MutableDoubleEndedIterator};
#[doc(no_inline)] pub use num::{Num, NumCast, CheckedAdd, CheckedSub, CheckedMul, CheckedDiv};
#[doc(no_inline)] pub use num::{Signed, Unsigned, Primitive, Int, Float};
#[doc(no_inline)] pub use num::{FloatMath, ToPrimitive, FromPrimitive};
#[doc(no_inline)] pub use boxed::Box;
#[doc(no_inline)] pub use path::{GenericPath, Path, PosixPath, WindowsPath};
#[doc(no_inline)] pub use ptr::RawPtr;
#[doc(no_inline)] pub use io::{Buffer, Writer, Reader, Seek};
#[doc(no_inline)] pub use str::{Str, StrVector, StrSlice};
#[doc(no_inline)] pub use str::{IntoMaybeOwned, StrAllocating, UnicodeStrSlice};
#[doc(no_inline)] pub use to_string::{ToString, IntoStr};
#[doc(no_inline)] pub use tuple::{Tuple1, Tuple2, Tuple3, Tuple4};
#[doc(no_inline)] pub use tuple::{Tuple5, Tuple6, Tuple7, Tuple8};
#[doc(no_inline)] pub use tuple::{Tuple9, Tuple10, Tuple11, Tuple12};
#[doc(no_inline)] pub use slice::{CloneableVector, ImmutableCloneableVector};
#[doc(no_inline)] pub use slice::{MutableCloneableSlice, MutableOrdSlice};
#[doc(no_inline)] pub use slice::{ImmutableSlice, MutableSlice};
#[doc(no_inline)] pub use slice::{ImmutablePartialEqSlice, ImmutableOrdSlice};
#[doc(no_inline)] pub use slice::{AsSlice, VectorVector, BoxedSlice};
#[doc(no_inline)] pub use slice::MutableSliceAllocating;
#[doc(no_inline)] pub use string::String;
#[doc(no_inline)] pub use vec::Vec;

// Reexported runtime types
#[doc(no_inline)] pub use comm::{sync_channel, channel};
#[doc(no_inline)] pub use comm::{SyncSender, Sender, Receiver};
#[doc(no_inline)] pub use task::spawn;
<commit_msg>Add ptr::RawMutPtr to prelude<commit_after>// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! The Rust prelude
//!
//! Because `std` is required by most serious Rust software, it is
//! imported at the topmost level of every crate by default, as if the
//! first line of each crate was
//!
//! ```ignore
//! extern crate std;
//! ```
//!
//! This means that the contents of std can be accessed from any context
//! with the `std::` path prefix, as in `use std::vec`, `use std::task::spawn`,
//! etc.
//!
//! Additionally, `std` contains a `prelude` module that reexports many of the
//! most common traits, types and functions. The contents of the prelude are
//! imported into every *module* by default.  Implicitly, all modules behave as if
//! they contained the following prologue:
//!
//! ```ignore
//! use std::prelude::*;
//! ```
//!
//! The prelude is primarily concerned with exporting *traits* that are so
//! pervasive that it would be obnoxious to import for every use, particularly
//! those that define methods on primitive types. It does include a few
//! particularly useful standalone functions, like `from_str`, `range`, and
//! `drop`, `spawn`, and `channel`.

#![experimental]

// Reexported core operators
#[doc(no_inline)] pub use kinds::{Copy, Send, Sized, Sync};
#[doc(no_inline)] pub use ops::{Add, Sub, Mul, Div, Rem, Neg, Not};
#[doc(no_inline)] pub use ops::{BitAnd, BitOr, BitXor};
#[doc(no_inline)] pub use ops::{Drop, Deref, DerefMut};
#[doc(no_inline)] pub use ops::{Shl, Shr};
#[doc(no_inline)] pub use ops::{Index, IndexMut};
#[doc(no_inline)] pub use ops::{Slice, SliceMut};
#[doc(no_inline)] pub use ops::{Fn, FnMut, FnOnce};
#[doc(no_inline)] pub use option::{Option, Some, None};
#[doc(no_inline)] pub use result::{Result, Ok, Err};

// Reexported functions
#[doc(no_inline)] pub use from_str::from_str;
#[doc(no_inline)] pub use iter::range;
#[doc(no_inline)] pub use mem::drop;

// Reexported types and traits

#[doc(no_inline)] pub use ascii::{Ascii, AsciiCast, OwnedAsciiCast, AsciiStr};
#[doc(no_inline)] pub use ascii::IntoBytes;
#[doc(no_inline)] pub use c_str::ToCStr;
#[doc(no_inline)] pub use char::{Char, UnicodeChar};
#[doc(no_inline)] pub use clone::Clone;
#[doc(no_inline)] pub use cmp::{PartialEq, PartialOrd, Eq, Ord};
#[doc(no_inline)] pub use cmp::{Ordering, Less, Equal, Greater, Equiv};
#[doc(no_inline)] pub use collections::{Collection, Mutable, Map, MutableMap, MutableSeq};
#[doc(no_inline)] pub use collections::{Set, MutableSet};
#[doc(no_inline)] pub use iter::{FromIterator, Extendable, ExactSize};
#[doc(no_inline)] pub use iter::{Iterator, DoubleEndedIterator};
#[doc(no_inline)] pub use iter::{RandomAccessIterator, CloneableIterator};
#[doc(no_inline)] pub use iter::{OrdIterator, MutableDoubleEndedIterator};
#[doc(no_inline)] pub use num::{Num, NumCast, CheckedAdd, CheckedSub, CheckedMul, CheckedDiv};
#[doc(no_inline)] pub use num::{Signed, Unsigned, Primitive, Int, Float};
#[doc(no_inline)] pub use num::{FloatMath, ToPrimitive, FromPrimitive};
#[doc(no_inline)] pub use boxed::Box;
#[doc(no_inline)] pub use path::{GenericPath, Path, PosixPath, WindowsPath};
#[doc(no_inline)] pub use ptr::{RawPtr, RawMutPtr};
#[doc(no_inline)] pub use io::{Buffer, Writer, Reader, Seek};
#[doc(no_inline)] pub use str::{Str, StrVector, StrSlice};
#[doc(no_inline)] pub use str::{IntoMaybeOwned, StrAllocating, UnicodeStrSlice};
#[doc(no_inline)] pub use to_string::{ToString, IntoStr};
#[doc(no_inline)] pub use tuple::{Tuple1, Tuple2, Tuple3, Tuple4};
#[doc(no_inline)] pub use tuple::{Tuple5, Tuple6, Tuple7, Tuple8};
#[doc(no_inline)] pub use tuple::{Tuple9, Tuple10, Tuple11, Tuple12};
#[doc(no_inline)] pub use slice::{CloneableVector, ImmutableCloneableVector};
#[doc(no_inline)] pub use slice::{MutableCloneableSlice, MutableOrdSlice};
#[doc(no_inline)] pub use slice::{ImmutableSlice, MutableSlice};
#[doc(no_inline)] pub use slice::{ImmutablePartialEqSlice, ImmutableOrdSlice};
#[doc(no_inline)] pub use slice::{AsSlice, VectorVector, BoxedSlice};
#[doc(no_inline)] pub use slice::MutableSliceAllocating;
#[doc(no_inline)] pub use string::String;
#[doc(no_inline)] pub use vec::Vec;

// Reexported runtime types
#[doc(no_inline)] pub use comm::{sync_channel, channel};
#[doc(no_inline)] pub use comm::{SyncSender, Sender, Receiver};
#[doc(no_inline)] pub use task::spawn;
<|endoftext|>


<commit_before>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// FIXME: #13994: port to the sized deallocation API when available
// FIXME: #13996: need a way to mark the `allocate` and `reallocate` return values as `noalias`

use intrinsics::{abort, cttz32};
use libc::{c_int, c_void, size_t};
use ptr::RawPtr;

#[link(name = "jemalloc", kind = "static")]
extern {
    fn je_mallocx(size: size_t, flags: c_int) -> *mut c_void;
    fn je_rallocx(ptr: *mut c_void, size: size_t, flags: c_int) -> *mut c_void;
    fn je_xallocx(ptr: *mut c_void, size: size_t, extra: size_t, flags: c_int) -> size_t;
    fn je_dallocx(ptr: *mut c_void, flags: c_int);
    fn je_nallocx(size: size_t, flags: c_int) -> size_t;
}

// -lpthread needs to occur after -ljemalloc, the earlier argument isn't enough
#[cfg(not(windows), not(target_os = "android"))]
#[link(name = "pthread")]
extern {}

// MALLOCX_ALIGN(a) macro
#[inline(always)]
fn mallocx_align(a: uint) -> c_int { unsafe { cttz32(a as u32) as c_int } }

/// Return a pointer to `size` bytes of memory.
///
/// Behavior is undefined if the requested size is 0 or the alignment is not a power of 2. The
/// alignment must be no larger than the largest supported page size on the platform.
#[inline]
pub unsafe fn allocate(size: uint, align: uint) -> *mut u8 {
    let ptr = je_mallocx(size as size_t, mallocx_align(align)) as *mut u8;
    if ptr.is_null() {
        abort()
    }
    ptr
}

/// Extend or shrink the allocation referenced by `ptr` to `size` bytes of memory.
///
/// Behavior is undefined if the requested size is 0 or the alignment is not a power of 2. The
/// alignment must be no larger than the largest supported page size on the platform.
///
/// The `old_size` and `align` parameters are the parameters that were used to create the
/// allocation referenced by `ptr`. The `old_size` parameter may also be the value returned by
/// `usable_size` for the requested size.
#[inline]
#[allow(unused_variable)] // for the parameter names in the documentation
pub unsafe fn reallocate(ptr: *mut u8, size: uint, align: uint, old_size: uint) -> *mut u8 {
    let ptr = je_rallocx(ptr as *mut c_void, size as size_t, mallocx_align(align)) as *mut u8;
    if ptr.is_null() {
        abort()
    }
    ptr
}

/// Extend or shrink the allocation referenced by `ptr` to `size` bytes of memory in-place.
///
/// Return true if successful, otherwise false if the allocation was not altered.
///
/// Behavior is undefined if the requested size is 0 or the alignment is not a power of 2. The
/// alignment must be no larger than the largest supported page size on the platform.
///
/// The `old_size` and `align` parameters are the parameters that were used to
/// create the allocation referenced by `ptr`. The `old_size` parameter may be
/// any value in range_inclusive(requested_size, usable_size).
#[inline]
#[allow(unused_variable)] // for the parameter names in the documentation
pub unsafe fn reallocate_inplace(ptr: *mut u8, size: uint, align: uint, old_size: uint) -> bool {
    je_xallocx(ptr as *mut c_void, size as size_t, 0, mallocx_align(align)) == size as size_t
}

/// Deallocate the memory referenced by `ptr`.
///
/// The `ptr` parameter must not be null.
///
/// The `size` and `align` parameters are the parameters that were used to create the
/// allocation referenced by `ptr`. The `size` parameter may also be the value returned by
/// `usable_size` for the requested size.
#[inline]
#[allow(unused_variable)] // for the parameter names in the documentation
pub unsafe fn deallocate(ptr: *mut u8, size: uint, align: uint) {
    je_dallocx(ptr as *mut c_void, mallocx_align(align))
}

/// Return the usable size of an allocation created with the specified the `size` and `align`.
#[inline]
pub fn usable_size(size: uint, align: uint) -> uint {
    unsafe { je_nallocx(size as size_t, mallocx_align(align)) as uint }
}

/// The allocator for unique pointers.
#[cfg(stage0)]
#[lang="exchange_malloc"]
#[inline(always)]
pub unsafe fn exchange_malloc_(size: uint) -> *mut u8 {
    exchange_malloc(size)
}

/// The allocator for unique pointers.
#[cfg(not(test), not(stage0))]
#[lang="exchange_malloc"]
#[inline(always)]
pub unsafe fn exchange_malloc_(size: uint, align: uint) -> *mut u8 {
    exchange_malloc(size, align)
}

/// The allocator for unique pointers.
#[cfg(stage0)]
#[inline]
pub unsafe fn exchange_malloc(size: uint) -> *mut u8 {
    // The compiler never calls `exchange_free` on ~ZeroSizeType, so zero-size
    // allocations can point to this `static`. It would be incorrect to use a null
    // pointer, due to enums assuming types like unique pointers are never null.
    static EMPTY: () = ();

    if size == 0 {
        &EMPTY as *() as *mut u8
    } else {
        allocate(size, 8)
    }
}

/// The allocator for unique pointers.
#[cfg(not(stage0))]
#[inline]
pub unsafe fn exchange_malloc(size: uint, align: uint) -> *mut u8 {
    // The compiler never calls `exchange_free` on ~ZeroSizeType, so zero-size
    // allocations can point to this `static`. It would be incorrect to use a null
    // pointer, due to enums assuming types like unique pointers are never null.
    static EMPTY: () = ();

    if size == 0 {
        &EMPTY as *() as *mut u8
    } else {
        allocate(size, align)
    }
}

#[cfg(not(test))]
#[lang="exchange_free"]
#[inline]
// FIXME: #13994 (rustc should pass align and size here)
pub unsafe fn exchange_free_(ptr: *mut u8) {
    exchange_free(ptr, 0, 8)
}

#[inline]
pub unsafe fn exchange_free(ptr: *mut u8, size: uint, align: uint) {
    deallocate(ptr, size, align);
}

// FIXME: #7496
#[cfg(not(test))]
#[lang="closure_exchange_malloc"]
#[inline]
unsafe fn closure_exchange_malloc(drop_glue: fn(*mut u8), size: uint, align: uint) -> *mut u8 {
    let total_size = ::rt::util::get_box_size(size, align);
    let p = allocate(total_size, 8);

    let alloc = p as *mut ::raw::Box<()>;
    (*alloc).drop_glue = drop_glue;

    alloc as *mut u8
}

// hack for libcore
#[no_mangle]
#[doc(hidden)]
#[deprecated]
#[cfg(stage0, not(test))]
pub extern "C" fn rust_malloc(size: uint) -> *mut u8 {
    unsafe { exchange_malloc(size) }
}

// hack for libcore
#[no_mangle]
#[doc(hidden)]
#[deprecated]
#[cfg(not(stage0), not(test))]
pub extern "C" fn rust_malloc(size: uint, align: uint) -> *mut u8 {
    unsafe { exchange_malloc(size, align) }
}

// hack for libcore
#[no_mangle]
#[doc(hidden)]
#[deprecated]
#[cfg(not(test))]
pub extern "C" fn rust_free(ptr: *mut u8, size: uint, align: uint) {
    unsafe { exchange_free(ptr, size, align) }
}

#[cfg(test)]
mod bench {
    extern crate test;
    use self::test::Bencher;

    #[bench]
    fn alloc_owned_small(b: &mut Bencher) {
        b.iter(|| {
            box 10
        })
    }

    #[bench]
    fn alloc_owned_big(b: &mut Bencher) {
        b.iter(|| {
            box [10, ..1000]
        })
    }
}
<commit_msg>mark rust_malloc/rust_free as unsafe<commit_after>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// FIXME: #13994: port to the sized deallocation API when available
// FIXME: #13996: need a way to mark the `allocate` and `reallocate` return values as `noalias`

use intrinsics::{abort, cttz32};
use libc::{c_int, c_void, size_t};
use ptr::RawPtr;

#[link(name = "jemalloc", kind = "static")]
extern {
    fn je_mallocx(size: size_t, flags: c_int) -> *mut c_void;
    fn je_rallocx(ptr: *mut c_void, size: size_t, flags: c_int) -> *mut c_void;
    fn je_xallocx(ptr: *mut c_void, size: size_t, extra: size_t, flags: c_int) -> size_t;
    fn je_dallocx(ptr: *mut c_void, flags: c_int);
    fn je_nallocx(size: size_t, flags: c_int) -> size_t;
}

// -lpthread needs to occur after -ljemalloc, the earlier argument isn't enough
#[cfg(not(windows), not(target_os = "android"))]
#[link(name = "pthread")]
extern {}

// MALLOCX_ALIGN(a) macro
#[inline(always)]
fn mallocx_align(a: uint) -> c_int { unsafe { cttz32(a as u32) as c_int } }

/// Return a pointer to `size` bytes of memory.
///
/// Behavior is undefined if the requested size is 0 or the alignment is not a power of 2. The
/// alignment must be no larger than the largest supported page size on the platform.
#[inline]
pub unsafe fn allocate(size: uint, align: uint) -> *mut u8 {
    let ptr = je_mallocx(size as size_t, mallocx_align(align)) as *mut u8;
    if ptr.is_null() {
        abort()
    }
    ptr
}

/// Extend or shrink the allocation referenced by `ptr` to `size` bytes of memory.
///
/// Behavior is undefined if the requested size is 0 or the alignment is not a power of 2. The
/// alignment must be no larger than the largest supported page size on the platform.
///
/// The `old_size` and `align` parameters are the parameters that were used to create the
/// allocation referenced by `ptr`. The `old_size` parameter may also be the value returned by
/// `usable_size` for the requested size.
#[inline]
#[allow(unused_variable)] // for the parameter names in the documentation
pub unsafe fn reallocate(ptr: *mut u8, size: uint, align: uint, old_size: uint) -> *mut u8 {
    let ptr = je_rallocx(ptr as *mut c_void, size as size_t, mallocx_align(align)) as *mut u8;
    if ptr.is_null() {
        abort()
    }
    ptr
}

/// Extend or shrink the allocation referenced by `ptr` to `size` bytes of memory in-place.
///
/// Return true if successful, otherwise false if the allocation was not altered.
///
/// Behavior is undefined if the requested size is 0 or the alignment is not a power of 2. The
/// alignment must be no larger than the largest supported page size on the platform.
///
/// The `old_size` and `align` parameters are the parameters that were used to
/// create the allocation referenced by `ptr`. The `old_size` parameter may be
/// any value in range_inclusive(requested_size, usable_size).
#[inline]
#[allow(unused_variable)] // for the parameter names in the documentation
pub unsafe fn reallocate_inplace(ptr: *mut u8, size: uint, align: uint, old_size: uint) -> bool {
    je_xallocx(ptr as *mut c_void, size as size_t, 0, mallocx_align(align)) == size as size_t
}

/// Deallocate the memory referenced by `ptr`.
///
/// The `ptr` parameter must not be null.
///
/// The `size` and `align` parameters are the parameters that were used to create the
/// allocation referenced by `ptr`. The `size` parameter may also be the value returned by
/// `usable_size` for the requested size.
#[inline]
#[allow(unused_variable)] // for the parameter names in the documentation
pub unsafe fn deallocate(ptr: *mut u8, size: uint, align: uint) {
    je_dallocx(ptr as *mut c_void, mallocx_align(align))
}

/// Return the usable size of an allocation created with the specified the `size` and `align`.
#[inline]
pub fn usable_size(size: uint, align: uint) -> uint {
    unsafe { je_nallocx(size as size_t, mallocx_align(align)) as uint }
}

/// The allocator for unique pointers.
#[cfg(stage0)]
#[lang="exchange_malloc"]
#[inline(always)]
pub unsafe fn exchange_malloc_(size: uint) -> *mut u8 {
    exchange_malloc(size)
}

/// The allocator for unique pointers.
#[cfg(not(test), not(stage0))]
#[lang="exchange_malloc"]
#[inline(always)]
pub unsafe fn exchange_malloc_(size: uint, align: uint) -> *mut u8 {
    exchange_malloc(size, align)
}

/// The allocator for unique pointers.
#[cfg(stage0)]
#[inline]
pub unsafe fn exchange_malloc(size: uint) -> *mut u8 {
    // The compiler never calls `exchange_free` on ~ZeroSizeType, so zero-size
    // allocations can point to this `static`. It would be incorrect to use a null
    // pointer, due to enums assuming types like unique pointers are never null.
    static EMPTY: () = ();

    if size == 0 {
        &EMPTY as *() as *mut u8
    } else {
        allocate(size, 8)
    }
}

/// The allocator for unique pointers.
#[cfg(not(stage0))]
#[inline]
pub unsafe fn exchange_malloc(size: uint, align: uint) -> *mut u8 {
    // The compiler never calls `exchange_free` on ~ZeroSizeType, so zero-size
    // allocations can point to this `static`. It would be incorrect to use a null
    // pointer, due to enums assuming types like unique pointers are never null.
    static EMPTY: () = ();

    if size == 0 {
        &EMPTY as *() as *mut u8
    } else {
        allocate(size, align)
    }
}

#[cfg(not(test))]
#[lang="exchange_free"]
#[inline]
// FIXME: #13994 (rustc should pass align and size here)
pub unsafe fn exchange_free_(ptr: *mut u8) {
    exchange_free(ptr, 0, 8)
}

#[inline]
pub unsafe fn exchange_free(ptr: *mut u8, size: uint, align: uint) {
    deallocate(ptr, size, align);
}

// FIXME: #7496
#[cfg(not(test))]
#[lang="closure_exchange_malloc"]
#[inline]
unsafe fn closure_exchange_malloc(drop_glue: fn(*mut u8), size: uint, align: uint) -> *mut u8 {
    let total_size = ::rt::util::get_box_size(size, align);
    let p = allocate(total_size, 8);

    let alloc = p as *mut ::raw::Box<()>;
    (*alloc).drop_glue = drop_glue;

    alloc as *mut u8
}

// hack for libcore
#[no_mangle]
#[doc(hidden)]
#[deprecated]
#[cfg(stage0, not(test))]
pub unsafe extern "C" fn rust_malloc(size: uint) -> *mut u8 {
    exchange_malloc(size)
}

// hack for libcore
#[no_mangle]
#[doc(hidden)]
#[deprecated]
#[cfg(not(stage0), not(test))]
pub unsafe extern "C" fn rust_malloc(size: uint, align: uint) -> *mut u8 {
    exchange_malloc(size, align)
}

// hack for libcore
#[no_mangle]
#[doc(hidden)]
#[deprecated]
#[cfg(not(test))]
pub unsafe extern "C" fn rust_free(ptr: *mut u8, size: uint, align: uint) {
    exchange_free(ptr, size, align)
}

#[cfg(test)]
mod bench {
    extern crate test;
    use self::test::Bencher;

    #[bench]
    fn alloc_owned_small(b: &mut Bencher) {
        b.iter(|| {
            box 10
        })
    }

    #[bench]
    fn alloc_owned_big(b: &mut Bencher) {
        b.iter(|| {
            box [10, ..1000]
        })
    }
}
<|endoftext|>


<commit_before>use std::io;
pub mod log_events;
use self::log_events::*;

pub fn parse_line(line: Result<String, io::Error>) -> Result<LogEvent, &'static str> {
    if line.is_err() {
        return Err("Failed to read line.");
    }

    let line2 = line.unwrap();

    if line2.contains("->") {
        let request = Request::new_from_log_line(&line2);

        return match request {
            Ok(request) => Ok(LogEvent::Request(request)),
            Err(err) => Err(err),
        };
    }

    if line2.contains("<-") {
        let response = Response::new_from_log_line(&line2);

        return match response {
            Ok(response) => Ok(LogEvent::Response(response)),
            Err(err) => Err(err),
        };
    }

    Err("Line is neither a Request nor a Response")
}

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

    #[test]
    fn test_parse_line_request() {
        let line = "08/Apr/2016:09:58:47 +0200 [02] -> GET /content/some/other.html HTTP/1.1"
            .to_string();

        let event = match parse_line(Ok(line)).unwrap() {
            LogEvent::Request(request) => request,
            LogEvent::Response(_) => unreachable!(),
        };

        assert_eq!(event.id, 2);
    }

    #[test]
    fn test_parse_line_response() {
        let line = "08/Apr/2016:09:58:48 +0200 [05] <- 200 text/html 10ms".to_string();

        let event = match parse_line(Ok(line)).unwrap() {
            LogEvent::Request(_) => unreachable!(),
            LogEvent::Response(response) => response,
        };

        assert_eq!(event.id, 5);
    }

    #[test]
    fn test_parse_line_unrecognized() {
        let line = "08/Apr/2016:09:58:48 +0200 [05] XY 200 text/html 10ms".to_string();

        let event = parse_line(Ok(line));

        assert_eq!(event, Err("Line is neither a Request nor a Response"));
    }

    #[test]
    fn test_parse_line_with_response_arrow_in_url() {
        let line = "08/Apr/2016:09:58:47 +0200 [02] -> GET /content/<-.html HTTP/1.1".to_string();

        let _ = match parse_line(Ok(line)).unwrap() {
            LogEvent::Request(request) => request,
            LogEvent::Response(_) => unreachable!(),
        };
    }
}
<commit_msg>Prefer match over ifs<commit_after>use std::io;
pub mod log_events;
use self::log_events::*;

pub fn parse_line(line: Result<String, io::Error>) -> Result<LogEvent, &'static str> {
    match line {
        Err(_) => return Err("Failed to read line."),
        Ok(ref line) if line.contains("->") => {
            match Request::new_from_log_line(line) {
                Ok(request) => Ok(LogEvent::Request(request)),
                Err(err) => Err(err),
            }
        }
        Ok(ref line) if line.contains("<-") => {
            match Response::new_from_log_line(line) {
                Ok(response) => Ok(LogEvent::Response(response)),
                Err(err) => Err(err),
            }
        }
        Ok(_) => Err("Line is neither a Request nor a Response"),
    }
}

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

    #[test]
    fn test_parse_line_request() {
        let line = "08/Apr/2016:09:58:47 +0200 [02] -> GET /content/some/other.html HTTP/1.1"
            .to_string();

        let event = match parse_line(Ok(line)).unwrap() {
            LogEvent::Request(request) => request,
            LogEvent::Response(_) => unreachable!(),
        };

        assert_eq!(event.id, 2);
    }

    #[test]
    fn test_parse_line_response() {
        let line = "08/Apr/2016:09:58:48 +0200 [05] <- 200 text/html 10ms".to_string();

        let event = match parse_line(Ok(line)).unwrap() {
            LogEvent::Request(_) => unreachable!(),
            LogEvent::Response(response) => response,
        };

        assert_eq!(event.id, 5);
    }

    #[test]
    fn test_parse_line_unrecognized() {
        let line = "08/Apr/2016:09:58:48 +0200 [05] XY 200 text/html 10ms".to_string();

        let event = parse_line(Ok(line));

        assert_eq!(event, Err("Line is neither a Request nor a Response"));
    }

    #[test]
    fn test_parse_line_with_response_arrow_in_url() {
        let line = "08/Apr/2016:09:58:47 +0200 [02] -> GET /content/<-.html HTTP/1.1".to_string();

        let _ = match parse_line(Ok(line)).unwrap() {
            LogEvent::Request(request) => request,
            LogEvent::Response(_) => unreachable!(),
        };
    }
}
<|endoftext|>


<commit_before>use num::{ Float, ToPrimitive, FromPrimitive };
use frame::Frameable;
use color::{ Color, Colorable };
use dimensions::Dimensions;
use graphics;
use graphics::Graphics;
use graphics::character::CharacterCache;
use label;
use label::FontSize;
use mouse::Mouse;
use point::Point;
use rectangle;
use rectangle::{
    Corner
};
use ui_context::{ UIID, UiContext };
use utils::{
    clamp,
    map_range,
    val_to_string,
};
use vecmath::{
    vec2_add,
    vec2_sub,
};
use widget::Widget;

/// Represents the state of the xy_pad widget.
#[derive(Debug, PartialEq, Clone, Copy)]
pub enum State {
    Normal,
    Highlighted,
    Clicked,
}

impl State {
    /// Return the associated Rectangle state.
    fn as_rectangle_state(&self) -> rectangle::State {
        match self {
            &State::Normal => rectangle::State::Normal,
            &State::Highlighted => rectangle::State::Highlighted,
            &State::Clicked => rectangle::State::Clicked,
        }
    }
}

widget_fns!(XYPad, State, Widget::XYPad(State::Normal));

/// Check the current state of the button.
fn get_new_state(is_over: bool,
                 prev: State,
                 mouse: Mouse) -> State {
    use mouse::ButtonState::{Down, Up};
    use self::State::{Normal, Highlighted, Clicked};
    match (is_over, prev, mouse.left) {
        (true,  Normal,  Down) => Normal,
        (true,  _,       Down) => Clicked,
        (true,  _,       Up)   => Highlighted,
        (false, Clicked, Down) => Clicked,
        _                      => Normal,
    }
}

/// Draw the crosshair.
fn draw_crosshair<B: Graphics>(
    win_w: f64,
    win_h: f64,
    graphics: &mut B,
    pos: Point,
    line_width: f64,
    vert_x: f64, hori_y: f64,
    pad_dim: Dimensions,
    color: Color
) {
    let draw_state = graphics::default_draw_state();
    let transform = graphics::abs_transform(win_w, win_h);
    let Color(col) = color;
    let line = graphics::Line::new(col, 0.5 * line_width);
    line.draw(
        [vert_x, pos[1], vert_x, pos[1] + pad_dim[1]],
        draw_state,
        transform,
        graphics
    );
    line.draw(
        [pos[0], hori_y, pos[0] + pad_dim[0], hori_y],
        draw_state,
        transform,
        graphics
    );
}

/// A context on which the builder pattern can be implemented.
pub struct XYPad<'a, X, Y, F> {
    ui_id: UIID,
    x: X, min_x: X, max_x: X,
    y: Y, min_y: Y, max_y: Y,
    line_width: f64,
    font_size: FontSize,
    pos: Point,
    dim: Dimensions,
    maybe_callback: Option<F>,
    maybe_color: Option<Color>,
    maybe_frame: Option<f64>,
    maybe_frame_color: Option<Color>,
    maybe_label: Option<&'a str>,
    maybe_label_color: Option<Color>,
    maybe_label_font_size: Option<u32>,
}

impl <'a, X, Y, F> XYPad<'a, X, Y, F> {
    #[inline]
    pub fn line_width(self, width: f64) -> XYPad<'a, X, Y, F> {
        XYPad { line_width: width, ..self }
    }
    #[inline]
    pub fn value_font_size(self, size: FontSize) -> XYPad<'a, X, Y, F> {
        XYPad { font_size: size, ..self }
    }
}

impl<'a, X, Y, F> XYPad<'a, X, Y, F> {
    /// An xy_pad builder method to be implemented by the UiContext.
    pub fn new(ui_id: UIID,
              x_val: X, min_x: X, max_x: X,
              y_val: Y, min_y: Y, max_y: Y) -> XYPad<'a, X, Y, F> {
        XYPad {
            ui_id: ui_id,
            x: x_val, min_x: min_x, max_x: max_x,
            y: y_val, min_y: min_y, max_y: max_y,
            line_width: 1.0,
            font_size: 18u32,
            pos: [0.0, 0.0],
            dim: [128.0, 128.0],
            maybe_callback: None,
            maybe_color: None,
            maybe_frame: None,
            maybe_frame_color: None,
            maybe_label: None,
            maybe_label_color: None,
            maybe_label_font_size: None,
        }
    }
}

impl<'a, X, Y, F> Colorable for XYPad<'a, X, Y, F> {
    fn color(mut self, color: Color) -> Self {
        self.maybe_color = Some(color);
        self
    }
}

impl<'a, X, Y, F> Frameable for XYPad<'a, X, Y, F> {
    fn frame(mut self, width: f64) -> Self {
        self.maybe_frame = Some(width);
        self
    }
    fn frame_color(mut self, color: Color) -> Self {
        self.maybe_frame_color = Some(color);
        self
    }
}

/*
quack! {
    xy_pad: XYPad['a, X, Y, F]
    get:
        fn () -> Size [] { Size(xy_pad.dim) }
        fn () -> DefaultWidgetState [] {
            DefaultWidgetState(Widget::XYPad(State::Normal))
        }
        fn () -> Id [] { Id(xy_pad.ui_id) }
    set:
        fn (val: Callback<F>) [where F: FnMut(X, Y) + 'a] {
            xy_pad.maybe_callback = Some(val.0)
        }
        fn (val: LabelText<'a>) [] { xy_pad.maybe_label = Some(val.0) }
        fn (val: LabelColor) [] { xy_pad.maybe_label_color = Some(val.0) }
        fn (val: LabelFontSize) [] { xy_pad.maybe_label_font_size = Some(val.0) }
        fn (val: Position) [] { xy_pad.pos = val.0 }
        fn (val: Size) [] { xy_pad.dim = val.0 }
    action:
}
*/

impl<'a, X, Y, F> ::draw::Drawable for XYPad<'a, X, Y, F>
    where
        X: Float + ToPrimitive + FromPrimitive + ToString,
        Y: Float + ToPrimitive + FromPrimitive + ToString,
        F: FnMut(X, Y) + 'a
{

    fn draw<B, C>(&mut self, uic: &mut UiContext<C>, graphics: &mut B)
        where
            B: Graphics<Texture = <C as CharacterCache>::Texture>,
            C: CharacterCache
    {

        // Init.
        let state = *get_state(uic, self.ui_id);
        let mouse = uic.get_mouse_state();
        let frame_w = self.maybe_frame.unwrap_or(uic.theme.frame_width);
        let frame_w2 = frame_w * 2.0;
        let maybe_frame = match frame_w > 0.0 {
            true => Some((frame_w, self.maybe_frame_color.unwrap_or(uic.theme.frame_color))),
            false => None,
        };
        let pad_dim = vec2_sub(self.dim, [frame_w2; 2]);
        let pad_pos = vec2_add(self.pos, [frame_w, frame_w]);
        let is_over_pad = rectangle::is_over(pad_pos, mouse.pos, pad_dim);
        let new_state = get_new_state(is_over_pad, state, mouse);

        // Determine new values.
        let (new_x, new_y) = match (is_over_pad, new_state) {
            (_, State::Normal) | (_, State::Highlighted) => (self.x, self.y),
            (_, State::Clicked) => {
                let temp_x = clamp(mouse.pos[0], pad_pos[0], pad_pos[0] + pad_dim[0]);
                let temp_y = clamp(mouse.pos[1], pad_pos[1], pad_pos[1] + pad_dim[1]);
                (map_range(temp_x - self.pos[0], pad_dim[0], 0.0, self.min_x, self.max_x),
                 map_range(temp_y - self.pos[1], pad_dim[1], 0.0, self.min_y, self.max_y))
            }
        };

        // Callback if value is changed or the pad is clicked/released.
        match self.maybe_callback {
            Some(ref mut callback) => {
                if self.x != new_x || self.y != new_y { (*callback)(new_x, new_y) }
                else {
                    match (state, new_state) {
                        (State::Highlighted, State::Clicked)
                        | (State::Clicked, State::Highlighted) => (*callback)(new_x, new_y),
                        _ => (),
                    }
                }
            },
            None => (),
        }

        // Draw.
        let rect_state = new_state.as_rectangle_state();
        let color = self.maybe_color.unwrap_or(uic.theme.shape_color);
        rectangle::draw(uic.win_w, uic.win_h, graphics, rect_state, self.pos,
                        self.dim, maybe_frame, color);
        let (vert_x, hori_y) = match (is_over_pad, new_state) {
            (_, State::Normal) | (_, State::Highlighted) =>
                (pad_pos[0] + map_range(new_x, self.min_x, self.max_x, pad_dim[0], 0.0),
                 pad_pos[1] + map_range(new_y, self.min_y, self.max_y, pad_dim[1], 0.0)),
            (_, State::Clicked) =>
                (clamp(mouse.pos[0], pad_pos[0], pad_pos[0] + pad_dim[0]),
                 clamp(mouse.pos[1], pad_pos[1], pad_pos[1] + pad_dim[1])),
        };
        // Crosshair.
        draw_crosshair(uic.win_w, uic.win_h, graphics, pad_pos, self.line_width,
                       vert_x, hori_y, pad_dim, color.plain_contrast());
        // Label.
        if let Some(l_text) = self.maybe_label {
            let l_color = self.maybe_label_color.unwrap_or(uic.theme.label_color);
            let l_size = self.maybe_label_font_size.unwrap_or(uic.theme.font_size_medium);
            let l_w = label::width(uic, l_size, l_text);
            let l_x = pad_pos[0] + (pad_dim[0] - l_w) / 2.0;
            let l_y = pad_pos[1] + (pad_dim[1] - l_size as f64) / 2.0;
            let l_pos = [l_x, l_y];
            uic.draw_text(graphics, l_pos, l_size, l_color, l_text);
        }
        // xy value string.
        let x_string = val_to_string(self.x, self.max_x,
                                     self.max_x - self.min_x, self.dim[0] as usize);
        let y_string = val_to_string(self.y, self.max_y,
                                     self.max_y - self.min_y, self.dim[1] as usize);
        let xy_string = format!("{}, {}", x_string, y_string);
        let xy_string_w = label::width(uic, self.font_size, &xy_string);
        let xy_string_pos = {
            match rectangle::corner(pad_pos, [vert_x, hori_y], pad_dim) {
                Corner::TopLeft => [vert_x, hori_y],
                Corner::TopRight => [vert_x - xy_string_w, hori_y],
                Corner::BottomLeft => [vert_x, hori_y - self.font_size as f64],
                Corner::BottomRight => [vert_x - xy_string_w, hori_y - self.font_size as f64],
            }
        };
        uic.draw_text(graphics, xy_string_pos, self.font_size,
                    color.plain_contrast(), &xy_string);

        set_state(uic, self.ui_id, Widget::XYPad(new_state), self.pos, self.dim);

    }
}
<commit_msg>Implemented `Callable` for `XYPad`<commit_after>use num::{ Float, ToPrimitive, FromPrimitive };
use callback::Callable;
use frame::Frameable;
use color::{ Color, Colorable };
use dimensions::Dimensions;
use graphics;
use graphics::Graphics;
use graphics::character::CharacterCache;
use label;
use label::FontSize;
use mouse::Mouse;
use point::Point;
use rectangle;
use rectangle::{
    Corner
};
use ui_context::{ UIID, UiContext };
use utils::{
    clamp,
    map_range,
    val_to_string,
};
use vecmath::{
    vec2_add,
    vec2_sub,
};
use widget::Widget;

/// Represents the state of the xy_pad widget.
#[derive(Debug, PartialEq, Clone, Copy)]
pub enum State {
    Normal,
    Highlighted,
    Clicked,
}

impl State {
    /// Return the associated Rectangle state.
    fn as_rectangle_state(&self) -> rectangle::State {
        match self {
            &State::Normal => rectangle::State::Normal,
            &State::Highlighted => rectangle::State::Highlighted,
            &State::Clicked => rectangle::State::Clicked,
        }
    }
}

widget_fns!(XYPad, State, Widget::XYPad(State::Normal));

/// Check the current state of the button.
fn get_new_state(is_over: bool,
                 prev: State,
                 mouse: Mouse) -> State {
    use mouse::ButtonState::{Down, Up};
    use self::State::{Normal, Highlighted, Clicked};
    match (is_over, prev, mouse.left) {
        (true,  Normal,  Down) => Normal,
        (true,  _,       Down) => Clicked,
        (true,  _,       Up)   => Highlighted,
        (false, Clicked, Down) => Clicked,
        _                      => Normal,
    }
}

/// Draw the crosshair.
fn draw_crosshair<B: Graphics>(
    win_w: f64,
    win_h: f64,
    graphics: &mut B,
    pos: Point,
    line_width: f64,
    vert_x: f64, hori_y: f64,
    pad_dim: Dimensions,
    color: Color
) {
    let draw_state = graphics::default_draw_state();
    let transform = graphics::abs_transform(win_w, win_h);
    let Color(col) = color;
    let line = graphics::Line::new(col, 0.5 * line_width);
    line.draw(
        [vert_x, pos[1], vert_x, pos[1] + pad_dim[1]],
        draw_state,
        transform,
        graphics
    );
    line.draw(
        [pos[0], hori_y, pos[0] + pad_dim[0], hori_y],
        draw_state,
        transform,
        graphics
    );
}

/// A context on which the builder pattern can be implemented.
pub struct XYPad<'a, X, Y, F> {
    ui_id: UIID,
    x: X, min_x: X, max_x: X,
    y: Y, min_y: Y, max_y: Y,
    line_width: f64,
    font_size: FontSize,
    pos: Point,
    dim: Dimensions,
    maybe_callback: Option<F>,
    maybe_color: Option<Color>,
    maybe_frame: Option<f64>,
    maybe_frame_color: Option<Color>,
    maybe_label: Option<&'a str>,
    maybe_label_color: Option<Color>,
    maybe_label_font_size: Option<u32>,
}

impl <'a, X, Y, F> XYPad<'a, X, Y, F> {
    #[inline]
    pub fn line_width(self, width: f64) -> XYPad<'a, X, Y, F> {
        XYPad { line_width: width, ..self }
    }
    #[inline]
    pub fn value_font_size(self, size: FontSize) -> XYPad<'a, X, Y, F> {
        XYPad { font_size: size, ..self }
    }
}

impl<'a, X, Y, F> XYPad<'a, X, Y, F> {
    /// An xy_pad builder method to be implemented by the UiContext.
    pub fn new(ui_id: UIID,
              x_val: X, min_x: X, max_x: X,
              y_val: Y, min_y: Y, max_y: Y) -> XYPad<'a, X, Y, F> {
        XYPad {
            ui_id: ui_id,
            x: x_val, min_x: min_x, max_x: max_x,
            y: y_val, min_y: min_y, max_y: max_y,
            line_width: 1.0,
            font_size: 18u32,
            pos: [0.0, 0.0],
            dim: [128.0, 128.0],
            maybe_callback: None,
            maybe_color: None,
            maybe_frame: None,
            maybe_frame_color: None,
            maybe_label: None,
            maybe_label_color: None,
            maybe_label_font_size: None,
        }
    }
}

impl<'a, X, Y, F> Colorable for XYPad<'a, X, Y, F> {
    fn color(mut self, color: Color) -> Self {
        self.maybe_color = Some(color);
        self
    }
}

impl<'a, X, Y, F> Frameable for XYPad<'a, X, Y, F> {
    fn frame(mut self, width: f64) -> Self {
        self.maybe_frame = Some(width);
        self
    }
    fn frame_color(mut self, color: Color) -> Self {
        self.maybe_frame_color = Some(color);
        self
    }
}

impl<'a, X, Y, F> Callable<F> for XYPad<'a, X, Y, F> {
    fn callback(mut self, cb: F) -> Self {
        self.maybe_callback = Some(cb);
        self
    }
}

/*
quack! {
    xy_pad: XYPad['a, X, Y, F]
    get:
        fn () -> Size [] { Size(xy_pad.dim) }
        fn () -> DefaultWidgetState [] {
            DefaultWidgetState(Widget::XYPad(State::Normal))
        }
        fn () -> Id [] { Id(xy_pad.ui_id) }
    set:
        fn (val: LabelText<'a>) [] { xy_pad.maybe_label = Some(val.0) }
        fn (val: LabelColor) [] { xy_pad.maybe_label_color = Some(val.0) }
        fn (val: LabelFontSize) [] { xy_pad.maybe_label_font_size = Some(val.0) }
        fn (val: Position) [] { xy_pad.pos = val.0 }
        fn (val: Size) [] { xy_pad.dim = val.0 }
    action:
}
*/

impl<'a, X, Y, F> ::draw::Drawable for XYPad<'a, X, Y, F>
    where
        X: Float + ToPrimitive + FromPrimitive + ToString,
        Y: Float + ToPrimitive + FromPrimitive + ToString,
        F: FnMut(X, Y) + 'a
{

    fn draw<B, C>(&mut self, uic: &mut UiContext<C>, graphics: &mut B)
        where
            B: Graphics<Texture = <C as CharacterCache>::Texture>,
            C: CharacterCache
    {

        // Init.
        let state = *get_state(uic, self.ui_id);
        let mouse = uic.get_mouse_state();
        let frame_w = self.maybe_frame.unwrap_or(uic.theme.frame_width);
        let frame_w2 = frame_w * 2.0;
        let maybe_frame = match frame_w > 0.0 {
            true => Some((frame_w, self.maybe_frame_color.unwrap_or(uic.theme.frame_color))),
            false => None,
        };
        let pad_dim = vec2_sub(self.dim, [frame_w2; 2]);
        let pad_pos = vec2_add(self.pos, [frame_w, frame_w]);
        let is_over_pad = rectangle::is_over(pad_pos, mouse.pos, pad_dim);
        let new_state = get_new_state(is_over_pad, state, mouse);

        // Determine new values.
        let (new_x, new_y) = match (is_over_pad, new_state) {
            (_, State::Normal) | (_, State::Highlighted) => (self.x, self.y),
            (_, State::Clicked) => {
                let temp_x = clamp(mouse.pos[0], pad_pos[0], pad_pos[0] + pad_dim[0]);
                let temp_y = clamp(mouse.pos[1], pad_pos[1], pad_pos[1] + pad_dim[1]);
                (map_range(temp_x - self.pos[0], pad_dim[0], 0.0, self.min_x, self.max_x),
                 map_range(temp_y - self.pos[1], pad_dim[1], 0.0, self.min_y, self.max_y))
            }
        };

        // Callback if value is changed or the pad is clicked/released.
        match self.maybe_callback {
            Some(ref mut callback) => {
                if self.x != new_x || self.y != new_y { (*callback)(new_x, new_y) }
                else {
                    match (state, new_state) {
                        (State::Highlighted, State::Clicked)
                        | (State::Clicked, State::Highlighted) => (*callback)(new_x, new_y),
                        _ => (),
                    }
                }
            },
            None => (),
        }

        // Draw.
        let rect_state = new_state.as_rectangle_state();
        let color = self.maybe_color.unwrap_or(uic.theme.shape_color);
        rectangle::draw(uic.win_w, uic.win_h, graphics, rect_state, self.pos,
                        self.dim, maybe_frame, color);
        let (vert_x, hori_y) = match (is_over_pad, new_state) {
            (_, State::Normal) | (_, State::Highlighted) =>
                (pad_pos[0] + map_range(new_x, self.min_x, self.max_x, pad_dim[0], 0.0),
                 pad_pos[1] + map_range(new_y, self.min_y, self.max_y, pad_dim[1], 0.0)),
            (_, State::Clicked) =>
                (clamp(mouse.pos[0], pad_pos[0], pad_pos[0] + pad_dim[0]),
                 clamp(mouse.pos[1], pad_pos[1], pad_pos[1] + pad_dim[1])),
        };
        // Crosshair.
        draw_crosshair(uic.win_w, uic.win_h, graphics, pad_pos, self.line_width,
                       vert_x, hori_y, pad_dim, color.plain_contrast());
        // Label.
        if let Some(l_text) = self.maybe_label {
            let l_color = self.maybe_label_color.unwrap_or(uic.theme.label_color);
            let l_size = self.maybe_label_font_size.unwrap_or(uic.theme.font_size_medium);
            let l_w = label::width(uic, l_size, l_text);
            let l_x = pad_pos[0] + (pad_dim[0] - l_w) / 2.0;
            let l_y = pad_pos[1] + (pad_dim[1] - l_size as f64) / 2.0;
            let l_pos = [l_x, l_y];
            uic.draw_text(graphics, l_pos, l_size, l_color, l_text);
        }
        // xy value string.
        let x_string = val_to_string(self.x, self.max_x,
                                     self.max_x - self.min_x, self.dim[0] as usize);
        let y_string = val_to_string(self.y, self.max_y,
                                     self.max_y - self.min_y, self.dim[1] as usize);
        let xy_string = format!("{}, {}", x_string, y_string);
        let xy_string_w = label::width(uic, self.font_size, &xy_string);
        let xy_string_pos = {
            match rectangle::corner(pad_pos, [vert_x, hori_y], pad_dim) {
                Corner::TopLeft => [vert_x, hori_y],
                Corner::TopRight => [vert_x - xy_string_w, hori_y],
                Corner::BottomLeft => [vert_x, hori_y - self.font_size as f64],
                Corner::BottomRight => [vert_x - xy_string_w, hori_y - self.font_size as f64],
            }
        };
        uic.draw_text(graphics, xy_string_pos, self.font_size,
                    color.plain_contrast(), &xy_string);

        set_state(uic, self.ui_id, Widget::XYPad(new_state), self.pos, self.dim);

    }
}
<|endoftext|>