<commit_before>extern crate serde_json;
extern crate hex;

use self::hex::ToHex;
use self::serde_json::Value;

use errors::common::CommonError;
use utils::crypto::hash::Hash;

pub fn serialize_signature(v: Value) -> Result<String, CommonError> {
    match v {
        Value::Bool(value) => Ok(value.to_string()),
        Value::Number(value) => Ok(value.to_string()),
        Value::String(value) => Ok(value),
        Value::Array(array) => {
            let mut result = "".to_string();
            let length = array.len();
            for (index, element) in array.iter().enumerate() {
                result += &serialize_signature(element.clone())?;
                if index < length - 1 {
                    result += ",";
                }
            }
            Ok(result)
        },
        Value::Object(map) => {
            let mut result = "".to_string();
            let length = map.len();
            for (index, key) in map.keys().enumerate() {
                let mut value = map[key].clone();
                if key == "raw" {
                    let mut ctx = Hash::new_context()?;
                    ctx.update(&value.as_str().ok_or(CommonError::InvalidState("Cannot update hash context".to_string()))?.as_bytes())?;
                    value = Value::String(ctx.finish2()?.as_ref().to_hex());
                }
                result = result + key + ":" + &serialize_signature(value)?;
                if index < length - 1 {
                    result += "|";
                }
            }
            Ok(result)
        },
        _ => Ok("".to_string())
    }
}

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

    #[test]
    fn signature_serialize_works() {
        let data = r#"{
                        "name": "John Doe",
                        "age": 43,
                        "operation": {
                            "hash": "cool hash",
                            "dest": 54
                        },
                        "phones": [
                          "1234567",
                          "2345678",
                          {"rust": 5, "age": 1},
                          3
                        ]
                    }"#;
        let msg: Value = serde_json::from_str(data).unwrap();

        let result = "age:43|name:John Doe|operation:dest:54|hash:cool hash|phones:1234567,2345678,age:1|rust:5,3";

        assert_eq!(serialize_signature(msg).unwrap(), result)
    }

    #[test]
    fn signature_serialize_works_with_raw() {
        let data = r#"{
                        "name": "John Doe",
                        "age": 43,
                        "operation": {
                            "hash": "cool hash",
                            "dest": 54,
                            "raw": "string for hash"
                        },
                        "phones": [
                          "1234567",
                          "2345678",
                          {"rust": 5, "age": 1},
                          3
                        ]
                    }"#;
        let msg: Value = serde_json::from_str(data).unwrap();

        let result = "age:43|name:John Doe|operation:dest:54|hash:cool hash|raw:1dcd0759ce38f57049344a6b3c5fc18144fca1724713090c2ceeffa788c02711|phones:1234567,2345678,age:1|rust:5,3";

        assert_eq!(serialize_signature(msg).unwrap(), result)
    }
}<commit_msg>Add error test case into signature_serializer.<commit_after>extern crate serde_json;
extern crate hex;

use self::hex::ToHex;
use self::serde_json::Value;

use errors::common::CommonError;
use utils::crypto::hash::Hash;

pub fn serialize_signature(v: Value) -> Result<String, CommonError> {
    match v {
        Value::Bool(value) => Ok(value.to_string()),
        Value::Number(value) => Ok(value.to_string()),
        Value::String(value) => Ok(value),
        Value::Array(array) => {
            let mut result = "".to_string();
            let length = array.len();
            for (index, element) in array.iter().enumerate() {
                result += &serialize_signature(element.clone())?;
                if index < length - 1 {
                    result += ",";
                }
            }
            Ok(result)
        },
        Value::Object(map) => {
            let mut result = "".to_string();
            let length = map.len();
            for (index, key) in map.keys().enumerate() {
                let mut value = map[key].clone();
                if key == "raw" {
                    let mut ctx = Hash::new_context()?;
                    ctx.update(&value.as_str().ok_or(CommonError::InvalidState("Cannot update hash context".to_string()))?.as_bytes())?;
                    value = Value::String(ctx.finish2()?.as_ref().to_hex());
                }
                result = result + key + ":" + &serialize_signature(value)?;
                if index < length - 1 {
                    result += "|";
                }
            }
            Ok(result)
        },
        _ => Ok("".to_string())
    }
}

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

    #[test]
    fn signature_serialize_works() {
        let data = r#"{
                        "name": "John Doe",
                        "age": 43,
                        "operation": {
                            "hash": "cool hash",
                            "dest": 54
                        },
                        "phones": [
                          "1234567",
                          "2345678",
                          {"rust": 5, "age": 1},
                          3
                        ]
                    }"#;
        let msg: Value = serde_json::from_str(data).unwrap();

        let result = "age:43|name:John Doe|operation:dest:54|hash:cool hash|phones:1234567,2345678,age:1|rust:5,3";

        assert_eq!(serialize_signature(msg).unwrap(), result)
    }

    #[test]
    fn signature_serialize_works_with_raw() {
        let data = r#"{
                        "name": "John Doe",
                        "age": 43,
                        "operation": {
                            "hash": "cool hash",
                            "dest": 54,
                            "raw": "string for hash"
                        },
                        "phones": [
                          "1234567",
                          "2345678",
                          {"rust": 5, "age": 1},
                          3
                        ]
                    }"#;
        let msg: Value = serde_json::from_str(data).unwrap();

        let result = "age:43|name:John Doe|operation:dest:54|hash:cool hash|raw:1dcd0759ce38f57049344a6b3c5fc18144fca1724713090c2ceeffa788c02711|phones:1234567,2345678,age:1|rust:5,3";

        assert_eq!(serialize_signature(msg).unwrap(), result)
    }

    #[test]
    #[ignore] /* FIXME implement ignoring signature field as in python code */
    fn signature_serialize_works_with_null() {
        let data = r#"{"signature": null}"#;
        let v: serde_json::Value = serde_json::from_str(data).unwrap();
        let serialized = serialize_signature(v).unwrap();
        println!("{:?}", serialized);
        assert_eq!(serialized, "");
    }
}<|endoftext|>


<commit_before><commit_msg>Take AsRef<str> rather than &String<commit_after><|endoftext|>


<commit_before><commit_msg>Add youtube-dl DJ bot example<commit_after>extern crate discord;
extern crate time;
extern crate serde_json;

use std::env;
use discord::{Discord, State};
use discord::voice::VoiceConnection;
use discord::model::Event;

// A simple DJ bot example.
// Use by issuing the command "!dj <youtube-link>" in PM or a visible text channel.
// The bot will join the voice channel of the person issuing the command.
// "!dj stop" will stop playing, and "!dj quit" will quit the voice channel.
// The bot will quit any voice channel it is the last user in.

pub fn main() {
	// log in to the API
	let args: Vec<_> = env::args().collect();
	let discord = Discord::new_cache(
		"tokens.txt",
		args.get(1).expect("No email specified"),
		args.get(2).map(|x| &**x),
	).expect("Login failed");

	// establish websocket and voice connection
	let (mut connection, ready) = discord.connect().expect("connect failed");
	println!("[Ready] {} is serving {} servers", ready.user.username, ready.servers.len());
	let mut voice = VoiceConnection::new(ready.user.id.clone());
	let mut state = State::new(ready);
	let mut current_channel = None;

	// receive events forever
	loop {
		let event = match connection.recv_event() {
			Ok(event) => event,
			Err(err) => {
				println!("[Warning] Receive error: {:?}", err);
				if let discord::Error::WebSocket(..) = err {
					// Handle the websocket connection being dropped
					let (new_connection, ready) = discord.connect().expect("connect failed");
					connection = new_connection;
					state = State::new(ready);
					println!("[Ready] Reconnected successfully.");
				}
				continue
			},
		};
		state.update(&event);
		voice.update(&event);

		match event {
			Event::Closed(n) => {
				println!("[Error] Connection closed with status: {}", n);
				break
			},
			Event::MessageCreate(message) => {
				use std::ascii::AsciiExt;
				// safeguard: stop if the message is from us
				if message.author.id == state.user().id {
					continue
				}

				// reply to a command if there was one
				let mut split = message.content.split(" ");
				let first_word = split.next().unwrap_or("");
				let argument = split.next().unwrap_or("");

				if first_word.eq_ignore_ascii_case("!dj") {
					if argument.eq_ignore_ascii_case("stop") {
						voice.stop();
					} else if argument.eq_ignore_ascii_case("quit") {
						connection.voice_disconnect();
					} else {
						let output = (|| {
							for server in state.servers() {
								for vstate in &server.voice_states {
									if vstate.user_id == message.author.id {
										if let Some(ref chan) = vstate.channel_id {
											let stream = match discord::voice::open_ytdl_stream(&argument) {
												Ok(stream) => stream,
												Err(error) => return format!("Error: {}", error),
											};
											voice.stop();
											connection.voice_connect(&server.id, chan);
											voice.play(stream);
											return String::new()
										}
									}
								}
							}
							"You must be in a voice channel to DJ".into()
						})();
						if output.len() > 0 {
							warn(discord.send_message(&message.channel_id, &output, "", false));
						}
					}
				}
			}
			Event::VoiceStateUpdate(server_id, voice_state) => {
				if voice_state.user_id == state.user().id {
					current_channel = voice_state.channel_id.map(|c| (server_id, c));
				} else if let Some((ref cur_server, ref cur_channel)) = current_channel {
					// If we are in a voice channel, && someone on our server moves/hangs up,
					if *cur_server == server_id {
						// && our current voice channel is empty, disconnect from voice
						if let Some(srv) = state.servers().iter().find(|srv| srv.id == server_id) {
							if srv.voice_states.iter().filter(|vs| vs.channel_id.as_ref() == Some(cur_channel)).count() <= 1 {
								connection.voice_disconnect();
							}
						}
					}
				}
			}
			_ => {}, // discard other events
		}
	}
}

fn warn<T, E: ::std::fmt::Debug>(result: Result<T, E>) {
	match result {
		Ok(_) => {},
		Err(err) => println!("[Warning] {:?}", err)
	}
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use resource_task::{ProgressMsg, Metadata, Payload, Done, LoaderTask, start_sending};

use std::io;
use std::io::File;
use servo_util::task::spawn_named;

static READ_SIZE: uint = 8192;

fn read_all(reader: &mut io::Stream, progress_chan: &Sender<ProgressMsg>)
        -> Result<(), String> {
    loop {
        let mut buf = vec!();
        match reader.push_at_least(READ_SIZE, READ_SIZE, &mut buf) {
            Ok(_) => progress_chan.send(Payload(buf)),
            Err(e) => match e.kind {
                io::EndOfFile => {
                    if buf.len() > 0 {
                        progress_chan.send(Payload(buf));
                    }
                    return Ok(());
                }
                _ => return Err(e.desc.to_string()),
            }
        }
    }
}

pub fn factory() -> LoaderTask {
    let f: LoaderTask = proc(load_data, start_chan) {
        let url = load_data.url;
        assert!("file" == url.scheme.as_slice());
        let progress_chan = start_sending(start_chan, Metadata::default(url.clone()));
        spawn_named("file_loader", proc() {
            match File::open_mode(&Path::new(url.serialize_path().unwrap()), io::Open, io::Read) {
                Ok(ref mut reader) => {
                    let res = read_all(reader as &mut io::Stream, &progress_chan);
                    progress_chan.send(Done(res));
                }
                Err(e) => {
                    progress_chan.send(Done(Err(e.desc.to_string())));
                }
            };
        });
    };
    f
}
<commit_msg>Fix loading of file URLs with spaces<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use resource_task::{ProgressMsg, Metadata, Payload, Done, LoaderTask, start_sending};

use std::io;
use std::io::File;
use servo_util::task::spawn_named;

static READ_SIZE: uint = 8192;

fn read_all(reader: &mut io::Stream, progress_chan: &Sender<ProgressMsg>)
        -> Result<(), String> {
    loop {
        let mut buf = vec!();
        match reader.push_at_least(READ_SIZE, READ_SIZE, &mut buf) {
            Ok(_) => progress_chan.send(Payload(buf)),
            Err(e) => match e.kind {
                io::EndOfFile => {
                    if buf.len() > 0 {
                        progress_chan.send(Payload(buf));
                    }
                    return Ok(());
                }
                _ => return Err(e.desc.to_string()),
            }
        }
    }
}

pub fn factory() -> LoaderTask {
    let f: LoaderTask = proc(load_data, start_chan) {
        let url = load_data.url;
        assert!("file" == url.scheme.as_slice());
        let progress_chan = start_sending(start_chan, Metadata::default(url.clone()));
        spawn_named("file_loader", proc() {
            let file_path: Path = url.to_file_path().unwrap();
            match File::open_mode(&Path::new(file_path), io::Open, io::Read) {
                Ok(ref mut reader) => {
                    let res = read_all(reader as &mut io::Stream, &progress_chan);
                    progress_chan.send(Done(res));
                }
                Err(e) => {
                    progress_chan.send(Done(Err(e.desc.to_string())));
                }
            };
        });
    };
    f
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use devtools_traits::{CachedConsoleMessage, CachedConsoleMessageTypes, PAGE_ERROR, CONSOLE_API};
use devtools_traits::{EvaluateJSReply, NodeInfo, Modification, TimelineMarker, TimelineMarkerType};
use devtools_traits::{ConsoleAPI, PageError};
use dom::bindings::conversions::FromJSValConvertible;
use dom::bindings::conversions::StringificationBehavior;
use dom::bindings::js::Root;
use dom::bindings::codegen::InheritTypes::{NodeCast, ElementCast};
use dom::bindings::codegen::Bindings::DocumentBinding::DocumentMethods;
use dom::bindings::codegen::Bindings::DOMRectBinding::{DOMRectMethods};
use dom::bindings::codegen::Bindings::ElementBinding::{ElementMethods};
use dom::node::{Node, NodeHelpers};
use dom::window::{WindowHelpers, ScriptHelpers};
use dom::document::DocumentHelpers;
use page::{IterablePage, Page};
use msg::constellation_msg::PipelineId;
use script_task::{get_page, ScriptTask};
use js::jsapi::RootedValue;
use js::jsval::UndefinedValue;

use std::sync::mpsc::Sender;
use std::rc::Rc;

pub fn handle_evaluate_js(page: &Rc<Page>, pipeline: PipelineId, eval: String, reply: Sender<EvaluateJSReply>){
    let page = get_page(&*page, pipeline);
    let window = page.window();
    let cx = window.r().get_cx();
    let mut rval = RootedValue::new(cx, UndefinedValue());
    window.r().evaluate_js_on_global_with_result(&eval, rval.handle_mut());

    reply.send(if rval.ptr.is_undefined() {
        EvaluateJSReply::VoidValue
    } else if rval.ptr.is_boolean() {
        EvaluateJSReply::BooleanValue(rval.ptr.to_boolean())
    } else if rval.ptr.is_double() {
        EvaluateJSReply::NumberValue(FromJSValConvertible::from_jsval(cx, rval.handle(), ()).unwrap())
    } else if rval.ptr.is_string() {
        //FIXME: use jsstring_to_str when jsval grows to_jsstring
        EvaluateJSReply::StringValue(
            FromJSValConvertible::from_jsval(cx, rval.handle(), StringificationBehavior::Default).unwrap())
    } else if rval.ptr.is_null() {
        EvaluateJSReply::NullValue
    } else {
        //FIXME: jsvals don't have an is_int32/is_number yet
        assert!(rval.ptr.is_object());
        panic!("object values unimplemented")
    }).unwrap();
}

pub fn handle_get_root_node(page: &Rc<Page>, pipeline: PipelineId, reply: Sender<NodeInfo>) {
    let page = get_page(&*page, pipeline);
    let document = page.document();

    let node = NodeCast::from_ref(document.r());
    reply.send(node.summarize()).unwrap();
}

pub fn handle_get_document_element(page: &Rc<Page>, pipeline: PipelineId, reply: Sender<NodeInfo>) {
    let page = get_page(&*page, pipeline);
    let document = page.document();
    let document_element = document.r().GetDocumentElement().unwrap();

    let node = NodeCast::from_ref(document_element.r());
    reply.send(node.summarize()).unwrap();
}

fn find_node_by_unique_id(page: &Rc<Page>, pipeline: PipelineId, node_id: String) -> Root<Node> {
    let page = get_page(&*page, pipeline);
    let document = page.document();
    let node = NodeCast::from_ref(document.r());

    for candidate in node.traverse_preorder() {
        if candidate.r().get_unique_id() == node_id {
            return candidate;
        }
    }

    panic!("couldn't find node with unique id {}", node_id)
}

pub fn handle_get_children(page: &Rc<Page>, pipeline: PipelineId, node_id: String, reply: Sender<Vec<NodeInfo>>) {
    let parent = find_node_by_unique_id(&*page, pipeline, node_id);
    let children = parent.r().children().map(|child| {
        child.r().summarize()
    }).collect();
    reply.send(children).unwrap();
}

pub fn handle_get_layout(page: &Rc<Page>, pipeline: PipelineId, node_id: String, reply: Sender<(f32, f32)>) {
    let node = find_node_by_unique_id(&*page, pipeline, node_id);
    let elem = ElementCast::to_ref(node.r()).expect("should be getting layout of element");
    let rect = elem.GetBoundingClientRect();
    let width = *rect.r().Width();
    let height = *rect.r().Height();
    reply.send((width, height)).unwrap();
}

pub fn handle_get_cached_messages(_pipeline_id: PipelineId,
                                  message_types: CachedConsoleMessageTypes,
                                  reply: Sender<Vec<CachedConsoleMessage>>) {
    //TODO: check the messageTypes against a global Cache for console messages and page exceptions
    let mut messages = Vec::new();
    if message_types.contains(PAGE_ERROR) {
        //TODO: make script error reporter pass all reported errors
        //      to devtools and cache them for returning here.
        let msg = PageError {
            _type: "PageError".to_owned(),
            errorMessage: "page error test".to_owned(),
            sourceName: String::new(),
            lineText: String::new(),
            lineNumber: 0,
            columnNumber: 0,
            category: String::new(),
            timeStamp: 0,
            error: false,
            warning: false,
            exception: false,
            strict: false,
            private: false,
        };
        messages.push(CachedConsoleMessage::PageError(msg));
    }
    if message_types.contains(CONSOLE_API) {
        //TODO: do for real
        let msg = ConsoleAPI {
            _type: "ConsoleAPI".to_owned(),
            level: "error".to_owned(),
            filename: "http://localhost/~mihai/mozilla/test.html".to_owned(),
            lineNumber: 0,
            functionName: String::new(),
            timeStamp: 0,
            private: false,
            arguments: vec!["console error test".to_owned()],
        };
        messages.push(CachedConsoleMessage::ConsoleAPI(msg));
    }
    reply.send(messages).unwrap();
}

pub fn handle_modify_attribute(page: &Rc<Page>,
                               pipeline: PipelineId,
                               node_id: String,
                               modifications: Vec<Modification>) {
    let node = find_node_by_unique_id(&*page, pipeline, node_id);
    let elem = ElementCast::to_ref(node.r()).expect("should be getting layout of element");

    for modification in modifications.iter(){
        match modification.newValue {
            Some(ref string) => {
                let _ = elem.SetAttribute(modification.attributeName.clone(), string.clone());
            },
            None => elem.RemoveAttribute(modification.attributeName.clone()),
        }
    }
}

pub fn handle_wants_live_notifications(page: &Rc<Page>, pipeline_id: PipelineId, send_notifications: bool) {
    let page = get_page(&*page, pipeline_id);
    let window = page.window();
    window.r().set_devtools_wants_updates(send_notifications);
}

pub fn handle_set_timeline_markers(page: &Rc<Page>,
                                   script_task: &ScriptTask,
                                   marker_types: Vec<TimelineMarkerType>,
                                   reply: Sender<TimelineMarker>) {
    for marker_type in &marker_types {
        match *marker_type {
            TimelineMarkerType::Reflow => {
                let window = page.window();
                window.r().set_devtools_timeline_marker(TimelineMarkerType::Reflow, reply.clone());
            }
            TimelineMarkerType::DOMEvent => {
                script_task.set_devtools_timeline_marker(TimelineMarkerType::DOMEvent, reply.clone());
            }
        }
    }
}

pub fn handle_drop_timeline_markers(page: &Rc<Page>,
                                    script_task: &ScriptTask,
                                    marker_types: Vec<TimelineMarkerType>) {
    let window = page.window();
    for marker_type in &marker_types {
        match *marker_type {
            TimelineMarkerType::Reflow => {
                window.r().drop_devtools_timeline_markers();
            }
            TimelineMarkerType::DOMEvent => {
                script_task.drop_devtools_timeline_markers();
            }
        }
    }
}

pub fn handle_request_animation_frame(page: &Rc<Page>, id: PipelineId, callback: Box<Fn(f64, )>) {
    let page = page.find(id).expect("There is no such page");
    let doc = page.document();
    doc.r().request_animation_frame(callback);
}
<commit_msg>Auto merge of #6726 - samfoo:int32-panic, r=Ms2ger<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use devtools_traits::{CachedConsoleMessage, CachedConsoleMessageTypes, PAGE_ERROR, CONSOLE_API};
use devtools_traits::{EvaluateJSReply, NodeInfo, Modification, TimelineMarker, TimelineMarkerType};
use devtools_traits::{ConsoleAPI, PageError};
use dom::bindings::conversions::FromJSValConvertible;
use dom::bindings::conversions::StringificationBehavior;
use dom::bindings::js::Root;
use dom::bindings::codegen::InheritTypes::{NodeCast, ElementCast};
use dom::bindings::codegen::Bindings::DocumentBinding::DocumentMethods;
use dom::bindings::codegen::Bindings::DOMRectBinding::{DOMRectMethods};
use dom::bindings::codegen::Bindings::ElementBinding::{ElementMethods};
use dom::node::{Node, NodeHelpers};
use dom::window::{WindowHelpers, ScriptHelpers};
use dom::document::DocumentHelpers;
use page::{IterablePage, Page};
use msg::constellation_msg::PipelineId;
use script_task::{get_page, ScriptTask};
use js::jsapi::RootedValue;
use js::jsval::UndefinedValue;

use std::sync::mpsc::Sender;
use std::rc::Rc;

pub fn handle_evaluate_js(
        page: &Rc<Page>,
        pipeline: PipelineId,
        eval: String,
        reply: Sender<EvaluateJSReply>
    ) {
    let page = get_page(&*page, pipeline);
    let window = page.window();
    let cx = window.r().get_cx();
    let mut rval = RootedValue::new(cx, UndefinedValue());
    window.r().evaluate_js_on_global_with_result(&eval, rval.handle_mut());

    reply.send(if rval.ptr.is_undefined() {
        EvaluateJSReply::VoidValue
    } else if rval.ptr.is_boolean() {
        EvaluateJSReply::BooleanValue(rval.ptr.to_boolean())
    } else if rval.ptr.is_double() || rval.ptr.is_int32() {
        EvaluateJSReply::NumberValue(
            FromJSValConvertible::from_jsval(cx, rval.handle(), ()).unwrap()
        )
    } else if rval.ptr.is_string() {
        //FIXME: use jsstring_to_str when jsval grows to_jsstring
        EvaluateJSReply::StringValue(
            FromJSValConvertible::from_jsval(cx, rval.handle(), StringificationBehavior::Default).unwrap())
    } else if rval.ptr.is_null() {
        EvaluateJSReply::NullValue
    } else {
        //FIXME: jsvals don't have an is_int32/is_number yet
        assert!(rval.ptr.is_object());
        panic!("object values unimplemented")
    }).unwrap();
}

pub fn handle_get_root_node(page: &Rc<Page>, pipeline: PipelineId, reply: Sender<NodeInfo>) {
    let page = get_page(&*page, pipeline);
    let document = page.document();

    let node = NodeCast::from_ref(document.r());
    reply.send(node.summarize()).unwrap();
}

pub fn handle_get_document_element(page: &Rc<Page>, pipeline: PipelineId, reply: Sender<NodeInfo>) {
    let page = get_page(&*page, pipeline);
    let document = page.document();
    let document_element = document.r().GetDocumentElement().unwrap();

    let node = NodeCast::from_ref(document_element.r());
    reply.send(node.summarize()).unwrap();
}

fn find_node_by_unique_id(page: &Rc<Page>, pipeline: PipelineId, node_id: String) -> Root<Node> {
    let page = get_page(&*page, pipeline);
    let document = page.document();
    let node = NodeCast::from_ref(document.r());

    for candidate in node.traverse_preorder() {
        if candidate.r().get_unique_id() == node_id {
            return candidate;
        }
    }

    panic!("couldn't find node with unique id {}", node_id)
}

pub fn handle_get_children(page: &Rc<Page>, pipeline: PipelineId, node_id: String, reply: Sender<Vec<NodeInfo>>) {
    let parent = find_node_by_unique_id(&*page, pipeline, node_id);
    let children = parent.r().children().map(|child| {
        child.r().summarize()
    }).collect();
    reply.send(children).unwrap();
}

pub fn handle_get_layout(page: &Rc<Page>, pipeline: PipelineId, node_id: String, reply: Sender<(f32, f32)>) {
    let node = find_node_by_unique_id(&*page, pipeline, node_id);
    let elem = ElementCast::to_ref(node.r()).expect("should be getting layout of element");
    let rect = elem.GetBoundingClientRect();
    let width = *rect.r().Width();
    let height = *rect.r().Height();
    reply.send((width, height)).unwrap();
}

pub fn handle_get_cached_messages(_pipeline_id: PipelineId,
                                  message_types: CachedConsoleMessageTypes,
                                  reply: Sender<Vec<CachedConsoleMessage>>) {
    //TODO: check the messageTypes against a global Cache for console messages and page exceptions
    let mut messages = Vec::new();
    if message_types.contains(PAGE_ERROR) {
        //TODO: make script error reporter pass all reported errors
        //      to devtools and cache them for returning here.
        let msg = PageError {
            _type: "PageError".to_owned(),
            errorMessage: "page error test".to_owned(),
            sourceName: String::new(),
            lineText: String::new(),
            lineNumber: 0,
            columnNumber: 0,
            category: String::new(),
            timeStamp: 0,
            error: false,
            warning: false,
            exception: false,
            strict: false,
            private: false,
        };
        messages.push(CachedConsoleMessage::PageError(msg));
    }
    if message_types.contains(CONSOLE_API) {
        //TODO: do for real
        let msg = ConsoleAPI {
            _type: "ConsoleAPI".to_owned(),
            level: "error".to_owned(),
            filename: "http://localhost/~mihai/mozilla/test.html".to_owned(),
            lineNumber: 0,
            functionName: String::new(),
            timeStamp: 0,
            private: false,
            arguments: vec!["console error test".to_owned()],
        };
        messages.push(CachedConsoleMessage::ConsoleAPI(msg));
    }
    reply.send(messages).unwrap();
}

pub fn handle_modify_attribute(page: &Rc<Page>,
                               pipeline: PipelineId,
                               node_id: String,
                               modifications: Vec<Modification>) {
    let node = find_node_by_unique_id(&*page, pipeline, node_id);
    let elem = ElementCast::to_ref(node.r()).expect("should be getting layout of element");

    for modification in modifications.iter(){
        match modification.newValue {
            Some(ref string) => {
                let _ = elem.SetAttribute(modification.attributeName.clone(), string.clone());
            },
            None => elem.RemoveAttribute(modification.attributeName.clone()),
        }
    }
}

pub fn handle_wants_live_notifications(page: &Rc<Page>, pipeline_id: PipelineId, send_notifications: bool) {
    let page = get_page(&*page, pipeline_id);
    let window = page.window();
    window.r().set_devtools_wants_updates(send_notifications);
}

pub fn handle_set_timeline_markers(page: &Rc<Page>,
                                   script_task: &ScriptTask,
                                   marker_types: Vec<TimelineMarkerType>,
                                   reply: Sender<TimelineMarker>) {
    for marker_type in &marker_types {
        match *marker_type {
            TimelineMarkerType::Reflow => {
                let window = page.window();
                window.r().set_devtools_timeline_marker(TimelineMarkerType::Reflow, reply.clone());
            }
            TimelineMarkerType::DOMEvent => {
                script_task.set_devtools_timeline_marker(TimelineMarkerType::DOMEvent, reply.clone());
            }
        }
    }
}

pub fn handle_drop_timeline_markers(page: &Rc<Page>,
                                    script_task: &ScriptTask,
                                    marker_types: Vec<TimelineMarkerType>) {
    let window = page.window();
    for marker_type in &marker_types {
        match *marker_type {
            TimelineMarkerType::Reflow => {
                window.r().drop_devtools_timeline_markers();
            }
            TimelineMarkerType::DOMEvent => {
                script_task.drop_devtools_timeline_markers();
            }
        }
    }
}

pub fn handle_request_animation_frame(page: &Rc<Page>, id: PipelineId, callback: Box<Fn(f64, )>) {
    let page = page.find(id).expect("There is no such page");
    let doc = page.document();
    doc.r().request_animation_frame(callback);
}
<|endoftext|>


<commit_before>// Copyright 2014 The Gfx-rs Developers.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use s = super::super::shade;
use super::gl;
use std::cell::Cell;

pub fn create_object(stage: s::Stage, data: &[u8]) -> (Option<super::Shader>, String) {
    let target = match stage {
        s::Vertex => gl::VERTEX_SHADER,
        s::Geometry => gl::GEOMETRY_SHADER,
        s::Fragment => gl::FRAGMENT_SHADER,
    };
    let name = gl::CreateShader(target);
    let mut length = data.len() as gl::types::GLint;
    unsafe {
        gl::ShaderSource(name, 1, &(data.as_ptr() as *gl::types::GLchar), &length);
    }
    gl::CompileShader(name);
    info!("\tCompiled shader {}", name);
    // get info message
    let mut status = 0 as gl::types::GLint;
    length = 0;
    unsafe {
        gl::GetShaderiv(name, gl::COMPILE_STATUS,  &mut status);
        gl::GetShaderiv(name, gl::INFO_LOG_LENGTH, &mut length);
    }
    let mut info = String::with_capacity(length as uint);
    info.grow(length as uint, 0u8 as char);
    unsafe {
        gl::GetShaderInfoLog(name, length, &mut length,
            info.as_slice().as_ptr() as *mut gl::types::GLchar);
    }
    info.truncate(length as uint);
    (if status != 0 {Some(name)} else {None}, info)
}

fn query_program_int(prog: super::Program, query: gl::types::GLenum) -> gl::types::GLint {
    let mut ret = 0 as gl::types::GLint;
    unsafe {
        gl::GetProgramiv(prog, query, &mut ret);
    }
    ret
}

enum StorageType {
    Var(s::BaseType, s::ContainerType),
    Sampler(s::BaseType, s::SamplerType),
    Unknown,
}

impl StorageType {
    fn new(storage: gl::types::GLenum) -> StorageType {
        match storage {
            gl::FLOAT                        => Var(s::BaseF32, s::Single),
            gl::FLOAT_VEC2                   => Var(s::BaseF32, s::Vector(2)),
            gl::FLOAT_VEC3                   => Var(s::BaseF32, s::Vector(3)),
            gl::FLOAT_VEC4                   => Var(s::BaseF32, s::Vector(4)),

            gl::INT                          => Var(s::BaseI32, s::Single),
            gl::INT_VEC2                     => Var(s::BaseI32, s::Vector(4)),
            gl::INT_VEC3                     => Var(s::BaseI32, s::Vector(4)),
            gl::INT_VEC4                     => Var(s::BaseI32, s::Vector(4)),

            gl::UNSIGNED_INT                 => Var(s::BaseU32, s::Single),
            gl::UNSIGNED_INT_VEC2            => Var(s::BaseU32, s::Vector(2)),
            gl::UNSIGNED_INT_VEC3            => Var(s::BaseU32, s::Vector(1)),
            gl::UNSIGNED_INT_VEC4            => Var(s::BaseU32, s::Vector(4)),

            gl::BOOL                         => Var(s::BaseBool, s::Single),
            gl::BOOL_VEC2                    => Var(s::BaseBool, s::Vector(2)),
            gl::BOOL_VEC3                    => Var(s::BaseBool, s::Vector(3)),
            gl::BOOL_VEC4                    => Var(s::BaseBool, s::Vector(4)),

            gl::FLOAT_MAT2                   => Var(s::BaseF32, s::Matrix(s::ColumnMajor, 2, 2)),
            gl::FLOAT_MAT3                   => Var(s::BaseF32, s::Matrix(s::ColumnMajor, 3, 3)),
            gl::FLOAT_MAT4                   => Var(s::BaseF32, s::Matrix(s::ColumnMajor, 4, 4)),
            gl::FLOAT_MAT2x3                 => Var(s::BaseF32, s::Matrix(s::ColumnMajor, 2, 3)),
            gl::FLOAT_MAT2x4                 => Var(s::BaseF32, s::Matrix(s::ColumnMajor, 2, 4)),
            gl::FLOAT_MAT3x2                 => Var(s::BaseF32, s::Matrix(s::ColumnMajor, 3, 2)),
            gl::FLOAT_MAT3x4                 => Var(s::BaseF32, s::Matrix(s::ColumnMajor, 3, 4)),
            gl::FLOAT_MAT4x2                 => Var(s::BaseF32, s::Matrix(s::ColumnMajor, 4, 2)),
            gl::FLOAT_MAT4x3                 => Var(s::BaseF32, s::Matrix(s::ColumnMajor, 4, 3)),

            // TODO: double matrices

            gl::SAMPLER_1D                   => Sampler(s::BaseF32, s::Sampler1D(s::NoArray, s::NoShadow)),
            gl::SAMPLER_1D_ARRAY             => Sampler(s::BaseF32, s::Sampler1D(s::Array,   s::NoShadow)),
            gl::SAMPLER_1D_SHADOW            => Sampler(s::BaseF32, s::Sampler1D(s::NoArray, s::Shadow)),
            gl::SAMPLER_1D_ARRAY_SHADOW      => Sampler(s::BaseF32, s::Sampler1D(s::Array,   s::Shadow)),

            gl::SAMPLER_2D                   => Sampler(s::BaseF32, s::Sampler2D(s::NoArray, s::NoShadow, s::NoMultiSample, s::NoRect)),
            gl::SAMPLER_2D_ARRAY             => Sampler(s::BaseF32, s::Sampler2D(s::Array,   s::NoShadow, s::NoMultiSample, s::NoRect)),
            gl::SAMPLER_2D_SHADOW            => Sampler(s::BaseF32, s::Sampler2D(s::NoArray, s::Shadow,   s::NoMultiSample, s::NoRect)),
            gl::SAMPLER_2D_MULTISAMPLE       => Sampler(s::BaseF32, s::Sampler2D(s::NoArray, s::NoShadow, s::MultiSample,   s::NoRect)),
            gl::SAMPLER_2D_RECT              => Sampler(s::BaseF32, s::Sampler2D(s::NoArray, s::NoShadow, s::NoMultiSample, s::Rect)),
            gl::SAMPLER_2D_ARRAY_SHADOW      => Sampler(s::BaseF32, s::Sampler2D(s::Array,   s::Shadow,   s::NoMultiSample, s::NoRect)),
            gl::SAMPLER_2D_MULTISAMPLE_ARRAY => Sampler(s::BaseF32, s::Sampler2D(s::Array,   s::NoShadow, s::MultiSample,   s::NoRect)),
            gl::SAMPLER_2D_RECT_SHADOW       => Sampler(s::BaseF32, s::Sampler2D(s::NoArray, s::Shadow,   s::NoMultiSample, s::Rect)),

            gl::SAMPLER_3D                   => Sampler(s::BaseF32, s::Sampler3D),
            gl::SAMPLER_CUBE                 => Sampler(s::BaseF32, s::SamplerCube(s::NoShadow)),
            gl::SAMPLER_CUBE_SHADOW          => Sampler(s::BaseF32, s::SamplerCube(s::Shadow)),

            // TODO: int samplers

            // TODO: unsigned samplers

            _ => Unknown,
        }
    }
}

fn query_attributes(prog: super::Program) -> Vec<s::Attribute> {
    let num     = query_program_int(prog, gl::ACTIVE_ATTRIBUTES);
    let max_len = query_program_int(prog, gl::ACTIVE_ATTRIBUTE_MAX_LENGTH);
    let mut name = String::with_capacity(max_len as uint);
    name.grow(max_len as uint, 0u8 as char);
    range(0, num as gl::types::GLuint).map(|i| {
        let mut length = 0 as gl::types::GLint;
        let mut size = 0 as gl::types::GLint;
        let mut storage = 0 as gl::types::GLenum;
        let loc = unsafe {
            let raw = name.as_slice().as_ptr() as *mut gl::types::GLchar;
            gl::GetActiveAttrib(prog, i, max_len, &mut length, &mut size, &mut storage, raw);
            gl::GetAttribLocation(prog, raw as *gl::types::GLchar)
        };
        let real_name = name.as_slice().slice_to(length as uint).to_string();
        let (base, container) = match StorageType::new(storage) {
            Var(b, c) => (b, c),
            _ => fail!("Unrecognized attribute storage: {}", storage)
        };
        info!("\t\tAttrib[{}] = '{}'\t{}\t{}", loc, real_name, base, container);
        s::Attribute {
            name: real_name,
            location: loc as uint,
            count: size as uint,
            base_type: base,
            container: container,
        }
    }).collect()
}

fn query_blocks(prog: super::Program) -> Vec<s::BlockVar> {
    let num     = query_program_int(prog, gl::ACTIVE_UNIFORM_BLOCKS);
    range(0, num as gl::types::GLuint).map(|i| {
        let mut length  = 0 as gl::types::GLint;
        let mut size    = 0 as gl::types::GLint;
        let mut tmp     = 0 as gl::types::GLint;
        let mut usage = 0u8;
        unsafe {
            gl::GetActiveUniformBlockiv(prog, i, gl::UNIFORM_BLOCK_NAME_LENGTH, &mut size);
            for (stage, &eval) in [gl::UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER,
                    gl::UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER].iter().enumerate() {
                gl::GetActiveUniformBlockiv(prog, i, eval, &mut tmp);
                if tmp != 0 {usage |= 1<<stage;}
            }
        }
        let mut name = String::with_capacity(size as uint); //includes terminating null
        name.grow(size as uint, 0u8 as char);
        let mut actual_name_size = 0 as gl::types::GLint;
        unsafe {
            gl::GetActiveUniformBlockName(prog, i, size, &mut actual_name_size,
                name.as_slice().as_ptr() as *mut gl::types::GLchar);
            gl::GetActiveUniformBlockiv(prog, i, gl::UNIFORM_BLOCK_DATA_SIZE, &mut size);
        }
        name.truncate(actual_name_size as uint);
        info!("\t\tBlock '{}' of size {}", name, size);
        s::BlockVar {
            name: name,
            size: size as uint,
            usage: usage,
            active_slot: Cell::new(0),
        }
    }).collect()
}

fn query_parameters(prog: super::Program) -> (Vec<s::UniformVar>, Vec<s::SamplerVar>) {
    let mut uniforms = Vec::new();
    let mut textures = Vec::new();
    let total_num = query_program_int(prog, gl::ACTIVE_UNIFORMS);
    let indices: Vec<gl::types::GLuint> = range(0, total_num as gl::types::GLuint).collect();
    let mut block_indices = Vec::from_elem(total_num as uint, 0 as gl::types::GLint);
    unsafe {
        gl::GetActiveUniformsiv(prog, total_num as gl::types::GLsizei,
            indices.as_slice().as_ptr(), gl::UNIFORM_BLOCK_INDEX,
            block_indices.as_mut_slice().as_mut_ptr());
        //TODO: UNIFORM_IS_ROW_MAJOR
    }
    // prepare the name string
    let max_len = query_program_int(prog, gl::ACTIVE_UNIFORM_MAX_LENGTH);
    let mut name = String::with_capacity(max_len as uint);
    name.grow(max_len as uint, 0u8 as char);
    // walk the indices
    for (&i, _) in indices.iter().zip(block_indices.iter()).filter(|&(_, &b)| b<0) {
        let mut length = 0 as gl::types::GLint;
        let mut size = 0 as gl::types::GLint;
        let mut storage = 0 as gl::types::GLenum;
        let loc = unsafe {
            let raw = name.as_slice().as_ptr() as *mut gl::types::GLchar;
            gl::GetActiveUniform(prog, i,
                max_len, &mut length, &mut size, &mut storage, raw);
            gl::GetUniformLocation(prog, raw as *gl::types::GLchar)
        };
        let real_name = name.as_slice().slice_to(length as uint).to_string();
        match StorageType::new(storage) {
            Var(base, container) => {
                info!("\t\tUniform[{}] = '{}'\t{}\t{}", loc, real_name, base, container);
                uniforms.push(s::UniformVar {
                    name: real_name,
                    location: loc as uint,
                    count: size as uint,
                    base_type: base,
                    container: container,
                    active_value: Cell::new(s::ValueUnitialized),
                });
            },
            Sampler(base, sam_type) => {
                info!("\t\tSampler[{}] = '{}'\t{}\t{}", loc, real_name, base, sam_type);
                textures.push(s::SamplerVar {
                    name: real_name,
                    location: loc as uint,
                    base_type: base,
                    sampler_type: sam_type,
                    active_slot: Cell::new(0),
                });
            },
            Unknown => fail!("Unrecognized uniform storage: {}", storage)
        }
    }
    (uniforms, textures)
}

pub fn create_program(shaders: &[super::Shader]) -> (Option<s::ProgramMeta>, String) {
    let name = gl::CreateProgram();
    for &sh in shaders.iter() {
        gl::AttachShader(name, sh);
    }
    gl::LinkProgram(name);
    info!("\tLinked program {}", name);
    // get info message
    let status      = query_program_int(name, gl::LINK_STATUS);
    let mut length  = query_program_int(name, gl::INFO_LOG_LENGTH);
    let mut info = String::with_capacity(length as uint);
    info.grow(length as uint, 0u8 as char);
    unsafe {
        gl::GetProgramInfoLog(name, length, &mut length,
            info.as_slice().as_ptr() as *mut gl::types::GLchar);
    }
    info.truncate(length as uint);
    (if status != 0 {
        let (uniforms, textures) = query_parameters(name);
        let meta = s::ProgramMeta {
            name: name,
            attributes: query_attributes(name),
            uniforms: uniforms,
            blocks: query_blocks(name),
            textures: textures,
        };
        Some(meta)
    }else {
        None
    }, info)
}
<commit_msg>Fix dimensions<commit_after>// Copyright 2014 The Gfx-rs Developers.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use s = super::super::shade;
use super::gl;
use std::cell::Cell;

pub fn create_object(stage: s::Stage, data: &[u8]) -> (Option<super::Shader>, String) {
    let target = match stage {
        s::Vertex => gl::VERTEX_SHADER,
        s::Geometry => gl::GEOMETRY_SHADER,
        s::Fragment => gl::FRAGMENT_SHADER,
    };
    let name = gl::CreateShader(target);
    let mut length = data.len() as gl::types::GLint;
    unsafe {
        gl::ShaderSource(name, 1, &(data.as_ptr() as *gl::types::GLchar), &length);
    }
    gl::CompileShader(name);
    info!("\tCompiled shader {}", name);
    // get info message
    let mut status = 0 as gl::types::GLint;
    length = 0;
    unsafe {
        gl::GetShaderiv(name, gl::COMPILE_STATUS,  &mut status);
        gl::GetShaderiv(name, gl::INFO_LOG_LENGTH, &mut length);
    }
    let mut info = String::with_capacity(length as uint);
    info.grow(length as uint, 0u8 as char);
    unsafe {
        gl::GetShaderInfoLog(name, length, &mut length,
            info.as_slice().as_ptr() as *mut gl::types::GLchar);
    }
    info.truncate(length as uint);
    (if status != 0 {Some(name)} else {None}, info)
}

fn query_program_int(prog: super::Program, query: gl::types::GLenum) -> gl::types::GLint {
    let mut ret = 0 as gl::types::GLint;
    unsafe {
        gl::GetProgramiv(prog, query, &mut ret);
    }
    ret
}

enum StorageType {
    Var(s::BaseType, s::ContainerType),
    Sampler(s::BaseType, s::SamplerType),
    Unknown,
}

impl StorageType {
    fn new(storage: gl::types::GLenum) -> StorageType {
        match storage {
            gl::FLOAT                        => Var(s::BaseF32, s::Single),
            gl::FLOAT_VEC2                   => Var(s::BaseF32, s::Vector(2)),
            gl::FLOAT_VEC3                   => Var(s::BaseF32, s::Vector(3)),
            gl::FLOAT_VEC4                   => Var(s::BaseF32, s::Vector(4)),

            gl::INT                          => Var(s::BaseI32, s::Single),
            gl::INT_VEC2                     => Var(s::BaseI32, s::Vector(2)),
            gl::INT_VEC3                     => Var(s::BaseI32, s::Vector(3)),
            gl::INT_VEC4                     => Var(s::BaseI32, s::Vector(4)),

            gl::UNSIGNED_INT                 => Var(s::BaseU32, s::Single),
            gl::UNSIGNED_INT_VEC2            => Var(s::BaseU32, s::Vector(2)),
            gl::UNSIGNED_INT_VEC3            => Var(s::BaseU32, s::Vector(3)),
            gl::UNSIGNED_INT_VEC4            => Var(s::BaseU32, s::Vector(4)),

            gl::BOOL                         => Var(s::BaseBool, s::Single),
            gl::BOOL_VEC2                    => Var(s::BaseBool, s::Vector(2)),
            gl::BOOL_VEC3                    => Var(s::BaseBool, s::Vector(3)),
            gl::BOOL_VEC4                    => Var(s::BaseBool, s::Vector(4)),

            gl::FLOAT_MAT2                   => Var(s::BaseF32, s::Matrix(s::ColumnMajor, 2, 2)),
            gl::FLOAT_MAT3                   => Var(s::BaseF32, s::Matrix(s::ColumnMajor, 3, 3)),
            gl::FLOAT_MAT4                   => Var(s::BaseF32, s::Matrix(s::ColumnMajor, 4, 4)),
            gl::FLOAT_MAT2x3                 => Var(s::BaseF32, s::Matrix(s::ColumnMajor, 2, 3)),
            gl::FLOAT_MAT2x4                 => Var(s::BaseF32, s::Matrix(s::ColumnMajor, 2, 4)),
            gl::FLOAT_MAT3x2                 => Var(s::BaseF32, s::Matrix(s::ColumnMajor, 3, 2)),
            gl::FLOAT_MAT3x4                 => Var(s::BaseF32, s::Matrix(s::ColumnMajor, 3, 4)),
            gl::FLOAT_MAT4x2                 => Var(s::BaseF32, s::Matrix(s::ColumnMajor, 4, 2)),
            gl::FLOAT_MAT4x3                 => Var(s::BaseF32, s::Matrix(s::ColumnMajor, 4, 3)),

            // TODO: double matrices

            gl::SAMPLER_1D                   => Sampler(s::BaseF32, s::Sampler1D(s::NoArray, s::NoShadow)),
            gl::SAMPLER_1D_ARRAY             => Sampler(s::BaseF32, s::Sampler1D(s::Array,   s::NoShadow)),
            gl::SAMPLER_1D_SHADOW            => Sampler(s::BaseF32, s::Sampler1D(s::NoArray, s::Shadow)),
            gl::SAMPLER_1D_ARRAY_SHADOW      => Sampler(s::BaseF32, s::Sampler1D(s::Array,   s::Shadow)),

            gl::SAMPLER_2D                   => Sampler(s::BaseF32, s::Sampler2D(s::NoArray, s::NoShadow, s::NoMultiSample, s::NoRect)),
            gl::SAMPLER_2D_ARRAY             => Sampler(s::BaseF32, s::Sampler2D(s::Array,   s::NoShadow, s::NoMultiSample, s::NoRect)),
            gl::SAMPLER_2D_SHADOW            => Sampler(s::BaseF32, s::Sampler2D(s::NoArray, s::Shadow,   s::NoMultiSample, s::NoRect)),
            gl::SAMPLER_2D_MULTISAMPLE       => Sampler(s::BaseF32, s::Sampler2D(s::NoArray, s::NoShadow, s::MultiSample,   s::NoRect)),
            gl::SAMPLER_2D_RECT              => Sampler(s::BaseF32, s::Sampler2D(s::NoArray, s::NoShadow, s::NoMultiSample, s::Rect)),
            gl::SAMPLER_2D_ARRAY_SHADOW      => Sampler(s::BaseF32, s::Sampler2D(s::Array,   s::Shadow,   s::NoMultiSample, s::NoRect)),
            gl::SAMPLER_2D_MULTISAMPLE_ARRAY => Sampler(s::BaseF32, s::Sampler2D(s::Array,   s::NoShadow, s::MultiSample,   s::NoRect)),
            gl::SAMPLER_2D_RECT_SHADOW       => Sampler(s::BaseF32, s::Sampler2D(s::NoArray, s::Shadow,   s::NoMultiSample, s::Rect)),

            gl::SAMPLER_3D                   => Sampler(s::BaseF32, s::Sampler3D),
            gl::SAMPLER_CUBE                 => Sampler(s::BaseF32, s::SamplerCube(s::NoShadow)),
            gl::SAMPLER_CUBE_SHADOW          => Sampler(s::BaseF32, s::SamplerCube(s::Shadow)),

            // TODO: int samplers

            // TODO: unsigned samplers

            _ => Unknown,
        }
    }
}

fn query_attributes(prog: super::Program) -> Vec<s::Attribute> {
    let num     = query_program_int(prog, gl::ACTIVE_ATTRIBUTES);
    let max_len = query_program_int(prog, gl::ACTIVE_ATTRIBUTE_MAX_LENGTH);
    let mut name = String::with_capacity(max_len as uint);
    name.grow(max_len as uint, 0u8 as char);
    range(0, num as gl::types::GLuint).map(|i| {
        let mut length = 0 as gl::types::GLint;
        let mut size = 0 as gl::types::GLint;
        let mut storage = 0 as gl::types::GLenum;
        let loc = unsafe {
            let raw = name.as_slice().as_ptr() as *mut gl::types::GLchar;
            gl::GetActiveAttrib(prog, i, max_len, &mut length, &mut size, &mut storage, raw);
            gl::GetAttribLocation(prog, raw as *gl::types::GLchar)
        };
        let real_name = name.as_slice().slice_to(length as uint).to_string();
        let (base, container) = match StorageType::new(storage) {
            Var(b, c) => (b, c),
            _ => fail!("Unrecognized attribute storage: {}", storage)
        };
        info!("\t\tAttrib[{}] = '{}'\t{}\t{}", loc, real_name, base, container);
        s::Attribute {
            name: real_name,
            location: loc as uint,
            count: size as uint,
            base_type: base,
            container: container,
        }
    }).collect()
}

fn query_blocks(prog: super::Program) -> Vec<s::BlockVar> {
    let num     = query_program_int(prog, gl::ACTIVE_UNIFORM_BLOCKS);
    range(0, num as gl::types::GLuint).map(|i| {
        let mut length  = 0 as gl::types::GLint;
        let mut size    = 0 as gl::types::GLint;
        let mut tmp     = 0 as gl::types::GLint;
        let mut usage = 0u8;
        unsafe {
            gl::GetActiveUniformBlockiv(prog, i, gl::UNIFORM_BLOCK_NAME_LENGTH, &mut size);
            for (stage, &eval) in [gl::UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER,
                    gl::UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER].iter().enumerate() {
                gl::GetActiveUniformBlockiv(prog, i, eval, &mut tmp);
                if tmp != 0 {usage |= 1<<stage;}
            }
        }
        let mut name = String::with_capacity(size as uint); //includes terminating null
        name.grow(size as uint, 0u8 as char);
        let mut actual_name_size = 0 as gl::types::GLint;
        unsafe {
            gl::GetActiveUniformBlockName(prog, i, size, &mut actual_name_size,
                name.as_slice().as_ptr() as *mut gl::types::GLchar);
            gl::GetActiveUniformBlockiv(prog, i, gl::UNIFORM_BLOCK_DATA_SIZE, &mut size);
        }
        name.truncate(actual_name_size as uint);
        info!("\t\tBlock '{}' of size {}", name, size);
        s::BlockVar {
            name: name,
            size: size as uint,
            usage: usage,
            active_slot: Cell::new(0),
        }
    }).collect()
}

fn query_parameters(prog: super::Program) -> (Vec<s::UniformVar>, Vec<s::SamplerVar>) {
    let mut uniforms = Vec::new();
    let mut textures = Vec::new();
    let total_num = query_program_int(prog, gl::ACTIVE_UNIFORMS);
    let indices: Vec<gl::types::GLuint> = range(0, total_num as gl::types::GLuint).collect();
    let mut block_indices = Vec::from_elem(total_num as uint, 0 as gl::types::GLint);
    unsafe {
        gl::GetActiveUniformsiv(prog, total_num as gl::types::GLsizei,
            indices.as_slice().as_ptr(), gl::UNIFORM_BLOCK_INDEX,
            block_indices.as_mut_slice().as_mut_ptr());
        //TODO: UNIFORM_IS_ROW_MAJOR
    }
    // prepare the name string
    let max_len = query_program_int(prog, gl::ACTIVE_UNIFORM_MAX_LENGTH);
    let mut name = String::with_capacity(max_len as uint);
    name.grow(max_len as uint, 0u8 as char);
    // walk the indices
    for (&i, _) in indices.iter().zip(block_indices.iter()).filter(|&(_, &b)| b<0) {
        let mut length = 0 as gl::types::GLint;
        let mut size = 0 as gl::types::GLint;
        let mut storage = 0 as gl::types::GLenum;
        let loc = unsafe {
            let raw = name.as_slice().as_ptr() as *mut gl::types::GLchar;
            gl::GetActiveUniform(prog, i,
                max_len, &mut length, &mut size, &mut storage, raw);
            gl::GetUniformLocation(prog, raw as *gl::types::GLchar)
        };
        let real_name = name.as_slice().slice_to(length as uint).to_string();
        match StorageType::new(storage) {
            Var(base, container) => {
                info!("\t\tUniform[{}] = '{}'\t{}\t{}", loc, real_name, base, container);
                uniforms.push(s::UniformVar {
                    name: real_name,
                    location: loc as uint,
                    count: size as uint,
                    base_type: base,
                    container: container,
                    active_value: Cell::new(s::ValueUnitialized),
                });
            },
            Sampler(base, sam_type) => {
                info!("\t\tSampler[{}] = '{}'\t{}\t{}", loc, real_name, base, sam_type);
                textures.push(s::SamplerVar {
                    name: real_name,
                    location: loc as uint,
                    base_type: base,
                    sampler_type: sam_type,
                    active_slot: Cell::new(0),
                });
            },
            Unknown => fail!("Unrecognized uniform storage: {}", storage)
        }
    }
    (uniforms, textures)
}

pub fn create_program(shaders: &[super::Shader]) -> (Option<s::ProgramMeta>, String) {
    let name = gl::CreateProgram();
    for &sh in shaders.iter() {
        gl::AttachShader(name, sh);
    }
    gl::LinkProgram(name);
    info!("\tLinked program {}", name);
    // get info message
    let status      = query_program_int(name, gl::LINK_STATUS);
    let mut length  = query_program_int(name, gl::INFO_LOG_LENGTH);
    let mut info = String::with_capacity(length as uint);
    info.grow(length as uint, 0u8 as char);
    unsafe {
        gl::GetProgramInfoLog(name, length, &mut length,
            info.as_slice().as_ptr() as *mut gl::types::GLchar);
    }
    info.truncate(length as uint);
    (if status != 0 {
        let (uniforms, textures) = query_parameters(name);
        let meta = s::ProgramMeta {
            name: name,
            attributes: query_attributes(name),
            uniforms: uniforms,
            blocks: query_blocks(name),
            textures: textures,
        };
        Some(meta)
    }else {
        None
    }, info)
}
<|endoftext|>


<commit_before><commit_msg>Remove the depth image barrier as I don't think it influences anything given the order of submissions<commit_after><|endoftext|>


<commit_before><commit_msg>Add bindings.rs for PAM module generated by bindgen<commit_after>/* automatically generated by rust-bindgen */

pub const __LINUX_PAM__: ::std::os::raw::c_uint = 1;
pub const __LINUX_PAM_MINOR__: ::std::os::raw::c_uint = 0;
pub const PAM_SUCCESS: ::std::os::raw::c_uint = 0;
pub const PAM_OPEN_ERR: ::std::os::raw::c_uint = 1;
pub const PAM_SYMBOL_ERR: ::std::os::raw::c_uint = 2;
pub const PAM_SERVICE_ERR: ::std::os::raw::c_uint = 3;
pub const PAM_SYSTEM_ERR: ::std::os::raw::c_uint = 4;
pub const PAM_BUF_ERR: ::std::os::raw::c_uint = 5;
pub const PAM_PERM_DENIED: ::std::os::raw::c_uint = 6;
pub const PAM_AUTH_ERR: ::std::os::raw::c_uint = 7;
pub const PAM_CRED_INSUFFICIENT: ::std::os::raw::c_uint = 8;
pub const PAM_AUTHINFO_UNAVAIL: ::std::os::raw::c_uint = 9;
pub const PAM_USER_UNKNOWN: ::std::os::raw::c_uint = 10;
pub const PAM_MAXTRIES: ::std::os::raw::c_uint = 11;
pub const PAM_NEW_AUTHTOK_REQD: ::std::os::raw::c_uint = 12;
pub const PAM_ACCT_EXPIRED: ::std::os::raw::c_uint = 13;
pub const PAM_SESSION_ERR: ::std::os::raw::c_uint = 14;
pub const PAM_CRED_UNAVAIL: ::std::os::raw::c_uint = 15;
pub const PAM_CRED_EXPIRED: ::std::os::raw::c_uint = 16;
pub const PAM_CRED_ERR: ::std::os::raw::c_uint = 17;
pub const PAM_NO_MODULE_DATA: ::std::os::raw::c_uint = 18;
pub const PAM_CONV_ERR: ::std::os::raw::c_uint = 19;
pub const PAM_AUTHTOK_ERR: ::std::os::raw::c_uint = 20;
pub const PAM_AUTHTOK_RECOVERY_ERR: ::std::os::raw::c_uint = 21;
pub const PAM_AUTHTOK_LOCK_BUSY: ::std::os::raw::c_uint = 22;
pub const PAM_AUTHTOK_DISABLE_AGING: ::std::os::raw::c_uint = 23;
pub const PAM_TRY_AGAIN: ::std::os::raw::c_uint = 24;
pub const PAM_IGNORE: ::std::os::raw::c_uint = 25;
pub const PAM_ABORT: ::std::os::raw::c_uint = 26;
pub const PAM_AUTHTOK_EXPIRED: ::std::os::raw::c_uint = 27;
pub const PAM_MODULE_UNKNOWN: ::std::os::raw::c_uint = 28;
pub const PAM_BAD_ITEM: ::std::os::raw::c_uint = 29;
pub const PAM_CONV_AGAIN: ::std::os::raw::c_uint = 30;
pub const PAM_INCOMPLETE: ::std::os::raw::c_uint = 31;
pub const _PAM_RETURN_VALUES: ::std::os::raw::c_uint = 32;
pub const PAM_SILENT: ::std::os::raw::c_uint = 32768;
pub const PAM_DISALLOW_NULL_AUTHTOK: ::std::os::raw::c_uint = 1;
pub const PAM_ESTABLISH_CRED: ::std::os::raw::c_uint = 2;
pub const PAM_DELETE_CRED: ::std::os::raw::c_uint = 4;
pub const PAM_REINITIALIZE_CRED: ::std::os::raw::c_uint = 8;
pub const PAM_REFRESH_CRED: ::std::os::raw::c_uint = 16;
pub const PAM_CHANGE_EXPIRED_AUTHTOK: ::std::os::raw::c_uint = 32;
pub const PAM_SERVICE: ::std::os::raw::c_uint = 1;
pub const PAM_USER: ::std::os::raw::c_uint = 2;
pub const PAM_TTY: ::std::os::raw::c_uint = 3;
pub const PAM_RHOST: ::std::os::raw::c_uint = 4;
pub const PAM_CONV: ::std::os::raw::c_uint = 5;
pub const PAM_AUTHTOK: ::std::os::raw::c_uint = 6;
pub const PAM_OLDAUTHTOK: ::std::os::raw::c_uint = 7;
pub const PAM_RUSER: ::std::os::raw::c_uint = 8;
pub const PAM_USER_PROMPT: ::std::os::raw::c_uint = 9;
pub const PAM_FAIL_DELAY: ::std::os::raw::c_uint = 10;
pub const PAM_XDISPLAY: ::std::os::raw::c_uint = 11;
pub const PAM_XAUTHDATA: ::std::os::raw::c_uint = 12;
pub const PAM_AUTHTOK_TYPE: ::std::os::raw::c_uint = 13;
pub const PAM_DATA_SILENT: ::std::os::raw::c_uint = 1073741824;
pub const PAM_PROMPT_ECHO_OFF: ::std::os::raw::c_uint = 1;
pub const PAM_PROMPT_ECHO_ON: ::std::os::raw::c_uint = 2;
pub const PAM_ERROR_MSG: ::std::os::raw::c_uint = 3;
pub const PAM_TEXT_INFO: ::std::os::raw::c_uint = 4;
pub const PAM_RADIO_TYPE: ::std::os::raw::c_uint = 5;
pub const PAM_BINARY_PROMPT: ::std::os::raw::c_uint = 7;
pub const PAM_MAX_NUM_MSG: ::std::os::raw::c_uint = 32;
pub const PAM_MAX_MSG_SIZE: ::std::os::raw::c_uint = 512;
pub const PAM_MAX_RESP_SIZE: ::std::os::raw::c_uint = 512;
pub const PAM_AUTHTOK_RECOVER_ERR: ::std::os::raw::c_uint = 21;
pub const PAM_PRELIM_CHECK: ::std::os::raw::c_uint = 16384;
pub const PAM_UPDATE_AUTHTOK: ::std::os::raw::c_uint = 8192;
pub const PAM_DATA_REPLACE: ::std::os::raw::c_uint = 536870912;
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct pam_handle {
    _unused: [u8; 0],
}
pub type pam_handle_t = pam_handle;
extern "C" {
    pub fn pam_set_item(pamh: *mut pam_handle_t,
                        item_type: ::std::os::raw::c_int,
                        item: *const ::std::os::raw::c_void)
     -> ::std::os::raw::c_int;
}
extern "C" {
    pub fn pam_get_item(pamh: *const pam_handle_t,
                        item_type: ::std::os::raw::c_int,
                        item: *mut *const ::std::os::raw::c_void)
     -> ::std::os::raw::c_int;
}
extern "C" {
    pub fn pam_strerror(pamh: *mut pam_handle_t,
                        errnum: ::std::os::raw::c_int)
     -> *const ::std::os::raw::c_char;
}
extern "C" {
    pub fn pam_putenv(pamh: *mut pam_handle_t,
                      name_value: *const ::std::os::raw::c_char)
     -> ::std::os::raw::c_int;
}
extern "C" {
    pub fn pam_getenv(pamh: *mut pam_handle_t,
                      name: *const ::std::os::raw::c_char)
     -> *const ::std::os::raw::c_char;
}
extern "C" {
    pub fn pam_getenvlist(pamh: *mut pam_handle_t)
     -> *mut *mut ::std::os::raw::c_char;
}
extern "C" {
    pub fn pam_fail_delay(pamh: *mut pam_handle_t,
                          musec_delay: ::std::os::raw::c_uint)
     -> ::std::os::raw::c_int;
}
#[repr(C)]
#[derive(Debug, Copy)]
pub struct pam_message {
    pub msg_style: ::std::os::raw::c_int,
    pub msg: *const ::std::os::raw::c_char,
}
#[test]
fn bindgen_test_layout_pam_message() {
    assert_eq!(::std::mem::size_of::<pam_message>() , 16usize , concat ! (
               "Size of: " , stringify ! ( pam_message ) ));
    assert_eq! (::std::mem::align_of::<pam_message>() , 8usize , concat ! (
                "Alignment of " , stringify ! ( pam_message ) ));
    assert_eq! (unsafe {
                & ( * ( 0 as * const pam_message ) ) . msg_style as * const _
                as usize } , 0usize , concat ! (
                "Alignment of field: " , stringify ! ( pam_message ) , "::" ,
                stringify ! ( msg_style ) ));
    assert_eq! (unsafe {
                & ( * ( 0 as * const pam_message ) ) . msg as * const _ as
                usize } , 8usize , concat ! (
                "Alignment of field: " , stringify ! ( pam_message ) , "::" ,
                stringify ! ( msg ) ));
}
impl Clone for pam_message {
    fn clone(&self) -> Self { *self }
}
#[repr(C)]
#[derive(Debug, Copy)]
pub struct pam_response {
    pub resp: *mut ::std::os::raw::c_char,
    pub resp_retcode: ::std::os::raw::c_int,
}
#[test]
fn bindgen_test_layout_pam_response() {
    assert_eq!(::std::mem::size_of::<pam_response>() , 16usize , concat ! (
               "Size of: " , stringify ! ( pam_response ) ));
    assert_eq! (::std::mem::align_of::<pam_response>() , 8usize , concat ! (
                "Alignment of " , stringify ! ( pam_response ) ));
    assert_eq! (unsafe {
                & ( * ( 0 as * const pam_response ) ) . resp as * const _ as
                usize } , 0usize , concat ! (
                "Alignment of field: " , stringify ! ( pam_response ) , "::" ,
                stringify ! ( resp ) ));
    assert_eq! (unsafe {
                & ( * ( 0 as * const pam_response ) ) . resp_retcode as *
                const _ as usize } , 8usize , concat ! (
                "Alignment of field: " , stringify ! ( pam_response ) , "::" ,
                stringify ! ( resp_retcode ) ));
}
impl Clone for pam_response {
    fn clone(&self) -> Self { *self }
}
#[repr(C)]
#[derive(Debug, Copy)]
pub struct pam_conv {
    pub conv: ::std::option::Option<unsafe extern "C" fn(num_msg:
                                                             ::std::os::raw::c_int,
                                                         msg:
                                                             *mut *const pam_message,
                                                         resp:
                                                             *mut *mut pam_response,
                                                         appdata_ptr:
                                                             *mut ::std::os::raw::c_void)
                                        -> ::std::os::raw::c_int>,
    pub appdata_ptr: *mut ::std::os::raw::c_void,
}
#[test]
fn bindgen_test_layout_pam_conv() {
    assert_eq!(::std::mem::size_of::<pam_conv>() , 16usize , concat ! (
               "Size of: " , stringify ! ( pam_conv ) ));
    assert_eq! (::std::mem::align_of::<pam_conv>() , 8usize , concat ! (
                "Alignment of " , stringify ! ( pam_conv ) ));
    assert_eq! (unsafe {
                & ( * ( 0 as * const pam_conv ) ) . conv as * const _ as usize
                } , 0usize , concat ! (
                "Alignment of field: " , stringify ! ( pam_conv ) , "::" ,
                stringify ! ( conv ) ));
    assert_eq! (unsafe {
                & ( * ( 0 as * const pam_conv ) ) . appdata_ptr as * const _
                as usize } , 8usize , concat ! (
                "Alignment of field: " , stringify ! ( pam_conv ) , "::" ,
                stringify ! ( appdata_ptr ) ));
}
impl Clone for pam_conv {
    fn clone(&self) -> Self { *self }
}
#[repr(C)]
#[derive(Debug, Copy)]
pub struct pam_xauth_data {
    pub namelen: ::std::os::raw::c_int,
    pub name: *mut ::std::os::raw::c_char,
    pub datalen: ::std::os::raw::c_int,
    pub data: *mut ::std::os::raw::c_char,
}
#[test]
fn bindgen_test_layout_pam_xauth_data() {
    assert_eq!(::std::mem::size_of::<pam_xauth_data>() , 32usize , concat ! (
               "Size of: " , stringify ! ( pam_xauth_data ) ));
    assert_eq! (::std::mem::align_of::<pam_xauth_data>() , 8usize , concat ! (
                "Alignment of " , stringify ! ( pam_xauth_data ) ));
    assert_eq! (unsafe {
                & ( * ( 0 as * const pam_xauth_data ) ) . namelen as * const _
                as usize } , 0usize , concat ! (
                "Alignment of field: " , stringify ! ( pam_xauth_data ) , "::"
                , stringify ! ( namelen ) ));
    assert_eq! (unsafe {
                & ( * ( 0 as * const pam_xauth_data ) ) . name as * const _ as
                usize } , 8usize , concat ! (
                "Alignment of field: " , stringify ! ( pam_xauth_data ) , "::"
                , stringify ! ( name ) ));
    assert_eq! (unsafe {
                & ( * ( 0 as * const pam_xauth_data ) ) . datalen as * const _
                as usize } , 16usize , concat ! (
                "Alignment of field: " , stringify ! ( pam_xauth_data ) , "::"
                , stringify ! ( datalen ) ));
    assert_eq! (unsafe {
                & ( * ( 0 as * const pam_xauth_data ) ) . data as * const _ as
                usize } , 24usize , concat ! (
                "Alignment of field: " , stringify ! ( pam_xauth_data ) , "::"
                , stringify ! ( data ) ));
}
impl Clone for pam_xauth_data {
    fn clone(&self) -> Self { *self }
}
extern "C" {
    pub fn pam_start(service_name: *const ::std::os::raw::c_char,
                     user: *const ::std::os::raw::c_char,
                     pam_conversation: *const pam_conv,
                     pamh: *mut *mut pam_handle_t) -> ::std::os::raw::c_int;
}
extern "C" {
    pub fn pam_end(pamh: *mut pam_handle_t, pam_status: ::std::os::raw::c_int)
     -> ::std::os::raw::c_int;
}
extern "C" {
    pub fn pam_authenticate(pamh: *mut pam_handle_t,
                            flags: ::std::os::raw::c_int)
     -> ::std::os::raw::c_int;
}
extern "C" {
    pub fn pam_setcred(pamh: *mut pam_handle_t, flags: ::std::os::raw::c_int)
     -> ::std::os::raw::c_int;
}
extern "C" {
    pub fn pam_acct_mgmt(pamh: *mut pam_handle_t,
                         flags: ::std::os::raw::c_int)
     -> ::std::os::raw::c_int;
}
extern "C" {
    pub fn pam_open_session(pamh: *mut pam_handle_t,
                            flags: ::std::os::raw::c_int)
     -> ::std::os::raw::c_int;
}
extern "C" {
    pub fn pam_close_session(pamh: *mut pam_handle_t,
                             flags: ::std::os::raw::c_int)
     -> ::std::os::raw::c_int;
}
extern "C" {
    pub fn pam_chauthtok(pamh: *mut pam_handle_t,
                         flags: ::std::os::raw::c_int)
     -> ::std::os::raw::c_int;
}
extern "C" {
    pub fn pam_set_data(pamh: *mut pam_handle_t,
                        module_data_name: *const ::std::os::raw::c_char,
                        data: *mut ::std::os::raw::c_void,
                        cleanup:
                            ::std::option::Option<unsafe extern "C" fn(pamh:
                                                                           *mut pam_handle_t,
                                                                       data:
                                                                           *mut ::std::os::raw::c_void,
                                                                       error_status:
                                                                           ::std::os::raw::c_int)>)
     -> ::std::os::raw::c_int;
}
extern "C" {
    pub fn pam_get_data(pamh: *const pam_handle_t,
                        module_data_name: *const ::std::os::raw::c_char,
                        data: *mut *const ::std::os::raw::c_void)
     -> ::std::os::raw::c_int;
}
extern "C" {
    pub fn pam_get_user(pamh: *mut pam_handle_t,
                        user: *mut *const ::std::os::raw::c_char,
                        prompt: *const ::std::os::raw::c_char)
     -> ::std::os::raw::c_int;
}
/*
extern "C" {
    pub fn pam_sm_authenticate(pamh: *mut pam_handle_t,
                               flags: ::std::os::raw::c_int,
                               argc: ::std::os::raw::c_int,
                               argv: *mut *const ::std::os::raw::c_char)
     -> ::std::os::raw::c_int;
}
extern "C" {
    pub fn pam_sm_setcred(pamh: *mut pam_handle_t,
                          flags: ::std::os::raw::c_int,
                          argc: ::std::os::raw::c_int,
                          argv: *mut *const ::std::os::raw::c_char)
     -> ::std::os::raw::c_int;
}
extern "C" {
    pub fn pam_sm_acct_mgmt(pamh: *mut pam_handle_t,
                            flags: ::std::os::raw::c_int,
                            argc: ::std::os::raw::c_int,
                            argv: *mut *const ::std::os::raw::c_char)
     -> ::std::os::raw::c_int;
}
extern "C" {
    pub fn pam_sm_open_session(pamh: *mut pam_handle_t,
                               flags: ::std::os::raw::c_int,
                               argc: ::std::os::raw::c_int,
                               argv: *mut *const ::std::os::raw::c_char)
     -> ::std::os::raw::c_int;
}
extern "C" {
    pub fn pam_sm_close_session(pamh: *mut pam_handle_t,
                                flags: ::std::os::raw::c_int,
                                argc: ::std::os::raw::c_int,
                                argv: *mut *const ::std::os::raw::c_char)
     -> ::std::os::raw::c_int;
}
extern "C" {
    pub fn pam_sm_chauthtok(pamh: *mut pam_handle_t,
                            flags: ::std::os::raw::c_int,
                            argc: ::std::os::raw::c_int,
                            argv: *mut *const ::std::os::raw::c_char)
     -> ::std::os::raw::c_int;
}
*/
<|endoftext|>


<commit_before><commit_msg>test!<commit_after><|endoftext|>


<commit_before><commit_msg>Add two benches: parsing .debug_abbrev and parsing .debug_info<commit_after>#![feature(test)]

extern crate gimli;
extern crate test;

use gimli::{DebugAbbrev, DebugInfo, LittleEndian};

use std::env;
use std::fs::File;
use std::io::Read;
use std::path::PathBuf;

fn read_section(section: &str) -> Vec<u8> {
    let mut path = PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap());
    path.push("./fixtures/self/");
    path.push(section);

    assert!(path.is_file());
    let mut file = File::open(path).unwrap();

    let mut buf = Vec::new();
    file.read_to_end(&mut buf).unwrap();
    buf
}

#[bench]
fn bench_parsing_debug_abbrev(b: &mut test::Bencher) {
    let debug_abbrev = read_section("debug_abbrev");

    b.iter(|| {
        let debug_abbrev = DebugAbbrev::<LittleEndian>::new(&debug_abbrev);
        test::black_box(debug_abbrev.abbreviations().expect("Should parse abbreviations"));
    });
}

#[bench]
fn bench_parsing_debug_info(b: &mut test::Bencher) {
    let debug_abbrev = read_section("debug_abbrev");
    let debug_abbrev = DebugAbbrev::<LittleEndian>::new(&debug_abbrev);
    let abbrevs = debug_abbrev.abbreviations().expect("Should parse abbreviations");

    let debug_info = read_section("debug_info");

    b.iter(|| {
        let debug_info = DebugInfo::<LittleEndian>::new(&debug_info);

        for unit in debug_info.compilation_units() {
            let unit = unit.expect("Should parse compilation unit");

            let mut cursor = unit.entries(&abbrevs);

            loop {
                let entry = cursor.current()
                    .expect("Should have a current entry")
                    .expect("And should parse that entry OK");

                for attr in entry.attrs() {
                    test::black_box(attr.expect("Should parse entry's attribute"));
                }

                if let None = cursor.next_dfs() {
                    break;
                }
            }
        }
    });
}
<|endoftext|>


<commit_before>use file::{File, GREY};
use self::FileType::*;

use std::old_io as io;

use ansi_term::Style;
use ansi_term::Style::Plain;
use ansi_term::Colour::{Red, Green, Yellow, Blue, Cyan, Fixed};

#[derive(PartialEq, Debug, Copy)]
pub enum FileType {
    Normal, Directory, Executable, Immediate, Compiled, Symlink, Special,
    Image, Video, Music, Lossless, Compressed, Document, Temp, Crypto,
}

static IMAGE_TYPES: &'static [&'static str] = &[
    "png", "jpeg", "jpg", "gif", "bmp", "tiff", "tif",
    "ppm", "pgm", "pbm", "pnm", "webp", "raw", "arw",
    "svg", "stl", "eps", "dvi", "ps", "cbr",
    "cbz", "xpm", "ico" ];

static VIDEO_TYPES: &'static [&'static str] = &[
    "avi", "flv", "m2v", "mkv", "mov", "mp4", "mpeg",
    "mpg", "ogm", "ogv", "vob", "wmv" ];

static MUSIC_TYPES: &'static [&'static str] = &[
    "aac", "m4a", "mp3", "ogg", "wma" ];

static MUSIC_LOSSLESS: &'static [&'static str] = &[
    "alac", "ape", "flac", "wav" ];

static COMPRESSED_TYPES: &'static [&'static str] = &[
    "zip", "tar", "Z", "gz", "bz2", "a", "ar", "7z",
    "iso", "dmg", "tc", "rar", "par" ];

static DOCUMENT_TYPES: &'static [&'static str] = &[
    "djvu", "doc", "docx", "dvi", "eml", "eps", "fotd",
    "odp", "odt", "pdf", "ppt", "pptx", "rtf",
    "xls", "xlsx" ];

static TEMP_TYPES: &'static [&'static str] = &[
    "tmp", "swp", "swo", "swn", "bak" ];

static CRYPTO_TYPES: &'static [&'static str] = &[
    "asc", "gpg", "sig", "signature", "pgp" ];

static COMPILED_TYPES: &'static [&'static str] = &[
    "class", "elc", "hi", "o", "pyc" ];

static BUILD_TYPES: &'static [&'static str] = &[
    "Makefile", "Cargo.toml", "SConstruct", "CMakeLists.txt",
    "build.gradle", "Rakefile", "Gruntfile.js",
    "Gruntfile.coffee" ];

impl FileType {

    /// Get the `ansi_term::Style` that a file of this type should use.
    pub fn style(&self) -> Style {
        match *self {
            Normal     => Plain,
            Directory  => Blue.bold(),
            Symlink    => Cyan.normal(),
            Special    => Yellow.normal(),
            Executable => Green.bold(),
            Image      => Fixed(133).normal(),
            Video      => Fixed(135).normal(),
            Music      => Fixed(92).normal(),
            Lossless   => Fixed(93).normal(),
            Crypto     => Fixed(109).normal(),
            Document   => Fixed(105).normal(),
            Compressed => Red.normal(),
            Temp       => GREY.normal(),
            Immediate  => Yellow.bold().underline(),
            Compiled   => Fixed(137).normal(),
        }
    }
}

pub trait HasType {
    /// For a given file, find out what type it has.
    fn get_type(&self) -> FileType;
}

impl<'a> HasType for File<'a> {
    fn get_type(&self) -> FileType {
        let name = &self.name[..];
        if self.stat.kind == io::FileType::Directory {
            return Directory;
        }
        else if self.stat.kind == io::FileType::Symlink {
            return Symlink;
        }
        else if self.stat.kind == io::FileType::BlockSpecial || self.stat.kind == io::FileType::NamedPipe || self.stat.kind == io::FileType::Unknown {
            return Special;
        }
        else if self.stat.perm.contains(io::USER_EXECUTE) {
            return Executable;
        }
        else if name.starts_with("README") || BUILD_TYPES.iter().any(|&s| s == name) {
            return Immediate;
        }
        else if let Some(ref ext) = self.ext {
            if IMAGE_TYPES.iter().any(|&s| s == *ext) {
                return Image;
            }
            else if VIDEO_TYPES.iter().any(|&s| s == *ext) {
                return Video;
            }
            else if MUSIC_TYPES.iter().any(|&s| s == *ext) {
                return Music;
            }
            else if MUSIC_LOSSLESS.iter().any(|&s| s == *ext) {
                return Lossless;
            }
            else if CRYPTO_TYPES.iter().any(|&s| s == *ext) {
                return Crypto;
            }
            else if DOCUMENT_TYPES.iter().any(|&s| s == *ext) {
                return Document;
            }
            else if COMPRESSED_TYPES.iter().any(|&s| s == *ext) {
                return Compressed;
            }
            else if self.is_tmpfile() || TEMP_TYPES.iter().any(|&s| s == *ext) {
                return Temp;
            }

            let source_files = self.get_source_files();
            if source_files.is_empty() {
                return Normal;
            }
            else if source_files.iter().any(|path| self.dir.map(|d| d.contains(path)).unwrap_or(false)) {
                return Temp;
            }
            else if COMPILED_TYPES.iter().any(|&s| s == *ext) {
                return Compiled;
            }
        }

        return Normal;  // no filetype
    }
}

#[cfg(test)]
mod test {
    use super::*;
    use file::test::{dummy_stat, new_file};

    #[test]
    fn lowercase() {
        let file = new_file(dummy_stat(), "/barracks.wav");
        assert_eq!(FileType::Lossless, file.get_type())
    }

    #[test]
    fn uppercase() {
        let file = new_file(dummy_stat(), "/BARRACKS.WAV");
        assert_eq!(FileType::Lossless, file.get_type())
    }

    #[test]
    fn cargo() {
        let file = new_file(dummy_stat(), "/Cargo.toml");
        assert_eq!(FileType::Immediate, file.get_type())
    }

    #[test]
    fn not_cargo() {
        let file = new_file(dummy_stat(), "/cargo.toml");
        assert_eq!(FileType::Normal, file.get_type())
    }

}
<commit_msg>Simplify filetype detection code<commit_after>use file::{File, GREY};
use self::FileType::*;

use std::old_io as io;

use ansi_term::Style;
use ansi_term::Style::Plain;
use ansi_term::Colour::{Red, Green, Yellow, Blue, Cyan, Fixed};

#[derive(PartialEq, Debug, Copy)]
pub enum FileType {
    Normal, Directory, Executable, Immediate, Compiled, Symlink, Special,
    Image, Video, Music, Lossless, Compressed, Document, Temp, Crypto,
}

static IMAGE_TYPES: &'static [&'static str] = &[
    "png", "jpeg", "jpg", "gif", "bmp", "tiff", "tif",
    "ppm", "pgm", "pbm", "pnm", "webp", "raw", "arw",
    "svg", "stl", "eps", "dvi", "ps", "cbr",
    "cbz", "xpm", "ico" ];

static VIDEO_TYPES: &'static [&'static str] = &[
    "avi", "flv", "m2v", "mkv", "mov", "mp4", "mpeg",
    "mpg", "ogm", "ogv", "vob", "wmv" ];

static MUSIC_TYPES: &'static [&'static str] = &[
    "aac", "m4a", "mp3", "ogg", "wma" ];

static MUSIC_LOSSLESS: &'static [&'static str] = &[
    "alac", "ape", "flac", "wav" ];

static COMPRESSED_TYPES: &'static [&'static str] = &[
    "zip", "tar", "Z", "gz", "bz2", "a", "ar", "7z",
    "iso", "dmg", "tc", "rar", "par" ];

static DOCUMENT_TYPES: &'static [&'static str] = &[
    "djvu", "doc", "docx", "dvi", "eml", "eps", "fotd",
    "odp", "odt", "pdf", "ppt", "pptx", "rtf",
    "xls", "xlsx" ];

static TEMP_TYPES: &'static [&'static str] = &[
    "tmp", "swp", "swo", "swn", "bak" ];

static CRYPTO_TYPES: &'static [&'static str] = &[
    "asc", "gpg", "sig", "signature", "pgp" ];

static COMPILED_TYPES: &'static [&'static str] = &[
    "class", "elc", "hi", "o", "pyc" ];

static BUILD_TYPES: &'static [&'static str] = &[
    "Makefile", "Cargo.toml", "SConstruct", "CMakeLists.txt",
    "build.gradle", "Rakefile", "Gruntfile.js",
    "Gruntfile.coffee" ];

impl FileType {

    /// Get the `ansi_term::Style` that a file of this type should use.
    pub fn style(&self) -> Style {
        match *self {
            Normal     => Plain,
            Directory  => Blue.bold(),
            Symlink    => Cyan.normal(),
            Special    => Yellow.normal(),
            Executable => Green.bold(),
            Image      => Fixed(133).normal(),
            Video      => Fixed(135).normal(),
            Music      => Fixed(92).normal(),
            Lossless   => Fixed(93).normal(),
            Crypto     => Fixed(109).normal(),
            Document   => Fixed(105).normal(),
            Compressed => Red.normal(),
            Temp       => GREY.normal(),
            Immediate  => Yellow.bold().underline(),
            Compiled   => Fixed(137).normal(),
        }
    }
}

pub trait HasType {
    /// For a given file, find out what type it has.
    fn get_type(&self) -> FileType;
}

impl<'a> HasType for File<'a> {
    fn get_type(&self) -> FileType {

        match self.stat.kind {
            io::FileType::Directory    => return Directory,
            io::FileType::Symlink      => return Symlink,
            io::FileType::BlockSpecial => return Special,
            io::FileType::NamedPipe    => return Special,
            io::FileType::Unknown      => return Special,
            _ => {}
        }

        if self.name.starts_with("README") || BUILD_TYPES.contains(&&self.name[..]) {
            return Immediate;
        }
        else if let Some(ref ext) = self.ext {
            if IMAGE_TYPES.contains(&&ext[..]) {
                return Image;
            }
            else if VIDEO_TYPES.contains(&&ext[..]) {
                return Video;
            }
            else if MUSIC_TYPES.contains(&&ext[..]) {
                return Music;
            }
            else if MUSIC_LOSSLESS.contains(&&ext[..]) {
                return Lossless;
            }
            else if CRYPTO_TYPES.contains(&&ext[..]) {
                return Crypto;
            }
            else if DOCUMENT_TYPES.contains(&&ext[..]) {
                return Document;
            }
            else if COMPRESSED_TYPES.contains(&&ext[..]) {
                return Compressed;
            }
            else if self.is_tmpfile() || TEMP_TYPES.contains(&&ext[..]) {
                return Temp;
            }

            let source_files = self.get_source_files();
            if source_files.is_empty() {
                return Normal;
            }
            else if source_files.iter().any(|path| self.dir.map(|d| d.contains(path)).unwrap_or(false)) {
                return Temp;
            }
            else if COMPILED_TYPES.contains(&&ext[..]) {
                return Compiled;
            }
        }

        return Normal;  // no filetype
    }
}

#[cfg(test)]
mod test {
    use super::*;
    use file::test::{dummy_stat, new_file};

    #[test]
    fn lowercase() {
        let file = new_file(dummy_stat(), "/barracks.wav");
        assert_eq!(FileType::Lossless, file.get_type())
    }

    #[test]
    fn uppercase() {
        let file = new_file(dummy_stat(), "/BARRACKS.WAV");
        assert_eq!(FileType::Lossless, file.get_type())
    }

    #[test]
    fn cargo() {
        let file = new_file(dummy_stat(), "/Cargo.toml");
        assert_eq!(FileType::Immediate, file.get_type())
    }

    #[test]
    fn not_cargo() {
        let file = new_file(dummy_stat(), "/cargo.toml");
        assert_eq!(FileType::Normal, file.get_type())
    }

}
<|endoftext|>


<commit_before>// Rust JSON serialization library
// Copyright (c) 2011 Google Inc.

import float;
import map;
import option;
import option::{some, none};
import str;
import vec;

export json;
export to_str;
export from_str;

export num;
export string;
export boolean;
export list;
export dict;

/*
Tag: json

Represents a json value.
*/
tag json {
    /* Variant: num */
    num(float);
    /* Variant: string */
    string(str);
    /* Variant: boolean */
    boolean(bool);
    /* Variant: list */
    list(@[json]);
    /* Variant: dict */
    dict(map::hashmap<str,json>);
}

/*
Function: to_str

Serializes a json value into a string.
*/
fn to_str(j: json) -> str {
    alt j {
        num(f) { float::to_str(f, 6u) }
        string(s) { #fmt["\"%s\"", s] } // XXX: escape
        boolean(true) { "true" }
        boolean(false) { "false" }
        list(@js) {
            str::concat(["[",
                    str::connect(
                        vec::map::<json,str>({ |e| to_str(e) }, js),
                        ", "),
                    "]"])
        }
        dict(m) {
            let parts = [];
            m.items({ |k, v|
                        vec::grow(parts, 1u,
                                  str::concat(["\"", k, "\": ", to_str(v)])
                        )
            });
            str::concat(["{ ", str::connect(parts, ", "), " }"])
        }
    }
}

fn rest(s: str) -> str {
    assert(str::char_len(s) >= 1u);
    str::char_slice(s, 1u, str::char_len(s))
}

fn from_str_str(s: str) -> (option::t<json>, str) {
    let pos = 0u;
    let len = str::byte_len(s);
    let escape = false;
    let res = "";

    alt str::char_at(s, 0u) {
        '"' { pos = 1u; }
        _ { ret (none, s); }
    }

    while (pos < len) {
        let chr = str::char_range_at(s, pos);
        let c = chr.ch;
        pos = chr.next;
        if (escape) {
            res = res + str::from_char(c);
            escape = false;
            cont;
        }
        if (c == '\\') {
            escape = true;
            cont;
        } else if (c == '"') {
            ret (some(string(res)), str::char_slice(s, pos, str::char_len(s)));
        }
        res = res + str::from_char(c);
    }

    ret (none, s);
}

fn from_str_list(s: str) -> (option::t<json>, str) {
    if str::char_at(s, 0u) != '[' { ret (none, s); }
    let s0 = str::trim_left(rest(s));
    let vals = [];
    if str::is_empty(s0) { ret (none, s0); }
    if str::char_at(s0, 0u) == ']' { ret (some(list(@[])), rest(s0)); }
    while str::is_not_empty(s0) {
        s0 = str::trim_left(s0);
        let (next, s1) = from_str_helper(s0);
        s0 = s1;
        alt next {
            some(j) { vec::grow(vals, 1u, j); }
            none { ret (none, s0); }
        }
        s0 = str::trim_left(s0);
        if str::is_empty(s0) { ret (none, s0); }
        alt str::char_at(s0, 0u) {
            ',' { }
            ']' { ret (some(list(@vals)), rest(s0)); }
            _ { ret (none, s0); }
        }
        s0 = rest(s0);
    }
    ret (none, s0);
}

fn from_str_dict(s: str) -> (option::t<json>, str) {
    if str::char_at(s, 0u) != '{' { ret (none, s); }
    let s0 = str::trim_left(rest(s));
    let vals = map::new_str_hash::<json>();
    if str::is_empty(s0) { ret (none, s0); }
    if str::char_at(s0, 0u) == '}' { ret (some(dict(vals)), rest(s0)); }
    while str::is_not_empty(s0) {
        s0 = str::trim_left(s0);
        let (next, s1) = from_str_helper(s0);    // key
        let key = "";
        s0 = s1;
        alt next {
            some(string(k)) { key = k; }
            _ { ret (none, s0); }
        }
        s0 = str::trim_left(s0);
        if str::is_empty(s0) { ret (none, s0); }
        if str::char_at(s0, 0u) != ':' { ret (none, s0); }
        s0 = str::trim_left(rest(s0));
        let (next, s1) = from_str_helper(s0);    // value
        s0 = s1;
        alt next {
            some(j) { vals.insert(key, j); }
            _ { ret (none, s0); }
        }
        s0 = str::trim_left(s0);
        if str::is_empty(s0) { ret (none, s0); }
        alt str::char_at(s0, 0u) {
            ',' { }
            '}' { ret (some(dict(vals)), rest(s0)); }
            _ { ret (none, s0); }
        }
        s0 = str::trim_left(rest(s0));
    }
    (none, s)
}

fn from_str_float(s: str) -> (option::t<json>, str) {
    let pos = 0u;
    let len = str::byte_len(s);
    let res = 0f;
    let neg = 1.f;

    alt str::char_at(s, 0u) {
        '-' {
            neg = -1.f;
            pos = 1u;
        }
        '+' {
            pos = 1u;
        }
        '0' to '9' | '.' { }
        _ { ret (none, s); }
    }

    while (pos < len) {
        let opos = pos;
        let chr = str::char_range_at(s, pos);
        let c = chr.ch;
        pos = chr.next;
        alt c {
            '0' to '9' {
                res = res * 10f;
                res += ((c as int) - ('0' as int)) as float;
            }
            '.' { break; }
            _ { ret (some(num(neg * res)),
                     str::char_slice(s, opos, str::char_len(s))); }
        }
    }

    if pos == len {
        ret (some(num(neg * res)), str::char_slice(s, pos, str::char_len(s)));
    }

    let dec = 1.f;
    while (pos < len) {
        let opos = pos;
        let chr = str::char_range_at(s, pos);
        let c = chr.ch;
        pos = chr.next;
        alt c {
            '0' to '9' {
                dec /= 10.f;
                res += (((c as int) - ('0' as int)) as float) * dec;
            }
            _ { ret (some(num(neg * res)),
                     str::char_slice(s, opos, str::char_len(s))); }
        }
    }
    ret (some(num(neg * res)), str::char_slice(s, pos, str::char_len(s)));
}

fn from_str_bool(s: str) -> (option::t<json>, str) {
    if (str::starts_with(s, "true")) {
        (some(boolean(true)), str::slice(s, 4u, str::byte_len(s)))
    } else if (str::starts_with(s, "false")) {
        (some(boolean(false)), str::slice(s, 5u, str::byte_len(s)))
    } else {
        (none, s)
    }
}

fn from_str_helper(s: str) -> (option::t<json>, str) {
    let s = str::trim_left(s);
    if str::is_empty(s) { ret (none, s); }
    let start = str::char_at(s, 0u);
    alt start {
        '"' { from_str_str(s) }
        '[' { from_str_list(s) }
        '{' { from_str_dict(s) }
        '0' to '9' | '-' | '+' | '.' { from_str_float(s) }
        't' | 'f' { from_str_bool(s) }
        _ { ret (none, s); }
    }
}

/*
Function: from_str

Deserializes a json value from a string.
*/
fn from_str(s: str) -> option::t<json> {
    let (j, _) = from_str_helper(s);
    j
}
<commit_msg>Fix long lines<commit_after>// Rust JSON serialization library
// Copyright (c) 2011 Google Inc.

import float;
import map;
import option;
import option::{some, none};
import str;
import vec;

export json;
export to_str;
export from_str;

export num;
export string;
export boolean;
export list;
export dict;

/*
Tag: json

Represents a json value.
*/
tag json {
    /* Variant: num */
    num(float);
    /* Variant: string */
    string(str);
    /* Variant: boolean */
    boolean(bool);
    /* Variant: list */
    list(@[json]);
    /* Variant: dict */
    dict(map::hashmap<str,json>);
}

/*
Function: to_str

Serializes a json value into a string.
*/
fn to_str(j: json) -> str {
    alt j {
        num(f) { float::to_str(f, 6u) }
        string(s) { #fmt["\"%s\"", s] } // XXX: escape
        boolean(true) { "true" }
        boolean(false) { "false" }
        list(@js) {
            str::concat(["[",
                    str::connect(
                        vec::map::<json,str>({ |e| to_str(e) }, js),
                        ", "),
                    "]"])
        }
        dict(m) {
            let parts = [];
            m.items({ |k, v|
                        vec::grow(parts, 1u,
                                  str::concat(["\"", k, "\": ", to_str(v)])
                        )
            });
            str::concat(["{ ", str::connect(parts, ", "), " }"])
        }
    }
}

fn rest(s: str) -> str {
    assert(str::char_len(s) >= 1u);
    str::char_slice(s, 1u, str::char_len(s))
}

fn from_str_str(s: str) -> (option::t<json>, str) {
    let pos = 0u;
    let len = str::byte_len(s);
    let escape = false;
    let res = "";

    alt str::char_at(s, 0u) {
        '"' { pos = 1u; }
        _ { ret (none, s); }
    }

    while (pos < len) {
        let chr = str::char_range_at(s, pos);
        let c = chr.ch;
        pos = chr.next;
        if (escape) {
            res = res + str::from_char(c);
            escape = false;
            cont;
        }
        if (c == '\\') {
            escape = true;
            cont;
        } else if (c == '"') {
            ret (some(string(res)),
                 str::char_slice(s, pos, str::char_len(s)));
        }
        res = res + str::from_char(c);
    }

    ret (none, s);
}

fn from_str_list(s: str) -> (option::t<json>, str) {
    if str::char_at(s, 0u) != '[' { ret (none, s); }
    let s0 = str::trim_left(rest(s));
    let vals = [];
    if str::is_empty(s0) { ret (none, s0); }
    if str::char_at(s0, 0u) == ']' { ret (some(list(@[])), rest(s0)); }
    while str::is_not_empty(s0) {
        s0 = str::trim_left(s0);
        let (next, s1) = from_str_helper(s0);
        s0 = s1;
        alt next {
            some(j) { vec::grow(vals, 1u, j); }
            none { ret (none, s0); }
        }
        s0 = str::trim_left(s0);
        if str::is_empty(s0) { ret (none, s0); }
        alt str::char_at(s0, 0u) {
            ',' { }
            ']' { ret (some(list(@vals)), rest(s0)); }
            _ { ret (none, s0); }
        }
        s0 = rest(s0);
    }
    ret (none, s0);
}

fn from_str_dict(s: str) -> (option::t<json>, str) {
    if str::char_at(s, 0u) != '{' { ret (none, s); }
    let s0 = str::trim_left(rest(s));
    let vals = map::new_str_hash::<json>();
    if str::is_empty(s0) { ret (none, s0); }
    if str::char_at(s0, 0u) == '}' { ret (some(dict(vals)), rest(s0)); }
    while str::is_not_empty(s0) {
        s0 = str::trim_left(s0);
        let (next, s1) = from_str_helper(s0);    // key
        let key = "";
        s0 = s1;
        alt next {
            some(string(k)) { key = k; }
            _ { ret (none, s0); }
        }
        s0 = str::trim_left(s0);
        if str::is_empty(s0) { ret (none, s0); }
        if str::char_at(s0, 0u) != ':' { ret (none, s0); }
        s0 = str::trim_left(rest(s0));
        let (next, s1) = from_str_helper(s0);    // value
        s0 = s1;
        alt next {
            some(j) { vals.insert(key, j); }
            _ { ret (none, s0); }
        }
        s0 = str::trim_left(s0);
        if str::is_empty(s0) { ret (none, s0); }
        alt str::char_at(s0, 0u) {
            ',' { }
            '}' { ret (some(dict(vals)), rest(s0)); }
            _ { ret (none, s0); }
        }
        s0 = str::trim_left(rest(s0));
    }
    (none, s)
}

fn from_str_float(s: str) -> (option::t<json>, str) {
    let pos = 0u;
    let len = str::byte_len(s);
    let res = 0f;
    let neg = 1.f;

    alt str::char_at(s, 0u) {
        '-' {
            neg = -1.f;
            pos = 1u;
        }
        '+' {
            pos = 1u;
        }
        '0' to '9' | '.' { }
        _ { ret (none, s); }
    }

    while (pos < len) {
        let opos = pos;
        let chr = str::char_range_at(s, pos);
        let c = chr.ch;
        pos = chr.next;
        alt c {
            '0' to '9' {
                res = res * 10f;
                res += ((c as int) - ('0' as int)) as float;
            }
            '.' { break; }
            _ { ret (some(num(neg * res)),
                     str::char_slice(s, opos, str::char_len(s))); }
        }
    }

    if pos == len {
        ret (some(num(neg * res)), str::char_slice(s, pos, str::char_len(s)));
    }

    let dec = 1.f;
    while (pos < len) {
        let opos = pos;
        let chr = str::char_range_at(s, pos);
        let c = chr.ch;
        pos = chr.next;
        alt c {
            '0' to '9' {
                dec /= 10.f;
                res += (((c as int) - ('0' as int)) as float) * dec;
            }
            _ { ret (some(num(neg * res)),
                     str::char_slice(s, opos, str::char_len(s))); }
        }
    }
    ret (some(num(neg * res)), str::char_slice(s, pos, str::char_len(s)));
}

fn from_str_bool(s: str) -> (option::t<json>, str) {
    if (str::starts_with(s, "true")) {
        (some(boolean(true)), str::slice(s, 4u, str::byte_len(s)))
    } else if (str::starts_with(s, "false")) {
        (some(boolean(false)), str::slice(s, 5u, str::byte_len(s)))
    } else {
        (none, s)
    }
}

fn from_str_helper(s: str) -> (option::t<json>, str) {
    let s = str::trim_left(s);
    if str::is_empty(s) { ret (none, s); }
    let start = str::char_at(s, 0u);
    alt start {
        '"' { from_str_str(s) }
        '[' { from_str_list(s) }
        '{' { from_str_dict(s) }
        '0' to '9' | '-' | '+' | '.' { from_str_float(s) }
        't' | 'f' { from_str_bool(s) }
        _ { ret (none, s); }
    }
}

/*
Function: from_str

Deserializes a json value from a string.
*/
fn from_str(s: str) -> option::t<json> {
    let (j, _) = from_str_helper(s);
    j
}
<|endoftext|>


<commit_before><commit_msg>Add a test for m.room_key serialization<commit_after><|endoftext|>


<commit_before><commit_msg>Show cursor again when Terminal gets dropped<commit_after><|endoftext|>


<commit_before><commit_msg>Ensure we skip the XML Decl on timetables.<commit_after><|endoftext|>


<commit_before><commit_msg>update the bad error handling.<commit_after><|endoftext|>


<commit_before><commit_msg>not documentation<commit_after><|endoftext|>