<commit_before>use libc::types::os::common::bsd44::{ifaddrs, sockaddr, sockaddr_in, in_addr};
use libc::funcs::bsd43::{getifaddrs,freeifaddrs,socket,bind,listen,accept};
use std::ptr;
use libc;

//OS
use libc::consts::os::bsd44::{AF_INET,AF_INET6,SOCK_STREAM};
use libc::consts::os::extra::O_NONBLOCK;

//POSIX88
use libc::funcs::posix88::unistd::close;
use libc::funcs::posix88::fcntl::{fcntl};
use libc::consts::os::posix88::{EWOULDBLOCK,EAGAIN};

use libc::consts::os::posix01::{F_GETFL,F_SETFL};

use std::num::FromPrimitive;
use std::mem::{size_of,transmute};
use std::os::errno;

use errors;

extern {
	fn htonl(host : u32 ) -> u32;
	fn htons(host : u16 ) -> u16;
}

#[deriving(Eq, PartialEq, Show)]
pub enum Address {
	IPv4(u8, u8, u8, u8, u16)
}

pub fn localhost(port:u16) -> Address { IPv4(127,0,0,1, port) }

impl Address {
	pub fn to_addr(&self) -> sockaddr {
        match *self {
			IPv4(a1, a2, a3, a4, port) => {
		        let socket_address = sockaddr_in {
			        sin_family : AF_INET as u16,
			        sin_addr : in_addr {
			            s_addr : unsafe{htonl(a1 as u32 << 24 | a2 as u32 << 16 | a3 as u32 << 8 | a4 as u32)}
			        },
			        sin_port : unsafe{htons(port)},
			        sin_zero : [0, 0, 0, 0, 0, 0, 0, 0, ]
		        };

		        return unsafe{transmute(socket_address)};
	        }
		}
	}

	pub fn to_family(&self) -> i32 {
		match *self {
			IPv4(_,_,_,_,_) => AF_INET
		}
	}
}

//pub struct Address {
//	addr : *const sockaddr,
//}
//
//impl Address{
//	pub fn protocol(&self) -> Option<Protocol> {
//		unsafe {
//			return FromPrimitive::from_u16((*self.addr).sa_family);
//		}
//	}
//}
//
//pub struct AddressInformation {
//	addresses: Vec<Address>,
//	ptr: *mut ifaddrs
//}
//
//impl Drop for AddressInformation {
//	fn drop(&mut self) {
//		unsafe {
//			freeifaddrs(self.ptr);
//		}
//	}
//}

//impl AddressInformation {
//	pub fn new() -> Result<AddressInformation, ()> {
//		unsafe {
//			let mut addr : *mut ifaddrs = ptr::null_mut();
//
//			let result = getifaddrs(&mut addr);
//
//			if result == -1 {
//				return Err(());
//			}
//
//			let mut currentAddress = addr;
//			let mut addresses = Vec::new();
//
//			while currentAddress != ptr::null_mut() {
//				addresses.push(Address {addr: & (*(*currentAddress).ifa_addr)});
//
//				currentAddress = (*currentAddress).ifa_next;
//			}
//
//
//
//			Ok(AddressInformation { addresses: addresses, ptr : addr })
//		}
//	}
//
////	pub fn with_protocol(&mut self, protocol: Protocol) {
////		self.addresses = self.addresses
////						.into_iter()
////						.filter(|a| { a.protocol().unwrap_or(Invalid) == protocol })
////						.collect::<Vec<Address>>();
////	}
//}

#[deriving(Show)]
pub struct RemoteSocket {
	pub handle: libc::c_int,
//	pub addr: Address
}

impl RemoteSocket {
	pub fn make_non_blocking(& self) -> Result<(), ()> {

		let mut flags = unsafe {fcntl (self.handle, F_GETFL, 0u32)};

		if flags == -1 {
			error!("Error encountered while modifying socket mode to be non-blocking");
			return Err(());
		}

		flags |= O_NONBLOCK;

		if unsafe {fcntl (self.handle, F_SETFL, flags)} == -1 {
			error!("Error encountered while modifying socket mode to be non-blocking");
			return Err(());
		}

		return Ok(())
	}
}

impl Drop for RemoteSocket {
fn drop(&mut self) {
	unsafe {
		debug!("Closing remote socket ({})", self);
		close(self.handle);
	}
}
}

#[deriving(Show)]
pub struct ServerSocket {
	pub handle: libc::c_int
}

impl ServerSocket {
	pub fn new(address: &Address) -> Result<ServerSocket, ()> {

			debug!("Attempting to create socket descriptor");

			let fd = unsafe {socket(address.to_family(), SOCK_STREAM | O_NONBLOCK, 0)};

			let socket = ServerSocket{handle: fd};

			if fd != -1 {
				debug!("Binding to socket ({}) on with address ({})", socket, address);

				let addr = address.to_addr();
				let result = unsafe {bind(fd, &addr, size_of::<sockaddr>() as u32)};

				return Ok(socket)
			} else {
				error!("Error creating socket descriptor - errno {}", fd);

				return Err(())
			}
	}

	pub fn listen(&self) -> Result<(),()> {
		unsafe {
			if listen(self.handle, 128) != -1 {
				debug!("Listening to socket ({})", self);
				Ok(())
			} else {
				Err(())
			}
		}
	}

	pub fn accept(&self) -> Result<RemoteSocket,()> {
		let mut addr = IPv4(0,0,0,0,0).to_addr();
		let mut len = size_of::<sockaddr>() as u32;

		let result = unsafe {accept(self.handle, &mut addr, &mut len)};

		if result == -1 {
			if errno() == EAGAIN as int || errno() == EWOULDBLOCK as int {
				Err(())
			}  else {
				debug!("Error accepting socket ({})", self);
				errors::print_error("Error accepting socket");
				Err(())
			}
		} else {
			let remote = RemoteSocket{ handle: result };
			remote.make_non_blocking();

			Ok( remote )
		}
	}
}

impl Drop for ServerSocket {
	fn drop(&mut self) {
		unsafe {
			debug!("Closing socket ({})", self);
			close(self.handle);
		}
	}
}
<commit_msg>Removed commented out code<commit_after>use libc::types::os::common::bsd44::{ifaddrs, sockaddr, sockaddr_in, in_addr};
use libc::funcs::bsd43::{getifaddrs,freeifaddrs,socket,bind,listen,accept};
use std::ptr;
use libc;

//OS
use libc::consts::os::bsd44::{AF_INET,AF_INET6,SOCK_STREAM};
use libc::consts::os::extra::O_NONBLOCK;

//POSIX88
use libc::funcs::posix88::unistd::close;
use libc::funcs::posix88::fcntl::{fcntl};
use libc::consts::os::posix88::{EWOULDBLOCK,EAGAIN};

use libc::consts::os::posix01::{F_GETFL,F_SETFL};

use std::num::FromPrimitive;
use std::mem::{size_of,transmute};
use std::os::errno;

use errors;

extern {
	fn htonl(host : u32 ) -> u32;
	fn htons(host : u16 ) -> u16;
}

#[deriving(Eq, PartialEq, Show)]
pub enum Address {
	IPv4(u8, u8, u8, u8, u16)
}

pub fn localhost(port:u16) -> Address { IPv4(127,0,0,1, port) }

impl Address {
	pub fn to_addr(&self) -> sockaddr {
        match *self {
			IPv4(a1, a2, a3, a4, port) => {
		        let socket_address = sockaddr_in {
			        sin_family : AF_INET as u16,
			        sin_addr : in_addr {
			            s_addr : unsafe{htonl(a1 as u32 << 24 | a2 as u32 << 16 | a3 as u32 << 8 | a4 as u32)}
			        },
			        sin_port : unsafe{htons(port)},
			        sin_zero : [0, 0, 0, 0, 0, 0, 0, 0, ]
		        };

		        return unsafe{transmute(socket_address)};
	        }
		}
	}

	pub fn to_family(&self) -> i32 {
		match *self {
			IPv4(_,_,_,_,_) => AF_INET
		}
	}
}

#[deriving(Show)]
pub struct RemoteSocket {
	pub handle: libc::c_int,
}

impl RemoteSocket {
	pub fn make_non_blocking(& self) -> Result<(), ()> {

		let mut flags = unsafe {fcntl (self.handle, F_GETFL, 0u32)};

		if flags == -1 {
			error!("Error encountered while modifying socket mode to be non-blocking");
			return Err(());
		}

		flags |= O_NONBLOCK;

		if unsafe {fcntl (self.handle, F_SETFL, flags)} == -1 {
			error!("Error encountered while modifying socket mode to be non-blocking");
			return Err(());
		}

		return Ok(())
	}
}

impl Drop for RemoteSocket {
fn drop(&mut self) {
	unsafe {
		debug!("Closing remote socket ({})", self);
		close(self.handle);
	}
}
}

#[deriving(Show)]
pub struct ServerSocket {
	pub handle: libc::c_int
}

impl ServerSocket {
	pub fn new(address: &Address) -> Result<ServerSocket, ()> {

			debug!("Attempting to create socket descriptor");

			let fd = unsafe {socket(address.to_family(), SOCK_STREAM | O_NONBLOCK, 0)};

			let socket = ServerSocket{handle: fd};

			if fd != -1 {
				debug!("Binding to socket ({}) on with address ({})", socket, address);

				let addr = address.to_addr();
				let result = unsafe {bind(fd, &addr, size_of::<sockaddr>() as u32)};

				return Ok(socket)
			} else {
				error!("Error creating socket descriptor - errno {}", fd);

				return Err(())
			}
	}

	pub fn listen(&self) -> Result<(),()> {
		unsafe {
			if listen(self.handle, 128) != -1 {
				debug!("Listening to socket ({})", self);
				Ok(())
			} else {
				Err(())
			}
		}
	}

	pub fn accept(&self) -> Result<RemoteSocket,()> {
		let mut addr = IPv4(0,0,0,0,0).to_addr();
		let mut len = size_of::<sockaddr>() as u32;

		let result = unsafe {accept(self.handle, &mut addr, &mut len)};

		if result == -1 {
			if errno() == EAGAIN as int || errno() == EWOULDBLOCK as int {
				Err(())
			}  else {
				debug!("Error accepting socket ({})", self);
				errors::print_error("Error accepting socket");
				Err(())
			}
		} else {
			let remote = RemoteSocket{ handle: result };
			remote.make_non_blocking();

			Ok( remote )
		}
	}
}

impl Drop for ServerSocket {
	fn drop(&mut self) {
		unsafe {
			debug!("Closing socket ({})", self);
			close(self.handle);
		}
	}
}
<|endoftext|>


<commit_before>// Copyright (C) 2016 Élisabeth HENRY.
//
// This file is part of Crowbook.
//
// Crowbook is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published
// by the Free Software Foundation, either version 2.1 of the License, or
// (at your option) any later version.
//
// Caribon is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Lesser General Public License for more details.
//
// You should have received ba copy of the GNU Lesser General Public License
// along with Crowbook.  If not, see <http://www.gnu.org/licenses/>.

use token::Token;
use error::{Result, Error, Source};
use logger::Logger;

use std::mem;
use std::fs::File;
use std::path::Path;
use std::convert::AsRef;
use std::io::Read;
use std::collections::HashMap;
use std::ops::BitOr;

use cmark::{Parser as CMParser, Event, Tag, Options, OPTION_ENABLE_FOOTNOTES, OPTION_ENABLE_TABLES};

#[derive(Debug, Copy, Clone, PartialEq)]
/// The list of features used in a document.
pub struct Features {
    pub image: bool,
    pub blockquote: bool,
    pub codeblock: bool,
    pub ordered_list: bool,
    pub footnote: bool,
    pub table: bool,
    pub url: bool,
}

impl Features {
    /// Creates a new set of features where all are set to false
    pub fn new() -> Features {
        Features {
            image: false,
            blockquote: false,
            codeblock: false,
            ordered_list: false,
            footnote: false,
            table: false,
            url: false,
        }
    }
}

impl BitOr for Features {
    type Output = Self;

    fn bitor(self, rhs: Self) -> Self {
        Features {
            image: self.image | rhs.image,
            blockquote: self.blockquote | rhs.blockquote,
            codeblock: self.codeblock | rhs.codeblock,
            ordered_list: self.ordered_list | rhs.ordered_list,
            footnote: self.footnote | rhs.footnote,
            table: self.table | rhs.table,
            url: self.url | rhs.url,
        }
    }
}

/// A parser that reads markdown and convert it to AST (a vector of `Token`s)
///
/// This AST can then be used by various renderes.
///
/// As this Parser uses Pulldown-cmark's one, it should be able to parse most
/// *valid* CommonMark variant of Markdown.
///
/// Compared to other Markdown parser, it might fail more often on invalid code, e.g.
/// footnotes references that are not defined anywhere.
///
/// # Examples
///
/// ```
/// use crowbook::Parser;
/// let mut parser = Parser::new();
/// let result = parser.parse("Some *valid* Markdown[^1]\n\n[^1]: with a valid footnote");
/// assert!(result.is_ok());
/// ```
///
/// ```
/// use crowbook::Parser;
/// let mut parser = Parser::new();
/// let result = parser.parse("Some footnote pointing to nothing[^1] ");
/// assert!(result.is_err());
/// ```
pub struct Parser {
    footnotes: HashMap<String, Vec<Token>>,
    source: Source,
    features: Features,
}

impl Parser {
    /// Creates a parser
    pub fn new() -> Parser {
        Parser {
            footnotes: HashMap::new(),
            source: Source::empty(),
            features: Features::new(),
        }
    }

    /// Sets a parser's source file
    pub fn set_source_file(&mut self, s: &str) {
        self.source = Source::new(s);
    }

    /// Parse a file and returns an AST or  an error
    pub fn parse_file<P: AsRef<Path>>(&mut self, filename: P) -> Result<Vec<Token>> {
        let path: &Path = filename.as_ref();
        let mut f = File::open(path)
            .map_err(|_| {
                Error::file_not_found(&self.source,
                                      lformat!("markdown file"),
                                      format!("{}", path.display()))
            })?;
        let mut s = String::new();

        f.read_to_string(&mut s)
            .map_err(|_| {
                Error::parser(&self.source,
                              lformat!("file {file} contains invalid UTF-8, could not parse it",
                                       file = path.display()))
            })?;
        self.parse(&s)
    }

    /// Parse a string and returns an AST  an Error.
    pub fn parse(&mut self, s: &str) -> Result<Vec<Token>> {
        let mut opts = Options::empty();
        opts.insert(OPTION_ENABLE_TABLES);
        opts.insert(OPTION_ENABLE_FOOTNOTES);
        let mut p = CMParser::new_ext(s, opts);

        let mut res = vec![];
        self.parse_events(&mut p, &mut res, None)?;

        self.parse_footnotes(&mut res)?;

        collapse(&mut res);

        find_standalone(&mut res);
        Ok(res)
    }

    /// Parse an inline string and returns a list of `Token`.
    ///
    /// This function removes the outermost `Paragraph` in most of the
    /// cases, as it is meant to be used for an inline string (e.g. metadata)
    pub fn parse_inline(&mut self, s: &str) -> Result<Vec<Token>> {
        let mut tokens = self.parse(s)?;
        // Unfortunately, parser will put all this in a paragraph, so we might need to remove it.
        if tokens.len() == 1 {
            let res = match tokens[0] {
                Token::Paragraph(ref mut v) => Some(mem::replace(v, vec![])),
                _ => None,
            };
            match res {
                Some(tokens) => Ok(tokens),
                _ => Ok(tokens),
            }
        } else {
            Ok(tokens)
        }
    }

    /// Returns the list of features used by this parser
    pub fn features(&self) -> Features {
        self.features
    }

    /// Replace footnote reference with their definition
    fn parse_footnotes(&mut self, v: &mut Vec<Token>) -> Result<()> {
        for token in v {
            match *token {
                Token::Footnote(ref mut content) => {
                    let reference = if let Token::Str(ref text) = content[0] {
                        text.clone()
                    } else {
                        panic!("Reference is not a vector of a single Token::Str");
                    };
                    if let Some(in_vec) = self.footnotes.get(&reference) {
                        *content = in_vec.clone();
                    } else {
                        return Err(Error::parser(&self.source,
                                                 lformat!("footnote reference {reference} does \
                                                           not have a matching definition",
                                                          reference = &reference)));
                    }
                }
                Token::Paragraph(ref mut vec) |
                Token::Header(_, ref mut vec) |
                Token::Emphasis(ref mut vec) |
                Token::Strong(ref mut vec) |
                Token::Code(ref mut vec) |
                Token::BlockQuote(ref mut vec) |
                Token::CodeBlock(_, ref mut vec) |
                Token::List(ref mut vec) |
                Token::OrderedList(_, ref mut vec) |
                Token::Item(ref mut vec) |
                Token::Table(_, ref mut vec) |
                Token::TableHead(ref mut vec) |
                Token::TableRow(ref mut vec) |
                Token::TableCell(ref mut vec) |
                Token::Link(_, _, ref mut vec) |
                Token::Image(_, _, ref mut vec) => self.parse_footnotes(vec)?,
                _ => (),
            }
        }
        Ok(())
    }

    fn parse_events<'a>(&mut self,
                        p: &mut CMParser<'a>,
                        v: &mut Vec<Token>,
                        current_tag: Option<&Tag>)
                        -> Result<()> {
        while let Some(event) = p.next() {
            match event {
                Event::Html(text) |
                Event::InlineHtml(text) |
                Event::Text(text) => {
                    v.push(Token::Str(text.into_owned()));
                }
                Event::Start(tag) => self.parse_tag(p, v, tag)?,
                Event::End(tag) => {
                    debug_assert!(format!("{:?}", Some(&tag)) == format!("{:?}", current_tag),
                                  format!("Error: opening and closing tags mismatch!\n{:?} ≠ \
                                           {:?}",
                                          tag,
                                          current_tag));
                    break;
                }
                Event::SoftBreak => v.push(Token::SoftBreak),
                Event::HardBreak => v.push(Token::HardBreak),
                Event::FootnoteReference(text) => {
                    v.push(Token::Footnote(vec![Token::Str(text.into_owned())]))
                }
            }
        }
        Ok(())
    }

    fn parse_tag<'a>(&mut self,
                     p: &mut CMParser<'a>,
                     v: &mut Vec<Token>,
                     tag: Tag<'a>)
                     -> Result<()> {
        let mut res = vec![];

        self.parse_events(p, &mut res, Some(&tag))?;

        let token = match tag {
            Tag::Paragraph => Token::Paragraph(res),
            Tag::Emphasis => Token::Emphasis(res),
            Tag::Strong => Token::Strong(res),
            Tag::Code => Token::Code(res),
            Tag::Header(x) => Token::Header(x, res),
            Tag::Link(url, title) => {
                self.features.url = true;
                Token::Link(url.into_owned(), title.into_owned(), res)
            },
            Tag::Image(url, title) => {
                self.features.image = true;
                Token::Image(url.into_owned(), title.into_owned(), res)
            },
            Tag::Rule => Token::Rule,
            Tag::List(opt) => {
                if let Some(n) = opt {
                    self.features.ordered_list = true;
                    Token::OrderedList(n, res)
                } else {
                    Token::List(res)
                }
            }
            Tag::Item => Token::Item(res),
            Tag::BlockQuote => {
                self.features.blockquote = true;
                Token::BlockQuote(res)
            },
            Tag::CodeBlock(language) => {
                self.features.codeblock = true;
                Token::CodeBlock(language.into_owned(), res)
            },
            Tag::Table(v) => {
                self.features.table = true;
                // TODO: actually use v's alignments
                Token::Table(v.len() as i32, res)
            },
            Tag::TableHead => Token::TableHead(res),
            Tag::TableRow => Token::TableRow(res),
            Tag::TableCell => Token::TableCell(res),
            Tag::FootnoteDefinition(reference) => {
                if self.footnotes.contains_key(reference.as_ref()) {
                    Logger::display_warning(lformat!("in {file}, found footnote definition for \
                                                      note '{reference}' but previous \
                                                      definition already exist, overriding it",
                                                     file = self.source,
                                                     reference = reference));
                }
                self.footnotes.insert(reference.into_owned(), res);
                Token::SoftBreak
            }
        };
        v.push(token);
        Ok(())
    }
}

/// Replace consecutives Strs by a Str of both, collapse soft breaks to previous std and so on
fn collapse(ast: &mut Vec<Token>) {
    if ast.len() < 2 {
        return;
    }

    let mut i = 0;
    while i < ast.len() {
        if ast[i].is_str() && i < ast.len() - 1 {
            if ast[i + 1].is_str() {
                // Two consecutives Str, concatenate them
                let token = ast.remove(i + 1);
                if let (&mut Token::Str(ref mut dest), Token::Str(ref source)) = (&mut ast[i],
                                                                                token) {
                    //                        dest.push(' ');
                    dest.push_str(source);
                    continue;
                } else {
                    unreachable!();
                }
            } else if ast[i + 1] == Token::SoftBreak {
                ast.remove(i + 1);
                if let &mut Token::Str(ref mut dest) = &mut ast[i] {
                    dest.push(' ');
                    continue;
                } else {
                    unreachable!();
                }
            }
        }

        // If token is containing others, recurse into them
        if let Some(ref mut inner) = ast[i].inner_mut() {
            collapse(inner);
        }
        i += 1;
    }
}

/// Replace images which are alone in a paragraph by standalone images
fn find_standalone(ast: &mut Vec<Token>) {
    for token in ast {
        let res = if let &mut Token::Paragraph(ref mut inner) = token {
            if inner.len() == 1 {
                if inner[0].is_image() {
                    if let Token::Image(source, title, inner) = mem::replace(&mut inner[0],
                                                                             Token::Rule) {
                        Token::StandaloneImage(source, title, inner)
                    } else {
                        unreachable!();
                    }
                } else {
                    // If paragraph only contains a link only containing an image, ok too
                    // Fixme: messy code and unnecessary clone
                    if let Token::Link(ref url, ref alt, ref mut inner) = inner[0] {
                        if inner[0].is_image() {
                            if let Token::Image(source, title, inner) = mem::replace(&mut inner[0],
                                                                                Token::Rule) {
                                Token::Link(url.clone(), alt.clone(), vec![Token::StandaloneImage(source, title, inner)])
                            } else {
                                unreachable!();
                            }
                        } else {
                            continue;
                        }
                    } else {
                        continue;
                    }
                }
            } else {
                continue;
            }
        } else {
            continue;
        };

        *token = res;
    }
}
<commit_msg>Add support for superscript<commit_after>// Copyright (C) 2016 Élisabeth HENRY.
//
// This file is part of Crowbook.
//
// Crowbook is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published
// by the Free Software Foundation, either version 2.1 of the License, or
// (at your option) any later version.
//
// Caribon is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Lesser General Public License for more details.
//
// You should have received ba copy of the GNU Lesser General Public License
// along with Crowbook.  If not, see <http://www.gnu.org/licenses/>.

use token::Token;
use error::{Result, Error, Source};
use logger::Logger;

use std::mem;
use std::fs::File;
use std::path::Path;
use std::convert::AsRef;
use std::io::Read;
use std::collections::HashMap;
use std::ops::BitOr;

use cmark::{Parser as CMParser, Event, Tag, Options, OPTION_ENABLE_FOOTNOTES, OPTION_ENABLE_TABLES};

#[derive(Debug, Copy, Clone, PartialEq)]
/// The list of features used in a document.
pub struct Features {
    pub image: bool,
    pub blockquote: bool,
    pub codeblock: bool,
    pub ordered_list: bool,
    pub footnote: bool,
    pub table: bool,
    pub url: bool,
    pub subscript: bool,
    pub superscript: bool,
}

impl Features {
    /// Creates a new set of features where all are set to false
    pub fn new() -> Features {
        Features {
            image: false,
            blockquote: false,
            codeblock: false,
            ordered_list: false,
            footnote: false,
            table: false,
            url: false,
            subscript: false,
            superscript: false,
        }
    }
}

impl BitOr for Features {
    type Output = Self;

    fn bitor(self, rhs: Self) -> Self {
        Features {
            image: self.image | rhs.image,
            blockquote: self.blockquote | rhs.blockquote,
            codeblock: self.codeblock | rhs.codeblock,
            ordered_list: self.ordered_list | rhs.ordered_list,
            footnote: self.footnote | rhs.footnote,
            table: self.table | rhs.table,
            url: self.url | rhs.url,
            subscript: self.subscript | rhs.subscript,
            superscript: self.superscript | rhs.superscript,
        }
    }
}

/// A parser that reads markdown and convert it to AST (a vector of `Token`s)
///
/// This AST can then be used by various renderes.
///
/// As this Parser uses Pulldown-cmark's one, it should be able to parse most
/// *valid* CommonMark variant of Markdown.
///
/// Compared to other Markdown parser, it might fail more often on invalid code, e.g.
/// footnotes references that are not defined anywhere.
///
/// # Examples
///
/// ```
/// use crowbook::Parser;
/// let mut parser = Parser::new();
/// let result = parser.parse("Some *valid* Markdown[^1]\n\n[^1]: with a valid footnote");
/// assert!(result.is_ok());
/// ```
///
/// ```
/// use crowbook::Parser;
/// let mut parser = Parser::new();
/// let result = parser.parse("Some footnote pointing to nothing[^1] ");
/// assert!(result.is_err());
/// ```
pub struct Parser {
    footnotes: HashMap<String, Vec<Token>>,
    source: Source,
    features: Features,
}

impl Parser {
    /// Creates a parser
    pub fn new() -> Parser {
        Parser {
            footnotes: HashMap::new(),
            source: Source::empty(),
            features: Features::new(),
        }
    }

    /// Sets a parser's source file
    pub fn set_source_file(&mut self, s: &str) {
        self.source = Source::new(s);
    }

    /// Parse a file and returns an AST or  an error
    pub fn parse_file<P: AsRef<Path>>(&mut self, filename: P) -> Result<Vec<Token>> {
        let path: &Path = filename.as_ref();
        let mut f = File::open(path)
            .map_err(|_| {
                Error::file_not_found(&self.source,
                                      lformat!("markdown file"),
                                      format!("{}", path.display()))
            })?;
        let mut s = String::new();

        f.read_to_string(&mut s)
            .map_err(|_| {
                Error::parser(&self.source,
                              lformat!("file {file} contains invalid UTF-8, could not parse it",
                                       file = path.display()))
            })?;
        self.parse(&s)
    }

    /// Parse a string and returns an AST  an Error.
    pub fn parse(&mut self, s: &str) -> Result<Vec<Token>> {
        let mut opts = Options::empty();
        opts.insert(OPTION_ENABLE_TABLES);
        opts.insert(OPTION_ENABLE_FOOTNOTES);
        let mut p = CMParser::new_ext(s, opts);

        let mut res = vec![];
        self.parse_events(&mut p, &mut res, None)?;

        self.parse_footnotes(&mut res)?;

        collapse(&mut res);

        find_standalone(&mut res);

        // Transform superscript and subscript
        for mut token in &mut res {
            if let Some(mut v) = token.inner_mut() {
                self.parse_super_vec(&mut v);
            }
        }

        Ok(res)
    }

    /// Parse an inline string and returns a list of `Token`.
    ///
    /// This function removes the outermost `Paragraph` in most of the
    /// cases, as it is meant to be used for an inline string (e.g. metadata)
    pub fn parse_inline(&mut self, s: &str) -> Result<Vec<Token>> {
        let mut tokens = self.parse(s)?;
        // Unfortunately, parser will put all this in a paragraph, so we might need to remove it.
        if tokens.len() == 1 {
            let res = match tokens[0] {
                Token::Paragraph(ref mut v) => Some(mem::replace(v, vec![])),
                _ => None,
            };
            match res {
                Some(tokens) => Ok(tokens),
                _ => Ok(tokens),
            }
        } else {
            Ok(tokens)
        }
    }

    /// Returns the list of features used by this parser
    pub fn features(&self) -> Features {
        self.features
    }

    /// Replace footnote reference with their definition
    fn parse_footnotes(&mut self, v: &mut Vec<Token>) -> Result<()> {
        for token in v {
            match *token {
                Token::Footnote(ref mut content) => {
                    let reference = if let Token::Str(ref text) = content[0] {
                        text.clone()
                    } else {
                        panic!("Reference is not a vector of a single Token::Str");
                    };
                    if let Some(in_vec) = self.footnotes.get(&reference) {
                        *content = in_vec.clone();
                    } else {
                        return Err(Error::parser(&self.source,
                                                 lformat!("footnote reference {reference} does \
                                                           not have a matching definition",
                                                          reference = &reference)));
                    }
                }
                Token::Paragraph(ref mut vec) |
                Token::Header(_, ref mut vec) |
                Token::Emphasis(ref mut vec) |
                Token::Strong(ref mut vec) |
                Token::Code(ref mut vec) |
                Token::BlockQuote(ref mut vec) |
                Token::CodeBlock(_, ref mut vec) |
                Token::List(ref mut vec) |
                Token::OrderedList(_, ref mut vec) |
                Token::Item(ref mut vec) |
                Token::Table(_, ref mut vec) |
                Token::TableHead(ref mut vec) |
                Token::TableRow(ref mut vec) |
                Token::TableCell(ref mut vec) |
                Token::Link(_, _, ref mut vec) |
                Token::Image(_, _, ref mut vec) => self.parse_footnotes(vec)?,
                _ => (),
            }
        }
        Ok(())
    }

    /// Looks for super script in a vector of token
    fn parse_super_vec(&mut self, mut v: &mut Vec<Token>) {
        for i in 0..v.len() {
            let new = if let Token::Str(ref s) = v[i] {
                parse_super_str(s)
            } else {
                None
            };
            if let Some(mut new) = new {
                self.features.superscript = true;
                let mut post = v.split_off(i);
                post.remove(0);
                self.parse_super_vec(&mut post);
                v.append(&mut new);
                v.append(&mut post);
                return;
            }
        }
    }

    fn parse_events<'a>(&mut self,
                        p: &mut CMParser<'a>,
                        v: &mut Vec<Token>,
                        current_tag: Option<&Tag>)
                        -> Result<()> {
        while let Some(event) = p.next() {
            match event {
                Event::Html(text) |
                Event::InlineHtml(text) |
                Event::Text(text) => {
                    v.push(Token::Str(text.into_owned()));
                }
                Event::Start(tag) => self.parse_tag(p, v, tag)?,
                Event::End(tag) => {
                    debug_assert!(format!("{:?}", Some(&tag)) == format!("{:?}", current_tag),
                                  format!("Error: opening and closing tags mismatch!\n{:?} ≠ \
                                           {:?}",
                                          tag,
                                          current_tag));
                    break;
                }
                Event::SoftBreak => v.push(Token::SoftBreak),
                Event::HardBreak => v.push(Token::HardBreak),
                Event::FootnoteReference(text) => {
                    v.push(Token::Footnote(vec![Token::Str(text.into_owned())]))
                }
            }
        }
        Ok(())
    }

    fn parse_tag<'a>(&mut self,
                     p: &mut CMParser<'a>,
                     v: &mut Vec<Token>,
                     tag: Tag<'a>)
                     -> Result<()> {
        let mut res = vec![];

        self.parse_events(p, &mut res, Some(&tag))?;

        let token = match tag {
            Tag::Paragraph => Token::Paragraph(res),
            Tag::Emphasis => Token::Emphasis(res),
            Tag::Strong => Token::Strong(res),
            Tag::Code => Token::Code(res),
            Tag::Header(x) => Token::Header(x, res),
            Tag::Link(url, title) => {
                self.features.url = true;
                Token::Link(url.into_owned(), title.into_owned(), res)
            },
            Tag::Image(url, title) => {
                self.features.image = true;
                Token::Image(url.into_owned(), title.into_owned(), res)
            },
            Tag::Rule => Token::Rule,
            Tag::List(opt) => {
                if let Some(n) = opt {
                    self.features.ordered_list = true;
                    Token::OrderedList(n, res)
                } else {
                    Token::List(res)
                }
            }
            Tag::Item => Token::Item(res),
            Tag::BlockQuote => {
                self.features.blockquote = true;
                Token::BlockQuote(res)
            },
            Tag::CodeBlock(language) => {
                self.features.codeblock = true;
                Token::CodeBlock(language.into_owned(), res)
            },
            Tag::Table(v) => {
                self.features.table = true;
                // TODO: actually use v's alignments
                Token::Table(v.len() as i32, res)
            },
            Tag::TableHead => Token::TableHead(res),
            Tag::TableRow => Token::TableRow(res),
            Tag::TableCell => Token::TableCell(res),
            Tag::FootnoteDefinition(reference) => {
                if self.footnotes.contains_key(reference.as_ref()) {
                    Logger::display_warning(lformat!("in {file}, found footnote definition for \
                                                      note '{reference}' but previous \
                                                      definition already exist, overriding it",
                                                     file = self.source,
                                                     reference = reference));
                }
                self.footnotes.insert(reference.into_owned(), res);
                Token::SoftBreak
            }
        };
        v.push(token);
        Ok(())
    }
}

/// Look to a string and see if there is some superscript in it. If true, returns a vec of toens
fn parse_super_str(s: &str) -> Option<Vec<Token>> {
    fn escape(s: String) -> String {
        s.replace("\\^", "^")
    }
    let match_indices = s.match_indices('^');
    for (begin, _) in match_indices {
        let bytes = s.as_bytes();
        let len = bytes.len();
        // Check if ^ was escaped
        if begin > 0 && bytes[begin - 1] == b'\\' {
            continue;
        } else if begin + 1 >= len {
            return None;
        } else {
            let mut i = begin + 1;
            let mut sup = vec![];
            let mut end = None;
            while i < len {
                match bytes[i] {
                    b'\\' => {
                        if i+1 < len && bytes[i+1] == b' ' {
                            sup.push(b' ');
                            i += 2;
                        } else if i + 1 < len && bytes[i+1] == b'^' {
                            sup.push(b'^');
                            i += 2;
                        } else {
                            sup.push(b'\\');
                            i += 1;
                        }
                    },
                    b' ' => {
                        return None;
                    },
                    b'^' => {
                        end = Some(i);
                        break;
                    },
                    b => {
                        sup.push(b);
                        i += 1;
                    },
                }
            }
            if let Some(end) = end {
                let mut tokens = vec![];
                if begin > 0 {
                    let pre_part = String::from_utf8((&bytes[0..begin])
                                                     .to_owned())
                        .unwrap();
                    tokens.push(Token::Str(escape(pre_part)));
                }
                let sup_part = String::from_utf8(sup).unwrap();
                tokens.push(Token::Superscript(vec![Token::Str(sup_part)]));
                if end+1 < len {
                    let post_part = String::from_utf8((&bytes[end + 1..]).to_owned()).unwrap();
                    if let Some(mut v) = parse_super_str(&post_part) {
                        tokens.append(&mut v);
                    } else {
                        tokens.push(Token::Str(escape(post_part)));
                    }
                }
                return Some(tokens);
            } else {
                return None;
            }
        }
    }
    return None;
}

#[test]
fn test_parse_super_str() {
    assert!(parse_super_str("String without superscript").is_none());
    assert!(parse_super_str("String \\^without\\^ superscript").is_none());
    assert!(parse_super_str("String ^without superscript").is_none());
    assert!(parse_super_str("String ^without superscript^").is_none());
    assert_eq!(parse_super_str("^up^"), Some(vec!(Token::Superscript(vec!(Token::Str(String::from("up")))))));
    assert_eq!(parse_super_str("foo^up^ bar"),
               Some(vec!(Token::Str("foo".to_owned()),
                         Token::Superscript(vec!(Token::Str("up".to_owned()))),
                         Token::Str(" bar".to_owned()))));
    assert_eq!(parse_super_str("foo^up^ bar^up^baz"),
               Some(vec!(Token::Str("foo".to_owned()),
                         Token::Superscript(vec!(Token::Str("up".to_owned()))),
                         Token::Str(" bar".to_owned()),
                         Token::Superscript(vec!(Token::Str("up".to_owned()))),
                         Token::Str("baz".to_owned()))));
    assert_eq!(parse_super_str("foo^up^ bar^baz"),
               Some(vec!(Token::Str("foo".to_owned()),
                         Token::Superscript(vec!(Token::Str("up".to_owned()))),
                         Token::Str(" bar^baz".to_owned()))));
    assert_eq!(parse_super_str("foo\\^bar^up^"),
               Some(vec!(Token::Str("foo^bar".to_owned()),
                         Token::Superscript(vec!(Token::Str("up".to_owned()))))));
    assert_eq!(parse_super_str("foo^bar\\^up^"),
               Some(vec!(Token::Str("foo".to_owned()),
                         Token::Superscript(vec!(Token::Str("bar^up".to_owned()))))));
    assert_eq!(parse_super_str("foo^bar up^"),
               None);
    assert_eq!(parse_super_str("foo^bar\\ up^"),
               Some(vec!(Token::Str("foo".to_owned()),
                         Token::Superscript(vec!(Token::Str("bar up".to_owned()))))));

}

/// Replace consecutives Strs by a Str of both, collapse soft breaks to previous std and so on
fn collapse(ast: &mut Vec<Token>) {
    if ast.len() < 2 {
        return;
    }

    let mut i = 0;
    while i < ast.len() {
        if ast[i].is_str() && i < ast.len() - 1 {
            if ast[i + 1].is_str() {
                // Two consecutives Str, concatenate them
                let token = ast.remove(i + 1);
                if let (&mut Token::Str(ref mut dest), Token::Str(ref source)) = (&mut ast[i],
                                                                                token) {
                    //                        dest.push(' ');
                    dest.push_str(source);
                    continue;
                } else {
                    unreachable!();
                }
            } else if ast[i + 1] == Token::SoftBreak {
                ast.remove(i + 1);
                if let &mut Token::Str(ref mut dest) = &mut ast[i] {
                    dest.push(' ');
                    continue;
                } else {
                    unreachable!();
                }
            }
        }

        // If token is containing others, recurse into them
        if let Some(ref mut inner) = ast[i].inner_mut() {
            collapse(inner);
        }
        i += 1;
    }
}

/// Replace images which are alone in a paragraph by standalone images
fn find_standalone(ast: &mut Vec<Token>) {
    for token in ast {
        let res = if let &mut Token::Paragraph(ref mut inner) = token {
            if inner.len() == 1 {
                if inner[0].is_image() {
                    if let Token::Image(source, title, inner) = mem::replace(&mut inner[0],
                                                                             Token::Rule) {
                        Token::StandaloneImage(source, title, inner)
                    } else {
                        unreachable!();
                    }
                } else {
                    // If paragraph only contains a link only containing an image, ok too
                    // Fixme: messy code and unnecessary clone
                    if let Token::Link(ref url, ref alt, ref mut inner) = inner[0] {
                        if inner[0].is_image() {
                            if let Token::Image(source, title, inner) = mem::replace(&mut inner[0],
                                                                                Token::Rule) {
                                Token::Link(url.clone(), alt.clone(), vec![Token::StandaloneImage(source, title, inner)])
                            } else {
                                unreachable!();
                            }
                        } else {
                            continue;
                        }
                    } else {
                        continue;
                    }
                }
            } else {
                continue;
            }
        } else {
            continue;
        };

        *token = res;
    }
}
<|endoftext|>


<commit_before>
// Std imports
use std::num;

// local imports

use matrix::*;

#[doc="Returns the determinant of a matrix.

# Remarks

The determinant is defined only for square matrices.

The determinant of an empty matrix is 1.
See http://en.wikipedia.org/wiki/Matrix_(mathematics)#Empty_matrices.

"]
pub fn  det<T:Number+Signed>(m : &Matrix<T>)->Result<T,SRError>{
    if !m.is_square(){
        return Err(IsNotSquareMatrix);
    }
    if m.is_empty(){
        return Ok(num::One::one());
    }
    Ok(det_(m))
}

/// Private implementation of determinant
/// Assumes that matrix is indeed square.
fn det_<T:Number+Signed>(m : &Matrix<T>)->T{
    let a0 = m.get(0, 0);
    debug!("m: {}", m);
    if m.is_scalar(){
        return a0;
    }
    let n = m.num_cols();
    let mut m2 = m.sub_matrix(1,1, n-1, n-1);
    let ps = m.as_ptr();
    let pd = m2.as_mut_ptr();
    let mut sign : T  = num::One::one();
    let mut result = sign * a0 * det_(&m2);
    sign = -sign;
    for c in range(0, n-1){
        for r in range(1, n){
            debug!("r : {}, c : {}", r , c);
            let src_offset = m.cell_to_offset(r, c);
            let dst_offset = m2.cell_to_offset(r - 1, c);
            debug_assert!(src_offset < m.capacity() as int);
            debug_assert!(dst_offset < m2.capacity() as int);
            unsafe {
                let v = *ps.offset(src_offset);
                //debug!("v = {}", v);
                *pd.offset(dst_offset) = v;
            }
        }
        let ai = m.get(0, c+1);
        let ai_minor_det =  det_(&m2);
        debug!("sign: {}, ai: {}, Ai : {}", sign, ai, ai_minor_det);
        result = result + sign * ai * ai_minor_det;
        sign = -sign;
    }
    result
}

#[cfg(test)]
mod test{
    use super::*;
    use matrix::*;
    use std::num;
    use testdata;

    #[test]
    fn test_det_0(){
        let m = matrix_cw_i64(2,2, [1, 2, 3, 4]);
        let d = det(&m).unwrap();
        assert_eq!(d, -2);
    }

    #[test]
    fn test_det_1(){
        let m = matrix_cw_i64(3, 3, [1, 2, 3, 4, 5, 6, 7, 8, 9]);
        let d = det(&m).unwrap();
        assert_eq!(d, 0);
    }

    #[test]
    fn test_det_hadamard(){
        let m = hadamard(4).unwrap();
        let d = det(&m).unwrap();
        assert_eq!(d, 16.0);

        let m = hadamard(8).unwrap();
        let d = det(&m).unwrap();
        assert_eq!(d, 4096.0);
    }

    #[test]
    fn test_det_hilbert(){
        assert_eq!(hilbert(1).det().unwrap(), 1.0);
        assert!(num::abs(hilbert(2).det().unwrap() - 0.083333333333333) < 1e-10);
        assert!(num::abs(hilbert(4).det().unwrap() - 1.653439153439264e-07) < 1e-10);
        assert!(num::abs(hilbert(8).det().unwrap() - 2.737050310006999e-33) < 1e-10);
    }

    #[test]
    fn test_empty_mat_det(){
        let m : MatrixI64 = Matrix::new(0, 0);
        let d = m.det().unwrap();
        assert_eq!(d, 1);
    }

    #[test]
    fn test_examples_from_testdata(){
        assert_eq!(testdata::matrix::square_0().det().unwrap(), -13.);
        assert_eq!(testdata::matrix::square_1().det().unwrap(), 6.);
    }

}
<commit_msg>naive and fast elimination based implementation of determinant.<commit_after>
// Std imports
use std::num;
use std::num::{One};

// local imports

use matrix::*;

#[doc="Returns the determinant of a matrix.

# Remarks

This is a naive implementation of determinant based on the
definition of determinant.  See det_float for better implementation
for floating point matrices.

Usually determinants based on
elimination or factorization are much faster.

The determinant is defined only for square matrices.

The determinant of an empty matrix is 1.
See http://en.wikipedia.org/wiki/Matrix_(mathematics)#Empty_matrices.

"]
pub fn  det<T:Number+Signed>(m : &Matrix<T>)->Result<T,SRError>{
    if !m.is_square(){
        return Err(IsNotSquareMatrix);
    }
    if m.is_empty(){
        return Ok(num::One::one());
    }
    Ok(det_naive(m))
}

#[doc="Returns the determinant of a matrix of floating point numbers.

# Remarks
"]
pub fn  det_float<T:Number+Signed+Float>(m : &Matrix<T>)->Result<T,SRError>{
    if !m.is_square(){
        return Err(IsNotSquareMatrix);
    }
    if m.is_empty(){
        return Ok(num::One::one());
    }
    Ok(det_ge(&mut m.clone()))
}

/// Private implementation of determinant
/// Assumes that matrix is indeed square.
pub fn det_naive<T:Number+Signed>(m : &Matrix<T>)->T{
    let a0 = m.get(0, 0);
    //debug!("m: {}", m);
    if m.is_scalar(){
        return a0;
    }
    let n = m.num_cols();
    let mut m2 = m.sub_matrix(1,1, n-1, n-1);
    let ps = m.as_ptr();
    let pd = m2.as_mut_ptr();
    let mut sign : T  = num::One::one();
    let mut result = sign * a0 * det_naive(&m2);
    sign = -sign;
    for c in range(0, n-1){
        for r in range(1, n){
            debug!("r : {}, c : {}", r , c);
            let src_offset = m.cell_to_offset(r, c);
            let dst_offset = m2.cell_to_offset(r - 1, c);
            //debug_assert!(src_offset < m.capacity() as int);
            //debug_assert!(dst_offset < m2.capacity() as int);
            unsafe {
                let v = *ps.offset(src_offset);
                //debug!("v = {}", v);
                *pd.offset(dst_offset) = v;
            }
        }
        let ai = m.get(0, c+1);
        let ai_minor_det =  det_naive(&m2);
        //debug!("sign: {}, ai: {}, Ai : {}", sign, ai, ai_minor_det);
        result = result + sign * ai * ai_minor_det;
        sign = -sign;
    }
    result
}

#[doc="Computes determinant using Gaussian
elimination with partial pivoting
"]
pub fn det_ge<T:Number+Signed+Float>(a : &mut Matrix<T>)->T{
    assert!(a.is_square());
    let o = One::one();
    let mut result : T = o;
    let n = a.num_cols();
    // Iterate over rows
    for k in range(0, n){
        // We are working on k-th row.
        // Find the pivot position in the row
        let (_, cc) = a.max_abs_scalar_in_row(k, k, n);
        if cc > k {
            // We need to exchange columns of the submatrix.
            let mut l_tr = a.view(k, k, n - k, n - k);
            l_tr.eco_switch(0, cc - k);
            // The sign of determinant would change
            // depending on whether the permutation is
            // even or odd.
            let diff = cc - k;
            if (diff & 1) != 0 {
                // the gap in columns is odd.
                // we should change the sign of determinant.
                result = - result;
            }
        }
        // The top right part of L matrix
        let mut l_tr  = a.view(k, k, n - k, n -k);
        // Pick up the pivot
        let pivot = l_tr.get(0, 0);
        if pivot.is_zero() {
            // This is a singular matrix
            return pivot;
        }
        // Update determinant
        result = result * pivot;
        // bring 1 in the diagonal
        l_tr.eco_scale(0, o/pivot);
        for c in range(1, l_tr.num_cols()){
            let first = l_tr.get(0, c);
            l_tr.eco_scale_add(c, 0, -first);
        }
    }
    result
}

/******************************************************
 *
 *   Unit tests
 *
 ******************************************************/

#[cfg(test)]
mod test{
    use super::*;
    use matrix::*;
    use std::num;
    use testdata;

    #[test]
    fn test_det_0(){
        let m = matrix_rw_f64(2,2, [
            1., 2.,
            3., 4.]);
        let d = det_naive(&m);
        assert_eq!(d, -2.);
        let d = det_ge(&mut m.clone());
        assert_eq!(d, -2.);
    }

    #[test]
    fn test_det_1(){
        let m = matrix_rw_f64(3, 3, [1., 2., 3.,
            4., 5., 6.,
            7., 8., 9.]);
        let d = det_naive(&m);
        assert_eq!(d, 0.);
        let d = det_ge(&mut m.clone());
        assert_eq!(d, 0.);
    }

    #[test]
    fn test_det_hadamard(){
        let m = hadamard(4).unwrap();
        let d = det_naive(&m);
        assert_eq!(d, 16.0);
        let d = det_ge(&mut m.clone());
        assert_eq!(d, 16.0);

        let m = hadamard(8).unwrap();
        let d = det_naive(&m);
        assert_eq!(d, 4096.0);
        let d = det_ge(&mut m.clone());
        assert_eq!(d, 4096.0);
    }

    #[test]
    fn test_det_hilbert(){
        let sizes = vec![1u, 2, 4, 8];
        let determinants = vec![1.0, 0.083333333333333,
            1.653439153439264e-07, 2.737050310006999e-33];
        let threshold =  1e-10;
        for (size, expected_value) in sizes.iter().zip(determinants.iter()){
            let m = hilbert(*size);
            let d = det_naive(&m);
            assert!(num::abs(d - *expected_value) < threshold);
            let d = det_ge(&mut m.clone());
            assert!(num::abs(d - *expected_value) < threshold);
        }
    }

    #[test]
    fn test_empty_mat_det(){
        let m : MatrixI64 = Matrix::new(0, 0);
        let d = m.det().unwrap();
        assert_eq!(d, 1);
    }

    #[test]
    fn test_examples_from_testdata(){
        assert_eq!(testdata::matrix::square_0().det().unwrap(), -13.);
        assert_eq!(testdata::matrix::square_1().det().unwrap(), 6.);
    }

}

/******************************************************
 *
 *   Benchmarks
 *
 ******************************************************/

#[cfg(test)]
mod bench{

    extern crate test;
    use self::test::Bencher;
    use super::*;
    use matrix::*;

    #[bench]
    fn bench_det_naive_hadamard_8 (b: &mut Bencher){
        let a = hadamard(8).unwrap();
        b.iter(|| {
            det_naive(&a);
        });
    }
    #[bench]
    fn bench_det_ge_hadamard_8 (b: &mut Bencher){
        let a = hadamard(8).unwrap();
        b.iter(|| {
            det_ge(&mut a.clone());
        });
    }
    #[bench]
    #[ignore]
    fn bench_det_naive_hadamard_16 (b: &mut Bencher){
        let a = hadamard(16).unwrap();
        b.iter(|| {
            det_naive(&a);
        });
    }
}
<|endoftext|>


<commit_before>use std::borrow::Cow;
use std::fmt::{self, Debug};

use serde::ser::{Serialize, Serializer, SerializeStruct};
use serde::de::{self, Deserialize, Deserializer, DeserializeSeed, IntoDeserializer, MapAccess, Unexpected, Visitor};
use serde::de::value::BorrowedStrDeserializer;

use error::Error;

/// Represents any valid JSON value as a series of raw bytes.
///
/// This type can be used to defer parsing parts of a payload until later,
/// or to embed it verbatim into another JSON payload.
///
/// When serializing, a value of this type will retain its original formatting
/// and will not be minified or pretty-printed.
///
/// When deserializing, this type can not be used with the `#[serde(flatten)]` attribute,
/// as it relies on the original input buffer.

#[derive(Clone)]
pub struct RawValue<'a>(Cow<'a, str>);

impl<'a> Debug for RawValue<'a> {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        formatter
            .debug_tuple("RawValue")
            .field(&format_args!("{}", self.0))
            .finish()
    }
}

impl<'a> AsRef<str> for RawValue<'a> {
    fn as_ref(&self) -> &str {
        &self.0
    }
}

impl<'a> fmt::Display for RawValue<'a> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.write_str(&self.0)
    }
}

pub const SERDE_STRUCT_NAME: &'static str = "$serde_json::RawValue";
pub const SERDE_STRUCT_FIELD_NAME: &'static str = "$serde_json::RawValue::id";

impl<'a> Serialize for RawValue<'a> {
    #[inline]
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        let mut s = serializer.serialize_struct(SERDE_STRUCT_NAME, 1)?;
        s.serialize_field(SERDE_STRUCT_FIELD_NAME, &self.0)?;
        s.end()
    }
}

impl<'a, 'de: 'a> Deserialize<'de> for RawValue<'a> {
    #[inline]
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        struct RawValueVisitor;

        impl<'de> Visitor<'de> for RawValueVisitor {
            type Value = RawValue<'de>;

            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
                write!(formatter, "any valid JSON value")
            }

            fn visit_map<V>(self, mut visitor: V) -> Result<Self::Value, V::Error>
            where
                V: MapAccess<'de>,
            {
                let value = visitor.next_key::<RawKey>()?;
                if value.is_none() {
                    return Err(de::Error::invalid_type(Unexpected::Map, &self));
                }
                visitor.next_value_seed(RawValueFromString)
            }
        }

        deserializer.deserialize_newtype_struct(SERDE_STRUCT_NAME, RawValueVisitor)
    }
}

struct RawKey;

impl<'de> Deserialize<'de> for RawKey {
    fn deserialize<D>(deserializer: D) -> Result<RawKey, D::Error>
    where
        D: Deserializer<'de>,
    {
        struct FieldVisitor;

        impl<'de> Visitor<'de> for FieldVisitor {
            type Value = ();

            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
                formatter.write_str("raw value")
            }

            fn visit_str<E>(self, s: &str) -> Result<(), E>
            where
                E: de::Error,
            {
                if s == SERDE_STRUCT_FIELD_NAME {
                    Ok(())
                } else {
                    Err(de::Error::custom("unexpected raw value"))
                }
            }
        }

        deserializer.deserialize_identifier(FieldVisitor)?;
        Ok(RawKey)
    }
}

pub struct RawValueFromString;

impl<'de> DeserializeSeed<'de> for RawValueFromString {
    type Value = RawValue<'de>;

    fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
    where
        D: Deserializer<'de>,
    {
        deserializer.deserialize_str(self)
    }
}

impl<'de> Visitor<'de> for RawValueFromString {
    type Value = RawValue<'de>;

    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        formatter.write_str("raw value")
    }

    fn visit_borrowed_str<E>(self, s: &'de str) -> Result<Self::Value, E>
    where
        E: de::Error,
    {
        Ok(RawValue(Cow::Borrowed(s)))
    }

    fn visit_string<E>(self, s: String) -> Result<Self::Value, E>
    where
        E: de::Error,
    {
        Ok(RawValue(Cow::Owned(s)))
    }
}

struct RawKeyDeserializer;

impl<'de> Deserializer<'de> for RawKeyDeserializer {
    type Error = Error;

    fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Error>
    where
        V: de::Visitor<'de>,
    {
        visitor.visit_borrowed_str(SERDE_STRUCT_FIELD_NAME)
    }

    forward_to_deserialize_any! {
        bool u8 u16 u32 u64 u128 i8 i16 i32 i64 i128 f32 f64 char str string seq
        bytes byte_buf map struct option unit newtype_struct ignored_any
        unit_struct tuple_struct tuple enum identifier
    }
}

pub struct OwnedRawDeserializer {
    pub raw_value: Option<String>,
}

impl<'de> MapAccess<'de> for OwnedRawDeserializer {
    type Error = Error;

    fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>, Error>
    where
        K: de::DeserializeSeed<'de>,
    {
        if self.raw_value.is_none() {
            return Ok(None);
        }
        seed.deserialize(RawKeyDeserializer).map(Some)
    }

    fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value, Error>
    where
        V: de::DeserializeSeed<'de>,
    {
        seed.deserialize(self.raw_value.take().unwrap().into_deserializer())
    }
}

pub struct BorrowedRawDeserializer<'de> {
    pub raw_value: Option<&'de str>,
}

impl<'de> MapAccess<'de> for BorrowedRawDeserializer<'de> {
    type Error = Error;

    fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>, Error>
    where
        K: de::DeserializeSeed<'de>,
    {
        if self.raw_value.is_none() {
            return Ok(None);
        }
        seed.deserialize(RawKeyDeserializer).map(Some)
    }

    fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value, Error>
    where
        V: de::DeserializeSeed<'de>,
    {
        seed.deserialize(BorrowedStrDeserializer::new(self.raw_value.take().unwrap()))
    }
}
<commit_msg>Name the RawValue private field<commit_after>use std::borrow::Cow;
use std::fmt::{self, Debug};

use serde::ser::{Serialize, Serializer, SerializeStruct};
use serde::de::{self, Deserialize, Deserializer, DeserializeSeed, IntoDeserializer, MapAccess, Unexpected, Visitor};
use serde::de::value::BorrowedStrDeserializer;

use error::Error;

/// Represents any valid JSON value as a series of raw bytes.
///
/// This type can be used to defer parsing parts of a payload until later,
/// or to embed it verbatim into another JSON payload.
///
/// When serializing, a value of this type will retain its original formatting
/// and will not be minified or pretty-printed.
///
/// When deserializing, this type can not be used with the `#[serde(flatten)]` attribute,
/// as it relies on the original input buffer.

#[derive(Clone)]
pub struct RawValue<'a> {
    cow: Cow<'a, str>,
}

impl<'a> Debug for RawValue<'a> {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        formatter
            .debug_tuple("RawValue")
            .field(&format_args!("{}", self.cow))
            .finish()
    }
}

impl<'a> AsRef<str> for RawValue<'a> {
    fn as_ref(&self) -> &str {
        &self.cow
    }
}

impl<'a> fmt::Display for RawValue<'a> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.write_str(&self.cow)
    }
}

pub const SERDE_STRUCT_NAME: &'static str = "$serde_json::RawValue";
pub const SERDE_STRUCT_FIELD_NAME: &'static str = "$serde_json::RawValue::id";

impl<'a> Serialize for RawValue<'a> {
    #[inline]
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        let mut s = serializer.serialize_struct(SERDE_STRUCT_NAME, 1)?;
        s.serialize_field(SERDE_STRUCT_FIELD_NAME, &self.cow)?;
        s.end()
    }
}

impl<'a, 'de: 'a> Deserialize<'de> for RawValue<'a> {
    #[inline]
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        struct RawValueVisitor;

        impl<'de> Visitor<'de> for RawValueVisitor {
            type Value = RawValue<'de>;

            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
                write!(formatter, "any valid JSON value")
            }

            fn visit_map<V>(self, mut visitor: V) -> Result<Self::Value, V::Error>
            where
                V: MapAccess<'de>,
            {
                let value = visitor.next_key::<RawKey>()?;
                if value.is_none() {
                    return Err(de::Error::invalid_type(Unexpected::Map, &self));
                }
                visitor.next_value_seed(RawValueFromString)
            }
        }

        deserializer.deserialize_newtype_struct(SERDE_STRUCT_NAME, RawValueVisitor)
    }
}

struct RawKey;

impl<'de> Deserialize<'de> for RawKey {
    fn deserialize<D>(deserializer: D) -> Result<RawKey, D::Error>
    where
        D: Deserializer<'de>,
    {
        struct FieldVisitor;

        impl<'de> Visitor<'de> for FieldVisitor {
            type Value = ();

            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
                formatter.write_str("raw value")
            }

            fn visit_str<E>(self, s: &str) -> Result<(), E>
            where
                E: de::Error,
            {
                if s == SERDE_STRUCT_FIELD_NAME {
                    Ok(())
                } else {
                    Err(de::Error::custom("unexpected raw value"))
                }
            }
        }

        deserializer.deserialize_identifier(FieldVisitor)?;
        Ok(RawKey)
    }
}

pub struct RawValueFromString;

impl<'de> DeserializeSeed<'de> for RawValueFromString {
    type Value = RawValue<'de>;

    fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
    where
        D: Deserializer<'de>,
    {
        deserializer.deserialize_str(self)
    }
}

impl<'de> Visitor<'de> for RawValueFromString {
    type Value = RawValue<'de>;

    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        formatter.write_str("raw value")
    }

    fn visit_borrowed_str<E>(self, s: &'de str) -> Result<Self::Value, E>
    where
        E: de::Error,
    {
        Ok(RawValue { cow: Cow::Borrowed(s) })
    }

    fn visit_string<E>(self, s: String) -> Result<Self::Value, E>
    where
        E: de::Error,
    {
        Ok(RawValue { cow: Cow::Owned(s) })
    }
}

struct RawKeyDeserializer;

impl<'de> Deserializer<'de> for RawKeyDeserializer {
    type Error = Error;

    fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Error>
    where
        V: de::Visitor<'de>,
    {
        visitor.visit_borrowed_str(SERDE_STRUCT_FIELD_NAME)
    }

    forward_to_deserialize_any! {
        bool u8 u16 u32 u64 u128 i8 i16 i32 i64 i128 f32 f64 char str string seq
        bytes byte_buf map struct option unit newtype_struct ignored_any
        unit_struct tuple_struct tuple enum identifier
    }
}

pub struct OwnedRawDeserializer {
    pub raw_value: Option<String>,
}

impl<'de> MapAccess<'de> for OwnedRawDeserializer {
    type Error = Error;

    fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>, Error>
    where
        K: de::DeserializeSeed<'de>,
    {
        if self.raw_value.is_none() {
            return Ok(None);
        }
        seed.deserialize(RawKeyDeserializer).map(Some)
    }

    fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value, Error>
    where
        V: de::DeserializeSeed<'de>,
    {
        seed.deserialize(self.raw_value.take().unwrap().into_deserializer())
    }
}

pub struct BorrowedRawDeserializer<'de> {
    pub raw_value: Option<&'de str>,
}

impl<'de> MapAccess<'de> for BorrowedRawDeserializer<'de> {
    type Error = Error;

    fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>, Error>
    where
        K: de::DeserializeSeed<'de>,
    {
        if self.raw_value.is_none() {
            return Ok(None);
        }
        seed.deserialize(RawKeyDeserializer).map(Some)
    }

    fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value, Error>
    where
        V: de::DeserializeSeed<'de>,
    {
        seed.deserialize(BorrowedStrDeserializer::new(self.raw_value.take().unwrap()))
    }
}
<|endoftext|>


<commit_before>use libc::{c_void,c_char,c_int,c_long,size_t};
use std;
use std::c_str::CString;
use std::ptr::null;
use std::mem::transmute;
use native;

pub struct Config {
    pub port: uint,
    pub threads: uint
}

impl Config {
    pub fn default() -> Config {
        Config { port: 8888, threads: 50 }
    }
}

#[link(name = "civetweb", kind = "static")]
extern {
    fn mg_start(callbacks: *MgCallbacks, user_data: *c_void, options: **c_char) -> *MgContext;
    fn mg_stop(context: *MgContext);
    fn mg_set_request_handler(context: *MgContext, uri: *c_char, handler: MgRequestHandler, data: *c_void);
    fn mg_read(connection: *mut MgConnection, buf: *c_void, len: size_t) -> c_int;
    fn mg_write(connection: *mut MgConnection, data: *c_void, len: size_t) -> c_int;
    fn mg_get_header(connection: *mut MgConnection, name: *c_char) -> *c_char;
    fn mg_get_request_info(connection: *mut MgConnection) -> *MgRequestInfo;
}

enum MgContext {}

pub struct Server(*MgContext);

pub struct ServerCallback<T> {
    callback: fn(&mut Connection, &T) -> Result<(), ()>,
    param: T
}

impl<T> ServerCallback<T> {
    pub fn new(callback: fn(&mut Connection, &T) -> Result<(), ()>, param: T) -> ServerCallback<T> {
        ServerCallback { callback: callback, param: param }
    }
}

impl Server {
    fn as_ref<'a>(&'a self) -> &'a MgContext {
        match *self { Server(context) => unsafe { &*context } }
    }

    pub fn start<T: 'static>(options: Config, callback: ServerCallback<T>) -> Server {
        let Config { port, threads } = options;
        let options = vec!(
            "listening_ports".to_c_str(), port.to_str().to_c_str(),
            "num_threads".to_c_str(), threads.to_str().to_c_str(),
        );
        let mut ptrs: Vec<_> = options.iter().map(|a| a.with_ref(|p| p)).collect();
        ptrs.push(0 as *_);

        let context = start(ptrs.as_ptr());
        let uri = "**".to_c_str();
        unsafe {
            mg_set_request_handler(context, uri.with_ref(|p| p),
                                   raw_handler::<T>,
                                   transmute(box callback));
        }
        Server(context)
    }
}

impl Drop for Server {
    fn drop(&mut self) {
        unsafe { mg_stop(self.as_ref()) }
    }
}

fn raw_handler<T: 'static>(conn: *mut MgConnection, param: *c_void) -> int {
    let callback: &ServerCallback<T> = unsafe { transmute(param) };
    let task = native::task::new((0, std::uint::MAX));
    let mut result = None;

    task.run(|| {
        let mut connection = Connection(conn);
        result = Some((callback.callback)(&mut connection, &callback.param));
    });

    match result {
        None => 0,
        Some(Err(_)) => 0,
        Some(Ok(_)) => 1
    }
}

pub enum MgConnection {}

pub struct Connection(*mut MgConnection);

impl Connection {
    fn unwrap(&self) -> *mut MgConnection {
        match *self { Connection(conn) => conn }
    }
}

type MgRequestHandler = fn(*mut MgConnection, *c_void) -> int;

#[allow(dead_code)]
struct MgHeader {
    name: *c_char,
    value: *c_char
}

pub struct Header<'a>(*MgHeader);

impl<'a> Header<'a> {
    fn as_ref(&self) -> &'a MgHeader {
        match *self { Header(header) => unsafe { &*header } }
    }

    pub fn name(&self) -> Option<&'a str> {
        to_slice(self.as_ref(), |header| header.name)
    }

    pub fn value(&self) -> Option<&'a str> {
        to_slice(self.as_ref(), |header| header.value)
    }
}

struct MgRequestInfo {
    request_method: *c_char,
    uri: *c_char,
    http_version: *c_char,
    query_string: *c_char,
    remote_user: *c_char,
    remote_ip: c_long,
    remote_port: c_int,
    is_ssl: bool,

    #[allow(dead_code)]
    user_data: *c_void,
    #[allow(dead_code)]
    conn_data: *c_void,

    num_headers: c_int,
    headers: [MgHeader, ..64]
}

pub struct RequestInfo<'a>(*MgRequestInfo);

impl<'a> RequestInfo<'a> {
    pub fn as_ref<'a>(&'a self) -> &'a MgRequestInfo {
        match *self { RequestInfo(info) => unsafe { &*info } }
    }

    pub fn num_headers(&self) -> int {
        self.as_ref().num_headers as int
    }

    pub fn method<'a>(&'a self) -> Option<&'a str> {
        to_slice(self.as_ref(), |info| info.request_method)
    }

    pub fn url<'a>(&'a self) -> Option<&'a str> {
        to_slice(self.as_ref(), |info| info.uri)
    }

    pub fn http_version<'a>(&'a self) -> Option<&'a str> {
        to_slice(self.as_ref(), |info| info.http_version)
    }

    pub fn query_string<'a>(&'a self) -> Option<&'a str> {
        to_slice(self.as_ref(), |info| info.query_string)
    }

    pub fn remote_user<'a>(&'a self) -> Option<&'a str> {
        to_slice(self.as_ref(), |info| info.remote_user)
    }

    pub fn remote_ip(&self) -> int {
        self.as_ref().remote_ip as int
    }

    pub fn remote_port(&self) -> int {
        self.as_ref().remote_port as int
    }

    pub fn is_ssl(&self) -> bool {
        self.as_ref().is_ssl
    }
}

#[allow(dead_code)]
struct MgCallbacks {
    begin_request: *c_void,
    end_request: *c_void,
    log_message: *c_void,
    init_ssl: *c_void,
    websocket_connect: *c_void,
    websocket_ready: *c_void,
    websocket_data: *c_void,
    connection_close: *c_void,
    open_file: *c_void,
    init_lua: *c_void,
    upload: *c_void,
    http_error: *c_void
}

impl MgCallbacks {
    fn new() -> MgCallbacks {
        MgCallbacks {
            begin_request: null(),
            end_request: null(),
            log_message: null(),
            init_ssl: null(),
            websocket_connect: null(),
            websocket_ready: null(),
            websocket_data: null(),
            connection_close: null(),
            open_file: null(),
            init_lua: null(),
            upload: null(),
            http_error: null()
        }
    }
}

fn to_slice<'a, T>(obj: &'a T, callback: |&'a T|:'static -> *c_char) -> Option<&'a str> {
    let chars = callback(obj);

    if unsafe { chars.is_null() || *chars == 0 } {
        return None;
    }

    let c_string = unsafe { CString::new(chars, false) };
    let len = c_string.len();

    unsafe { Some(transmute(std::raw::Slice { data: chars, len: len })) }
}

pub fn start(options: **c_char) -> *MgContext {
    unsafe { mg_start(&MgCallbacks::new(), null(), options) }
}

pub fn read(conn: &Connection, buf: &mut [u8]) -> i32 {
    unsafe { mg_read(conn.unwrap(), buf.as_ptr() as *c_void, buf.len() as size_t) }
}

pub fn write(conn: &Connection, bytes: &[u8]) -> i32 {
    let c_bytes = bytes.as_ptr() as *c_void;
    unsafe { mg_write(conn.unwrap(), c_bytes, bytes.len() as size_t) }
}

pub fn get_header(conn: &Connection, string: &str) -> Option<String> {
    let cstr = unsafe { mg_get_header(conn.unwrap(), string.to_c_str().unwrap()).to_option() };

    cstr.map(|c| unsafe { CString::new(c, false) }.as_str().to_str())
}

pub fn get_request_info<'a>(conn: &'a Connection) -> Option<RequestInfo<'a>> {
    (unsafe { mg_get_request_info(conn.unwrap()).to_option() }).map(|info| RequestInfo(info))
}

pub fn get_headers<'a>(conn: &'a Connection) -> Vec<Header<'a>> {
    match get_request_info(conn) {
        Some(info) => info.as_ref().headers.iter().map(|h| Header(h)).collect(),
        None => vec!()
    }
}
<commit_msg>Require Share for the extra param<commit_after>use libc::{c_void,c_char,c_int,c_long,size_t};
use std;
use std::c_str::CString;
use std::ptr::null;
use std::mem::transmute;
use native;

pub struct Config {
    pub port: uint,
    pub threads: uint
}

impl Config {
    pub fn default() -> Config {
        Config { port: 8888, threads: 50 }
    }
}

#[link(name = "civetweb", kind = "static")]
extern {
    fn mg_start(callbacks: *MgCallbacks, user_data: *c_void, options: **c_char) -> *MgContext;
    fn mg_stop(context: *MgContext);
    fn mg_set_request_handler(context: *MgContext, uri: *c_char, handler: MgRequestHandler, data: *c_void);
    fn mg_read(connection: *mut MgConnection, buf: *c_void, len: size_t) -> c_int;
    fn mg_write(connection: *mut MgConnection, data: *c_void, len: size_t) -> c_int;
    fn mg_get_header(connection: *mut MgConnection, name: *c_char) -> *c_char;
    fn mg_get_request_info(connection: *mut MgConnection) -> *MgRequestInfo;
}

enum MgContext {}

pub struct Server(*MgContext);

pub struct ServerCallback<T> {
    callback: fn(&mut Connection, &T) -> Result<(), ()>,
    param: T
}

impl<T: Share> ServerCallback<T> {
    pub fn new(callback: fn(&mut Connection, &T) -> Result<(), ()>,
               param: T) -> ServerCallback<T> {
        ServerCallback { callback: callback, param: param }
    }
}

impl Server {
    fn as_ref<'a>(&'a self) -> &'a MgContext {
        match *self { Server(context) => unsafe { &*context } }
    }

    pub fn start<T: 'static + Share>(options: Config,
                                     callback: ServerCallback<T>) -> Server {
        let Config { port, threads } = options;
        let options = vec!(
            "listening_ports".to_c_str(), port.to_str().to_c_str(),
            "num_threads".to_c_str(), threads.to_str().to_c_str(),
        );
        let mut ptrs: Vec<_> = options.iter().map(|a| a.with_ref(|p| p)).collect();
        ptrs.push(0 as *_);

        let context = start(ptrs.as_ptr());
        let uri = "**".to_c_str();
        unsafe {
            mg_set_request_handler(context, uri.with_ref(|p| p),
                                   raw_handler::<T>,
                                   transmute(box callback));
        }
        Server(context)
    }
}

impl Drop for Server {
    fn drop(&mut self) {
        unsafe { mg_stop(self.as_ref()) }
    }
}

fn raw_handler<T: 'static>(conn: *mut MgConnection, param: *c_void) -> int {
    let callback: &ServerCallback<T> = unsafe { transmute(param) };
    let task = native::task::new((0, std::uint::MAX));
    let mut result = None;

    task.run(|| {
        let mut connection = Connection(conn);
        result = Some((callback.callback)(&mut connection, &callback.param));
    });

    match result {
        None => 0,
        Some(Err(_)) => 0,
        Some(Ok(_)) => 1
    }
}

pub enum MgConnection {}

pub struct Connection(*mut MgConnection);

impl Connection {
    fn unwrap(&self) -> *mut MgConnection {
        match *self { Connection(conn) => conn }
    }
}

type MgRequestHandler = fn(*mut MgConnection, *c_void) -> int;

#[allow(dead_code)]
struct MgHeader {
    name: *c_char,
    value: *c_char
}

pub struct Header<'a>(*MgHeader);

impl<'a> Header<'a> {
    fn as_ref(&self) -> &'a MgHeader {
        match *self { Header(header) => unsafe { &*header } }
    }

    pub fn name(&self) -> Option<&'a str> {
        to_slice(self.as_ref(), |header| header.name)
    }

    pub fn value(&self) -> Option<&'a str> {
        to_slice(self.as_ref(), |header| header.value)
    }
}

struct MgRequestInfo {
    request_method: *c_char,
    uri: *c_char,
    http_version: *c_char,
    query_string: *c_char,
    remote_user: *c_char,
    remote_ip: c_long,
    remote_port: c_int,
    is_ssl: bool,

    #[allow(dead_code)]
    user_data: *c_void,
    #[allow(dead_code)]
    conn_data: *c_void,

    num_headers: c_int,
    headers: [MgHeader, ..64]
}

pub struct RequestInfo<'a>(*MgRequestInfo);

impl<'a> RequestInfo<'a> {
    pub fn as_ref<'a>(&'a self) -> &'a MgRequestInfo {
        match *self { RequestInfo(info) => unsafe { &*info } }
    }

    pub fn num_headers(&self) -> int {
        self.as_ref().num_headers as int
    }

    pub fn method<'a>(&'a self) -> Option<&'a str> {
        to_slice(self.as_ref(), |info| info.request_method)
    }

    pub fn url<'a>(&'a self) -> Option<&'a str> {
        to_slice(self.as_ref(), |info| info.uri)
    }

    pub fn http_version<'a>(&'a self) -> Option<&'a str> {
        to_slice(self.as_ref(), |info| info.http_version)
    }

    pub fn query_string<'a>(&'a self) -> Option<&'a str> {
        to_slice(self.as_ref(), |info| info.query_string)
    }

    pub fn remote_user<'a>(&'a self) -> Option<&'a str> {
        to_slice(self.as_ref(), |info| info.remote_user)
    }

    pub fn remote_ip(&self) -> int {
        self.as_ref().remote_ip as int
    }

    pub fn remote_port(&self) -> int {
        self.as_ref().remote_port as int
    }

    pub fn is_ssl(&self) -> bool {
        self.as_ref().is_ssl
    }
}

#[allow(dead_code)]
struct MgCallbacks {
    begin_request: *c_void,
    end_request: *c_void,
    log_message: *c_void,
    init_ssl: *c_void,
    websocket_connect: *c_void,
    websocket_ready: *c_void,
    websocket_data: *c_void,
    connection_close: *c_void,
    open_file: *c_void,
    init_lua: *c_void,
    upload: *c_void,
    http_error: *c_void
}

impl MgCallbacks {
    fn new() -> MgCallbacks {
        MgCallbacks {
            begin_request: null(),
            end_request: null(),
            log_message: null(),
            init_ssl: null(),
            websocket_connect: null(),
            websocket_ready: null(),
            websocket_data: null(),
            connection_close: null(),
            open_file: null(),
            init_lua: null(),
            upload: null(),
            http_error: null()
        }
    }
}

fn to_slice<'a, T>(obj: &'a T, callback: |&'a T|:'static -> *c_char) -> Option<&'a str> {
    let chars = callback(obj);

    if unsafe { chars.is_null() || *chars == 0 } {
        return None;
    }

    let c_string = unsafe { CString::new(chars, false) };
    let len = c_string.len();

    unsafe { Some(transmute(std::raw::Slice { data: chars, len: len })) }
}

pub fn start(options: **c_char) -> *MgContext {
    unsafe { mg_start(&MgCallbacks::new(), null(), options) }
}

pub fn read(conn: &Connection, buf: &mut [u8]) -> i32 {
    unsafe { mg_read(conn.unwrap(), buf.as_ptr() as *c_void, buf.len() as size_t) }
}

pub fn write(conn: &Connection, bytes: &[u8]) -> i32 {
    let c_bytes = bytes.as_ptr() as *c_void;
    unsafe { mg_write(conn.unwrap(), c_bytes, bytes.len() as size_t) }
}

pub fn get_header(conn: &Connection, string: &str) -> Option<String> {
    let cstr = unsafe { mg_get_header(conn.unwrap(), string.to_c_str().unwrap()).to_option() };

    cstr.map(|c| unsafe { CString::new(c, false) }.as_str().to_str())
}

pub fn get_request_info<'a>(conn: &'a Connection) -> Option<RequestInfo<'a>> {
    (unsafe { mg_get_request_info(conn.unwrap()).to_option() }).map(|info| RequestInfo(info))
}

pub fn get_headers<'a>(conn: &'a Connection) -> Vec<Header<'a>> {
    match get_request_info(conn) {
        Some(info) => info.as_ref().headers.iter().map(|h| Header(h)).collect(),
        None => vec!()
    }
}
<|endoftext|>