<commit_before>use MockBuilder;

use std::net::{TcpStream, TcpListener};
use std::io::{Write, Read, BufReader, BufRead};
use std::thread;
use std::sync::atomic::{AtomicUsize, AtomicBool, Ordering, ATOMIC_USIZE_INIT, ATOMIC_BOOL_INIT};
use std::iter::Iterator;
use std::collections::HashMap;

pub static PORT: AtomicUsize = ATOMIC_USIZE_INIT;
pub static SERVER_THREAD_SPAWNED: AtomicBool = ATOMIC_BOOL_INIT;
pub static REQUEST_SERVER_STOP: AtomicBool = ATOMIC_BOOL_INIT;
pub static STOP_REQUEST: &'static [u8] = b"STOP";

struct Mock {
    method: String,
    path: String,
    headers: HashMap<String, String>,
    response: String
}

impl Mock {
    pub fn new(method: String, path: String, response: String) -> Mock {
        let headers = HashMap::new();

        Mock {
            method: method,
            path: path,
            headers: headers,
            response: response
        }
    }

    pub fn matches(&self, request: &Request) -> bool {
        request.method == self.method && request.path == self.path
    }
}

struct Request {
    method: String,
    path: String,
    headers: HashMap<String, String>,
    body: String
}

impl Request {
    pub fn is_internal(&self) -> bool {
        self.path == "/mockito"
    }
}

pub fn instance() {
    if is_listening() { return };

    start(None)
}

pub fn start(port: Option<u16>) {
    let requested_port = port.unwrap_or(0);
    let listener = TcpListener::bind(&*format!("127.0.0.1:{}", requested_port)).unwrap();
    let assigned_port = listener.local_addr().unwrap().port();

    set_port(assigned_port);

    thread::spawn(move || {
        let mut mocks: Vec<Mock> = Vec::new();

        for stream in listener.incoming() {
            match stream {
                Ok(stream) => handle_request(stream, &mut mocks),
                Err(e)     => println!("Error: {}", e)
            }
        }

        drop(listener);
    });
}

pub fn new(mock: String) {
    let mut stream = TcpStream::connect(&*host()).unwrap();

    stream.write_all(b"POST /mockito HTTP/1.1\n\n").unwrap_or(());
    stream.write_all(mock.as_bytes()).unwrap_or(());
}

pub fn reset() {
    let mut stream = TcpStream::connect(&*host()).unwrap();

    stream.write_all(b"DELETE /mockito HTTP/1.1\n\n").unwrap_or(());
}

pub fn is_listening() -> bool {
    TcpStream::connect(&*host()).is_ok()
}

pub fn port() -> u16 {
    PORT.load(Ordering::SeqCst) as u16
}

fn set_port(port: u16) {
    PORT.store(port as usize, Ordering::SeqCst);
}

pub fn host() -> String {
    format!("127.0.0.1:{}", port())
}

pub fn host_with_protocol() -> String {
    format!("http://127.0.0.1:{}", port())
}

fn handle_request(mut stream: TcpStream, mocks: &mut Vec<Mock>) {
    match parse(&mut stream) {
        Some(ref request) if request.is_internal() => handle_command(&mut stream, request, mocks),
        Some(ref request) => handle_mock(&mut stream, request, mocks),
        None => { stream.write_all(b"HTTP/1.1 400 Bad Request\n\n").unwrap_or(()); }
    }
}

fn handle_command(stream: &mut TcpStream, request: &Request, mocks: &mut Vec<Mock>) {
    match (&*request.method, &*request.path) {
        ("POST", "/mockito") => {
            match (request.headers.get("x-mock-method"), request.headers.get("x-mock-path")) {
                (Some(mock_method), Some(mock_path)) => {
                    let mock = Mock::new(mock_method.clone(), mock_path.clone(), request.body.clone());
                    mocks.push(mock);
                    stream.write_all(b"HTTP/1.1 200 OK\n\n").unwrap_or(());
                },
                _ => {
                    stream.write_all(b"HTTP/1.1 422 Unprocessable Entity\n\nX-Mock-Method and/or X-Mock-Path headers missing.").unwrap_or(());
                }
            }
        },
        ("DELETE", "/mockito") => {
            mocks.clear();
            stream.write_all(b"HTTP/1.1 200 OK\n\n").unwrap_or(());
        },
        _ => { stream.write_all(b"HTTP/1.1 404 Not Found\n\n").unwrap_or(()); }
    }
}

fn handle_mock(stream: &mut TcpStream, request: &Request, mocks: &mut Vec<Mock>) {
    match mocks.iter().find(|mock| mock.matches(request)) {
        Some(mock) => {
            stream.write_all(mock.response.as_bytes()).unwrap_or(());
            return
        },
        None => { stream.write_all(b"HTTP/1.1 404 Not Found\n\n").unwrap_or(()); }
    }
}

fn parse(stream: &mut TcpStream) -> Option<Request> {
    let mut reader = BufReader::new(stream);

    let mut request_line = String::new();
    if reader.read_line(&mut request_line).is_err() { return None }

    // Parse request line
    let (method, path) = match request_line.split_whitespace().collect::<Vec<&str>>() {
        ref elements if elements.len() == 2 || elements.len() == 3 => (elements[0], elements[1]),
        _ => return None
    };

    // Parse headers
    let mut headers = HashMap::new();
    loop {
        let mut header_line = String::new();
        match reader.read_line(&mut header_line) {
            Ok(_) if header_line.trim().len() > 0 => {
                let parts: Vec<&str> = header_line.splitn(2, ":").collect();

                if parts.len() != 2 { return None }

                let field = parts[0].trim().to_lowercase().to_string();
                let value = parts[1].trim().to_string();

                headers.insert(field, value);
            },
            Ok(_) => break,
            Err(_) => return None
        }
    }

    // Parse body
    let default_content_length = "0".to_string();
    let content_length = headers.get("content-length").unwrap_or(&default_content_length).clone();
    let length = content_length.parse::<u64>().unwrap_or(0);

    let mut body = String::new();
    reader.take(length).read_to_string(&mut body).unwrap_or(0);

    Some(Request {
        method: method.to_string(),
        path: path.to_string(),
        headers: headers,
        body: body
    })
}

pub struct MockServer {
    // listener_mutex: Arc<Mutex<TcpListener>>,
    port: u16
}

impl MockServer {
    pub fn new(mocks: Vec<MockBuilder>) -> Self {
        let listener = TcpListener::bind("127.0.0.1:0").unwrap();
        let port = listener.local_addr().unwrap().port();

        Self::set_port(port);

        // let listener_mutex = Arc::new(Mutex::new(listener));
        // let cloned_listener = listener_mutex.clone();

        thread::spawn(move || {
            for stream in listener.incoming() {
                match stream {
                    Ok(mut stream) => {
                        let mut buf = [0; 4];
                        stream.read(&mut buf);

                        if buf == STOP_REQUEST { break }

                        Self::handle_client(stream, &mocks)
                    },
                    Err(e) => println!("Error: {}", e)
                }
            }
        });

        MockServer {
            // listener_mutex: listener_mutex,
            port: port
        }
    }

    pub fn is_listening(&self) -> bool {
        TcpStream::connect(&*Self::host()).is_ok()
    }

    pub fn stop(&mut self) {
        let _ = TcpStream::connect(&*Self::host()).and_then(|mut stream| stream.write_all(STOP_REQUEST));

        while self.is_listening() {}

        Self::set_port(0);
    }

    pub fn port() -> u16 {
        PORT.load(Ordering::SeqCst) as u16
    }

    pub fn host() -> String {
        format!("127.0.0.1:{}", Self::port())
    }

    pub fn host_with_protocol() -> String {
        format!("http://127.0.0.1:{}", Self::port())
    }

    fn set_port(port: u16) {
        PORT.store(port as usize, Ordering::SeqCst);
    }

    fn handle_client(mut stream: TcpStream, mocks: &Vec<MockBuilder>) {
        let response = "HTTP/1.1 200 OK\n\nHello world";

        stream.write(response.as_bytes()).unwrap();
    }
}

impl Drop for MockServer {
    fn drop(&mut self) {
        self.stop()
    }
}

#[cfg(test)]
mod mock_server_tests {
    use server::MockServer;

    #[test]
    fn test_new_server_is_listening() {
        let server = MockServer::new(vec!());

        assert!(server.is_listening());
    }

    #[test]
    fn test_server_has_port() {
        let server = MockServer::new(vec!());

        assert!(server.port != 0);
    }

    #[test]
    fn test_server_stop() {
        let mut server = MockServer::new(vec!());
        assert!(server.is_listening());

        server.stop();
        assert!(!server.is_listening());
    }

    #[test]
    fn test_dropping_server() {
        assert!(MockServer::port() == 0);

        {
            let server = MockServer::new(vec!());
            assert!(MockServer::port() != 0);
        }

        assert!(MockServer::port() == 0);
    }
}
<commit_msg>Matchers<commit_after>use MockBuilder;

use std::net::{TcpStream, TcpListener};
use std::io::{Write, Read, BufReader, BufRead};
use std::thread;
use std::sync::atomic::{AtomicUsize, AtomicBool, Ordering, ATOMIC_USIZE_INIT, ATOMIC_BOOL_INIT};
use std::iter::Iterator;
use std::collections::HashMap;

pub static PORT: AtomicUsize = ATOMIC_USIZE_INIT;
pub static SERVER_THREAD_SPAWNED: AtomicBool = ATOMIC_BOOL_INIT;
pub static REQUEST_SERVER_STOP: AtomicBool = ATOMIC_BOOL_INIT;
pub static STOP_REQUEST: &'static [u8] = b"STOP";

struct Mock {
    method: String,
    path: String,
    headers: HashMap<String, String>,
    response: String
}

impl Mock {
    pub fn new(method: String, path: String, response: String) -> Mock {
        let headers = HashMap::new();

        Mock {
            method: method,
            path: path,
            headers: headers,
            response: response
        }
    }

    pub fn matches(&self, request: &Request) -> bool {
        self.method_matches(request)
            && self.path_matches(request)
            && self.headers_match(request)
    }

    fn method_matches(&self, request: &Request) -> bool {
        request.method == self.method
    }

    fn path_matches(&self, request: &Request) -> bool {
        request.path == self.path
    }

    fn headers_match(&self, request: &Request) -> bool {
        for (field, value) in self.headers.iter() {
            match request.headers.get(field) {
                Some(request_value) if request_value == value => continue,
                _ => return false
            }
        }

        true
    }
}

struct Request {
    method: String,
    path: String,
    headers: HashMap<String, String>,
    body: String
}

impl Request {
    pub fn is_internal(&self) -> bool {
        self.path == "/mockito"
    }
}

pub fn instance() {
    if is_listening() { return };

    start(None)
}

pub fn start(port: Option<u16>) {
    let requested_port = port.unwrap_or(0);
    let listener = TcpListener::bind(&*format!("127.0.0.1:{}", requested_port)).unwrap();
    let assigned_port = listener.local_addr().unwrap().port();

    set_port(assigned_port);

    thread::spawn(move || {
        let mut mocks: Vec<Mock> = Vec::new();

        for stream in listener.incoming() {
            match stream {
                Ok(stream) => handle_request(stream, &mut mocks),
                Err(e)     => println!("Error: {}", e)
            }
        }

        drop(listener);
    });
}

pub fn new(mock: String) {
    let mut stream = TcpStream::connect(&*host()).unwrap();

    stream.write_all(b"POST /mockito HTTP/1.1\n\n").unwrap_or(());
    stream.write_all(mock.as_bytes()).unwrap_or(());
}

pub fn reset() {
    let mut stream = TcpStream::connect(&*host()).unwrap();

    stream.write_all(b"DELETE /mockito HTTP/1.1\n\n").unwrap_or(());
}

pub fn is_listening() -> bool {
    TcpStream::connect(&*host()).is_ok()
}

pub fn port() -> u16 {
    PORT.load(Ordering::SeqCst) as u16
}

fn set_port(port: u16) {
    PORT.store(port as usize, Ordering::SeqCst);
}

pub fn host() -> String {
    format!("127.0.0.1:{}", port())
}

pub fn host_with_protocol() -> String {
    format!("http://127.0.0.1:{}", port())
}

fn handle_request(mut stream: TcpStream, mocks: &mut Vec<Mock>) {
    match parse(&mut stream) {
        Some(ref request) if request.is_internal() => handle_command(&mut stream, request, mocks),
        Some(ref request) => handle_mock(&mut stream, request, mocks),
        None => { stream.write_all(b"HTTP/1.1 400 Bad Request\n\n").unwrap_or(()); }
    }
}

fn handle_command(stream: &mut TcpStream, request: &Request, mocks: &mut Vec<Mock>) {
    match (&*request.method, &*request.path) {
        ("POST", "/mockito") => {
            match (request.headers.get("x-mock-method"), request.headers.get("x-mock-path")) {
                (Some(mock_method), Some(mock_path)) => {
                    let mock = Mock::new(mock_method.clone(), mock_path.clone(), request.body.clone());
                    mocks.push(mock);
                    stream.write_all(b"HTTP/1.1 200 OK\n\n").unwrap_or(());
                },
                _ => {
                    stream.write_all(b"HTTP/1.1 422 Unprocessable Entity\n\nX-Mock-Method and/or X-Mock-Path headers missing.").unwrap_or(());
                }
            }
        },
        ("DELETE", "/mockito") => {
            mocks.clear();
            stream.write_all(b"HTTP/1.1 200 OK\n\n").unwrap_or(());
        },
        _ => { stream.write_all(b"HTTP/1.1 404 Not Found\n\n").unwrap_or(()); }
    }
}

fn handle_mock(stream: &mut TcpStream, request: &Request, mocks: &mut Vec<Mock>) {
    match mocks.iter().find(|mock| mock.matches(request)) {
        Some(mock) => {
            stream.write_all(mock.response.as_bytes()).unwrap_or(());
            return
        },
        None => { stream.write_all(b"HTTP/1.1 501 Not Implemented\n\n").unwrap_or(()); }
    }
}

fn parse(stream: &mut TcpStream) -> Option<Request> {
    let mut reader = BufReader::new(stream);

    let mut request_line = String::new();
    if reader.read_line(&mut request_line).is_err() { return None }

    // Parse request line
    let (method, path) = match request_line.split_whitespace().collect::<Vec<&str>>() {
        ref elements if elements.len() == 2 || elements.len() == 3 => (elements[0], elements[1]),
        _ => return None
    };

    // Parse headers
    let mut headers = HashMap::new();
    loop {
        let mut header_line = String::new();
        match reader.read_line(&mut header_line) {
            Ok(_) if header_line.trim().len() > 0 => {
                let parts: Vec<&str> = header_line.splitn(2, ":").collect();

                if parts.len() != 2 { return None }

                let field = parts[0].trim().to_lowercase().to_string();
                let value = parts[1].trim().to_string();

                headers.insert(field, value);
            },
            Ok(_) => break,
            Err(_) => return None
        }
    }

    // TODO: Ignore body if request is internal

    // Parse body
    let default_content_length = "0".to_string();
    let content_length = headers.get("content-length").unwrap_or(&default_content_length).clone();
    let length = content_length.parse::<u64>().unwrap_or(0);

    let mut body = String::new();
    reader.take(length).read_to_string(&mut body).unwrap_or(0);

    Some(Request {
        method: method.to_string(),
        path: path.to_string(),
        headers: headers,
        body: body
    })
}

pub struct MockServer {
    // listener_mutex: Arc<Mutex<TcpListener>>,
    port: u16
}

impl MockServer {
    pub fn new(mocks: Vec<MockBuilder>) -> Self {
        let listener = TcpListener::bind("127.0.0.1:0").unwrap();
        let port = listener.local_addr().unwrap().port();

        Self::set_port(port);

        // let listener_mutex = Arc::new(Mutex::new(listener));
        // let cloned_listener = listener_mutex.clone();

        thread::spawn(move || {
            for stream in listener.incoming() {
                match stream {
                    Ok(mut stream) => {
                        let mut buf = [0; 4];
                        stream.read(&mut buf);

                        if buf == STOP_REQUEST { break }

                        Self::handle_client(stream, &mocks)
                    },
                    Err(e) => println!("Error: {}", e)
                }
            }
        });

        MockServer {
            // listener_mutex: listener_mutex,
            port: port
        }
    }

    pub fn is_listening(&self) -> bool {
        TcpStream::connect(&*Self::host()).is_ok()
    }

    pub fn stop(&mut self) {
        let _ = TcpStream::connect(&*Self::host()).and_then(|mut stream| stream.write_all(STOP_REQUEST));

        while self.is_listening() {}

        Self::set_port(0);
    }

    pub fn port() -> u16 {
        PORT.load(Ordering::SeqCst) as u16
    }

    pub fn host() -> String {
        format!("127.0.0.1:{}", Self::port())
    }

    pub fn host_with_protocol() -> String {
        format!("http://127.0.0.1:{}", Self::port())
    }

    fn set_port(port: u16) {
        PORT.store(port as usize, Ordering::SeqCst);
    }

    fn handle_client(mut stream: TcpStream, mocks: &Vec<MockBuilder>) {
        let response = "HTTP/1.1 200 OK\n\nHello world";

        stream.write(response.as_bytes()).unwrap();
    }
}

impl Drop for MockServer {
    fn drop(&mut self) {
        self.stop()
    }
}

#[cfg(test)]
mod mock_server_tests {
    use server::MockServer;

    #[test]
    fn test_new_server_is_listening() {
        let server = MockServer::new(vec!());

        assert!(server.is_listening());
    }

    #[test]
    fn test_server_has_port() {
        let server = MockServer::new(vec!());

        assert!(server.port != 0);
    }

    #[test]
    fn test_server_stop() {
        let mut server = MockServer::new(vec!());
        assert!(server.is_listening());

        server.stop();
        assert!(!server.is_listening());
    }

    #[test]
    fn test_dropping_server() {
        assert!(MockServer::port() == 0);

        {
            let server = MockServer::new(vec!());
            assert!(MockServer::port() != 0);
        }

        assert!(MockServer::port() == 0);
    }
}
<|endoftext|>


<commit_before>//! `Server` listens for HTTP requests.
//!
//!```rust
//!# use rustful::server::Server;
//!# use rustful::router::Router;
//!# let routes = [];
//!let server = Server {
//!	handlers: Router::from_routes(routes),
//!	port: 8080
//!};
//!
//!server.run();
//!```

use router::Router;
use request::Request;
use response::Response;
use response::status::NotFound;

use http;
use http::server::{ResponseWriter, Config};
use http::server::request::{AbsoluteUri, AbsolutePath};
use http::headers::content_type::MediaType;
use http::method::Post;

use std::io::net::ip::{SocketAddr, Ipv4Addr, Port};
use std::str::from_utf8_owned;
use std::uint;
use std::io::BufReader;
use std::vec::Vec;

use collections::hashmap::HashMap;

use time;

use HTTP = http::server::Server;

///A handler function for routing.
pub type HandlerFn = fn(&Request, &mut Response);

#[deriving(Clone)]
pub struct Server {
	///A routing tree with response handlers
	pub handlers: Router<HandlerFn>,

	///The port where the server will listen for requests
	pub port: Port
}

impl Server {
	///Start the server and run forever.
	///This will only return if the initial connection fails.
	pub fn run(&self) {
		self.clone().serve_forever();
	}
}

impl HTTP for Server {
	fn get_config(&self) -> Config {
		Config {
			bind_address: SocketAddr {
				ip: Ipv4Addr(0, 0, 0, 0),
				port: self.port
			}
		}
	}

	fn handle_request(&self, request: &http::server::request::Request, writer: &mut ResponseWriter) {
		let mut response = Response::new(writer);
		response.headers.date = Some(time::now_utc());
		response.headers.content_type = Some(MediaType {
			type_: StrBuf::from_str("text"),
			subtype: StrBuf::from_str("plain"),
			parameters: vec!((StrBuf::from_str("charset"), StrBuf::from_str("UTF-8")))
		});
		response.headers.server = Some(StrBuf::from_str("rustful"));

		let found = match build_request(request) {
			Some(mut request) => match self.handlers.find(request.method.clone(), request.path) {
				Some((&handler, variables)) => {
					request.variables = variables;
					handler(&request, &mut response);
					true
				},
				None => false
			},
			None => false
		};

		if !found {
			let content = bytes!("File not found");
			response.headers.content_length = Some(content.len());
			response.status = NotFound;
			match response.write(content) {
				Err(e) => println!("error while writing 404: {}", e),
				_ => {}
			}
		}

		response.end();
	}
}

fn build_request<'a>(request: &'a http::server::request::Request) -> Option<Request<'a>> {
	let path = match request.request_uri {
		AbsoluteUri(ref url) => {
			Some((url.path.as_slice(), url.query.iter().map(|v| v.clone()).collect(), url.fragment.as_ref().map(|v| v.as_slice())))
		},
		AbsolutePath(ref path) => Some(parse_path(path.as_slice())),
		_ => None
	};

	match path {
		Some((path, query, fragment)) => {
			let post = if request.method == Post {
				parse_parameters(request.body.as_slice())
			} else {
				HashMap::new()
			};

			Some(Request {
				headers: *request.headers.clone(),
				method: request.method.clone(),
				path: path,
				variables: HashMap::new(),
				post: post,
				query: query,
				fragment: fragment,
				body: request.body.as_slice()
			})
		}
		None => None
	}
}

fn parse_parameters(source: &str) -> HashMap<~str, ~str> {
	let mut parameters = HashMap::new();
	for parameter in source.split('&') {
		let parts: Vec<&str> = parameter.split('=').collect();
		match parts.as_slice() {
			[name, value] => {
				parameters.insert(url_decode(name), url_decode(value));
			},
			[name] => {
				parameters.insert(url_decode(name), "".to_owned());
			},
			[name, value, ..] => {
				parameters.insert(url_decode(name), url_decode(value));
			},
			[] => {}
		}
	}

	parameters
}

fn parse_path<'a>(path: &'a str) -> (&'a str, HashMap<~str, ~str>, Option<&'a str>) {
	match path.find('?') {
		Some(index) => {
			let (query, fragment) = parse_fragment(path.slice(index+1, path.len()));
			(path.slice(0, index), parse_parameters(query), fragment)
		},
		None => {
			let (path, fragment) = parse_fragment(path);
			(path, HashMap::new(), fragment)
		}
	}
}

fn parse_fragment<'a>(path: &'a str) -> (&'a str, Option<&'a str>) {
	match path.find('#') {
		Some(index) => (path.slice(0, index), Some(path.slice(index+1, path.len()))),
		None => (path, None)
	}
}

fn url_decode(string: &str) -> ~str {
	let mut rdr = BufReader::new(string.as_bytes());
	let mut out = Vec::new();

	loop {
		let mut buf = [0];
		let ch = match rdr.read(buf) {
			Err(..) => break,
			Ok(..) => buf[0] as char
		};
		match ch {
			'%' => {
				let mut bytes = [0, 0];
				match rdr.read(bytes) {
					Ok(2) => {}
					_ => fail!()
				}
				let ch = uint::parse_bytes(bytes, 16u).unwrap() as u8;
				out.push(ch);
			}
			ch => out.push(ch as u8)
		}
	}

	from_utf8_owned(out.as_slice().to_owned()).unwrap_or(string.to_owned())
}

#[test]
fn parsing_parameters() {
	let parameters = parse_parameters("a=1&aa=2&ab=202");
	let a = "1".to_owned();
	let aa = "2".to_owned();
	let ab = "202".to_owned();
	assert_eq!(parameters.find(&"a".to_owned()), Some(&a));
	assert_eq!(parameters.find(&"aa".to_owned()), Some(&aa));
	assert_eq!(parameters.find(&"ab".to_owned()), Some(&ab));
}

#[test]
fn parsing_strange_parameters() {
	let parameters = parse_parameters("a=1=2&=2&ab=");
	let a = "1".to_owned();
	let aa = "2".to_owned();
	let ab = "".to_owned();
	assert_eq!(parameters.find(&"a".to_owned()), Some(&a));
	assert_eq!(parameters.find(&"".to_owned()), Some(&aa));
	assert_eq!(parameters.find(&"ab".to_owned()), Some(&ab));
}

#[test]
fn parse_path_parts() {
	let with = "this".to_owned();
	let and = "that".to_owned();
	let (path, query, fragment) = parse_path("/path/to/something?with=this&and=that#lol");
	assert_eq!(path, "/path/to/something");
	assert_eq!(query.find(&"with".to_owned()), Some(&with));
	assert_eq!(query.find(&"and".to_owned()), Some(&and));
	assert_eq!(fragment, Some("lol"));
}

#[test]
fn parse_strange_path() {
	let with = "this".to_owned();
	let and = "what?".to_owned();
	let (path, query, fragment) = parse_path("/path/to/something?with=this&and=what?#");
	assert_eq!(path, "/path/to/something");
	assert_eq!(query.find(&"with".to_owned()), Some(&with));
	assert_eq!(query.find(&"and".to_owned()), Some(&and));
	assert_eq!(fragment, Some(""));
}

#[test]
fn parse_missing_path_parts() {
	let with = "this".to_owned();
	let and = "that".to_owned();
	let (path, query, fragment) = parse_path("/path/to/something?with=this&and=that");
	assert_eq!(path, "/path/to/something");
	assert_eq!(query.find(&"with".to_owned()), Some(&with));
	assert_eq!(query.find(&"and".to_owned()), Some(&and));
	assert_eq!(fragment, None);

	let (path, query, fragment) = parse_path("/path/to/something#lol");
	assert_eq!(path, "/path/to/something");
	assert_eq!(query.len(), 0);
	assert_eq!(fragment, Some("lol"));

	let (path, query, fragment) = parse_path("?with=this&and=that#lol");
	assert_eq!(path, "");
	assert_eq!(query.find(&"with".to_owned()), Some(&with));
	assert_eq!(query.find(&"and".to_owned()), Some(&and));
	assert_eq!(fragment, Some("lol"));
}<commit_msg>'+' istead of '%20' in query strings is handled correctly<commit_after>//! `Server` listens for HTTP requests.
//!
//!```rust
//!# use rustful::server::Server;
//!# use rustful::router::Router;
//!# let routes = [];
//!let server = Server {
//!	handlers: Router::from_routes(routes),
//!	port: 8080
//!};
//!
//!server.run();
//!```

use router::Router;
use request::Request;
use response::Response;
use response::status::NotFound;

use http;
use http::server::{ResponseWriter, Config};
use http::server::request::{AbsoluteUri, AbsolutePath};
use http::headers::content_type::MediaType;
use http::method::Post;

use std::io::net::ip::{SocketAddr, Ipv4Addr, Port};
use std::str::from_utf8_owned;
use std::uint;
use std::io::BufReader;
use std::vec::Vec;

use collections::hashmap::HashMap;

use time;

use HTTP = http::server::Server;

///A handler function for routing.
pub type HandlerFn = fn(&Request, &mut Response);

#[deriving(Clone)]
pub struct Server {
	///A routing tree with response handlers
	pub handlers: Router<HandlerFn>,

	///The port where the server will listen for requests
	pub port: Port
}

impl Server {
	///Start the server and run forever.
	///This will only return if the initial connection fails.
	pub fn run(&self) {
		self.clone().serve_forever();
	}
}

impl HTTP for Server {
	fn get_config(&self) -> Config {
		Config {
			bind_address: SocketAddr {
				ip: Ipv4Addr(0, 0, 0, 0),
				port: self.port
			}
		}
	}

	fn handle_request(&self, request: &http::server::request::Request, writer: &mut ResponseWriter) {
		let mut response = Response::new(writer);
		response.headers.date = Some(time::now_utc());
		response.headers.content_type = Some(MediaType {
			type_: StrBuf::from_str("text"),
			subtype: StrBuf::from_str("plain"),
			parameters: vec!((StrBuf::from_str("charset"), StrBuf::from_str("UTF-8")))
		});
		response.headers.server = Some(StrBuf::from_str("rustful"));

		let found = match build_request(request) {
			Some(mut request) => match self.handlers.find(request.method.clone(), request.path) {
				Some((&handler, variables)) => {
					request.variables = variables;
					handler(&request, &mut response);
					true
				},
				None => false
			},
			None => false
		};

		if !found {
			let content = bytes!("File not found");
			response.headers.content_length = Some(content.len());
			response.status = NotFound;
			match response.write(content) {
				Err(e) => println!("error while writing 404: {}", e),
				_ => {}
			}
		}

		response.end();
	}
}

fn build_request<'a>(request: &'a http::server::request::Request) -> Option<Request<'a>> {
	let path = match request.request_uri {
		AbsoluteUri(ref url) => {
			Some((url.path.as_slice(), url.query.iter().map(|v| v.clone()).collect(), url.fragment.as_ref().map(|v| v.as_slice())))
		},
		AbsolutePath(ref path) => Some(parse_path(path.as_slice())),
		_ => None
	};

	match path {
		Some((path, query, fragment)) => {
			let post = if request.method == Post {
				parse_parameters(request.body.as_slice())
			} else {
				HashMap::new()
			};

			Some(Request {
				headers: *request.headers.clone(),
				method: request.method.clone(),
				path: path,
				variables: HashMap::new(),
				post: post,
				query: query,
				fragment: fragment,
				body: request.body.as_slice()
			})
		}
		None => None
	}
}

fn parse_parameters(source: &str) -> HashMap<~str, ~str> {
	let mut parameters = HashMap::new();
	for parameter in source.split('&') {
		let parts: Vec<&str> = parameter.split('=').collect();
		match parts.as_slice() {
			[name, value] => {
				parameters.insert(url_decode(name), url_decode(value));
			},
			[name] => {
				parameters.insert(url_decode(name), "".to_owned());
			},
			[name, value, ..] => {
				parameters.insert(url_decode(name), url_decode(value));
			},
			[] => {}
		}
	}

	parameters
}

fn parse_path<'a>(path: &'a str) -> (&'a str, HashMap<~str, ~str>, Option<&'a str>) {
	match path.find('?') {
		Some(index) => {
			let (query, fragment) = parse_fragment(path.slice(index+1, path.len()));
			(path.slice(0, index), parse_parameters(query), fragment)
		},
		None => {
			let (path, fragment) = parse_fragment(path);
			(path, HashMap::new(), fragment)
		}
	}
}

fn parse_fragment<'a>(path: &'a str) -> (&'a str, Option<&'a str>) {
	match path.find('#') {
		Some(index) => (path.slice(0, index), Some(path.slice(index+1, path.len()))),
		None => (path, None)
	}
}

fn url_decode(string: &str) -> ~str {
	let mut rdr = BufReader::new(string.as_bytes());
	let mut out = Vec::new();

	loop {
		let mut buf = [0];
		let ch = match rdr.read(buf) {
			Err(..) => break,
			Ok(..) => buf[0] as char
		};
		match ch {
			'+' => out.push(' ' as u8),
			'%' => {
				let mut bytes = [0, 0];
				match rdr.read(bytes) {
					Ok(2) => {}
					_ => fail!()
				}
				let ch = uint::parse_bytes(bytes, 16u).unwrap() as u8;
				out.push(ch);
			}
			ch => out.push(ch as u8)
		}
	}

	from_utf8_owned(out.as_slice().to_owned()).unwrap_or(string.to_owned())
}

#[test]
fn parsing_parameters() {
	let parameters = parse_parameters("a=1&aa=2&ab=202");
	let a = "1".to_owned();
	let aa = "2".to_owned();
	let ab = "202".to_owned();
	assert_eq!(parameters.find(&"a".to_owned()), Some(&a));
	assert_eq!(parameters.find(&"aa".to_owned()), Some(&aa));
	assert_eq!(parameters.find(&"ab".to_owned()), Some(&ab));
}

#[test]
fn parsing_parameters_with_plus() {
	let parameters = parse_parameters("a=1&aa=2+%2B+extra+meat&ab=202+fifth+avenue");
	let a = "1".to_owned();
	let aa = "2 + extra meat".to_owned();
	let ab = "202 fifth avenue".to_owned();
	assert_eq!(parameters.find(&"a".to_owned()), Some(&a));
	assert_eq!(parameters.find(&"aa".to_owned()), Some(&aa));
	assert_eq!(parameters.find(&"ab".to_owned()), Some(&ab));
}

#[test]
fn parsing_strange_parameters() {
	let parameters = parse_parameters("a=1=2&=2&ab=");
	let a = "1".to_owned();
	let aa = "2".to_owned();
	let ab = "".to_owned();
	assert_eq!(parameters.find(&"a".to_owned()), Some(&a));
	assert_eq!(parameters.find(&"".to_owned()), Some(&aa));
	assert_eq!(parameters.find(&"ab".to_owned()), Some(&ab));
}

#[test]
fn parse_path_parts() {
	let with = "this".to_owned();
	let and = "that".to_owned();
	let (path, query, fragment) = parse_path("/path/to/something?with=this&and=that#lol");
	assert_eq!(path, "/path/to/something");
	assert_eq!(query.find(&"with".to_owned()), Some(&with));
	assert_eq!(query.find(&"and".to_owned()), Some(&and));
	assert_eq!(fragment, Some("lol"));
}

#[test]
fn parse_strange_path() {
	let with = "this".to_owned();
	let and = "what?".to_owned();
	let (path, query, fragment) = parse_path("/path/to/something?with=this&and=what?#");
	assert_eq!(path, "/path/to/something");
	assert_eq!(query.find(&"with".to_owned()), Some(&with));
	assert_eq!(query.find(&"and".to_owned()), Some(&and));
	assert_eq!(fragment, Some(""));
}

#[test]
fn parse_missing_path_parts() {
	let with = "this".to_owned();
	let and = "that".to_owned();
	let (path, query, fragment) = parse_path("/path/to/something?with=this&and=that");
	assert_eq!(path, "/path/to/something");
	assert_eq!(query.find(&"with".to_owned()), Some(&with));
	assert_eq!(query.find(&"and".to_owned()), Some(&and));
	assert_eq!(fragment, None);

	let (path, query, fragment) = parse_path("/path/to/something#lol");
	assert_eq!(path, "/path/to/something");
	assert_eq!(query.len(), 0);
	assert_eq!(fragment, Some("lol"));

	let (path, query, fragment) = parse_path("?with=this&and=that#lol");
	assert_eq!(path, "");
	assert_eq!(query.find(&"with".to_owned()), Some(&with));
	assert_eq!(query.find(&"and".to_owned()), Some(&and));
	assert_eq!(fragment, Some("lol"));
}<|endoftext|>


<commit_before>use grain_capnp::{PowerboxCapability, UiView, UiSession};
use web_session_capnp::{WebSession};

use capnp::capability::{ClientHook, FromServer};
use capnp::AnyPointer;
use capnp_rpc::rpc::{RpcConnectionState, SturdyRefRestorer};
use capnp_rpc::capability::{LocalClient};

pub struct UiViewImpl;

impl PowerboxCapability::Server for UiViewImpl {
    fn get_powerbox_info(&mut self, context : PowerboxCapability::GetPowerboxInfoContext) {
        context.done()
    }
}

impl UiView::Server for UiViewImpl {
    fn get_view_info(&mut self, context : UiView::GetViewInfoContext) {
        context.done()
    }

    fn new_session(&mut self, mut context : UiView::NewSessionContext) {
        println!("asked for a new session!");
        let (_, results) = context.get();
        let client : WebSession::Client = FromServer::new(None::<LocalClient>, ~WebSessionImpl);
        results.set_session(UiSession::Client { client : client.client});
        context.done()
    }
}

pub struct WebSessionImpl;

impl UiSession::Server for WebSessionImpl {

}

impl WebSession::Server for WebSessionImpl {
    fn get(&mut self, context : WebSession::GetContext) {
        println!("GET");
        context.done()
    }
    fn post(&mut self, context : WebSession::PostContext) {
        println!("POST");
        context.done()
    }
    fn put(&mut self, context : WebSession::PutContext) {
        println!("PUT");
        context.done()
    }
    fn delete(&mut self, context : WebSession::DeleteContext) {
        println!("DELETE");
        context.done()
    }
    fn open_web_socket(&mut self, context : WebSession::OpenWebSocketContext) {
        println!("OPEN WEB SOCKET");
        context.done()
    }
}

pub struct FdStream {
    inner : ~::std::rt::rtio::RtioFileStream:Send,
}

impl FdStream {
    pub fn new(fd : ::libc::c_int) -> ::std::io::IoResult<FdStream> {
        ::std::rt::rtio::LocalIo::maybe_raise(|io| {
            Ok (FdStream { inner : io.fs_from_raw_fd(fd, ::std::rt::rtio::DontClose) })
        })
    }
}

impl Reader for FdStream {
    fn read(&mut self, buf : &mut [u8]) -> ::std::io::IoResult<uint> {
        self.inner.read(buf).map(|i| i as uint)
    }
}

impl Writer for FdStream {
    fn write(&mut self, buf : &[u8]) -> ::std::io::IoResult<()> {
        self.inner.write(buf)
    }
}

pub struct Restorer;

impl SturdyRefRestorer for Restorer {
    fn restore(&self, obj_id : AnyPointer::Reader) -> Option<~ClientHook:Send> {
        if obj_id.is_null() {
            let client : UiView::Client = FromServer::new(None::<LocalClient>, ~UiViewImpl);
            Some(client.client.hook)
        } else {
            None
        }
    }
}

pub fn main() -> ::std::io::IoResult<()> {
    let ifs = try!(FdStream::new(3));
    let ofs = try!(FdStream::new(3));

    let connection_state = RpcConnectionState::new();
    connection_state.run(ifs, ofs, Restorer);

    Ok(())
}

<commit_msg>hello world<commit_after>use grain_capnp::{PowerboxCapability, UiView, UiSession};
use web_session_capnp::{WebSession};

use capnp::capability::{ClientHook, FromServer};
use capnp::AnyPointer;
use capnp_rpc::rpc::{RpcConnectionState, SturdyRefRestorer};
use capnp_rpc::capability::{LocalClient};

pub struct UiViewImpl;

impl PowerboxCapability::Server for UiViewImpl {
    fn get_powerbox_info(&mut self, context : PowerboxCapability::GetPowerboxInfoContext) {
        context.done()
    }
}

impl UiView::Server for UiViewImpl {
    fn get_view_info(&mut self, context : UiView::GetViewInfoContext) {
        context.done()
    }

    fn new_session(&mut self, mut context : UiView::NewSessionContext) {
        println!("asked for a new session!");
        let (_, results) = context.get();

        let client : WebSession::Client = FromServer::new(None::<LocalClient>, ~WebSessionImpl);
        // we need to do this dance to upcast.
        results.set_session(UiSession::Client { client : client.client});

        context.done()
    }
}

pub struct WebSessionImpl;

impl UiSession::Server for WebSessionImpl {

}

impl WebSession::Server for WebSessionImpl {
    fn get(&mut self, mut context : WebSession::GetContext) {
        println!("GET");
        let (params, results) = context.get();
        println!("path = {}", params.get_path());
        let content = results.init_content();
        content.set_mime_type("text/plain");
        content.get_body().set_bytes(bytes!("hello world"));
        context.done()
    }
    fn post(&mut self, context : WebSession::PostContext) {
        println!("POST");
        context.done()
    }
    fn put(&mut self, context : WebSession::PutContext) {
        println!("PUT");
        context.done()
    }
    fn delete(&mut self, context : WebSession::DeleteContext) {
        println!("DELETE");
        context.done()
    }
    fn open_web_socket(&mut self, context : WebSession::OpenWebSocketContext) {
        println!("OPEN WEB SOCKET");
        context.done()
    }
}

pub struct FdStream {
    inner : ~::std::rt::rtio::RtioFileStream:Send,
}

impl FdStream {
    pub fn new(fd : ::libc::c_int) -> ::std::io::IoResult<FdStream> {
        ::std::rt::rtio::LocalIo::maybe_raise(|io| {
            Ok (FdStream { inner : io.fs_from_raw_fd(fd, ::std::rt::rtio::DontClose) })
        })
    }
}

impl Reader for FdStream {
    fn read(&mut self, buf : &mut [u8]) -> ::std::io::IoResult<uint> {
        self.inner.read(buf).map(|i| i as uint)
    }
}

impl Writer for FdStream {
    fn write(&mut self, buf : &[u8]) -> ::std::io::IoResult<()> {
        self.inner.write(buf)
    }
}

pub struct Restorer;

impl SturdyRefRestorer for Restorer {
    fn restore(&self, obj_id : AnyPointer::Reader) -> Option<~ClientHook:Send> {
        if obj_id.is_null() {
            let client : UiView::Client = FromServer::new(None::<LocalClient>, ~UiViewImpl);
            Some(client.client.hook)
        } else {
            None
        }
    }
}

pub fn main() -> ::std::io::IoResult<()> {
    let ifs = try!(FdStream::new(3));
    let ofs = try!(FdStream::new(3));

    let connection_state = RpcConnectionState::new();
    connection_state.run(ifs, ofs, Restorer);

    Ok(())
}

<|endoftext|>


<commit_before>use std::rc::Rc;
use std::collections::HashMap;

use uuid::Uuid;

use graphics::{ self, Graphics, ImageSize };
use graphics::math::{ Scalar, Matrix2d, Vec2d, Vec3d };

/// A sprite is a texture with some properties.
pub struct Sprite<I: ImageSize> {
    id: Uuid,

    visible: bool,

    anchor: Vec2d,

    position: Vec2d,
    rotation: Scalar,
    scale: Vec2d,
    color: Vec3d,

    flip_x: bool,
    flip_y: bool,

    opacity: f32,

    children: Vec<Sprite<I>>,
    children_index: HashMap<Uuid, usize>,

    texture: Rc<I>,
}

impl<I: ImageSize> Sprite<I> {
    /// Crate sprite from a texture
    pub fn from_texture(texture: Rc<I>) -> Sprite<I> {
        Sprite {
            id: Uuid::new_v4(),

            visible: true,

            anchor: [0.5, 0.5],

            position: [0.0, 0.0],
            rotation: 0.0,
            scale: [1.0, 1.0],
            color: [1.0,1.0,0.0],

            flip_x: false,
            flip_y: false,

            opacity: 1.0,

            texture: texture,

            children: Vec::new(),
            children_index: HashMap::new(),
        }
    }

    /// Get the sprite's id
    #[inline(always)]
    pub fn id(&self) -> Uuid {
        self.id.clone()
    }

    /// Whether or not the sprite is visible
    pub fn visible(&self) -> bool {
        self.visible
    }

    /// Set the sprite's visibility
    pub fn set_visible(&mut self, visible: bool) {
        self.visible = visible;
    }

    /// Get the sprite's anchor point
    ///
    /// The value is normalized. Default value is [0.5, 0.5] (the center of texture)
    #[inline(always)]
    pub fn anchor(&self) -> (Scalar, Scalar) {
        (self.anchor[0], self.anchor[1])
    }

    /// Set the sprite's anchor point
    #[inline(always)]
    pub fn set_anchor(&mut self, x: Scalar, y: Scalar) {
        self.anchor = [x, y];
    }

    /// Get the sprite's position
    #[inline(always)]
    pub fn position(&self) -> (Scalar, Scalar) {
        (self.position[0], self.position[1])
    }

    /// Set the sprite's position
    #[inline(always)]
    pub fn set_position(&mut self, x: Scalar, y: Scalar) {
        self.position = [x, y];
    }

    /// Get the sprite's rotation (in degree)
    #[inline(always)]
    pub fn rotation(&self) -> Scalar {
        self.rotation
    }

    /// Set the sprite's rotation (in degree)
    #[inline(always)]
    pub fn set_rotation(&mut self, deg: Scalar) {
        self.rotation = deg;
    }

    /// Get the sprite's scale
    #[inline(always)]
    pub fn scale(&self) -> (Scalar, Scalar) {
        (self.scale[0], self.scale[1])
    }

    /// Set the sprite's scale
    #[inline(always)]
    pub fn set_scale(&mut self, sx: Scalar, sy: Scalar) {
        self.scale = [sx, sy];
    }

    /// Whether or not the sprite is flipped horizontally.
    ///
    /// It only flips the texture of the sprite,
    /// and not the texture of the sprite’s children.
    ///
    /// Also, flipping the texture doesn’t alter the `anchor`.
    ///
    /// If you want to flip the `anchor` too,
    /// and/or to flip the children too use: sprite.scale.x *= -1;
    #[inline(always)]
    pub fn flip_x(&self) -> bool {
        self.flip_x
    }

    /// Flip the sprite
    #[inline(always)]
    pub fn set_flip_x(&mut self, flip_x: bool) {
        self.flip_x = flip_x;
    }

    /// Whether or not the sprite is flipped vertically.
    ///
    /// It only flips the texture of the sprite,
    /// and not the texture of the sprite’s children.
    ///
    /// Also, flipping the texture doesn’t alter the `anchor`.
    ///
    /// If you want to flip the `anchor` too,
    /// and/or to flip the children too use: sprite.scale.y *= -1;
    #[inline(always)]
    pub fn flip_y(&self) -> bool {
        self.flip_y
    }

    /// Flip the sprite
    #[inline(always)]
    pub fn set_flip_y(&mut self, flip_y: bool) {
        self.flip_y = flip_y;
    }

    /// Get the sprite's opacity
    #[inline(always)]
    pub fn opacity(&self) -> f32 {
        self.opacity
    }

    /// Set the sprite's opacity
    #[inline(always)]
    pub fn set_opacity(&mut self, opacity: f32) {
        self.opacity = opacity;
    }

    /// Get the sprite's texture
    #[inline(always)]
    pub fn texture(&self) -> &Rc<I> {
        &self.texture
    }

    /// Set the sprite's texture
    #[inline(always)]
    pub fn set_texture(&mut self, texture: Rc<I>) {
        self.texture = texture;
    }

    /// Add a sprite as the child of this sprite, return the added sprite's id.
    pub fn add_child(&mut self, sprite: Sprite<I>) -> Uuid {
        let id = sprite.id();
        self.children.push(sprite);
        self.children_index.insert(id.clone(), self.children.len() - 1);
        id
    }

    /// Remove the child by `id` from this sprite's children or grandchild
    pub fn remove_child(&mut self, id: Uuid) -> Option<Sprite<I>> {
        if let Some(index) = self.children_index.remove(&id) {
            let removed = self.children.remove(index);
            // Removing a element of vector will alter the index,
            // update the mapping from uuid to index.
            for i in index..self.children.len() {
                let uuid = self.children[i].id();
                self.children_index.insert(uuid, i);
            }
            Some(removed)
        } else {
            for child in self.children.iter_mut() {
                if let Some(c) = child.remove_child(id.clone()) {
                    return Some(c);
                }
            }
            None
        }
    }

    /// Find the child by `id` from this sprite's children or grandchild
    pub fn child(&self, id: Uuid) -> Option<&Sprite<I>> {
        if let Some(index) = self.children_index.get(&id) {
            Some(&self.children[*index])
        } else {
            for child in self.children.iter() {
                if let Some(c) = child.child(id.clone()) {
                    return Some(c);
                }
            }
            None
        }
    }

    /// Find the child by `id` from this sprite's children or grandchild, mutability
    pub fn child_mut(&mut self, id: Uuid) -> Option<&mut Sprite<I>> {
        if let Some(index) = self.children_index.get(&id) {
            Some(&mut self.children[*index])
        } else {
            for child in self.children.iter_mut() {
                if let Some(c) = child.child_mut(id.clone()) {
                    return Some(c);
                }
            }
            None
        }
    }

    /// Get the sprite's children
    #[inline(always)]
    pub fn children(&self) -> &Vec<Sprite<I>> {
        &self.children
    }

    /// Draw this sprite and its children
    pub fn draw<B: Graphics<Texture = I>>(&self, t: Matrix2d, b: &mut B) {
        use graphics::*;

        if !self.visible {
            return;
        }

        let (w, h) = self.texture.get_size();
        let w = w as f64;
        let h = h as f64;
        let anchor = [self.anchor[0] * w, self.anchor[1] * h];

        let transformed = t.trans(self.position[0], self.position[1])
                           .rot_deg(self.rotation)
                           .scale(self.scale[0], self.scale[1]);

        let mut model = transformed;

        if self.flip_x {
            model = model.trans(w - 2.0 * anchor[0], 0.0).flip_h();
        }

        if self.flip_y {
            model = model.trans(0.0, h - 2.0 * anchor[1]).flip_v();
        }

        let draw_state = default_draw_state();

        // for debug: bounding_box
        //model.rgb(1.0, 0.0, 0.0).draw(b);

        graphics::Image::new()
            .color([self.color[0] as f32, self.color[1] as f32, self.color[2] as f32, self.opacity])
            .rect([-anchor[0], -anchor[1], w, h])
            .draw(&*self.texture, draw_state, model, b);

        // for debug: anchor point
        //c.trans(self.position[0], self.position[1]).rect(-5.0, -5.0, 10.0, 10.0).rgb(0.0, 0.0, 1.0).draw(b);

        for child in self.children.iter() {
            child.draw(transformed, b);
        }
    }

    /// Get the sprite's bounding box
    pub fn bounding_box(&self) -> graphics::types::Rectangle {
        let (w, h) = self.texture.get_size();
        let w = w as f64 * self.scale[0];
        let h = h as f64 * self.scale[1];

        [
            self.position[0] - self.anchor[0] * w,
            self.position[1] - self.anchor[1] * h,
            w,
            h
        ]
    }
}
<commit_msg>Updating color functions<commit_after>use std::rc::Rc;
use std::collections::HashMap;

use uuid::Uuid;

use graphics::{ self, Graphics, ImageSize };
use graphics::math::{ Scalar, Matrix2d, Vec2d, Vec3d };

/// A sprite is a texture with some properties.
pub struct Sprite<I: ImageSize> {
    id: Uuid,

    visible: bool,

    anchor: Vec2d,

    position: Vec2d,
    rotation: Scalar,
    scale: Vec2d,
    color: Vec3d,

    flip_x: bool,
    flip_y: bool,

    opacity: f32,

    children: Vec<Sprite<I>>,
    children_index: HashMap<Uuid, usize>,

    texture: Rc<I>,
}

impl<I: ImageSize> Sprite<I> {
    /// Crate sprite from a texture
    pub fn from_texture(texture: Rc<I>) -> Sprite<I> {
        Sprite {
            id: Uuid::new_v4(),

            visible: true,

            anchor: [0.5, 0.5],

            position: [0.0, 0.0],
            rotation: 0.0,
            scale: [1.0, 1.0],
            color: [1.0,1.0,1.0],

            flip_x: false,
            flip_y: false,

            opacity: 1.0,

            texture: texture,

            children: Vec::new(),
            children_index: HashMap::new(),
        }
    }

    /// Get the sprite's id
    #[inline(always)]
    pub fn id(&self) -> Uuid {
        self.id.clone()
    }

    /// Whether or not the sprite is visible
    pub fn visible(&self) -> bool {
        self.visible
    }

    /// Set the sprite's visibility
    pub fn set_visible(&mut self, visible: bool) {
        self.visible = visible;
    }

    /// Get the sprite's anchor point
    ///
    /// The value is normalized. Default value is [0.5, 0.5] (the center of texture)
    #[inline(always)]
    pub fn anchor(&self) -> (Scalar, Scalar) {
        (self.anchor[0], self.anchor[1])
    }

    /// Set the sprite's anchor point
    #[inline(always)]
    pub fn set_anchor(&mut self, x: Scalar, y: Scalar) {
        self.anchor = [x, y];
    }

    /// Get the sprite's position
    #[inline(always)]
    pub fn position(&self) -> (Scalar, Scalar) {
        (self.position[0], self.position[1])
    }

    /// Set the sprite's position
    #[inline(always)]
    pub fn set_position(&mut self, x: Scalar, y: Scalar) {
        self.position = [x, y];
    }

    /// Set the sprite's draw color (tint)
    #[inline(always)]
    pub fn set_color(&mut self, r: f64, g: f64, b: f64) {
        self.color = [r, g, b];
    }

    /// get the sprite's color.
    #[inline(always)]
    pub fn color(&self) -> (f64, f64, f64) {
        (self.color[0], self.color[1], self.color[2])
    }

    /// Get the sprite's rotation (in degree)
    #[inline(always)]
    pub fn rotation(&self) -> Scalar {
        self.rotation
    }

    /// Set the sprite's rotation (in degree)
    #[inline(always)]
    pub fn set_rotation(&mut self, deg: Scalar) {
        self.rotation = deg;
    }

    /// Get the sprite's scale
    #[inline(always)]
    pub fn scale(&self) -> (Scalar, Scalar) {
        (self.scale[0], self.scale[1])
    }

    /// Set the sprite's scale
    #[inline(always)]
    pub fn set_scale(&mut self, sx: Scalar, sy: Scalar) {
        self.scale = [sx, sy];
    }

    /// Whether or not the sprite is flipped horizontally.
    ///
    /// It only flips the texture of the sprite,
    /// and not the texture of the sprite’s children.
    ///
    /// Also, flipping the texture doesn’t alter the `anchor`.
    ///
    /// If you want to flip the `anchor` too,
    /// and/or to flip the children too use: sprite.scale.x *= -1;
    #[inline(always)]
    pub fn flip_x(&self) -> bool {
        self.flip_x
    }

    /// Flip the sprite
    #[inline(always)]
    pub fn set_flip_x(&mut self, flip_x: bool) {
        self.flip_x = flip_x;
    }

    /// Whether or not the sprite is flipped vertically.
    ///
    /// It only flips the texture of the sprite,
    /// and not the texture of the sprite’s children.
    ///
    /// Also, flipping the texture doesn’t alter the `anchor`.
    ///
    /// If you want to flip the `anchor` too,
    /// and/or to flip the children too use: sprite.scale.y *= -1;
    #[inline(always)]
    pub fn flip_y(&self) -> bool {
        self.flip_y
    }

    /// Flip the sprite
    #[inline(always)]
    pub fn set_flip_y(&mut self, flip_y: bool) {
        self.flip_y = flip_y;
    }

    /// Get the sprite's opacity
    #[inline(always)]
    pub fn opacity(&self) -> f32 {
        self.opacity
    }

    /// Set the sprite's opacity
    #[inline(always)]
    pub fn set_opacity(&mut self, opacity: f32) {
        self.opacity = opacity;
    }

    /// Get the sprite's texture
    #[inline(always)]
    pub fn texture(&self) -> &Rc<I> {
        &self.texture
    }

    /// Set the sprite's texture
    #[inline(always)]
    pub fn set_texture(&mut self, texture: Rc<I>) {
        self.texture = texture;
    }

    /// Add a sprite as the child of this sprite, return the added sprite's id.
    pub fn add_child(&mut self, sprite: Sprite<I>) -> Uuid {
        let id = sprite.id();
        self.children.push(sprite);
        self.children_index.insert(id.clone(), self.children.len() - 1);
        id
    }

    /// Remove the child by `id` from this sprite's children or grandchild
    pub fn remove_child(&mut self, id: Uuid) -> Option<Sprite<I>> {
        if let Some(index) = self.children_index.remove(&id) {
            let removed = self.children.remove(index);
            // Removing a element of vector will alter the index,
            // update the mapping from uuid to index.
            for i in index..self.children.len() {
                let uuid = self.children[i].id();
                self.children_index.insert(uuid, i);
            }
            Some(removed)
        } else {
            for child in self.children.iter_mut() {
                if let Some(c) = child.remove_child(id.clone()) {
                    return Some(c);
                }
            }
            None
        }
    }

    /// Find the child by `id` from this sprite's children or grandchild
    pub fn child(&self, id: Uuid) -> Option<&Sprite<I>> {
        if let Some(index) = self.children_index.get(&id) {
            Some(&self.children[*index])
        } else {
            for child in self.children.iter() {
                if let Some(c) = child.child(id.clone()) {
                    return Some(c);
                }
            }
            None
        }
    }

    /// Find the child by `id` from this sprite's children or grandchild, mutability
    pub fn child_mut(&mut self, id: Uuid) -> Option<&mut Sprite<I>> {
        if let Some(index) = self.children_index.get(&id) {
            Some(&mut self.children[*index])
        } else {
            for child in self.children.iter_mut() {
                if let Some(c) = child.child_mut(id.clone()) {
                    return Some(c);
                }
            }
            None
        }
    }

    /// Get the sprite's children
    #[inline(always)]
    pub fn children(&self) -> &Vec<Sprite<I>> {
        &self.children
    }

    /// Draw this sprite and its children
    pub fn draw<B: Graphics<Texture = I>>(&self, t: Matrix2d, b: &mut B) {
        use graphics::*;

        if !self.visible {
            return;
        }

        let (w, h) = self.texture.get_size();
        let w = w as f64;
        let h = h as f64;
        let anchor = [self.anchor[0] * w, self.anchor[1] * h];

        let transformed = t.trans(self.position[0], self.position[1])
                           .rot_deg(self.rotation)
                           .scale(self.scale[0], self.scale[1]);

        let mut model = transformed;

        if self.flip_x {
            model = model.trans(w - 2.0 * anchor[0], 0.0).flip_h();
        }

        if self.flip_y {
            model = model.trans(0.0, h - 2.0 * anchor[1]).flip_v();
        }

        let draw_state = default_draw_state();

        // for debug: bounding_box
        //model.rgb(1.0, 0.0, 0.0).draw(b);

        graphics::Image::new()
            .color([self.color[0] as f32, self.color[1] as f32, self.color[2] as f32, self.opacity])
            .rect([-anchor[0], -anchor[1], w, h])
            .draw(&*self.texture, draw_state, model, b);

        // for debug: anchor point
        //c.trans(self.position[0], self.position[1]).rect(-5.0, -5.0, 10.0, 10.0).rgb(0.0, 0.0, 1.0).draw(b);

        for child in self.children.iter() {
            child.draw(transformed, b);
        }
    }

    /// Get the sprite's bounding box
    pub fn bounding_box(&self) -> graphics::types::Rectangle {
        let (w, h) = self.texture.get_size();
        let w = w as f64 * self.scale[0];
        let h = h as f64 * self.scale[1];

        [
            self.position[0] - self.anchor[0] * w,
            self.position[1] - self.anchor[1] * h,
            w,
            h
        ]
    }
}
<|endoftext|>


<commit_before>use libc;

use std::ptr::null_mut;

/// 16k is enough for anybody.
const STACK_SIZE: u64 = 16384;

/// Get the offset in bytes of some particular struct member.
///
/// Idea is simply to see what the address of that member would be if the
/// struct was created at address 0x0 (which gives its offset in bytes).
macro_rules! offset_of {
    ($kind:ty, $member:ident) => {
        unsafe {
            let ptr = 0x0usize as *const $kind;
            let member_addr: usize = std::mem::transmute(&(*ptr).$member);

            member_addr
        }
    };
}

/// Return a pointer to the TLS value at the given offset.
macro_rules! get_thread_mem {
    ($offset:expr, $kind:ty) => {{
        let dest_ptr: *mut $kind;

        // We can't use constant segment offsets here due to some odd
        // asm! behavior, so just use indirect (it's slower, oh well).
        asm!("mov %fs:($1), $0"
             : "=r"(dest_ptr)
             : "r" ($offset)
             :: "volatile");

        dest_ptr
    }};
}

macro_rules! set_thread_mem {
    ($offset:expr, $expression:expr) => {
        asm!("movl $1, %fs:($0)" :
             : "r"($offset), "i"($expression)
             :: "volatile");
    };
}

#[repr(C, packed)]
#[derive(Debug)]
pub struct ControlBlockHead {
    tcb: *mut libc::c_void,
    dtv: *mut libc::c_void,
    thread_self: *mut Thread,

    /// We don't actually care about the rest.
    padding: [*mut libc::c_void; 21],
}

#[repr(C, packed)]
#[derive(Debug)]
pub struct Thread {
    header: ControlBlockHead,

    /// This thread's id
    pub tid: libc::pid_t,

    /// This thread's parent pid
    pub pid: libc::pid_t,

    pub magic: usize
}

unsafe fn get_thread_tcb() {
}

pub unsafe fn get_current_thread() -> () {
    let thd_ptr: *mut Thread = get_thread_mem!(0, Thread);
    if thd_ptr.is_null() { panic!("TLS thread return NULL"); }

    let thd = &*thd_ptr;

    println!("magic = {}", thd.magic);
}

pub unsafe fn allocate_stack() -> *mut libc::c_void {
    let prot = libc::PROT_EXEC | libc::PROT_READ | libc::PROT_WRITE;
    let flags = libc::MAP_PRIVATE | libc::MAP_ANONYMOUS | libc::MAP_STACK;

    let stack = libc::mmap(null_mut(), STACK_SIZE, prot, flags, -1, 0);

    if stack == libc::MAP_FAILED || stack.is_null() {
        panic!("couldn't mmap space for stack");
    }

    stack
}
<commit_msg>ditto<commit_after>use libc;

use std::ptr::null_mut;

/// 16k is enough for anybody.
const STACK_SIZE: u64 = 16384;

/// Get the offset in bytes of some particular struct member.
///
/// Idea is simply to see what the address of that member would be if the
/// struct was created at address 0x0 (which gives its offset in bytes).
macro_rules! offset_of {
    ($kind:ty, $member:ident) => {
        unsafe {
            let ptr = 0x0usize as *const $kind;
            let member_addr = (&(*ptr).$member as *const _) as usize;

            member_addr
        }
    };
}

/// Return a pointer to the TLS value at the given offset.
macro_rules! get_thread_mem {
    ($offset:expr, $kind:ty) => {{
        let dest_ptr: *mut $kind;

        // We can't use constant segment offsets here due to some odd
        // asm! behavior, so just use indirect (it's slower, oh well).
        asm!("mov %fs:($1), $0"
             : "=r"(dest_ptr)
             : "r" ($offset)
             :: "volatile");

        dest_ptr
    }};
}

macro_rules! set_thread_mem {
    ($offset:expr, $expression:expr) => {
        asm!("movl $1, %fs:($0)" :
             : "r"($offset), "i"($expression)
             :: "volatile");
    };
}

#[repr(C, packed)]
#[derive(Debug)]
pub struct ControlBlockHead {
    tcb: *mut libc::c_void,
    dtv: *mut libc::c_void,
    thread_self: *mut Thread,

    /// We don't actually care about the rest.
    padding: [*mut libc::c_void; 21],
}

#[repr(C, packed)]
#[derive(Debug)]
pub struct Thread {
    header: ControlBlockHead,

    /// This thread's id
    pub tid: libc::pid_t,

    /// This thread's parent pid
    pub pid: libc::pid_t,

    pub magic: usize
}

unsafe fn get_thread_tcb() {
}

pub unsafe fn get_current_thread() -> () {
    let thd_ptr: *mut Thread = get_thread_mem!(0, Thread);
    if thd_ptr.is_null() { panic!("TLS thread return NULL"); }

    let thd = &*thd_ptr;

    println!("magic = {}", thd.magic);
}

pub unsafe fn allocate_stack() -> *mut libc::c_void {
    let prot = libc::PROT_EXEC | libc::PROT_READ | libc::PROT_WRITE;
    let flags = libc::MAP_PRIVATE | libc::MAP_ANONYMOUS | libc::MAP_STACK;

    let stack = libc::mmap(null_mut(), STACK_SIZE, prot, flags, -1, 0);

    if stack == libc::MAP_FAILED || stack.is_null() {
        panic!("couldn't mmap space for stack");
    }

    stack
}
<|endoftext|>


<commit_before>use core::{
    cell::UnsafeCell,
    fmt,
    ops::{Deref, DerefMut},
    sync::atomic::{spin_loop_hint, AtomicUsize, Ordering},
};

/// A ticket lock for mutual exclusion based on spinning.
///
/// A ticket lock is similair to a queue management system.
/// When a thread tries to lock the values,
/// it is assigned a ticket, and it spins until its ticket is the next in line.
/// When releasing the value, the next ticket will be processed.
pub struct TicketLock<T: ?Sized> {
    next_ticket: AtomicUsize,
    next_serving: AtomicUsize,
    value: UnsafeCell<T>,
}

/// A guard that protects some data.
///
/// When the guard is dropped, the next ticket will be processed.
pub struct LockGuard<'a, T: ?Sized + 'a> {
    next_serving: &'a AtomicUsize,
    ticket: usize,
    value: &'a mut T,
}

unsafe impl<T: ?Sized + Send> Sync for TicketLock<T> {}
unsafe impl<T: ?Sized + Send> Send for TicketLock<T> {}

impl<T> TicketLock<T> {
    /// Creates a new `TicketLock` that wraps the given value.
    ///
    /// This method can be used in static context.
    ///
    /// ```
    /// static LOCK: spin::TicketLock<i32> = spin::TicketLock::new(123);
    ///
    /// # fn main() {
    /// let value = LOCK.lock();
    /// assert_eq!(value, 123);
    /// drop(value);
    /// #}
    /// ```
    pub const fn new(value: T) -> Self {
        Self {
            next_ticket: AtomicUsize::new(0),
            next_serving: AtomicUsize::new(0),
            value: UnsafeCell::new(value),
        }
    }

    /// Unwraps the inner value of this lock.
    pub fn into_inner(self) -> T {
        self.value.into_inner()
    }
}

impl<T: ?Sized> TicketLock<T> {
    /// Spins the thread until the value can be locked.
    ///
    /// The returned value can be used to modify the value,
    /// and will be unlocked after dropping the return value.
    pub fn lock(&self) -> LockGuard<T> {
        let ticket = self.next_ticket.fetch_add(1, Ordering::Relaxed);

        while self.next_serving.load(Ordering::Relaxed) != ticket {
            spin_loop_hint();
        }

        LockGuard {
            next_serving: &self.next_serving,
            ticket,
            // Safety
            // We know that we are the next ticket to be served,
            // so there's no other thread accessing the value.
            //
            // Every other thread has another ticket number so it's
            // definitely stuck in the spin loop above.
            value: unsafe { &mut *self.value.get() },
        }
    }

    /// Tries to lock this lock. If it's already locked, `None` is returned,
    /// otherwise a guard that protects the data is returned.
    pub fn try_lock(&self) -> Option<LockGuard<T>> {
        let ticket = self
            .next_ticket
            .fetch_update(Ordering::SeqCst, Ordering::SeqCst, |ticket| {
                if self.next_serving.load(Ordering::Acquire) == ticket {
                    Some(ticket + 1)
                } else {
                    None
                }
            });

        ticket.ok().map(|ticket| LockGuard {
            next_serving: &self.next_serving,
            ticket,
            // Safety
            // We have a ticket that is equal to the next_serving ticket, so we know:
            // - that no other thread can have the same ticket id as this thread
            // - that we are the next one to be served so we have exclusive access to the value
            value: unsafe { &mut *self.value.get() },
        })
    }

    /// Returns a mutable reference to the underlying data.
    ///
    /// This will not lock this lock, since this method borrows
    /// this lock mutably so no locking is needed.
    pub fn get_mut(&mut self) -> &mut T {
        // Safety:
        // We know that there are no other references to `self`,
        // so it's safe to return a exclusive reference to the value.
        unsafe { &mut *self.value.get() }
    }
}

impl<T: ?Sized + Default> Default for TicketLock<T> {
    fn default() -> TicketLock<T> {
        TicketLock::new(Default::default())
    }
}

impl<'a, T: ?Sized + fmt::Debug> fmt::Debug for LockGuard<'a, T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Debug::fmt(&**self, f)
    }
}

impl<'a, T: ?Sized + fmt::Display> fmt::Display for LockGuard<'a, T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Display::fmt(&**self, f)
    }
}

impl<'a, T: ?Sized> Deref for LockGuard<'a, T> {
    type Target = T;
    fn deref(&self) -> &T {
        self.value
    }
}

impl<'a, T: ?Sized> DerefMut for LockGuard<'a, T> {
    fn deref_mut(&mut self) -> &mut T {
        self.value
    }
}

impl<'a, T: ?Sized> Drop for LockGuard<'a, T> {
    fn drop(&mut self) {
        let new_ticket = self.ticket + 1;
        self.next_serving.store(new_ticket, Ordering::Release);
    }
}

#[cfg(test)]
mod tests {
    use std::prelude::v1::*;

    use std::sync::atomic::{AtomicUsize, Ordering};
    use std::sync::mpsc::channel;
    use std::sync::Arc;
    use std::thread;

    use super::*;

    #[derive(Eq, PartialEq, Debug)]
    struct NonCopy(i32);

    #[test]
    fn smoke() {
        let m = TicketLock::new(());
        drop(m.lock());
        drop(m.lock());
    }

    #[test]
    fn lots_and_lots() {
        static M: TicketLock<()> = TicketLock::new(());
        static mut CNT: u32 = 0;
        const J: u32 = 1000;
        const K: u32 = 3;

        fn inc() {
            for _ in 0..J {
                unsafe {
                    let _g = M.lock();
                    CNT += 1;
                }
            }
        }

        let (tx, rx) = channel();
        for _ in 0..K {
            let tx2 = tx.clone();
            thread::spawn(move || {
                inc();
                tx2.send(()).unwrap();
            });
            let tx2 = tx.clone();
            thread::spawn(move || {
                inc();
                tx2.send(()).unwrap();
            });
        }

        drop(tx);
        for _ in 0..2 * K {
            rx.recv().unwrap();
        }
        assert_eq!(unsafe { CNT }, J * K * 2);
    }

    #[test]
    fn try_lock() {
        let mutex = TicketLock::new(42);

        // First lock succeeds
        let a = mutex.try_lock();
        assert_eq!(a.as_ref().map(|r| **r), Some(42));

        // Additional lock failes
        let b = mutex.try_lock();
        assert!(b.is_none());

        // After dropping lock, it succeeds again
        ::core::mem::drop(a);
        let c = mutex.try_lock();
        assert_eq!(c.as_ref().map(|r| **r), Some(42));
    }

    #[test]
    fn test_into_inner() {
        let m = TicketLock::new(NonCopy(10));
        assert_eq!(m.into_inner(), NonCopy(10));
    }

    #[test]
    fn test_into_inner_drop() {
        struct Foo(Arc<AtomicUsize>);
        impl Drop for Foo {
            fn drop(&mut self) {
                self.0.fetch_add(1, Ordering::SeqCst);
            }
        }
        let num_drops = Arc::new(AtomicUsize::new(0));
        let m = TicketLock::new(Foo(num_drops.clone()));
        assert_eq!(num_drops.load(Ordering::SeqCst), 0);
        {
            let _inner = m.into_inner();
            assert_eq!(num_drops.load(Ordering::SeqCst), 0);
        }
        assert_eq!(num_drops.load(Ordering::SeqCst), 1);
    }

    #[test]
    fn test_mutex_arc_nested() {
        // Tests nested mutexes and access
        // to underlying data.
        let arc = Arc::new(TicketLock::new(1));
        let arc2 = Arc::new(TicketLock::new(arc));
        let (tx, rx) = channel();
        let _t = thread::spawn(move || {
            let lock = arc2.lock();
            let lock2 = lock.lock();
            assert_eq!(*lock2, 1);
            tx.send(()).unwrap();
        });
        rx.recv().unwrap();
    }

    #[test]
    fn test_mutex_arc_access_in_unwind() {
        let arc = Arc::new(TicketLock::new(1));
        let arc2 = arc.clone();
        let _ = thread::spawn(move || -> () {
            struct Unwinder {
                i: Arc<TicketLock<i32>>,
            }
            impl Drop for Unwinder {
                fn drop(&mut self) {
                    *self.i.lock() += 1;
                }
            }
            let _u = Unwinder { i: arc2 };
            panic!();
        })
        .join();
        let lock = arc.lock();
        assert_eq!(*lock, 2);
    }

    #[test]
    fn test_mutex_unsized() {
        let mutex: &TicketLock<[i32]> = &TicketLock::new([1, 2, 3]);
        {
            let b = &mut *mutex.lock();
            b[0] = 4;
            b[2] = 5;
        }
        let comp: &[i32] = &[4, 2, 5];
        assert_eq!(&*mutex.lock(), comp);
    }
}
<commit_msg>Implement requested changes<commit_after>use core::{
    cell::UnsafeCell,
    fmt,
    ops::{Deref, DerefMut},
    sync::atomic::{spin_loop_hint as cpu_relax, AtomicUsize, Ordering},
};

/// A ticket lock for mutual exclusion based on spinning.
///
/// A ticket lock is similair to a queue management system.
/// When a thread tries to lock the values,
/// it is assigned a ticket, and it spins until its ticket is the next in line.
/// When releasing the value, the next ticket will be processed.
pub struct TicketMutex<T: ?Sized> {
    next_ticket: AtomicUsize,
    next_serving: AtomicUsize,
    value: UnsafeCell<T>,
}

/// A guard that protects some data.
///
/// When the guard is dropped, the next ticket will be processed.
pub struct TicketMutexGuard<'a, T: ?Sized + 'a> {
    next_serving: &'a AtomicUsize,
    ticket: usize,
    value: &'a mut T,
}

unsafe impl<T: ?Sized + Send> Sync for TicketMutex<T> {}
unsafe impl<T: ?Sized + Send> Send for TicketMutex<T> {}

impl<T> TicketMutex<T> {
    /// Creates a new `TicketMutex` that wraps the given value.
    ///
    /// This method can be used in static context.
    ///
    /// ```
    /// static LOCK: spin::TicketMutex<i32> = spin::TicketMutex::new(123);
    ///
    /// # fn main() {
    /// let value = LOCK.lock();
    /// assert_eq!(*value, 123);
    /// drop(value);
    /// # }
    /// ```
    pub const fn new(value: T) -> Self {
        Self {
            next_ticket: AtomicUsize::new(0),
            next_serving: AtomicUsize::new(0),
            value: UnsafeCell::new(value),
        }
    }

    /// Unwraps the inner value of this lock.
    pub fn into_inner(self) -> T {
        self.value.into_inner()
    }
}

impl<T: ?Sized> TicketMutex<T> {
    /// Spins the thread until the value can be locked.
    ///
    /// The returned value can be used to modify the value,
    /// and will be unlocked after dropping the return value.
    pub fn lock(&self) -> TicketMutexGuard<T> {
        let ticket = self.next_ticket.fetch_add(1, Ordering::Relaxed);

        while self.next_serving.load(Ordering::Acquire) != ticket {
            cpu_relax();
        }

        TicketMutexGuard {
            next_serving: &self.next_serving,
            ticket,
            // Safety
            // We know that we are the next ticket to be served,
            // so there's no other thread accessing the value.
            //
            // Every other thread has another ticket number so it's
            // definitely stuck in the spin loop above.
            value: unsafe { &mut *self.value.get() },
        }
    }

    /// Tries to lock this lock. If it's already locked, `None` is returned,
    /// otherwise a guard that protects the data is returned.
    pub fn try_lock(&self) -> Option<TicketMutexGuard<T>> {
        let ticket = self
            .next_ticket
            .fetch_update(Ordering::SeqCst, Ordering::SeqCst, |ticket| {
                if self.next_serving.load(Ordering::Acquire) == ticket {
                    Some(ticket + 1)
                } else {
                    None
                }
            });

        ticket.ok().map(|ticket| TicketMutexGuard {
            next_serving: &self.next_serving,
            ticket,
            // Safety
            // We have a ticket that is equal to the next_serving ticket, so we know:
            // - that no other thread can have the same ticket id as this thread
            // - that we are the next one to be served so we have exclusive access to the value
            value: unsafe { &mut *self.value.get() },
        })
    }

    /// Returns a mutable reference to the underlying data.
    ///
    /// This will not lock this lock, since this method borrows
    /// this lock mutably so no locking is needed.
    pub fn get_mut(&mut self) -> &mut T {
        // Safety:
        // We know that there are no other references to `self`,
        // so it's safe to return a exclusive reference to the value.
        unsafe { &mut *self.value.get() }
    }
}

impl<T> From<T> for TicketMutex<T> {
    fn from(value: T) -> Self {
        Self::new(value)
    }
}

impl<T: ?Sized + Default> Default for TicketMutex<T> {
    fn default() -> TicketMutex<T> {
        TicketMutex::new(Default::default())
    }
}

impl<'a, T: ?Sized + fmt::Debug> fmt::Debug for TicketMutexGuard<'a, T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Debug::fmt(&**self, f)
    }
}

impl<'a, T: ?Sized + fmt::Display> fmt::Display for TicketMutexGuard<'a, T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Display::fmt(&**self, f)
    }
}

impl<'a, T: ?Sized> Deref for TicketMutexGuard<'a, T> {
    type Target = T;
    fn deref(&self) -> &T {
        self.value
    }
}

impl<'a, T: ?Sized> DerefMut for TicketMutexGuard<'a, T> {
    fn deref_mut(&mut self) -> &mut T {
        self.value
    }
}

impl<'a, T: ?Sized> Drop for TicketMutexGuard<'a, T> {
    fn drop(&mut self) {
        let new_ticket = self.ticket + 1;
        self.next_serving.store(new_ticket, Ordering::Release);
    }
}

#[cfg(test)]
mod tests {
    use std::prelude::v1::*;

    use std::sync::atomic::{AtomicUsize, Ordering};
    use std::sync::mpsc::channel;
    use std::sync::Arc;
    use std::thread;

    use super::*;

    #[derive(Eq, PartialEq, Debug)]
    struct NonCopy(i32);

    #[test]
    fn smoke() {
        let m = TicketMutex::new(());
        drop(m.lock());
        drop(m.lock());
    }

    #[test]
    fn lots_and_lots() {
        static M: TicketMutex<()> = TicketMutex::new(());
        static mut CNT: u32 = 0;
        const J: u32 = 1000;
        const K: u32 = 3;

        fn inc() {
            for _ in 0..J {
                unsafe {
                    let _g = M.lock();
                    CNT += 1;
                }
            }
        }

        let (tx, rx) = channel();
        for _ in 0..K {
            let tx2 = tx.clone();
            thread::spawn(move || {
                inc();
                tx2.send(()).unwrap();
            });
            let tx2 = tx.clone();
            thread::spawn(move || {
                inc();
                tx2.send(()).unwrap();
            });
        }

        drop(tx);
        for _ in 0..2 * K {
            rx.recv().unwrap();
        }
        assert_eq!(unsafe { CNT }, J * K * 2);
    }

    #[test]
    fn try_lock() {
        let mutex = TicketMutex::new(42);

        // First lock succeeds
        let a = mutex.try_lock();
        assert_eq!(a.as_ref().map(|r| **r), Some(42));

        // Additional lock failes
        let b = mutex.try_lock();
        assert!(b.is_none());

        // After dropping lock, it succeeds again
        ::core::mem::drop(a);
        let c = mutex.try_lock();
        assert_eq!(c.as_ref().map(|r| **r), Some(42));
    }

    #[test]
    fn test_into_inner() {
        let m = TicketMutex::new(NonCopy(10));
        assert_eq!(m.into_inner(), NonCopy(10));
    }

    #[test]
    fn test_into_inner_drop() {
        struct Foo(Arc<AtomicUsize>);
        impl Drop for Foo {
            fn drop(&mut self) {
                self.0.fetch_add(1, Ordering::SeqCst);
            }
        }
        let num_drops = Arc::new(AtomicUsize::new(0));
        let m = TicketMutex::new(Foo(num_drops.clone()));
        assert_eq!(num_drops.load(Ordering::SeqCst), 0);
        {
            let _inner = m.into_inner();
            assert_eq!(num_drops.load(Ordering::SeqCst), 0);
        }
        assert_eq!(num_drops.load(Ordering::SeqCst), 1);
    }

    #[test]
    fn test_mutex_arc_nested() {
        // Tests nested mutexes and access
        // to underlying data.
        let arc = Arc::new(TicketMutex::new(1));
        let arc2 = Arc::new(TicketMutex::new(arc));
        let (tx, rx) = channel();
        let _t = thread::spawn(move || {
            let lock = arc2.lock();
            let lock2 = lock.lock();
            assert_eq!(*lock2, 1);
            tx.send(()).unwrap();
        });
        rx.recv().unwrap();
    }

    #[test]
    fn test_mutex_arc_access_in_unwind() {
        let arc = Arc::new(TicketMutex::new(1));
        let arc2 = arc.clone();
        let _ = thread::spawn(move || -> () {
            struct Unwinder {
                i: Arc<TicketMutex<i32>>,
            }
            impl Drop for Unwinder {
                fn drop(&mut self) {
                    *self.i.lock() += 1;
                }
            }
            let _u = Unwinder { i: arc2 };
            panic!();
        })
        .join();
        let lock = arc.lock();
        assert_eq!(*lock, 2);
    }

    #[test]
    fn test_mutex_unsized() {
        let mutex: &TicketMutex<[i32]> = &TicketMutex::new([1, 2, 3]);
        {
            let b = &mut *mutex.lock();
            b[0] = 4;
            b[2] = 5;
        }
        let comp: &[i32] = &[4, 2, 5];
        assert_eq!(&*mutex.lock(), comp);
    }
}
<|endoftext|>


<commit_before>use cfg::ColorScheme;

use ui::{BB, Px};
use ui::layout::{CollectCx, CollectBB, Layout};
use ui::color::Scheme;
use ui::draw::{Draw, DrawCx};
use ui::event::*;
use ui::text;

pub struct Set<T> {
    bb: BB<Px>,
    tabs: Vec<T>,
    current: usize
}

const TAB_WIDTH: Px = 150.0;

impl<T> Set<T> {
    pub fn new() -> Set<T> {
        Set {
            bb: BB::default(),
            tabs: vec![],
            current: 0
        }
    }

    pub fn add(&mut self, x: T) {
        if self.current + 1 < self.tabs.len() {
            self.current += 1;
        }
        self.tabs.insert(self.current, x);
    }

    pub fn remove(&mut self) -> Option<T> {
        if self.current >= self.tabs.len() {
            None
        } else {
            if self.current > 0 {
                self.current -= 1;
            }
            Some(self.tabs.remove(self.current))
        }
    }

    pub fn current(&self) -> Option<&T> {
        self.tabs.get(self.current)
    }

    pub fn current_mut(&mut self) -> Option<&mut T> {
        self.tabs.get_mut(self.current)
    }
}

impl<T: Layout> Layout for Set<T> {
    fn bb(&self) -> BB<Px> { self.bb }
    fn collect<'a>(&'a mut self, cx: &mut CollectCx<'a>) -> CollectBB<'a> {
        let bb = cx.area(&mut self.bb, "<tabset>");
        if let Some(tab) = self.tabs.get_mut(self.current) {
            let tb = tab.collect(cx);

            let height = cx.fonts().metrics(text::Regular).height * 2.0;

            cx.equal(bb.x1, tb.x1);
            cx.equal(tb.x2, bb.x2);
            cx.distance(bb.y1, tb.y1, height);
            cx.equal(tb.y2, bb.y2);
        }
        bb
    }
}

pub trait Tab {
    fn title(&self) -> String;
}

impl<T> Draw for Set<T> where T: Layout + Tab + Draw {
    fn draw(&self, cx: &mut DrawCx) {
        let [x, y] = self.bb.top_left();
        let metrics = cx.fonts().metrics(text::Regular);

        // Background for all tabs.
        cx.fill(BB::rect(x, y, (self.tabs.len() as Px) * TAB_WIDTH, metrics.height * 2.0),
                ColorScheme.inactive());

        for (i, tab) in self.tabs.iter().enumerate() {
            let text = tab.title();
            let w = cx.fonts().text_width(text::Regular, &text);

            // Background for each tab.
            let x = x + (i as Px) * TAB_WIDTH;
            cx.fill(BB::rect(x + 1.0, y, TAB_WIDTH - 2.0, metrics.height * 2.0),
                    ColorScheme.background());

            // Focus highlight.
            if i == self.current {
                let y = y + metrics.height * 2.0 - 5.0;
                cx.fill(BB::rect(x + 3.0, y, TAB_WIDTH - 3.0, 2.0), ColorScheme.focus());
            }

            cx.text(text::Regular, [(x + (TAB_WIDTH - w) / 2.0).round(),
                                    (y + metrics.height * 0.5).round()],
                                    ColorScheme.normal(), &text);
        }

        self.current().map(|tab| tab.draw(cx));
    }
}

trait SetDispatch<T, E> {
    fn dispatch(&mut self, _ev: &E) -> bool { false }
}

impl<E, T> Dispatch<E> for Set<T> where Set<T>: SetDispatch<T, E>, T: Dispatch<E> {
    fn dispatch(&mut self, ev: &E) -> bool {
        if self.current < self.tabs.len() {
            self.tabs[self.current].dispatch(ev) | SetDispatch::dispatch(self, ev)
        } else {
            false
        }
    }
}

impl<T> SetDispatch<MouseDown> for Set<T> where T: Layout {
    fn dispatch(&mut self, ev: &MouseDown) -> bool {
        let pos = [ev.x, ev.y];
        if self.bb.contains(pos) && !self.tabs[self.current].bb().contains(pos) {
            let new_tab = ((ev.x - self.bb.x1) / TAB_WIDTH) as usize;
            if new_tab < self.tabs.len() && new_tab != self.current {
                self.current = new_tab;
                return true;
            }
        }
        false
    }
}

impl<T> SetDispatch<T, MouseUp> for Set<T> {}
impl<T> SetDispatch<T, MouseMove> for Set<T> {}
impl<T> SetDispatch<T, MouseScroll> for Set<T> {}
impl<T> SetDispatch<T, Update> for Set<T> {}
impl<'a, T> SetDispatch<T, TextInput<'a>> for Set<T> {}
impl<T> SetDispatch<T, KeyDown> for Set<T> {}
impl<T> SetDispatch<T, KeyUp> for Set<T> {}
<commit_msg>ui::tab: remove redundant type parameter from SetDispatch.<commit_after>use cfg::ColorScheme;

use ui::{BB, Px};
use ui::layout::{CollectCx, CollectBB, Layout};
use ui::color::Scheme;
use ui::draw::{Draw, DrawCx};
use ui::event::*;
use ui::text;

pub struct Set<T> {
    bb: BB<Px>,
    tabs: Vec<T>,
    current: usize
}

const TAB_WIDTH: Px = 150.0;

impl<T> Set<T> {
    pub fn new() -> Set<T> {
        Set {
            bb: BB::default(),
            tabs: vec![],
            current: 0
        }
    }

    pub fn add(&mut self, x: T) {
        if self.current + 1 < self.tabs.len() {
            self.current += 1;
        }
        self.tabs.insert(self.current, x);
    }

    pub fn remove(&mut self) -> Option<T> {
        if self.current >= self.tabs.len() {
            None
        } else {
            if self.current > 0 {
                self.current -= 1;
            }
            Some(self.tabs.remove(self.current))
        }
    }

    pub fn current(&self) -> Option<&T> {
        self.tabs.get(self.current)
    }

    pub fn current_mut(&mut self) -> Option<&mut T> {
        self.tabs.get_mut(self.current)
    }
}

impl<T: Layout> Layout for Set<T> {
    fn bb(&self) -> BB<Px> { self.bb }
    fn collect<'a>(&'a mut self, cx: &mut CollectCx<'a>) -> CollectBB<'a> {
        let bb = cx.area(&mut self.bb, "<tabset>");
        if let Some(tab) = self.tabs.get_mut(self.current) {
            let tb = tab.collect(cx);

            let height = cx.fonts().metrics(text::Regular).height * 2.0;

            cx.equal(bb.x1, tb.x1);
            cx.equal(tb.x2, bb.x2);
            cx.distance(bb.y1, tb.y1, height);
            cx.equal(tb.y2, bb.y2);
        }
        bb
    }
}

pub trait Tab {
    fn title(&self) -> String;
}

impl<T> Draw for Set<T> where T: Layout + Tab + Draw {
    fn draw(&self, cx: &mut DrawCx) {
        let [x, y] = self.bb.top_left();
        let metrics = cx.fonts().metrics(text::Regular);

        // Background for all tabs.
        cx.fill(BB::rect(x, y, (self.tabs.len() as Px) * TAB_WIDTH, metrics.height * 2.0),
                ColorScheme.inactive());

        for (i, tab) in self.tabs.iter().enumerate() {
            let text = tab.title();
            let w = cx.fonts().text_width(text::Regular, &text);

            // Background for each tab.
            let x = x + (i as Px) * TAB_WIDTH;
            cx.fill(BB::rect(x + 1.0, y, TAB_WIDTH - 2.0, metrics.height * 2.0),
                    ColorScheme.background());

            // Focus highlight.
            if i == self.current {
                let y = y + metrics.height * 2.0 - 5.0;
                cx.fill(BB::rect(x + 3.0, y, TAB_WIDTH - 3.0, 2.0), ColorScheme.focus());
            }

            cx.text(text::Regular, [(x + (TAB_WIDTH - w) / 2.0).round(),
                                    (y + metrics.height * 0.5).round()],
                                    ColorScheme.normal(), &text);
        }

        self.current().map(|tab| tab.draw(cx));
    }
}

trait SetDispatch<E> {
    fn dispatch(&mut self, _ev: &E) -> bool { false }
}

impl<E, T> Dispatch<E> for Set<T> where Set<T>: SetDispatch<E>, T: Dispatch<E> {
    fn dispatch(&mut self, ev: &E) -> bool {
        if self.current < self.tabs.len() {
            self.tabs[self.current].dispatch(ev) | SetDispatch::dispatch(self, ev)
        } else {
            false
        }
    }
}

impl<T> SetDispatch<MouseDown> for Set<T> where T: Layout {
    fn dispatch(&mut self, ev: &MouseDown) -> bool {
        let pos = [ev.x, ev.y];
        if self.bb.contains(pos) && !self.tabs[self.current].bb().contains(pos) {
            let new_tab = ((ev.x - self.bb.x1) / TAB_WIDTH) as usize;
            if new_tab < self.tabs.len() && new_tab != self.current {
                self.current = new_tab;
                return true;
            }
        }
        false
    }
}

impl<T> SetDispatch<MouseUp> for Set<T> {}
impl<T> SetDispatch<MouseMove> for Set<T> {}
impl<T> SetDispatch<MouseScroll> for Set<T> {}
impl<T> SetDispatch<Update> for Set<T> {}
impl<'a, T> SetDispatch<TextInput<'a>> for Set<T> {}
impl<T> SetDispatch<KeyDown> for Set<T> {}
impl<T> SetDispatch<KeyUp> for Set<T> {}
<|endoftext|>