<commit_before>/// The representation of the installed toolchain and its components.
/// `Components` and `DirectoryPackage` are the two sides of the
/// installation / uninstallation process.

use rustup_utils::utils;
use prefix::InstallPrefix;
use errors::*;

use component::transaction::Transaction;
use component::package::{INSTALLER_VERSION, VERSION_FILE};

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

const COMPONENTS_FILE: &'static str = "components";

#[derive(Clone, Debug)]
pub struct Components {
    prefix: InstallPrefix,
}

impl Components {
    pub fn open(prefix: InstallPrefix) -> Result<Self> {
        let c = Components { prefix: prefix };

        // Validate that the metadata uses a format we know
        if let Some(v) = try!(c.read_version()) {
            if v != INSTALLER_VERSION {
                return Err(ErrorKind::BadInstalledMetadataVersion(v).into());
            }
        }

        Ok(c)
    }
    fn rel_components_file(&self) -> PathBuf {
        self.prefix.rel_manifest_file(COMPONENTS_FILE)
    }
    fn rel_component_manifest(&self, name: &str) -> PathBuf {
        self.prefix.rel_manifest_file(&format!("manifest-{}", name))
    }
    fn read_version(&self) -> Result<Option<String>> {
        let p = self.prefix.manifest_file(VERSION_FILE);
        if utils::is_file(&p) {
            Ok(Some(try!(utils::read_file(VERSION_FILE, &p)).trim().to_string()))
        } else {
            Ok(None)
        }
    }
    fn write_version(&self, tx: &mut Transaction) -> Result<()> {
        try!(tx.modify_file(self.prefix.rel_manifest_file(VERSION_FILE)));
        try!(utils::write_file(VERSION_FILE,
                               &self.prefix.manifest_file(VERSION_FILE),
                               INSTALLER_VERSION));

        Ok(())
    }
    pub fn list(&self) -> Result<Vec<Component>> {
        let path = self.prefix.abs_path(self.rel_components_file());
        if !utils::is_file(&path) {
            return Ok(Vec::new());
        }
        let content = try!(utils::read_file("components", &path));
        Ok(content.lines()
                  .map(|s| {
                      Component {
                          components: self.clone(),
                          name: s.to_owned(),
                      }
                  })
                  .collect())
    }
    pub fn add<'a>(&self, name: &str, tx: Transaction<'a>) -> ComponentBuilder<'a> {
        ComponentBuilder {
            components: self.clone(),
            name: name.to_owned(),
            parts: Vec::new(),
            tx: tx,
        }
    }
    pub fn find(&self, name: &str) -> Result<Option<Component>> {
        let result = try!(self.list());
        Ok(result.into_iter().filter(|c| (c.name() == name)).next())
    }
    pub fn prefix(&self) -> InstallPrefix {
        self.prefix.clone()
    }
}

pub struct ComponentBuilder<'a> {
    components: Components,
    name: String,
    parts: Vec<ComponentPart>,
    tx: Transaction<'a>
}

impl<'a> ComponentBuilder<'a> {
    pub fn add_file(&mut self, path: PathBuf) -> Result<File> {
        self.parts.push(ComponentPart("file".to_owned(), path.clone()));
        self.tx.add_file(&self.name, path)
    }
    pub fn copy_file(&mut self, path: PathBuf, src: &Path) -> Result<()> {
        self.parts.push(ComponentPart("file".to_owned(), path.clone()));
        self.tx.copy_file(&self.name, path, src)
    }
    pub fn copy_dir(&mut self, path: PathBuf, src: &Path) -> Result<()> {
        self.parts.push(ComponentPart("dir".to_owned(), path.clone()));
        self.tx.copy_dir(&self.name, path, src)
    }

    pub fn finish(mut self) -> Result<Transaction<'a>> {
        // Write component manifest
        let path = self.components.rel_component_manifest(&self.name);
        let abs_path = self.components.prefix.abs_path(&path);
        let mut file = try!(self.tx.add_file(&self.name, path));
        for part in self.parts {
            // FIXME: This writes relative paths to the component manifest,
            // but rust-installer writes absolute paths.
            try!(utils::write_line("component", &mut file, &abs_path, &part.encode()));
        }

        // Add component to components file
        let path = self.components.rel_components_file();
        let abs_path = self.components.prefix.abs_path(&path);
        try!(self.tx.modify_file(path));
        try!(utils::append_file("components", &abs_path, &self.name));

        // Drop in the version file for future use
        try!(self.components.write_version(&mut self.tx));

        Ok(self.tx)
    }
}

#[derive(Debug)]
pub struct ComponentPart(pub String, pub PathBuf);

impl ComponentPart {
    pub fn encode(&self) -> String {
        format!("{}:{}", &self.0, &self.1.to_string_lossy())
    }
    pub fn decode(line: &str) -> Option<Self> {
        line.find(":")
            .map(|pos| ComponentPart(line[0..pos].to_owned(),
                                     PathBuf::from(&line[(pos + 1)..])))
    }
}

#[derive(Clone, Debug)]
pub struct Component {
    components: Components,
    name: String,
}

impl Component {
    pub fn manifest_name(&self) -> String {
        format!("manifest-{}", &self.name)
    }
    pub fn manifest_file(&self) -> PathBuf {
        self.components.prefix.manifest_file(&self.manifest_name())
    }
    pub fn rel_manifest_file(&self) -> PathBuf {
        self.components.prefix.rel_manifest_file(&self.manifest_name())
    }
    pub fn name(&self) -> &str {
        &self.name
    }
    pub fn parts(&self) -> Result<Vec<ComponentPart>> {
        let mut result = Vec::new();
        for line in try!(utils::read_file("component", &self.manifest_file())).lines() {
            result.push(try!(ComponentPart::decode(line)
                                 .ok_or_else(|| ErrorKind::CorruptComponent(self.name.clone()))));
        }
        Ok(result)
    }
    pub fn uninstall<'a>(&self, mut tx: Transaction<'a>) -> Result<Transaction<'a>> {
        // Update components file
        let path = self.components.rel_components_file();
        let abs_path = self.components.prefix.abs_path(&path);
        let temp = try!(tx.temp().new_file());
        try!(utils::filter_file("components", &abs_path, &temp, |l| (l != self.name)));
        try!(tx.modify_file(path));
        try!(utils::rename_file("components", &temp, &abs_path));

        // TODO: If this is the last component remove the components file
        // and the version file.

        // Track visited directories
        use std::collections::HashSet;
        use std::collections::hash_set::IntoIter;
        use std::fs::read_dir;

        // dirs will contain the set of longest disjoint directory paths seen
        // ancestors help in filtering seen paths and constructing dirs
        // All seen paths must be relative to avoid surprises
        struct PruneSet {
            dirs: HashSet<PathBuf>,
            ancestors: HashSet<PathBuf>,
            prefix: PathBuf,
        }

        impl PruneSet {
            fn seen(&mut self, mut path: PathBuf) {
                if !path.is_relative() || !path.pop() {
                    return;
                }
                if self.dirs.contains(&path) || self.ancestors.contains(&path) {
                    return;
                }
                self.dirs.insert(path.clone());
                while path.pop() {
                    if path.file_name().is_none() {
			break;
		    }
		    if self.dirs.contains(&path) {
			self.dirs.remove(&path);
		    }
		    if self.ancestors.contains(&path) {
			break;
		    }
		    self.ancestors.insert(path.clone());
                }
            }
        }

        struct PruneIter {
            iter: IntoIter<PathBuf>,
            path_buf: Option<PathBuf>,
            prefix: PathBuf,
        }

        impl IntoIterator for PruneSet {
            type Item = PathBuf;
            type IntoIter = PruneIter;

            fn into_iter(self) -> Self::IntoIter {
                PruneIter {
                    iter: self.dirs.into_iter(),
                    path_buf: None,
                    prefix: self.prefix,
                }
            }
        }

        // Returns only empty directories
        impl Iterator for PruneIter {
            type Item = PathBuf;

            fn next(&mut self) -> Option<Self::Item> {
                self.path_buf = match self.path_buf {
                    None => self.iter.next(),
                    Some(_) => {
                        let mut path_buf = self.path_buf.take().unwrap();
                        match path_buf.file_name() {
                            Some(_) => if path_buf.pop() { Some(path_buf) } else { None },
                            None => self.iter.next(),
                        }
                    },
                };
                if self.path_buf.is_none() {
                    return None;
                }
                let full_path = self.prefix.join(self.path_buf.as_ref().unwrap());
                let empty = match read_dir(full_path) {
                    Ok(dir) => dir.count() == 0,
                    Err(_) => false,
                };
                if empty {
                    self.path_buf.clone()
                } else {
                    self.next()
                }
            }
        }

        // Remove parts
        let mut pset = PruneSet {
            dirs: HashSet::new(),
            ancestors: HashSet::new(),
            prefix: self.components.prefix.abs_path(""),
        };
        for part in try!(self.parts()).into_iter().rev() {
            match &*part.0 {
                "file" => {
                    try!(tx.remove_file(&self.name, part.1.clone()));
                    pset.seen(part.1);
                },
                "dir" => {
                    try!(tx.remove_dir(&self.name, part.1.clone()));
                    pset.seen(part.1);
                },
                _ => return Err(ErrorKind::CorruptComponent(self.name.clone()).into()),
            }
        }
        for empty_dir in pset {
            try!(tx.remove_dir(&self.name, empty_dir));
        }

        // Remove component manifest
        try!(tx.remove_file(&self.name, self.rel_manifest_file()));

        Ok(tx)
    }
}
<commit_msg>Misc small cleanups in component uninstall<commit_after>/// The representation of the installed toolchain and its components.
/// `Components` and `DirectoryPackage` are the two sides of the
/// installation / uninstallation process.

use rustup_utils::utils;
use prefix::InstallPrefix;
use errors::*;

use component::transaction::Transaction;
use component::package::{INSTALLER_VERSION, VERSION_FILE};

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

const COMPONENTS_FILE: &'static str = "components";

#[derive(Clone, Debug)]
pub struct Components {
    prefix: InstallPrefix,
}

impl Components {
    pub fn open(prefix: InstallPrefix) -> Result<Self> {
        let c = Components { prefix: prefix };

        // Validate that the metadata uses a format we know
        if let Some(v) = try!(c.read_version()) {
            if v != INSTALLER_VERSION {
                return Err(ErrorKind::BadInstalledMetadataVersion(v).into());
            }
        }

        Ok(c)
    }
    fn rel_components_file(&self) -> PathBuf {
        self.prefix.rel_manifest_file(COMPONENTS_FILE)
    }
    fn rel_component_manifest(&self, name: &str) -> PathBuf {
        self.prefix.rel_manifest_file(&format!("manifest-{}", name))
    }
    fn read_version(&self) -> Result<Option<String>> {
        let p = self.prefix.manifest_file(VERSION_FILE);
        if utils::is_file(&p) {
            Ok(Some(try!(utils::read_file(VERSION_FILE, &p)).trim().to_string()))
        } else {
            Ok(None)
        }
    }
    fn write_version(&self, tx: &mut Transaction) -> Result<()> {
        try!(tx.modify_file(self.prefix.rel_manifest_file(VERSION_FILE)));
        try!(utils::write_file(VERSION_FILE,
                               &self.prefix.manifest_file(VERSION_FILE),
                               INSTALLER_VERSION));

        Ok(())
    }
    pub fn list(&self) -> Result<Vec<Component>> {
        let path = self.prefix.abs_path(self.rel_components_file());
        if !utils::is_file(&path) {
            return Ok(Vec::new());
        }
        let content = try!(utils::read_file("components", &path));
        Ok(content.lines()
                  .map(|s| {
                      Component {
                          components: self.clone(),
                          name: s.to_owned(),
                      }
                  })
                  .collect())
    }
    pub fn add<'a>(&self, name: &str, tx: Transaction<'a>) -> ComponentBuilder<'a> {
        ComponentBuilder {
            components: self.clone(),
            name: name.to_owned(),
            parts: Vec::new(),
            tx: tx,
        }
    }
    pub fn find(&self, name: &str) -> Result<Option<Component>> {
        let result = try!(self.list());
        Ok(result.into_iter().filter(|c| (c.name() == name)).next())
    }
    pub fn prefix(&self) -> InstallPrefix {
        self.prefix.clone()
    }
}

pub struct ComponentBuilder<'a> {
    components: Components,
    name: String,
    parts: Vec<ComponentPart>,
    tx: Transaction<'a>
}

impl<'a> ComponentBuilder<'a> {
    pub fn add_file(&mut self, path: PathBuf) -> Result<File> {
        self.parts.push(ComponentPart("file".to_owned(), path.clone()));
        self.tx.add_file(&self.name, path)
    }
    pub fn copy_file(&mut self, path: PathBuf, src: &Path) -> Result<()> {
        self.parts.push(ComponentPart("file".to_owned(), path.clone()));
        self.tx.copy_file(&self.name, path, src)
    }
    pub fn copy_dir(&mut self, path: PathBuf, src: &Path) -> Result<()> {
        self.parts.push(ComponentPart("dir".to_owned(), path.clone()));
        self.tx.copy_dir(&self.name, path, src)
    }

    pub fn finish(mut self) -> Result<Transaction<'a>> {
        // Write component manifest
        let path = self.components.rel_component_manifest(&self.name);
        let abs_path = self.components.prefix.abs_path(&path);
        let mut file = try!(self.tx.add_file(&self.name, path));
        for part in self.parts {
            // FIXME: This writes relative paths to the component manifest,
            // but rust-installer writes absolute paths.
            try!(utils::write_line("component", &mut file, &abs_path, &part.encode()));
        }

        // Add component to components file
        let path = self.components.rel_components_file();
        let abs_path = self.components.prefix.abs_path(&path);
        try!(self.tx.modify_file(path));
        try!(utils::append_file("components", &abs_path, &self.name));

        // Drop in the version file for future use
        try!(self.components.write_version(&mut self.tx));

        Ok(self.tx)
    }
}

#[derive(Debug)]
pub struct ComponentPart(pub String, pub PathBuf);

impl ComponentPart {
    pub fn encode(&self) -> String {
        format!("{}:{}", &self.0, &self.1.to_string_lossy())
    }
    pub fn decode(line: &str) -> Option<Self> {
        line.find(":")
            .map(|pos| ComponentPart(line[0..pos].to_owned(),
                                     PathBuf::from(&line[(pos + 1)..])))
    }
}

#[derive(Clone, Debug)]
pub struct Component {
    components: Components,
    name: String,
}

impl Component {
    pub fn manifest_name(&self) -> String {
        format!("manifest-{}", &self.name)
    }
    pub fn manifest_file(&self) -> PathBuf {
        self.components.prefix.manifest_file(&self.manifest_name())
    }
    pub fn rel_manifest_file(&self) -> PathBuf {
        self.components.prefix.rel_manifest_file(&self.manifest_name())
    }
    pub fn name(&self) -> &str {
        &self.name
    }
    pub fn parts(&self) -> Result<Vec<ComponentPart>> {
        let mut result = Vec::new();
        for line in try!(utils::read_file("component", &self.manifest_file())).lines() {
            result.push(try!(ComponentPart::decode(line)
                                 .ok_or_else(|| ErrorKind::CorruptComponent(self.name.clone()))));
        }
        Ok(result)
    }
    pub fn uninstall<'a>(&self, mut tx: Transaction<'a>) -> Result<Transaction<'a>> {
        // Update components file
        let path = self.components.rel_components_file();
        let abs_path = self.components.prefix.abs_path(&path);
        let temp = try!(tx.temp().new_file());
        try!(utils::filter_file("components", &abs_path, &temp, |l| (l != self.name)));
        try!(tx.modify_file(path));
        try!(utils::rename_file("components", &temp, &abs_path));

        // TODO: If this is the last component remove the components file
        // and the version file.

        // Track visited directories
        use std::collections::HashSet;
        use std::collections::hash_set::IntoIter;
        use std::fs::read_dir;

        // dirs will contain the set of longest disjoint directory paths seen
        // ancestors help in filtering seen paths and constructing dirs
        // All seen paths must be relative to avoid surprises
        struct PruneSet {
            dirs: HashSet<PathBuf>,
            ancestors: HashSet<PathBuf>,
            prefix: PathBuf,
        }

        impl PruneSet {
            fn seen(&mut self, mut path: PathBuf) {
                if !path.is_relative() || !path.pop() {
                    return;
                }
                if self.dirs.contains(&path) || self.ancestors.contains(&path) {
                    return;
                }
                self.dirs.insert(path.clone());
                while path.pop() {
                    if path.file_name().is_none() {
                        break;
                    }
                    if self.dirs.contains(&path) {
                        self.dirs.remove(&path);
                    }
                    if self.ancestors.contains(&path) {
                        break;
                    }
                    self.ancestors.insert(path.clone());
                }
            }
        }

        struct PruneIter {
            iter: IntoIter<PathBuf>,
            path_buf: Option<PathBuf>,
            prefix: PathBuf,
        }

        impl IntoIterator for PruneSet {
            type Item = PathBuf;
            type IntoIter = PruneIter;

            fn into_iter(self) -> Self::IntoIter {
                PruneIter {
                    iter: self.dirs.into_iter(),
                    path_buf: None,
                    prefix: self.prefix,
                }
            }
        }

        // Returns only empty directories
        impl Iterator for PruneIter {
            type Item = PathBuf;

            fn next(&mut self) -> Option<Self::Item> {
                self.path_buf = match self.path_buf {
                    None => self.iter.next(),
                    Some(_) => {
                        let mut path_buf = self.path_buf.take().unwrap();
                        match path_buf.file_name() {
                            Some(_) => if path_buf.pop() { Some(path_buf) } else { None },
                            None => self.iter.next(),
                        }
                    },
                };
                if self.path_buf.is_none() {
                    return None;
                }
                let full_path = self.prefix.join(self.path_buf.as_ref().unwrap());
                let empty = match read_dir(full_path) {
                    Ok(dir) => dir.count() == 0,
                    Err(_) => false,
                };
                if empty {
                    self.path_buf.clone()
                } else {
                    // No dir above can be empty, go to next path in dirs
                    self.path_buf = None;
                    self.next()
                }
            }
        }

        // Remove parts
        let mut pset = PruneSet {
            dirs: HashSet::new(),
            ancestors: HashSet::new(),
            prefix: self.components.prefix.abs_path(""),
        };
        for part in try!(self.parts()).into_iter().rev() {
            match &*part.0 {
                "file" => try!(tx.remove_file(&self.name, part.1.clone())),
                "dir" => try!(tx.remove_dir(&self.name, part.1.clone())),
                _ => return Err(ErrorKind::CorruptComponent(self.name.clone()).into()),
            }
            pset.seen(part.1);
        }
        for empty_dir in pset {
            try!(tx.remove_dir(&self.name, empty_dir));
        }

        // Remove component manifest
        try!(tx.remove_file(&self.name, self.rel_manifest_file()));

        Ok(tx)
    }
}
<|endoftext|>


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

//! # The Rust core allocation library
//!
//! This is the lowest level library through which allocation in Rust can be
//! performed.
//!
//! This library, like libcore, is not intended for general usage, but rather as
//! a building block of other libraries. The types and interfaces in this
//! library are reexported through the [standard library](../std/index.html),
//! and should not be used through this library.
//!
//! Currently, there are four major definitions in this library.
//!
//! ## Boxed values
//!
//! The [`Box`](boxed/index.html) type is a smart pointer type. There can
//! only be one owner of a `Box`, and the owner can decide to mutate the
//! contents, which live on the heap.
//!
//! This type can be sent among threads efficiently as the size of a `Box` value
//! is the same as that of a pointer. Tree-like data structures are often built
//! with boxes because each node often has only one owner, the parent.
//!
//! ## Reference counted pointers
//!
//! The [`Rc`](rc/index.html) type is a non-threadsafe reference-counted pointer
//! type intended for sharing memory within a thread. An `Rc` pointer wraps a
//! type, `T`, and only allows access to `&T`, a shared reference.
//!
//! This type is useful when inherited mutability (such as using `Box`) is too
//! constraining for an application, and is often paired with the `Cell` or
//! `RefCell` types in order to allow mutation.
//!
//! ## Atomically reference counted pointers
//!
//! The [`Arc`](arc/index.html) type is the threadsafe equivalent of the `Rc`
//! type. It provides all the same functionality of `Rc`, except it requires
//! that the contained type `T` is shareable. Additionally, `Arc<T>` is itself
//! sendable while `Rc<T>` is not.
//!
//! This types allows for shared access to the contained data, and is often
//! paired with synchronization primitives such as mutexes to allow mutation of
//! shared resources.
//!
//! ## Heap interfaces
//!
//! The [`heap`](heap/index.html) module defines the low-level interface to the
//! default global allocator. It is not compatible with the libc allocator API.

// Do not remove on snapshot creation. Needed for bootstrap. (Issue #22364)
#![cfg_attr(stage0, feature(custom_attribute))]
#![crate_name = "alloc"]
#![crate_type = "rlib"]
#![staged_api]
#![allow(unused_attributes)]
#![unstable(feature = "alloc",
            reason = "this library is unlikely to be stabilized in its current \
                      form or name",
            issue = "27783")]
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
       html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
       html_root_url = "https://doc.rust-lang.org/nightly/",
       issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/",
       test(no_crate_inject))]
#![no_std]
#![cfg_attr(not(stage0), needs_allocator)]

#![feature(allocator)]
#![feature(box_syntax)]
#![feature(coerce_unsized)]
#![feature(core)]
#![feature(core_intrinsics)]
#![feature(core_slice_ext)]
#![feature(custom_attribute)]
#![feature(fundamental)]
#![feature(lang_items)]
#![feature(no_std)]
#![feature(nonzero)]
#![feature(num_bits_bytes)]
#![feature(optin_builtin_traits)]
#![feature(placement_in_syntax)]
#![feature(placement_new_protocol)]
#![feature(raw)]
#![feature(shared)]
#![feature(staged_api)]
#![feature(unboxed_closures)]
#![feature(unique)]
#![feature(unsafe_no_drop_flag, filling_drop)]
// SNAP 1af31d4
#![allow(unused_features)]
// SNAP 1af31d4
#![allow(unused_attributes)]
#![feature(dropck_parametricity)]
#![feature(unsize)]
#![feature(core_slice_ext)]
#![feature(core_str_ext)]
#![feature(drop_in_place)]

#![cfg_attr(stage0, feature(alloc_system))]
#![cfg_attr(not(stage0), feature(needs_allocator))]

#![cfg_attr(test, feature(test, rustc_private, box_heap))]

#[cfg(stage0)]
extern crate alloc_system;

// Allow testing this library

#[cfg(test)]
#[macro_use]
extern crate std;
#[cfg(test)]
#[macro_use]
extern crate log;

// Heaps provided for low-level allocation strategies

pub mod heap;

// Primitive types using the heaps above

// Need to conditionally define the mod from `boxed.rs` to avoid
// duplicating the lang-items when building in test cfg; but also need
// to allow code to have `use boxed::HEAP;`
// and `use boxed::Box;` declarations.
#[cfg(not(test))]
pub mod boxed;
#[cfg(test)]
mod boxed {
    pub use std::boxed::{Box, HEAP};
}
#[cfg(test)]
mod boxed_test;
pub mod arc;
pub mod rc;
pub mod raw_vec;

/// Common out-of-memory routine
#[cold]
#[inline(never)]
#[unstable(feature = "oom", reason = "not a scrutinized interface",
           issue = "27700")]
pub fn oom() -> ! {
    // FIXME(#14674): This really needs to do something other than just abort
    //                here, but any printing done must be *guaranteed* to not
    //                allocate.
    unsafe { core::intrinsics::abort() }
}
<commit_msg>liballoc: deny warnings in doctests<commit_after>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! # The Rust core allocation library
//!
//! This is the lowest level library through which allocation in Rust can be
//! performed.
//!
//! This library, like libcore, is not intended for general usage, but rather as
//! a building block of other libraries. The types and interfaces in this
//! library are reexported through the [standard library](../std/index.html),
//! and should not be used through this library.
//!
//! Currently, there are four major definitions in this library.
//!
//! ## Boxed values
//!
//! The [`Box`](boxed/index.html) type is a smart pointer type. There can
//! only be one owner of a `Box`, and the owner can decide to mutate the
//! contents, which live on the heap.
//!
//! This type can be sent among threads efficiently as the size of a `Box` value
//! is the same as that of a pointer. Tree-like data structures are often built
//! with boxes because each node often has only one owner, the parent.
//!
//! ## Reference counted pointers
//!
//! The [`Rc`](rc/index.html) type is a non-threadsafe reference-counted pointer
//! type intended for sharing memory within a thread. An `Rc` pointer wraps a
//! type, `T`, and only allows access to `&T`, a shared reference.
//!
//! This type is useful when inherited mutability (such as using `Box`) is too
//! constraining for an application, and is often paired with the `Cell` or
//! `RefCell` types in order to allow mutation.
//!
//! ## Atomically reference counted pointers
//!
//! The [`Arc`](arc/index.html) type is the threadsafe equivalent of the `Rc`
//! type. It provides all the same functionality of `Rc`, except it requires
//! that the contained type `T` is shareable. Additionally, `Arc<T>` is itself
//! sendable while `Rc<T>` is not.
//!
//! This types allows for shared access to the contained data, and is often
//! paired with synchronization primitives such as mutexes to allow mutation of
//! shared resources.
//!
//! ## Heap interfaces
//!
//! The [`heap`](heap/index.html) module defines the low-level interface to the
//! default global allocator. It is not compatible with the libc allocator API.

// Do not remove on snapshot creation. Needed for bootstrap. (Issue #22364)
#![cfg_attr(stage0, feature(custom_attribute))]
#![crate_name = "alloc"]
#![crate_type = "rlib"]
#![staged_api]
#![allow(unused_attributes)]
#![unstable(feature = "alloc",
            reason = "this library is unlikely to be stabilized in its current \
                      form or name",
            issue = "27783")]
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
       html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
       html_root_url = "https://doc.rust-lang.org/nightly/",
       issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/",
       test(no_crate_inject, attr(allow(unused_variables), deny(warnings))))]
#![no_std]
#![cfg_attr(not(stage0), needs_allocator)]

#![feature(allocator)]
#![feature(box_syntax)]
#![feature(coerce_unsized)]
#![feature(core)]
#![feature(core_intrinsics)]
#![feature(core_slice_ext)]
#![feature(custom_attribute)]
#![feature(fundamental)]
#![feature(lang_items)]
#![feature(no_std)]
#![feature(nonzero)]
#![feature(num_bits_bytes)]
#![feature(optin_builtin_traits)]
#![feature(placement_in_syntax)]
#![feature(placement_new_protocol)]
#![feature(raw)]
#![feature(shared)]
#![feature(staged_api)]
#![feature(unboxed_closures)]
#![feature(unique)]
#![feature(unsafe_no_drop_flag, filling_drop)]
// SNAP 1af31d4
#![allow(unused_features)]
// SNAP 1af31d4
#![allow(unused_attributes)]
#![feature(dropck_parametricity)]
#![feature(unsize)]
#![feature(core_slice_ext)]
#![feature(core_str_ext)]
#![feature(drop_in_place)]

#![cfg_attr(stage0, feature(alloc_system))]
#![cfg_attr(not(stage0), feature(needs_allocator))]

#![cfg_attr(test, feature(test, rustc_private, box_heap))]

#[cfg(stage0)]
extern crate alloc_system;

// Allow testing this library

#[cfg(test)]
#[macro_use]
extern crate std;
#[cfg(test)]
#[macro_use]
extern crate log;

// Heaps provided for low-level allocation strategies

pub mod heap;

// Primitive types using the heaps above

// Need to conditionally define the mod from `boxed.rs` to avoid
// duplicating the lang-items when building in test cfg; but also need
// to allow code to have `use boxed::HEAP;`
// and `use boxed::Box;` declarations.
#[cfg(not(test))]
pub mod boxed;
#[cfg(test)]
mod boxed {
    pub use std::boxed::{Box, HEAP};
}
#[cfg(test)]
mod boxed_test;
pub mod arc;
pub mod rc;
pub mod raw_vec;

/// Common out-of-memory routine
#[cold]
#[inline(never)]
#[unstable(feature = "oom", reason = "not a scrutinized interface",
           issue = "27700")]
pub fn oom() -> ! {
    // FIXME(#14674): This really needs to do something other than just abort
    //                here, but any printing done must be *guaranteed* to not
    //                allocate.
    unsafe { core::intrinsics::abort() }
}
<|endoftext|>


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

#![crate_name = "foo"]

// @has foo/struct.SomeStruct.html '//*[@class="sidebar-links"]/a[@href="#method.some_fn-1"]' \
//          "some_fn"
pub struct SomeStruct<T> { _inner: T }

impl SomeStruct<()> {
    pub fn some_fn(&self) {}
}

impl SomeStruct<usize> {
    pub fn some_fn(&self) {}
}
<|endoftext|>


<commit_before><commit_msg>add build.rs<commit_after>#![feature(path_ext)]

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

extern crate gcc;

#[cfg(unix)]
const OSDependent: &'static [&'static str] = &["glslang", "OSDependent", "Linux"];
#[cfg(win)]
const OSDependent: &'static [&'static str] = &["glslang", "OSDependent", "Windows"];

const SEARCH_DIRS: &'static [&'static [&'static str]] = &[
    &["glslang"],
    &["glslang", "gen"],
    &["glslang", "GenericCodeGen"],
    &["glslang", "Include"],
    &["glslang", "MachineIndependent"],
    &["glslang", "MachineIndependent", "preprocessor"],
    &["glslang", "Public"],
    OSDependent,
    &["OGLCompilersDLL"],
];

fn main() {
    let src_root = Path::new(&env::var("CARGO_MANIFEST_DIR").unwrap())
        .join("extern").join("glslang");

    let mut config = gcc::Config::new();
    config.cpp(true);

    for file in find_sources(&src_root) {
        config.file(file);
    }

    for dir in resolve_search_dirs(&src_root) {
        config.include(dir);
    }

    config.compile("libglslang.a");
}

fn find_sources<P: AsRef<Path>>(root: &P) -> Vec<PathBuf> {
    let mut sources = Vec::new();

    for search_dir in resolve_search_dirs(root) {

        for file in fs::read_dir(search_dir).unwrap().filter_map(|e| {
            let path = e.unwrap().path();

            let mut ok = false;

            if let Some(ext) = path.extension() {
                if path.is_file() && ext == "cpp" {
                    ok = true;
                }
            }

            if ok { Some(path) } else { None }
        }) {
            sources.push(file)
        }
    }

    sources
}

fn resolve_search_dirs<P: AsRef<Path>>(root: &P) -> Vec<PathBuf> {
    SEARCH_DIRS.iter().map(|dir| {
        let mut buf = root.as_ref().to_owned();

        for component in *dir {
            buf.push(component)
        }

        buf
    }).collect()
}
<|endoftext|>


<commit_before><commit_msg>updated build.rs to use 'git describe'<commit_after><|endoftext|>


<commit_before><commit_msg>Reverse arg order for stsr disassembly<commit_after><|endoftext|>


<commit_before><commit_msg>Give a better error message when not compiling on Windows<commit_after>fn main() {
    if std::env::var("CARGO_CFG_WINDOWS").is_err() {
        eprintln!("error: winreg is only supported on Windows platforms");
        eprintln!(
            "help: if your application is multi-platform, use \
            `[target.'cfg(windows)'.dependencies] winreg = \"...\"`"
        );
        eprintln!("help: if your application is only supported on Windows, use `--target x86_64-pc-windows-gnu` or some other windows platform");
        std::process::exit(1);
    }
}
<|endoftext|>


<commit_before><commit_msg>We don't need these comments anymore<commit_after><|endoftext|>


<commit_before><commit_msg>[move] Appease doc tests with move-analyzer library<commit_after>// Copyright (c) The Diem Core Contributors
// SPDX-License-Identifier: Apache-2.0
<|endoftext|>


<commit_before><commit_msg>Oops I have goofed.<commit_after><|endoftext|>


<commit_before>use au = gfx::geometry;
use core::dlist::DList;
use core::dvec::DVec;
use css::values::{BoxAuto, BoxLength, Px};
use dl = gfx::display_list;
use dom::rcu;
use geom::point::Point2D;
use geom::rect::Rect;
use geom::size::Size2D;
use gfx::geometry::au;
use layout::box::{RenderBox, RenderBoxTree, ImageBox, TextBox, GenericBox, UnscannedTextBox};
use layout::context::LayoutContext;
use layout::flow::{FlowContext, InlineFlow};
use layout::text::TextBoxData;
use num::Num;
use servo_text::text_run::TextRun;
use std::arc;
use util::tree;

/*
Lineboxes are represented as offsets into the child list, rather than
as an object that "owns" boxes. Choosing a different set of line
breaks requires a new list of offsets, and possibly some splitting and
merging of TextBoxes.

A similar list will keep track of the mapping between CSS boxes and
the corresponding render boxes in the inline flow.

After line breaks are determined, render boxes in the inline flow may
overlap visually. For example, in the case of nested inline CSS boxes,
outer inlines must be at least as large as the inner inlines, for
purposes of drawing noninherited things like backgrounds, borders,
outlines.

N.B. roc has an alternative design where the list instead consists of
things like "start outer box, text, start inner box, text, end inner
box, text, end outer box, text". This seems a little complicated to
serve as the starting point, but the current design doesn't make it
hard to try out that alternative.
*/

type BoxRange = {start: u8, len: u8};

// stack-allocated object for scanning an inline flow into
// TextRun-containing TextBoxes.
struct TextRunScanner {
    mut in_clump: bool,
    mut clump_start: uint,
    mut clump_end: uint,
    flow: @FlowContext,
}

fn TextRunScanner(flow: @FlowContext) -> TextRunScanner {
    TextRunScanner {
        in_clump: false,
        clump_start: 0,
        clump_end: 0,
        flow: flow,
    }
}

impl TextRunScanner {
    fn scan_for_runs(ctx: &LayoutContext) {
        // if reused, must be reset.
        assert !self.in_clump;
        let in_boxes = self.flow.inline().boxes;
        assert in_boxes.len() > 0;

        debug!("scanning %u boxes for text runs...", in_boxes.len());

        let temp_boxes = DVec();
        let mut prev_box: @RenderBox = in_boxes[0];

        for uint::range(0, in_boxes.len()) |i| {
            debug!("considering box: %?", in_boxes[i].debug_str());

            let can_coalesce_with_prev = i > 0 && boxes_can_be_coalesced(prev_box, in_boxes[i]);

            match (self.in_clump, can_coalesce_with_prev) {
                // start a new clump
                (false, _)    => { self.reset_clump_to_index(i); },
                // extend clump
                (true, true)  => { self.clump_end = i; },
                // boundary detected; flush and start new clump
                (true, false) => {
                    self.flush_clump_to_list(ctx, &temp_boxes);
                    self.reset_clump_to_index(i);
                }
            };

            prev_box = in_boxes[i];
        }

        // handle remaining clumps
        if self.in_clump {
            self.flush_clump_to_list(ctx, &temp_boxes);
        }

        debug!("swapping out boxes.");
        // swap out old and new box list of flow
        self.flow.inline().boxes.set(dvec::unwrap(temp_boxes));

        debug!("new inline flow boxes:");
        do self.flow.inline().boxes.each |box| {
            debug!("%s", box.debug_str()); true
        }

        // helper functions
        pure fn boxes_can_be_coalesced(a: @RenderBox, b: @RenderBox) -> bool {
            assert !core::box::ptr_eq(a, b);

            match (a, b) {
                // TODO: check whether text styles, fonts are the same.
                (@UnscannedTextBox(*), @UnscannedTextBox(*)) => a.can_merge_with_box(b),
                (_, _) => false
            }
        }
    }

    fn reset_clump_to_index(i: uint) {
        debug!("resetting clump to %u", i);

        self.clump_start = i;
        self.clump_end = i;
        self.in_clump = true;
    }

    fn flush_clump_to_list(ctx: &LayoutContext, temp_boxes: &DVec<@RenderBox>) {
        assert self.in_clump;

        debug!("flushing when start=%?,end=%?", self.clump_start, self.clump_end);

        let in_boxes = self.flow.inline().boxes;
        let is_singleton = (self.clump_start == self.clump_end);
        let is_text_clump = match in_boxes[self.clump_start] {
            @UnscannedTextBox(*) => true,
            _ => false
        };

        // TODO: repair the mapping of DOM elements to boxes if it changed.
        // (the mapping does not yet exist; see Issue #103)
        match (is_singleton, is_text_clump) {
            (false, false) => fail ~"WAT: can't coalesce non-text boxes in flush_clump_to_list()!",
            (true, false) => { temp_boxes.push(in_boxes[self.clump_start]); }
            (true, true)  => {
                let text = in_boxes[self.clump_start].raw_text();
                // TODO: use actual font for corresponding DOM node to create text run.
                let run = TextRun(&*ctx.font_cache.get_test_font(), text);
                let box_guts = TextBoxData(@run, 0, text.len());
                debug!("pushing when start=%?,end=%?", self.clump_start, self.clump_end);
                temp_boxes.push(@TextBox(copy *in_boxes[self.clump_start].d(), box_guts));
            },
            (false, true) => {
                let mut run_str : ~str = ~"";
                // TODO: is using ropes to construct the merged text any faster?
                do uint::range(self.clump_start, self.clump_end+1) |i| {
                    run_str = str::append(run_str, in_boxes[i].raw_text()); true
                }
                // TODO: use actual font for corresponding DOM node to create text run.
                let run = TextRun(&*ctx.font_cache.get_test_font(), move run_str);
                let box_guts = TextBoxData(@run, 0, run.text.len());
                debug!("pushing when start=%?,end=%?", self.clump_start, self.clump_end);
                temp_boxes.push(@TextBox(copy *in_boxes[self.clump_start].d(), box_guts));
            }
        }
        self.in_clump = false;
    }
}

struct InlineFlowData {
    // A vec of all inline render boxes. Several boxes may
    // correspond to one Node/Element.
    boxes: DVec<@RenderBox>,
    // vec of ranges into boxes that represents line positions.
    // these ranges are disjoint, and are the result of inline layout.
    lines: DVec<BoxRange>,
    // vec of ranges into boxes that represent elements. These
    // ranges must be disjoint or well-nested, and are only related to
    // the content of boxes (not lines)
    elems: DVec<BoxRange>
}

fn InlineFlowData() -> InlineFlowData {
    InlineFlowData {
        boxes: DVec(),
        lines: DVec(),
        elems: DVec()
    }
}

trait InlineLayout {
    pure fn starts_inline_flow() -> bool;

    fn bubble_widths_inline(@self, ctx: &LayoutContext);
    fn assign_widths_inline(@self, ctx: &LayoutContext);
    fn assign_height_inline(@self, ctx: &LayoutContext);
    fn build_display_list_inline(@self, a: &dl::DisplayListBuilder, b: &Rect<au>, c: &Point2D<au>, d: &dl::DisplayList);
}

impl FlowContext : InlineLayout {
    pure fn starts_inline_flow() -> bool { match self { InlineFlow(*) => true, _ => false } }

    fn bubble_widths_inline(@self, ctx: &LayoutContext) {
        assert self.starts_inline_flow();

        debug!("box count: %u", self.inline().boxes.len());

        let scanner = TextRunScanner(self);
        scanner.scan_for_runs(ctx);

        let mut min_width = au(0);
        let mut pref_width = au(0);

        debug!("/box count: %u", self.inline().boxes.len());

        for self.inline().boxes.each |box| {
            debug!("measuring box: %s", box.debug_str());
            min_width = au::max(min_width, box.get_min_width(ctx));
            pref_width = au::max(pref_width, box.get_pref_width(ctx));
        }

        self.d().min_width = min_width;
        self.d().pref_width = pref_width;
    }

    /* Recursively (top-down) determines the actual width of child
    contexts and boxes. When called on this context, the context has
    had its width set by the parent context. */
    fn assign_widths_inline(@self, ctx: &LayoutContext) {
        assert self.starts_inline_flow();

        /* Perform inline flow with the available width. */
        //let avail_width = self.d().position.size.width;

        let line_height = au::from_px(20);
        //let mut cur_x = au(0);
        let mut cur_y = au(0);

        // TODO: remove test font uses
        let test_font = ctx.font_cache.get_test_font();

        for self.inline().boxes.each |box| {
            /* TODO: actually do inline flow.
            - Create a working linebox, and successively put boxes
            into it, splitting if necessary.

            - Set width and height for each positioned element based on
            where its chunks ended up.

            - Save the dvec of this context's lineboxes. */

            box.d().position.size.width = match *box {
                @ImageBox(_,img) => au::from_px(img.get_size().get_default(Size2D(0,0)).width),
                @TextBox(_,d) => {
                    // TODO: measure twice, cut once doesn't apply to text. Shouldn't need
                    // to measure text again here (should be inside TextBox.split)
                    let metrics = test_font.measure_text(d.run, d.offset, d.length);
                    metrics.advance
                },
                // TODO: this should be set to the extents of its children
                @GenericBox(*) => au(0),
                _ => fail fmt!("Tried to assign width to unknown Box variant: %?", box)
            };

            box.d().position.size.height = match *box {
                @ImageBox(_,img) => au::from_px(img.get_size().get_default(Size2D(0,0)).height),
                // TODO: we should use the bounding box of the actual text, i think?
                @TextBox(*) => test_font.metrics.em_size,
                // TODO: this should be set to the extents of its children
                @GenericBox(*) => au(0),
                _ => fail fmt!("Tried to assign width to unknown Box variant: %?", box)
            };

            box.d().position.origin = Point2D(au(0), cur_y);
            cur_y = cur_y.add(&au::max(line_height, box.d().position.size.height));
        } // for boxes.each |box|

    self.d().position.size.height = cur_y;

    /* There are no child contexts, so stop here. */

    // TODO: once there are 'inline-block' elements, this won't be
    // true.  In that case, perform inline flow, and then set the
    // block flow context's width as the width of the
    // 'inline-block' box that created this flow.
    }

    fn assign_height_inline(@self, _ctx: &LayoutContext) {
        // Don't need to set box or ctx heights, since that is done
        // during inline flowing.
    }

    fn build_display_list_inline(@self, builder: &dl::DisplayListBuilder, dirty: &Rect<au>,
                                 offset: &Point2D<au>, list: &dl::DisplayList) {

        assert self.starts_inline_flow();

        // TODO: if the CSS box introducing this inline context is *not* anonymous,
        // we need to draw it too, in a way similar to BlowFlowContext

        // TODO: once we form line boxes and have their cached bounds, we can be
        // smarter and not recurse on a line if nothing in it can intersect dirty
        debug!("building display list for %u inline boxes", self.inline().boxes.len());
        for self.inline().boxes.each |box| {
            box.build_display_list(builder, dirty, offset, list)
        }

        // TODO: should inline-block elements have flows as children
        // of the inline flow, or should the flow be nested inside the
        // box somehow? Maybe it's best to unify flows and boxes into
        // the same enum, so inline-block flows are normal
        // (indivisible) children in the inline flow child list.
    }

} // @FlowContext : InlineLayout
<commit_msg>Remove some insidious implicit copying in the TextRunScanner.<commit_after>use au = gfx::geometry;
use core::dlist::DList;
use core::dvec::DVec;
use css::values::{BoxAuto, BoxLength, Px};
use dl = gfx::display_list;
use dom::rcu;
use geom::point::Point2D;
use geom::rect::Rect;
use geom::size::Size2D;
use gfx::geometry::au;
use layout::box::{RenderBox, RenderBoxTree, ImageBox, TextBox, GenericBox, UnscannedTextBox};
use layout::context::LayoutContext;
use layout::flow::{FlowContext, InlineFlow};
use layout::text::TextBoxData;
use num::Num;
use servo_text::text_run::TextRun;
use std::arc;
use util::tree;

/*
Lineboxes are represented as offsets into the child list, rather than
as an object that "owns" boxes. Choosing a different set of line
breaks requires a new list of offsets, and possibly some splitting and
merging of TextBoxes.

A similar list will keep track of the mapping between CSS boxes and
the corresponding render boxes in the inline flow.

After line breaks are determined, render boxes in the inline flow may
overlap visually. For example, in the case of nested inline CSS boxes,
outer inlines must be at least as large as the inner inlines, for
purposes of drawing noninherited things like backgrounds, borders,
outlines.

N.B. roc has an alternative design where the list instead consists of
things like "start outer box, text, start inner box, text, end inner
box, text, end outer box, text". This seems a little complicated to
serve as the starting point, but the current design doesn't make it
hard to try out that alternative.
*/

type BoxRange = {start: u8, len: u8};

// stack-allocated object for scanning an inline flow into
// TextRun-containing TextBoxes.
struct TextRunScanner {
    mut in_clump: bool,
    mut clump_start: uint,
    mut clump_end: uint,
    flow: @FlowContext,
}

fn TextRunScanner(flow: @FlowContext) -> TextRunScanner {
    TextRunScanner {
        in_clump: false,
        clump_start: 0,
        clump_end: 0,
        flow: flow,
    }
}

impl TextRunScanner {
    fn scan_for_runs(ctx: &LayoutContext) {
        // if reused, must be reset.
        assert !self.in_clump;
        assert self.flow.inline().boxes.len() > 0;

        do self.flow.inline().boxes.swap |in_boxes| {
            debug!("scanning %u boxes for text runs...", in_boxes.len());

            let temp_boxes = DVec();
            let mut prev_box: @RenderBox = in_boxes[0];

            for uint::range(0, in_boxes.len()) |i| {
                debug!("considering box: %?", in_boxes[i].debug_str());

                let can_coalesce_with_prev = i > 0 && boxes_can_be_coalesced(prev_box, in_boxes[i]);

                match (self.in_clump, can_coalesce_with_prev) {
                    // start a new clump
                    (false, _)    => { self.reset_clump_to_index(i); },
                    // extend clump
                    (true, true)  => { self.clump_end = i; },
                    // boundary detected; flush and start new clump
                    (true, false) => {
                        self.flush_clump_to_list(ctx, in_boxes, &temp_boxes);
                        self.reset_clump_to_index(i);
                    }
                };

                prev_box = in_boxes[i];
            }
            // handle remaining clumps
            if self.in_clump {
                self.flush_clump_to_list(ctx, in_boxes, &temp_boxes);
            }

            debug!("swapping out boxes.");
            // swap out old and new box list of flow, by supplying
            // temp boxes as return value to boxes.swap |...|
            dvec::unwrap(temp_boxes)
        }

        // helper functions
        pure fn boxes_can_be_coalesced(a: @RenderBox, b: @RenderBox) -> bool {
            assert !core::box::ptr_eq(a, b);

            match (a, b) {
                // TODO: check whether text styles, fonts are the same.
                (@UnscannedTextBox(*), @UnscannedTextBox(*)) => a.can_merge_with_box(b),
                (_, _) => false
            }
        }
    }

    fn reset_clump_to_index(i: uint) {
        debug!("resetting clump to %u", i);

        self.clump_start = i;
        self.clump_end = i;
        self.in_clump = true;
    }

    fn flush_clump_to_list(ctx: &LayoutContext,
                           in_boxes: &[@RenderBox], temp_boxes: &DVec<@RenderBox>) {
        assert self.in_clump;

        debug!("flushing when start=%?,end=%?", self.clump_start, self.clump_end);

        let is_singleton = (self.clump_start == self.clump_end);
        let is_text_clump = match in_boxes[self.clump_start] {
            @UnscannedTextBox(*) => true,
            _ => false
        };

        // TODO: repair the mapping of DOM elements to boxes if it changed.
        // (the mapping does not yet exist; see Issue #103)
        match (is_singleton, is_text_clump) {
            (false, false) => fail ~"WAT: can't coalesce non-text boxes in flush_clump_to_list()!",
            (true, false) => { temp_boxes.push(in_boxes[self.clump_start]); }
            (true, true)  => {
                let text = in_boxes[self.clump_start].raw_text();
                // TODO: use actual font for corresponding DOM node to create text run.
                let run = TextRun(&*ctx.font_cache.get_test_font(), text);
                let box_guts = TextBoxData(@run, 0, text.len());
                debug!("pushing when start=%?,end=%?", self.clump_start, self.clump_end);
                temp_boxes.push(@TextBox(copy *in_boxes[self.clump_start].d(), box_guts));
            },
            (false, true) => {
                let mut run_str : ~str = ~"";
                // TODO: is using ropes to construct the merged text any faster?
                do uint::range(self.clump_start, self.clump_end+1) |i| {
                    run_str = str::append(copy run_str, in_boxes[i].raw_text()); true
                }
                // TODO: use actual font for corresponding DOM node to create text run.
                let run = @TextRun(&*ctx.font_cache.get_test_font(), move run_str);
                let box_guts = TextBoxData(run, 0, run.text.len());
                debug!("pushing when start=%?,end=%?", self.clump_start, self.clump_end);
                temp_boxes.push(@TextBox(copy *in_boxes[self.clump_start].d(), box_guts));
            }
        }
        self.in_clump = false;
    }
}

struct InlineFlowData {
    // A vec of all inline render boxes. Several boxes may
    // correspond to one Node/Element.
    boxes: DVec<@RenderBox>,
    // vec of ranges into boxes that represents line positions.
    // these ranges are disjoint, and are the result of inline layout.
    lines: DVec<BoxRange>,
    // vec of ranges into boxes that represent elements. These
    // ranges must be disjoint or well-nested, and are only related to
    // the content of boxes (not lines)
    elems: DVec<BoxRange>
}

fn InlineFlowData() -> InlineFlowData {
    InlineFlowData {
        boxes: DVec(),
        lines: DVec(),
        elems: DVec()
    }
}

trait InlineLayout {
    pure fn starts_inline_flow() -> bool;

    fn bubble_widths_inline(@self, ctx: &LayoutContext);
    fn assign_widths_inline(@self, ctx: &LayoutContext);
    fn assign_height_inline(@self, ctx: &LayoutContext);
    fn build_display_list_inline(@self, a: &dl::DisplayListBuilder, b: &Rect<au>, c: &Point2D<au>, d: &dl::DisplayList);
}

impl FlowContext : InlineLayout {
    pure fn starts_inline_flow() -> bool { match self { InlineFlow(*) => true, _ => false } }

    fn bubble_widths_inline(@self, ctx: &LayoutContext) {
        assert self.starts_inline_flow();

        debug!("box count: %u", self.inline().boxes.len());

        let scanner = TextRunScanner(self);
        scanner.scan_for_runs(ctx);

        let mut min_width = au(0);
        let mut pref_width = au(0);

        debug!("/box count: %u", self.inline().boxes.len());

        for self.inline().boxes.each |box| {
            debug!("measuring box: %s", box.debug_str());
            min_width = au::max(min_width, box.get_min_width(ctx));
            pref_width = au::max(pref_width, box.get_pref_width(ctx));
        }

        self.d().min_width = min_width;
        self.d().pref_width = pref_width;
    }

    /* Recursively (top-down) determines the actual width of child
    contexts and boxes. When called on this context, the context has
    had its width set by the parent context. */
    fn assign_widths_inline(@self, ctx: &LayoutContext) {
        assert self.starts_inline_flow();

        /* Perform inline flow with the available width. */
        //let avail_width = self.d().position.size.width;

        let line_height = au::from_px(20);
        //let mut cur_x = au(0);
        let mut cur_y = au(0);

        // TODO: remove test font uses
        let test_font = ctx.font_cache.get_test_font();

        for self.inline().boxes.each |box| {
            /* TODO: actually do inline flow.
            - Create a working linebox, and successively put boxes
            into it, splitting if necessary.

            - Set width and height for each positioned element based on
            where its chunks ended up.

            - Save the dvec of this context's lineboxes. */

            box.d().position.size.width = match *box {
                @ImageBox(_,img) => au::from_px(img.get_size().get_default(Size2D(0,0)).width),
                @TextBox(_,d) => {
                    // TODO: measure twice, cut once doesn't apply to text. Shouldn't need
                    // to measure text again here (should be inside TextBox.split)
                    let metrics = test_font.measure_text(d.run, d.offset, d.length);
                    metrics.advance
                },
                // TODO: this should be set to the extents of its children
                @GenericBox(*) => au(0),
                _ => fail fmt!("Tried to assign width to unknown Box variant: %?", box)
            };

            box.d().position.size.height = match *box {
                @ImageBox(_,img) => au::from_px(img.get_size().get_default(Size2D(0,0)).height),
                // TODO: we should use the bounding box of the actual text, i think?
                @TextBox(*) => test_font.metrics.em_size,
                // TODO: this should be set to the extents of its children
                @GenericBox(*) => au(0),
                _ => fail fmt!("Tried to assign width to unknown Box variant: %?", box)
            };

            box.d().position.origin = Point2D(au(0), cur_y);
            cur_y = cur_y.add(&au::max(line_height, box.d().position.size.height));
        } // for boxes.each |box|

    self.d().position.size.height = cur_y;

    /* There are no child contexts, so stop here. */

    // TODO: once there are 'inline-block' elements, this won't be
    // true.  In that case, perform inline flow, and then set the
    // block flow context's width as the width of the
    // 'inline-block' box that created this flow.
    }

    fn assign_height_inline(@self, _ctx: &LayoutContext) {
        // Don't need to set box or ctx heights, since that is done
        // during inline flowing.
    }

    fn build_display_list_inline(@self, builder: &dl::DisplayListBuilder, dirty: &Rect<au>,
                                 offset: &Point2D<au>, list: &dl::DisplayList) {

        assert self.starts_inline_flow();

        // TODO: if the CSS box introducing this inline context is *not* anonymous,
        // we need to draw it too, in a way similar to BlowFlowContext

        // TODO: once we form line boxes and have their cached bounds, we can be
        // smarter and not recurse on a line if nothing in it can intersect dirty
        debug!("building display list for %u inline boxes", self.inline().boxes.len());
        for self.inline().boxes.each |box| {
            box.build_display_list(builder, dirty, offset, list)
        }

        // TODO: should inline-block elements have flows as children
        // of the inline flow, or should the flow be nested inside the
        // box somehow? Maybe it's best to unify flows and boxes into
        // the same enum, so inline-block flows are normal
        // (indivisible) children in the inline flow child list.
    }

} // @FlowContext : InlineLayout
<|endoftext|>


<commit_before><commit_msg> removed filter for testing<commit_after><|endoftext|>


<commit_before><commit_msg>parser: remove dead code<commit_after><|endoftext|>


<commit_before><commit_msg>Implement capped statements cache<commit_after>use std::borrow::Borrow;
use std::collections::{HashMap, VecDeque};
use std::collections::hash_map::IntoIter;
use std::hash::{BuildHasherDefault, Hash};
use super::InnerStmt;
use twox_hash::XxHash;

#[derive(Debug)]
pub struct StmtCache {
    cap: usize,
    map: HashMap<String, InnerStmt, BuildHasherDefault<XxHash>>,
    order: VecDeque<String>,
}

impl StmtCache {
    pub fn new(cap: usize) -> StmtCache {
        StmtCache {
            cap,
            map: Default::default(),
            order: VecDeque::with_capacity(cap),
        }
    }

    pub fn contains<T>(&self, key: &T) -> bool
        where String: Borrow<T>,
              T: Hash + Eq,
              T: ?Sized
    {
        self.map.contains_key(key)
    }

    pub fn get<T>(&mut self, key: &T) -> Option<&InnerStmt>
        where String: Borrow<T>,
              String: PartialEq<T>,
              T: Hash + Eq,
              T: ?Sized
    {
        if self.map.contains_key(key) {
            if let Some(mut pos) = self.order.iter().position(|x| x == key) {
                while pos < self.order.len() - 1 {
                    self.order.swap(pos, pos + 1);
                    pos += 1;
                }
            }
            self.map.get(key)
        } else {
            None
        }
    }

    pub fn put(&mut self, key: String, value: InnerStmt) -> Option<InnerStmt> {
        self.map.insert(key.clone(), value);
        self.order.push_front(key);
        if self.order.len() > self.cap {
            self.order.pop_back().and_then(|stmt| self.map.remove(&stmt))
        } else {
            None
        }
    }

    pub fn clear(&mut self) {
        self.map.clear();
        self.order.clear();
    }

    pub fn into_iter(self) -> IntoIter<String, InnerStmt> {
        self.map.into_iter()
    }

    pub fn get_cap(&self) -> usize {
        self.cap
    }
}<|endoftext|>


<commit_before>/*
Module: list

A standard linked list
*/

import option::{some, none};

/* Section: Types */

/*
Tag: list
*/
tag list<T> {
    /* Variant: cons */
    cons(T, @list<T>);
    /* Variant: nil */
    nil;
}

/*Section: Operations */

/*
Function: from_vec

Create a list from a vector
*/
fn from_vec<T>(v: [mutable? T]) -> list<T> {
    *vec::foldr({ |h, t| @cons(h, t) }, @nil::<T>, v)
}

/*
Function: foldl

Left fold

Applies `f` to the first argument in the list and `u`, then applies
`f` to the second argument and the result of the previous call,
and so on, returning the accumulated result.

Parameters:

ls_ - The list to fold
u - The initial value
f - The function to apply
*/
fn foldl<T, U>(ls_: list<T>, u: U, f: block(T, U) -> U) -> U {
    let accum: U = u;
    let ls = ls_;
    while true {
        alt ls {
          cons(hd, tl) { accum = f(hd, accum); ls = *tl; }
          nil. { break; }
        }
    }
    ret accum;
}

/*
Function: find

Search for an element that matches a given predicate

Apply function `f` to each element of `v`, starting from the first.
When function `f` returns true then an option containing the element
is returned. If `f` matches no elements then none is returned.
*/
fn find<T, U>(ls_: list<T>, f: block(T) -> option::t<U>) -> option::t<U> {
    let ls = ls_;
    while true {
        alt ls {
          cons(hd, tl) {
            alt f(hd) { none. { ls = *tl; } some(rs) { ret some(rs); } }
          }
          nil. { break; }
        }
    }
    ret none;
}

/*
Function: has

Returns true if a list contains an element with the given value
*/
fn has<T>(ls_: list<T>, elt: T) -> bool {
    let ls = ls_;
    while true {
        alt ls {
          cons(hd, tl) { if elt == hd { ret true; } else { ls = *tl; } }
          nil. { break; }
        }
    }
    ret false;
}

/*
Function: length

Returns the length of a list
*/
fn length<T>(ls: list<T>) -> uint {
    fn count<T>(_t: T, &&u: uint) -> uint { ret u + 1u; }
    ret foldl(ls, 0u, bind count(_, _));
}

/*
Function: cdr

Returns all but the first element of a list
*/
fn cdr<T>(ls: list<T>) -> list<T> {
    alt ls { cons(_, tl) { ret *tl; } nil. { fail "list empty" } }
}

/*
Function: car

Returns the first element of a list
*/
fn car<T>(ls: list<T>) -> T {
    alt ls { cons(hd, _) { ret hd; } nil. { fail "list empty" } }
}

/*
Function: append

Appends one list to another
*/
fn append<T>(l: list<T>, m: list<T>) -> list<T> {
    alt l {
      nil. { ret m; }
      cons(x, xs) { let rest = append(*xs, m); ret cons(x, @rest); }
    }
}

// Local Variables:
// mode: rust;
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// compile-command: "make -k -C $RBUILD 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
// End:
<commit_msg>stdlib: Rename the 'ls_' param in list functions to 'ls'<commit_after>/*
Module: list

A standard linked list
*/

import option::{some, none};

/* Section: Types */

/*
Tag: list
*/
tag list<T> {
    /* Variant: cons */
    cons(T, @list<T>);
    /* Variant: nil */
    nil;
}

/*Section: Operations */

/*
Function: from_vec

Create a list from a vector
*/
fn from_vec<T>(v: [mutable? T]) -> list<T> {
    *vec::foldr({ |h, t| @cons(h, t) }, @nil::<T>, v)
}

/*
Function: foldl

Left fold

Applies `f` to the first argument in the list and `u`, then applies
`f` to the second argument and the result of the previous call,
and so on, returning the accumulated result.

Parameters:

ls - The list to fold
u - The initial value
f - The function to apply
*/
fn foldl<T, U>(ls: list<T>, u: U, f: block(T, U) -> U) -> U {
    let accum: U = u;
    let ls = ls;
    while true {
        alt ls {
          cons(hd, tl) { accum = f(hd, accum); ls = *tl; }
          nil. { break; }
        }
    }
    ret accum;
}

/*
Function: find

Search for an element that matches a given predicate

Apply function `f` to each element of `v`, starting from the first.
When function `f` returns true then an option containing the element
is returned. If `f` matches no elements then none is returned.
*/
fn find<T, U>(ls: list<T>, f: block(T) -> option::t<U>) -> option::t<U> {
    let ls = ls;
    while true {
        alt ls {
          cons(hd, tl) {
            alt f(hd) { none. { ls = *tl; } some(rs) { ret some(rs); } }
          }
          nil. { break; }
        }
    }
    ret none;
}

/*
Function: has

Returns true if a list contains an element with the given value
*/
fn has<T>(ls: list<T>, elt: T) -> bool {
    let ls = ls;
    while true {
        alt ls {
          cons(hd, tl) { if elt == hd { ret true; } else { ls = *tl; } }
          nil. { break; }
        }
    }
    ret false;
}

/*
Function: length

Returns the length of a list
*/
fn length<T>(ls: list<T>) -> uint {
    fn count<T>(_t: T, &&u: uint) -> uint { ret u + 1u; }
    ret foldl(ls, 0u, bind count(_, _));
}

/*
Function: cdr

Returns all but the first element of a list
*/
fn cdr<T>(ls: list<T>) -> list<T> {
    alt ls { cons(_, tl) { ret *tl; } nil. { fail "list empty" } }
}

/*
Function: car

Returns the first element of a list
*/
fn car<T>(ls: list<T>) -> T {
    alt ls { cons(hd, _) { ret hd; } nil. { fail "list empty" } }
}

/*
Function: append

Appends one list to another
*/
fn append<T>(l: list<T>, m: list<T>) -> list<T> {
    alt l {
      nil. { ret m; }
      cons(x, xs) { let rest = append(*xs, m); ret cons(x, @rest); }
    }
}

// Local Variables:
// mode: rust;
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// compile-command: "make -k -C $RBUILD 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
// End:
<|endoftext|>


<commit_before><commit_msg>Add problem #109<commit_after>#[link(name = "prob0109", vers = "0.0")];
#[crate_type = "lib"];

extern mod math;
use std::vec;
use std::num::Zero;
use math::poly;

pub static EXPECTED_ANSWER: &'static str = "38182";

fn square<T: Zero + Add<T, T> + Mul<T, T>>(n: &[T]) -> ~[T] { poly::mul(n, n) }

pub fn solve() -> ~str {
    let mut single = vec::from_elem(26, 0);
    let mut double = vec::from_elem(51, 0);
    let mut triple = vec::from_elem(61, 0);
    let mut dup    = vec::from_elem(121, 0);
    for i in range(1, 21) {
        single[1 * i] = 1;
        double[2 * i] = 1;
        triple[3 * i] = 1;
        dup[2 * i] += 1;
        dup[4 * i] += 1;
        dup[6 * i] += 1;
    }
    single[25] = 1;
    double[50] = 1;
    dup[50]    += 1;
    dup[100]   += 1;

    let p_all = poly::add(poly::add(single, double), triple);
    let p1    = double.clone();
    let p2    = poly::mul(p_all, double);
    let p3    = poly::mul(poly::add(square(p_all), dup).map(|n| n / 2), double);
    let total = poly::add(poly::add(p1, p2), p3);
    return total.iter().take(100).fold(0, |i, &a| i + a).to_str();
}
<|endoftext|>


<commit_before><commit_msg>Skeleton for problem 2319<commit_after>// https://leetcode.com/problems/check-if-matrix-is-x-matrix/
pub fn check_x_matrix(grid: Vec<Vec<i32>>) -> bool {
    todo!()
}

fn main() {
    println!(
        "{}",
        check_x_matrix(vec![
            vec![2, 0, 0, 1],
            vec![0, 3, 1, 0],
            vec![0, 5, 2, 0],
            vec![4, 0, 0, 2]
        ])
    ); // true
    println!(
        "{}",
        check_x_matrix(vec![vec![5, 7, 0], vec![0, 3, 1], vec![0, 5, 0]])
    ); // true
}
<|endoftext|>


<commit_before><commit_msg>Skeleton for problem 2442<commit_after>// https://leetcode.com/problems/count-number-of-distinct-integers-after-reverse-operations/
pub fn count_distinct_integers(nums: Vec<i32>) -> i32 {
    todo!()
}

fn main() {
    println!("{}", count_distinct_integers(vec![1, 13, 10, 12, 31])); // 6
    println!("{}", count_distinct_integers(vec![2, 2, 2])); // 1
}
<|endoftext|>


<commit_before><commit_msg>Syncfile: started code to read it back in<commit_after><|endoftext|>


<commit_before><commit_msg>require allocator for PDF to ease computation of context map<commit_after>#[derive(Copy, Clone, Default, Debug)]
pub struct PDF([i32;16]);

<|endoftext|>


<commit_before>extern crate rand;
extern crate ryu;

use std::mem;

use rand::{Rng, SeedableRng};

const SAMPLES: usize = 10000;
const ITERATIONS: usize = 1000;

struct MeanAndVariance {
    n: i64,
    mean: f64,
    m2: f64,
}

impl MeanAndVariance {
    fn new() -> Self {
        MeanAndVariance {
            n: 0,
            mean: 0.0,
            m2: 0.0,
        }
    }

    fn update(&mut self, x: f64) {
        self.n += 1;
        let d = x - self.mean;
        self.mean += d / self.n as f64;
        let d2 = x - self.mean;
        self.m2 += d * d2;
    }

    fn variance(&self) -> f64 {
        self.m2 / (self.n - 1) as f64
    }
}

macro_rules! benchmark {
    ($name:ident, |$var:ident: $ty:ident| $computation:expr) => {
        fn $name() -> usize {
            let mut rng = rand::prng::XorShiftRng::from_seed([123u8; 16]);
            let mut mv = MeanAndVariance::new();
            let mut throwaway = 0;
            for _ in 0..SAMPLES {
                let $var = loop {
                    let f = $ty::from_bits(rng.gen());
                    if f.is_finite() {
                        break f;
                    }
                };

                let t1 = std::time::SystemTime::now();
                for _ in 0..ITERATIONS {
                    throwaway += $computation;
                }
                let duration = t1.elapsed().unwrap();
                let nanos = duration.as_secs() * 1_000_000_000 + duration.subsec_nanos() as u64;
                mv.update(nanos as f64 / ITERATIONS as f64);
            }
            println!(
                "{:12} {:8.3} {:8.3}",
                concat!(stringify!($name), ":"),
                mv.mean,
                mv.variance().sqrt()
            );
            throwaway
        }
    };
}

benchmark!(original32, |f: f32| unsafe {
    let mut buffer: [u8; 15] = mem::uninitialized();
    ryu::raw::f2s_buffered_n(f, &mut buffer[0])
});

benchmark!(pretty32, |f: f32| ryu::Buffer::new().format(f).len());

benchmark!(original64, |f: f64| unsafe {
    let mut buffer: [u8; 24] = mem::uninitialized();
    ryu::raw::d2s_buffered_n(f, &mut buffer[0])
});

benchmark!(pretty64, |f: f64| ryu::Buffer::new().format(f).len());

fn main() {
    println!("{:>20}{:>9}", "Average", "Stddev");
    let mut throwaway = 0;
    throwaway += original32();
    throwaway += pretty32();
    throwaway += original64();
    throwaway += pretty64();
    if std::env::var_os("ryu-benchmark").is_some() {
        // Prevent the compiler from optimizing the code away.
        println!("{}", throwaway);
    }
}
<commit_msg>Focus on pretty benchmark<commit_after>extern crate rand;
extern crate ryu;

use rand::{Rng, SeedableRng};

const SAMPLES: usize = 10000;
const ITERATIONS: usize = 1000;

struct MeanAndVariance {
    n: i64,
    mean: f64,
    m2: f64,
}

impl MeanAndVariance {
    fn new() -> Self {
        MeanAndVariance {
            n: 0,
            mean: 0.0,
            m2: 0.0,
        }
    }

    fn update(&mut self, x: f64) {
        self.n += 1;
        let d = x - self.mean;
        self.mean += d / self.n as f64;
        let d2 = x - self.mean;
        self.m2 += d * d2;
    }

    fn variance(&self) -> f64 {
        self.m2 / (self.n - 1) as f64
    }
}

macro_rules! benchmark {
    ($name:ident, $ty:ident) => {
        fn $name() -> usize {
            let mut rng = rand::prng::XorShiftRng::from_seed([123u8; 16]);
            let mut mv = MeanAndVariance::new();
            let mut throwaway = 0;
            for _ in 0..SAMPLES {
                let f = loop {
                    let f = $ty::from_bits(rng.gen());
                    if f.is_finite() {
                        break f;
                    }
                };

                let t1 = std::time::SystemTime::now();
                for _ in 0..ITERATIONS {
                    throwaway += ryu::Buffer::new().format(f).len();
                }
                let duration = t1.elapsed().unwrap();
                let nanos = duration.as_secs() * 1_000_000_000 + duration.subsec_nanos() as u64;
                mv.update(nanos as f64 / ITERATIONS as f64);
            }
            println!(
                "{:12} {:8.3} {:8.3}",
                concat!(stringify!($name), ":"),
                mv.mean,
                mv.variance().sqrt()
            );
            throwaway
        }
    };
}

benchmark!(pretty32, f32);
benchmark!(pretty64, f64);

fn main() {
    println!("{:>20}{:>9}", "Average", "Stddev");
    let mut throwaway = 0;
    throwaway += pretty32();
    throwaway += pretty64();
    if std::env::var_os("ryu-benchmark").is_some() {
        // Prevent the compiler from optimizing the code away.
        println!("{}", throwaway);
    }
}
<|endoftext|>


<commit_before>use core::mem::size_of;

use common::memory::*;
use common::pci::*;

use programs::common::*;

struct STE {
    pub ptr: u64,
    pub length: u64
}

struct TRB {
    pub data: u64,
    pub status: u32,
    pub control: u32
}

impl TRB {
    pub fn new() -> TRB {
        TRB {
           data: 0,
           status: 0,
           control: 0
        }
    }

    pub fn from_type(trb_type: u32) -> TRB {
        TRB {
            data: 0,
            status: 0,
            control: (trb_type & 0x3F) << 10
        }
    }
}

pub struct EHCI {
    pub bus: usize,
    pub slot: usize,
    pub func: usize,
    pub base: usize,
    pub memory_mapped: bool,
    pub irq: u8
}

impl SessionModule for EHCI {
    fn on_irq(&mut self, irq: u8){
        if irq == self.irq {
            //d("EHCI handle");

            unsafe{
                let CAPLENGTH = self.base as *mut u8;

                let opbase = self.base + *CAPLENGTH as usize;

                let USBSTS = (opbase + 4) as *mut u32;
                //d(" USBSTS ");
                //dh(*USBSTS as usize);

                *USBSTS = 0b111111;

                //d(" USBSTS ");
                //dh(*USBSTS as usize);

                //let FRINDEX = (opbase + 0xC) as *mut u32;
                //d(" FRINDEX ");
                //dh(*FRINDEX as usize);
            }

            //dl();
        }
    }
}

impl EHCI {
    pub unsafe fn init(&self){
        d("EHCI on: ");
        dh(self.base);
        if self.memory_mapped {
            d(" memory mapped");
        }else{
            d(" port mapped");
        }
        d(" IRQ: ");
        dbh(self.irq);

        pci_write(self.bus, self.slot, self.func, 0x04, pci_read(self.bus, self.slot, self.func, 0x04) | 4); // Bus master

        let CAPLENGTH = self.base as *mut u8;

        d(" CAPLENGTH ");
        dd(*CAPLENGTH as usize);

        let opbase = self.base + *CAPLENGTH as usize;

        let USBCMD = opbase as *mut u32;
        let USBSTS = (opbase + 4) as *mut u32;
        let USBINTR = (opbase + 8) as *mut u32;
        let FRINDEX = (opbase + 0xC) as *mut u32;
        let CTRLDSSEGMENT = (opbase + 0x10) as *mut u32;
        let PERIODICLISTBASE = (opbase + 0x14) as *mut u32;
        let ASYNCLISTADDR = (opbase + 0x18) as *mut u32;
        let CONFIGFLAG = (opbase + 0x40) as *mut u32;
        let PORTSC = (opbase + 0x44) as *mut u32;

        *USBCMD &= 0xFFFFFFFE;
        d(" CMD ");
        dh(*USBCMD as usize);

        d(" STS ");
        dh(*USBSTS as usize);

        //*CTRLDSSEGMENT = 0;

        *USBINTR = 0b111111;

        let periodiclist = alloc(4096) as *mut u32;

        for i in 0..1024 {
            *periodiclist.offset(i) = periodiclist as u32 | 1;
        }
        *PERIODICLISTBASE = periodiclist as u32;

        *USBCMD |= 1;
        *CONFIGFLAG = 1;

        d(" CMD ");
        dh(*USBCMD as usize);

        d(" STS ");
        dh(*USBSTS as usize);

        dl();

        for i in 0..16 {
            if *PORTSC.offset(i) & 1 == 1 {
                d("Device on port ");
                dd(i as usize);
                dl();
            }
        }
    }
}
<commit_msg>WIP USB<commit_after>use core::mem::size_of;
use core::ptr;

use common::memory::*;
use common::pci::*;

use programs::common::*;

struct SETUP {
    request_type: u8,
    request: u8,
    value: u16,
    index: u16,
    len: u16
}

struct QTD {
    next: u32,
    next_alt: u32,
    token: u32,
    buffers: [u32; 5]
}

struct QueueHead {
    next: u32,
    characteristics: u32,
    capabilities: u32,
    qtd_ptr: u32,
    qtd: QTD
}

pub struct EHCI {
    pub bus: usize,
    pub slot: usize,
    pub func: usize,
    pub base: usize,
    pub memory_mapped: bool,
    pub irq: u8
}

impl SessionModule for EHCI {
    fn on_irq(&mut self, irq: u8){
        if irq == self.irq {
            //d("EHCI handle");

            unsafe{
                let CAPLENGTH = self.base as *mut u8;

                let opbase = self.base + *CAPLENGTH as usize;

                let USBSTS = (opbase + 4) as *mut u32;
                //d(" USBSTS ");
                //dh(*USBSTS as usize);

                *USBSTS = 0b111111;

                //d(" USBSTS ");
                //dh(*USBSTS as usize);

                //let FRINDEX = (opbase + 0xC) as *mut u32;
                //d(" FRINDEX ");
                //dh(*FRINDEX as usize);
            }

            //dl();
        }
    }
}

impl EHCI {
    pub unsafe fn init(&self){
        d("EHCI on: ");
        dh(self.base);
        if self.memory_mapped {
            d(" memory mapped");
        }else{
            d(" port mapped");
        }
        d(" IRQ: ");
        dbh(self.irq);

        pci_write(self.bus, self.slot, self.func, 0x04, pci_read(self.bus, self.slot, self.func, 0x04) | 4); // Bus master

        let CAPLENGTH = self.base as *mut u8;

        d(" CAPLENGTH ");
        dd(*CAPLENGTH as usize);

        let opbase = self.base + *CAPLENGTH as usize;

        let USBCMD = opbase as *mut u32;
        let USBSTS = (opbase + 4) as *mut u32;
        let USBINTR = (opbase + 8) as *mut u32;
        let FRINDEX = (opbase + 0xC) as *mut u32;
        let CTRLDSSEGMENT = (opbase + 0x10) as *mut u32;
        let PERIODICLISTBASE = (opbase + 0x14) as *mut u32;
        let ASYNCLISTADDR = (opbase + 0x18) as *mut u32;
        let CONFIGFLAG = (opbase + 0x40) as *mut u32;
        let PORTSC = (opbase + 0x44) as *mut u32;

        d(" CMD ");
        dh(*USBCMD as usize);

        d(" STS ");
        dh(*USBSTS as usize);

        *USBCMD &= 0xFFFFFFF0;

        d(" CMD ");
        dh(*USBCMD as usize);

        d(" STS ");
        dh(*USBSTS as usize);

        //*CTRLDSSEGMENT = 0;

        *USBINTR = 0b111111;

        *USBCMD |= 1;
        *CONFIGFLAG = 1;

        d(" CMD ");
        dh(*USBCMD as usize);

        d(" STS ");
        dh(*USBSTS as usize);

        dl();

        for i in 0..16 {
            if *PORTSC.offset(i) & 1 == 1 {
                d("Device on port ");
                dd(i as usize);
                d(" ");
                dh(*PORTSC.offset(i) as usize);
                dl();

                let out_qtd = alloc(size_of::<QTD>()) as *mut QTD;
                ptr::write(out_qtd, QTD {
                    next: 1,
                    next_alt: 1,
                    token: (1 << 31) | (0b11 << 10) | 0x80,
                    buffers: [0, 0, 0, 0, 0]
                });

                let in_data = alloc(64) as *mut u8;
                for i in 0..64{
                    *in_data.offset(i) = 0;
                }

                let in_qtd = alloc(size_of::<QTD>()) as *mut QTD;
                ptr::write(in_qtd, QTD {
                    next: out_qtd as u32,
                    next_alt: 1,
                    token: (1 << 31) | (64 << 16) | (0b11 << 10) | (0b01 << 8) | 0x80,
                    buffers: [in_data as u32, 0, 0, 0, 0]
                });

                let setup_packet = alloc(size_of::<SETUP>()) as *mut SETUP;
                ptr::write(setup_packet, SETUP {
                    request_type: 0b10000000,
                    request: 6,
                    value: 1 << 8,
                    index: 0,
                    len: 64
                });

                let setup_qtd = alloc(size_of::<QTD>()) as *mut QTD;
                ptr::write(setup_qtd, QTD {
                    next: in_qtd as u32,
                    next_alt: 1,
                    token: ((size_of::<SETUP>() as u32) << 16) | (0b11 << 10) | (0b10 << 8) | 0x80,
                    buffers: [setup_packet as u32, 0, 0, 0, 0]
                });

                let queuehead = alloc(size_of::<QueueHead>()) as *mut QueueHead;
                ptr::write(queuehead, QueueHead {
                    next: 1,
                    characteristics: (64 << 16) | (1 << 15) | (1 << 14) | (0b10 << 12),
                    capabilities: (0b11 << 30),
                    qtd_ptr: setup_qtd as u32,
                    qtd: ptr::read(setup_qtd)
                });

                d("Prepare");
                    d(" CMD ");
                    dh(*USBCMD as usize);

                    d(" PTR ");
                    dh(queuehead as usize);
                dl();

                d("Send");
                    *ASYNCLISTADDR = queuehead as u32;

                    *USBCMD |= (1 << 5);

                    d(" CMD ");
                    dh(*USBCMD as usize);

                    d(" STS ");
                    dh(*USBSTS as usize);
                dl();

                loop {
                    d("Wait");
                        if *USBSTS & 0xA000  == 0 {
                            break;
                        }

                        d(" CMD ");
                        dh(*USBCMD as usize);

                        d(" STS ");
                        dh(*USBSTS as usize);
                    dl();
                }

                d(" Stop");
                    *USBCMD &= 0xFFFFFFFF - (1 << 5);

                    d(" CMD ");
                    dh(*USBCMD as usize);

                    d(" STS ");
                    dh(*USBSTS as usize);
                dl();

                d("Data");
                for i in 0..64 {
                    d(" ");
                    db(*in_data.offset(i));
                }
                dl();

                //Only detect one device for testing
                break;
            }
        }
    }
}
<|endoftext|>