<commit_before>use std::path::PathBuf;

use git2::{Repository, Signature};
use toml::Value;

use libimagerror::into::IntoError;
use libimagerror::trace::trace_error;
use libimagstore::hook::error::CustomData;
use libimagstore::hook::error::HookErrorKind as HEK;

use vcs::git::result::Result;
use vcs::git::error::{MapErrInto, GitHookErrorKind as GHEK};
use vcs::git::config::{author_name, author_mail, committer_name, committer_mail};

struct Person<'a> {
    pub name: &'a str,
    pub mail: &'a str,
}

impl<'a> Person<'a> {
    fn new(name: &'a str, mail: &'a str) -> Person<'a> {
        Person { name: name, mail: mail }
    }
}

pub struct Runtime<'a> {
    repository: Option<Repository>,
    author: Option<Person<'a>>,
    committer: Option<Person<'a>>,

    config: Option<Value>,
}

impl<'a> Runtime<'a> {

    pub fn new(storepath: &PathBuf) -> Runtime<'a> {
        Runtime {
            repository: match Repository::open(storepath) {
                Ok(r) => Some(r),
                Err(e) => {
                    trace_error(&e);
                    None
                },
            },

            author: None,
            committer: None,
            config: None,
        }
    }

    pub fn set_config(&mut self, cfg: &Value) -> Result<()> {
        let config = cfg.clone();
        let res = author_name(&config)
            .and_then(|n| author_mail(&config).map(|m| Person::new(n, m)))
            .and_then(|author| {
                committer_name(&config)
                    .and_then(|n| committer_mail(&config).map(|m| (author, Person::new(n, m))))
            })
            .map(|(author, committer)| {
                self.author = Some(author);
                self.committer = Some(committer);
            });
        self.config = Some(config);
        res
    }

    pub fn has_repository(&self) -> bool {
        self.repository.is_some()
    }

    pub fn has_config(&self) -> bool {
        self.config.is_some()
    }

    pub fn config_value_or_err(&self) -> HookResult<&Value> {
        self.config
            .as_ref()
            .ok_or(GHEK::NoConfigError.into_error())
            .map_err_into(GHEK::ConfigError)
            .map_err(Box::new)
            .map_err(|e| HEK::HookExecutionError.into_error_with_cause(e))
            .map_err(|mut e| e.with_custom_data(CustomData::default().aborting(false)))
    }

    pub fn new_committer_sig(&self) -> Option<Result<Signature>> {
        self.committer
            .as_ref()
            .map(|c| {
                Signature::now(c.name, c.mail)
                    .map_err(|e| GHEK::MkSignature.into_error_with_cause(Box::new(e)))
            })
    }

    pub fn repository(&self) -> Result<&Repository> {
        self.repository.as_ref().ok_or(GHEK::MkRepo.into_error())
    }

    pub fn ensure_cfg_branch_is_checked_out(&self) -> HookResult<()> {
        use vcs::git::config::ensure_branch;

        let head = try!(self
                        .repository()
                        .and_then(|r| {
                            r.head().map_err_into(GHEK::HeadFetchError)
                        })
                        .map_err(Box::new)
                        .map_err(|e| HEK::HookExecutionError.into_error_with_cause(e)));

        // TODO: Fail if not on branch? hmmh... I'm not sure
        if head.is_branch() {
            return Err(GHEK::NotOnBranch.into_error())
                .map_err(Box::new)
                .map_err(|e| HEK::HookExecutionError.into_error_with_cause(e));
        }

        // Check out appropriate branch ... or fail
        match ensure_branch(self.config.as_ref()) {
            Ok(Some(s)) => {
                match head.name().map(|name| name == s) {
                    Some(b) => {
                        if b {
                            debug!("Branch already checked out.");
                            Ok(())
                        } else {
                            debug!("Branch not checked out.");
                            unimplemented!()
                        }
                    },

                    None => Err(GHEK::RepositoryBranchNameFetchingError.into_error())
                        .map_err_into(GHEK::RepositoryBranchError)
                        .map_err_into(GHEK::RepositoryError),
                }
            },
            Ok(None) => {
                debug!("No branch to checkout");
                Ok(())
            },

            Err(e) => Err(e).map_err_into(GHEK::RepositoryError),
        }
        .map_err(Box::new)
        .map_err(|e| HEK::HookExecutionError.into_error_with_cause(e))
    }

}

<commit_msg>Add Runtime::new_committer_sig()<commit_after>use std::path::PathBuf;

use git2::{Repository, Signature};
use toml::Value;

use libimagerror::into::IntoError;
use libimagerror::trace::trace_error;
use libimagstore::hook::error::CustomData;
use libimagstore::hook::error::HookErrorKind as HEK;

use vcs::git::result::Result;
use vcs::git::error::{MapErrInto, GitHookErrorKind as GHEK};
use vcs::git::config::{author_name, author_mail, committer_name, committer_mail};

struct Person<'a> {
    pub name: &'a str,
    pub mail: &'a str,
}

impl<'a> Person<'a> {
    fn new(name: &'a str, mail: &'a str) -> Person<'a> {
        Person { name: name, mail: mail }
    }
}

pub struct Runtime<'a> {
    repository: Option<Repository>,
    author: Option<Person<'a>>,
    committer: Option<Person<'a>>,

    config: Option<Value>,
}

impl<'a> Runtime<'a> {

    pub fn new(storepath: &PathBuf) -> Runtime<'a> {
        Runtime {
            repository: match Repository::open(storepath) {
                Ok(r) => Some(r),
                Err(e) => {
                    trace_error(&e);
                    None
                },
            },

            author: None,
            committer: None,
            config: None,
        }
    }

    pub fn set_config(&mut self, cfg: &Value) -> Result<()> {
        let config = cfg.clone();
        let res = author_name(&config)
            .and_then(|n| author_mail(&config).map(|m| Person::new(n, m)))
            .and_then(|author| {
                committer_name(&config)
                    .and_then(|n| committer_mail(&config).map(|m| (author, Person::new(n, m))))
            })
            .map(|(author, committer)| {
                self.author = Some(author);
                self.committer = Some(committer);
            });
        self.config = Some(config);
        res
    }

    pub fn has_repository(&self) -> bool {
        self.repository.is_some()
    }

    pub fn has_config(&self) -> bool {
        self.config.is_some()
    }

    pub fn config_value_or_err(&self) -> HookResult<&Value> {
        self.config
            .as_ref()
            .ok_or(GHEK::NoConfigError.into_error())
            .map_err_into(GHEK::ConfigError)
            .map_err(Box::new)
            .map_err(|e| HEK::HookExecutionError.into_error_with_cause(e))
            .map_err(|mut e| e.with_custom_data(CustomData::default().aborting(false)))
    }

    pub fn new_committer_sig(&self) -> Option<Result<Signature>> {
        self.committer
            .as_ref()
            .map(|c| {
                Signature::now(c.name, c.mail)
                    .map_err(|e| GHEK::MkSignature.into_error_with_cause(Box::new(e)))
            })
    }

    pub fn new_committer_sig(&self) -> Option<Result<Signature>> {
        self.committer
            .as_ref()
            .map(|c| {
                Signature::now(c.name, c.mail)
                    .map_err(|e| GHEK::MkSignature.into_error_with_cause(Box::new(e)))
            })
    }

    pub fn repository(&self) -> Result<&Repository> {
        self.repository.as_ref().ok_or(GHEK::MkRepo.into_error())
    }

    pub fn ensure_cfg_branch_is_checked_out(&self) -> HookResult<()> {
        use vcs::git::config::ensure_branch;

        let head = try!(self
                        .repository()
                        .and_then(|r| {
                            r.head().map_err_into(GHEK::HeadFetchError)
                        })
                        .map_err(Box::new)
                        .map_err(|e| HEK::HookExecutionError.into_error_with_cause(e)));

        // TODO: Fail if not on branch? hmmh... I'm not sure
        if head.is_branch() {
            return Err(GHEK::NotOnBranch.into_error())
                .map_err(Box::new)
                .map_err(|e| HEK::HookExecutionError.into_error_with_cause(e));
        }

        // Check out appropriate branch ... or fail
        match ensure_branch(self.config.as_ref()) {
            Ok(Some(s)) => {
                match head.name().map(|name| name == s) {
                    Some(b) => {
                        if b {
                            debug!("Branch already checked out.");
                            Ok(())
                        } else {
                            debug!("Branch not checked out.");
                            unimplemented!()
                        }
                    },

                    None => Err(GHEK::RepositoryBranchNameFetchingError.into_error())
                        .map_err_into(GHEK::RepositoryBranchError)
                        .map_err_into(GHEK::RepositoryError),
                }
            },
            Ok(None) => {
                debug!("No branch to checkout");
                Ok(())
            },

            Err(e) => Err(e).map_err_into(GHEK::RepositoryError),
        }
        .map_err(Box::new)
        .map_err(|e| HEK::HookExecutionError.into_error_with_cause(e))
    }

}

<|endoftext|>


<commit_before><commit_msg>Tidy up the modelview_quaternion function<commit_after><|endoftext|>


<commit_before>use std::iter::Peekable;
use std::num::ParseIntError;
use hyper::client::response::*;
use std::collections::HashMap;

use xml::reader::*;
use std::io::BufReader;
use std::fs::File;
use xml::reader::events::*;

/// generic Error for XML parsing
#[derive(Debug)]
pub struct XmlParseError(pub String);

impl XmlParseError {
	pub fn new(msg: &str) -> XmlParseError {
		XmlParseError(msg.to_string())
	}
}

/// syntactic sugar for the XML event stack we pass around
pub type XmlStack<'a> = Peekable<Events<'a, Response>>;

pub trait Peek {
    fn peek(&mut self) -> Option<&XmlEvent>;
}

pub trait Next {
	fn next(&mut self) -> Option<XmlEvent>;
}

// Wraps the Hyper Response type
pub struct XmlResponseFromAws<'b> {
	xml_stack: Peekable<Events<'b, Response>> // refactor to use XmlStack type?
}

// I cannot explain how these lifetimes work to a child, therefore I need to understand them better:
impl <'b>XmlResponseFromAws<'b> {
	pub fn new<'c>(stack: Peekable<Events<'b, Response>>) -> XmlResponseFromAws {
		XmlResponseFromAws {
			xml_stack: stack,
		}
	}
}

// Need peek and next implemented.
impl <'b>Peek for XmlResponseFromAws<'b> {
	fn peek(&mut self) -> Option<&XmlEvent> {
		return self.xml_stack.peek();
	}
}

impl <'b> Next for XmlResponseFromAws<'b> {
	fn next(&mut self) -> Option<XmlEvent> {
		return self.xml_stack.next();
	}
}

impl From<ParseIntError> for XmlParseError{
    fn from(_e:ParseIntError) -> XmlParseError { XmlParseError::new("ParseIntError") }
}

// Testing helper:
pub struct XmlResponseFromFile<'a> {
	xml_stack: Peekable<Events<'a, BufReader<File>>>,
}

// I cannot explain how these lifetimes work to a child, therefore I need to understand them better:
impl <'a>XmlResponseFromFile<'a> {
	pub fn new<'c>(my_stack: Peekable<Events<'a, BufReader<File>>>) -> XmlResponseFromFile {
		return XmlResponseFromFile { xml_stack: my_stack };
	}
}

// Need peek and next implemented.
impl <'b> Peek for XmlResponseFromFile <'b> {
	fn peek(&mut self) -> Option<&XmlEvent> {
		return self.xml_stack.peek();
	}
}

impl <'b> Next for XmlResponseFromFile <'b> {
	fn next(&mut self) -> Option<XmlEvent> {
		return self.xml_stack.next();
	}
}
// /testing helper

/// parse Some(String) if the next tag has the right name, otherwise None
pub fn optional_string_field<T: Peek + Next>(field_name: &str, stack: &mut T) -> Result<Option<String>, XmlParseError> {
	if try!(peek_at_name(stack)) == field_name {
		let val = try!(string_field(field_name, stack));
		Ok(Some(val))
	} else {
		Ok(None)
	}
}

/// return a string field with the right name or throw a parse error
pub fn string_field<T: Peek + Next>(name: &str, stack: &mut T) -> Result<String, XmlParseError> {
	try!(start_element(name, stack));
	let value = try!(characters(stack));
	try!(end_element(name, stack));
	Ok(value)
}

/// return some XML Characters
pub fn characters<T: Peek + Next>(stack: &mut T) -> Result<String, XmlParseError> {
	if let Some(XmlEvent::Characters(data)) = stack.next() {
		Ok(data.to_string())
	} else {
		Err(XmlParseError::new("Expected characters"))
	}
}

/// get the name of the current element in the stack.  throw a parse error if it's not a StartElement
pub fn peek_at_name<T: Peek + Next>(stack: &mut T) -> Result<String, XmlParseError> {
	let current = stack.peek();
	if let Some(&XmlEvent::StartElement{ref name, ..}) = current {
		Ok(name.local_name.to_string())
	} else {
		Ok("".to_string())
	}
}

/// consume a StartElement with a specific name or throw an XmlParseError
pub fn start_element<T: Peek + Next>(element_name: &str, stack: &mut T)  -> Result<HashMap<String, String>, XmlParseError> {
	let next = stack.next();
	if let Some(XmlEvent::StartElement { name, attributes, .. }) = next {
		if name.local_name != element_name {
			Err(XmlParseError::new(&format!("Expected {} got {}", element_name, name.local_name)))
		} else {
			let mut attr_map = HashMap::new();
			for attr in attributes {
				attr_map.insert(attr.name.local_name, attr.value);
			}
			Ok(attr_map)
		}
	} else {
		Err(XmlParseError::new(&format!("Expected StartElement {}", element_name)))
	}
}

/// consume an EndElement with a specific name or throw an XmlParseError
pub fn end_element<T: Peek + Next>(element_name: &str, stack: &mut T)  -> Result<(), XmlParseError> {
	let next = stack.next();
	if let Some(XmlEvent::EndElement { name, .. }) = next {
		if name.local_name != element_name {
			Err(XmlParseError::new(&format!("Expected {} got {}", element_name, name.local_name)))
		} else {
			Ok(())
		}
	}else {
		Err(XmlParseError::new(&format!("Expected EndElement {} got {:?}", element_name, next)))
	}
}

#[cfg(test)]
mod tests {
    use super::*;
	use xml::reader::*;
	use std::io::BufReader;
	use std::fs::File;

	#[test]
	fn peek_at_name_happy_path() {
	    let file = File::open("tests/sample-data/list_queues_with_queue.xml").unwrap();
	    let file = BufReader::new(file);
	    let mut my_parser  = EventReader::new(file);
	    let my_stack = my_parser.events().peekable();
	    let mut reader = XmlResponseFromFile::new(my_stack);

	    loop {
	        reader.next();
	        match peek_at_name(&mut reader) {
	            Ok(data) => {
	                // println!("Got {}", data);
	                if data == "QueueUrl" {
	                    return;
	                }
	            }
	            Err(_) => panic!("Couldn't peek at name")
	        }
	    }
	}

	#[test]
	fn start_element_happy_path() {
	    let file = File::open("tests/sample-data/list_queues_with_queue.xml").unwrap();
	    let file = BufReader::new(file);
	    let mut my_parser  = EventReader::new(file);
	    let my_stack = my_parser.events().peekable();
	    let mut reader = XmlResponseFromFile::new(my_stack);

	    // skip two leading fields since we ignore them (xml declaration, return type declaration)
	    reader.next();
	    reader.next();

	    match start_element("ListQueuesResult", &mut reader) {
	        Ok(_) => (),
	        Err(_) => panic!("Couldn't find start element")
	    }
	}

	#[test]
	fn string_field_happy_path() {
	    let file = File::open("tests/sample-data/list_queues_with_queue.xml").unwrap();
	    let file = BufReader::new(file);
	    let mut my_parser  = EventReader::new(file);
	    let my_stack = my_parser.events().peekable();
	    let mut reader = XmlResponseFromFile::new(my_stack);

	    // skip two leading fields since we ignore them (xml declaration, return type declaration)
	    reader.next();
	    reader.next();

	    reader.next(); // reader now at ListQueuesResult

	    // now we're set up to use string:
	    let my_chars = string_field("QueueUrl", &mut reader).unwrap();
		assert_eq!(my_chars, "https://sqs.us-east-1.amazonaws.com/347452556413/testqueue")
	}

	#[test]
	fn end_element_happy_path() {
	    let file = File::open("tests/sample-data/list_queues_with_queue.xml").unwrap();
	    let file = BufReader::new(file);
	    let mut my_parser  = EventReader::new(file);
	    let my_stack = my_parser.events().peekable();
	    let mut reader = XmlResponseFromFile::new(my_stack);

	    // skip two leading fields since we ignore them (xml declaration, return type declaration)
	    reader.next();
	    reader.next();

	    // TODO: this is fragile and not good: do some looping to find end element?
	    // But need to do it without being dependent on peek_at_name.
	    reader.next();
	    reader.next();
	    reader.next();
	    reader.next();

	    match end_element("ListQueuesResult", &mut reader) {
	        Ok(_) => (),
	        Err(_) => panic!("Couldn't find end element")
	    }
	}

}
<commit_msg>Minor cleanups on xmlutil.<commit_after>use std::iter::Peekable;
use std::num::ParseIntError;
use hyper::client::response::*;
use std::collections::HashMap;
use xml::reader::*;
use std::io::BufReader;
use std::fs::File;
use xml::reader::events::*;

/// generic Error for XML parsing
#[derive(Debug)]
pub struct XmlParseError(pub String);

impl XmlParseError {
	pub fn new(msg: &str) -> XmlParseError {
		XmlParseError(msg.to_string())
	}
}

/// syntactic sugar for the XML event stack we pass around
pub type XmlStack<'a> = Peekable<Events<'a, Response>>;

pub trait Peek {
    fn peek(&mut self) -> Option<&XmlEvent>;
}

pub trait Next {
	fn next(&mut self) -> Option<XmlEvent>;
}

// Wraps the Hyper Response type
pub struct XmlResponseFromAws<'b> {
	xml_stack: Peekable<Events<'b, Response>> // refactor to use XmlStack type?
}

impl <'b>XmlResponseFromAws<'b> {
	pub fn new<'c>(stack: Peekable<Events<'b, Response>>) -> XmlResponseFromAws {
		XmlResponseFromAws {
			xml_stack: stack,
		}
	}
}

impl <'b>Peek for XmlResponseFromAws<'b> {
	fn peek(&mut self) -> Option<&XmlEvent> {
		return self.xml_stack.peek();
	}
}

impl <'b> Next for XmlResponseFromAws<'b> {
	fn next(&mut self) -> Option<XmlEvent> {
		return self.xml_stack.next();
	}
}

impl From<ParseIntError> for XmlParseError{
    fn from(_e:ParseIntError) -> XmlParseError { XmlParseError::new("ParseIntError") }
}

// Testing helper:
pub struct XmlResponseFromFile<'a> {
	xml_stack: Peekable<Events<'a, BufReader<File>>>,
}

// I cannot explain how these lifetimes work to a child, therefore I need to understand them better:
impl <'a>XmlResponseFromFile<'a> {
	pub fn new<'c>(my_stack: Peekable<Events<'a, BufReader<File>>>) -> XmlResponseFromFile {
		return XmlResponseFromFile { xml_stack: my_stack };
	}
}

// Need peek and next implemented.
impl <'b> Peek for XmlResponseFromFile <'b> {
	fn peek(&mut self) -> Option<&XmlEvent> {
		return self.xml_stack.peek();
	}
}

impl <'b> Next for XmlResponseFromFile <'b> {
	fn next(&mut self) -> Option<XmlEvent> {
		return self.xml_stack.next();
	}
}
// /testing helper

/// parse Some(String) if the next tag has the right name, otherwise None
pub fn optional_string_field<T: Peek + Next>(field_name: &str, stack: &mut T) -> Result<Option<String>, XmlParseError> {
	if try!(peek_at_name(stack)) == field_name {
		let val = try!(string_field(field_name, stack));
		Ok(Some(val))
	} else {
		Ok(None)
	}
}

/// return a string field with the right name or throw a parse error
pub fn string_field<T: Peek + Next>(name: &str, stack: &mut T) -> Result<String, XmlParseError> {
	try!(start_element(name, stack));
	let value = try!(characters(stack));
	try!(end_element(name, stack));
	Ok(value)
}

/// return some XML Characters
pub fn characters<T: Peek + Next>(stack: &mut T) -> Result<String, XmlParseError> {
	if let Some(XmlEvent::Characters(data)) = stack.next() {
		Ok(data.to_string())
	} else {
		Err(XmlParseError::new("Expected characters"))
	}
}

/// get the name of the current element in the stack.  throw a parse error if it's not a StartElement
pub fn peek_at_name<T: Peek + Next>(stack: &mut T) -> Result<String, XmlParseError> {
	let current = stack.peek();
	if let Some(&XmlEvent::StartElement{ref name, ..}) = current {
		Ok(name.local_name.to_string())
	} else {
		Ok("".to_string())
	}
}

/// consume a StartElement with a specific name or throw an XmlParseError
pub fn start_element<T: Peek + Next>(element_name: &str, stack: &mut T)  -> Result<HashMap<String, String>, XmlParseError> {
	let next = stack.next();
	if let Some(XmlEvent::StartElement { name, attributes, .. }) = next {
		if name.local_name != element_name {
			Err(XmlParseError::new(&format!("Expected {} got {}", element_name, name.local_name)))
		} else {
			let mut attr_map = HashMap::new();
			for attr in attributes {
				attr_map.insert(attr.name.local_name, attr.value);
			}
			Ok(attr_map)
		}
	} else {
		Err(XmlParseError::new(&format!("Expected StartElement {}", element_name)))
	}
}

/// consume an EndElement with a specific name or throw an XmlParseError
pub fn end_element<T: Peek + Next>(element_name: &str, stack: &mut T)  -> Result<(), XmlParseError> {
	let next = stack.next();
	if let Some(XmlEvent::EndElement { name, .. }) = next {
		if name.local_name != element_name {
			Err(XmlParseError::new(&format!("Expected {} got {}", element_name, name.local_name)))
		} else {
			Ok(())
		}
	}else {
		Err(XmlParseError::new(&format!("Expected EndElement {} got {:?}", element_name, next)))
	}
}

#[cfg(test)]
mod tests {
    use super::*;
	use xml::reader::*;
	use std::io::BufReader;
	use std::fs::File;

	#[test]
	fn peek_at_name_happy_path() {
	    let file = File::open("tests/sample-data/list_queues_with_queue.xml").unwrap();
	    let file = BufReader::new(file);
	    let mut my_parser  = EventReader::new(file);
	    let my_stack = my_parser.events().peekable();
	    let mut reader = XmlResponseFromFile::new(my_stack);

	    loop {
	        reader.next();
	        match peek_at_name(&mut reader) {
	            Ok(data) => {
	                // println!("Got {}", data);
	                if data == "QueueUrl" {
	                    return;
	                }
	            }
	            Err(_) => panic!("Couldn't peek at name")
	        }
	    }
	}

	#[test]
	fn start_element_happy_path() {
	    let file = File::open("tests/sample-data/list_queues_with_queue.xml").unwrap();
	    let file = BufReader::new(file);
	    let mut my_parser  = EventReader::new(file);
	    let my_stack = my_parser.events().peekable();
	    let mut reader = XmlResponseFromFile::new(my_stack);

	    // skip two leading fields since we ignore them (xml declaration, return type declaration)
	    reader.next();
	    reader.next();

	    match start_element("ListQueuesResult", &mut reader) {
	        Ok(_) => (),
	        Err(_) => panic!("Couldn't find start element")
	    }
	}

	#[test]
	fn string_field_happy_path() {
	    let file = File::open("tests/sample-data/list_queues_with_queue.xml").unwrap();
	    let file = BufReader::new(file);
	    let mut my_parser  = EventReader::new(file);
	    let my_stack = my_parser.events().peekable();
	    let mut reader = XmlResponseFromFile::new(my_stack);

	    // skip two leading fields since we ignore them (xml declaration, return type declaration)
	    reader.next();
	    reader.next();

	    reader.next(); // reader now at ListQueuesResult

	    // now we're set up to use string:
	    let my_chars = string_field("QueueUrl", &mut reader).unwrap();
		assert_eq!(my_chars, "https://sqs.us-east-1.amazonaws.com/347452556413/testqueue")
	}

	#[test]
	fn end_element_happy_path() {
	    let file = File::open("tests/sample-data/list_queues_with_queue.xml").unwrap();
	    let file = BufReader::new(file);
	    let mut my_parser  = EventReader::new(file);
	    let my_stack = my_parser.events().peekable();
	    let mut reader = XmlResponseFromFile::new(my_stack);

	    // skip two leading fields since we ignore them (xml declaration, return type declaration)
	    reader.next();
	    reader.next();

	    // TODO: this is fragile and not good: do some looping to find end element?
	    // But need to do it without being dependent on peek_at_name.
	    reader.next();
	    reader.next();
	    reader.next();
	    reader.next();

	    match end_element("ListQueuesResult", &mut reader) {
	        Ok(_) => (),
	        Err(_) => panic!("Couldn't find end element")
	    }
	}

}
<|endoftext|>


<commit_before><commit_msg>Perform velocity resolution before interpenetration<commit_after><|endoftext|>


<commit_before><commit_msg>Basic auth.<commit_after><|endoftext|>


<commit_before><commit_msg>add inherent-method-collision test<commit_after>// Test that we do NOT warn for inherent methods invoked via `T::` form.
//
// check-pass

#![deny(future_prelude_collision)]

pub struct MySeq {}

impl MySeq {
    pub fn from_iter(_: impl IntoIterator<Item = u32>) {}
}

fn main() {
    MySeq::from_iter(Some(22));
}
<|endoftext|>


<commit_before><commit_msg>Started om mini-DOM example.<commit_after>extern crate linjs;
#[macro_use] extern crate linjs_derive;

use linjs::CanAlloc;
use linjs::CanInitialize;
use linjs::JSContext;
use linjs::JSManaged;
use linjs::JSManageable;
use linjs::JSRunnable;

use std::marker::PhantomData;

// -------------------------------------------------------------------

type Window<'a, C> = JSManaged<'a, C, NativeWindow<'a, C>>;

#[derive(JSManageable)]
struct NativeWindow<'a, C> {
    console: Console<'a, C>,
    body: Element<'a, C>,
}

// -------------------------------------------------------------------

type Console<'a, C> = JSManaged<'a, C, NativeConsole<'a, C>>;

#[derive(JSManageable)]
struct NativeConsole<'a, C>(PhantomData<(&'a(), C)>);

fn new_console<'a, C, S>(cx: &'a mut JSContext<S>) -> Console<'a, C> where
    C: 'a,
    S: CanAlloc<C>,
{
    cx.manage(NativeConsole(PhantomData))
}

// -------------------------------------------------------------------

type Element<'a, C> = JSManaged<'a, C, NativeElement<'a, C>>;

#[derive(JSManageable)]
struct NativeElement<'a, C> {
    parent: Option<Element<'a, C>>,
    children: Vec<Element<'a, C>>,
}

fn new_element<'a, C, S>(cx: &'a mut JSContext<S>) -> Element<'a, C> where
    S: CanAlloc<C>,
    C: 'a,
{
    cx.manage(NativeElement {
        parent: None,
        children: Vec::new(),
    })
}

// -------------------------------------------------------------------

struct Main;

impl JSRunnable for Main {
    fn run<C, S>(self, cx: JSContext<S>) where S: CanInitialize<C> {
        println!("Hello, world.");
    }
}

fn main() {
    Main.start();
}
<|endoftext|>


<commit_before><commit_msg>Return proper errors from UtxoSet::update<commit_after><|endoftext|>


<commit_before>// Copyright 2017 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.

use std::fs;
use std::env;
use std::path::PathBuf;
use std::process::Command;

use Mode;
use Compiler;
use builder::{Step, RunConfig, ShouldRun, Builder};
use util::{copy, exe, add_lib_path};
use compile::{self, libtest_stamp, libstd_stamp, librustc_stamp};
use native;
use channel::GitInfo;
use cache::Interned;

#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub struct CleanTools {
    pub compiler: Compiler,
    pub target: Interned<String>,
    pub mode: Mode,
}

impl Step for CleanTools {
    type Output = ();

    fn should_run(run: ShouldRun) -> ShouldRun {
        run.never()
    }

    /// Build a tool in `src/tools`
    ///
    /// This will build the specified tool with the specified `host` compiler in
    /// `stage` into the normal cargo output directory.
    fn run(self, builder: &Builder) {
        let build = builder.build;
        let compiler = self.compiler;
        let target = self.target;
        let mode = self.mode;

        let stamp = match mode {
            Mode::Libstd => libstd_stamp(build, compiler, target),
            Mode::Libtest => libtest_stamp(build, compiler, target),
            Mode::Librustc => librustc_stamp(build, compiler, target),
            _ => panic!(),
        };
        let out_dir = build.cargo_out(compiler, Mode::Tool, target);
        build.clear_if_dirty(&out_dir, &stamp);
    }
}

#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
struct ToolBuild {
    compiler: Compiler,
    target: Interned<String>,
    tool: &'static str,
    mode: Mode,
}

impl Step for ToolBuild {
    type Output = PathBuf;

    fn should_run(run: ShouldRun) -> ShouldRun {
        run.never()
    }

    /// Build a tool in `src/tools`
    ///
    /// This will build the specified tool with the specified `host` compiler in
    /// `stage` into the normal cargo output directory.
    fn run(self, builder: &Builder) -> PathBuf {
        let build = builder.build;
        let compiler = self.compiler;
        let target = self.target;
        let tool = self.tool;

        match self.mode {
            Mode::Libstd => builder.ensure(compile::Std { compiler, target }),
            Mode::Libtest => builder.ensure(compile::Test { compiler, target }),
            Mode::Librustc => builder.ensure(compile::Rustc { compiler, target }),
            Mode::Tool => panic!("unexpected Mode::Tool for tool build")
        }

        let _folder = build.fold_output(|| format!("stage{}-{}", compiler.stage, tool));
        println!("Building stage{} tool {} ({})", compiler.stage, tool, target);

        let mut cargo = prepare_tool_cargo(builder, compiler, target, tool);
        build.run(&mut cargo);
        build.cargo_out(compiler, Mode::Tool, target).join(exe(tool, &compiler.host))
    }
}

fn prepare_tool_cargo(
    builder: &Builder,
    compiler: Compiler,
    target: Interned<String>,
    tool: &'static str,
) -> Command {
    let build = builder.build;
    let mut cargo = builder.cargo(compiler, Mode::Tool, target, "build");
    let dir = build.src.join("src/tools").join(tool);
    cargo.arg("--manifest-path").arg(dir.join("Cargo.toml"));

    // We don't want to build tools dynamically as they'll be running across
    // stages and such and it's just easier if they're not dynamically linked.
    cargo.env("RUSTC_NO_PREFER_DYNAMIC", "1");

    if let Some(dir) = build.openssl_install_dir(target) {
        cargo.env("OPENSSL_STATIC", "1");
        cargo.env("OPENSSL_DIR", dir);
        cargo.env("LIBZ_SYS_STATIC", "1");
    }

    cargo.env("CFG_RELEASE_CHANNEL", &build.config.channel);

    let info = GitInfo::new(&build.config, &dir);
    if let Some(sha) = info.sha() {
        cargo.env("CFG_COMMIT_HASH", sha);
    }
    if let Some(sha_short) = info.sha_short() {
        cargo.env("CFG_SHORT_COMMIT_HASH", sha_short);
    }
    if let Some(date) = info.commit_date() {
        cargo.env("CFG_COMMIT_DATE", date);
    }
    cargo
}

macro_rules! tool {
    ($($name:ident, $path:expr, $tool_name:expr, $mode:expr;)+) => {
        #[derive(Copy, Clone)]
        pub enum Tool {
            $(
                $name,
            )+
        }

        impl<'a> Builder<'a> {
            pub fn tool_exe(&self, tool: Tool) -> PathBuf {
                match tool {
                    $(Tool::$name =>
                        self.ensure($name {
                            compiler: self.compiler(0, self.build.build),
                            target: self.build.build,
                        }),
                    )+
                }
            }
        }

        $(
            #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
        pub struct $name {
            pub compiler: Compiler,
            pub target: Interned<String>,
        }

        impl Step for $name {
            type Output = PathBuf;

            fn should_run(run: ShouldRun) -> ShouldRun {
                run.path($path)
            }

            fn make_run(run: RunConfig) {
                run.builder.ensure($name {
                    compiler: run.builder.compiler(run.builder.top_stage, run.builder.build.build),
                    target: run.target,
                });
            }

            fn run(self, builder: &Builder) -> PathBuf {
                builder.ensure(ToolBuild {
                    compiler: self.compiler,
                    target: self.target,
                    tool: $tool_name,
                    mode: $mode,
                })
            }
        }
        )+
    }
}

tool!(
    Rustbook, "src/tools/rustbook", "rustbook", Mode::Librustc;
    ErrorIndex, "src/tools/error_index_generator", "error_index_generator", Mode::Librustc;
    UnstableBookGen, "src/tools/unstable-book-gen", "unstable-book-gen", Mode::Libstd;
    Tidy, "src/tools/tidy", "tidy", Mode::Libstd;
    Linkchecker, "src/tools/linkchecker", "linkchecker", Mode::Libstd;
    CargoTest, "src/tools/cargotest", "cargotest", Mode::Libstd;
    Compiletest, "src/tools/compiletest", "compiletest", Mode::Libtest;
    BuildManifest, "src/tools/build-manifest", "build-manifest", Mode::Libstd;
    RemoteTestClient, "src/tools/remote-test-client", "remote-test-client", Mode::Libstd;
    RustInstaller, "src/tools/rust-installer", "rust-installer", Mode::Libstd;
);

#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub struct RemoteTestServer {
    pub compiler: Compiler,
    pub target: Interned<String>,
}

impl Step for RemoteTestServer {
    type Output = PathBuf;

    fn should_run(run: ShouldRun) -> ShouldRun {
        run.path("src/tools/remote-test-server")
    }

    fn make_run(run: RunConfig) {
        run.builder.ensure(RemoteTestServer {
            compiler: run.builder.compiler(run.builder.top_stage, run.builder.build.build),
            target: run.target,
        });
    }

    fn run(self, builder: &Builder) -> PathBuf {
        builder.ensure(ToolBuild {
            compiler: self.compiler,
            target: self.target,
            tool: "remote-test-server",
            mode: Mode::Libstd,
        })
    }
}

#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub struct Rustdoc {
    pub host: Interned<String>,
}

impl Step for Rustdoc {
    type Output = PathBuf;
    const DEFAULT: bool = true;
    const ONLY_HOSTS: bool = true;

    fn should_run(run: ShouldRun) -> ShouldRun {
        run.path("src/tools/rustdoc")
    }

    fn make_run(run: RunConfig) {
        run.builder.ensure(Rustdoc {
            host: run.host,
        });
    }

    fn run(self, builder: &Builder) -> PathBuf {
        let build = builder.build;
        let target_compiler = builder.compiler(builder.top_stage, self.host);
        let target = target_compiler.host;
        let build_compiler = if target_compiler.stage == 0 {
            builder.compiler(0, builder.build.build)
        } else if target_compiler.stage >= 2 {
            // Past stage 2, we consider the compiler to be ABI-compatible and hence capable of
            // building rustdoc itself.
            builder.compiler(target_compiler.stage, builder.build.build)
        } else {
            // Similar to `compile::Assemble`, build with the previous stage's compiler. Otherwise
            // we'd have stageN/bin/rustc and stageN/bin/rustdoc be effectively different stage
            // compilers, which isn't what we want.
            builder.compiler(target_compiler.stage - 1, builder.build.build)
        };

        builder.ensure(compile::Rustc { compiler: build_compiler, target });

        let _folder = build.fold_output(|| format!("stage{}-rustdoc", target_compiler.stage));
        println!("Building rustdoc for stage{} ({})", target_compiler.stage, target_compiler.host);

        let mut cargo = prepare_tool_cargo(builder, build_compiler, target, "rustdoc");
        build.run(&mut cargo);
        // Cargo adds a number of paths to the dylib search path on windows, which results in
        // the wrong rustdoc being executed. To avoid the conflicting rustdocs, we name the "tool"
        // rustdoc a different name.
        let tool_rustdoc = build.cargo_out(build_compiler, Mode::Tool, target)
            .join(exe("rustdoc-tool-binary", &target_compiler.host));

        // don't create a stage0-sysroot/bin directory.
        if target_compiler.stage > 0 {
            let sysroot = builder.sysroot(target_compiler);
            let bindir = sysroot.join("bin");
            t!(fs::create_dir_all(&bindir));
            let bin_rustdoc = bindir.join(exe("rustdoc", &*target_compiler.host));
            let _ = fs::remove_file(&bin_rustdoc);
            copy(&tool_rustdoc, &bin_rustdoc);
            bin_rustdoc
        } else {
            tool_rustdoc
        }
    }
}

#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub struct Cargo {
    pub compiler: Compiler,
    pub target: Interned<String>,
}

impl Step for Cargo {
    type Output = PathBuf;
    const DEFAULT: bool = true;
    const ONLY_HOSTS: bool = true;

    fn should_run(run: ShouldRun) -> ShouldRun {
        let builder = run.builder;
        run.path("src/tools/cargo").default_condition(builder.build.config.extended)
    }

    fn make_run(run: RunConfig) {
        run.builder.ensure(Cargo {
            compiler: run.builder.compiler(run.builder.top_stage, run.builder.build.build),
            target: run.target,
        });
    }

    fn run(self, builder: &Builder) -> PathBuf {
        builder.ensure(native::Openssl {
            target: self.target,
        });
        // Cargo depends on procedural macros, which requires a full host
        // compiler to be available, so we need to depend on that.
        builder.ensure(compile::Rustc {
            compiler: self.compiler,
            target: builder.build.build,
        });
        builder.ensure(ToolBuild {
            compiler: self.compiler,
            target: self.target,
            tool: "cargo",
            mode: Mode::Librustc,
        })
    }
}

#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub struct Rls {
    pub compiler: Compiler,
    pub target: Interned<String>,
}

impl Step for Rls {
    type Output = PathBuf;
    const DEFAULT: bool = true;
    const ONLY_HOSTS: bool = true;

    fn should_run(run: ShouldRun) -> ShouldRun {
        let builder = run.builder;
        run.path("src/tools/rls").default_condition(builder.build.config.extended)
    }

    fn make_run(run: RunConfig) {
        run.builder.ensure(Rls {
            compiler: run.builder.compiler(run.builder.top_stage, run.builder.build.build),
            target: run.target,
        });
    }

    fn run(self, builder: &Builder) -> PathBuf {
        builder.ensure(native::Openssl {
            target: self.target,
        });
        // RLS depends on procedural macros, which requires a full host
        // compiler to be available, so we need to depend on that.
        builder.ensure(compile::Rustc {
            compiler: self.compiler,
            target: builder.build.build,
        });
        builder.ensure(ToolBuild {
            compiler: self.compiler,
            target: self.target,
            tool: "rls",
            mode: Mode::Librustc,
        })
    }
}

impl<'a> Builder<'a> {
    /// Get a `Command` which is ready to run `tool` in `stage` built for
    /// `host`.
    pub fn tool_cmd(&self, tool: Tool) -> Command {
        let mut cmd = Command::new(self.tool_exe(tool));
        let compiler = self.compiler(0, self.build.build);
        self.prepare_tool_cmd(compiler, &mut cmd);
        cmd
    }

    /// Prepares the `cmd` provided to be able to run the `compiler` provided.
    ///
    /// Notably this munges the dynamic library lookup path to point to the
    /// right location to run `compiler`.
    fn prepare_tool_cmd(&self, compiler: Compiler, cmd: &mut Command) {
        let host = &compiler.host;
        let mut paths: Vec<PathBuf> = vec![
            PathBuf::from(&self.sysroot_libdir(compiler, compiler.host)),
            self.cargo_out(compiler, Mode::Tool, *host).join("deps"),
        ];

        // On MSVC a tool may invoke a C compiler (e.g. compiletest in run-make
        // mode) and that C compiler may need some extra PATH modification. Do
        // so here.
        if compiler.host.contains("msvc") {
            let curpaths = env::var_os("PATH").unwrap_or_default();
            let curpaths = env::split_paths(&curpaths).collect::<Vec<_>>();
            for &(ref k, ref v) in self.cc[&compiler.host].0.env() {
                if k != "PATH" {
                    continue
                }
                for path in env::split_paths(v) {
                    if !curpaths.contains(&path) {
                        paths.push(path);
                    }
                }
            }
        }
        add_lib_path(paths, cmd);
    }
}
<commit_msg>Set CFG_VERSION env var for tool builds<commit_after>// Copyright 2017 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.

use std::fs;
use std::env;
use std::path::PathBuf;
use std::process::Command;

use Mode;
use Compiler;
use builder::{Step, RunConfig, ShouldRun, Builder};
use util::{copy, exe, add_lib_path};
use compile::{self, libtest_stamp, libstd_stamp, librustc_stamp};
use native;
use channel::GitInfo;
use cache::Interned;

#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub struct CleanTools {
    pub compiler: Compiler,
    pub target: Interned<String>,
    pub mode: Mode,
}

impl Step for CleanTools {
    type Output = ();

    fn should_run(run: ShouldRun) -> ShouldRun {
        run.never()
    }

    /// Build a tool in `src/tools`
    ///
    /// This will build the specified tool with the specified `host` compiler in
    /// `stage` into the normal cargo output directory.
    fn run(self, builder: &Builder) {
        let build = builder.build;
        let compiler = self.compiler;
        let target = self.target;
        let mode = self.mode;

        let stamp = match mode {
            Mode::Libstd => libstd_stamp(build, compiler, target),
            Mode::Libtest => libtest_stamp(build, compiler, target),
            Mode::Librustc => librustc_stamp(build, compiler, target),
            _ => panic!(),
        };
        let out_dir = build.cargo_out(compiler, Mode::Tool, target);
        build.clear_if_dirty(&out_dir, &stamp);
    }
}

#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
struct ToolBuild {
    compiler: Compiler,
    target: Interned<String>,
    tool: &'static str,
    mode: Mode,
}

impl Step for ToolBuild {
    type Output = PathBuf;

    fn should_run(run: ShouldRun) -> ShouldRun {
        run.never()
    }

    /// Build a tool in `src/tools`
    ///
    /// This will build the specified tool with the specified `host` compiler in
    /// `stage` into the normal cargo output directory.
    fn run(self, builder: &Builder) -> PathBuf {
        let build = builder.build;
        let compiler = self.compiler;
        let target = self.target;
        let tool = self.tool;

        match self.mode {
            Mode::Libstd => builder.ensure(compile::Std { compiler, target }),
            Mode::Libtest => builder.ensure(compile::Test { compiler, target }),
            Mode::Librustc => builder.ensure(compile::Rustc { compiler, target }),
            Mode::Tool => panic!("unexpected Mode::Tool for tool build")
        }

        let _folder = build.fold_output(|| format!("stage{}-{}", compiler.stage, tool));
        println!("Building stage{} tool {} ({})", compiler.stage, tool, target);

        let mut cargo = prepare_tool_cargo(builder, compiler, target, tool);
        build.run(&mut cargo);
        build.cargo_out(compiler, Mode::Tool, target).join(exe(tool, &compiler.host))
    }
}

fn prepare_tool_cargo(
    builder: &Builder,
    compiler: Compiler,
    target: Interned<String>,
    tool: &'static str,
) -> Command {
    let build = builder.build;
    let mut cargo = builder.cargo(compiler, Mode::Tool, target, "build");
    let dir = build.src.join("src/tools").join(tool);
    cargo.arg("--manifest-path").arg(dir.join("Cargo.toml"));

    // We don't want to build tools dynamically as they'll be running across
    // stages and such and it's just easier if they're not dynamically linked.
    cargo.env("RUSTC_NO_PREFER_DYNAMIC", "1");

    if let Some(dir) = build.openssl_install_dir(target) {
        cargo.env("OPENSSL_STATIC", "1");
        cargo.env("OPENSSL_DIR", dir);
        cargo.env("LIBZ_SYS_STATIC", "1");
    }

    cargo.env("CFG_RELEASE_CHANNEL", &build.config.channel);
    cargo.env("CFG_VERSION", build.rust_version());

    let info = GitInfo::new(&build.config, &dir);
    if let Some(sha) = info.sha() {
        cargo.env("CFG_COMMIT_HASH", sha);
    }
    if let Some(sha_short) = info.sha_short() {
        cargo.env("CFG_SHORT_COMMIT_HASH", sha_short);
    }
    if let Some(date) = info.commit_date() {
        cargo.env("CFG_COMMIT_DATE", date);
    }
    cargo
}

macro_rules! tool {
    ($($name:ident, $path:expr, $tool_name:expr, $mode:expr;)+) => {
        #[derive(Copy, Clone)]
        pub enum Tool {
            $(
                $name,
            )+
        }

        impl<'a> Builder<'a> {
            pub fn tool_exe(&self, tool: Tool) -> PathBuf {
                match tool {
                    $(Tool::$name =>
                        self.ensure($name {
                            compiler: self.compiler(0, self.build.build),
                            target: self.build.build,
                        }),
                    )+
                }
            }
        }

        $(
            #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
        pub struct $name {
            pub compiler: Compiler,
            pub target: Interned<String>,
        }

        impl Step for $name {
            type Output = PathBuf;

            fn should_run(run: ShouldRun) -> ShouldRun {
                run.path($path)
            }

            fn make_run(run: RunConfig) {
                run.builder.ensure($name {
                    compiler: run.builder.compiler(run.builder.top_stage, run.builder.build.build),
                    target: run.target,
                });
            }

            fn run(self, builder: &Builder) -> PathBuf {
                builder.ensure(ToolBuild {
                    compiler: self.compiler,
                    target: self.target,
                    tool: $tool_name,
                    mode: $mode,
                })
            }
        }
        )+
    }
}

tool!(
    Rustbook, "src/tools/rustbook", "rustbook", Mode::Librustc;
    ErrorIndex, "src/tools/error_index_generator", "error_index_generator", Mode::Librustc;
    UnstableBookGen, "src/tools/unstable-book-gen", "unstable-book-gen", Mode::Libstd;
    Tidy, "src/tools/tidy", "tidy", Mode::Libstd;
    Linkchecker, "src/tools/linkchecker", "linkchecker", Mode::Libstd;
    CargoTest, "src/tools/cargotest", "cargotest", Mode::Libstd;
    Compiletest, "src/tools/compiletest", "compiletest", Mode::Libtest;
    BuildManifest, "src/tools/build-manifest", "build-manifest", Mode::Libstd;
    RemoteTestClient, "src/tools/remote-test-client", "remote-test-client", Mode::Libstd;
    RustInstaller, "src/tools/rust-installer", "rust-installer", Mode::Libstd;
);

#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub struct RemoteTestServer {
    pub compiler: Compiler,
    pub target: Interned<String>,
}

impl Step for RemoteTestServer {
    type Output = PathBuf;

    fn should_run(run: ShouldRun) -> ShouldRun {
        run.path("src/tools/remote-test-server")
    }

    fn make_run(run: RunConfig) {
        run.builder.ensure(RemoteTestServer {
            compiler: run.builder.compiler(run.builder.top_stage, run.builder.build.build),
            target: run.target,
        });
    }

    fn run(self, builder: &Builder) -> PathBuf {
        builder.ensure(ToolBuild {
            compiler: self.compiler,
            target: self.target,
            tool: "remote-test-server",
            mode: Mode::Libstd,
        })
    }
}

#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub struct Rustdoc {
    pub host: Interned<String>,
}

impl Step for Rustdoc {
    type Output = PathBuf;
    const DEFAULT: bool = true;
    const ONLY_HOSTS: bool = true;

    fn should_run(run: ShouldRun) -> ShouldRun {
        run.path("src/tools/rustdoc")
    }

    fn make_run(run: RunConfig) {
        run.builder.ensure(Rustdoc {
            host: run.host,
        });
    }

    fn run(self, builder: &Builder) -> PathBuf {
        let build = builder.build;
        let target_compiler = builder.compiler(builder.top_stage, self.host);
        let target = target_compiler.host;
        let build_compiler = if target_compiler.stage == 0 {
            builder.compiler(0, builder.build.build)
        } else if target_compiler.stage >= 2 {
            // Past stage 2, we consider the compiler to be ABI-compatible and hence capable of
            // building rustdoc itself.
            builder.compiler(target_compiler.stage, builder.build.build)
        } else {
            // Similar to `compile::Assemble`, build with the previous stage's compiler. Otherwise
            // we'd have stageN/bin/rustc and stageN/bin/rustdoc be effectively different stage
            // compilers, which isn't what we want.
            builder.compiler(target_compiler.stage - 1, builder.build.build)
        };

        builder.ensure(compile::Rustc { compiler: build_compiler, target });

        let _folder = build.fold_output(|| format!("stage{}-rustdoc", target_compiler.stage));
        println!("Building rustdoc for stage{} ({})", target_compiler.stage, target_compiler.host);

        let mut cargo = prepare_tool_cargo(builder, build_compiler, target, "rustdoc");
        build.run(&mut cargo);
        // Cargo adds a number of paths to the dylib search path on windows, which results in
        // the wrong rustdoc being executed. To avoid the conflicting rustdocs, we name the "tool"
        // rustdoc a different name.
        let tool_rustdoc = build.cargo_out(build_compiler, Mode::Tool, target)
            .join(exe("rustdoc-tool-binary", &target_compiler.host));

        // don't create a stage0-sysroot/bin directory.
        if target_compiler.stage > 0 {
            let sysroot = builder.sysroot(target_compiler);
            let bindir = sysroot.join("bin");
            t!(fs::create_dir_all(&bindir));
            let bin_rustdoc = bindir.join(exe("rustdoc", &*target_compiler.host));
            let _ = fs::remove_file(&bin_rustdoc);
            copy(&tool_rustdoc, &bin_rustdoc);
            bin_rustdoc
        } else {
            tool_rustdoc
        }
    }
}

#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub struct Cargo {
    pub compiler: Compiler,
    pub target: Interned<String>,
}

impl Step for Cargo {
    type Output = PathBuf;
    const DEFAULT: bool = true;
    const ONLY_HOSTS: bool = true;

    fn should_run(run: ShouldRun) -> ShouldRun {
        let builder = run.builder;
        run.path("src/tools/cargo").default_condition(builder.build.config.extended)
    }

    fn make_run(run: RunConfig) {
        run.builder.ensure(Cargo {
            compiler: run.builder.compiler(run.builder.top_stage, run.builder.build.build),
            target: run.target,
        });
    }

    fn run(self, builder: &Builder) -> PathBuf {
        builder.ensure(native::Openssl {
            target: self.target,
        });
        // Cargo depends on procedural macros, which requires a full host
        // compiler to be available, so we need to depend on that.
        builder.ensure(compile::Rustc {
            compiler: self.compiler,
            target: builder.build.build,
        });
        builder.ensure(ToolBuild {
            compiler: self.compiler,
            target: self.target,
            tool: "cargo",
            mode: Mode::Librustc,
        })
    }
}

#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub struct Rls {
    pub compiler: Compiler,
    pub target: Interned<String>,
}

impl Step for Rls {
    type Output = PathBuf;
    const DEFAULT: bool = true;
    const ONLY_HOSTS: bool = true;

    fn should_run(run: ShouldRun) -> ShouldRun {
        let builder = run.builder;
        run.path("src/tools/rls").default_condition(builder.build.config.extended)
    }

    fn make_run(run: RunConfig) {
        run.builder.ensure(Rls {
            compiler: run.builder.compiler(run.builder.top_stage, run.builder.build.build),
            target: run.target,
        });
    }

    fn run(self, builder: &Builder) -> PathBuf {
        builder.ensure(native::Openssl {
            target: self.target,
        });
        // RLS depends on procedural macros, which requires a full host
        // compiler to be available, so we need to depend on that.
        builder.ensure(compile::Rustc {
            compiler: self.compiler,
            target: builder.build.build,
        });
        builder.ensure(ToolBuild {
            compiler: self.compiler,
            target: self.target,
            tool: "rls",
            mode: Mode::Librustc,
        })
    }
}

impl<'a> Builder<'a> {
    /// Get a `Command` which is ready to run `tool` in `stage` built for
    /// `host`.
    pub fn tool_cmd(&self, tool: Tool) -> Command {
        let mut cmd = Command::new(self.tool_exe(tool));
        let compiler = self.compiler(0, self.build.build);
        self.prepare_tool_cmd(compiler, &mut cmd);
        cmd
    }

    /// Prepares the `cmd` provided to be able to run the `compiler` provided.
    ///
    /// Notably this munges the dynamic library lookup path to point to the
    /// right location to run `compiler`.
    fn prepare_tool_cmd(&self, compiler: Compiler, cmd: &mut Command) {
        let host = &compiler.host;
        let mut paths: Vec<PathBuf> = vec![
            PathBuf::from(&self.sysroot_libdir(compiler, compiler.host)),
            self.cargo_out(compiler, Mode::Tool, *host).join("deps"),
        ];

        // On MSVC a tool may invoke a C compiler (e.g. compiletest in run-make
        // mode) and that C compiler may need some extra PATH modification. Do
        // so here.
        if compiler.host.contains("msvc") {
            let curpaths = env::var_os("PATH").unwrap_or_default();
            let curpaths = env::split_paths(&curpaths).collect::<Vec<_>>();
            for &(ref k, ref v) in self.cc[&compiler.host].0.env() {
                if k != "PATH" {
                    continue
                }
                for path in env::split_paths(v) {
                    if !curpaths.contains(&path) {
                        paths.push(path);
                    }
                }
            }
        }
        add_lib_path(paths, cmd);
    }
}
<|endoftext|>


<commit_before><commit_msg>Add audio whitenoise example<commit_after>extern crate sdl2;
use sdl2::audio::{AudioCallback, AudioSpecDesired};
use std::rand::{Rng, StdRng};

struct MyCallback {
    /// Random number generator for white noise
    rng: StdRng,
    volume: f32
}
impl AudioCallback<f32> for MyCallback {
    fn callback(&mut self, out: &mut [f32]) {
        // Generate white noise
        for x in out.iter_mut() {
            *x = self.rng.next_f32() * self.volume;
        }
    }
}

fn main() {
    sdl2::init(sdl2::INIT_AUDIO);

    let desired_spec = AudioSpecDesired {
        freq: 44100,
        channels: 1,
        callback: box MyCallback { rng: StdRng::new().unwrap(), volume: 1.0 }
    };

    // None: use default device
    // false: Playback
    let mut device = match desired_spec.open_audio_device(None, false) {
        Ok(device) => device,
        Err(s) => panic!("{}", s)
    };

    // Show obtained AudioSpec
    println!("{}", device.get_spec());

    // Start playback
    device.resume();

    // Play for 1 second
    sdl2::timer::delay(1000);

    {
        // Acquire a lock. This lets us read and modify callback data.
        let mut lock = device.lock();
        (*lock).volume = 0.5;
        // Lock guard is dropped here
    }

    // Play for another second
    sdl2::timer::delay(1000);

    // Device is automatically closed when dropped
}
<|endoftext|>


<commit_before><commit_msg>Add test case for #77062<commit_after>// build-pass

fn main() {
    let _ = &[(); usize::MAX];
}
<|endoftext|>


<commit_before><commit_msg>Added a test for relay in which server should get two clients at once.<commit_after><|endoftext|>


<commit_before><commit_msg>improve Engine::run<commit_after><|endoftext|>


<commit_before><commit_msg>Remove GetIter<commit_after><|endoftext|>


<commit_before><commit_msg>Get rid of a redundant assertion in a test<commit_after><|endoftext|>


<commit_before>// copyright 2013 the rust project developers. see the copyright
// file at the top-level directory of this distribution and at
// http://rust-lang.org/copyright.
//
// licensed under the apache license, version 2.0 <license-apache or
// http://www.apache.org/licenses/license-2.0> or the mit license
// <license-mit or http://opensource.org/licenses/mit>, at your
// option. this file may not be copied, modified, or distributed
// except according to those terms.
use option::{Option, Some, None};
use result::{Ok, Err};
use rt::io::{io_error};
use rt::rtio::{IoFactory, IoFactoryObject,
               RtioTimer, RtioTimerObject};
use rt::local::Local;

pub struct Timer(~RtioTimerObject);

impl Timer {
    fn new_on_rt(i: ~RtioTimerObject) -> Timer {
        Timer(i)
    }

    pub fn new() -> Option<Timer> {
        let timer = unsafe {
            rtdebug!("Timer::init: borrowing io to init timer");
            let io = Local::unsafe_borrow::<IoFactoryObject>();
            rtdebug!("about to init timer");
            (*io).timer_init()
        };
        match timer {
            Ok(t) => Some(Timer::new_on_rt(t)),
            Err(ioerr) => {
                rtdebug!("Timer::init: failed to init: %?", ioerr);
                io_error::cond.raise(ioerr);
                None
            }
        }
    }
}

impl RtioTimer for Timer {
    fn sleep(&self, msecs: u64) {
        (**self).sleep(msecs);
    }
}

#[cfg(test)]
mod test {
    use super::*;
    use rt::test::*;
    use option::{Some, None};
    #[test]
    fn test_io_timer_sleep_simple() {
        do run_in_newsched_task {
            let timer = Timer::new();
            match timer {
                Some(t) => t.sleep(1),
                None => assert!(false)
            }
        }
    }
}<commit_msg>std: make check appeasement<commit_after>// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use option::{Option, Some, None};
use result::{Ok, Err};
use rt::io::{io_error};
use rt::rtio::{IoFactory, IoFactoryObject,
               RtioTimer, RtioTimerObject};
use rt::local::Local;

pub struct Timer(~RtioTimerObject);

impl Timer {
    fn new_on_rt(i: ~RtioTimerObject) -> Timer {
        Timer(i)
    }

    pub fn new() -> Option<Timer> {
        let timer = unsafe {
            rtdebug!("Timer::init: borrowing io to init timer");
            let io = Local::unsafe_borrow::<IoFactoryObject>();
            rtdebug!("about to init timer");
            (*io).timer_init()
        };
        match timer {
            Ok(t) => Some(Timer::new_on_rt(t)),
            Err(ioerr) => {
                rtdebug!("Timer::init: failed to init: %?", ioerr);
                io_error::cond.raise(ioerr);
                None
            }
        }
    }
}

impl RtioTimer for Timer {
    fn sleep(&self, msecs: u64) {
        (**self).sleep(msecs);
    }
}

#[cfg(test)]
mod test {
    use super::*;
    use rt::test::*;
    use option::{Some, None};
    #[test]
    fn test_io_timer_sleep_simple() {
        do run_in_newsched_task {
            let timer = Timer::new();
            match timer {
                Some(t) => t.sleep(1),
                None => assert!(false)
            }
        }
    }
}<|endoftext|>


<commit_before><commit_msg>Support qualified name in type and trait names. Finish type name parser.<commit_after><|endoftext|>


<commit_before>import stackwalk::Word;
import libc::size_t;
import libc::uintptr_t;
import send_map::linear::LinearMap;

export Word;
export gc;
export cleanup_stack_for_failure;

// Mirrors rust_stack.h stk_seg
struct StackSegment {
    let prev: *StackSegment;
    let next: *StackSegment;
    let end: uintptr_t;
    // And other fields which we don't care about...
}

extern mod rustrt {
    fn rust_annihilate_box(ptr: *Word);

    #[rust_stack]
    fn rust_call_tydesc_glue(root: *Word, tydesc: *Word, field: size_t);

    #[rust_stack]
    fn rust_gc_metadata() -> *Word;

    fn rust_get_stack_segment() -> *StackSegment;
}

unsafe fn is_frame_in_segment(fp: *Word, segment: *StackSegment) -> bool {
    let begin: Word = unsafe::reinterpret_cast(&segment);
    let end: Word = unsafe::reinterpret_cast(&(*segment).end);
    let frame: Word = unsafe::reinterpret_cast(&fp);

    return begin <= frame && frame <= end;
}

type SafePoint = { sp_meta: *Word, fn_meta: *Word };

unsafe fn is_safe_point(pc: *Word) -> Option<SafePoint> {
    let module_meta = rustrt::rust_gc_metadata();
    let num_safe_points_ptr: *u32 = unsafe::reinterpret_cast(&module_meta);
    let num_safe_points = *num_safe_points_ptr as Word;
    let safe_points: *Word =
        ptr::offset(unsafe::reinterpret_cast(&module_meta), 1);

    if ptr::is_null(pc) {
        return None;
    }

    let mut sp = 0 as Word;
    while sp < num_safe_points {
        let sp_loc = *ptr::offset(safe_points, sp*3) as *Word;
        if sp_loc == pc {
            return Some(
                {sp_meta: *ptr::offset(safe_points, sp*3 + 1) as *Word,
                 fn_meta: *ptr::offset(safe_points, sp*3 + 2) as *Word});
        }
        sp += 1;
    }
    return None;
}

type Visitor = fn(root: **Word, tydesc: *Word) -> bool;

unsafe fn bump<T, U>(ptr: *T, count: uint) -> *U {
    return unsafe::reinterpret_cast(&ptr::offset(ptr, count));
}

unsafe fn align_to_pointer<T>(ptr: *T) -> *T {
    let align = sys::min_align_of::<*T>();
    let ptr: uint = unsafe::reinterpret_cast(&ptr);
    let ptr = (ptr + (align - 1)) & -align;
    return unsafe::reinterpret_cast(&ptr);
}

unsafe fn walk_safe_point(fp: *Word, sp: SafePoint, visitor: Visitor) {
    let fp_bytes: *u8 = unsafe::reinterpret_cast(&fp);
    let sp_meta_u32s: *u32 = unsafe::reinterpret_cast(&sp.sp_meta);

    let num_stack_roots = *sp_meta_u32s as uint;
    let num_reg_roots = *ptr::offset(sp_meta_u32s, 1) as uint;

    let stack_roots: *u32 =
        unsafe::reinterpret_cast(&ptr::offset(sp_meta_u32s, 2));
    let reg_roots: *u8 =
        unsafe::reinterpret_cast(&ptr::offset(stack_roots, num_stack_roots));
    let addrspaces: *Word =
        unsafe::reinterpret_cast(&ptr::offset(reg_roots, num_reg_roots));
    let tydescs: ***Word =
        unsafe::reinterpret_cast(&ptr::offset(addrspaces, num_stack_roots));

    // Stack roots
    let mut sri = 0;
    while sri < num_stack_roots {
        if *ptr::offset(addrspaces, sri) >= 1 {
            let root =
                ptr::offset(fp_bytes, *ptr::offset(stack_roots, sri) as Word)
                as **Word;
            let tydescpp = ptr::offset(tydescs, sri);
            let tydesc = if ptr::is_not_null(tydescpp) &&
                ptr::is_not_null(*tydescpp) {
                **tydescpp
            } else {
                ptr::null()
            };
            if !visitor(root, tydesc) { return; }
        }
        sri += 1;
    }

    // Register roots
    let mut rri = 0;
    while rri < num_reg_roots {
        if *ptr::offset(addrspaces, num_stack_roots + rri) == 1 {
            // FIXME(#2997): Need to find callee saved registers on the stack.
        }
        rri += 1;
    }
}

type Memory = uint;

const task_local_heap: Memory = 1;
const exchange_heap:   Memory = 2;
const stack:           Memory = 4;

const need_cleanup:    Memory = exchange_heap | stack;

unsafe fn find_segment_for_frame(fp: *Word, segment: *StackSegment)
    -> {segment: *StackSegment, boundary: bool} {
    // Check if frame is in either current frame or previous frame.
    let in_segment = is_frame_in_segment(fp, segment);
    let in_prev_segment = ptr::is_not_null((*segment).prev) &&
        is_frame_in_segment(fp, (*segment).prev);

    // If frame is not in either segment, walk down segment list until
    // we find the segment containing this frame.
    if !in_segment && !in_prev_segment {
        let mut segment = segment;
        while ptr::is_not_null((*segment).next) &&
            is_frame_in_segment(fp, (*segment).next) {
            segment = (*segment).next;
        }
        return {segment: segment, boundary: false};
    }

    // If frame is in previous frame, then we're at a boundary.
    if !in_segment && in_prev_segment {
        return {segment: (*segment).prev, boundary: true};
    }

    // Otherwise, we're somewhere on the inside of the frame.
    return {segment: segment, boundary: false};
}

unsafe fn walk_gc_roots(mem: Memory, sentinel: **Word, visitor: Visitor) {
    let mut segment = rustrt::rust_get_stack_segment();
    let mut last_ret: *Word = ptr::null();
    // To avoid collecting memory used by the GC itself, skip stack
    // frames until past the root GC stack frame. The root GC stack
    // frame is marked by a sentinel, which is a box pointer stored on
    // the stack.
    let mut reached_sentinel = ptr::is_null(sentinel);
    for stackwalk::walk_stack |frame| {
        unsafe {
            let pc = last_ret;
            let {segment: next_segment, boundary: boundary} =
                find_segment_for_frame(frame.fp, segment);
            segment = next_segment;
            let ret_offset = if boundary { 4 } else { 1 };
            last_ret = *ptr::offset(frame.fp, ret_offset) as *Word;

            if ptr::is_null(pc) {
                again;
            }

            let mut delay_reached_sentinel = reached_sentinel;
            let sp = is_safe_point(pc);
            match sp {
              Some(sp_info) => {
                for walk_safe_point(frame.fp, sp_info) |root, tydesc| {
                    // Skip roots until we see the sentinel.
                    if !reached_sentinel {
                        if root == sentinel {
                            delay_reached_sentinel = true;
                        }
                        again;
                    }

                    // Skip null pointers, which can occur when a
                    // unique pointer has already been freed.
                    if ptr::is_null(*root) {
                        again;
                    }

                    if ptr::is_null(tydesc) {
                        // Root is a generic box.
                        let refcount = **root;
                        if mem | task_local_heap != 0 && refcount != -1 {
                            if !visitor(root, tydesc) { return; }
                        } else if mem | exchange_heap != 0 && refcount == -1 {
                            if !visitor(root, tydesc) { return; }
                        }
                    } else {
                        // Root is a non-immediate.
                        if mem | stack != 0 {
                            if !visitor(root, tydesc) { return; }
                        }
                    }
                }
              }
              None => ()
            }
            reached_sentinel = delay_reached_sentinel;
        }
    }
}

fn gc() {
    unsafe {
        for walk_gc_roots(task_local_heap, ptr::null()) |_root, _tydesc| {
            // FIXME(#2997): Walk roots and mark them.
            io::stdout().write([46]); // .
        }
    }
}

type RootSet = LinearMap<*Word,()>;

fn RootSet() -> RootSet {
    LinearMap()
}

#[cfg(gc)]
fn expect_sentinel() -> bool { true }

#[cfg(nogc)]
fn expect_sentinel() -> bool { false }

// This should only be called from fail, as it will drop the roots
// which are *live* on the stack, rather than dropping those that are
// dead.
fn cleanup_stack_for_failure() {
    unsafe {
        // Leave a sentinel on the stack to mark the current frame. The
        // stack walker will ignore any frames above the sentinel, thus
        // avoiding collecting any memory being used by the stack walker
        // itself.
        //
        // However, when core itself is not compiled with GC, then none of
        // the functions in core will have GC metadata, which means we
        // won't be able to find the sentinel root on the stack. In this
        // case, we can safely skip the sentinel since we won't find our
        // own stack roots on the stack anyway.
        let sentinel_box = ~0;
        let sentinel: **Word = if expect_sentinel() {
            unsafe::reinterpret_cast(&ptr::addr_of(sentinel_box))
        } else {
            ptr::null()
        };

        let mut roots = ~RootSet();
        for walk_gc_roots(need_cleanup, sentinel) |root, tydesc| {
            // Track roots to avoid double frees.
            if option::is_some(roots.find(&*root)) {
                again;
            }
            roots.insert(*root, ());

            if ptr::is_null(tydesc) {
                rustrt::rust_annihilate_box(*root);
            } else {
                rustrt::rust_call_tydesc_glue(*root, tydesc, 3 as size_t);
            }
        }
    }
}
<commit_msg>gc: Documentation.<commit_after>/*! Precise Garbage Collector

The precise GC exposes two functions, gc and
cleanup_stack_for_failure. The gc function is the entry point to the
garbage collector itself. The cleanup_stack_for_failure is the entry
point for GC-based cleanup.

Precise GC depends on changes to LLVM's GC which add support for
automatic rooting and addrspace-based metadata marking. Rather than
explicitly rooting pointers with LLVM's gcroot intrinsic, the GC
merely creates allocas for pointers, and allows an LLVM pass to
automatically infer roots based on the allocas present in a function
(and live at a given location). The compiler communicates the type of
the pointer to LLVM by setting the addrspace of the pointer type. The
compiler then emits a map from addrspace to tydesc, which LLVM then
uses to match pointers with their tydesc. The GC reads the metadata
table produced by LLVM, and uses it to determine which glue functions
to call to free objects on their respective heaps.

GC-based cleanup is a replacement for landing pads which relies on the
GC infrastructure to find pointers on the stack to cleanup. Whereas
the normal GC needs to walk task-local heap allocations, the cleanup
code needs to walk exchange heap allocations and stack-allocations
with destructors.

*/

import stackwalk::Word;
import libc::size_t;
import libc::uintptr_t;
import send_map::linear::LinearMap;

export Word;
export gc;
export cleanup_stack_for_failure;

// Mirrors rust_stack.h stk_seg
struct StackSegment {
    let prev: *StackSegment;
    let next: *StackSegment;
    let end: uintptr_t;
    // And other fields which we don't care about...
}

extern mod rustrt {
    fn rust_annihilate_box(ptr: *Word);

    #[rust_stack]
    fn rust_call_tydesc_glue(root: *Word, tydesc: *Word, field: size_t);

    #[rust_stack]
    fn rust_gc_metadata() -> *Word;

    fn rust_get_stack_segment() -> *StackSegment;
}

// Is fp contained in segment?
unsafe fn is_frame_in_segment(fp: *Word, segment: *StackSegment) -> bool {
    let begin: Word = unsafe::reinterpret_cast(&segment);
    let end: Word = unsafe::reinterpret_cast(&(*segment).end);
    let frame: Word = unsafe::reinterpret_cast(&fp);

    return begin <= frame && frame <= end;
}

type SafePoint = { sp_meta: *Word, fn_meta: *Word };

// Returns the safe point metadata for the given program counter, if
// any.
unsafe fn is_safe_point(pc: *Word) -> Option<SafePoint> {
    let module_meta = rustrt::rust_gc_metadata();
    let num_safe_points_ptr: *u32 = unsafe::reinterpret_cast(&module_meta);
    let num_safe_points = *num_safe_points_ptr as Word;
    let safe_points: *Word =
        ptr::offset(unsafe::reinterpret_cast(&module_meta), 1);

    if ptr::is_null(pc) {
        return None;
    }

    // FIXME (#2997): Use binary rather than linear search.
    let mut sp = 0 as Word;
    while sp < num_safe_points {
        let sp_loc = *ptr::offset(safe_points, sp*3) as *Word;
        if sp_loc == pc {
            return Some(
                {sp_meta: *ptr::offset(safe_points, sp*3 + 1) as *Word,
                 fn_meta: *ptr::offset(safe_points, sp*3 + 2) as *Word});
        }
        sp += 1;
    }
    return None;
}

type Visitor = fn(root: **Word, tydesc: *Word) -> bool;

unsafe fn bump<T, U>(ptr: *T, count: uint) -> *U {
    return unsafe::reinterpret_cast(&ptr::offset(ptr, count));
}

unsafe fn align_to_pointer<T>(ptr: *T) -> *T {
    let align = sys::min_align_of::<*T>();
    let ptr: uint = unsafe::reinterpret_cast(&ptr);
    let ptr = (ptr + (align - 1)) & -align;
    return unsafe::reinterpret_cast(&ptr);
}

// Walks the list of roots for the given safe point, and calls visitor
// on each root.
unsafe fn walk_safe_point(fp: *Word, sp: SafePoint, visitor: Visitor) {
    let fp_bytes: *u8 = unsafe::reinterpret_cast(&fp);
    let sp_meta_u32s: *u32 = unsafe::reinterpret_cast(&sp.sp_meta);

    let num_stack_roots = *sp_meta_u32s as uint;
    let num_reg_roots = *ptr::offset(sp_meta_u32s, 1) as uint;

    let stack_roots: *u32 =
        unsafe::reinterpret_cast(&ptr::offset(sp_meta_u32s, 2));
    let reg_roots: *u8 =
        unsafe::reinterpret_cast(&ptr::offset(stack_roots, num_stack_roots));
    let addrspaces: *Word =
        unsafe::reinterpret_cast(&ptr::offset(reg_roots, num_reg_roots));
    let tydescs: ***Word =
        unsafe::reinterpret_cast(&ptr::offset(addrspaces, num_stack_roots));

    // Stack roots
    let mut sri = 0;
    while sri < num_stack_roots {
        if *ptr::offset(addrspaces, sri) >= 1 {
            let root =
                ptr::offset(fp_bytes, *ptr::offset(stack_roots, sri) as Word)
                as **Word;
            let tydescpp = ptr::offset(tydescs, sri);
            let tydesc = if ptr::is_not_null(tydescpp) &&
                ptr::is_not_null(*tydescpp) {
                **tydescpp
            } else {
                ptr::null()
            };
            if !visitor(root, tydesc) { return; }
        }
        sri += 1;
    }

    // Register roots
    let mut rri = 0;
    while rri < num_reg_roots {
        if *ptr::offset(addrspaces, num_stack_roots + rri) == 1 {
            // FIXME(#2997): Need to find callee saved registers on the stack.
        }
        rri += 1;
    }
}

type Memory = uint;

const task_local_heap: Memory = 1;
const exchange_heap:   Memory = 2;
const stack:           Memory = 4;

const need_cleanup:    Memory = exchange_heap | stack;

// Find and return the segment containing the given frame pointer. At
// stack segment boundaries, returns true for boundary, so that the
// caller can do any special handling to identify where the correct
// return address is in the stack frame.
unsafe fn find_segment_for_frame(fp: *Word, segment: *StackSegment)
    -> {segment: *StackSegment, boundary: bool} {
    // Check if frame is in either current frame or previous frame.
    let in_segment = is_frame_in_segment(fp, segment);
    let in_prev_segment = ptr::is_not_null((*segment).prev) &&
        is_frame_in_segment(fp, (*segment).prev);

    // If frame is not in either segment, walk down segment list until
    // we find the segment containing this frame.
    if !in_segment && !in_prev_segment {
        let mut segment = segment;
        while ptr::is_not_null((*segment).next) &&
            is_frame_in_segment(fp, (*segment).next) {
            segment = (*segment).next;
        }
        return {segment: segment, boundary: false};
    }

    // If frame is in previous frame, then we're at a boundary.
    if !in_segment && in_prev_segment {
        return {segment: (*segment).prev, boundary: true};
    }

    // Otherwise, we're somewhere on the inside of the frame.
    return {segment: segment, boundary: false};
}

// Walks stack, searching for roots of the requested type, and passes
// each root to the visitor.
unsafe fn walk_gc_roots(mem: Memory, sentinel: **Word, visitor: Visitor) {
    let mut segment = rustrt::rust_get_stack_segment();
    let mut last_ret: *Word = ptr::null();
    // To avoid collecting memory used by the GC itself, skip stack
    // frames until past the root GC stack frame. The root GC stack
    // frame is marked by a sentinel, which is a box pointer stored on
    // the stack.
    let mut reached_sentinel = ptr::is_null(sentinel);
    for stackwalk::walk_stack |frame| {
        unsafe {
            let pc = last_ret;
            let {segment: next_segment, boundary: boundary} =
                find_segment_for_frame(frame.fp, segment);
            segment = next_segment;
            // Each stack segment is bounded by a morestack frame. The
            // morestack frame includes two return addresses, one for
            // morestack itself, at the normal offset from the frame
            // pointer, and then a second return address for the
            // function prologue (which called morestack after
            // determining that it had hit the end of the stack).
            // Since morestack itself takes two parameters, the offset
            // for this second return address is 3 greater than the
            // return address for morestack.
            let ret_offset = if boundary { 4 } else { 1 };
            last_ret = *ptr::offset(frame.fp, ret_offset) as *Word;

            if ptr::is_null(pc) {
                again;
            }

            let mut delay_reached_sentinel = reached_sentinel;
            let sp = is_safe_point(pc);
            match sp {
              Some(sp_info) => {
                for walk_safe_point(frame.fp, sp_info) |root, tydesc| {
                    // Skip roots until we see the sentinel.
                    if !reached_sentinel {
                        if root == sentinel {
                            delay_reached_sentinel = true;
                        }
                        again;
                    }

                    // Skip null pointers, which can occur when a
                    // unique pointer has already been freed.
                    if ptr::is_null(*root) {
                        again;
                    }

                    if ptr::is_null(tydesc) {
                        // Root is a generic box.
                        let refcount = **root;
                        if mem | task_local_heap != 0 && refcount != -1 {
                            if !visitor(root, tydesc) { return; }
                        } else if mem | exchange_heap != 0 && refcount == -1 {
                            if !visitor(root, tydesc) { return; }
                        }
                    } else {
                        // Root is a non-immediate.
                        if mem | stack != 0 {
                            if !visitor(root, tydesc) { return; }
                        }
                    }
                }
              }
              None => ()
            }
            reached_sentinel = delay_reached_sentinel;
        }
    }
}

fn gc() {
    unsafe {
        for walk_gc_roots(task_local_heap, ptr::null()) |_root, _tydesc| {
            // FIXME(#2997): Walk roots and mark them.
            io::stdout().write([46]); // .
        }
    }
}

type RootSet = LinearMap<*Word,()>;

fn RootSet() -> RootSet {
    LinearMap()
}

#[cfg(gc)]
fn expect_sentinel() -> bool { true }

#[cfg(nogc)]
fn expect_sentinel() -> bool { false }

// Entry point for GC-based cleanup. Walks stack looking for exchange
// heap and stack allocations requiring drop, and runs all
// destructors.
//
// This should only be called from fail, as it will drop the roots
// which are *live* on the stack, rather than dropping those that are
// dead.
fn cleanup_stack_for_failure() {
    unsafe {
        // Leave a sentinel on the stack to mark the current frame. The
        // stack walker will ignore any frames above the sentinel, thus
        // avoiding collecting any memory being used by the stack walker
        // itself.
        //
        // However, when core itself is not compiled with GC, then none of
        // the functions in core will have GC metadata, which means we
        // won't be able to find the sentinel root on the stack. In this
        // case, we can safely skip the sentinel since we won't find our
        // own stack roots on the stack anyway.
        let sentinel_box = ~0;
        let sentinel: **Word = if expect_sentinel() {
            unsafe::reinterpret_cast(&ptr::addr_of(sentinel_box))
        } else {
            ptr::null()
        };

        let mut roots = ~RootSet();
        for walk_gc_roots(need_cleanup, sentinel) |root, tydesc| {
            // Track roots to avoid double frees.
            if option::is_some(roots.find(&*root)) {
                again;
            }
            roots.insert(*root, ());

            if ptr::is_null(tydesc) {
                rustrt::rust_annihilate_box(*root);
            } else {
                rustrt::rust_call_tydesc_glue(*root, tydesc, 3 as size_t);
            }
        }
    }
}
<|endoftext|>