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

use serde::de::{self, Deserialize, Deserializer, Visitor, MapAccess};

pub type MemberType = String;
pub type CallbackPtr = usize;
pub type MemberSpawner = fn() -> Box<super::traits::UiControl>;

pub const ID: &str = "id";
pub const TYPE: &str = "type";
pub const CHILD: &str = "child";
pub const CHILDREN: &str = "children";

const FIELDS: &[&str] = &[ID, TYPE];

pub const MEMBER_TYPE_LINEAR_LAYOUT: &str = "LinearLayout";
pub const MEMBER_TYPE_BUTTON: &str = "Button";

pub struct MarkupRegistry {
	spawners: HashMap<MemberType, MemberSpawner>,
	ids: HashMap<String, super::ids::Id>,
	bindings: HashMap<String, CallbackPtr>,
}

impl MarkupRegistry {
	pub fn new() -> MarkupRegistry {
		MarkupRegistry {
			spawners: HashMap::new(),
			ids: HashMap::new(),
			bindings: HashMap::new(),
		}
	}

	pub fn register_member(&mut self, member_type: MemberType, member_spawner: MemberSpawner) -> Result<(), MarkupError> {
		if self.spawners.get(&member_type).is_none() {
			self.spawners.insert(member_type, member_spawner);
			Ok(())
		} else {
			Err(MarkupError::MemberAlreadyRegistered)
		}
	}
	pub fn unregister_member(&mut self, member_type: &MemberType) -> Result<(), MarkupError> {
		if self.spawners.remove(member_type).is_none() {
			Err(MarkupError::MemberNotFound)
		} else {
			Ok(())
		}
	}
	pub fn member(&self, member_type: &MemberType) -> Result<&MemberSpawner, MarkupError> {
		self.spawners.get(member_type).ok_or(MarkupError::MemberNotFound)
	}

	pub fn bind_callback(&mut self, name: &str, callback: CallbackPtr) -> Result<(), MarkupError> {
		if self.bindings.get(name).is_none() {
			self.bindings.insert(name.into(), callback);
			Ok(())
		} else {
			Err(MarkupError::CallbackAlreadyBinded)
		}
	}
	pub fn unbind_callback(&mut self, name: &str) -> Result<(), MarkupError> {
		if self.bindings.remove(name).is_none() {
			Err(MarkupError::CallbackNotFound)
		} else {
			Ok(())
		}
	}
	pub fn callback(&self, name: &str) -> Result<&CallbackPtr, MarkupError> {
		self.bindings.get(name).ok_or(MarkupError::CallbackNotFound)
	}

	pub fn store_id(&mut self, control_id: &str, generated_id: super::ids::Id) -> Result<(), MarkupError> {
		if self.ids.get(control_id).is_none() {
			self.ids.insert(control_id.into(), generated_id);
			Ok(())
		} else {
			Err(MarkupError::IdAlreadyExists)
		}
	}
	pub fn remove_id(&mut self, control_id: &str) -> Result<(), MarkupError> {
		if self.ids.remove(control_id).is_none() {
			Err(MarkupError::IdNotFound)
		} else {
			Ok(())
		}
	}
	pub fn id(&self, control_id: &str) -> Result<&super::ids::Id, MarkupError> {
		self.ids.get(control_id).ok_or(MarkupError::IdNotFound)
	}
}

#[derive(Debug, Clone)]
pub enum MarkupError {
	MemberNotFound,
	MemberAlreadyRegistered,
	CallbackNotFound,
	CallbackAlreadyBinded,
	IdNotFound,
	IdAlreadyExists,
}

#[derive(Debug, Clone)]
pub struct Markup {
	pub id: Option<String>,
	pub member_type: MemberType,
	pub attributes: HashMap<String, MarkupNode>
}

#[derive(Debug, Clone)]
pub enum MarkupNode {
	Attribute(String),
	Child(Markup),
	Children(Vec<Markup>),
}

impl MarkupNode {
	pub fn as_attribute(&self) -> &str {
		match *self {
			MarkupNode::Attribute(ref attr) => attr.as_str(),
			_ => panic!("MarkupNode is not an Attribute: {:?}", self),
		}
	}
	pub fn as_child(&self) -> &Markup {
		match *self {
			MarkupNode::Child(ref markup) => markup,
			_ => panic!("MarkupNode is not a Child Markup: {:?}", self),
		}
	}
	pub fn as_children(&self) -> &[Markup] {
		match *self {
			MarkupNode::Children(ref children) => children.as_slice(),
			_ => panic!("MarkupNode is not the Children Markups: {:?}", self),
		}
	}
}

impl <'de> Deserialize<'de> for Markup {
	fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: Deserializer<'de> {
		deserializer.deserialize_struct("Markup", FIELDS, MarkupVisitor)
	}
}

struct MarkupVisitor;

impl<'de> Visitor<'de> for MarkupVisitor {
    type Value = Markup;

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

    fn visit_map<V>(self, mut map: V) -> Result<Markup, V::Error> where V: MapAccess<'de> {
        let mut id = None;
        let mut member_type = None;
        let mut child_found = false;

        let mut attributes = HashMap::new();

        while let Some(key) = map.next_key()? {
        	println!("{} found", key);

            match key {
                TYPE => {
                    if member_type.is_some() {
                        return Err(de::Error::duplicate_field(TYPE));
                    }
                    member_type = Some(map.next_value()?);
                },
                ID => {
                    if id.is_some() {
                        return Err(de::Error::duplicate_field(ID));
                    }
                    id = Some(map.next_value()?);
                },
                CHILD => {
                	if child_found {
	                	return Err(de::Error::duplicate_field("child / children"));
                	} else {
	                	attributes.insert(key.into(), MarkupNode::Child(map.next_value::<Markup>()?));
	                	child_found = true;
                	}
                },
                CHILDREN => {
                	if child_found {
	                	return Err(de::Error::duplicate_field("child / children"));
                	} else {
	                	attributes.insert(key.into(), MarkupNode::Children(map.next_value::<Vec<Markup>>()?));
	                	child_found = true;
                	}
                }
                _ => {
                	attributes.insert(key.into(), MarkupNode::Attribute(map.next_value::<String>()?));
                },
            }
        }
        Ok(Markup {
	        id: id,
	        member_type: member_type.ok_or_else(|| de::Error::missing_field(TYPE))?,
	        attributes: attributes,
        })
    }
}

pub fn parse_markup(json: &str, registry: &mut MarkupRegistry) -> Box<super::traits::UiControl> {
	let markup: Markup = super::serde_json::from_str(json).unwrap();

	let mut control = registry.member(&markup.member_type).unwrap()();
	control.fill_from_markup(&markup, registry);
	control
}

#[macro_export]
macro_rules! bind_markup_callback {
	($reg: ident, $cb: ident) => {
		registry.bind_callback(stringify!($cb), $cb as CallbackPtr).unwrap();
	}
}
#[macro_export]
macro_rules! fill_from_markup_base {
	($this: expr, $mrk: ident, $reg: ident, $typ:ty, [$($arg:ident),+]) => {
		if !&[$($arg),+].contains(&$mrk.member_type.as_str()) {
			match $mrk.id {
				Some(ref id) => panic!("Markup does not belong to {}: {} ({})", stringify!($typ), $mrk.member_type, id),
				None => panic!("Markup does not belong to {}: {}", stringify!($typ), $mrk.member_type),
			}
		}
    	if let Some(ref id) = $mrk.id {
    		$reg.store_id(&id, $this.id()).unwrap();
    	}
	}
}
#[macro_export]
macro_rules! fill_from_markup_label {
	($this: expr, $mrk: ident) => {
		$this.set_label(&$mrk.attributes.get("label").unwrap().as_attribute());
	}
}
#[macro_export]
macro_rules! fill_from_markup_callbacks {
	($this: expr, $mrk: ident, $reg: ident, [$($cbname:expr => $cbtyp:ty),+]) => {
		$(if let Some(callback) = $mrk.attributes.get($cbname) {
    		let callback = $reg.callback(callback.as_attribute()).unwrap();
    		$this.on_left_click(Some(Box::new(unsafe {
    			let callback: $cbtyp = mem::transmute(*callback);
    			callback
    		})));
    	})+
	}
}
#[macro_export]
macro_rules! fill_from_markup_children {
	($this: expr, $mrk: ident, $reg: ident) => {
		for child_markup in $mrk.attributes.get(::plygui_api::markup::CHILDREN).unwrap_or(&::plygui_api::markup::MarkupNode::Children(vec![])).as_children() {
    		let mut child = $reg.member(&child_markup.member_type).unwrap()();
    		child.fill_from_markup(child_markup, $reg);
			$this.push_child(child);
		}
	}
}<commit_msg>Closure callbacks (experimental!)<commit_after>use std::fmt;
use std::collections::HashMap;

use serde::de::{self, Deserialize, Deserializer, Visitor, MapAccess};

pub type MemberType = String;
pub type CallbackPtr = usize;
pub type MemberSpawner = fn() -> Box<super::traits::UiControl>;

pub const ID: &str = "id";
pub const TYPE: &str = "type";
pub const CHILD: &str = "child";
pub const CHILDREN: &str = "children";

const FIELDS: &[&str] = &[ID, TYPE];

pub const MEMBER_TYPE_LINEAR_LAYOUT: &str = "LinearLayout";
pub const MEMBER_TYPE_BUTTON: &str = "Button";

pub struct MarkupRegistry {
	spawners: HashMap<MemberType, MemberSpawner>,
	ids: HashMap<String, super::ids::Id>,
	bindings: HashMap<String, CallbackPtr>,
}

impl MarkupRegistry {
	pub fn new() -> MarkupRegistry {
		MarkupRegistry {
			spawners: HashMap::new(),
			ids: HashMap::new(),
			bindings: HashMap::new(),
		}
	}

	pub fn register_member(&mut self, member_type: MemberType, member_spawner: MemberSpawner) -> Result<(), MarkupError> {
		if self.spawners.get(&member_type).is_none() {
			self.spawners.insert(member_type, member_spawner);
			Ok(())
		} else {
			Err(MarkupError::MemberAlreadyRegistered)
		}
	}
	pub fn unregister_member(&mut self, member_type: &MemberType) -> Result<(), MarkupError> {
		if self.spawners.remove(member_type).is_none() {
			Err(MarkupError::MemberNotFound)
		} else {
			Ok(())
		}
	}
	pub fn member(&self, member_type: &MemberType) -> Result<&MemberSpawner, MarkupError> {
		self.spawners.get(member_type).ok_or(MarkupError::MemberNotFound)
	}

	pub fn bind_callback(&mut self, name: &str, callback: CallbackPtr) -> Result<(), MarkupError> {
		if self.bindings.get(name).is_none() {
			self.bindings.insert(name.into(), callback);
			Ok(())
		} else {
			Err(MarkupError::CallbackAlreadyBinded)
		}
	}
	pub fn unbind_callback(&mut self, name: &str) -> Result<(), MarkupError> {
		if self.bindings.remove(name).is_none() {
			Err(MarkupError::CallbackNotFound)
		} else {
			Ok(())
		}
	}
	pub fn callback(&self, name: &str) -> Result<&CallbackPtr, MarkupError> {
		self.bindings.get(name).ok_or(MarkupError::CallbackNotFound)
	}

	pub fn store_id(&mut self, control_id: &str, generated_id: super::ids::Id) -> Result<(), MarkupError> {
		if self.ids.get(control_id).is_none() {
			self.ids.insert(control_id.into(), generated_id);
			Ok(())
		} else {
			Err(MarkupError::IdAlreadyExists)
		}
	}
	pub fn remove_id(&mut self, control_id: &str) -> Result<(), MarkupError> {
		if self.ids.remove(control_id).is_none() {
			Err(MarkupError::IdNotFound)
		} else {
			Ok(())
		}
	}
	pub fn id(&self, control_id: &str) -> Result<&super::ids::Id, MarkupError> {
		self.ids.get(control_id).ok_or(MarkupError::IdNotFound)
	}
}

#[derive(Debug, Clone)]
pub enum MarkupError {
	MemberNotFound,
	MemberAlreadyRegistered,
	CallbackNotFound,
	CallbackAlreadyBinded,
	IdNotFound,
	IdAlreadyExists,
}

#[derive(Debug, Clone)]
pub struct Markup {
	pub id: Option<String>,
	pub member_type: MemberType,
	pub attributes: HashMap<String, MarkupNode>
}

#[derive(Debug, Clone)]
pub enum MarkupNode {
	Attribute(String),
	Child(Markup),
	Children(Vec<Markup>),
}

impl MarkupNode {
	pub fn as_attribute(&self) -> &str {
		match *self {
			MarkupNode::Attribute(ref attr) => attr.as_str(),
			_ => panic!("MarkupNode is not an Attribute: {:?}", self),
		}
	}
	pub fn as_child(&self) -> &Markup {
		match *self {
			MarkupNode::Child(ref markup) => markup,
			_ => panic!("MarkupNode is not a Child Markup: {:?}", self),
		}
	}
	pub fn as_children(&self) -> &[Markup] {
		match *self {
			MarkupNode::Children(ref children) => children.as_slice(),
			_ => panic!("MarkupNode is not the Children Markups: {:?}", self),
		}
	}
}

impl <'de> Deserialize<'de> for Markup {
	fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: Deserializer<'de> {
		deserializer.deserialize_struct("Markup", FIELDS, MarkupVisitor)
	}
}

struct MarkupVisitor;

impl<'de> Visitor<'de> for MarkupVisitor {
    type Value = Markup;

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

    fn visit_map<V>(self, mut map: V) -> Result<Markup, V::Error> where V: MapAccess<'de> {
        let mut id = None;
        let mut member_type = None;
        let mut child_found = false;

        let mut attributes = HashMap::new();

        while let Some(key) = map.next_key()? {
        	println!("{} found", key);

            match key {
                TYPE => {
                    if member_type.is_some() {
                        return Err(de::Error::duplicate_field(TYPE));
                    }
                    member_type = Some(map.next_value()?);
                },
                ID => {
                    if id.is_some() {
                        return Err(de::Error::duplicate_field(ID));
                    }
                    id = Some(map.next_value()?);
                },
                CHILD => {
                	if child_found {
	                	return Err(de::Error::duplicate_field("child / children"));
                	} else {
	                	attributes.insert(key.into(), MarkupNode::Child(map.next_value::<Markup>()?));
	                	child_found = true;
                	}
                },
                CHILDREN => {
                	if child_found {
	                	return Err(de::Error::duplicate_field("child / children"));
                	} else {
	                	attributes.insert(key.into(), MarkupNode::Children(map.next_value::<Vec<Markup>>()?));
	                	child_found = true;
                	}
                }
                _ => {
                	attributes.insert(key.into(), MarkupNode::Attribute(map.next_value::<String>()?));
                },
            }
        }
        Ok(Markup {
	        id: id,
	        member_type: member_type.ok_or_else(|| de::Error::missing_field(TYPE))?,
	        attributes: attributes,
        })
    }
}

pub fn parse_markup(json: &str, registry: &mut MarkupRegistry) -> Box<super::traits::UiControl> {
	let markup: Markup = super::serde_json::from_str(json).unwrap();

	let mut control = registry.member(&markup.member_type).unwrap()();
	control.fill_from_markup(&markup, registry);
	control
}

#[macro_export]
macro_rules! bind_markup_callback {
	($reg: ident, $cb: ident) => {
		registry.bind_callback(stringify!($cb), $cb as CallbackPtr).unwrap();
	}
}
#[macro_export]
macro_rules! fill_from_markup_base {
	($this: expr, $mrk: ident, $reg: ident, $typ:ty, [$($arg:ident),+]) => {
		if !&[$($arg),+].contains(&$mrk.member_type.as_str()) {
			match $mrk.id {
				Some(ref id) => panic!("Markup does not belong to {}: {} ({})", stringify!($typ), $mrk.member_type, id),
				None => panic!("Markup does not belong to {}: {}", stringify!($typ), $mrk.member_type),
			}
		}
    	if let Some(ref id) = $mrk.id {
    		$reg.store_id(&id, $this.id()).unwrap();
    	}
	}
}
#[macro_export]
macro_rules! fill_from_markup_label {
	($this: expr, $mrk: ident) => {
		$this.set_label(&$mrk.attributes.get("label").unwrap().as_attribute());
	}
}
#[macro_export]
macro_rules! fill_from_markup_callbacks {
	($this: expr, $mrk: ident, $reg: ident, [$($cbname:expr => $cbtyp:ty),+]) => {
		$(if let Some(callback) = $mrk.attributes.get($cbname) {
    		let callback = $reg.callback(callback.as_attribute()).unwrap();
    		$this.on_left_click(Some(unsafe {
    			let callback: *mut Box<$cbtyp> = mem::transmute(*callback);
    			*Box::from_raw(callback)
    		}));
    	})+
	}
}
#[macro_export]
macro_rules! fill_from_markup_children {
	($this: expr, $mrk: ident, $reg: ident) => {
		for child_markup in $mrk.attributes.get(::plygui_api::markup::CHILDREN).unwrap_or(&::plygui_api::markup::MarkupNode::Children(vec![])).as_children() {
    		let mut child = $reg.member(&child_markup.member_type).unwrap()();
    		child.fill_from_markup(child_markup, $reg);
			$this.push_child(child);
		}
	}
}<|endoftext|>


<commit_before>//! This module exposes an interface for building status bars which can be
//! inserted in the UI either above or below the buffer view.
//!
//! Status bars must `impl` the `StatusBar` trait and define an `update`
//! function that updates their internal state and a `render` function that
//! displays them on the terminal at the given y index.

use std::cmp;
use rustbox::RustBox;

use super::TermUi;
use super::util::{RustBoxExt, LineBuilder};

pub trait StatusBar {
    /// Updates the status bar's state.
    fn update(&mut self, ui: &mut TermUi);

    /// Calculates the height of the bar in the given terminal.
    fn height(&self, ui: &TermUi) -> usize;

    /// Renders the bar at the given position.
    ///
    /// Nothing enforces that the bar actually renders at the given position.
    /// Bars can render anything wherever they like. Happy hacking!
    fn render(&mut self, y: usize, rb: &mut TermUi);
}

pub struct MainBar;

impl StatusBar for MainBar {
    fn update(&mut self, _: &mut TermUi) {
    }

    fn height(&self, _ui: &TermUi) -> usize { 1 }

    fn render(&mut self, y: usize, ui: &mut TermUi) {
        use rustbox::{RB_NORMAL};
        use rustbox::Color::*;
        // use super::util::AlignCol::*;

        let buf = ui.view.buf.borrow();
        let buf_name = buf.name();

        // TODO: Right align scroll display
        let buf_scroll = match ui.view.scroll.clone() {
            Some(_) => format!("{}", ui.view.scroll_height()),
            None => "BOT".to_owned(),
        };

        ui.rb.blank_line(y, RB_NORMAL, Default, Black);

        let mut lb = LineBuilder::new();
        lb.skip(1);
        lb.add_column(buf_name.to_owned()).fgcolor(White).bgcolor(Black);
        lb.skip(1);
        lb.add_column(" | ".to_owned());
        lb.add_column(buf_scroll).fgcolor(White).bgcolor(Black);

        lb.print(y, &mut ui.rb);
    }
}

const ALERT_LIST_MAX_H: usize = 5;

pub struct AlertBar;

impl StatusBar for AlertBar {
    fn update(&mut self, _: &mut TermUi) {
    }

    fn height(&self, ui: &TermUi) -> usize {
        cmp::min(ui.alerts.count(), ALERT_LIST_MAX_H)
    }

    fn render(&mut self, y: usize, ui: &mut TermUi) {
        use rustbox::{RB_NORMAL};
        use rustbox::Color::*;
        // use super::util::AlignCol::*;

        for i in 0..self.height(ui) {
            ui.rb.blank_line(y+i, RB_NORMAL, White, Black);

            let alert = ui.alerts.get(i);
            let mut lb = LineBuilder::new();
            lb.add_column(format!("{}: ", i+1)).fgcolor(White).bgcolor(Black).pad_left(4);
            lb.add_column(alert.msg.clone()).fgcolor(White).bgcolor(Black);

            lb.print(y+i, &mut ui.rb);
        }

        // let mut lb = LineBuilder::new();
        // lb.skip(1);
        // lb.add_column(buf_name.to_owned()).fgcolor(White).bgcolor(Black);
        // lb.skip(1);
        // lb.add_column(" | ".to_owned());
        // lb.add_column(buf_scroll).fgcolor(White).bgcolor(Black);

        // lb.print(y, &mut ui.rb);
    }
}
<commit_msg>Remove unused import<commit_after>//! This module exposes an interface for building status bars which can be
//! inserted in the UI either above or below the buffer view.
//!
//! Status bars must `impl` the `StatusBar` trait and define an `update`
//! function that updates their internal state and a `render` function that
//! displays them on the terminal at the given y index.

use std::cmp;

use super::TermUi;
use super::util::{RustBoxExt, LineBuilder};

pub trait StatusBar {
    /// Updates the status bar's state.
    fn update(&mut self, ui: &mut TermUi);

    /// Calculates the height of the bar in the given terminal.
    fn height(&self, ui: &TermUi) -> usize;

    /// Renders the bar at the given position.
    ///
    /// Nothing enforces that the bar actually renders at the given position.
    /// Bars can render anything wherever they like. Happy hacking!
    fn render(&mut self, y: usize, rb: &mut TermUi);
}

pub struct MainBar;

impl StatusBar for MainBar {
    fn update(&mut self, _: &mut TermUi) {
    }

    fn height(&self, _ui: &TermUi) -> usize { 1 }

    fn render(&mut self, y: usize, ui: &mut TermUi) {
        use rustbox::{RB_NORMAL};
        use rustbox::Color::*;
        // use super::util::AlignCol::*;

        let buf = ui.view.buf.borrow();
        let buf_name = buf.name();

        // TODO: Right align scroll display
        let buf_scroll = match ui.view.scroll.clone() {
            Some(_) => format!("{}", ui.view.scroll_height()),
            None => "BOT".to_owned(),
        };

        ui.rb.blank_line(y, RB_NORMAL, Default, Black);

        let mut lb = LineBuilder::new();
        lb.skip(1);
        lb.add_column(buf_name.to_owned()).fgcolor(White).bgcolor(Black);
        lb.skip(1);
        lb.add_column(" | ".to_owned());
        lb.add_column(buf_scroll).fgcolor(White).bgcolor(Black);

        lb.print(y, &mut ui.rb);
    }
}

const ALERT_LIST_MAX_H: usize = 5;

pub struct AlertBar;

impl StatusBar for AlertBar {
    fn update(&mut self, _: &mut TermUi) {
    }

    fn height(&self, ui: &TermUi) -> usize {
        cmp::min(ui.alerts.count(), ALERT_LIST_MAX_H)
    }

    fn render(&mut self, y: usize, ui: &mut TermUi) {
        use rustbox::{RB_NORMAL};
        use rustbox::Color::*;
        // use super::util::AlignCol::*;

        for i in 0..self.height(ui) {
            ui.rb.blank_line(y+i, RB_NORMAL, White, Black);

            let alert = ui.alerts.get(i);
            let mut lb = LineBuilder::new();
            lb.add_column(format!("{}: ", i+1)).fgcolor(White).bgcolor(Black).pad_left(4);
            lb.add_column(alert.msg.clone()).fgcolor(White).bgcolor(Black);

            lb.print(y+i, &mut ui.rb);
        }

        // let mut lb = LineBuilder::new();
        // lb.skip(1);
        // lb.add_column(buf_name.to_owned()).fgcolor(White).bgcolor(Black);
        // lb.skip(1);
        // lb.add_column(" | ".to_owned());
        // lb.add_column(buf_scroll).fgcolor(White).bgcolor(Black);

        // lb.print(y, &mut ui.rb);
    }
}
<|endoftext|>


<commit_before>extern crate mioco;
extern crate env_logger;
extern crate httparse;

use std::net::SocketAddr;
use std::str::FromStr;
use std::io::{self, Write, Read};
use mioco::net::TcpListener;

const DEFAULT_LISTEN_ADDR : &'static str = "127.0.0.1:5555";

fn listend_addr() -> SocketAddr {
    FromStr::from_str(DEFAULT_LISTEN_ADDR).unwrap()
}

const RESPONSE: &'static str = "HTTP/1.1 200 OK\r
Content-Length: 11\r
\r
Hello World";

const RESPONSE_404: &'static str = "HTTP/1.1 404 Not Found\r
Content-Length: 11\r
\r
Hello World";

fn main() {
    env_logger::init().unwrap();
    let addr = listend_addr();

    let listener = TcpListener::bind(&addr).unwrap();

    println!("Starting mioco http server on {:?}", listener.local_addr().unwrap());

    mioco::spawn(move || {
        let mut joins : Vec<_> = (0..mioco::thread_num()).map(|_| {
            let listener = listener.try_clone().unwrap();
            mioco::spawn(move || -> io::Result<()> {
                loop {
                    let (mut conn, _addr) = listener.accept()?;
                    mioco::spawn(move || -> io::Result<()> {
                        let mut buf_i = 0;
                        let mut buf = [0u8; 1024];

                        let mut headers = [httparse::EMPTY_HEADER; 16];
                        loop {
                            let len = try!(conn.read(&mut buf[buf_i..]));

                            if len == 0 {
                                return Ok(());
                            }

                            buf_i += len;

                            let mut req = httparse::Request::new(&mut headers);
                            let res = req.parse(&buf[0..buf_i]).unwrap();

                            if res.is_complete() {
                                let req_len = res.unwrap();
                                match req.path {
                                    Some(ref _path) => {
                                        let _ = try!(conn.write_all(&RESPONSE.as_bytes()));
                                        if req_len != buf_i {
                                            // request has a body; TODO: handle it
                                        }
                                        buf_i = 0;
                                    },
                                    None => {
                                        let _ = try!(conn.write_all(&RESPONSE_404.as_bytes()));
                                        return Ok(());
                                    }
                                }
                            }
                        }
                    });
                }
            })
        }).collect();

        joins.drain(..).map(|join| join.join().unwrap()).count();
    }).join().unwrap();
}
<commit_msg>Rustfmt http-server<commit_after>extern crate mioco;
extern crate env_logger;
extern crate httparse;

use std::net::SocketAddr;
use std::str::FromStr;
use std::io::{self, Write, Read};
use mioco::net::TcpListener;

const DEFAULT_LISTEN_ADDR: &'static str = "127.0.0.1:5555";

fn listend_addr() -> SocketAddr {
    FromStr::from_str(DEFAULT_LISTEN_ADDR).unwrap()
}

const RESPONSE: &'static str = "HTTP/1.1 200 OK\r
Content-Length: 11\r
\r
Hello World";

const RESPONSE_404: &'static str = "HTTP/1.1 404 Not Found\r
Content-Length: 11\r
\r
Hello World";

fn main() {
    env_logger::init().unwrap();
    let addr = listend_addr();

    let listener = TcpListener::bind(&addr).unwrap();

    println!("Starting mioco http server on {:?}",
             listener.local_addr().unwrap());

    mioco::spawn(move || {
        let mut joins: Vec<_> = (0..mioco::thread_num())
            .map(|_| {
                let listener = listener.try_clone().unwrap();
                mioco::spawn(move || -> io::Result<()> {
                    loop {
                        let (mut conn, _addr) = listener.accept()?;
                        mioco::spawn(move || -> io::Result<()> {
                            let mut buf_i = 0;
                            let mut buf = [0u8; 1024];

                            let mut headers = [httparse::EMPTY_HEADER; 16];
                            loop {
                                let len = try!(conn.read(&mut buf[buf_i..]));

                                if len == 0 {
                                    return Ok(());
                                }

                                buf_i += len;

                                let mut req = httparse::Request::new(&mut headers);
                                let res = req.parse(&buf[0..buf_i]).unwrap();

                                if res.is_complete() {
                                    let req_len = res.unwrap();
                                    match req.path {
                                        Some(ref _path) => {
                                            let _ = try!(conn.write_all(&RESPONSE.as_bytes()));
                                            if req_len != buf_i {
                                                // request has a body; TODO: handle it
                                            }
                                            buf_i = 0;
                                        }
                                        None => {
                                            let _ = try!(conn.write_all(&RESPONSE_404.as_bytes()));
                                            return Ok(());
                                        }
                                    }
                                }
                            }
                        });
                    }
                })
            })
            .collect();

        joins.drain(..).map(|join| join.join().unwrap()).count();
    })
            .join()
            .unwrap();
}
<|endoftext|>


<commit_before>use std::io::Cursor;
use byteorder::{LittleEndian, ReadBytesExt};

const C1: u32 = 0xcc9e2d51;
const C2: u32 = 0x1b873593;
const R1: u32 = 15;
const R2: u32 = 13;
const M: u32 = 5;
const N: u32 = 0xe6546b64;

/// MurmurHash3 (32 bit, seeded)
///
/// # Examples
///
/// ```
/// use murmur3::seeded;
///
/// let murmur32_hash = seeded("abcd".as_bytes(), 1234);
/// assert_eq!(murmur32_hash, 893017187);
/// ```
pub fn seeded(data: &[u8], seed: u32) -> u32 {
    let mut hash = seed;
    let len = data.len();

    for byte_index in (0..len).step_by(4) {
        let remaining_bytes = len - byte_index;
        if remaining_bytes >= 4 {
            let buf = &data[byte_index..byte_index + 4];

            hash = _process_chunk(hash, &buf);

            hash = (hash << R2) | (hash >> (32 - R2));
            hash = (hash.wrapping_mul(M)).wrapping_add(N);

        } else {
            let mut buf = [0u8; 4];
            buf.clone_from_slice(&data[byte_index..len]);

            hash = _process_chunk(hash, &buf);
        }
    }

    hash = hash ^ (len as u32);
    hash = hash ^ (hash >> 16);
    hash = hash.wrapping_mul(0x85ebca6b);
    hash = hash ^ (hash >> 13);
    hash = hash.wrapping_mul(0xC2b2ae35);
    hash = hash ^ (hash >> 16);

    return hash;
}

/// MurmurHash3 (32 bit, unseeded)
///
/// # Examples
///
/// ```
/// use murmur3::unseeded;
///
/// let murmur32_hash = unseeded("abcd".as_bytes());
/// assert_eq!(murmur32_hash, 1139631978);
/// ```
pub fn unseeded(data: &[u8]) -> u32 {
    seeded(data, 0)
}

fn _process_chunk(hash: u32, buf: &[u8]) -> u32 {
    let mut buf_reader = Cursor::new(buf);
    let mut chunk = buf_reader.read_u32::<LittleEndian>().unwrap();

    chunk = chunk.wrapping_mul(C1);
    chunk = (chunk << R1) | (chunk >> (32 - R1));
    chunk = chunk.wrapping_mul(C2);

    hash ^ chunk
}

#[test]
fn seeded_test() {
    let mut hash = seeded("abcdefghabcdefghabcdefghabcdefghabcdefghabcdefghabcdefghabcdefgh".as_bytes(),
                          1234);
    assert_eq!(hash, 1618858773);

    hash = seeded("abcdefgh".as_bytes(), 1234);
    assert_eq!(hash, 4037461305);

    hash = seeded("abcdefg".as_bytes(), 1234);
    assert_eq!(hash, 1113025207);

    hash = seeded("abcdefg".as_bytes(), 5678);
    assert_eq!(hash, 1081589395);

    hash = seeded("abcd".as_bytes(), 1234);
    assert_eq!(hash, 893017187);

    hash = seeded("ab1".as_bytes(), 1234);
    assert_eq!(hash, 672282314);

    hash = seeded("a b".as_bytes(), 1234);
    assert_eq!(hash, 629887092);

    hash = seeded("a".as_bytes(), 1234);
    assert_eq!(hash, 1374314456);

    hash = seeded("".as_bytes(), 1234);
    assert_eq!(hash, 254590987);
}

#[test]
fn unseeded_test() {
    let mut hash = unseeded("abcdefghabcdefghabcdefghabcdefghabcdefghabcdefghabcdefghabcdefgh".as_bytes());
    assert_eq!(hash, 3788670109);

    hash = unseeded("abcdefgh".as_bytes());
    assert_eq!(hash, 1239272644);

    hash = unseeded("abcdefg".as_bytes());
    assert_eq!(hash, 2285673222);

    hash = unseeded("abcd".as_bytes());
    assert_eq!(hash, 1139631978);

    hash = unseeded("ab1".as_bytes());
    assert_eq!(hash, 1110413313);

    hash = unseeded("a b".as_bytes());
    assert_eq!(hash, 1033158525);

    hash = unseeded("a".as_bytes());
    assert_eq!(hash, 1009084850);

    hash = unseeded("".as_bytes());
    assert_eq!(hash, 0);
}
<commit_msg>Automatically handle endiannesss<commit_after>use std::io::Cursor;
use byteorder::{LittleEndian, ReadBytesExt};

const C1: u32 = 0xcc9e2d51;
const C2: u32 = 0x1b873593;
const R1: u32 = 15;
const R2: u32 = 13;
const M: u32 = 5;
const N: u32 = 0xe6546b64;

/// MurmurHash3 (32 bit, seeded)
///
/// # Examples
///
/// ```
/// use murmur3::seeded;
///
/// let murmur32_hash = seeded("abcd".as_bytes(), 1234);
/// assert_eq!(murmur32_hash, 893017187);
/// ```
pub fn seeded(data: &[u8], seed: u32) -> u32 {
    let mut hash = seed;
    let len = data.len();

    for byte_index in (0..len).step_by(4) {
        let remaining_bytes = len - byte_index;
        if remaining_bytes >= 4 {
            let buf = &data[byte_index..byte_index + 4];

            hash = _process_chunk(hash, &buf);

            hash = (hash << R2) | (hash >> (32 - R2));
            hash = (hash.wrapping_mul(M)).wrapping_add(N);

        } else {
            let mut buf = [0u8; 4];
            buf.clone_from_slice(&data[byte_index..len]);

            hash = _process_chunk(hash, &buf);
        }
    }

    hash = hash ^ (len as u32);
    hash = hash ^ (hash >> 16);
    hash = hash.wrapping_mul(0x85ebca6b);
    hash = hash ^ (hash >> 13);
    hash = hash.wrapping_mul(0xC2b2ae35);
    hash = hash ^ (hash >> 16);

    return hash;
}

/// MurmurHash3 (32 bit, unseeded)
///
/// # Examples
///
/// ```
/// use murmur3::unseeded;
///
/// let murmur32_hash = unseeded("abcd".as_bytes());
/// assert_eq!(murmur32_hash, 1139631978);
/// ```
pub fn unseeded(data: &[u8]) -> u32 {
    seeded(data, 0)
}

#[cfg(target_endian="big")]
macro_rules! read_u32 {
    ($buf_reader:expr) => ($buf_reader.read_u32::<BigEndian>().unwrap());
}

#[cfg(target_endian="little")]
macro_rules! read_u32 {
    ($buf_reader:expr) => ($buf_reader.read_u32::<LittleEndian>().unwrap());
}

fn _process_chunk(hash: u32, buf: &[u8]) -> u32 {
    let mut buf_reader = Cursor::new(buf);
    let mut chunk = read_u32!(buf_reader);

    chunk = chunk.wrapping_mul(C1);
    chunk = (chunk << R1) | (chunk >> (32 - R1));
    chunk = chunk.wrapping_mul(C2);

    hash ^ chunk
}

#[test]
fn seeded_test() {
    let mut hash = seeded("abcdefghabcdefghabcdefghabcdefghabcdefghabcdefghabcdefghabcdefgh".as_bytes(),
                          1234);
    assert_eq!(hash, 1618858773);

    hash = seeded("abcdefgh".as_bytes(), 1234);
    assert_eq!(hash, 4037461305);

    hash = seeded("abcdefg".as_bytes(), 1234);
    assert_eq!(hash, 1113025207);

    hash = seeded("abcdefg".as_bytes(), 5678);
    assert_eq!(hash, 1081589395);

    hash = seeded("abcd".as_bytes(), 1234);
    assert_eq!(hash, 893017187);

    hash = seeded("ab1".as_bytes(), 1234);
    assert_eq!(hash, 672282314);

    hash = seeded("a b".as_bytes(), 1234);
    assert_eq!(hash, 629887092);

    hash = seeded("a".as_bytes(), 1234);
    assert_eq!(hash, 1374314456);

    hash = seeded("".as_bytes(), 1234);
    assert_eq!(hash, 254590987);
}

#[test]
fn unseeded_test() {
    let mut hash = unseeded("abcdefghabcdefghabcdefghabcdefghabcdefghabcdefghabcdefghabcdefgh".as_bytes());
    assert_eq!(hash, 3788670109);

    hash = unseeded("abcdefgh".as_bytes());
    assert_eq!(hash, 1239272644);

    hash = unseeded("abcdefg".as_bytes());
    assert_eq!(hash, 2285673222);

    hash = unseeded("abcd".as_bytes());
    assert_eq!(hash, 1139631978);

    hash = unseeded("ab1".as_bytes());
    assert_eq!(hash, 1110413313);

    hash = unseeded("a b".as_bytes());
    assert_eq!(hash, 1033158525);

    hash = unseeded("a".as_bytes());
    assert_eq!(hash, 1009084850);

    hash = unseeded("".as_bytes());
    assert_eq!(hash, 0);
}
<|endoftext|>


<commit_before>use Message;
use state::State;

#[derive(Clone, Debug)]
pub struct Conditions {
    pub timeout: u32,
    pub renew_timeout: Option<u32>,
    pub first_opens: Option<bool>,
    pub last_closes: Option<bool>,
    pub max_size: Option<usize>,
    pub patterns: Vec<String>
}

impl Conditions {
    fn new(timeout: u32) -> Conditions {
        Conditions {
            timeout: timeout,
            renew_timeout: None,
            first_opens: None,
            last_closes: None,
            max_size: None,
            patterns: Vec::new()
        }
    }

    pub fn ignore_message(&self, message: &Message) -> bool {
        !self.patterns.contains(message.uuid()) && self.patterns.len() > 0
    }

    pub fn is_opening(&self, message: &Message) -> bool {
        self.first_opens.map_or(true, |first_message_opens_the_context| {
            if first_message_opens_the_context {
                self.patterns.first().unwrap() == message.uuid()
            } else {
                true
            }
        })
    }

    pub fn is_closing(&self, state: &State) -> bool {
        println!("checking close");
        self.is_max_size_reached(state) || self.is_closing_message(state) || self.is_any_timer_expired(state)
    }

    fn is_max_size_reached(&self, state: &State) -> bool {
        self.max_size.map_or(false, |max_size| state.messages().len() >= max_size)
    }

    fn is_closing_message(&self, state: &State) -> bool {
        self.last_closes.map_or(false, |last_message_closes_the_context| {
            if last_message_closes_the_context {
                self.patterns.last().unwrap() == state.messages().last().unwrap().uuid()
            } else {
                false
            }
        })
    }

    fn is_any_timer_expired(&self, state: &State) -> bool {
        self.is_timeout_expired(state) || self.is_renew_timeout_expired(state)
    }

    fn is_timeout_expired(&self, state: &State) -> bool {
        state.elapsed_time() >= self.timeout
    }

    fn is_renew_timeout_expired(&self, state: &State) -> bool {
        self.renew_timeout.map_or(false, |renew_timeout| {
            state.elapsed_time_since_last_message() >= renew_timeout
        })
    }
}

pub struct Builder {
    conditions: Conditions
}

impl Builder {
    pub fn new(timeout: u32) -> Builder {
        Builder{
            conditions: Conditions::new(timeout)
        }
    }

    pub fn renew_timeout(&mut self, timeout: u32) -> &mut Builder {
        self.conditions.renew_timeout = Some(timeout);
        self
    }

    pub fn first_opens(&mut self, first_opens: bool) -> &mut Builder {
        self.conditions.first_opens = Some(first_opens);
        self
    }

    pub fn last_closes(&mut self, last_closes: bool) -> &mut Builder {
        self.conditions.last_closes = Some(last_closes);
        self
    }
    pub fn max_size(&mut self, max_size: usize) -> &mut Builder {
        self.conditions.max_size = Some(max_size);
        self
    }

    pub fn patterns(&mut self, patterns: Vec<String>) -> &mut Builder {
        self.conditions.patterns = patterns;
        self
    }

    pub fn build(&mut self) -> Conditions {
        self.conditions.clone()
    }
}
<commit_msg>Conditions: add unit tests<commit_after>use Message;
use state::State;

#[derive(Clone, Debug)]
pub struct Conditions {
    pub timeout: u32,
    pub renew_timeout: Option<u32>,
    pub first_opens: Option<bool>,
    pub last_closes: Option<bool>,
    pub max_size: Option<usize>,
    pub patterns: Vec<String>
}

impl Conditions {
    fn new(timeout: u32) -> Conditions {
        Conditions {
            timeout: timeout,
            renew_timeout: None,
            first_opens: None,
            last_closes: None,
            max_size: None,
            patterns: Vec::new()
        }
    }

    pub fn ignore_message(&self, message: &Message) -> bool {
        !self.patterns.contains(message.uuid()) && self.patterns.len() > 0
    }

    pub fn is_opening(&self, message: &Message) -> bool {
        self.first_opens.map_or(true, |first_message_opens_the_context| {
            if first_message_opens_the_context {
                self.patterns.first().unwrap() == message.uuid()
            } else {
                true
            }
        })
    }

    pub fn is_closing(&self, state: &State) -> bool {
        println!("checking close");
        self.is_max_size_reached(state) || self.is_closing_message(state) || self.is_any_timer_expired(state)
    }

    fn is_max_size_reached(&self, state: &State) -> bool {
        self.max_size.map_or(false, |max_size| state.messages().len() >= max_size)
    }

    fn is_closing_message(&self, state: &State) -> bool {
        self.last_closes.map_or(false, |last_message_closes_the_context| {
            if last_message_closes_the_context {
                self.patterns.last().unwrap() == state.messages().last().unwrap().uuid()
            } else {
                false
            }
        })
    }

    fn is_any_timer_expired(&self, state: &State) -> bool {
        self.is_timeout_expired(state) || self.is_renew_timeout_expired(state)
    }

    fn is_timeout_expired(&self, state: &State) -> bool {
        state.elapsed_time() >= self.timeout
    }

    fn is_renew_timeout_expired(&self, state: &State) -> bool {
        self.renew_timeout.map_or(false, |renew_timeout| {
            state.elapsed_time_since_last_message() >= renew_timeout
        })
    }
}

pub struct Builder {
    conditions: Conditions
}

impl Builder {
    pub fn new(timeout: u32) -> Builder {
        Builder{
            conditions: Conditions::new(timeout)
        }
    }

    pub fn renew_timeout(&mut self, timeout: u32) -> &mut Builder {
        self.conditions.renew_timeout = Some(timeout);
        self
    }

    pub fn first_opens(&mut self, first_opens: bool) -> &mut Builder {
        self.conditions.first_opens = Some(first_opens);
        self
    }

    pub fn last_closes(&mut self, last_closes: bool) -> &mut Builder {
        self.conditions.last_closes = Some(last_closes);
        self
    }
    pub fn max_size(&mut self, max_size: usize) -> &mut Builder {
        self.conditions.max_size = Some(max_size);
        self
    }

    pub fn patterns(&mut self, patterns: Vec<String>) -> &mut Builder {
        self.conditions.patterns = patterns;
        self
    }

    pub fn build(&mut self) -> Conditions {
        self.conditions.clone()
    }
}

#[cfg(test)]
mod test {
    use std::rc::Rc;

    use message;
    use state::State;
    use super::Builder;

    #[test]
    fn test_given_close_condition_when_an_unknown_message_received_then_it_is_ignored() {
        let timeout = 100;
        let msg_id = "1".to_string();
        let condition = Builder::new(timeout).patterns(vec![msg_id.clone()]).build();
        let msg_which_should_not_be_ignored = message::Builder::new(msg_id.clone()).build();
        let msg_which_should_be_ignored = message::Builder::new("2".to_string()).build();
        assert_true!(condition.ignore_message(&msg_which_should_be_ignored));
        assert_false!(condition.ignore_message(&msg_which_should_not_be_ignored));
    }

    #[test]
    fn test_given_condition_when_an_opening_message_is_received_then_the_state_becomes_opened() {
        let timeout = 100;
        let msg_id = "1".to_string();
        let condition = Builder::new(timeout).patterns(vec![msg_id.clone()]).first_opens(true).build();
        let msg_which_should_not_be_ignored = message::Builder::new(msg_id.clone()).build();
        let msg_which_should_be_ignored = message::Builder::new("2".to_string()).build();
        assert_false!(condition.is_opening(&msg_which_should_be_ignored));
        assert_true!(condition.is_opening(&msg_which_should_not_be_ignored));
    }

    #[test]
    fn test_given_condition_when_a_closing_message_is_received_then_the_state_becomes_closed() {
        let timeout = 100;
        let msg_id = "1".to_string();
        let mut state = State::new();
        let condition = Builder::new(timeout).patterns(vec!["1".to_string(), "2".to_string()]).last_closes(true).build();
        let msg_1 = message::Builder::new(msg_id.clone()).build();
        let msg_closing = Rc::new(message::Builder::new("2".to_string()).build());
        assert_true!(condition.is_opening(&msg_1));
        state.open();
        state.add_message(msg_closing);
        assert_true!(condition.is_closing(&mut state));
    }
}
<|endoftext|>


<commit_before>//! Due to netlink's loose treatment of types, parsing attributes can be hard to model in
//! Rust. `neli`'s current solution is the following:
//!
//! ```no_run
//! // This was received from the socket
//! let nlmsg = neli::nl::Nlmsghdr::new(None, neli::consts::GenlId::Ctrl, Vec::new(), None, None,
//!         neli::genl::Genlmsghdr::new::<u16>(neli::consts::CtrlCmd::Unspec, 2, Vec::new()).unwrap());
//!
//! // Get parsing handler for the attributes in this message where the next call
//! // to either get_nested_attributes() or get_payload_with() will expect a u16 type
//! // to be provided
//! let mut handle = nlmsg.nl_payload.get_attr_handle::<u16>();
//!
//! // Get the nested attribute where the Nlattr field of nla_type is equal to 1 and return
//! // a handler containing only this nested attribute internally
//! let mut next = handle.get_nested_attributes::<u16>(1).unwrap();
//!
//! // Get the nested attribute where the Nlattr field of nla_type is equal to 1 and return
//! // the payload of this attribute as a u32
//! let thirty_two_bit_integer = next.get_payload::<u32>(1, None).unwrap();
//! ```

use std::io::{Read,Write};
use std::slice;

use buffering::copy::{StreamReadBuffer,StreamWriteBuffer};
use libc;

use Nl;
use err::{SerError,DeError};
use consts::{alignto,NlAttrType};

impl<T> Nl for Vec<Nlattr<T>> where T: NlAttrType {
    fn serialize(&self, mem: &mut StreamWriteBuffer) -> Result<(), SerError> {
        for item in self.iter() {
            item.serialize(mem)?;
        }
        Ok(())
    }

    fn deserialize<B>(mem: &mut StreamReadBuffer<B>) -> Result<Self, DeError>
            where B: AsRef<[u8]> {
        let mut vec = Vec::new();
        let mut size_hint = mem.take_size_hint().unwrap_or(0);
        while size_hint > 0 || !mem.at_end() {
            let next = Nlattr::<T>::deserialize(mem)?;
            if size_hint > 0 {
                size_hint -= next.asize();
            }
            vec.push(next);
        }
        Ok(vec)
    }

    fn size(&self) -> usize {
        self.iter().fold(0, |acc, next| {
            acc + alignto(next.size())
        })
    }
}

/// Struct representing netlink attributes and payloads
#[derive(Debug,PartialEq)]
pub struct Nlattr<T> {
    /// Length of the attribute header and payload together
    pub nla_len: u16,
    /// Enum representing the type of the attribute payload
    pub nla_type: T,
    /// Payload of the attribute - either parsed or a binary buffer
    pub payload: Vec<u8>,
}

impl<T> Nlattr<T> where T: NlAttrType {
    /// Create new netlink attribute with a payload
    pub fn new_binary_payload(nla_len: Option<u16>, nla_type: T, payload: Vec<u8>)
            -> Self {
        let mut nla = Nlattr {
            nla_type,
            payload,
            nla_len: 0,
        };
        nla.nla_len = nla_len.unwrap_or(nla.size() as u16);
        nla
    }

    /// Create new netlink attribute with a payload from an object implementing `Nl`
    pub fn new_nl_payload<P>(nla_len: Option<u16>, nla_type: T, payload: P)
            -> Result<Self, SerError> where P: Nl {
        let mut mem = StreamWriteBuffer::new_growable(Some(payload.asize()));
        mem.set_size_hint(payload.size());
        payload.serialize(&mut mem)?;
        let mut nla = Nlattr {
            nla_type,
            payload: mem.as_ref().to_vec(),
            nla_len: 0,
        };
        nla.nla_len = nla_len.unwrap_or(nla.size() as u16);
        Ok(nla)
    }

    /// Get handle for attribute parsing and traversal
    pub fn get_attr_handle<'a, P>(&'a self) -> AttrHandle<'a, P> where P: NlAttrType {
        AttrHandle::Bin(self.payload.as_slice())
    }
}

impl<T> Nl for Nlattr<T> where T: NlAttrType {
    fn serialize(&self, mem: &mut StreamWriteBuffer) -> Result<(), SerError> {
        self.nla_len.serialize(mem)?;
        self.nla_type.serialize(mem)?;
        self.payload.serialize(mem)?;
        let padding_len = alignto(self.nla_len as usize) - self.nla_len as usize;
        if padding_len > 0 {
            mem.write(&mut [0u8; 4][0..padding_len])?;
        }
        Ok(())
    }

    fn deserialize<B>(mem: &mut StreamReadBuffer<B>) -> Result<Self, DeError> where B: AsRef<[u8]> {
        let nla_len = u16::deserialize(mem)?;
        let nla_type = T::deserialize(mem)?;
        mem.set_size_hint(nla_len as usize - (nla_len.size() + nla_type.size()));
        let payload = Vec::<u8>::deserialize(mem)?;
        let padding_len = alignto(nla_len as usize) - nla_len as usize;
        if padding_len > 0 {
            let padding = &mut [0u8; libc::NLA_ALIGNTO as usize][0..padding_len];
            let _ = mem.read_exact(padding)?;
        }
        let nla = Nlattr {
            nla_len,
            nla_type,
            payload,
        };
        Ok(nla)
    }

    fn size(&self) -> usize {
        self.nla_len.size() + self.nla_type.size() + self.payload.size()
    }
}

/// Handle returned by `Genlmsghdr` for traversing nested attribute structures
pub enum AttrHandle<'a, P> where P: NlAttrType {
    /// Binary internal representation of attributes
    Bin(&'a [u8]),
    /// Rust representation of attributes
    Parsed(Vec<Nlattr<P>>),
}

impl<'a, P> AttrHandle<'a, P> where P: NlAttrType {
    /// Get length if attribute handle has been parsed
    pub fn len(&self) -> Option<usize> {
        match *self {
            AttrHandle::Parsed(ref v) => Some(v.len()),
            _ => None,
        }
    }

    /// If attributes are parsed, pass back iterator over attributes
    pub fn iter(&self) -> Option<slice::Iter<Nlattr<P>>> {
        match *self {
            AttrHandle::Parsed(ref v) => Some(v.iter()),
            _ => None,
        }
    }

    /// Parse a binary payload into nested attributes
    pub fn parse_nested_attributes(&mut self) -> Result<&mut AttrHandle<'a, P>, DeError> {
        let opt_v = match *self {
            AttrHandle::Bin(v) => {
                let mut len = v.asize();
                let mut attrs = Vec::new();
                let mut mem = StreamReadBuffer::new(v);
                while len > 0 {
                    let hdr = Nlattr::deserialize(&mut mem)?;
                    len -= hdr.asize();
                    attrs.push(hdr);
                }
                Some(attrs)
            },
            _ => None,
        };
        match opt_v {
            Some(v) => { *self = AttrHandle::Parsed(v); },
            None => (),
        };
        Ok(self)
    }

    /// Get the payload of an attribute as a handle for parsing nested attributes
    pub fn get_nested_attributes<S>(&mut self, payload: P) -> Result<AttrHandle<S>, DeError>
            where S: NlAttrType {
        let nested = self.parse_nested_attributes()?.get_attribute(payload);
        match nested {
            Some(a) => Ok(AttrHandle::Bin(a.payload.as_slice())),
            None => Err(DeError::new("Failed to find requested attribute")),
        }
    }

    /// Get nested attributes from a parsed handle
    pub fn get_attribute(&'a self, p: P) -> Option<&'a Nlattr<P>> {
        match *self {
            AttrHandle::Parsed(ref parsed) => {
                for item in parsed {
                    if item.nla_type == p {
                        return Some(&item);
                    }
                }
                None
            },
            _ => None,
        }
    }

    /// Mutably get nested attributes from a parsed handle
    pub fn get_attribute_mut(&'a mut self, p: P) -> Option<&'a mut Nlattr<P>> {
        match *self {
            AttrHandle::Parsed(ref mut parsed) => {
                for item in parsed {
                    if item.nla_type == p {
                        return Some(item);
                    }
                }
                None
            },
            _ => None,
        }
    }

    /// Parse binary payload as a type that implements `Nl` using `deserialize` with an option size
    /// hint
    pub fn get_payload<R>(&mut self, attr: P, size_hint: Option<usize>) -> Result<R, DeError>
            where R: Nl {
        match self.parse_nested_attributes()?.get_attribute(attr) {
            Some(ref a) => {
                let mut mem = StreamReadBuffer::new(&a.payload);
                if let Some(w) = size_hint {
                    mem.set_size_hint(w);
                }
                R::deserialize(&mut mem)
            },
            _ => Err(DeError::new("Failed to find specified attribute")),
        }
    }
}
<commit_msg>Add tests for nlattr.rs padding issues/serialize/deserialize to detect breakage moving forward<commit_after>//! Due to netlink's loose treatment of types, parsing attributes can be hard to model in
//! Rust. `neli`'s current solution is the following:
//!
//! ```no_run
//! // This was received from the socket
//! let nlmsg = neli::nl::Nlmsghdr::new(None, neli::consts::GenlId::Ctrl, Vec::new(), None, None,
//!         neli::genl::Genlmsghdr::new::<u16>(neli::consts::CtrlCmd::Unspec, 2, Vec::new()).unwrap());
//!
//! // Get parsing handler for the attributes in this message where the next call
//! // to either get_nested_attributes() or get_payload_with() will expect a u16 type
//! // to be provided
//! let mut handle = nlmsg.nl_payload.get_attr_handle::<u16>();
//!
//! // Get the nested attribute where the Nlattr field of nla_type is equal to 1 and return
//! // a handler containing only this nested attribute internally
//! let mut next = handle.get_nested_attributes::<u16>(1).unwrap();
//!
//! // Get the nested attribute where the Nlattr field of nla_type is equal to 1 and return
//! // the payload of this attribute as a u32
//! let thirty_two_bit_integer = next.get_payload::<u32>(1, None).unwrap();
//! ```

use std::io::{Read,Write};
use std::slice;

use buffering::copy::{StreamReadBuffer,StreamWriteBuffer};
use libc;

use Nl;
use err::{SerError,DeError};
use consts::{alignto,NlAttrType};

impl<T> Nl for Vec<Nlattr<T>> where T: NlAttrType {
    fn serialize(&self, mem: &mut StreamWriteBuffer) -> Result<(), SerError> {
        for item in self.iter() {
            item.serialize(mem)?;
        }
        Ok(())
    }

    fn deserialize<B>(mem: &mut StreamReadBuffer<B>) -> Result<Self, DeError>
            where B: AsRef<[u8]> {
        let mut vec = Vec::new();
        let mut size_hint = mem.take_size_hint().unwrap_or(0);
        while size_hint > 0 || !mem.at_end() {
            let next = Nlattr::<T>::deserialize(mem)?;
            if size_hint > 0 {
                size_hint -= next.asize();
            }
            vec.push(next);
        }
        Ok(vec)
    }

    fn size(&self) -> usize {
        self.iter().fold(0, |acc, next| {
            acc + alignto(next.size())
        })
    }
}

/// Struct representing netlink attributes and payloads
#[derive(Debug,PartialEq)]
pub struct Nlattr<T> {
    /// Length of the attribute header and payload together
    pub nla_len: u16,
    /// Enum representing the type of the attribute payload
    pub nla_type: T,
    /// Payload of the attribute - either parsed or a binary buffer
    pub payload: Vec<u8>,
}

impl<T> Nlattr<T> where T: NlAttrType {
    /// Create new netlink attribute with a payload
    pub fn new_binary_payload(nla_len: Option<u16>, nla_type: T, payload: Vec<u8>)
            -> Self {
        let mut nla = Nlattr {
            nla_type,
            payload,
            nla_len: 0,
        };
        nla.nla_len = nla_len.unwrap_or(nla.size() as u16);
        nla
    }

    /// Create new netlink attribute with a payload from an object implementing `Nl`
    pub fn new_nl_payload<P>(nla_len: Option<u16>, nla_type: T, payload: P)
            -> Result<Self, SerError> where P: Nl {
        let mut mem = StreamWriteBuffer::new_growable(Some(payload.asize()));
        mem.set_size_hint(payload.size());
        payload.serialize(&mut mem)?;
        let mut nla = Nlattr {
            nla_type,
            payload: mem.as_ref().to_vec(),
            nla_len: 0,
        };
        nla.nla_len = nla_len.unwrap_or(nla.size() as u16);
        Ok(nla)
    }

    /// Get handle for attribute parsing and traversal
    pub fn get_attr_handle<'a, P>(&'a self) -> AttrHandle<'a, P> where P: NlAttrType {
        AttrHandle::Bin(self.payload.as_slice())
    }
}

impl<T> Nl for Nlattr<T> where T: NlAttrType {
    fn serialize(&self, mem: &mut StreamWriteBuffer) -> Result<(), SerError> {
        self.nla_len.serialize(mem)?;
        self.nla_type.serialize(mem)?;
        self.payload.serialize(mem)?;
        let padding_len = alignto(self.nla_len as usize) - self.nla_len as usize;
        if padding_len > 0 {
            mem.write(&mut [0u8; 4][0..padding_len])?;
        }
        Ok(())
    }

    fn deserialize<B>(mem: &mut StreamReadBuffer<B>) -> Result<Self, DeError> where B: AsRef<[u8]> {
        let nla_len = u16::deserialize(mem)?;
        let nla_type = T::deserialize(mem)?;
        mem.set_size_hint(nla_len as usize - (nla_len.size() + nla_type.size()));
        let payload = Vec::<u8>::deserialize(mem)?;
        let padding_len = alignto(nla_len as usize) - nla_len as usize;
        if padding_len > 0 {
            let padding = &mut [0u8; libc::NLA_ALIGNTO as usize][0..padding_len];
            let _ = mem.read_exact(padding)?;
        }
        let nla = Nlattr {
            nla_len,
            nla_type,
            payload,
        };
        Ok(nla)
    }

    fn size(&self) -> usize {
        self.nla_len.size() + self.nla_type.size() + self.payload.size()
    }
}

/// Handle returned by `Genlmsghdr` for traversing nested attribute structures
pub enum AttrHandle<'a, P> where P: NlAttrType {
    /// Binary internal representation of attributes
    Bin(&'a [u8]),
    /// Rust representation of attributes
    Parsed(Vec<Nlattr<P>>),
}

impl<'a, P> AttrHandle<'a, P> where P: NlAttrType {
    /// Get length if attribute handle has been parsed
    pub fn len(&self) -> Option<usize> {
        match *self {
            AttrHandle::Parsed(ref v) => Some(v.len()),
            _ => None,
        }
    }

    /// If attributes are parsed, pass back iterator over attributes
    pub fn iter(&self) -> Option<slice::Iter<Nlattr<P>>> {
        match *self {
            AttrHandle::Parsed(ref v) => Some(v.iter()),
            _ => None,
        }
    }

    /// Parse a binary payload into nested attributes
    pub fn parse_nested_attributes(&mut self) -> Result<&mut AttrHandle<'a, P>, DeError> {
        let opt_v = match *self {
            AttrHandle::Bin(v) => {
                let mut len = v.asize();
                let mut attrs = Vec::new();
                let mut mem = StreamReadBuffer::new(v);
                while len > 0 {
                    let hdr = Nlattr::deserialize(&mut mem)?;
                    len -= hdr.asize();
                    attrs.push(hdr);
                }
                Some(attrs)
            },
            _ => None,
        };
        match opt_v {
            Some(v) => { *self = AttrHandle::Parsed(v); },
            None => (),
        };
        Ok(self)
    }

    /// Get the payload of an attribute as a handle for parsing nested attributes
    pub fn get_nested_attributes<S>(&mut self, payload: P) -> Result<AttrHandle<S>, DeError>
            where S: NlAttrType {
        let nested = self.parse_nested_attributes()?.get_attribute(payload);
        match nested {
            Some(a) => Ok(AttrHandle::Bin(a.payload.as_slice())),
            None => Err(DeError::new("Failed to find requested attribute")),
        }
    }

    /// Get nested attributes from a parsed handle
    pub fn get_attribute(&'a self, p: P) -> Option<&'a Nlattr<P>> {
        match *self {
            AttrHandle::Parsed(ref parsed) => {
                for item in parsed {
                    if item.nla_type == p {
                        return Some(&item);
                    }
                }
                None
            },
            _ => None,
        }
    }

    /// Mutably get nested attributes from a parsed handle
    pub fn get_attribute_mut(&'a mut self, p: P) -> Option<&'a mut Nlattr<P>> {
        match *self {
            AttrHandle::Parsed(ref mut parsed) => {
                for item in parsed {
                    if item.nla_type == p {
                        return Some(item);
                    }
                }
                None
            },
            _ => None,
        }
    }

    /// Parse binary payload as a type that implements `Nl` using `deserialize` with an option size
    /// hint
    pub fn get_payload<R>(&mut self, attr: P, size_hint: Option<usize>) -> Result<R, DeError>
            where R: Nl {
        match self.parse_nested_attributes()?.get_attribute(attr) {
            Some(ref a) => {
                let mut mem = StreamReadBuffer::new(&a.payload);
                if let Some(w) = size_hint {
                    mem.set_size_hint(w);
                }
                R::deserialize(&mut mem)
            },
            _ => Err(DeError::new("Failed to find specified attribute")),
        }
    }
}

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

    extern crate byteorder;

    use std::io::Cursor;

    use byteorder::{ByteOrder,WriteBytesExt,NativeEndian};

    use consts::CtrlAttr;

    #[test]
    fn test_padding_size_calculation() {
        let nlattr = Nlattr::new_nl_payload(None, CtrlAttr::Unspec, 4u16).unwrap();
        let mut vec = vec![0; 2];
        NativeEndian::write_u16(vec.as_mut_slice(), 4);
        assert_eq!(nlattr, Nlattr { nla_len: 6, nla_type: CtrlAttr::Unspec, payload: vec });
    }

    #[test]
    fn test_nl_nlattr() {
        let nlattr = Nlattr::new_nl_payload(None, CtrlAttr::Unspec, 4u16).unwrap();
        let mut nlattr_serialized = StreamWriteBuffer::new_growable(Some(nlattr.asize()));
        nlattr.serialize(&mut nlattr_serialized).unwrap();

        let mut nlattr_desired_serialized = Cursor::new(vec![0; nlattr.size()]);
        nlattr_desired_serialized.write_u16::<NativeEndian>(6).unwrap();
        nlattr_desired_serialized.write_u16::<NativeEndian>(CtrlAttr::Unspec.into()).unwrap();
        nlattr_desired_serialized.write_u16::<NativeEndian>(4).unwrap();
        nlattr_desired_serialized.write(&[0, 0]).unwrap();

        assert_eq!(nlattr_serialized.as_ref(), nlattr_desired_serialized.into_inner().as_slice());

        let mut vec = vec![0; 2];
        NativeEndian::write_u16(vec.as_mut_slice(), 4);
        let nlattr_desired_deserialized = Nlattr { nla_len: 6, nla_type: CtrlAttr::Unspec,
                                                   payload: vec };

        let mut nlattr_deserialize_buffer = Cursor::new(
            vec![0; nlattr_desired_deserialized.asize()]
        );
        nlattr_deserialize_buffer.write_u16::<NativeEndian>(6).unwrap();
        nlattr_deserialize_buffer.write_u16::<NativeEndian>(CtrlAttr::Unspec.into()).unwrap();
        nlattr_deserialize_buffer.write_u16::<NativeEndian>(4).unwrap();
        nlattr_deserialize_buffer.write(&[0, 0]).unwrap();
        let mut reader = StreamReadBuffer::new(nlattr_deserialize_buffer.into_inner());
        let nlattr_deserialized = Nlattr::<CtrlAttr>::deserialize(&mut reader).unwrap();
        assert_eq!(nlattr_deserialized, nlattr_desired_deserialized);
    }
}
<|endoftext|>


<commit_before>// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use error::Error;
use num_traits::NumCast;
use serde::de::{self, Visitor, Unexpected};
use serde::{Serialize, Serializer, Deserialize, Deserializer};
use std::fmt::{self, Debug, Display};
use std::i64;

/// Represents a JSON number, whether integer or floating point.
#[derive(Clone, PartialEq)]
pub struct Number {
    n: N,
}

// "N" is a prefix of "NegInt"... this is a false positive.
// https://github.com/Manishearth/rust-clippy/issues/1241
#[cfg_attr(feature = "cargo-clippy", allow(enum_variant_names))]
#[derive(Copy, Clone, Debug, PartialEq)]
enum N {
    PosInt(u64),
    /// Always less than zero.
    NegInt(i64),
    /// Always finite.
    Float(f64),
}

impl Number {
    /// Returns true if the `Number` is an integer between `i64::MIN` and
    /// `i64::MAX`.
    ///
    /// For any Number on which `is_i64` returns true, `as_i64` is guaranteed to
    /// return the integer value.
    ///
    /// ```rust
    /// # #[macro_use]
    /// # extern crate serde_json;
    /// #
    /// # use std::i64;
    /// #
    /// # fn main() {
    /// let big = i64::MAX as u64 + 10;
    /// let v = json!({ "a": 64, "b": big, "c": 256.0 });
    ///
    /// assert!(v["a"].is_i64());
    ///
    /// // Greater than i64::MAX.
    /// assert!(!v["b"].is_i64());
    ///
    /// // Numbers with a decimal point are not considered integers.
    /// assert!(!v["c"].is_i64());
    /// # }
    /// ```
    #[inline]
    pub fn is_i64(&self) -> bool {
        match self.n {
            N::PosInt(v) => v <= i64::MAX as u64,
            N::NegInt(_) => true,
            N::Float(_) => false,
        }
    }

    /// Returns true if the `Number` is an integer between zero and `u64::MAX`.
    ///
    /// For any Number on which `is_u64` returns true, `as_u64` is guaranteed to
    /// return the integer value.
    ///
    /// ```rust
    /// # #[macro_use]
    /// # extern crate serde_json;
    /// #
    /// # fn main() {
    /// let v = json!({ "a": 64, "b": -64, "c": 256.0 });
    ///
    /// assert!(v["a"].is_u64());
    ///
    /// // Negative integer.
    /// assert!(!v["b"].is_u64());
    ///
    /// // Numbers with a decimal point are not considered integers.
    /// assert!(!v["c"].is_u64());
    /// # }
    /// ```
    #[inline]
    pub fn is_u64(&self) -> bool {
        match self.n {
            N::PosInt(_) => true,
            N::NegInt(_) | N::Float(_) => false,
        }
    }

    /// Returns true if the `Number` can be represented by f64.
    ///
    /// For any Number on which `is_f64` returns true, `as_f64` is guaranteed to
    /// return the floating point value.
    ///
    /// Currently this function returns true if and only if both `is_i64` and
    /// `is_u64` return false but this is not a guarantee in the future.
    ///
    /// ```rust
    /// # #[macro_use]
    /// # extern crate serde_json;
    /// #
    /// # fn main() {
    /// let v = json!({ "a": 256.0, "b": 64, "c": -64 });
    ///
    /// assert!(v["a"].is_f64());
    ///
    /// // Integers.
    /// assert!(!v["b"].is_f64());
    /// assert!(!v["c"].is_f64());
    /// # }
    /// ```
    #[inline]
    pub fn is_f64(&self) -> bool {
        match self.n {
            N::Float(_) => true,
            N::PosInt(_) | N::NegInt(_) => false,
        }
    }

    /// If the `Number` is an integer, represent it as i64 if possible. Returns
    /// None otherwise.
    ///
    /// ```rust
    /// # #[macro_use]
    /// # extern crate serde_json;
    /// #
    /// # use std::i64;
    /// #
    /// # fn main() {
    /// let big = i64::MAX as u64 + 10;
    /// let v = json!({ "a": 64, "b": big, "c": 256.0 });
    ///
    /// assert_eq!(v["a"].as_i64(), Some(64));
    /// assert_eq!(v["b"].as_i64(), None);
    /// assert_eq!(v["c"].as_i64(), None);
    /// # }
    /// ```
    #[inline]
    pub fn as_i64(&self) -> Option<i64> {
        match self.n {
            N::PosInt(n) => NumCast::from(n),
            N::NegInt(n) => Some(n),
            N::Float(_) => None,
        }
    }

    /// If the `Number` is an integer, represent it as u64 if possible. Returns
    /// None otherwise.
    ///
    /// ```rust
    /// # #[macro_use]
    /// # extern crate serde_json;
    /// #
    /// # fn main() {
    /// let v = json!({ "a": 64, "b": -64, "c": 256.0 });
    ///
    /// assert_eq!(v["a"].as_u64(), Some(64));
    /// assert_eq!(v["b"].as_u64(), None);
    /// assert_eq!(v["c"].as_u64(), None);
    /// # }
    /// ```
    #[inline]
    pub fn as_u64(&self) -> Option<u64> {
        match self.n {
            N::PosInt(n) => Some(n),
            N::NegInt(n) => NumCast::from(n),
            N::Float(_) => None,
        }
    }

    /// Represents the number as f64 if possible. Returns None otherwise.
    ///
    /// ```rust
    /// # #[macro_use]
    /// # extern crate serde_json;
    /// #
    /// # fn main() {
    /// let v = json!({ "a": 256.0, "b": 64, "c": -64 });
    ///
    /// assert_eq!(v["a"].as_f64(), Some(256.0));
    /// assert_eq!(v["b"].as_f64(), Some(64.0));
    /// assert_eq!(v["c"].as_f64(), Some(-64.0));
    /// # }
    /// ```
    #[inline]
    pub fn as_f64(&self) -> Option<f64> {
        match self.n {
            N::PosInt(n) => NumCast::from(n),
            N::NegInt(n) => NumCast::from(n),
            N::Float(n) => Some(n),
        }
    }

    /// Converts a finite `f64` to a `Number`. Infinite or NaN values are not JSON
    /// numbers.
    ///
    /// ```rust
    /// # use std::f64;
    /// #
    /// # use serde_json::Number;
    /// #
    /// assert!(Number::from_f64(256.0).is_some());
    ///
    /// assert!(Number::from_f64(f64::NAN).is_none());
    /// ```
    #[inline]
    pub fn from_f64(f: f64) -> Option<Number> {
        if f.is_finite() {
            Some(Number { n: N::Float(f) })
        } else {
            None
        }
    }
}

impl fmt::Display for Number {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        match self.n {
            N::PosInt(i) => Display::fmt(&i, formatter),
            N::NegInt(i) => Display::fmt(&i, formatter),
            N::Float(f) => Display::fmt(&f, formatter),
        }
    }
}

impl Debug for Number {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        Debug::fmt(&self.n, formatter)
    }
}

impl Serialize for Number {
    #[inline]
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        match self.n {
            N::PosInt(i) => serializer.serialize_u64(i),
            N::NegInt(i) => serializer.serialize_i64(i),
            N::Float(f) => serializer.serialize_f64(f),
        }
    }
}

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

        impl<'de> Visitor<'de> for NumberVisitor {
            type Value = Number;

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

            #[inline]
            fn visit_i64<E>(self, value: i64) -> Result<Number, E> {
                Ok(value.into())
            }

            #[inline]
            fn visit_u64<E>(self, value: u64) -> Result<Number, E> {
                Ok(value.into())
            }

            #[inline]
            fn visit_f64<E>(self, value: f64) -> Result<Number, E>
            where
                E: de::Error,
            {
                Number::from_f64(value).ok_or_else(|| de::Error::custom("not a JSON number"))
            }
        }

        deserializer.deserialize_any(NumberVisitor)
    }
}

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

    #[inline]
    fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Error>
    where
        V: Visitor<'de>,
    {
        match self.n {
            N::PosInt(i) => visitor.visit_u64(i),
            N::NegInt(i) => visitor.visit_i64(i),
            N::Float(f) => visitor.visit_f64(f),
        }
    }

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

impl<'de, 'a> Deserializer<'de> for &'a Number {
    type Error = Error;

    #[inline]
    fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Error>
    where
        V: Visitor<'de>,
    {
        match self.n {
            N::PosInt(i) => visitor.visit_u64(i),
            N::NegInt(i) => visitor.visit_i64(i),
            N::Float(f) => visitor.visit_f64(f),
        }
    }

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

macro_rules! from_signed {
    ($($signed_ty:ident)*) => {
        $(
            impl From<$signed_ty> for Number {
                #[inline]
                fn from(i: $signed_ty) -> Self {
                    if i < 0 {
                        Number { n: N::NegInt(i as i64) }
                    } else {
                        Number { n: N::PosInt(i as u64) }
                    }
                }
            }
        )*
    };
}

macro_rules! from_unsigned {
    ($($unsigned_ty:ident)*) => {
        $(
            impl From<$unsigned_ty> for Number {
                #[inline]
                fn from(u: $unsigned_ty) -> Self {
                    Number { n: N::PosInt(u as u64) }
                }
            }
        )*
    };
}

from_signed!(i8 i16 i32 i64 isize);
from_unsigned!(u8 u16 u32 u64 usize);

impl Number {
    // Not public API. Should be pub(crate).
    #[doc(hidden)]
    pub fn unexpected(&self) -> Unexpected {
        match self.n {
            N::PosInt(u) => Unexpected::Unsigned(u),
            N::NegInt(i) => Unexpected::Signed(i),
            N::Float(f) => Unexpected::Float(f),
        }
    }
}
<commit_msg>Warn about enum_variant_names violations in enum N<commit_after>// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use error::Error;
use num_traits::NumCast;
use serde::de::{self, Visitor, Unexpected};
use serde::{Serialize, Serializer, Deserialize, Deserializer};
use std::fmt::{self, Debug, Display};
use std::i64;

/// Represents a JSON number, whether integer or floating point.
#[derive(Clone, PartialEq)]
pub struct Number {
    n: N,
}

#[derive(Copy, Clone, Debug, PartialEq)]
enum N {
    PosInt(u64),
    /// Always less than zero.
    NegInt(i64),
    /// Always finite.
    Float(f64),
}

impl Number {
    /// Returns true if the `Number` is an integer between `i64::MIN` and
    /// `i64::MAX`.
    ///
    /// For any Number on which `is_i64` returns true, `as_i64` is guaranteed to
    /// return the integer value.
    ///
    /// ```rust
    /// # #[macro_use]
    /// # extern crate serde_json;
    /// #
    /// # use std::i64;
    /// #
    /// # fn main() {
    /// let big = i64::MAX as u64 + 10;
    /// let v = json!({ "a": 64, "b": big, "c": 256.0 });
    ///
    /// assert!(v["a"].is_i64());
    ///
    /// // Greater than i64::MAX.
    /// assert!(!v["b"].is_i64());
    ///
    /// // Numbers with a decimal point are not considered integers.
    /// assert!(!v["c"].is_i64());
    /// # }
    /// ```
    #[inline]
    pub fn is_i64(&self) -> bool {
        match self.n {
            N::PosInt(v) => v <= i64::MAX as u64,
            N::NegInt(_) => true,
            N::Float(_) => false,
        }
    }

    /// Returns true if the `Number` is an integer between zero and `u64::MAX`.
    ///
    /// For any Number on which `is_u64` returns true, `as_u64` is guaranteed to
    /// return the integer value.
    ///
    /// ```rust
    /// # #[macro_use]
    /// # extern crate serde_json;
    /// #
    /// # fn main() {
    /// let v = json!({ "a": 64, "b": -64, "c": 256.0 });
    ///
    /// assert!(v["a"].is_u64());
    ///
    /// // Negative integer.
    /// assert!(!v["b"].is_u64());
    ///
    /// // Numbers with a decimal point are not considered integers.
    /// assert!(!v["c"].is_u64());
    /// # }
    /// ```
    #[inline]
    pub fn is_u64(&self) -> bool {
        match self.n {
            N::PosInt(_) => true,
            N::NegInt(_) | N::Float(_) => false,
        }
    }

    /// Returns true if the `Number` can be represented by f64.
    ///
    /// For any Number on which `is_f64` returns true, `as_f64` is guaranteed to
    /// return the floating point value.
    ///
    /// Currently this function returns true if and only if both `is_i64` and
    /// `is_u64` return false but this is not a guarantee in the future.
    ///
    /// ```rust
    /// # #[macro_use]
    /// # extern crate serde_json;
    /// #
    /// # fn main() {
    /// let v = json!({ "a": 256.0, "b": 64, "c": -64 });
    ///
    /// assert!(v["a"].is_f64());
    ///
    /// // Integers.
    /// assert!(!v["b"].is_f64());
    /// assert!(!v["c"].is_f64());
    /// # }
    /// ```
    #[inline]
    pub fn is_f64(&self) -> bool {
        match self.n {
            N::Float(_) => true,
            N::PosInt(_) | N::NegInt(_) => false,
        }
    }

    /// If the `Number` is an integer, represent it as i64 if possible. Returns
    /// None otherwise.
    ///
    /// ```rust
    /// # #[macro_use]
    /// # extern crate serde_json;
    /// #
    /// # use std::i64;
    /// #
    /// # fn main() {
    /// let big = i64::MAX as u64 + 10;
    /// let v = json!({ "a": 64, "b": big, "c": 256.0 });
    ///
    /// assert_eq!(v["a"].as_i64(), Some(64));
    /// assert_eq!(v["b"].as_i64(), None);
    /// assert_eq!(v["c"].as_i64(), None);
    /// # }
    /// ```
    #[inline]
    pub fn as_i64(&self) -> Option<i64> {
        match self.n {
            N::PosInt(n) => NumCast::from(n),
            N::NegInt(n) => Some(n),
            N::Float(_) => None,
        }
    }

    /// If the `Number` is an integer, represent it as u64 if possible. Returns
    /// None otherwise.
    ///
    /// ```rust
    /// # #[macro_use]
    /// # extern crate serde_json;
    /// #
    /// # fn main() {
    /// let v = json!({ "a": 64, "b": -64, "c": 256.0 });
    ///
    /// assert_eq!(v["a"].as_u64(), Some(64));
    /// assert_eq!(v["b"].as_u64(), None);
    /// assert_eq!(v["c"].as_u64(), None);
    /// # }
    /// ```
    #[inline]
    pub fn as_u64(&self) -> Option<u64> {
        match self.n {
            N::PosInt(n) => Some(n),
            N::NegInt(n) => NumCast::from(n),
            N::Float(_) => None,
        }
    }

    /// Represents the number as f64 if possible. Returns None otherwise.
    ///
    /// ```rust
    /// # #[macro_use]
    /// # extern crate serde_json;
    /// #
    /// # fn main() {
    /// let v = json!({ "a": 256.0, "b": 64, "c": -64 });
    ///
    /// assert_eq!(v["a"].as_f64(), Some(256.0));
    /// assert_eq!(v["b"].as_f64(), Some(64.0));
    /// assert_eq!(v["c"].as_f64(), Some(-64.0));
    /// # }
    /// ```
    #[inline]
    pub fn as_f64(&self) -> Option<f64> {
        match self.n {
            N::PosInt(n) => NumCast::from(n),
            N::NegInt(n) => NumCast::from(n),
            N::Float(n) => Some(n),
        }
    }

    /// Converts a finite `f64` to a `Number`. Infinite or NaN values are not JSON
    /// numbers.
    ///
    /// ```rust
    /// # use std::f64;
    /// #
    /// # use serde_json::Number;
    /// #
    /// assert!(Number::from_f64(256.0).is_some());
    ///
    /// assert!(Number::from_f64(f64::NAN).is_none());
    /// ```
    #[inline]
    pub fn from_f64(f: f64) -> Option<Number> {
        if f.is_finite() {
            Some(Number { n: N::Float(f) })
        } else {
            None
        }
    }
}

impl fmt::Display for Number {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        match self.n {
            N::PosInt(i) => Display::fmt(&i, formatter),
            N::NegInt(i) => Display::fmt(&i, formatter),
            N::Float(f) => Display::fmt(&f, formatter),
        }
    }
}

impl Debug for Number {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        Debug::fmt(&self.n, formatter)
    }
}

impl Serialize for Number {
    #[inline]
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        match self.n {
            N::PosInt(i) => serializer.serialize_u64(i),
            N::NegInt(i) => serializer.serialize_i64(i),
            N::Float(f) => serializer.serialize_f64(f),
        }
    }
}

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

        impl<'de> Visitor<'de> for NumberVisitor {
            type Value = Number;

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

            #[inline]
            fn visit_i64<E>(self, value: i64) -> Result<Number, E> {
                Ok(value.into())
            }

            #[inline]
            fn visit_u64<E>(self, value: u64) -> Result<Number, E> {
                Ok(value.into())
            }

            #[inline]
            fn visit_f64<E>(self, value: f64) -> Result<Number, E>
            where
                E: de::Error,
            {
                Number::from_f64(value).ok_or_else(|| de::Error::custom("not a JSON number"))
            }
        }

        deserializer.deserialize_any(NumberVisitor)
    }
}

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

    #[inline]
    fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Error>
    where
        V: Visitor<'de>,
    {
        match self.n {
            N::PosInt(i) => visitor.visit_u64(i),
            N::NegInt(i) => visitor.visit_i64(i),
            N::Float(f) => visitor.visit_f64(f),
        }
    }

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

impl<'de, 'a> Deserializer<'de> for &'a Number {
    type Error = Error;

    #[inline]
    fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Error>
    where
        V: Visitor<'de>,
    {
        match self.n {
            N::PosInt(i) => visitor.visit_u64(i),
            N::NegInt(i) => visitor.visit_i64(i),
            N::Float(f) => visitor.visit_f64(f),
        }
    }

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

macro_rules! from_signed {
    ($($signed_ty:ident)*) => {
        $(
            impl From<$signed_ty> for Number {
                #[inline]
                fn from(i: $signed_ty) -> Self {
                    if i < 0 {
                        Number { n: N::NegInt(i as i64) }
                    } else {
                        Number { n: N::PosInt(i as u64) }
                    }
                }
            }
        )*
    };
}

macro_rules! from_unsigned {
    ($($unsigned_ty:ident)*) => {
        $(
            impl From<$unsigned_ty> for Number {
                #[inline]
                fn from(u: $unsigned_ty) -> Self {
                    Number { n: N::PosInt(u as u64) }
                }
            }
        )*
    };
}

from_signed!(i8 i16 i32 i64 isize);
from_unsigned!(u8 u16 u32 u64 usize);

impl Number {
    // Not public API. Should be pub(crate).
    #[doc(hidden)]
    pub fn unexpected(&self) -> Unexpected {
        match self.n {
            N::PosInt(u) => Unexpected::Unsigned(u),
            N::NegInt(i) => Unexpected::Signed(i),
            N::Float(f) => Unexpected::Float(f),
        }
    }
}
<|endoftext|>