<commit_before>
// https://users.rust-lang.org/t/what-am-i-doing-wrong-go-program-is-12x-faster-than-rust/5692/13
// https://doc.rust-lang.org/rustc-serialize/rustc_serialize/json/index.html
// https://serde.rs/codegen-hybrid.html

// FIXME: Use https://github.com/nox/serde_urlencoded
// FIXME: Make sure that all structs above Issue are not using `String`s instead of `Enum`s.
// FIXME: Harmonize the different state enums (e.g. IssueState, MergeRequestState, Authors)
// FIXME: Move all enums here (ListingOrderBy, ListingSort, etc.)
// FIXME: Use a type for sha1
// FIXME: Use chrono crate for dates
// FIXME: Use unsigned integers where it makes sense (id, iid, etc.)
// FIXME: Verify all `match` in push_str() in build_query(): They should contain all members.
// FIXME: Get rid of build_query(), use serde's Serialize instead.
// FIXME: Write nicer wrappers, getting rid of Listing.

#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
pub enum ListingSort {
    #[serde(rename = "asc")]
    Asc,
    #[serde(rename = "desc")]
    Desc,
}

#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
pub enum ListingVisibility {
    #[serde(rename = "public")]
    Public,
    #[serde(rename = "internal")]
    Internal,
    #[serde(rename = "private")]
    Private,
}

#[derive(Debug, Serialize, Deserialize)]
pub enum IssueState {
    #[serde(rename = "opened")]
    Opened,

    #[serde(rename = "closed")]
    Closed,
}

#[derive(Debug, Serialize, Deserialize)]
pub enum UserState {
    #[serde(rename = "active")]
    Active,

    #[serde(rename = "blocked")]
    Blocked,
}

#[derive(Debug, Serialize, Deserialize)]
pub enum MilestoneState {
    #[serde(rename = "active")]
    Active,

    #[serde(rename = "closed")]
    Closed,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct Version {
    pub version: String,
    pub revision: String,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct Group {
    pub id: i64,
    pub name: String,
    pub path: String,
    pub description: String,
    pub visibility_level: i64,
    pub lfs_enabled: bool,
    pub avatar_url: Option<String>,
    pub web_url: String,
    pub request_access_enabled: bool,
}

pub type Groups = Vec<Group>;

#[derive(Debug, Serialize, Deserialize)]
pub struct ProjectOwner {
    pub name: String,
    pub username: String,
    pub id: i64,
    pub state: String,
    pub avatar_url: String,
    pub web_url: String,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct ProjectNamespaceAvatar {
    pub url: Option<String>,
}

#[derive(Default, Debug, Serialize, Deserialize)]
pub struct ProjectNamespace {
    pub id: i64,
    pub name: String,
    pub path: String,
    pub owner_id: Option<i64>,  // FIXME: Why would a project not have this?
    pub created_at: String,  // FIXME: Date instead?
    pub updated_at: String,  // FIXME: Date instead?
    pub description: String,
    pub avatar: Option<ProjectNamespaceAvatar>,
    pub membership_lock: Option<bool>,
    pub share_with_group_lock: bool,
    pub visibility_level: i64,
    pub request_access_enabled: bool,
    pub ldap_sync_status: Option<String>,
    pub ldap_sync_error: Option<String>,  // FIXME: Is String the proper type?
    pub ldap_sync_last_update_at: Option<String>,  // FIXME: Is String the proper type?
    pub ldap_sync_last_successful_update_at: Option<String>,  // FIXME: Is String the proper type?
    pub ldap_sync_last_sync_at: Option<String>,  // FIXME: Is String the proper type?
    pub deleted_at: Option<String>,  // FIXME: Is String the proper type?
    pub lfs_enabled: Option<String>,  // FIXME: Is String the proper type?
    pub repository_size_limit: Option<String>  // FIXME: Is String the proper type?
}

#[derive(Debug, Serialize, Deserialize)]
pub struct ProjectForkedFrom {
    pub id: i64,
    pub http_url_to_repo: String,
    pub web_url: String,
    pub name: String,
    pub name_with_namespace: String,
    pub path: String,
    pub path_with_namespace: String,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct ProjectAccess {
    pub access_level: i64,
    pub notification_level: i64,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct ProjectPermissions {
    pub project_access: Option<ProjectAccess>,
    pub group_access: Option<ProjectAccess>,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct ProjectSharedWithGroup {
    pub group_id: i64,
    pub group_name: String,
    pub group_access_level: i64,
}

// https://users.rust-lang.org/t/what-am-i-doing-wrong-go-program-is-12x-faster-than-rust/5692/13
// https://doc.rust-lang.org/rustc-serialize/rustc_serialize/json/index.html
#[derive(Default, Debug, Serialize, Deserialize)]
pub struct Project {
    pub id: i64,
    pub description: String,
    pub default_branch: Option<String>,
    pub tag_list: Vec<String>,
    pub public: bool,
    pub archived: bool,
    pub visibility_level: i64,
    pub ssh_url_to_repo: String,
    pub http_url_to_repo: String,
    pub web_url: String,
    // owner: Option<ProjectOwner>,  // FIXME: Why would a project not have an owner?
    pub name: String,
    pub name_with_namespace: String,
    pub path: String,
    pub path_with_namespace: String,
    pub container_registry_enabled: Option<bool>,
    pub issues_enabled: Option<bool>,
    pub merge_requests_enabled: Option<bool>,
    pub wiki_enabled: Option<bool>,
    pub builds_enabled: Option<bool>,
    pub snippets_enabled: Option<bool>,
    pub created_at: String,  // FIXME: Date instead?
    pub last_activity_at: String,  // FIXME: Date instead?
    pub shared_runners_enabled: bool,
    pub lfs_enabled: bool,
    pub creator_id: i64,
    pub namespace: ProjectNamespace,
    pub forked_from_project: Option<ProjectForkedFrom>,
    pub avatar_url: Option<String>,
    pub star_count: i64,
    pub forks_count: i64,
    pub open_issues_count: Option<i64>,
    pub runners_token: Option<String>,
    pub public_builds: bool,
    pub shared_with_groups: Vec<ProjectSharedWithGroup>,
    pub only_allow_merge_if_build_succeeds: bool,
    pub request_access_enabled: bool,
    pub only_allow_merge_if_all_discussions_are_resolved: Option<bool>,  // FIXME: Is bool the proper type?
    pub approvals_before_merge: Option<i64>,
    pub permissions: Option<ProjectPermissions>,
}

pub type Projects = Vec<Project>;

#[derive(Debug, Serialize, Deserialize)]
pub struct Milestone {
    pub id: i64,
    pub iid: i64,
    pub project_id: i64,
    pub title: String,
    pub description: String,
    pub state: MilestoneState,
    pub created_at: String,  // FIXME: Use date type?
    pub updated_at: String,  // FIXME: Use date type?
    pub due_date: Option<String>  // FIXME: Use date type?
}

#[derive(Debug, Serialize, Deserialize)]
pub struct User {
    pub name: String,
    pub username: String,
    pub id: i64,
    pub state: UserState,
    pub avatar_url: Option<String>,
    pub web_url: Option<String>
}

#[derive(Debug, Serialize, Deserialize)]
pub struct Issue {
    pub id: i64,
    pub iid: i64,
    pub project_id: i64,
    pub title: String,
    pub description: String,
    pub state: IssueState,
    pub created_at: String,  // FIXME: Use date type?
    pub updated_at: String,  // FIXME: Use date type?
    pub labels: Vec<String>,
    pub milestone: Option<Milestone>,
    pub assignee: Option<User>,
    pub author: User,
    pub subscribed: bool,
    pub user_notes_count: i64,
    pub upvotes: i64,
    pub downvotes: i64,
    pub due_date: Option<String>,  // FIXME: Use date type?
    pub confidential: bool,
    pub web_url: Option<String>
}

pub type Issues = Vec<Issue>;
<commit_msg>Fix: Let some ProjectNamespace members be optional, as returned by gitlab.com<commit_after>
// https://users.rust-lang.org/t/what-am-i-doing-wrong-go-program-is-12x-faster-than-rust/5692/13
// https://doc.rust-lang.org/rustc-serialize/rustc_serialize/json/index.html
// https://serde.rs/codegen-hybrid.html

// FIXME: Use https://github.com/nox/serde_urlencoded
// FIXME: Make sure that all structs above Issue are not using `String`s instead of `Enum`s.
// FIXME: Harmonize the different state enums (e.g. IssueState, MergeRequestState, Authors)
// FIXME: Move all enums here (ListingOrderBy, ListingSort, etc.)
// FIXME: Use a type for sha1
// FIXME: Use chrono crate for dates
// FIXME: Use unsigned integers where it makes sense (id, iid, etc.)
// FIXME: Verify all `match` in push_str() in build_query(): They should contain all members.
// FIXME: Get rid of build_query(), use serde's Serialize instead.
// FIXME: Write nicer wrappers, getting rid of Listing.

#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
pub enum ListingSort {
    #[serde(rename = "asc")]
    Asc,
    #[serde(rename = "desc")]
    Desc,
}

#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
pub enum ListingVisibility {
    #[serde(rename = "public")]
    Public,
    #[serde(rename = "internal")]
    Internal,
    #[serde(rename = "private")]
    Private,
}

#[derive(Debug, Serialize, Deserialize)]
pub enum IssueState {
    #[serde(rename = "opened")]
    Opened,

    #[serde(rename = "closed")]
    Closed,
}

#[derive(Debug, Serialize, Deserialize)]
pub enum UserState {
    #[serde(rename = "active")]
    Active,

    #[serde(rename = "blocked")]
    Blocked,
}

#[derive(Debug, Serialize, Deserialize)]
pub enum MilestoneState {
    #[serde(rename = "active")]
    Active,

    #[serde(rename = "closed")]
    Closed,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct Version {
    pub version: String,
    pub revision: String,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct Group {
    pub id: i64,
    pub name: String,
    pub path: String,
    pub description: String,
    pub visibility_level: i64,
    pub lfs_enabled: bool,
    pub avatar_url: Option<String>,
    pub web_url: String,
    pub request_access_enabled: bool,
}

pub type Groups = Vec<Group>;

#[derive(Debug, Serialize, Deserialize)]
pub struct ProjectOwner {
    pub name: String,
    pub username: String,
    pub id: i64,
    pub state: String,
    pub avatar_url: String,
    pub web_url: String,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct ProjectNamespaceAvatar {
    pub url: Option<String>,
}

#[derive(Default, Debug, Serialize, Deserialize)]
pub struct ProjectNamespace {
    pub id: i64,
    pub name: String,
    pub path: String,
    pub owner_id: Option<i64>,  // FIXME: Why would a project not have this?
    pub created_at: Option<String>,  // FIXME: Date instead?
    pub updated_at: Option<String>,  // FIXME: Date instead?
    pub description: Option<String>,
    pub avatar: Option<ProjectNamespaceAvatar>,
    pub membership_lock: Option<bool>,
    pub share_with_group_lock: Option<bool>,
    pub visibility_level: Option<i64>,
    pub request_access_enabled: Option<bool>,
    pub ldap_sync_status: Option<String>,
    pub ldap_sync_error: Option<String>,  // FIXME: Is String the proper type?
    pub ldap_sync_last_update_at: Option<String>,  // FIXME: Is String the proper type?
    pub ldap_sync_last_successful_update_at: Option<String>,  // FIXME: Is String the proper type?
    pub ldap_sync_last_sync_at: Option<String>,  // FIXME: Is String the proper type?
    pub deleted_at: Option<String>,  // FIXME: Is String the proper type?
    pub lfs_enabled: Option<String>,  // FIXME: Is String the proper type?
    pub repository_size_limit: Option<String>  // FIXME: Is String the proper type?
}

#[derive(Debug, Serialize, Deserialize)]
pub struct ProjectForkedFrom {
    pub id: i64,
    pub http_url_to_repo: String,
    pub web_url: String,
    pub name: String,
    pub name_with_namespace: String,
    pub path: String,
    pub path_with_namespace: String,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct ProjectAccess {
    pub access_level: i64,
    pub notification_level: i64,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct ProjectPermissions {
    pub project_access: Option<ProjectAccess>,
    pub group_access: Option<ProjectAccess>,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct ProjectSharedWithGroup {
    pub group_id: i64,
    pub group_name: String,
    pub group_access_level: i64,
}

// https://users.rust-lang.org/t/what-am-i-doing-wrong-go-program-is-12x-faster-than-rust/5692/13
// https://doc.rust-lang.org/rustc-serialize/rustc_serialize/json/index.html
#[derive(Default, Debug, Serialize, Deserialize)]
pub struct Project {
    pub id: i64,
    pub description: String,
    pub default_branch: Option<String>,
    pub tag_list: Vec<String>,
    pub public: bool,
    pub archived: bool,
    pub visibility_level: i64,
    pub ssh_url_to_repo: String,
    pub http_url_to_repo: String,
    pub web_url: String,
    // owner: Option<ProjectOwner>,  // FIXME: Why would a project not have an owner?
    pub name: String,
    pub name_with_namespace: String,
    pub path: String,
    pub path_with_namespace: String,
    pub container_registry_enabled: Option<bool>,
    pub issues_enabled: Option<bool>,
    pub merge_requests_enabled: Option<bool>,
    pub wiki_enabled: Option<bool>,
    pub builds_enabled: Option<bool>,
    pub snippets_enabled: Option<bool>,
    pub created_at: String,  // FIXME: Date instead?
    pub last_activity_at: String,  // FIXME: Date instead?
    pub shared_runners_enabled: bool,
    pub lfs_enabled: bool,
    pub creator_id: i64,
    pub namespace: ProjectNamespace,
    pub forked_from_project: Option<ProjectForkedFrom>,
    pub avatar_url: Option<String>,
    pub star_count: i64,
    pub forks_count: i64,
    pub open_issues_count: Option<i64>,
    pub runners_token: Option<String>,
    pub public_builds: bool,
    pub shared_with_groups: Vec<ProjectSharedWithGroup>,
    pub only_allow_merge_if_build_succeeds: bool,
    pub request_access_enabled: bool,
    pub only_allow_merge_if_all_discussions_are_resolved: Option<bool>,  // FIXME: Is bool the proper type?
    pub approvals_before_merge: Option<i64>,
    pub permissions: Option<ProjectPermissions>,
}

pub type Projects = Vec<Project>;

#[derive(Debug, Serialize, Deserialize)]
pub struct Milestone {
    pub id: i64,
    pub iid: i64,
    pub project_id: i64,
    pub title: String,
    pub description: String,
    pub state: MilestoneState,
    pub created_at: String,  // FIXME: Use date type?
    pub updated_at: String,  // FIXME: Use date type?
    pub due_date: Option<String>  // FIXME: Use date type?
}

#[derive(Debug, Serialize, Deserialize)]
pub struct User {
    pub name: String,
    pub username: String,
    pub id: i64,
    pub state: UserState,
    pub avatar_url: Option<String>,
    pub web_url: Option<String>
}

#[derive(Debug, Serialize, Deserialize)]
pub struct Issue {
    pub id: i64,
    pub iid: i64,
    pub project_id: i64,
    pub title: String,
    pub description: String,
    pub state: IssueState,
    pub created_at: String,  // FIXME: Use date type?
    pub updated_at: String,  // FIXME: Use date type?
    pub labels: Vec<String>,
    pub milestone: Option<Milestone>,
    pub assignee: Option<User>,
    pub author: User,
    pub subscribed: bool,
    pub user_notes_count: i64,
    pub upvotes: i64,
    pub downvotes: i64,
    pub due_date: Option<String>,  // FIXME: Use date type?
    pub confidential: bool,
    pub web_url: Option<String>
}

pub type Issues = Vec<Issue>;
<|endoftext|>


<commit_before>use std::iter;

/// A structure for manipulating Table Of Content
#[derive(Debug)]
pub struct Toc {
    elements: Vec<TocElement>,
    numbered: bool,
}

impl Toc {
    /// Create a new, empty, Toc
    pub fn new() -> Toc {
        Toc {
            elements: vec!(),
            numbered: false,
        }
    }

    /// Sets numbering of the Toc
    pub fn numbered(&mut self, numbered: bool) {
        self.numbered = numbered;
    }

    /// Adds an element
    pub fn add(&mut self, level: i32, url: String, title: String) {
        let element = TocElement::new(level, url, title);
        self.elements.push(element);
    }

    /// Render the Toc in either
 or
 form (according to Self::numbered
    pub fn render(&self) -> String {
        let mut output = String::new();

        let mut x = 0;
        let mut level = 0;
        output.push_str(&self.render_vec(&mut x, &mut level));
        for i in (0..level).rev() {
            output.push_str(&format!(
                "{}</{}>",
                iter::repeat(' ').take(i as usize).collect::<String>(),
                if self.numbered {"ol"} else {"ul"}));
        }
        output
    }

    fn render_vec(&self, x: &mut usize, level: &mut i32) -> String {
        let orig_level = *level;
        let mut content = String::new();
        while *x < self.elements.len() {
            let elem = &self.elements[*x];

            if elem.level <= orig_level {
                return content
            }

            *x += 1;

            if elem.level > *level {
                for i in *level..elem.level {
                    content.push_str(&format!(
                        "{}{}\n",
                        iter::repeat(' ').take(i as usize).collect::<String>(),
                        if self.numbered {"
"} else {"
"}));
                    *level = elem.level;
                }
            } else if elem.level < *level {
                for i in (elem.level..*level).rev() {
                    content.push_str(&format!(
                        "{}</{}>\n",
                        iter::repeat(' ').take(i as usize).collect::<String>(),
                        if self.numbered {"ol"} else {"ul"}));
                }
                *level = elem.level;
            }
            let spaces:String = iter::repeat(' ').take(elem.level as usize).collect();
            content.push_str(&format!(
                "{}
{}\n",
                spaces,
                elem.url,
                elem.title));
            content.push_str(&self.render_vec(x, level));

            for i in (elem.level..*level).rev() {
                content.push_str(&format!("{}</{}>\n",
                                          iter::repeat(' ').take(i as usize).collect::<String>(),
                                          if self.numbered {"ol"} else {"ul"}));
            }
            *level = elem.level;
            content.push_str(&format!("{}
\n", spaces));

        }
        content
    }
}

#[derive(Debug)]
struct TocElement {
    level: i32,
    url: String,
    title: String,
}

impl TocElement {
    pub fn new(level: i32, url: String, title: String) -> TocElement {
        TocElement {
            level: level,
            url: url,
            title: title,
        }
    }
}

<commit_msg>Add comment on toc numbering<commit_after>use std::iter;

/// A structure for manipulating Table Of Content
#[derive(Debug)]
pub struct Toc {
    elements: Vec<TocElement>,
    numbered: bool,
}

impl Toc {
    /// Create a new, empty, Toc
    pub fn new() -> Toc {
        Toc {
            elements: vec!(),
            numbered: false,
        }
    }

    /// Sets numbering of the Toc
    ///
    /// Only affects whether the generated HTML code should be
 or
 (epub)
    pub fn numbered(&mut self, numbered: bool) {
        self.numbered = numbered;
    }

    /// Adds an element
    pub fn add(&mut self, level: i32, url: String, title: String) {
        let element = TocElement::new(level, url, title);
        self.elements.push(element);
    }

    /// Render the Toc in either
 or
 form (according to Self::numbered
    pub fn render(&self) -> String {
        let mut output = String::new();

        let mut x = 0;
        let mut level = 0;
        output.push_str(&self.render_vec(&mut x, &mut level));
        for i in (0..level).rev() {
            output.push_str(&format!(
                "{}</{}>",
                iter::repeat(' ').take(i as usize).collect::<String>(),
                if self.numbered {"ol"} else {"ul"}));
        }
        output
    }

    fn render_vec(&self, x: &mut usize, level: &mut i32) -> String {
        let orig_level = *level;
        let mut content = String::new();
        while *x < self.elements.len() {
            let elem = &self.elements[*x];

            if elem.level <= orig_level {
                return content
            }

            *x += 1;

            if elem.level > *level {
                for i in *level..elem.level {
                    content.push_str(&format!(
                        "{}{}\n",
                        iter::repeat(' ').take(i as usize).collect::<String>(),
                        if self.numbered {"
"} else {"
"}));
                    *level = elem.level;
                }
            } else if elem.level < *level {
                for i in (elem.level..*level).rev() {
                    content.push_str(&format!(
                        "{}</{}>\n",
                        iter::repeat(' ').take(i as usize).collect::<String>(),
                        if self.numbered {"ol"} else {"ul"}));
                }
                *level = elem.level;
            }
            let spaces:String = iter::repeat(' ').take(elem.level as usize).collect();
            content.push_str(&format!(
                "{}
{}\n",
                spaces,
                elem.url,
                elem.title));
            content.push_str(&self.render_vec(x, level));

            for i in (elem.level..*level).rev() {
                content.push_str(&format!("{}</{}>\n",
                                          iter::repeat(' ').take(i as usize).collect::<String>(),
                                          if self.numbered {"ol"} else {"ul"}));
            }
            *level = elem.level;
            content.push_str(&format!("{}
\n", spaces));

        }
        content
    }
}

#[derive(Debug)]
struct TocElement {
    level: i32,
    url: String,
    title: String,
}

impl TocElement {
    pub fn new(level: i32, url: String, title: String) -> TocElement {
        TocElement {
            level: level,
            url: url,
            title: title,
        }
    }
}

<|endoftext|>


<commit_before>use redox::{Vec, String, ToString};
use redox::collections::{BTreeMap, VecDeque};

use super::dvaddr::DVAddr;
use super::zio;

// Our implementation of the Adaptive Replacement Cache (ARC) is set up to allocate
// its buffer on the heap rather than in a private pool thing. This makes it much
// simpler to implement, but defers the fragmentation problem to the heap allocator.
// We named the type `ArCache` to avoid confusion with Rust's `Arc` reference type.
pub struct ArCache {
    mru_map: BTreeMap<DVAddr, Vec<u8>>, // Most recently used cache
    mru_queue: VecDeque<DVAddr>, // Oldest paths are at the end
    mru_size: usize, // Max mru cache size in bytes
    mru_used: usize, // Used bytes in mru cache
}

impl ArCache {
    pub fn new() -> Self {
        ArCache {
            mru_map: BTreeMap::new(),
            mru_queue: VecDeque::new(),
            mru_size: 10,
            mru_used: 0,
        }
    }

    pub fn read(&mut self, reader: &mut zio::Reader, dva: &DVAddr) -> Result<Vec<u8>, String> {
        if let Some(block) = self.mru_map.get(dva) {
            // Block is cached
            return Ok(block.clone());
        }

        // Block isn't cached, have to read it from disk
        let block = reader.read(dva.sector() as usize, dva.asize() as usize);

        // If necessary, make room for the block in the cache
        while self.mru_used + block.len() > self.mru_size {
            let last_dva = match self.mru_queue.pop_back()
            {
                Some(dva) => dva,
                None => return Err("No more ARC MRU items to free".to_string()),
            };
            self.mru_map.remove(&last_dva);
            self.mru_used -= last_dva.asize() as usize;
        }

        // Add the block to the cache
        self.mru_used += block.len();
        self.mru_map.insert(*dva, block);
        self.mru_queue.push_front(*dva);
        Ok(self.mru_map.get(dva).unwrap().clone())
    }
}
<commit_msg>Added TODOs in ARC for stratact<commit_after>use redox::{Vec, String, ToString};
use redox::collections::{BTreeMap, VecDeque};

use super::dvaddr::DVAddr;
use super::zio;

// Our implementation of the Adaptive Replacement Cache (ARC) is set up to allocate
// its buffer on the heap rather than in a private pool thing. This makes it much
// simpler to implement, but defers the fragmentation problem to the heap allocator.
// We named the type `ArCache` to avoid confusion with Rust's `Arc` reference type.
pub struct ArCache {
    // MRU
    // TODO: keep track of use counts. So mru_map becomes (use_count: u64, Vec<u8>)
    mru_map: BTreeMap<DVAddr, Vec<u8>>, // Most recently used cache
    mru_queue: VecDeque<DVAddr>, // Oldest DVAddrs are at the end
    mru_size: usize, // Max mru cache size in bytes
    mru_used: usize, // Used bytes in mru cache

    // MFU
    // TODO: Keep track of use counts. So mfu_map becomes (use_count: u64, Vec<u8>). Reset the use
    // count every once in a while. For instance, every 1000 reads. This will probably end up being
    // a knob for the user.
    mfu_map: BTreeMap<DVAddr, Vec<u8>>, // Most frequently used cache
    // TODO: Keep track of minimum frequency.
    mfu_min_freq: u64,
    mfu_size: usize, // Max mfu cache size in bytes
    mfu_used: usize, // Used bytes in mfu cache
}

impl ArCache {
    pub fn new() -> Self {
        ArCache {
            mru_map: BTreeMap::new(),
            mru_queue: VecDeque::new(),
            mru_size: 10,
            mru_used: 0,

            mfu_map: BTreeMap::new(),
            mfu_size: 10,
            mfu_used: 0,
        }
    }

    pub fn read(&mut self, reader: &mut zio::Reader, dva: &DVAddr) -> Result<Vec<u8>, String> {
        if let Some(block) = self.mru_map.get(dva) {
            // TODO: Keep track of MRU DVA use count. If it gets used a second time, move the block into
            // the MFU cache.

            // Block is cached
            return Ok(block.clone());
        }
        if let Some(block) = self.mfu_map.get(dva) {
            // TODO: keep track of DVA use count
            // Block is cached
            return Ok(block.clone());
        }

        // Block isn't cached, have to read it from disk
        let block = reader.read(dva.sector() as usize, dva.asize() as usize);
        self.cache_block(block);
    }

    fn mru_cache_block(&mut self, block: Vec<u8>) {
        // If necessary, make room for the block in the cache
        while self.mru_used + block.len() > self.mru_size {
            let last_dva = match self.mru_queue.pop_back()
            {
                Some(dva) => dva,
                None => return Err("No more ARC MRU items to free".to_string()),
            };
            self.mru_map.remove(&last_dva);
            self.mru_used -= last_dva.asize() as usize;
        }

        // Add the block to the cache
        self.mru_used += block.len();
        self.mru_map.insert(*dva, block);
        self.mru_queue.push_front(*dva);
        Ok(self.mru_map.get(dva).unwrap().clone())
    }

    // TODO: mfu_cache_block
}
<|endoftext|>


<commit_before>use super::ErrorCode;
use bindings::root::*;
use std::ptr;
use std::os::raw::c_void;
use std::ffi::CStr;

pub use bindings::root::spv::ExecutionModel;

#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
pub struct WorkgroupSize {
    pub x: u32,
    pub y: u32,
    pub z: u32,
}

#[derive(Debug, Clone)]
pub struct EntryPoint {
    pub name: String,
    pub execution_model: ExecutionModel,
    pub workgroup_size: WorkgroupSize,
}

#[derive(Debug, Clone)]
pub struct Module<'a> {
    ir: &'a [u32],
}

impl<'a> Module<'a> {
    pub fn new(ir: &[u32]) -> Module {
        Module { ir }
    }
}

pub struct ParsedModule {
    pub entry_points: Vec<EntryPoint>,
    pub(crate) ir: Vec<u32>,
}

impl ParsedModule {
    fn new(ir: Vec<u32>, entry_points: Vec<EntryPoint>) -> ParsedModule {
        ParsedModule { entry_points, ir }
    }
}

#[derive(Debug, Clone)]
pub struct ParserOptions;

impl ParserOptions {
    pub fn new() -> ParserOptions {
        ParserOptions
    }
}

#[derive(Debug, Clone)]
pub struct Parser {
    _unconstructable: (),
}

impl Parser {
    pub fn new() -> Parser {
        Parser {
            _unconstructable: (),
        }
    }

    pub fn parse(
        &self,
        module: &Module,
        _options: &ParserOptions,
    ) -> Result<ParsedModule, ErrorCode> {
        unsafe {
            let mut entry_points_raw = ptr::null_mut();
            let mut entry_points_raw_length = 0 as usize;

            let mut ir = vec![0; module.ir.len()];
            ir.copy_from_slice(module.ir);

            check!(sc_internal_compiler_base_parse(
                ir.as_ptr() as *const u32,
                ir.len() as usize,
                &mut entry_points_raw,
                &mut entry_points_raw_length,
            ));

            let entry_points = (0..entry_points_raw_length)
                .map(|offset| {
                    let entry_point_raw_ptr = entry_points_raw.offset(offset as isize);
                    let entry_point_raw = *entry_point_raw_ptr;
                    let name = match CStr::from_ptr(entry_point_raw.name)
                        .to_owned()
                        .into_string()
                    {
                        Ok(n) => n,
                        _ => return Err(ErrorCode::Unhandled),
                    };

                    let entry_point = EntryPoint {
                        name,
                        execution_model: entry_point_raw.execution_model,
                        workgroup_size: WorkgroupSize {
                            x: entry_point_raw.workgroup_size_x,
                            y: entry_point_raw.workgroup_size_y,
                            z: entry_point_raw.workgroup_size_z,
                        },
                    };

                    check!(sc_internal_free_pointer(
                        entry_point_raw.name as *mut c_void,
                    ));
                    check!(sc_internal_free_pointer(entry_point_raw_ptr as *mut c_void));

                    Ok(entry_point)
                })
                .collect::<Result<Vec<_>, _>>();

            Ok(ParsedModule::new(
                ir,
                match entry_points {
                    Ok(e) => e,
                    Err(e) => return Err(e),
                },
            ))
        }
    }
}
<commit_msg>Create separate execution model enum and map to it instead<commit_after>use super::ErrorCode;
use bindings::root::*;
use std::ptr;
use std::os::raw::c_void;
use std::ffi::CStr;

#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
pub enum ExecutionModel {
    Vertex = 0,
    TessellationControl = 1,
    TessellationEvaluation = 2,
    Geometry = 3,
    Fragment = 4,
    GlCompute = 5,
    Kernel = 6,
}

impl ExecutionModel {
    fn from_raw(raw: spv::ExecutionModel) -> Result<ExecutionModel, ErrorCode> {
        match raw {
            spv::ExecutionModel::ExecutionModelVertex => Ok(ExecutionModel::Vertex),
            spv::ExecutionModel::ExecutionModelTessellationControl => {
                Ok(ExecutionModel::TessellationControl)
            }
            spv::ExecutionModel::ExecutionModelTessellationEvaluation => {
                Ok(ExecutionModel::TessellationEvaluation)
            }
            spv::ExecutionModel::ExecutionModelGeometry => Ok(ExecutionModel::Geometry),
            spv::ExecutionModel::ExecutionModelFragment => Ok(ExecutionModel::Fragment),
            spv::ExecutionModel::ExecutionModelGLCompute => Ok(ExecutionModel::GlCompute),
            spv::ExecutionModel::ExecutionModelKernel => Ok(ExecutionModel::Kernel),
            _ => Err(ErrorCode::Unhandled),
        }
    }
}

#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
pub struct WorkgroupSize {
    pub x: u32,
    pub y: u32,
    pub z: u32,
}

#[derive(Debug, Clone)]
pub struct EntryPoint {
    pub name: String,
    pub execution_model: ExecutionModel,
    pub workgroup_size: WorkgroupSize,
}

#[derive(Debug, Clone)]
pub struct Module<'a> {
    ir: &'a [u32],
}

impl<'a> Module<'a> {
    pub fn new(ir: &[u32]) -> Module {
        Module { ir }
    }
}

pub struct ParsedModule {
    pub entry_points: Vec<EntryPoint>,
    pub(crate) ir: Vec<u32>,
}

impl ParsedModule {
    fn new(ir: Vec<u32>, entry_points: Vec<EntryPoint>) -> ParsedModule {
        ParsedModule { entry_points, ir }
    }
}

#[derive(Debug, Clone)]
pub struct ParserOptions;

impl ParserOptions {
    pub fn new() -> ParserOptions {
        ParserOptions
    }
}

#[derive(Debug, Clone)]
pub struct Parser {
    _unconstructable: (),
}

impl Parser {
    pub fn new() -> Parser {
        Parser {
            _unconstructable: (),
        }
    }

    pub fn parse(
        &self,
        module: &Module,
        _options: &ParserOptions,
    ) -> Result<ParsedModule, ErrorCode> {
        unsafe {
            let mut entry_points_raw = ptr::null_mut();
            let mut entry_points_raw_length = 0 as usize;

            let mut ir = vec![0; module.ir.len()];
            ir.copy_from_slice(module.ir);

            check!(sc_internal_compiler_base_parse(
                ir.as_ptr() as *const u32,
                ir.len() as usize,
                &mut entry_points_raw,
                &mut entry_points_raw_length,
            ));

            let entry_points = (0..entry_points_raw_length)
                .map(|offset| {
                    let entry_point_raw_ptr = entry_points_raw.offset(offset as isize);
                    let entry_point_raw = *entry_point_raw_ptr;
                    let name = match CStr::from_ptr(entry_point_raw.name)
                        .to_owned()
                        .into_string()
                    {
                        Ok(n) => n,
                        _ => return Err(ErrorCode::Unhandled),
                    };

                    let entry_point = EntryPoint {
                        name,
                        execution_model: try!(
                            ExecutionModel::from_raw(entry_point_raw.execution_model,)
                        ),
                        workgroup_size: WorkgroupSize {
                            x: entry_point_raw.workgroup_size_x,
                            y: entry_point_raw.workgroup_size_y,
                            z: entry_point_raw.workgroup_size_z,
                        },
                    };

                    check!(sc_internal_free_pointer(
                        entry_point_raw.name as *mut c_void,
                    ));
                    check!(sc_internal_free_pointer(entry_point_raw_ptr as *mut c_void));

                    Ok(entry_point)
                })
                .collect::<Result<Vec<_>, _>>();

            Ok(ParsedModule::new(ir, try!(entry_points)))
        }
    }
}
<|endoftext|>


<commit_before>use std::io;
use std::io::{Read, Write};
use std::marker::PhantomData;
use std::mem;
use std::sync::atomic;

use kernel32;
use winapi;

use consts::{self, KeyPress};
use ::error;
use ::Result;

pub type Handle = winapi::HANDLE;
pub type Mode = winapi::DWORD;
pub const STDIN_FILENO: winapi::DWORD = winapi::STD_INPUT_HANDLE;
pub const STDOUT_FILENO: winapi::DWORD = winapi::STD_OUTPUT_HANDLE;

fn get_std_handle(fd: winapi::DWORD) -> Result<winapi::HANDLE> {
    let handle = unsafe { kernel32::GetStdHandle(fd) };
    if handle == winapi::INVALID_HANDLE_VALUE {
        try!(Err(io::Error::last_os_error()));
    } else if handle.is_null() {
        try!(Err(io::Error::new(io::ErrorKind::Other,
                                "no stdio handle available for this process")));
    }
    Ok(handle)
}

#[macro_export]
macro_rules! check {
    ($funcall:expr) => {
        {
        let rc = unsafe { $funcall };
        if rc == 0 {
            try!(Err(io::Error::last_os_error()));
        }
        rc
        }
    };
}

/// Try to get the number of columns in the current terminal,
/// or assume 80 if it fails.
pub fn get_columns(handle: Handle) -> usize {
    let (cols, _) = get_win_size();
    cols
}

/// Try to get the number of rows in the current terminal,
/// or assume 24 if it fails.
pub fn get_rows(_: Handle) -> usize {
    let (_, rows) = get_win_size();
    rows
}

fn get_win_size() -> (usize, usize) {
    let mut info = unsafe { mem::zeroed() };
    match unsafe { kernel32::GetConsoleScreenBufferInfo(handle, &mut info) } {
        0 => (80, 24),
        _ => (info.dwSize.X as usize, 1 + inf.srWindow.Bottom - inf.srWindow.Top),
    }
}

/// Checking for an unsupported TERM in windows is a no-op
pub fn is_unsupported_term() -> bool {
    false
}

fn get_console_mode(handle: winapi::HANDLE) -> Result<Mode> {
    let mut original_mode = 0;
    check!(kernel32::GetConsoleMode(handle, &mut original_mode));
    Ok(original_mode)
}

/// Return whether or not STDIN, STDOUT or STDERR is a TTY
pub fn is_a_tty(fd: winapi::DWORD) -> bool {
    let handle = get_std_handle(fd);
    match handle {
        Ok(handle) => {
            // If this function doesn't fail then fd is a TTY
            get_console_mode(handle).is_ok()
        }
        Err(_) => false,
    }
}

/// Enable raw mode for the TERM
pub fn enable_raw_mode() -> Result<Mode> {
    let handle = try!(get_std_handle(STDIN_FILENO));
    let original_mode = try!(get_console_mode(handle));
    // Disable these modes
    let raw = original_mode &
              !(winapi::wincon::ENABLE_LINE_INPUT | winapi::wincon::ENABLE_ECHO_INPUT |
                winapi::wincon::ENABLE_PROCESSED_INPUT);
    // Enable these modes
    let raw = raw | winapi::wincon::ENABLE_EXTENDED_FLAGS;
    let raw = raw | winapi::wincon::ENABLE_INSERT_MODE;
    let raw = raw | winapi::wincon::ENABLE_QUICK_EDIT_MODE;
    let raw = raw | winapi::wincon::ENABLE_WINDOW_INPUT;
    check!(kernel32::SetConsoleMode(handle, raw));
    Ok(original_mode)
}

/// Disable Raw mode for the term
pub fn disable_raw_mode(original_mode: Mode) -> Result<()> {
    let handle = try!(get_std_handle(STDIN_FILENO));
    check!(kernel32::SetConsoleMode(handle, original_mode));
    Ok(())
}

pub fn stdout_handle() -> Result<Handle> {
    let handle = try!(get_std_handle(STDOUT_FILENO));
    Ok(handle)
}

/// Clear the screen. Used to handle ctrl+l
pub fn clear_screen(_: &mut Write, handle: Handle) -> Result<()> {
    let mut info = unsafe { mem::zeroed() };
    check!(kernel32::GetConsoleScreenBufferInfo(handle, &mut info));
    let coord = winapi::COORD { X: 0, Y: 0 };
    check!(kernel32::SetConsoleCursorPosition(handle, coord));
    let mut _count = 0;
    let n = info.dwSize.X as winapi::DWORD * info.dwSize.Y as winapi::DWORD;
    check!(kernel32::FillConsoleOutputCharacterA(handle,
                                                 ' ' as winapi::CHAR,
                                                 n,
                                                 coord,
                                                 &mut _count));
    Ok(())
}

/// Console input reader
pub struct RawReader<R> {
    handle: winapi::HANDLE,
    buf: Option<u16>,
    phantom: PhantomData<R>,
}

impl<R: Read> RawReader<R> {
    pub fn new(_: R) -> Result<RawReader<R>> {
        let handle = try!(get_std_handle(STDIN_FILENO));
        Ok(RawReader {
            handle: handle,
            buf: None,
            phantom: PhantomData,
        })
    }

    pub fn next_key(&mut self, _: bool) -> Result<KeyPress> {
        use std::char::decode_utf16;
        // use winapi::{LEFT_ALT_PRESSED, LEFT_CTRL_PRESSED, RIGHT_ALT_PRESSED, RIGHT_CTRL_PRESSED};
        use winapi::{LEFT_ALT_PRESSED, RIGHT_ALT_PRESSED};

        let mut rec: winapi::INPUT_RECORD = unsafe { mem::zeroed() };
        let mut count = 0;
        let mut esc_seen = false;
        loop {
            // TODO GetNumberOfConsoleInputEvents
            check!(kernel32::ReadConsoleInputW(self.handle,
                                               &mut rec,
                                               1 as winapi::DWORD,
                                               &mut count));

            if rec.EventType == winapi::WINDOW_BUFFER_SIZE_EVENT {
                SIGWINCH.store(true, atomic::Ordering::SeqCst);
                return Err(error::ReadlineError::WindowResize);
            } else if rec.EventType != winapi::KEY_EVENT {
                continue;
            }
            let key_event = unsafe { rec.KeyEvent() };
            // writeln!(io::stderr(), "key_event: {:?}", key_event).unwrap();
            if key_event.bKeyDown == 0 &&
               key_event.wVirtualKeyCode != winapi::VK_MENU as winapi::WORD {
                continue;
            }

            // let alt_gr = key_event.dwControlKeyState & (LEFT_CTRL_PRESSED | RIGHT_ALT_PRESSED) ==
            // (LEFT_CTRL_PRESSED | RIGHT_ALT_PRESSED);
            let alt = key_event.dwControlKeyState & (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED) ==
                      (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED);
            // let ctrl = key_event.dwControlKeyState & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED) ==
            // (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED);
            let meta = alt || esc_seen;

            let utf16 = key_event.UnicodeChar;
            if utf16 == 0 {
                match key_event.wVirtualKeyCode as i32 {
                    winapi::VK_LEFT => return Ok(KeyPress::Left),
                    winapi::VK_RIGHT => return Ok(KeyPress::Right),
                    winapi::VK_UP => return Ok(KeyPress::Up),
                    winapi::VK_DOWN => return Ok(KeyPress::Down),
                    winapi::VK_DELETE => return Ok(KeyPress::Delete),
                    winapi::VK_HOME => return Ok(KeyPress::Home),
                    winapi::VK_END => return Ok(KeyPress::End),
                    _ => continue,
                };
            } else if utf16 == 27 {
                esc_seen = true;
                continue;
            } else {
                // TODO How to support surrogate pair ?
                self.buf = Some(utf16);
                let orc = decode_utf16(self).next();
                if orc.is_none() {
                    return Err(error::ReadlineError::Eof);
                }
                let c = try!(orc.unwrap());
                if meta {
                    match c {
                        'b' | 'B' => return Ok(KeyPress::Meta('B')),
                        'c' | 'C' => return Ok(KeyPress::Meta('C')),
                        'd' | 'D' => return Ok(KeyPress::Meta('D')),
                        'f' | 'F' => return Ok(KeyPress::Meta('F')),
                        'l' | 'L' => return Ok(KeyPress::Meta('L')),
                        't' | 'T' => return Ok(KeyPress::Meta('T')),
                        'u' | 'U' => return Ok(KeyPress::Meta('U')),
                        'y' | 'Y' => return Ok(KeyPress::Meta('Y')),
                        _ => return Ok(KeyPress::UnknownEscSeq),
                    }
                } else {
                    return Ok(consts::char_to_key_press(c));
                }
            }
        }
    }
}

impl<R: Read> Iterator for RawReader<R> {
    type Item = u16;

    fn next(&mut self) -> Option<u16> {
        let buf = self.buf;
        self.buf = None;
        buf
    }
}

pub static SIGWINCH: atomic::AtomicBool = atomic::ATOMIC_BOOL_INIT;

pub fn install_sigwinch_handler() {
    // See ReadConsoleInputW && WINDOW_BUFFER_SIZE_EVENT
}
<commit_msg>Fix windows part<commit_after>use std::io;
use std::io::{Read, Write};
use std::marker::PhantomData;
use std::mem;
use std::sync::atomic;

use kernel32;
use winapi;

use consts::{self, KeyPress};
use ::error;
use ::Result;

pub type Handle = winapi::HANDLE;
pub type Mode = winapi::DWORD;
pub const STDIN_FILENO: winapi::DWORD = winapi::STD_INPUT_HANDLE;
pub const STDOUT_FILENO: winapi::DWORD = winapi::STD_OUTPUT_HANDLE;

fn get_std_handle(fd: winapi::DWORD) -> Result<winapi::HANDLE> {
    let handle = unsafe { kernel32::GetStdHandle(fd) };
    if handle == winapi::INVALID_HANDLE_VALUE {
        try!(Err(io::Error::last_os_error()));
    } else if handle.is_null() {
        try!(Err(io::Error::new(io::ErrorKind::Other,
                                "no stdio handle available for this process")));
    }
    Ok(handle)
}

#[macro_export]
macro_rules! check {
    ($funcall:expr) => {
        {
        let rc = unsafe { $funcall };
        if rc == 0 {
            try!(Err(io::Error::last_os_error()));
        }
        rc
        }
    };
}

/// Try to get the number of columns in the current terminal,
/// or assume 80 if it fails.
pub fn get_columns(handle: Handle) -> usize {
    let (cols, _) = get_win_size(handle);
    cols
}

/// Try to get the number of rows in the current terminal,
/// or assume 24 if it fails.
pub fn get_rows(handle: Handle) -> usize {
    let (_, rows) = get_win_size(handle);
    rows
}

fn get_win_size(handle: Handle) -> (usize, usize) {
    let mut info = unsafe { mem::zeroed() };
    match unsafe { kernel32::GetConsoleScreenBufferInfo(handle, &mut info) } {
        0 => (80, 24),
        _ => (info.dwSize.X as usize, 1 + info.srWindow.Bottom - info.srWindow.Top),
    }
}

/// Checking for an unsupported TERM in windows is a no-op
pub fn is_unsupported_term() -> bool {
    false
}

fn get_console_mode(handle: winapi::HANDLE) -> Result<Mode> {
    let mut original_mode = 0;
    check!(kernel32::GetConsoleMode(handle, &mut original_mode));
    Ok(original_mode)
}

/// Return whether or not STDIN, STDOUT or STDERR is a TTY
pub fn is_a_tty(fd: winapi::DWORD) -> bool {
    let handle = get_std_handle(fd);
    match handle {
        Ok(handle) => {
            // If this function doesn't fail then fd is a TTY
            get_console_mode(handle).is_ok()
        }
        Err(_) => false,
    }
}

/// Enable raw mode for the TERM
pub fn enable_raw_mode() -> Result<Mode> {
    let handle = try!(get_std_handle(STDIN_FILENO));
    let original_mode = try!(get_console_mode(handle));
    // Disable these modes
    let raw = original_mode &
              !(winapi::wincon::ENABLE_LINE_INPUT | winapi::wincon::ENABLE_ECHO_INPUT |
                winapi::wincon::ENABLE_PROCESSED_INPUT);
    // Enable these modes
    let raw = raw | winapi::wincon::ENABLE_EXTENDED_FLAGS;
    let raw = raw | winapi::wincon::ENABLE_INSERT_MODE;
    let raw = raw | winapi::wincon::ENABLE_QUICK_EDIT_MODE;
    let raw = raw | winapi::wincon::ENABLE_WINDOW_INPUT;
    check!(kernel32::SetConsoleMode(handle, raw));
    Ok(original_mode)
}

/// Disable Raw mode for the term
pub fn disable_raw_mode(original_mode: Mode) -> Result<()> {
    let handle = try!(get_std_handle(STDIN_FILENO));
    check!(kernel32::SetConsoleMode(handle, original_mode));
    Ok(())
}

pub fn stdout_handle() -> Result<Handle> {
    let handle = try!(get_std_handle(STDOUT_FILENO));
    Ok(handle)
}

/// Clear the screen. Used to handle ctrl+l
pub fn clear_screen(_: &mut Write, handle: Handle) -> Result<()> {
    let mut info = unsafe { mem::zeroed() };
    check!(kernel32::GetConsoleScreenBufferInfo(handle, &mut info));
    let coord = winapi::COORD { X: 0, Y: 0 };
    check!(kernel32::SetConsoleCursorPosition(handle, coord));
    let mut _count = 0;
    let n = info.dwSize.X as winapi::DWORD * info.dwSize.Y as winapi::DWORD;
    check!(kernel32::FillConsoleOutputCharacterA(handle,
                                                 ' ' as winapi::CHAR,
                                                 n,
                                                 coord,
                                                 &mut _count));
    Ok(())
}

/// Console input reader
pub struct RawReader<R> {
    handle: winapi::HANDLE,
    buf: Option<u16>,
    phantom: PhantomData<R>,
}

impl<R: Read> RawReader<R> {
    pub fn new(_: R) -> Result<RawReader<R>> {
        let handle = try!(get_std_handle(STDIN_FILENO));
        Ok(RawReader {
            handle: handle,
            buf: None,
            phantom: PhantomData,
        })
    }

    pub fn next_key(&mut self, _: bool) -> Result<KeyPress> {
        use std::char::decode_utf16;
        // use winapi::{LEFT_ALT_PRESSED, LEFT_CTRL_PRESSED, RIGHT_ALT_PRESSED, RIGHT_CTRL_PRESSED};
        use winapi::{LEFT_ALT_PRESSED, RIGHT_ALT_PRESSED};

        let mut rec: winapi::INPUT_RECORD = unsafe { mem::zeroed() };
        let mut count = 0;
        let mut esc_seen = false;
        loop {
            // TODO GetNumberOfConsoleInputEvents
            check!(kernel32::ReadConsoleInputW(self.handle,
                                               &mut rec,
                                               1 as winapi::DWORD,
                                               &mut count));

            if rec.EventType == winapi::WINDOW_BUFFER_SIZE_EVENT {
                SIGWINCH.store(true, atomic::Ordering::SeqCst);
                return Err(error::ReadlineError::WindowResize);
            } else if rec.EventType != winapi::KEY_EVENT {
                continue;
            }
            let key_event = unsafe { rec.KeyEvent() };
            // writeln!(io::stderr(), "key_event: {:?}", key_event).unwrap();
            if key_event.bKeyDown == 0 &&
               key_event.wVirtualKeyCode != winapi::VK_MENU as winapi::WORD {
                continue;
            }

            // let alt_gr = key_event.dwControlKeyState & (LEFT_CTRL_PRESSED | RIGHT_ALT_PRESSED) ==
            // (LEFT_CTRL_PRESSED | RIGHT_ALT_PRESSED);
            let alt = key_event.dwControlKeyState & (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED) ==
                      (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED);
            // let ctrl = key_event.dwControlKeyState & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED) ==
            // (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED);
            let meta = alt || esc_seen;

            let utf16 = key_event.UnicodeChar;
            if utf16 == 0 {
                match key_event.wVirtualKeyCode as i32 {
                    winapi::VK_LEFT => return Ok(KeyPress::Left),
                    winapi::VK_RIGHT => return Ok(KeyPress::Right),
                    winapi::VK_UP => return Ok(KeyPress::Up),
                    winapi::VK_DOWN => return Ok(KeyPress::Down),
                    winapi::VK_DELETE => return Ok(KeyPress::Delete),
                    winapi::VK_HOME => return Ok(KeyPress::Home),
                    winapi::VK_END => return Ok(KeyPress::End),
                    _ => continue,
                };
            } else if utf16 == 27 {
                esc_seen = true;
                continue;
            } else {
                // TODO How to support surrogate pair ?
                self.buf = Some(utf16);
                let orc = decode_utf16(self).next();
                if orc.is_none() {
                    return Err(error::ReadlineError::Eof);
                }
                let c = try!(orc.unwrap());
                if meta {
                    match c {
                        'b' | 'B' => return Ok(KeyPress::Meta('B')),
                        'c' | 'C' => return Ok(KeyPress::Meta('C')),
                        'd' | 'D' => return Ok(KeyPress::Meta('D')),
                        'f' | 'F' => return Ok(KeyPress::Meta('F')),
                        'l' | 'L' => return Ok(KeyPress::Meta('L')),
                        't' | 'T' => return Ok(KeyPress::Meta('T')),
                        'u' | 'U' => return Ok(KeyPress::Meta('U')),
                        'y' | 'Y' => return Ok(KeyPress::Meta('Y')),
                        _ => return Ok(KeyPress::UnknownEscSeq),
                    }
                } else {
                    return Ok(consts::char_to_key_press(c));
                }
            }
        }
    }
}

impl<R: Read> Iterator for RawReader<R> {
    type Item = u16;

    fn next(&mut self) -> Option<u16> {
        let buf = self.buf;
        self.buf = None;
        buf
    }
}

pub static SIGWINCH: atomic::AtomicBool = atomic::ATOMIC_BOOL_INIT;

pub fn install_sigwinch_handler() {
    // See ReadConsoleInputW && WINDOW_BUFFER_SIZE_EVENT
}
<|endoftext|>


<commit_before>use std::io;

use ::Asn1Info;
use tag;
use err;
use ber::enc;

/// Provides the methods required to serialize this Rust type into an ASN.1 stream.
///
/// When implementing this for a simple primitive type, implementing `serialize_value`
/// should be all that's required.
pub trait BerSerialize: Asn1Info {
  /// Serialize a value into ASN.1 data as DER.
  fn serialize<W: io::Write>(&self, writer: &mut W) -> Result<(), err::EncodeError> {
    self.serialize_enc(enc::DER, writer)
  }

  /// Serialize a value into ASN.1 data using a specific set of encoding rules.
  fn serialize_enc<E: enc::BerEncRules, W: io::Write>
      (&self, e: E, writer: &mut W) -> Result<(), err::EncodeError> {
    debug!("Encoding the type {}", Self::asn1_type());
    if let Some(r) = self._serialize_enc(e, writer) {
      return r;
    }

    let tag = match Self::asn1_tag() {
      Some(tag) => tag,
      None => {
        debug!("Type does not have a tag");
        return self.serialize_value(e, writer);
      },
    };

    try!(tag.write_tag(writer));

    // If this is indefinite length and constructed, write the data directly.
    if E::len_rules() == enc::LenEnc::Indefinite &&
       tag.constructed {
      debug!("Using indefinite length");
      try!(tag::Len::Indef.write_len(writer));
      try!(self.serialize_value(e, writer));
      try!(tag::Len::write_indef_end(writer));
    // Otherwise write to a Vec first, so we can write the length.
    } else {
      debug!("Using definite length encoding");
      let mut bytes: Vec<u8> = Vec::new();
      try!(self.serialize_value(e, &mut bytes));
      try!(tag::Len::write_len(Some(bytes.len() as tag::LenNum).into(), writer));
      try!(writer.write_all(&bytes));
    }

    Ok(())
  }

  fn _serialize_enc<E: enc::BerEncRules, W: io::Write>
      (&self, e: E, writer: &mut W) -> Option<Result<(), err::EncodeError>> {
    let _ = (e, writer);
    None
  }

  /// Serialise a value into ASN.1 data, without a tag (implicit tagging).
  fn serialize_value<E: enc::BerEncRules, W: io::Write>
    (&self, e: E, writer: &mut W) -> Result<(), err::EncodeError>;
}

/// Provides the methods required to deserialize this Rust type from an ASN.1 stream.
///
/// When implementing this for a simple primitive type, implementing `deserialize_value`
/// should be all that's required.
pub trait BerDeserialize: Asn1Info + Sized {
  /// Deserialize ASN.1 data into a Rust value, accepting any valid BER.
  fn deserialize<I: Iterator<Item=io::Result<u8>>>(reader: &mut I) -> Result<Self, err::DecodeError> {
    Self::deserialize_enc(enc::BER, reader)
  }

  /// Deserialize ASN.1 data into a Rust value, using a specific set of encoding rules.
  fn deserialize_enc<E: enc::BerEncRules, I: Iterator<Item=io::Result<u8>>>
      (e: E, reader: &mut I) -> Result<Self, err::DecodeError> {
    let (tag, len) = try!(tag::read_taglen(reader));
    Self::deserialize_with_tag(e, reader, tag, len)
  }

  /// Deserialize ASN.1 data into a Rust value, using a specific set of encoding rules, and
  /// also providing the decoded tag and length.
  ///
  /// This function assumes the next bytes to decode are
  /// the BER length of this element.
  fn deserialize_with_tag<E: enc::BerEncRules, I: Iterator<Item=io::Result<u8>>>
      (e: E, reader: &mut I, tag: tag::Tag, len: tag::Len) -> Result<Self, err::DecodeError> {
    debug!("Decoding the type {}", Self::asn1_type());
    if let Some(r) = Self::_deserialize_with_tag(e, reader, tag, len) {
      return r;
    }

    if let None = Self::asn1_tag() {
      panic!("Trying to decode item with no defined tag.");
    };

    if Some(tag) != Self::asn1_tag() {
      if let Some(our_tag) = Self::asn1_tag() {
        error!("Expected tag {}, but found tag {}", tag, our_tag);
      } else {
        error!("Expected tag {}, but found no tag", tag);
      }
      return Err(err::DecodeError::TagTypeMismatch);
    }

    // Handle any indefinite length error conditions.
    if len == tag::Len::Indef {
      // Return an error if the encoding rules only allow definite length
      // encoding.
      if E::len_rules() == enc::LenEnc::Definite {
        error!("Encountered indefinite length encoding, but encoding rules don't allow this");
        return Err(err::DecodeError::IndefiniteLen);
      // If this element is primitve, the length isn't allowed to be indefinite length.
      } else if !tag.constructed {
        error!("Encountered indefinite length encoding, but this is a primitive element");
        return Err(err::DecodeError::PrimIndef)
      }
    }
    // Read the main data.
    let item: Self = try!(Self::deserialize_value(e, reader, len));

    // If this is encoded with an indefinte length, try to read the end octets.
    if len == tag::Len::Indef {
      try!(tag::Len::read_indef_end(reader));
    }

    Ok(item)
  }

  fn _deserialize_with_tag<E: enc::BerEncRules, I: Iterator<Item=io::Result<u8>>>
      (e: E, reader: &mut I, tag: tag::Tag, len: tag::Len) -> Option<Result<Self, err::DecodeError>> {
    let _ = (e, reader, tag, len);
    None
  }

  /// Deserialize an ASN.1 value from a BER stream, after having the tag and length
  /// decoded.
  ///
  /// The data length must be explicitly passed to this function. For primitive types,
  /// an error will be returned if this length is Indefinite.
  fn deserialize_value<E: enc::BerEncRules, I: Iterator<Item=io::Result<u8>>>
    (e: E, reader: &mut I, len: tag::Len) -> Result<Self, err::DecodeError> {
    let (_, _, _) = (e, reader, len);
    panic!("deserialize_value must be implemented for types that require it");
  }
}
<commit_msg>Use warn! instead of error! in traits.rs<commit_after>use std::io;

use ::Asn1Info;
use tag;
use err;
use ber::enc;

/// Provides the methods required to serialize this Rust type into an ASN.1 stream.
///
/// When implementing this for a simple primitive type, implementing `serialize_value`
/// should be all that's required.
pub trait BerSerialize: Asn1Info {
  /// Serialize a value into ASN.1 data as DER.
  fn serialize<W: io::Write>(&self, writer: &mut W) -> Result<(), err::EncodeError> {
    self.serialize_enc(enc::DER, writer)
  }

  /// Serialize a value into ASN.1 data using a specific set of encoding rules.
  fn serialize_enc<E: enc::BerEncRules, W: io::Write>
      (&self, e: E, writer: &mut W) -> Result<(), err::EncodeError> {
    debug!("Encoding the type {}", Self::asn1_type());
    if let Some(r) = self._serialize_enc(e, writer) {
      return r;
    }

    let tag = match Self::asn1_tag() {
      Some(tag) => tag,
      None => {
        debug!("Type does not have a tag");
        return self.serialize_value(e, writer);
      },
    };

    try!(tag.write_tag(writer));

    // If this is indefinite length and constructed, write the data directly.
    if E::len_rules() == enc::LenEnc::Indefinite &&
       tag.constructed {
      debug!("Using indefinite length");
      try!(tag::Len::Indef.write_len(writer));
      try!(self.serialize_value(e, writer));
      try!(tag::Len::write_indef_end(writer));
    // Otherwise write to a Vec first, so we can write the length.
    } else {
      debug!("Using definite length encoding");
      let mut bytes: Vec<u8> = Vec::new();
      try!(self.serialize_value(e, &mut bytes));
      try!(tag::Len::write_len(Some(bytes.len() as tag::LenNum).into(), writer));
      try!(writer.write_all(&bytes));
    }

    Ok(())
  }

  fn _serialize_enc<E: enc::BerEncRules, W: io::Write>
      (&self, e: E, writer: &mut W) -> Option<Result<(), err::EncodeError>> {
    let _ = (e, writer);
    None
  }

  /// Serialise a value into ASN.1 data, without a tag (implicit tagging).
  fn serialize_value<E: enc::BerEncRules, W: io::Write>
    (&self, e: E, writer: &mut W) -> Result<(), err::EncodeError>;
}

/// Provides the methods required to deserialize this Rust type from an ASN.1 stream.
///
/// When implementing this for a simple primitive type, implementing `deserialize_value`
/// should be all that's required.
pub trait BerDeserialize: Asn1Info + Sized {
  /// Deserialize ASN.1 data into a Rust value, accepting any valid BER.
  fn deserialize<I: Iterator<Item=io::Result<u8>>>(reader: &mut I) -> Result<Self, err::DecodeError> {
    Self::deserialize_enc(enc::BER, reader)
  }

  /// Deserialize ASN.1 data into a Rust value, using a specific set of encoding rules.
  fn deserialize_enc<E: enc::BerEncRules, I: Iterator<Item=io::Result<u8>>>
      (e: E, reader: &mut I) -> Result<Self, err::DecodeError> {
    let (tag, len) = try!(tag::read_taglen(reader));
    Self::deserialize_with_tag(e, reader, tag, len)
  }

  /// Deserialize ASN.1 data into a Rust value, using a specific set of encoding rules, and
  /// also providing the decoded tag and length.
  ///
  /// This function assumes the next bytes to decode are
  /// the BER length of this element.
  fn deserialize_with_tag<E: enc::BerEncRules, I: Iterator<Item=io::Result<u8>>>
      (e: E, reader: &mut I, tag: tag::Tag, len: tag::Len) -> Result<Self, err::DecodeError> {
    debug!("Decoding the type {}", Self::asn1_type());
    if let Some(r) = Self::_deserialize_with_tag(e, reader, tag, len) {
      return r;
    }

    if Some(tag) != Self::asn1_tag() {
      if let Some(our_tag) = Self::asn1_tag() {
        warn!("Expected tag {}, but found tag {}", tag, our_tag);
      } else {
        warn!("Expected tag {}, but found no tag", tag);
      }
      return Err(err::DecodeError::TagTypeMismatch);
    }

    // Handle any indefinite length error conditions.
    if len == tag::Len::Indef {
      // Return an error if the encoding rules only allow definite length
      // encoding.
      if E::len_rules() == enc::LenEnc::Definite {
        warn!("Encountered indefinite length encoding, but encoding rules don't allow this");
        return Err(err::DecodeError::IndefiniteLen);
      // If this element is primitve, the length isn't allowed to be indefinite length.
      } else if !tag.constructed {
        warn!("Encountered indefinite length encoding, but this is a primitive element");
        return Err(err::DecodeError::PrimIndef)
      }
    }
    // Read the main data.
    let item: Self = try!(Self::deserialize_value(e, reader, len));

    // If this is encoded with an indefinte length, try to read the end octets.
    if len == tag::Len::Indef {
      try!(tag::Len::read_indef_end(reader));
    }

    Ok(item)
  }

  fn _deserialize_with_tag<E: enc::BerEncRules, I: Iterator<Item=io::Result<u8>>>
      (e: E, reader: &mut I, tag: tag::Tag, len: tag::Len) -> Option<Result<Self, err::DecodeError>> {
    let _ = (e, reader, tag, len);
    None
  }

  /// Deserialize an ASN.1 value from a BER stream, after having the tag and length
  /// decoded.
  ///
  /// The data length must be explicitly passed to this function. For primitive types,
  /// an error will be returned if this length is Indefinite.
  fn deserialize_value<E: enc::BerEncRules, I: Iterator<Item=io::Result<u8>>>
    (e: E, reader: &mut I, len: tag::Len) -> Result<Self, err::DecodeError> {
    let (_, _, _) = (e, reader, len);
    panic!("deserialize_value must be implemented for types that require it");
  }
}
<|endoftext|>


<commit_before>pub mod village_manager;

use self::village_manager::*;
use village::*;
use village::resource::*;
use village_mind::*;
use village_mind::trade_request::*;
use std::cell::RefCell;
use std::rc::Rc;
use std::collections::HashMap;

#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
pub enum PriceDirection {
    Upward,
    Downward,
    Equilibrium,
}

pub struct Simulation {
    village_managers: Vec<VillageManager>,
    pub prices: HashMap<ResourceType, u32>,
    pub price_directions: HashMap<ResourceType, PriceDirection>,
}

impl Simulation {
    pub fn new() -> Simulation {

        let mut simulation = Simulation {
            village_managers: vec!(),
            prices: HashMap::new(),
            price_directions: HashMap::new(),
        };

        //for each resource (other than gold), put the starting price at one gold
        for resource_type in ResourceType::iterator() {
            if *resource_type != ResourceType::Gold {
                simulation.prices.insert(*resource_type, 1);
                simulation.price_directions.insert(*resource_type, PriceDirection::Equilibrium);
            }
        }
        simulation
    }

    pub fn add_village(&mut self, village: Village) {
        let villageRC = Rc::new(RefCell::new(village));
        let village_manager = VillageManager {
            village: villageRC.clone(),
            village_mind: VillageMind::new(villageRC.clone()),
        };

        self.village_managers.push(village_manager);
    }

    pub fn village_managers(&self) -> &Vec<VillageManager> {
        &self.village_managers
    }

    pub fn simulate(&mut self) {
        // update the villages and village minds with the new information
        for vm in self.village_managers.iter_mut() {
            vm.village.borrow_mut().simulate();
            vm.village_mind.manage_village();
        }

        // do the trading phase until no more trade request are given
        let mut trading = true;
        let mut trade_requests : Vec<TradeRequest> = Vec::new();

        while trading {
            trade_requests.clear();

            for mut vm in self.village_managers.iter_mut() {
                trade_requests.append(&mut vm.village_mind.trade());
            }

            if trade_requests.len() == 0 {
                trading = false;
            }
        }

        // update village minds
        for vm in self.village_managers.iter_mut() {
            vm.village_mind.manage_village();
        }
    }

    pub fn handleTrades(&mut self, trade_requests: &mut Vec<TradeRequest>) {
        // get the trade request for each resource type minus gold
        for resource_type in ResourceType::iterator().filter(|r| **r != ResourceType::Gold) {
            // get the total number of buys and sells requested for a resource at the current price
            let mut buys = 0;
            let mut sells = 0;
            for trade_request in trade_requests.iter_mut().filter(|t| t.resource_type == *resource_type) {
                if trade_request.trade_type == TradeType::Buy {
                    buys += trade_request.amount;
                } else {
                    sells += trade_request.amount;
                }
            }

            // if number of buys and sells are equal consider the price at equilibrium and fulfill the trade requests
            if buys == sells {
                for trade_request_of_type in trade_requests.iter_mut().filter(|t| t.resource_type == *resource_type) {
                    trade_request_of_type.success = true;
                }
                println!("{0}", self.price_directions.len());
                self.price_directions.insert(*resource_type, PriceDirection::Equilibrium);
            }
            // if the of buyers are greater then sellers, the price direction will be upward
//            if buys > sells {
//                self.Pri
//            }

        }
    }
}

#[cfg(test)]
mod tests {
    use village::*;
    use village_mind::*;
    use simulation::*;
    use village::resource::*;
    use village_mind::trade_request::*;

    fn default_village() -> Village {
        Village::new(|w: &worker::Worker| false)
    }

    #[test]
    fn add_village() {
        let mut simulation = Simulation::new();
        simulation.add_village(default_village());

        assert_eq!(1, simulation.village_managers().len());
    }

    #[test]
    fn initial_resource_prices() {
        let mut simulation = Simulation::new();

        assert_eq!(1, *simulation.prices.get(&ResourceType::Food).unwrap());
    }

    #[test]
    fn initial_price_directions() {
        let mut simulation = Simulation::new();

        assert_eq!(PriceDirection::Equilibrium, *simulation.price_directions.get(&ResourceType::Food).unwrap());
    }

    #[test]
    fn handle_trades_basic_sell_and_buy() {
        let mut simulation = Simulation::new();
        let mut trade_requests : Vec<TradeRequest> = Vec::new();
        trade_requests.push(TradeRequest::new(TradeType::Buy, 1, ResourceType::Food));
        trade_requests.push(TradeRequest::new(TradeType::Sell, 1, ResourceType::Food));
        simulation.handleTrades(&mut trade_requests);

        assert_eq!(true, trade_requests.get(0).unwrap().success);
        assert_eq!(true, trade_requests.get(1).unwrap().success);
    }
}<commit_msg>Finished handling basic trading<commit_after>pub mod village_manager;

use self::village_manager::*;
use village::*;
use village::resource::*;
use village_mind::*;
use village_mind::trade_request::*;
use std::cell::RefCell;
use std::rc::Rc;
use std::collections::HashMap;

#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
pub enum PriceDirection {
    Upward,
    Downward,
    Equilibrium,
}

pub struct Simulation {
    village_managers: Vec<VillageManager>,
    pub prices: HashMap<ResourceType, u32>,
    pub price_directions: HashMap<ResourceType, PriceDirection>,
}

impl Simulation {
    pub fn new() -> Simulation {

        let mut simulation = Simulation {
            village_managers: vec!(),
            prices: HashMap::new(),
            price_directions: HashMap::new(),
        };

        //for each resource (other than gold), put the starting price at one gold
        for resource_type in ResourceType::iterator() {
            if *resource_type != ResourceType::Gold {
                simulation.prices.insert(*resource_type, 5);
                simulation.price_directions.insert(*resource_type, PriceDirection::Equilibrium);
            }
        }
        simulation
    }

    pub fn add_village(&mut self, village: Village) {
        let villageRC = Rc::new(RefCell::new(village));
        let village_manager = VillageManager {
            village: villageRC.clone(),
            village_mind: VillageMind::new(villageRC.clone()),
        };

        self.village_managers.push(village_manager);
    }

    pub fn village_managers(&self) -> &Vec<VillageManager> {
        &self.village_managers
    }

    pub fn simulate(&mut self) {
        // update the villages and village minds with the new information
        for vm in self.village_managers.iter_mut() {
            vm.village.borrow_mut().simulate();
            vm.village_mind.manage_village();
        }

        // do the trading phase until no more trade request are given
        let mut trading = true;
        let mut trade_requests : Vec<TradeRequest> = Vec::new();

        while trading {
            trade_requests.clear();

            for mut vm in self.village_managers.iter_mut() {
                trade_requests.append(&mut vm.village_mind.trade());
            }

            if trade_requests.len() == 0 {
                trading = false;
            }
        }

        // update village minds
        for vm in self.village_managers.iter_mut() {
            vm.village_mind.manage_village();
        }
    }

    pub fn handleTrades(&mut self, trade_requests: &mut Vec<TradeRequest>) {
        // get the trade request for each resource type minus gold
        for resource_type in ResourceType::iterator().filter(|r| **r != ResourceType::Gold) {
            // get the total number of buys and sells requested for a resource at the current price
            let mut buys = 0;
            let mut sells = 0;
            for trade_request in trade_requests.iter_mut().filter(|t| t.resource_type == *resource_type) {
                if trade_request.trade_type == TradeType::Buy {
                    buys += trade_request.amount;
                } else {
                    sells += trade_request.amount;
                }
            }

            // if number of buys and sells are equal consider the price at equilibrium and fulfill the trade requests
            if buys == sells {
                for trade_request_of_type in trade_requests.iter_mut().filter(|t| t.resource_type == *resource_type) {
                    trade_request_of_type.success = true;
                }
                self.price_directions.insert(*resource_type, PriceDirection::Equilibrium);
            }
            // if the number of buyers are greater then sellers, the price direction will be upward and the price will increase
            else if buys > sells {
                self.price_directions.insert(*resource_type, PriceDirection::Upward);
                let price = self.prices.get_mut(resource_type).unwrap();
                *price += 1;
            }
            // if the number of sellers are greater then the number of buyers, the price direction will be downward and the price will decrease
            else {
                self.price_directions.insert(*resource_type, PriceDirection::Downward);
                let price = self.prices.get_mut(resource_type).unwrap();
                *price -= 1;
            }
        }
    }
}

#[cfg(test)]
mod tests {
    use village::*;
    use village_mind::*;
    use simulation::*;
    use village::resource::*;
    use village_mind::trade_request::*;

    fn default_village() -> Village {
        Village::new(|w: &worker::Worker| false)
    }

    #[test]
    fn add_village() {
        let mut simulation = Simulation::new();
        simulation.add_village(default_village());

        assert_eq!(1, simulation.village_managers().len());
    }

    #[test]
    fn initial_resource_prices() {
        let mut simulation = Simulation::new();

        assert_eq!(5, *simulation.prices.get(&ResourceType::Food).unwrap());
    }

    #[test]
    fn initial_price_directions() {
        let mut simulation = Simulation::new();

        assert_eq!(PriceDirection::Equilibrium, *simulation.price_directions.get(&ResourceType::Food).unwrap());
    }

    #[test]
    fn handle_trades_basic_sell_and_buy() {
        let mut simulation = Simulation::new();
        let mut trade_requests : Vec<TradeRequest> = Vec::new();
        trade_requests.push(TradeRequest::new(TradeType::Buy, 1, ResourceType::Food));
        trade_requests.push(TradeRequest::new(TradeType::Sell, 1, ResourceType::Food));
        simulation.handleTrades(&mut trade_requests);

        assert_eq!(true, trade_requests.get(0).unwrap().success);
        assert_eq!(true, trade_requests.get(1).unwrap().success);
        assert_eq!(PriceDirection::Equilibrium, *simulation.price_directions.get(&ResourceType::Food).unwrap());
    }

    #[test]
    fn handle_trades_upward_price() {
        let mut simulation = Simulation::new();
        let mut trade_requests : Vec<TradeRequest> = Vec::new();
        trade_requests.push(TradeRequest::new(TradeType::Buy, 1, ResourceType::Food));
        simulation.handleTrades(&mut trade_requests);

        assert_eq!(false, trade_requests.get(0).unwrap().success);
        assert_eq!(PriceDirection::Upward, *simulation.price_directions.get(&ResourceType::Food).unwrap());
        assert_eq!(6, *simulation.prices.get(&ResourceType::Food).unwrap());
    }

    #[test]
    fn handle_trades_downward_price() {
        let mut simulation = Simulation::new();
        let mut trade_requests : Vec<TradeRequest> = Vec::new();
        trade_requests.push(TradeRequest::new(TradeType::Sell, 1, ResourceType::Food));
        simulation.handleTrades(&mut trade_requests);

        assert_eq!(false, trade_requests.get(0).unwrap().success);
        assert_eq!(PriceDirection::Downward, *simulation.price_directions.get(&ResourceType::Food).unwrap());
        assert_eq!(4, *simulation.prices.get(&ResourceType::Food).unwrap());
    }
}<|endoftext|>


<commit_before>// Copyright 2014 The html5ever Project Developers. See the
// COPYRIGHT file at the top-level directory of this distribution.
//
// 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.

#![experimental="This module uses unsafe code, has not been thoroughly \
                 audited, and the performance gains vs. RcDom have not \
                 been demonstrated"]

//! A simple DOM where every node is owned by its parent.
//!
//! Since ownership is more complicated during parsing, we actually
//! build a different type and then transmute to the public `Node`.
//! This is believed to be memory safe, but if you want to be extra
//! careful you can use `RcDom` instead.

use core::prelude::*;

use sink::common::{NodeEnum, Document, Doctype, Text, Comment, Element};

use tokenizer::Attribute;
use tree_builder::{TreeSink, QuirksMode, NodeOrText, AppendNode, AppendText};
use tree_builder;
use serialize::{Serializable, Serializer};
use driver::ParseResult;

use core::cell::UnsafeCell;
use core::default::Default;
use core::mem::transmute;
use core::marker;
use core::mem;
use core::ptr;
use alloc::boxed::Box;
use collections::vec::Vec;
use collections::string::String;
use std::string::CowString;
use std::io::{Writer, IoResult};
use std::collections::HashSet;
use std::ops::{Deref, DerefMut};

use string_cache::QualName;

/// The internal type we use for nodes during parsing.
struct SquishyNode {
    node: NodeEnum,
    parent: Handle,
    children: Vec<Handle>,
}

impl SquishyNode {
    fn new(node: NodeEnum) -> SquishyNode {
        SquishyNode {
            node: node,
            parent: Handle::null(),
            children: vec!(),
        }
    }
}

struct Handle {
    ptr: *const UnsafeCell<SquishyNode>,
    no_send: marker::NoSend,
    no_sync: marker::NoSync,
}

impl Handle {
    fn new(ptr: *const UnsafeCell<SquishyNode>) -> Handle {
        Handle {
            ptr: ptr,
            no_send: marker::NoSend,
            no_sync: marker::NoSync,
        }
    }

    fn null() -> Handle {
        Handle::new(ptr::null())
    }

    fn is_null(&self) -> bool {
        self.ptr.is_null()
    }
}

impl PartialEq for Handle {
    fn eq(&self, other: &Handle) -> bool {
        self.ptr == other.ptr
    }
}

impl Eq for Handle { }

impl Clone for Handle {
    fn clone(&self) -> Handle {
        Handle::new(self.ptr)
    }
}

impl Copy for Handle { }

// The safety of `Deref` and `DerefMut` depends on the invariant that `Handle`s
// can't escape the `Sink`, because nodes are deallocated by consuming the
// `Sink`.

impl DerefMut for Handle {
    fn deref_mut<'a>(&'a mut self) -> &'a mut SquishyNode {
        unsafe {
            transmute::<_, &'a mut SquishyNode>((*self.ptr).get())
        }
    }
}

impl Deref for Handle {
    type Target = SquishyNode;
    fn deref<'a>(&'a self) -> &'a SquishyNode {
        unsafe {
            transmute::<_, &'a SquishyNode>((*self.ptr).get())
        }
    }
}

fn append(mut new_parent: Handle, mut child: Handle) {
    new_parent.children.push(child);
    let parent = &mut child.parent;
    assert!(parent.is_null());
    *parent = new_parent
}

fn get_parent_and_index(child: Handle) -> Option<(Handle, uint)> {
    if child.parent.is_null() {
        return None;
    }

    let to_find = child;
    match child.parent.children.iter().enumerate().find(|&(_, n)| *n == to_find) {
        Some((i, _)) => Some((child.parent, i)),
        None => panic!("have parent but couldn't find in parent's children!"),
    }
}

fn append_to_existing_text(mut prev: Handle, text: &str) -> bool {
    match prev.deref_mut().node {
        Text(ref mut existing) => {
            existing.push_str(text);
            true
        }
        _ => false,
    }
}

pub struct Sink {
    nodes: Vec<Box<UnsafeCell<SquishyNode>>>,
    document: Handle,
    errors: Vec<CowString<'static>>,
    quirks_mode: QuirksMode,
}

impl Default for Sink {
    fn default() -> Sink {
        let mut sink = Sink {
            nodes: vec!(),
            document: Handle::null(),
            errors: vec!(),
            quirks_mode: tree_builder::NoQuirks,
        };
        sink.document = sink.new_node(Document);
        sink
    }
}

impl Sink {
    fn new_node(&mut self, node: NodeEnum) -> Handle {
        self.nodes.push(box UnsafeCell::new(SquishyNode::new(node)));
        let ptr: *const UnsafeCell<SquishyNode> = &**self.nodes.last().unwrap();
        Handle::new(ptr)
    }

    // FIXME(rust-lang/rust#18296): This is separate from remove_from_parent so
    // we can call it.
    fn unparent(&mut self, mut target: Handle) {
        let (mut parent, i) = unwrap_or_return!(get_parent_and_index(target), ());
        parent.children.remove(i);
        target.parent = Handle::null();
    }
}

impl TreeSink<Handle> for Sink {
    fn parse_error(&mut self, msg: CowString<'static>) {
        self.errors.push(msg);
    }

    fn get_document(&mut self) -> Handle {
        self.document
    }

    fn set_quirks_mode(&mut self, mode: QuirksMode) {
        self.quirks_mode = mode;
    }

    fn same_node(&self, x: Handle, y: Handle) -> bool {
        x == y
    }

    fn elem_name(&self, target: Handle) -> QualName {
        match target.node {
            Element(ref name, _) => name.clone(),
            _ => panic!("not an element!"),
        }
    }

    fn create_element(&mut self, name: QualName, attrs: Vec<Attribute>) -> Handle {
        self.new_node(Element(name, attrs))
    }

    fn create_comment(&mut self, text: String) -> Handle {
        self.new_node(Comment(text))
    }

    fn append(&mut self, parent: Handle, child: NodeOrText<Handle>) {
        // Append to an existing Text node if we have one.
        match child {
            AppendText(ref text) => match parent.children.last() {
                Some(h) => if append_to_existing_text(*h, text.as_slice()) { return; },
                _ => (),
            },
            _ => (),
        }

        append(parent, match child {
            AppendText(text) => self.new_node(Text(text)),
            AppendNode(node) => node
        });
    }

    fn append_before_sibling(&mut self,
            sibling: Handle,
            child: NodeOrText<Handle>) -> Result<(), NodeOrText<Handle>> {
        let (mut parent, i) = unwrap_or_return!(get_parent_and_index(sibling), Err(child));

        let mut child = match (child, i) {
            // No previous node.
            (AppendText(text), 0) => self.new_node(Text(text)),

            // Look for a text node before the insertion point.
            (AppendText(text), i) => {
                let prev = parent.children[i-1];
                if append_to_existing_text(prev, text.as_slice()) {
                    return Ok(());
                }
                self.new_node(Text(text))
            }

            // The tree builder promises we won't have a text node after
            // the insertion point.

            // Any other kind of node.
            (AppendNode(node), _) => node,
        };

        if !child.parent.is_null() {
            self.unparent(child);
        }

        child.parent = parent;
        parent.children.insert(i, child);
        Ok(())
    }

    fn append_doctype_to_document(&mut self, name: String, public_id: String, system_id: String) {
        append(self.document, self.new_node(Doctype(name, public_id, system_id)));
    }

    fn add_attrs_if_missing(&mut self, mut target: Handle, mut attrs: Vec<Attribute>) {
        let existing = match target.deref_mut().node {
            Element(_, ref mut attrs) => attrs,
            _ => return,
        };

        // FIXME: quadratic time
        attrs.retain(|attr|
            !existing.iter().any(|e| e.name == attr.name));
        existing.extend(attrs.into_iter());
    }

    fn remove_from_parent(&mut self, target: Handle) {
        self.unparent(target);
    }

    fn mark_script_already_started(&mut self, _node: Handle) { }
}

pub struct Node {
    pub node: NodeEnum,
    _parent_not_accessible: uint,
    pub children: Vec<Box<Node>>,
}

pub struct OwnedDom {
    pub document: Box<Node>,
    pub errors: Vec<CowString<'static>>,
    pub quirks_mode: QuirksMode,
}

impl ParseResult<Sink> for OwnedDom {
    fn get_result(sink: Sink) -> OwnedDom {
        fn walk(live: &mut HashSet<uint>, node: Handle) {
            live.insert(node.ptr as uint);
            for &child in node.deref().children.iter() {
                walk(live, child);
            }
        }

        // Collect addresses of all the nodes that made it into the final tree.
        let mut live = HashSet::new();
        walk(&mut live, sink.document);

        // Forget about the nodes in the final tree; they will be owned by
        // their parent.  In the process of iterating we drop all nodes that
        // aren't in the tree.
        for node in sink.nodes.into_iter() {
            let ptr: *const UnsafeCell<SquishyNode> = &*node;
            if live.contains(&(ptr as uint)) {
                unsafe {
                    mem::forget(node);
                }
            }
        }

        let old_addrs = addrs_of!(sink.document => node, parent, children);

        // Transmute the root to a Node, finalizing the transfer of ownership.
        let document = unsafe {
            mem::transmute::<*const UnsafeCell<SquishyNode>, Box<Node>>(sink.document.ptr)
        };

        // FIXME: do this assertion statically
        let new_addrs = addrs_of!(document => node, _parent_not_accessible, children);
        assert_eq!(old_addrs, new_addrs);

        OwnedDom {
            document: document,
            errors: sink.errors,
            quirks_mode: sink.quirks_mode,
        }
    }
}

impl Serializable for Node {
    fn serialize<'wr, Wr: Writer>(&self,
            serializer: &mut Serializer<'wr, Wr>,
            incl_self: bool) -> IoResult<()> {

        match (incl_self, &self.node) {
            (_, &Element(ref name, ref attrs)) => {
                if incl_self {
                    try!(serializer.start_elem(name.clone(),
                        attrs.iter().map(|at| (&at.name, at.value.as_slice()))));
                }

                for child in self.children.iter() {
                    try!(child.serialize(serializer, true));
                }

                if incl_self {
                    try!(serializer.end_elem(name.clone()));
                }
                Ok(())
            }

            (false, &Document) => {
                for child in self.children.iter() {
                    try!(child.serialize(serializer, true));
                }
                Ok(())
            }

            (false, _) => Ok(()),

            (true, &Doctype(ref name, _, _)) => serializer.write_doctype(name.as_slice()),
            (true, &Text(ref text)) => serializer.write_text(text.as_slice()),
            (true, &Comment(ref text)) => serializer.write_comment(text.as_slice()),

            (true, &Document) => panic!("Can't serialize Document node itself"),
        }
    }
}
<commit_msg>Upgrade to rustc 1.0.0-dev (ed530d7a3 2015-01-16 22:41:16 +0000)<commit_after>// Copyright 2014 The html5ever Project Developers. See the
// COPYRIGHT file at the top-level directory of this distribution.
//
// 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.

#![experimental="This module uses unsafe code, has not been thoroughly \
                 audited, and the performance gains vs. RcDom have not \
                 been demonstrated"]

//! A simple DOM where every node is owned by its parent.
//!
//! Since ownership is more complicated during parsing, we actually
//! build a different type and then transmute to the public `Node`.
//! This is believed to be memory safe, but if you want to be extra
//! careful you can use `RcDom` instead.

use core::prelude::*;

use sink::common::{NodeEnum, Document, Doctype, Text, Comment, Element};

use tokenizer::Attribute;
use tree_builder::{TreeSink, QuirksMode, NodeOrText, AppendNode, AppendText};
use tree_builder;
use serialize::{Serializable, Serializer};
use driver::ParseResult;

use core::cell::UnsafeCell;
use core::default::Default;
use core::mem::transmute;
use core::mem;
use core::ptr;
use alloc::boxed::Box;
use collections::vec::Vec;
use collections::string::String;
use std::string::CowString;
use std::io::{Writer, IoResult};
use std::collections::HashSet;
use std::ops::{Deref, DerefMut};

use string_cache::QualName;

/// The internal type we use for nodes during parsing.
struct SquishyNode {
    node: NodeEnum,
    parent: Handle,
    children: Vec<Handle>,
}

impl SquishyNode {
    fn new(node: NodeEnum) -> SquishyNode {
        SquishyNode {
            node: node,
            parent: Handle::null(),
            children: vec!(),
        }
    }
}

struct Handle {
    ptr: *const UnsafeCell<SquishyNode>,
}

impl Handle {
    fn new(ptr: *const UnsafeCell<SquishyNode>) -> Handle {
        Handle {
            ptr: ptr,
        }
    }

    fn null() -> Handle {
        Handle::new(ptr::null())
    }

    fn is_null(&self) -> bool {
        self.ptr.is_null()
    }
}

impl PartialEq for Handle {
    fn eq(&self, other: &Handle) -> bool {
        self.ptr == other.ptr
    }
}

impl Eq for Handle { }

impl Clone for Handle {
    fn clone(&self) -> Handle {
        Handle::new(self.ptr)
    }
}

impl Copy for Handle { }

// The safety of `Deref` and `DerefMut` depends on the invariant that `Handle`s
// can't escape the `Sink`, because nodes are deallocated by consuming the
// `Sink`.

impl DerefMut for Handle {
    fn deref_mut<'a>(&'a mut self) -> &'a mut SquishyNode {
        unsafe {
            transmute::<_, &'a mut SquishyNode>((*self.ptr).get())
        }
    }
}

impl Deref for Handle {
    type Target = SquishyNode;
    fn deref<'a>(&'a self) -> &'a SquishyNode {
        unsafe {
            transmute::<_, &'a SquishyNode>((*self.ptr).get())
        }
    }
}

fn append(mut new_parent: Handle, mut child: Handle) {
    new_parent.children.push(child);
    let parent = &mut child.parent;
    assert!(parent.is_null());
    *parent = new_parent
}

fn get_parent_and_index(child: Handle) -> Option<(Handle, uint)> {
    if child.parent.is_null() {
        return None;
    }

    let to_find = child;
    match child.parent.children.iter().enumerate().find(|&(_, n)| *n == to_find) {
        Some((i, _)) => Some((child.parent, i)),
        None => panic!("have parent but couldn't find in parent's children!"),
    }
}

fn append_to_existing_text(mut prev: Handle, text: &str) -> bool {
    match prev.deref_mut().node {
        Text(ref mut existing) => {
            existing.push_str(text);
            true
        }
        _ => false,
    }
}

pub struct Sink {
    nodes: Vec<Box<UnsafeCell<SquishyNode>>>,
    document: Handle,
    errors: Vec<CowString<'static>>,
    quirks_mode: QuirksMode,
}

impl Default for Sink {
    fn default() -> Sink {
        let mut sink = Sink {
            nodes: vec!(),
            document: Handle::null(),
            errors: vec!(),
            quirks_mode: tree_builder::NoQuirks,
        };
        sink.document = sink.new_node(Document);
        sink
    }
}

impl Sink {
    fn new_node(&mut self, node: NodeEnum) -> Handle {
        self.nodes.push(box UnsafeCell::new(SquishyNode::new(node)));
        let ptr: *const UnsafeCell<SquishyNode> = &**self.nodes.last().unwrap();
        Handle::new(ptr)
    }

    // FIXME(rust-lang/rust#18296): This is separate from remove_from_parent so
    // we can call it.
    fn unparent(&mut self, mut target: Handle) {
        let (mut parent, i) = unwrap_or_return!(get_parent_and_index(target), ());
        parent.children.remove(i);
        target.parent = Handle::null();
    }
}

impl TreeSink<Handle> for Sink {
    fn parse_error(&mut self, msg: CowString<'static>) {
        self.errors.push(msg);
    }

    fn get_document(&mut self) -> Handle {
        self.document
    }

    fn set_quirks_mode(&mut self, mode: QuirksMode) {
        self.quirks_mode = mode;
    }

    fn same_node(&self, x: Handle, y: Handle) -> bool {
        x == y
    }

    fn elem_name(&self, target: Handle) -> QualName {
        match target.node {
            Element(ref name, _) => name.clone(),
            _ => panic!("not an element!"),
        }
    }

    fn create_element(&mut self, name: QualName, attrs: Vec<Attribute>) -> Handle {
        self.new_node(Element(name, attrs))
    }

    fn create_comment(&mut self, text: String) -> Handle {
        self.new_node(Comment(text))
    }

    fn append(&mut self, parent: Handle, child: NodeOrText<Handle>) {
        // Append to an existing Text node if we have one.
        match child {
            AppendText(ref text) => match parent.children.last() {
                Some(h) => if append_to_existing_text(*h, text.as_slice()) { return; },
                _ => (),
            },
            _ => (),
        }

        append(parent, match child {
            AppendText(text) => self.new_node(Text(text)),
            AppendNode(node) => node
        });
    }

    fn append_before_sibling(&mut self,
            sibling: Handle,
            child: NodeOrText<Handle>) -> Result<(), NodeOrText<Handle>> {
        let (mut parent, i) = unwrap_or_return!(get_parent_and_index(sibling), Err(child));

        let mut child = match (child, i) {
            // No previous node.
            (AppendText(text), 0) => self.new_node(Text(text)),

            // Look for a text node before the insertion point.
            (AppendText(text), i) => {
                let prev = parent.children[i-1];
                if append_to_existing_text(prev, text.as_slice()) {
                    return Ok(());
                }
                self.new_node(Text(text))
            }

            // The tree builder promises we won't have a text node after
            // the insertion point.

            // Any other kind of node.
            (AppendNode(node), _) => node,
        };

        if !child.parent.is_null() {
            self.unparent(child);
        }

        child.parent = parent;
        parent.children.insert(i, child);
        Ok(())
    }

    fn append_doctype_to_document(&mut self, name: String, public_id: String, system_id: String) {
        append(self.document, self.new_node(Doctype(name, public_id, system_id)));
    }

    fn add_attrs_if_missing(&mut self, mut target: Handle, mut attrs: Vec<Attribute>) {
        let existing = match target.deref_mut().node {
            Element(_, ref mut attrs) => attrs,
            _ => return,
        };

        // FIXME: quadratic time
        attrs.retain(|attr|
            !existing.iter().any(|e| e.name == attr.name));
        existing.extend(attrs.into_iter());
    }

    fn remove_from_parent(&mut self, target: Handle) {
        self.unparent(target);
    }

    fn mark_script_already_started(&mut self, _node: Handle) { }
}

pub struct Node {
    pub node: NodeEnum,
    _parent_not_accessible: uint,
    pub children: Vec<Box<Node>>,
}

pub struct OwnedDom {
    pub document: Box<Node>,
    pub errors: Vec<CowString<'static>>,
    pub quirks_mode: QuirksMode,
}

impl ParseResult<Sink> for OwnedDom {
    fn get_result(sink: Sink) -> OwnedDom {
        fn walk(live: &mut HashSet<uint>, node: Handle) {
            live.insert(node.ptr as uint);
            for &child in node.deref().children.iter() {
                walk(live, child);
            }
        }

        // Collect addresses of all the nodes that made it into the final tree.
        let mut live = HashSet::new();
        walk(&mut live, sink.document);

        // Forget about the nodes in the final tree; they will be owned by
        // their parent.  In the process of iterating we drop all nodes that
        // aren't in the tree.
        for node in sink.nodes.into_iter() {
            let ptr: *const UnsafeCell<SquishyNode> = &*node;
            if live.contains(&(ptr as uint)) {
                unsafe {
                    mem::forget(node);
                }
            }
        }

        let old_addrs = addrs_of!(sink.document => node, parent, children);

        // Transmute the root to a Node, finalizing the transfer of ownership.
        let document = unsafe {
            mem::transmute::<*const UnsafeCell<SquishyNode>, Box<Node>>(sink.document.ptr)
        };

        // FIXME: do this assertion statically
        let new_addrs = addrs_of!(document => node, _parent_not_accessible, children);
        assert_eq!(old_addrs, new_addrs);

        OwnedDom {
            document: document,
            errors: sink.errors,
            quirks_mode: sink.quirks_mode,
        }
    }
}

impl Serializable for Node {
    fn serialize<'wr, Wr: Writer>(&self,
            serializer: &mut Serializer<'wr, Wr>,
            incl_self: bool) -> IoResult<()> {

        match (incl_self, &self.node) {
            (_, &Element(ref name, ref attrs)) => {
                if incl_self {
                    try!(serializer.start_elem(name.clone(),
                        attrs.iter().map(|at| (&at.name, at.value.as_slice()))));
                }

                for child in self.children.iter() {
                    try!(child.serialize(serializer, true));
                }

                if incl_self {
                    try!(serializer.end_elem(name.clone()));
                }
                Ok(())
            }

            (false, &Document) => {
                for child in self.children.iter() {
                    try!(child.serialize(serializer, true));
                }
                Ok(())
            }

            (false, _) => Ok(()),

            (true, &Doctype(ref name, _, _)) => serializer.write_doctype(name.as_slice()),
            (true, &Text(ref text)) => serializer.write_text(text.as_slice()),
            (true, &Comment(ref text)) => serializer.write_comment(text.as_slice()),

            (true, &Document) => panic!("Can't serialize Document node itself"),
        }
    }
}
<|endoftext|>