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

pub struct LoggingMem {
	ops: Vec<Operation>,
	mem: HashMap<AddressSpace, [u8; 1024]>
}

#[derive(Copy, Clone, Debug, PartialEq)]
pub struct AddressSpace(Mode, Segment);
#[derive(Copy, Clone, Debug, PartialEq)]
enum Segment {
	Program, Data
}
#[derive(Copy, Clone, Debug, PartialEq)]
enum Mode {
	User, Supervisor
}

#[derive(Copy, Clone, Debug, PartialEq)]
pub enum Operation {
	None,
	ReadByte(AddressSpace, u32),
	ReadWord(AddressSpace, u32),
	ReadLong(AddressSpace, u32),
	WriteByte(AddressSpace, u32, u32),
	WriteWord(AddressSpace, u32, u32),
	WriteLong(AddressSpace, u32, u32),
}
pub const SUPERVISOR_PROGRAM: AddressSpace = AddressSpace(Mode::Supervisor, Segment::Program);
pub const SUPERVISOR_DATA: AddressSpace = AddressSpace(Mode::Supervisor, Segment::Data);
pub const USER_PROGRAM: AddressSpace = AddressSpace(Mode::User, Segment::Program);
pub const USER_DATA: AddressSpace = AddressSpace(Mode::User, Segment::Data);

trait AddressBus {
	fn read_u8(address_space: AddressSpace, address: u32) -> u32;
	fn read_u16(address_space: AddressSpace, address: u32) -> u32;
	fn read_u32(address_space: AddressSpace, address: u32) -> u32;
	fn write_u8(address_space: AddressSpace, address: u32, value: u32);
	fn write_u16(address_space: AddressSpace, address: u32, value: u32);
	fn write_u32(address_space: AddressSpace, address: u32, value: u32);
}

impl AddressBus for LoggingMem {
	fn read_u8(address_space: AddressSpace, address: u32) -> u32 {
		return 0;
	}
	fn read_u16(address_space: AddressSpace, address: u32) -> u32 {
		return 0;
	}

	fn read_u32(address_space: AddressSpace, address: u32) -> u32 {
		return 0;
	}

	fn write_u8(address_space: AddressSpace, address: u32, value: u32) {
	}

	fn write_u16(address_space: AddressSpace, address: u32, value: u32) {
	}

	fn write_u32(address_space: AddressSpace, address: u32, value: u32) {
	}
}

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

	#[test]
	fn new_sets_pc() {
	}
}<commit_msg>Add LoggingMem implementation and tests<commit_after>use std::cell::RefCell;
use std::collections::HashMap;
const PAGE_MASK: u32 = 0b1111_1111_1111_1100_0000_0000; // 16K pages
const ADDR_MASK: u32 = 0b0000_0000_0000_0011_1111_1111; // 1K page size
type Page = [u8; (ADDR_MASK+1) as usize];

pub struct LoggingMem {
	pub log: RefCell<Vec<Operation>>,
	pages: HashMap<u32, Page>,
	initializer: u32,
}

#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
pub struct AddressSpace(Mode, Segment);

#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
enum Segment {
	Program, Data
}
#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
enum Mode {
	User, Supervisor
}

#[derive(Copy, Clone, Debug, PartialEq)]
pub enum Operation {
	None,
	ReadByte(AddressSpace, u32),
	ReadWord(AddressSpace, u32),
	ReadLong(AddressSpace, u32),
	WriteByte(AddressSpace, u32, u32),
	WriteWord(AddressSpace, u32, u32),
	WriteLong(AddressSpace, u32, u32),
}
pub const SUPERVISOR_PROGRAM: AddressSpace = AddressSpace(Mode::Supervisor, Segment::Program);
pub const SUPERVISOR_DATA: AddressSpace = AddressSpace(Mode::Supervisor, Segment::Data);
pub const USER_PROGRAM: AddressSpace = AddressSpace(Mode::User, Segment::Program);
pub const USER_DATA: AddressSpace = AddressSpace(Mode::User, Segment::Data);

trait AddressBus {
	fn read_u8(&self, address_space: AddressSpace, address: u32) -> u32;
	fn read_u16(&self, address_space: AddressSpace, address: u32) -> u32;
	fn read_u32(&self, address_space: AddressSpace, address: u32) -> u32;
	fn write_u8(&mut self, address_space: AddressSpace, address: u32, value: u32);
	fn write_u16(&mut self, address_space: AddressSpace, address: u32, value: u32);
	fn write_u32(&mut self, address_space: AddressSpace, address: u32, value: u32);
}

impl LoggingMem {
	fn new(initializer: u32) -> LoggingMem {
		let mut lmem = LoggingMem { log: RefCell::new(Vec::new()), pages: HashMap::new(), initializer: initializer };
		lmem
	}
	fn loglen(&self) -> usize {
		let log = self.log.borrow();
		log.len()
	}
	fn getlog(&self, index: usize) -> Operation {
		let log = self.log.borrow();
		log[index]
	}
	fn ensure_page(&self, address: u32) -> u32 {
		let page = address & PAGE_MASK;
		if !self.pages.contains_key(&page) {
			self.pages.insert(page, [0u8; (ADDR_MASK + 1) as usize]);
			let mut page = self.pages[&page];
			for v in 0..((ADDR_MASK+1) / 4) {
				page[(4*v+0) as usize] = ((self.initializer >> 24) & 0xFF) as u8;
				page[(4*v+1) as usize] = ((self.initializer >> 16) & 0xFF) as u8;
				page[(4*v+2) as usize] = ((self.initializer >>  8) & 0xFF) as u8;
				page[(4*v+3) as usize] = ((self.initializer >>  0) & 0xFF) as u8;
			}
		}
		page
	}
	fn read_byte(&self, address: u32) -> u32 {
		let index = (address & ADDR_MASK) as usize;
		//self.pages[&self.ensure_page(address)][index] as u32
		0
	}

	fn write_byte(&mut self, address: u32, value: u8) {
		let index = (address & ADDR_MASK) as usize;
		let page = self.ensure_page(address);
		let mut page = self.pages[&page];
		page[index] = value;
	}
}

impl AddressBus for LoggingMem {
	fn read_u8(&self, address_space: AddressSpace, address: u32) -> u32 {
		let mut log = self.log.borrow_mut();
		log.push(Operation::ReadByte(address_space, address));
		self.read_byte(address)
	}

	fn read_u16(&self, address_space: AddressSpace, address: u32) -> u32 {
		let mut log = self.log.borrow_mut();
		log.push(Operation::ReadWord(address_space, address));
		((self.read_byte(address+0) as u16) << 8
		|(self.read_byte(address+1) as u16) << 0
		) as u32
	}

	fn read_u32(&self, address_space: AddressSpace, address: u32) -> u32 {
		let mut log = self.log.borrow_mut();
		log.push(Operation::ReadLong(address_space, address));
		((self.read_byte(address+0) as u32) << 24
		|(self.read_byte(address+1) as u32) << 16
		|(self.read_byte(address+2) as u32) <<  8
		|(self.read_byte(address+3) as u32) <<  0) as u32
	}

	fn write_u8(&mut self, address_space: AddressSpace, address: u32, value: u32) {
		{
			let mut log = self.log.borrow_mut();
			log.push(Operation::WriteByte(address_space, address, value));
		}
		self.write_byte(address, (value & 0xFF) as u8);
	}

	fn write_u16(&mut self, address_space: AddressSpace, address: u32, value: u32) {
		{
			let mut log = self.log.borrow_mut();
			log.push(Operation::WriteWord(address_space, address, value));
		}
		self.write_byte(address+0, ((value >>  8) & 0xFF) as u8);
		self.write_byte(address+1, ((value >>  0) & 0xFF) as u8);
	}

	fn write_u32(&mut self, address_space: AddressSpace, address: u32, value: u32) {
		{
			let mut log = self.log.borrow_mut();
			log.push(Operation::WriteLong(address_space, address, value));
		}
		self.write_byte(address+0, ((value >> 24) & 0xFF) as u8);
		self.write_byte(address+1, ((value >> 16) & 0xFF) as u8);
		self.write_byte(address+2, ((value >>  8) & 0xFF) as u8);
		self.write_byte(address+3, ((value >>  0) & 0xFF) as u8);
	}
}

#[cfg(test)]
mod tests {
	use super::{LoggingMem, AddressBus, Operation, SUPERVISOR_DATA, SUPERVISOR_PROGRAM, USER_DATA, USER_PROGRAM};

	#[test]
	fn read_initialized_memory() {
		let mem = LoggingMem::new(0x01020304);
		for v in 0..256 {
			assert_eq!(0x01, mem.read_u8(SUPERVISOR_DATA, 4*v+0));
			assert_eq!(0x02, mem.read_u8(SUPERVISOR_DATA, 4*v+1));
			assert_eq!(0x03, mem.read_u8(SUPERVISOR_DATA, 4*v+2));
			assert_eq!(0x04, mem.read_u8(SUPERVISOR_DATA, 4*v+3));
		}
		for v in 0..256 {
			assert_eq!(0x0102, mem.read_u16(SUPERVISOR_DATA, 4*v+0));
			assert_eq!(0x0203, mem.read_u16(SUPERVISOR_DATA, 4*v+1));
			assert_eq!(0x0304, mem.read_u16(SUPERVISOR_DATA, 4*v+2));
			if 4*v+3 < 1023 {
				assert_eq!(0x0401, mem.read_u16(SUPERVISOR_DATA, 4*v+3));
			}
		}
		for v in 0..255 {
			assert_eq!(0x01020304, mem.read_u32(SUPERVISOR_DATA, 4*v+0));
			assert_eq!(0x02030401, mem.read_u32(SUPERVISOR_DATA, 4*v+1));
			assert_eq!(0x03040102, mem.read_u32(SUPERVISOR_DATA, 4*v+2));
			assert_eq!(0x04010203, mem.read_u32(SUPERVISOR_DATA, 4*v+3));
		}
		assert_eq!(0x01020304, mem.read_u32(SUPERVISOR_DATA, 4*255));
	}

	#[test]
	fn read_your_u32_writes() {
		let mut mem = LoggingMem::new(0x01020304);
		let pattern = 0xAAAA7777;
		let address = 128;
		assert!(pattern != mem.read_u32(SUPERVISOR_DATA, address));
		mem.write_u32(SUPERVISOR_DATA, address, pattern);
		assert_eq!(pattern, mem.read_u32(SUPERVISOR_DATA, address));
	}

	#[test]
	fn read_your_u16_writes() {
		let mut mem = LoggingMem::new(0x01020304);
		let pattern = 0xAAAA7777;
		let address = 128;
		assert!(pattern != mem.read_u16(SUPERVISOR_DATA, address));
		mem.write_u16(SUPERVISOR_DATA, address, pattern);
		assert_eq!(pattern & 0xFFFF, mem.read_u16(SUPERVISOR_DATA, address));
	}

	#[test]
	fn read_your_u8_writes() {
		let mut mem = LoggingMem::new(0x01020304);
		let pattern = 0xAAAA7777;
		let address = 128;
		assert!(pattern != mem.read_u8(SUPERVISOR_DATA, address));
		mem.write_u8(SUPERVISOR_DATA, address, pattern);
		assert_eq!(pattern & 0xFF, mem.read_u8(SUPERVISOR_DATA, address));
	}

	#[test]
	fn read_u8_is_logged() {
		let mem = LoggingMem::new(0x01020304);
		let address = 128;
		mem.read_u8(SUPERVISOR_DATA, address);
		assert!(mem.loglen() > 0);
		assert_eq!(Operation::ReadByte(SUPERVISOR_DATA, address), mem.getlog(0));
	}

	#[test]
	fn read_u16_is_logged() {
		let mem = LoggingMem::new(0x01020304);
		let address = 128;
		mem.read_u16(SUPERVISOR_PROGRAM, address);
		assert!(mem.loglen() > 0);
		assert_eq!(Operation::ReadWord(SUPERVISOR_PROGRAM, address), mem.getlog(0));
	}

	#[test]
	fn read_u32_is_logged() {
		let mem = LoggingMem::new(0x01020304);
		let address = 128;
		mem.read_u32(USER_DATA, address);
		assert!(mem.loglen() > 0);
		assert_eq!(Operation::ReadLong(USER_DATA, address), mem.getlog(0));
	}

	#[test]
	fn write_u8_is_logged() {
		let mut mem = LoggingMem::new(0x01020304);
		let address = 128;
		let pattern = 0xAAAA7777;
		mem.write_u8(SUPERVISOR_DATA, address, pattern);
		assert!(mem.loglen() > 0);
		assert_eq!(Operation::WriteByte(SUPERVISOR_DATA, address, pattern), mem.getlog(0));
	}

	#[test]
	fn write_u16_is_logged() {
		let mut mem = LoggingMem::new(0x01020304);
		let address = 128;
		let pattern = 0xAAAA7777;
		mem.write_u16(SUPERVISOR_PROGRAM, address, pattern);
		assert!(mem.loglen() > 0);
		assert_eq!(Operation::WriteWord(SUPERVISOR_PROGRAM, address, pattern), mem.getlog(0));
	}

	#[test]
	fn write_u32_is_logged() {
		let mut mem = LoggingMem::new(0x01020304);
		let address = 128;
		let pattern = 0xAAAA7777;
		mem.write_u32(USER_DATA, address, pattern);
		assert!(mem.loglen() > 0);
		assert_eq!(Operation::WriteLong(USER_DATA, address, pattern), mem.getlog(0));
	}

	#[test]
	fn shared_address_space() {
		let mut mem = LoggingMem::new(0x01020304);
		let pattern = 0xAAAA7777;
		let address = 128;
		assert!(pattern != mem.read_u32(SUPERVISOR_DATA, address));
		assert!(pattern != mem.read_u32(SUPERVISOR_PROGRAM, address));
		assert!(pattern != mem.read_u32(USER_DATA, address));
		assert!(pattern != mem.read_u32(USER_PROGRAM, address));
		mem.write_u32(SUPERVISOR_DATA, address, pattern);

		assert_eq!(pattern, mem.read_u32(SUPERVISOR_DATA, address));
		assert_eq!(pattern, mem.read_u32(SUPERVISOR_PROGRAM, address));
		assert_eq!(pattern, mem.read_u32(USER_DATA, address));
		assert_eq!(pattern, mem.read_u32(USER_PROGRAM, address));
	}
}<|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 = ["listening_ports".to_str(), port.to_str(), "num_threads".to_str(), threads.to_str()];

        let mut server = None;
        let mut cb = Some(box callback);

        options.with_c_strs(true, |options| {
            let context = start(options);
            server = Some(Server(context));

            unsafe { mg_set_request_handler(context, "**".to_c_str().unwrap(), raw_handler::<T>, transmute(cb.take_unwrap())) }
        });

        server.unwrap()
    }
}

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 (tx, rx) = channel();
    let callback: &ServerCallback<T> = unsafe { transmute(param) };

    let mut task = native::task::new((0, std::uint::MAX));
    task.death.on_exit = Some(proc(r) tx.send(r));

    let mut result = None;

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

    let _ = rx.recv();

    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 u64) }
}

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 u64) }
}

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!()
    }
}

trait WithCStrs {
    fn with_c_strs(&self, null_terminated: bool, f: |**c_char|) ;
}

impl<'a, T: ToCStr> WithCStrs for &'a [T] {
    fn with_c_strs(&self, null_terminate: bool, f: |**c_char|) {
        let c_strs: Vec<CString> = self.iter().map(|s: &T| s.to_c_str()).collect();
        let mut ptrs: Vec<*c_char> = c_strs.iter().map(|c: &CString| c.with_ref(|ptr| ptr)).collect();
        if null_terminate {
            ptrs.push(null());
        }
        f(ptrs.as_ptr())
    }
}
<commit_msg>Fix compilation on 32-bit<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> 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 = ["listening_ports".to_str(), port.to_str(), "num_threads".to_str(), threads.to_str()];

        let mut server = None;
        let mut cb = Some(box callback);

        options.with_c_strs(true, |options| {
            let context = start(options);
            server = Some(Server(context));

            unsafe { mg_set_request_handler(context, "**".to_c_str().unwrap(), raw_handler::<T>, transmute(cb.take_unwrap())) }
        });

        server.unwrap()
    }
}

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 (tx, rx) = channel();
    let callback: &ServerCallback<T> = unsafe { transmute(param) };

    let mut task = native::task::new((0, std::uint::MAX));
    task.death.on_exit = Some(proc(r) tx.send(r));

    let mut result = None;

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

    let _ = rx.recv();

    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!()
    }
}

trait WithCStrs {
    fn with_c_strs(&self, null_terminated: bool, f: |**c_char|) ;
}

impl<'a, T: ToCStr> WithCStrs for &'a [T] {
    fn with_c_strs(&self, null_terminate: bool, f: |**c_char|) {
        let c_strs: Vec<CString> = self.iter().map(|s: &T| s.to_c_str()).collect();
        let mut ptrs: Vec<*c_char> = c_strs.iter().map(|c: &CString| c.with_ref(|ptr| ptr)).collect();
        if null_terminate {
            ptrs.push(null());
        }
        f(ptrs.as_ptr())
    }
}
<|endoftext|>


<commit_before>//! Reset and clock control

use volatile::RW;

#[repr(C)]
pub struct Rcc {
    /// Clock control register
    /* 0x00 */ cr: RW<u32>,
    /// Clock configuration register
    /* 0x04 */ cfgr: RW<u32>,
    /// Clock interrupt register
    /* 0x08 */ cir: RW<u32>,
    /// APB2 peripheral reset register
    /* 0x0C */ pub apb2rstr: RW<apb2rstr::Register>,
    /// APB1 peripheral reset register
    /* 0x10 */ pub apb1rstr: RW<apb1rstr::Register>,
    /// AHB peripheral clock enable register
    /* 0x14 */ ahbenr: RW<u32>,
    /// APB2 peripheral clock enable register
    /* 0x18 */ pub apb2enr: RW<apb2enr::Register>,
    /// APB1 peripheral clock enable register
    /* 0x1C */ pub apb1enr: RW<apb1enr::Register>,
    /// Backup domain control register
    /* 0x20 */ bdcr: RW<u32>,
    /// Control/status register
    /* 0x24 */ csr: RW<u32>,
    /* 0x28 */ _0: u32,
    /// Clock configuration register 2
    /* 0x2C */ cfgr2: RW<u32>,
}

reg!(apb2rstr: u32 {
    AFIORST: 0,
    IOPARST: 2,
    IOPBRST: 3,
    IOPCRST: 4,
    IOPDRST: 5,
    IOPERST: 6,
    IOPFRST: 7,
    IOPGRST: 8,
    ADC1RST: 9,
    TIM1RST: 11,
    SPI1RST: 12,
    USART1RST: 14,
    TIM15RST: 16,
    TIM16RST: 17,
    TIM17RST: 18,
});

reg!(apb1rstr: u32 {
    TIM2RST: 0,
    TIM3RST: 1,
    TIM4RST: 2,
    TIM5RST: 3,
    TIM6RST: 4,
    TIM7RST: 5,
    TIM12RST: 6,
    TIM13RST: 7,
    TIM14RST: 8,
    WWDGRST: 11,
    SPI2RST: 14,
    SPI3RST: 15,
    USART2RST: 17,
    USART3RST: 18,
    UART4RST: 19,
    UART5RST: 20,
    I2C1RST: 21,
    I2C2RST: 22,
    BKPRST: 27,
    PWRRST: 28,
    DACRST: 29,
    CECRST: 30,
});

reg!(apb2enr: u32 {
    AFIOEN: 0,
    IOPAEN: 2,
    IOPBEN: 3,
    IOPCEN: 4,
    IOPDEN: 5,
    IOPEEN: 6,
    IOPFEN: 7,
    IOPGEN: 8,
    ADC1EN: 9,
    TIM1EN: 11,
    SPI1EN: 12,
    USART1EN: 14,
    TIM15EN: 16,
    TIM16EN: 17,
    TIM17EN: 18,
});

reg!(apb1enr: u32 {
    TIM2EN: 0,
    TIM3EN: 1,
    TIM4EN: 2,
    TIM5EN: 3,
    TIM6EN: 4,
    TIM7EN: 5,
    TIM12EN: 6,
    TIM13EN: 7,
    TIM14EN: 8,
    WWDGEN: 11,
    SPI2EN: 14,
    SPI3EN: 15,
    USART2EN: 17,
    USART3EN: 18,
    UART4EN: 19,
    UART5EN: 20,
    I2C1EN: 21,
    I2C2EN: 22,
    BKPEN: 27,
    PWREN: 28,
    DACEN: 29,
    CECEN: 30,
});
<commit_msg>feat(rcc): expose the ahbenr register<commit_after>//! Reset and clock control

use volatile::RW;

#[repr(C)]
pub struct Rcc {
    /// Clock control register
    /* 0x00 */ cr: RW<u32>,
    /// Clock configuration register
    /* 0x04 */ cfgr: RW<u32>,
    /// Clock interrupt register
    /* 0x08 */ cir: RW<u32>,
    /// APB2 peripheral reset register
    /* 0x0C */ pub apb2rstr: RW<apb2rstr::Register>,
    /// APB1 peripheral reset register
    /* 0x10 */ pub apb1rstr: RW<apb1rstr::Register>,
    /// AHB peripheral clock enable register
    /* 0x14 */ pub ahbenr: RW<ahbenr::Register>,
    /// APB2 peripheral clock enable register
    /* 0x18 */ pub apb2enr: RW<apb2enr::Register>,
    /// APB1 peripheral clock enable register
    /* 0x1C */ pub apb1enr: RW<apb1enr::Register>,
    /// Backup domain control register
    /* 0x20 */ bdcr: RW<u32>,
    /// Control/status register
    /* 0x24 */ csr: RW<u32>,
    /* 0x28 */ _0: u32,
    /// Clock configuration register 2
    /* 0x2C */ cfgr2: RW<u32>,
}

reg!(apb2rstr: u32 {
    AFIORST: 0,
    IOPARST: 2,
    IOPBRST: 3,
    IOPCRST: 4,
    IOPDRST: 5,
    IOPERST: 6,
    IOPFRST: 7,
    IOPGRST: 8,
    ADC1RST: 9,
    TIM1RST: 11,
    SPI1RST: 12,
    USART1RST: 14,
    TIM15RST: 16,
    TIM16RST: 17,
    TIM17RST: 18,
});

reg!(apb1rstr: u32 {
    TIM2RST: 0,
    TIM3RST: 1,
    TIM4RST: 2,
    TIM5RST: 3,
    TIM6RST: 4,
    TIM7RST: 5,
    TIM12RST: 6,
    TIM13RST: 7,
    TIM14RST: 8,
    WWDGRST: 11,
    SPI2RST: 14,
    SPI3RST: 15,
    USART2RST: 17,
    USART3RST: 18,
    UART4RST: 19,
    UART5RST: 20,
    I2C1RST: 21,
    I2C2RST: 22,
    BKPRST: 27,
    PWRRST: 28,
    DACRST: 29,
    CECRST: 30,
});

reg!(ahbenr: u32 {
    DMA1EN: 0,
    DMA2EN: 1,
    SRAMEN: 2,
    FLITFEN: 4,
    CRCEN: 6,
    FSMCEN: 8,
});

reg!(apb2enr: u32 {
    AFIOEN: 0,
    IOPAEN: 2,
    IOPBEN: 3,
    IOPCEN: 4,
    IOPDEN: 5,
    IOPEEN: 6,
    IOPFEN: 7,
    IOPGEN: 8,
    ADC1EN: 9,
    TIM1EN: 11,
    SPI1EN: 12,
    USART1EN: 14,
    TIM15EN: 16,
    TIM16EN: 17,
    TIM17EN: 18,
});

reg!(apb1enr: u32 {
    TIM2EN: 0,
    TIM3EN: 1,
    TIM4EN: 2,
    TIM5EN: 3,
    TIM6EN: 4,
    TIM7EN: 5,
    TIM12EN: 6,
    TIM13EN: 7,
    TIM14EN: 8,
    WWDGEN: 11,
    SPI2EN: 14,
    SPI3EN: 15,
    USART2EN: 17,
    USART3EN: 18,
    UART4EN: 19,
    UART5EN: 20,
    I2C1EN: 21,
    I2C2EN: 22,
    BKPEN: 27,
    PWREN: 28,
    DACEN: 29,
    CECEN: 30,
});
<|endoftext|>


<commit_before>extern crate combine;

use std::collections::VecDeque;
use std::error::Error as StdError;
use std::fmt;
use std::io::{self, BufRead, Read, Write};
use std::marker::PhantomData;
use std::sync::{Arc, Mutex};

use jsonrpc_core::{Error, ErrorCode, Params, RpcMethodSimple, RpcNotificationSimple, Value};
use futures::{self, Async, AsyncSink, Future, IntoFuture, Poll, Sink, StartSend};

use serde;
use serde_json::{from_value, to_string, to_value};

use BoxFuture;

pub struct ServerError<E> {
    pub message: String,
    pub data: Option<E>,
}

impl<E, D> From<E> for ServerError<D>
where
    E: fmt::Display,
{
    fn from(err: E) -> ServerError<D> {
        ServerError {
            message: err.to_string(),
            data: None,
        }
    }
}

pub trait LanguageServerCommand<P>: Send + Sync + 'static {
    type Output: serde::Serialize;
    type Error: serde::Serialize;
    fn execute(&self, param: P) -> BoxFuture<Self::Output, ServerError<Self::Error>>;

    fn invalid_params(&self) -> Option<Self::Error> {
        None
    }
}

impl<'de, F, P, O, E> LanguageServerCommand<P> for F
where
    F: Fn(P) -> BoxFuture<O, ServerError<E>> + Send + Sync + 'static,
    P: serde::Deserialize<'de>,
    O: serde::Serialize,
    E: serde::Serialize,
{
    type Output = O;
    type Error = E;

    fn execute(&self, param: P) -> BoxFuture<Self::Output, ServerError<Self::Error>> {
        self(param)
    }
}

pub trait LanguageServerNotification<P>: Send + Sync + 'static {
    fn execute(&self, param: P);
}

impl<'de, F, P> LanguageServerNotification<P> for F
where
    F: Fn(P) + Send + Sync + 'static,
    P: serde::Deserialize<'de> + 'static,
{
    fn execute(&self, param: P) {
        self(param)
    }
}
pub struct ServerCommand<T, P>(pub T, PhantomData<fn(P)>);

impl<T, P> ServerCommand<T, P> {
    pub fn method(command: T) -> ServerCommand<T, P>
    where
        T: LanguageServerCommand<P>,
        P: for<'de> serde::Deserialize<'de> + 'static,
    {
        ServerCommand(command, PhantomData)
    }

    pub fn notification(command: T) -> ServerCommand<T, P>
    where
        T: LanguageServerNotification<P>,
        P: for<'de> serde::Deserialize<'de> + 'static,
    {
        ServerCommand(command, PhantomData)
    }
}

impl<P, T> RpcMethodSimple for ServerCommand<T, P>
where
    T: LanguageServerCommand<P>,
    P: for<'de> serde::Deserialize<'de> + 'static,
{
    fn call(&self, param: Params) -> BoxFuture<Value, Error> {
        let value = match param {
            Params::Map(map) => Value::Object(map),
            Params::Array(arr) => Value::Array(arr),
            Params::None => Value::Null,
        };
        let err = match from_value(value.clone()) {
            Ok(value) => {
                return Box::new(self.0.execute(value).then(|result| {
                    match result {
                        Ok(value) => Ok(
                            to_value(&value).expect("result data could not be serialized"),
                        ).into_future(),
                        Err(error) => Err(Error {
                            code: ErrorCode::InternalError,
                            message: error.message,
                            data: error
                                .data
                                .as_ref()
                                .map(|v| to_value(v).expect("error data could not be serialized")),
                        }).into_future(),
                    }
                }))
            }
            Err(err) => err,
        };
        let data = self.0.invalid_params();
        Box::new(futures::failed(Error {
            code: ErrorCode::InvalidParams,
            message: format!("Invalid params: {}", err),
            data: data.as_ref()
                .map(|v| to_value(v).expect("error data could not be serialized")),
        }))
    }
}

impl<T, P> RpcNotificationSimple for ServerCommand<T, P>
where
    T: LanguageServerNotification<P>,
    P: for<'de> serde::Deserialize<'de> + 'static,
{
    fn execute(&self, param: Params) {
        match param {
            Params::Map(map) => match from_value(Value::Object(map)) {
                Ok(value) => {
                    self.0.execute(value);
                }
                Err(err) => log_message!("Invalid parameters. Reason: {}", err),
            },
            _ => log_message!("Invalid parameters: {:?}", param),
        }
    }
}

pub fn read_message<R>(mut reader: R) -> Result<Option<String>, Box<StdError>>
where
    R: BufRead + Read,
{
    let mut header = String::new();
    let n = try!(reader.read_line(&mut header));
    if n == 0 {
        return Ok(None);
    }

    if header.starts_with("Content-Length: ") {
        let content_length = {
            let len = header["Content-Length:".len()..].trim();
            debug!("{}", len);
            try!(len.parse::<usize>())
        };
        while header != "\r\n" {
            header.clear();
            try!(reader.read_line(&mut header));
        }
        let mut content = vec![0; content_length];
        try!(reader.read_exact(&mut content));
        Ok(Some(try!(String::from_utf8(content))))
    } else {
        Err(format!("Invalid message: `{}`", header).into())
    }
}

pub fn write_message<W, T>(output: W, value: &T) -> io::Result<()>
where
    W: Write,
    T: serde::Serialize,
{
    let response = to_string(&value).unwrap();
    write_message_str(output, &response)
}

pub fn write_message_str<W>(mut output: W, response: &str) -> io::Result<()>
where
    W: Write,
{
    debug!("Respond: {}", response);
    try!(write!(
        output,
        "Content-Length: {}\r\n\r\n{}",
        response.len(),
        response
    ));
    try!(output.flush());
    Ok(())
}

extern crate bytes;

use std::str;

use tokio_io::codec::{Decoder, Encoder};
use self::bytes::{BufMut, BytesMut};

#[derive(Debug)]
pub struct LanguageServerDecoder {
    message_length: Option<usize>,
}

impl LanguageServerDecoder {
    pub fn new() -> LanguageServerDecoder {
        LanguageServerDecoder {
            message_length: None,
        }
    }
}

use self::combine::range::{range, take};
use self::combine::{skip_many, Parser, many1};
use self::combine::primitives::{Error as CombineError, ParseError};
use self::combine::byte::digit;

fn combine_decode<'a, P>(
    mut parser: P,
    src: &'a [u8],
) -> Result<Option<(P::Output, usize)>, ParseError<usize, u8, String>>
where
    P: Parser<Input = &'a [u8]>,
{
    match parser.parse(&src[..]) {
        Ok((message, rest)) => Ok(Some((message, src.len() - rest.len()))),
        Err(err) => {
            return if err.errors
                .iter()
                .any(|err| *err == CombineError::end_of_input())
            {
                Ok(None)
            } else {
                Err(
                    err.map_range(|r| {
                        str::from_utf8(r)
                            .ok()
                            .map_or_else(|| format!("{:?}", r), |s| s.to_string())
                    }).map_position(|p| p.translate_position(&src[..])),
                )
            }
        }
    }
}

impl Decoder for LanguageServerDecoder {
    type Item = String;
    type Error = Box<::std::error::Error>;

    fn decode(&mut self, src: &mut BytesMut) -> Result<Option<Self::Item>, Self::Error> {
        let (result, removed_len) = {
            let parser = (
                skip_many(range(&b"\r\n"[..])),
                range(&b"Content-Length: "[..]),
                many1(digit()),
                range(&b"\r\n\r\n"[..]),
            ).map(|t| t.2)
                .and_then(|digits: Vec<u8>| unsafe {
                    String::from_utf8_unchecked(digits).parse::<usize>()
                })
                .then(|message_length| take(message_length))
                .map(|bytes: &[u8]| bytes.to_owned());

            match combine_decode(parser, &src[..])? {
                None => return Ok(None),
                Some(x) => x,
            }
        };
        src.split_to(removed_len);
        Ok(Some(String::from_utf8(result)?))
    }
}

#[derive(Debug)]
pub struct LanguageServerEncoder;

impl Encoder for LanguageServerEncoder {
    type Item = String;
    type Error = Box<::std::error::Error>;
    fn encode(&mut self, item: Self::Item, dst: &mut BytesMut) -> Result<(), Self::Error> {
        write_message_str(dst.writer(), &item)?;
        Ok(())
    }
}

pub struct Entry<K, V> {
    pub key: K,
    pub value: V,
}

#[derive(Debug)]
pub struct SharedSink<S>(Arc<Mutex<S>>);

impl<S> Clone for SharedSink<S> {
    fn clone(&self) -> Self {
        SharedSink(self.0.clone())
    }
}

impl<S> SharedSink<S> {
    pub fn new(sink: S) -> SharedSink<S> {
        SharedSink(Arc::new(Mutex::new(sink)))
    }
}

impl<S> Sink for SharedSink<S>
where
    S: Sink,
{
    type SinkItem = S::SinkItem;
    type SinkError = S::SinkError;

    fn start_send(&mut self, item: Self::SinkItem) -> StartSend<Self::SinkItem, Self::SinkError> {
        self.0.lock().unwrap().start_send(item)
    }

    fn poll_complete(&mut self) -> Poll<(), Self::SinkError> {
        self.0.lock().unwrap().poll_complete()
    }

    fn close(&mut self) -> Poll<(), Self::SinkError> {
        self.0.lock().unwrap().close()
    }
}

/// Queue which only keeps the latest work item for each key
pub struct UniqueQueue<S, K, V> {
    sink: S,
    queue: VecDeque<Entry<K, V>>,
}

impl<S, K, V> UniqueQueue<S, K, V> {
    pub fn new(sink: S) -> Self {
        UniqueQueue {
            sink,
            queue: VecDeque::new(),
        }
    }
}

impl<S, K, V> Sink for UniqueQueue<S, K, V>
where
    S: Sink<SinkItem = Entry<K, V>>,
    K: PartialEq,
{
    type SinkItem = Entry<K, V>;
    type SinkError = S::SinkError;

    fn start_send(&mut self, item: Self::SinkItem) -> StartSend<Self::SinkItem, Self::SinkError> {
        match self.sink.start_send(item)? {
            AsyncSink::Ready => Ok(AsyncSink::Ready),
            AsyncSink::NotReady(item) => {
                if let Some(entry) = self.queue.iter_mut().find(|entry| entry.key == item.key) {
                    entry.value = item.value;
                }
                Ok(AsyncSink::Ready)
            }
        }
    }

    fn poll_complete(&mut self) -> Poll<(), Self::SinkError> {
        while let Some(item) = self.queue.pop_front() {
            match self.sink.start_send(item)? {
                AsyncSink::Ready => (),
                AsyncSink::NotReady(item) => {
                    self.queue.push_front(item);
                    break;
                }
            }
        }
        if self.queue.is_empty() {
            self.sink.poll_complete()
        } else {
            Ok(Async::NotReady)
        }
    }

    fn close(&mut self) -> Poll<(), Self::SinkError> {
        try_ready!(self.poll_complete());
        self.sink.close()
    }
}

pub struct SinkFn<F, I> {
    f: F,
    _marker: PhantomData<fn(I) -> I>,
}

pub fn sink_fn<F, I, E>(f: F) -> SinkFn<F, I>
where
    F: FnMut(I) -> StartSend<I, E>,
{
    SinkFn {
        f,
        _marker: PhantomData,
    }
}

impl<F, I, E> Sink for SinkFn<F, I>
where
    F: FnMut(I) -> StartSend<I, E>,
{
    type SinkItem = I;
    type SinkError = E;

    fn start_send(&mut self, item: Self::SinkItem) -> StartSend<Self::SinkItem, Self::SinkError> {
        (self.f)(item)
    }

    fn poll_complete(&mut self) -> Poll<(), Self::SinkError> {
        Ok(Async::Ready(()))
    }
}
<commit_msg>refactor: Make the message decoding a real state machine<commit_after>extern crate combine;

use std::collections::VecDeque;
use std::error::Error as StdError;
use std::fmt;
use std::io::{self, BufRead, Read, Write};
use std::marker::PhantomData;
use std::sync::{Arc, Mutex};

use jsonrpc_core::{Error, ErrorCode, Params, RpcMethodSimple, RpcNotificationSimple, Value};
use futures::{self, Async, AsyncSink, Future, IntoFuture, Poll, Sink, StartSend};

use serde;
use serde_json::{from_value, to_string, to_value};

use BoxFuture;

pub struct ServerError<E> {
    pub message: String,
    pub data: Option<E>,
}

impl<E, D> From<E> for ServerError<D>
where
    E: fmt::Display,
{
    fn from(err: E) -> ServerError<D> {
        ServerError {
            message: err.to_string(),
            data: None,
        }
    }
}

pub trait LanguageServerCommand<P>: Send + Sync + 'static {
    type Output: serde::Serialize;
    type Error: serde::Serialize;
    fn execute(&self, param: P) -> BoxFuture<Self::Output, ServerError<Self::Error>>;

    fn invalid_params(&self) -> Option<Self::Error> {
        None
    }
}

impl<'de, F, P, O, E> LanguageServerCommand<P> for F
where
    F: Fn(P) -> BoxFuture<O, ServerError<E>> + Send + Sync + 'static,
    P: serde::Deserialize<'de>,
    O: serde::Serialize,
    E: serde::Serialize,
{
    type Output = O;
    type Error = E;

    fn execute(&self, param: P) -> BoxFuture<Self::Output, ServerError<Self::Error>> {
        self(param)
    }
}

pub trait LanguageServerNotification<P>: Send + Sync + 'static {
    fn execute(&self, param: P);
}

impl<'de, F, P> LanguageServerNotification<P> for F
where
    F: Fn(P) + Send + Sync + 'static,
    P: serde::Deserialize<'de> + 'static,
{
    fn execute(&self, param: P) {
        self(param)
    }
}
pub struct ServerCommand<T, P>(pub T, PhantomData<fn(P)>);

impl<T, P> ServerCommand<T, P> {
    pub fn method(command: T) -> ServerCommand<T, P>
    where
        T: LanguageServerCommand<P>,
        P: for<'de> serde::Deserialize<'de> + 'static,
    {
        ServerCommand(command, PhantomData)
    }

    pub fn notification(command: T) -> ServerCommand<T, P>
    where
        T: LanguageServerNotification<P>,
        P: for<'de> serde::Deserialize<'de> + 'static,
    {
        ServerCommand(command, PhantomData)
    }
}

impl<P, T> RpcMethodSimple for ServerCommand<T, P>
where
    T: LanguageServerCommand<P>,
    P: for<'de> serde::Deserialize<'de> + 'static,
{
    fn call(&self, param: Params) -> BoxFuture<Value, Error> {
        let value = match param {
            Params::Map(map) => Value::Object(map),
            Params::Array(arr) => Value::Array(arr),
            Params::None => Value::Null,
        };
        let err = match from_value(value.clone()) {
            Ok(value) => {
                return Box::new(self.0.execute(value).then(|result| {
                    match result {
                        Ok(value) => Ok(
                            to_value(&value).expect("result data could not be serialized"),
                        ).into_future(),
                        Err(error) => Err(Error {
                            code: ErrorCode::InternalError,
                            message: error.message,
                            data: error
                                .data
                                .as_ref()
                                .map(|v| to_value(v).expect("error data could not be serialized")),
                        }).into_future(),
                    }
                }))
            }
            Err(err) => err,
        };
        let data = self.0.invalid_params();
        Box::new(futures::failed(Error {
            code: ErrorCode::InvalidParams,
            message: format!("Invalid params: {}", err),
            data: data.as_ref()
                .map(|v| to_value(v).expect("error data could not be serialized")),
        }))
    }
}

impl<T, P> RpcNotificationSimple for ServerCommand<T, P>
where
    T: LanguageServerNotification<P>,
    P: for<'de> serde::Deserialize<'de> + 'static,
{
    fn execute(&self, param: Params) {
        match param {
            Params::Map(map) => match from_value(Value::Object(map)) {
                Ok(value) => {
                    self.0.execute(value);
                }
                Err(err) => log_message!("Invalid parameters. Reason: {}", err),
            },
            _ => log_message!("Invalid parameters: {:?}", param),
        }
    }
}

pub fn read_message<R>(mut reader: R) -> Result<Option<String>, Box<StdError>>
where
    R: BufRead + Read,
{
    let mut header = String::new();
    let n = try!(reader.read_line(&mut header));
    if n == 0 {
        return Ok(None);
    }

    if header.starts_with("Content-Length: ") {
        let content_length = {
            let len = header["Content-Length:".len()..].trim();
            debug!("{}", len);
            try!(len.parse::<usize>())
        };
        while header != "\r\n" {
            header.clear();
            try!(reader.read_line(&mut header));
        }
        let mut content = vec![0; content_length];
        try!(reader.read_exact(&mut content));
        Ok(Some(try!(String::from_utf8(content))))
    } else {
        Err(format!("Invalid message: `{}`", header).into())
    }
}

pub fn write_message<W, T>(output: W, value: &T) -> io::Result<()>
where
    W: Write,
    T: serde::Serialize,
{
    let response = to_string(&value).unwrap();
    write_message_str(output, &response)
}

pub fn write_message_str<W>(mut output: W, response: &str) -> io::Result<()>
where
    W: Write,
{
    debug!("Respond: {}", response);
    try!(write!(
        output,
        "Content-Length: {}\r\n\r\n{}",
        response.len(),
        response
    ));
    try!(output.flush());
    Ok(())
}

extern crate bytes;

use std::str;

use tokio_io::codec::{Decoder, Encoder};
use self::bytes::{BufMut, BytesMut};

#[derive(Debug)]
enum State {
    Nothing,
    ContentLength(usize),
}

#[derive(Debug)]
pub struct LanguageServerDecoder {
    state: State,
}

impl LanguageServerDecoder {
    pub fn new() -> LanguageServerDecoder {
        LanguageServerDecoder {
            state: State::Nothing,
        }
    }
}

use self::combine::range::{range, take};
use self::combine::{skip_many, Parser, many1};
use self::combine::primitives::{Error as CombineError, ParseError};
use self::combine::byte::digit;

fn combine_decode<'a, P, R>(
    mut parser: P,
    src: &'a [u8],
) -> Result<Option<(R, usize)>, ParseError<usize, u8, String>>
where
    P: Parser<Input = &'a [u8], Output = R>,
{
    match parser.parse(&src[..]) {
        Ok((message, rest)) => Ok(Some((message, src.len() - rest.len()))),
        Err(err) => {
            return if err.errors
                .iter()
                .any(|err| *err == CombineError::end_of_input())
            {
                Ok(None)
            } else {
                Err(
                    err.map_range(|r| {
                        str::from_utf8(r)
                            .ok()
                            .map_or_else(|| format!("{:?}", r), |s| s.to_string())
                    }).map_position(|p| p.translate_position(&src[..])),
                )
            }
        }
    }
}

macro_rules! decode {
    ($parser: expr, $src: expr) => {
        {
            let (output, removed_len) = {
                match combine_decode($parser, &$src[..])? {
                    None => return Ok(None),
                    Some(x) => x,
                }
            };
            $src.split_to(removed_len);
            output
        }
    };
}

impl Decoder for LanguageServerDecoder {
    type Item = String;
    type Error = Box<::std::error::Error>;

    fn decode(&mut self, src: &mut BytesMut) -> Result<Option<Self::Item>, Self::Error> {
        loop {
            match self.state {
                State::Nothing => {
                    let value = decode!(
                        (
                            skip_many(range(&b"\r\n"[..])),
                            range(&b"Content-Length: "[..]),
                            many1(digit()),
                            range(&b"\r\n\r\n"[..]),
                        ).map(|t| t.2)
                            .and_then(|digits: Vec<u8>| unsafe {
                                String::from_utf8_unchecked(digits).parse::<usize>()
                            }),
                        src
                    );

                    self.state = State::ContentLength(value);
                }
                State::ContentLength(message_length) => {
                    let message = decode!(
                        take(message_length).map(|bytes: &[u8]| bytes.to_owned()),
                        src
                    );
                    self.state = State::Nothing;
                    return Ok(Some(String::from_utf8(message)?));
                }
            }
        }
    }
}

#[derive(Debug)]
pub struct LanguageServerEncoder;

impl Encoder for LanguageServerEncoder {
    type Item = String;
    type Error = Box<::std::error::Error>;
    fn encode(&mut self, item: Self::Item, dst: &mut BytesMut) -> Result<(), Self::Error> {
        write_message_str(dst.writer(), &item)?;
        Ok(())
    }
}

pub struct Entry<K, V> {
    pub key: K,
    pub value: V,
}

#[derive(Debug)]
pub struct SharedSink<S>(Arc<Mutex<S>>);

impl<S> Clone for SharedSink<S> {
    fn clone(&self) -> Self {
        SharedSink(self.0.clone())
    }
}

impl<S> SharedSink<S> {
    pub fn new(sink: S) -> SharedSink<S> {
        SharedSink(Arc::new(Mutex::new(sink)))
    }
}

impl<S> Sink for SharedSink<S>
where
    S: Sink,
{
    type SinkItem = S::SinkItem;
    type SinkError = S::SinkError;

    fn start_send(&mut self, item: Self::SinkItem) -> StartSend<Self::SinkItem, Self::SinkError> {
        self.0.lock().unwrap().start_send(item)
    }

    fn poll_complete(&mut self) -> Poll<(), Self::SinkError> {
        self.0.lock().unwrap().poll_complete()
    }

    fn close(&mut self) -> Poll<(), Self::SinkError> {
        self.0.lock().unwrap().close()
    }
}

/// Queue which only keeps the latest work item for each key
pub struct UniqueQueue<S, K, V> {
    sink: S,
    queue: VecDeque<Entry<K, V>>,
}

impl<S, K, V> UniqueQueue<S, K, V> {
    pub fn new(sink: S) -> Self {
        UniqueQueue {
            sink,
            queue: VecDeque::new(),
        }
    }
}

impl<S, K, V> Sink for UniqueQueue<S, K, V>
where
    S: Sink<SinkItem = Entry<K, V>>,
    K: PartialEq,
{
    type SinkItem = Entry<K, V>;
    type SinkError = S::SinkError;

    fn start_send(&mut self, item: Self::SinkItem) -> StartSend<Self::SinkItem, Self::SinkError> {
        match self.sink.start_send(item)? {
            AsyncSink::Ready => Ok(AsyncSink::Ready),
            AsyncSink::NotReady(item) => {
                if let Some(entry) = self.queue.iter_mut().find(|entry| entry.key == item.key) {
                    entry.value = item.value;
                }
                Ok(AsyncSink::Ready)
            }
        }
    }

    fn poll_complete(&mut self) -> Poll<(), Self::SinkError> {
        while let Some(item) = self.queue.pop_front() {
            match self.sink.start_send(item)? {
                AsyncSink::Ready => (),
                AsyncSink::NotReady(item) => {
                    self.queue.push_front(item);
                    break;
                }
            }
        }
        if self.queue.is_empty() {
            self.sink.poll_complete()
        } else {
            Ok(Async::NotReady)
        }
    }

    fn close(&mut self) -> Poll<(), Self::SinkError> {
        try_ready!(self.poll_complete());
        self.sink.close()
    }
}

pub struct SinkFn<F, I> {
    f: F,
    _marker: PhantomData<fn(I) -> I>,
}

pub fn sink_fn<F, I, E>(f: F) -> SinkFn<F, I>
where
    F: FnMut(I) -> StartSend<I, E>,
{
    SinkFn {
        f,
        _marker: PhantomData,
    }
}

impl<F, I, E> Sink for SinkFn<F, I>
where
    F: FnMut(I) -> StartSend<I, E>,
{
    type SinkItem = I;
    type SinkError = E;

    fn start_send(&mut self, item: Self::SinkItem) -> StartSend<Self::SinkItem, Self::SinkError> {
        (self.f)(item)
    }

    fn poll_complete(&mut self) -> Poll<(), Self::SinkError> {
        Ok(Async::Ready(()))
    }
}
<|endoftext|>


<commit_before>/// The Toml Set extensions

use toml::Value;

use tokenizer::tokenize_with_seperator;
use tokenizer::Token;
use error::*;

pub trait TomlValueSetExt {

    /// Extension function for setting a value in the current toml::Value document
    /// using a custom seperator
    ///
    /// # Semantics
    ///
    /// The function _never_ creates intermediate data structures (Tables or Arrays) in the
    /// document.
    ///
    /// # Return value
    ///
    /// * If the set operation worked correctly, `Ok(None)` is returned.
    /// * If the set operation replaced an existing value `Ok(Some(old_value))` is returned
    /// * On failure, `Err(e)` is returned:
    ///     * If the query is `"a.b.c"` but there is no table `"b"`: error
    ///     * If the query is `"a.b.[0]"` but "`b"` is not an array: error
    ///     * If the query is `"a.b.[3]"` but the array at "`b"` has no index `3`: error
    ///     * etc.
    ///
    fn set_with_seperator(&mut self, query: &String, sep: char, value: Value) -> Result<Option<Value>>;

    /// Extension function for setting a value from the current toml::Value document
    ///
    /// See documentation of `TomlValueSetExt::set_with_seperator`
    fn set(&mut self, query: &String, value: Value) -> Result<Option<Value>> {
        self.set_with_seperator(query, '.', value)
    }

}

impl TomlValueSetExt for Value {

    fn set_with_seperator(&mut self, query: &String, sep: char, value: Value) -> Result<Option<Value>> {
        use resolver::mut_resolver::resolve;

        let mut tokens = try!(tokenize_with_seperator(query, sep));
        let last = tokens.pop_last();

        let mut val = try!(resolve(self, &tokens));
        let last = last.unwrap_or_else(|| Box::new(tokens));

        match *last {
            Token::Identifier { ident, .. } => {
                match val {
                    &mut Value::Table(ref mut t) => {
                        Ok(t.insert(ident, value))
                    },
                    &mut Value::Array(_) => {
                        let kind = ErrorKind::NoIdentifierInArray(ident);
                        Err(Error::from(kind))
                    }
                    _ => unimplemented!()
                }
            }

            Token::Index { idx, .. } => {
                match val {
                    &mut Value::Array(ref mut a) => {
                        if a.len() > idx {
                            let result = a.swap_remove(idx);
                            a.insert(idx, value);
                            Ok(Some(result))
                        } else {
                            a.push(value);
                            Ok(None)
                        }
                    }
                    &mut Value::Table(_) => {
                        let kind = ErrorKind::NoIndexInTable(idx);
                        Err(Error::from(kind))
                    }
                    _ => unimplemented!()
                }
            }

        }
    }

}

#[cfg(test)]
mod test {
    use super::*;
    use toml::Value;
    use toml::from_str as toml_from_str;

    #[test]
    fn test_set_with_seperator_into_table() {
        let mut toml : Value = toml_from_str(r#"
        [table]
        a = 0
        "#).unwrap();

        let res = toml.set_with_seperator(&String::from("table.a"), '.', Value::Integer(1));

        assert!(res.is_ok());

        let res = res.unwrap();
        assert!(res.is_some());
        let res = res.unwrap();
        assert!(is_match!(res, Value::Integer(0)));

        assert!(is_match!(toml, Value::Table(_)));
        match toml {
            Value::Table(ref t) => {
                assert!(!t.is_empty());

                let inner = t.get("table");
                assert!(inner.is_some());

                let inner = inner.unwrap();
                assert!(is_match!(inner, &Value::Table(_)));
                match inner {
                    &Value::Table(ref t) => {
                        assert!(!t.is_empty());

                        let a = t.get("a");
                        assert!(a.is_some());

                        let a = a.unwrap();
                        assert!(is_match!(a, &Value::Integer(1)));
                    },
                    _ => panic!("What just happenend?"),
                }
            },
            _ => panic!("What just happenend?"),
        }
    }

    #[test]
    fn test_set_with_seperator_into_table_key_nonexistent() {
        let mut toml : Value = toml_from_str(r#"
        [table]
        "#).unwrap();

        let res = toml.set_with_seperator(&String::from("table.a"), '.', Value::Integer(1));

        assert!(res.is_ok());
        let res = res.unwrap();

        assert!(res.is_none());

        assert!(is_match!(toml, Value::Table(_)));
        match toml {
            Value::Table(ref t) => {
                assert!(!t.is_empty());

                let inner = t.get("table");
                assert!(inner.is_some());

                let inner = inner.unwrap();
                assert!(is_match!(inner, &Value::Table(_)));
                match inner {
                    &Value::Table(ref t) => {
                        assert!(!t.is_empty());

                        let a = t.get("a");
                        assert!(a.is_some());

                        let a = a.unwrap();
                        assert!(is_match!(a, &Value::Integer(1)));
                    },
                    _ => panic!("What just happenend?"),
                }
            },
            _ => panic!("What just happenend?"),
        }
    }

    #[test]
    fn test_set_with_seperator_into_array() {
        use std::ops::Index;

        let mut toml : Value = toml_from_str(r#"
        array = [ 0 ]
        "#).unwrap();

        let res = toml.set_with_seperator(&String::from("array.[0]"), '.', Value::Integer(1));

        assert!(res.is_ok());

        let res = res.unwrap();
        assert!(res.is_some());
        let res = res.unwrap();
        assert!(is_match!(res, Value::Integer(0)));

        assert!(is_match!(toml, Value::Table(_)));
        match toml {
            Value::Table(ref t) => {
                assert!(!t.is_empty());

                let inner = t.get("array");
                assert!(inner.is_some());

                let inner = inner.unwrap();
                assert!(is_match!(inner, &Value::Array(_)));
                match inner {
                    &Value::Array(ref a) => {
                        assert!(!a.is_empty());
                        assert!(is_match!(a.index(0), &Value::Integer(1)));
                    },
                    _ => panic!("What just happenend?"),
                }
            },
            _ => panic!("What just happenend?"),
        }
    }

    #[test]
    fn test_set_with_seperator_into_table_index_nonexistent() {
        use std::ops::Index;

        let mut toml : Value = toml_from_str(r#"
        array = []
        "#).unwrap();

        let res = toml.set_with_seperator(&String::from("array.[0]"), '.', Value::Integer(1));

        assert!(res.is_ok());

        let res = res.unwrap();
        assert!(res.is_none());

        assert!(is_match!(toml, Value::Table(_)));
        match toml {
            Value::Table(ref t) => {
                assert!(!t.is_empty());

                let inner = t.get("array");
                assert!(inner.is_some());

                let inner = inner.unwrap();
                assert!(is_match!(inner, &Value::Array(_)));
                match inner {
                    &Value::Array(ref a) => {
                        assert!(!a.is_empty());
                        assert!(is_match!(a.index(0), &Value::Integer(1)));
                    },
                    _ => panic!("What just happenend?"),
                }
            },
            _ => panic!("What just happenend?"),
        }
    }

    #[test]
    fn test_set_with_seperator_into_nested_table() {
        let mut toml : Value = toml_from_str(r#"
        [a.b.c]
        d = 0
        "#).unwrap();

        let res = toml.set_with_seperator(&String::from("a.b.c.d"), '.', Value::Integer(1));

        assert!(res.is_ok());

        let res = res.unwrap();
        assert!(res.is_some());
        let res = res.unwrap();
        assert!(is_match!(res, Value::Integer(0)));

        assert!(is_match!(toml, Value::Table(_)));
        match toml {
            Value::Table(ref t) => {
                assert!(!t.is_empty());

                let a = t.get("a");
                assert!(a.is_some());

                let a = a.unwrap();
                assert!(is_match!(a, &Value::Table(_)));
                match a {
                    &Value::Table(ref a) => {
                        assert!(!a.is_empty());

                        let b_tab = a.get("b");
                        assert!(b_tab.is_some());

                        let b_tab = b_tab.unwrap();
                        assert!(is_match!(b_tab, &Value::Table(_)));
                        match b_tab {
                            &Value::Table(ref b) => {
                                assert!(!b.is_empty());

                                let c_tab = b.get("c");
                                assert!(c_tab.is_some());

                                let c_tab = c_tab.unwrap();
                                assert!(is_match!(c_tab, &Value::Table(_)));
                                match c_tab {
                                    &Value::Table(ref c) => {
                                        assert!(!c.is_empty());

                                        let d = c.get("d");
                                        assert!(d.is_some());

                                        let d = d.unwrap();
                                        assert!(is_match!(d, &Value::Integer(1)));
                                    },
                                    _ => panic!("What just happenend?"),
                                }
                            },
                            _ => panic!("What just happenend?"),
                        }
                    },
                    _ => panic!("What just happenend?"),
                }
            },
            _ => panic!("What just happenend?"),
        }
    }

    #[test]
    fn test_set_with_seperator_into_nonexistent_table() {
        let mut toml : Value = toml_from_str("").unwrap();

        let res = toml.set_with_seperator(&String::from("table.a"), '.', Value::Integer(1));

        assert!(res.is_err());

        let res = res.unwrap_err();
        assert!(is_match!(res.kind(), &ErrorKind::IdentifierNotFoundInDocument(_)));
    }

    #[test]
    fn test_set_with_seperator_into_nonexistent_array() {
        let mut toml : Value = toml_from_str("").unwrap();

        let res = toml.set_with_seperator(&String::from("[0]"), '.', Value::Integer(1));

        assert!(res.is_err());

        let res = res.unwrap_err();
        assert!(is_match!(res.kind(), &ErrorKind::NoIndexInTable(0)));
    }

    #[test]
    fn test_set_with_seperator_ident_into_ary() {
        let mut toml : Value = toml_from_str(r#"
        array = [ 0 ]
        "#).unwrap();

        let res = toml.set_with_seperator(&String::from("array.foo"), '.', Value::Integer(2));

        assert!(res.is_err());
        let res = res.unwrap_err();

        assert!(is_match!(res.kind(), &ErrorKind::NoIdentifierInArray(_)));
    }

    #[test]
    fn test_set_with_seperator_index_into_table() {
        let mut toml : Value = toml_from_str(r#"
        foo = { bar = 1 }
        "#).unwrap();

        let res = toml.set_with_seperator(&String::from("foo.[0]"), '.', Value::Integer(2));

        assert!(res.is_err());
        let res = res.unwrap_err();

        assert!(is_match!(res.kind(), &ErrorKind::NoIndexInTable(_)));
    }

    #[test]
    fn test_set_with_seperator_ident_into_non_structure() {
        let mut toml : Value = toml_from_str(r#"
        val = 0
        "#).unwrap();

        let res = toml.set_with_seperator(&String::from("val.foo"), '.', Value::Integer(2));

        assert!(res.is_err());
        let res = res.unwrap_err();

        assert!(is_match!(res.kind(), &ErrorKind::QueryingValueAsTable(_)));
    }

    #[test]
    fn test_set_with_seperator_index_into_non_structure() {
        let mut toml : Value = toml_from_str(r#"
        foo = 1
        "#).unwrap();

        let res = toml.set_with_seperator(&String::from("foo.[0]"), '.', Value::Integer(2));

        assert!(res.is_err());
        let res = res.unwrap_err();

        assert!(is_match!(res.kind(), &ErrorKind::QueryingValueAsArray(_)));
    }

}

<commit_msg>Impl Value::set_with_seperator to fix test_set_with_seperator_ident_into_non_structure<commit_after>/// The Toml Set extensions

use toml::Value;

use tokenizer::tokenize_with_seperator;
use tokenizer::Token;
use error::*;

pub trait TomlValueSetExt {

    /// Extension function for setting a value in the current toml::Value document
    /// using a custom seperator
    ///
    /// # Semantics
    ///
    /// The function _never_ creates intermediate data structures (Tables or Arrays) in the
    /// document.
    ///
    /// # Return value
    ///
    /// * If the set operation worked correctly, `Ok(None)` is returned.
    /// * If the set operation replaced an existing value `Ok(Some(old_value))` is returned
    /// * On failure, `Err(e)` is returned:
    ///     * If the query is `"a.b.c"` but there is no table `"b"`: error
    ///     * If the query is `"a.b.[0]"` but "`b"` is not an array: error
    ///     * If the query is `"a.b.[3]"` but the array at "`b"` has no index `3`: error
    ///     * etc.
    ///
    fn set_with_seperator(&mut self, query: &String, sep: char, value: Value) -> Result<Option<Value>>;

    /// Extension function for setting a value from the current toml::Value document
    ///
    /// See documentation of `TomlValueSetExt::set_with_seperator`
    fn set(&mut self, query: &String, value: Value) -> Result<Option<Value>> {
        self.set_with_seperator(query, '.', value)
    }

}

impl TomlValueSetExt for Value {

    fn set_with_seperator(&mut self, query: &String, sep: char, value: Value) -> Result<Option<Value>> {
        use resolver::mut_resolver::resolve;

        let mut tokens = try!(tokenize_with_seperator(query, sep));
        let last = tokens.pop_last();

        let mut val = try!(resolve(self, &tokens));
        let last = last.unwrap_or_else(|| Box::new(tokens));

        match *last {
            Token::Identifier { ident, .. } => {
                match val {
                    &mut Value::Table(ref mut t) => {
                        Ok(t.insert(ident, value))
                    },
                    &mut Value::Array(_) => {
                        let kind = ErrorKind::NoIdentifierInArray(ident);
                        Err(Error::from(kind))
                    }
                    _ => {
                        let kind = ErrorKind::QueryingValueAsTable(ident);
                        Err(Error::from(kind))
                    }
                }
            }

            Token::Index { idx, .. } => {
                match val {
                    &mut Value::Array(ref mut a) => {
                        if a.len() > idx {
                            let result = a.swap_remove(idx);
                            a.insert(idx, value);
                            Ok(Some(result))
                        } else {
                            a.push(value);
                            Ok(None)
                        }
                    }
                    &mut Value::Table(_) => {
                        let kind = ErrorKind::NoIndexInTable(idx);
                        Err(Error::from(kind))
                    }
                    _ => unimplemented!()
                }
            }

        }
    }

}

#[cfg(test)]
mod test {
    use super::*;
    use toml::Value;
    use toml::from_str as toml_from_str;

    #[test]
    fn test_set_with_seperator_into_table() {
        let mut toml : Value = toml_from_str(r#"
        [table]
        a = 0
        "#).unwrap();

        let res = toml.set_with_seperator(&String::from("table.a"), '.', Value::Integer(1));

        assert!(res.is_ok());

        let res = res.unwrap();
        assert!(res.is_some());
        let res = res.unwrap();
        assert!(is_match!(res, Value::Integer(0)));

        assert!(is_match!(toml, Value::Table(_)));
        match toml {
            Value::Table(ref t) => {
                assert!(!t.is_empty());

                let inner = t.get("table");
                assert!(inner.is_some());

                let inner = inner.unwrap();
                assert!(is_match!(inner, &Value::Table(_)));
                match inner {
                    &Value::Table(ref t) => {
                        assert!(!t.is_empty());

                        let a = t.get("a");
                        assert!(a.is_some());

                        let a = a.unwrap();
                        assert!(is_match!(a, &Value::Integer(1)));
                    },
                    _ => panic!("What just happenend?"),
                }
            },
            _ => panic!("What just happenend?"),
        }
    }

    #[test]
    fn test_set_with_seperator_into_table_key_nonexistent() {
        let mut toml : Value = toml_from_str(r#"
        [table]
        "#).unwrap();

        let res = toml.set_with_seperator(&String::from("table.a"), '.', Value::Integer(1));

        assert!(res.is_ok());
        let res = res.unwrap();

        assert!(res.is_none());

        assert!(is_match!(toml, Value::Table(_)));
        match toml {
            Value::Table(ref t) => {
                assert!(!t.is_empty());

                let inner = t.get("table");
                assert!(inner.is_some());

                let inner = inner.unwrap();
                assert!(is_match!(inner, &Value::Table(_)));
                match inner {
                    &Value::Table(ref t) => {
                        assert!(!t.is_empty());

                        let a = t.get("a");
                        assert!(a.is_some());

                        let a = a.unwrap();
                        assert!(is_match!(a, &Value::Integer(1)));
                    },
                    _ => panic!("What just happenend?"),
                }
            },
            _ => panic!("What just happenend?"),
        }
    }

    #[test]
    fn test_set_with_seperator_into_array() {
        use std::ops::Index;

        let mut toml : Value = toml_from_str(r#"
        array = [ 0 ]
        "#).unwrap();

        let res = toml.set_with_seperator(&String::from("array.[0]"), '.', Value::Integer(1));

        assert!(res.is_ok());

        let res = res.unwrap();
        assert!(res.is_some());
        let res = res.unwrap();
        assert!(is_match!(res, Value::Integer(0)));

        assert!(is_match!(toml, Value::Table(_)));
        match toml {
            Value::Table(ref t) => {
                assert!(!t.is_empty());

                let inner = t.get("array");
                assert!(inner.is_some());

                let inner = inner.unwrap();
                assert!(is_match!(inner, &Value::Array(_)));
                match inner {
                    &Value::Array(ref a) => {
                        assert!(!a.is_empty());
                        assert!(is_match!(a.index(0), &Value::Integer(1)));
                    },
                    _ => panic!("What just happenend?"),
                }
            },
            _ => panic!("What just happenend?"),
        }
    }

    #[test]
    fn test_set_with_seperator_into_table_index_nonexistent() {
        use std::ops::Index;

        let mut toml : Value = toml_from_str(r#"
        array = []
        "#).unwrap();

        let res = toml.set_with_seperator(&String::from("array.[0]"), '.', Value::Integer(1));

        assert!(res.is_ok());

        let res = res.unwrap();
        assert!(res.is_none());

        assert!(is_match!(toml, Value::Table(_)));
        match toml {
            Value::Table(ref t) => {
                assert!(!t.is_empty());

                let inner = t.get("array");
                assert!(inner.is_some());

                let inner = inner.unwrap();
                assert!(is_match!(inner, &Value::Array(_)));
                match inner {
                    &Value::Array(ref a) => {
                        assert!(!a.is_empty());
                        assert!(is_match!(a.index(0), &Value::Integer(1)));
                    },
                    _ => panic!("What just happenend?"),
                }
            },
            _ => panic!("What just happenend?"),
        }
    }

    #[test]
    fn test_set_with_seperator_into_nested_table() {
        let mut toml : Value = toml_from_str(r#"
        [a.b.c]
        d = 0
        "#).unwrap();

        let res = toml.set_with_seperator(&String::from("a.b.c.d"), '.', Value::Integer(1));

        assert!(res.is_ok());

        let res = res.unwrap();
        assert!(res.is_some());
        let res = res.unwrap();
        assert!(is_match!(res, Value::Integer(0)));

        assert!(is_match!(toml, Value::Table(_)));
        match toml {
            Value::Table(ref t) => {
                assert!(!t.is_empty());

                let a = t.get("a");
                assert!(a.is_some());

                let a = a.unwrap();
                assert!(is_match!(a, &Value::Table(_)));
                match a {
                    &Value::Table(ref a) => {
                        assert!(!a.is_empty());

                        let b_tab = a.get("b");
                        assert!(b_tab.is_some());

                        let b_tab = b_tab.unwrap();
                        assert!(is_match!(b_tab, &Value::Table(_)));
                        match b_tab {
                            &Value::Table(ref b) => {
                                assert!(!b.is_empty());

                                let c_tab = b.get("c");
                                assert!(c_tab.is_some());

                                let c_tab = c_tab.unwrap();
                                assert!(is_match!(c_tab, &Value::Table(_)));
                                match c_tab {
                                    &Value::Table(ref c) => {
                                        assert!(!c.is_empty());

                                        let d = c.get("d");
                                        assert!(d.is_some());

                                        let d = d.unwrap();
                                        assert!(is_match!(d, &Value::Integer(1)));
                                    },
                                    _ => panic!("What just happenend?"),
                                }
                            },
                            _ => panic!("What just happenend?"),
                        }
                    },
                    _ => panic!("What just happenend?"),
                }
            },
            _ => panic!("What just happenend?"),
        }
    }

    #[test]
    fn test_set_with_seperator_into_nonexistent_table() {
        let mut toml : Value = toml_from_str("").unwrap();

        let res = toml.set_with_seperator(&String::from("table.a"), '.', Value::Integer(1));

        assert!(res.is_err());

        let res = res.unwrap_err();
        assert!(is_match!(res.kind(), &ErrorKind::IdentifierNotFoundInDocument(_)));
    }

    #[test]
    fn test_set_with_seperator_into_nonexistent_array() {
        let mut toml : Value = toml_from_str("").unwrap();

        let res = toml.set_with_seperator(&String::from("[0]"), '.', Value::Integer(1));

        assert!(res.is_err());

        let res = res.unwrap_err();
        assert!(is_match!(res.kind(), &ErrorKind::NoIndexInTable(0)));
    }

    #[test]
    fn test_set_with_seperator_ident_into_ary() {
        let mut toml : Value = toml_from_str(r#"
        array = [ 0 ]
        "#).unwrap();

        let res = toml.set_with_seperator(&String::from("array.foo"), '.', Value::Integer(2));

        assert!(res.is_err());
        let res = res.unwrap_err();

        assert!(is_match!(res.kind(), &ErrorKind::NoIdentifierInArray(_)));
    }

    #[test]
    fn test_set_with_seperator_index_into_table() {
        let mut toml : Value = toml_from_str(r#"
        foo = { bar = 1 }
        "#).unwrap();

        let res = toml.set_with_seperator(&String::from("foo.[0]"), '.', Value::Integer(2));

        assert!(res.is_err());
        let res = res.unwrap_err();

        assert!(is_match!(res.kind(), &ErrorKind::NoIndexInTable(_)));
    }

    #[test]
    fn test_set_with_seperator_ident_into_non_structure() {
        let mut toml : Value = toml_from_str(r#"
        val = 0
        "#).unwrap();

        let res = toml.set_with_seperator(&String::from("val.foo"), '.', Value::Integer(2));

        assert!(res.is_err());
        let res = res.unwrap_err();

        assert!(is_match!(res.kind(), &ErrorKind::QueryingValueAsTable(_)));
    }

    #[test]
    fn test_set_with_seperator_index_into_non_structure() {
        let mut toml : Value = toml_from_str(r#"
        foo = 1
        "#).unwrap();

        let res = toml.set_with_seperator(&String::from("foo.[0]"), '.', Value::Integer(2));

        assert!(res.is_err());
        let res = res.unwrap_err();

        assert!(is_match!(res.kind(), &ErrorKind::QueryingValueAsArray(_)));
    }

}

<|endoftext|>