<commit_before>use error::Error;
use client::Client;
use params::{List, Metadata, Timestamp};
use resources::{Currency, Discount, Plan};
use serde_qs as qs;

/// The set of parameters that can be used when creating or updating an invoice.
///
/// For more details see https://stripe.com/docs/api#create_invoice, https://stripe.com/docs/api#update_invoice.
#[derive(Default, Serialize)]
pub struct InvoiceParams<'a> {
    #[serde(skip_serializing_if = "Option::is_none")]
    pub application_fee: Option<u64>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub customer: Option<&'a str>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub description: Option<&'a str>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub statement_descriptor: Option<&'a str>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub subscription: Option<&'a str>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub tax_percent: Option<f64>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub closed: Option<bool>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub forgiven: Option<bool>,
}

#[derive(Default, Serialize)]
pub struct InvoiceItemParams<'a> {
    #[serde(skip_serializing_if = "Option::is_none")]
    pub amount: Option<i64>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub currency: Option<Currency>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub customer: Option<&'a str>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub description: Option<&'a str>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub discountable: Option<bool>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub invoice: Option<&'a str>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub metadata: Option<bool>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub subscription: Option<bool>,
}

/*
#[derive(Serialize)]
pub struct InvoiceListLinesParams {
    #[serde(skip_serializing_if = "Option::is_none")] pub limit: Option<u64>,
    #[serde(skip_serializing_if = "Option::is_none")] pub ending_before: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")] pub starting_after: Option<String>,

    ..
}
*/

/// Period is a structure representing a start and end dates.
#[derive(Debug, Deserialize)]
pub struct Period {
    pub start: Timestamp,
    pub end: Timestamp,
}

/// The resource representing a Stripe invoice line item.
///
/// For more details see https://stripe.com/docs/api#invoice_line_item_object.
#[derive(Debug, Deserialize)]
pub struct InvoiceItem {
    pub id: String,
    pub amount: i64,
    pub currency: Currency,
    pub description: Option<String>,
    pub discountable: bool,
    pub livemode: bool,
    pub metadata: Metadata,
    pub period: Period,
    pub plan: Option<Plan>,
    pub proration: bool,
    pub quantity: Option<u64>,
    pub subscription: Option<String>,
    pub subscription_item: Option<String>,
    #[serde(default)]
    // NOTE: Missing in response to InvoiceItem create
    #[serde(rename = "type")]
    pub item_type: String, // (invoiceitem, subscription)
}

/// The resource representing a Stripe invoice.
///
/// For more details see https://stripe.com/docs/api#invoice_object.
#[derive(Debug, Deserialize)]
pub struct Invoice {
    pub id: String,
    pub amount_due: u64,
    pub application_fee: Option<u64>,
    pub attempt_count: u64,
    pub attempted: bool,
    pub charge: Option<String>,
    pub closed: bool,
    pub currency: Currency,
    pub customer: String,
    pub date: Timestamp,
    pub description: Option<String>,
    pub discount: Option<Discount>,
    pub ending_balance: Option<i64>,
    pub forgiven: bool,
    pub lines: List<InvoiceItem>,
    pub livemode: bool,
    pub metadata: Metadata,
    pub next_payment_attempt: Option<Timestamp>,
    pub paid: bool,
    pub period_end: Timestamp,
    pub period_start: Timestamp,
    pub receipt_number: Option<String>,
    pub starting_balance: i64,
    pub statment_descriptor: Option<String>,
    pub subscription: Option<String>,
    pub subscription_proration_date: Option<Timestamp>,
    pub subtotal: i64,
    pub tax: Option<i64>,
    pub tax_percent: Option<f64>,
    pub total: i64,
    pub webhooks_delivered_at: Option<Timestamp>,
}

#[derive(Default, Serialize)]
pub struct InvoiceListParams<'a> {
    #[serde(skip_serializing_if = "Option::is_none")]
    pub limit: Option<u64>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub customer: Option<&'a str>,
}

impl Invoice {
    /// Creates a new invoice.
    ///
    /// For more details see https://stripe.com/docs/api#create_invoice.
    pub fn create(client: &Client, params: InvoiceParams) -> Result<Invoice, Error> {
        client.post("/invoices", params)
    }

    /// Retrieves the details of an invoice.
    ///
    /// For more details see https://stripe.com/docs/api#retrieve_invoice.
    pub fn retrieve(client: &Client, invoice_id: &str) -> Result<Invoice, Error> {
        client.get(&format!("/invoices/{}", invoice_id))
    }

    // TODO: Implement InvoiceListLinesParams
    // pub fn get_lines(client: &Client, invoice_id: &str, params: InvoiceListLinesParams) -> Result<List<InvoiceItem>, Error> {
    //     client.get(&format!("/invoices/{}/lines", invoice_id))
    // }

    // TODO: Implement InvoiceUpcomingParams
    // pub fn get_upcoming(client: &Client, params: InvoiceUpcomingParams) -> Result<Invoice, Error> {
    //     client.get(&format!("/invoices/upcoming?customer={}", invoice_id))
    // }

    /// Pays an invoice.
    ///
    /// For more details see https://stripe.com/docs/api#pay_invoice.
    pub fn pay(client: &Client, invoice_id: &str) -> Result<Invoice, Error> {
        client.post_empty(&format!("/invoices/{}/pay", invoice_id))
    }

    /// Updates an invoice.
    ///
    /// For more details see https://stripe.com/docs/api#update_invoice.
    pub fn update(client: &Client, invoice_id: &str, params: InvoiceParams) -> Result<Invoice, Error> {
        client.post(&format!("/invoices/{}", invoice_id), &params)
    }

    /// Lists all invoices with optional customer_id and limit params
    ///
    /// For more details see https://stripe.com/docs/api#list_invoices.
    pub fn list(client: &Client, params: InvoiceListParams) -> Result<List<Invoice>, Error> {
        client.get(&format!("/invoices?{}", qs::to_string(&params)?))
    }
}

impl InvoiceItem {
    /// Creates an invoice line item.
    ///
    /// For more details see https://stripe.com/docs/api/node#invoice_line_item_object
    pub fn create(client: &Client, params: InvoiceItemParams) -> Result<InvoiceItem, Error> {
        client.post(&format!("/invoiceitems"), &params)
    }
}
<commit_msg>Add missing params to InvoiceListParams<commit_after>use error::Error;
use client::Client;
use params::{List, Metadata, RangeQuery, Timestamp};
use resources::{Currency, Discount, Plan};
use serde_qs as qs;

/// The set of parameters that can be used when creating or updating an invoice.
///
/// For more details see https://stripe.com/docs/api#create_invoice, https://stripe.com/docs/api#update_invoice.
#[derive(Default, Serialize)]
pub struct InvoiceParams<'a> {
    #[serde(skip_serializing_if = "Option::is_none")]
    pub application_fee: Option<u64>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub customer: Option<&'a str>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub description: Option<&'a str>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub statement_descriptor: Option<&'a str>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub subscription: Option<&'a str>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub tax_percent: Option<f64>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub closed: Option<bool>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub forgiven: Option<bool>,
}

#[derive(Default, Serialize)]
pub struct InvoiceItemParams<'a> {
    #[serde(skip_serializing_if = "Option::is_none")]
    pub amount: Option<i64>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub currency: Option<Currency>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub customer: Option<&'a str>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub description: Option<&'a str>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub discountable: Option<bool>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub invoice: Option<&'a str>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub metadata: Option<bool>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub subscription: Option<bool>,
}

/*
#[derive(Serialize)]
pub struct InvoiceListLinesParams {
    #[serde(skip_serializing_if = "Option::is_none")] pub limit: Option<u64>,
    #[serde(skip_serializing_if = "Option::is_none")] pub ending_before: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")] pub starting_after: Option<String>,

    ..
}
*/

/// Period is a structure representing a start and end dates.
#[derive(Debug, Deserialize)]
pub struct Period {
    pub start: Timestamp,
    pub end: Timestamp,
}

/// The resource representing a Stripe invoice line item.
///
/// For more details see https://stripe.com/docs/api#invoice_line_item_object.
#[derive(Debug, Deserialize)]
pub struct InvoiceItem {
    pub id: String,
    pub amount: i64,
    pub currency: Currency,
    pub description: Option<String>,
    pub discountable: bool,
    pub livemode: bool,
    pub metadata: Metadata,
    pub period: Period,
    pub plan: Option<Plan>,
    pub proration: bool,
    pub quantity: Option<u64>,
    pub subscription: Option<String>,
    pub subscription_item: Option<String>,
    #[serde(default)]
    // NOTE: Missing in response to InvoiceItem create
    #[serde(rename = "type")]
    pub item_type: String, // (invoiceitem, subscription)
}

/// The resource representing a Stripe invoice.
///
/// For more details see https://stripe.com/docs/api#invoice_object.
#[derive(Debug, Deserialize)]
pub struct Invoice {
    pub id: String,
    pub amount_due: u64,
    pub application_fee: Option<u64>,
    pub attempt_count: u64,
    pub attempted: bool,
    pub charge: Option<String>,
    pub closed: bool,
    pub currency: Currency,
    pub customer: String,
    pub date: Timestamp,
    pub description: Option<String>,
    pub discount: Option<Discount>,
    pub ending_balance: Option<i64>,
    pub forgiven: bool,
    pub lines: List<InvoiceItem>,
    pub livemode: bool,
    pub metadata: Metadata,
    pub next_payment_attempt: Option<Timestamp>,
    pub paid: bool,
    pub period_end: Timestamp,
    pub period_start: Timestamp,
    pub receipt_number: Option<String>,
    pub starting_balance: i64,
    pub statment_descriptor: Option<String>,
    pub subscription: Option<String>,
    pub subscription_proration_date: Option<Timestamp>,
    pub subtotal: i64,
    pub tax: Option<i64>,
    pub tax_percent: Option<f64>,
    pub total: i64,
    pub webhooks_delivered_at: Option<Timestamp>,
}

#[derive(Default, Serialize)]
pub struct InvoiceListParams<'a> {
    #[serde(skip_serializing_if = "Option::is_none")]
    pub customer: Option<&'a str>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub date: Option<RangeQuery<Timestamp>>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub ending_before: Option<&'a str>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub limit: Option<u64>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub starting_after: Option<&'a str>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub subscription: Option<&'a str>,
}

impl Invoice {
    /// Creates a new invoice.
    ///
    /// For more details see https://stripe.com/docs/api#create_invoice.
    pub fn create(client: &Client, params: InvoiceParams) -> Result<Invoice, Error> {
        client.post("/invoices", params)
    }

    /// Retrieves the details of an invoice.
    ///
    /// For more details see https://stripe.com/docs/api#retrieve_invoice.
    pub fn retrieve(client: &Client, invoice_id: &str) -> Result<Invoice, Error> {
        client.get(&format!("/invoices/{}", invoice_id))
    }

    // TODO: Implement InvoiceListLinesParams
    // pub fn get_lines(client: &Client, invoice_id: &str, params: InvoiceListLinesParams) -> Result<List<InvoiceItem>, Error> {
    //     client.get(&format!("/invoices/{}/lines", invoice_id))
    // }

    // TODO: Implement InvoiceUpcomingParams
    // pub fn get_upcoming(client: &Client, params: InvoiceUpcomingParams) -> Result<Invoice, Error> {
    //     client.get(&format!("/invoices/upcoming?customer={}", invoice_id))
    // }

    /// Pays an invoice.
    ///
    /// For more details see https://stripe.com/docs/api#pay_invoice.
    pub fn pay(client: &Client, invoice_id: &str) -> Result<Invoice, Error> {
        client.post_empty(&format!("/invoices/{}/pay", invoice_id))
    }

    /// Updates an invoice.
    ///
    /// For more details see https://stripe.com/docs/api#update_invoice.
    pub fn update(client: &Client, invoice_id: &str, params: InvoiceParams) -> Result<Invoice, Error> {
        client.post(&format!("/invoices/{}", invoice_id), &params)
    }

    /// Lists all invoices.
    ///
    /// For more details see https://stripe.com/docs/api#list_invoices.
    pub fn list(client: &Client, params: InvoiceListParams) -> Result<List<Invoice>, Error> {
        client.get(&format!("/invoices?{}", qs::to_string(&params)?))
    }
}

impl InvoiceItem {
    /// Creates an invoice line item.
    ///
    /// For more details see https://stripe.com/docs/api/node#invoice_line_item_object
    pub fn create(client: &Client, params: InvoiceItemParams) -> Result<InvoiceItem, Error> {
        client.post(&format!("/invoiceitems"), &params)
    }
}
<|endoftext|>


<commit_before><commit_msg>Tweak input/output/kernel weights (1/21/3) (#2006)<commit_after><|endoftext|>


<commit_before>//! Store SBD messages on the filesystem.

use std::fs;
use std::path::{Path, PathBuf};

use walkdir;

use {Result, Error};
use mo::Message;
use storage;

const SBD_EXTENSION: &'static str = "sbd";

/// A structure for managing storing and retriving SBD messages on a filesystem.
///
/// Messages are stored in a directory hierarchy under a single root directory.
/// Message storage and retrieval are managed by a `Storage` object, which is
/// configured for a single root directory.
#[derive(Debug)]
pub struct Storage {
    root: PathBuf,
}

impl Storage {
    /// Opens a new storage for a given directory.
    ///
    /// # Errors
    ///
    /// If the directory does not exist, returns an `NotADirectory` error.
    ///
    /// # Examples
    ///
    /// ```
    /// use sbd::storage::FilesystemStorage;
    /// let storage = FilesystemStorage::open("data").unwrap();
    /// assert!(FilesystemStorage::open("not/a/directory").is_err());
    /// ```
    pub fn open<P: AsRef<Path>>(root: P) -> Result<Storage> {
        let metadata = try!(fs::metadata(root.as_ref()));
        if !metadata.is_dir() {
            Err(Error::NotADirectory(root.as_ref().as_os_str().to_os_string()))
        } else {
            Ok(Storage { root: root.as_ref().to_path_buf() })
        }
    }

    /// Returns a `StorageIterator` over the messages in this storage.
    ///
    /// # Examples
    ///
    /// ```
    /// use sbd::storage::FilesystemStorage;
    /// for message in FilesystemStorage::open("data").unwrap().iter() {
    ///     println!("{:?}", message);
    /// }
    /// ```
    pub fn iter(&self) -> StorageIterator {
        StorageIterator::new(&self.root)
    }
}

impl storage::Storage for Storage {
    fn store(&mut self, message: Message) -> Result<()> {
        let mut path_buf = self.root.clone();
        path_buf.push(message.imei());
        path_buf.push(message.time_of_session().format("%Y").to_string());
        path_buf.push(message.time_of_session().format("%m").to_string());
        try!(fs::create_dir_all(&path_buf));
        path_buf.push(message.time_of_session()
            .format(&format!("%y%m%d_%H%M%S.{}", SBD_EXTENSION))
            .to_string());
        let mut file = try!(fs::File::create(&path_buf));
        try!(message.write_to(&mut file));
        Ok(())
    }

    fn messages(&self) -> Result<Vec<Message>> {
        self.iter().collect()
    }

    fn messages_from_imei(&self, imei: &str) -> Result<Vec<Message>> {
        let mut path = self.root.clone();
        path.push(imei);
        StorageIterator::new(&path).collect()
    }
}

/// An iterator over the messages in a `Storage`.
///
/// For now, this iterator will just return all messages with an `sbd` extension under the root of
/// the storage tree. We could try to get smarter and mirror the pattern logic for saving, but for
/// now that's more work and complexity than we need.
///
/// # Errors
///
/// This iterator's `Item` is a `sbd::Result<Message>`, because a file with an `sbd` extension
/// might not convert to a message successfully.
#[allow(missing_debug_implementations)]
pub struct StorageIterator {
    iter: walkdir::Iter,
}

impl StorageIterator {
    fn new(root: &Path) -> StorageIterator {
        StorageIterator { iter: walkdir::WalkDir::new(root).into_iter() }
    }
}

impl Iterator for StorageIterator {
    type Item = Result<Message>;
    fn next(&mut self) -> Option<Self::Item> {
        self.iter
            .by_ref()
            .skip_while(|r| {
                r.as_ref()
                    .map(|d| d.path().extension().map_or(true, |e| e != SBD_EXTENSION))
                    .unwrap_or(true)
            })
            .next()
            .map(|r| r.map_err(Error::from).and_then(|d| Message::from_path(d.path())))
    }
}

#[cfg(test)]
mod tests {
    use std::path::PathBuf;

    extern crate tempdir;
    use self::tempdir::TempDir;

    use super::*;

    use mo::Message;
    use storage::Storage as StorageTrait;

    #[test]
    fn open() {
        Storage::open(TempDir::new("").unwrap().path()).unwrap();
    }

    #[test]
    fn no_directory() {
        assert!(Storage::open("not/a/real/directory").is_err());
    }

    #[test]
    fn file_is_error() {
        assert!(Storage::open("data/0-mo.sbd").is_err());
    }

    #[test]
    fn store() {
        let tempdir = TempDir::new("").unwrap();
        let mut storage = Storage::open(tempdir.path()).unwrap();
        let message = Message::from_path("data/0-mo.sbd").unwrap();
        storage.store(message).unwrap();
        let mut message_path = PathBuf::from(tempdir.path());
        message_path.push("300234063904190");
        message_path.push("2015");
        message_path.push("07");
        message_path.push("150709_181508.sbd");
        Message::from_path(message_path).unwrap();
    }

    #[test]
    fn iter() {
        let tempdir = TempDir::new("").unwrap();
        let mut storage = Storage::open(tempdir.path()).unwrap();
        assert_eq!(0, storage.iter().collect::<Vec<_>>().len());
        let message = Message::from_path("data/0-mo.sbd").unwrap();
        storage.store(message).unwrap();
        assert_eq!(1, storage.iter().collect::<Vec<_>>().len());
    }

    #[test]
    fn messages_from_imei() {
        let tempdir = TempDir::new("").unwrap();
        let mut storage = Storage::open(tempdir.path()).unwrap();
        let message = Message::from_path("data/0-mo.sbd").unwrap();
        storage.store(message.clone()).unwrap();
        let messages = storage.messages_from_imei("300234063904190").unwrap();
        assert_eq!(vec![message], messages);
        let messages = storage.messages_from_imei("300234063904191").unwrap();
        assert!(messages.is_empty());
    }

}
<commit_msg>Implement clone for FilesystemStorage<commit_after>//! Store SBD messages on the filesystem.

use std::fs;
use std::path::{Path, PathBuf};

use walkdir;

use {Result, Error};
use mo::Message;
use storage;

const SBD_EXTENSION: &'static str = "sbd";

/// A structure for managing storing and retriving SBD messages on a filesystem.
///
/// Messages are stored in a directory hierarchy under a single root directory.
/// Message storage and retrieval are managed by a `Storage` object, which is
/// configured for a single root directory.
#[derive(Clone, Debug)]
pub struct Storage {
    root: PathBuf,
}

impl Storage {
    /// Opens a new storage for a given directory.
    ///
    /// # Errors
    ///
    /// If the directory does not exist, returns an `NotADirectory` error.
    ///
    /// # Examples
    ///
    /// ```
    /// use sbd::storage::FilesystemStorage;
    /// let storage = FilesystemStorage::open("data").unwrap();
    /// assert!(FilesystemStorage::open("not/a/directory").is_err());
    /// ```
    pub fn open<P: AsRef<Path>>(root: P) -> Result<Storage> {
        let metadata = try!(fs::metadata(root.as_ref()));
        if !metadata.is_dir() {
            Err(Error::NotADirectory(root.as_ref().as_os_str().to_os_string()))
        } else {
            Ok(Storage { root: root.as_ref().to_path_buf() })
        }
    }

    /// Returns a `StorageIterator` over the messages in this storage.
    ///
    /// # Examples
    ///
    /// ```
    /// use sbd::storage::FilesystemStorage;
    /// for message in FilesystemStorage::open("data").unwrap().iter() {
    ///     println!("{:?}", message);
    /// }
    /// ```
    pub fn iter(&self) -> StorageIterator {
        StorageIterator::new(&self.root)
    }
}

impl storage::Storage for Storage {
    fn store(&mut self, message: Message) -> Result<()> {
        let mut path_buf = self.root.clone();
        path_buf.push(message.imei());
        path_buf.push(message.time_of_session().format("%Y").to_string());
        path_buf.push(message.time_of_session().format("%m").to_string());
        try!(fs::create_dir_all(&path_buf));
        path_buf.push(message.time_of_session()
            .format(&format!("%y%m%d_%H%M%S.{}", SBD_EXTENSION))
            .to_string());
        let mut file = try!(fs::File::create(&path_buf));
        try!(message.write_to(&mut file));
        Ok(())
    }

    fn messages(&self) -> Result<Vec<Message>> {
        self.iter().collect()
    }

    fn messages_from_imei(&self, imei: &str) -> Result<Vec<Message>> {
        let mut path = self.root.clone();
        path.push(imei);
        StorageIterator::new(&path).collect()
    }
}

/// An iterator over the messages in a `Storage`.
///
/// For now, this iterator will just return all messages with an `sbd` extension under the root of
/// the storage tree. We could try to get smarter and mirror the pattern logic for saving, but for
/// now that's more work and complexity than we need.
///
/// # Errors
///
/// This iterator's `Item` is a `sbd::Result<Message>`, because a file with an `sbd` extension
/// might not convert to a message successfully.
#[allow(missing_debug_implementations)]
pub struct StorageIterator {
    iter: walkdir::Iter,
}

impl StorageIterator {
    fn new(root: &Path) -> StorageIterator {
        StorageIterator { iter: walkdir::WalkDir::new(root).into_iter() }
    }
}

impl Iterator for StorageIterator {
    type Item = Result<Message>;
    fn next(&mut self) -> Option<Self::Item> {
        self.iter
            .by_ref()
            .skip_while(|r| {
                r.as_ref()
                    .map(|d| d.path().extension().map_or(true, |e| e != SBD_EXTENSION))
                    .unwrap_or(true)
            })
            .next()
            .map(|r| r.map_err(Error::from).and_then(|d| Message::from_path(d.path())))
    }
}

#[cfg(test)]
mod tests {
    use std::path::PathBuf;

    extern crate tempdir;
    use self::tempdir::TempDir;

    use super::*;

    use mo::Message;
    use storage::Storage as StorageTrait;

    #[test]
    fn open() {
        Storage::open(TempDir::new("").unwrap().path()).unwrap();
    }

    #[test]
    fn no_directory() {
        assert!(Storage::open("not/a/real/directory").is_err());
    }

    #[test]
    fn file_is_error() {
        assert!(Storage::open("data/0-mo.sbd").is_err());
    }

    #[test]
    fn store() {
        let tempdir = TempDir::new("").unwrap();
        let mut storage = Storage::open(tempdir.path()).unwrap();
        let message = Message::from_path("data/0-mo.sbd").unwrap();
        storage.store(message).unwrap();
        let mut message_path = PathBuf::from(tempdir.path());
        message_path.push("300234063904190");
        message_path.push("2015");
        message_path.push("07");
        message_path.push("150709_181508.sbd");
        Message::from_path(message_path).unwrap();
    }

    #[test]
    fn iter() {
        let tempdir = TempDir::new("").unwrap();
        let mut storage = Storage::open(tempdir.path()).unwrap();
        assert_eq!(0, storage.iter().collect::<Vec<_>>().len());
        let message = Message::from_path("data/0-mo.sbd").unwrap();
        storage.store(message).unwrap();
        assert_eq!(1, storage.iter().collect::<Vec<_>>().len());
    }

    #[test]
    fn messages_from_imei() {
        let tempdir = TempDir::new("").unwrap();
        let mut storage = Storage::open(tempdir.path()).unwrap();
        let message = Message::from_path("data/0-mo.sbd").unwrap();
        storage.store(message.clone()).unwrap();
        let messages = storage.messages_from_imei("300234063904190").unwrap();
        assert_eq!(vec![message], messages);
        let messages = storage.messages_from_imei("300234063904191").unwrap();
        assert!(messages.is_empty());
    }

}
<|endoftext|>


<commit_before>use context::CommandContext;
use version::Version;
use version::Api;
use gl;

use std::{ mem, fmt };
use std::error::Error;

use texture::any::TextureAny;
use TextureExt;
use GlObject;

/// Error that can happen when retrieving the internal format of a texture.
#[derive(Copy, Clone, Debug)]
pub enum GetFormatError {
    /// The backend doesn't support retrieving the internal format.
    NotSupported,
}

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

impl Error for GetFormatError {
    fn description(&self) -> &str {
        use self::GetFormatError::*;
        match *self {
            NotSupported =>
                "The backend doesn't support retrieving the internal format",
        }
    }
}

/// Internal format of a texture.
///
/// The actual format of a texture is not necessarily one of the predefined ones, so we have
/// to use a very generic description.
// TODO: change bits to be u16 for consistency with the rest of the library
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum InternalFormat {
    /// The format has one component.
    OneComponent {
        /// Type of the first component of the format.
        ty1: InternalFormatType,
        /// Number of bits of the first component.
        bits1: usize,
    },

    /// The format has two components.
    TwoComponents {
        /// Type of the first component of the format.
        ty1: InternalFormatType,
        /// Number of bits of the first component.
        bits1: usize,
        /// Type of the second component.
        ty2: InternalFormatType,
        /// Number of bits of the second component.
        bits2: usize,
    },

    /// The format has three components.
    ThreeComponents {
        /// Type of the first component of the format.
        ty1: InternalFormatType,
        /// Number of bits of the first component.
        bits1: usize,
        /// Type of the second component.
        ty2: InternalFormatType,
        /// Number of bits of the second component.
        bits2: usize,
        /// Type of the third component.
        ty3: InternalFormatType,
        /// Number of bits of the third component.
        bits3: usize,
    },

    /// The format has four components.
    FourComponents {
        /// Type of the first component of the format.
        ty1: InternalFormatType,
        /// Number of bits of the first component.
        bits1: usize,
        /// Type of the second component.
        ty2: InternalFormatType,
        /// Number of bits of the second component.
        bits2: usize,
        /// Type of the third component.
        ty3: InternalFormatType,
        /// Number of bits of the third component.
        bits3: usize,
        /// Type of the fourth component.
        ty4: InternalFormatType,
        /// Number of bits of the fourth component.
        bits4: usize,
    },
}

impl InternalFormat {
    /// Returns the total number of bits of this format.
    #[inline]
    pub fn get_total_bits(&self) -> usize {
        match self {
            &InternalFormat::OneComponent { bits1, .. } => bits1,
            &InternalFormat::TwoComponents { bits1, bits2, .. } => bits1 + bits2,
            &InternalFormat::ThreeComponents { bits1, bits2, bits3, .. } => bits1 + bits2 + bits3,
            &InternalFormat::FourComponents { bits1, bits2, bits3, bits4, .. } =>
                                                                    bits1 + bits2 + bits3 + bits4,
        }
    }
}

/// Format of a component of an internal format.
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum InternalFormatType {
    /// Floating point texture with signed components.
    SignedNormalized,
    /// Floating point texture with unsigned components.
    UnsignedNormalized,
    /// Floating point texture with floats.
    Float,
    /// Integral texture.
    Int,
    /// Unsigned texture.
    UnsignedInt,
}

impl InternalFormatType {
    /// Builds the `InternalFormatType` of the GLenum. Panics if the value is not recognized.
    #[inline]
    fn from_glenum(val: gl::types::GLenum) -> InternalFormatType {
        match val {
            gl::SIGNED_NORMALIZED => InternalFormatType::SignedNormalized,
            gl::UNSIGNED_NORMALIZED => InternalFormatType::UnsignedNormalized,
            gl::FLOAT => InternalFormatType::Float,
            gl::INT => InternalFormatType::Int,
            gl::UNSIGNED_INT => InternalFormatType::UnsignedInt,
            gl::NONE => unreachable!(),     // separating this case for easier debugging
            _ => unreachable!(),
        }
    }
}

/// Determines the format of a texture.
///
/// A `TextureAny` is guaranteed to have the same format for each mipmap.
pub fn get_format(ctxt: &mut CommandContext, texture: &TextureAny)
                  -> Result<InternalFormat, GetFormatError>
{
    if ctxt.version >= &Version(Api::Gl, 3, 0) || ctxt.version >= &Version(Api::GlEs, 3, 0) {
        #[allow(deprecated)] // For uninitialized()
        let (red_sz, red_ty, green_sz, green_ty, blue_sz, blue_ty,
             alpha_sz, alpha_ty, depth_sz, depth_ty) = unsafe
        {
            let mut red_sz = mem::uninitialized();
            let mut red_ty = mem::uninitialized();
            let mut green_sz = mem::uninitialized();
            let mut green_ty = mem::uninitialized();
            let mut blue_sz = mem::uninitialized();
            let mut blue_ty = mem::uninitialized();
            let mut alpha_sz = mem::uninitialized();
            let mut alpha_ty = mem::uninitialized();
            let mut depth_sz = mem::uninitialized();
            let mut depth_ty = mem::uninitialized();

            if ctxt.version >= &Version(Api::Gl, 4, 5) ||
               ctxt.extensions.gl_arb_direct_state_access
            {
                let id = texture.get_id();
                ctxt.gl.GetTextureLevelParameteriv(id, 0, gl::TEXTURE_RED_SIZE, &mut red_sz);
                ctxt.gl.GetTextureLevelParameteriv(id, 0, gl::TEXTURE_RED_TYPE, &mut red_ty);
                ctxt.gl.GetTextureLevelParameteriv(id, 0, gl::TEXTURE_GREEN_SIZE, &mut green_sz);
                ctxt.gl.GetTextureLevelParameteriv(id, 0, gl::TEXTURE_GREEN_TYPE, &mut green_ty);
                ctxt.gl.GetTextureLevelParameteriv(id, 0, gl::TEXTURE_BLUE_SIZE, &mut blue_sz);
                ctxt.gl.GetTextureLevelParameteriv(id, 0, gl::TEXTURE_BLUE_TYPE, &mut blue_ty);
                ctxt.gl.GetTextureLevelParameteriv(id, 0, gl::TEXTURE_ALPHA_SIZE, &mut alpha_sz);
                ctxt.gl.GetTextureLevelParameteriv(id, 0, gl::TEXTURE_ALPHA_TYPE, &mut alpha_ty);
                ctxt.gl.GetTextureLevelParameteriv(id, 0, gl::TEXTURE_DEPTH_SIZE, &mut depth_sz);
                ctxt.gl.GetTextureLevelParameteriv(id, 0, gl::TEXTURE_DEPTH_TYPE, &mut depth_ty);

            } else if ctxt.extensions.gl_ext_direct_state_access {
                let id = texture.get_id();
                let bind_point = texture.get_bind_point();

                ctxt.gl.GetTextureLevelParameterivEXT(id, bind_point, 0, gl::TEXTURE_RED_SIZE,
                                                      &mut red_sz);
                ctxt.gl.GetTextureLevelParameterivEXT(id, bind_point, 0, gl::TEXTURE_RED_TYPE,
                                                      &mut red_ty);
                ctxt.gl.GetTextureLevelParameterivEXT(id, bind_point, 0, gl::TEXTURE_GREEN_SIZE,
                                                      &mut green_sz);
                ctxt.gl.GetTextureLevelParameterivEXT(id, bind_point, 0, gl::TEXTURE_GREEN_TYPE,
                                                      &mut green_ty);
                ctxt.gl.GetTextureLevelParameterivEXT(id, bind_point, 0, gl::TEXTURE_BLUE_SIZE,
                                                      &mut blue_sz);
                ctxt.gl.GetTextureLevelParameterivEXT(id, bind_point, 0, gl::TEXTURE_BLUE_TYPE,
                                                      &mut blue_ty);
                ctxt.gl.GetTextureLevelParameterivEXT(id, bind_point, 0, gl::TEXTURE_ALPHA_SIZE,
                                                      &mut alpha_sz);
                ctxt.gl.GetTextureLevelParameterivEXT(id, bind_point, 0, gl::TEXTURE_ALPHA_TYPE,
                                                      &mut alpha_ty);
                ctxt.gl.GetTextureLevelParameterivEXT(id, bind_point, 0, gl::TEXTURE_DEPTH_SIZE,
                                                      &mut depth_sz);
                ctxt.gl.GetTextureLevelParameterivEXT(id, bind_point, 0, gl::TEXTURE_DEPTH_TYPE,
                                                      &mut depth_ty);

            } else {
                let bind_point = texture.bind_to_current(ctxt);
                ctxt.gl.GetTexLevelParameteriv(bind_point, 0, gl::TEXTURE_RED_SIZE, &mut red_sz);
                ctxt.gl.GetTexLevelParameteriv(bind_point, 0, gl::TEXTURE_RED_TYPE, &mut red_ty);
                ctxt.gl.GetTexLevelParameteriv(bind_point, 0, gl::TEXTURE_GREEN_SIZE,
                                               &mut green_sz);
                ctxt.gl.GetTexLevelParameteriv(bind_point, 0, gl::TEXTURE_GREEN_TYPE,
                                               &mut green_ty);
                ctxt.gl.GetTexLevelParameteriv(bind_point, 0, gl::TEXTURE_BLUE_SIZE, &mut blue_sz);
                ctxt.gl.GetTexLevelParameteriv(bind_point, 0, gl::TEXTURE_BLUE_TYPE, &mut blue_ty);
                ctxt.gl.GetTexLevelParameteriv(bind_point, 0, gl::TEXTURE_ALPHA_SIZE,
                                               &mut alpha_sz);
                ctxt.gl.GetTexLevelParameteriv(bind_point, 0, gl::TEXTURE_ALPHA_TYPE,
                                               &mut alpha_ty);
                ctxt.gl.GetTexLevelParameteriv(bind_point, 0, gl::TEXTURE_DEPTH_SIZE,
                                               &mut depth_sz);
                ctxt.gl.GetTexLevelParameteriv(bind_point, 0, gl::TEXTURE_DEPTH_TYPE,
                                               &mut depth_ty);
            }

            (red_sz as gl::types::GLenum, red_ty as gl::types::GLenum,
             green_sz as gl::types::GLenum, green_ty as gl::types::GLenum,
             blue_sz as gl::types::GLenum, blue_ty as gl::types::GLenum,
             alpha_sz as gl::types::GLenum, alpha_ty as gl::types::GLenum,
             depth_sz as gl::types::GLenum, depth_ty as gl::types::GLenum)
        };

        Ok(match (red_sz, red_ty, green_sz, green_ty, blue_sz, blue_ty,
               alpha_sz, alpha_ty, depth_sz, depth_ty)
        {
            (_, gl::NONE, _, _, _, _, _, _, sz1, ty1) => InternalFormat::OneComponent {
                ty1: InternalFormatType::from_glenum(ty1),
                bits1: sz1 as usize,
            },
            (sz1, ty1, _, gl::NONE, _, _, _, _, _, _) => InternalFormat::OneComponent {
                ty1: InternalFormatType::from_glenum(ty1),
                bits1: sz1 as usize,
            },
            (sz1, ty1, sz2, ty2, _, gl::NONE, _, _, _, _) => InternalFormat::TwoComponents {
                ty1: InternalFormatType::from_glenum(ty1),
                bits1: sz1 as usize,
                ty2: InternalFormatType::from_glenum(ty2),
                bits2: sz2 as usize,
            },
            (sz1, ty1, sz2, ty2, sz3, ty3, _, gl::NONE, _, _) => InternalFormat::ThreeComponents {
                ty1: InternalFormatType::from_glenum(ty1),
                bits1: sz1 as usize,
                ty2: InternalFormatType::from_glenum(ty2),
                bits2: sz2 as usize,
                ty3: InternalFormatType::from_glenum(ty3),
                bits3: sz3 as usize,
            },
            (sz1, ty1, sz2, ty2, sz3, ty3, sz4, ty4, _, gl::NONE) => InternalFormat::FourComponents {
                ty1: InternalFormatType::from_glenum(ty1),
                bits1: sz1 as usize,
                ty2: InternalFormatType::from_glenum(ty2),
                bits2: sz2 as usize,
                ty3: InternalFormatType::from_glenum(ty3),
                bits3: sz3 as usize,
                ty4: InternalFormatType::from_glenum(ty4),
                bits4: sz4 as usize,
            },
            _ => unreachable!()
        })

    } else {
        // FIXME: GL2
        Err(GetFormatError::NotSupported)
    }
}
<commit_msg>lots of ints<commit_after>use context::CommandContext;
use version::Version;
use version::Api;
use gl;

use std::{ mem, fmt };
use std::error::Error;

use texture::any::TextureAny;
use TextureExt;
use GlObject;

/// Error that can happen when retrieving the internal format of a texture.
#[derive(Copy, Clone, Debug)]
pub enum GetFormatError {
    /// The backend doesn't support retrieving the internal format.
    NotSupported,
}

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

impl Error for GetFormatError {
    fn description(&self) -> &str {
        use self::GetFormatError::*;
        match *self {
            NotSupported =>
                "The backend doesn't support retrieving the internal format",
        }
    }
}

/// Internal format of a texture.
///
/// The actual format of a texture is not necessarily one of the predefined ones, so we have
/// to use a very generic description.
// TODO: change bits to be u16 for consistency with the rest of the library
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum InternalFormat {
    /// The format has one component.
    OneComponent {
        /// Type of the first component of the format.
        ty1: InternalFormatType,
        /// Number of bits of the first component.
        bits1: usize,
    },

    /// The format has two components.
    TwoComponents {
        /// Type of the first component of the format.
        ty1: InternalFormatType,
        /// Number of bits of the first component.
        bits1: usize,
        /// Type of the second component.
        ty2: InternalFormatType,
        /// Number of bits of the second component.
        bits2: usize,
    },

    /// The format has three components.
    ThreeComponents {
        /// Type of the first component of the format.
        ty1: InternalFormatType,
        /// Number of bits of the first component.
        bits1: usize,
        /// Type of the second component.
        ty2: InternalFormatType,
        /// Number of bits of the second component.
        bits2: usize,
        /// Type of the third component.
        ty3: InternalFormatType,
        /// Number of bits of the third component.
        bits3: usize,
    },

    /// The format has four components.
    FourComponents {
        /// Type of the first component of the format.
        ty1: InternalFormatType,
        /// Number of bits of the first component.
        bits1: usize,
        /// Type of the second component.
        ty2: InternalFormatType,
        /// Number of bits of the second component.
        bits2: usize,
        /// Type of the third component.
        ty3: InternalFormatType,
        /// Number of bits of the third component.
        bits3: usize,
        /// Type of the fourth component.
        ty4: InternalFormatType,
        /// Number of bits of the fourth component.
        bits4: usize,
    },
}

impl InternalFormat {
    /// Returns the total number of bits of this format.
    #[inline]
    pub fn get_total_bits(&self) -> usize {
        match self {
            &InternalFormat::OneComponent { bits1, .. } => bits1,
            &InternalFormat::TwoComponents { bits1, bits2, .. } => bits1 + bits2,
            &InternalFormat::ThreeComponents { bits1, bits2, bits3, .. } => bits1 + bits2 + bits3,
            &InternalFormat::FourComponents { bits1, bits2, bits3, bits4, .. } =>
                                                                    bits1 + bits2 + bits3 + bits4,
        }
    }
}

/// Format of a component of an internal format.
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum InternalFormatType {
    /// Floating point texture with signed components.
    SignedNormalized,
    /// Floating point texture with unsigned components.
    UnsignedNormalized,
    /// Floating point texture with floats.
    Float,
    /// Integral texture.
    Int,
    /// Unsigned texture.
    UnsignedInt,
}

impl InternalFormatType {
    /// Builds the `InternalFormatType` of the GLenum. Panics if the value is not recognized.
    #[inline]
    fn from_glenum(val: gl::types::GLenum) -> InternalFormatType {
        match val {
            gl::SIGNED_NORMALIZED => InternalFormatType::SignedNormalized,
            gl::UNSIGNED_NORMALIZED => InternalFormatType::UnsignedNormalized,
            gl::FLOAT => InternalFormatType::Float,
            gl::INT => InternalFormatType::Int,
            gl::UNSIGNED_INT => InternalFormatType::UnsignedInt,
            gl::NONE => unreachable!(),     // separating this case for easier debugging
            _ => unreachable!(),
        }
    }
}

/// Determines the format of a texture.
///
/// A `TextureAny` is guaranteed to have the same format for each mipmap.
pub fn get_format(ctxt: &mut CommandContext, texture: &TextureAny)
                  -> Result<InternalFormat, GetFormatError>
{
    if ctxt.version >= &Version(Api::Gl, 3, 0) || ctxt.version >= &Version(Api::GlEs, 3, 0) {
        #[allow(deprecated)] // For uninitialized()
        let (red_sz, red_ty, green_sz, green_ty, blue_sz, blue_ty,
             alpha_sz, alpha_ty, depth_sz, depth_ty) = unsafe
        {
            let mut red_sz = 0;
            let mut red_ty = 0;
            let mut green_sz = 0;
            let mut green_ty = 0;
            let mut blue_sz = 0;
            let mut blue_ty = 0;
            let mut alpha_sz = 0;
            let mut alpha_ty = 0;
            let mut depth_sz = 0;
            let mut depth_ty = 0;

            if ctxt.version >= &Version(Api::Gl, 4, 5) ||
               ctxt.extensions.gl_arb_direct_state_access
            {
                let id = texture.get_id();
                ctxt.gl.GetTextureLevelParameteriv(id, 0, gl::TEXTURE_RED_SIZE, &mut red_sz);
                ctxt.gl.GetTextureLevelParameteriv(id, 0, gl::TEXTURE_RED_TYPE, &mut red_ty);
                ctxt.gl.GetTextureLevelParameteriv(id, 0, gl::TEXTURE_GREEN_SIZE, &mut green_sz);
                ctxt.gl.GetTextureLevelParameteriv(id, 0, gl::TEXTURE_GREEN_TYPE, &mut green_ty);
                ctxt.gl.GetTextureLevelParameteriv(id, 0, gl::TEXTURE_BLUE_SIZE, &mut blue_sz);
                ctxt.gl.GetTextureLevelParameteriv(id, 0, gl::TEXTURE_BLUE_TYPE, &mut blue_ty);
                ctxt.gl.GetTextureLevelParameteriv(id, 0, gl::TEXTURE_ALPHA_SIZE, &mut alpha_sz);
                ctxt.gl.GetTextureLevelParameteriv(id, 0, gl::TEXTURE_ALPHA_TYPE, &mut alpha_ty);
                ctxt.gl.GetTextureLevelParameteriv(id, 0, gl::TEXTURE_DEPTH_SIZE, &mut depth_sz);
                ctxt.gl.GetTextureLevelParameteriv(id, 0, gl::TEXTURE_DEPTH_TYPE, &mut depth_ty);

            } else if ctxt.extensions.gl_ext_direct_state_access {
                let id = texture.get_id();
                let bind_point = texture.get_bind_point();

                ctxt.gl.GetTextureLevelParameterivEXT(id, bind_point, 0, gl::TEXTURE_RED_SIZE,
                                                      &mut red_sz);
                ctxt.gl.GetTextureLevelParameterivEXT(id, bind_point, 0, gl::TEXTURE_RED_TYPE,
                                                      &mut red_ty);
                ctxt.gl.GetTextureLevelParameterivEXT(id, bind_point, 0, gl::TEXTURE_GREEN_SIZE,
                                                      &mut green_sz);
                ctxt.gl.GetTextureLevelParameterivEXT(id, bind_point, 0, gl::TEXTURE_GREEN_TYPE,
                                                      &mut green_ty);
                ctxt.gl.GetTextureLevelParameterivEXT(id, bind_point, 0, gl::TEXTURE_BLUE_SIZE,
                                                      &mut blue_sz);
                ctxt.gl.GetTextureLevelParameterivEXT(id, bind_point, 0, gl::TEXTURE_BLUE_TYPE,
                                                      &mut blue_ty);
                ctxt.gl.GetTextureLevelParameterivEXT(id, bind_point, 0, gl::TEXTURE_ALPHA_SIZE,
                                                      &mut alpha_sz);
                ctxt.gl.GetTextureLevelParameterivEXT(id, bind_point, 0, gl::TEXTURE_ALPHA_TYPE,
                                                      &mut alpha_ty);
                ctxt.gl.GetTextureLevelParameterivEXT(id, bind_point, 0, gl::TEXTURE_DEPTH_SIZE,
                                                      &mut depth_sz);
                ctxt.gl.GetTextureLevelParameterivEXT(id, bind_point, 0, gl::TEXTURE_DEPTH_TYPE,
                                                      &mut depth_ty);

            } else {
                let bind_point = texture.bind_to_current(ctxt);
                ctxt.gl.GetTexLevelParameteriv(bind_point, 0, gl::TEXTURE_RED_SIZE, &mut red_sz);
                ctxt.gl.GetTexLevelParameteriv(bind_point, 0, gl::TEXTURE_RED_TYPE, &mut red_ty);
                ctxt.gl.GetTexLevelParameteriv(bind_point, 0, gl::TEXTURE_GREEN_SIZE,
                                               &mut green_sz);
                ctxt.gl.GetTexLevelParameteriv(bind_point, 0, gl::TEXTURE_GREEN_TYPE,
                                               &mut green_ty);
                ctxt.gl.GetTexLevelParameteriv(bind_point, 0, gl::TEXTURE_BLUE_SIZE, &mut blue_sz);
                ctxt.gl.GetTexLevelParameteriv(bind_point, 0, gl::TEXTURE_BLUE_TYPE, &mut blue_ty);
                ctxt.gl.GetTexLevelParameteriv(bind_point, 0, gl::TEXTURE_ALPHA_SIZE,
                                               &mut alpha_sz);
                ctxt.gl.GetTexLevelParameteriv(bind_point, 0, gl::TEXTURE_ALPHA_TYPE,
                                               &mut alpha_ty);
                ctxt.gl.GetTexLevelParameteriv(bind_point, 0, gl::TEXTURE_DEPTH_SIZE,
                                               &mut depth_sz);
                ctxt.gl.GetTexLevelParameteriv(bind_point, 0, gl::TEXTURE_DEPTH_TYPE,
                                               &mut depth_ty);
            }

            (red_sz as gl::types::GLenum, red_ty as gl::types::GLenum,
             green_sz as gl::types::GLenum, green_ty as gl::types::GLenum,
             blue_sz as gl::types::GLenum, blue_ty as gl::types::GLenum,
             alpha_sz as gl::types::GLenum, alpha_ty as gl::types::GLenum,
             depth_sz as gl::types::GLenum, depth_ty as gl::types::GLenum)
        };

        Ok(match (red_sz, red_ty, green_sz, green_ty, blue_sz, blue_ty,
               alpha_sz, alpha_ty, depth_sz, depth_ty)
        {
            (_, gl::NONE, _, _, _, _, _, _, sz1, ty1) => InternalFormat::OneComponent {
                ty1: InternalFormatType::from_glenum(ty1),
                bits1: sz1 as usize,
            },
            (sz1, ty1, _, gl::NONE, _, _, _, _, _, _) => InternalFormat::OneComponent {
                ty1: InternalFormatType::from_glenum(ty1),
                bits1: sz1 as usize,
            },
            (sz1, ty1, sz2, ty2, _, gl::NONE, _, _, _, _) => InternalFormat::TwoComponents {
                ty1: InternalFormatType::from_glenum(ty1),
                bits1: sz1 as usize,
                ty2: InternalFormatType::from_glenum(ty2),
                bits2: sz2 as usize,
            },
            (sz1, ty1, sz2, ty2, sz3, ty3, _, gl::NONE, _, _) => InternalFormat::ThreeComponents {
                ty1: InternalFormatType::from_glenum(ty1),
                bits1: sz1 as usize,
                ty2: InternalFormatType::from_glenum(ty2),
                bits2: sz2 as usize,
                ty3: InternalFormatType::from_glenum(ty3),
                bits3: sz3 as usize,
            },
            (sz1, ty1, sz2, ty2, sz3, ty3, sz4, ty4, _, gl::NONE) => InternalFormat::FourComponents {
                ty1: InternalFormatType::from_glenum(ty1),
                bits1: sz1 as usize,
                ty2: InternalFormatType::from_glenum(ty2),
                bits2: sz2 as usize,
                ty3: InternalFormatType::from_glenum(ty3),
                bits3: sz3 as usize,
                ty4: InternalFormatType::from_glenum(ty4),
                bits4: sz4 as usize,
            },
            _ => unreachable!()
        })

    } else {
        // FIXME: GL2
        Err(GetFormatError::NotSupported)
    }
}
<|endoftext|>


<commit_before>// TODO Disable interrupt before entering those.
use spin::{Mutex};
use core::mem::{size_of};
use core::slice;
use utils::{align_down, block_count};
use core::ptr::{Unique};
use super::{PTEntry, PT_P, PT_RW, flush, BASE_PAGE_LENGTH};
use arch::init::{object_pool_pt, object_pool_pt_mut, OBJECT_POOL_SIZE, OBJECT_POOL_START_VADDR};
use common::{PAddr, VAddr};

static _next_free: Mutex<usize> = Mutex::new(0);

pub unsafe fn with_object_vaddr<Return, F: FnOnce(VAddr) -> Return>(paddr: PAddr, size: usize, f: F)
                                                                -> Return {
    let aligned = align_down(paddr, BASE_PAGE_LENGTH);
    let before_start = paddr.into(): usize - aligned.into(): usize;
    let required_page_size = block_count((paddr + size).into(): usize - aligned.into(): usize,
                                         BASE_PAGE_LENGTH);

    let next_free_base;

    {
        let mut next_free = _next_free.lock();
        next_free_base = *next_free;

        for i in 0..required_page_size {
            object_pool_pt_mut()[next_free_base + i] = PTEntry::new(aligned + (i * BASE_PAGE_LENGTH), PT_P | PT_RW);
            unsafe { flush(OBJECT_POOL_START_VADDR + (next_free_base * BASE_PAGE_LENGTH) + i * BASE_PAGE_LENGTH); }
        }

        *next_free = next_free_base + required_page_size;
    }

    let vaddr = OBJECT_POOL_START_VADDR + ((next_free_base * BASE_PAGE_LENGTH) + before_start);

    let result = f(vaddr);

    {
        let mut next_free = _next_free.lock();
        assert!(next_free_base == (*next_free - required_page_size));

        for i in 0..required_page_size {
            object_pool_pt_mut()[next_free_base + i] = PTEntry::empty();
            unsafe { flush(OBJECT_POOL_START_VADDR + (next_free_base * BASE_PAGE_LENGTH) + i * BASE_PAGE_LENGTH); }
        }

        *next_free = next_free_base;
    }

    result
}

pub unsafe fn with_object_unique<T, Return, F: FnOnce(Unique<T>) -> Return>(paddr: PAddr, f: F)
                                                                            -> Return {
    let size = size_of::<T>();
    with_object_vaddr(paddr, size, |vaddr| {
        let unique = unsafe {
            Unique::new(vaddr.into(): usize as *mut T) };
        f(unique)
    })
}

pub unsafe fn with_slice<T, Return, F: FnOnce(&[T]) -> Return>(paddr: PAddr, size: usize, f: F)
                                                               -> Return {
    let allsize = size * (size_of::<T>());
    with_object_vaddr(paddr, allsize, |vaddr| {
        let slice = unsafe {
            slice::from_raw_parts::<T>(vaddr.into(): usize as *const _, allsize) };
        f(slice)
    })
}

pub unsafe fn with_slice_mut<T, Return, F: FnOnce(&mut [T]) -> Return>(paddr: PAddr, size: usize, f: F)
                                                                       -> Return {
    let allsize = size * (size_of::<T>());
    with_object_vaddr(paddr, allsize, |vaddr| {
        let mut slice = unsafe {
            slice::from_raw_parts_mut::<T>(vaddr.into(): usize as *mut _, allsize) };
        f(slice)
    })
}

pub unsafe fn with_object<T, Return, F: FnOnce(&T) -> Return>(paddr: PAddr, f: F) -> Return {
    with_object_unique(paddr, |unique| {
        f(unsafe { unique.get() })
    })
}

pub unsafe fn with_object_mut<T, Return, F: FnOnce(&mut T) -> Return>(paddr: PAddr, f: F) -> Return {
    with_object_unique(paddr, |mut unique| {
        f(unsafe { unique.get_mut() })
    })
}
<commit_msg>WIP: ObjectGuard<commit_after>// TODO Disable interrupt before entering those.
use spin::{Mutex};
use core::mem::{size_of};
use core::slice;
use utils::{align_down, block_count};
use core::ptr::{Unique};
use super::{PTEntry, PT_P, PT_RW, flush, BASE_PAGE_LENGTH};
use arch::init::{object_pool_pt, object_pool_pt_mut, OBJECT_POOL_SIZE, OBJECT_POOL_START_VADDR};
use common::{PAddr, VAddr};

static _next_free: Mutex<usize> = Mutex::new(0);

pub struct ObjectGuard<T: Sized> {
    mapping_start_index: usize,
    mapping_size: usize,
    pointer: NonZero<*const T>,
    _marker: PhantomData<T>,
}

impl<T: Sized> ObjectGuard<T> {
    pub unsafe fn new(paddr: PAddr) -> ObjectGuard<T> {
        let aligned = align_down(paddr, BASE_PAGE_LENGTH);
        let before_start = paddr.into(): usize - aligned.into(): usize;
        let size = size_of::<T>();
        let required_page_size = block_count((paddr + size).into(): usize - aligned.into(): usize,
                                             BASE_PAGE_LENGTH);

        let object_pool = object_pool_pt_mut();
        let mapping_start_index: usize = {
            let mut mapping_start_index: Option<usize> = None;

            for i in 0..object_pool.len() {
                let available = true;
                for j in 0..required_page_size {
                    if object_pool[i + j].is_present() {
                        available = false;
                        break;
                    }
                }

                if available {
                    mapping_start_index = Some(i);
                    break;
                }
            }

            mapping_start_index
        }.unwrap();

        for i in 0..required_page_size {
            object_pool[mapping_start_index + i] = PTEntry::new(aligned + (i * BASE_PAGE_LENGTH), PT_P | PT_RW);
            unsafe { flush(OBJECT_POOL_START_VADDR + (mapping_start_index * BASE_PAGE_LENGTH) + i * BASE_PAGE_LENGTH); }
        }

        let vaddr = OBJECT_POOL_START_VADDR + ((mapping_start_index * BASE_PAGE_LENGTH) + before_start);

        ObjectGuard::<T> {
            mapping_start_index: mapping_start_index,
            mapping_size: required_page_size,
            pointer: NonZero::new(vaddr.into(): usize as *mut T),
            _marker: PhantomData
        }
    }
}

impl<T: Sized> Drop for ObjectGuard<T> {
    fn drop(&mut self) {
        let object_pool = object_pool_pt_mut();

        for i in 0..self.mapping_size {
            object_pool[self.mapping_start_index + i] = PTEntry::empty();
            unsafe { flush(OBJECT_POOL_START_VADDR + (self.mapping_start_index * BASE_PAGE_LENGTH) + i * BASE_PAGE_LENGTH); }
        }
    }
}

pub unsafe fn with_object_vaddr<Return, F: FnOnce(VAddr) -> Return>(paddr: PAddr, size: usize, f: F)
                                                                -> Return {
    let aligned = align_down(paddr, BASE_PAGE_LENGTH);
    let before_start = paddr.into(): usize - aligned.into(): usize;
    let required_page_size = block_count((paddr + size).into(): usize - aligned.into(): usize,
                                         BASE_PAGE_LENGTH);

    let next_free_base;

    {
        let mut next_free = _next_free.lock();
        next_free_base = *next_free;

        for i in 0..required_page_size {
            object_pool_pt_mut()[next_free_base + i] = PTEntry::new(aligned + (i * BASE_PAGE_LENGTH), PT_P | PT_RW);
            unsafe { flush(OBJECT_POOL_START_VADDR + (next_free_base * BASE_PAGE_LENGTH) + i * BASE_PAGE_LENGTH); }
        }

        *next_free = next_free_base + required_page_size;
    }

    let vaddr = OBJECT_POOL_START_VADDR + ((next_free_base * BASE_PAGE_LENGTH) + before_start);

    let result = f(vaddr);

    {
        let mut next_free = _next_free.lock();
        assert!(next_free_base == (*next_free - required_page_size));

        for i in 0..required_page_size {
            object_pool_pt_mut()[next_free_base + i] = PTEntry::empty();
            unsafe { flush(OBJECT_POOL_START_VADDR + (next_free_base * BASE_PAGE_LENGTH) + i * BASE_PAGE_LENGTH); }
        }

        *next_free = next_free_base;
    }

    result
}

pub unsafe fn with_object_unique<T, Return, F: FnOnce(Unique<T>) -> Return>(paddr: PAddr, f: F)
                                                                            -> Return {
    let size = size_of::<T>();
    with_object_vaddr(paddr, size, |vaddr| {
        let unique = unsafe {
            Unique::new(vaddr.into(): usize as *mut T) };
        f(unique)
    })
}

pub unsafe fn with_slice<T, Return, F: FnOnce(&[T]) -> Return>(paddr: PAddr, size: usize, f: F)
                                                               -> Return {
    let allsize = size * (size_of::<T>());
    with_object_vaddr(paddr, allsize, |vaddr| {
        let slice = unsafe {
            slice::from_raw_parts::<T>(vaddr.into(): usize as *const _, allsize) };
        f(slice)
    })
}

pub unsafe fn with_slice_mut<T, Return, F: FnOnce(&mut [T]) -> Return>(paddr: PAddr, size: usize, f: F)
                                                                       -> Return {
    let allsize = size * (size_of::<T>());
    with_object_vaddr(paddr, allsize, |vaddr| {
        let mut slice = unsafe {
            slice::from_raw_parts_mut::<T>(vaddr.into(): usize as *mut _, allsize) };
        f(slice)
    })
}

pub unsafe fn with_object<T, Return, F: FnOnce(&T) -> Return>(paddr: PAddr, f: F) -> Return {
    with_object_unique(paddr, |unique| {
        f(unsafe { unique.get() })
    })
}

pub unsafe fn with_object_mut<T, Return, F: FnOnce(&mut T) -> Return>(paddr: PAddr, f: F) -> Return {
    with_object_unique(paddr, |mut unique| {
        f(unsafe { unique.get_mut() })
    })
}
<|endoftext|>


<commit_before>#![allow(non_upper_case_globals)]
extern crate libc;

use keycode::{MOD_2, Keystroke};
use layout::Rect;
use std::ptr::null_mut;
use std::mem::{uninitialized, transmute};
use std::str::raw::c_str_to_static_slice;
use self::libc::{c_void, c_int, c_char};
use self::libc::funcs::c95::stdlib::malloc;
use self::XlibEvent::*;
use xlib::*;

extern fn error_handler(display: *mut Display, event: *mut XErrorEvent) -> c_int {
  // TODO: proper error handling
  // HACK: fixes LeaveNotify on invalid windows
  return 0;
}

const KeyPress               : i32 = 2;
const EnterNotify            : i32 = 7;
const FocusOut               : i32 = 10;
const Destroy                : i32 = 17;
const MapRequest             : i32 = 20;
const ConfigureRequest       : i32 = 23;

pub struct XlibWindowSystem {
  display:   *mut Display,
  root:      Window,
  event:     *mut c_void
}

pub enum XlibEvent {
  XMapRequest(Window),
  XConfigurationRequest(Window, WindowChanges, u32),
  XDestroy(Window),
  XEnterNotify(Window),
  XFocusOut(Window),
  XKeyPress(Window, Keystroke),
  Ignored
}

pub struct WindowChanges {
  pub x: u32,
  pub y: u32,
  pub width: u32,
  pub height: u32,
  pub border_width: u32,
  pub sibling: Window,
  pub stack_mode: u32,
}

impl XlibWindowSystem {
  pub fn new() -> Option<XlibWindowSystem> {
    unsafe {
      let display = XOpenDisplay(null_mut());
      if display.is_null() {
        return None;
      }

      let root = XDefaultRootWindow(display);
      XSelectInput(display, root, 0x1A0035);

      XSetErrorHandler(error_handler as *mut u8);

      Some(XlibWindowSystem{
        display: display,
        root: root,
        event: malloc(256)
      })
    }
  }

  pub fn setup_window(&self, x: u32, y: u32, width: u32, height: u32, border_width: u32, border_color: u32, window: Window) {
    self.set_window_border_width(window, border_width);
    self.set_window_border_color(window, border_color);
    self.move_resize_window(window, x, y, width - (2 * border_width), height - (2 * border_width));
  }

  pub fn configure_window(&mut self, window: Window, window_changes: WindowChanges, mask: u32) {
    unsafe {
      let mut ret_window_changes = XWindowChanges{
        x: window_changes.x as i32,
        y: window_changes.y as i32,
        width: window_changes.width as i32,
        height: window_changes.height as i32,
        border_width: window_changes.border_width as i32,
        sibling: window_changes.sibling,
        stack_mode: window_changes.stack_mode as i32
      };
      XConfigureWindow(self.display, window, mask, &mut ret_window_changes);
    }
  }

  pub fn new_vroot(&self) -> Window {
    unsafe {
      let window = XCreateSimpleWindow(self.display, self.root, 0, 0, self.get_display_width(0), self.get_display_height(0), 0, 0, 0);
      XMapWindow(self.display, window);
      window
    }
  }

  pub fn map_to_parent(&self, parent: Window, window: Window) {
    unsafe {
      XReparentWindow(self.display, window, parent, 0, 0);
      XMapWindow(self.display, window);
    }
  }

  pub fn move_resize_window(&self, window: Window, x: u32, y: u32, width: u32, height: u32) {
    unsafe {
      XMoveResizeWindow(self.display, window, x as i32, y as i32, width, height);
    }
  }

  pub fn raise_window(&self, window: Window) {
    unsafe {
      XRaiseWindow(self.display, window);
    }
  }

  pub fn focus_window(&self, window: Window, color: u32) {
    unsafe {
      XSetInputFocus(self.display, window, 1, 0);
      XSetWindowBorder(self.display, window, color);
    }
  }

  pub fn kill_window(&self, window: Window) {
    unsafe {
      XKillClient(self.display, window);
    }
  }

  pub fn sync(&self) {
    unsafe {
      XSync(self.display, 1);
    }
  }

  pub fn grab_modifier(&self, mod_key: u8) {
    unsafe {
      XGrabKey(self.display, 0, mod_key as u32, self.root, 1, 0, 1);
      XGrabKey(self.display, 0, (mod_key | MOD_2) as u32, self.root, 1, 0, 1 );
    }
  }

  pub fn keycode_to_string(&self, keycode: u32) -> String {
    unsafe {
      let keysym = XKeycodeToKeysym(self.display, keycode as u8, 0);
      String::from_str(c_str_to_static_slice(transmute(XKeysymToString(keysym))))
    }
  }

  pub fn set_window_border_width(&self, window: Window, width: u32) {
    if window != self.root {
      unsafe {
        XSetWindowBorderWidth(self.display, window, width);
      }
    }
  }

  pub fn set_window_border_color(&self, window: Window, color: u32) {
    if window != self.root {
      unsafe {
        XSetWindowBorder(self.display, window, color);
      }
    }
  }

  pub fn get_display_width(&self, screen: u32) -> u32 {
    unsafe {
      XDisplayWidth(self.display, screen as i32) as u32
    }
  }

  pub fn get_display_height(&self, screen: u32) -> u32 {
    unsafe {
      XDisplayHeight(self.display, screen as i32) as u32
    }
  }

  pub fn get_display_rect(&self, screen: u32) -> Rect {
    Rect{x: 0, y: 0, width: self.get_display_width(screen), height: self.get_display_height(screen)}
  }

  pub fn get_window_name(&self, window: Window) -> String {
    if window == self.root {
      return String::from_str("root");
    }

    unsafe {
      let mut name : *mut c_char = uninitialized();
      XFetchName(self.display, window, &mut name);
      String::from_str(c_str_to_static_slice(transmute(name)))
    }
  }

  fn cast_event_to<T>(&self) -> &T {
    unsafe {
      &*(self.event as *const T)
    }
  }

  pub fn get_event(&self) -> XlibEvent {
    unsafe {
      XNextEvent(self.display, self.event);
    }

    let evt_type : c_int = *self.cast_event_to();
    match evt_type{
      MapRequest => {
        let evt : &XMapRequestEvent = self.cast_event_to();
        unsafe {
          XSelectInput(self.display, evt.window, 0x420030);
        }

        XMapRequest(evt.window)
      },
      ConfigureRequest => {
        let event : &XConfigureRequestEvent = self.cast_event_to();
        let changes = WindowChanges{
          x: event.x as u32,
          y: event.y as u32,
          width: event.width as u32,
          height: event.height as u32,
          border_width: event.border_width as u32,
          sibling: event.above as Window,
          stack_mode: event.detail as u32
        };
        XConfigurationRequest(event.window, changes, event.value_mask)
      },
      Destroy => {
        let evt : &XDestroyWindowEvent = self.cast_event_to();
        XDestroy(evt.window)
      },
      EnterNotify => {
        let evt : &XEnterWindowEvent = self.cast_event_to();
        if evt.detail != 2 {
          XEnterNotify(evt.window)
        } else {
          Ignored
        }
      },
      FocusOut => {
        let evt : &XFocusOutEvent = self.cast_event_to();
        if evt.detail != 5 {
          XFocusOut(evt.window)
        } else {
          Ignored
        }
      },
      KeyPress => {
        let evt : &XKeyPressedEvent = self.cast_event_to();
        XKeyPress(evt.window, Keystroke{mods: evt.state as u8, key: self.keycode_to_string(evt.keycode)})
      },
      _ => {
        Ignored
      }
    }
  }
}
<commit_msg>preparing graceful kill<commit_after>#![allow(non_upper_case_globals)]
extern crate libc;

use keycode::{MOD_2, Keystroke};
use layout::Rect;
use std::c_vec::CVec;
use std::ptr::null_mut;
use std::mem::{uninitialized, transmute};
use std::str::raw::c_str_to_static_slice;
use self::libc::{c_void, c_int, c_char};
use self::libc::funcs::c95::stdlib::malloc;
use self::XlibEvent::*;
use xlib::*;

extern fn error_handler(display: *mut Display, event: *mut XErrorEvent) -> c_int {
  // TODO: proper error handling
  // HACK: fixes LeaveNotify on invalid windows
  return 0;
}

const KeyPress               : i32 = 2;
const EnterNotify            : i32 = 7;
const FocusOut               : i32 = 10;
const Destroy                : i32 = 17;
const MapRequest             : i32 = 20;
const ConfigureRequest       : i32 = 23;

pub struct XlibWindowSystem {
  display:   *mut Display,
  root:      Window,
  event:     *mut c_void
}

pub enum XlibEvent {
  XMapRequest(Window),
  XConfigurationRequest(Window, WindowChanges, u32),
  XDestroy(Window),
  XEnterNotify(Window),
  XFocusOut(Window),
  XKeyPress(Window, Keystroke),
  Ignored
}

pub struct WindowChanges {
  pub x: u32,
  pub y: u32,
  pub width: u32,
  pub height: u32,
  pub border_width: u32,
  pub sibling: Window,
  pub stack_mode: u32,
}

impl XlibWindowSystem {
  pub fn new() -> Option<XlibWindowSystem> {
    unsafe {
      let display = XOpenDisplay(null_mut());
      if display.is_null() {
        return None;
      }

      let root = XDefaultRootWindow(display);
      XSelectInput(display, root, 0x1A0035);

      XSetErrorHandler(error_handler as *mut u8);

      Some(XlibWindowSystem{
        display: display,
        root: root,
        event: malloc(256)
      })
    }
  }

  pub fn setup_window(&self, x: u32, y: u32, width: u32, height: u32, border_width: u32, border_color: u32, window: Window) {
    self.set_window_border_width(window, border_width);
    self.set_window_border_color(window, border_color);
    self.move_resize_window(window, x, y, width - (2 * border_width), height - (2 * border_width));
  }

  pub fn configure_window(&mut self, window: Window, window_changes: WindowChanges, mask: u32) {
    unsafe {
      let mut ret_window_changes = XWindowChanges{
        x: window_changes.x as i32,
        y: window_changes.y as i32,
        width: window_changes.width as i32,
        height: window_changes.height as i32,
        border_width: window_changes.border_width as i32,
        sibling: window_changes.sibling,
        stack_mode: window_changes.stack_mode as i32
      };
      XConfigureWindow(self.display, window, mask, &mut ret_window_changes);
    }
  }

  pub fn new_vroot(&self) -> Window {
    unsafe {
      let window = XCreateSimpleWindow(self.display, self.root, 0, 0, self.get_display_width(0), self.get_display_height(0), 0, 0, 0);
      XMapWindow(self.display, window);
      window
    }
  }

  pub fn map_to_parent(&self, parent: Window, window: Window) {
    unsafe {
      XReparentWindow(self.display, window, parent, 0, 0);
      XMapWindow(self.display, window);
    }
  }

  pub fn move_resize_window(&self, window: Window, x: u32, y: u32, width: u32, height: u32) {
    unsafe {
      XMoveResizeWindow(self.display, window, x as i32, y as i32, width, height);
    }
  }

  pub fn raise_window(&self, window: Window) {
    unsafe {
      XRaiseWindow(self.display, window);
    }
  }

  pub fn focus_window(&self, window: Window, color: u32) {
    unsafe {
      XSetInputFocus(self.display, window, 1, 0);
      XSetWindowBorder(self.display, window, color as u64);
    }
  }

  fn has_protocol(&self, window: Window, protocol: &str) -> bool {
    unsafe {
      let mut count : c_int = uninitialized();
      let mut atom : Atom = uninitialized();
      let mut atoms : *mut Atom = uninitialized();

      atom = XInternAtom(self.display, protocol.to_c_str().as_mut_ptr(), 1);
      XGetWMProtocols(self.display, window, &mut atoms, &mut count);
      CVec::new(atoms, count as uint).as_slice().contains(&atom)
    }
  }

  pub fn kill_window(&self, window: Window) {
    unsafe {
      if self.has_protocol(window, "WM_DELETE_WINDOW") {
        let mut msg : XClientMessageEvent = uninitialized();
        msg.format = 23;
        msg.display = self.display;
        msg.window = window;
        msg.message_type = XInternAtom(self.display, "WM_PROTOCOLS".to_c_str().as_mut_ptr(), 1);

        let data : union_unnamed2 = [XInternAtom(self.display, "WM_DELETE_WINDOW".to_c_str().as_mut_ptr(), 1), 0, 0, 0, 0];
        msg.data = data;

        XSendEvent(self.display, window, 0, 0, transmute(&msg));
      } else {
        XKillClient(self.display, window);
      }
    }
  }

  pub fn sync(&self) {
    unsafe {
      XSync(self.display, 1);
    }
  }

  pub fn grab_modifier(&self, mod_key: u8) {
    unsafe {
      XGrabKey(self.display, 0, mod_key as u32, self.root, 1, 0, 1);
      XGrabKey(self.display, 0, (mod_key | MOD_2) as u32, self.root, 1, 0, 1 );
    }
  }

  pub fn keycode_to_string(&self, keycode: u32) -> String {
    unsafe {
      let keysym = XKeycodeToKeysym(self.display, keycode as u8, 0);
      String::from_str(c_str_to_static_slice(transmute(XKeysymToString(keysym))))
    }
  }

  pub fn set_window_border_width(&self, window: Window, width: u32) {
    if window != self.root {
      unsafe {
        XSetWindowBorderWidth(self.display, window, width);
      }
    }
  }

  pub fn set_window_border_color(&self, window: Window, color: u32) {
    if window != self.root {
      unsafe {
        XSetWindowBorder(self.display, window, color as u64);
      }
    }
  }

  pub fn get_display_width(&self, screen: u32) -> u32 {
    unsafe {
      XDisplayWidth(self.display, screen as i32) as u32
    }
  }

  pub fn get_display_height(&self, screen: u32) -> u32 {
    unsafe {
      XDisplayHeight(self.display, screen as i32) as u32
    }
  }

  pub fn get_display_rect(&self, screen: u32) -> Rect {
    Rect{x: 0, y: 0, width: self.get_display_width(screen), height: self.get_display_height(screen)}
  }

  pub fn get_window_name(&self, window: Window) -> String {
    if window == self.root {
      return String::from_str("root");
    }

    unsafe {
      let mut name : *mut c_char = uninitialized();
      XFetchName(self.display, window, &mut name);
      String::from_str(c_str_to_static_slice(transmute(name)))
    }
  }

  fn cast_event_to<T>(&self) -> &T {
    unsafe {
      &*(self.event as *const T)
    }
  }

  pub fn get_event(&self) -> XlibEvent {
    unsafe {
      XNextEvent(self.display, self.event);
    }

    let evt_type : c_int = *self.cast_event_to();
    match evt_type{
      MapRequest => {
        let evt : &XMapRequestEvent = self.cast_event_to();
        unsafe {
          XSelectInput(self.display, evt.window, 0x420030);
        }

        XMapRequest(evt.window)
      },
      ConfigureRequest => {
        let event : &XConfigureRequestEvent = self.cast_event_to();
        let changes = WindowChanges{
          x: event.x as u32,
          y: event.y as u32,
          width: event.width as u32,
          height: event.height as u32,
          border_width: event.border_width as u32,
          sibling: event.above as Window,
          stack_mode: event.detail as u32
        };
        XConfigurationRequest(event.window, changes, event.value_mask as u32)
      },
      Destroy => {
        let evt : &XDestroyWindowEvent = self.cast_event_to();
        XDestroy(evt.window)
      },
      EnterNotify => {
        let evt : &XEnterWindowEvent = self.cast_event_to();
        if evt.detail != 2 {
          XEnterNotify(evt.window)
        } else {
          Ignored
        }
      },
      FocusOut => {
        let evt : &XFocusOutEvent = self.cast_event_to();
        if evt.detail != 5 {
          XFocusOut(evt.window)
        } else {
          Ignored
        }
      },
      KeyPress => {
        let evt : &XKeyPressedEvent = self.cast_event_to();
        XKeyPress(evt.window, Keystroke{mods: evt.state as u8, key: self.keycode_to_string(evt.keycode)})
      },
      _ => {
        Ignored
      }
    }
  }
}
<|endoftext|>


<commit_before>#[ allow( unused_imports ) ]
use clone_dyn::clone_dyn;

fn main()
{

  #[ cfg( any( feature = "use_std", feature = "use_alloc" ) ) ]
  {
    #[ clone_dyn ]
    trait Trait1
    {
    }

    let vec = Vec::< Box< dyn Trait1 > >::new();
    let _vec2 = vec.clone(); /* <- it does not work without `clone_dyn` */
  }

}
<commit_msg>!test<commit_after>#[ allow( unused_imports ) ]
use clone_dyn::clone_dyn;

fn main()
{

  #[ cfg( any( feature = "use_std", feature = "use_alloc" ) ) ]
  {

    #[ clone_dyn ]
    trait Trait1
    {
    }

    let vec = Vec::< Box< dyn Trait1 > >::new();
    let _vec2 = vec.clone(); /* <- it does not work without `clone_dyn` */

  }

}
<|endoftext|>