<commit_before>extern crate rand;

pub use self::rand::Rng;

use super::structure::{Program,Condition,Command,Expression,Sensor};

#[macro_export]
macro_rules! pickWeighted {
    ($total: expr, $( $lower: expr, $upper: expr, $expression: expr),+) => {{
        let mut rng = rand::thread_rng();
		    match rng.gen_range(0, $total) {
            $( i @ $lower...$upper if i < $upper => $expression,)+
			      _ => panic!(),
		    }
    }}
}

impl rand::Rand for Program {
	fn rand<R: rand::Rng>(rng: &mut R) -> Self {
		match rng.gen_range(0, 2) {
			i @ 0...1 if i < 1 => Program::If(Condition::rand(rng), Box::new(Program::rand(rng)), Box::new(Program::rand(rng))),
			i @ 1...2 if i < 2 => Program::Command(Command::rand(rng)),
			_ => panic!(),
		}
	}
}

impl rand::Rand for Condition {
	fn rand<R: rand::Rng>(rng: &mut R) -> Self {
		match rng.gen_range(0, 10) {
			i @ 0...1  if i < 1  => Condition::True,
			i @ 1...2  if i < 2  => Condition::False,
			i @ 2...3  if i < 3  => Condition::Not(Box::new(Condition::rand(rng))),
			i @ 3...4  if i < 4  => Condition::Or(Box::new(Condition::rand(rng)), Box::new(Condition::rand(rng))),
			i @ 4...5  if i < 5  => Condition::And(Box::new(Condition::rand(rng)), Box::new(Condition::rand(rng))),
			i @ 5...6  if i < 6  => Condition::Less(Box::new(Expression::rand(rng)), Box::new(Expression::rand(rng))),
			i @ 6...7  if i < 7  => Condition::LessEqual(Box::new(Expression::rand(rng)), Box::new(Expression::rand(rng))),
			i @ 7...8  if i < 8  => Condition::Equal(Box::new(Expression::rand(rng)), Box::new(Expression::rand(rng))),
			i @ 8...9  if i < 9  => Condition::GreaterEqual(Box::new(Expression::rand(rng)), Box::new(Expression::rand(rng))),
			i @ 9...10 if i < 10 => Condition::Greater(Box::new(Expression::rand(rng)), Box::new(Expression::rand(rng))),
			_ => panic!(),
		}
	}
}

impl rand::Rand for Command {
	fn rand<R: rand::Rng>(rng: &mut R) -> Self {
		match rng.gen_range(0, 4) {
			i @ 0...1 if i < 1 => Command::Skip,
			i @ 1...2 if i < 2 => Command::Left,
			i @ 2...3 if i < 3 => Command::Right,
			i @ 3...4 if i < 4 => Command::Up,
			_ => panic!(),
		}
	}
}

impl rand::Rand for Expression {
	fn rand<R: rand::Rng>(rng: &mut R) -> Self {
		match rng.gen_range(0, 6) {
			i @ 0...1 if i < 1 => Expression::Constant(rng.next_f32()),
			i @ 1...2 if i < 2 => Expression::Sensor(Sensor::rand(rng)),
			i @ 2...3 if i < 3 => Expression::Plus(Box::new(Expression::rand(rng)), Box::new(Expression::rand(rng))),
			i @ 3...4 if i < 4 => Expression::Minus(Box::new(Expression::rand(rng)), Box::new(Expression::rand(rng))),
			i @ 4...5 if i < 5 => Expression::Multiply(Box::new(Expression::rand(rng)), Box::new(Expression::rand(rng))),
			i @ 5...6 if i < 6 => Expression::Divide(Box::new(Expression::rand(rng)), Box::new(Expression::rand(rng))),
			_ => panic!(),
		}
	}
}

impl rand::Rand for Sensor {
	fn rand<R: rand::Rng>(rng: &mut R) -> Self {
		match rng.gen_range(0, 6) {
			i @ 0...1 if i < 1 => Sensor::X,
			i @ 1...2 if i < 2 => Sensor::Y,
			i @ 2...3 if i < 3 => Sensor::Vx,
			i @ 3...4 if i < 4 => Sensor::Vy,
			i @ 4...5 if i < 5 => Sensor::O,
			i @ 5...6 if i < 6 => Sensor::W,
			_ => panic!(),
		}
	}
}
<commit_msg>Create a pick macro<commit_after>extern crate rand;

pub use self::rand::Rng;

use super::structure::{Program,Condition,Command,Expression,Sensor};

#[macro_export]
macro_rules! pick {
    ($( $weight: expr, $expression: expr),+) => {{
        let total = 0 $(+ $weight)+;
        let mut bound = 0;

        let mut rng = rand::thread_rng();
        let random_number = rng.gen_range(0, total);
        let result = $( if bound <= random_number && random_number < { bound += $weight; bound } {
            $expression
        } else )+ {
           panic!();
        };
        result
    }}
}

impl rand::Rand for Program {
	fn rand<R: rand::Rng>(rng: &mut R) -> Self {
		match rng.gen_range(0, 2) {
			i @ 0...1 if i < 1 => Program::If(Condition::rand(rng), Box::new(Program::rand(rng)), Box::new(Program::rand(rng))),
			i @ 1...2 if i < 2 => Program::Command(Command::rand(rng)),
			_ => panic!(),
		}
	}
}

impl rand::Rand for Condition {
	fn rand<R: rand::Rng>(rng: &mut R) -> Self {
		match rng.gen_range(0, 10) {
			i @ 0...1  if i < 1  => Condition::True,
			i @ 1...2  if i < 2  => Condition::False,
			i @ 2...3  if i < 3  => Condition::Not(Box::new(Condition::rand(rng))),
			i @ 3...4  if i < 4  => Condition::Or(Box::new(Condition::rand(rng)), Box::new(Condition::rand(rng))),
			i @ 4...5  if i < 5  => Condition::And(Box::new(Condition::rand(rng)), Box::new(Condition::rand(rng))),
			i @ 5...6  if i < 6  => Condition::Less(Box::new(Expression::rand(rng)), Box::new(Expression::rand(rng))),
			i @ 6...7  if i < 7  => Condition::LessEqual(Box::new(Expression::rand(rng)), Box::new(Expression::rand(rng))),
			i @ 7...8  if i < 8  => Condition::Equal(Box::new(Expression::rand(rng)), Box::new(Expression::rand(rng))),
			i @ 8...9  if i < 9  => Condition::GreaterEqual(Box::new(Expression::rand(rng)), Box::new(Expression::rand(rng))),
			i @ 9...10 if i < 10 => Condition::Greater(Box::new(Expression::rand(rng)), Box::new(Expression::rand(rng))),
			_ => panic!(),
		}
	}
}

impl rand::Rand for Command {
	fn rand<R: rand::Rng>(rng: &mut R) -> Self {
		match rng.gen_range(0, 4) {
			i @ 0...1 if i < 1 => Command::Skip,
			i @ 1...2 if i < 2 => Command::Left,
			i @ 2...3 if i < 3 => Command::Right,
			i @ 3...4 if i < 4 => Command::Up,
			_ => panic!(),
		}
	}
}

impl rand::Rand for Expression {
	fn rand<R: rand::Rng>(rng: &mut R) -> Self {
		match rng.gen_range(0, 6) {
			i @ 0...1 if i < 1 => Expression::Constant(rng.next_f32()),
			i @ 1...2 if i < 2 => Expression::Sensor(Sensor::rand(rng)),
			i @ 2...3 if i < 3 => Expression::Plus(Box::new(Expression::rand(rng)), Box::new(Expression::rand(rng))),
			i @ 3...4 if i < 4 => Expression::Minus(Box::new(Expression::rand(rng)), Box::new(Expression::rand(rng))),
			i @ 4...5 if i < 5 => Expression::Multiply(Box::new(Expression::rand(rng)), Box::new(Expression::rand(rng))),
			i @ 5...6 if i < 6 => Expression::Divide(Box::new(Expression::rand(rng)), Box::new(Expression::rand(rng))),
			_ => panic!(),
		}
	}
}

impl rand::Rand for Sensor {
	fn rand<R: rand::Rng>(rng: &mut R) -> Self {
		match rng.gen_range(0, 6) {
			i @ 0...1 if i < 1 => Sensor::X,
			i @ 1...2 if i < 2 => Sensor::Y,
			i @ 2...3 if i < 3 => Sensor::Vx,
			i @ 3...4 if i < 4 => Sensor::Vy,
			i @ 4...5 if i < 5 => Sensor::O,
			i @ 5...6 if i < 6 => Sensor::W,
			_ => panic!(),
		}
	}
}
<|endoftext|>


<commit_before>use std::iter::Iterator;
use std::collections::HashSet;
use std::hash::Hash;

struct Visited<T> {
    hash_set: HashSet<T>
}

impl<T> Visited<T> where T: Hash + Clone + Eq {
    fn new() -> Visited<T> {
        Visited {
            hash_set: HashSet::new()
        }
    }

    fn insert(&mut self, value: &T) -> bool {
        self.hash_set.insert(value.clone())
    }
}

pub trait SearchGoal<T> {
    fn is_goal(&self, state: &T) -> bool;
}

impl<T> SearchGoal<T> for T where T: PartialEq {
    fn is_goal(&self, state: &T) -> bool {
        *self == *state
    }
}

pub trait SearchSpace {
    type State: Hash + Clone + Eq;
    type Action: Clone;
    type Iterator: Iterator<Item=(Self::Action, Self::State)>;

    fn expand(&self, state: &Self::State) -> Self::Iterator;

    fn dfs<G>(&self, start: Self::State, goal: G) -> Option<Vec<Self::Action>>
    where G: SearchGoal<Self::State> {
        if goal.is_goal(&start) {
            return Some(vec![]);
        }

        let mut visited = Visited::new();
        let mut stack = vec![(self.expand(&start), None)];

        loop {
            let next = match stack.last_mut() {
                None => return None,
                Some(&mut (ref mut iter, _)) => iter.next()
            };
            if let Some((action, state)) = next {
                if !visited.insert(&state) {
                    continue;
                }
                if goal.is_goal(&state) {
                    return Some(
                        stack.iter()
                             .map(|&(_, ref a)| a)
                             .cloned()
                             .filter_map(|x| x)
                             .chain(Some(action).into_iter())
                             .collect()
                    )
                }
                stack.push((self.expand(&state), Some(action)));
            } else {
                stack.pop();
            }
        }
    }
}

#[cfg(test)]
pub mod tests {
    use std::vec::IntoIter;
    use super::SearchSpace;

    #[test]
    pub fn test_dfs() {
        struct TestSearch;

        #[derive(Debug, PartialEq, Clone)]
        enum Dir { Left, Right }

        impl SearchSpace for TestSearch {
            type State = i32;
            type Action = Dir;
            type Iterator = IntoIter<(Self::Action, Self::State)>;

            fn expand(&self, state: &Self::State) -> Self::Iterator {
                if *state == 0 {
                    vec![(Dir::Left, 1), (Dir::Right, 2)].into_iter()
                } else if *state == 1 {
                    vec![(Dir::Left, 3), (Dir::Right, 4)].into_iter()
                } else if *state == 2 {
                    vec![(Dir::Left, 2)].into_iter()
                } else {
                    vec![].into_iter()
                }
            }
        }

        let ts = TestSearch;

        assert_eq!(ts.dfs(0, 0).unwrap(), vec![]);
        assert_eq!(ts.dfs(0, 1).unwrap(), vec![Dir::Left]);
        assert_eq!(ts.dfs(0, 2).unwrap(), vec![Dir::Right]);
        assert_eq!(ts.dfs(0, 3).unwrap(), vec![Dir::Left, Dir::Left]);
        assert_eq!(ts.dfs(0, 4).unwrap(), vec![Dir::Left, Dir::Right]);
        assert_eq!(ts.dfs(2, 2).unwrap(), vec![]);
        assert!(ts.dfs(2, 0).is_none());
        assert!(ts.dfs(5, 0).is_none());
    }
}
<commit_msg>no need for Action Clone bound<commit_after>use std::iter::Iterator;
use std::collections::HashSet;
use std::hash::Hash;

struct Visited<T> {
    hash_set: HashSet<T>
}

impl<T> Visited<T> where T: Hash + Clone + Eq {
    fn new() -> Visited<T> {
        Visited {
            hash_set: HashSet::new()
        }
    }

    fn insert(&mut self, value: &T) -> bool {
        self.hash_set.insert(value.clone())
    }
}

pub trait SearchGoal<T> {
    fn is_goal(&self, state: &T) -> bool;
}

impl<T> SearchGoal<T> for T where T: PartialEq {
    fn is_goal(&self, state: &T) -> bool {
        *self == *state
    }
}

pub trait SearchSpace {
    type State: Hash + Clone + Eq;
    type Action;
    type Iterator: Iterator<Item=(Self::Action, Self::State)>;

    fn expand(&self, state: &Self::State) -> Self::Iterator;

    fn dfs<G>(&self, start: Self::State, goal: G) -> Option<Vec<Self::Action>>
    where G: SearchGoal<Self::State> {
        if goal.is_goal(&start) {
            return Some(vec![]);
        }

        let mut visited = Visited::new();
        let mut stack = vec![(self.expand(&start), None)];

        loop {
            let next = match stack.last_mut() {
                None => return None,
                Some(&mut (ref mut iter, _)) => iter.next()
            };
            if let Some((action, state)) = next {
                if !visited.insert(&state) {
                    continue;
                }
                if goal.is_goal(&state) {
                    return Some(
                        stack.into_iter()
                             .filter_map(|(_, a)| a)
                             .chain(Some(action).into_iter())
                             .collect()
                    )
                }
                stack.push((self.expand(&state), Some(action)));
            } else {
                stack.pop();
            }
        }
    }
}

#[cfg(test)]
pub mod tests {
    use std::vec::IntoIter;
    use super::SearchSpace;

    #[test]
    pub fn test_dfs() {
        struct TestSearch;

        #[derive(Debug, PartialEq, Clone)]
        enum Dir { Left, Right }

        impl SearchSpace for TestSearch {
            type State = i32;
            type Action = Dir;
            type Iterator = IntoIter<(Self::Action, Self::State)>;

            fn expand(&self, state: &Self::State) -> Self::Iterator {
                if *state == 0 {
                    vec![(Dir::Left, 1), (Dir::Right, 2)].into_iter()
                } else if *state == 1 {
                    vec![(Dir::Left, 3), (Dir::Right, 4)].into_iter()
                } else if *state == 2 {
                    vec![(Dir::Left, 2)].into_iter()
                } else {
                    vec![].into_iter()
                }
            }
        }

        let ts = TestSearch;

        assert_eq!(ts.dfs(0, 0).unwrap(), vec![]);
        assert_eq!(ts.dfs(0, 1).unwrap(), vec![Dir::Left]);
        assert_eq!(ts.dfs(0, 2).unwrap(), vec![Dir::Right]);
        assert_eq!(ts.dfs(0, 3).unwrap(), vec![Dir::Left, Dir::Left]);
        assert_eq!(ts.dfs(0, 4).unwrap(), vec![Dir::Left, Dir::Right]);
        assert_eq!(ts.dfs(2, 2).unwrap(), vec![]);
        assert!(ts.dfs(2, 0).is_none());
        assert!(ts.dfs(5, 0).is_none());
    }
}
<|endoftext|>


<commit_before>extern crate dbus;
use self::dbus::{Connection, ConnectionItem, Message, NameFlag, ReleaseNameReply};
use self::dbus::obj::ObjectPath;

use super::error::DBusError;
use super::target::DBusTarget;

use std::collections::btree_map::{BTreeMap, Entry};
use std::error::Error;

pub struct DBusServer<'a> {
    conn: &'a Connection,
    name: String,

    objects: BTreeMap<String, ObjectPath<'a>>,
    signals: BTreeMap<DBusTarget, Vec<fn (&Connection, &DBusTarget) -> ()>>
}

impl<'a> DBusServer<'a> {
    pub fn new(conn: &'a Connection, name: &str) -> Result<DBusServer<'a>, dbus::Error> {
        try!(conn.register_name(name, NameFlag::DoNotQueue as u32));

        Ok(DBusServer {
            conn: conn,
            name: name.to_owned(),

            objects: BTreeMap::new(),
            signals: BTreeMap::new(),
        })
    }

    pub fn name(&self) -> &str {
        &self.name
    }

    pub fn add_object(&mut self, path: &str, add_interfaces: fn (&mut ObjectPath<'a>) -> ()) -> Result<&mut Self, Box<Error>> {
        // XXX: Use `.map` when type resolution works better. Currently, `.map` causes the caller
        // type to be set in stone due to eager type resolution and no fluidity in setting it. This
        // causes the type to be too concrete on the caller side which then fails to map to the end
        // result type of `.map` even though `.map` is "transparent" to the error type.
        Result::map(match self.objects.entry(path.to_owned()) {
            Entry::Vacant(v)    => {
                let mut obj = ObjectPath::new(self.conn, path, true);
                try!(obj.set_registered(true));

                // Add interfaces.
                add_interfaces(&mut obj);

                v.insert(obj);

                Ok(())
            },
            Entry::Occupied(_)  => Err(Box::new(DBusError::PathAlreadyRegistered(path.to_owned()))),
        }, |_| self)
    }

    pub fn remove_object(&mut self, path: &str) -> Result<&mut Self, DBusError> {
        match self.objects.remove(path) {
            Some(_) => Ok(self),
            None    => Err(DBusError::NoSuchPath(path.to_owned())),
        }
    }

    pub fn connect(&mut self, signal: DBusTarget, callback: fn (&Connection, &DBusTarget) -> ()) -> &mut Self {
        match self.signals.entry(signal) {
            Entry::Vacant(v)    => { v.insert(vec![callback]); },
            Entry::Occupied(o)  => o.into_mut().push(callback),
        };

        self
    }

    pub fn run(&mut self) -> () {
        self.conn.iter(100).fold((), |_, item| {
            match item {
                ConnectionItem::MethodCall(m)   => self._call_method(m),
                ConnectionItem::Signal(s)       => self._match_signal(s),
                ConnectionItem::Nothing         => (),
            }
        });
    }

    fn _call_method(&mut self, m: Message) -> () {
        self.objects.iter_mut().fold(Some(m), |opt_m, (_, object)| {
            opt_m.and_then(|mut m| {
                match object.handle_message(&mut m) {
                    None          => Some(m),
                    Some(Ok(()))  => None,
                    Some(Err(())) => {
                        println!("failed to send a reply for {:?}", m);
                        None
                    },
                }
            })
        });
    }

    fn _match_signal(&self, m: Message) -> () {
        let ref signals = self.signals;
        let conn = self.conn;

        DBusTarget::extract(&m).and_then(|signal| {
            signals.get(&signal).map(|fs| {
                fs.iter().fold((conn, signal), |(conn, signal), f| {
                    f(&conn, &signal);
                    (conn, signal)
                })
            })
        });
    }
}

impl<'a> Drop for DBusServer<'a> {
    fn drop(&mut self) {
        let res = self.conn.release_name(&self.name);
        match res {
            Ok(reply) =>
                match reply {
                    ReleaseNameReply::Released    => (),
                    ReleaseNameReply::NonExistent => panic!("internal error: non-existent name {}?!", self.name),
                    ReleaseNameReply::NotOwner    => panic!("internal error: not the owner of {}?!", self.name),
                },
            Err(err) => println!("failed to release {}: {:?}: {:?}", self.name, err.name(), err.message()),
        }
    }
}
<commit_msg>server: allow external iteration<commit_after>extern crate dbus;
use self::dbus::{Connection, Message, MessageType, NameFlag, ReleaseNameReply};
use self::dbus::obj::ObjectPath;

use super::error::DBusError;
use super::target::DBusTarget;

use std::collections::btree_map::{BTreeMap, Entry};
use std::error::Error;

pub struct DBusServer<'a> {
    conn: &'a Connection,
    name: String,

    objects: BTreeMap<String, ObjectPath<'a>>,
    signals: BTreeMap<DBusTarget, Vec<fn (&Connection, &DBusTarget) -> ()>>
}

impl<'a> DBusServer<'a> {
    pub fn new(conn: &'a Connection, name: &str) -> Result<DBusServer<'a>, dbus::Error> {
        try!(conn.register_name(name, NameFlag::DoNotQueue as u32));

        Ok(DBusServer {
            conn: conn,
            name: name.to_owned(),

            objects: BTreeMap::new(),
            signals: BTreeMap::new(),
        })
    }

    pub fn name(&self) -> &str {
        &self.name
    }

    pub fn add_object(&mut self, path: &str, add_interfaces: fn (&mut ObjectPath<'a>) -> ()) -> Result<&mut Self, Box<Error>> {
        // XXX: Use `.map` when type resolution works better. Currently, `.map` causes the caller
        // type to be set in stone due to eager type resolution and no fluidity in setting it. This
        // causes the type to be too concrete on the caller side which then fails to map to the end
        // result type of `.map` even though `.map` is "transparent" to the error type.
        Result::map(match self.objects.entry(path.to_owned()) {
            Entry::Vacant(v)    => {
                let mut obj = ObjectPath::new(self.conn, path, true);
                try!(obj.set_registered(true));

                // Add interfaces.
                add_interfaces(&mut obj);

                v.insert(obj);

                Ok(())
            },
            Entry::Occupied(_)  => Err(Box::new(DBusError::PathAlreadyRegistered(path.to_owned()))),
        }, |_| self)
    }

    pub fn remove_object(&mut self, path: &str) -> Result<&mut Self, DBusError> {
        match self.objects.remove(path) {
            Some(_) => Ok(self),
            None    => Err(DBusError::NoSuchPath(path.to_owned())),
        }
    }

    pub fn connect(&mut self, signal: DBusTarget, callback: fn (&Connection, &DBusTarget) -> ()) -> &mut Self {
        match self.signals.entry(signal) {
            Entry::Vacant(v)    => { v.insert(vec![callback]); },
            Entry::Occupied(o)  => o.into_mut().push(callback),
        };

        self
    }

    pub fn handle_message<'b>(&mut self, m: &'b mut Message) -> Option<&'b mut Message> {
        match m.msg_type() {
            MessageType::Signal     => Some(self._match_signal(m)),
            MessageType::MethodCall => self._call_method(m),
            _                       => Some(m),
        }
    }

    fn _call_method<'b>(&mut self, m: &'b mut Message) -> Option<&'b mut Message> {
        self.objects.iter_mut().fold(Some(m), |opt_m, (_, object)| {
            opt_m.and_then(|mut m| {
                match object.handle_message(&mut m) {
                    None          => Some(m),
                    Some(Ok(()))  => None,
                    Some(Err(())) => {
                        println!("failed to send a reply for {:?}", m);
                        None
                    },
                }
            })
        })
    }

    fn _match_signal<'b>(&self, m: &'b mut Message) -> &'b mut Message {
        let ref signals = self.signals;
        let conn = self.conn;

        DBusTarget::extract(m).and_then(|signal| {
            signals.get(&signal).map(|fs| {
                fs.iter().fold((conn, signal), |(conn, signal), f| {
                    f(&conn, &signal);
                    (conn, signal)
                })
            })
        });

        m
    }
}

impl<'a> Drop for DBusServer<'a> {
    fn drop(&mut self) {
        let res = self.conn.release_name(&self.name);
        match res {
            Ok(reply) =>
                match reply {
                    ReleaseNameReply::Released    => (),
                    ReleaseNameReply::NonExistent => panic!("internal error: non-existent name {}?!", self.name),
                    ReleaseNameReply::NotOwner    => panic!("internal error: not the owner of {}?!", self.name),
                },
            Err(err) => println!("failed to release {}: {:?}: {:?}", self.name, err.name(), err.message()),
        }
    }
}
<|endoftext|>


<commit_before>use std::net::{UdpSocket, SocketAddr, Ipv4Addr, IpAddr};
use std;
use std::cell::Cell;

use packet::*;
use options;
use NAK;

///! This is a convenience module that simplifies the writing of a DHCP server service.

pub struct Server {
    out_buf: Cell<[u8; 1500]>,
    socket: UdpSocket,
    src: SocketAddr,
    server_ip: [u8; 4],
}

pub trait Handler {
    fn handle_request(&mut self, &Server, u8, Packet);
}

/// Orders and filters options based on PARAMETER_REQUEST_LIST received from client.
/// DHCP_MESSAGE_TYPE and SERVER_IDENTIFIER are always first and always retained.
/// This function is called by Reply.
pub fn filter_options_by_req(opts: &mut Vec<options::Option>, req_params: &[u8]) {
    let mut pos = 0;
    let h = &[options::DHCP_MESSAGE_TYPE as u8, options::SERVER_IDENTIFIER as u8] as &[u8];
    for z in [h, req_params].iter() {
        for r in z.iter() {
            let mut found = false;
            let mut at = 0;
            for (i, o) in opts[pos..].iter().enumerate() {
                if o.code == *r {
                    found = true;
                    at = i + pos;
                    break;
                }
            }
            if found {
                opts.swap(pos, at);
                pos = pos + 1;
            }
        }
    }
    opts.truncate(pos);
}

impl Server {
    pub fn serve<H: Handler>(udp_soc: UdpSocket,
                             server_ip: [u8; 4],
                             mut handler: H)
                             -> std::io::Error {
        let mut in_buf: [u8; 1500] = [0; 1500];
        let mut s = Server {
            out_buf: Cell::new([0; 1500]),
            socket: udp_soc,
            server_ip: server_ip,
            src: SocketAddr::new(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)), 0),
        };
        loop {
            match s.socket.recv_from(&mut in_buf) {
                Err(e) => return e,
                Ok((l, src)) => {
                    if let Ok(p) = decode(&in_buf[..l]) {
                        if let Some(msg_type) = p.option(options::DHCP_MESSAGE_TYPE) {
                            if msg_type.len() != 1 {
                                continue;
                            }
                            s.src = src;
                            handler.handle_request(&s, msg_type[0], p);
                        }
                    }
                }
            }
        }
    }

    /// Constructs and sends a reply packet back to the client.
    /// additional_options should not include DHCP_MESSAGE_TYPE nor SERVER_IDENTIFIER as these
    /// are added automatically.
    pub fn reply(&self,
                 msg_type: u8,
                 additional_options: Vec<options::Option>,
                 offer_ip: [u8; 4],
                 req_packet: Packet)
                 -> std::io::Result<usize> {
        let mt = &[msg_type];

        let mut opts: Vec<options::Option> = Vec::with_capacity(additional_options.len() + 2);
        opts.push(options::Option {
            code: options::DHCP_MESSAGE_TYPE,
            data: mt,
        });
        opts.push(options::Option {
            code: options::SERVER_IDENTIFIER,
            data: &self.server_ip,
        });
        opts.extend(additional_options);

        if let Some(prl) = req_packet.option(options::PARAMETER_REQUEST_LIST) {
            filter_options_by_req(&mut opts, &prl);
        }

        self.send(Packet {
            reply: true,
            hops: 0,
            xid: req_packet.xid,
            secs: 0,
            broadcast: req_packet.broadcast,
            ciaddr: if msg_type == NAK {
                [0, 0, 0, 0]
            } else {
                req_packet.ciaddr
            },
            yiaddr: offer_ip,
            siaddr: [0, 0, 0, 0],
            giaddr: req_packet.giaddr,
            chaddr: req_packet.chaddr,
            options: opts,
        })
    }

    /// Checks the packet see if it was intended for this DHCP server (as opposed to some other also on the network).
    pub fn for_this_server(&self, packet: &Packet) -> bool {
        match packet.option(options::SERVER_IDENTIFIER) {
            None => false,
            Some(x) => (x == &self.server_ip),
        }
    }

    /// Encodes and sends a DHCP packet back to the client.
    pub fn send(&self, p: Packet) -> std::io::Result<usize> {
        let mut addr = self.src;
        if p.broadcast || addr.ip() == IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)) {
            addr.set_ip(IpAddr::V4(Ipv4Addr::new(255, 255, 255, 255)));
        }
        self.socket.send_to(p.encode(&mut self.out_buf.get()), addr)
    }
}
<commit_msg>Always retain IP_ADDRESS_LEASE_TIME option, if present (fixes #1)<commit_after>use std::net::{UdpSocket, SocketAddr, Ipv4Addr, IpAddr};
use std;
use std::cell::Cell;

use packet::*;
use options;
use NAK;

///! This is a convenience module that simplifies the writing of a DHCP server service.

pub struct Server {
    out_buf: Cell<[u8; 1500]>,
    socket: UdpSocket,
    src: SocketAddr,
    server_ip: [u8; 4],
}

pub trait Handler {
    fn handle_request(&mut self, &Server, u8, Packet);
}

/// Orders and filters options based on PARAMETER_REQUEST_LIST received from client.
/// DHCP_MESSAGE_TYPE and SERVER_IDENTIFIER are always first and always retained.
/// This function is called by Reply.
pub fn filter_options_by_req(opts: &mut Vec<options::Option>, req_params: &[u8]) {
    let mut pos = 0;
    let h = &[options::DHCP_MESSAGE_TYPE as u8, options::SERVER_IDENTIFIER as u8, options::IP_ADDRESS_LEASE_TIME as u8] as &[u8];
    for z in [h, req_params].iter() {
        for r in z.iter() {
            let mut found = false;
            let mut at = 0;
            for (i, o) in opts[pos..].iter().enumerate() {
                if o.code == *r {
                    found = true;
                    at = i + pos;
                    break;
                }
            }
            if found {
                opts.swap(pos, at);
                pos = pos + 1;
            }
        }
    }
    opts.truncate(pos);
}

impl Server {
    pub fn serve<H: Handler>(udp_soc: UdpSocket,
                             server_ip: [u8; 4],
                             mut handler: H)
                             -> std::io::Error {
        let mut in_buf: [u8; 1500] = [0; 1500];
        let mut s = Server {
            out_buf: Cell::new([0; 1500]),
            socket: udp_soc,
            server_ip: server_ip,
            src: SocketAddr::new(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)), 0),
        };
        loop {
            match s.socket.recv_from(&mut in_buf) {
                Err(e) => return e,
                Ok((l, src)) => {
                    if let Ok(p) = decode(&in_buf[..l]) {
                        if let Some(msg_type) = p.option(options::DHCP_MESSAGE_TYPE) {
                            if msg_type.len() != 1 {
                                continue;
                            }
                            s.src = src;
                            handler.handle_request(&s, msg_type[0], p);
                        }
                    }
                }
            }
        }
    }

    /// Constructs and sends a reply packet back to the client.
    /// additional_options should not include DHCP_MESSAGE_TYPE nor SERVER_IDENTIFIER as these
    /// are added automatically.
    pub fn reply(&self,
                 msg_type: u8,
                 additional_options: Vec<options::Option>,
                 offer_ip: [u8; 4],
                 req_packet: Packet)
                 -> std::io::Result<usize> {
        let mt = &[msg_type];

        let mut opts: Vec<options::Option> = Vec::with_capacity(additional_options.len() + 2);
        opts.push(options::Option {
            code: options::DHCP_MESSAGE_TYPE,
            data: mt,
        });
        opts.push(options::Option {
            code: options::SERVER_IDENTIFIER,
            data: &self.server_ip,
        });
        opts.extend(additional_options);

        if let Some(prl) = req_packet.option(options::PARAMETER_REQUEST_LIST) {
            filter_options_by_req(&mut opts, &prl);
        }

        self.send(Packet {
            reply: true,
            hops: 0,
            xid: req_packet.xid,
            secs: 0,
            broadcast: req_packet.broadcast,
            ciaddr: if msg_type == NAK {
                [0, 0, 0, 0]
            } else {
                req_packet.ciaddr
            },
            yiaddr: offer_ip,
            siaddr: [0, 0, 0, 0],
            giaddr: req_packet.giaddr,
            chaddr: req_packet.chaddr,
            options: opts,
        })
    }

    /// Checks the packet see if it was intended for this DHCP server (as opposed to some other also on the network).
    pub fn for_this_server(&self, packet: &Packet) -> bool {
        match packet.option(options::SERVER_IDENTIFIER) {
            None => false,
            Some(x) => (x == &self.server_ip),
        }
    }

    /// Encodes and sends a DHCP packet back to the client.
    pub fn send(&self, p: Packet) -> std::io::Result<usize> {
        let mut addr = self.src;
        if p.broadcast || addr.ip() == IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)) {
            addr.set_ip(IpAddr::V4(Ipv4Addr::new(255, 255, 255, 255)));
        }
        self.socket.send_to(p.encode(&mut self.out_buf.get()), addr)
    }
}
<|endoftext|>


<commit_before>extern crate rand;

use self::rand::{thread_rng,Rng};

use std::collections::HashMap;
use std::sync::{Arc,RwLock,Mutex,mpsc};

use super::libcoinche::{bid,cards,pos,game};

pub enum ServerError {
    BadPlayerId,
    BadEventId,
    PlayInAuction,
    BidInGame,
    Bid(bid::BidError),
    Play(game::PlayError),
}

pub enum Action {
    Bid(bid::Contract),
    Coinche,
    Pass,
    Play(cards::Card),
}

#[derive(Clone)]
pub enum PlayerEvent {
    Bidded(bid::Contract),
    Coinched,
    Passed,
    CardPlayed(cards::Card),
}

// Player just joined a new party. He's given a player id, and his position.
pub struct NewPartyInfo {
    pub player_id: u32,
    pub player_pos: pos::PlayerPos,
}

// Represents an event that can happen during the game.
#[derive(Clone)]
pub enum EventType {
    // The party is cancelled. Contains an optional explanation.
    PartyCancelled(String),

    // A player did something!
    FromPlayer(pos::PlayerPos, PlayerEvent),

    // Bid over: contains the contract and the author
    BidOver(pos::PlayerPos, bid::Contract),
    // The bid was cancelled, probably because no one bidded anything.
    // A new game is probably on its way.
    BidCancelled,

    // Trick over: contains the winner
    TrickOver(pos::PlayerPos),

    // New game: contains the first player, and the player's hand
    NewGame(pos::PlayerPos, [cards::Hand;4]),

    // Game over: contains scores
    GameOver([i32;2], pos::Team, [i32;2]),
}

#[derive(Clone)]
pub struct Event {
    pub event: EventType,
    pub id: usize,
}

pub struct Order {
    pub author: pos::PlayerPos,
    pub action: Action
}

pub struct Server {
    party_list: RwLock<PartyList>,

    waiting_list: Mutex<Vec<mpsc::Sender<NewPartyInfo>>>,
}

pub enum Game {
    Bidding(bid::Auction),
    Playing(game::GameState),
}

pub struct Party {
    game: Game,

    scores: [i32; 2],

    events: Vec<EventType>,
    observers: Vec<mpsc::Sender<Event>>,
}

fn new_party(first: pos::PlayerPos) -> Party {
    Party {
        game: Game::Bidding(bid::new_auction(first)),
        scores: [0;2],
        events: Vec::new(),
        observers: Vec::new(),
    }
}

impl Party {
    fn add_event(&mut self, event: EventType) {
        let ev = Event{
            event: event.clone(),
            id: self.events.len(),
        };
        for sender in self.observers.iter() {
            // TODO: handle cancelled wait?
            sender.send(ev.clone()).unwrap();
        }
        self.observers.clear();
        self.events.push(event);
    }

    fn play_card(&mut self, pos: pos::PlayerPos, card: cards::Card) -> Result<Event,ServerError> {
        let result = match &mut self.game {
            &mut Game::Bidding(_) => {
                // Bad time for a card play!
                return Err(ServerError::PlayInAuction);
            },
            &mut Game::Playing(ref mut game) => {
                match game.play_card(pos, card) {
                    Ok(result) => result,
                    Err(err) => {
                        // Nothing to see here
                        return Err(ServerError::Play(err));
                    },
                }
            },
        };
        self.add_event(EventType::FromPlayer(pos, PlayerEvent::CardPlayed(card)));
        match result {
            game::TrickResult::Nothing => (),
            game::TrickResult::TrickOver(winner, game_result) => {
                self.add_event(EventType::TrickOver(winner));
                match game_result {
                    game::GameResult::Nothing => (),
                    game::GameResult::GameOver(points, winners, scores) => {
                        for i in 0..2 { self.scores[i] += scores[i]; }
                        let total_scores = self.scores;
                        self.add_event(EventType::GameOver(points, winners, total_scores));
                        // Prepare next game?
                    }
                }
            },
        }

        // Dummy event before handling the real case
        Ok(Event{
            event: EventType::BidCancelled,
            id:0
        })

    }
}

pub struct PlayerInfo {
    pub party: Arc<RwLock<Party>>,
    pub pos: pos::PlayerPos,
}

pub struct PartyList {
    pub player_map: HashMap<u32,PlayerInfo>,
}

impl PartyList {
    fn make_ids(&self) -> [u32; 4] {
        // Expect self.player_map to be locked
        let mut result = [0;4];

        for i in 0..4 {
            loop {
                let id = thread_rng().next_u32();
                if self.player_map.contains_key(&id) {
                    continue;
                }
                let mut ok = true;
                for j in 0..i {
                    if result[j] == id {
                        ok = false;
                        break;
                    }
                }
                if !ok {
                    continue;
                }

                result[i] = id;
            }
        }

        result
    }
}

enum WaitResult {
    Ready(Event),
    Waiting(mpsc::Receiver<Event>),
}

enum JoinResult {
    Ready(NewPartyInfo),
    Waiting(mpsc::Receiver<NewPartyInfo>),
}

impl Server {
    pub fn join(&self) -> Option<NewPartyInfo> {
        match self.get_join_result() {
            // TODO: add a timeout (max: 20s)
            // TODO: handle cancelled join?
            JoinResult::Ready(info) => Some(info),
            JoinResult::Waiting(rx) => Some(rx.recv().unwrap()),
        }
    }

    fn get_join_result(&self) -> JoinResult {
        let mut waiters = self.waiting_list.lock().unwrap();
        if waiters.len() >= 3 {
            // It's a PARTEY!
            let info = self.make_party([
                                       waiters.pop().unwrap(),
                                       waiters.pop().unwrap(),
                                       waiters.pop().unwrap(),
            ]);
            return JoinResult::Ready(info);
        } else {
            let (tx,rx) = mpsc::channel();
            waiters.push(tx);
            return JoinResult::Waiting(rx);
        }
    }

    fn make_party(&self, others: [mpsc::Sender<NewPartyInfo>; 3]) -> NewPartyInfo {
        let mut list = self.party_list.write().unwrap();

        // Generate 4 new IDS
        let ids = list.make_ids();

        let party = Arc::new(RwLock::new(new_party(pos::P0)));
        // Kickstart it with a new game!

        // Prepare the players info
        for i in 0..4 {
            list.player_map.insert(ids[i], PlayerInfo {
                party: party.clone(),
                pos: pos::PlayerPos(i),
            });
        }

        // Tell everyone. They'll love it.
        // TODO: handle cancelled channels (?)
        for i in 0..3 {
            others[i].send(NewPartyInfo{
                player_id: ids[i],
                player_pos: pos::PlayerPos(i),
            }).unwrap();
        }

        // Even you, weird 4th dude.
        NewPartyInfo{
            player_id: ids[3],
            player_pos: pos::P3,
        }
    }

    // Play a card in the current game
    pub fn play_card(&self, player_id: u32, card: cards::Card) -> Result<Event,ServerError> {
        let list = self.party_list.read().unwrap();

        let info = match list.player_map.get(&player_id) {
            Some(info) => info,
            None => return Err(ServerError::BadPlayerId),
        };

        let mut party = info.party.write().unwrap();
        party.play_card(info.pos, card)

    }

    // TODO: add bidding and stuff?

    // Waits until the given event_id happens
    pub fn wait(&self, player_id: u32, event_id: usize) -> Result<Event,ServerError> {
        let res = self.get_wait_result(player_id, event_id);

        // TODO: add a timeout (~15s?)

        match res {
            Err(err) => Err(err),
            Ok(WaitResult::Ready(event)) => Ok(event),
            // TODO: handle case where the wait is cancelled
            // (don't unwrap, return an error instead?)
            Ok(WaitResult::Waiting(rx)) => Ok(rx.recv().unwrap()),
        }
    }

    // Check if the event ID is already available. If not, returns a channel that will produce it one
    // day, so that we don't keep the locks while waiting.
    fn get_wait_result(&self, player_id: u32, event_id: usize) -> Result<WaitResult,ServerError> {
        let list = self.party_list.read().unwrap();

        let info = match list.player_map.get(&player_id) {
            Some(info) => info,
            None => return Err(ServerError::BadPlayerId),
        };

        let mut party = info.party.write().unwrap();

        if party.events.len() > event_id {
            return Ok(WaitResult::Ready(Event {
                event: party.events[event_id].clone(),
                id: event_id,
            }));
        } else if event_id > party.events.len() {
            // We are too ambitious! One event at a time!
            return Err(ServerError::BadEventId);
        }

        let (tx, rx) = mpsc::channel();
        party.observers.push(tx);

        Ok(WaitResult::Waiting(rx))
    }
}

<commit_msg>Correctly send play_card event<commit_after>extern crate rand;

use self::rand::{thread_rng,Rng};

use std::collections::HashMap;
use std::sync::{Arc,RwLock,Mutex,mpsc};

use super::libcoinche::{bid,cards,pos,game};

pub enum ServerError {
    BadPlayerId,
    BadEventId,
    PlayInAuction,
    BidInGame,
    Bid(bid::BidError),
    Play(game::PlayError),
}

pub enum Action {
    Bid(bid::Contract),
    Coinche,
    Pass,
    Play(cards::Card),
}

#[derive(Clone)]
pub enum PlayerEvent {
    Bidded(bid::Contract),
    Coinched,
    Passed,
    CardPlayed(cards::Card),
}

// Player just joined a new party. He's given a player id, and his position.
pub struct NewPartyInfo {
    pub player_id: u32,
    pub player_pos: pos::PlayerPos,
}

// Represents an event that can happen during the game.
#[derive(Clone)]
pub enum EventType {
    // The party is cancelled. Contains an optional explanation.
    PartyCancelled(String),

    // A player did something!
    FromPlayer(pos::PlayerPos, PlayerEvent),

    // Bid over: contains the contract and the author
    BidOver(pos::PlayerPos, bid::Contract),
    // The bid was cancelled, probably because no one bidded anything.
    // A new game is probably on its way.
    BidCancelled,

    // Trick over: contains the winner
    TrickOver(pos::PlayerPos),

    // New game: contains the first player, and the player's hand
    NewGame(pos::PlayerPos, [cards::Hand;4]),

    // Game over: contains scores
    GameOver([i32;2], pos::Team, [i32;2]),
}

#[derive(Clone)]
pub struct Event {
    pub event: EventType,
    pub id: usize,
}

pub struct Order {
    pub author: pos::PlayerPos,
    pub action: Action
}

pub struct Server {
    party_list: RwLock<PartyList>,

    waiting_list: Mutex<Vec<mpsc::Sender<NewPartyInfo>>>,
}

pub enum Game {
    Bidding(bid::Auction),
    Playing(game::GameState),
}

pub struct Party {
    game: Game,

    scores: [i32; 2],

    events: Vec<EventType>,
    observers: Vec<mpsc::Sender<Event>>,
}

fn new_party(first: pos::PlayerPos) -> Party {
    Party {
        game: Game::Bidding(bid::new_auction(first)),
        scores: [0;2],
        events: Vec::new(),
        observers: Vec::new(),
    }
}

impl Party {
    fn add_event(&mut self, event: EventType) -> Event {
        let ev = Event{
            event: event.clone(),
            id: self.events.len(),
        };
        for sender in self.observers.iter() {
            // TODO: handle cancelled wait?
            sender.send(ev.clone()).unwrap();
        }
        self.observers.clear();
        self.events.push(event);

        ev
    }

    fn play_card(&mut self, pos: pos::PlayerPos, card: cards::Card) -> Result<Event,ServerError> {
        let result = match &mut self.game {
            &mut Game::Bidding(_) => {
                // Bad time for a card play!
                return Err(ServerError::PlayInAuction);
            },
            &mut Game::Playing(ref mut game) => {
                match game.play_card(pos, card) {
                    Ok(result) => result,
                    Err(err) => {
                        // Nothing to see here
                        return Err(ServerError::Play(err));
                    },
                }
            },
        };
        // This is the main event we want to send.
        // TODO: Batch event dispatch, and send all those together.
        let main_event = self.add_event(EventType::FromPlayer(pos, PlayerEvent::CardPlayed(card)));
        match result {
            game::TrickResult::Nothing => (),
            game::TrickResult::TrickOver(winner, game_result) => {
                self.add_event(EventType::TrickOver(winner));
                match game_result {
                    game::GameResult::Nothing => (),
                    game::GameResult::GameOver(points, winners, scores) => {
                        for i in 0..2 { self.scores[i] += scores[i]; }
                        let total_scores = self.scores;
                        self.add_event(EventType::GameOver(points, winners, total_scores));
                        // TODO: Prepare next game?
                        // Maybe keep it in the history?
                    }
                }
            },
        }

        Ok(main_event)
    }
}

pub struct PlayerInfo {
    pub party: Arc<RwLock<Party>>,
    pub pos: pos::PlayerPos,
}

pub struct PartyList {
    pub player_map: HashMap<u32,PlayerInfo>,
}

impl PartyList {
    fn make_ids(&self) -> [u32; 4] {
        // Expect self.player_map to be locked
        let mut result = [0;4];

        for i in 0..4 {
            loop {
                let id = thread_rng().next_u32();
                if self.player_map.contains_key(&id) {
                    continue;
                }
                let mut ok = true;
                for j in 0..i {
                    if result[j] == id {
                        ok = false;
                        break;
                    }
                }
                if !ok {
                    continue;
                }

                result[i] = id;
            }
        }

        result
    }
}

enum WaitResult {
    Ready(Event),
    Waiting(mpsc::Receiver<Event>),
}

enum JoinResult {
    Ready(NewPartyInfo),
    Waiting(mpsc::Receiver<NewPartyInfo>),
}

impl Server {
    pub fn join(&self) -> Option<NewPartyInfo> {
        match self.get_join_result() {
            // TODO: add a timeout (max: 20s)
            // TODO: handle cancelled join?
            JoinResult::Ready(info) => Some(info),
            JoinResult::Waiting(rx) => Some(rx.recv().unwrap()),
        }
    }

    fn get_join_result(&self) -> JoinResult {
        let mut waiters = self.waiting_list.lock().unwrap();
        if waiters.len() >= 3 {
            // It's a PARTEY!
            let info = self.make_party([
                                       waiters.pop().unwrap(),
                                       waiters.pop().unwrap(),
                                       waiters.pop().unwrap(),
            ]);
            return JoinResult::Ready(info);
        } else {
            let (tx,rx) = mpsc::channel();
            waiters.push(tx);
            return JoinResult::Waiting(rx);
        }
    }

    fn make_party(&self, others: [mpsc::Sender<NewPartyInfo>; 3]) -> NewPartyInfo {
        let mut list = self.party_list.write().unwrap();

        // Generate 4 new IDS
        let ids = list.make_ids();

        let party = Arc::new(RwLock::new(new_party(pos::P0)));
        // Kickstart it with a new game!

        // Prepare the players info
        for i in 0..4 {
            list.player_map.insert(ids[i], PlayerInfo {
                party: party.clone(),
                pos: pos::PlayerPos(i),
            });
        }

        // Tell everyone. They'll love it.
        // TODO: handle cancelled channels (?)
        for i in 0..3 {
            others[i].send(NewPartyInfo{
                player_id: ids[i],
                player_pos: pos::PlayerPos(i),
            }).unwrap();
        }

        // Even you, weird 4th dude.
        NewPartyInfo{
            player_id: ids[3],
            player_pos: pos::P3,
        }
    }

    // Play a card in the current game
    pub fn play_card(&self, player_id: u32, card: cards::Card) -> Result<Event,ServerError> {
        let list = self.party_list.read().unwrap();

        let info = match list.player_map.get(&player_id) {
            Some(info) => info,
            None => return Err(ServerError::BadPlayerId),
        };

        let mut party = info.party.write().unwrap();
        party.play_card(info.pos, card)

    }

    // TODO: add bidding and stuff?

    // Waits until the given event_id happens
    pub fn wait(&self, player_id: u32, event_id: usize) -> Result<Event,ServerError> {
        let res = self.get_wait_result(player_id, event_id);

        // TODO: add a timeout (~15s?)

        match res {
            Err(err) => Err(err),
            Ok(WaitResult::Ready(event)) => Ok(event),
            // TODO: handle case where the wait is cancelled
            // (don't unwrap, return an error instead?)
            Ok(WaitResult::Waiting(rx)) => Ok(rx.recv().unwrap()),
        }
    }

    // Check if the event ID is already available. If not, returns a channel that will produce it one
    // day, so that we don't keep the locks while waiting.
    fn get_wait_result(&self, player_id: u32, event_id: usize) -> Result<WaitResult,ServerError> {
        let list = self.party_list.read().unwrap();

        let info = match list.player_map.get(&player_id) {
            Some(info) => info,
            None => return Err(ServerError::BadPlayerId),
        };

        let mut party = info.party.write().unwrap();

        if party.events.len() > event_id {
            return Ok(WaitResult::Ready(Event {
                event: party.events[event_id].clone(),
                id: event_id,
            }));
        } else if event_id > party.events.len() {
            // We are too ambitious! One event at a time!
            return Err(ServerError::BadEventId);
        }

        let (tx, rx) = mpsc::channel();
        party.observers.push(tx);

        Ok(WaitResult::Waiting(rx))
    }
}

<|endoftext|>


<commit_before>
use languageserver_types::*;
use serde;
use serde_json;
use std::{
    io,
    mem,
    str
};
use std::collections::{
    HashMap
};
use tokio_core::io::{
    Codec,
    EasyBuf
};

macro_rules! server_messages {
    (
        methods {
            $( $method_name : pat => $method_type : ident $( ( $method_param : ty ) )*; )*
        },
        notifications {
            $( $notif_name : pat => $notif_type : ident $( ( $notif_param : ty ) )*; )*
        }
    ) => {
        #[derive( Debug )]
        pub enum RequestMethod {
            $( $method_type $( ( $method_param ) )*, )*
        }

        #[derive( Debug )]
        pub enum NotificationMethod {
            $( $notif_type $( ( $notif_param ) )*, )*
        }

        pub fn parse_server_message( msg_json_str : &str ) -> io::Result< ServerMessage > {
            let msg_json : serde_json::Value = match serde_json::from_str( msg_json_str ) {
                Ok( msg_json ) => msg_json,
                Err( _ ) => return Err( new_invalid_data_error( "Invalid JSON data." ) )
            };

            if let Some( method_val ) = msg_json.lookup( "method" ) {
                let method = match method_val.as_str( ) {
                    Some( method ) => method,
                    None => return Err( new_invalid_data_error( "Invalid 'method' field, could not parse as String." ) )
                };
                match method {
                    $(
                        $method_name => {
                            let msg_id = match msg_json.lookup( "id" ) {
                                Some( msg_id ) => {
                                    match msg_id.as_i64( ) {
                                        Some( msg_id ) => msg_id,
                                        None => return Err( new_invalid_data_error( "Invalid 'id' field, could not parse as number." ) )
                                    }
                                },
                                None => return Err( new_invalid_data_error( "Missing required 'id' field." ) )
                            };
                            let msg = RequestMessage {
                                id     : msg_id,
                                method : RequestMethod::$method_type $( ( parse_parameters::< $method_param >( &msg_json )? ) )*
                            };
                            Ok( ServerMessage::Request( msg ) )
                        }
                    ),*
                    $(
                        $notif_name => {
                            let notif = NotificationMessage {
                                method : NotificationMethod::$notif_type $( ( parse_parameters::< $notif_param >( &msg_json )? ) )*
                            };
                            Ok( ServerMessage::Notification( notif ) )
                        }
                    ),*
                    _ => Err( new_invalid_data_error( "Invalid request method." ) )
                }
            }
            else {
                return Err( new_invalid_data_error( "Missing required 'method' field." ) );
            }
        }
    };
}

macro_rules! server_responses {
    (
        datas {
            $( $data_type : ident( $data_param : ty ); )*
        },
        errors {
            $( $err_name : ident( $err_val : expr ); )*
        }
    ) => {
        #[derive( Debug )]
        pub enum RequestResponseData {
            $( $data_type ( $data_param ) ),*
        }

        $( pub static $err_name : i64 = $err_val; )*

        impl serde::Serialize for RequestResponseData {

            fn serialize< S >( &self, serializer : &mut S ) -> Result< ( ), S::Error > where S : serde::Serializer {
                match *self {
                    $(
                        RequestResponseData::$data_type( ref param ) => {
                            param.serialize( serializer )
                        }
                    ),*
                }
            }

        }
    }
}

#[derive( Debug )]
pub struct IncomingServerMessage {
    headers : HashMap< String, String >,
    message : ServerMessage
}

#[derive( Debug )]
pub struct OutgoingServerMessage {
    headers : HashMap< String, String >,
    message : ClientMessage
}

#[derive( Debug )]
pub enum ServerMessage {
    Request( RequestMessage ),
    Notification( NotificationMessage )
}

#[derive( Debug )]
pub enum ClientMessage {
    Response( RequestResponseMessage )
}

#[derive( Debug )]
pub struct RequestMessage {
    pub id     : i64,
    pub method : RequestMethod
}

#[derive( Debug )]
pub struct NotificationMessage {
    pub method : NotificationMethod
}

#[derive( Debug, Serialize )]
pub struct RequestResponseError {
    pub code    : i64,
    pub message : String
}

#[derive( Debug )]
pub struct RequestResponseMessage {
    id     : i64,
    result : Option< RequestResponseData >,
    error  : Option< RequestResponseError >
}

server_messages! {
    methods {
        "initialize" => Initialize( InitializeParams );
        "shutdown" => Shutdown;
        "textDocument/completion" => Completion( TextDocumentPositionParams );
        "completionItem/resolve" => CompletionResolve( CompletionItem );
        "textDocument/hover" => Hover( TextDocumentPositionParams );
        "textDocument/signatureHelp" => SignatureHelp( TextDocumentPositionParams );
        "textDocument/definition" => GotoDefinition( TextDocumentPositionParams );
        "textDocument/references" => FindReferences( ReferenceParams );
        "textDocument/documentHighlight" => DocumentHighlights( TextDocumentPositionParams );
        "textDocument/documentSymbol" => DocumentSymbols( DocumentSymbolParams );
        "workspace/symbol" => WorkspaceSymbols( WorkspaceSymbolParams );
        "textDocument/codeAction" => CodeAction( CodeActionParams );
        "textDocument/codeLens" => CodeLens( CodeLensParams );
        "codeLens/resolve" => CodeLensResolve( CodeLens );
        "textDocument/documentLink" => DocumentLink( DocumentLinkParams );
        "documentLink/resolve" => DocumentLinkResolve( DocumentLink );
        "textDocument/formatting" => DocumentFormatting( DocumentFormattingParams );
        "textDocument/rangeFormatting" => DocumentRangeFormatting( DocumentRangeFormattingParams );
        "textDocument/onTypeFormatting" => DocumentOnTypeFormatting( DocumentOnTypeFormattingParams );
        "textDocument/rename" => Rename( RenameParams );
    },
    notifications {
        "exit" => Exit;
        "workspace/didChangeConfiguration" => DidChangeConfiguration( DidChangeConfigurationParams );
        "textDocument/didOpen" => DidOpenTextDocument( DidOpenTextDocumentParams );
        "textDocument/didChange" => DidChangeTextDocument( DidChangeTextDocumentParams );
        "textDocument/didSave" => DidSaveTextDocument( DidSaveTextDocumentParams );
        "textDocument/didClose" => DidCloseTextDocument( DidCloseTextDocumentParams );
        "textDocument/didChangeWatchedFiles" => DidChangeWatchedFiles( DidChangeWatchedFilesParams );
    }
}

server_responses! {
    datas {
        Init( InitializeResult );
        SymbolInfo( Vec< SymbolInformation > );
        CompletionItems( Vec< CompletionItem > );
        WorkspaceEdit( WorkspaceEdit );
        TextEdit( [ TextEdit; 1 ] );
        Locations( Vec< Location > );
        Highlights( Vec< DocumentHighlight > );
        HoverSuccess( Hover );
    },
    errors {
        PARSE_ERROR( -32700 );
        INVALID_REQUEST( -32600 );
        METHOD_NOT_FOUND( -32601 );
        INVALID_PARAMS( -32602 );
        INTERNAL_ERROR( -32603 );
        SERVER_ERROR_START( -32099 );
        SERVER_ERROR_END( -32000 );
        SERVER_NOT_INITIALIZED( -32002 );
        UNKNOWN_ERROR_CODE( -32001 );
    }
}

fn new_invalid_data_error( error_msg : &'static str ) -> io::Error {
    io::Error::new( io::ErrorKind::InvalidData, error_msg )
}

fn parse_parameters< T >( msg_json : &serde_json::Value ) -> io::Result< T > where T : serde::Deserialize {
    let params = match msg_json.lookup( "params" ) {
        Some( params ) => params.to_owned( ),
        None => return Err( new_invalid_data_error( "Missing required 'params' field." ) )
    };

    match serde_json::from_value( params ) {
        Ok( value ) => Ok( value ),
        Err( _ ) => Err( new_invalid_data_error( "Unable to parse parameter field." ) )
    }
}

fn easybuf_to_utf8( buf : &EasyBuf ) -> io::Result< &str > {
    match str::from_utf8( buf.as_ref( ) ) {
        Ok( s ) => Ok( s ),
        Err( _ ) => Err( new_invalid_data_error( "Unable to parse bytes as UTF-8." ) )
    }
}

enum RLSCodecState {
    Headers,
    Body
}

pub struct RLSCodec {
    codec_state    : RLSCodecState,
    headers        : HashMap< String, String >,
    content_length : usize
}

impl RLSCodec {

    pub fn new( ) -> Self {
        RLSCodec {
            codec_state    : RLSCodecState::Headers,
            headers        : HashMap::new( ),
            content_length : 0
        }
    }

    fn read_header( &mut self, buf : &mut EasyBuf ) -> io::Result< bool > {
        if let Some( pos ) = buf.as_ref( ).windows( 2 ).position( | bytes | bytes == b"\r\n" ) {
            let header_bytes = buf.drain_to( pos );
            buf.drain_to( 2 );

            if pos == 0 {
                self.content_length = self.parse_content_length( )?;
                self.codec_state    = RLSCodecState::Body;

                trace!( "Finished parsing headers. Waiting for '{}' bytes for body.", self.content_length );
            }
            else {
                let header_str = easybuf_to_utf8( &header_bytes )?;
                trace!( "Received header line: {}", header_str );

                let mut header_parts = header_str.split( ": " );

                if header_parts.clone( ).count( ) != 2 {
                    return Err( new_invalid_data_error( "Unable to parse invalid header." ) );
                }

                let header_key = header_parts.next( ).unwrap( );
                let header_val = header_parts.next( ).unwrap( );

                self.headers.insert( header_key.to_string( ), header_val.to_string( ) );
            }
            Ok( true )
        }
        else {
            Ok( false )
        }
    }

    fn parse_content_length( &self ) -> io::Result< usize > {
        if let Some( content_length_str ) = self.headers.get( "Content-Length" ) {
            if let Ok( content_length ) = content_length_str.parse::< usize >( ) {
                Ok( content_length )
            }
            else {
                Err( new_invalid_data_error( "Unable to parse 'Content-Length' header into usize." ) )
            }
        }
        else {
            Err( new_invalid_data_error( "Missing required 'Content-Length' header." ) )
        }
    }

    fn reset_codec( &mut self ) -> HashMap< String, String > {
        let mut new_headers = HashMap::new( );
        mem::swap( &mut self.headers, &mut new_headers );

        self.codec_state = RLSCodecState::Headers;

        new_headers
    }

    fn parse_body_contents( &mut self, buf : &mut EasyBuf ) -> io::Result< Option< IncomingServerMessage > > {
        if buf.len( ) < self.content_length {
            return Ok( None );
        }

        let body_bytes = buf.drain_to( self.content_length );
        let body_str   = easybuf_to_utf8( &body_bytes )?;
        trace!( "Received body contents: {}", body_str );

        let message = parse_server_message( body_str )?;
        trace!( "Parsed server message: {:?}", message );

        let headers = self.reset_codec( );

        Ok( Some( IncomingServerMessage{
            headers : headers,
            message : message
        } ) )
    }

}

impl Codec for RLSCodec {

    type In  = IncomingServerMessage;
    type Out = OutgoingServerMessage;

    fn decode( &mut self, buf : &mut EasyBuf ) -> io::Result< Option< Self::In > > {
        loop {
            match self.codec_state {
                RLSCodecState::Headers => {
                    if !self.read_header( buf )? {
                        return Ok( None );
                    }
                },
                RLSCodecState::Body => {
                    return self.parse_body_contents( buf );
                }
            }
        }
    }

    fn encode( &mut self, msg : OutgoingServerMessage, buffer : &mut Vec< u8 > ) -> io::Result< ( ) > {
        let OutgoingServerMessage{ mut headers, message } = msg;

        let msg_json = message.into_json( );
        headers.insert( "Content-Length".to_string( ), msg_json.as_bytes( ).len( ).to_string( ) );
        headers.insert( "Content-Type".to_string( ), "application/vscode-jsonrpc; charset=utf8".to_string( ) );

        for ( ref key, ref val ) in headers {
            trace!( "Sending header: {} = {}", key, val );

            buffer.extend_from_slice( key.as_bytes( ) );
            buffer.extend_from_slice( b": " );
            buffer.extend_from_slice( val.as_bytes( ) );
            buffer.extend_from_slice( b"\r\n" );
        }
        buffer.extend_from_slice( b"\r\n" );

        trace!( "Sending body: {}", msg_json );
        buffer.extend_from_slice( msg_json.as_bytes( ) );

        Ok( ( ) )
    }
}

impl ClientMessage {

    fn into_json( self ) -> String {
        match self {
            ClientMessage::Response( value ) => {

                #[derive( Serialize )]
                struct ResponseMessage {
                    jsonrpc : &'static str,
                    id      : i64,
                    result  : Option< RequestResponseData >,
                    error   : Option< RequestResponseError >
                }

                serde_json::to_string( &ResponseMessage {
                    jsonrpc : "2.0",
                    id      : value.id,
                    result  : value.result,
                    error   : value.error
                } ).unwrap( )
            }
        }
    }

}<commit_msg>Change to use predefined constants for matching method names.<commit_after>
#![allow( non_upper_case_globals )]

use languageserver_types::*;
use serde;
use serde_json;
use std::{
    io,
    mem,
    str
};
use std::collections::{
    HashMap
};
use tokio_core::io::{
    Codec,
    EasyBuf
};

macro_rules! server_messages {
    (
        methods {
            $( $method_name : ident => $method_type : ident $( ( $method_param : ty ) )*; )*
        },
        notifications {
            $( $notif_name : ident => $notif_type : ident $( ( $notif_param : ty ) )*; )*
        }
    ) => {
        #[derive( Debug )]
        pub enum RequestMethod {
            $( $method_type $( ( $method_param ) )*, )*
        }

        #[derive( Debug )]
        pub enum NotificationMethod {
            $( $notif_type $( ( $notif_param ) )*, )*
        }

        pub fn parse_server_message( msg_json_str : &str ) -> io::Result< ServerMessage > {
            let msg_json : serde_json::Value = match serde_json::from_str( msg_json_str ) {
                Ok( msg_json ) => msg_json,
                Err( _ ) => return Err( new_invalid_data_error( "Invalid JSON data." ) )
            };

            if let Some( method_val ) = msg_json.lookup( "method" ) {
                let method = match method_val.as_str( ) {
                    Some( method ) => method,
                    None => return Err( new_invalid_data_error( "Invalid 'method' field, could not parse as String." ) )
                };
                match method {
                    $(
                        $method_name => {
                            let msg_id = match msg_json.lookup( "id" ) {
                                Some( msg_id ) => {
                                    match msg_id.as_i64( ) {
                                        Some( msg_id ) => msg_id,
                                        None => return Err( new_invalid_data_error( "Invalid 'id' field, could not parse as number." ) )
                                    }
                                },
                                None => return Err( new_invalid_data_error( "Missing required 'id' field." ) )
                            };
                            let msg = RequestMessage {
                                id     : msg_id,
                                method : RequestMethod::$method_type $( ( parse_parameters::< $method_param >( &msg_json )? ) )*
                            };
                            Ok( ServerMessage::Request( msg ) )
                        }
                    ),*
                    $(
                        $notif_name => {
                            let notif = NotificationMessage {
                                method : NotificationMethod::$notif_type $( ( parse_parameters::< $notif_param >( &msg_json )? ) )*
                            };
                            Ok( ServerMessage::Notification( notif ) )
                        }
                    ),*
                    _ => Err( new_invalid_data_error( "Invalid request method." ) )
                }
            }
            else {
                return Err( new_invalid_data_error( "Missing required 'method' field." ) );
            }
        }
    };
}

macro_rules! server_responses {
    (
        datas {
            $( $data_type : ident( $data_param : ty ); )*
        },
        errors {
            $( $err_name : ident( $err_val : expr ); )*
        }
    ) => {
        #[derive( Debug )]
        pub enum RequestResponseData {
            $( $data_type ( $data_param ) ),*
        }

        $( pub static $err_name : i64 = $err_val; )*

        impl serde::Serialize for RequestResponseData {

            fn serialize< S >( &self, serializer : &mut S ) -> Result< ( ), S::Error > where S : serde::Serializer {
                match *self {
                    $(
                        RequestResponseData::$data_type( ref param ) => {
                            param.serialize( serializer )
                        }
                    ),*
                }
            }

        }
    }
}

#[derive( Debug )]
pub struct IncomingServerMessage {
    headers : HashMap< String, String >,
    message : ServerMessage
}

#[derive( Debug )]
pub struct OutgoingServerMessage {
    headers : HashMap< String, String >,
    message : ClientMessage
}

#[derive( Debug )]
pub enum ServerMessage {
    Request( RequestMessage ),
    Notification( NotificationMessage )
}

#[derive( Debug )]
pub enum ClientMessage {
    Response( RequestResponseMessage )
}

#[derive( Debug )]
pub struct RequestMessage {
    pub id     : i64,
    pub method : RequestMethod
}

#[derive( Debug )]
pub struct NotificationMessage {
    pub method : NotificationMethod
}

#[derive( Debug, Serialize )]
pub struct RequestResponseError {
    pub code    : i64,
    pub message : String
}

#[derive( Debug )]
pub struct RequestResponseMessage {
    id     : i64,
    result : Option< RequestResponseData >,
    error  : Option< RequestResponseError >
}

server_messages! {
    methods {
        REQUEST__Initialize                        => Initialize( InitializeParams );
        REQUEST__Shutdown                          => Shutdown;
        REQUEST__Completion                        => Completion( TextDocumentPositionParams );
        REQUEST__ResolveCompletionItem             => CompletionResolve( CompletionItem );
        REQUEST__Hover                             => Hover( TextDocumentPositionParams );
        REQUEST__SignatureHelp                     => SignatureHelp( TextDocumentPositionParams );
        REQUEST__GotoDefinition                    => GotoDefinition( TextDocumentPositionParams );
        REQUEST__References                        => FindReferences( ReferenceParams );
        REQUEST__DocumentHighlight                 => DocumentHighlights( TextDocumentPositionParams );
        REQUEST__DocumentSymbols                   => DocumentSymbols( DocumentSymbolParams );
        REQUEST__WorkspaceSymbols                  => WorkspaceSymbols( WorkspaceSymbolParams );
        REQUEST__CodeAction                        => CodeAction( CodeActionParams );
        REQUEST__CodeLens                          => CodeLens( CodeLensParams );
        REQUEST__CodeLensResolve                   => CodeLensResolve( CodeLens );
        REQUEST__DocumentLink                      => DocumentLink( DocumentLinkParams );
        REQUEST__DocumentLinkResolve               => DocumentLinkResolve( DocumentLink );
        REQUEST__Formatting                        => DocumentFormatting( DocumentFormattingParams );
        REQUEST__RangeFormatting                   => DocumentRangeFormatting( DocumentRangeFormattingParams );
        REQUEST__OnTypeFormatting                  => DocumentOnTypeFormatting( DocumentOnTypeFormattingParams );
        REQUEST__Rename                            => Rename( RenameParams );
    },
    notifications {
        NOTIFICATION__Cancel                       => Cancel( CancelParams );
        NOTIFICATION__Exit                         => Exit;
        NOTIFICATION__WorkspaceChangeConfiguration => DidChangeConfiguration( DidChangeConfigurationParams );
        NOTIFICATION__DidOpenTextDocument          => DidOpenTextDocument( DidOpenTextDocumentParams );
        NOTIFICATION__DidChangeTextDocument        => DidChangeTextDocument( DidChangeTextDocumentParams );
        NOTIFICATION__DidCloseTextDocument         => DidCloseTextDocument( DidCloseTextDocumentParams );
        NOTIFICATION__DidSaveTextDocument          => DidSaveTextDocument( DidSaveTextDocumentParams );
        NOTIFICATION__DidChangeWatchedFiles        => DidChangeWatchedFiles( DidChangeWatchedFilesParams );
    }
}

server_responses! {
    datas {
        Init( InitializeResult );
        SymbolInfo( Vec< SymbolInformation > );
        CompletionItems( Vec< CompletionItem > );
        WorkspaceEdit( WorkspaceEdit );
        TextEdit( [ TextEdit; 1 ] );
        Locations( Vec< Location > );
        Highlights( Vec< DocumentHighlight > );
        HoverSuccess( Hover );
    },
    errors {
        PARSE_ERROR( -32700 );
        INVALID_REQUEST( -32600 );
        METHOD_NOT_FOUND( -32601 );
        INVALID_PARAMS( -32602 );
        INTERNAL_ERROR( -32603 );
        SERVER_ERROR_START( -32099 );
        SERVER_ERROR_END( -32000 );
        SERVER_NOT_INITIALIZED( -32002 );
        UNKNOWN_ERROR_CODE( -32001 );
    }
}

fn new_invalid_data_error( error_msg : &'static str ) -> io::Error {
    io::Error::new( io::ErrorKind::InvalidData, error_msg )
}

fn parse_parameters< T >( msg_json : &serde_json::Value ) -> io::Result< T > where T : serde::Deserialize {
    let params = match msg_json.lookup( "params" ) {
        Some( params ) => params.to_owned( ),
        None => return Err( new_invalid_data_error( "Missing required 'params' field." ) )
    };

    match serde_json::from_value( params ) {
        Ok( value ) => Ok( value ),
        Err( _ ) => Err( new_invalid_data_error( "Unable to parse parameter field." ) )
    }
}

fn easybuf_to_utf8( buf : &EasyBuf ) -> io::Result< &str > {
    match str::from_utf8( buf.as_ref( ) ) {
        Ok( s ) => Ok( s ),
        Err( _ ) => Err( new_invalid_data_error( "Unable to parse bytes as UTF-8." ) )
    }
}

enum RLSCodecState {
    Headers,
    Body
}

pub struct RLSCodec {
    codec_state    : RLSCodecState,
    headers        : HashMap< String, String >,
    content_length : usize
}

impl RLSCodec {

    pub fn new( ) -> Self {
        RLSCodec {
            codec_state    : RLSCodecState::Headers,
            headers        : HashMap::new( ),
            content_length : 0
        }
    }

    fn read_header( &mut self, buf : &mut EasyBuf ) -> io::Result< bool > {
        if let Some( pos ) = buf.as_ref( ).windows( 2 ).position( | bytes | bytes == b"\r\n" ) {
            let header_bytes = buf.drain_to( pos );
            buf.drain_to( 2 );

            if pos == 0 {
                self.content_length = self.parse_content_length( )?;
                self.codec_state    = RLSCodecState::Body;

                trace!( "Finished parsing headers. Waiting for '{}' bytes for body.", self.content_length );
            }
            else {
                let header_str = easybuf_to_utf8( &header_bytes )?;
                trace!( "Received header line: {}", header_str );

                let mut header_parts = header_str.split( ": " );

                if header_parts.clone( ).count( ) != 2 {
                    return Err( new_invalid_data_error( "Unable to parse invalid header." ) );
                }

                let header_key = header_parts.next( ).unwrap( );
                let header_val = header_parts.next( ).unwrap( );

                self.headers.insert( header_key.to_string( ), header_val.to_string( ) );
            }
            Ok( true )
        }
        else {
            Ok( false )
        }
    }

    fn parse_content_length( &self ) -> io::Result< usize > {
        if let Some( content_length_str ) = self.headers.get( "Content-Length" ) {
            if let Ok( content_length ) = content_length_str.parse::< usize >( ) {
                Ok( content_length )
            }
            else {
                Err( new_invalid_data_error( "Unable to parse 'Content-Length' header into usize." ) )
            }
        }
        else {
            Err( new_invalid_data_error( "Missing required 'Content-Length' header." ) )
        }
    }

    fn reset_codec( &mut self ) -> HashMap< String, String > {
        let mut new_headers = HashMap::new( );
        mem::swap( &mut self.headers, &mut new_headers );

        self.codec_state = RLSCodecState::Headers;

        new_headers
    }

    fn parse_body_contents( &mut self, buf : &mut EasyBuf ) -> io::Result< Option< IncomingServerMessage > > {
        if buf.len( ) < self.content_length {
            return Ok( None );
        }

        let body_bytes = buf.drain_to( self.content_length );
        let body_str   = easybuf_to_utf8( &body_bytes )?;
        trace!( "Received body contents: {}", body_str );

        let message = parse_server_message( body_str )?;
        trace!( "Parsed server message: {:?}", message );

        let headers = self.reset_codec( );

        Ok( Some( IncomingServerMessage{
            headers : headers,
            message : message
        } ) )
    }

}

impl Codec for RLSCodec {

    type In  = IncomingServerMessage;
    type Out = OutgoingServerMessage;

    fn decode( &mut self, buf : &mut EasyBuf ) -> io::Result< Option< Self::In > > {
        loop {
            match self.codec_state {
                RLSCodecState::Headers => {
                    if !self.read_header( buf )? {
                        return Ok( None );
                    }
                },
                RLSCodecState::Body => {
                    return self.parse_body_contents( buf );
                }
            }
        }
    }

    fn encode( &mut self, msg : OutgoingServerMessage, buffer : &mut Vec< u8 > ) -> io::Result< ( ) > {
        let OutgoingServerMessage{ mut headers, message } = msg;

        let msg_json = message.into_json( );
        headers.insert( "Content-Length".to_string( ), msg_json.as_bytes( ).len( ).to_string( ) );
        headers.insert( "Content-Type".to_string( ), "application/vscode-jsonrpc; charset=utf8".to_string( ) );

        for ( ref key, ref val ) in headers {
            trace!( "Sending header: {} = {}", key, val );

            buffer.extend_from_slice( key.as_bytes( ) );
            buffer.extend_from_slice( b": " );
            buffer.extend_from_slice( val.as_bytes( ) );
            buffer.extend_from_slice( b"\r\n" );
        }
        buffer.extend_from_slice( b"\r\n" );

        trace!( "Sending body: {}", msg_json );
        buffer.extend_from_slice( msg_json.as_bytes( ) );

        Ok( ( ) )
    }
}

impl ClientMessage {

    fn into_json( self ) -> String {
        match self {
            ClientMessage::Response( value ) => {

                #[derive( Serialize )]
                struct ResponseMessage {
                    jsonrpc : &'static str,
                    id      : i64,
                    result  : Option< RequestResponseData >,
                    error   : Option< RequestResponseError >
                }

                serde_json::to_string( &ResponseMessage {
                    jsonrpc : "2.0",
                    id      : value.id,
                    result  : value.result,
                    error   : value.error
                } ).unwrap( )
            }
        }
    }

}<|endoftext|>